Web 4

Doctrine, not aspiration

Principles

Five principles govern what the estate builds and what it refuses to build. Each is enforced somewhere by a test, a gate, or the absence of a parameter — phrased as a refusal, because a guideline is a sentence an agent can be prompted past and a missing parameter is not.

1 Minor units only

Every figure is `{ minor, currency }` — a whole number of minor units beside an explicit currency. A float anywhere in a policy, a payment or a ledger state is refused, and the CLI refuses `2500.0` in the file text before JSON.parse can quietly round it. A figure with no currency is not money; a string is not an integer.

2 Narrowing only

A policy attenuated for a sub-agent may only narrow: caps ≤, allowlists ⊆, rails ⊆, jurisdictions ⊆, human gate ≤, same currency, same period. `attenuate(parent, child)` refuses any widening and names every widened dimension.

3 A human gate on money is mandatory

Any policy whose per-transaction cap is above zero must carry `humanApprovalAbove`, strictly below that cap — a gate no permitted payment can reach is a missing gate. `0` escalates everything; a closed policy that can pay nobody may omit it.

4 A pure evaluator

`evaluate(policy, payment, ledgerState)` reads no clock, opens no connection and mutates nothing. The period's spent-so-far is injected, never fetched — and when a period is capped and no ledger state is supplied, the answer is `deny`, because unknown is not zero.

5 allow / deny / escalate, with reasons

`deny` and `escalate` always carry `{ code, message }` reasons, and every failing check is named rather than only the first. `allow` carries none and never widens beyond what the policy says: a payment above the human threshold is `escalate`, never `allow`.