Policy Language
Bundles and rules
A bundle is a header plus an unordered set of rules. A rule is a guard, an effect, and reviewable metadata.
The bundle header pins the policy identity, the version, the schema the bundle is type-checked against, and the semantic mode. Everything after the header is rules. Because rule order is meaningless, a bundle diff is a set diff: rules added, rules removed, rules changed. Review tools, the analyzer, and governance all operate on that set structure.
Rules carry signed artifact metadata: a stable rule identifier, a title, an optional control reference into the institution's control framework, an owner, and a review-by date. Audit answers such as “which rules implement control CTRL-PAY-004 and when were they last reviewed” are computed from the artifact itself.
Rule anatomy
Three kinds. forbid denies, permit admits, require attaches obligations while preserving the verdict.
permit rule treasury-large-transfers
title "Treasury: large transfers under dual control"
control "CTRL-PAY-004"
owner treasury.desk-head
review-by 2027-01-31
when operation == Sign
and payload is PlainTransfer
and asset == USDC
and amount > USDC 10_000
and destination in set treasury_counterparties
require approval 2 of group treasury_officers within 4h
where approver != requester
require approval 1 of group risk_office within 4h
require meter tenant_daily_notional
add notional_usd(amount) limit USD 5_000_000 per 24hClause discipline
The verifier enforces which clauses each rule kind may carry.
forbid:when, optionalunless, mandatoryreason; produces a reasoned DENY.permit:when, optionalunless, optionalrequireblock; admits matching operations and attaches permit-local obligations.require:when, optionalunless, mandatoryrequireblock; attaches obligations under property P4.
Authoring frontends
The canonical artifact is the typed AST. The .dpl text form and the console rule builder are two frontends producing the same AST; compiling either yields the same package root. Text serves review workflows and version control; the builder serves operators. Both feed the same compiler path.