feat(m7.3): cross-tenant admin HTTP endpoints #95

Open
sharang wants to merge 1 commits from feat/m7.3-admin-endpoints into main
Owner

Summary

Cross-tenant operator endpoints on top of the M7.2-D DatabasePool primitives:

  • GET /api/v1/admin/tenants — list tenant DBs
  • DELETE /api/v1/admin/tenants/{tenant_id} — drop (GDPR delete)

Auth is a static bearer (ADMIN_API_TOKEN env), explicitly NOT a Keycloak JWT. The whole point of these endpoints is to operate across tenants, and a customer JWT always carries a single tenant_id, which would be a semantic conflict. Constant-time comparison so byte-level timing probes don't work.

Design

  • ADMIN_API_TOKEN env on the agent. When unset, the admin routes aren't mounted at all (404 rather than 401) — an operator who hasn't opted in can't even fingerprint the surface.
  • Admin sub-router is built in start_api_server when the token is configured, then merged into the main router with its own require_admin_token middleware.
  • compliance-core::auth gains a PUBLIC_PREFIXES list. Paths under /api/v1/admin/ bypass require_jwt_auth so the customer JWT path and the admin token path never collide.
  • require_tenant_status passes through naturally — admin requests carry no TenantContext.

Files

File What
compliance-core/src/auth.rs PUBLIC_PREFIXES list + prefix-aware skip in require_jwt_auth
compliance-core/src/config.rs admin_api_token + tenant_registry_url on AgentConfig (the latter is for the upcoming scheduler→registry PR — adding now to avoid bumping the config shape twice)
compliance-agent/src/config.rs Env wiring for both
compliance-agent/src/api/handlers/admin.rs (new) list_tenant_dbs, drop_tenant_db, require_admin_token middleware, constant-time tokens_eq with a small test
compliance-agent/src/api/server.rs Conditional admin sub-router + merge
Test fixtures Two new None fields in both AgentConfig constructions

Test plan

  • cargo fmt --all -- --check clean
  • cargo clippy --workspace --exclude compliance-dashboard -- -D warnings clean
  • cargo test -p compliance-core --lib — 7 pass
  • cargo test -p compliance-agent --lib — 229 pass (+1 new for tokens_eq)
  • Manual after deploy: with ADMIN_API_TOKEN=secret set on the agent, curl -H "Authorization: Bearer secret" $AGENT/api/v1/admin/tenants returns a JSON list. Without the env, the same call returns 404.

Production

  • Set ADMIN_API_TOKEN in orca-infra (per-tenant secret, NOT committed) when ready to expose. Without it, the routes literally don't exist on the binary.
  • Long-term: replace the static bearer with a dedicated admin realm in Keycloak. Token rotation is currently an env change + restart; revocation responsiveness is zero. Acceptable for ops-only endpoints but should harden before any customer-facing admin UI.

🤖 Generated with Claude Code

