CONTROLS / ELPIS
Control layers & rule reference
The five layers that decide a payment, and every rule that can refuse or escalate one.
The five layers
Controls run in a fixed order. Earlier layers are absolute; later layers may escalate rather than refuse, precisely because the earlier ones will not let a catastrophic action through.
| Layer | Type | Effect of a failure |
|---|---|---|
| 1 — Hard rules | Deterministic arithmetic on facts | Blocks (no money moves) |
| 2 — Contract controls | What the vault contract itself enforces | Blocks |
| 3 — Policy | Interpreted business policy | Escalates to a human |
| 4 — Approval | The decision to require a person | Holds for approval |
| 5 — Supervisor | LLM-assisted review (warn / freeze / escalate) | Cannot authorise |
Layer 5 can only ever make the system more cautious. There is no code path where a supervisor verdict releases an action that layer 1–4 refused.
Rule reference
Every rule returns a fact other than pass/fail: a stated reason. Rules marked blocking refuse the action; the rest escalate to approval.
| Rule id | Layer | Blocks | Checks |
|---|---|---|---|
| math.balance_sufficient | 1 | Yes | The pool has the liquid funds. |
| math.min_reserve_preserved | 1 | Yes | The payment does not breach the pool’s reserve floor. |
| math.treasury_reserve_preserved | 1 | Yes | The treasury minimum reserve across pools is kept. |
| math.committed_funds_protected | 1 | Yes | Committed obligations stay funded. |
| math.idempotency_unique | 1 | Yes | This intent has not already produced an action. |
| math.max_transaction_size | 1 | No | Amount is within the per-transaction limit. |
| math.daily_autonomous_limit | 1 | No | Today’s autonomous spend stays within the daily limit. |
| math.account_recoverability_requirement | 1 | No | The class meets the account’s minimum recoverability. |
| contract.escrow_available | 2 | No | The amount is within what the vault will hold in escrow. |
| contract.spend_ceiling | 2 | No | The vault’s per-transaction and per-day ceilings. |
| contract.recipient_allowlist | 2 | No | The recipient is on the vault’s allowlist. |
| contract.freeze_control | 2 | No | The vault is not paused. |
| policy.recipient_changed | 3 | Yes | The recipient’s wallet details changed — frozen. |
| policy.new_counterparty | 3 | No | First payment to an unknown counterparty. |
| policy.amount_anomaly | 3 | No | Amount is within 3× the counterparty’s own median. |
| policy.document_anchor | 3 | No | A qualifying payment cites its supporting document. |
| policy.irreversible_scrutiny | 3 | No | R4 actions are looked at by a person. |
| policy.new_counterparties_scrutiny | 3 | No | Several new counterparties in one window. |
| policy.prefer_early_strategic_vendors | 3 | No | Preference ordering among vendors. |
| policy.preserve_extra_liquidity | 3 | No | Holds more liquidity than the floor requires. |
Seeded policy values
The defaults a new organization starts with. All are editable policy rows, not constants.
| Key | Default | Controls |
|---|---|---|
| min_reserve | $10,000 | Treasury minimum reserve. |
| daily_autonomous_limit | $5,000 | Maximum autonomous spend per day. |
| max_transaction_size | $25,000 | Largest single transaction. |
| escrow_max_amount | $15,000 | Largest amount held in escrow (above it → R4). |
| document_anchor_threshold | $10,000 | Above it, a payment must cite a document. |
| new_recipient_max_amount | $2,000 | Largest autonomous first payment. |
| anomaly_multiplier | 3 | Multiple of a counterparty’s median that is “normal”. |
| obligation_horizon_days | 30 | Commitment horizon for reserve maths. |
| min_runway_days | 45 | Minimum runway floor. |
| invest_horizon_days | 7 | Do not invest funds needed within this window. |
| daily_autonomous_invest_limit | $50,000 | Autonomous investment cap per day. |
| lazarus_window_minutes | 30 | Cancellable window on a staged payment. |
| onchain_max_per_tx | $25,000 | Vault ceiling — per transaction. |
| onchain_max_per_day | $100,000 | Vault ceiling — per day. |
| require_approval_irreversible | true | R4 always needs a human. |
Reading a decision
The API returns every rule result, so the reason a payment was refused is never a mystery. The failing rule’s detail states the numbers involved, and blockedBy lists only the blocking failures. See Approval and Supervisor.