Skip to content

Commit d20d9cc

Browse files
NAOR YUVALclaude
authored andcommitted
docs: comprehensive documentation consistency and clarity pass
- Fix all broken ./doc/ links in README.md → correct ./docs/implementation/ and ./docs/reference/ paths; update repo structure diagram (doc → docs) - Fix examples/parking/fleet-policy.json: allowedAssets string array → object array format matching spec (kind/currency/issuer) - Fix SDK docs: add missing required grantId parameter to createBudgetAuthorization and createSignedBudgetAuthorization examples in both docs/reference/sdk.md and docs/implementation/sdk.md; add null-return note - Fix stale path references: parking-session/ → parking/ (3 occurrences in parking/README.md and .gitignore), fleet-simulator/ → machine-commerce/ (machine-commerce/README.md, simulate.mjs, reference-profiles.md) - Differentiate SDK docs: rewrite docs/implementation/sdk.md as a lifecycle guide (PolicyGrant → SBA → SPA → verify, chain linkage table, end-to-end example); docs/reference/sdk.md remains the pure API reference - Add Vehicle Wallet Roles section to machine-wallet-guardrails.md: session authority role (creates/signs SBA) and payment decision service role (evaluates requests, signs SPA locally) - Add Key Resolution section to verifier.md: HTTPS well-known baseline, optional DID resolution, and inline keys for self-contained bundles Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 35f30d3 commit d20d9cc

11 files changed

Lines changed: 156 additions & 99 deletions

File tree

.gitignore

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ dist/
55
*.test.d.ts
66
.DS_Store
77
diff.tmp
8-
examples/parking-session/guardrails-demo-bundle.json
9-
examples/parking-session/guardrails-demo-tampered.json
8+
examples/parking/guardrails-demo-bundle.json
9+
examples/parking/guardrails-demo-tampered.json
1010
examples/fleet-payment/fleet-demo-bundle.json
11-
examples/parking-session/offline-demo-bundle.json
11+
examples/parking/offline-demo-bundle.json

