# Project Status > Last updated: 2026-04-09 --- ## Overall Progress ```mermaid pie title Component Completion "Done" : 99 "Missing features" : 1 ``` --- ## Integration Test Summary Live test: `xcecli` against running `apiserver` with builtin test data. | Status | Commands (after all fixes) | |---|---| | ✅ Working | `login`, `logout`, `list`, `whoami`, `permissions list`, `roles list/view/add/delete`, `users list/view/assignrole/unassignrole/permissions4user`, `hosts list/open/close`, `queues list/open/close/active/deactive`, `jobs submit/list/kill/stop/resume/checkpoint`, `resources distribution/definition list` | | ⚠️ Expected | `jobs list` (no filter = current user only, by design); `clusters list` (empty — no backend data) | | ❌ Broken | none | --- ## Done ### apiserver - [x] Gin HTTP server with config loading (Viper + JSON schema validation) - [x] JWT authentication — logon / logout, token stored server-side per user - [x] Middleware stack: IP whitelist → URL whitelist → rate limiter → JWT validator - [x] RBAC engine — roles, permissions, domain-scoped access control - [x] Auth provider abstraction — PAM (Linux), config-file, LDAP stub, OAuth2 stub - [x] Full REST API surface (30 endpoints across jobs, hosts, queues, clusters, resources, files, roles, users, permissions) - [x] In-memory generic `DataStore[K,V]` with filter / sort / paginate pipeline - [x] Job ID generator (Snowflake-style, cluster-aware) - [x] File upload with MIME type validation and size limits - [x] Structured logging with `zap` + log rotation (`lumberjack`) - [x] Per-endpoint rate limiting (token bucket, configurable window) - [x] Backend stub + notification handler interfaces ready for integration - [x] **S1** — JWT secret loaded from `XCE_JWT_SECRET` env var; falls back to config file - [x] **S3** — Removed hardcoded mock RBAC maps from `rbac_check.go` - [x] **S4** — Whitelist pattern matching: `pathMatchesPattern()` — exact paths no longer truncated; wildcards fixed for all sub-paths - [x] **F4** — CORS middleware: configurable via `app.yaml`, handles preflight (OPTIONS 204) ### xcecli - [x] Cobra CLI with command groups; auth-check middleware on all commands - [x] Multi-server config (`~/.xce/config.json`) with token + expiry tracking - [x] All command groups: auth, permissions, roles, users, jobs, hosts, queues, clusters, resources - [x] Paginated table output for all resource types - [x] **T1** — `roles list` / `users list`: removed `unique=true` param; client-side cross-page dedup - [x] **T3b/M3** — `UnmarshalOrderMapRow`: all row types unwrap server `{Fields,Data}` wrapper; all list commands show real data; `num_cpus` tag fixed - [x] **T5** — Column truncation fixed in `roles view` / `users view` / `permissions4user` - [x] **T7** — `xce logout --url` now optional; defaults to active server - [x] **T8** — `jobs submit -f /path` plain paths no longer error - [x] **A1** — Authorization header: removed leading space; all 5 request methods consistent - [x] **A3** — `SetRootCAs`: HTTPS + empty cert → `InsecureSkipVerify`; HTTPS + cert path → load pool - [x] **T9** — `xce hosts select -R "expr"` command; POSTs to `/xce/v1/hosts/select` (returns empty until backend) - [x] **Job time display** — `SUBMIT_TIME` now shows `Apr 08 17:00` instead of `-`; `parseJobTime()` supports RFC3339 and space formats - [x] **Build** — xcecli builds static (no libssl.so.3) via `CGO_ENABLED=0`; pam/openssl removed from nix shell until backend integration ### Infrastructure - [x] Nix flake dev shell (`nix develop`) — Go 1.25, PAM, OpenSSL, meson, gnumake, swag, gopls, delve - [x] Meson build/test: `/xce-build apiserver` (unit tests), `meson test -C --suite apiserver` (CGO-backed backend tests), `tests/regression/run.sh` (integration) - [x] Regression suite: `tests/regression/run.sh` — 29 tests, all pass - [x] Unit tests across: `apiserver/store`, `apiserver/utils`, `apiserver/controllers`, `xcecli/cmd/auth`, `xcecli/cmd/jobs`, `xcecli/cmd/roles`, `xcecli/cmd/users`, `xcecli/common/request`, `xcecli/models` --- ## Todo ### 🟡 Missing features | ID | Component | Task | |---|---|---| | F1 | server+cli | File delete: uncomment server route + `xce files delete` command | ### 🔵 Cleanup | ID | Component | Task | |---|---|---| | Q1 | apiserver | Regenerate Swagger docs (`swag init`) | --- ## Upcoming: Backend Integration Prep - [ ] Register `DefaultHandler` with backend notification system so store is populated from real data - [ ] Replace `backend/stub.go` no-ops with real C library / gRPC calls - [ ] Decide persistence strategy — `lib/pq` (PostgreSQL) in `go.mod` but unused; store is pure in-memory - [ ] Make `clusterID` configurable (hardcoded `const clusterID = 1` in `controllers/jobs.go`)