Skip to main content
Seven top-level prefixes that answer one question: what is this tenant allowed to do, and what decides?
Start with POST /v1/policy/explain. It is pure — no side effect, no ledger row, nothing enqueued, nothing metered — and it calls the same helpers the enforcing path calls. It is the thing to run before you decide whether to act.

What is real, and what refuses

Seven of seventeen serve real data. The other ten answer 501 not_configured and name the missing table — see the durable runtime refusal contract for why that shape, not {"items": []}.

Naming the tenant

Every tenant-scoped operation here takes an optional ?tenant=<tenant_user_id>. Omit it and the caller’s own subject answers.
?tenant= is not an authority bypass. It resolves through the same subject resolver as every other route, so a key sealed to one tenant cannot read another tenant’s resolved policy by naming it. An explain endpoint that leaked a peer’s authority would be an oracle for exactly the thing it exists to describe.

Verdict vocabulary

The engine’s verdicts, and the one word that is not one of them: approve is not a verdict. It is what a rule author writes; when the condition is unsatisfied it folds to park. Rendering approve as an outcome is how a UI ends up showing a state the engine never produces.

The layers, and which of them exist here

The design has six policy layers. This build represents three, and the snapshot says which: