@peac/mappings-ucp 0.9.31

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/dist/mapper.js ADDED
@@ -0,0 +1,165 @@
1
+ /**
2
+ * @peac/mappings-ucp - UCP to PEAC receipt mapping
3
+ *
4
+ * Maps UCP order data to PEAC receipt claims.
5
+ * Amounts are in minor units (cents), NOT micros.
6
+ */
7
+ import { ErrorCodes, ucpError } from './errors.js';
8
+ /**
9
+ * Generate a unique receipt ID.
10
+ * Uses timestamp + random suffix for uniqueness.
11
+ */
12
+ function generateReceiptId() {
13
+ const timestamp = Date.now().toString(36);
14
+ const random = Math.random().toString(36).slice(2, 10);
15
+ return `rcpt_${timestamp}_${random}`;
16
+ }
17
+ /**
18
+ * Derive order status from line items.
19
+ */
20
+ function deriveOrderStatus(order) {
21
+ const lineItems = order.line_items;
22
+ if (lineItems.length === 0) {
23
+ return 'processing';
24
+ }
25
+ const allFulfilled = lineItems.every((li) => li.status === 'fulfilled');
26
+ const someFulfilled = lineItems.some((li) => li.status === 'fulfilled' || li.status === 'partial');
27
+ if (allFulfilled) {
28
+ return 'completed';
29
+ }
30
+ if (someFulfilled) {
31
+ return 'partial';
32
+ }
33
+ return 'processing';
34
+ }
35
+ /**
36
+ * Extract totals by type from UCP order.
37
+ */
38
+ function extractTotals(order) {
39
+ const result = {};
40
+ for (const total of order.totals) {
41
+ result[total.type] = total.amount;
42
+ }
43
+ return result;
44
+ }
45
+ /**
46
+ * Validate UCP order has required fields.
47
+ */
48
+ function validateOrder(order) {
49
+ if (!order.id) {
50
+ throw ucpError(ErrorCodes.ORDER_MISSING_ID, 'Order must have an id');
51
+ }
52
+ if (!order.line_items || !Array.isArray(order.line_items)) {
53
+ throw ucpError(ErrorCodes.ORDER_MISSING_LINE_ITEMS, 'Order must have line_items array');
54
+ }
55
+ if (!order.totals || !Array.isArray(order.totals)) {
56
+ throw ucpError(ErrorCodes.ORDER_MISSING_TOTALS, 'Order must have totals array');
57
+ }
58
+ // Find the total amount
59
+ const totalEntry = order.totals.find((t) => t.type === 'total');
60
+ if (!totalEntry) {
61
+ throw ucpError(ErrorCodes.ORDER_MISSING_TOTALS, 'Order totals must include a "total" entry');
62
+ }
63
+ }
64
+ /**
65
+ * Map a UCP order to PEAC receipt claims.
66
+ *
67
+ * @param options - Mapping options
68
+ * @returns PEAC receipt claims (ready for signing)
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * const claims = mapUcpOrderToReceipt({
73
+ * order: ucpOrder,
74
+ * issuer: 'https://merchant.example.com',
75
+ * subject: 'agent:shopper-bot-123',
76
+ * currency: 'USD',
77
+ * });
78
+ *
79
+ * // Sign with @peac/protocol
80
+ * const receipt = await issue(claims, privateKey, kid);
81
+ * ```
82
+ */
83
+ export function mapUcpOrderToReceipt(options) {
84
+ const { order, issuer, subject, currency, receipt_id, issued_at } = options;
85
+ // Validate order
86
+ validateOrder(order);
87
+ // Get the total amount (in minor units)
88
+ const totalEntry = order.totals.find((t) => t.type === 'total');
89
+ const amount = totalEntry.amount;
90
+ // Derive status
91
+ const orderStatus = deriveOrderStatus(order);
92
+ // Map to payment status
93
+ const paymentStatus = orderStatus === 'processing' ? 'pending' : 'completed';
94
+ // Extract all totals
95
+ const totals = extractTotals(order);
96
+ // Build receipt claims
97
+ const claims = {
98
+ jti: receipt_id ?? generateReceiptId(),
99
+ iss: issuer,
100
+ sub: subject,
101
+ iat: issued_at
102
+ ? Math.floor(new Date(issued_at).getTime() / 1000)
103
+ : Math.floor(Date.now() / 1000),
104
+ payment: {
105
+ rail: 'ucp',
106
+ currency,
107
+ amount,
108
+ status: paymentStatus,
109
+ evidence: {
110
+ order_id: order.id,
111
+ ...(order.checkout_id && { checkout_id: order.checkout_id }),
112
+ line_items: order.line_items.length,
113
+ totals,
114
+ },
115
+ },
116
+ ext: {
117
+ 'dev.ucp/order_id': order.id,
118
+ ...(order.checkout_id && { 'dev.ucp/checkout_id': order.checkout_id }),
119
+ 'dev.ucp/order_status': orderStatus,
120
+ ...(order.permalink_url && { 'dev.ucp/permalink': order.permalink_url }),
121
+ },
122
+ };
123
+ return claims;
124
+ }
125
+ /**
126
+ * Extract line item summary for evidence.
127
+ */
128
+ export function extractLineItemSummary(order) {
129
+ return order.line_items.map((li) => ({
130
+ id: li.id,
131
+ title: li.item.title,
132
+ quantity: li.quantity.total,
133
+ price: li.item.price,
134
+ status: li.status,
135
+ }));
136
+ }
137
+ /**
138
+ * Calculate order summary statistics.
139
+ */
140
+ export function calculateOrderStats(order) {
141
+ let totalItems = 0;
142
+ let fulfilledItems = 0;
143
+ let pendingItems = 0;
144
+ let totalQuantity = 0;
145
+ let fulfilledQuantity = 0;
146
+ for (const li of order.line_items) {
147
+ totalItems++;
148
+ totalQuantity += li.quantity.total;
149
+ fulfilledQuantity += li.quantity.fulfilled;
150
+ if (li.status === 'fulfilled') {
151
+ fulfilledItems++;
152
+ }
153
+ else {
154
+ pendingItems++;
155
+ }
156
+ }
157
+ return {
158
+ total_items: totalItems,
159
+ fulfilled_items: fulfilledItems,
160
+ pending_items: pendingItems,
161
+ total_quantity: totalQuantity,
162
+ fulfilled_quantity: fulfilledQuantity,
163
+ };
164
+ }
165
+ //# sourceMappingURL=mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.js","sourceRoot":"","sources":["../src/mapper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,360 @@
1
+ /**
2
+ * @peac/mappings-ucp - Type definitions
3
+ *
4
+ * Google Universal Commerce Protocol (UCP) types and evidence schema.
5
+ * UCP webhooks use detached JWS (RFC 7797) with ES256/ES384/ES512.
6
+ */
7
+ /**
8
+ * UCP Evidence schema version.
9
+ * Used in policy/policy.yaml for dispute bundles.
10
+ */
11
+ export declare const UCP_EVIDENCE_VERSION: "org.peacprotocol.ucp/0.1";
12
+ /**
13
+ * Supported JWS algorithms for UCP webhook signatures.
14
+ * ES256 is most common, ES384/ES512 for higher security.
15
+ */
16
+ export type UcpSignatureAlgorithm = 'ES256' | 'ES384' | 'ES512';
17
+ /**
18
+ * UCP amounts are in minor units (cents), NOT micros.
19
+ * e.g., $10.00 = 1000 (cents)
20
+ */
21
+ export type MinorUnits = number;
22
+ /**
23
+ * Verification mode for webhook signatures.
24
+ * - 'raw': Verify against raw request body bytes
25
+ * - 'jcs': Verify against JCS-canonicalized body
26
+ */
27
+ export type VerificationMode = 'raw' | 'jcs';
28
+ /**
29
+ * b64 header parameter for detached JWS.
30
+ * - true: Payload is base64url-encoded before signing (default per RFC 7515)
31
+ * - false: Payload bytes used directly (RFC 7797 unencoded payload)
32
+ * - undefined: Treat as true per spec
33
+ */
34
+ export type B64Mode = true | false | undefined;
35
+ /**
36
+ * Parsed JWS header for UCP signatures.
37
+ */
38
+ export interface UcpJwsHeader {
39
+ /** Algorithm (ES256, ES384, ES512) */
40
+ alg: UcpSignatureAlgorithm;
41
+ /** Key ID referencing signing_keys in UCP profile */
42
+ kid: string;
43
+ /** b64 parameter (RFC 7797) */
44
+ b64?: boolean;
45
+ /** Critical headers that MUST be understood */
46
+ crit?: string[];
47
+ /** Type (typically 'JWT') */
48
+ typ?: string;
49
+ }
50
+ /**
51
+ * Result of parsing a detached JWS from Request-Signature header.
52
+ */
53
+ export interface ParsedDetachedJws {
54
+ /** Original header string value */
55
+ raw_header_value: string;
56
+ /** Parsed protected header */
57
+ header: UcpJwsHeader;
58
+ /** Base64url-encoded protected header */
59
+ protected_b64url: string;
60
+ /** Base64url-encoded signature */
61
+ signature_b64url: string;
62
+ /** Whether b64=false was specified */
63
+ is_unencoded_payload: boolean;
64
+ }
65
+ /**
66
+ * UCP signing key from business profile.
67
+ */
68
+ export interface UcpSigningKey {
69
+ /** Key type (EC for ECDSA) */
70
+ kty: 'EC';
71
+ /** Curve (P-256, P-384, P-521) */
72
+ crv: 'P-256' | 'P-384' | 'P-521';
73
+ /** Key ID */
74
+ kid: string;
75
+ /** X coordinate (base64url) */
76
+ x: string;
77
+ /** Y coordinate (base64url) */
78
+ y: string;
79
+ /** Algorithm */
80
+ alg?: UcpSignatureAlgorithm;
81
+ /** Key use */
82
+ use?: 'sig';
83
+ }
84
+ /**
85
+ * UCP business profile (from /.well-known/ucp).
86
+ */
87
+ export interface UcpProfile {
88
+ /** Profile version */
89
+ version: string;
90
+ /** Business ID */
91
+ business_id: string;
92
+ /** Signing keys for webhook verification */
93
+ signing_keys: UcpSigningKey[];
94
+ /** Capabilities supported */
95
+ capabilities?: UcpCapability[];
96
+ }
97
+ /**
98
+ * UCP capability declaration.
99
+ */
100
+ export interface UcpCapability {
101
+ /** Capability name (e.g., 'dev.ucp.shopping.order') */
102
+ name: string;
103
+ /** Capability version */
104
+ version: string;
105
+ /** Capability config */
106
+ config?: Record<string, unknown>;
107
+ }
108
+ /**
109
+ * Verification attempt record for evidence.
110
+ */
111
+ export interface VerificationAttempt {
112
+ /** Mode attempted */
113
+ mode: VerificationMode;
114
+ /** Whether this attempt succeeded */
115
+ success: boolean;
116
+ /** Error code if failed */
117
+ error_code?: string;
118
+ /** Error message if failed */
119
+ error_message?: string;
120
+ }
121
+ /**
122
+ * Payload representation for evidence.
123
+ * Stores both raw and JCS forms for reproducible verification.
124
+ */
125
+ export interface PayloadEvidence {
126
+ /** SHA-256 hash of raw request body bytes (hex) */
127
+ raw_sha256_hex: string;
128
+ /** Raw body bytes as base64url (optional, recommended for <= 256KB) */
129
+ raw_bytes_b64url?: string;
130
+ /** SHA-256 hash of JCS-canonicalized body (hex, if JSON parseable) */
131
+ jcs_sha256_hex?: string;
132
+ /** JCS-canonicalized JSON text (optional, for human review) */
133
+ jcs_text?: string;
134
+ /** Whether JSON parsing succeeded */
135
+ json_parseable: boolean;
136
+ }
137
+ /**
138
+ * Signature evidence for dispute bundle.
139
+ */
140
+ export interface SignatureEvidence {
141
+ /** Full Request-Signature header value */
142
+ header_value: string;
143
+ /** Parsed key ID */
144
+ kid: string;
145
+ /** Parsed algorithm */
146
+ alg: UcpSignatureAlgorithm;
147
+ /** b64 mode (true, false, or absent -> null) */
148
+ b64: boolean | null;
149
+ /** Critical headers if present */
150
+ crit?: string[];
151
+ /** Whether verification succeeded */
152
+ verified: boolean;
153
+ /** Which verification mode succeeded */
154
+ verification_mode_used?: VerificationMode;
155
+ /** All verification attempts (for debugging) */
156
+ verification_attempts: VerificationAttempt[];
157
+ }
158
+ /**
159
+ * Profile snapshot for offline audit.
160
+ */
161
+ export interface ProfileSnapshot {
162
+ /** Profile URL */
163
+ url: string;
164
+ /** When profile was fetched (ISO 8601) */
165
+ fetched_at: string;
166
+ /** SHA-256 of JCS-canonicalized profile JSON (hex) */
167
+ profile_jcs_sha256_hex: string;
168
+ /** JWK thumbprint of the key used (RFC 7638) */
169
+ key_thumbprint?: string;
170
+ /** Full JWK used (for offline verification) */
171
+ key_jwk?: UcpSigningKey;
172
+ }
173
+ /**
174
+ * UCP webhook event metadata.
175
+ */
176
+ export interface WebhookEventMeta {
177
+ /** Event type (e.g., 'order.created') */
178
+ type: string;
179
+ /** Resource ID (e.g., order_id) */
180
+ resource_id?: string;
181
+ /** Event timestamp from payload (ISO 8601) */
182
+ timestamp?: string;
183
+ }
184
+ /**
185
+ * Complete UCP webhook evidence for dispute bundle.
186
+ * Stored in policy/policy.yaml with fixed key ordering.
187
+ */
188
+ export interface UcpWebhookEvidence {
189
+ /** Schema version - prevents misinterpretation as executable policy */
190
+ peac_bundle_metadata_version: typeof UCP_EVIDENCE_VERSION;
191
+ /** Kind marker - clearly not executable policy */
192
+ kind: 'evidence_attachment';
193
+ /** Evidence scope */
194
+ scope: 'ucp_webhook';
195
+ /** Webhook request metadata */
196
+ request: {
197
+ /** HTTP method */
198
+ method: string;
199
+ /** Request path */
200
+ path: string;
201
+ /** When request was received (ISO 8601, injected for determinism) */
202
+ received_at: string;
203
+ };
204
+ /** Payload evidence with both raw and JCS representations */
205
+ payload: PayloadEvidence;
206
+ /** Signature evidence */
207
+ signature: SignatureEvidence;
208
+ /** Event metadata from payload */
209
+ event?: WebhookEventMeta;
210
+ /** Business profile snapshot */
211
+ profile: ProfileSnapshot;
212
+ /** Links to PEAC receipts in this bundle */
213
+ linked_receipts?: LinkedReceipt[];
214
+ }
215
+ /**
216
+ * Link to a PEAC receipt in the same bundle.
217
+ */
218
+ export interface LinkedReceipt {
219
+ /** Receipt ID (jti claim) */
220
+ receipt_id: string;
221
+ /** Relationship to the webhook event */
222
+ relationship: 'issued_for_order' | 'issued_for_checkout' | 'issued_for_adjustment';
223
+ }
224
+ /**
225
+ * Options for verifying a UCP webhook signature.
226
+ */
227
+ export interface VerifyUcpWebhookOptions {
228
+ /** Request-Signature header value */
229
+ signature_header: string;
230
+ /** Raw request body bytes */
231
+ body_bytes: Uint8Array;
232
+ /** Profile URL for key discovery */
233
+ profile_url: string;
234
+ /** Optional: pre-fetched profile (skips fetch) */
235
+ profile?: UcpProfile;
236
+ /** Optional: timestamp for profile fetch (for deterministic evidence) */
237
+ fetched_at?: string;
238
+ /** Optional: maximum body size to include in evidence (default 256KB) */
239
+ max_body_evidence_bytes?: number;
240
+ }
241
+ /**
242
+ * Result of UCP webhook signature verification.
243
+ * Includes profile and key for single-fetch evidence capture.
244
+ */
245
+ export interface VerifyUcpWebhookResult {
246
+ /** Whether signature is valid */
247
+ valid: boolean;
248
+ /** Which verification mode succeeded (if valid) */
249
+ mode_used?: VerificationMode;
250
+ /** Parsed header info */
251
+ header: UcpJwsHeader;
252
+ /** Key used for verification */
253
+ key?: UcpSigningKey;
254
+ /** Fetched profile (for evidence capture - avoids double-fetch) */
255
+ profile?: UcpProfile;
256
+ /** Raw profile JSON string (for deterministic hashing) */
257
+ profile_raw?: string;
258
+ /** All verification attempts */
259
+ attempts: VerificationAttempt[];
260
+ /** Error code (if invalid) */
261
+ error_code?: string;
262
+ /** Error message (if invalid) */
263
+ error_message?: string;
264
+ }
265
+ /**
266
+ * UCP order line item for receipt mapping.
267
+ */
268
+ export interface UcpLineItem {
269
+ /** Line item ID */
270
+ id: string;
271
+ /** Item details */
272
+ item: {
273
+ id: string;
274
+ title: string;
275
+ price: MinorUnits;
276
+ };
277
+ /** Quantities */
278
+ quantity: {
279
+ total: number;
280
+ fulfilled: number;
281
+ };
282
+ /** Status */
283
+ status: 'processing' | 'partial' | 'fulfilled';
284
+ }
285
+ /**
286
+ * UCP order for receipt mapping.
287
+ */
288
+ export interface UcpOrder {
289
+ /** Order ID */
290
+ id: string;
291
+ /** Checkout ID that created this order */
292
+ checkout_id?: string;
293
+ /** Order permalink */
294
+ permalink_url?: string;
295
+ /** Line items */
296
+ line_items: UcpLineItem[];
297
+ /** Order totals */
298
+ totals: Array<{
299
+ type: 'subtotal' | 'shipping' | 'tax' | 'total' | string;
300
+ amount: MinorUnits;
301
+ }>;
302
+ /** Fulfillment info */
303
+ fulfillment?: {
304
+ expectations: unknown[];
305
+ events: unknown[];
306
+ };
307
+ /** Adjustments (refunds, returns, etc.) */
308
+ adjustments?: unknown[];
309
+ }
310
+ /**
311
+ * Options for mapping UCP order to PEAC receipt claims.
312
+ */
313
+ export interface MapUcpOrderOptions {
314
+ /** UCP order object */
315
+ order: UcpOrder;
316
+ /** Issuer URI (PEAC publisher) */
317
+ issuer: string;
318
+ /** Subject URI (buyer/agent) */
319
+ subject: string;
320
+ /** Currency code (ISO 4217) */
321
+ currency: string;
322
+ /** Optional receipt ID (generated if not provided) */
323
+ receipt_id?: string;
324
+ /** Optional issued_at (for deterministic fixtures) */
325
+ issued_at?: string;
326
+ }
327
+ /**
328
+ * PEAC receipt claims mapped from UCP order.
329
+ */
330
+ export interface MappedReceiptClaims {
331
+ /** Receipt ID */
332
+ jti: string;
333
+ /** Issuer */
334
+ iss: string;
335
+ /** Subject */
336
+ sub: string;
337
+ /** Issued at (Unix timestamp) */
338
+ iat: number;
339
+ /** Payment evidence */
340
+ payment: {
341
+ rail: 'ucp';
342
+ currency: string;
343
+ amount: MinorUnits;
344
+ status: 'completed' | 'pending';
345
+ evidence: {
346
+ order_id: string;
347
+ checkout_id?: string;
348
+ line_items: number;
349
+ totals: Record<string, MinorUnits>;
350
+ };
351
+ };
352
+ /** UCP-specific extensions */
353
+ ext: {
354
+ 'dev.ucp/order_id': string;
355
+ 'dev.ucp/checkout_id'?: string;
356
+ 'dev.ucp/order_status': string;
357
+ 'dev.ucp/permalink'?: string;
358
+ };
359
+ }
360
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @peac/mappings-ucp - Type definitions
3
+ *
4
+ * Google Universal Commerce Protocol (UCP) types and evidence schema.
5
+ * UCP webhooks use detached JWS (RFC 7797) with ES256/ES384/ES512.
6
+ */
7
+ /**
8
+ * UCP Evidence schema version.
9
+ * Used in policy/policy.yaml for dispute bundles.
10
+ */
11
+ export const UCP_EVIDENCE_VERSION = 'org.peacprotocol.ucp/0.1';
12
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,0BAAmC,CAAC"}
package/dist/util.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @peac/mappings-ucp - Shared utilities
3
+ *
4
+ * Crypto and encoding helpers used by both verification and evidence generation.
5
+ * Extracted to prevent architectural coupling between modules.
6
+ */
7
+ /**
8
+ * SHA-256 hash as hex string.
9
+ */
10
+ export declare function sha256Hex(data: Uint8Array): string;
11
+ /**
12
+ * SHA-256 hash as Uint8Array.
13
+ */
14
+ export declare function sha256Bytes(data: Uint8Array): Uint8Array;
15
+ /**
16
+ * Base64url encode without padding.
17
+ * Uses standard base64 + manual conversion for maximum portability.
18
+ * Works with Node.js 12+ (does not require 'base64url' encoding from Node 15.7.0+).
19
+ */
20
+ export declare function base64urlEncode(data: Uint8Array): string;
21
+ /**
22
+ * JCS canonicalize (RFC 8785) - synchronous.
23
+ * Produces deterministic JSON with sorted keys and no whitespace.
24
+ */
25
+ export declare function jcsCanonicalizeSync(obj: unknown): string;
26
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAElD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAExD;AA4BD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAwBxD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CA8BxD"}