Constraints¶
Constraints are the typed rules that bound what a LedgerFlow warrant authorizes. Unlike generic policy languages, LedgerFlow uses a closed set of constraint types — each with clear semantics, verifiable without external state.
Design Rationale¶
Generic policy engines (OPA, Cedar, CEL) are powerful but introduce complexity:
- Schema compilation and evaluation overhead
- Risk of policy misconfiguration
- Difficulty in static analysis and auditing
LedgerFlow v1 uses typed constraints — a fixed set of structures the verifier can check with simple field comparisons. This keeps verification fast, audit-friendly, and safe.
Constraint Types¶
Merchant Constraint¶
Restricts which merchants can accept the warrant.
pub struct MerchantConstraint {
pub merchant_ids: Vec<String>, // stable merchant identifiers
pub host_suffixes: Vec<String>, // hostname suffixes (e.g., "api.example.com")
}
- Empty
merchant_idsandhost_suffixesmeans any merchant - Both fields present: merchant must match at least one entry in either field
- Host suffixes support wildcard-like matching:
".example.com"matches"api.example.com"
Resource Constraint¶
Restricts which HTTP resources the agent may access.
pub struct ResourceConstraint {
pub http_methods: Vec<String>, // e.g., ["GET", "POST"]
pub path_prefixes: Vec<String>, // e.g., ["/api/v1/data", "/v2/query"]
}
- Empty
http_methodsallows all methods - Empty
path_prefixesallows all paths - Path prefix matching is prefix-based:
/api/v1matches/api/v1/resource
Tool Constraint¶
Restricts which AI tools, models, or actions the agent may invoke. This is the AI-native constraint.
pub struct ToolConstraint {
pub tool_names: Vec<String>, // e.g., ["web_search", "code_execution"]
pub model_providers: Vec<String>, // e.g., ["openai", "anthropic"]
pub action_labels: Vec<String>, // e.g., ["read", "generate"]
}
The merchant maps request context to these labels before verification. LedgerFlow does not need to understand model internals — it only checks labels.
Payment Constraint¶
Restricts the financial parameters of authorized payments.
pub struct PaymentConstraint {
pub max_per_request: AmountLimit,
pub period_limit: Option<PeriodLimit>,
pub allowed_assets: Vec<AssetRef>,
pub allowed_rails: Vec<PaymentRail>,
pub allowed_schemes: Vec<String>,
pub payee_ids: Vec<String>,
}
| Field | Description |
|---|---|
max_per_request |
Maximum amount per single payment |
period_limit |
Optional rolling window limit (e.g., $100/day) |
allowed_assets |
Which assets are allowed (e.g., USDC, USDT) |
allowed_rails |
High-level rails: Onchain, Exchange, Custodial, TraditionalGateway |
allowed_schemes |
Specific x402 settlement schemes |
payee_ids |
Bind to specific merchant-facing payee identities |
Sponsorship Constraint¶
Controls whether the agent can use sponsored execution (e.g., gas sponsorship, paymaster).
pub struct SponsorshipConstraint {
pub allow_sponsored_execution: bool,
pub sponsor_ids: Vec<String>,
}
This authorizes sponsored execution without pushing paymaster or contract logic into LedgerFlow core.
Constraint Composition¶
All constraints in a warrant are AND-composed. The warrant authorizes a payment only if every constraint passes.
To grant broader authority, issue multiple warrants or use fewer constraints.
Attenuation Rules¶
When delegating a warrant, constraints can only be narrowed, never expanded:
| Parent Constraint | Delegation Rule |
|---|---|
merchant_ids: [A, B] |
Sub-warrant: subset of [A, B] or same |
max_per_request: 100 |
Sub-warrant: <= 100 |
tool_names: [T1, T2] |
Sub-warrant: subset of [T1, T2] |
expires_at: T |
Sub-warrant: <= T |
max_depth: 3 |
Sub-warrant: < 3 |
This monotonic property is enforced at warrant issuance time, not at verification time.
Constraint Examples¶
Example 1: Research Agent¶
Authorize an agent to query data APIs with a $5 per-request limit:
{
"constraints": [
{
"kind": "merchant",
"host_suffixes": [".data-provider.io"]
},
{
"kind": "resource",
"http_methods": ["GET"],
"path_prefixes": ["/api/v1/query"]
},
{
"kind": "payment",
"max_per_request": { "amount": "5000000", "asset": "USDC" },
"allowed_rails": ["Onchain"]
}
]
}
Example 2: Code Agent with Tool Scope¶
Authorize an agent to use specific AI tools on a single merchant:
{
"constraints": [
{
"kind": "merchant",
"merchant_ids": ["code-execution-platform"]
},
{
"kind": "tool",
"tool_names": ["sandbox_run", "lint_check"],
"model_providers": ["anthropic"]
},
{
"kind": "payment",
"max_per_request": { "amount": "1000000", "asset": "USDC" },
"period_limit": { "amount": "10000000", "period_seconds": 86400 }
}
]
}
Example 3: Delegated Sub-Agent¶
A parent warrant holder delegates to a sub-agent with reduced scope:
{
"constraints": [
{
"kind": "merchant",
"merchant_ids": ["data-provider-1"]
},
{
"kind": "payment",
"max_per_request": { "amount": "100000", "asset": "USDC" }
}
],
"delegation": { "can_delegate": false, "max_depth": 0 }
}
Future Extensions¶
LedgerFlow v2 may add:
- Period-based constraints with ZedToken-like consistency
- Conditional constraints using typed context evaluation
- Constraint sets for multi-tenant warrants
- Constraint templates for common authorization patterns
See Also¶
- Protocol — Wire format and proof model
- Core Concepts — Warrants, delegation, and identity
- Security — How constraints are enforced