SQLite lives only inside this process. Chronicle and TokenOps are facets (agent sidecars + UI tabs), never database clients.
One SQLite file (CONTROL_PLANE_DB, default control_plane.db). WAL.
No Postgres. Agents and the browser never receive a DB path.
Local/dev: run control-plane serve. Clients talk HTTP.
TOKENOPS_EMBEDDED=1 remains TokenOps-only for unit tests that never start this service.
Every HTTP route is owned by exactly one caller class:
| Caller | Who | Scopes |
|---|---|---|
agent-chronicle |
Chronicle sidecar in the agent | ingest write, read for fixture replay |
agent-tokenops |
TokenOps sidecar in the agent | ingest write, read for governance/ledger |
ui |
Control plane Admin / Chronicle / TokenOps tabs | read + admin |
Agent needs two things:
- Ingest —
POST /v1/envelopes:batchis the only ingest API. Clientbatch_size=1means flush every envelope (still the batch route). - Replay fixture —
GET /v1/traces/{trace_id}/envelopesreturns the full ordered envelope list for that trace (enough to stub-replay).
UI (same process as the DB, but talks HTTP so the split stays honest):
GET /v1/tracessearch / filter / sortGET /v1/traces/{trace_id}summaryGET /v1/traces/{trace_id}/envelopeswaterfall
No unbounded GET /envelopes. No single-envelope POST.
Full spec: api-contract.md.
Agent (0.2.x):
POST /v1/runsregister (intent,user_dims,mode) → returns the full record incl.registered_atGET /v1/runs/{id}/registrationGET /v1/governance/{agent}— policy params now carrydata_scope(local|global)POST /v1/ledger/precheck— one read per pre_call pass (halt + spent + inflight- optional window)
POST /v1/ledger/events:batch— one write per crossing (spent_add/admit/complete/step/halt_mark/halt_clear), idempotentGET|POST|DELETE /v1/ledger/runs/{id}/haltPATCH /v1/run-records/{id}— status / ended_at / halt_reason / detector / governance_events (steps/cost_microsare derived, ignored)- Legacy, deprecated → removed in 0.3.0: single-op
/v1/ledger/{spent,inflight,halt}/*,PUT /v1/run-records
UI:
- CRUD
/v1/segments|budgets|policies GET /v1/run-records(+problematic_only)POST /v1/admin/seed-if-empty|reseed-governance|clear-*
TokenOps SDK uses HTTP for all of the above when TOKENOPS_URL /
CONTROL_PLANE_URL is set. It must not open SQLite in that mode.
Same FastAPI process serves a small HTML app (component CSS in
control_plane/web/static). No login screen.
| Tab | Role |
|---|---|
| Admin | Sidecar API keys (Chronicle / TokenOps / UI). Create, list, revoke. |
| Chronicle | Trace search, lookup, waterfall. |
| TokenOps | Budgets, policies, segments; run list with breaches. |
Keys are stored hashed in SQLite (prefix shown after create). Env
CONTROL_PLANE_API_KEYS still seeds. Empty key table = local anonymous
dev (all scopes, tenant local).
Format: name:tenant:scope+scope in env; generated keys are random tokens.