Request lifecycle
The commercial pilot persists one fail-closed state machine per request.
awaiting_approvals -> approved -> authorized -> executed
| |
+-> rejected +-> expired
validation_completed may be appended as an evidence event while the request
remains authorized. It proves an external validation receipt was produced; it
does not claim that a transaction was constructed, broadcast, or confirmed.
Transition ownership
| Transition | Required role | Main checks |
|---|---|---|
| Submit | Initiator | Exact policy scope, amount, decimals, destination, idempotency |
| Approve | Eligible approver | Actor eligibility, no duplicate, initiator separation |
| Reject | Eligible approver | Non-terminal request and recorded reason |
| Authorize | Security administrator | Approval threshold, exact policy and evidence binding |
| Execute | Executor | Valid certificate, validity window, adapter idempotency |
| Inspect/export | Auditor or authenticated operator | No state mutation |
Retry and idempotency
- The request ID is derived from tenant and idempotency context.
- An exact retry returns the existing record.
- Changed business fields under the same idempotency key fail with conflict.
- External adapters must reconcile by stable request ID before submitting again.
- Terminal states cannot be approved, rejected, authorized, or executed again.
Failure model
| Class | Typical API result | Operator response |
|---|---|---|
| Invalid or out-of-policy input | 400 | Correct the request; do not retry unchanged |
| Missing or invalid credential | 401 | Re-authenticate with the correct private credential |
| Wrong role or ineligible actor | 403 | Route to the role named by the policy |
| Unknown request | 404 | Confirm request ID and environment |
| Idempotency or state conflict | 409 | Fetch the existing record and reconcile |
| Provider uncertainty | Request remains reconcilable | Query provider/chain state before any resubmission |
| Authorization expiry | Terminal expired evidence | Start a new request under current policy |
Exact error response stability is not yet guaranteed across release candidates. Partner integrations should branch on HTTP class and stable request state, then record the bounded diagnostic message for review.