@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,2978 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // src/cli/providerDossierCheckCli.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/errors.ts
46
+ var ProbeMeshError = class extends Error {
47
+ code;
48
+ status = "failed";
49
+ capability;
50
+ provider;
51
+ callId;
52
+ receiptRefs;
53
+ safety;
54
+ timeline;
55
+ retrySafety;
56
+ attempt;
57
+ route;
58
+ cause;
59
+ constructor(options) {
60
+ super(options.message);
61
+ this.name = "ProbeMeshError";
62
+ this.code = options.code;
63
+ this.capability = options.capability;
64
+ this.provider = options.provider;
65
+ this.callId = options.callId;
66
+ this.receiptRefs = options.receiptRefs;
67
+ this.safety = options.safety;
68
+ this.timeline = options.timeline;
69
+ this.retrySafety = options.retrySafety;
70
+ this.attempt = options.attempt;
71
+ this.route = options.route;
72
+ this.cause = options.cause;
73
+ }
74
+ toJSON() {
75
+ return {
76
+ name: this.name,
77
+ code: this.code,
78
+ message: this.message,
79
+ status: this.status,
80
+ capability: this.capability,
81
+ provider: this.provider,
82
+ callId: this.callId,
83
+ receiptRefs: this.receiptRefs,
84
+ safety: this.safety,
85
+ timeline: this.timeline,
86
+ retrySafety: this.retrySafety,
87
+ attempt: this.attempt,
88
+ route: this.route
89
+ };
90
+ }
91
+ };
92
+
93
+ // src/paymentOptions.ts
94
+ function resolveProviderPaymentOption(input) {
95
+ const options = getProviderPaymentOptions(input);
96
+ const candidates = options.filter((option) => optionSupportsCapability(option, input.capability)).map((option, index) => ({
97
+ option,
98
+ index,
99
+ cost: pricingToCost(resolvePaymentOptionPricing(option, input.capability) ?? resolvePricing(input.pricing, input.capability)),
100
+ receiptTypes: option.receiptTypes ?? []
101
+ }));
102
+ const filtered = candidates.filter(
103
+ ({ option, receiptTypes }) => optionMatchesPaymentPreferences(option, receiptTypes, input.paymentPreferences)
104
+ );
105
+ if (filtered.length === 0) {
106
+ return {
107
+ options,
108
+ reason: createNoPaymentOptionReason(input, candidates.length)
109
+ };
110
+ }
111
+ const selected = choosePaymentOption(
112
+ filtered,
113
+ input.paymentPreferences,
114
+ input.paymentStrategy
115
+ );
116
+ return {
117
+ options,
118
+ selection: {
119
+ providerId: input.providerId,
120
+ optionId: selected.option.id,
121
+ protocolMode: selected.option.protocolMode,
122
+ cost: selected.cost,
123
+ receiptTypes: [...selected.receiptTypes],
124
+ score: selected.score,
125
+ scoreReasons: [...selected.scoreReasons],
126
+ metadata: cloneSerializable(selected.option.metadata)
127
+ }
128
+ };
129
+ }
130
+ function getProviderPaymentOptions(input) {
131
+ if (input.paymentOptions && input.paymentOptions.length > 0) {
132
+ return cloneSerializable(input.paymentOptions);
133
+ }
134
+ return [
135
+ {
136
+ id: "default",
137
+ protocolMode: input.providerMode ?? "local",
138
+ capabilities: [...input.capabilities],
139
+ ...input.pricing !== void 0 ? { pricing: cloneSerializable(input.pricing) } : {},
140
+ receiptTypes: [...input.defaultReceiptTypes ?? []]
141
+ }
142
+ ];
143
+ }
144
+ function validateProviderPaymentOptions(paymentOptions, path, capabilities, errors) {
145
+ if (paymentOptions === void 0) {
146
+ return;
147
+ }
148
+ if (!Array.isArray(paymentOptions) || paymentOptions.length === 0) {
149
+ errors.push({
150
+ path,
151
+ message: "paymentOptions must be a non-empty array when provided."
152
+ });
153
+ return;
154
+ }
155
+ const seen = /* @__PURE__ */ new Set();
156
+ paymentOptions.forEach((option, index) => {
157
+ const optionPath = `${path}.${index}`;
158
+ if (!isRecord(option)) {
159
+ errors.push({
160
+ path: optionPath,
161
+ message: "payment option must be an object."
162
+ });
163
+ return;
164
+ }
165
+ validateNonEmptyString(option.id, `${optionPath}.id`, errors);
166
+ validateNonEmptyString(option.protocolMode, `${optionPath}.protocolMode`, errors);
167
+ if (typeof option.id === "string") {
168
+ if (seen.has(option.id)) {
169
+ errors.push({
170
+ path: `${optionPath}.id`,
171
+ message: `duplicate payment option "${option.id}".`
172
+ });
173
+ }
174
+ seen.add(option.id);
175
+ }
176
+ if (option.capabilities !== void 0) {
177
+ validateStringArray(option.capabilities, `${optionPath}.capabilities`, errors);
178
+ if (Array.isArray(option.capabilities)) {
179
+ for (const capability of option.capabilities) {
180
+ if (typeof capability === "string" && capability.length > 0 && !capabilities.includes(capability)) {
181
+ errors.push({
182
+ path: `${optionPath}.capabilities`,
183
+ message: `payment option capability "${capability}" is not declared by the provider.`
184
+ });
185
+ }
186
+ }
187
+ }
188
+ }
189
+ if (option.pricing !== void 0) {
190
+ validatePricingDeclaration(option.pricing, `${optionPath}.pricing`, errors);
191
+ }
192
+ if (option.receiptTypes !== void 0) {
193
+ if (!Array.isArray(option.receiptTypes) || option.receiptTypes.some((receiptType) => !isReceiptType(receiptType))) {
194
+ errors.push({
195
+ path: `${optionPath}.receiptTypes`,
196
+ message: "payment option receiptTypes must contain known receipt types."
197
+ });
198
+ }
199
+ }
200
+ if (option.metadata !== void 0 && !isRecord(option.metadata)) {
201
+ errors.push({
202
+ path: `${optionPath}.metadata`,
203
+ message: "payment option metadata must be an object when provided."
204
+ });
205
+ }
206
+ });
207
+ }
208
+ function validatePaymentPreferences(paymentPreferences, capability) {
209
+ if (paymentPreferences === void 0) {
210
+ return;
211
+ }
212
+ if (!isRecord(paymentPreferences)) {
213
+ throw new ProbeMeshError({
214
+ code: "invalid_request",
215
+ message: "paymentPreferences must be an object when provided.",
216
+ capability
217
+ });
218
+ }
219
+ validatePreferenceStringArray(
220
+ paymentPreferences.allowedProtocols,
221
+ "allowedProtocols",
222
+ capability
223
+ );
224
+ validatePreferenceStringArray(
225
+ paymentPreferences.preferredProtocols,
226
+ "preferredProtocols",
227
+ capability
228
+ );
229
+ validatePreferenceStringArray(
230
+ paymentPreferences.blockedProtocols,
231
+ "blockedProtocols",
232
+ capability
233
+ );
234
+ validatePreferenceStringArray(
235
+ paymentPreferences.allowedPaymentOptions,
236
+ "allowedPaymentOptions",
237
+ capability
238
+ );
239
+ validatePreferenceStringArray(
240
+ paymentPreferences.preferredPaymentOptions,
241
+ "preferredPaymentOptions",
242
+ capability
243
+ );
244
+ validatePreferenceStringArray(
245
+ paymentPreferences.blockedPaymentOptions,
246
+ "blockedPaymentOptions",
247
+ capability
248
+ );
249
+ if (paymentPreferences.requiredReceiptTypes !== void 0 && (!Array.isArray(paymentPreferences.requiredReceiptTypes) || paymentPreferences.requiredReceiptTypes.some((receiptType) => !isReceiptType(receiptType)))) {
250
+ throw new ProbeMeshError({
251
+ code: "invalid_request",
252
+ message: "paymentPreferences.requiredReceiptTypes must contain known receipt types.",
253
+ capability
254
+ });
255
+ }
256
+ }
257
+ function validatePaymentStrategy(paymentStrategy, capability) {
258
+ if (paymentStrategy === void 0) {
259
+ return;
260
+ }
261
+ if (!isRecord(paymentStrategy)) {
262
+ throw new ProbeMeshError({
263
+ code: "invalid_request",
264
+ message: "paymentStrategy must be an object when provided.",
265
+ capability
266
+ });
267
+ }
268
+ if (!isPaymentStrategyMode(paymentStrategy.mode)) {
269
+ throw new ProbeMeshError({
270
+ code: "invalid_request",
271
+ message: 'paymentStrategy.mode must be one of "provider_order", "lowest_cost", "preferred_protocol", or "receipt_coverage".',
272
+ capability
273
+ });
274
+ }
275
+ if (paymentStrategy.preferredReceiptTypes !== void 0 && (!Array.isArray(paymentStrategy.preferredReceiptTypes) || paymentStrategy.preferredReceiptTypes.some(
276
+ (receiptType) => !isReceiptType(receiptType)
277
+ ))) {
278
+ throw new ProbeMeshError({
279
+ code: "invalid_request",
280
+ message: "paymentStrategy.preferredReceiptTypes must contain known receipt types.",
281
+ capability
282
+ });
283
+ }
284
+ }
285
+ function mergePaymentPreferences(first, second) {
286
+ if (!first && !second) {
287
+ return void 0;
288
+ }
289
+ return compactPaymentPreferences({
290
+ allowedProtocols: intersectArrays(first?.allowedProtocols, second?.allowedProtocols),
291
+ preferredProtocols: second?.preferredProtocols ?? first?.preferredProtocols,
292
+ blockedProtocols: unionArrays(first?.blockedProtocols, second?.blockedProtocols),
293
+ allowedPaymentOptions: intersectArrays(
294
+ first?.allowedPaymentOptions,
295
+ second?.allowedPaymentOptions
296
+ ),
297
+ preferredPaymentOptions: second?.preferredPaymentOptions ?? first?.preferredPaymentOptions,
298
+ blockedPaymentOptions: unionArrays(
299
+ first?.blockedPaymentOptions,
300
+ second?.blockedPaymentOptions
301
+ ),
302
+ requiredReceiptTypes: unionArrays(
303
+ first?.requiredReceiptTypes,
304
+ second?.requiredReceiptTypes
305
+ )
306
+ });
307
+ }
308
+ function optionSupportsCapability(option, capability) {
309
+ return !option.capabilities || option.capabilities.includes(capability);
310
+ }
311
+ function optionMatchesPaymentPreferences(option, receiptTypes, preferences) {
312
+ if (!preferences) {
313
+ return true;
314
+ }
315
+ if (preferences.allowedProtocols && !preferences.allowedProtocols.includes(option.protocolMode)) {
316
+ return false;
317
+ }
318
+ if (preferences.blockedProtocols?.includes(option.protocolMode)) {
319
+ return false;
320
+ }
321
+ if (preferences.allowedPaymentOptions && !preferences.allowedPaymentOptions.includes(option.id)) {
322
+ return false;
323
+ }
324
+ if (preferences.blockedPaymentOptions?.includes(option.id)) {
325
+ return false;
326
+ }
327
+ const receiptSet = new Set(receiptTypes);
328
+ return (preferences.requiredReceiptTypes ?? []).every(
329
+ (receiptType) => receiptSet.has(receiptType)
330
+ );
331
+ }
332
+ function choosePaymentOption(candidates, preferences, strategy) {
333
+ const mode = strategy?.mode ?? "provider_order";
334
+ const ranked = [...candidates].sort(
335
+ (left, right) => comparePaymentOptions(left, right, preferences, strategy)
336
+ );
337
+ return ranked.map((candidate, rank) => ({
338
+ ...candidate,
339
+ score: rank,
340
+ scoreReasons: createScoreReasons(candidate, preferences, strategy, mode)
341
+ }))[0];
342
+ }
343
+ function preferenceIndex(preferences, value) {
344
+ const index = preferences.indexOf(value);
345
+ return index === -1 ? Number.MAX_SAFE_INTEGER : index;
346
+ }
347
+ function comparePaymentOptions(left, right, preferences, strategy) {
348
+ switch (strategy?.mode ?? "provider_order") {
349
+ case "lowest_cost":
350
+ return compareCost(left, right) || left.index - right.index;
351
+ case "preferred_protocol":
352
+ return comparePreferredProtocol(left, right, preferences) || compareCost(left, right) || left.index - right.index;
353
+ case "receipt_coverage":
354
+ return compareReceiptCoverage(left, right, preferences, strategy) || comparePreferredProtocol(left, right, preferences) || compareCost(left, right) || left.index - right.index;
355
+ case "provider_order":
356
+ return compareProviderOrder(left, right, preferences);
357
+ }
358
+ }
359
+ function compareProviderOrder(left, right, preferences) {
360
+ const optionPreference = preferences?.preferredPaymentOptions ?? [];
361
+ const protocolPreference = preferences?.preferredProtocols ?? [];
362
+ const optionPreferenceDelta = preferenceIndex(optionPreference, left.option.id) - preferenceIndex(optionPreference, right.option.id);
363
+ if (optionPreferenceDelta !== 0) {
364
+ return optionPreferenceDelta;
365
+ }
366
+ const protocolPreferenceDelta = preferenceIndex(protocolPreference, left.option.protocolMode) - preferenceIndex(protocolPreference, right.option.protocolMode);
367
+ if (protocolPreferenceDelta !== 0) {
368
+ return protocolPreferenceDelta;
369
+ }
370
+ return left.index - right.index;
371
+ }
372
+ function comparePreferredProtocol(left, right, preferences) {
373
+ const protocolPreference = preferences?.preferredProtocols ?? [];
374
+ return preferenceIndex(protocolPreference, left.option.protocolMode) - preferenceIndex(protocolPreference, right.option.protocolMode);
375
+ }
376
+ function compareCost(left, right) {
377
+ const leftCost = costSortValue(left.cost);
378
+ const rightCost = costSortValue(right.cost);
379
+ if (leftCost === rightCost) {
380
+ return 0;
381
+ }
382
+ return leftCost < rightCost ? -1 : 1;
383
+ }
384
+ function compareReceiptCoverage(left, right, preferences, strategy) {
385
+ return receiptCoverage(right, preferences, strategy) - receiptCoverage(left, preferences, strategy);
386
+ }
387
+ function receiptCoverage(candidate, preferences, strategy) {
388
+ const desiredReceiptTypes = strategy?.preferredReceiptTypes ?? preferences?.requiredReceiptTypes ?? [];
389
+ const receiptSet = new Set(candidate.receiptTypes);
390
+ if (desiredReceiptTypes.length > 0) {
391
+ return desiredReceiptTypes.filter((receiptType) => receiptSet.has(receiptType)).length;
392
+ }
393
+ return receiptSet.size;
394
+ }
395
+ function costSortValue(cost) {
396
+ return cost?.amountUsd ?? Number.POSITIVE_INFINITY;
397
+ }
398
+ function createScoreReasons(candidate, preferences, strategy, mode) {
399
+ const reasons = [`strategy:${mode}`];
400
+ if (mode === "provider_order") {
401
+ const preferredOptionIndex = preferenceIndex(
402
+ preferences?.preferredPaymentOptions ?? [],
403
+ candidate.option.id
404
+ );
405
+ const preferredProtocolIndex = preferenceIndex(
406
+ preferences?.preferredProtocols ?? [],
407
+ candidate.option.protocolMode
408
+ );
409
+ if (preferredOptionIndex !== Number.MAX_SAFE_INTEGER) {
410
+ reasons.push(`preferred_option:${candidate.option.id}`);
411
+ } else if (preferredProtocolIndex !== Number.MAX_SAFE_INTEGER) {
412
+ reasons.push(`preferred_protocol:${candidate.option.protocolMode}`);
413
+ } else {
414
+ reasons.push(`provider_order:${candidate.index}`);
415
+ }
416
+ }
417
+ if (mode === "lowest_cost" || mode === "preferred_protocol" || mode === "receipt_coverage") {
418
+ reasons.push(
419
+ candidate.cost ? `cost:${candidate.cost.amountUsd}` : "cost:unknown"
420
+ );
421
+ }
422
+ if (mode === "preferred_protocol") {
423
+ reasons.push(
424
+ isPreferredProtocol(candidate, preferences) ? `preferred_protocol:${candidate.option.protocolMode}` : `protocol:${candidate.option.protocolMode}`
425
+ );
426
+ }
427
+ if (mode === "receipt_coverage") {
428
+ const desiredReceiptTypes = strategy?.preferredReceiptTypes ?? preferences?.requiredReceiptTypes ?? [];
429
+ reasons.push(
430
+ desiredReceiptTypes.length > 0 ? `receipt_coverage:${receiptCoverage(candidate, preferences, strategy)}/${desiredReceiptTypes.length}` : `receipt_coverage:${candidate.receiptTypes.length}`
431
+ );
432
+ if (isPreferredProtocol(candidate, preferences)) {
433
+ reasons.push(`preferred_protocol:${candidate.option.protocolMode}`);
434
+ }
435
+ }
436
+ return reasons;
437
+ }
438
+ function isPreferredProtocol(candidate, preferences) {
439
+ return preferences?.preferredProtocols?.includes(candidate.option.protocolMode) ?? false;
440
+ }
441
+ function createNoPaymentOptionReason(input, capabilityCandidateCount) {
442
+ if (capabilityCandidateCount === 0) {
443
+ return `Provider "${input.providerId}" has no payment option for capability "${input.capability}".`;
444
+ }
445
+ return `Provider "${input.providerId}" has no payment option matching paymentPreferences for capability "${input.capability}".`;
446
+ }
447
+ function resolvePaymentOptionPricing(option, capability) {
448
+ return resolvePricing(option.pricing, capability);
449
+ }
450
+ function resolvePricing(pricing, capability) {
451
+ if (!pricing) {
452
+ return void 0;
453
+ }
454
+ if (isPricing(pricing)) {
455
+ return pricing;
456
+ }
457
+ const capabilityPricing = pricing[capability];
458
+ return isPricing(capabilityPricing) ? capabilityPricing : void 0;
459
+ }
460
+ function pricingToCost(pricing) {
461
+ if (!pricing) {
462
+ return void 0;
463
+ }
464
+ return {
465
+ amountUsd: pricing.amountUsd,
466
+ currency: pricing.currency ?? "USD",
467
+ unit: pricing.unit
468
+ };
469
+ }
470
+ function validatePreferenceStringArray(value, field, capability) {
471
+ if (value !== void 0 && (!Array.isArray(value) || value.some((entry) => typeof entry !== "string" || entry.length === 0))) {
472
+ throw new ProbeMeshError({
473
+ code: "invalid_request",
474
+ message: `paymentPreferences.${field} must be an array of non-empty strings when provided.`,
475
+ capability
476
+ });
477
+ }
478
+ }
479
+ function validatePricingDeclaration(pricing, path, errors) {
480
+ if (!isRecord(pricing)) {
481
+ errors.push({
482
+ path,
483
+ message: "payment option pricing must be an object."
484
+ });
485
+ return;
486
+ }
487
+ if (isPricing(pricing)) {
488
+ validatePricing(pricing, path, errors);
489
+ return;
490
+ }
491
+ for (const [capability, capabilityPricing] of Object.entries(pricing)) {
492
+ validatePricing(capabilityPricing, `${path}.${capability}`, errors);
493
+ }
494
+ }
495
+ function validatePricing(pricing, path, errors) {
496
+ if (!isRecord(pricing)) {
497
+ errors.push({
498
+ path,
499
+ message: "payment option pricing entry must be an object."
500
+ });
501
+ return;
502
+ }
503
+ validateNonEmptyString(pricing.unit, `${path}.unit`, errors);
504
+ if (typeof pricing.amountUsd !== "number" || !Number.isFinite(pricing.amountUsd) || pricing.amountUsd < 0) {
505
+ errors.push({
506
+ path: `${path}.amountUsd`,
507
+ message: "amountUsd must be a non-negative number."
508
+ });
509
+ }
510
+ if (pricing.currency !== void 0 && typeof pricing.currency !== "string") {
511
+ errors.push({
512
+ path: `${path}.currency`,
513
+ message: "currency must be a string when provided."
514
+ });
515
+ }
516
+ }
517
+ function validateStringArray(value, path, errors) {
518
+ if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string" || entry.length === 0)) {
519
+ errors.push({
520
+ path,
521
+ message: `${path} must be an array of non-empty strings.`
522
+ });
523
+ }
524
+ }
525
+ function validateNonEmptyString(value, path, errors) {
526
+ if (typeof value !== "string" || value.length === 0) {
527
+ errors.push({
528
+ path,
529
+ message: `${path} must be a non-empty string.`
530
+ });
531
+ }
532
+ }
533
+ function isPricing(value) {
534
+ return isRecord(value) && typeof value.unit === "string" && value.unit.length > 0 && typeof value.amountUsd === "number" && Number.isFinite(value.amountUsd) && value.amountUsd >= 0 && (value.currency === void 0 || typeof value.currency === "string");
535
+ }
536
+ function isReceiptType(value) {
537
+ return value === "payment_proof" || value === "settlement_confirmation" || value === "provider_delivery" || value === "provider_response_evidence" || value === "authorization_decision";
538
+ }
539
+ function isPaymentStrategyMode(value) {
540
+ return value === "provider_order" || value === "lowest_cost" || value === "preferred_protocol" || value === "receipt_coverage";
541
+ }
542
+ function compactPaymentPreferences(preferences) {
543
+ const entries = Object.entries(preferences).filter(
544
+ ([, value]) => value !== void 0 && (!Array.isArray(value) || value.length > 0)
545
+ );
546
+ return entries.length > 0 ? Object.fromEntries(entries) : void 0;
547
+ }
548
+ function intersectArrays(first, second) {
549
+ if (first === void 0) {
550
+ return second === void 0 ? void 0 : [...second];
551
+ }
552
+ if (second === void 0) {
553
+ return [...first];
554
+ }
555
+ const secondValues = new Set(second);
556
+ return first.filter((value) => secondValues.has(value));
557
+ }
558
+ function unionArrays(first, second) {
559
+ const values = [...first ?? [], ...second ?? []];
560
+ return values.length > 0 ? [...new Set(values)] : void 0;
561
+ }
562
+ function isRecord(value) {
563
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
564
+ }
565
+ function cloneSerializable(value) {
566
+ if (value === void 0) {
567
+ return value;
568
+ }
569
+ return JSON.parse(JSON.stringify(value));
570
+ }
571
+
572
+ // src/providerKit/manifest.ts
573
+ var JSON_SCHEMA_HINT_KEYS = /* @__PURE__ */ new Set([
574
+ "$schema",
575
+ "$id",
576
+ "type",
577
+ "properties",
578
+ "required",
579
+ "items",
580
+ "enum",
581
+ "description",
582
+ "additionalProperties",
583
+ "oneOf",
584
+ "anyOf",
585
+ "allOf"
586
+ ]);
587
+ function validateProviderManifest(manifest) {
588
+ const errors = [];
589
+ if (!isRecord2(manifest)) {
590
+ return {
591
+ valid: false,
592
+ errors: [
593
+ {
594
+ path: "$",
595
+ message: "Provider manifest must be an object."
596
+ }
597
+ ]
598
+ };
599
+ }
600
+ validateNonEmptyString2(manifest.id, "id", errors);
601
+ validateNonEmptyString2(manifest.displayName, "displayName", errors);
602
+ validateCapabilityList(manifest.capabilities, errors);
603
+ validateNonEmptyString2(manifest.protocolMode, "protocolMode", errors);
604
+ validateProviderPaymentOptions(
605
+ manifest.paymentOptions,
606
+ "paymentOptions",
607
+ Array.isArray(manifest.capabilities) ? manifest.capabilities : [],
608
+ errors
609
+ );
610
+ validatePricingDeclaration2(
611
+ manifest.pricing,
612
+ "pricing",
613
+ manifest.capabilities,
614
+ errors
615
+ );
616
+ validateSchemaDeclaration(
617
+ manifest.inputSchema,
618
+ "inputSchema",
619
+ manifest.capabilities,
620
+ errors
621
+ );
622
+ validateSchemaDeclaration(
623
+ manifest.outputSchema,
624
+ "outputSchema",
625
+ manifest.capabilities,
626
+ errors
627
+ );
628
+ validateReceipts(manifest.receipts, errors);
629
+ if (manifest.limits !== void 0) {
630
+ validateLimits(manifest.limits, errors);
631
+ }
632
+ return {
633
+ valid: errors.length === 0,
634
+ errors
635
+ };
636
+ }
637
+ function isSharedJsonSchemaLike(value) {
638
+ if (!isRecord2(value)) {
639
+ return false;
640
+ }
641
+ return Object.keys(value).some((key) => JSON_SCHEMA_HINT_KEYS.has(key));
642
+ }
643
+ function isSharedPricing(value) {
644
+ return isRecord2(value) && typeof value.unit === "string" && value.unit.length > 0 && typeof value.amountUsd === "number";
645
+ }
646
+ function validateCapabilityList(capabilities, errors) {
647
+ if (!Array.isArray(capabilities) || capabilities.length === 0) {
648
+ errors.push({
649
+ path: "capabilities",
650
+ message: "capabilities must be a non-empty array."
651
+ });
652
+ return;
653
+ }
654
+ const seen = /* @__PURE__ */ new Set();
655
+ capabilities.forEach((capability, index) => {
656
+ if (typeof capability !== "string" || capability.length === 0) {
657
+ errors.push({
658
+ path: `capabilities.${index}`,
659
+ message: "capability ids must be non-empty strings."
660
+ });
661
+ return;
662
+ }
663
+ if (seen.has(capability)) {
664
+ errors.push({
665
+ path: `capabilities.${index}`,
666
+ message: `duplicate capability "${capability}".`
667
+ });
668
+ }
669
+ seen.add(capability);
670
+ });
671
+ }
672
+ function validatePricingDeclaration2(pricing, path, capabilities, errors) {
673
+ if (!isRecord2(pricing)) {
674
+ errors.push({
675
+ path,
676
+ message: "pricing must be an object."
677
+ });
678
+ return;
679
+ }
680
+ if (isSharedPricing(pricing)) {
681
+ validatePricing2(pricing, path, errors);
682
+ return;
683
+ }
684
+ if (!Array.isArray(capabilities)) {
685
+ return;
686
+ }
687
+ for (const capability of capabilities) {
688
+ if (typeof capability !== "string" || capability.length === 0) {
689
+ continue;
690
+ }
691
+ validatePricing2(pricing[capability], `${path}.${capability}`, errors);
692
+ }
693
+ }
694
+ function validatePricing2(pricing, path, errors) {
695
+ if (!isRecord2(pricing)) {
696
+ errors.push({
697
+ path,
698
+ message: "pricing entry must be an object."
699
+ });
700
+ return;
701
+ }
702
+ validateNonEmptyString2(pricing.unit, `${path}.unit`, errors);
703
+ if (typeof pricing.amountUsd !== "number" || !Number.isFinite(pricing.amountUsd) || pricing.amountUsd < 0) {
704
+ errors.push({
705
+ path: `${path}.amountUsd`,
706
+ message: "amountUsd must be a non-negative number."
707
+ });
708
+ }
709
+ if (pricing.currency !== void 0 && typeof pricing.currency !== "string") {
710
+ errors.push({
711
+ path: `${path}.currency`,
712
+ message: "currency must be a string when provided."
713
+ });
714
+ }
715
+ }
716
+ function validateSchemaDeclaration(schema, path, capabilities, errors) {
717
+ if (!isRecord2(schema)) {
718
+ errors.push({
719
+ path,
720
+ message: `${path} must be an object.`
721
+ });
722
+ return;
723
+ }
724
+ if (isSharedJsonSchemaLike(schema)) {
725
+ validateSchemaLike(schema, path, errors);
726
+ return;
727
+ }
728
+ if (!Array.isArray(capabilities)) {
729
+ return;
730
+ }
731
+ for (const capability of capabilities) {
732
+ if (typeof capability !== "string" || capability.length === 0) {
733
+ continue;
734
+ }
735
+ validateSchemaLike(schema[capability], `${path}.${capability}`, errors);
736
+ }
737
+ }
738
+ function validateSchemaLike(schema, path, errors) {
739
+ if (!isRecord2(schema)) {
740
+ errors.push({
741
+ path,
742
+ message: "schema entry must be an object."
743
+ });
744
+ return;
745
+ }
746
+ if (schema.type !== void 0 && typeof schema.type !== "string") {
747
+ errors.push({
748
+ path: `${path}.type`,
749
+ message: "schema type must be a string when provided."
750
+ });
751
+ }
752
+ if (schema.properties !== void 0 && !isRecord2(schema.properties)) {
753
+ errors.push({
754
+ path: `${path}.properties`,
755
+ message: "schema properties must be an object when provided."
756
+ });
757
+ }
758
+ if (schema.required !== void 0 && (!Array.isArray(schema.required) || schema.required.some((field) => typeof field !== "string"))) {
759
+ errors.push({
760
+ path: `${path}.required`,
761
+ message: "schema required must be an array of strings when provided."
762
+ });
763
+ }
764
+ }
765
+ function validateReceipts(receipts, errors) {
766
+ if (!isRecord2(receipts)) {
767
+ errors.push({
768
+ path: "receipts",
769
+ message: "receipts must be an object."
770
+ });
771
+ return;
772
+ }
773
+ validateBoolean(receipts.payment, "receipts.payment", errors);
774
+ validateBoolean(receipts.delivery, "receipts.delivery", errors);
775
+ validateBoolean(
776
+ receipts.responseEvidence,
777
+ "receipts.responseEvidence",
778
+ errors
779
+ );
780
+ }
781
+ function validateLimits(limits, errors) {
782
+ if (!isRecord2(limits)) {
783
+ errors.push({
784
+ path: "limits",
785
+ message: "limits must be an object when provided."
786
+ });
787
+ return;
788
+ }
789
+ const typedLimits = limits;
790
+ if (typedLimits.maxRequestsPerMinute !== void 0 && (!Number.isFinite(typedLimits.maxRequestsPerMinute) || typedLimits.maxRequestsPerMinute <= 0)) {
791
+ errors.push({
792
+ path: "limits.maxRequestsPerMinute",
793
+ message: "maxRequestsPerMinute must be a positive number when provided."
794
+ });
795
+ }
796
+ }
797
+ function validateNonEmptyString2(value, path, errors) {
798
+ if (typeof value !== "string" || value.length === 0) {
799
+ errors.push({
800
+ path,
801
+ message: `${path} must be a non-empty string.`
802
+ });
803
+ }
804
+ }
805
+ function validateBoolean(value, path, errors) {
806
+ if (typeof value !== "boolean") {
807
+ errors.push({
808
+ path,
809
+ message: `${path} must be a boolean.`
810
+ });
811
+ }
812
+ }
813
+ function isRecord2(value) {
814
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
815
+ }
816
+
817
+ // src/protocols/x402Redaction.ts
818
+ var DEFAULT_REPLACEMENT = "[REDACTED]";
819
+ var DEFAULT_MAX_DEPTH = 12;
820
+ var PRIVATE_KEY_PATTERN = /\b0x[a-fA-F0-9]{64}\b/g;
821
+ var HEX_SIGNATURE_PATTERN = /\b0x[a-fA-F0-9]{130}\b/g;
822
+ var SECRET_FIELD_NAMES = /* @__PURE__ */ new Set([
823
+ "api-key",
824
+ "apikey",
825
+ "authorization",
826
+ "bearer",
827
+ "payment-required",
828
+ "payment-response",
829
+ "payment-signature",
830
+ "privatekey",
831
+ "signature",
832
+ "x-api-key"
833
+ ]);
834
+ function redactX402Secrets(value, options = {}) {
835
+ const replacement = options.replacement ?? DEFAULT_REPLACEMENT;
836
+ const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
837
+ const seen = /* @__PURE__ */ new WeakSet();
838
+ return redactValue(value, {
839
+ replacement,
840
+ maxDepth,
841
+ depth: 0,
842
+ seen,
843
+ key: void 0
844
+ });
845
+ }
846
+ function redactValue(value, context) {
847
+ if (context.key && shouldRedactKey(context.key)) {
848
+ return context.replacement;
849
+ }
850
+ if (typeof value === "string") {
851
+ return redactString(value, context.replacement);
852
+ }
853
+ if (value === null || typeof value !== "object" || value instanceof Date) {
854
+ return value;
855
+ }
856
+ if (context.depth >= context.maxDepth) {
857
+ return "[MaxDepth]";
858
+ }
859
+ if (context.seen.has(value)) {
860
+ return "[Circular]";
861
+ }
862
+ context.seen.add(value);
863
+ if (Array.isArray(value)) {
864
+ return value.map(
865
+ (entry) => redactValue(entry, {
866
+ ...context,
867
+ depth: context.depth + 1,
868
+ key: void 0
869
+ })
870
+ );
871
+ }
872
+ return Object.fromEntries(
873
+ Object.entries(value).map(([key, entry]) => [
874
+ key,
875
+ redactValue(entry, {
876
+ ...context,
877
+ depth: context.depth + 1,
878
+ key
879
+ })
880
+ ])
881
+ );
882
+ }
883
+ function shouldRedactKey(key) {
884
+ const normalized = key.toLowerCase().replace(/_/g, "-");
885
+ 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");
886
+ }
887
+ function redactString(value, replacement) {
888
+ return value.replace(PRIVATE_KEY_PATTERN, replacement).replace(HEX_SIGNATURE_PATTERN, replacement);
889
+ }
890
+
891
+ // src/providerCatalogArtifact.ts
892
+ var PROVIDER_CATALOG_ARTIFACT_SCHEMA_VERSION = "probemesh.provider-catalog.v1";
893
+ function validateProviderCatalogArtifact(artifact) {
894
+ const errors = [];
895
+ if (!isRecord3(artifact)) {
896
+ return {
897
+ valid: false,
898
+ errors: [
899
+ {
900
+ path: "$",
901
+ message: "Provider catalog artifact must be an object."
902
+ }
903
+ ]
904
+ };
905
+ }
906
+ if (artifact.schemaVersion !== PROVIDER_CATALOG_ARTIFACT_SCHEMA_VERSION) {
907
+ errors.push({
908
+ path: "schemaVersion",
909
+ message: `schemaVersion must be "${PROVIDER_CATALOG_ARTIFACT_SCHEMA_VERSION}".`
910
+ });
911
+ }
912
+ validateNonEmptyString3(artifact.artifactId, "artifactId", errors);
913
+ validateIsoTimestamp(artifact.generatedAt, "generatedAt", errors);
914
+ if (artifact.status !== "ready" && artifact.status !== "rejected") {
915
+ errors.push({
916
+ path: "status",
917
+ message: 'status must be "ready" or "rejected".'
918
+ });
919
+ }
920
+ const manifestValidation = validateProviderManifest(artifact.provider);
921
+ for (const manifestError of manifestValidation.errors) {
922
+ errors.push({
923
+ path: `provider.${manifestError.path}`,
924
+ message: manifestError.message
925
+ });
926
+ }
927
+ validateAcceptanceArtifact(artifact.acceptance, errors);
928
+ return {
929
+ valid: errors.length === 0,
930
+ errors
931
+ };
932
+ }
933
+ function validateAcceptanceArtifact(acceptance, errors) {
934
+ if (!isRecord3(acceptance)) {
935
+ errors.push({
936
+ path: "acceptance",
937
+ message: "acceptance must be an object."
938
+ });
939
+ return;
940
+ }
941
+ validateNonEmptyString3(acceptance.title, "acceptance.title", errors);
942
+ if (acceptance.status !== "passed" && acceptance.status !== "failed") {
943
+ errors.push({
944
+ path: "acceptance.status",
945
+ message: 'acceptance.status must be "passed" or "failed".'
946
+ });
947
+ }
948
+ if (!isRecord3(acceptance.gate)) {
949
+ errors.push({
950
+ path: "acceptance.gate",
951
+ message: "acceptance.gate must be an object."
952
+ });
953
+ } else {
954
+ if (typeof acceptance.gate.accepted !== "boolean") {
955
+ errors.push({
956
+ path: "acceptance.gate.accepted",
957
+ message: "acceptance.gate.accepted must be a boolean."
958
+ });
959
+ }
960
+ if (acceptance.gate.status !== "accepted" && acceptance.gate.status !== "rejected") {
961
+ errors.push({
962
+ path: "acceptance.gate.status",
963
+ message: 'acceptance.gate.status must be "accepted" or "rejected".'
964
+ });
965
+ }
966
+ }
967
+ validateStringArray2(
968
+ acceptance.failedChecks,
969
+ "acceptance.failedChecks",
970
+ errors
971
+ );
972
+ validateReceiptSummary(acceptance.receipts, errors);
973
+ validateStringArray2(
974
+ acceptance.timelineEventTypes,
975
+ "acceptance.timelineEventTypes",
976
+ errors
977
+ );
978
+ validateStringArray2(
979
+ acceptance.telemetryEventTypes,
980
+ "acceptance.telemetryEventTypes",
981
+ errors
982
+ );
983
+ }
984
+ function validateReceiptSummary(receipts, errors) {
985
+ if (!isRecord3(receipts)) {
986
+ errors.push({
987
+ path: "acceptance.receipts",
988
+ message: "acceptance.receipts must be an object."
989
+ });
990
+ return;
991
+ }
992
+ if (typeof receipts.total !== "number" || !Number.isFinite(receipts.total)) {
993
+ errors.push({
994
+ path: "acceptance.receipts.total",
995
+ message: "acceptance.receipts.total must be a number."
996
+ });
997
+ }
998
+ validateStringArray2(receipts.types, "acceptance.receipts.types", errors);
999
+ validateStringArray2(
1000
+ receipts.providers,
1001
+ "acceptance.receipts.providers",
1002
+ errors
1003
+ );
1004
+ for (const key of [
1005
+ "hasPaymentProof",
1006
+ "hasSettlementConfirmation",
1007
+ "hasProviderDelivery"
1008
+ ]) {
1009
+ if (typeof receipts[key] !== "boolean") {
1010
+ errors.push({
1011
+ path: `acceptance.receipts.${key}`,
1012
+ message: `acceptance.receipts.${key} must be a boolean.`
1013
+ });
1014
+ }
1015
+ }
1016
+ }
1017
+ function validateStringArray2(value, path, errors) {
1018
+ if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) {
1019
+ errors.push({
1020
+ path,
1021
+ message: `${path} must be an array of strings.`
1022
+ });
1023
+ }
1024
+ }
1025
+ function validateNonEmptyString3(value, path, errors) {
1026
+ if (typeof value !== "string" || value.length === 0) {
1027
+ errors.push({
1028
+ path,
1029
+ message: `${path} must be a non-empty string.`
1030
+ });
1031
+ }
1032
+ }
1033
+ function validateIsoTimestamp(value, path, errors) {
1034
+ if (typeof value !== "string" || Number.isNaN(Date.parse(value))) {
1035
+ errors.push({
1036
+ path,
1037
+ message: `${path} must be an ISO timestamp string.`
1038
+ });
1039
+ }
1040
+ }
1041
+ function isRecord3(value) {
1042
+ return !!value && typeof value === "object" && !Array.isArray(value);
1043
+ }
1044
+
1045
+ // src/providerCatalog.ts
1046
+ var PROVIDER_CATALOG_SCHEMA_VERSION = "probemesh.provider-catalog.index.v1";
1047
+ function validateProviderCatalog(catalog) {
1048
+ const errors = [];
1049
+ if (!isRecord4(catalog)) {
1050
+ return {
1051
+ valid: false,
1052
+ errors: [
1053
+ {
1054
+ path: "$",
1055
+ message: "Provider catalog must be an object."
1056
+ }
1057
+ ]
1058
+ };
1059
+ }
1060
+ if (catalog.schemaVersion !== PROVIDER_CATALOG_SCHEMA_VERSION) {
1061
+ errors.push({
1062
+ path: "schemaVersion",
1063
+ message: `schemaVersion must be "${PROVIDER_CATALOG_SCHEMA_VERSION}".`
1064
+ });
1065
+ }
1066
+ validateIsoTimestamp2(catalog.generatedAt, "generatedAt", errors);
1067
+ if (!Array.isArray(catalog.entries)) {
1068
+ errors.push({
1069
+ path: "entries",
1070
+ message: "entries must be an array."
1071
+ });
1072
+ } else {
1073
+ catalog.entries.forEach(
1074
+ (entry, index) => validateProviderCatalogEntry(entry, `entries.${index}`, errors)
1075
+ );
1076
+ }
1077
+ return {
1078
+ valid: errors.length === 0,
1079
+ errors
1080
+ };
1081
+ }
1082
+ function assertProviderCatalog(catalog) {
1083
+ const result = validateProviderCatalog(catalog);
1084
+ if (result.valid) {
1085
+ return;
1086
+ }
1087
+ throw new ProbeMeshError({
1088
+ code: "invalid_request",
1089
+ message: `Invalid provider catalog: ${formatValidationErrors(result.errors)}`
1090
+ });
1091
+ }
1092
+ function createProviderCatalog(options) {
1093
+ assertProviderCatalogOptions(options);
1094
+ const entries = options.artifacts.map((artifact, index) => {
1095
+ const validation = validateProviderCatalogArtifact(artifact);
1096
+ if (!validation.valid) {
1097
+ throw new ProbeMeshError({
1098
+ code: "invalid_request",
1099
+ message: `Invalid provider catalog artifact at index ${index}: ${formatValidationErrors(
1100
+ validation.errors
1101
+ )}`
1102
+ });
1103
+ }
1104
+ return createCatalogEntryFromArtifact(artifact);
1105
+ });
1106
+ const catalog = {
1107
+ schemaVersion: PROVIDER_CATALOG_SCHEMA_VERSION,
1108
+ generatedAt: options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
1109
+ entries
1110
+ };
1111
+ assertProviderCatalog(catalog);
1112
+ return catalog;
1113
+ }
1114
+ function findProviderCatalogMatches(catalog, query) {
1115
+ assertProviderCatalog(catalog);
1116
+ assertProviderCatalogQuery(query);
1117
+ const requiredStatus = query.status ?? "ready";
1118
+ const requiredReceiptTypes = query.requiredReceiptTypes ?? [];
1119
+ const providerIds = query.providerIds;
1120
+ const blockedProviderIds = new Set(query.blockedProviderIds ?? []);
1121
+ return catalog.entries.flatMap((entry) => {
1122
+ const providerId = entry.provider.id;
1123
+ if (entry.status !== requiredStatus) {
1124
+ return [];
1125
+ }
1126
+ if (!entry.provider.capabilities.includes(query.capability)) {
1127
+ return [];
1128
+ }
1129
+ if (query.protocolMode !== void 0 && entry.provider.protocolMode !== query.protocolMode) {
1130
+ return [];
1131
+ }
1132
+ if (providerIds !== void 0 && !providerIds.includes(providerId)) {
1133
+ return [];
1134
+ }
1135
+ if (blockedProviderIds.has(providerId)) {
1136
+ return [];
1137
+ }
1138
+ const paymentPreferences = mergePaymentPreferences(
1139
+ query.protocolMode ? {
1140
+ allowedProtocols: [query.protocolMode]
1141
+ } : void 0,
1142
+ query.paymentPreferences
1143
+ );
1144
+ const paymentResolution = resolveProviderPaymentOption({
1145
+ providerId,
1146
+ providerMode: entry.provider.protocolMode,
1147
+ capabilities: entry.provider.capabilities,
1148
+ capability: query.capability,
1149
+ pricing: entry.provider.pricing,
1150
+ paymentOptions: entry.provider.paymentOptions,
1151
+ paymentPreferences,
1152
+ paymentStrategy: query.paymentStrategy,
1153
+ defaultReceiptTypes: entry.acceptance.receipts.types
1154
+ });
1155
+ const cost = paymentSelectionCost(paymentResolution.selection) ?? resolveCatalogCost(entry, query.capability);
1156
+ if (query.maxCostUsd !== void 0 && (cost === void 0 || cost.amountUsd > query.maxCostUsd)) {
1157
+ return [];
1158
+ }
1159
+ if (!hasRequiredReceiptTypes(entry, requiredReceiptTypes)) {
1160
+ return [];
1161
+ }
1162
+ if (!paymentResolution.selection) {
1163
+ return [];
1164
+ }
1165
+ return [
1166
+ {
1167
+ entry,
1168
+ providerId,
1169
+ capability: query.capability,
1170
+ status: entry.status,
1171
+ cost,
1172
+ paymentSelection: paymentResolution.selection,
1173
+ reasons: createMatchReasons(
1174
+ entry,
1175
+ query,
1176
+ cost,
1177
+ paymentResolution.selection
1178
+ )
1179
+ }
1180
+ ];
1181
+ });
1182
+ }
1183
+ function summarizeProviderCatalog(catalog) {
1184
+ assertProviderCatalog(catalog);
1185
+ const providers = /* @__PURE__ */ new Set();
1186
+ const capabilities = /* @__PURE__ */ new Set();
1187
+ const protocolModes = /* @__PURE__ */ new Set();
1188
+ let readyEntries = 0;
1189
+ let rejectedEntries = 0;
1190
+ for (const entry of catalog.entries) {
1191
+ providers.add(entry.provider.id);
1192
+ protocolModes.add(entry.provider.protocolMode);
1193
+ for (const capability of entry.provider.capabilities) {
1194
+ capabilities.add(capability);
1195
+ }
1196
+ if (entry.status === "ready") {
1197
+ readyEntries += 1;
1198
+ } else {
1199
+ rejectedEntries += 1;
1200
+ }
1201
+ }
1202
+ return {
1203
+ schemaVersion: catalog.schemaVersion,
1204
+ generatedAt: catalog.generatedAt,
1205
+ totalEntries: catalog.entries.length,
1206
+ readyEntries,
1207
+ rejectedEntries,
1208
+ providers: [...providers],
1209
+ capabilities: [...capabilities],
1210
+ protocolModes: [...protocolModes]
1211
+ };
1212
+ }
1213
+ function assertProviderCatalogOptions(options) {
1214
+ if (!isRecord4(options)) {
1215
+ throw new ProbeMeshError({
1216
+ code: "invalid_request",
1217
+ message: "Provider catalog options must be an object."
1218
+ });
1219
+ }
1220
+ if (!Array.isArray(options.artifacts)) {
1221
+ throw new ProbeMeshError({
1222
+ code: "invalid_request",
1223
+ message: "Provider catalog options require an artifacts array."
1224
+ });
1225
+ }
1226
+ if (options.generatedAt !== void 0 && (typeof options.generatedAt !== "string" || Number.isNaN(Date.parse(options.generatedAt)))) {
1227
+ throw new ProbeMeshError({
1228
+ code: "invalid_request",
1229
+ message: "Provider catalog generatedAt must be an ISO timestamp."
1230
+ });
1231
+ }
1232
+ }
1233
+ function assertProviderCatalogQuery(query) {
1234
+ if (!isRecord4(query)) {
1235
+ throw new ProbeMeshError({
1236
+ code: "invalid_request",
1237
+ message: "Provider catalog query must be an object."
1238
+ });
1239
+ }
1240
+ if (typeof query.capability !== "string" || query.capability.length === 0) {
1241
+ throw new ProbeMeshError({
1242
+ code: "invalid_request",
1243
+ message: "Provider catalog query capability must be a non-empty string."
1244
+ });
1245
+ }
1246
+ if (query.protocolMode !== void 0 && (typeof query.protocolMode !== "string" || query.protocolMode.length === 0)) {
1247
+ throw new ProbeMeshError({
1248
+ code: "invalid_request",
1249
+ message: "Provider catalog query protocolMode must be a non-empty string."
1250
+ });
1251
+ }
1252
+ validatePaymentPreferences(query.paymentPreferences, query.capability);
1253
+ validatePaymentStrategy(query.paymentStrategy, query.capability);
1254
+ if (query.maxCostUsd !== void 0 && (typeof query.maxCostUsd !== "number" || !Number.isFinite(query.maxCostUsd) || query.maxCostUsd < 0)) {
1255
+ throw new ProbeMeshError({
1256
+ code: "invalid_request",
1257
+ message: "Provider catalog query maxCostUsd must be a non-negative finite number."
1258
+ });
1259
+ }
1260
+ if (query.status !== void 0 && query.status !== "ready" && query.status !== "rejected") {
1261
+ throw new ProbeMeshError({
1262
+ code: "invalid_request",
1263
+ message: 'Provider catalog query status must be "ready" or "rejected".'
1264
+ });
1265
+ }
1266
+ validateQueryStringArray(query.providerIds, "providerIds");
1267
+ validateQueryStringArray(query.blockedProviderIds, "blockedProviderIds");
1268
+ if (query.requiredReceiptTypes !== void 0 && (!Array.isArray(query.requiredReceiptTypes) || query.requiredReceiptTypes.some((receiptType) => !isReceiptType2(receiptType)))) {
1269
+ throw new ProbeMeshError({
1270
+ code: "invalid_request",
1271
+ message: "Provider catalog query requiredReceiptTypes must contain known receipt types."
1272
+ });
1273
+ }
1274
+ }
1275
+ function createCatalogEntryFromArtifact(artifact) {
1276
+ return {
1277
+ artifactId: artifact.artifactId,
1278
+ generatedAt: artifact.generatedAt,
1279
+ status: artifact.status,
1280
+ provider: {
1281
+ id: artifact.provider.id,
1282
+ displayName: artifact.provider.displayName,
1283
+ capabilities: [...artifact.provider.capabilities],
1284
+ protocolMode: artifact.provider.protocolMode,
1285
+ paymentOptions: cloneSerializable2(artifact.provider.paymentOptions),
1286
+ pricing: cloneSerializable2(artifact.provider.pricing),
1287
+ receipts: cloneSerializable2(artifact.provider.receipts),
1288
+ limits: cloneSerializable2(artifact.provider.limits)
1289
+ },
1290
+ acceptance: {
1291
+ gate: cloneSerializable2(artifact.acceptance.gate),
1292
+ failedChecks: [...artifact.acceptance.failedChecks],
1293
+ receipts: cloneSerializable2(artifact.acceptance.receipts),
1294
+ safety: cloneSerializable2(artifact.acceptance.safety),
1295
+ retrySafety: cloneSerializable2(artifact.acceptance.retrySafety),
1296
+ route: cloneSerializable2(artifact.acceptance.route),
1297
+ timelineEventTypes: [...artifact.acceptance.timelineEventTypes],
1298
+ telemetryEventTypes: [...artifact.acceptance.telemetryEventTypes],
1299
+ errorCode: artifact.acceptance.errorCode
1300
+ }
1301
+ };
1302
+ }
1303
+ function resolveCatalogCost(entry, capability) {
1304
+ const pricing = entry.provider.pricing;
1305
+ if (isProbeMeshPricing(pricing)) {
1306
+ return pricingToCost2(pricing);
1307
+ }
1308
+ const capabilityPricing = pricing[capability];
1309
+ if (!isProbeMeshPricing(capabilityPricing)) {
1310
+ return void 0;
1311
+ }
1312
+ return pricingToCost2(capabilityPricing);
1313
+ }
1314
+ function pricingToCost2(pricing) {
1315
+ return {
1316
+ amountUsd: pricing.amountUsd,
1317
+ currency: pricing.currency,
1318
+ unit: pricing.unit
1319
+ };
1320
+ }
1321
+ function hasRequiredReceiptTypes(entry, requiredReceiptTypes) {
1322
+ const receiptTypes = new Set(entry.acceptance.receipts.types);
1323
+ return requiredReceiptTypes.every(
1324
+ (receiptType) => receiptTypes.has(receiptType)
1325
+ );
1326
+ }
1327
+ function createMatchReasons(entry, query, cost, paymentSelection) {
1328
+ const reasons = [
1329
+ `status:${entry.status}`,
1330
+ `capability:${query.capability}`,
1331
+ `protocol:${entry.provider.protocolMode}`
1332
+ ];
1333
+ if (query.paymentPreferences !== void 0) {
1334
+ reasons.push("payment_preferences:matched");
1335
+ }
1336
+ if (query.paymentStrategy !== void 0) {
1337
+ reasons.push(`payment_strategy:${query.paymentStrategy.mode}`);
1338
+ }
1339
+ if (paymentSelection?.score !== void 0) {
1340
+ reasons.push(`payment_score:${paymentSelection.score}`);
1341
+ }
1342
+ for (const scoreReason of paymentSelection?.scoreReasons ?? []) {
1343
+ reasons.push(`payment_score_reason:${scoreReason}`);
1344
+ }
1345
+ if (query.providerIds !== void 0) {
1346
+ reasons.push("provider:allowed");
1347
+ }
1348
+ if (query.maxCostUsd !== void 0 && cost !== void 0) {
1349
+ reasons.push(`cost:${cost.amountUsd}<=${query.maxCostUsd}`);
1350
+ }
1351
+ if ((query.requiredReceiptTypes ?? []).length > 0) {
1352
+ reasons.push(`receipts:${query.requiredReceiptTypes?.join(",")}`);
1353
+ }
1354
+ return reasons;
1355
+ }
1356
+ function paymentSelectionCost(selection) {
1357
+ return selection?.cost;
1358
+ }
1359
+ function validateQueryStringArray(value, name) {
1360
+ if (value !== void 0 && (!Array.isArray(value) || value.some((entry) => typeof entry !== "string" || entry.length === 0))) {
1361
+ throw new ProbeMeshError({
1362
+ code: "invalid_request",
1363
+ message: `Provider catalog query ${name} must be an array of non-empty strings.`
1364
+ });
1365
+ }
1366
+ }
1367
+ function isProbeMeshPricing(value) {
1368
+ return isRecord4(value) && typeof value.unit === "string" && typeof value.amountUsd === "number" && Number.isFinite(value.amountUsd) && value.amountUsd >= 0 && (value.currency === void 0 || typeof value.currency === "string");
1369
+ }
1370
+ function isReceiptType2(value) {
1371
+ return value === "payment_proof" || value === "settlement_confirmation" || value === "provider_delivery" || value === "provider_response_evidence" || value === "authorization_decision";
1372
+ }
1373
+ function cloneSerializable2(value) {
1374
+ if (value === void 0) {
1375
+ return value;
1376
+ }
1377
+ return JSON.parse(JSON.stringify(value));
1378
+ }
1379
+ function validateProviderCatalogEntry(entry, path, errors) {
1380
+ if (!isRecord4(entry)) {
1381
+ errors.push({
1382
+ path,
1383
+ message: "catalog entry must be an object."
1384
+ });
1385
+ return;
1386
+ }
1387
+ validateNonEmptyString4(entry.artifactId, `${path}.artifactId`, errors);
1388
+ validateIsoTimestamp2(entry.generatedAt, `${path}.generatedAt`, errors);
1389
+ if (entry.status !== "ready" && entry.status !== "rejected") {
1390
+ errors.push({
1391
+ path: `${path}.status`,
1392
+ message: 'status must be "ready" or "rejected".'
1393
+ });
1394
+ }
1395
+ validateEntryProvider(entry.provider, `${path}.provider`, errors);
1396
+ validateEntryAcceptance(entry.acceptance, `${path}.acceptance`, errors);
1397
+ }
1398
+ function validateEntryProvider(provider, path, errors) {
1399
+ if (!isRecord4(provider)) {
1400
+ errors.push({
1401
+ path,
1402
+ message: "provider must be an object."
1403
+ });
1404
+ return;
1405
+ }
1406
+ validateNonEmptyString4(provider.id, `${path}.id`, errors);
1407
+ validateNonEmptyString4(provider.displayName, `${path}.displayName`, errors);
1408
+ validateStringArray3(provider.capabilities, `${path}.capabilities`, errors);
1409
+ validateNonEmptyString4(provider.protocolMode, `${path}.protocolMode`, errors);
1410
+ validateProviderPaymentOptions(
1411
+ provider.paymentOptions,
1412
+ `${path}.paymentOptions`,
1413
+ Array.isArray(provider.capabilities) ? provider.capabilities : [],
1414
+ errors
1415
+ );
1416
+ validatePricingDeclaration3(provider.pricing, `${path}.pricing`, errors);
1417
+ validateReceiptSupport(provider.receipts, `${path}.receipts`, errors);
1418
+ if (provider.limits !== void 0 && !isRecord4(provider.limits)) {
1419
+ errors.push({
1420
+ path: `${path}.limits`,
1421
+ message: "limits must be an object when provided."
1422
+ });
1423
+ }
1424
+ }
1425
+ function validateEntryAcceptance(acceptance, path, errors) {
1426
+ if (!isRecord4(acceptance)) {
1427
+ errors.push({
1428
+ path,
1429
+ message: "acceptance must be an object."
1430
+ });
1431
+ return;
1432
+ }
1433
+ if (!isRecord4(acceptance.gate)) {
1434
+ errors.push({
1435
+ path: `${path}.gate`,
1436
+ message: "gate must be an object."
1437
+ });
1438
+ } else {
1439
+ if (typeof acceptance.gate.accepted !== "boolean") {
1440
+ errors.push({
1441
+ path: `${path}.gate.accepted`,
1442
+ message: "gate.accepted must be a boolean."
1443
+ });
1444
+ }
1445
+ if (acceptance.gate.status !== "accepted" && acceptance.gate.status !== "rejected") {
1446
+ errors.push({
1447
+ path: `${path}.gate.status`,
1448
+ message: 'gate.status must be "accepted" or "rejected".'
1449
+ });
1450
+ }
1451
+ }
1452
+ validateStringArray3(acceptance.failedChecks, `${path}.failedChecks`, errors);
1453
+ validateReceiptSummary2(acceptance.receipts, `${path}.receipts`, errors);
1454
+ validateStringArray3(
1455
+ acceptance.timelineEventTypes,
1456
+ `${path}.timelineEventTypes`,
1457
+ errors
1458
+ );
1459
+ validateStringArray3(
1460
+ acceptance.telemetryEventTypes,
1461
+ `${path}.telemetryEventTypes`,
1462
+ errors
1463
+ );
1464
+ }
1465
+ function validatePricingDeclaration3(pricing, path, errors) {
1466
+ if (!isRecord4(pricing)) {
1467
+ errors.push({
1468
+ path,
1469
+ message: "pricing must be an object."
1470
+ });
1471
+ return;
1472
+ }
1473
+ if (isPricingObject(pricing)) {
1474
+ validatePricingObject(pricing, path, errors);
1475
+ return;
1476
+ }
1477
+ for (const [capability, capabilityPricing] of Object.entries(pricing)) {
1478
+ validateNonEmptyString4(capability, `${path}.${capability}`, errors);
1479
+ validatePricingObject(capabilityPricing, `${path}.${capability}`, errors);
1480
+ }
1481
+ }
1482
+ function validatePricingObject(pricing, path, errors) {
1483
+ if (!isRecord4(pricing)) {
1484
+ errors.push({
1485
+ path,
1486
+ message: "pricing entry must be an object."
1487
+ });
1488
+ return;
1489
+ }
1490
+ validateNonEmptyString4(pricing.unit, `${path}.unit`, errors);
1491
+ if (typeof pricing.amountUsd !== "number" || !Number.isFinite(pricing.amountUsd) || pricing.amountUsd < 0) {
1492
+ errors.push({
1493
+ path: `${path}.amountUsd`,
1494
+ message: "amountUsd must be a non-negative finite number."
1495
+ });
1496
+ }
1497
+ if (pricing.currency !== void 0 && typeof pricing.currency !== "string") {
1498
+ errors.push({
1499
+ path: `${path}.currency`,
1500
+ message: "currency must be a string when provided."
1501
+ });
1502
+ }
1503
+ }
1504
+ function validateReceiptSupport(receipts, path, errors) {
1505
+ if (!isRecord4(receipts)) {
1506
+ errors.push({
1507
+ path,
1508
+ message: "receipts must be an object."
1509
+ });
1510
+ return;
1511
+ }
1512
+ for (const key of ["payment", "delivery", "responseEvidence"]) {
1513
+ if (typeof receipts[key] !== "boolean") {
1514
+ errors.push({
1515
+ path: `${path}.${key}`,
1516
+ message: `${key} must be a boolean.`
1517
+ });
1518
+ }
1519
+ }
1520
+ }
1521
+ function validateReceiptSummary2(receipts, path, errors) {
1522
+ if (!isRecord4(receipts)) {
1523
+ errors.push({
1524
+ path,
1525
+ message: "receipts must be an object."
1526
+ });
1527
+ return;
1528
+ }
1529
+ if (typeof receipts.total !== "number" || !Number.isFinite(receipts.total)) {
1530
+ errors.push({
1531
+ path: `${path}.total`,
1532
+ message: "total must be a finite number."
1533
+ });
1534
+ }
1535
+ validateStringArray3(receipts.types, `${path}.types`, errors);
1536
+ validateStringArray3(receipts.providers, `${path}.providers`, errors);
1537
+ for (const key of [
1538
+ "hasPaymentProof",
1539
+ "hasSettlementConfirmation",
1540
+ "hasProviderDelivery"
1541
+ ]) {
1542
+ if (typeof receipts[key] !== "boolean") {
1543
+ errors.push({
1544
+ path: `${path}.${key}`,
1545
+ message: `${key} must be a boolean.`
1546
+ });
1547
+ }
1548
+ }
1549
+ }
1550
+ function isPricingObject(value) {
1551
+ return "unit" in value || "amountUsd" in value || "currency" in value;
1552
+ }
1553
+ function validateStringArray3(value, path, errors) {
1554
+ if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string" || entry.length === 0)) {
1555
+ errors.push({
1556
+ path,
1557
+ message: `${path} must be an array of non-empty strings.`
1558
+ });
1559
+ }
1560
+ }
1561
+ function validateNonEmptyString4(value, path, errors) {
1562
+ if (typeof value !== "string" || value.length === 0) {
1563
+ errors.push({
1564
+ path,
1565
+ message: `${path} must be a non-empty string.`
1566
+ });
1567
+ }
1568
+ }
1569
+ function validateIsoTimestamp2(value, path, errors) {
1570
+ if (typeof value !== "string" || Number.isNaN(Date.parse(value))) {
1571
+ errors.push({
1572
+ path,
1573
+ message: `${path} must be an ISO timestamp string.`
1574
+ });
1575
+ }
1576
+ }
1577
+ function formatValidationErrors(errors) {
1578
+ return errors.map((error) => `${error.path}: ${error.message}`).join("; ");
1579
+ }
1580
+ function isRecord4(value) {
1581
+ return !!value && typeof value === "object" && !Array.isArray(value);
1582
+ }
1583
+
1584
+ // src/providerCatalogPolicy.ts
1585
+ function evaluateProviderCatalogPolicy(options) {
1586
+ assertEvaluationOptions(options);
1587
+ const catalogPolicy = resolveCatalogPolicy(options.catalogPolicy);
1588
+ const adapterInventory = options.adapterInventory;
1589
+ const adapterIds = new Set(adapterInventory.map((adapter) => adapter.id));
1590
+ const catalogSummary = summarizeProviderCatalog(options.catalog);
1591
+ const checks = [
1592
+ {
1593
+ name: "catalog_valid",
1594
+ status: "passed",
1595
+ message: "Provider catalog is valid."
1596
+ },
1597
+ {
1598
+ name: "adapter_inventory_valid",
1599
+ status: "passed",
1600
+ message: "Adapter inventory is valid."
1601
+ }
1602
+ ];
1603
+ const queryResults = options.queries.map(
1604
+ (query) => evaluateQuery({
1605
+ catalog: options.catalog,
1606
+ catalogPolicy,
1607
+ query,
1608
+ adapterInventory,
1609
+ adapterIds,
1610
+ checks
1611
+ })
1612
+ );
1613
+ const failedChecks = checks.filter((check) => check.status === "failed").length;
1614
+ const routeableMatches = queryResults.reduce(
1615
+ (total, result) => total + result.routeableMatches.length,
1616
+ 0
1617
+ );
1618
+ const missingAdapterMatches = queryResults.reduce(
1619
+ (total, result) => total + result.missingAdapterMatches.length,
1620
+ 0
1621
+ );
1622
+ return {
1623
+ status: failedChecks === 0 ? "passed" : "failed",
1624
+ checks,
1625
+ summary: {
1626
+ ...catalogSummary,
1627
+ totalQueries: options.queries.length,
1628
+ passedChecks: checks.length - failedChecks,
1629
+ failedChecks,
1630
+ routeableMatches,
1631
+ missingAdapterMatches
1632
+ },
1633
+ queryResults
1634
+ };
1635
+ }
1636
+ function assertEvaluationOptions(options) {
1637
+ if (!isRecord5(options)) {
1638
+ throw new ProbeMeshError({
1639
+ code: "invalid_request",
1640
+ message: "Provider catalog policy evaluation options must be an object."
1641
+ });
1642
+ }
1643
+ assertProviderCatalog(options.catalog);
1644
+ assertAdapterInventory(options.adapterInventory);
1645
+ if (!Array.isArray(options.queries) || options.queries.length === 0) {
1646
+ throw new ProbeMeshError({
1647
+ code: "invalid_request",
1648
+ message: "Provider catalog policy evaluation requires at least one query."
1649
+ });
1650
+ }
1651
+ options.queries.forEach(
1652
+ (query, index) => assertExpectedQuery(query, `queries.${index}`)
1653
+ );
1654
+ assertCatalogPolicyOptions(options.catalogPolicy, "catalogPolicy");
1655
+ }
1656
+ function assertAdapterInventory(adapterInventory) {
1657
+ if (!Array.isArray(adapterInventory)) {
1658
+ throw new ProbeMeshError({
1659
+ code: "invalid_request",
1660
+ message: "Provider catalog policy adapterInventory must be an array."
1661
+ });
1662
+ }
1663
+ const seen = /* @__PURE__ */ new Set();
1664
+ adapterInventory.forEach((adapter, index) => {
1665
+ const path = `adapterInventory.${index}`;
1666
+ if (!isRecord5(adapter)) {
1667
+ throw new ProbeMeshError({
1668
+ code: "invalid_request",
1669
+ message: `${path} must be an object.`
1670
+ });
1671
+ }
1672
+ if (typeof adapter.id !== "string" || adapter.id.length === 0) {
1673
+ throw new ProbeMeshError({
1674
+ code: "invalid_request",
1675
+ message: `${path}.id must be a non-empty string.`
1676
+ });
1677
+ }
1678
+ if (seen.has(adapter.id)) {
1679
+ throw new ProbeMeshError({
1680
+ code: "invalid_request",
1681
+ message: `${path}.id duplicates adapter "${adapter.id}".`
1682
+ });
1683
+ }
1684
+ seen.add(adapter.id);
1685
+ if (!Array.isArray(adapter.capabilities) || adapter.capabilities.some(
1686
+ (capability) => typeof capability !== "string" || capability.length === 0
1687
+ )) {
1688
+ throw new ProbeMeshError({
1689
+ code: "invalid_request",
1690
+ message: `${path}.capabilities must be an array of non-empty strings.`
1691
+ });
1692
+ }
1693
+ if (adapter.paymentOptions !== void 0 && (!Array.isArray(adapter.paymentOptions) || adapter.paymentOptions.some(
1694
+ (option) => !isRecord5(option) || typeof option.id !== "string" || option.id.length === 0 || typeof option.protocolMode !== "string" || option.protocolMode.length === 0
1695
+ ))) {
1696
+ throw new ProbeMeshError({
1697
+ code: "invalid_request",
1698
+ message: `${path}.paymentOptions must be an array of payment option objects when provided.`
1699
+ });
1700
+ }
1701
+ });
1702
+ }
1703
+ function assertExpectedQuery(query, path) {
1704
+ if (!isRecord5(query)) {
1705
+ throw new ProbeMeshError({
1706
+ code: "invalid_request",
1707
+ message: `${path} must be an object.`
1708
+ });
1709
+ }
1710
+ if (typeof query.capability !== "string" || query.capability.length === 0) {
1711
+ throw new ProbeMeshError({
1712
+ code: "invalid_request",
1713
+ message: `${path}.capability must be a non-empty string.`
1714
+ });
1715
+ }
1716
+ const minMatches = query.minMatches;
1717
+ if (minMatches !== void 0 && (typeof minMatches !== "number" || !Number.isInteger(minMatches) || minMatches < 0)) {
1718
+ throw new ProbeMeshError({
1719
+ code: "invalid_request",
1720
+ message: `${path}.minMatches must be a non-negative integer.`
1721
+ });
1722
+ }
1723
+ assertCatalogPolicyOptions(query, path);
1724
+ }
1725
+ function assertCatalogPolicyOptions(policy, path) {
1726
+ if (policy === void 0) {
1727
+ return;
1728
+ }
1729
+ if (!isRecord5(policy)) {
1730
+ throw new ProbeMeshError({
1731
+ code: "invalid_request",
1732
+ message: `${path} must be an object when provided.`
1733
+ });
1734
+ }
1735
+ if (policy.status !== void 0 && policy.status !== "ready" && policy.status !== "rejected") {
1736
+ throw new ProbeMeshError({
1737
+ code: "invalid_request",
1738
+ message: `${path}.status must be "ready" or "rejected".`
1739
+ });
1740
+ }
1741
+ if (policy.protocolMode !== void 0 && (typeof policy.protocolMode !== "string" || policy.protocolMode.length === 0)) {
1742
+ throw new ProbeMeshError({
1743
+ code: "invalid_request",
1744
+ message: `${path}.protocolMode must be a non-empty string.`
1745
+ });
1746
+ }
1747
+ validatePaymentPreferences(policy.paymentPreferences, `${path}.paymentPreferences`);
1748
+ validatePaymentStrategy(policy.paymentStrategy, `${path}.paymentStrategy`);
1749
+ if (policy.maxCostUsd !== void 0 && (typeof policy.maxCostUsd !== "number" || !Number.isFinite(policy.maxCostUsd) || policy.maxCostUsd < 0)) {
1750
+ throw new ProbeMeshError({
1751
+ code: "invalid_request",
1752
+ message: `${path}.maxCostUsd must be a non-negative finite number.`
1753
+ });
1754
+ }
1755
+ validateStringArray4(policy.providerIds, `${path}.providerIds`);
1756
+ validateStringArray4(policy.blockedProviderIds, `${path}.blockedProviderIds`);
1757
+ if (policy.requiredReceiptTypes !== void 0 && (!Array.isArray(policy.requiredReceiptTypes) || policy.requiredReceiptTypes.some((receiptType) => !isReceiptType3(receiptType)))) {
1758
+ throw new ProbeMeshError({
1759
+ code: "invalid_request",
1760
+ message: `${path}.requiredReceiptTypes must contain known receipt types.`
1761
+ });
1762
+ }
1763
+ }
1764
+ function evaluateQuery(options) {
1765
+ const resolvedQuery = resolveQuery(options.catalogPolicy, options.query);
1766
+ const matches = findProviderCatalogMatches(options.catalog, resolvedQuery);
1767
+ const routeableMatches = matches.filter(
1768
+ (match) => hasRouteableAdapter(match, options.adapterInventory)
1769
+ );
1770
+ const missingAdapterMatches = matches.filter((match) => !options.adapterIds.has(match.providerId)).map((match) => ({
1771
+ providerId: match.providerId,
1772
+ capability: match.capability,
1773
+ catalogArtifactId: match.entry.artifactId,
1774
+ catalogStatus: match.entry.status,
1775
+ reasons: [
1776
+ ...match.reasons,
1777
+ `missing_adapter:${match.providerId}`
1778
+ ]
1779
+ }));
1780
+ const skippedProviders = createSkippedProviders(
1781
+ options.catalog.entries,
1782
+ options.query.capability,
1783
+ matches,
1784
+ resolvedQuery,
1785
+ options.adapterInventory
1786
+ );
1787
+ const minMatches = options.query.minMatches ?? 1;
1788
+ pushCheck(options.checks, {
1789
+ name: "ready_matches",
1790
+ status: matches.length >= minMatches ? "passed" : "failed",
1791
+ capability: options.query.capability,
1792
+ message: matches.length >= minMatches ? `Found ${matches.length} catalog match(es) for "${options.query.capability}".` : `Expected at least ${minMatches} catalog match(es) for "${options.query.capability}", found ${matches.length}.`
1793
+ });
1794
+ pushCheck(options.checks, {
1795
+ name: "routeable_matches",
1796
+ status: routeableMatches.length >= minMatches ? "passed" : "failed",
1797
+ capability: options.query.capability,
1798
+ message: routeableMatches.length >= minMatches ? `Found ${routeableMatches.length} routeable adapter-backed match(es) for "${options.query.capability}".` : `Expected at least ${minMatches} routeable adapter-backed match(es) for "${options.query.capability}", found ${routeableMatches.length}.`
1799
+ });
1800
+ for (const missingMatch of missingAdapterMatches) {
1801
+ pushCheck(options.checks, {
1802
+ name: "missing_adapter",
1803
+ status: routeableMatches.length >= minMatches ? "passed" : "failed",
1804
+ capability: missingMatch.capability,
1805
+ providerId: missingMatch.providerId,
1806
+ message: routeableMatches.length >= minMatches ? `Catalog provider "${missingMatch.providerId}" matches policy but is missing from adapter inventory; minimum routeable matches are still satisfied.` : `Catalog provider "${missingMatch.providerId}" matches policy but is missing from adapter inventory.`
1807
+ });
1808
+ }
1809
+ return {
1810
+ query: options.query,
1811
+ matches,
1812
+ routeableMatches,
1813
+ missingAdapterMatches,
1814
+ skippedProviders
1815
+ };
1816
+ }
1817
+ function resolveCatalogPolicy(policy) {
1818
+ return {
1819
+ enabled: policy?.enabled ?? true,
1820
+ status: policy?.status ?? "ready",
1821
+ protocolMode: policy?.protocolMode,
1822
+ paymentPreferences: policy?.paymentPreferences,
1823
+ paymentStrategy: policy?.paymentStrategy,
1824
+ maxCostUsd: policy?.maxCostUsd,
1825
+ requiredReceiptTypes: policy?.requiredReceiptTypes,
1826
+ providerIds: policy?.providerIds,
1827
+ blockedProviderIds: policy?.blockedProviderIds
1828
+ };
1829
+ }
1830
+ function resolveQuery(policy, query) {
1831
+ const queryPolicy = resolveCatalogPolicy(query);
1832
+ const activePolicy = policy.enabled ? policy : resolveCatalogPolicy(void 0);
1833
+ return {
1834
+ capability: query.capability,
1835
+ protocolMode: queryPolicy.protocolMode ?? activePolicy.protocolMode,
1836
+ paymentPreferences: mergePaymentPreferences(
1837
+ activePolicy.paymentPreferences,
1838
+ queryPolicy.paymentPreferences
1839
+ ),
1840
+ paymentStrategy: queryPolicy.paymentStrategy ?? activePolicy.paymentStrategy,
1841
+ maxCostUsd: strictestMaxCostUsd(
1842
+ queryPolicy.maxCostUsd,
1843
+ activePolicy.maxCostUsd
1844
+ ),
1845
+ requiredReceiptTypes: unionProviderIds(
1846
+ queryPolicy.requiredReceiptTypes,
1847
+ activePolicy.requiredReceiptTypes
1848
+ ),
1849
+ providerIds: intersectProviderIds(
1850
+ queryPolicy.providerIds,
1851
+ activePolicy.providerIds
1852
+ ),
1853
+ blockedProviderIds: unionProviderIds(
1854
+ queryPolicy.blockedProviderIds,
1855
+ activePolicy.blockedProviderIds
1856
+ ),
1857
+ status: queryPolicy.status ?? activePolicy.status
1858
+ };
1859
+ }
1860
+ function hasRouteableAdapter(match, adapterInventory) {
1861
+ return adapterInventory.some(
1862
+ (adapter) => adapter.id === match.providerId && adapter.capabilities.includes(match.capability) && (adapter.paymentOptions === void 0 || match.paymentSelection === void 0 || adapter.paymentOptions.some(
1863
+ (option) => option.id === match.paymentSelection?.optionId
1864
+ ))
1865
+ );
1866
+ }
1867
+ function createSkippedProviders(entries, capability, matches, query, adapterInventory) {
1868
+ const matchIds = new Set(matches.map((match) => match.providerId));
1869
+ const adapterIds = new Set(adapterInventory.map((adapter) => adapter.id));
1870
+ const catalogProviderIds = new Set(entries.map((entry) => entry.provider.id));
1871
+ const skippedCatalogEntries = entries.filter((entry) => entry.provider.capabilities.includes(capability)).filter((entry) => !matchIds.has(entry.provider.id)).map((entry) => ({
1872
+ providerId: entry.provider.id,
1873
+ capability,
1874
+ catalogArtifactId: entry.artifactId,
1875
+ catalogStatus: entry.status,
1876
+ reasons: explainSkippedEntry(entry, query, adapterIds)
1877
+ }));
1878
+ const inventoryOnlyAdapters = adapterInventory.filter((adapter) => adapter.capabilities.includes(capability)).filter((adapter) => !catalogProviderIds.has(adapter.id)).map((adapter) => ({
1879
+ providerId: adapter.id,
1880
+ capability,
1881
+ inventoryOnly: true,
1882
+ reasons: ["adapter:not_in_catalog"]
1883
+ }));
1884
+ return [...skippedCatalogEntries, ...inventoryOnlyAdapters];
1885
+ }
1886
+ function explainSkippedEntry(entry, query, adapterIds) {
1887
+ const reasons = [];
1888
+ const providerId = entry.provider.id;
1889
+ if (entry.status !== (query.status ?? "ready")) {
1890
+ reasons.push(`status:${entry.status}`);
1891
+ }
1892
+ if (query.protocolMode && entry.provider.protocolMode !== query.protocolMode) {
1893
+ reasons.push(`protocol:${entry.provider.protocolMode}`);
1894
+ }
1895
+ if (query.paymentPreferences) {
1896
+ const paymentMatch = findProviderCatalogMatches(
1897
+ {
1898
+ schemaVersion: "probemesh.provider-catalog.index.v1",
1899
+ generatedAt: "1970-01-01T00:00:00.000Z",
1900
+ entries: [entry]
1901
+ },
1902
+ {
1903
+ capability: query.capability,
1904
+ paymentPreferences: query.paymentPreferences,
1905
+ status: entry.status
1906
+ }
1907
+ );
1908
+ if (paymentMatch.length === 0) {
1909
+ reasons.push("payment_preferences:not_matched");
1910
+ }
1911
+ }
1912
+ if (query.providerIds && !query.providerIds.includes(providerId)) {
1913
+ reasons.push("provider:not_allowed");
1914
+ }
1915
+ if (query.blockedProviderIds?.includes(providerId)) {
1916
+ reasons.push("provider:blocked");
1917
+ }
1918
+ const cost = resolveCatalogCost2(entry, query.capability);
1919
+ if (query.maxCostUsd !== void 0 && (cost === void 0 || cost.amountUsd > query.maxCostUsd)) {
1920
+ reasons.push(`cost:${cost?.amountUsd ?? "unknown"}>${query.maxCostUsd}`);
1921
+ }
1922
+ const receiptTypes = new Set(entry.acceptance.receipts.types);
1923
+ for (const receiptType of query.requiredReceiptTypes ?? []) {
1924
+ if (!receiptTypes.has(receiptType)) {
1925
+ reasons.push(`missing_receipt:${receiptType}`);
1926
+ }
1927
+ }
1928
+ if (!adapterIds.has(providerId)) {
1929
+ reasons.push(`missing_adapter:${providerId}`);
1930
+ }
1931
+ return reasons.length > 0 ? reasons : ["not_matched"];
1932
+ }
1933
+ function resolveCatalogCost2(entry, capability) {
1934
+ const pricing = entry.provider.pricing;
1935
+ if (isPricing2(pricing)) {
1936
+ return pricing;
1937
+ }
1938
+ const capabilityPricing = pricing[capability];
1939
+ return isPricing2(capabilityPricing) ? capabilityPricing : void 0;
1940
+ }
1941
+ function pushCheck(checks, check) {
1942
+ checks.push(check);
1943
+ }
1944
+ function strictestMaxCostUsd(first, second) {
1945
+ if (first === void 0) {
1946
+ return second;
1947
+ }
1948
+ if (second === void 0) {
1949
+ return first;
1950
+ }
1951
+ return Math.min(first, second);
1952
+ }
1953
+ function intersectProviderIds(first, second) {
1954
+ if (!first) {
1955
+ return second;
1956
+ }
1957
+ if (!second) {
1958
+ return first;
1959
+ }
1960
+ return first.filter((providerId) => second.includes(providerId));
1961
+ }
1962
+ function unionProviderIds(first, second) {
1963
+ return [.../* @__PURE__ */ new Set([...first ?? [], ...second ?? []])];
1964
+ }
1965
+ function validateStringArray4(value, path) {
1966
+ if (value !== void 0 && (!Array.isArray(value) || value.some((entry) => typeof entry !== "string" || entry.length === 0))) {
1967
+ throw new ProbeMeshError({
1968
+ code: "invalid_request",
1969
+ message: `${path} must be an array of non-empty strings.`
1970
+ });
1971
+ }
1972
+ }
1973
+ function isPricing2(value) {
1974
+ return isRecord5(value) && typeof value.unit === "string" && typeof value.amountUsd === "number" && Number.isFinite(value.amountUsd) && value.amountUsd >= 0 && (value.currency === void 0 || typeof value.currency === "string");
1975
+ }
1976
+ function isReceiptType3(value) {
1977
+ return value === "payment_proof" || value === "settlement_confirmation" || value === "provider_delivery" || value === "provider_response_evidence" || value === "authorization_decision";
1978
+ }
1979
+ function isRecord5(value) {
1980
+ return !!value && typeof value === "object" && !Array.isArray(value);
1981
+ }
1982
+
1983
+ // src/providerOnboardingDossier.ts
1984
+ var import_node_crypto2 = require("crypto");
1985
+
1986
+ // src/providerConformanceArtifact.ts
1987
+ var import_node_crypto = require("crypto");
1988
+ var PROVIDER_CONFORMANCE_ARTIFACT_SCHEMA_VERSION = "probemesh.provider-conformance.v1";
1989
+ function validateProviderConformanceArtifact(artifact) {
1990
+ const errors = [];
1991
+ if (!isRecord6(artifact)) {
1992
+ return {
1993
+ valid: false,
1994
+ errors: [
1995
+ {
1996
+ path: "$",
1997
+ message: "Provider conformance artifact must be an object."
1998
+ }
1999
+ ]
2000
+ };
2001
+ }
2002
+ if (artifact.schemaVersion !== PROVIDER_CONFORMANCE_ARTIFACT_SCHEMA_VERSION) {
2003
+ errors.push({
2004
+ path: "schemaVersion",
2005
+ message: `schemaVersion must be "${PROVIDER_CONFORMANCE_ARTIFACT_SCHEMA_VERSION}".`
2006
+ });
2007
+ }
2008
+ validateNonEmptyString5(artifact.artifactId, "artifactId", errors);
2009
+ validateIsoTimestamp3(artifact.generatedAt, "generatedAt", errors);
2010
+ if (artifact.status !== "verified" && artifact.status !== "failed") {
2011
+ errors.push({
2012
+ path: "status",
2013
+ message: 'status must be "verified" or "failed".'
2014
+ });
2015
+ }
2016
+ if (artifact.hashAlgorithm !== "sha256") {
2017
+ errors.push({
2018
+ path: "hashAlgorithm",
2019
+ message: 'hashAlgorithm must be "sha256".'
2020
+ });
2021
+ }
2022
+ validateHashes(artifact.hashes, errors);
2023
+ validateManifestSummary(artifact.provider, errors);
2024
+ validateConformanceSummary(artifact.conformance, errors);
2025
+ return {
2026
+ valid: errors.length === 0,
2027
+ errors
2028
+ };
2029
+ }
2030
+ function validateManifestSummary(provider, errors) {
2031
+ if (!isRecord6(provider)) {
2032
+ errors.push({
2033
+ path: "provider",
2034
+ message: "provider must be an object."
2035
+ });
2036
+ return;
2037
+ }
2038
+ validateNonEmptyString5(provider.id, "provider.id", errors);
2039
+ validateNonEmptyString5(provider.displayName, "provider.displayName", errors);
2040
+ if (!Array.isArray(provider.capabilities) || provider.capabilities.some((capability) => typeof capability !== "string")) {
2041
+ errors.push({
2042
+ path: "provider.capabilities",
2043
+ message: "provider.capabilities must be an array of strings."
2044
+ });
2045
+ }
2046
+ validateNonEmptyString5(provider.protocolMode, "provider.protocolMode", errors);
2047
+ if (!isRecord6(provider.receipts)) {
2048
+ errors.push({
2049
+ path: "provider.receipts",
2050
+ message: "provider.receipts must be an object."
2051
+ });
2052
+ }
2053
+ if (!isRecord6(provider.schemas) || typeof provider.schemas.inputDeclared !== "boolean" || typeof provider.schemas.outputDeclared !== "boolean") {
2054
+ errors.push({
2055
+ path: "provider.schemas",
2056
+ message: "provider.schemas must include inputDeclared and outputDeclared booleans."
2057
+ });
2058
+ }
2059
+ }
2060
+ function validateConformanceSummary(conformance, errors) {
2061
+ if (!isRecord6(conformance)) {
2062
+ errors.push({
2063
+ path: "conformance",
2064
+ message: "conformance must be an object."
2065
+ });
2066
+ return;
2067
+ }
2068
+ validateNonEmptyString5(conformance.title, "conformance.title", errors);
2069
+ if (conformance.status !== "passed" && conformance.status !== "failed") {
2070
+ errors.push({
2071
+ path: "conformance.status",
2072
+ message: 'conformance.status must be "passed" or "failed".'
2073
+ });
2074
+ }
2075
+ if (!isRecord6(conformance.summary)) {
2076
+ errors.push({
2077
+ path: "conformance.summary",
2078
+ message: "conformance.summary must be an object."
2079
+ });
2080
+ }
2081
+ if (!Array.isArray(conformance.checks) || conformance.checks.some((check) => !isRecord6(check))) {
2082
+ errors.push({
2083
+ path: "conformance.checks",
2084
+ message: "conformance.checks must be an array of check objects."
2085
+ });
2086
+ }
2087
+ if (!Array.isArray(conformance.failedChecks) || conformance.failedChecks.some((checkName) => typeof checkName !== "string")) {
2088
+ errors.push({
2089
+ path: "conformance.failedChecks",
2090
+ message: "conformance.failedChecks must be an array of strings."
2091
+ });
2092
+ }
2093
+ if (!isRecord6(conformance.receipts)) {
2094
+ errors.push({
2095
+ path: "conformance.receipts",
2096
+ message: "conformance.receipts must be an object."
2097
+ });
2098
+ }
2099
+ if (!Array.isArray(conformance.timelineEventTypes) || conformance.timelineEventTypes.some((eventType) => typeof eventType !== "string")) {
2100
+ errors.push({
2101
+ path: "conformance.timelineEventTypes",
2102
+ message: "conformance.timelineEventTypes must be an array of strings."
2103
+ });
2104
+ }
2105
+ if (!Array.isArray(conformance.telemetryEventTypes) || conformance.telemetryEventTypes.some((eventType) => typeof eventType !== "string")) {
2106
+ errors.push({
2107
+ path: "conformance.telemetryEventTypes",
2108
+ message: "conformance.telemetryEventTypes must be an array of strings."
2109
+ });
2110
+ }
2111
+ }
2112
+ function validateHashes(hashes, errors) {
2113
+ if (!isRecord6(hashes)) {
2114
+ errors.push({
2115
+ path: "hashes",
2116
+ message: "hashes must be an object."
2117
+ });
2118
+ return;
2119
+ }
2120
+ for (const field of ["manifest", "report", "checks", "artifact"]) {
2121
+ const value = hashes[field];
2122
+ if (typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value)) {
2123
+ errors.push({
2124
+ path: `hashes.${field}`,
2125
+ message: `${field} hash must be a sha256 hex string.`
2126
+ });
2127
+ }
2128
+ }
2129
+ }
2130
+ function validateNonEmptyString5(value, path, errors) {
2131
+ if (typeof value !== "string" || value.length === 0) {
2132
+ errors.push({
2133
+ path,
2134
+ message: `${path} must be a non-empty string.`
2135
+ });
2136
+ }
2137
+ }
2138
+ function validateIsoTimestamp3(value, path, errors) {
2139
+ if (typeof value !== "string" || Number.isNaN(Date.parse(value))) {
2140
+ errors.push({
2141
+ path,
2142
+ message: `${path} must be an ISO timestamp.`
2143
+ });
2144
+ }
2145
+ }
2146
+ function isRecord6(value) {
2147
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2148
+ }
2149
+
2150
+ // src/providerOnboardingDossier.ts
2151
+ var PROVIDER_ONBOARDING_DOSSIER_SCHEMA_VERSION = "probemesh.provider-onboarding-dossier.v1";
2152
+ function validateProviderOnboardingDossier(dossier) {
2153
+ const errors = [];
2154
+ if (!isRecord7(dossier)) {
2155
+ return {
2156
+ valid: false,
2157
+ errors: [
2158
+ {
2159
+ path: "$",
2160
+ message: "Provider onboarding dossier must be an object."
2161
+ }
2162
+ ]
2163
+ };
2164
+ }
2165
+ if (dossier.schemaVersion !== PROVIDER_ONBOARDING_DOSSIER_SCHEMA_VERSION) {
2166
+ errors.push({
2167
+ path: "schemaVersion",
2168
+ message: `schemaVersion must be "${PROVIDER_ONBOARDING_DOSSIER_SCHEMA_VERSION}".`
2169
+ });
2170
+ }
2171
+ validateNonEmptyString6(dossier.dossierId, "dossierId", errors);
2172
+ validateIsoTimestamp4(dossier.generatedAt, "generatedAt", errors);
2173
+ if (dossier.status !== "ready" && dossier.status !== "failed") {
2174
+ errors.push({
2175
+ path: "status",
2176
+ message: 'status must be "ready" or "failed".'
2177
+ });
2178
+ }
2179
+ if (dossier.hashAlgorithm !== "sha256") {
2180
+ errors.push({
2181
+ path: "hashAlgorithm",
2182
+ message: 'hashAlgorithm must be "sha256".'
2183
+ });
2184
+ }
2185
+ validateProviderSummary(dossier.provider, errors);
2186
+ validateReadiness(dossier.readiness, errors);
2187
+ validateEvidence(dossier.evidence, errors);
2188
+ validateNestedArtifacts(dossier.artifacts, errors);
2189
+ validateHashes2(dossier, errors);
2190
+ return {
2191
+ valid: errors.length === 0,
2192
+ errors
2193
+ };
2194
+ }
2195
+ function assertProviderOnboardingDossier(dossier) {
2196
+ const result = validateProviderOnboardingDossier(dossier);
2197
+ if (result.valid) {
2198
+ return;
2199
+ }
2200
+ throw new ProbeMeshError({
2201
+ code: "invalid_request",
2202
+ message: `Invalid provider onboarding dossier: ${formatValidationErrors2(
2203
+ result.errors
2204
+ )}`
2205
+ });
2206
+ }
2207
+ function validateProviderSummary(provider, errors) {
2208
+ if (!isRecord7(provider)) {
2209
+ errors.push({
2210
+ path: "provider",
2211
+ message: "provider must be an object."
2212
+ });
2213
+ return;
2214
+ }
2215
+ validateNonEmptyString6(provider.id, "provider.id", errors);
2216
+ validateNonEmptyString6(provider.displayName, "provider.displayName", errors);
2217
+ validateNonEmptyString6(provider.protocolMode, "provider.protocolMode", errors);
2218
+ if (!Array.isArray(provider.capabilities) || provider.capabilities.some((capability) => typeof capability !== "string")) {
2219
+ errors.push({
2220
+ path: "provider.capabilities",
2221
+ message: "provider.capabilities must be an array of strings."
2222
+ });
2223
+ }
2224
+ }
2225
+ function validateReadiness(readiness, errors) {
2226
+ if (!isRecord7(readiness)) {
2227
+ errors.push({
2228
+ path: "readiness",
2229
+ message: "readiness must be an object."
2230
+ });
2231
+ return;
2232
+ }
2233
+ if (typeof readiness.ready !== "boolean") {
2234
+ errors.push({
2235
+ path: "readiness.ready",
2236
+ message: "readiness.ready must be a boolean."
2237
+ });
2238
+ }
2239
+ if (readiness.status !== "ready" && readiness.status !== "failed") {
2240
+ errors.push({
2241
+ path: "readiness.status",
2242
+ message: 'readiness.status must be "ready" or "failed".'
2243
+ });
2244
+ }
2245
+ if (!Array.isArray(readiness.reasons) || readiness.reasons.some((reason) => typeof reason !== "string")) {
2246
+ errors.push({
2247
+ path: "readiness.reasons",
2248
+ message: "readiness.reasons must be an array of strings."
2249
+ });
2250
+ }
2251
+ if (!Array.isArray(readiness.failedChecks) || readiness.failedChecks.some((check) => typeof check !== "string")) {
2252
+ errors.push({
2253
+ path: "readiness.failedChecks",
2254
+ message: "readiness.failedChecks must be an array of strings."
2255
+ });
2256
+ }
2257
+ }
2258
+ function validateEvidence(evidence, errors) {
2259
+ if (!isRecord7(evidence)) {
2260
+ errors.push({
2261
+ path: "evidence",
2262
+ message: "evidence must be an object."
2263
+ });
2264
+ return;
2265
+ }
2266
+ if (!isRecord7(evidence.catalog)) {
2267
+ errors.push({
2268
+ path: "evidence.catalog",
2269
+ message: "evidence.catalog must be an object."
2270
+ });
2271
+ } else {
2272
+ validateNonEmptyString6(
2273
+ evidence.catalog.artifactId,
2274
+ "evidence.catalog.artifactId",
2275
+ errors
2276
+ );
2277
+ if (evidence.catalog.status !== "ready" && evidence.catalog.status !== "rejected") {
2278
+ errors.push({
2279
+ path: "evidence.catalog.status",
2280
+ message: 'evidence.catalog.status must be "ready" or "rejected".'
2281
+ });
2282
+ }
2283
+ if (typeof evidence.catalog.accepted !== "boolean") {
2284
+ errors.push({
2285
+ path: "evidence.catalog.accepted",
2286
+ message: "evidence.catalog.accepted must be a boolean."
2287
+ });
2288
+ }
2289
+ }
2290
+ if (!isRecord7(evidence.conformance)) {
2291
+ errors.push({
2292
+ path: "evidence.conformance",
2293
+ message: "evidence.conformance must be an object."
2294
+ });
2295
+ } else {
2296
+ validateNonEmptyString6(
2297
+ evidence.conformance.artifactId,
2298
+ "evidence.conformance.artifactId",
2299
+ errors
2300
+ );
2301
+ if (evidence.conformance.status !== "verified" && evidence.conformance.status !== "failed") {
2302
+ errors.push({
2303
+ path: "evidence.conformance.status",
2304
+ message: 'evidence.conformance.status must be "verified" or "failed".'
2305
+ });
2306
+ }
2307
+ }
2308
+ if (!isRecord7(evidence.receipts)) {
2309
+ errors.push({
2310
+ path: "evidence.receipts",
2311
+ message: "evidence.receipts must be an object."
2312
+ });
2313
+ }
2314
+ if (!Array.isArray(evidence.timelineEventTypes) || evidence.timelineEventTypes.some((type) => typeof type !== "string")) {
2315
+ errors.push({
2316
+ path: "evidence.timelineEventTypes",
2317
+ message: "evidence.timelineEventTypes must be an array of strings."
2318
+ });
2319
+ }
2320
+ if (!Array.isArray(evidence.telemetryEventTypes) || evidence.telemetryEventTypes.some((type) => typeof type !== "string")) {
2321
+ errors.push({
2322
+ path: "evidence.telemetryEventTypes",
2323
+ message: "evidence.telemetryEventTypes must be an array of strings."
2324
+ });
2325
+ }
2326
+ }
2327
+ function validateNestedArtifacts(artifacts, errors) {
2328
+ if (!isRecord7(artifacts)) {
2329
+ errors.push({
2330
+ path: "artifacts",
2331
+ message: "artifacts must be an object."
2332
+ });
2333
+ return;
2334
+ }
2335
+ const catalogValidation = validateProviderCatalogArtifact(artifacts.catalog);
2336
+ for (const error of catalogValidation.errors) {
2337
+ errors.push({
2338
+ path: `artifacts.catalog.${error.path}`,
2339
+ message: error.message
2340
+ });
2341
+ }
2342
+ const conformanceValidation = validateProviderConformanceArtifact(
2343
+ artifacts.conformance
2344
+ );
2345
+ for (const error of conformanceValidation.errors) {
2346
+ errors.push({
2347
+ path: `artifacts.conformance.${error.path}`,
2348
+ message: error.message
2349
+ });
2350
+ }
2351
+ if (isRecord7(artifacts.catalog) && isRecord7(artifacts.conformance) && isRecord7(artifacts.catalog.provider) && isRecord7(artifacts.conformance.provider) && artifacts.catalog.provider.id !== artifacts.conformance.provider.id) {
2352
+ errors.push({
2353
+ path: "artifacts",
2354
+ message: "catalog and conformance artifacts must reference the same provider id."
2355
+ });
2356
+ }
2357
+ }
2358
+ function validateHashes2(dossier, errors) {
2359
+ if (!isRecord7(dossier.hashes)) {
2360
+ errors.push({
2361
+ path: "hashes",
2362
+ message: "hashes must be an object."
2363
+ });
2364
+ return;
2365
+ }
2366
+ for (const field of [
2367
+ "catalogArtifact",
2368
+ "conformanceArtifact",
2369
+ "readiness",
2370
+ "dossier"
2371
+ ]) {
2372
+ const value = dossier.hashes[field];
2373
+ if (typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value)) {
2374
+ errors.push({
2375
+ path: `hashes.${field}`,
2376
+ message: `${field} hash must be a sha256 hex string.`
2377
+ });
2378
+ }
2379
+ }
2380
+ if (!isRecord7(dossier.artifacts) || !isRecord7(dossier.readiness) || errors.some((error) => error.path.startsWith("hashes."))) {
2381
+ return;
2382
+ }
2383
+ const expectedHashes = {
2384
+ catalogArtifact: hashStableJson(dossier.artifacts.catalog),
2385
+ conformanceArtifact: hashStableJson(dossier.artifacts.conformance),
2386
+ readiness: hashStableJson(dossier.readiness),
2387
+ dossier: ""
2388
+ };
2389
+ const expectedDossierHash = hashDossierContent({
2390
+ ...dossier,
2391
+ hashes: expectedHashes
2392
+ });
2393
+ for (const [field, expected] of Object.entries({
2394
+ ...expectedHashes,
2395
+ dossier: expectedDossierHash
2396
+ })) {
2397
+ if (dossier.hashes[field] !== expected) {
2398
+ errors.push({
2399
+ path: `hashes.${field}`,
2400
+ message: `${field} hash does not match dossier content.`
2401
+ });
2402
+ }
2403
+ }
2404
+ }
2405
+ function hashStableJson(value) {
2406
+ return (0, import_node_crypto2.createHash)("sha256").update(stableStringify(value)).digest("hex");
2407
+ }
2408
+ function hashDossierContent(dossier) {
2409
+ return hashStableJson(dossier);
2410
+ }
2411
+ function stableStringify(value) {
2412
+ if (value === null || typeof value !== "object") {
2413
+ return JSON.stringify(value);
2414
+ }
2415
+ if (Array.isArray(value)) {
2416
+ return `[${value.map((entry) => stableStringify(entry)).join(",")}]`;
2417
+ }
2418
+ const entries = Object.entries(value).filter(([, entry]) => entry !== void 0).sort(([left], [right]) => left.localeCompare(right));
2419
+ return `{${entries.map(([key, entry]) => `${JSON.stringify(key)}:${stableStringify(entry)}`).join(",")}}`;
2420
+ }
2421
+ function isRecord7(value) {
2422
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2423
+ }
2424
+ function validateNonEmptyString6(value, path, errors) {
2425
+ if (typeof value !== "string" || value.length === 0) {
2426
+ errors.push({
2427
+ path,
2428
+ message: `${path} must be a non-empty string.`
2429
+ });
2430
+ }
2431
+ }
2432
+ function validateIsoTimestamp4(value, path, errors) {
2433
+ if (typeof value !== "string" || Number.isNaN(Date.parse(value))) {
2434
+ errors.push({
2435
+ path,
2436
+ message: `${path} must be an ISO timestamp.`
2437
+ });
2438
+ }
2439
+ }
2440
+ function formatValidationErrors2(errors) {
2441
+ return errors.map((error) => `${error.path}: ${error.message}`).join("; ");
2442
+ }
2443
+
2444
+ // src/providerOnboardingDossierImport.ts
2445
+ function parseProviderOnboardingDossierJson(json) {
2446
+ if (typeof json !== "string") {
2447
+ throw new ProbeMeshError({
2448
+ code: "invalid_request",
2449
+ message: "Provider onboarding dossier JSON must be a string."
2450
+ });
2451
+ }
2452
+ let parsed;
2453
+ try {
2454
+ parsed = JSON.parse(json);
2455
+ } catch (cause) {
2456
+ throw new ProbeMeshError({
2457
+ code: "invalid_request",
2458
+ message: "Provider onboarding dossier JSON must be valid JSON.",
2459
+ cause
2460
+ });
2461
+ }
2462
+ assertProviderOnboardingDossier(parsed);
2463
+ return parsed;
2464
+ }
2465
+ function createProviderCatalogFromOnboardingDossiers(options) {
2466
+ assertDossierListOptions(options);
2467
+ const readyArtifacts = options.dossiers.filter((dossier) => dossier.status === "ready").map((dossier) => dossier.artifacts.catalog);
2468
+ return createProviderCatalog({
2469
+ artifacts: readyArtifacts,
2470
+ generatedAt: options.generatedAt
2471
+ });
2472
+ }
2473
+ function evaluateProviderOnboardingDossiers(options) {
2474
+ assertEvaluationOptions2(options);
2475
+ const catalog = createProviderCatalogFromOnboardingDossiers({
2476
+ dossiers: options.dossiers,
2477
+ generatedAt: options.generatedAt
2478
+ });
2479
+ const dossierResults = options.dossiers.map(summarizeDossierImport);
2480
+ const readyDossiers = dossierResults.filter((dossier) => dossier.imported).length;
2481
+ const failedDossiers = dossierResults.length - readyDossiers;
2482
+ const checks = [
2483
+ {
2484
+ name: "dossiers_valid",
2485
+ status: "passed",
2486
+ message: `${options.dossiers.length} provider onboarding dossier(s) are valid.`
2487
+ },
2488
+ readyDossiers > 0 ? {
2489
+ name: "ready_dossiers",
2490
+ status: "passed",
2491
+ message: `${readyDossiers} ready dossier(s) were imported into the buyer catalog.`
2492
+ } : {
2493
+ name: "ready_dossiers",
2494
+ status: "failed",
2495
+ message: "No ready dossiers were available for buyer catalog import."
2496
+ }
2497
+ ];
2498
+ let policyEvaluation;
2499
+ if (options.policy) {
2500
+ policyEvaluation = evaluateProviderCatalogPolicy({
2501
+ catalog,
2502
+ catalogPolicy: options.policy.catalogPolicy,
2503
+ adapterInventory: options.policy.adapterInventory,
2504
+ queries: options.policy.queries
2505
+ });
2506
+ checks.push({
2507
+ name: "catalog_policy",
2508
+ status: policyEvaluation.status === "passed" ? "passed" : "failed",
2509
+ message: policyEvaluation.status === "passed" ? "Imported dossier catalog passed the buyer catalog policy checks." : "Imported dossier catalog failed the buyer catalog policy checks."
2510
+ });
2511
+ }
2512
+ if (failedDossiers > 0) {
2513
+ checks.push({
2514
+ name: "failed_dossiers_excluded",
2515
+ status: "passed",
2516
+ message: `${failedDossiers} failed dossier(s) were kept in the report and excluded from the buyer catalog.`
2517
+ });
2518
+ }
2519
+ const failedChecks = checks.filter((check) => check.status === "failed").length;
2520
+ const catalogSummary = summarizeProviderCatalog(catalog);
2521
+ return {
2522
+ status: failedChecks === 0 ? "passed" : "failed",
2523
+ checks,
2524
+ summary: {
2525
+ ...catalogSummary,
2526
+ totalDossiers: options.dossiers.length,
2527
+ readyDossiers,
2528
+ failedDossiers,
2529
+ importedDossiers: readyDossiers,
2530
+ excludedDossiers: failedDossiers,
2531
+ policyStatus: policyEvaluation?.status
2532
+ },
2533
+ catalog,
2534
+ dossiers: dossierResults,
2535
+ policyEvaluation
2536
+ };
2537
+ }
2538
+ function createProviderOnboardingDossierImportReport(result, options = {}) {
2539
+ const report = {
2540
+ title: options.title ?? "ProbeMesh Provider Onboarding Dossier Import Report",
2541
+ generatedAt: options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
2542
+ status: result.status,
2543
+ summary: cloneSerializable3(result.summary),
2544
+ checks: cloneSerializable3(result.checks),
2545
+ dossiers: cloneSerializable3(result.dossiers),
2546
+ policyEvaluation: cloneSerializable3(result.policyEvaluation)
2547
+ };
2548
+ return sanitizeReport(report, options.forbiddenOutputValues ?? []);
2549
+ }
2550
+ function formatProviderOnboardingDossierImportReport(report, options = {}) {
2551
+ if ((options.format ?? "json") === "markdown") {
2552
+ return formatMarkdownReport(report);
2553
+ }
2554
+ return JSON.stringify(report, null, 2);
2555
+ }
2556
+ function assertDossierListOptions(options) {
2557
+ if (!isRecord8(options)) {
2558
+ throw new ProbeMeshError({
2559
+ code: "invalid_request",
2560
+ message: "Provider onboarding dossier import options must be an object."
2561
+ });
2562
+ }
2563
+ if (!Array.isArray(options.dossiers)) {
2564
+ throw new ProbeMeshError({
2565
+ code: "invalid_request",
2566
+ message: "Provider onboarding dossier import options require dossiers array."
2567
+ });
2568
+ }
2569
+ options.dossiers.forEach((dossier, index) => {
2570
+ const validation = validateProviderOnboardingDossier(dossier);
2571
+ if (!validation.valid) {
2572
+ throw new ProbeMeshError({
2573
+ code: "invalid_request",
2574
+ message: `Invalid provider onboarding dossier at index ${index}: ${formatValidationErrors3(
2575
+ validation.errors
2576
+ )}`
2577
+ });
2578
+ }
2579
+ });
2580
+ if (options.generatedAt !== void 0 && (typeof options.generatedAt !== "string" || Number.isNaN(Date.parse(options.generatedAt)))) {
2581
+ throw new ProbeMeshError({
2582
+ code: "invalid_request",
2583
+ message: "Provider onboarding dossier import generatedAt must be an ISO timestamp."
2584
+ });
2585
+ }
2586
+ }
2587
+ function assertEvaluationOptions2(options) {
2588
+ assertDossierListOptions(options);
2589
+ if (options.dossiers.length === 0) {
2590
+ throw new ProbeMeshError({
2591
+ code: "invalid_request",
2592
+ message: "Provider onboarding dossier evaluation requires at least one dossier."
2593
+ });
2594
+ }
2595
+ if (options.policy === void 0) {
2596
+ return;
2597
+ }
2598
+ if (!isRecord8(options.policy)) {
2599
+ throw new ProbeMeshError({
2600
+ code: "invalid_request",
2601
+ message: "Provider onboarding dossier policy options must be an object."
2602
+ });
2603
+ }
2604
+ if (!Array.isArray(options.policy.adapterInventory)) {
2605
+ throw new ProbeMeshError({
2606
+ code: "invalid_request",
2607
+ message: "Provider onboarding dossier policy requires adapterInventory array."
2608
+ });
2609
+ }
2610
+ if (!Array.isArray(options.policy.queries) || options.policy.queries.length === 0) {
2611
+ throw new ProbeMeshError({
2612
+ code: "invalid_request",
2613
+ message: "Provider onboarding dossier policy requires at least one query."
2614
+ });
2615
+ }
2616
+ }
2617
+ function summarizeDossierImport(dossier) {
2618
+ return {
2619
+ dossierId: dossier.dossierId,
2620
+ providerId: dossier.provider.id,
2621
+ status: dossier.status,
2622
+ catalogArtifactId: dossier.evidence.catalog.artifactId,
2623
+ conformanceArtifactId: dossier.evidence.conformance.artifactId,
2624
+ imported: dossier.status === "ready",
2625
+ reasons: [...dossier.readiness.reasons],
2626
+ failedChecks: [...dossier.readiness.failedChecks]
2627
+ };
2628
+ }
2629
+ function formatMarkdownReport(report) {
2630
+ const lines = [
2631
+ `# ${report.title}`,
2632
+ "",
2633
+ `Status: ${report.status}`,
2634
+ `Generated: ${report.generatedAt}`,
2635
+ "",
2636
+ "## Summary",
2637
+ `- Total dossiers: ${report.summary.totalDossiers}`,
2638
+ `- Ready dossiers: ${report.summary.readyDossiers}`,
2639
+ `- Failed dossiers: ${report.summary.failedDossiers}`,
2640
+ `- Imported dossiers: ${report.summary.importedDossiers}`,
2641
+ `- Excluded dossiers: ${report.summary.excludedDossiers}`,
2642
+ `- Catalog entries: ${report.summary.totalEntries}`,
2643
+ `- Providers: ${formatInlineList(report.summary.providers)}`,
2644
+ `- Capabilities: ${formatInlineList(report.summary.capabilities)}`,
2645
+ `- Policy status: ${report.summary.policyStatus ?? "not_run"}`,
2646
+ "",
2647
+ "## Checks",
2648
+ ...report.checks.map(
2649
+ (check) => `- [${check.status === "passed" ? "x" : " "}] ${check.name}: ${check.message}`
2650
+ ),
2651
+ "",
2652
+ "## Dossiers",
2653
+ ...report.dossiers.map(
2654
+ (dossier) => `- ${dossier.dossierId}: ${dossier.status} / ${dossier.providerId} / ${dossier.imported ? "imported" : "excluded"}`
2655
+ )
2656
+ ];
2657
+ if (report.policyEvaluation) {
2658
+ lines.push(
2659
+ "",
2660
+ "## Policy",
2661
+ `- Status: ${report.policyEvaluation.status}`,
2662
+ `- Routeable matches: ${report.policyEvaluation.summary.routeableMatches}`,
2663
+ `- Missing adapter matches: ${report.policyEvaluation.summary.missingAdapterMatches}`
2664
+ );
2665
+ }
2666
+ return `${lines.join("\n")}
2667
+ `;
2668
+ }
2669
+ function sanitizeReport(value, forbiddenOutputValues) {
2670
+ const forbiddenValues = forbiddenOutputValues.filter((entry) => entry.length > 0);
2671
+ return redactX402Secrets(
2672
+ replaceForbiddenValues(value, forbiddenValues, /* @__PURE__ */ new WeakSet())
2673
+ );
2674
+ }
2675
+ function replaceForbiddenValues(value, forbiddenValues, seen) {
2676
+ if (typeof value === "string") {
2677
+ return forbiddenValues.reduce(
2678
+ (current, forbidden) => current.split(forbidden).join("[REDACTED]"),
2679
+ value
2680
+ );
2681
+ }
2682
+ if (value === null || typeof value !== "object" || value instanceof Date) {
2683
+ return value;
2684
+ }
2685
+ if (seen.has(value)) {
2686
+ return "[Circular]";
2687
+ }
2688
+ seen.add(value);
2689
+ if (Array.isArray(value)) {
2690
+ const entries2 = value.map(
2691
+ (entry) => replaceForbiddenValues(entry, forbiddenValues, seen)
2692
+ );
2693
+ seen.delete(value);
2694
+ return entries2;
2695
+ }
2696
+ const entries = Object.fromEntries(
2697
+ Object.entries(value).map(([key, entry]) => [
2698
+ key,
2699
+ replaceForbiddenValues(entry, forbiddenValues, seen)
2700
+ ])
2701
+ );
2702
+ seen.delete(value);
2703
+ return entries;
2704
+ }
2705
+ function cloneSerializable3(value) {
2706
+ if (value === void 0) {
2707
+ return value;
2708
+ }
2709
+ return JSON.parse(JSON.stringify(value));
2710
+ }
2711
+ function formatInlineList(values) {
2712
+ return values.length > 0 ? values.join(", ") : "none";
2713
+ }
2714
+ function isRecord8(value) {
2715
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2716
+ }
2717
+ function formatValidationErrors3(errors) {
2718
+ return errors.map((error) => `${error.path}: ${error.message}`).join("; ");
2719
+ }
2720
+
2721
+ // src/cli/providerDossierCheckCli.ts
2722
+ var USAGE = "Usage: probemesh-dossier-check --config <path> [--format markdown|json] [--out-json <path>] [--out-md <path>] [--out-catalog <path>] [--title <text>] [--generated-at <iso>]";
2723
+ async function runProviderDossierCheckCli(options = {}) {
2724
+ const argv = options.argv ?? [];
2725
+ const cwd = options.cwd ?? process.cwd();
2726
+ try {
2727
+ const parsedArgs = parseCliArgs(argv);
2728
+ if (parsedArgs.help) {
2729
+ return {
2730
+ exitCode: 0,
2731
+ skipped: true,
2732
+ stdout: `${USAGE}
2733
+ `
2734
+ };
2735
+ }
2736
+ if (!parsedArgs.configPath) {
2737
+ return cliFailure("--config <path> is required.");
2738
+ }
2739
+ const configExport = await loadCliConfig(parsedArgs.configPath, {
2740
+ argv,
2741
+ cwd
2742
+ });
2743
+ if (isCliSkip(configExport)) {
2744
+ return {
2745
+ exitCode: 0,
2746
+ skipped: true,
2747
+ skip: configExport,
2748
+ stdout: `provider dossier check skipped: ${configExport.reason}
2749
+ `
2750
+ };
2751
+ }
2752
+ assertCliConfig(configExport);
2753
+ const dossiers = await resolveDossiers(configExport, cwd);
2754
+ const evaluation = evaluateProviderOnboardingDossiers({
2755
+ dossiers,
2756
+ generatedAt: parsedArgs.generatedAt ?? configExport.catalog?.generatedAt,
2757
+ policy: configExport.policy
2758
+ });
2759
+ const report = createProviderOnboardingDossierImportReport(evaluation, {
2760
+ ...configExport.report ?? {},
2761
+ title: parsedArgs.title ?? configExport.report?.title,
2762
+ generatedAt: parsedArgs.generatedAt ?? configExport.report?.generatedAt
2763
+ });
2764
+ const selectedFormat = parsedArgs.format ?? configExport.report?.format ?? "markdown";
2765
+ const stdout = formatProviderOnboardingDossierImportReport(report, {
2766
+ format: selectedFormat
2767
+ });
2768
+ const artifactPaths = await writeArtifacts({
2769
+ cwd,
2770
+ report,
2771
+ catalog: evaluation.catalog,
2772
+ outputs: {
2773
+ json: parsedArgs.outJson ?? configExport.outputs?.json,
2774
+ markdown: parsedArgs.outMarkdown ?? configExport.outputs?.markdown,
2775
+ catalog: parsedArgs.outCatalog ?? configExport.outputs?.catalog
2776
+ }
2777
+ });
2778
+ return {
2779
+ exitCode: evaluation.status === "passed" ? 0 : 1,
2780
+ skipped: false,
2781
+ evaluation,
2782
+ report,
2783
+ catalog: evaluation.catalog,
2784
+ stdout,
2785
+ artifactPaths
2786
+ };
2787
+ } catch (error) {
2788
+ return cliFailure(
2789
+ error instanceof Error ? error.message : "Unknown provider dossier check CLI failure."
2790
+ );
2791
+ }
2792
+ }
2793
+ function parseCliArgs(argv) {
2794
+ const parsedArgs = {};
2795
+ for (let index = 0; index < argv.length; index += 1) {
2796
+ const arg = argv[index];
2797
+ if (arg === "--") {
2798
+ continue;
2799
+ }
2800
+ if (arg === "--help" || arg === "-h") {
2801
+ parsedArgs.help = true;
2802
+ continue;
2803
+ }
2804
+ if (arg === "--config") {
2805
+ parsedArgs.configPath = requireValue(argv, index, arg);
2806
+ index += 1;
2807
+ continue;
2808
+ }
2809
+ if (arg === "--format") {
2810
+ const format = requireValue(argv, index, arg);
2811
+ if (format !== "markdown" && format !== "json") {
2812
+ throw new Error("--format must be markdown or json.");
2813
+ }
2814
+ parsedArgs.format = format;
2815
+ index += 1;
2816
+ continue;
2817
+ }
2818
+ if (arg === "--out-json") {
2819
+ parsedArgs.outJson = requireValue(argv, index, arg);
2820
+ index += 1;
2821
+ continue;
2822
+ }
2823
+ if (arg === "--out-md") {
2824
+ parsedArgs.outMarkdown = requireValue(argv, index, arg);
2825
+ index += 1;
2826
+ continue;
2827
+ }
2828
+ if (arg === "--out-catalog") {
2829
+ parsedArgs.outCatalog = requireValue(argv, index, arg);
2830
+ index += 1;
2831
+ continue;
2832
+ }
2833
+ if (arg === "--title") {
2834
+ parsedArgs.title = requireValue(argv, index, arg);
2835
+ index += 1;
2836
+ continue;
2837
+ }
2838
+ if (arg === "--generated-at") {
2839
+ parsedArgs.generatedAt = requireValue(argv, index, arg);
2840
+ index += 1;
2841
+ continue;
2842
+ }
2843
+ throw new Error(`Unknown argument "${arg}".`);
2844
+ }
2845
+ return parsedArgs;
2846
+ }
2847
+ function requireValue(argv, index, flag) {
2848
+ const value = argv[index + 1];
2849
+ if (!value || value.startsWith("--")) {
2850
+ throw new Error(`${flag} requires a value.`);
2851
+ }
2852
+ return value;
2853
+ }
2854
+ async function loadCliConfig(configPath, context) {
2855
+ const configExport = await loadCliConfigDefault(configPath, context.cwd);
2856
+ if (typeof configExport === "function") {
2857
+ return configExport(context);
2858
+ }
2859
+ return configExport;
2860
+ }
2861
+ function isCliSkip(value) {
2862
+ return !!value && typeof value === "object" && !Array.isArray(value) && value.skip === true && typeof value.reason === "string";
2863
+ }
2864
+ function assertCliConfig(config) {
2865
+ if (!config || typeof config !== "object" || Array.isArray(config)) {
2866
+ throw new Error("Provider dossier check CLI config must be an object.");
2867
+ }
2868
+ const candidate = config;
2869
+ if (candidate.dossiers !== void 0 && !Array.isArray(candidate.dossiers)) {
2870
+ throw new Error("Provider dossier check CLI dossiers must be an array.");
2871
+ }
2872
+ if (candidate.dossierFiles !== void 0 && (!Array.isArray(candidate.dossierFiles) || candidate.dossierFiles.some((file) => typeof file !== "string"))) {
2873
+ throw new Error("Provider dossier check CLI dossierFiles must be an array of strings.");
2874
+ }
2875
+ if ((candidate.dossiers?.length ?? 0) === 0 && (candidate.dossierFiles?.length ?? 0) === 0) {
2876
+ throw new Error("Provider dossier check CLI config requires dossiers or dossierFiles.");
2877
+ }
2878
+ if (candidate.catalog !== void 0 && !isRecord9(candidate.catalog)) {
2879
+ throw new Error("Provider dossier check CLI catalog config must be an object.");
2880
+ }
2881
+ if (candidate.policy !== void 0 && !isRecord9(candidate.policy)) {
2882
+ throw new Error("Provider dossier check CLI policy config must be an object.");
2883
+ }
2884
+ if (candidate.outputs !== void 0) {
2885
+ assertOutputs(candidate.outputs);
2886
+ }
2887
+ }
2888
+ function assertOutputs(outputs) {
2889
+ if (!isRecord9(outputs)) {
2890
+ throw new Error("Provider dossier check CLI outputs must be an object.");
2891
+ }
2892
+ for (const [key, value] of Object.entries(outputs)) {
2893
+ if (!["json", "markdown", "catalog"].includes(key) || value !== void 0 && typeof value !== "string") {
2894
+ throw new Error(
2895
+ "Provider dossier check CLI outputs may only include json, markdown, and catalog string paths."
2896
+ );
2897
+ }
2898
+ }
2899
+ }
2900
+ async function resolveDossiers(config, cwd) {
2901
+ const dossiers = [
2902
+ ...config.dossiers ?? []
2903
+ ];
2904
+ for (const dossierFile of config.dossierFiles ?? []) {
2905
+ const parsed = JSON.parse(await (0, import_promises2.readFile)((0, import_node_path2.resolve)(cwd, dossierFile), "utf8"));
2906
+ const entries = Array.isArray(parsed) ? parsed : [parsed];
2907
+ for (const entry of entries) {
2908
+ dossiers.push(parseProviderOnboardingDossierJson(JSON.stringify(entry)));
2909
+ }
2910
+ }
2911
+ return dossiers;
2912
+ }
2913
+ async function writeArtifacts(options) {
2914
+ const artifactPaths = {};
2915
+ if (options.outputs.json) {
2916
+ const path = (0, import_node_path2.resolve)(options.cwd, options.outputs.json);
2917
+ await writeTextFile(
2918
+ path,
2919
+ formatProviderOnboardingDossierImportReport(options.report, {
2920
+ format: "json"
2921
+ })
2922
+ );
2923
+ artifactPaths.json = path;
2924
+ }
2925
+ if (options.outputs.markdown) {
2926
+ const path = (0, import_node_path2.resolve)(options.cwd, options.outputs.markdown);
2927
+ await writeTextFile(
2928
+ path,
2929
+ formatProviderOnboardingDossierImportReport(options.report, {
2930
+ format: "markdown"
2931
+ })
2932
+ );
2933
+ artifactPaths.markdown = path;
2934
+ }
2935
+ if (options.outputs.catalog) {
2936
+ const path = (0, import_node_path2.resolve)(options.cwd, options.outputs.catalog);
2937
+ await writeTextFile(path, `${JSON.stringify(options.catalog, null, 2)}
2938
+ `);
2939
+ artifactPaths.catalog = path;
2940
+ }
2941
+ return artifactPaths;
2942
+ }
2943
+ async function writeTextFile(path, body) {
2944
+ await (0, import_promises2.mkdir)((0, import_node_path2.dirname)(path), {
2945
+ recursive: true
2946
+ });
2947
+ await (0, import_promises2.writeFile)(path, body, "utf8");
2948
+ }
2949
+ function cliFailure(message) {
2950
+ return {
2951
+ exitCode: 2,
2952
+ skipped: false,
2953
+ stdout: "",
2954
+ stderr: `Provider dossier check CLI failed: ${message}
2955
+ ${USAGE}
2956
+ `
2957
+ };
2958
+ }
2959
+ function isRecord9(value) {
2960
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2961
+ }
2962
+
2963
+ // src/cli/provider-dossier-check.ts
2964
+ void main();
2965
+ async function main() {
2966
+ const result = await runProviderDossierCheckCli({
2967
+ argv: process.argv.slice(2),
2968
+ cwd: process.cwd()
2969
+ });
2970
+ if (result.stdout) {
2971
+ process.stdout.write(result.stdout);
2972
+ }
2973
+ if (result.stderr) {
2974
+ process.stderr.write(result.stderr);
2975
+ }
2976
+ process.exitCode = result.exitCode;
2977
+ }
2978
+ //# sourceMappingURL=provider-dossier-check.cjs.map