sk-… key; the access-control middleware resolves the key’s user and evaluates that user’s jq policy against the request context. You provision keys, map routes to scopes, and attach jq conditions.
Prerequisites
The gate is on by default. Before it can admit requests in a real deployment, these backing pieces must be in place.1
Access control is enabled
The gate runs unless you set
ACCESS_CONTROL_ENABLE=false. Leave it unset (or true) in production — the quickstart disables it only for local, auth-free development.2
A Redis for the live auth context
The identity provider’s api-key records and the per-user live counters live in a plain Redis — any standard
redis-server. No RedisJSON module or redis-stack image is required. Point the connection with ACCESS_CONTROL_REDIS_URL (default redis://localhost:6379/0).3
A Postgres policy store
Scopes, route mappings, and per-user policy bodies live in Postgres — the only policy store. Configure the connection through the
ACCESS_CONTROL_STORE_* env (ACCESS_CONTROL_STORE_PG_HOST, ACCESS_CONTROL_STORE_PG_DB defaulting to tai, and the password via ACCESS_CONTROL_STORE_PG_PASSWORD).4
An identity provider in the manifest
The skeleton ships no concrete identity provider, so a deployment with the gate on must name one as a lifecycle module in the manifest. The default is the redis-backed api-key provider:It registers itself as the
examples/access_control/identity_manifest.yaml
redis provider at import; ACCESS_CONTROL_AUTH_PROVIDER (default redis) selects it. Swap the module and the provider name to use a different authn backend.5
Probe routes pinned public
The guard denies any route it has no mapping for to ordinary identities (a condition-free
* super-admin key is admitted — a root identity is never gated by a missing route row). Probes carry no key, so they are unauthenticated and still need an explicit public pin — pin your liveness and readiness probes public through the public-routes door before an orchestrator probes them:Provision an API key
Create a key for a user. The rawsk-… value is printed once — capture it then. Grant scopes with the repeatable --scope, and attach an inline jq authorization condition with --condition.
--scope flag — the command’s own help confirms it:
examples/cli/keys_create_help.sh
--api-key-stdin flag, or set TAI_API_KEY in the environment. There is no --api-key VALUE flag, because a value would leak via ps and shell history.
Map routes to scopes
A scope maps URLs to a named policy target. Add a URL to a scope, optionally with a dynamic match pattern, and list the current mappings.Write and validate a jq condition
A jq condition compiles against the request context and returns whether the request is allowed. Validate one before you save it — compile it, and optionally sample-evaluate it against aJqAuthContext-shaped sample.
--condition.
1
Draft the condition
Write a jq expression over the request context and compile-check it with
tai keys validate-condition.2
Attach it to a key
Create the key with
--condition (inline) or --condition-id (a stored condition), plus any --condition-kwargs.3
Track policy changes
Each user’s enforced policy is append-only and versioned. List the history with
tai keys policy-versions, and roll back with tai keys policy-rollback.Verify enforcement
Prove the gate before you trust it: call a guarded route with two keys. A key whose policy grants the route’s scope reaches the resource with200; a valid key that lacks the scope is denied with a fixed 403. Set TAI_BASE_URL to your server and the X-Api-Key header to each key.
An allowed key reaches the resource:
examples/access_control/verify_allowed.sh
403, with the full reason logged only server-side:
examples/access_control/verify_denied.sh
AuthAdapter → AccessControlAuthBackend → ResourceGuardMiddleware chain in docs CI, so a change that breaks allow/deny enforcement breaks this step.
Delegate with owned keys
A key minted by a non-admin is an owned key — capped at a subset of its owner’s scopes, isolated to its own data, and attenuated with the owner on every request. To mint a capped key for a teammate or device, inspect what it can do withtai auth whoami, and share it by one-time QR claim link, follow the
owned-keys guide.
See also
- Access control — the key, scope, and jq policy model.
- Owned keys — capped sub-identities, the capability projection, and data isolation.
- The versioning spine — the append-only policy history.
- CLI reference — the full
tai keysandtai scopessurface.

