Keeper evaluates the policy's rules together to determine whether an action is allowed and which approvals it needs. Evaluation continues after a rule matches.
Allow and deny
allow "small-payment" if (request.amount > 0 and request.amount <= 1000)
deny "blocked-country" if (request.country in ["XX", "YY"])
Each rule condition must be Boolean. Use when { ... } instead of if (...) when several checks are clearer on separate lines. The text label is optional. The compiler assigns an identifier to an unlabeled rule. Labels appear in decision results and help explain a match.
The decision follows these rules:
- Any matching
denymakes the decision deny. - Otherwise, any matching
allowpermits the action, subject to its approval requirements. - If no allow matches, the fallback decides. It is deny unless the document declares
default allow.
Conditions of later rules still run after an allow or deny matches. A failing expression stops evaluation even if an earlier rule allowed the action.
Declare eligible approvers
An approver declaration specifies a credential that a requirement can select. For an inline public key:
approver reviewer {
type = "public-key"
id = "treasury-reviewer"
algorithm = "ED25519"
publicKey64 = "11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo="
}
This is a test public key. Replace it with the reviewer's key. The alias reviewer is the name used in source expressions. id identifies the approver. Declarations do not themselves request an approval.
To use a registered Signature or WebAuthn credential, pin its returned reference:
approver reviewer {
type = "reference"
id = "treasury-reviewer"
ref = "treasury-reviewer@sha256:<credential-digest>"
}
Replace the placeholder with the exact reference from registration. Keeper resolves and validates that credential when loading the authority. A metadata change does not replace the pinned credential. See Approvers API for registration.
Add approval requirements
require reviewer if (request.amount > 100)
require 2 of [finance, security] if (request.amount > 500)
require reviewer means one approval from that approver. require 2 of [...] requires two distinct eligible approvers from the list. Omitting the condition makes the requirement unconditional.
A requirement does not grant allow. The action must also pass an allow rule or an allowing fallback. Every matching requirement accumulates and must be satisfied. Another matching allow cannot remove one.
To require both finance and security approval, declare a requirement for each group. A 1 of [finance, security] requirement accepts either approver.
Complete reviewed-payment policy
authority "reviewed-payment" {
intent = "custom"
version = "1"
input request { amount: Number }
approver reviewer {
type = "public-key"
id = "treasury-reviewer"
algorithm = "ED25519"
publicKey64 = "11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo="
}
policy "reviewed-payment" {
allow if (request.amount > 0 and request.amount <= 1000)
require reviewer if (request.amount > 100)
}
}
| Amount | Policy result |
|---|---|
0 or a negative number |
Deny |
100 |
Allow |
100.01 through 1000 |
Allow with the reviewer's approval |
Greater than 1000 |
Deny |
Keeper verifies the proof against the operation being signed. The policy only declares the eligible approvers and threshold. It cannot create a proof or accept an unverified assertion that approval happened. Four-eye control covers preparation, expiry, and replay protection.
Fallback behavior
default deny states the normal fallback explicitly. default allow permits actions when no allow matches and no deny matches, so it requires careful limits through deny rules.
default allow require reviewer
This requirement applies to fallback approval when no explicit allow rule matched. Explicit allow rules use their own requirements. If every permitted action needs a reviewer, use an unconditional require reviewer alongside the allow rules.
Requests containing several actions
Some native intents, including payment mandates, evaluate several actions. Every action must be permitted. One denied action denies the request, and requirements from all permitted actions accumulate. A native policy that receives one list of calls can instead constrain that whole list directly. The intent guide defines which input model it uses.
Continue with Native transaction policies.