## Summary Cross-tenant operator endpoints on top of the M7.2-D `DatabasePool` primitives: - `GET /api/v1/admin/tenants` — list tenant DBs - `DELETE /api/v1/admin/tenants/{tenant_id}` — drop (GDPR delete) **Auth is a static bearer (`ADMIN_API_TOKEN` env), explicitly NOT a Keycloak JWT.** The whole point of these endpoints is to operate across tenants, and a customer JWT always carries a single `tenant_id`, which would be a semantic conflict. Constant-time comparison so byte-level timing probes don't work. ## Design - `ADMIN_API_TOKEN` env on the agent. **When unset, the admin routes aren't mounted at all (404 rather than 401)** — an operator who hasn't opted in can't even fingerprint the surface. - Admin sub-router is built in `start_api_server` when the token is configured, then merged into the main router with its own `require_admin_token` middleware. - `compliance-core::auth` gains a `PUBLIC_PREFIXES` list. Paths under `/api/v1/admin/` bypass `require_jwt_auth` so the customer JWT path and the admin token path never collide. - `require_tenant_status` passes through naturally — admin requests carry no TenantContext. ## Files | File | What | |---|---| | `compliance-core/src/auth.rs` | `PUBLIC_PREFIXES` list + prefix-aware skip in `require_jwt_auth` | | `compliance-core/src/config.rs` | `admin_api_token` + `tenant_registry_url` on `AgentConfig` (the latter is for the upcoming scheduler→registry PR — adding now to avoid bumping the config shape twice) | | `compliance-agent/src/config.rs` | Env wiring for both | | `compliance-agent/src/api/handlers/admin.rs` (new) | `list_tenant_dbs`, `drop_tenant_db`, `require_admin_token` middleware, constant-time `tokens_eq` with a small test | | `compliance-agent/src/api/server.rs` | Conditional admin sub-router + merge | | Test fixtures | Two new `None` fields in both AgentConfig constructions | ## Test plan - [x] `cargo fmt --all -- --check` clean - [x] `cargo clippy --workspace --exclude compliance-dashboard -- -D warnings` clean - [x] `cargo test -p compliance-core --lib` — 7 pass - [x] `cargo test -p compliance-agent --lib` — 229 pass (+1 new for `tokens_eq`) - [ ] Manual after deploy: with `ADMIN_API_TOKEN=secret` set on the agent, `curl -H "Authorization: Bearer secret" $AGENT/api/v1/admin/tenants` returns a JSON list. Without the env, the same call returns 404. ## Production - Set `ADMIN_API_TOKEN` in `orca-infra` (per-tenant secret, NOT committed) when ready to expose. Without it, the routes literally don't exist on the binary. - **Long-term**: replace the static bearer with a dedicated admin realm in Keycloak. Token rotation is currently an env change + restart; revocation responsiveness is zero. Acceptable for ops-only endpoints but should harden before any customer-facing admin UI. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
sharang added 1 commit 2026-06-18 11:03:07 +00:00
feat(m7.3): cross-tenant admin HTTP endpoints
CI / Check (pull_request) Successful in 8m4s
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
CI / Deploy MCP (pull_request) Has been skipped
e20e7f1c6e
Adds two cross-tenant operator endpoints on top of the M7.2-D
DatabasePool primitives:
- GET    /api/v1/admin/tenants              → list tenant DBs
- DELETE /api/v1/admin/tenants/{tenant_id}  → drop (GDPR delete)

Auth is a static bearer (ADMIN_API_TOKEN env), explicitly NOT a
Keycloak JWT — the whole point is to operate across tenants and a
customer JWT always carries a single tenant_id, which would be a
semantic conflict. Comparison is constant-time to avoid byte-level
timing probes.

Design
- ADMIN_API_TOKEN env on the agent. When unset, the admin routes
  aren't mounted at all (404 rather than 401). An operator who
  hasn't opted in can't fingerprint the surface.
- Admin sub-router is built in start_api_server when the token is
  configured, then merged into the main router with its own
  require_admin_token middleware.
- compliance-core::auth gains a PUBLIC_PREFIXES list. Paths under
  /api/v1/admin/ bypass require_jwt_auth so the customer JWT path
  and the admin token path never collide.
- require_tenant_status passes through naturally — admin requests
  carry no TenantContext.

Files
- compliance-core/src/auth.rs — PUBLIC_PREFIXES + prefix-aware skip.
- compliance-core/src/config.rs — admin_api_token + tenant_registry_url
  fields on AgentConfig. tenant_registry_url is added now so the
  scheduler→registry PR doesn't have to bump the config shape again.
- compliance-agent/src/config.rs — env wiring for both.
- compliance-agent/src/api/handlers/admin.rs (new) — list_tenant_dbs,
  drop_tenant_db, require_admin_token middleware, tokens_eq helper
  with a small test.
- compliance-agent/src/api/server.rs — conditional admin sub-router
  + merge.
- Test harness fixtures updated for the two new config fields.

Test plan
- cargo fmt --all clean
- cargo clippy --workspace --exclude compliance-dashboard
  -- -D warnings clean
- cargo test -p compliance-core --lib — 7 pass
- cargo test -p compliance-agent --lib — 229 pass (+1 new for
  tokens_eq)

Production
- Set ADMIN_API_TOKEN in orca-infra (per-secret, NOT committed) when
  ready to expose these endpoints. Without the env, the routes
  literally don't exist on the binary.
- Long-term: replace the static bearer with a dedicated admin realm
  in Keycloak. Token rotation is just an env change + restart for
  now; revocation responsiveness is zero.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Some checks are pending
CI / Check (pull_request) Successful in 8m4s
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
CI / Deploy MCP (pull_request) Has been skipped
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/m7.3-admin-endpoints:feat/m7.3-admin-endpoints
git checkout feat/m7.3-admin-endpoints
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sharang/compliance-scanner-agent#95