Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Authentication

Every route under /api requires a bearer JWT, issued by the tenant’s Keycloak realm. Two public routes exist outside /api: GET /healthz and GET /readyz.

curl -sS "$RULEFLOW_API/api/whoami" -H "Authorization: Bearer $TOKEN"
{ "sub": "f2a1...", "email": "alice@acme.com", "tenant": "acme", "roles": ["business-analyst", "approver"] }

Token verification

The token is verified against the realm’s JWKS (issuer + /protocol/openid-connect/certs), algorithm RS256, expiry required, issuer matched case-insensitively. On success, the claims are attached to the request context for the rest of the handler chain.

Claims

FieldJSON keyNotes
SubjectsubKeycloak user id
Emailemailomitted if the user has none
Tenanttenantrequired on every tenant-scoped route
Rolesrolesrealm roles (realm_access.roles)

A request with no tenant claim (or an empty one) is rejected 403 on every tenant-scoped route — "no tenant in token". There is no default tenant. See Tenancy & isolation for how the claim is provisioned and why it can be trusted.

Roles

Roles gate specific actions, independent of tenancy:

RoleRequired for
approver (or admin)Deploying to / rolling back a protected environment (staging, prod, production)
approver (or admin)Completing an assigned human task on someone else’s behalf
adminEvery route under /admin/* (/admin/usage, /admin/tenants*) — deliberately cross-tenant surfaces

A missing role returns 403 with a message naming the required role, e.g. "admin/tenants requires the 'admin' role".

Errors

Every error response has the same shape:

{ "error": "human-readable message" }

Common status codes across the API: 400 invalid body/params, 403 no tenant claim or missing role, 404 not found (including cross-tenant lookups — see Tenancy), 409 idempotency-key conflict, 429 quota exceeded, 503 a backing service (engine, runtime, search) is not configured in this deployment.