README.md

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,23 @@ The service is designed to sit between **application logic** (such as parking sy
99

1010
For the rationale behind the protocol, see:
1111

12-
[Why MPCP Exists](./doc/Why_MPCP.md)
12+
[Why MPCP Exists](https://github.com/mpcp-protocol/mpcp-spec/blob/main/docs/overview/what-is-mpcp.md)
1313

14-
For the full documentation site (overview, guides, examples, reference), see **[docs/](./docs/)**. When [GitHub Pages](https://docs.github.com/en/pages) is enabled, the site is published automatically from `main`.
15-
16-
**To enable the docs site:** go to **Settings → Pages** → Source: **Deploy from a branch** → Branch: **gh-pages** → Save. The workflow pushes the built site to `gh-pages` on each push to `main`.
14+
For the full documentation site (overview, guides, examples, reference), see **[docs/](./docs/)**.
1715

1816
For the full protocol specification, see:
1917

20-
[Machine Payment Control Protocol Specification](./doc/protocol/mpcp.md)
18+
[Machine Payment Control Protocol Specification](https://github.com/mpcp-protocol/mpcp-spec/blob/main/docs/protocol/mpcp.md)
2119

2220
This document defines the MPCP artifacts, verification rules, canonical hashing, replay protection, the authorization lifecycle, and the verification algorithm used by MPCP implementations.
2321

24-
For compatibility and versioning policy (what is stable, how 1.0/1.1/2.0 evolve), see [Compatibility and Versioning](./doc/architecture/COMPATIBILITY_AND_VERSIONING.md).
25-
2622
## Documentation Layout
2723

28-
This repository contains two documentation layers:
24+
This repository contains one documentation layer:
25+
26+
- **docs/** — Developer documentation site (guides, examples, reference, API)
2927

30-
- **doc/** — Protocol specification and architecture documents (normative)
31-
- **docs/** — Developer documentation site (guides, examples, reference)
28+
The canonical protocol specification lives in the [mpcp-spec](https://github.com/mpcp-protocol/mpcp-spec) repository.
3229

3330
---
3431

@@ -205,20 +202,20 @@ These are used to bind authorizations to a specific settlement intent.
205202

206203
## Intent Anchoring (optional)
207204

208-
Optional support for publishing intent hashes to distributed ledgers (public auditability, dispute protection). **Mock anchor** for development; **Hedera HCS** adapter for real anchoring. See [Intent Anchoring](./doc/architecture/INTENT_ANCHORING.md).
205+
Optional support for publishing intent hashes to distributed ledgers (public auditability, dispute protection). **Mock anchor** for development; **Hedera HCS** adapter for real anchoring. See [Intent Anchoring](./docs/implementation/intent-anchoring.md).
209206

210207
## Dispute Verification (optional)
211208

212-
`verifyDisputedSettlement` validates disputed settlements using the full MPCP chain plus optional ledger anchor. See [Dispute Verification](./doc/architecture/DISPUTE_VERIFICATION.md).
209+
`verifyDisputedSettlement` validates disputed settlements using the full MPCP chain plus optional ledger anchor. See [Dispute Verification](./docs/implementation/dispute-verification.md).
213210

214211
## Reference Service API (optional)
215212

216-
Backend-friendly facade: `issueBudget`, `verifySettlementService`, `verifyDispute` / `verifyDisputeAsync`, `anchorIntent`. See [REFERENCE_SERVICE_API](./doc/architecture/REFERENCE_SERVICE_API.md). Import from `mpcp-service/service`.
213+
Backend-friendly facade: `issueBudget`, `verifySettlementService`, `verifyDispute` / `verifyDisputeAsync`, `anchorIntent`. See [Reference Service API](./docs/reference/service-api.md). Import from `mpcp-service/service`.
217214

218215
## Fleet Operator Tooling (optional)
219216

220217
- **Settlement verification logs**`mpcp verify <file> --append-log audit.jsonl` appends verification results to a JSONL audit trail
221-
- **Fleet policy summary**`mpcp policy-summary <policy.json>` prints policy constraints. Use `--profile <name>` for lightweight reference-profile validation [(parking, charging, fleet-offline, hosted-rail)](./doc/architecture/REFERENCE_PROFILES.md). See [Fleet Operator Tooling](./doc/architecture/FLEET_OPERATOR_TOOLING.md).
218+
- **Fleet policy summary**`mpcp policy-summary <policy.json>` prints policy constraints. Use `--profile <name>` for lightweight reference-profile validation [(parking, charging, fleet-offline, hosted-rail)](./docs/implementation/reference-profiles.md). See [Fleet Operator Tooling](./docs/implementation/fleet-operator-tooling.md).
222219

223220
---
224221

@@ -299,7 +296,7 @@ mpcp-service
299296
│ └── ...
300297
301298
├── test
302-
├── doc
299+
├── docs
303300
├── package.json
304301
└── tsconfig.json
305302
```

docs/implementation/machine-wallet-guardrails.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,41 @@ MPCP provides three layers of enforcement before a machine can pay:
3535
- **Intent hash** — SPA binds to a canonical SettlementIntent
3636
- **Tamper resistance** — SettlementIntent and final settlement must match the signed authorization
3737

38+
## Vehicle Wallet Roles
39+
40+
In an autonomous deployment, the vehicle wallet plays **two distinct roles** in the MPCP authorization pipeline.
41+
42+
### Session Authority
43+
44+
The wallet creates and signs the **SignedBudgetAuthorization (SBA)** before the session begins. This establishes the session-level spending envelope:
45+
46+
- Sets `maxAmountMinor` — the total spend ceiling for the session
47+
- Sets `destinationAllowlist` — the permitted payees
48+
- Binds to the PolicyGrant via `grantId`
49+
50+
The SBA is signed with the wallet's SBA key (`MPCP_SBA_SIGNING_PRIVATE_KEY_PEM`). Verifiers check this signature to confirm the budget was set by a trusted session authority.
51+
52+
### Payment Decision Service
53+
54+
For each payment request within the session, the wallet evaluates the request against the loaded policy chain and, if approved, creates and signs a **SignedPaymentAuthorization (SPA)**:
55+
56+
- Assigns a unique `decisionId`
57+
- Commits to the specific amount, destination, and asset
58+
- Computes and binds an `intentHash` to a canonical SettlementIntent
59+
- Signs with the wallet's SPA key (`MPCP_SPA_SIGNING_PRIVATE_KEY_PEM`)
60+
61+
This decision is made **locally** — no central approval API is contacted. The SPA is a cryptographic proof that the wallet approved this specific payment within the authorized budget.
62+
63+
### Why Two Roles?
64+
65+
Separating session authority from payment decisions allows fleet operators to:
66+
67+
- Pre-authorize a spending envelope (SBA) before the vehicle enters service
68+
- Let the vehicle make individual payment decisions (SPA) locally within that envelope
69+
- Give verifiers a complete, self-contained authorization chain to validate
70+
71+
---
72+
3873
## Wallet Integration
3974

4075
A machine wallet integrates MPCP by performing checks *before* signing an SPA.

docs/implementation/reference-profiles.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ Profiles define expected policy shape. Use `mpcp policy-summary` with `--profile
9393
```bash
9494
mpcp policy-summary profiles/parking.json --profile parking
9595
mpcp policy-summary profiles/xrpl-stablecoin.json --profile xrpl-stablecoin
96-
mpcp policy-summary examples/fleet-simulator/fleet-policy.json --profile parking
96+
mpcp policy-summary examples/machine-commerce/fleet-policy.json --profile parking
9797
```
9898

9999
Validation checks: `allowedRails` in the policy must be a subset of the profile’s allowed rails; if the policy declares `_profile`, it must match the profile name.

docs/implementation/sdk.md

Lines changed: 50 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,50 @@
1-
# SDK Reference
1+
# SDK — Implementation Guide
22

3-
The MPCP SDK provides lower-level artifact creation, hashing, and verification.
3+
The MPCP SDK creates and verifies authorization artifacts. This guide shows how the artifacts fit together as a connected lifecycle.
44

5-
## Install
5+
For the full API reference (all function signatures, parameters, and env vars), see [SDK Reference](../reference/sdk.md).
66

7-
```bash
8-
npm install mpcp-service
7+
## Artifact Lifecycle
8+
9+
MPCP authorization flows through three artifact types, each constraining the next:
10+
11+
```
12+
PolicyGrant → SBA (session budget) → SPA (per-payment) → Settlement
913
```
1014

11-
## Import
15+
Each artifact references the previous via shared fields:
16+
17+
| Field | Carried by | Links to |
18+
|-------|-----------|----------|
19+
| `grantId` | SBA | `PolicyGrant.grantId` |
20+
| `sessionId` | SPA | `SBA.authorization.sessionId` |
21+
| `intentHash` | SPA | `computeSettlementIntentHash(intent)` |
22+
23+
## Full Lifecycle Example
1224

1325
```typescript
1426
import {
1527
createPolicyGrant,
16-
createBudgetAuthorization,
1728
createSignedBudgetAuthorization,
18-
createSignedPaymentAuthorization,
1929
createSettlementIntent,
30+
createSignedPaymentAuthorization,
2031
computeSettlementIntentHash,
21-
computeIntentHash,
22-
canonicalJson,
23-
verifyPolicyGrant,
24-
verifySettlement,
25-
verifySettlementWithReport,
26-
verifySettlementDetailed,
2732
} from "mpcp-service/sdk";
28-
```
29-
30-
## Policy Grant
31-
32-
```typescript
33-
import { createPolicyGrant } from "mpcp-service/sdk";
3433

34+
// 1. PolicyGrant — fleet policy evaluation result
35+
// Defines allowed rails, assets, and expiration for this session.
3536
const grant = createPolicyGrant({
3637
policyHash: "a1b2c3",
37-
allowedRails: ["xrpl", "evm"],
38+
allowedRails: ["xrpl"],
3839
allowedAssets: [{ kind: "IOU", currency: "RLUSD", issuer: "rIssuer" }],
3940
expiresAt: "2030-12-31T23:59:59Z",
4041
});
41-
```
42-
43-
## Budget Authorization
44-
45-
```typescript
46-
import {
47-
createBudgetAuthorization,
48-
createSignedBudgetAuthorization,
49-
} from "mpcp-service/sdk";
5042

51-
const budgetAuth = createBudgetAuthorization({
43+
// 2. SBA — session spending envelope
44+
// grantId binds this SBA to the PolicyGrant above.
45+
// Returns null if MPCP_SBA_SIGNING_PRIVATE_KEY_PEM is not set.
46+
const sba = createSignedBudgetAuthorization({
47+
grantId: grant.grantId,
5248
sessionId: "sess-123",
5349
vehicleId: "veh-456",
5450
policyHash: "a1b2c3",
@@ -60,36 +56,17 @@ const budgetAuth = createBudgetAuthorization({
6056
expiresAt: "2030-12-31T23:59:59Z",
6157
});
6258

63-
// Signed (requires MPCP_SBA_SIGNING_PRIVATE_KEY_PEM)
64-
const sba = createSignedBudgetAuthorization({
65-
sessionId: budgetAuth.sessionId,
66-
vehicleId: budgetAuth.vehicleId,
67-
policyHash: budgetAuth.policyHash,
68-
currency: budgetAuth.currency,
69-
maxAmountMinor: budgetAuth.maxAmountMinor,
70-
allowedRails: budgetAuth.allowedRails,
71-
allowedAssets: budgetAuth.allowedAssets,
72-
destinationAllowlist: budgetAuth.destinationAllowlist,
73-
expiresAt: budgetAuth.expiresAt,
74-
});
75-
```
76-
77-
## Payment Authorization
78-
79-
```typescript
80-
import {
81-
createSignedPaymentAuthorization,
82-
createSettlementIntent,
83-
computeSettlementIntentHash,
84-
} from "mpcp-service/sdk";
85-
59+
// 3. SettlementIntent — canonical representation of the payment
8660
const intent = createSettlementIntent({
8761
rail: "xrpl",
8862
amount: "1000",
8963
destination: "rParking",
9064
asset: { kind: "IOU", currency: "RLUSD", issuer: "rIssuer" },
9165
});
9266

67+
// 4. SPA — per-payment authorization
68+
// sessionId matches SBA. intentHash binds SPA to the specific settlement.
69+
// Returns null if MPCP_SPA_SIGNING_PRIVATE_KEY_PEM is not set.
9370
const spa = createSignedPaymentAuthorization({
9471
decisionId: "dec-789",
9572
sessionId: "sess-123",
@@ -102,42 +79,43 @@ const spa = createSignedPaymentAuthorization({
10279
intentHash: computeSettlementIntentHash(intent),
10380
expiresAt: "2030-12-31T23:59:59Z",
10481
});
105-
```
106-
107-
Requires `MPCP_SPA_SIGNING_PRIVATE_KEY_PEM`.
108-
109-
## Hashing
11082

111-
```typescript
112-
import { computeSettlementIntentHash, computeIntentHash, canonicalJson } from "mpcp-service/sdk";
83+
// 5. Verify the settlement bundle
84+
import { verifySettlement } from "mpcp-service/sdk";
11385

114-
const intentHash = computeSettlementIntentHash(intent);
115-
const canonical = canonicalJson({ rail: "xrpl", amount: "1000", destination: "rDest" });
86+
const result = verifySettlement({
87+
policyGrant: grant,
88+
signedBudgetAuthorization: sba,
89+
signedPaymentAuthorization: spa,
90+
settlementIntent: intent,
91+
settlement: { rail: "xrpl", amount: "1000", destination: "rParking", asset: intent.asset },
92+
});
93+
// result.valid === true
11694
```
11795

118-
## Verification
96+
## Vehicle Wallet Roles
11997

120-
```typescript
121-
import { verifySettlement, verifySettlementWithReport, verifySettlementDetailed } from "mpcp-service/sdk";
98+
In an autonomous deployment, the wallet plays both roles in this lifecycle:
12299

123-
const result = verifySettlement(context);
124-
const { result, steps } = verifySettlementWithReport(context);
125-
const { valid, checks } = verifySettlementDetailed(context);
126-
```
100+
- **Session authority** — signs the SBA, establishing the session budget
101+
- **Payment decision service** — evaluates each payment request and signs the SPA locally
102+
103+
See [Machine Wallet Guardrails](machine-wallet-guardrails.md) for the full guardrail model, threat analysis, and integration checklist.
127104

128105
## Environment Variables
129106

130107
| Variable | Purpose |
131108
|----------|---------|
132109
| MPCP_SBA_SIGNING_PRIVATE_KEY_PEM | Private key for signing SBAs |
133110
| MPCP_SBA_SIGNING_PUBLIC_KEY_PEM | Public key for verifying SBAs |
134-
| MPCP_SBA_SIGNING_KEY_ID | Key identifier (default: mpcp-sba-signing-key-1) |
111+
| MPCP_SBA_SIGNING_KEY_ID | Key identifier (default: `mpcp-sba-signing-key-1`) |
135112
| MPCP_SPA_SIGNING_PRIVATE_KEY_PEM | Private key for signing SPAs |
136113
| MPCP_SPA_SIGNING_PUBLIC_KEY_PEM | Public key for verifying SPAs |
137-
| MPCP_SPA_SIGNING_KEY_ID | Key identifier (default: mpcp-spa-signing-key-1) |
114+
| MPCP_SPA_SIGNING_KEY_ID | Key identifier (default: `mpcp-spa-signing-key-1`) |
138115

139116
## See Also
140117

118+
- [SDK Reference](../reference/sdk.md) — Full API reference
141119
- [MPCP Reference Flow](https://github.com/mpcp-protocol/mpcp-spec/blob/main/docs/architecture/reference-flow.md) — End-to-end flow with SDK usage
142120
- [Service API](../reference/service-api.md) — Higher-level facade
143121
- [Build a Machine Wallet](https://github.com/mpcp-protocol/mpcp-spec/blob/main/docs/guides/build-a-machine-wallet.md)

docs/implementation/verifier.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,49 @@ if (result.valid) {
4040

4141
The `context` includes policyGrant, signedBudgetAuthorization, signedPaymentAuthorization, settlement, paymentPolicyDecision, decisionId, and optional settlementIntent.
4242

43+
## Key Resolution
44+
45+
MPCP signatures include an `issuerKeyId` field that identifies which public key to use for verification. Verifiers resolve the key using one of two mechanisms.
46+
47+
### HTTPS Well-Known (Baseline)
48+
49+
The issuer publishes their public keys at:
50+
51+
```
52+
https://{issuerDomain}/.well-known/mpcp-keys.json
53+
```
54+
55+
Format:
56+
57+
```json
58+
{
59+
"keys": [
60+
{
61+
"keyId": "mpcp-sba-signing-key-1",
62+
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n",
63+
"use": "sba"
64+
},
65+
{
66+
"keyId": "mpcp-spa-signing-key-1",
67+
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n",
68+
"use": "spa"
69+
}
70+
]
71+
}
72+
```
73+
74+
The `issuerKeyId` in the signed envelope identifies which entry to use.
75+
76+
### DID Document (Optional)
77+
78+
For issuers using decentralized identifiers, keys may be resolved via a DID document. The `issuerKeyId` corresponds to a `verificationMethod` in the DID document. DID resolution is an optional enhancement over the HTTPS well-known baseline.
79+
80+
### Inline Keys (Self-Contained Bundles)
81+
82+
Settlement bundles for development and conformance testing may include `sbaPublicKeyPem` and `spaPublicKeyPem` directly. This avoids external resolution and makes bundles self-contained for `mpcp verify`.
83+
84+
---
85+
4386
## Dispute Verification
4487

4588
When a settlement is disputed, `verifyDisputedSettlement` runs full chain verification plus optional ledger anchor verification. If the intent was anchored (e.g., to Hedera HCS), the anchor can be checked against the expected intentHash.

docs/reference/sdk.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
The MPCP SDK provides lower-level artifact creation, hashing, and verification.
44

5+
For a narrative walkthrough showing how the artifacts connect end-to-end, see [SDK — Implementation Guide](../implementation/sdk.md).
6+
57
## Install
68

79
```bash
@@ -49,6 +51,7 @@ import {
4951
} from "mpcp-service/sdk";
5052

5153
const budgetAuth = createBudgetAuthorization({
54+
grantId: grant.grantId, // from createPolicyGrant
5255
sessionId: "sess-123",
5356
vehicleId: "veh-456",
5457
policyHash: "a1b2c3",
@@ -60,8 +63,9 @@ const budgetAuth = createBudgetAuthorization({
6063
expiresAt: "2030-12-31T23:59:59Z",
6164
});
6265

63-
// Signed (requires MPCP_SBA_SIGNING_PRIVATE_KEY_PEM)
66+
// Signed (requires MPCP_SBA_SIGNING_PRIVATE_KEY_PEM — returns null if not set)
6467
const sba = createSignedBudgetAuthorization({
68+
grantId: budgetAuth.grantId,
6569
sessionId: budgetAuth.sessionId,
6670
vehicleId: budgetAuth.vehicleId,
6771
policyHash: budgetAuth.policyHash,

0 commit comments

Comments
 (0)