BBramaDocs

Brama HTTP API reference

Transport and identity

Two guards stand in front of every path in the route table: the transport guard, which every route passes through including /health, and the identity guard, which every route except /health and /readyz passes through. This page is what both of them check, what a caller sends to satisfy them, and the shape of the answer when one of them refuses.

Accepted transports

A request is accepted only when its peer is loopback, the address the gateway itself bound, a peer named in BRAMA_ENCRYPTED_PEER_IPS (a mesh hop that is already encrypted), or a proxy named in BRAMA_TRUSTED_PROXY_IPS whose Forwarded/X-Forwarded-Proto headers state https. Anything else receives status 426 with this body; it asked no provider, so it carries no attempts:

{"error":{"code":"secure_transport_required",
 "message":"HTTPS is required except for direct loopback requests",
 "retryable":false,"type":"transport_error"}}

Forwarded headers presented by a peer that is not in BRAMA_TRUSTED_PROXY_IPS are never read as evidence of the scheme. The guard runs before the handler, so a refused request never reaches a provider and never touches the vault.

Bearers

Protected routes take exactly one Authorization: Bearer <token> value. The token is compared in constant time against the identities in BRAMA_MODEL_ROUTER_CLIENT_IDENTITIES. A bearer that is not in that table is resolved against Skarbiec, the authority that issued it, and, for account-scoped routes, against Wisent Identity. When an authority cannot answer, the request is refused rather than admitted, and every request asks again, so a revocation takes effect on the next request without restarting the gateway.

An unavailable workload authority produces a workload_authority_unavailable event in the gateway log before the client receives its service-unavailable refusal. The event identifies POST <Skarbiec origin>/v1/tokens/introspect and the actual transport, HTTP, response-read or JSON failure. Server-error and rate-limit responses retain the authority's response body; both credentials carried by the introspection request are redacted if reflected in that body. A response-body read failure retains the HTTP status and the read error. A malformed successful answer retains its status and parser error, not the answer's contents. These diagnostics do not authorize the bearer or turn a rejected credential into a dependency failure.

The gateway's current boot log is available through brama diagnose. The CLI and graphical consumers continue to receive the same admission refusal; operator diagnostics explain which authority operation failed without returning credentials to the requesting client.

Workload introspection, human user lookup and organization authorization share strict response-byte decoding: invalid UTF-8 or malformed JSON cannot become an accepted identity through text replacement. User-lookup failures emit wisent_identity_unavailable; organization-authorization failures emit organization_authority_unavailable with the failed POST <Identity origin>/rest/v1/rpc/authorize_organization operation and actual client, transport, HTTP, response-read or parser cause. Bearer and authority-key values reflected by an HTTP failure are redacted. Authentication and organization-permission refusals retain their existing unauthorized or forbidden statuses. The workload qualification below covers the shared response reader through Skarbiec; it does not qualify human organization membership.

Real workload-authority qualification

tests/authentication/authority.rs calls the real brama subscription lease list command with a vault-backed workload bearer and retains its exit status, complete output and newly appended gateway diagnostics. Use an isolated gateway with no concurrent callers or lease writers. Its control bearer must be admitted independently of the authority under qualification; the workload bearer must be absent from the gateway's boot identity table and belong to a real Skarbiec workload with access to the subscription pool. No model call, account purchase, token mutation, service restart or lease mutation is part of this journey.

Supply BRAMA, CLI_SOURCE_REVISION, GATEWAY_SOURCE_REVISION, CONSUMER and control BEARER_ROLE, plus WORKLOAD_BEARER_ROLE, the actual local GATEWAY_LOG path and ADMISSION_STATUS. The expected status is either HTTP OK or HTTP Service Unavailable. The refusal run additionally requires the real AUTHORITY_HTTP_STATUS, AUTHORITY_OPERATION and a nonempty, credential-free AUTHORITY_CAUSE from the authority's error body. The authority status must be a server error or Too Many Requests. The journey checks that the CLI refuses and that the new log event preserves that operation, status and cause. A separately authorized run checks the workload sees the same actual lease state as the control identity. Both runs verify unchanged final lease state.

The test checks the CLI binary and actual gateway source revisions before the admission call. Evidence is retained under target/real-tests/subscriptions/<run UUID>/report.json using the shared real-CLI evidence support. Supply the real authority failure and recovery fixtures; do not replace either with a mock, generated response or a healthy process check. A missing fixture or an unexecuted journey is not qualification.

cargo test --test workload-authority -- --ignored --nocapture

A model-scoped bearer — one carrying allowed_models — may reach the five inference paths, /v1/models, the subscription pool and plan usage; the allowlist itself is then enforced per request, further in. Every other path, including /v1/aliases and the whole admin family, answers 403 forbidden. A request with no bearer at all on a protected path is 401 unauthorized.

The organization header

A human bearer is not yet an identity: it names a user, and a user may belong to several organizations. The request states which one with a single X-Wisent-Organization-ID header carrying a UUID, and Brama asks Wisent Identity to authorize that user for that organization with that same bearer. The identity it caches is keyed on the token digest and the organization id, so a bearer authorized for one organization is not an identity in another.

A missing header, more than one of them, a value that is not a UUID, or an organization the bearer is not authorized for is refused. The first three answer 400 a valid X-Wisent-Organization-ID header is required; an unauthorized pairing answers 403 forbidden. Workload bearers carry no organization context and send no such header.

Agent signatures

An agent-scoped operation additionally signs the exact raw request body with the HMAC trio described in concepts/entitlement. The signature is over the bytes as sent, so a proxy that reformats the body invalidates it. A route that requires the trio and does not receive it names the header that is missing, for example 401 {"message":"missing x-agent-id header"} (captured on model:"best").

Where a request field would restate an identity the signature already proves, sending it is refused instead of being ignored — see discovery and subscriptions for the two cases, agent_id on a pool write and any field at all on plan usage.

Shared request limits

Three limits hold for every request the gateway admits.

  • A request has no deadline of its own: its one attempt runs until the provider answers or refuses, and that answer or refusal is what the caller receives.
  • A request has no size of its own: the routes that carry a prompt or media — /v1/chat/completions, /v1/messages, /v1/responses, /v1/decisions, /v1/embeddings, /v1/moderations and the image and voice routes — read the whole body, and a prompt longer than the routed model accepts is refused by the provider as context_length_exceeded, naming the model.
  • Unknown request fields are refused with the deserializer's own sentence, naming the field it did not expect and listing the fields it did. The bodies on every page in this family are therefore exhaustive.

The refusal envelope

Every refusal on every route uses one envelope, whose fields — type, code, message, retryable and attempts — are documented in errors. Two cases are worth stating here because they are the shape of the route contract.

A request naming an alias this gateway declares, whose state is anything other than serving, is refused with 503 and code alias_unserviceable. Its details carry state, one of no_route, capability_absent or routes_file_invalid, and route, the single destination the registry maps that alias to. The message is the same sentence GET /v1/aliases gives as the row's reason, so the refusal and the listing agree.

A request naming an alias this gateway does not declare is 404, and its details carry the same two fields, with state reporting that there is no route for that name. In both cases the refusal is what the caller receives: the resolved route is attempted once, and its answer, including its refusal, is the answer to the request.

{"error":{"code":"alias_unserviceable","type":"invalid_request_error",
 "message":"alias `ox-alpha` routes to openrouter/stealth/ox-alpha but this gateway holds no provider credential for openrouter",
 "retryable":false,
 "details":{"state":"capability_absent","route":"openrouter/stealth/ox-alpha"}}}

Repairing the state an alias is in is an operator action, not a client one: point the alias at a route this gateway can reach, or issue the provider capability here. The registry write is PUT /v1/admin/routes, and brama routes migrate brings an existing registry document to the current shape.