@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,1193 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // src/cli/auditTrailExportCli.ts
5
+ var import_promises2 = require("fs/promises");
6
+ var import_node_path2 = require("path");
7
+
8
+ // src/cli/configLoader.ts
9
+ var import_promises = require("fs/promises");
10
+ var import_node_path = require("path");
11
+ var import_node_url = require("url");
12
+ async function loadCliConfigDefault(configPath, cwd) {
13
+ const resolvedPath = (0, import_node_path.resolve)(cwd, configPath);
14
+ const moduleUrl = (0, import_node_url.pathToFileURL)(resolvedPath);
15
+ try {
16
+ const loadedModule = await import(
17
+ /* @vite-ignore */
18
+ moduleUrl.href
19
+ );
20
+ return loadedModule.default;
21
+ } catch (error) {
22
+ return loadSelfContainedConfigFallback(resolvedPath, error);
23
+ }
24
+ }
25
+ async function loadSelfContainedConfigFallback(resolvedPath, importError) {
26
+ const source = await (0, import_promises.readFile)(resolvedPath, "utf8");
27
+ if (/\bimport\s/.test(source) || !/\bexport\s+default\b/.test(source)) {
28
+ throw importError;
29
+ }
30
+ const transformedSource = source.replace(
31
+ /\bexport\s+default\b/,
32
+ "const __probemeshDefault ="
33
+ );
34
+ try {
35
+ const factory = new Function(
36
+ `${transformedSource}
37
+ return __probemeshDefault;`
38
+ );
39
+ return factory();
40
+ } catch {
41
+ throw importError;
42
+ }
43
+ }
44
+
45
+ // src/auditTrailBundle.ts
46
+ var import_node_crypto2 = require("crypto");
47
+
48
+ // src/callAuditArtifact.ts
49
+ var import_node_crypto = require("crypto");
50
+
51
+ // src/errors.ts
52
+ var ProbeMeshError = class extends Error {
53
+ code;
54
+ status = "failed";
55
+ capability;
56
+ provider;
57
+ callId;
58
+ receiptRefs;
59
+ safety;
60
+ timeline;
61
+ retrySafety;
62
+ attempt;
63
+ route;
64
+ cause;
65
+ constructor(options) {
66
+ super(options.message);
67
+ this.name = "ProbeMeshError";
68
+ this.code = options.code;
69
+ this.capability = options.capability;
70
+ this.provider = options.provider;
71
+ this.callId = options.callId;
72
+ this.receiptRefs = options.receiptRefs;
73
+ this.safety = options.safety;
74
+ this.timeline = options.timeline;
75
+ this.retrySafety = options.retrySafety;
76
+ this.attempt = options.attempt;
77
+ this.route = options.route;
78
+ this.cause = options.cause;
79
+ }
80
+ toJSON() {
81
+ return {
82
+ name: this.name,
83
+ code: this.code,
84
+ message: this.message,
85
+ status: this.status,
86
+ capability: this.capability,
87
+ provider: this.provider,
88
+ callId: this.callId,
89
+ receiptRefs: this.receiptRefs,
90
+ safety: this.safety,
91
+ timeline: this.timeline,
92
+ retrySafety: this.retrySafety,
93
+ attempt: this.attempt,
94
+ route: this.route
95
+ };
96
+ }
97
+ };
98
+
99
+ // src/protocols/x402Redaction.ts
100
+ var DEFAULT_REPLACEMENT = "[REDACTED]";
101
+ var DEFAULT_MAX_DEPTH = 12;
102
+ var PRIVATE_KEY_PATTERN = /\b0x[a-fA-F0-9]{64}\b/g;
103
+ var HEX_SIGNATURE_PATTERN = /\b0x[a-fA-F0-9]{130}\b/g;
104
+ var SECRET_FIELD_NAMES = /* @__PURE__ */ new Set([
105
+ "api-key",
106
+ "apikey",
107
+ "authorization",
108
+ "bearer",
109
+ "payment-required",
110
+ "payment-response",
111
+ "payment-signature",
112
+ "privatekey",
113
+ "signature",
114
+ "x-api-key"
115
+ ]);
116
+ function redactX402Secrets(value, options = {}) {
117
+ const replacement = options.replacement ?? DEFAULT_REPLACEMENT;
118
+ const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
119
+ const seen = /* @__PURE__ */ new WeakSet();
120
+ return redactValue(value, {
121
+ replacement,
122
+ maxDepth,
123
+ depth: 0,
124
+ seen,
125
+ key: void 0
126
+ });
127
+ }
128
+ function redactValue(value, context) {
129
+ if (context.key && shouldRedactKey(context.key)) {
130
+ return context.replacement;
131
+ }
132
+ if (typeof value === "string") {
133
+ return redactString(value, context.replacement);
134
+ }
135
+ if (value === null || typeof value !== "object" || value instanceof Date) {
136
+ return value;
137
+ }
138
+ if (context.depth >= context.maxDepth) {
139
+ return "[MaxDepth]";
140
+ }
141
+ if (context.seen.has(value)) {
142
+ return "[Circular]";
143
+ }
144
+ context.seen.add(value);
145
+ if (Array.isArray(value)) {
146
+ return value.map(
147
+ (entry) => redactValue(entry, {
148
+ ...context,
149
+ depth: context.depth + 1,
150
+ key: void 0
151
+ })
152
+ );
153
+ }
154
+ return Object.fromEntries(
155
+ Object.entries(value).map(([key, entry]) => [
156
+ key,
157
+ redactValue(entry, {
158
+ ...context,
159
+ depth: context.depth + 1,
160
+ key
161
+ })
162
+ ])
163
+ );
164
+ }
165
+ function shouldRedactKey(key) {
166
+ const normalized = key.toLowerCase().replace(/_/g, "-");
167
+ return SECRET_FIELD_NAMES.has(normalized) || normalized.includes("private-key") || normalized.includes("privatekey") || normalized.includes("payment-signature") || normalized.includes("payment-response") || normalized.includes("payment-required") || normalized.includes("api-key");
168
+ }
169
+ function redactString(value, replacement) {
170
+ return value.replace(PRIVATE_KEY_PATTERN, replacement).replace(HEX_SIGNATURE_PATTERN, replacement);
171
+ }
172
+
173
+ // src/callAuditArtifact.ts
174
+ var PROBEMESH_CALL_AUDIT_ARTIFACT_SCHEMA_VERSION = "probemesh.call-audit.v1";
175
+ function validateProbeMeshCallAuditArtifact(artifact) {
176
+ const errors = [];
177
+ if (!isRecord(artifact)) {
178
+ return {
179
+ valid: false,
180
+ errors: [
181
+ {
182
+ path: "$",
183
+ message: "ProbeMesh call audit artifact must be an object."
184
+ }
185
+ ]
186
+ };
187
+ }
188
+ if (artifact.schemaVersion !== PROBEMESH_CALL_AUDIT_ARTIFACT_SCHEMA_VERSION) {
189
+ errors.push({
190
+ path: "schemaVersion",
191
+ message: `schemaVersion must be "${PROBEMESH_CALL_AUDIT_ARTIFACT_SCHEMA_VERSION}".`
192
+ });
193
+ }
194
+ validateNonEmptyString(artifact.artifactId, "artifactId", errors);
195
+ validateIsoTimestamp(artifact.generatedAt, "generatedAt", errors);
196
+ if (artifact.status !== "completed" && artifact.status !== "failed") {
197
+ errors.push({
198
+ path: "status",
199
+ message: 'status must be "completed" or "failed".'
200
+ });
201
+ }
202
+ if (artifact.hashAlgorithm !== "sha256") {
203
+ errors.push({
204
+ path: "hashAlgorithm",
205
+ message: 'hashAlgorithm must be "sha256".'
206
+ });
207
+ }
208
+ validateHashes(artifact.hashes, errors);
209
+ validateCallSummary(artifact.call, artifact.status, errors);
210
+ validateRequestProof(artifact.request, artifact.hashes, errors);
211
+ validateEvidence(artifact.evidence, errors);
212
+ if (errors.length === 0) {
213
+ const typedArtifact = artifact;
214
+ pushHashMismatch(
215
+ errors,
216
+ "hashes.route",
217
+ typedArtifact.hashes.route,
218
+ hashStableJson(typedArtifact.evidence.route ?? null)
219
+ );
220
+ pushHashMismatch(
221
+ errors,
222
+ "hashes.timeline",
223
+ typedArtifact.hashes.timeline,
224
+ hashStableJson(typedArtifact.evidence.timeline)
225
+ );
226
+ pushHashMismatch(
227
+ errors,
228
+ "hashes.receipts",
229
+ typedArtifact.hashes.receipts,
230
+ hashStableJson(typedArtifact.evidence.receiptRefs)
231
+ );
232
+ pushHashMismatch(
233
+ errors,
234
+ "hashes.safety",
235
+ typedArtifact.hashes.safety,
236
+ hashStableJson(typedArtifact.evidence.safety ?? null)
237
+ );
238
+ pushHashMismatch(
239
+ errors,
240
+ "hashes.retrySafety",
241
+ typedArtifact.hashes.retrySafety,
242
+ hashStableJson(typedArtifact.evidence.retrySafety ?? null)
243
+ );
244
+ pushHashMismatch(
245
+ errors,
246
+ "hashes.artifact",
247
+ typedArtifact.hashes.artifact,
248
+ hashArtifactContent(typedArtifact)
249
+ );
250
+ }
251
+ return {
252
+ valid: errors.length === 0,
253
+ errors
254
+ };
255
+ }
256
+ function validateHashes(hashes, errors) {
257
+ if (!isRecord(hashes)) {
258
+ errors.push({
259
+ path: "hashes",
260
+ message: "hashes must be an object."
261
+ });
262
+ return;
263
+ }
264
+ for (const key of [
265
+ "request",
266
+ "route",
267
+ "timeline",
268
+ "receipts",
269
+ "safety",
270
+ "retrySafety",
271
+ "artifact"
272
+ ]) {
273
+ validateSha256String(hashes[key], `hashes.${key}`, errors);
274
+ }
275
+ }
276
+ function validateCallSummary(call, status, errors) {
277
+ if (!isRecord(call)) {
278
+ errors.push({
279
+ path: "call",
280
+ message: "call must be an object."
281
+ });
282
+ return;
283
+ }
284
+ validateNonEmptyString(call.capability, "call.capability", errors);
285
+ if (call.status !== status) {
286
+ errors.push({
287
+ path: "call.status",
288
+ message: "call.status must match artifact status."
289
+ });
290
+ }
291
+ if (call.callId !== void 0) {
292
+ validateNonEmptyString(call.callId, "call.callId", errors);
293
+ }
294
+ if (call.providerId !== void 0) {
295
+ validateNonEmptyString(call.providerId, "call.providerId", errors);
296
+ }
297
+ if (call.errorCode !== void 0 && (typeof call.errorCode !== "string" || call.errorCode.length === 0)) {
298
+ errors.push({
299
+ path: "call.errorCode",
300
+ message: "call.errorCode must be a non-empty string when provided."
301
+ });
302
+ }
303
+ if (call.latencyMs !== void 0 && (typeof call.latencyMs !== "number" || !Number.isFinite(call.latencyMs) || call.latencyMs < 0)) {
304
+ errors.push({
305
+ path: "call.latencyMs",
306
+ message: "call.latencyMs must be a non-negative finite number."
307
+ });
308
+ }
309
+ }
310
+ function validateRequestProof(request, hashes, errors) {
311
+ if (!isRecord(request)) {
312
+ errors.push({
313
+ path: "request",
314
+ message: "request must be an object."
315
+ });
316
+ return;
317
+ }
318
+ validateSha256String(request.requestHash, "request.requestHash", errors);
319
+ if (isRecord(hashes) && hashes.request !== request.requestHash) {
320
+ errors.push({
321
+ path: "hashes.request",
322
+ message: "hashes.request must equal request.requestHash."
323
+ });
324
+ }
325
+ if (request.idempotencyKey !== void 0) {
326
+ validateNonEmptyString(
327
+ request.idempotencyKey,
328
+ "request.idempotencyKey",
329
+ errors
330
+ );
331
+ }
332
+ }
333
+ function validateEvidence(evidence, errors) {
334
+ if (!isRecord(evidence)) {
335
+ errors.push({
336
+ path: "evidence",
337
+ message: "evidence must be an object."
338
+ });
339
+ return;
340
+ }
341
+ validateReceiptSummary(evidence.receiptSummary, errors);
342
+ validateReceiptRefs(evidence.receiptRefs, errors);
343
+ validateTimelineSummary(evidence.timeline, errors);
344
+ }
345
+ function validateReceiptSummary(summary, errors) {
346
+ if (!isRecord(summary)) {
347
+ errors.push({
348
+ path: "evidence.receiptSummary",
349
+ message: "evidence.receiptSummary must be an object."
350
+ });
351
+ return;
352
+ }
353
+ if (typeof summary.total !== "number" || !Number.isFinite(summary.total)) {
354
+ errors.push({
355
+ path: "evidence.receiptSummary.total",
356
+ message: "evidence.receiptSummary.total must be a number."
357
+ });
358
+ }
359
+ validateStringArray(summary.types, "evidence.receiptSummary.types", errors);
360
+ validateStringArray(
361
+ summary.providers,
362
+ "evidence.receiptSummary.providers",
363
+ errors
364
+ );
365
+ if (!isRecord(summary.byType)) {
366
+ errors.push({
367
+ path: "evidence.receiptSummary.byType",
368
+ message: "evidence.receiptSummary.byType must be an object."
369
+ });
370
+ }
371
+ for (const key of [
372
+ "hasPaymentProof",
373
+ "hasSettlementConfirmation",
374
+ "hasProviderDelivery"
375
+ ]) {
376
+ if (typeof summary[key] !== "boolean") {
377
+ errors.push({
378
+ path: `evidence.receiptSummary.${key}`,
379
+ message: `evidence.receiptSummary.${key} must be a boolean.`
380
+ });
381
+ }
382
+ }
383
+ }
384
+ function validateReceiptRefs(receiptRefs, errors) {
385
+ if (!Array.isArray(receiptRefs)) {
386
+ errors.push({
387
+ path: "evidence.receiptRefs",
388
+ message: "evidence.receiptRefs must be an array."
389
+ });
390
+ return;
391
+ }
392
+ receiptRefs.forEach((receiptRef, index) => {
393
+ if (!isRecord(receiptRef)) {
394
+ errors.push({
395
+ path: `evidence.receiptRefs.${index}`,
396
+ message: "receipt ref must be an object."
397
+ });
398
+ return;
399
+ }
400
+ for (const key of ["type", "provider", "status", "ref", "timestamp"]) {
401
+ validateNonEmptyString(
402
+ receiptRef[key],
403
+ `evidence.receiptRefs.${index}.${key}`,
404
+ errors
405
+ );
406
+ }
407
+ });
408
+ }
409
+ function validateTimelineSummary(timeline, errors) {
410
+ if (!isRecord(timeline)) {
411
+ errors.push({
412
+ path: "evidence.timeline",
413
+ message: "evidence.timeline must be an object."
414
+ });
415
+ return;
416
+ }
417
+ if (timeline.routeId !== void 0) {
418
+ validateNonEmptyString(timeline.routeId, "evidence.timeline.routeId", errors);
419
+ }
420
+ validateStringArray(
421
+ timeline.eventTypes,
422
+ "evidence.timeline.eventTypes",
423
+ errors
424
+ );
425
+ if (!Array.isArray(timeline.events)) {
426
+ errors.push({
427
+ path: "evidence.timeline.events",
428
+ message: "evidence.timeline.events must be an array."
429
+ });
430
+ return;
431
+ }
432
+ timeline.events.forEach((event, index) => {
433
+ if (!isRecord(event)) {
434
+ errors.push({
435
+ path: `evidence.timeline.events.${index}`,
436
+ message: "timeline event must be an object."
437
+ });
438
+ return;
439
+ }
440
+ validateNonEmptyString(
441
+ event.type,
442
+ `evidence.timeline.events.${index}.type`,
443
+ errors
444
+ );
445
+ validateIsoTimestamp(
446
+ event.timestamp,
447
+ `evidence.timeline.events.${index}.timestamp`,
448
+ errors
449
+ );
450
+ });
451
+ }
452
+ function hashArtifactContent(artifact) {
453
+ return hashStableJson({
454
+ ...artifact,
455
+ hashes: {
456
+ ...artifact.hashes,
457
+ artifact: ""
458
+ }
459
+ });
460
+ }
461
+ function pushHashMismatch(errors, path, expected, actual) {
462
+ if (expected === actual) {
463
+ return;
464
+ }
465
+ errors.push({
466
+ path,
467
+ message: `${path} does not match artifact content.`
468
+ });
469
+ }
470
+ function hashStableJson(value) {
471
+ return (0, import_node_crypto.createHash)("sha256").update(stableStringify(value)).digest("hex");
472
+ }
473
+ function stableStringify(value) {
474
+ return JSON.stringify(sortSerializable(value));
475
+ }
476
+ function sortSerializable(value) {
477
+ if (Array.isArray(value)) {
478
+ return value.map(sortSerializable);
479
+ }
480
+ if (!isRecord(value)) {
481
+ return value;
482
+ }
483
+ return Object.fromEntries(
484
+ Object.keys(value).sort().filter((key) => value[key] !== void 0).map((key) => [key, sortSerializable(value[key])])
485
+ );
486
+ }
487
+ function validateSha256String(value, path, errors) {
488
+ if (typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value)) {
489
+ errors.push({
490
+ path,
491
+ message: `${path} must be a sha256 hex string.`
492
+ });
493
+ }
494
+ }
495
+ function validateNonEmptyString(value, path, errors) {
496
+ if (typeof value !== "string" || value.length === 0) {
497
+ errors.push({
498
+ path,
499
+ message: `${path} must be a non-empty string.`
500
+ });
501
+ }
502
+ }
503
+ function validateIsoTimestamp(value, path, errors) {
504
+ if (typeof value !== "string" || Number.isNaN(Date.parse(value))) {
505
+ errors.push({
506
+ path,
507
+ message: `${path} must be an ISO timestamp.`
508
+ });
509
+ }
510
+ }
511
+ function validateStringArray(value, path, errors) {
512
+ if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string" || entry.length === 0)) {
513
+ errors.push({
514
+ path,
515
+ message: `${path} must be an array of non-empty strings.`
516
+ });
517
+ }
518
+ }
519
+ function isRecord(value) {
520
+ return !!value && typeof value === "object" && !Array.isArray(value);
521
+ }
522
+
523
+ // src/auditTrailBundle.ts
524
+ var PROBEMESH_AUDIT_TRAIL_BUNDLE_SCHEMA_VERSION = "probemesh.audit-trail.v1";
525
+ function createProbeMeshAuditTrailBundle(options) {
526
+ assertBundleOptions(options);
527
+ for (const [index, artifact] of options.artifacts.entries()) {
528
+ const validation = validateProbeMeshCallAuditArtifact(artifact);
529
+ if (!validation.valid) {
530
+ throw new ProbeMeshError({
531
+ code: "invalid_request",
532
+ message: `Invalid ProbeMesh call audit artifact at index ${index}: ${formatValidationErrors(
533
+ validation.errors
534
+ )}`
535
+ });
536
+ }
537
+ }
538
+ const artifacts = sanitizeBundleOutput(
539
+ options.artifacts,
540
+ options.forbiddenOutputValues ?? []
541
+ );
542
+ const summary = summarizeArtifacts(artifacts);
543
+ const hashesWithoutBundle = {
544
+ artifacts: hashStableJson2(artifacts),
545
+ summary: hashStableJson2(summary),
546
+ bundle: ""
547
+ };
548
+ const bundleBase = {
549
+ schemaVersion: PROBEMESH_AUDIT_TRAIL_BUNDLE_SCHEMA_VERSION,
550
+ bundleId: options.bundleId ?? `audit_trail_${hashStableJson2({
551
+ artifacts: hashesWithoutBundle.artifacts,
552
+ summary: hashesWithoutBundle.summary
553
+ }).slice(0, 16)}`,
554
+ generatedAt: options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
555
+ status: artifacts.length > 0 ? "complete" : "incomplete",
556
+ hashAlgorithm: "sha256",
557
+ hashes: hashesWithoutBundle,
558
+ summary,
559
+ artifacts
560
+ };
561
+ const bundle = {
562
+ ...bundleBase,
563
+ hashes: {
564
+ ...hashesWithoutBundle,
565
+ bundle: hashBundleContent(bundleBase)
566
+ }
567
+ };
568
+ assertProbeMeshAuditTrailBundle(bundle);
569
+ return bundle;
570
+ }
571
+ function validateProbeMeshAuditTrailBundle(bundle) {
572
+ const errors = [];
573
+ if (!isRecord2(bundle)) {
574
+ return {
575
+ valid: false,
576
+ errors: [
577
+ {
578
+ path: "$",
579
+ message: "ProbeMesh audit trail bundle must be an object."
580
+ }
581
+ ]
582
+ };
583
+ }
584
+ if (bundle.schemaVersion !== PROBEMESH_AUDIT_TRAIL_BUNDLE_SCHEMA_VERSION) {
585
+ errors.push({
586
+ path: "schemaVersion",
587
+ message: `schemaVersion must be "${PROBEMESH_AUDIT_TRAIL_BUNDLE_SCHEMA_VERSION}".`
588
+ });
589
+ }
590
+ validateNonEmptyString2(bundle.bundleId, "bundleId", errors);
591
+ validateIsoTimestamp2(bundle.generatedAt, "generatedAt", errors);
592
+ if (bundle.status !== "complete" && bundle.status !== "incomplete") {
593
+ errors.push({
594
+ path: "status",
595
+ message: 'status must be "complete" or "incomplete".'
596
+ });
597
+ }
598
+ if (bundle.hashAlgorithm !== "sha256") {
599
+ errors.push({
600
+ path: "hashAlgorithm",
601
+ message: 'hashAlgorithm must be "sha256".'
602
+ });
603
+ }
604
+ validateHashes2(bundle.hashes, errors);
605
+ validateSummary(bundle.summary, errors);
606
+ if (!Array.isArray(bundle.artifacts)) {
607
+ errors.push({
608
+ path: "artifacts",
609
+ message: "artifacts must be an array."
610
+ });
611
+ } else {
612
+ bundle.artifacts.forEach((artifact, index) => {
613
+ const validation = validateProbeMeshCallAuditArtifact(artifact);
614
+ for (const artifactError of validation.errors) {
615
+ errors.push({
616
+ path: `artifacts.${index}.${artifactError.path}`,
617
+ message: artifactError.message
618
+ });
619
+ }
620
+ });
621
+ }
622
+ if (errors.length === 0) {
623
+ const typedBundle = bundle;
624
+ pushHashMismatch2(
625
+ errors,
626
+ "hashes.artifacts",
627
+ typedBundle.hashes.artifacts,
628
+ hashStableJson2(typedBundle.artifacts)
629
+ );
630
+ pushHashMismatch2(
631
+ errors,
632
+ "hashes.summary",
633
+ typedBundle.hashes.summary,
634
+ hashStableJson2(typedBundle.summary)
635
+ );
636
+ pushHashMismatch2(
637
+ errors,
638
+ "hashes.bundle",
639
+ typedBundle.hashes.bundle,
640
+ hashBundleContent(typedBundle)
641
+ );
642
+ const expectedSummary = summarizeArtifacts(typedBundle.artifacts);
643
+ if (stableStringify2(typedBundle.summary) !== stableStringify2(expectedSummary)) {
644
+ errors.push({
645
+ path: "summary",
646
+ message: "summary does not match bundle artifacts."
647
+ });
648
+ }
649
+ }
650
+ return {
651
+ valid: errors.length === 0,
652
+ errors
653
+ };
654
+ }
655
+ function assertProbeMeshAuditTrailBundle(bundle) {
656
+ const result = validateProbeMeshAuditTrailBundle(bundle);
657
+ if (result.valid) {
658
+ return;
659
+ }
660
+ throw new ProbeMeshError({
661
+ code: "invalid_request",
662
+ message: `Invalid ProbeMesh audit trail bundle: ${formatValidationErrors(
663
+ result.errors
664
+ )}`
665
+ });
666
+ }
667
+ function formatProbeMeshAuditTrailBundle(bundle, options = {}) {
668
+ assertProbeMeshAuditTrailBundle(bundle);
669
+ if ((options.format ?? "json") === "markdown") {
670
+ return formatBundleMarkdown(bundle);
671
+ }
672
+ return JSON.stringify(bundle, null, 2);
673
+ }
674
+ function assertBundleOptions(options) {
675
+ if (!isRecord2(options)) {
676
+ throw new ProbeMeshError({
677
+ code: "invalid_request",
678
+ message: "ProbeMesh audit trail bundle options must be an object."
679
+ });
680
+ }
681
+ if (!Array.isArray(options.artifacts)) {
682
+ throw new ProbeMeshError({
683
+ code: "invalid_request",
684
+ message: "ProbeMesh audit trail bundle artifacts must be an array."
685
+ });
686
+ }
687
+ if (options.generatedAt !== void 0 && (typeof options.generatedAt !== "string" || Number.isNaN(Date.parse(options.generatedAt)))) {
688
+ throw new ProbeMeshError({
689
+ code: "invalid_request",
690
+ message: "ProbeMesh audit trail bundle generatedAt must be an ISO timestamp."
691
+ });
692
+ }
693
+ if (options.bundleId !== void 0 && (typeof options.bundleId !== "string" || options.bundleId.length === 0)) {
694
+ throw new ProbeMeshError({
695
+ code: "invalid_request",
696
+ message: "ProbeMesh audit trail bundleId must be a non-empty string."
697
+ });
698
+ }
699
+ if (options.forbiddenOutputValues !== void 0 && (!Array.isArray(options.forbiddenOutputValues) || options.forbiddenOutputValues.some((value) => typeof value !== "string"))) {
700
+ throw new ProbeMeshError({
701
+ code: "invalid_request",
702
+ message: "ProbeMesh audit trail bundle forbiddenOutputValues must be an array of strings."
703
+ });
704
+ }
705
+ }
706
+ function summarizeArtifacts(artifacts) {
707
+ const providers = [];
708
+ const capabilities = [];
709
+ const receiptTypes = [];
710
+ const policyBundleIds = [];
711
+ let unsafePaymentEvidenceCalls = 0;
712
+ let retrySafeFailures = 0;
713
+ let uncoveredPolicyFailures = 0;
714
+ for (const artifact of artifacts) {
715
+ pushUnique(providers, artifact.call.providerId);
716
+ pushUnique(capabilities, artifact.call.capability);
717
+ for (const receiptType of artifact.evidence.receiptSummary.types) {
718
+ pushUnique(receiptTypes, receiptType);
719
+ }
720
+ const attestationBundleId = artifact.evidence.route?.attestation?.bundleId;
721
+ pushUnique(policyBundleIds, attestationBundleId);
722
+ if (artifact.evidence.safety?.moneyMayHaveMoved === true || artifact.evidence.receiptSummary.hasPaymentProof) {
723
+ unsafePaymentEvidenceCalls += 1;
724
+ }
725
+ if (artifact.status === "failed" && artifact.evidence.retrySafety?.safeToAutoRetry === true) {
726
+ retrySafeFailures += 1;
727
+ }
728
+ if (artifact.status === "failed" && artifact.evidence.route?.explanation?.attempts.some(
729
+ (attempt) => attempt.reason === "skipped_policy_bundle_uncovered"
730
+ ) === true) {
731
+ uncoveredPolicyFailures += 1;
732
+ }
733
+ }
734
+ return {
735
+ totalCalls: artifacts.length,
736
+ completedCalls: artifacts.filter((artifact) => artifact.status === "completed").length,
737
+ failedCalls: artifacts.filter((artifact) => artifact.status === "failed").length,
738
+ providers,
739
+ capabilities,
740
+ receiptTypes,
741
+ policyBundleIds,
742
+ unsafePaymentEvidenceCalls,
743
+ retrySafeFailures,
744
+ uncoveredPolicyFailures
745
+ };
746
+ }
747
+ function validateHashes2(hashes, errors) {
748
+ if (!isRecord2(hashes)) {
749
+ errors.push({
750
+ path: "hashes",
751
+ message: "hashes must be an object."
752
+ });
753
+ return;
754
+ }
755
+ for (const key of ["artifacts", "summary", "bundle"]) {
756
+ validateSha256String2(hashes[key], `hashes.${key}`, errors);
757
+ }
758
+ }
759
+ function validateSummary(summary, errors) {
760
+ if (!isRecord2(summary)) {
761
+ errors.push({
762
+ path: "summary",
763
+ message: "summary must be an object."
764
+ });
765
+ return;
766
+ }
767
+ for (const key of [
768
+ "totalCalls",
769
+ "completedCalls",
770
+ "failedCalls",
771
+ "unsafePaymentEvidenceCalls",
772
+ "retrySafeFailures",
773
+ "uncoveredPolicyFailures"
774
+ ]) {
775
+ if (typeof summary[key] !== "number" || !Number.isFinite(summary[key]) || summary[key] < 0) {
776
+ errors.push({
777
+ path: `summary.${key}`,
778
+ message: `summary.${key} must be a non-negative finite number.`
779
+ });
780
+ }
781
+ }
782
+ validateStringArray2(summary.providers, "summary.providers", errors);
783
+ validateStringArray2(summary.capabilities, "summary.capabilities", errors);
784
+ validateStringArray2(summary.receiptTypes, "summary.receiptTypes", errors);
785
+ validateStringArray2(summary.policyBundleIds, "summary.policyBundleIds", errors);
786
+ }
787
+ function hashBundleContent(bundle) {
788
+ return hashStableJson2({
789
+ ...bundle,
790
+ hashes: {
791
+ ...bundle.hashes,
792
+ bundle: ""
793
+ }
794
+ });
795
+ }
796
+ function pushHashMismatch2(errors, path, expected, actual) {
797
+ if (expected === actual) {
798
+ return;
799
+ }
800
+ errors.push({
801
+ path,
802
+ message: `${path} does not match bundle content.`
803
+ });
804
+ }
805
+ function hashStableJson2(value) {
806
+ return (0, import_node_crypto2.createHash)("sha256").update(stableStringify2(value)).digest("hex");
807
+ }
808
+ function stableStringify2(value) {
809
+ return JSON.stringify(sortSerializable2(value));
810
+ }
811
+ function sortSerializable2(value) {
812
+ if (Array.isArray(value)) {
813
+ return value.map(sortSerializable2);
814
+ }
815
+ if (!isRecord2(value)) {
816
+ return value;
817
+ }
818
+ return Object.fromEntries(
819
+ Object.keys(value).sort().filter((key) => value[key] !== void 0).map((key) => [key, sortSerializable2(value[key])])
820
+ );
821
+ }
822
+ function sanitizeBundleOutput(value, forbiddenOutputValues) {
823
+ const forbiddenValues = forbiddenOutputValues.filter((entry) => entry.length > 0);
824
+ return redactX402Secrets(
825
+ replaceForbiddenValues(cloneSerializable(value), forbiddenValues)
826
+ );
827
+ }
828
+ function replaceForbiddenValues(value, forbiddenValues) {
829
+ if (typeof value === "string") {
830
+ return forbiddenValues.reduce(
831
+ (current, forbidden) => current.split(forbidden).join("[REDACTED]"),
832
+ value
833
+ );
834
+ }
835
+ if (value === null || typeof value !== "object" || value instanceof Date) {
836
+ return value;
837
+ }
838
+ if (Array.isArray(value)) {
839
+ return value.map((entry) => replaceForbiddenValues(entry, forbiddenValues));
840
+ }
841
+ return Object.fromEntries(
842
+ Object.entries(value).map(([key, entry]) => [
843
+ key,
844
+ replaceForbiddenValues(entry, forbiddenValues)
845
+ ])
846
+ );
847
+ }
848
+ function cloneSerializable(value) {
849
+ if (value === void 0) {
850
+ return value;
851
+ }
852
+ return JSON.parse(JSON.stringify(value));
853
+ }
854
+ function formatBundleMarkdown(bundle) {
855
+ return [
856
+ `# ProbeMesh Audit Trail Bundle`,
857
+ ``,
858
+ `Status: ${bundle.status}`,
859
+ `Schema: ${bundle.schemaVersion}`,
860
+ `Bundle ID: ${bundle.bundleId}`,
861
+ `Generated: ${bundle.generatedAt}`,
862
+ ``,
863
+ `## Summary`,
864
+ `- Total calls: ${bundle.summary.totalCalls}`,
865
+ `- Completed: ${bundle.summary.completedCalls}`,
866
+ `- Failed: ${bundle.summary.failedCalls}`,
867
+ `- Providers: ${formatInlineList(bundle.summary.providers)}`,
868
+ `- Capabilities: ${formatInlineList(bundle.summary.capabilities)}`,
869
+ `- Receipt types: ${formatInlineList(bundle.summary.receiptTypes)}`,
870
+ `- Policy bundles: ${formatInlineList(bundle.summary.policyBundleIds)}`,
871
+ `- Unsafe payment evidence calls: ${bundle.summary.unsafePaymentEvidenceCalls}`,
872
+ `- Retry-safe failures: ${bundle.summary.retrySafeFailures}`,
873
+ `- Uncovered policy failures: ${bundle.summary.uncoveredPolicyFailures}`,
874
+ ``,
875
+ `## Artifacts`,
876
+ ...bundle.artifacts.map(
877
+ (artifact) => `- ${artifact.call.callId ?? artifact.artifactId}: ${artifact.status} / ${artifact.call.capability} / ${artifact.call.providerId ?? "none"}`
878
+ ),
879
+ ``,
880
+ `## Hashes`,
881
+ `- Bundle: ${bundle.hashes.bundle}`,
882
+ `- Artifacts: ${bundle.hashes.artifacts}`,
883
+ `- Summary: ${bundle.hashes.summary}`
884
+ ].join("\n");
885
+ }
886
+ function formatInlineList(values) {
887
+ return values.length === 0 ? "none" : values.join(", ");
888
+ }
889
+ function pushUnique(values, value) {
890
+ if (value && !values.includes(value)) {
891
+ values.push(value);
892
+ }
893
+ }
894
+ function validateSha256String2(value, path, errors) {
895
+ if (typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value)) {
896
+ errors.push({
897
+ path,
898
+ message: `${path} must be a sha256 hex string.`
899
+ });
900
+ }
901
+ }
902
+ function validateNonEmptyString2(value, path, errors) {
903
+ if (typeof value !== "string" || value.length === 0) {
904
+ errors.push({
905
+ path,
906
+ message: `${path} must be a non-empty string.`
907
+ });
908
+ }
909
+ }
910
+ function validateIsoTimestamp2(value, path, errors) {
911
+ if (typeof value !== "string" || Number.isNaN(Date.parse(value))) {
912
+ errors.push({
913
+ path,
914
+ message: `${path} must be an ISO timestamp.`
915
+ });
916
+ }
917
+ }
918
+ function validateStringArray2(value, path, errors) {
919
+ if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string" || entry.length === 0)) {
920
+ errors.push({
921
+ path,
922
+ message: `${path} must be an array of non-empty strings.`
923
+ });
924
+ }
925
+ }
926
+ function isRecord2(value) {
927
+ return !!value && typeof value === "object" && !Array.isArray(value);
928
+ }
929
+ function formatValidationErrors(errors) {
930
+ return errors.map((error) => `${error.path}: ${error.message}`).join("; ");
931
+ }
932
+
933
+ // src/cli/auditTrailExportCli.ts
934
+ var USAGE = "Usage: probemesh-audit-trail-export --config <path> [--format markdown|json] [--out-json <path>] [--out-md <path>] [--bundle-id <text>] [--generated-at <iso>]";
935
+ async function runProbeMeshAuditTrailExportCli(options = {}) {
936
+ const argv = options.argv ?? [];
937
+ const cwd = options.cwd ?? process.cwd();
938
+ try {
939
+ const parsedArgs = parseCliArgs(argv);
940
+ if (parsedArgs.help) {
941
+ return {
942
+ exitCode: 0,
943
+ skipped: true,
944
+ stdout: `${USAGE}
945
+ `
946
+ };
947
+ }
948
+ if (!parsedArgs.configPath) {
949
+ return cliFailure("--config <path> is required.");
950
+ }
951
+ const configExport = await loadCliConfig(parsedArgs.configPath, {
952
+ argv,
953
+ cwd
954
+ });
955
+ if (isCliSkip(configExport)) {
956
+ return {
957
+ exitCode: 0,
958
+ skipped: true,
959
+ skip: configExport,
960
+ stdout: `ProbeMesh audit trail export skipped: ${configExport.reason}
961
+ `
962
+ };
963
+ }
964
+ assertCliConfig(configExport);
965
+ const artifacts = await loadArtifacts({
966
+ cwd,
967
+ inlineArtifacts: configExport.artifacts,
968
+ artifactFiles: configExport.artifactFiles
969
+ });
970
+ const bundle = createProbeMeshAuditTrailBundle({
971
+ artifacts,
972
+ bundleId: parsedArgs.bundleId ?? configExport.bundle?.bundleId,
973
+ generatedAt: parsedArgs.generatedAt ?? configExport.bundle?.generatedAt,
974
+ forbiddenOutputValues: configExport.bundle?.forbiddenOutputValues
975
+ });
976
+ const selectedFormat = parsedArgs.format ?? configExport.bundle?.format ?? "markdown";
977
+ const stdout = formatProbeMeshAuditTrailBundle(bundle, {
978
+ format: selectedFormat
979
+ });
980
+ const artifactPaths = await writeArtifacts({
981
+ cwd,
982
+ bundle,
983
+ outputs: {
984
+ json: parsedArgs.outJson ?? configExport.outputs?.json,
985
+ markdown: parsedArgs.outMarkdown ?? configExport.outputs?.markdown
986
+ }
987
+ });
988
+ return {
989
+ exitCode: bundle.status === "complete" ? 0 : 1,
990
+ skipped: false,
991
+ bundle,
992
+ stdout,
993
+ artifactPaths
994
+ };
995
+ } catch (error) {
996
+ return cliFailure(
997
+ error instanceof Error ? error.message : "Unknown audit trail export CLI failure."
998
+ );
999
+ }
1000
+ }
1001
+ function parseCliArgs(argv) {
1002
+ const parsedArgs = {};
1003
+ for (let index = 0; index < argv.length; index += 1) {
1004
+ const arg = argv[index];
1005
+ if (arg === "--") {
1006
+ continue;
1007
+ }
1008
+ if (arg === "--help" || arg === "-h") {
1009
+ parsedArgs.help = true;
1010
+ continue;
1011
+ }
1012
+ if (arg === "--config") {
1013
+ parsedArgs.configPath = requireValue(argv, index, arg);
1014
+ index += 1;
1015
+ continue;
1016
+ }
1017
+ if (arg === "--format") {
1018
+ const format = requireValue(argv, index, arg);
1019
+ if (format !== "markdown" && format !== "json") {
1020
+ throw new Error("--format must be markdown or json.");
1021
+ }
1022
+ parsedArgs.format = format;
1023
+ index += 1;
1024
+ continue;
1025
+ }
1026
+ if (arg === "--out-json") {
1027
+ parsedArgs.outJson = requireValue(argv, index, arg);
1028
+ index += 1;
1029
+ continue;
1030
+ }
1031
+ if (arg === "--out-md") {
1032
+ parsedArgs.outMarkdown = requireValue(argv, index, arg);
1033
+ index += 1;
1034
+ continue;
1035
+ }
1036
+ if (arg === "--bundle-id") {
1037
+ parsedArgs.bundleId = requireValue(argv, index, arg);
1038
+ index += 1;
1039
+ continue;
1040
+ }
1041
+ if (arg === "--generated-at") {
1042
+ parsedArgs.generatedAt = requireValue(argv, index, arg);
1043
+ index += 1;
1044
+ continue;
1045
+ }
1046
+ throw new Error(`Unknown argument "${arg}".`);
1047
+ }
1048
+ return parsedArgs;
1049
+ }
1050
+ function requireValue(argv, index, flag) {
1051
+ const value = argv[index + 1];
1052
+ if (!value || value.startsWith("--")) {
1053
+ throw new Error(`${flag} requires a value.`);
1054
+ }
1055
+ return value;
1056
+ }
1057
+ async function loadCliConfig(configPath, context) {
1058
+ const configExport = await loadCliConfigDefault(configPath, context.cwd);
1059
+ if (typeof configExport === "function") {
1060
+ return configExport(context);
1061
+ }
1062
+ return configExport;
1063
+ }
1064
+ function isCliSkip(value) {
1065
+ return !!value && typeof value === "object" && !Array.isArray(value) && value.skip === true && typeof value.reason === "string";
1066
+ }
1067
+ function assertCliConfig(value) {
1068
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1069
+ throw new Error("Audit trail export CLI config must export an object.");
1070
+ }
1071
+ const config = value;
1072
+ if (config.artifacts !== void 0 && !Array.isArray(config.artifacts)) {
1073
+ throw new Error("Audit trail export CLI artifacts must be an array.");
1074
+ }
1075
+ if (config.artifactFiles !== void 0 && (!Array.isArray(config.artifactFiles) || config.artifactFiles.some((artifactFile) => typeof artifactFile !== "string"))) {
1076
+ throw new Error("Audit trail export CLI artifactFiles must be an array of strings.");
1077
+ }
1078
+ if (config.bundle !== void 0) {
1079
+ assertBundleConfig(config.bundle);
1080
+ }
1081
+ const outputs = config.outputs;
1082
+ if (outputs !== void 0 && (!outputs || typeof outputs !== "object" || Array.isArray(outputs) || outputs.json !== void 0 && typeof outputs.json !== "string" || outputs.markdown !== void 0 && typeof outputs.markdown !== "string")) {
1083
+ throw new Error("Audit trail export CLI outputs must contain string paths.");
1084
+ }
1085
+ }
1086
+ function assertBundleConfig(value) {
1087
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1088
+ throw new Error("Audit trail export CLI bundle config must be an object.");
1089
+ }
1090
+ const bundle = value;
1091
+ if (bundle.bundleId !== void 0 && typeof bundle.bundleId !== "string") {
1092
+ throw new Error("Audit trail export CLI bundleId must be a string.");
1093
+ }
1094
+ if (bundle.generatedAt !== void 0 && typeof bundle.generatedAt !== "string") {
1095
+ throw new Error("Audit trail export CLI generatedAt must be a string.");
1096
+ }
1097
+ if (bundle.forbiddenOutputValues !== void 0 && (!Array.isArray(bundle.forbiddenOutputValues) || bundle.forbiddenOutputValues.some((value2) => typeof value2 !== "string"))) {
1098
+ throw new Error(
1099
+ "Audit trail export CLI forbiddenOutputValues must be an array of strings."
1100
+ );
1101
+ }
1102
+ if (bundle.format !== void 0 && bundle.format !== "markdown" && bundle.format !== "json") {
1103
+ throw new Error("Audit trail export CLI bundle format must be markdown or json.");
1104
+ }
1105
+ }
1106
+ async function loadArtifacts(options) {
1107
+ const artifacts = [
1108
+ ...options.inlineArtifacts ?? []
1109
+ ];
1110
+ for (const artifactFile of options.artifactFiles ?? []) {
1111
+ const loadedArtifacts = await loadArtifactFile(options.cwd, artifactFile);
1112
+ artifacts.push(...loadedArtifacts);
1113
+ }
1114
+ return artifacts;
1115
+ }
1116
+ async function loadArtifactFile(cwd, artifactFile) {
1117
+ const artifactPath = (0, import_node_path2.resolve)(cwd, artifactFile);
1118
+ const body = await (0, import_promises2.readFile)(artifactPath, "utf8");
1119
+ let parsed;
1120
+ try {
1121
+ parsed = JSON.parse(body);
1122
+ } catch (error) {
1123
+ throw new Error(
1124
+ `Invalid audit artifact JSON in "${artifactFile}": ${error instanceof Error ? error.message : "parse failed"}`
1125
+ );
1126
+ }
1127
+ if (Array.isArray(parsed)) {
1128
+ return parsed;
1129
+ }
1130
+ if (parsed && typeof parsed === "object") {
1131
+ return [parsed];
1132
+ }
1133
+ throw new Error(
1134
+ `Audit artifact file "${artifactFile}" must contain an artifact object or artifact array.`
1135
+ );
1136
+ }
1137
+ async function writeArtifacts(options) {
1138
+ const artifactPaths = {};
1139
+ if (options.outputs.json) {
1140
+ const outputPath = (0, import_node_path2.resolve)(options.cwd, options.outputs.json);
1141
+ await writeArtifact(
1142
+ outputPath,
1143
+ formatProbeMeshAuditTrailBundle(options.bundle, {
1144
+ format: "json"
1145
+ })
1146
+ );
1147
+ artifactPaths.json = outputPath;
1148
+ }
1149
+ if (options.outputs.markdown) {
1150
+ const outputPath = (0, import_node_path2.resolve)(options.cwd, options.outputs.markdown);
1151
+ await writeArtifact(
1152
+ outputPath,
1153
+ formatProbeMeshAuditTrailBundle(options.bundle, {
1154
+ format: "markdown"
1155
+ })
1156
+ );
1157
+ artifactPaths.markdown = outputPath;
1158
+ }
1159
+ return artifactPaths;
1160
+ }
1161
+ async function writeArtifact(outputPath, body) {
1162
+ await (0, import_promises2.mkdir)((0, import_node_path2.dirname)(outputPath), {
1163
+ recursive: true
1164
+ });
1165
+ await (0, import_promises2.writeFile)(outputPath, body, "utf8");
1166
+ }
1167
+ function cliFailure(message) {
1168
+ return {
1169
+ exitCode: 2,
1170
+ skipped: false,
1171
+ stdout: "",
1172
+ stderr: `${message}
1173
+ ${USAGE}
1174
+ `
1175
+ };
1176
+ }
1177
+
1178
+ // src/cli/audit-trail-export.ts
1179
+ void main();
1180
+ async function main() {
1181
+ const result = await runProbeMeshAuditTrailExportCli({
1182
+ argv: process.argv.slice(2),
1183
+ cwd: process.cwd()
1184
+ });
1185
+ if (result.stdout) {
1186
+ process.stdout.write(result.stdout);
1187
+ }
1188
+ if (result.stderr) {
1189
+ process.stderr.write(result.stderr);
1190
+ }
1191
+ process.exitCode = result.exitCode;
1192
+ }
1193
+ //# sourceMappingURL=audit-trail-export.cjs.map