@fluxpointstudios/orynq-sdk-tool-receipts 0.2.0

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/index.js ADDED
@@ -0,0 +1,503 @@
1
+ import { addEvent, verifyBundle } from '@fluxpointstudios/orynq-sdk-process-trace';
2
+ import { canonicalize, sha256StringHex } from '@fluxpointstudios/orynq-sdk-core/utils';
3
+ import { createHmac, timingSafeEqual, verify, createPublicKey, createPrivateKey, sign } from 'crypto';
4
+
5
+ // src/record.ts
6
+ async function hashToolPayload(value) {
7
+ const serialized = typeof value === "string" ? value : canonicalize(value);
8
+ return sha256StringHex(serialized);
9
+ }
10
+ async function addToolReceipt(run, spanId, opts) {
11
+ if (!opts.toolId) throw new Error("addToolReceipt: toolId is required");
12
+ if (!opts.receipt) throw new Error("addToolReceipt: receipt is required");
13
+ const event = {
14
+ kind: "tool-receipt",
15
+ visibility: opts.visibility ?? "private",
16
+ toolId: opts.toolId,
17
+ request: opts.request,
18
+ response: opts.response,
19
+ receipt: opts.receipt
20
+ };
21
+ const recorded = await addEvent(run, spanId, event);
22
+ return recorded;
23
+ }
24
+ var textEncoder = new TextEncoder();
25
+ function utf8(s) {
26
+ return Buffer.from(textEncoder.encode(s));
27
+ }
28
+ function constantTimeEqualHex(a, b) {
29
+ const ab = Buffer.from(a.toLowerCase(), "hex");
30
+ const bb = Buffer.from(b.toLowerCase(), "hex");
31
+ if (ab.length === 0 || ab.length !== bb.length) return false;
32
+ return timingSafeEqual(ab, bb);
33
+ }
34
+ async function resolveKey(event, ctx, { allowEmbedded }) {
35
+ if (ctx?.resolveKey) {
36
+ const k = await ctx.resolveKey(event);
37
+ if (k !== void 0) return k;
38
+ }
39
+ if (ctx?.keys && Object.prototype.hasOwnProperty.call(ctx.keys, event.receipt.signer)) {
40
+ return ctx.keys[event.receipt.signer];
41
+ }
42
+ if (allowEmbedded && ctx?.trustEmbeddedKeys === true) {
43
+ const p = event.receipt.params;
44
+ if (p && typeof p.publicKey === "string") return p.publicKey;
45
+ }
46
+ return void 0;
47
+ }
48
+ function keyToString(key) {
49
+ return typeof key === "string" ? key : Buffer.from(key).toString("utf8");
50
+ }
51
+ var SPKI_ALG_OIDS = [
52
+ // rsaEncryption 1.2.840.113549.1.1.1
53
+ [42, 134, 72, 134, 247, 13, 1, 1, 1],
54
+ // id-ecPublicKey 1.2.840.10045.2.1
55
+ [42, 134, 72, 206, 61, 2, 1],
56
+ // id-Ed25519 1.3.101.112
57
+ [43, 101, 112],
58
+ // id-Ed448 1.3.101.113
59
+ [43, 101, 113]
60
+ ];
61
+ function looksLikeDerPublicKey(bytes) {
62
+ if (bytes.length < 8 || bytes[0] !== 48) return false;
63
+ const lenByte = bytes[1];
64
+ let contentStart;
65
+ let contentLen;
66
+ if (lenByte < 128) {
67
+ contentStart = 2;
68
+ contentLen = lenByte;
69
+ } else if (lenByte === 129) {
70
+ contentStart = 3;
71
+ contentLen = bytes[2];
72
+ } else if (lenByte === 130) {
73
+ contentStart = 4;
74
+ contentLen = bytes[2] << 8 | bytes[3];
75
+ } else {
76
+ return false;
77
+ }
78
+ if (contentStart + contentLen !== bytes.length) return false;
79
+ return SPKI_ALG_OIDS.some((oid) => indexOfBytes(bytes, oid) !== -1);
80
+ }
81
+ function indexOfBytes(haystack, needle) {
82
+ outer: for (let i = 0; i + needle.length <= haystack.length; i++) {
83
+ for (let j = 0; j < needle.length; j++) {
84
+ if (haystack[i + j] !== needle[j]) continue outer;
85
+ }
86
+ return i;
87
+ }
88
+ return -1;
89
+ }
90
+ function looksLikeAsymmetricPublicKey(key) {
91
+ if (typeof key !== "string" && looksLikeDerPublicKey(key)) return true;
92
+ const s = keyToString(key).trim();
93
+ if (s.includes("-----BEGIN PUBLIC KEY-----") || s.includes("-----BEGIN RSA PUBLIC KEY-----")) {
94
+ return true;
95
+ }
96
+ if (s.startsWith("{")) {
97
+ try {
98
+ const jwk = JSON.parse(s);
99
+ const kty = typeof jwk.kty === "string" ? jwk.kty.toUpperCase() : "";
100
+ return kty === "RSA" || kty === "EC" || kty === "OKP";
101
+ } catch {
102
+ return false;
103
+ }
104
+ }
105
+ return false;
106
+ }
107
+ function assertSymmetricSecret(key, algLabel) {
108
+ if (looksLikeAsymmetricPublicKey(key)) {
109
+ throw new Error(
110
+ `${algLabel}: refusing to HMAC with an asymmetric public key (algorithm confusion). Provide the signer's symmetric secret out-of-band, or pin the asymmetric alg via keyAlgs.`
111
+ );
112
+ }
113
+ }
114
+ function assertAlgAllowed(event, ctx, alg) {
115
+ const allow = ctx?.keyAlgs?.[event.receipt.signer];
116
+ if (allow && !allow.includes(alg)) {
117
+ throw new Error(
118
+ `alg "${alg}" is not in the expected-algorithm allow-list for signer "${event.receipt.signer}"`
119
+ );
120
+ }
121
+ }
122
+ function parseStripeSignature(raw, params) {
123
+ if (raw.includes("v1=") || raw.includes("t=")) {
124
+ const parts = raw.split(",").map((p) => p.trim());
125
+ let t2;
126
+ const v1 = [];
127
+ for (const part of parts) {
128
+ const eq = part.indexOf("=");
129
+ if (eq === -1) continue;
130
+ const k = part.slice(0, eq);
131
+ const v = part.slice(eq + 1);
132
+ if (k === "t") t2 = v;
133
+ else if (k === "v1") v1.push(v);
134
+ }
135
+ return t2 !== void 0 ? { t: t2, v1 } : { v1 };
136
+ }
137
+ const t = typeof params?.timestamp === "string" ? params.timestamp : void 0;
138
+ return t !== void 0 ? { t, v1: [raw] } : { v1: [raw] };
139
+ }
140
+ async function verifyStripeReceipt(event, ctx) {
141
+ const secret = await resolveKey(event, ctx, { allowEmbedded: false });
142
+ if (secret === void 0) {
143
+ throw new Error(
144
+ "stripe-webhook: signing secret not found \u2014 provide it via verify context (keys/resolveKey), not the trace"
145
+ );
146
+ }
147
+ const { t, v1 } = parseStripeSignature(event.receipt.signature, event.receipt.params);
148
+ if (t === void 0) throw new Error("stripe-webhook: missing timestamp (t)");
149
+ if (v1.length === 0) throw new Error("stripe-webhook: missing v1 signature");
150
+ const toleranceSec = ctx?.toleranceSec ?? 300;
151
+ const now = ctx?.nowSec ?? Math.floor(Date.now() / 1e3);
152
+ const ts = Number(t);
153
+ if (!Number.isFinite(ts)) throw new Error("stripe-webhook: invalid timestamp");
154
+ if (Math.abs(now - ts) > toleranceSec) {
155
+ throw new Error(`stripe-webhook: timestamp outside tolerance (${toleranceSec}s)`);
156
+ }
157
+ const signedBase = `${t}.${event.receipt.signedPayload}`;
158
+ const expected = createHmac("sha256", keyToString(secret)).update(signedBase).digest("hex");
159
+ return v1.some((candidate) => constantTimeEqualHex(expected, candidate));
160
+ }
161
+ async function verifyGitHubReceipt(event, ctx) {
162
+ const secret = await resolveKey(event, ctx, { allowEmbedded: false });
163
+ if (secret === void 0) {
164
+ throw new Error(
165
+ "github-webhook: signing secret not found \u2014 provide it via verify context (keys/resolveKey)"
166
+ );
167
+ }
168
+ const ts = event.receipt.params?.timestamp;
169
+ if (typeof ts === "string" || typeof ts === "number") {
170
+ const tsNum = Number(ts);
171
+ if (!Number.isFinite(tsNum)) throw new Error("github-webhook: invalid timestamp");
172
+ const toleranceSec = ctx?.toleranceSec ?? 300;
173
+ const now = ctx?.nowSec ?? Math.floor(Date.now() / 1e3);
174
+ if (Math.abs(now - tsNum) > toleranceSec) {
175
+ throw new Error(`github-webhook: timestamp outside tolerance (${toleranceSec}s)`);
176
+ }
177
+ }
178
+ const provided = event.receipt.signature.startsWith("sha256=") ? event.receipt.signature.slice("sha256=".length) : event.receipt.signature;
179
+ const expected = createHmac("sha256", keyToString(secret)).update(event.receipt.signedPayload).digest("hex");
180
+ return constantTimeEqualHex(expected, provided);
181
+ }
182
+ function parseJws(event) {
183
+ const sp = event.receipt.signedPayload;
184
+ const segments = sp.split(".");
185
+ let signingInput;
186
+ let sigB64;
187
+ if (segments.length === 3) {
188
+ signingInput = `${segments[0]}.${segments[1]}`;
189
+ sigB64 = segments[2];
190
+ } else if (segments.length === 2) {
191
+ signingInput = sp;
192
+ sigB64 = event.receipt.signature;
193
+ } else {
194
+ throw new Error("jws: signedPayload must be a compact JWS (h.p.s) or signing input (h.p)");
195
+ }
196
+ const headerJson = Buffer.from(segments[0], "base64url").toString("utf8");
197
+ const header = JSON.parse(headerJson);
198
+ return { signingInput, signature: Buffer.from(sigB64, "base64url"), header };
199
+ }
200
+ async function verifyJwsReceipt(event, ctx) {
201
+ const { signingInput, signature, header } = parseJws(event);
202
+ const alg = header.alg;
203
+ if (!alg || alg === "none") throw new Error(`jws: unsupported alg "${alg}"`);
204
+ assertAlgAllowed(event, ctx, alg);
205
+ const data = utf8(signingInput);
206
+ if (alg.startsWith("HS")) {
207
+ const secret = await resolveKey(event, ctx, { allowEmbedded: false });
208
+ if (secret === void 0) throw new Error(`jws(${alg}): HMAC secret not found in verify context`);
209
+ assertSymmetricSecret(secret, `jws(${alg})`);
210
+ const hashAlg = `sha${alg.slice(2)}`;
211
+ const expected = createHmac(hashAlg, keyToString(secret)).update(data).digest();
212
+ return expected.length === signature.length && timingSafeEqual(expected, signature);
213
+ }
214
+ const keyMaterial = await resolveKey(event, ctx, { allowEmbedded: true });
215
+ if (keyMaterial === void 0) throw new Error(`jws(${alg}): public key not found`);
216
+ const publicKey = toPublicKey(keyMaterial);
217
+ if (alg.startsWith("RS")) {
218
+ return verify(`sha${alg.slice(2)}`, data, publicKey, signature);
219
+ }
220
+ if (alg.startsWith("PS")) {
221
+ const bits = alg.slice(2);
222
+ return verify(
223
+ `sha${bits}`,
224
+ data,
225
+ { key: publicKey, padding: 6, saltLength: Number(bits) / 8 },
226
+ signature
227
+ );
228
+ }
229
+ if (alg.startsWith("ES")) {
230
+ return verify(
231
+ `sha${alg.slice(2)}`,
232
+ data,
233
+ { key: publicKey, dsaEncoding: "ieee-p1363" },
234
+ signature
235
+ );
236
+ }
237
+ if (alg === "EdDSA") {
238
+ return verify(null, data, publicKey, signature);
239
+ }
240
+ throw new Error(`jws: unsupported alg "${alg}"`);
241
+ }
242
+ var RFC9421_HASH = {
243
+ "rsa-pss-sha512": "sha512",
244
+ "rsa-v1_5-sha256": "sha256",
245
+ "ecdsa-p256-sha256": "sha256",
246
+ "ecdsa-p384-sha384": "sha384"
247
+ };
248
+ async function verifyHttpMessageReceipt(event, ctx) {
249
+ const params = event.receipt.params ?? {};
250
+ const alg = typeof params.alg === "string" ? params.alg : void 0;
251
+ if (!alg) {
252
+ throw new Error("http-message-signatures: receipt.params.alg is required (RFC 9421 alg id)");
253
+ }
254
+ assertAlgAllowed(event, ctx, alg);
255
+ const data = utf8(event.receipt.signedPayload);
256
+ const signature = decodeSignature(event.receipt.signature);
257
+ if (alg === "ed25519") {
258
+ const keyMaterial2 = await resolveKey(event, ctx, { allowEmbedded: true });
259
+ if (keyMaterial2 === void 0) throw new Error("http-message-signatures(ed25519): public key not found");
260
+ return verify(null, data, toPublicKey(keyMaterial2), signature);
261
+ }
262
+ if (alg === "hmac-sha256") {
263
+ const secret = await resolveKey(event, ctx, { allowEmbedded: false });
264
+ if (secret === void 0) throw new Error("http-message-signatures(hmac-sha256): secret not found");
265
+ assertSymmetricSecret(secret, "http-message-signatures(hmac-sha256)");
266
+ const expected = createHmac("sha256", keyToString(secret)).update(data).digest();
267
+ return expected.length === signature.length && timingSafeEqual(expected, signature);
268
+ }
269
+ const hash = RFC9421_HASH[alg];
270
+ if (!hash) throw new Error(`http-message-signatures: unsupported alg "${alg}"`);
271
+ const keyMaterial = await resolveKey(event, ctx, { allowEmbedded: true });
272
+ if (keyMaterial === void 0) throw new Error(`http-message-signatures(${alg}): public key not found`);
273
+ const publicKey = toPublicKey(keyMaterial);
274
+ if (alg === "rsa-pss-sha512") {
275
+ return verify(hash, data, { key: publicKey, padding: 6, saltLength: 64 }, signature);
276
+ }
277
+ if (alg === "rsa-v1_5-sha256") {
278
+ return verify(hash, data, publicKey, signature);
279
+ }
280
+ return verify(hash, data, { key: publicKey, dsaEncoding: "ieee-p1363" }, signature);
281
+ }
282
+ function toPublicKey(material) {
283
+ if (typeof material === "string") {
284
+ const trimmed = material.trim();
285
+ if (trimmed.startsWith("{")) {
286
+ return createPublicKey({ key: JSON.parse(trimmed), format: "jwk" });
287
+ }
288
+ return createPublicKey(material);
289
+ }
290
+ return createPublicKey(Buffer.from(material));
291
+ }
292
+ function decodeSignature(sig) {
293
+ if (sig.startsWith("0x")) return Buffer.from(sig.slice(2), "hex");
294
+ if (/[-_]/.test(sig)) return Buffer.from(sig, "base64url");
295
+ return Buffer.from(sig, "base64");
296
+ }
297
+ async function responseCommitmentHash(event) {
298
+ const { scheme, signedPayload } = event.receipt;
299
+ switch (scheme) {
300
+ case "jws": {
301
+ const segs = signedPayload.split(".");
302
+ if (segs.length < 2 || !segs[1]) return null;
303
+ const body = Buffer.from(segs[1], "base64url").toString("utf8");
304
+ return sha256StringHex(body);
305
+ }
306
+ case "stripe-webhook":
307
+ case "github-webhook":
308
+ return sha256StringHex(signedPayload);
309
+ case "http-message-signatures":
310
+ return contentDigestSha256Hex(signedPayload);
311
+ default:
312
+ return null;
313
+ }
314
+ }
315
+ function jwsBindingContext(event) {
316
+ if (event.receipt.scheme !== "jws") return null;
317
+ const seg0 = event.receipt.signedPayload.split(".")[0];
318
+ if (!seg0) return null;
319
+ try {
320
+ const header = JSON.parse(Buffer.from(seg0, "base64url").toString("utf8"));
321
+ const b = header.orynqBinding;
322
+ if (!b || typeof b.runId !== "string") return null;
323
+ return typeof b.requestHash === "string" ? { runId: b.runId, requestHash: b.requestHash } : { runId: b.runId };
324
+ } catch {
325
+ return null;
326
+ }
327
+ }
328
+ function contentDigestSha256Hex(signatureBase) {
329
+ for (const line of signatureBase.split("\n")) {
330
+ const m = /^"content-digest":\s*(.+)$/i.exec(line.trim());
331
+ if (!m) continue;
332
+ const d = /sha-256=:([A-Za-z0-9+/=]+):/.exec(m[1]);
333
+ if (!d || !d[1]) return null;
334
+ return Buffer.from(d[1], "base64").toString("hex");
335
+ }
336
+ return null;
337
+ }
338
+ var BUILTIN_TOOL_RECEIPT_VERIFIERS = {
339
+ "stripe-webhook": verifyStripeReceipt,
340
+ "github-webhook": verifyGitHubReceipt,
341
+ jws: verifyJwsReceipt,
342
+ "http-message-signatures": verifyHttpMessageReceipt
343
+ };
344
+ function hexEq(a, b) {
345
+ const na = a.startsWith("0x") ? a.slice(2) : a;
346
+ const nb = b.startsWith("0x") ? b.slice(2) : b;
347
+ return na.toLowerCase() === nb.toLowerCase();
348
+ }
349
+ function extractToolReceipts(bundle) {
350
+ return bundle.privateRun.events.filter(
351
+ (e) => e.kind === "tool-receipt"
352
+ );
353
+ }
354
+ async function verifyToolReceipt(event, ctx) {
355
+ const scheme = event.receipt.scheme;
356
+ const base = {
357
+ eventId: event.id,
358
+ toolId: event.toolId,
359
+ scheme,
360
+ signer: event.receipt.signer
361
+ };
362
+ const callBound = false;
363
+ const verifier = ctx?.verifiers?.[scheme] ?? BUILTIN_TOOL_RECEIPT_VERIFIERS[scheme];
364
+ if (!verifier) {
365
+ return {
366
+ ...base,
367
+ callBound,
368
+ verified: false,
369
+ error: `no verifier registered for scheme "${scheme}"`
370
+ };
371
+ }
372
+ try {
373
+ const sigValid = await verifier(event, ctx);
374
+ if (!sigValid) return { ...base, callBound, verified: false, reason: "signature-invalid" };
375
+ const commit = await responseCommitmentHash(event);
376
+ if (commit === null) {
377
+ return { ...base, callBound, verified: false, reason: "response-not-bound" };
378
+ }
379
+ if (!hexEq(commit, event.response.hash)) {
380
+ return { ...base, callBound, verified: false, reason: "response-binding-mismatch" };
381
+ }
382
+ if (event.response.payload !== void 0) {
383
+ const payloadHash = await hashToolPayload(event.response.payload);
384
+ if (!hexEq(payloadHash, event.response.hash)) {
385
+ return { ...base, callBound, verified: false, reason: "response-payload-mismatch" };
386
+ }
387
+ }
388
+ let provenCallBound = false;
389
+ if (scheme === "jws") {
390
+ const bound = jwsBindingContext(event);
391
+ if (bound !== null) {
392
+ if (ctx?.runId !== void 0 && bound.runId !== ctx.runId) {
393
+ return { ...base, callBound, verified: false, reason: "call-binding-mismatch" };
394
+ }
395
+ if (bound.requestHash !== void 0 && !hexEq(bound.requestHash, event.request.hash)) {
396
+ return { ...base, callBound, verified: false, reason: "call-binding-mismatch" };
397
+ }
398
+ provenCallBound = bound.requestHash !== void 0 && hexEq(bound.requestHash, event.request.hash) && ctx?.runId !== void 0 && bound.runId === ctx.runId;
399
+ }
400
+ }
401
+ if (ctx?.requireCallBinding && !provenCallBound) {
402
+ return { ...base, callBound: provenCallBound, verified: false, reason: "call-binding-required" };
403
+ }
404
+ return { ...base, callBound: provenCallBound, verified: true };
405
+ } catch (error) {
406
+ return {
407
+ ...base,
408
+ callBound,
409
+ verified: false,
410
+ error: error instanceof Error ? error.message : String(error)
411
+ };
412
+ }
413
+ }
414
+ async function verifyToolReceipts(bundle, ctx) {
415
+ const events = extractToolReceipts(bundle);
416
+ const boundCtx = {
417
+ ...ctx,
418
+ runId: ctx?.runId ?? bundle.privateRun.id
419
+ };
420
+ const results = [];
421
+ for (const event of events) {
422
+ results.push(await verifyToolReceipt(event, boundCtx));
423
+ }
424
+ const failed = results.filter((r) => !r.verified);
425
+ return {
426
+ valid: failed.length === 0,
427
+ errors: failed.map(
428
+ (f) => `tool-receipt "${f.toolId}" (${f.scheme}) failed${f.reason ? ` [${f.reason}]` : ""}${f.error ? `: ${f.error}` : ""}`
429
+ ),
430
+ results
431
+ };
432
+ }
433
+ async function verifyTrace(bundle, ctx) {
434
+ const outcome = await verifyToolReceipts(bundle, ctx);
435
+ const result = await verifyBundle(bundle, {
436
+ toolReceipts: () => ({ valid: outcome.valid, errors: outcome.errors })
437
+ });
438
+ return { ...result, toolReceipts: outcome };
439
+ }
440
+ function b64url(input) {
441
+ return Buffer.from(input).toString("base64url");
442
+ }
443
+ function signJws(opts, signingInput) {
444
+ const data = Buffer.from(signingInput, "utf8");
445
+ if (opts.alg === "HS256") {
446
+ if (!opts.secret) throw new Error("createSigningProxy(HS256): `secret` is required");
447
+ return createHmac("sha256", opts.secret).update(data).digest();
448
+ }
449
+ if (!opts.privateKey) {
450
+ throw new Error(`createSigningProxy(${opts.alg}): \`privateKey\` is required`);
451
+ }
452
+ const key = typeof opts.privateKey === "string" ? createPrivateKey(opts.privateKey) : opts.privateKey;
453
+ if (opts.alg === "EdDSA") return sign(null, data, key);
454
+ if (opts.alg.startsWith("ES")) {
455
+ return sign(`sha${opts.alg.slice(2)}`, data, { key, dsaEncoding: "ieee-p1363" });
456
+ }
457
+ if (opts.alg.startsWith("PS")) {
458
+ return sign(`sha${opts.alg.slice(2)}`, data, {
459
+ key,
460
+ padding: 6,
461
+ saltLength: Number(opts.alg.slice(2)) / 8
462
+ });
463
+ }
464
+ if (opts.alg.startsWith("RS")) {
465
+ return sign(`sha${opts.alg.slice(2)}`, data, key);
466
+ }
467
+ throw new Error(`createSigningProxy: unsupported alg "${opts.alg}"`);
468
+ }
469
+ function createSigningProxy(opts) {
470
+ if (!opts.signer) throw new Error("createSigningProxy: `signer` is required");
471
+ return {
472
+ sign(payload) {
473
+ const header = { alg: opts.alg, typ: "JWT", kid: opts.signer };
474
+ if (opts.binding) {
475
+ header.orynqBinding = {
476
+ runId: opts.binding.runId,
477
+ ...opts.binding.requestHash !== void 0 ? { requestHash: opts.binding.requestHash } : {}
478
+ };
479
+ }
480
+ const h = b64url(JSON.stringify(header));
481
+ const body = typeof payload === "string" ? payload : canonicalize(payload);
482
+ const p = b64url(body);
483
+ const signingInput = `${h}.${p}`;
484
+ const sigB64 = b64url(signJws(opts, signingInput));
485
+ return {
486
+ // signedPayload is the JWS *signing input* (the bytes actually signed);
487
+ // the signature is carried separately so it is independently checkable.
488
+ scheme: "jws",
489
+ signer: opts.signer,
490
+ signature: sigB64,
491
+ signedPayload: signingInput,
492
+ ...opts.publicKey ? { params: { publicKey: opts.publicKey } } : {}
493
+ };
494
+ }
495
+ };
496
+ }
497
+
498
+ // src/index.ts
499
+ var VERSION = "0.1.0";
500
+
501
+ export { BUILTIN_TOOL_RECEIPT_VERIFIERS, VERSION, addToolReceipt, createSigningProxy, extractToolReceipts, hashToolPayload, jwsBindingContext, verifyGitHubReceipt, verifyHttpMessageReceipt, verifyJwsReceipt, verifyStripeReceipt, verifyToolReceipt, verifyToolReceipts, verifyTrace };
502
+ //# sourceMappingURL=index.js.map
503
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/record.ts","../src/schemes.ts","../src/verify.ts","../src/signing-proxy.ts","../src/index.ts"],"names":["t","cryptoVerify","keyMaterial","sha256StringHex","createHmac","cryptoSign","canonicalize"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @fileoverview Helpers to record `tool-receipt` events into a trace (issue #60).\n */\n\nimport type {\n TraceRun,\n TraceEvent,\n ToolReceiptEvent,\n Visibility,\n} from \"@fluxpointstudios/orynq-sdk-process-trace\";\nimport { addEvent } from \"@fluxpointstudios/orynq-sdk-process-trace\";\nimport { sha256StringHex, canonicalize } from \"@fluxpointstudios/orynq-sdk-core/utils\";\n\n/**\n * Deterministically hash a request/response payload for the `request.hash` /\n * `response.hash` commitments (canonical JSON, SHA-256 hex). Strings are hashed\n * as-is; everything else is canonicalized first.\n */\nexport async function hashToolPayload(value: unknown): Promise<string> {\n const serialized = typeof value === \"string\" ? value : canonicalize(value);\n return sha256StringHex(serialized);\n}\n\nexport interface AddToolReceiptOptions {\n toolId: string;\n /** Commitment to the request (use {@link hashToolPayload}). */\n request: { hash: string };\n /** Commitment to the response, with an optional retained payload. */\n response: { hash: string; payload?: unknown };\n /** The independently-verifiable signed receipt. */\n receipt: ToolReceiptEvent[\"receipt\"];\n /** Event visibility (default \"private\" — responses may carry PII). */\n visibility?: Visibility;\n}\n\n/**\n * Append a `tool-receipt` event to a span.\n *\n * @returns the recorded {@link ToolReceiptEvent} (with runtime fields).\n */\nexport async function addToolReceipt(\n run: TraceRun,\n spanId: string,\n opts: AddToolReceiptOptions\n): Promise<ToolReceiptEvent> {\n if (!opts.toolId) throw new Error(\"addToolReceipt: toolId is required\");\n if (!opts.receipt) throw new Error(\"addToolReceipt: receipt is required\");\n\n const event: Omit<ToolReceiptEvent, \"id\" | \"seq\" | \"timestamp\" | \"hash\"> = {\n kind: \"tool-receipt\",\n visibility: opts.visibility ?? \"private\",\n toolId: opts.toolId,\n request: opts.request,\n response: opts.response,\n receipt: opts.receipt,\n };\n\n const recorded: TraceEvent = await addEvent(run, spanId, event);\n return recorded as ToolReceiptEvent;\n}\n","/**\n * @fileoverview Signature-scheme verifiers for tool-call receipts (issue #60).\n *\n * Each verifier checks that `receipt.signature` is a valid signature over\n * `receipt.signedPayload` for `receipt.signer`, per its scheme:\n *\n * - `http-message-signatures` — RFC 9421 (signature base provided as signedPayload)\n * - `stripe-webhook` — Stripe `Stripe-Signature` HMAC-SHA256 (timestamped; freshness-checked)\n * - `github-webhook` — GitHub `X-Hub-Signature-256` HMAC-SHA256 (no signed\n * timestamp; freshness-checked only when `params.timestamp` is recorded,\n * otherwise anti-replay rests on the bundle Merkle commitment)\n * - `jws` — compact JWS / JWT (HS*, RS*, PS*, ES*, EdDSA)\n *\n * Symmetric secrets (webhooks, HS*) MUST be supplied out-of-band via the\n * {@link ToolReceiptVerifyContext} — never embedded in the trace. Asymmetric\n * *public* keys may be embedded in `receipt.params.publicKey`.\n */\n\nimport {\n createHmac,\n createPublicKey,\n timingSafeEqual,\n verify as cryptoVerify,\n type KeyObject,\n} from \"node:crypto\";\nimport type { ToolReceiptEvent } from \"@fluxpointstudios/orynq-sdk-process-trace\";\nimport { sha256StringHex } from \"@fluxpointstudios/orynq-sdk-core/utils\";\n\ntype MaybePromise<T> = T | Promise<T>;\n\n/** Key/secret resolution + policy context for receipt verification. */\nexport interface ToolReceiptVerifyContext {\n /** Verification keys/secrets keyed by `receipt.signer`. */\n keys?: Record<string, string>;\n /** Dynamic key/secret resolver (takes precedence over `keys`). */\n resolveKey?: (event: ToolReceiptEvent) => MaybePromise<string | Uint8Array | undefined>;\n /** Max age (seconds) for replay-protected schemes (Stripe). Default 300. */\n toleranceSec?: number;\n /** Epoch-seconds clock override (testing). */\n nowSec?: number;\n /**\n * Optional per-signer expected-algorithm allow-list (defense-in-depth against\n * algorithm confusion). When present for a signer, any receipt whose resolved\n * `alg` is not listed is rejected — e.g. `{ \"tee://oracle\": [\"EdDSA\"] }` pins\n * that signer to EdDSA so an attacker-set `alg:HS256` is refused.\n */\n keyAlgs?: Record<string, string[]>;\n /**\n * Accept a public key embedded in `receipt.params.publicKey` when no\n * out-of-band key is configured. This is a CONVENIENCE for internal\n * consistency checks only — it is NOT an authenticity guarantee, because the\n * trace (and therefore the embedded key) is attacker-controlled. Default\n * false; supply the signer's key via `keys`/`resolveKey` for a trustworthy\n * verdict.\n */\n trustEmbeddedKeys?: boolean;\n}\n\nconst textEncoder = new TextEncoder();\n\nfunction utf8(s: string): Buffer {\n return Buffer.from(textEncoder.encode(s));\n}\n\nfunction constantTimeEqualHex(a: string, b: string): boolean {\n const ab = Buffer.from(a.toLowerCase(), \"hex\");\n const bb = Buffer.from(b.toLowerCase(), \"hex\");\n if (ab.length === 0 || ab.length !== bb.length) return false;\n return timingSafeEqual(ab, bb);\n}\n\nasync function resolveKey(\n event: ToolReceiptEvent,\n ctx: ToolReceiptVerifyContext | undefined,\n { allowEmbedded }: { allowEmbedded: boolean }\n): Promise<string | Uint8Array | undefined> {\n if (ctx?.resolveKey) {\n const k = await ctx.resolveKey(event);\n if (k !== undefined) return k;\n }\n if (ctx?.keys && Object.prototype.hasOwnProperty.call(ctx.keys, event.receipt.signer)) {\n return ctx.keys[event.receipt.signer];\n }\n // An embedded public key lives in the untrusted trace, so it is NOT trusted\n // for a passing verdict unless the caller explicitly opts in. Prefer an\n // out-of-band key via keys/resolveKey.\n if (allowEmbedded && ctx?.trustEmbeddedKeys === true) {\n const p = event.receipt.params;\n if (p && typeof p.publicKey === \"string\") return p.publicKey;\n }\n return undefined;\n}\n\nfunction keyToString(key: string | Uint8Array): string {\n return typeof key === \"string\" ? key : Buffer.from(key).toString(\"utf8\");\n}\n\n/** Algorithm-OID DER byte sequences that appear inside a SubjectPublicKeyInfo. */\nconst SPKI_ALG_OIDS: readonly (readonly number[])[] = [\n // rsaEncryption 1.2.840.113549.1.1.1\n [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01],\n // id-ecPublicKey 1.2.840.10045.2.1\n [0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01],\n // id-Ed25519 1.3.101.112\n [0x2b, 0x65, 0x70],\n // id-Ed448 1.3.101.113\n [0x2b, 0x65, 0x71],\n];\n\n/**\n * True when raw bytes are a DER-encoded SubjectPublicKeyInfo: an outer SEQUENCE\n * (`0x30`) whose DER length header (short-form `< 0x80`, or long-form `0x81`/\n * `0x82`) frames the whole buffer, carrying a known asymmetric algorithm OID.\n * Covers Ed25519 (`30 2a`), EC P-256/P-384 (`30 59`/`30 76`), and RSA\n * (`30 82 ..`). This catches a public key handed to the HMAC path as raw DER\n * (Uint8Array/Buffer), which the PEM/JWK string checks above miss.\n */\nfunction looksLikeDerPublicKey(bytes: Uint8Array): boolean {\n if (bytes.length < 8 || bytes[0] !== 0x30) return false;\n const lenByte = bytes[1]!;\n let contentStart: number;\n let contentLen: number;\n if (lenByte < 0x80) {\n contentStart = 2;\n contentLen = lenByte;\n } else if (lenByte === 0x81) {\n contentStart = 3;\n contentLen = bytes[2]!;\n } else if (lenByte === 0x82) {\n contentStart = 4;\n contentLen = (bytes[2]! << 8) | bytes[3]!;\n } else {\n return false;\n }\n // The length header must frame exactly the remaining bytes — a genuine DER doc,\n // not arbitrary secret bytes that happen to start with 0x30.\n if (contentStart + contentLen !== bytes.length) return false;\n return SPKI_ALG_OIDS.some((oid) => indexOfBytes(bytes, oid) !== -1);\n}\n\n/** Index of a byte subsequence in a byte array, or -1. */\nfunction indexOfBytes(haystack: Uint8Array, needle: readonly number[]): number {\n outer: for (let i = 0; i + needle.length <= haystack.length; i++) {\n for (let j = 0; j < needle.length; j++) {\n if (haystack[i + j] !== needle[j]) continue outer;\n }\n return i;\n }\n return -1;\n}\n\n/**\n * True when the resolved key material is an ASYMMETRIC PUBLIC key — a PEM\n * SPKI/PKCS#1 public block, a JWK with an asymmetric `kty`, or raw DER-encoded\n * SubjectPublicKeyInfo bytes. Such material is public (known to an attacker), so\n * it must NEVER be fed into an HMAC branch: an attacker who sets `alg:HS256`\n * could HMAC with the public key and forge a \"valid\" symmetric signature (JWT\n * algorithm confusion).\n */\nfunction looksLikeAsymmetricPublicKey(key: string | Uint8Array): boolean {\n if (typeof key !== \"string\" && looksLikeDerPublicKey(key)) return true;\n const s = keyToString(key).trim();\n if (\n s.includes(\"-----BEGIN PUBLIC KEY-----\") ||\n s.includes(\"-----BEGIN RSA PUBLIC KEY-----\")\n ) {\n return true;\n }\n if (s.startsWith(\"{\")) {\n try {\n const jwk = JSON.parse(s) as { kty?: unknown };\n const kty = typeof jwk.kty === \"string\" ? jwk.kty.toUpperCase() : \"\";\n return kty === \"RSA\" || kty === \"EC\" || kty === \"OKP\";\n } catch {\n return false;\n }\n }\n return false;\n}\n\n/**\n * Guard an HMAC/symmetric verification against a key that is actually an\n * asymmetric public key. Symmetric secrets are arbitrary bytes, so we only\n * refuse material that is unambiguously a public key.\n */\nfunction assertSymmetricSecret(key: string | Uint8Array, algLabel: string): void {\n if (looksLikeAsymmetricPublicKey(key)) {\n throw new Error(\n `${algLabel}: refusing to HMAC with an asymmetric public key (algorithm confusion). ` +\n \"Provide the signer's symmetric secret out-of-band, or pin the asymmetric alg via keyAlgs.\"\n );\n }\n}\n\n/**\n * Enforce the optional per-signer expected-algorithm allow-list (defense in\n * depth). Throws when the signer is pinned and `alg` is not allowed.\n */\nfunction assertAlgAllowed(\n event: ToolReceiptEvent,\n ctx: ToolReceiptVerifyContext | undefined,\n alg: string\n): void {\n const allow = ctx?.keyAlgs?.[event.receipt.signer];\n if (allow && !allow.includes(alg)) {\n throw new Error(\n `alg \"${alg}\" is not in the expected-algorithm allow-list for signer \"${event.receipt.signer}\"`\n );\n }\n}\n\n// =============================================================================\n// Stripe webhook (HMAC-SHA256 over `${t}.${payload}`)\n// =============================================================================\n\n/** Parse a `t=...,v1=...` Stripe-Signature header (or fall back to a bare hex sig). */\nfunction parseStripeSignature(\n raw: string,\n params: Record<string, unknown> | undefined\n): { t?: string; v1: string[] } {\n if (raw.includes(\"v1=\") || raw.includes(\"t=\")) {\n const parts = raw.split(\",\").map((p) => p.trim());\n let t: string | undefined;\n const v1: string[] = [];\n for (const part of parts) {\n const eq = part.indexOf(\"=\");\n if (eq === -1) continue;\n const k = part.slice(0, eq);\n const v = part.slice(eq + 1);\n if (k === \"t\") t = v;\n else if (k === \"v1\") v1.push(v);\n }\n return t !== undefined ? { t, v1 } : { v1 };\n }\n // Bare signature: timestamp must come from params.\n const t = typeof params?.timestamp === \"string\" ? (params.timestamp as string) : undefined;\n return t !== undefined ? { t, v1: [raw] } : { v1: [raw] };\n}\n\nexport async function verifyStripeReceipt(\n event: ToolReceiptEvent,\n ctx?: ToolReceiptVerifyContext\n): Promise<boolean> {\n const secret = await resolveKey(event, ctx, { allowEmbedded: false });\n if (secret === undefined) {\n throw new Error(\n \"stripe-webhook: signing secret not found — provide it via verify context (keys/resolveKey), not the trace\"\n );\n }\n const { t, v1 } = parseStripeSignature(event.receipt.signature, event.receipt.params);\n if (t === undefined) throw new Error(\"stripe-webhook: missing timestamp (t)\");\n if (v1.length === 0) throw new Error(\"stripe-webhook: missing v1 signature\");\n\n const toleranceSec = ctx?.toleranceSec ?? 300;\n const now = ctx?.nowSec ?? Math.floor(Date.now() / 1000);\n const ts = Number(t);\n if (!Number.isFinite(ts)) throw new Error(\"stripe-webhook: invalid timestamp\");\n if (Math.abs(now - ts) > toleranceSec) {\n throw new Error(`stripe-webhook: timestamp outside tolerance (${toleranceSec}s)`);\n }\n\n const signedBase = `${t}.${event.receipt.signedPayload}`;\n const expected = createHmac(\"sha256\", keyToString(secret)).update(signedBase).digest(\"hex\");\n return v1.some((candidate) => constantTimeEqualHex(expected, candidate));\n}\n\n// =============================================================================\n// GitHub webhook (HMAC-SHA256, `sha256=...`)\n// =============================================================================\n\nexport async function verifyGitHubReceipt(\n event: ToolReceiptEvent,\n ctx?: ToolReceiptVerifyContext\n): Promise<boolean> {\n const secret = await resolveKey(event, ctx, { allowEmbedded: false });\n if (secret === undefined) {\n throw new Error(\n \"github-webhook: signing secret not found — provide it via verify context (keys/resolveKey)\"\n );\n }\n // GitHub's signature carries no timestamp, so freshness can't be enforced\n // cryptographically — a timestamp-less receipt's anti-replay is the bundle\n // Merkle commitment. When the recorder DID capture `params.timestamp`, hold it\n // to the same tolerance window Stripe uses so a stale receipt is rejected.\n const ts = event.receipt.params?.timestamp;\n if (typeof ts === \"string\" || typeof ts === \"number\") {\n const tsNum = Number(ts);\n if (!Number.isFinite(tsNum)) throw new Error(\"github-webhook: invalid timestamp\");\n const toleranceSec = ctx?.toleranceSec ?? 300;\n const now = ctx?.nowSec ?? Math.floor(Date.now() / 1000);\n if (Math.abs(now - tsNum) > toleranceSec) {\n throw new Error(`github-webhook: timestamp outside tolerance (${toleranceSec}s)`);\n }\n }\n const provided = event.receipt.signature.startsWith(\"sha256=\")\n ? event.receipt.signature.slice(\"sha256=\".length)\n : event.receipt.signature;\n const expected = createHmac(\"sha256\", keyToString(secret))\n .update(event.receipt.signedPayload)\n .digest(\"hex\");\n return constantTimeEqualHex(expected, provided);\n}\n\n// =============================================================================\n// JWS / JWT (compact)\n// =============================================================================\n\ninterface JwsParts {\n signingInput: string;\n signature: Buffer;\n header: { alg?: string; [k: string]: unknown };\n}\n\nfunction parseJws(event: ToolReceiptEvent): JwsParts {\n const sp = event.receipt.signedPayload;\n const segments = sp.split(\".\");\n let signingInput: string;\n let sigB64: string;\n if (segments.length === 3) {\n // signedPayload is the full compact JWS.\n signingInput = `${segments[0]}.${segments[1]}`;\n sigB64 = segments[2]!;\n } else if (segments.length === 2) {\n // signedPayload is the signing input; signature carried separately.\n signingInput = sp;\n sigB64 = event.receipt.signature;\n } else {\n throw new Error(\"jws: signedPayload must be a compact JWS (h.p.s) or signing input (h.p)\");\n }\n const headerJson = Buffer.from(segments[0]!, \"base64url\").toString(\"utf8\");\n const header = JSON.parse(headerJson) as { alg?: string };\n return { signingInput, signature: Buffer.from(sigB64, \"base64url\"), header };\n}\n\nexport async function verifyJwsReceipt(\n event: ToolReceiptEvent,\n ctx?: ToolReceiptVerifyContext\n): Promise<boolean> {\n const { signingInput, signature, header } = parseJws(event);\n const alg = header.alg;\n if (!alg || alg === \"none\") throw new Error(`jws: unsupported alg \"${alg}\"`);\n assertAlgAllowed(event, ctx, alg);\n const data = utf8(signingInput);\n\n if (alg.startsWith(\"HS\")) {\n const secret = await resolveKey(event, ctx, { allowEmbedded: false });\n if (secret === undefined) throw new Error(`jws(${alg}): HMAC secret not found in verify context`);\n // The alg comes from the attacker-controlled JWS header. Refuse to HMAC with\n // an asymmetric public key (JWT algorithm confusion).\n assertSymmetricSecret(secret, `jws(${alg})`);\n const hashAlg = `sha${alg.slice(2)}`;\n const expected = createHmac(hashAlg, keyToString(secret)).update(data).digest();\n return expected.length === signature.length && timingSafeEqual(expected, signature);\n }\n\n // Asymmetric — public key may be embedded.\n const keyMaterial = await resolveKey(event, ctx, { allowEmbedded: true });\n if (keyMaterial === undefined) throw new Error(`jws(${alg}): public key not found`);\n const publicKey = toPublicKey(keyMaterial);\n\n if (alg.startsWith(\"RS\")) {\n return cryptoVerify(`sha${alg.slice(2)}`, data, publicKey, signature);\n }\n if (alg.startsWith(\"PS\")) {\n const bits = alg.slice(2);\n return cryptoVerify(\n `sha${bits}`,\n data,\n { key: publicKey, padding: 6 /* RSA_PKCS1_PSS_PADDING */, saltLength: Number(bits) / 8 },\n signature\n );\n }\n if (alg.startsWith(\"ES\")) {\n // JWS ECDSA signatures are raw r||s (IEEE-P1363).\n return cryptoVerify(\n `sha${alg.slice(2)}`,\n data,\n { key: publicKey, dsaEncoding: \"ieee-p1363\" },\n signature\n );\n }\n if (alg === \"EdDSA\") {\n return cryptoVerify(null, data, publicKey, signature);\n }\n throw new Error(`jws: unsupported alg \"${alg}\"`);\n}\n\n// =============================================================================\n// RFC 9421 — HTTP Message Signatures\n// =============================================================================\n\n/** RFC 9421 algorithm registry names we support. */\nconst RFC9421_HASH: Record<string, string> = {\n \"rsa-pss-sha512\": \"sha512\",\n \"rsa-v1_5-sha256\": \"sha256\",\n \"ecdsa-p256-sha256\": \"sha256\",\n \"ecdsa-p384-sha384\": \"sha384\",\n};\n\nexport async function verifyHttpMessageReceipt(\n event: ToolReceiptEvent,\n ctx?: ToolReceiptVerifyContext\n): Promise<boolean> {\n const params = event.receipt.params ?? {};\n const alg = typeof params.alg === \"string\" ? (params.alg as string) : undefined;\n if (!alg) {\n throw new Error(\"http-message-signatures: receipt.params.alg is required (RFC 9421 alg id)\");\n }\n assertAlgAllowed(event, ctx, alg);\n // The signature base is the canonical signed bytes.\n const data = utf8(event.receipt.signedPayload);\n const signature = decodeSignature(event.receipt.signature);\n\n if (alg === \"ed25519\") {\n const keyMaterial = await resolveKey(event, ctx, { allowEmbedded: true });\n if (keyMaterial === undefined) throw new Error(\"http-message-signatures(ed25519): public key not found\");\n return cryptoVerify(null, data, toPublicKey(keyMaterial), signature);\n }\n\n if (alg === \"hmac-sha256\") {\n const secret = await resolveKey(event, ctx, { allowEmbedded: false });\n if (secret === undefined) throw new Error(\"http-message-signatures(hmac-sha256): secret not found\");\n // The alg is attacker-controlled — refuse to HMAC with an asymmetric public\n // key (algorithm confusion).\n assertSymmetricSecret(secret, \"http-message-signatures(hmac-sha256)\");\n const expected = createHmac(\"sha256\", keyToString(secret)).update(data).digest();\n return expected.length === signature.length && timingSafeEqual(expected, signature);\n }\n\n const hash = RFC9421_HASH[alg];\n if (!hash) throw new Error(`http-message-signatures: unsupported alg \"${alg}\"`);\n const keyMaterial = await resolveKey(event, ctx, { allowEmbedded: true });\n if (keyMaterial === undefined) throw new Error(`http-message-signatures(${alg}): public key not found`);\n const publicKey = toPublicKey(keyMaterial);\n\n if (alg === \"rsa-pss-sha512\") {\n return cryptoVerify(hash, data, { key: publicKey, padding: 6, saltLength: 64 }, signature);\n }\n if (alg === \"rsa-v1_5-sha256\") {\n return cryptoVerify(hash, data, publicKey, signature);\n }\n // ECDSA — RFC 9421 uses raw (IEEE-P1363) signatures.\n return cryptoVerify(hash, data, { key: publicKey, dsaEncoding: \"ieee-p1363\" }, signature);\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nfunction toPublicKey(material: string | Uint8Array): KeyObject {\n if (typeof material === \"string\") {\n const trimmed = material.trim();\n if (trimmed.startsWith(\"{\")) {\n return createPublicKey({ key: JSON.parse(trimmed), format: \"jwk\" });\n }\n return createPublicKey(material);\n }\n return createPublicKey(Buffer.from(material));\n}\n\n/**\n * Decode a signature string that may be 0x-hex, base64url, or standard base64\n * (the encodings used by RFC 9421 / JWS receipts in the wild).\n */\nfunction decodeSignature(sig: string): Buffer {\n if (sig.startsWith(\"0x\")) return Buffer.from(sig.slice(2), \"hex\");\n if (/[-_]/.test(sig)) return Buffer.from(sig, \"base64url\");\n return Buffer.from(sig, \"base64\");\n}\n\n// =============================================================================\n// Response binding — the signed content must commit to the recorded response\n// =============================================================================\n\n/**\n * The sha-256 hex the signed material commits to, or `null` when the scheme's\n * signed bytes structurally cannot bind the response (e.g. an RFC 9421\n * signature base with no `content-digest` component). A `null` MUST cause\n * verification to fail: a valid signature that does not cover the recorded\n * response proves nothing about it.\n */\nexport async function responseCommitmentHash(event: ToolReceiptEvent): Promise<string | null> {\n const { scheme, signedPayload } = event.receipt;\n switch (scheme) {\n case \"jws\": {\n // signedPayload is the JWS signing input `h.p[.s]`; the payload segment\n // is the exact bytes the tool signed (canonical response body).\n const segs = signedPayload.split(\".\");\n if (segs.length < 2 || !segs[1]) return null;\n const body = Buffer.from(segs[1], \"base64url\").toString(\"utf8\");\n return sha256StringHex(body);\n }\n case \"stripe-webhook\":\n case \"github-webhook\":\n // The signed webhook body IS the tool response.\n return sha256StringHex(signedPayload);\n case \"http-message-signatures\":\n // RFC 9421 signs a signature base, not the body; the body is bound only\n // via a `content-digest` component inside that base.\n return contentDigestSha256Hex(signedPayload);\n default:\n return null;\n }\n}\n\n/**\n * Read the signed call-binding context ({runId, requestHash}) from a self-signed\n * JWS receipt's header, or `null` when the receipt is not a bound JWS. Because\n * the header is part of the JWS signing input, these values are covered by the\n * signature — lifting the receipt into another trace/request breaks the match.\n */\nexport function jwsBindingContext(\n event: ToolReceiptEvent\n): { runId: string; requestHash?: string } | null {\n if (event.receipt.scheme !== \"jws\") return null;\n const seg0 = event.receipt.signedPayload.split(\".\")[0];\n if (!seg0) return null;\n try {\n const header = JSON.parse(Buffer.from(seg0, \"base64url\").toString(\"utf8\")) as {\n orynqBinding?: { runId?: unknown; requestHash?: unknown };\n };\n const b = header.orynqBinding;\n if (!b || typeof b.runId !== \"string\") return null;\n return typeof b.requestHash === \"string\"\n ? { runId: b.runId, requestHash: b.requestHash }\n : { runId: b.runId };\n } catch {\n return null;\n }\n}\n\n/** Extract the sha-256 content-digest (hex) from an RFC 9421 signature base. */\nfunction contentDigestSha256Hex(signatureBase: string): string | null {\n for (const line of signatureBase.split(\"\\n\")) {\n const m = /^\"content-digest\":\\s*(.+)$/i.exec(line.trim());\n if (!m) continue;\n const d = /sha-256=:([A-Za-z0-9+/=]+):/.exec(m[1]!);\n if (!d || !d[1]) return null;\n return Buffer.from(d[1], \"base64\").toString(\"hex\");\n }\n return null;\n}\n","/**\n * @fileoverview Verification dispatch for tool-call receipts (issue #60).\n *\n * `verifyToolReceipts(bundle, ctx)` verifies every `tool-receipt` event in a\n * bundle; `verifyTrace(bundle, ctx)` additionally runs the full process-trace\n * `verifyBundle()` and folds the receipt result into its `checks` so a single\n * call gives auditors \"did the trace verify AND did every tool actually return\n * what the wrapper claims\".\n */\n\nimport type {\n ToolReceiptEvent,\n TraceBundle,\n TraceVerificationResult,\n} from \"@fluxpointstudios/orynq-sdk-process-trace\";\nimport { verifyBundle } from \"@fluxpointstudios/orynq-sdk-process-trace\";\nimport {\n verifyStripeReceipt,\n verifyGitHubReceipt,\n verifyJwsReceipt,\n verifyHttpMessageReceipt,\n responseCommitmentHash,\n jwsBindingContext,\n type ToolReceiptVerifyContext,\n} from \"./schemes.js\";\nimport { hashToolPayload } from \"./record.js\";\n\n/** A verifier for a single receipt scheme. */\nexport type ToolReceiptSchemeVerifier = (\n event: ToolReceiptEvent,\n ctx?: ToolReceiptVerifyContext\n) => Promise<boolean>;\n\n/** Built-in verifiers keyed by `receipt.scheme`. */\nexport const BUILTIN_TOOL_RECEIPT_VERIFIERS: Record<string, ToolReceiptSchemeVerifier> = {\n \"stripe-webhook\": verifyStripeReceipt,\n \"github-webhook\": verifyGitHubReceipt,\n jws: verifyJwsReceipt,\n \"http-message-signatures\": verifyHttpMessageReceipt,\n};\n\n/** Per-receipt verification result. */\nexport interface ToolReceiptVerificationResult {\n eventId: string;\n toolId: string;\n scheme: string;\n signer: string;\n verified: boolean;\n /**\n * True ONLY when the signature cryptographically binds this receipt to THIS\n * trace's runId AND the recorded request hash (self-signed JWS anti-lie path,\n * with a signed `orynqBinding.{runId,requestHash}` that both matched). A JWS\n * with no binding, or one that binds only the runId, is `false` — the request\n * is not authenticated. Always `false` for external webhook schemes\n * (stripe/github/rfc9421): those prove authenticity of the response body but\n * cannot cover our runId/request, so call-binding is not provable by the\n * signature and request-attribution must not be inferred — anti-replay for them\n * relies on the bundle Merkle commitment + the scheme's own timestamp window.\n */\n callBound: boolean;\n /** When not verified, a short machine-readable reason. */\n reason?: string;\n error?: string;\n}\n\n/** Case-insensitive, 0x-tolerant hex equality. */\nfunction hexEq(a: string, b: string): boolean {\n const na = a.startsWith(\"0x\") ? a.slice(2) : a;\n const nb = b.startsWith(\"0x\") ? b.slice(2) : b;\n return na.toLowerCase() === nb.toLowerCase();\n}\n\n/** Context for {@link verifyToolReceipts}; extends key resolution with custom schemes. */\nexport interface VerifyToolReceiptsContext extends ToolReceiptVerifyContext {\n /** Register or override scheme verifiers (e.g. a custom/internal scheme). */\n verifiers?: Record<string, ToolReceiptSchemeVerifier>;\n /**\n * The enclosing trace's run id. Self-signed JWS receipts commit to it (and to\n * the request hash) so a genuine receipt cannot be lifted into another trace.\n * {@link verifyToolReceipts} supplies it automatically from the bundle.\n */\n runId?: string;\n /**\n * When true, a receipt whose signature does not provably bind THIS call\n * (runId + request hash) is `verified: false` with reason `call-binding-required`.\n * Use this when request-attribution must be cryptographic: it rejects unbound\n * JWS receipts and all webhook schemes (whose external signatures cannot cover\n * our request). Default false — call-binding is reported via `callBound` but not\n * required.\n */\n requireCallBinding?: boolean;\n}\n\n/** Extract all `tool-receipt` events from a bundle (ordered by seq). */\nexport function extractToolReceipts(bundle: TraceBundle): ToolReceiptEvent[] {\n return bundle.privateRun.events.filter(\n (e): e is ToolReceiptEvent => e.kind === \"tool-receipt\"\n );\n}\n\n/** Verify a single tool-receipt event. Never throws — failures land in `error`. */\nexport async function verifyToolReceipt(\n event: ToolReceiptEvent,\n ctx?: VerifyToolReceiptsContext\n): Promise<ToolReceiptVerificationResult> {\n const scheme = event.receipt.scheme;\n const base = {\n eventId: event.id,\n toolId: event.toolId,\n scheme,\n signer: event.receipt.signer,\n };\n // `callBound` reflects PROVEN call-binding, computed after the checks below —\n // never assumed from the scheme. Only a self-signed JWS carrying a signed\n // `orynqBinding.{runId,requestHash}` that both match can be call-bound; external\n // webhook schemes never can (their signature cannot cover our runId/request).\n const callBound = false;\n const verifier = ctx?.verifiers?.[scheme] ?? BUILTIN_TOOL_RECEIPT_VERIFIERS[scheme];\n if (!verifier) {\n return {\n ...base,\n callBound,\n verified: false,\n error: `no verifier registered for scheme \"${scheme}\"`,\n };\n }\n try {\n const sigValid = await verifier(event, ctx);\n if (!sigValid) return { ...base, callBound, verified: false, reason: \"signature-invalid\" };\n // A valid signature is necessary but NOT sufficient: the signed content\n // must commit to the recorded response, else a genuine receipt for output\n // A can be paired with a fabricated response B (issue #60's core guarantee).\n const commit = await responseCommitmentHash(event);\n if (commit === null) {\n return { ...base, callBound, verified: false, reason: \"response-not-bound\" };\n }\n if (!hexEq(commit, event.response.hash)) {\n return { ...base, callBound, verified: false, reason: \"response-binding-mismatch\" };\n }\n // Auditors read the retained human-readable `response.payload`; when present\n // it MUST hash to the bound `response.hash`, else an honest signature can be\n // paired with a fabricated payload the auditor sees.\n if (event.response.payload !== undefined) {\n const payloadHash = await hashToolPayload(event.response.payload);\n if (!hexEq(payloadHash, event.response.hash)) {\n return { ...base, callBound, verified: false, reason: \"response-payload-mismatch\" };\n }\n }\n // Self-signed JWS receipts additionally commit to a binding context\n // {runId, requestHash}. When present, the enclosing trace's runId AND the\n // recorded request hash MUST both match — this authenticates the request and\n // blocks lifting a genuine receipt into a different trace/request. A JWS that\n // binds only runId (or nothing) is NOT call-bound: its request is\n // unauthenticated. External webhooks can never cover runId/request, so their\n // anti-replay is the bundle Merkle commitment + timestamp.\n let provenCallBound = false;\n if (scheme === \"jws\") {\n const bound = jwsBindingContext(event);\n if (bound !== null) {\n // A signed binding is a commitment: any mismatch is a hard failure, not a\n // downgrade to \"unbound\" — the signer attested to a specific call.\n if (ctx?.runId !== undefined && bound.runId !== ctx.runId) {\n return { ...base, callBound, verified: false, reason: \"call-binding-mismatch\" };\n }\n if (bound.requestHash !== undefined && !hexEq(bound.requestHash, event.request.hash)) {\n return { ...base, callBound, verified: false, reason: \"call-binding-mismatch\" };\n }\n // Call-binding is PROVEN only when the request hash was signed and matched\n // AND the runId was verified against this trace. Binding only the runId\n // leaves the request unauthenticated → not call-bound.\n provenCallBound =\n bound.requestHash !== undefined &&\n hexEq(bound.requestHash, event.request.hash) &&\n ctx?.runId !== undefined &&\n bound.runId === ctx.runId;\n }\n }\n if (ctx?.requireCallBinding && !provenCallBound) {\n return { ...base, callBound: provenCallBound, verified: false, reason: \"call-binding-required\" };\n }\n return { ...base, callBound: provenCallBound, verified: true };\n } catch (error) {\n return {\n ...base,\n callBound,\n verified: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/** Aggregate outcome over all tool receipts in a bundle. */\nexport interface ToolReceiptsVerifyOutcome {\n valid: boolean;\n errors: string[];\n results: ToolReceiptVerificationResult[];\n}\n\n/** Verify every tool-receipt in a bundle. A trace with no receipts is `valid: true`. */\nexport async function verifyToolReceipts(\n bundle: TraceBundle,\n ctx?: VerifyToolReceiptsContext\n): Promise<ToolReceiptsVerifyOutcome> {\n const events = extractToolReceipts(bundle);\n // Bind receipt verification to THIS trace's run id (self-signed anti-replay).\n // An explicit ctx.runId takes precedence for advanced callers.\n const boundCtx: VerifyToolReceiptsContext = {\n ...ctx,\n runId: ctx?.runId ?? bundle.privateRun.id,\n };\n const results: ToolReceiptVerificationResult[] = [];\n for (const event of events) {\n results.push(await verifyToolReceipt(event, boundCtx));\n }\n const failed = results.filter((r) => !r.verified);\n return {\n valid: failed.length === 0,\n errors: failed.map(\n (f) =>\n `tool-receipt \"${f.toolId}\" (${f.scheme}) failed${f.reason ? ` [${f.reason}]` : \"\"}${f.error ? `: ${f.error}` : \"\"}`\n ),\n results,\n };\n}\n\n/** Combined result of {@link verifyTrace}. */\nexport interface VerifyTraceResult extends TraceVerificationResult {\n toolReceipts: ToolReceiptsVerifyOutcome;\n}\n\n/**\n * Verify the whole trace AND its tool receipts in one call. The receipt outcome\n * is folded into `checks.toolReceiptsValid` (so `valid` reflects receipts too)\n * and also returned in full under `toolReceipts`.\n */\nexport async function verifyTrace(\n bundle: TraceBundle,\n ctx?: VerifyToolReceiptsContext\n): Promise<VerifyTraceResult> {\n const outcome = await verifyToolReceipts(bundle, ctx);\n const result = await verifyBundle(bundle, {\n toolReceipts: () => ({ valid: outcome.valid, errors: outcome.errors }),\n });\n return { ...result, toolReceipts: outcome };\n}\n","/**\n * @fileoverview Signing-proxy helper — the \"anti-lie\" pattern (issue #60).\n *\n * Tools that do not sign their responses natively can be wrapped in a TEE/HSM-\n * signed envelope so the wrapper's claim (\"the tool returned X\") becomes\n * independently verifiable. This helper produces a JWS-signed\n * {@link ToolReceiptEvent.receipt} from a tool response; pair it with\n * `addToolReceipt` to record the receipt, and `verifyToolReceipts` to check it.\n *\n * @example\n * ```typescript\n * import { generateKeyPairSync } from \"node:crypto\";\n * const { privateKey, publicKey } = generateKeyPairSync(\"ed25519\");\n * const proxy = createSigningProxy({\n * signer: \"tee://pricing-proxy\",\n * alg: \"EdDSA\",\n * privateKey,\n * publicKey: publicKey.export({ type: \"spki\", format: \"pem\" }).toString(),\n * });\n * const receipt = proxy.sign({ price: 4200, currency: \"usd\" });\n * await addToolReceipt(run, span.id, { toolId, request, response, receipt });\n * ```\n */\n\nimport {\n createHmac,\n createPrivateKey,\n sign as cryptoSign,\n type KeyObject,\n} from \"node:crypto\";\nimport { canonicalize } from \"@fluxpointstudios/orynq-sdk-core/utils\";\nimport type { ToolReceiptEvent } from \"@fluxpointstudios/orynq-sdk-process-trace\";\n\n/** JWS algorithms supported by the signing proxy. */\nexport type JwsAlg =\n | \"EdDSA\"\n | \"ES256\"\n | \"ES384\"\n | \"RS256\"\n | \"RS512\"\n | \"PS256\"\n | \"PS512\"\n | \"HS256\";\n\nexport interface SigningProxyOptions {\n /** Verifier-resolvable identity recorded as `receipt.signer` (URL / DID / keyId). */\n signer: string;\n alg: JwsAlg;\n /** Private key (PEM or KeyObject) for asymmetric algorithms. */\n privateKey?: string | KeyObject;\n /** Shared secret for HS256. */\n secret?: string;\n /**\n * Public key (PEM or JWK string) to embed in `receipt.params.publicKey` so a\n * verifier can resolve it without out-of-band material. Safe to embed\n * (public keys only).\n */\n publicKey?: string;\n /**\n * Call-binding context signed into the receipt header so a genuine receipt\n * cannot be lifted into a different trace/request. Any signed value that\n * disagrees with the enclosing trace is a hard verification failure. To make a\n * receipt `callBound` (request cryptographically attributed), sign BOTH `runId`\n * AND `requestHash` — binding only the runId scopes the trace but leaves the\n * request unauthenticated, so the receipt verifies but is NOT `callBound`.\n */\n binding?: { runId: string; requestHash?: string };\n}\n\nfunction b64url(input: string | Buffer): string {\n return Buffer.from(input).toString(\"base64url\");\n}\n\nfunction signJws(opts: SigningProxyOptions, signingInput: string): Buffer {\n const data = Buffer.from(signingInput, \"utf8\");\n\n if (opts.alg === \"HS256\") {\n if (!opts.secret) throw new Error(\"createSigningProxy(HS256): `secret` is required\");\n return createHmac(\"sha256\", opts.secret).update(data).digest();\n }\n\n if (!opts.privateKey) {\n throw new Error(`createSigningProxy(${opts.alg}): \\`privateKey\\` is required`);\n }\n const key =\n typeof opts.privateKey === \"string\" ? createPrivateKey(opts.privateKey) : opts.privateKey;\n\n if (opts.alg === \"EdDSA\") return cryptoSign(null, data, key);\n if (opts.alg.startsWith(\"ES\")) {\n return cryptoSign(`sha${opts.alg.slice(2)}`, data, { key, dsaEncoding: \"ieee-p1363\" });\n }\n if (opts.alg.startsWith(\"PS\")) {\n return cryptoSign(`sha${opts.alg.slice(2)}`, data, {\n key,\n padding: 6 /* RSA_PKCS1_PSS_PADDING */,\n saltLength: Number(opts.alg.slice(2)) / 8,\n });\n }\n if (opts.alg.startsWith(\"RS\")) {\n return cryptoSign(`sha${opts.alg.slice(2)}`, data, key);\n }\n throw new Error(`createSigningProxy: unsupported alg \"${opts.alg}\"`);\n}\n\nexport interface SigningProxy {\n /** Wrap a tool response in a JWS-signed receipt ready for `addToolReceipt`. */\n sign(payload: unknown): ToolReceiptEvent[\"receipt\"];\n}\n\n/**\n * Create a signing proxy that turns unsigned tool responses into verifiable\n * JWS receipts. Use a TEE/HSM-held key in production.\n */\nexport function createSigningProxy(opts: SigningProxyOptions): SigningProxy {\n if (!opts.signer) throw new Error(\"createSigningProxy: `signer` is required\");\n return {\n sign(payload: unknown): ToolReceiptEvent[\"receipt\"] {\n // The call-binding lives in the (signed) header so the payload segment\n // stays the canonical response body the response-hash commitment covers.\n const header: Record<string, unknown> = { alg: opts.alg, typ: \"JWT\", kid: opts.signer };\n if (opts.binding) {\n header.orynqBinding = {\n runId: opts.binding.runId,\n ...(opts.binding.requestHash !== undefined\n ? { requestHash: opts.binding.requestHash }\n : {}),\n };\n }\n const h = b64url(JSON.stringify(header));\n const body = typeof payload === \"string\" ? payload : canonicalize(payload);\n const p = b64url(body);\n const signingInput = `${h}.${p}`;\n const sigB64 = b64url(signJws(opts, signingInput));\n return {\n // signedPayload is the JWS *signing input* (the bytes actually signed);\n // the signature is carried separately so it is independently checkable.\n scheme: \"jws\",\n signer: opts.signer,\n signature: sigB64,\n signedPayload: signingInput,\n ...(opts.publicKey ? { params: { publicKey: opts.publicKey } } : {}),\n };\n },\n };\n}\n","/**\n * @summary Main entry point for @fluxpointstudios/orynq-sdk-tool-receipts.\n *\n * Verifiable tool-call receipts for the Orynq process-trace SDK (issue #60).\n * Proves \"the tool actually returned this response\" — not just \"the agent says\n * the tool returned this response\" — by independently verifying signed receipts\n * recorded as `tool-receipt` events.\n *\n * Supported schemes: RFC 9421 HTTP Message Signatures, Stripe/GitHub webhook\n * signatures, and generic JWS. Plus a signing-proxy helper to wrap tools that\n * don't sign their responses natively (the \"anti-lie\" pattern).\n *\n * @example\n * ```typescript\n * import { addToolReceipt, hashToolPayload, verifyTrace } from \"@fluxpointstudios/orynq-sdk-tool-receipts\";\n *\n * await addToolReceipt(run, span.id, {\n * toolId: \"stripe.charges.create\",\n * request: { hash: await hashToolPayload(req) },\n * response: { hash: await hashToolPayload(res), payload: res },\n * receipt: { scheme: \"stripe-webhook\", signer: \"acct_123\", signature: sigHeader, signedPayload: rawBody },\n * });\n *\n * const result = await verifyTrace(bundle, { keys: { acct_123: process.env.STRIPE_WEBHOOK_SECRET! } });\n * // result.valid && result.toolReceipts.results[0].verified\n * ```\n */\n\n// Recording helpers\nexport { addToolReceipt, hashToolPayload } from \"./record.js\";\nexport type { AddToolReceiptOptions } from \"./record.js\";\n\n// Scheme verifiers + key-resolution context\nexport {\n verifyStripeReceipt,\n verifyGitHubReceipt,\n verifyJwsReceipt,\n verifyHttpMessageReceipt,\n jwsBindingContext,\n} from \"./schemes.js\";\nexport type { ToolReceiptVerifyContext } from \"./schemes.js\";\n\n// Verification dispatch\nexport {\n BUILTIN_TOOL_RECEIPT_VERIFIERS,\n extractToolReceipts,\n verifyToolReceipt,\n verifyToolReceipts,\n verifyTrace,\n} from \"./verify.js\";\nexport type {\n ToolReceiptSchemeVerifier,\n ToolReceiptVerificationResult,\n VerifyToolReceiptsContext,\n ToolReceiptsVerifyOutcome,\n VerifyTraceResult,\n} from \"./verify.js\";\n\n// Signing-proxy (anti-lie pattern)\nexport { createSigningProxy } from \"./signing-proxy.js\";\nexport type { SigningProxy, SigningProxyOptions, JwsAlg } from \"./signing-proxy.js\";\n\n/** Package version. */\nexport const VERSION = \"0.1.0\";\n"]}