@peac/mappings-ucp 0.12.5 → 0.12.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -138
- package/package.json +13 -9
package/README.md
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
# @peac/mappings-ucp
|
|
2
2
|
|
|
3
|
-
Universal Commerce Protocol (UCP) mapping to PEAC receipts and dispute evidence.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Webhook signature verification** - Detached JWS (RFC 7797) with ES256/ES384/ES512
|
|
8
|
-
- **Raw-first, JCS fallback** - Handles UCP's ambiguous canonicalization spec
|
|
9
|
-
- **UCP order to PEAC receipt mapping** - Amounts in minor units (cents)
|
|
10
|
-
- **Dispute evidence generation** - Hardened YAML schema for @peac/audit bundles
|
|
3
|
+
Universal Commerce Protocol (UCP) order mapping to PEAC signed receipts, webhook signature verification, and dispute evidence generation.
|
|
11
4
|
|
|
12
5
|
## Installation
|
|
13
6
|
|
|
@@ -15,163 +8,93 @@ Universal Commerce Protocol (UCP) mapping to PEAC receipts and dispute evidence.
|
|
|
15
8
|
pnpm add @peac/mappings-ucp
|
|
16
9
|
```
|
|
17
10
|
|
|
18
|
-
##
|
|
19
|
-
|
|
20
|
-
### Verify Webhook Signature
|
|
21
|
-
|
|
22
|
-
```typescript
|
|
23
|
-
import { verifyUcpWebhookSignature } from '@peac/mappings-ucp';
|
|
11
|
+
## What It Does
|
|
24
12
|
|
|
25
|
-
|
|
26
|
-
signature_header: req.headers['request-signature'],
|
|
27
|
-
body_bytes: rawBody, // Uint8Array
|
|
28
|
-
profile_url: 'https://business.example.com/.well-known/ucp',
|
|
29
|
-
});
|
|
13
|
+
`@peac/mappings-ucp` maps UCP order data to PEAC receipt claims, verifies UCP webhook signatures using detached JWS (RFC 7797), and generates structured dispute evidence bundles. Order state is kept distinct from payment state: the `payment_state_source` field marks whether payment status was explicitly provided or derived from order fulfillment, so downstream consumers can distinguish observed payment evidence from inferred status.
|
|
30
14
|
|
|
31
|
-
|
|
32
|
-
console.log(`Verified using ${result.mode_used} mode`);
|
|
33
|
-
console.log(`Key: ${result.key?.kid}`);
|
|
34
|
-
} else {
|
|
35
|
-
console.error(`Verification failed: ${result.error_code}`);
|
|
36
|
-
console.log('Attempts:', result.attempts);
|
|
37
|
-
}
|
|
38
|
-
```
|
|
15
|
+
## How Do I Use It?
|
|
39
16
|
|
|
40
|
-
### Map UCP
|
|
17
|
+
### Map a UCP order to receipt claims
|
|
41
18
|
|
|
42
19
|
```typescript
|
|
43
20
|
import { mapUcpOrderToReceipt } from '@peac/mappings-ucp';
|
|
44
|
-
import { issue } from '@peac/protocol';
|
|
45
21
|
|
|
46
22
|
const claims = mapUcpOrderToReceipt({
|
|
47
|
-
order:
|
|
48
|
-
issuer: 'https://
|
|
49
|
-
subject: '
|
|
23
|
+
order: ucpOrder,
|
|
24
|
+
issuer: 'https://merchant.example.com',
|
|
25
|
+
subject: 'agent:shopper-bot-123',
|
|
50
26
|
currency: 'USD',
|
|
51
27
|
});
|
|
52
28
|
|
|
53
29
|
// Sign with @peac/protocol
|
|
54
|
-
const
|
|
55
|
-
iss: 'https://platform.example.com',
|
|
56
|
-
kind: 'evidence',
|
|
57
|
-
type: 'org.peacprotocol/payment',
|
|
58
|
-
pillars: ['commerce'],
|
|
59
|
-
extensions: {
|
|
60
|
-
'org.peacprotocol/commerce': {
|
|
61
|
-
payment_rail: 'ucp',
|
|
62
|
-
amount_minor: String(claims.amount),
|
|
63
|
-
currency: claims.currency,
|
|
64
|
-
reference: claims.reference,
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
privateKey,
|
|
68
|
-
kid,
|
|
69
|
-
});
|
|
30
|
+
const receipt = await issue(claims, privateKey, kid);
|
|
70
31
|
```
|
|
71
32
|
|
|
72
|
-
###
|
|
33
|
+
### Verify a UCP webhook signature
|
|
73
34
|
|
|
74
35
|
```typescript
|
|
75
|
-
import {
|
|
76
|
-
import { createDisputeBundle } from '@peac/audit';
|
|
36
|
+
import { verifyUcpWebhookSignature } from '@peac/mappings-ucp';
|
|
77
37
|
|
|
78
|
-
|
|
79
|
-
const evidence = await createUcpDisputeEvidence({
|
|
38
|
+
const result = await verifyUcpWebhookSignature({
|
|
80
39
|
signature_header: req.headers['request-signature'],
|
|
81
40
|
body_bytes: rawBody,
|
|
82
|
-
method: 'POST',
|
|
83
|
-
path: '/webhooks/ucp/orders',
|
|
84
|
-
received_at: new Date().toISOString(),
|
|
85
41
|
profile_url: 'https://business.example.com/.well-known/ucp',
|
|
86
|
-
profile_fetched_at: new Date().toISOString(),
|
|
87
42
|
});
|
|
88
43
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
44
|
+
if (result.valid) {
|
|
45
|
+
// Signature verified; proceed with order mapping
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Extract line item summaries and order statistics
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { extractLineItemSummary, calculateOrderStats } from '@peac/mappings-ucp';
|
|
53
|
+
|
|
54
|
+
const summary = extractLineItemSummary(ucpOrder);
|
|
55
|
+
const stats = calculateOrderStats(ucpOrder);
|
|
56
|
+
|
|
57
|
+
console.log(stats.total_items); // number of line items
|
|
58
|
+
console.log(stats.fulfilled_items); // items marked fulfilled
|
|
97
59
|
```
|
|
98
60
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
The verification result includes `profile` and `profile_raw` fields, allowing callers to capture evidence without re-fetching.
|
|
121
|
-
|
|
122
|
-
## Evidence Schema
|
|
123
|
-
|
|
124
|
-
The evidence YAML uses a hardened schema that cannot be misinterpreted as executable policy:
|
|
125
|
-
|
|
126
|
-
```yaml
|
|
127
|
-
peac_bundle_metadata_version: 'org.peacprotocol.ucp/0.1'
|
|
128
|
-
kind: 'evidence_attachment'
|
|
129
|
-
scope: 'ucp_webhook'
|
|
130
|
-
|
|
131
|
-
request:
|
|
132
|
-
method: 'POST'
|
|
133
|
-
path: '/webhooks/ucp/orders'
|
|
134
|
-
received_at: '2026-01-13T12:00:00Z'
|
|
135
|
-
|
|
136
|
-
payload:
|
|
137
|
-
raw_sha256_hex: 'abc123...'
|
|
138
|
-
raw_bytes_b64url: 'eyJ...' # Optional, for bodies <= 256KB
|
|
139
|
-
jcs_sha256_hex: 'def456...' # If JSON parseable
|
|
140
|
-
json_parseable: true
|
|
141
|
-
|
|
142
|
-
signature:
|
|
143
|
-
header_value: 'eyJhbGc...' # Full Request-Signature header
|
|
144
|
-
kid: 'business-key-001'
|
|
145
|
-
alg: 'ES256'
|
|
146
|
-
b64: null
|
|
147
|
-
verified: true
|
|
148
|
-
verification_mode_used: 'raw'
|
|
149
|
-
verification_attempts:
|
|
150
|
-
- mode: 'raw'
|
|
151
|
-
success: true
|
|
152
|
-
|
|
153
|
-
profile:
|
|
154
|
-
url: 'https://business.example.com/.well-known/ucp'
|
|
155
|
-
fetched_at: '2026-01-13T11:59:30Z'
|
|
156
|
-
profile_jcs_sha256_hex: 'ghi789...'
|
|
157
|
-
key_jwk:
|
|
158
|
-
kty: 'EC'
|
|
159
|
-
crv: 'P-256'
|
|
160
|
-
kid: 'business-key-001'
|
|
161
|
-
x: '...'
|
|
162
|
-
y: '...'
|
|
61
|
+
### Attach and extract evidence carriers on webhook payloads
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import {
|
|
65
|
+
UcpCarrierAdapter,
|
|
66
|
+
attachCarrierToWebhookPayload,
|
|
67
|
+
extractCarrierFromWebhookPayload,
|
|
68
|
+
} from '@peac/mappings-ucp';
|
|
69
|
+
|
|
70
|
+
// Attach a signed receipt carrier to a UCP webhook payload
|
|
71
|
+
attachCarrierToWebhookPayload(webhookPayload, carrier);
|
|
72
|
+
|
|
73
|
+
// Extract carrier from an incoming webhook payload
|
|
74
|
+
const result = extractCarrierFromWebhookPayload(webhookPayload);
|
|
75
|
+
if (result) {
|
|
76
|
+
console.log(result.receipts[0].receipt_ref);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Or use the adapter interface
|
|
80
|
+
const adapter = new UcpCarrierAdapter();
|
|
81
|
+
const extracted = adapter.extract(webhookPayload);
|
|
163
82
|
```
|
|
164
83
|
|
|
165
|
-
##
|
|
84
|
+
## Integrates With
|
|
85
|
+
|
|
86
|
+
- `@peac/kernel` (Layer 0): Evidence carrier types and constants
|
|
87
|
+
- `@peac/schema` (Layer 1): Receipt schemas and carrier validation
|
|
88
|
+
- `@peac/protocol` (Layer 3): Sign mapped claims into receipts with `issue()`
|
|
89
|
+
|
|
90
|
+
## For Agent Developers
|
|
91
|
+
|
|
92
|
+
If you are building an AI agent that interacts with UCP-based commerce platforms:
|
|
166
93
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
| E_UCP_SIGNATURE_ALGORITHM_UNSUPPORTED | 400 | Algorithm not ES256/ES384/ES512 |
|
|
172
|
-
| E_UCP_KEY_NOT_FOUND | 401 | Key ID not in profile |
|
|
173
|
-
| E_UCP_SIGNATURE_INVALID | 401 | Signature verification failed |
|
|
174
|
-
| E_UCP_PROFILE_FETCH_FAILED | 502 | Failed to fetch UCP profile |
|
|
94
|
+
- Use `mapUcpOrderToReceipt()` to produce signed evidence of order observations
|
|
95
|
+
- Use `verifyUcpWebhookSignature()` to validate incoming webhook authenticity before mapping
|
|
96
|
+
- Order status reflects fulfillment state; payment status requires explicit `payment_state` when the upstream source provides it
|
|
97
|
+
- See the [llms.txt](https://github.com/peacprotocol/peac/blob/main/llms.txt) for a concise protocol overview
|
|
175
98
|
|
|
176
99
|
## License
|
|
177
100
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peac/mappings-ucp",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.6",
|
|
4
4
|
"description": "Google Universal Commerce Protocol (UCP) mapping to PEAC receipts and dispute evidence",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -15,19 +15,23 @@
|
|
|
15
15
|
"dist"
|
|
16
16
|
],
|
|
17
17
|
"keywords": [
|
|
18
|
+
"peac",
|
|
19
|
+
"peacprotocol",
|
|
20
|
+
"interaction-records",
|
|
21
|
+
"signed-records",
|
|
22
|
+
"receipts",
|
|
23
|
+
"originary",
|
|
18
24
|
"ucp",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"ap2",
|
|
23
|
-
"peac"
|
|
25
|
+
"universal-commerce",
|
|
26
|
+
"order-management",
|
|
27
|
+
"payment-evidence"
|
|
24
28
|
],
|
|
25
29
|
"author": "PEAC Protocol Contributors",
|
|
26
30
|
"license": "Apache-2.0",
|
|
27
31
|
"bugs": {
|
|
28
32
|
"url": "https://github.com/peacprotocol/peac/issues"
|
|
29
33
|
},
|
|
30
|
-
"homepage": "https://
|
|
34
|
+
"homepage": "https://github.com/peacprotocol/peac#readme",
|
|
31
35
|
"repository": {
|
|
32
36
|
"type": "git",
|
|
33
37
|
"url": "git+https://github.com/peacprotocol/peac.git",
|
|
@@ -38,8 +42,8 @@
|
|
|
38
42
|
},
|
|
39
43
|
"dependencies": {
|
|
40
44
|
"jose": "^5.2.0",
|
|
41
|
-
"@peac/kernel": "0.12.
|
|
42
|
-
"@peac/schema": "0.12.
|
|
45
|
+
"@peac/kernel": "0.12.6",
|
|
46
|
+
"@peac/schema": "0.12.6"
|
|
43
47
|
},
|
|
44
48
|
"devDependencies": {
|
|
45
49
|
"typescript": "^5.3.0",
|