Spawned from the credential-request-link discussion (2026-07-03): agents now compose HSM URLs/API calls (/keys?request=&assign=), other tools script against /api/keys and /api/harnesses, and the BYO-credentials epic will add broker endpoints consumed by every gateway. The API is becoming a contract; today it's an accretion.
Current state (observed)
- Routes are unversioned (
/api/keys, /api/harnesses, /api/settings, /api/people, /api/surfaces, …)
- Auth model is good but implicit: GETs ungated, mutations require the
hsm_session cookie (operator token HMAC). Nothing documents which routes exist or their shapes except the source.
- No error envelope convention (
{error} vs bare 404 HTML vs NextResponse defaults)
- Naming drift: agents are "harnesses" in the API (
h_* ids), "agents" everywhere in conversation; there is no /api/agents (a natural first guess — it 404s)
- No machine-readable schema; consumers (agents, scripts, future broker clients) reverse-engineer from
lib/services/*
Proposal
/api/v1 prefix with the current surface frozen as v1; old paths alias during a deprecation window
- OpenAPI spec generated from source (route handlers + zod schemas), served at
/api/v1/openapi.json; becomes the doc of record
- Uniform error envelope:
{ error: string, code?: string } + correct content-type on all API 4xx/5xx (no HTML 404s under /api)
- Explicit auth policy doc: ungated-GET / cookie-gated-mutation as a stated invariant, plus a second credential class (scoped automation tokens) for non-browser callers — needed before the credential broker lands
- Naming decision: pick
harnesses or agents once, alias the other
- First standardized flow: the credential-request pattern (
/keys?request=&assign=) documented as the canonical "intent link" idiom — GET encodes intent, never state change
Non-goals
Public internet exposure. This stays a tailnet-plane API; standardization is about contract quality, not reach.
Related: BYO-credentials epic (nimbleco-memory specs/2026-07-03-byo-user-credentials-epic.md) — broker endpoints should land on this surface, not beside it.
🤖 Generated with Claude Code
Spawned from the credential-request-link discussion (2026-07-03): agents now compose HSM URLs/API calls (
/keys?request=&assign=), other tools script against/api/keysand/api/harnesses, and the BYO-credentials epic will add broker endpoints consumed by every gateway. The API is becoming a contract; today it's an accretion.Current state (observed)
/api/keys,/api/harnesses,/api/settings,/api/people,/api/surfaces, …)hsm_sessioncookie (operator token HMAC). Nothing documents which routes exist or their shapes except the source.{error}vs bare 404 HTML vs NextResponse defaults)h_*ids), "agents" everywhere in conversation; there is no/api/agents(a natural first guess — it 404s)lib/services/*Proposal
/api/v1prefix with the current surface frozen as v1; old paths alias during a deprecation window/api/v1/openapi.json; becomes the doc of record{ error: string, code?: string }+ correct content-type on all API 4xx/5xx (no HTML 404s under/api)harnessesoragentsonce, alias the other/keys?request=&assign=) documented as the canonical "intent link" idiom — GET encodes intent, never state changeNon-goals
Public internet exposure. This stays a tailnet-plane API; standardization is about contract quality, not reach.
Related: BYO-credentials epic (nimbleco-memory
specs/2026-07-03-byo-user-credentials-epic.md) — broker endpoints should land on this surface, not beside it.🤖 Generated with Claude Code