# Project Structure ## Organization Philosophy **Layered monorepo, component-per-directory.** Each major subsystem lives under `src//` with its own Meson build file and CLAUDE.md. The Go frontend is isolated in `src/frontend/` as two independent Go modules. All C daemons share `src/lib/` (libxce) and public headers from `src/include/xce/`. ``` src/ ├── lib/ C — shared library (libxce): data structures, IPC, utilities │ ├── raft/ C — reusable Raft consensus module (raft.c/raft.h) │ └── testsuite/ C — libxce unit tests (test_*.c) ├── controller/ C — cluster controller daemon ├── worker/ C — per-node job execution daemon (xcecd) ├── scheduler/ C — job scheduling engine (plugin architecture) ├── autoscaler/ C — autoscaling engine (provider plugins) ├── frontend/ Go — apiserver (Gin REST) + xcecli (Cobra CLI) ├── include/xce/ C — public shared headers consumed across all daemons ├── schema/ Cap'n Proto schema files (c.capnp, controller.capnp) └── docs/ Project-wide documentation (markdown) ``` ## C Daemon Layout Pattern Each C daemon (`controller/`, `worker/`, `scheduler/`, `autoscaler/`) follows: ``` src// meson.build — build definition CLAUDE.md — component-specific AI guide include/ — component-internal headers src/ — .c implementation files (flat, one domain per file) testsuite/ — test programs (test_*.c) ``` **Exception**: `controller/` keeps its `.c` files flat in the component root (not in a nested `src/`). All other C daemons use `src//src/`. Plugin-based components add their own subdirectory: - `scheduler/` — plugins in `src/plugins/` - `autoscaler/` — providers in `src/autoscaler/providers/` ## Go Frontend Layout Pattern **apiserver** (`src/frontend/apiserver/`): | Package | Purpose | |---------|---------| | `cmd/` | Entry point, init sequence | | `router/` | Route registration + middleware chain | | `controllers/` | HTTP handlers — one file per resource | | `services/` | Business logic | | `store/` | Thread-safe in-memory KV stores (generics) | | `models/` | Request/response DTOs, domain structs | | `middleware/` | CORS, rate limiting, JWT, IP whitelist | | `backend/` | CGO bridge to C library | | `backend/auth/` | Pluggable auth providers | | `utils/` | Zap logger wrapper, config parsing, crypto | | `common/` | Global error codes and response helpers | | `config/` | YAML configs + JSON schemas | ## Naming Conventions ### C - **Files**: `snake_case.c` / `snake_case.h` — one domain per file - **Public headers**: `src/include/xce/.h` — the libxce API boundary - **Component headers**: `src//include/.h` - **Test files**: `test_.c` (e.g., `test_ha_cluster.c`, `test_persist_wal.c`) - **Functions**: `snake_case` with component prefix — `ha_*`, `cluster_*`, `xcecd_*`, `xce_*` - **Types**: `snake_case_t` suffix (e.g., `cluster_t`, `ha_state_t`) - **Struct tags**: `struct _s` (e.g., `struct cluster_s`) - **Enums/Macros**: `UPPER_SNAKE_CASE` with component prefix (`CTRL_PRIMARY`, `HA_DEFAULT_*`) ### Go - **Files**: one file per resource — `jobs.go`, `queues.go`, `hosts.go` - **Tests**: `*_test.go` co-located; integration tests as `integration_test.go`, `_control_test.go` - **Controller structs**: `{Resource}Controller` - **Handler methods**: `{Action}{Resource}` (e.g., `SubmitJob`, `ListJobs`) - **Permission strings**: `"action:scope"` (e.g., `"job:view:self"`) - **JSON tags**: `snake_case` ## Test Organization **C tests** (`testsuite/` inside each component): - Standalone `.c` programs, one per unit: `test_.c` - `test.c` provides the test runner harness - Tiered naming: `test_p1_integration.c`, `test_e2e_wal.c`, `test_p3_hardening.c` - Test-only symbols guarded by `#ifdef XCE_TESTING` **Go tests** (co-located `_test.go`): - Table-driven unit tests, `t.TempDir()` for fixtures - Global state reset helpers (e.g., `resetRBACState()`) for test isolation - `make test` = unit only; `make test-all` = unit + integration ## Code Organization Principles - **One domain per file** in C — `ha.c` owns HA logic, `job.c` owns job logic. No megafiles. - **Single Go module per binary** — apiserver and xcecli share no Go code at the module level. - **Controllers delegate to services** — HTTP handlers validate input and delegate; business logic lives in `services/`. - **Dependencies flow inward**: `controllers → services → store/backend`, never the reverse. - **Cap'n Proto for wire formats** — any new inter-daemon or persistence protocol uses `.capnp` schemas in `src/schema/`.