Skip to content

Commit 658e4df

Browse files
authored
feat(PR23): Machine Wallet Guardrails - guide, wallet integration example, threat model (#33)
1 parent cb00e55 commit 658e4df

7 files changed

Lines changed: 444 additions & 0 deletions

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Machine Wallet Guardrails Example
2+
3+
Runnable example demonstrating MPCP as a **machine wallet guardrail layer**.
4+
5+
## Overview
6+
7+
A machine wallet should not send funds unless payment requests satisfy:
8+
9+
- **PolicyGrant** constraints (rails, assets, expiration)
10+
- **SignedBudgetAuthorization** session limits (max amount, destination allowlist)
11+
- **SignedPaymentAuthorization** approval rules (amount binding, intent hash)
12+
13+
This example shows the integration pattern: check all three layers before signing.
14+
15+
## Run
16+
17+
```bash
18+
npm run build
19+
npm run example:wallet-guardrails
20+
```
21+
22+
Or:
23+
24+
```bash
25+
node examples/machine-wallet-guardrails/wallet-integration.mjs
26+
```
27+
28+
## What It Demonstrates
29+
30+
1. **Allowed request** — $15 to rParking passes all checks; SPA is signed
31+
2. **Wrong destination** — $5 to rAttacker is rejected (not in allowlist)
32+
3. **Would exceed budget** — $20 to rCharging when session already spent $15 is rejected
33+
34+
## Guardrail Check Flow
35+
36+
```
37+
Payment request → PolicyGrant check → SBA check → Sign SPA (or reject)
38+
```
39+
40+
See [Machine Wallet Guardrails](../implementation/machine-wallet-guardrails.md) for the full guide and threat model.
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# Machine Wallet Guardrails
2+
3+
MPCP acts as a **machine wallet guardrail layer**. A machine wallet should not send funds unless payment requests satisfy PolicyGrant constraints, SignedBudgetAuthorization session limits, and SignedPaymentAuthorization approval rules.
4+
5+
This guide describes the guardrail model, how to integrate it into a machine wallet, and threat-model considerations.
6+
7+
## The Guardrail Model
8+
9+
MPCP provides three layers of enforcement before a machine can pay:
10+
11+
| Layer | Artifact | Purpose |
12+
|-------|----------|---------|
13+
| 1 | PolicyGrant | Fleet-level constraints: allowed rails, assets, expiration |
14+
| 2 | SignedBudgetAuthorization (SBA) | Session spending envelope: max amount, destination allowlist |
15+
| 3 | SignedPaymentAuthorization (SPA) | Payment binding: specific amount, destination, intent hash |
16+
17+
**Rule:** The wallet must not sign an SPA unless the requested payment passes all three checks.
18+
19+
### Layer 1: PolicyGrant
20+
21+
- **Rails** — Is the settlement rail (xrpl, evm, etc.) permitted?
22+
- **Assets** — Is the asset (e.g. RLUSD IOU) in the allowed set?
23+
- **Expiration** — Has the grant expired?
24+
25+
### Layer 2: SignedBudgetAuthorization (SBA)
26+
27+
- **Max amount** — Does the requested amount fit within `maxAmountMinor`?
28+
- **Destination** — Is the payee in `destinationAllowlist`?
29+
- **Cumulative spend** — For session budgets, has the session already spent up to the limit?
30+
- **Expiration** — Has the budget expired?
31+
32+
### Layer 3: SignedPaymentAuthorization (SPA)
33+
34+
- **Amount binding** — SPA commits to a specific amount and destination
35+
- **Intent hash** — SPA binds to a canonical SettlementIntent
36+
- **Tamper resistance** — Settlement must match the signed authorization
37+
38+
## Wallet Integration
39+
40+
A machine wallet integrates MPCP by performing checks *before* signing an SPA.
41+
42+
### Decision Flow
43+
44+
```
45+
Payment request received
46+
47+
Check PolicyGrant (rail, asset, expiry)
48+
↓ PASS
49+
Check SBA (amount ≤ remaining, destination in allowlist, expiry)
50+
↓ PASS
51+
Create SettlementIntent + SPA
52+
53+
Sign SPA
54+
55+
Return SPA (and optional SettlementIntent) to payee
56+
```
57+
58+
### Integration Checklist
59+
60+
Before signing an SPA, the wallet **must**:
61+
62+
1. Validate the payment request against the loaded PolicyGrant
63+
2. Validate against the loaded SBA (amount, destination, session balance)
64+
3. Create a canonical SettlementIntent for the requested payment
65+
4. Use `createSignedPaymentAuthorization` with the policy decision and intent
66+
5. Never sign if any check fails
67+
68+
See the [wallet integration example](../examples/machine-wallet-guardrails.md) for a runnable implementation.
69+
70+
## Bounded Authorization
71+
72+
MPCP emphasizes **bounded authorization**: the machine is given a spending envelope, not open-ended access.
73+
74+
- **Pre-authorized** — Policy and budget are set before the session
75+
- **Cryptographically enforced** — SBA and SPA are signed; tampering is detectable
76+
- **Local verification** — The verifier (e.g. parking meter) can validate the chain without calling a central API
77+
78+
This makes MPCP attractive to fleet and robotics teams who need machines to spend money safely at scale.
79+
80+
---
81+
82+
## Threat Model: Overspend and Misuse Prevention
83+
84+
### Threat: Overspend
85+
86+
**Scenario:** An attacker or bug causes the machine to pay more than authorized.
87+
88+
**Mitigations:**
89+
90+
| Mitigation | How MPCP Helps |
91+
|------------|----------------|
92+
| SBA max amount | SPA binds to a specific amount; settlement above SBA limit is invalid |
93+
| Session balance tracking | Wallet tracks cumulative spend; refuses SPA if would exceed budget |
94+
| Verifier checks | Verifier validates amount ≤ SBA maxAmountMinor |
95+
| Deterministic verification | `mpcp verify` fails if settlement does not match SPA |
96+
97+
**Wallet responsibility:** Track session spend. Do not sign SPA if `requested amount + sessionSpent > maxAmountMinor`.
98+
99+
### Threat: Wrong Destination
100+
101+
**Scenario:** Funds are sent to an unauthorized recipient.
102+
103+
**Mitigations:**
104+
105+
| Mitigation | How MPCP Helps |
106+
|------------|----------------|
107+
| Destination allowlist | SBA `destinationAllowlist` constrains payees |
108+
| SPA binding | SPA commits to specific destination; cannot be redirected |
109+
| Verifier checks | Verifier validates destination in allowlist |
110+
111+
**Wallet responsibility:** Reject payment requests whose destination is not in `destinationAllowlist`.
112+
113+
### Threat: Unauthorized Rail or Asset
114+
115+
**Scenario:** Machine pays on a disallowed rail or with a disallowed asset.
116+
117+
**Mitigations:**
118+
119+
| Mitigation | How MPCP Helps |
120+
|------------|----------------|
121+
| PolicyGrant | allowedRails, allowedAssets |
122+
| SBA | SBA must match policy |
123+
| Verifier | Validates rail and asset consistency across chain |
124+
125+
**Wallet responsibility:** Reject requests for rails or assets not in PolicyGrant/SBA.
126+
127+
### Threat: Replay and Tampering
128+
129+
**Scenario:** Reuse of old SPA, or modification of settlement after signing.
130+
131+
**Mitigations:**
132+
133+
| Mitigation | How MPCP Helps |
134+
|------------|----------------|
135+
| Intent hash | SPA binds to canonical SettlementIntent; changed amount/destination invalidates hash |
136+
| Signatures | SBA and SPA are signed; tampering breaks verification |
137+
| Expiration | All artifacts have expiresAt; expired chain fails verify |
138+
139+
**Wallet responsibility:** Never reuse an SPA. Create a fresh SPA per payment.
140+
141+
### Threat: Key Compromise
142+
143+
**Scenario:** SPA or SBA signing key is stolen.
144+
145+
**Mitigations:**
146+
147+
- SBA keys are typically held by fleet/issuer; compromise affects one fleet
148+
- SPA keys are per-machine; rotate if compromised
149+
- Budget limits (maxAmountMinor) bound maximum loss per session
150+
- Short session expirations reduce exposure window
151+
152+
**Recommendation:** Use short-lived budgets for high-risk environments. Rotate SPA keys if compromise is suspected.
153+
154+
---
155+
156+
## Summary
157+
158+
- **Three-layer guardrail:** PolicyGrant → SBA → SPA
159+
- **Wallet rule:** Do not sign SPA unless all checks pass
160+
- **Threats addressed:** Overspend, wrong destination, wrong rail/asset, replay/tampering, key compromise
161+
- **Bounded authorization:** Pre-authorized limits, cryptographic enforcement, local verification
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Machine Wallet Guardrails
2+
3+
Runnable example showing how a machine wallet integrates MPCP guardrails before signing payments.
4+
5+
## Concept
6+
7+
A machine wallet should **not** send funds unless the payment request satisfies:
8+
9+
1. **PolicyGrant** — Rail, asset, expiration
10+
2. **SignedBudgetAuthorization (SBA)** — Session limits, destination allowlist
11+
3. **SignedPaymentAuthorization (SPA)** — Payment binding (amount, destination)
12+
13+
## Wallet Integration Example
14+
15+
`wallet-integration.mjs` demonstrates the check-before-sign flow:
16+
17+
- Load PolicyGrant and SBA
18+
- For each payment request: check guardrails, sign SPA only if all pass
19+
- Rejects: wrong destination, overspend, wrong rail/asset
20+
- Prints allowed vs rejected scenarios
21+
22+
**Run:**
23+
24+
```bash
25+
npm run build
26+
node examples/machine-wallet-guardrails/wallet-integration.mjs
27+
```
28+
29+
## Full Flow Demo
30+
31+
For a complete narrative demo (policy → budget → SPA → verification → tamper detection), see:
32+
33+
```bash
34+
npm run example:guardrails
35+
```
36+
37+
Or `examples/parking/demo-guardrails.mjs`.
38+
39+
## Guide
40+
41+
See [Machine Wallet Guardrails](../../docs/implementation/machine-wallet-guardrails.md) for the full guardrail model, integration checklist, and threat-model notes.

0 commit comments

Comments
 (0)