Skip to content

Commit 340dd5e

Browse files
naoryNAOR YUVALclaude
authored
feat(PR25): human-to-agent delegation profile (#41)
Extends MPCP to support human DID principals delegating bounded spending authority to AI agents via PolicyGrant. Schema / types: - PolicyGrantLike + CreatePolicyGrantInput: revocationEndpoint, allowedPurposes - BudgetScope: add TRIP for multi-day/multi-session delegations - budgetScopeSchema: add TRIP - policyGrantForVerificationSchema: add both new fields - SBA verifier: accept TRIP scope alongside SESSION New utility: - src/protocol/revocation.ts: checkRevocation() — async endpoint check with timeout; verifier stays stateless and synchronous - Exported from sdk/index.ts Demo: - examples/human-agent-trip/: Alice delegates $800 Paris trip to AI agent Shows purpose filtering, budget enforcement, post-trip audit, revocation - npm run example:human-agent-trip Tests: - test/protocol/revocation.test.ts (8 tests) - test/schema/artifact-schemas.test.ts: TRIP scope - test/protocol/policyGrant.test.ts: revocationEndpoint + allowedPurposes Co-authored-by: NAOR YUVAL <naoryuval@NAORs-MacBook-Air.local> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 94d1aaa commit 340dd5e

17 files changed

Lines changed: 1194 additions & 4 deletions
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Human-to-Agent Travel Budget Demo
2+
3+
Demonstrates MPCP's human-to-agent delegation pattern: Alice signs a PolicyGrant with her DID key,
4+
delegating an $800 travel budget to her AI trip planner for a 3-day Paris trip.
5+
6+
## Delegation chain
7+
8+
```
9+
Alice (DID key) → PolicyGrant → AI Agent → SBA (TRIP scope) → SPA → Settlement
10+
```
11+
12+
This mirrors the fleet pattern exactly:
13+
14+
```
15+
Fleet Operator (DID) → PolicyGrant → Vehicle Wallet → SBA → SPA → Settlement
16+
Human (DID) → PolicyGrant → AI Agent → SBA → SPA → Settlement
17+
```
18+
19+
## What this demo shows
20+
21+
| Feature | Demo behavior |
22+
|---------|--------------|
23+
| `allowedPurposes` | Agent enforces category filter — dining request skipped |
24+
| `revocationEndpoint` | Alice cancels mid-trip; `checkRevocation()` returns `{ revoked: true }` |
25+
| TRIP scope | Single SBA covers all 3 days, agent tracks cumulative spend |
26+
| Budget exceeded | $300 hotel attempt rejected ($550 + $300 > $800) |
27+
| Stateless verifier | Merchant verifies chain without calling Alice's wallet |
28+
| DID-signed PolicyGrant | Human principal, not fleet operator |
29+
30+
## Stops
31+
32+
| # | Service | Amount | Outcome |
33+
|---|---------|--------|---------|
34+
| 1 | Hotel (Mercure Paris) | $250 | Authorized |
35+
| 2 | Eurostar tickets | $120 | Authorized |
36+
| 3 | Restaurant booking || Skipped (`travel:dining` not in `allowedPurposes`) |
37+
| 4 | Car rental (Europcar) | $180 | Authorized |
38+
| 5 | Extra hotel night | $300 | Rejected (budget exceeded: $550 + $300 > $800) |
39+
40+
## Key fields
41+
42+
### PolicyGrant (signed by Alice)
43+
44+
```json
45+
{
46+
"allowedPurposes": ["travel:hotel", "travel:flight", "travel:transport"],
47+
"revocationEndpoint": "https://wallet.alice.example.com/revoke",
48+
"issuer": "did:key:z6Mk..."
49+
}
50+
```
51+
52+
### SBA (created by AI agent)
53+
54+
```json
55+
{
56+
"budgetScope": "TRIP",
57+
"maxAmountMinor": "80000",
58+
"vehicleId": "ai-trip-planner-v2"
59+
}
60+
```
61+
62+
### Revocation check
63+
64+
```javascript
65+
const { revoked, revokedAt } = await checkRevocation(endpoint, grantId);
66+
// → { revoked: true, revokedAt: "2026-04-11T14:22:00Z" }
67+
```
68+
69+
## Run
70+
71+
```bash
72+
npm run build && npm run example:human-agent-trip
73+
```
74+
75+
## See also
76+
77+
- [`docs/profiles/human-agent-profile.md`](../../mpcp-spec/docs/profiles/human-agent-profile.md)
78+
- [`src/protocol/revocation.ts`](../../src/protocol/revocation.ts)
79+
- Fleet trip demo: [`examples/fleet-trip/`](../fleet-trip/)
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
{
2+
"settlement": {
3+
"amount": "250000000",
4+
"rail": "xrpl",
5+
"asset": {
6+
"kind": "IOU",
7+
"currency": "RLUSD",
8+
"issuer": "rIssuer"
9+
},
10+
"destination": "rHotelMercureParis",
11+
"nowISO": "2026-04-10T15:00:00Z"
12+
},
13+
"settlementIntent": {
14+
"version": "1.0",
15+
"rail": "xrpl",
16+
"amount": "250000000",
17+
"createdAt": "2026-04-10T15:00:00Z",
18+
"destination": "rHotelMercureParis",
19+
"asset": {
20+
"kind": "IOU",
21+
"currency": "RLUSD",
22+
"issuer": "rIssuer"
23+
}
24+
},
25+
"spa": {
26+
"authorization": {
27+
"version": "1.0",
28+
"decisionId": "dec-hotel-001",
29+
"sessionId": "paris-trip-2026-alice",
30+
"policyHash": "a1b2c3d4e5f6",
31+
"budgetId": "b597142d-d0a3-416b-9494-a2ebfdc36232",
32+
"quoteId": "q-hotel-001",
33+
"rail": "xrpl",
34+
"asset": {
35+
"kind": "IOU",
36+
"currency": "RLUSD",
37+
"issuer": "rIssuer"
38+
},
39+
"amount": "250000000",
40+
"destination": "rHotelMercureParis",
41+
"intentHash": "d7a7c201c1f42401b9f0209482c560396d7caf8365a69d0cb1f92848c98adfed",
42+
"expiresAt": "2030-12-31T23:59:59Z",
43+
"nonce": "3794c12e-369e-4ff3-9092-b583bcb398e6"
44+
},
45+
"issuerKeyId": "agent-spa-key-1",
46+
"signature": "Og+BPRUdt/G01MnZh84vLCrvnMNPYqvxkiAAowqU/zuDvOORGtL++bxOfUm+2JM0n+13JytNtPJFce2ZnB98Aw=="
47+
},
48+
"sba": {
49+
"authorization": {
50+
"version": "1.0",
51+
"budgetId": "b597142d-d0a3-416b-9494-a2ebfdc36232",
52+
"grantId": "1aae4310-fbe4-4efb-b53b-67bbb69eeb9d",
53+
"sessionId": "paris-trip-2026-alice",
54+
"vehicleId": "ai-trip-planner-v2",
55+
"policyHash": "a1b2c3d4e5f6",
56+
"currency": "USD",
57+
"minorUnit": 2,
58+
"budgetScope": "TRIP",
59+
"maxAmountMinor": "80000",
60+
"allowedRails": [
61+
"xrpl"
62+
],
63+
"allowedAssets": [
64+
{
65+
"kind": "IOU",
66+
"currency": "RLUSD",
67+
"issuer": "rIssuer"
68+
}
69+
],
70+
"destinationAllowlist": [
71+
"rHotelMercureParis",
72+
"rEurostar",
73+
"rEuropcarParis"
74+
],
75+
"expiresAt": "2030-12-31T23:59:59Z"
76+
},
77+
"issuerKeyId": "agent-sba-key-1",
78+
"signature": "5keYWTKG/h1c0c2JGGcKwmJNbL7+V/5UCQMyz14Nz/gpW7KWRVycZ4RdagckpuOOX1ig/AtpK414xbrrTaP6Cw=="
79+
},
80+
"policyGrant": {
81+
"grantId": "1aae4310-fbe4-4efb-b53b-67bbb69eeb9d",
82+
"policyHash": "a1b2c3d4e5f6",
83+
"expiresAt": "2030-12-31T23:59:59Z",
84+
"allowedRails": [
85+
"xrpl"
86+
],
87+
"allowedAssets": [
88+
{
89+
"kind": "IOU",
90+
"currency": "RLUSD",
91+
"issuer": "rIssuer"
92+
}
93+
],
94+
"revocationEndpoint": "https://wallet.alice.example.com/revoke",
95+
"allowedPurposes": [
96+
"travel:hotel",
97+
"travel:flight",
98+
"travel:transport"
99+
],
100+
"issuer": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
101+
"issuerKeyId": "alice-did-key-1",
102+
"signature": "Wr2m1JmmPzzVJ7lkAqhGPPHOnVzL+9oF4Fr84JDDX/hKWPmfZfjPKdWes7EvQxZ+vydmjKAP1IHGjrgBMh70BQ=="
103+
},
104+
"paymentPolicyDecision": {
105+
"decisionId": "dec-hotel-001",
106+
"policyHash": "a1b2c3d4e5f6",
107+
"action": "ALLOW",
108+
"reasons": [
109+
"Within budget",
110+
"Purpose authorized",
111+
"Destination authorized"
112+
],
113+
"expiresAtISO": "2030-12-31T23:59:59Z",
114+
"rail": "xrpl",
115+
"asset": {
116+
"kind": "IOU",
117+
"currency": "RLUSD",
118+
"issuer": "rIssuer"
119+
},
120+
"priceFiat": {
121+
"amountMinor": "25000",
122+
"currency": "USD"
123+
},
124+
"chosen": {
125+
"rail": "xrpl",
126+
"quoteId": "q-hotel-001"
127+
},
128+
"settlementQuotes": [
129+
{
130+
"quoteId": "q-hotel-001",
131+
"rail": "xrpl",
132+
"amount": {
133+
"amount": "250000000",
134+
"decimals": 6
135+
},
136+
"destination": "rHotelMercureParis",
137+
"expiresAt": "2030-12-31T23:59:59Z",
138+
"asset": {
139+
"kind": "IOU",
140+
"currency": "RLUSD",
141+
"issuer": "rIssuer"
142+
}
143+
}
144+
]
145+
},
146+
"sbaPublicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAyruO/mCPiFMN58KD2MNnt1XXOx2pi3menrxgj8ErYJ8=\n-----END PUBLIC KEY-----\n",
147+
"spaPublicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAHsx6sy9p36RfOiPe7m+AVrES7Sqfoy4rPJsbRr5QHkA=\n-----END PUBLIC KEY-----\n"
148+
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
{
2+
"settlement": {
3+
"amount": "120000000",
4+
"rail": "xrpl",
5+
"asset": {
6+
"kind": "IOU",
7+
"currency": "RLUSD",
8+
"issuer": "rIssuer"
9+
},
10+
"destination": "rEurostar",
11+
"nowISO": "2026-04-11T08:30:00Z"
12+
},
13+
"settlementIntent": {
14+
"version": "1.0",
15+
"rail": "xrpl",
16+
"amount": "120000000",
17+
"createdAt": "2026-04-11T08:30:00Z",
18+
"destination": "rEurostar",
19+
"asset": {
20+
"kind": "IOU",
21+
"currency": "RLUSD",
22+
"issuer": "rIssuer"
23+
}
24+
},
25+
"spa": {
26+
"authorization": {
27+
"version": "1.0",
28+
"decisionId": "dec-train-001",
29+
"sessionId": "paris-trip-2026-alice",
30+
"policyHash": "a1b2c3d4e5f6",
31+
"budgetId": "b597142d-d0a3-416b-9494-a2ebfdc36232",
32+
"quoteId": "q-train-001",
33+
"rail": "xrpl",
34+
"asset": {
35+
"kind": "IOU",
36+
"currency": "RLUSD",
37+
"issuer": "rIssuer"
38+
},
39+
"amount": "120000000",
40+
"destination": "rEurostar",
41+
"intentHash": "2fee5e6437ebc327e7281c06f7f11f4d1c098b255cbc846a77e23554b3a732d0",
42+
"expiresAt": "2030-12-31T23:59:59Z",
43+
"nonce": "2f680707-a541-460c-8d5a-e6fd5a736124"
44+
},
45+
"issuerKeyId": "agent-spa-key-1",
46+
"signature": "4eICYdryBOHj+dNO1M1+wpYDcmPNchhl5d/64pNm+qJbuXLvnl5yz7aEiBY+DS8B/EVaHrGgaq4+iC6FoCLjCg=="
47+
},
48+
"sba": {
49+
"authorization": {
50+
"version": "1.0",
51+
"budgetId": "b597142d-d0a3-416b-9494-a2ebfdc36232",
52+
"grantId": "1aae4310-fbe4-4efb-b53b-67bbb69eeb9d",
53+
"sessionId": "paris-trip-2026-alice",
54+
"vehicleId": "ai-trip-planner-v2",
55+
"policyHash": "a1b2c3d4e5f6",
56+
"currency": "USD",
57+
"minorUnit": 2,
58+
"budgetScope": "TRIP",
59+
"maxAmountMinor": "80000",
60+
"allowedRails": [
61+
"xrpl"
62+
],
63+
"allowedAssets": [
64+
{
65+
"kind": "IOU",
66+
"currency": "RLUSD",
67+
"issuer": "rIssuer"
68+
}
69+
],
70+
"destinationAllowlist": [
71+
"rHotelMercureParis",
72+
"rEurostar",
73+
"rEuropcarParis"
74+
],
75+
"expiresAt": "2030-12-31T23:59:59Z"
76+
},
77+
"issuerKeyId": "agent-sba-key-1",
78+
"signature": "5keYWTKG/h1c0c2JGGcKwmJNbL7+V/5UCQMyz14Nz/gpW7KWRVycZ4RdagckpuOOX1ig/AtpK414xbrrTaP6Cw=="
79+
},
80+
"policyGrant": {
81+
"grantId": "1aae4310-fbe4-4efb-b53b-67bbb69eeb9d",
82+
"policyHash": "a1b2c3d4e5f6",
83+
"expiresAt": "2030-12-31T23:59:59Z",
84+
"allowedRails": [
85+
"xrpl"
86+
],
87+
"allowedAssets": [
88+
{
89+
"kind": "IOU",
90+
"currency": "RLUSD",
91+
"issuer": "rIssuer"
92+
}
93+
],
94+
"revocationEndpoint": "https://wallet.alice.example.com/revoke",
95+
"allowedPurposes": [
96+
"travel:hotel",
97+
"travel:flight",
98+
"travel:transport"
99+
],
100+
"issuer": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
101+
"issuerKeyId": "alice-did-key-1",
102+
"signature": "Wr2m1JmmPzzVJ7lkAqhGPPHOnVzL+9oF4Fr84JDDX/hKWPmfZfjPKdWes7EvQxZ+vydmjKAP1IHGjrgBMh70BQ=="
103+
},
104+
"paymentPolicyDecision": {
105+
"decisionId": "dec-train-001",
106+
"policyHash": "a1b2c3d4e5f6",
107+
"action": "ALLOW",
108+
"reasons": [
109+
"Within budget",
110+
"Purpose authorized",
111+
"Destination authorized"
112+
],
113+
"expiresAtISO": "2030-12-31T23:59:59Z",
114+
"rail": "xrpl",
115+
"asset": {
116+
"kind": "IOU",
117+
"currency": "RLUSD",
118+
"issuer": "rIssuer"
119+
},
120+
"priceFiat": {
121+
"amountMinor": "12000",
122+
"currency": "USD"
123+
},
124+
"chosen": {
125+
"rail": "xrpl",
126+
"quoteId": "q-train-001"
127+
},
128+
"settlementQuotes": [
129+
{
130+
"quoteId": "q-train-001",
131+
"rail": "xrpl",
132+
"amount": {
133+
"amount": "120000000",
134+
"decimals": 6
135+
},
136+
"destination": "rEurostar",
137+
"expiresAt": "2030-12-31T23:59:59Z",
138+
"asset": {
139+
"kind": "IOU",
140+
"currency": "RLUSD",
141+
"issuer": "rIssuer"
142+
}
143+
}
144+
]
145+
},
146+
"sbaPublicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAyruO/mCPiFMN58KD2MNnt1XXOx2pi3menrxgj8ErYJ8=\n-----END PUBLIC KEY-----\n",
147+
"spaPublicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAHsx6sy9p36RfOiPe7m+AVrES7Sqfoy4rPJsbRr5QHkA=\n-----END PUBLIC KEY-----\n"
148+
}

0 commit comments

Comments
 (0)