@probemesh/sdk 0.1.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.
Files changed (83) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +160 -0
  3. package/dist/chunk-257Y7LN2.js +827 -0
  4. package/dist/chunk-257Y7LN2.js.map +1 -0
  5. package/dist/chunk-2ASMVLG4.js +56 -0
  6. package/dist/chunk-2ASMVLG4.js.map +1 -0
  7. package/dist/chunk-2KWGHJYP.js +285 -0
  8. package/dist/chunk-2KWGHJYP.js.map +1 -0
  9. package/dist/chunk-3H7UGVI6.js +1117 -0
  10. package/dist/chunk-3H7UGVI6.js.map +1 -0
  11. package/dist/chunk-5Q3PDYIA.js +657 -0
  12. package/dist/chunk-5Q3PDYIA.js.map +1 -0
  13. package/dist/chunk-CXZOO3U4.js +550 -0
  14. package/dist/chunk-CXZOO3U4.js.map +1 -0
  15. package/dist/chunk-FRFBK4SY.js +270 -0
  16. package/dist/chunk-FRFBK4SY.js.map +1 -0
  17. package/dist/chunk-HJK52QJF.js +994 -0
  18. package/dist/chunk-HJK52QJF.js.map +1 -0
  19. package/dist/chunk-HNBDX7IU.js +705 -0
  20. package/dist/chunk-HNBDX7IU.js.map +1 -0
  21. package/dist/chunk-NYTV263W.js +116 -0
  22. package/dist/chunk-NYTV263W.js.map +1 -0
  23. package/dist/chunk-PXG54XOG.js +595 -0
  24. package/dist/chunk-PXG54XOG.js.map +1 -0
  25. package/dist/chunk-TDOBAMYM.js +607 -0
  26. package/dist/chunk-TDOBAMYM.js.map +1 -0
  27. package/dist/chunk-TV42EZSI.js +2157 -0
  28. package/dist/chunk-TV42EZSI.js.map +1 -0
  29. package/dist/chunk-UU2ZG7P7.js +408 -0
  30. package/dist/chunk-UU2ZG7P7.js.map +1 -0
  31. package/dist/chunk-WKN7QOCA.js +977 -0
  32. package/dist/chunk-WKN7QOCA.js.map +1 -0
  33. package/dist/chunk-ZJOLPBJJ.js +1091 -0
  34. package/dist/chunk-ZJOLPBJJ.js.map +1 -0
  35. package/dist/cli/audit-trail-export.cjs +1193 -0
  36. package/dist/cli/audit-trail-export.cjs.map +1 -0
  37. package/dist/cli/audit-trail-export.d.cts +1 -0
  38. package/dist/cli/audit-trail-export.d.ts +1 -0
  39. package/dist/cli/audit-trail-export.js +24 -0
  40. package/dist/cli/audit-trail-export.js.map +1 -0
  41. package/dist/cli/catalog-check.cjs +2687 -0
  42. package/dist/cli/catalog-check.cjs.map +1 -0
  43. package/dist/cli/catalog-check.d.cts +1 -0
  44. package/dist/cli/catalog-check.d.ts +1 -0
  45. package/dist/cli/catalog-check.js +26 -0
  46. package/dist/cli/catalog-check.js.map +1 -0
  47. package/dist/cli/probemesh-init.cjs +1049 -0
  48. package/dist/cli/probemesh-init.cjs.map +1 -0
  49. package/dist/cli/probemesh-init.d.cts +1 -0
  50. package/dist/cli/probemesh-init.d.ts +1 -0
  51. package/dist/cli/probemesh-init.js +22 -0
  52. package/dist/cli/probemesh-init.js.map +1 -0
  53. package/dist/cli/provider-conformance.cjs +6180 -0
  54. package/dist/cli/provider-conformance.cjs.map +1 -0
  55. package/dist/cli/provider-conformance.d.cts +1 -0
  56. package/dist/cli/provider-conformance.d.ts +1 -0
  57. package/dist/cli/provider-conformance.js +29 -0
  58. package/dist/cli/provider-conformance.js.map +1 -0
  59. package/dist/cli/provider-dossier-check.cjs +2978 -0
  60. package/dist/cli/provider-dossier-check.cjs.map +1 -0
  61. package/dist/cli/provider-dossier-check.d.cts +1 -0
  62. package/dist/cli/provider-dossier-check.d.ts +1 -0
  63. package/dist/cli/provider-dossier-check.js +27 -0
  64. package/dist/cli/provider-dossier-check.js.map +1 -0
  65. package/dist/cli/provider-dossier.cjs +1753 -0
  66. package/dist/cli/provider-dossier.cjs.map +1 -0
  67. package/dist/cli/provider-dossier.d.cts +1 -0
  68. package/dist/cli/provider-dossier.d.ts +1 -0
  69. package/dist/cli/provider-dossier.js +26 -0
  70. package/dist/cli/provider-dossier.js.map +1 -0
  71. package/dist/cli/x402-accept.cjs +6009 -0
  72. package/dist/cli/x402-accept.cjs.map +1 -0
  73. package/dist/cli/x402-accept.d.cts +1 -0
  74. package/dist/cli/x402-accept.d.ts +1 -0
  75. package/dist/cli/x402-accept.js +28 -0
  76. package/dist/cli/x402-accept.js.map +1 -0
  77. package/dist/index.cjs +13671 -0
  78. package/dist/index.cjs.map +1 -0
  79. package/dist/index.d.cts +2026 -0
  80. package/dist/index.d.ts +2026 -0
  81. package/dist/index.js +2560 -0
  82. package/dist/index.js.map +1 -0
  83. package/package.json +111 -0
