Approval Workflow
When policy returns REQUIRE_APPROVAL, AXIS does not execute the write. It creates a durable approval record and returns approval_id; the client must explicitly retry the request with that approval_id after a human approves it.
Approval does not execute the request. Approval is consent. The client must retry with the same approval_id; only then does AXIS evaluate policy with the approved flag and execute.
Approval flow
Approval lifecycle
| State | Meaning |
|---|---|
pending | Created; awaits operator resolution |
expired | TTL elapsed without resolution; not executable |
resolved(approve) | Human approved; consent recorded durably; still requires client retry with approval_id |
resolved(reject) | Human rejected; execution blocked forever for that approval |
Resolution is immutable: one decision per approval, accepted values approve / reject. Resolution writes audit evidence before the response. Approval store: local SQLite per install guide (AXIS_APPROVAL_DB_PATH=./data/approvals.sqlite); JSONL-backed per the security model. TTL is controlled by AXIS_APPROVAL_DEFAULT_TTL_SECONDS (default 300).
Resolve request
curl -sS -X POST http://localhost:6543/approvals/<approval_id>/resolve \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AXIS_OPERATOR_TOKEN" \
-d '{"decision": "approve", "note": "batch backfill verified"}'
Resolution requests require the operator token. Approval IDs are provided by AXIS in the 202 response; the Control Plane surfaces them with the pending request context.
Explicit retry
curl -sS -X POST http://localhost:6543/query \
-H "Content-Type: application/json" \
-d '{
"actor": "demo-ops",
"app": "demo-batch",
"tenant": "acme",
"role": "app_ops",
"host": "localhost",
"env": "prod",
"sql": "UPDATE accounts SET status = '\''active'\'' WHERE id = 42",
"approval_id": "<approval_id>"
}'
On retry with a valid approval_id, AXIS re-evaluates policy with the approved context. If policy still allows, the write executes; evidence is appended for the executed attempt.
Guarantees and limits
- No protected database write happens while an approval is pending or rejected.
- Expired or unknown
approval_idnever executes; retries fail with structured errors. - Open DB transactions are never held open across human approval wait times.
- Approvals do not expire or invalidate when policy is rolled back in v0.8 — a rolled-back policy re-evaluates the retry under the previous (now active) policy.
- Approval identity is operator-token-gated, not verified multi-party authorization: "v1" is single human or small trusted group review, not enterprise RBAC/SSO.
Because the resolved approval grants one execution path, protect the operator token, expire approvals with TTL, and treat rejection as permanent for that approval ID.
Related: Policy Engine · Audit & Evidence · Operating Modes