The Policy Firewall
Every authorize call runs an ordered chain of checks before anything is signed. Any failing check ends the chain with a DENY and a human-readable reason.
The chain
- 01Bearer authIs the API key valid and active?
- 02IdempotencyHave we already decided this exact request? Return the same answer.
- 03Kill-switchIs the org-wide emergency stop engaged?
- 04Action kindIs this type of action allowed by the policy?
- 05NetworkIs the target network allowed (e.g. casper-test vs casper)?
- 06Service scopeIs the destination service on the allowlist?
- 07Asset typeIs the asset being moved permitted?
- 08Per-transaction maxIs this single amount under the cap?
- 09Spend capUnder the rolling 30-day cap? Reserved atomically in Redis.
- 10Velocity limitUnder the max payments-per-hour?
- 11SignAll checks passed — produce the signature.
What a policy contains
- Spend cap — total over a rolling 30-day window.
- Velocity limit — max payments per hour.
- Per-transaction max — largest single amount.
- Service allowlist — which destinations may be paid.
- Allowed actions & networks, plus trade rules (max slippage, allowed risk labels).
NOTE
The spend cap is reserved atomically (Redis Lua), so two concurrent requests can never both slip past a nearly-full cap. Money is handled as exact integers — never floats.
DENY reasons are readable
A denied request comes back with plain English, e.g. “Spend cap is 100 CSPR. Already used 100 CSPR in the current 30-day window. Requested 5 CSPR would exceed the cap by 5 CSPR.” Your agent can log it or react to it directly.