@@ -0,0 +1,657 @@
1
+ import {
2
+ redactX402Secrets
3
+ } from "./chunk-NYTV263W.js";
4
+ import {
5
+ ProbeMeshError,
6
+ isProbeMeshError
7
+ } from "./chunk-2ASMVLG4.js";
8
+
9
+ // src/callAuditArtifact.ts
10
+ import { createHash } from "crypto";
11
+ var PROBEMESH_CALL_AUDIT_ARTIFACT_SCHEMA_VERSION = "probemesh.call-audit.v1";
12
+ function createProbeMeshCallAuditArtifact(options) {
13
+ assertAuditArtifactOptions(options);
14
+ const requestHash = hashStableJson(options.request);
15
+ const status = options.response ? "completed" : "failed";
16
+ const callId = options.response?.callId ?? options.error?.callId;
17
+ const capability = options.response?.capability ?? options.error?.capability ?? options.request.capability;
18
+ const receiptRefs = cloneSerializable(
19
+ options.response?.receiptRefs ?? options.error?.receiptRefs ?? []
20
+ );
21
+ const safety = cloneSerializable(
22
+ options.response?.safety ?? options.error?.safety
23
+ );
24
+ const retrySafety = cloneSerializable(
25
+ options.retrySafety ?? options.response?.retrySafety ?? options.error?.retrySafety
26
+ );
27
+ const attempt = cloneSerializable(
28
+ options.attempt ?? options.response?.attempt ?? options.error?.attempt
29
+ );
30
+ const route = cloneSerializable(
31
+ options.route ?? options.response?.route ?? options.error?.route
32
+ );
33
+ const timeline = cloneSerializable(
34
+ options.timeline ?? options.response?.timeline ?? options.error?.timeline
35
+ );
36
+ const timelineSummary = summarizeTimeline(timeline);
37
+ const baseContent = sanitizeAuditOutput(
38
+ {
39
+ schemaVersion: PROBEMESH_CALL_AUDIT_ARTIFACT_SCHEMA_VERSION,
40
+ artifactId: options.artifactId ?? `call_audit_${callId ?? requestHash.slice(0, 16)}`,
41
+ generatedAt: options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
42
+ status,
43
+ hashAlgorithm: "sha256",
44
+ call: {
45
+ callId,
46
+ capability,
47
+ status,
48
+ providerId: options.response?.provider.id ?? options.error?.provider,
49
+ errorCode: options.error?.code,
50
+ cost: cloneSerializable(options.response?.cost),
51
+ latencyMs: options.response?.latencyMs,
52
+ attempt
53
+ },
54
+ request: {
55
+ requestHash,
56
+ idempotencyKey: options.request.idempotencyKey
57
+ },
58
+ evidence: {
59
+ receiptSummary: summarizeAuditReceipts(receiptRefs),
60
+ receiptRefs,
61
+ safety,
62
+ retrySafety,
63
+ route,
64
+ timeline: timelineSummary
65
+ }
66
+ },
67
+ options.forbiddenOutputValues ?? []
68
+ );
69
+ const hashesWithoutArtifact = {
70
+ request: requestHash,
71
+ route: hashStableJson(baseContent.evidence.route ?? null),
72
+ timeline: hashStableJson(baseContent.evidence.timeline),
73
+ receipts: hashStableJson(baseContent.evidence.receiptRefs),
74
+ safety: hashStableJson(baseContent.evidence.safety ?? null),
75
+ retrySafety: hashStableJson(baseContent.evidence.retrySafety ?? null),
76
+ artifact: ""
77
+ };
78
+ const artifact = {
79
+ ...baseContent,
80
+ hashes: {
81
+ ...hashesWithoutArtifact,
82
+ artifact: hashArtifactContent({
83
+ ...baseContent,
84
+ hashes: hashesWithoutArtifact
85
+ })
86
+ }
87
+ };
88
+ assertProbeMeshCallAuditArtifact(artifact);
89
+ return artifact;
90
+ }
91
+ function validateProbeMeshCallAuditArtifact(artifact) {
92
+ const errors = [];
93
+ if (!isRecord(artifact)) {
94
+ return {
95
+ valid: false,
96
+ errors: [
97
+ {
98
+ path: "$",
99
+ message: "ProbeMesh call audit artifact must be an object."
100
+ }
101
+ ]
102
+ };
103
+ }
104
+ if (artifact.schemaVersion !== PROBEMESH_CALL_AUDIT_ARTIFACT_SCHEMA_VERSION) {
105
+ errors.push({
106
+ path: "schemaVersion",
107
+ message: `schemaVersion must be "${PROBEMESH_CALL_AUDIT_ARTIFACT_SCHEMA_VERSION}".`
108
+ });
109
+ }
110
+ validateNonEmptyString(artifact.artifactId, "artifactId", errors);
111
+ validateIsoTimestamp(artifact.generatedAt, "generatedAt", errors);
112
+ if (artifact.status !== "completed" && artifact.status !== "failed") {
113
+ errors.push({
114
+ path: "status",
115
+ message: 'status must be "completed" or "failed".'
116
+ });
117
+ }
118
+ if (artifact.hashAlgorithm !== "sha256") {
119
+ errors.push({
120
+ path: "hashAlgorithm",
121
+ message: 'hashAlgorithm must be "sha256".'
122
+ });
123
+ }
124
+ validateHashes(artifact.hashes, errors);
125
+ validateCallSummary(artifact.call, artifact.status, errors);
126
+ validateRequestProof(artifact.request, artifact.hashes, errors);
127
+ validateEvidence(artifact.evidence, errors);
128
+ if (errors.length === 0) {
129
+ const typedArtifact = artifact;
130
+ pushHashMismatch(
131
+ errors,
132
+ "hashes.route",
133
+ typedArtifact.hashes.route,
134
+ hashStableJson(typedArtifact.evidence.route ?? null)
135
+ );
136
+ pushHashMismatch(
137
+ errors,
138
+ "hashes.timeline",
139
+ typedArtifact.hashes.timeline,
140
+ hashStableJson(typedArtifact.evidence.timeline)
141
+ );
142
+ pushHashMismatch(
143
+ errors,
144
+ "hashes.receipts",
145
+ typedArtifact.hashes.receipts,
146
+ hashStableJson(typedArtifact.evidence.receiptRefs)
147
+ );
148
+ pushHashMismatch(
149
+ errors,
150
+ "hashes.safety",
151
+ typedArtifact.hashes.safety,
152
+ hashStableJson(typedArtifact.evidence.safety ?? null)
153
+ );
154
+ pushHashMismatch(
155
+ errors,
156
+ "hashes.retrySafety",
157
+ typedArtifact.hashes.retrySafety,
158
+ hashStableJson(typedArtifact.evidence.retrySafety ?? null)
159
+ );
160
+ pushHashMismatch(
161
+ errors,
162
+ "hashes.artifact",
163
+ typedArtifact.hashes.artifact,
164
+ hashArtifactContent(typedArtifact)
165
+ );
166
+ }
167
+ return {
168
+ valid: errors.length === 0,
169
+ errors
170
+ };
171
+ }
172
+ function assertProbeMeshCallAuditArtifact(artifact) {
173
+ const result = validateProbeMeshCallAuditArtifact(artifact);
174
+ if (result.valid) {
175
+ return;
176
+ }
177
+ throw new ProbeMeshError({
178
+ code: "invalid_request",
179
+ message: `Invalid ProbeMesh call audit artifact: ${formatValidationErrors(
180
+ result.errors
181
+ )}`
182
+ });
183
+ }
184
+ function formatProbeMeshCallAuditArtifact(artifact, options = {}) {
185
+ assertProbeMeshCallAuditArtifact(artifact);
186
+ if ((options.format ?? "json") === "markdown") {
187
+ return formatAuditArtifactMarkdown(artifact);
188
+ }
189
+ return JSON.stringify(artifact, null, 2);
190
+ }
191
+ function assertAuditArtifactOptions(options) {
192
+ if (!isRecord(options)) {
193
+ throw new ProbeMeshError({
194
+ code: "invalid_request",
195
+ message: "ProbeMesh call audit artifact options must be an object."
196
+ });
197
+ }
198
+ if (!isRecord(options.request)) {
199
+ throw new ProbeMeshError({
200
+ code: "invalid_request",
201
+ message: "ProbeMesh call audit artifact request must be an object."
202
+ });
203
+ }
204
+ if (typeof options.request.capability !== "string" || options.request.capability.length === 0) {
205
+ throw new ProbeMeshError({
206
+ code: "invalid_request",
207
+ message: "ProbeMesh call audit artifact request capability is required."
208
+ });
209
+ }
210
+ if (!("input" in options.request)) {
211
+ throw new ProbeMeshError({
212
+ code: "invalid_request",
213
+ message: "ProbeMesh call audit artifact request input is required for hashing."
214
+ });
215
+ }
216
+ if (options.response === void 0 && options.error === void 0 || options.response !== void 0 && options.error !== void 0) {
217
+ throw new ProbeMeshError({
218
+ code: "invalid_request",
219
+ message: "ProbeMesh call audit artifact requires exactly one response or error."
220
+ });
221
+ }
222
+ if (options.error !== void 0 && !isProbeMeshError(options.error)) {
223
+ throw new ProbeMeshError({
224
+ code: "invalid_request",
225
+ message: "ProbeMesh call audit artifact error must be a ProbeMeshError."
226
+ });
227
+ }
228
+ if (options.generatedAt !== void 0 && (typeof options.generatedAt !== "string" || Number.isNaN(Date.parse(options.generatedAt)))) {
229
+ throw new ProbeMeshError({
230
+ code: "invalid_request",
231
+ message: "ProbeMesh call audit artifact generatedAt must be an ISO timestamp."
232
+ });
233
+ }
234
+ if (options.artifactId !== void 0 && (typeof options.artifactId !== "string" || options.artifactId.length === 0)) {
235
+ throw new ProbeMeshError({
236
+ code: "invalid_request",
237
+ message: "ProbeMesh call audit artifact artifactId must be a non-empty string."
238
+ });
239
+ }
240
+ if (options.forbiddenOutputValues !== void 0 && (!Array.isArray(options.forbiddenOutputValues) || options.forbiddenOutputValues.some((value) => typeof value !== "string"))) {
241
+ throw new ProbeMeshError({
242
+ code: "invalid_request",
243
+ message: "ProbeMesh call audit artifact forbiddenOutputValues must be an array of strings."
244
+ });
245
+ }
246
+ }
247
+ function summarizeAuditReceipts(receiptRefs) {
248
+ const types = [];
249
+ const providers = [];
250
+ const byType = {};
251
+ for (const receiptRef of receiptRefs) {
252
+ if (!types.includes(receiptRef.type)) {
253
+ types.push(receiptRef.type);
254
+ }
255
+ if (!providers.includes(receiptRef.provider)) {
256
+ providers.push(receiptRef.provider);
257
+ }
258
+ byType[receiptRef.type] = (byType[receiptRef.type] ?? 0) + 1;
259
+ }
260
+ return {
261
+ total: receiptRefs.length,
262
+ types,
263
+ providers,
264
+ byType,
265
+ hasPaymentProof: receiptRefs.some(
266
+ (receiptRef) => receiptRef.type === "payment_proof"
267
+ ),
268
+ hasSettlementConfirmation: receiptRefs.some(
269
+ (receiptRef) => receiptRef.type === "settlement_confirmation"
270
+ ),
271
+ hasProviderDelivery: receiptRefs.some(
272
+ (receiptRef) => receiptRef.type === "provider_delivery"
273
+ )
274
+ };
275
+ }
276
+ function summarizeTimeline(timeline) {
277
+ if (!timeline) {
278
+ return {
279
+ eventTypes: [],
280
+ events: []
281
+ };
282
+ }
283
+ return {
284
+ routeId: timeline.routeId,
285
+ eventTypes: timeline.events.map((event) => event.type),
286
+ events: timeline.events.map((event) => ({
287
+ type: event.type,
288
+ timestamp: event.timestamp,
289
+ provider: event.provider,
290
+ status: event.status,
291
+ errorCode: event.errorCode,
292
+ receiptType: event.receiptRef?.type,
293
+ attestationBundleId: event.attestation?.bundleId
294
+ }))
295
+ };
296
+ }
297
+ function validateHashes(hashes, errors) {
298
+ if (!isRecord(hashes)) {
299
+ errors.push({
300
+ path: "hashes",
301
+ message: "hashes must be an object."
302
+ });
303
+ return;
304
+ }
305
+ for (const key of [
306
+ "request",
307
+ "route",
308
+ "timeline",
309
+ "receipts",
310
+ "safety",
311
+ "retrySafety",
312
+ "artifact"
313
+ ]) {
314
+ validateSha256String(hashes[key], `hashes.${key}`, errors);
315
+ }
316
+ }
317
+ function validateCallSummary(call, status, errors) {
318
+ if (!isRecord(call)) {
319
+ errors.push({
320
+ path: "call",
321
+ message: "call must be an object."
322
+ });
323
+ return;
324
+ }
325
+ validateNonEmptyString(call.capability, "call.capability", errors);
326
+ if (call.status !== status) {
327
+ errors.push({
328
+ path: "call.status",
329
+ message: "call.status must match artifact status."
330
+ });
331
+ }
332
+ if (call.callId !== void 0) {
333
+ validateNonEmptyString(call.callId, "call.callId", errors);
334
+ }
335
+ if (call.providerId !== void 0) {
336
+ validateNonEmptyString(call.providerId, "call.providerId", errors);
337
+ }
338
+ if (call.errorCode !== void 0 && (typeof call.errorCode !== "string" || call.errorCode.length === 0)) {
339
+ errors.push({
340
+ path: "call.errorCode",
341
+ message: "call.errorCode must be a non-empty string when provided."
342
+ });
343
+ }
344
+ if (call.latencyMs !== void 0 && (typeof call.latencyMs !== "number" || !Number.isFinite(call.latencyMs) || call.latencyMs < 0)) {
345
+ errors.push({
346
+ path: "call.latencyMs",
347
+ message: "call.latencyMs must be a non-negative finite number."
348
+ });
349
+ }
350
+ }
351
+ function validateRequestProof(request, hashes, errors) {
352
+ if (!isRecord(request)) {
353
+ errors.push({
354
+ path: "request",
355
+ message: "request must be an object."
356
+ });
357
+ return;
358
+ }
359
+ validateSha256String(request.requestHash, "request.requestHash", errors);
360
+ if (isRecord(hashes) && hashes.request !== request.requestHash) {
361
+ errors.push({
362
+ path: "hashes.request",
363
+ message: "hashes.request must equal request.requestHash."
364
+ });
365
+ }
366
+ if (request.idempotencyKey !== void 0) {
367
+ validateNonEmptyString(
368
+ request.idempotencyKey,
369
+ "request.idempotencyKey",
370
+ errors
371
+ );
372
+ }
373
+ }
374
+ function validateEvidence(evidence, errors) {
375
+ if (!isRecord(evidence)) {
376
+ errors.push({
377
+ path: "evidence",
378
+ message: "evidence must be an object."
379
+ });
380
+ return;
381
+ }
382
+ validateReceiptSummary(evidence.receiptSummary, errors);
383
+ validateReceiptRefs(evidence.receiptRefs, errors);
384
+ validateTimelineSummary(evidence.timeline, errors);
385
+ }
386
+ function validateReceiptSummary(summary, errors) {
387
+ if (!isRecord(summary)) {
388
+ errors.push({
389
+ path: "evidence.receiptSummary",
390
+ message: "evidence.receiptSummary must be an object."
391
+ });
392
+ return;
393
+ }
394
+ if (typeof summary.total !== "number" || !Number.isFinite(summary.total)) {
395
+ errors.push({
396
+ path: "evidence.receiptSummary.total",
397
+ message: "evidence.receiptSummary.total must be a number."
398
+ });
399
+ }
400
+ validateStringArray(summary.types, "evidence.receiptSummary.types", errors);
401
+ validateStringArray(
402
+ summary.providers,
403
+ "evidence.receiptSummary.providers",
404
+ errors
405
+ );
406
+ if (!isRecord(summary.byType)) {
407
+ errors.push({
408
+ path: "evidence.receiptSummary.byType",
409
+ message: "evidence.receiptSummary.byType must be an object."
410
+ });
411
+ }
412
+ for (const key of [
413
+ "hasPaymentProof",
414
+ "hasSettlementConfirmation",
415
+ "hasProviderDelivery"
416
+ ]) {
417
+ if (typeof summary[key] !== "boolean") {
418
+ errors.push({
419
+ path: `evidence.receiptSummary.${key}`,
420
+ message: `evidence.receiptSummary.${key} must be a boolean.`
421
+ });
422
+ }
423
+ }
424
+ }
425
+ function validateReceiptRefs(receiptRefs, errors) {
426
+ if (!Array.isArray(receiptRefs)) {
427
+ errors.push({
428
+ path: "evidence.receiptRefs",
429
+ message: "evidence.receiptRefs must be an array."
430
+ });
431
+ return;
432
+ }
433
+ receiptRefs.forEach((receiptRef, index) => {
434
+ if (!isRecord(receiptRef)) {
435
+ errors.push({
436
+ path: `evidence.receiptRefs.${index}`,
437
+ message: "receipt ref must be an object."
438
+ });
439
+ return;
440
+ }
441
+ for (const key of ["type", "provider", "status", "ref", "timestamp"]) {
442
+ validateNonEmptyString(
443
+ receiptRef[key],
444
+ `evidence.receiptRefs.${index}.${key}`,
445
+ errors
446
+ );
447
+ }
448
+ });
449
+ }
450
+ function validateTimelineSummary(timeline, errors) {
451
+ if (!isRecord(timeline)) {
452
+ errors.push({
453
+ path: "evidence.timeline",
454
+ message: "evidence.timeline must be an object."
455
+ });
456
+ return;
457
+ }
458
+ if (timeline.routeId !== void 0) {
459
+ validateNonEmptyString(timeline.routeId, "evidence.timeline.routeId", errors);
460
+ }
461
+ validateStringArray(
462
+ timeline.eventTypes,
463
+ "evidence.timeline.eventTypes",
464
+ errors
465
+ );
466
+ if (!Array.isArray(timeline.events)) {
467
+ errors.push({
468
+ path: "evidence.timeline.events",
469
+ message: "evidence.timeline.events must be an array."
470
+ });
471
+ return;
472
+ }
473
+ timeline.events.forEach((event, index) => {
474
+ if (!isRecord(event)) {
475
+ errors.push({
476
+ path: `evidence.timeline.events.${index}`,
477
+ message: "timeline event must be an object."
478
+ });
479
+ return;
480
+ }
481
+ validateNonEmptyString(
482
+ event.type,
483
+ `evidence.timeline.events.${index}.type`,
484
+ errors
485
+ );
486
+ validateIsoTimestamp(
487
+ event.timestamp,
488
+ `evidence.timeline.events.${index}.timestamp`,
489
+ errors
490
+ );
491
+ });
492
+ }
493
+ function hashArtifactContent(artifact) {
494
+ return hashStableJson({
495
+ ...artifact,
496
+ hashes: {
497
+ ...artifact.hashes,
498
+ artifact: ""
499
+ }
500
+ });
501
+ }
502
+ function pushHashMismatch(errors, path, expected, actual) {
503
+ if (expected === actual) {
504
+ return;
505
+ }
506
+ errors.push({
507
+ path,
508
+ message: `${path} does not match artifact content.`
509
+ });
510
+ }
511
+ function hashStableJson(value) {
512
+ return createHash("sha256").update(stableStringify(value)).digest("hex");
513
+ }
514
+ function stableStringify(value) {
515
+ return JSON.stringify(sortSerializable(value));
516
+ }
517
+ function sortSerializable(value) {
518
+ if (Array.isArray(value)) {
519
+ return value.map(sortSerializable);
520
+ }
521
+ if (!isRecord(value)) {
522
+ return value;
523
+ }
524
+ return Object.fromEntries(
525
+ Object.keys(value).sort().filter((key) => value[key] !== void 0).map((key) => [key, sortSerializable(value[key])])
526
+ );
527
+ }
528
+ function sanitizeAuditOutput(value, forbiddenOutputValues) {
529
+ const forbiddenValues = forbiddenOutputValues.filter((entry) => entry.length > 0);
530
+ return redactX402Secrets(
531
+ replaceForbiddenValues(cloneSerializable(value), forbiddenValues)
532
+ );
533
+ }
534
+ function replaceForbiddenValues(value, forbiddenValues) {
535
+ if (typeof value === "string") {
536
+ return forbiddenValues.reduce(
537
+ (current, forbidden) => current.split(forbidden).join("[REDACTED]"),
538
+ value
539
+ );
540
+ }
541
+ if (value === null || typeof value !== "object" || value instanceof Date) {
542
+ return value;
543
+ }
544
+ if (Array.isArray(value)) {
545
+ return value.map((entry) => replaceForbiddenValues(entry, forbiddenValues));
546
+ }
547
+ return Object.fromEntries(
548
+ Object.entries(value).map(([key, entry]) => [
549
+ key,
550
+ replaceForbiddenValues(entry, forbiddenValues)
551
+ ])
552
+ );
553
+ }
554
+ function cloneSerializable(value) {
555
+ if (value === void 0) {
556
+ return value;
557
+ }
558
+ return JSON.parse(JSON.stringify(value));
559
+ }
560
+ function formatAuditArtifactMarkdown(artifact) {
561
+ const attestation = artifact.evidence.route?.attestation;
562
+ return [
563
+ `# ProbeMesh Call Audit Artifact`,
564
+ ``,
565
+ `Status: ${artifact.status}`,
566
+ `Schema: ${artifact.schemaVersion}`,
567
+ `Artifact ID: ${artifact.artifactId}`,
568
+ `Generated: ${artifact.generatedAt}`,
569
+ ``,
570
+ `## Call`,
571
+ `- Call ID: ${artifact.call.callId ?? "none"}`,
572
+ `- Capability: ${artifact.call.capability}`,
573
+ `- Provider: ${artifact.call.providerId ?? "none"}`,
574
+ `- Error code: ${artifact.call.errorCode ?? "none"}`,
575
+ `- Cost USD: ${artifact.call.cost?.amountUsd ?? "none"}`,
576
+ `- Request hash: ${artifact.request.requestHash}`,
577
+ ``,
578
+ `## Evidence`,
579
+ `- Receipts: ${artifact.evidence.receiptSummary.total}`,
580
+ `- Receipt types: ${formatInlineList(artifact.evidence.receiptSummary.types)}`,
581
+ `- Payment proof: ${String(artifact.evidence.receiptSummary.hasPaymentProof)}`,
582
+ `- Settlement confirmation: ${String(
583
+ artifact.evidence.receiptSummary.hasSettlementConfirmation
584
+ )}`,
585
+ `- Provider delivery: ${String(
586
+ artifact.evidence.receiptSummary.hasProviderDelivery
587
+ )}`,
588
+ `- Money may have moved: ${String(
589
+ artifact.evidence.safety?.moneyMayHaveMoved ?? false
590
+ )}`,
591
+ `- Retry safe: ${String(
592
+ artifact.evidence.retrySafety?.safeToAutoRetry ?? false
593
+ )}`,
594
+ `- Route stop: ${artifact.evidence.route?.explanation?.stopReason ?? "none"}`,
595
+ `- Bundle: ${attestation?.bundleId ?? "none"}`,
596
+ `- Bundle verified: ${String(attestation?.runtimeVerified ?? false)}`,
597
+ `- Timeline events: ${formatInlineList(
598
+ artifact.evidence.timeline.eventTypes
599
+ )}`,
600
+ ``,
601
+ `## Hashes`,
602
+ `- Artifact: ${artifact.hashes.artifact}`,
603
+ `- Route: ${artifact.hashes.route}`,
604
+ `- Timeline: ${artifact.hashes.timeline}`,
605
+ `- Receipts: ${artifact.hashes.receipts}`
606
+ ].join("\n");
607
+ }
608
+ function formatInlineList(values) {
609
+ return values.length === 0 ? "none" : values.join(", ");
610
+ }
611
+ function validateSha256String(value, path, errors) {
612
+ if (typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value)) {
613
+ errors.push({
614
+ path,
615
+ message: `${path} must be a sha256 hex string.`
616
+ });
617
+ }
618
+ }
619
+ function validateNonEmptyString(value, path, errors) {
620
+ if (typeof value !== "string" || value.length === 0) {
621
+ errors.push({
622
+ path,
623
+ message: `${path} must be a non-empty string.`
624
+ });
625
+ }
626
+ }
627
+ function validateIsoTimestamp(value, path, errors) {
628
+ if (typeof value !== "string" || Number.isNaN(Date.parse(value))) {
629
+ errors.push({
630
+ path,
631
+ message: `${path} must be an ISO timestamp.`
632
+ });
633
+ }
634
+ }
635
+ function validateStringArray(value, path, errors) {
636
+ if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string" || entry.length === 0)) {
637
+ errors.push({
638
+ path,
639
+ message: `${path} must be an array of non-empty strings.`
640
+ });
641
+ }
642
+ }
643
+ function isRecord(value) {
644
+ return !!value && typeof value === "object" && !Array.isArray(value);
645
+ }
646
+ function formatValidationErrors(errors) {
647
+ return errors.map((error) => `${error.path}: ${error.message}`).join("; ");
648
+ }
649
+
650
+ export {
651
+ PROBEMESH_CALL_AUDIT_ARTIFACT_SCHEMA_VERSION,
652
+ createProbeMeshCallAuditArtifact,
653
+ validateProbeMeshCallAuditArtifact,
654
+ assertProbeMeshCallAuditArtifact,
655
+ formatProbeMeshCallAuditArtifact
656
+ };
657
+ //# sourceMappingURL=chunk-5Q3PDYIA.js.map