Request path and state¶
How one request reaches one provider call, what the two health endpoints are each evidence of, and every file the process writes. For the ownership split and the rule at each trust boundary, see ownership and boundaries.
One listener, two routers¶
brama serve binds one address (loopback unless BRAMA_BIND_ADDRESS names
an IP) and mounts two route sets (src/core/server.rs:3400-3455): a public
pair — /health, /readyz — and seventeen bearer-protected routes. Every
route, including /health, sits behind the transport guard.
The request path¶
flowchart TD
A[peer connects] --> B{transport guard}
B -- not loopback/trusted --> B426[426 secure_transport_required]
B --> C{bearer}
C -- unknown --> C1[Skarbiec introspection / Wisent Identity, 5s cache]
C -- invalid --> C401[401 unauthenticated]
C --> D{path scope / allowlist}
D -- out of scope --> D403[403 forbidden]
D --> E{model name}
E -- alias --> F[alias resolution: the registry's single route]
E -- provider/model --> G[direct dispatch: capability at final use]
E -- best / selector --> H{HMAC trio}
H -- missing/expired/wrong --> H401[401]
H --> I[subscription dispatch: rank candidates, pin the chosen account]
F -- alias undeclared --> F404[404, details.state + details.route]
F -- route cannot serve --> F503[503 alias_unserviceable, details.state + details.route]
F --> G
G --> J[provider HTTP call, 16MiB body bound]
I --> J
J -- provider refuses --> JR[refusal returned to the caller]
J --> K[response in caller's dialect + records]
Alias resolution has exactly one outcome per alias: the destination recorded
in routes. If that route refuses the call, its refusal is what the caller
receives, and Brama dispatches nowhere else. That attempt finishes on its
provider result or transport failure, not on an elapsed-time cutoff.
brama aliases prints the alias, its state and its
route, and GET /v1/aliases returns the same reading as rows of
{"alias","state","route","reason","required","authorized","last_answer","concurrency"} with the
states serving, no_route, capability_absent,
capability_check_failed and routes_file_invalid. A failed credential-route inspection retains the authority's operation and cause; it is not cached as an absent credential.
Validation is strict before any provider is considered: unknown JSON fields
are refused, a stated max_tokens must be at least one, temperature is bounded at 2, and a
model name outside the four-part vocabulary is
400 invalid_request (http-api). Every failure is logged
beside the client body as a fleet envelope
(concepts/envelope).
/health versus /readyz¶
The evidence rule, stated once: a green /health is evidence the process
exists; a green /readyz is evidence the product works. Nothing else about
the gateway may be concluded from /health.
/health never redeems a credential, lists subscriptions, or contacts a
provider, and its body says so — "dependencies": "not_probed". It answers
ok from a gateway whose every redemption is being refused (verified: a
standalone gateway with a garbage credential answers /health ok).
/readyz earns its verdict per request: it redeems one capability per
configured provider through the same broker call the request path makes,
checks that every active subscription contributes at least one discoverable
model, redeems one credential per active subscription, and reports vault
subscription accounts that carry no brama:agent: tag. ready is true only
when all four pass and at least one provider capability is configured;
otherwise the status is 503 and reason is one of the five sentences in
the runbook — with providers, denied,
routing, unroutable, subscriptions, unredeemable,
unroutable_accounts, operator_action_required, and build beside it,
and never a secret. Deploy gates and uptime monitors read /readyz.
State on disk¶
Everything Brama writes, and what it never writes:
| Path (default) | Contents |
|---|---|
$BRAMA_STATE_DIR/journal.jsonl (~/.brama/) |
append-only records: retire, reinstate, membership_removed, subscription_refresh, subscription_sign_in, subscription_acquisition, check (task quality); readers take the last matching record; never credential material. A record that cannot be appended fails its operation with the journal path and the OS cause (a retirement, reinstatement or purchase request is not reported as done; a verdict already decided carries journal_failure). Only a journal that does not exist yet reads as empty: an unreadable file or an undecodable line is a refusal with the path and cause, so dispatch, leasing, resets, acquisition and readiness never treat a member as not retired because its retirement could not be read; the pool report shows such a member as unknown with the journal's cause. |
BRAMA_SUBSCRIPTION_USAGE_FILE (~/.config/brama/subscription-usage.json) |
the usage ledger: measured counters, plan windows, blocks, credential state, probe verdicts; atomic owner-only writes |
BRAMA_DONATED_SUBSCRIPTIONS_FILE (~/.stado/var/brama/donated-subscriptions.json) |
donation metadata only, atomic 0600 rewrite |
BRAMA_PERF_PATH (perf.json in Brama's state directory) |
replaceable per-model latency/throughput telemetry; a file that cannot be read, parsed or written is logged as a perf_stats_* warning with its path and cause, and a path that cannot be placed (no state directory) is logged once as perf_stats_unplaced while the numbers stay in memory |
BRAMA_MODEL_CATALOG_CACHE ($BRAMA_STATE_DIR/models-dev-cache.json, state directory default $HOME/.brama) |
replaceable models.dev cache |
~/.local/state/brama/onboarding.json |
onboarding journey progress |
The route registry document is read, not owned: Stado stages it and the admin
routes commit to it, each write an atomic owner-only replacement of the whole
document. brama routes migrate uses that same
replacement to rewrite an existing file into the three known top-level fields
(schema_version, whose value is the number one, plus deployments and
routes), and prints the committed result.
Secrets live in Skarbiec; tokens and grants cross Brama only in memory. Process telemetry is not durable billing evidence; the ledger is the record that spans months.