Skip to main content

Explain

Would this action be allowed for this tenant, and what decides?
This endpoint is pure. No side effect, no ledger row, nothing enqueued, nothing metered — and side_effects: [] is on the wire so you do not have to take this page’s word for it. An explain that could itself be denied, or that wrote a row, would be unusable as the thing you run before deciding whether to act.It calls the same three helpers the enforcing path calls. An explain that reimplemented the decision would be a second policy.

Body

Reading because

layer alone is an assertion nobody can check, so rule names the config path you can go and look at. verdict is deny when the primitive is off or the capability is denied, park when approval is required, and allow otherwise. It is never approve — see the verdict vocabulary.

Snapshot

The resolved AccountKit — the tenant’s authority as the gate sees it right now.
statute_actions is a count. Enumerate them with GET /v1/policy/statute rather than making one response 31 rows nobody reads.

Statute

The actions that default to human approval.
This endpoint corrects its own name on the wire. The response carries "waivable": true.These are defaults, not a statute. Setting primitives_config.<primitive>.requiresApproval = false on an AccountKit opts a tenant out of any of them. A genuinely non-waivable layer does not exist in this build.If you are relying on “this action always requires a human”, verify it with POST /v1/policy/explain for the specific tenant. The statute list tells you what the platform defaults to, not what your tenant does.
outcome is approve on every row because that is the rule the author wrote. The engine folds it to the park verdict when the condition is unsatisfied.
The set covers money movement (cards, trading, domain purchase, company formation), identity (verification, browser signup), infrastructure (compute create and exec, phone provisioning), mobile device control, connections, and the destructive brain operations (brain.kb.delete, brain.document.delete, brain.forget, brain.proposal.accept). Read the live list rather than this sentence — it is the one that is current.
Two rows on this list are reported but not enforced by the decision engine. Measured on this build: the list this endpoint reads has 31 actions; the closed engine that actually decides has 29. The two extra rows are phone.voice_enable and phone.call.Consequence: for those two actions this endpoint says “defaults to human approval” and the engine that decides does not know it. POST /v1/policy/explain reads the same 31-action list, so it reports the same thing — it is not a second opinion here.Treat both endpoints as the declared intent. For phone.voice_enable and phone.call specifically, do not assume a human gate exists: set requiresApproval: true explicitly on the phone primitive in the AccountKit if you need one, and confirm with a real call in a sandbox environment.

The four that refuse

POST /v1/policy/waives answers 501, not the 403 statute_not_waivable the contract specifies. 403 would tell you the platform refused to waive something — when in fact it never evaluated anything, because there is no statute layer at all. The 403 becomes the correct answer the day a statute exists.