@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,607 @@
1
+ import {
2
+ validateProviderConformanceArtifact
3
+ } from "./chunk-UU2ZG7P7.js";
4
+ import {
5
+ validateProviderCatalogArtifact
6
+ } from "./chunk-3H7UGVI6.js";
7
+ import {
8
+ redactX402Secrets
9
+ } from "./chunk-NYTV263W.js";
10
+ import {
11
+ ProbeMeshError
12
+ } from "./chunk-2ASMVLG4.js";
13
+
14
+ // src/providerOnboardingDossier.ts
15
+ import { createHash } from "crypto";
16
+ var PROVIDER_ONBOARDING_DOSSIER_SCHEMA_VERSION = "probemesh.provider-onboarding-dossier.v1";
17
+ function createProviderOnboardingDossier(options) {
18
+ assertProviderOnboardingDossierOptions(options);
19
+ const status = options.catalogArtifact.status === "ready" && options.conformanceArtifact.status === "verified" ? "ready" : "failed";
20
+ const readiness = summarizeReadiness(
21
+ options.catalogArtifact,
22
+ options.conformanceArtifact,
23
+ status
24
+ );
25
+ const baseContent = sanitizeDossierOutput(
26
+ {
27
+ schemaVersion: PROVIDER_ONBOARDING_DOSSIER_SCHEMA_VERSION,
28
+ dossierId: options.dossierId ?? `${options.catalogArtifact.provider.id}:${options.catalogArtifact.artifactId}:${options.conformanceArtifact.artifactId}:dossier`,
29
+ generatedAt: options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
30
+ status,
31
+ hashAlgorithm: "sha256",
32
+ provider: summarizeProvider(options.catalogArtifact),
33
+ readiness,
34
+ evidence: summarizeEvidence(
35
+ options.catalogArtifact,
36
+ options.conformanceArtifact
37
+ ),
38
+ artifacts: {
39
+ catalog: cloneSerializable(options.catalogArtifact),
40
+ conformance: cloneSerializable(options.conformanceArtifact)
41
+ }
42
+ },
43
+ options.forbiddenOutputValues ?? []
44
+ );
45
+ const hashesWithoutDossier = {
46
+ catalogArtifact: hashStableJson(baseContent.artifacts.catalog),
47
+ conformanceArtifact: hashStableJson(baseContent.artifacts.conformance),
48
+ readiness: hashStableJson(baseContent.readiness),
49
+ dossier: ""
50
+ };
51
+ const dossier = {
52
+ ...baseContent,
53
+ hashes: {
54
+ ...hashesWithoutDossier,
55
+ dossier: hashDossierContent({
56
+ ...baseContent,
57
+ hashes: hashesWithoutDossier
58
+ })
59
+ }
60
+ };
61
+ assertProviderOnboardingDossier(dossier);
62
+ return dossier;
63
+ }
64
+ function validateProviderOnboardingDossier(dossier) {
65
+ const errors = [];
66
+ if (!isRecord(dossier)) {
67
+ return {
68
+ valid: false,
69
+ errors: [
70
+ {
71
+ path: "$",
72
+ message: "Provider onboarding dossier must be an object."
73
+ }
74
+ ]
75
+ };
76
+ }
77
+ if (dossier.schemaVersion !== PROVIDER_ONBOARDING_DOSSIER_SCHEMA_VERSION) {
78
+ errors.push({
79
+ path: "schemaVersion",
80
+ message: `schemaVersion must be "${PROVIDER_ONBOARDING_DOSSIER_SCHEMA_VERSION}".`
81
+ });
82
+ }
83
+ validateNonEmptyString(dossier.dossierId, "dossierId", errors);
84
+ validateIsoTimestamp(dossier.generatedAt, "generatedAt", errors);
85
+ if (dossier.status !== "ready" && dossier.status !== "failed") {
86
+ errors.push({
87
+ path: "status",
88
+ message: 'status must be "ready" or "failed".'
89
+ });
90
+ }
91
+ if (dossier.hashAlgorithm !== "sha256") {
92
+ errors.push({
93
+ path: "hashAlgorithm",
94
+ message: 'hashAlgorithm must be "sha256".'
95
+ });
96
+ }
97
+ validateProviderSummary(dossier.provider, errors);
98
+ validateReadiness(dossier.readiness, errors);
99
+ validateEvidence(dossier.evidence, errors);
100
+ validateNestedArtifacts(dossier.artifacts, errors);
101
+ validateHashes(dossier, errors);
102
+ return {
103
+ valid: errors.length === 0,
104
+ errors
105
+ };
106
+ }
107
+ function assertProviderOnboardingDossier(dossier) {
108
+ const result = validateProviderOnboardingDossier(dossier);
109
+ if (result.valid) {
110
+ return;
111
+ }
112
+ throw new ProbeMeshError({
113
+ code: "invalid_request",
114
+ message: `Invalid provider onboarding dossier: ${formatValidationErrors(
115
+ result.errors
116
+ )}`
117
+ });
118
+ }
119
+ function formatProviderOnboardingDossier(dossier, options = {}) {
120
+ assertProviderOnboardingDossier(dossier);
121
+ if ((options.format ?? "json") === "markdown") {
122
+ return formatDossierMarkdown(dossier, options.title);
123
+ }
124
+ return JSON.stringify(dossier, null, 2);
125
+ }
126
+ function assertProviderOnboardingDossierOptions(options) {
127
+ if (!options || typeof options !== "object" || Array.isArray(options)) {
128
+ throw new ProbeMeshError({
129
+ code: "invalid_request",
130
+ message: "Provider onboarding dossier options must be an object."
131
+ });
132
+ }
133
+ const catalogValidation = validateProviderCatalogArtifact(
134
+ options.catalogArtifact
135
+ );
136
+ if (!catalogValidation.valid) {
137
+ throw new ProbeMeshError({
138
+ code: "invalid_request",
139
+ message: `Invalid provider onboarding catalog artifact: ${formatValidationErrors(
140
+ catalogValidation.errors
141
+ )}`
142
+ });
143
+ }
144
+ const conformanceValidation = validateProviderConformanceArtifact(
145
+ options.conformanceArtifact
146
+ );
147
+ if (!conformanceValidation.valid) {
148
+ throw new ProbeMeshError({
149
+ code: "invalid_request",
150
+ message: `Invalid provider onboarding conformance artifact: ${formatValidationErrors(
151
+ conformanceValidation.errors
152
+ )}`
153
+ });
154
+ }
155
+ if (options.catalogArtifact.provider.id !== options.conformanceArtifact.provider.id) {
156
+ throw new ProbeMeshError({
157
+ code: "invalid_request",
158
+ message: "Provider onboarding dossier requires catalog and conformance artifacts for the same provider id."
159
+ });
160
+ }
161
+ if (options.generatedAt !== void 0 && (typeof options.generatedAt !== "string" || Number.isNaN(Date.parse(options.generatedAt)))) {
162
+ throw new ProbeMeshError({
163
+ code: "invalid_request",
164
+ message: "Provider onboarding dossier generatedAt must be an ISO timestamp."
165
+ });
166
+ }
167
+ if (options.dossierId !== void 0 && (typeof options.dossierId !== "string" || options.dossierId.length === 0)) {
168
+ throw new ProbeMeshError({
169
+ code: "invalid_request",
170
+ message: "Provider onboarding dossier dossierId must be a non-empty string."
171
+ });
172
+ }
173
+ if (options.forbiddenOutputValues !== void 0 && (!Array.isArray(options.forbiddenOutputValues) || options.forbiddenOutputValues.some((value) => typeof value !== "string"))) {
174
+ throw new ProbeMeshError({
175
+ code: "invalid_request",
176
+ message: "Provider onboarding dossier forbiddenOutputValues must be an array of strings."
177
+ });
178
+ }
179
+ }
180
+ function summarizeProvider(catalogArtifact) {
181
+ return {
182
+ id: catalogArtifact.provider.id,
183
+ displayName: catalogArtifact.provider.displayName,
184
+ capabilities: [...catalogArtifact.provider.capabilities],
185
+ protocolMode: catalogArtifact.provider.protocolMode,
186
+ pricing: cloneSerializable(catalogArtifact.provider.pricing),
187
+ paymentOptions: cloneSerializable(catalogArtifact.provider.paymentOptions)
188
+ };
189
+ }
190
+ function summarizeReadiness(catalogArtifact, conformanceArtifact, status) {
191
+ const reasons = [];
192
+ const failedChecks = [];
193
+ if (catalogArtifact.status === "ready") {
194
+ reasons.push("Catalog artifact is ready.");
195
+ } else {
196
+ reasons.push("Catalog artifact is rejected.");
197
+ failedChecks.push("catalog_not_ready");
198
+ }
199
+ if (conformanceArtifact.status === "verified") {
200
+ reasons.push("Conformance artifact is verified.");
201
+ } else {
202
+ reasons.push("Conformance artifact failed.");
203
+ failedChecks.push("conformance_not_verified");
204
+ }
205
+ for (const check of catalogArtifact.acceptance.failedChecks) {
206
+ failedChecks.push(`catalog:${check}`);
207
+ }
208
+ for (const check of conformanceArtifact.conformance.failedChecks) {
209
+ failedChecks.push(`conformance:${check}`);
210
+ }
211
+ return {
212
+ ready: status === "ready",
213
+ status,
214
+ reasons,
215
+ failedChecks: uniqueStrings(failedChecks)
216
+ };
217
+ }
218
+ function summarizeEvidence(catalogArtifact, conformanceArtifact) {
219
+ return {
220
+ catalog: {
221
+ artifactId: catalogArtifact.artifactId,
222
+ status: catalogArtifact.status,
223
+ acceptanceStatus: catalogArtifact.acceptance.status,
224
+ gateStatus: catalogArtifact.acceptance.gate.status,
225
+ accepted: catalogArtifact.acceptance.gate.accepted,
226
+ failedChecks: [...catalogArtifact.acceptance.failedChecks]
227
+ },
228
+ conformance: {
229
+ artifactId: conformanceArtifact.artifactId,
230
+ status: conformanceArtifact.status,
231
+ conformanceStatus: conformanceArtifact.conformance.status,
232
+ failedChecks: [...conformanceArtifact.conformance.failedChecks]
233
+ },
234
+ receipts: combineReceiptSummaries(
235
+ catalogArtifact.acceptance.receipts,
236
+ conformanceArtifact.conformance.receipts
237
+ ),
238
+ safety: {
239
+ acceptance: cloneSerializable(catalogArtifact.acceptance.safety),
240
+ conformance: cloneSerializable(conformanceArtifact.conformance.safety)
241
+ },
242
+ retrySafety: {
243
+ acceptance: cloneSerializable(catalogArtifact.acceptance.retrySafety),
244
+ conformance: cloneSerializable(conformanceArtifact.conformance.retrySafety)
245
+ },
246
+ route: {
247
+ acceptance: cloneSerializable(catalogArtifact.acceptance.route),
248
+ conformance: cloneSerializable(conformanceArtifact.conformance.route)
249
+ },
250
+ timelineEventTypes: uniqueStrings([
251
+ ...catalogArtifact.acceptance.timelineEventTypes,
252
+ ...conformanceArtifact.conformance.timelineEventTypes
253
+ ]),
254
+ telemetryEventTypes: uniqueStrings([
255
+ ...catalogArtifact.acceptance.telemetryEventTypes,
256
+ ...conformanceArtifact.conformance.telemetryEventTypes
257
+ ])
258
+ };
259
+ }
260
+ function combineReceiptSummaries(left, right) {
261
+ const byType = {};
262
+ for (const [type, count] of Object.entries(left.byType)) {
263
+ byType[type] = (byType[type] ?? 0) + Number(count);
264
+ }
265
+ for (const [type, count] of Object.entries(right.byType)) {
266
+ byType[type] = (byType[type] ?? 0) + Number(count);
267
+ }
268
+ return {
269
+ total: left.total + right.total,
270
+ types: uniqueStrings([...left.types, ...right.types]),
271
+ providers: uniqueStrings([...left.providers, ...right.providers]),
272
+ byType,
273
+ hasPaymentProof: left.hasPaymentProof || right.hasPaymentProof,
274
+ hasSettlementConfirmation: left.hasSettlementConfirmation || right.hasSettlementConfirmation,
275
+ hasProviderDelivery: left.hasProviderDelivery || right.hasProviderDelivery
276
+ };
277
+ }
278
+ function formatDossierMarkdown(dossier, title) {
279
+ const lines = [
280
+ `# ${title ?? `${dossier.provider.displayName} Onboarding Dossier`}`,
281
+ "",
282
+ `Status: ${dossier.status}`,
283
+ `Schema: ${dossier.schemaVersion}`,
284
+ `Dossier ID: ${dossier.dossierId}`,
285
+ `Generated: ${dossier.generatedAt}`,
286
+ `Provider: ${dossier.provider.id}`,
287
+ `Capabilities: ${formatInlineList(dossier.provider.capabilities)}`,
288
+ "",
289
+ "## Readiness",
290
+ `- Ready: ${String(dossier.readiness.ready)}`,
291
+ `- Reasons: ${formatInlineList(dossier.readiness.reasons)}`,
292
+ `- Failed checks: ${formatInlineList(dossier.readiness.failedChecks)}`,
293
+ "",
294
+ "## Evidence",
295
+ `- Catalog artifact: ${dossier.evidence.catalog.artifactId} (${dossier.evidence.catalog.status})`,
296
+ `- Conformance artifact: ${dossier.evidence.conformance.artifactId} (${dossier.evidence.conformance.status})`,
297
+ `- Receipts: ${formatInlineList(dossier.evidence.receipts.types)}`,
298
+ `- Timeline: ${formatInlineList(dossier.evidence.timelineEventTypes)}`,
299
+ "",
300
+ "## Safety",
301
+ `- Acceptance payment: ${dossier.evidence.safety.acceptance?.paymentStatus ?? "unknown"}`,
302
+ `- Conformance payment: ${dossier.evidence.safety.conformance?.paymentStatus ?? "unknown"}`,
303
+ `- Acceptance delivery: ${dossier.evidence.safety.acceptance?.deliveryStatus ?? "unknown"}`,
304
+ `- Conformance delivery: ${dossier.evidence.safety.conformance?.deliveryStatus ?? "unknown"}`,
305
+ "",
306
+ "## Hashes",
307
+ `- Catalog artifact: ${dossier.hashes.catalogArtifact}`,
308
+ `- Conformance artifact: ${dossier.hashes.conformanceArtifact}`,
309
+ `- Readiness: ${dossier.hashes.readiness}`,
310
+ `- Dossier: ${dossier.hashes.dossier}`
311
+ ];
312
+ return `${lines.join("\n")}
313
+ `;
314
+ }
315
+ function validateProviderSummary(provider, errors) {
316
+ if (!isRecord(provider)) {
317
+ errors.push({
318
+ path: "provider",
319
+ message: "provider must be an object."
320
+ });
321
+ return;
322
+ }
323
+ validateNonEmptyString(provider.id, "provider.id", errors);
324
+ validateNonEmptyString(provider.displayName, "provider.displayName", errors);
325
+ validateNonEmptyString(provider.protocolMode, "provider.protocolMode", errors);
326
+ if (!Array.isArray(provider.capabilities) || provider.capabilities.some((capability) => typeof capability !== "string")) {
327
+ errors.push({
328
+ path: "provider.capabilities",
329
+ message: "provider.capabilities must be an array of strings."
330
+ });
331
+ }
332
+ }
333
+ function validateReadiness(readiness, errors) {
334
+ if (!isRecord(readiness)) {
335
+ errors.push({
336
+ path: "readiness",
337
+ message: "readiness must be an object."
338
+ });
339
+ return;
340
+ }
341
+ if (typeof readiness.ready !== "boolean") {
342
+ errors.push({
343
+ path: "readiness.ready",
344
+ message: "readiness.ready must be a boolean."
345
+ });
346
+ }
347
+ if (readiness.status !== "ready" && readiness.status !== "failed") {
348
+ errors.push({
349
+ path: "readiness.status",
350
+ message: 'readiness.status must be "ready" or "failed".'
351
+ });
352
+ }
353
+ if (!Array.isArray(readiness.reasons) || readiness.reasons.some((reason) => typeof reason !== "string")) {
354
+ errors.push({
355
+ path: "readiness.reasons",
356
+ message: "readiness.reasons must be an array of strings."
357
+ });
358
+ }
359
+ if (!Array.isArray(readiness.failedChecks) || readiness.failedChecks.some((check) => typeof check !== "string")) {
360
+ errors.push({
361
+ path: "readiness.failedChecks",
362
+ message: "readiness.failedChecks must be an array of strings."
363
+ });
364
+ }
365
+ }
366
+ function validateEvidence(evidence, errors) {
367
+ if (!isRecord(evidence)) {
368
+ errors.push({
369
+ path: "evidence",
370
+ message: "evidence must be an object."
371
+ });
372
+ return;
373
+ }
374
+ if (!isRecord(evidence.catalog)) {
375
+ errors.push({
376
+ path: "evidence.catalog",
377
+ message: "evidence.catalog must be an object."
378
+ });
379
+ } else {
380
+ validateNonEmptyString(
381
+ evidence.catalog.artifactId,
382
+ "evidence.catalog.artifactId",
383
+ errors
384
+ );
385
+ if (evidence.catalog.status !== "ready" && evidence.catalog.status !== "rejected") {
386
+ errors.push({
387
+ path: "evidence.catalog.status",
388
+ message: 'evidence.catalog.status must be "ready" or "rejected".'
389
+ });
390
+ }
391
+ if (typeof evidence.catalog.accepted !== "boolean") {
392
+ errors.push({
393
+ path: "evidence.catalog.accepted",
394
+ message: "evidence.catalog.accepted must be a boolean."
395
+ });
396
+ }
397
+ }
398
+ if (!isRecord(evidence.conformance)) {
399
+ errors.push({
400
+ path: "evidence.conformance",
401
+ message: "evidence.conformance must be an object."
402
+ });
403
+ } else {
404
+ validateNonEmptyString(
405
+ evidence.conformance.artifactId,
406
+ "evidence.conformance.artifactId",
407
+ errors
408
+ );
409
+ if (evidence.conformance.status !== "verified" && evidence.conformance.status !== "failed") {
410
+ errors.push({
411
+ path: "evidence.conformance.status",
412
+ message: 'evidence.conformance.status must be "verified" or "failed".'
413
+ });
414
+ }
415
+ }
416
+ if (!isRecord(evidence.receipts)) {
417
+ errors.push({
418
+ path: "evidence.receipts",
419
+ message: "evidence.receipts must be an object."
420
+ });
421
+ }
422
+ if (!Array.isArray(evidence.timelineEventTypes) || evidence.timelineEventTypes.some((type) => typeof type !== "string")) {
423
+ errors.push({
424
+ path: "evidence.timelineEventTypes",
425
+ message: "evidence.timelineEventTypes must be an array of strings."
426
+ });
427
+ }
428
+ if (!Array.isArray(evidence.telemetryEventTypes) || evidence.telemetryEventTypes.some((type) => typeof type !== "string")) {
429
+ errors.push({
430
+ path: "evidence.telemetryEventTypes",
431
+ message: "evidence.telemetryEventTypes must be an array of strings."
432
+ });
433
+ }
434
+ }
435
+ function validateNestedArtifacts(artifacts, errors) {
436
+ if (!isRecord(artifacts)) {
437
+ errors.push({
438
+ path: "artifacts",
439
+ message: "artifacts must be an object."
440
+ });
441
+ return;
442
+ }
443
+ const catalogValidation = validateProviderCatalogArtifact(artifacts.catalog);
444
+ for (const error of catalogValidation.errors) {
445
+ errors.push({
446
+ path: `artifacts.catalog.${error.path}`,
447
+ message: error.message
448
+ });
449
+ }
450
+ const conformanceValidation = validateProviderConformanceArtifact(
451
+ artifacts.conformance
452
+ );
453
+ for (const error of conformanceValidation.errors) {
454
+ errors.push({
455
+ path: `artifacts.conformance.${error.path}`,
456
+ message: error.message
457
+ });
458
+ }
459
+ if (isRecord(artifacts.catalog) && isRecord(artifacts.conformance) && isRecord(artifacts.catalog.provider) && isRecord(artifacts.conformance.provider) && artifacts.catalog.provider.id !== artifacts.conformance.provider.id) {
460
+ errors.push({
461
+ path: "artifacts",
462
+ message: "catalog and conformance artifacts must reference the same provider id."
463
+ });
464
+ }
465
+ }
466
+ function validateHashes(dossier, errors) {
467
+ if (!isRecord(dossier.hashes)) {
468
+ errors.push({
469
+ path: "hashes",
470
+ message: "hashes must be an object."
471
+ });
472
+ return;
473
+ }
474
+ for (const field of [
475
+ "catalogArtifact",
476
+ "conformanceArtifact",
477
+ "readiness",
478
+ "dossier"
479
+ ]) {
480
+ const value = dossier.hashes[field];
481
+ if (typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value)) {
482
+ errors.push({
483
+ path: `hashes.${field}`,
484
+ message: `${field} hash must be a sha256 hex string.`
485
+ });
486
+ }
487
+ }
488
+ if (!isRecord(dossier.artifacts) || !isRecord(dossier.readiness) || errors.some((error) => error.path.startsWith("hashes."))) {
489
+ return;
490
+ }
491
+ const expectedHashes = {
492
+ catalogArtifact: hashStableJson(dossier.artifacts.catalog),
493
+ conformanceArtifact: hashStableJson(dossier.artifacts.conformance),
494
+ readiness: hashStableJson(dossier.readiness),
495
+ dossier: ""
496
+ };
497
+ const expectedDossierHash = hashDossierContent({
498
+ ...dossier,
499
+ hashes: expectedHashes
500
+ });
501
+ for (const [field, expected] of Object.entries({
502
+ ...expectedHashes,
503
+ dossier: expectedDossierHash
504
+ })) {
505
+ if (dossier.hashes[field] !== expected) {
506
+ errors.push({
507
+ path: `hashes.${field}`,
508
+ message: `${field} hash does not match dossier content.`
509
+ });
510
+ }
511
+ }
512
+ }
513
+ function sanitizeDossierOutput(value, forbiddenOutputValues) {
514
+ const forbiddenValues = forbiddenOutputValues.filter((entry) => entry.length > 0);
515
+ return redactX402Secrets(
516
+ replaceForbiddenValues(value, forbiddenValues, /* @__PURE__ */ new WeakSet())
517
+ );
518
+ }
519
+ function replaceForbiddenValues(value, forbiddenValues, seen) {
520
+ if (typeof value === "string") {
521
+ return forbiddenValues.reduce(
522
+ (current, forbidden) => current.split(forbidden).join("[REDACTED]"),
523
+ value
524
+ );
525
+ }
526
+ if (value === null || typeof value !== "object" || value instanceof Date) {
527
+ return value;
528
+ }
529
+ if (seen.has(value)) {
530
+ return "[Circular]";
531
+ }
532
+ seen.add(value);
533
+ if (Array.isArray(value)) {
534
+ const entries2 = value.map(
535
+ (entry) => replaceForbiddenValues(entry, forbiddenValues, seen)
536
+ );
537
+ seen.delete(value);
538
+ return entries2;
539
+ }
540
+ const entries = Object.fromEntries(
541
+ Object.entries(value).map(([key, entry]) => [
542
+ key,
543
+ replaceForbiddenValues(entry, forbiddenValues, seen)
544
+ ])
545
+ );
546
+ seen.delete(value);
547
+ return entries;
548
+ }
549
+ function cloneSerializable(value) {
550
+ if (value === void 0) {
551
+ return value;
552
+ }
553
+ return JSON.parse(JSON.stringify(value));
554
+ }
555
+ function hashStableJson(value) {
556
+ return createHash("sha256").update(stableStringify(value)).digest("hex");
557
+ }
558
+ function hashDossierContent(dossier) {
559
+ return hashStableJson(dossier);
560
+ }
561
+ function stableStringify(value) {
562
+ if (value === null || typeof value !== "object") {
563
+ return JSON.stringify(value);
564
+ }
565
+ if (Array.isArray(value)) {
566
+ return `[${value.map((entry) => stableStringify(entry)).join(",")}]`;
567
+ }
568
+ const entries = Object.entries(value).filter(([, entry]) => entry !== void 0).sort(([left], [right]) => left.localeCompare(right));
569
+ return `{${entries.map(([key, entry]) => `${JSON.stringify(key)}:${stableStringify(entry)}`).join(",")}}`;
570
+ }
571
+ function uniqueStrings(values) {
572
+ return [...new Set(values)].sort((left, right) => left.localeCompare(right));
573
+ }
574
+ function formatInlineList(values) {
575
+ return values.length > 0 ? values.join(", ") : "none";
576
+ }
577
+ function isRecord(value) {
578
+ return typeof value === "object" && value !== null && !Array.isArray(value);
579
+ }
580
+ function validateNonEmptyString(value, path, errors) {
581
+ if (typeof value !== "string" || value.length === 0) {
582
+ errors.push({
583
+ path,
584
+ message: `${path} must be a non-empty string.`
585
+ });
586
+ }
587
+ }
588
+ function validateIsoTimestamp(value, path, errors) {
589
+ if (typeof value !== "string" || Number.isNaN(Date.parse(value))) {
590
+ errors.push({
591
+ path,
592
+ message: `${path} must be an ISO timestamp.`
593
+ });
594
+ }
595
+ }
596
+ function formatValidationErrors(errors) {
597
+ return errors.map((error) => `${error.path}: ${error.message}`).join("; ");
598
+ }
599
+
600
+ export {
601
+ PROVIDER_ONBOARDING_DOSSIER_SCHEMA_VERSION,
602
+ createProviderOnboardingDossier,
603
+ validateProviderOnboardingDossier,
604
+ assertProviderOnboardingDossier,
605
+ formatProviderOnboardingDossier
606
+ };
607
+ //# sourceMappingURL=chunk-TDOBAMYM.js.map