BBramaDocs

Documentation topic: README.md

Operational model

  • Configuration: production policy is generated by scripts/start-with-skarbiec.sh from operator-owned configuration and scoped secret consumers. Missing, malformed, duplicate, or contradictory security configuration fails startup.
  • Dynamic inference routes: BRAMA_INFERENCE_ROUTES_FILE points at an owner-only snapshot maintained by the deployment operator. Brama reloads it per request, rejects symlinks and group/other-readable files, accepts only loopback or Tailscale IPv4 deployment endpoints, fails closed on malformed updates, and attempts centrally declared fallback routes in order.
  • Desktop credentials: standalone Brama Desktop launches its bundled Brama binary on loopback, sends provider credentials once over the child process's standard input, and keeps both its router bearer and provider credentials out of process arguments, files, logs, and Brama state. A Stado-discovered Brama installation may instead acquire its scoped bearer from Skarbiec.
  • State: $BRAMA_STATE_DIR/journal.jsonl contains retirement and quality records. $BRAMA_SUBSCRIPTION_USAGE_FILE, by default ~/.config/brama/subscription-usage.json and owner-readable only, holds the per-subscription usage ledger: measured counters, the newest plan reading per window with the instant it was read and where it came from, when the provider's usage report was last checked, any block, and the newest check verdict. It is written atomically and is not a cache — the question it answers spans months, not process lifetimes. A ledger written by an older gateway still loads: a reading that carries no instant of its own has no recorded_at_ms, is reported as not stated and is read as stale; it is never dated with the ledger file's modification time. A ledger that exists but cannot be read or decoded is never replaced: the gateway starts from an empty ledger in memory, keeps new observations visible in that process, refuses every ledger write until the file is repaired, and the subscription pool reports brama.subscriptions.ledger with the path and the cause; only a missing file starts a new ledger (see docs/usage-ledger.md). BRAMA_PERF_PATH, else perf.json in Brama's state directory, contains replaceable process telemetry. The entitlements router owns encrypted subscription credential storage in managed deployments.
  • Subscription discovery: a provider subscription is a Skarbiec item tagged brama:subscription and brama:agent:<agent>, carrying its provider and subscription id in brama:provider:<provider> and brama:id:<id>. Both the gateway and Brama Desktop filter on those tags, so vault item ids are opaque and renaming one changes nothing. scripts/provision-desktop-subscriptions.py writes the owner vault and scripts/provision-host-subscriptions.sh writes a managed host's vault; both are idempotent and derive their tags from scripts/skarbiec-subscriptions.json.
  • Plan usage from the provider's own report: every provider that rations a subscription publishes a report of how much of the ration is gone, and reading it spends no quota at all. claude-code publishes GET /api/oauth/usage on api.anthropic.com (five_hour, seven_day, seven_day_opus and seven_day_sonnet, each a utilization percentage with a reset instant), codex publishes GET /backend-api/wham/usage on chatgpt.com (rate_limit.primary_window and .secondary_window, each a used percentage with its window length and reset), and kimi publishes GET /coding/v1/usages on api.kimi.com (a usage object and a limits array of limit/used/remaining counts with their windows). Every other provider publishes nothing, and that absence is recorded as the provider's own answer rather than left as an unexplained blank. A subscription's report is read on a maintenance pass when it has no reading, a reading whose window has reset, a reading that names no reset, or a failed last read; the serving process runs its own passes (at start, at each moment its ledger states something becomes due, and after a refusal for want of a signed-in subscription), and brama maintain asks for one more. Reads are single-flighted per subscription and logged under plan_usage_*. A failed read never blanks a row: the last good reading is kept and served with stale true until a newer one replaces it.
  • Routing by what the plans have left: the readings above are not only for reading. A selector orders its candidate routes by the freest usable subscription behind each one, and an explicit route orders its bounded credentials the same way, both from the ledger and neither costing a provider call. Chance still breaks exact ties, so accounts at equal utilization stay decorrelated, but an account the provider says is 90 percent spent is no longer tried ahead of one at 10 percent. A window whose own reset instant has passed counts as empty; a subscription with no reading counts as free, because its first call writes the reading that corrects the placement.
  • One agent, one account, for the length of a window: the credential that served an agent is remembered per provider and tried first on that agent's next request, until the tightest window it reported resets, or, when the provider named no reset, until another account serves the agent. Two things depend on it: a provider's prompt cache lives behind one account, so scattering an agent's turns across a pool throws the cache away, and one conversation's spend belongs in one account's ledger rather than smeared across every account the agent owns. It is a preference and never a grant -- it is consulted after eligibility, skipped for a credential inside a block or reporting a full window, and it cannot outlive the process, because a pin whose window has passed is worth nothing anyway.
  • The one check that costs quota, and only on request: whether a provider will actually serve a credential can only be answered by a real request, so POST /v1/admin/subscriptions/:agent_id/:subscription_id/probe spends one minimal completion against one named subscription and records the verdict as probe with source completion. Nothing triggers it on a timer: with default configuration no timer performs a quota-consuming request. It is a route rather than a subcommand because redeeming the credential needs the capabilities and identities the launcher installed in the serving process, and a standalone desktop install holds its provider credentials only in that process's memory. A subscription inside a recorded block is refused with 409 rather than probed: the block already says the account is out of quota, and re-reading that sentence is what the block exists to prevent. The probe rotates to no other credential, retires nothing, and is logged under its own usage_probe_* events so it is never mistaken for a caller's request.
  • Refreshing expired grants between requests: each maintenance pass of the serving process refreshes every active subscription credential whose stated expiry has passed, single-flighted per subscription so a slow refresh is never started twice. A token is used until its stated expiry; a request the provider rejects forces a refresh on the request path. Refreshing costs no plan quota: a token endpoint is not a metered endpoint. A refusal is classified. A definitive one -- invalid_grant, invalid_token, a revoked or unauthorized refresh token, or a 401/403 that is not a transport failure -- is recorded as credential.state needs_reauthorization with the provider's own sentence as credential.cause, and that credential is left alone until a sign-in replaces it. A transient one -- a request the network never answered, a refused connection, any transport failure -- changes nothing and is retried by the next sweep. A refreshed grant that cannot be written back to the vault is a failed refresh, not a success: the rotated grant is dropped rather than spent from memory, because the provider has already invalidated the one still in the vault. Events are credential_refresh_* and credential_refreshed_ahead.
  • Credentials: callers use dedicated bearer items. Request-sign identities and provider capabilities remain separate. Secrets are redeemed at final use and are not written to JSON configuration, logs, or Brama state. Standalone launchers pass a provider-to-credential JSON object to brama serve --local-credentials-stdin over standard input. A service host without Skarbiec sets BRAMA_LOCAL_CREDENTIALS_FILE (here or in ~/.config/brama/service.env) to an owner-only (chmod 600) file holding that object; start-with-skarbiec then starts the gateway in the same standalone mode and runs none of its Skarbiec stages. A file that is not owner-only is refused with "BRAMA_LOCAL_CREDENTIALS_FILE must be readable by its owner only". stado product install brama --surface service --without skarbiec installs the service on such a host.
  • Network: Brama binds to loopback. Standalone desktop clients use their bundled process; managed clients may discover a local Brama service through Stado. Provider endpoints require approved HTTPS hosts, disable redirects, and bypass ambient proxies.
  • Failure: stable HTTP error codes distinguish invalid input, authentication, authorization, quota, an unanswered provider request, dependency unavailability, and provider failure. Retryability is included in the error envelope.
  • Observability: health and brama version expose secret-free build identity; structured logs record routing mode, selected route, attempts, outcome, and remediation class. /stats remains bearer-protected.
  • Upgrade and rollback: follow RELEASE.md. Immutable product version, source revision, platform, digest, and provenance are separate facts.
  • Qualification: evidence groups and consent boundaries are defined in TESTING.md.