@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 @@
1
+ {"version":3,"sources":["../src/callAuditArtifact.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\n\nimport { ProbeMeshError, isProbeMeshError } from \"./errors\";\nimport { redactX402Secrets } from \"./protocols/x402Redaction\";\nimport type {\n CallStatus,\n Cost,\n ProbeMeshAttemptMetadata,\n ProbeMeshCallRequest,\n ProbeMeshCallResponse,\n ProbeMeshCallSafety,\n ProbeMeshCallTimeline,\n ProbeMeshErrorCode,\n ProbeMeshRetrySafety,\n ProbeMeshRouteMetadata,\n ProbeMeshTimelineEventType,\n ReceiptRef,\n} from \"./types\";\n\nexport const PROBEMESH_CALL_AUDIT_ARTIFACT_SCHEMA_VERSION =\n \"probemesh.call-audit.v1\" as const;\n\nexport type ProbeMeshCallAuditArtifactStatus = \"completed\" | \"failed\";\n\nexport type ProbeMeshCallAuditArtifactFormat = \"json\" | \"markdown\";\n\nexport interface ProbeMeshCallAuditArtifactOptions {\n request: ProbeMeshCallRequest;\n response?: ProbeMeshCallResponse;\n error?: ProbeMeshError;\n generatedAt?: string;\n artifactId?: string;\n forbiddenOutputValues?: string[];\n timeline?: ProbeMeshCallTimeline;\n retrySafety?: ProbeMeshRetrySafety;\n attempt?: ProbeMeshAttemptMetadata;\n route?: ProbeMeshRouteMetadata;\n}\n\nexport interface ProbeMeshCallAuditArtifactHashes {\n request: string;\n route: string;\n timeline: string;\n receipts: string;\n safety: string;\n retrySafety: string;\n artifact: string;\n}\n\nexport interface ProbeMeshCallAuditArtifactReceiptSummary {\n total: number;\n types: string[];\n providers: string[];\n byType: Record<string, number>;\n hasPaymentProof: boolean;\n hasSettlementConfirmation: boolean;\n hasProviderDelivery: boolean;\n}\n\nexport interface ProbeMeshCallAuditArtifactTimelineEvent {\n type: ProbeMeshTimelineEventType;\n timestamp: string;\n provider?: string;\n status?: CallStatus;\n errorCode?: ProbeMeshErrorCode;\n receiptType?: string;\n attestationBundleId?: string;\n}\n\nexport interface ProbeMeshCallAuditArtifactTimelineSummary {\n routeId?: string;\n eventTypes: ProbeMeshTimelineEventType[];\n events: ProbeMeshCallAuditArtifactTimelineEvent[];\n}\n\nexport interface ProbeMeshCallAuditArtifactCallSummary {\n callId?: string;\n capability: string;\n status: ProbeMeshCallAuditArtifactStatus;\n providerId?: string;\n errorCode?: ProbeMeshErrorCode;\n cost?: Cost;\n latencyMs?: number;\n attempt?: ProbeMeshAttemptMetadata;\n}\n\nexport interface ProbeMeshCallAuditArtifactRequestProof {\n requestHash: string;\n idempotencyKey?: string;\n}\n\nexport interface ProbeMeshCallAuditArtifactEvidence {\n receiptSummary: ProbeMeshCallAuditArtifactReceiptSummary;\n receiptRefs: ReceiptRef[];\n safety?: ProbeMeshCallSafety;\n retrySafety?: ProbeMeshRetrySafety;\n route?: ProbeMeshRouteMetadata;\n timeline: ProbeMeshCallAuditArtifactTimelineSummary;\n}\n\nexport interface ProbeMeshCallAuditArtifact {\n schemaVersion: typeof PROBEMESH_CALL_AUDIT_ARTIFACT_SCHEMA_VERSION;\n artifactId: string;\n generatedAt: string;\n status: ProbeMeshCallAuditArtifactStatus;\n hashAlgorithm: \"sha256\";\n hashes: ProbeMeshCallAuditArtifactHashes;\n call: ProbeMeshCallAuditArtifactCallSummary;\n request: ProbeMeshCallAuditArtifactRequestProof;\n evidence: ProbeMeshCallAuditArtifactEvidence;\n}\n\nexport interface ProbeMeshCallAuditArtifactValidationError {\n path: string;\n message: string;\n}\n\nexport interface ProbeMeshCallAuditArtifactValidationResult {\n valid: boolean;\n errors: ProbeMeshCallAuditArtifactValidationError[];\n}\n\nexport function createProbeMeshCallAuditArtifact(\n options: ProbeMeshCallAuditArtifactOptions,\n): ProbeMeshCallAuditArtifact {\n assertAuditArtifactOptions(options);\n\n const requestHash = hashStableJson(options.request);\n const status: ProbeMeshCallAuditArtifactStatus = options.response\n ? \"completed\"\n : \"failed\";\n const callId = options.response?.callId ?? options.error?.callId;\n const capability =\n options.response?.capability ?? options.error?.capability ?? options.request.capability;\n const receiptRefs = cloneSerializable(\n options.response?.receiptRefs ?? options.error?.receiptRefs ?? [],\n );\n const safety = cloneSerializable(\n options.response?.safety ?? options.error?.safety,\n );\n const retrySafety = cloneSerializable(\n options.retrySafety ??\n options.response?.retrySafety ??\n options.error?.retrySafety,\n );\n const attempt = cloneSerializable(\n options.attempt ?? options.response?.attempt ?? options.error?.attempt,\n );\n const route = cloneSerializable(\n options.route ?? options.response?.route ?? options.error?.route,\n );\n const timeline = cloneSerializable(\n options.timeline ?? options.response?.timeline ?? options.error?.timeline,\n );\n const timelineSummary = summarizeTimeline(timeline);\n const baseContent = sanitizeAuditOutput(\n {\n schemaVersion: PROBEMESH_CALL_AUDIT_ARTIFACT_SCHEMA_VERSION,\n artifactId:\n options.artifactId ??\n `call_audit_${callId ?? requestHash.slice(0, 16)}`,\n generatedAt: options.generatedAt ?? new Date().toISOString(),\n status,\n hashAlgorithm: \"sha256\" as const,\n call: {\n callId,\n capability,\n status,\n providerId: options.response?.provider.id ?? options.error?.provider,\n errorCode: options.error?.code,\n cost: cloneSerializable(options.response?.cost),\n latencyMs: options.response?.latencyMs,\n attempt,\n },\n request: {\n requestHash,\n idempotencyKey: options.request.idempotencyKey,\n },\n evidence: {\n receiptSummary: summarizeAuditReceipts(receiptRefs),\n receiptRefs,\n safety,\n retrySafety,\n route,\n timeline: timelineSummary,\n },\n },\n options.forbiddenOutputValues ?? [],\n );\n const hashesWithoutArtifact: ProbeMeshCallAuditArtifactHashes = {\n request: requestHash,\n route: hashStableJson(baseContent.evidence.route ?? null),\n timeline: hashStableJson(baseContent.evidence.timeline),\n receipts: hashStableJson(baseContent.evidence.receiptRefs),\n safety: hashStableJson(baseContent.evidence.safety ?? null),\n retrySafety: hashStableJson(baseContent.evidence.retrySafety ?? null),\n artifact: \"\",\n };\n const artifact: ProbeMeshCallAuditArtifact = {\n ...baseContent,\n hashes: {\n ...hashesWithoutArtifact,\n artifact: hashArtifactContent({\n ...baseContent,\n hashes: hashesWithoutArtifact,\n }),\n },\n };\n\n assertProbeMeshCallAuditArtifact(artifact);\n\n return artifact;\n}\n\nexport function validateProbeMeshCallAuditArtifact(\n artifact: unknown,\n): ProbeMeshCallAuditArtifactValidationResult {\n const errors: ProbeMeshCallAuditArtifactValidationError[] = [];\n\n if (!isRecord(artifact)) {\n return {\n valid: false,\n errors: [\n {\n path: \"$\",\n message: \"ProbeMesh call audit artifact must be an object.\",\n },\n ],\n };\n }\n\n if (artifact.schemaVersion !== PROBEMESH_CALL_AUDIT_ARTIFACT_SCHEMA_VERSION) {\n errors.push({\n path: \"schemaVersion\",\n message: `schemaVersion must be \"${PROBEMESH_CALL_AUDIT_ARTIFACT_SCHEMA_VERSION}\".`,\n });\n }\n\n validateNonEmptyString(artifact.artifactId, \"artifactId\", errors);\n validateIsoTimestamp(artifact.generatedAt, \"generatedAt\", errors);\n\n if (artifact.status !== \"completed\" && artifact.status !== \"failed\") {\n errors.push({\n path: \"status\",\n message: 'status must be \"completed\" or \"failed\".',\n });\n }\n\n if (artifact.hashAlgorithm !== \"sha256\") {\n errors.push({\n path: \"hashAlgorithm\",\n message: 'hashAlgorithm must be \"sha256\".',\n });\n }\n\n validateHashes(artifact.hashes, errors);\n validateCallSummary(artifact.call, artifact.status, errors);\n validateRequestProof(artifact.request, artifact.hashes, errors);\n validateEvidence(artifact.evidence, errors);\n\n if (errors.length === 0) {\n const typedArtifact = artifact as unknown as ProbeMeshCallAuditArtifact;\n\n pushHashMismatch(\n errors,\n \"hashes.route\",\n typedArtifact.hashes.route,\n hashStableJson(typedArtifact.evidence.route ?? null),\n );\n pushHashMismatch(\n errors,\n \"hashes.timeline\",\n typedArtifact.hashes.timeline,\n hashStableJson(typedArtifact.evidence.timeline),\n );\n pushHashMismatch(\n errors,\n \"hashes.receipts\",\n typedArtifact.hashes.receipts,\n hashStableJson(typedArtifact.evidence.receiptRefs),\n );\n pushHashMismatch(\n errors,\n \"hashes.safety\",\n typedArtifact.hashes.safety,\n hashStableJson(typedArtifact.evidence.safety ?? null),\n );\n pushHashMismatch(\n errors,\n \"hashes.retrySafety\",\n typedArtifact.hashes.retrySafety,\n hashStableJson(typedArtifact.evidence.retrySafety ?? null),\n );\n pushHashMismatch(\n errors,\n \"hashes.artifact\",\n typedArtifact.hashes.artifact,\n hashArtifactContent(typedArtifact),\n );\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\nexport function assertProbeMeshCallAuditArtifact(\n artifact: unknown,\n): asserts artifact is ProbeMeshCallAuditArtifact {\n const result = validateProbeMeshCallAuditArtifact(artifact);\n\n if (result.valid) {\n return;\n }\n\n throw new ProbeMeshError({\n code: \"invalid_request\",\n message: `Invalid ProbeMesh call audit artifact: ${formatValidationErrors(\n result.errors,\n )}`,\n });\n}\n\nexport function formatProbeMeshCallAuditArtifact(\n artifact: ProbeMeshCallAuditArtifact,\n options: {\n format?: ProbeMeshCallAuditArtifactFormat;\n } = {},\n) {\n assertProbeMeshCallAuditArtifact(artifact);\n\n if ((options.format ?? \"json\") === \"markdown\") {\n return formatAuditArtifactMarkdown(artifact);\n }\n\n return JSON.stringify(artifact, null, 2);\n}\n\nfunction assertAuditArtifactOptions(\n options: ProbeMeshCallAuditArtifactOptions,\n): asserts options is ProbeMeshCallAuditArtifactOptions {\n if (!isRecord(options)) {\n throw new ProbeMeshError({\n code: \"invalid_request\",\n message: \"ProbeMesh call audit artifact options must be an object.\",\n });\n }\n\n if (!isRecord(options.request)) {\n throw new ProbeMeshError({\n code: \"invalid_request\",\n message: \"ProbeMesh call audit artifact request must be an object.\",\n });\n }\n\n if (\n typeof options.request.capability !== \"string\" ||\n options.request.capability.length === 0\n ) {\n throw new ProbeMeshError({\n code: \"invalid_request\",\n message: \"ProbeMesh call audit artifact request capability is required.\",\n });\n }\n\n if (!(\"input\" in options.request)) {\n throw new ProbeMeshError({\n code: \"invalid_request\",\n message: \"ProbeMesh call audit artifact request input is required for hashing.\",\n });\n }\n\n if (\n (options.response === undefined && options.error === undefined) ||\n (options.response !== undefined && options.error !== undefined)\n ) {\n throw new ProbeMeshError({\n code: \"invalid_request\",\n message:\n \"ProbeMesh call audit artifact requires exactly one response or error.\",\n });\n }\n\n if (options.error !== undefined && !isProbeMeshError(options.error)) {\n throw new ProbeMeshError({\n code: \"invalid_request\",\n message: \"ProbeMesh call audit artifact error must be a ProbeMeshError.\",\n });\n }\n\n if (\n options.generatedAt !== undefined &&\n (typeof options.generatedAt !== \"string\" ||\n Number.isNaN(Date.parse(options.generatedAt)))\n ) {\n throw new ProbeMeshError({\n code: \"invalid_request\",\n message: \"ProbeMesh call audit artifact generatedAt must be an ISO timestamp.\",\n });\n }\n\n if (\n options.artifactId !== undefined &&\n (typeof options.artifactId !== \"string\" || options.artifactId.length === 0)\n ) {\n throw new ProbeMeshError({\n code: \"invalid_request\",\n message: \"ProbeMesh call audit artifact artifactId must be a non-empty string.\",\n });\n }\n\n if (\n options.forbiddenOutputValues !== undefined &&\n (!Array.isArray(options.forbiddenOutputValues) ||\n options.forbiddenOutputValues.some((value) => typeof value !== \"string\"))\n ) {\n throw new ProbeMeshError({\n code: \"invalid_request\",\n message:\n \"ProbeMesh call audit artifact forbiddenOutputValues must be an array of strings.\",\n });\n }\n}\n\nfunction summarizeAuditReceipts(\n receiptRefs: ReceiptRef[],\n): ProbeMeshCallAuditArtifactReceiptSummary {\n const types: string[] = [];\n const providers: string[] = [];\n const byType: Record<string, number> = {};\n\n for (const receiptRef of receiptRefs) {\n if (!types.includes(receiptRef.type)) {\n types.push(receiptRef.type);\n }\n\n if (!providers.includes(receiptRef.provider)) {\n providers.push(receiptRef.provider);\n }\n\n byType[receiptRef.type] = (byType[receiptRef.type] ?? 0) + 1;\n }\n\n return {\n total: receiptRefs.length,\n types,\n providers,\n byType,\n hasPaymentProof: receiptRefs.some(\n (receiptRef) => receiptRef.type === \"payment_proof\",\n ),\n hasSettlementConfirmation: receiptRefs.some(\n (receiptRef) => receiptRef.type === \"settlement_confirmation\",\n ),\n hasProviderDelivery: receiptRefs.some(\n (receiptRef) => receiptRef.type === \"provider_delivery\",\n ),\n };\n}\n\nfunction summarizeTimeline(\n timeline: ProbeMeshCallTimeline | undefined,\n): ProbeMeshCallAuditArtifactTimelineSummary {\n if (!timeline) {\n return {\n eventTypes: [],\n events: [],\n };\n }\n\n return {\n routeId: timeline.routeId,\n eventTypes: timeline.events.map((event) => event.type),\n events: timeline.events.map((event) => ({\n type: event.type,\n timestamp: event.timestamp,\n provider: event.provider,\n status: event.status,\n errorCode: event.errorCode,\n receiptType: event.receiptRef?.type,\n attestationBundleId: event.attestation?.bundleId,\n })),\n };\n}\n\nfunction validateHashes(\n hashes: unknown,\n errors: ProbeMeshCallAuditArtifactValidationError[],\n) {\n if (!isRecord(hashes)) {\n errors.push({\n path: \"hashes\",\n message: \"hashes must be an object.\",\n });\n return;\n }\n\n for (const key of [\n \"request\",\n \"route\",\n \"timeline\",\n \"receipts\",\n \"safety\",\n \"retrySafety\",\n \"artifact\",\n ]) {\n validateSha256String(hashes[key], `hashes.${key}`, errors);\n }\n}\n\nfunction validateCallSummary(\n call: unknown,\n status: unknown,\n errors: ProbeMeshCallAuditArtifactValidationError[],\n) {\n if (!isRecord(call)) {\n errors.push({\n path: \"call\",\n message: \"call must be an object.\",\n });\n return;\n }\n\n validateNonEmptyString(call.capability, \"call.capability\", errors);\n\n if (call.status !== status) {\n errors.push({\n path: \"call.status\",\n message: \"call.status must match artifact status.\",\n });\n }\n\n if (call.callId !== undefined) {\n validateNonEmptyString(call.callId, \"call.callId\", errors);\n }\n\n if (call.providerId !== undefined) {\n validateNonEmptyString(call.providerId, \"call.providerId\", errors);\n }\n\n if (\n call.errorCode !== undefined &&\n (typeof call.errorCode !== \"string\" || call.errorCode.length === 0)\n ) {\n errors.push({\n path: \"call.errorCode\",\n message: \"call.errorCode must be a non-empty string when provided.\",\n });\n }\n\n if (\n call.latencyMs !== undefined &&\n (typeof call.latencyMs !== \"number\" ||\n !Number.isFinite(call.latencyMs) ||\n call.latencyMs < 0)\n ) {\n errors.push({\n path: \"call.latencyMs\",\n message: \"call.latencyMs must be a non-negative finite number.\",\n });\n }\n}\n\nfunction validateRequestProof(\n request: unknown,\n hashes: unknown,\n errors: ProbeMeshCallAuditArtifactValidationError[],\n) {\n if (!isRecord(request)) {\n errors.push({\n path: \"request\",\n message: \"request must be an object.\",\n });\n return;\n }\n\n validateSha256String(request.requestHash, \"request.requestHash\", errors);\n\n if (isRecord(hashes) && hashes.request !== request.requestHash) {\n errors.push({\n path: \"hashes.request\",\n message: \"hashes.request must equal request.requestHash.\",\n });\n }\n\n if (request.idempotencyKey !== undefined) {\n validateNonEmptyString(\n request.idempotencyKey,\n \"request.idempotencyKey\",\n errors,\n );\n }\n}\n\nfunction validateEvidence(\n evidence: unknown,\n errors: ProbeMeshCallAuditArtifactValidationError[],\n) {\n if (!isRecord(evidence)) {\n errors.push({\n path: \"evidence\",\n message: \"evidence must be an object.\",\n });\n return;\n }\n\n validateReceiptSummary(evidence.receiptSummary, errors);\n validateReceiptRefs(evidence.receiptRefs, errors);\n validateTimelineSummary(evidence.timeline, errors);\n}\n\nfunction validateReceiptSummary(\n summary: unknown,\n errors: ProbeMeshCallAuditArtifactValidationError[],\n) {\n if (!isRecord(summary)) {\n errors.push({\n path: \"evidence.receiptSummary\",\n message: \"evidence.receiptSummary must be an object.\",\n });\n return;\n }\n\n if (typeof summary.total !== \"number\" || !Number.isFinite(summary.total)) {\n errors.push({\n path: \"evidence.receiptSummary.total\",\n message: \"evidence.receiptSummary.total must be a number.\",\n });\n }\n\n validateStringArray(summary.types, \"evidence.receiptSummary.types\", errors);\n validateStringArray(\n summary.providers,\n \"evidence.receiptSummary.providers\",\n errors,\n );\n\n if (!isRecord(summary.byType)) {\n errors.push({\n path: \"evidence.receiptSummary.byType\",\n message: \"evidence.receiptSummary.byType must be an object.\",\n });\n }\n\n for (const key of [\n \"hasPaymentProof\",\n \"hasSettlementConfirmation\",\n \"hasProviderDelivery\",\n ]) {\n if (typeof summary[key] !== \"boolean\") {\n errors.push({\n path: `evidence.receiptSummary.${key}`,\n message: `evidence.receiptSummary.${key} must be a boolean.`,\n });\n }\n }\n}\n\nfunction validateReceiptRefs(\n receiptRefs: unknown,\n errors: ProbeMeshCallAuditArtifactValidationError[],\n) {\n if (!Array.isArray(receiptRefs)) {\n errors.push({\n path: \"evidence.receiptRefs\",\n message: \"evidence.receiptRefs must be an array.\",\n });\n return;\n }\n\n receiptRefs.forEach((receiptRef, index) => {\n if (!isRecord(receiptRef)) {\n errors.push({\n path: `evidence.receiptRefs.${index}`,\n message: \"receipt ref must be an object.\",\n });\n return;\n }\n\n for (const key of [\"type\", \"provider\", \"status\", \"ref\", \"timestamp\"]) {\n validateNonEmptyString(\n receiptRef[key],\n `evidence.receiptRefs.${index}.${key}`,\n errors,\n );\n }\n });\n}\n\nfunction validateTimelineSummary(\n timeline: unknown,\n errors: ProbeMeshCallAuditArtifactValidationError[],\n) {\n if (!isRecord(timeline)) {\n errors.push({\n path: \"evidence.timeline\",\n message: \"evidence.timeline must be an object.\",\n });\n return;\n }\n\n if (timeline.routeId !== undefined) {\n validateNonEmptyString(timeline.routeId, \"evidence.timeline.routeId\", errors);\n }\n\n validateStringArray(\n timeline.eventTypes,\n \"evidence.timeline.eventTypes\",\n errors,\n );\n\n if (!Array.isArray(timeline.events)) {\n errors.push({\n path: \"evidence.timeline.events\",\n message: \"evidence.timeline.events must be an array.\",\n });\n return;\n }\n\n timeline.events.forEach((event, index) => {\n if (!isRecord(event)) {\n errors.push({\n path: `evidence.timeline.events.${index}`,\n message: \"timeline event must be an object.\",\n });\n return;\n }\n\n validateNonEmptyString(\n event.type,\n `evidence.timeline.events.${index}.type`,\n errors,\n );\n validateIsoTimestamp(\n event.timestamp,\n `evidence.timeline.events.${index}.timestamp`,\n errors,\n );\n });\n}\n\nfunction hashArtifactContent(artifact: ProbeMeshCallAuditArtifact) {\n return hashStableJson({\n ...artifact,\n hashes: {\n ...artifact.hashes,\n artifact: \"\",\n },\n });\n}\n\nfunction pushHashMismatch(\n errors: ProbeMeshCallAuditArtifactValidationError[],\n path: string,\n expected: string,\n actual: string,\n) {\n if (expected === actual) {\n return;\n }\n\n errors.push({\n path,\n message: `${path} does not match artifact content.`,\n });\n}\n\nfunction hashStableJson(value: unknown) {\n return createHash(\"sha256\").update(stableStringify(value)).digest(\"hex\");\n}\n\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(sortSerializable(value));\n}\n\nfunction sortSerializable(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(sortSerializable);\n }\n\n if (!isRecord(value)) {\n return value;\n }\n\n return Object.fromEntries(\n Object.keys(value)\n .sort()\n .filter((key) => value[key] !== undefined)\n .map((key) => [key, sortSerializable(value[key])]),\n );\n}\n\nfunction sanitizeAuditOutput<T>(value: T, forbiddenOutputValues: string[]) {\n const forbiddenValues = forbiddenOutputValues.filter((entry) => entry.length > 0);\n\n return redactX402Secrets(\n replaceForbiddenValues(cloneSerializable(value), forbiddenValues),\n ) as T;\n}\n\nfunction replaceForbiddenValues(\n value: unknown,\n forbiddenValues: string[],\n): unknown {\n if (typeof value === \"string\") {\n return forbiddenValues.reduce(\n (current, forbidden) => current.split(forbidden).join(\"[REDACTED]\"),\n value,\n );\n }\n\n if (value === null || typeof value !== \"object\" || value instanceof Date) {\n return value;\n }\n\n if (Array.isArray(value)) {\n return value.map((entry) => replaceForbiddenValues(entry, forbiddenValues));\n }\n\n return Object.fromEntries(\n Object.entries(value).map(([key, entry]) => [\n key,\n replaceForbiddenValues(entry, forbiddenValues),\n ]),\n );\n}\n\nfunction cloneSerializable<T>(value: T): T {\n if (value === undefined) {\n return value;\n }\n\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\nfunction formatAuditArtifactMarkdown(artifact: ProbeMeshCallAuditArtifact) {\n const attestation = artifact.evidence.route?.attestation;\n\n return [\n `# ProbeMesh Call Audit Artifact`,\n ``,\n `Status: ${artifact.status}`,\n `Schema: ${artifact.schemaVersion}`,\n `Artifact ID: ${artifact.artifactId}`,\n `Generated: ${artifact.generatedAt}`,\n ``,\n `## Call`,\n `- Call ID: ${artifact.call.callId ?? \"none\"}`,\n `- Capability: ${artifact.call.capability}`,\n `- Provider: ${artifact.call.providerId ?? \"none\"}`,\n `- Error code: ${artifact.call.errorCode ?? \"none\"}`,\n `- Cost USD: ${artifact.call.cost?.amountUsd ?? \"none\"}`,\n `- Request hash: ${artifact.request.requestHash}`,\n ``,\n `## Evidence`,\n `- Receipts: ${artifact.evidence.receiptSummary.total}`,\n `- Receipt types: ${formatInlineList(artifact.evidence.receiptSummary.types)}`,\n `- Payment proof: ${String(artifact.evidence.receiptSummary.hasPaymentProof)}`,\n `- Settlement confirmation: ${String(\n artifact.evidence.receiptSummary.hasSettlementConfirmation,\n )}`,\n `- Provider delivery: ${String(\n artifact.evidence.receiptSummary.hasProviderDelivery,\n )}`,\n `- Money may have moved: ${String(\n artifact.evidence.safety?.moneyMayHaveMoved ?? false,\n )}`,\n `- Retry safe: ${String(\n artifact.evidence.retrySafety?.safeToAutoRetry ?? false,\n )}`,\n `- Route stop: ${\n artifact.evidence.route?.explanation?.stopReason ?? \"none\"\n }`,\n `- Bundle: ${attestation?.bundleId ?? \"none\"}`,\n `- Bundle verified: ${String(attestation?.runtimeVerified ?? false)}`,\n `- Timeline events: ${formatInlineList(\n artifact.evidence.timeline.eventTypes,\n )}`,\n ``,\n `## Hashes`,\n `- Artifact: ${artifact.hashes.artifact}`,\n `- Route: ${artifact.hashes.route}`,\n `- Timeline: ${artifact.hashes.timeline}`,\n `- Receipts: ${artifact.hashes.receipts}`,\n ].join(\"\\n\");\n}\n\nfunction formatInlineList(values: string[]) {\n return values.length === 0 ? \"none\" : values.join(\", \");\n}\n\nfunction validateSha256String(\n value: unknown,\n path: string,\n errors: ProbeMeshCallAuditArtifactValidationError[],\n) {\n if (typeof value !== \"string\" || !/^[a-f0-9]{64}$/.test(value)) {\n errors.push({\n path,\n message: `${path} must be a sha256 hex string.`,\n });\n }\n}\n\nfunction validateNonEmptyString(\n value: unknown,\n path: string,\n errors: ProbeMeshCallAuditArtifactValidationError[],\n) {\n if (typeof value !== \"string\" || value.length === 0) {\n errors.push({\n path,\n message: `${path} must be a non-empty string.`,\n });\n }\n}\n\nfunction validateIsoTimestamp(\n value: unknown,\n path: string,\n errors: ProbeMeshCallAuditArtifactValidationError[],\n) {\n if (typeof value !== \"string\" || Number.isNaN(Date.parse(value))) {\n errors.push({\n path,\n message: `${path} must be an ISO timestamp.`,\n });\n }\n}\n\nfunction validateStringArray(\n value: unknown,\n path: string,\n errors: ProbeMeshCallAuditArtifactValidationError[],\n) {\n if (\n !Array.isArray(value) ||\n value.some((entry) => typeof entry !== \"string\" || entry.length === 0)\n ) {\n errors.push({\n path,\n message: `${path} must be an array of non-empty strings.`,\n });\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction formatValidationErrors(errors: ProbeMeshCallAuditArtifactValidationError[]) {\n return errors.map((error) => `${error.path}: ${error.message}`).join(\"; \");\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,550 @@
1
+ import {
2
+ assertProviderCatalog,
3
+ evaluateProviderCatalogPolicy,
4
+ summarizeProviderCatalog
5
+ } from "./chunk-ZJOLPBJJ.js";
6
+ import {
7
+ ProbeMeshError
8
+ } from "./chunk-2ASMVLG4.js";
9
+
10
+ // src/providerCatalogPolicyBundle.ts
11
+ import { createHash } from "crypto";
12
+ var PROVIDER_CATALOG_POLICY_BUNDLE_SCHEMA_VERSION = "probemesh.catalog-policy-bundle.v1";
13
+ function createProviderCatalogPolicyBundle(options) {
14
+ assertBundleOptions(options);
15
+ const evaluation = options.evaluation ?? evaluateProviderCatalogPolicy({
16
+ catalog: options.catalog,
17
+ catalogPolicy: options.catalogPolicy,
18
+ adapterInventory: options.adapterInventory,
19
+ queries: options.queries
20
+ });
21
+ const hashesWithoutBundle = {
22
+ catalog: hashStableJson(options.catalog),
23
+ catalogPolicy: hashStableJson(options.catalogPolicy ?? null),
24
+ adapterInventory: hashStableJson(options.adapterInventory),
25
+ queries: hashStableJson(options.queries),
26
+ evaluation: hashStableJson(evaluation),
27
+ bundle: ""
28
+ };
29
+ const bundleBase = {
30
+ schemaVersion: PROVIDER_CATALOG_POLICY_BUNDLE_SCHEMA_VERSION,
31
+ bundleId: options.bundleId ?? `catalog_policy_bundle_${hashStableJson({
32
+ catalog: hashesWithoutBundle.catalog,
33
+ catalogPolicy: hashesWithoutBundle.catalogPolicy,
34
+ adapterInventory: hashesWithoutBundle.adapterInventory,
35
+ queries: hashesWithoutBundle.queries
36
+ }).slice(0, 16)}`,
37
+ generatedAt: options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
38
+ status: evaluation.status,
39
+ hashAlgorithm: "sha256",
40
+ hashes: hashesWithoutBundle,
41
+ catalogSummary: summarizeProviderCatalog(options.catalog),
42
+ evaluationSummary: cloneSerializable(evaluation.summary),
43
+ queryCoverage: evaluation.queryResults.map(createQueryCoverage),
44
+ checks: cloneSerializable(evaluation.checks),
45
+ failedChecks: evaluation.checks.filter((check) => check.status === "failed").map((check) => check.name),
46
+ queries: cloneSerializable(options.queries)
47
+ };
48
+ const bundle = {
49
+ ...bundleBase,
50
+ hashes: {
51
+ ...hashesWithoutBundle,
52
+ bundle: hashBundleContent(bundleBase)
53
+ }
54
+ };
55
+ const sanitizedBundle = sanitizeBundleOutput(
56
+ bundle,
57
+ options.forbiddenOutputValues ?? []
58
+ );
59
+ assertProviderCatalogPolicyBundle(sanitizedBundle);
60
+ return sanitizedBundle;
61
+ }
62
+ function validateProviderCatalogPolicyBundle(bundle) {
63
+ const errors = [];
64
+ if (!isRecord(bundle)) {
65
+ return {
66
+ valid: false,
67
+ errors: [
68
+ {
69
+ path: "$",
70
+ message: "Provider catalog policy bundle must be an object."
71
+ }
72
+ ]
73
+ };
74
+ }
75
+ if (bundle.schemaVersion !== PROVIDER_CATALOG_POLICY_BUNDLE_SCHEMA_VERSION) {
76
+ errors.push({
77
+ path: "schemaVersion",
78
+ message: `schemaVersion must be "${PROVIDER_CATALOG_POLICY_BUNDLE_SCHEMA_VERSION}".`
79
+ });
80
+ }
81
+ validateNonEmptyString(bundle.bundleId, "bundleId", errors);
82
+ validateIsoTimestamp(bundle.generatedAt, "generatedAt", errors);
83
+ if (bundle.status !== "passed" && bundle.status !== "failed") {
84
+ errors.push({
85
+ path: "status",
86
+ message: 'status must be "passed" or "failed".'
87
+ });
88
+ }
89
+ if (bundle.hashAlgorithm !== "sha256") {
90
+ errors.push({
91
+ path: "hashAlgorithm",
92
+ message: 'hashAlgorithm must be "sha256".'
93
+ });
94
+ }
95
+ validateHashes(bundle.hashes, errors);
96
+ validateObject(bundle.catalogSummary, "catalogSummary", errors);
97
+ validateObject(bundle.evaluationSummary, "evaluationSummary", errors);
98
+ validateQueryCoverage(bundle.queryCoverage, errors);
99
+ validateCheckArray(bundle.checks, "checks", errors);
100
+ validateStringArray(bundle.failedChecks, "failedChecks", errors);
101
+ if (!Array.isArray(bundle.queries) || bundle.queries.length === 0) {
102
+ errors.push({
103
+ path: "queries",
104
+ message: "queries must be a non-empty array."
105
+ });
106
+ }
107
+ if (errors.length === 0) {
108
+ const expectedBundleHash = hashBundleContent(
109
+ bundle
110
+ );
111
+ if (bundle.hashes.bundle !== expectedBundleHash) {
112
+ errors.push({
113
+ path: "hashes.bundle",
114
+ message: "bundle hash does not match bundle content."
115
+ });
116
+ }
117
+ }
118
+ return {
119
+ valid: errors.length === 0,
120
+ errors
121
+ };
122
+ }
123
+ function assertProviderCatalogPolicyBundle(bundle) {
124
+ const result = validateProviderCatalogPolicyBundle(bundle);
125
+ if (result.valid) {
126
+ return;
127
+ }
128
+ throw new ProbeMeshError({
129
+ code: "invalid_request",
130
+ message: `Invalid provider catalog policy bundle: ${formatValidationErrors(
131
+ result.errors
132
+ )}`
133
+ });
134
+ }
135
+ function formatProviderCatalogPolicyBundle(bundle, options = {}) {
136
+ assertProviderCatalogPolicyBundle(bundle);
137
+ if ((options.format ?? "json") === "markdown") {
138
+ return formatBundleMarkdown(bundle);
139
+ }
140
+ return JSON.stringify(bundle, null, 2);
141
+ }
142
+ function verifyProviderCatalogPolicyBundleRuntime(options) {
143
+ assertRuntimeVerificationOptions(options);
144
+ const errors = [];
145
+ const bundleValidation = validateProviderCatalogPolicyBundle(options.bundle);
146
+ errors.push(...bundleValidation.errors);
147
+ if (options.bundle.status !== "passed") {
148
+ errors.push({
149
+ path: "status",
150
+ message: "Provider catalog policy bundle must have passed evaluation."
151
+ });
152
+ }
153
+ const queries = options.queries ?? options.bundle.queries;
154
+ const evaluation = evaluateProviderCatalogPolicy({
155
+ catalog: options.catalog,
156
+ catalogPolicy: options.catalogPolicy,
157
+ adapterInventory: options.adapterInventory,
158
+ queries
159
+ });
160
+ const runtimeHashes = {
161
+ catalog: hashStableJson(options.catalog),
162
+ catalogPolicy: hashStableJson(options.catalogPolicy ?? null),
163
+ adapterInventory: hashStableJson(options.adapterInventory),
164
+ queries: hashStableJson(queries),
165
+ evaluation: hashStableJson(evaluation)
166
+ };
167
+ pushHashMismatch(
168
+ errors,
169
+ "catalog",
170
+ options.bundle.hashes.catalog,
171
+ runtimeHashes.catalog
172
+ );
173
+ pushHashMismatch(
174
+ errors,
175
+ "catalogPolicy",
176
+ options.bundle.hashes.catalogPolicy,
177
+ runtimeHashes.catalogPolicy
178
+ );
179
+ pushHashMismatch(
180
+ errors,
181
+ "adapterInventory",
182
+ options.bundle.hashes.adapterInventory,
183
+ runtimeHashes.adapterInventory
184
+ );
185
+ pushHashMismatch(
186
+ errors,
187
+ "queries",
188
+ options.bundle.hashes.queries,
189
+ runtimeHashes.queries
190
+ );
191
+ pushHashMismatch(
192
+ errors,
193
+ "evaluation",
194
+ options.bundle.hashes.evaluation,
195
+ runtimeHashes.evaluation
196
+ );
197
+ const queryIndex = options.capability === void 0 ? void 0 : options.bundle.queries.findIndex(
198
+ (query) => query.capability === options.capability
199
+ );
200
+ const covered = options.capability === void 0 ? true : queryIndex !== void 0 && queryIndex >= 0;
201
+ if (!covered) {
202
+ errors.push({
203
+ path: "queries",
204
+ message: `Capability "${options.capability}" is not covered by the policy bundle queries.`
205
+ });
206
+ }
207
+ const valid = errors.length === 0;
208
+ const attestation = {
209
+ schemaVersion: PROVIDER_CATALOG_POLICY_BUNDLE_SCHEMA_VERSION,
210
+ bundleId: options.bundle.bundleId,
211
+ status: options.bundle.status,
212
+ hashAlgorithm: options.bundle.hashAlgorithm,
213
+ bundleHash: options.bundle.hashes.bundle,
214
+ catalogHash: options.bundle.hashes.catalog,
215
+ catalogPolicyHash: options.bundle.hashes.catalogPolicy,
216
+ adapterInventoryHash: options.bundle.hashes.adapterInventory,
217
+ queriesHash: options.bundle.hashes.queries,
218
+ evaluationHash: options.bundle.hashes.evaluation,
219
+ runtimeVerified: valid,
220
+ covered,
221
+ capability: options.capability,
222
+ queryIndex: queryIndex !== void 0 && queryIndex >= 0 ? queryIndex : void 0,
223
+ reason: valid ? "runtime_verified" : errors[0]?.message
224
+ };
225
+ return {
226
+ valid,
227
+ attestation,
228
+ errors,
229
+ coveredQuery: queryIndex !== void 0 && queryIndex >= 0 ? options.bundle.queries[queryIndex] : void 0
230
+ };
231
+ }
232
+ function assertBundleOptions(options) {
233
+ if (!isRecord(options)) {
234
+ throw new ProbeMeshError({
235
+ code: "invalid_request",
236
+ message: "Provider catalog policy bundle options must be an object."
237
+ });
238
+ }
239
+ assertProviderCatalog(options.catalog);
240
+ if (!Array.isArray(options.adapterInventory)) {
241
+ throw new ProbeMeshError({
242
+ code: "invalid_request",
243
+ message: "Provider catalog policy bundle adapterInventory must be an array."
244
+ });
245
+ }
246
+ if (!Array.isArray(options.queries) || options.queries.length === 0) {
247
+ throw new ProbeMeshError({
248
+ code: "invalid_request",
249
+ message: "Provider catalog policy bundle requires at least one query."
250
+ });
251
+ }
252
+ if (options.bundleId !== void 0 && (typeof options.bundleId !== "string" || options.bundleId.length === 0)) {
253
+ throw new ProbeMeshError({
254
+ code: "invalid_request",
255
+ message: "Provider catalog policy bundleId must be a non-empty string."
256
+ });
257
+ }
258
+ if (options.generatedAt !== void 0 && (typeof options.generatedAt !== "string" || Number.isNaN(Date.parse(options.generatedAt)))) {
259
+ throw new ProbeMeshError({
260
+ code: "invalid_request",
261
+ message: "Provider catalog policy bundle generatedAt must be an ISO timestamp."
262
+ });
263
+ }
264
+ }
265
+ function assertRuntimeVerificationOptions(options) {
266
+ if (!isRecord(options)) {
267
+ throw new ProbeMeshError({
268
+ code: "invalid_request",
269
+ message: "Provider catalog policy bundle runtime options must be an object."
270
+ });
271
+ }
272
+ assertProviderCatalogPolicyBundle(options.bundle);
273
+ assertProviderCatalog(options.catalog);
274
+ if (!Array.isArray(options.adapterInventory)) {
275
+ throw new ProbeMeshError({
276
+ code: "invalid_request",
277
+ message: "Provider catalog policy bundle runtime adapterInventory must be an array."
278
+ });
279
+ }
280
+ if (options.queries !== void 0 && !Array.isArray(options.queries)) {
281
+ throw new ProbeMeshError({
282
+ code: "invalid_request",
283
+ message: "Provider catalog policy bundle runtime queries must be an array."
284
+ });
285
+ }
286
+ if (options.capability !== void 0 && (typeof options.capability !== "string" || options.capability.length === 0)) {
287
+ throw new ProbeMeshError({
288
+ code: "invalid_request",
289
+ message: "Provider catalog policy bundle runtime capability must be a string."
290
+ });
291
+ }
292
+ }
293
+ function createQueryCoverage(result) {
294
+ return {
295
+ capability: result.query.capability,
296
+ minMatches: result.query.minMatches ?? 1,
297
+ matches: result.matches.length,
298
+ routeableMatches: result.routeableMatches.length,
299
+ missingAdapterMatches: result.missingAdapterMatches.length,
300
+ providerIds: result.routeableMatches.map((match) => match.providerId)
301
+ };
302
+ }
303
+ function hashStableJson(value) {
304
+ return createHash("sha256").update(stableStringify(value)).digest("hex");
305
+ }
306
+ function hashBundleContent(bundle) {
307
+ return hashStableJson({
308
+ ...bundle,
309
+ hashes: {
310
+ ...bundle.hashes,
311
+ bundle: ""
312
+ }
313
+ });
314
+ }
315
+ function stableStringify(value) {
316
+ return JSON.stringify(sortSerializable(value));
317
+ }
318
+ function sortSerializable(value) {
319
+ if (Array.isArray(value)) {
320
+ return value.map(sortSerializable);
321
+ }
322
+ if (!isRecord(value)) {
323
+ return value;
324
+ }
325
+ return Object.fromEntries(
326
+ Object.keys(value).sort().filter((key) => value[key] !== void 0).map((key) => [key, sortSerializable(value[key])])
327
+ );
328
+ }
329
+ function pushHashMismatch(errors, name, expected, actual) {
330
+ if (expected !== actual) {
331
+ errors.push({
332
+ path: `hashes.${name}`,
333
+ message: `${name} hash does not match runtime input.`
334
+ });
335
+ }
336
+ }
337
+ function formatBundleMarkdown(bundle) {
338
+ const lines = [
339
+ `# Provider Catalog Policy Bundle ${bundle.bundleId}`,
340
+ "",
341
+ `Status: ${bundle.status}`,
342
+ `Generated: ${bundle.generatedAt}`,
343
+ `Bundle hash: ${bundle.hashes.bundle}`,
344
+ "",
345
+ "## Summary",
346
+ `- Catalog entries: ${bundle.catalogSummary.totalEntries}`,
347
+ `- Ready entries: ${bundle.catalogSummary.readyEntries}`,
348
+ `- Queries: ${bundle.queryCoverage.length}`,
349
+ `- Routeable matches: ${bundle.evaluationSummary.routeableMatches}`,
350
+ `- Failed checks: ${bundle.evaluationSummary.failedChecks}`,
351
+ "",
352
+ "## Query Coverage",
353
+ ...bundle.queryCoverage.map(
354
+ (coverage) => `- ${coverage.capability}: ${coverage.routeableMatches}/${coverage.minMatches} routeable (${formatInlineList(
355
+ coverage.providerIds
356
+ )})`
357
+ ),
358
+ "",
359
+ "## Checks",
360
+ ...bundle.checks.map(
361
+ (check) => `- ${check.status === "passed" ? "[x]" : "[ ]"} ${check.name}: ${check.message}`
362
+ )
363
+ ];
364
+ return `${lines.join("\n")}
365
+ `;
366
+ }
367
+ function validateHashes(value, errors) {
368
+ if (!isRecord(value)) {
369
+ errors.push({
370
+ path: "hashes",
371
+ message: "hashes must be an object."
372
+ });
373
+ return;
374
+ }
375
+ for (const key of [
376
+ "catalog",
377
+ "catalogPolicy",
378
+ "adapterInventory",
379
+ "queries",
380
+ "evaluation",
381
+ "bundle"
382
+ ]) {
383
+ validateSha256(value[key], `hashes.${key}`, errors);
384
+ }
385
+ }
386
+ function validateQueryCoverage(value, errors) {
387
+ if (!Array.isArray(value)) {
388
+ errors.push({
389
+ path: "queryCoverage",
390
+ message: "queryCoverage must be an array."
391
+ });
392
+ return;
393
+ }
394
+ value.forEach((coverage, index) => {
395
+ if (!isRecord(coverage)) {
396
+ errors.push({
397
+ path: `queryCoverage.${index}`,
398
+ message: "query coverage entry must be an object."
399
+ });
400
+ return;
401
+ }
402
+ validateNonEmptyString(coverage.capability, `queryCoverage.${index}.capability`, errors);
403
+ validateNonNegativeInteger(
404
+ coverage.minMatches,
405
+ `queryCoverage.${index}.minMatches`,
406
+ errors
407
+ );
408
+ validateNonNegativeInteger(
409
+ coverage.matches,
410
+ `queryCoverage.${index}.matches`,
411
+ errors
412
+ );
413
+ validateNonNegativeInteger(
414
+ coverage.routeableMatches,
415
+ `queryCoverage.${index}.routeableMatches`,
416
+ errors
417
+ );
418
+ validateNonNegativeInteger(
419
+ coverage.missingAdapterMatches,
420
+ `queryCoverage.${index}.missingAdapterMatches`,
421
+ errors
422
+ );
423
+ validateStringArray(coverage.providerIds, `queryCoverage.${index}.providerIds`, errors);
424
+ });
425
+ }
426
+ function validateCheckArray(value, path, errors) {
427
+ if (!Array.isArray(value)) {
428
+ errors.push({
429
+ path,
430
+ message: `${path} must be an array.`
431
+ });
432
+ return;
433
+ }
434
+ value.forEach((check, index) => {
435
+ if (!isRecord(check)) {
436
+ errors.push({
437
+ path: `${path}.${index}`,
438
+ message: "check must be an object."
439
+ });
440
+ return;
441
+ }
442
+ validateNonEmptyString(check.name, `${path}.${index}.name`, errors);
443
+ if (check.status !== "passed" && check.status !== "failed") {
444
+ errors.push({
445
+ path: `${path}.${index}.status`,
446
+ message: 'check status must be "passed" or "failed".'
447
+ });
448
+ }
449
+ validateNonEmptyString(check.message, `${path}.${index}.message`, errors);
450
+ });
451
+ }
452
+ function validateObject(value, path, errors) {
453
+ if (!isRecord(value)) {
454
+ errors.push({
455
+ path,
456
+ message: `${path} must be an object.`
457
+ });
458
+ }
459
+ }
460
+ function validateSha256(value, path, errors) {
461
+ if (typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value)) {
462
+ errors.push({
463
+ path,
464
+ message: `${path} must be a sha256 hex string.`
465
+ });
466
+ }
467
+ }
468
+ function validateNonEmptyString(value, path, errors) {
469
+ if (typeof value !== "string" || value.length === 0) {
470
+ errors.push({
471
+ path,
472
+ message: `${path} must be a non-empty string.`
473
+ });
474
+ }
475
+ }
476
+ function validateStringArray(value, path, errors) {
477
+ if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string" || entry.length === 0)) {
478
+ errors.push({
479
+ path,
480
+ message: `${path} must be an array of non-empty strings.`
481
+ });
482
+ }
483
+ }
484
+ function validateNonNegativeInteger(value, path, errors) {
485
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
486
+ errors.push({
487
+ path,
488
+ message: `${path} must be a non-negative integer.`
489
+ });
490
+ }
491
+ }
492
+ function validateIsoTimestamp(value, path, errors) {
493
+ if (typeof value !== "string" || Number.isNaN(Date.parse(value))) {
494
+ errors.push({
495
+ path,
496
+ message: `${path} must be an ISO timestamp.`
497
+ });
498
+ }
499
+ }
500
+ function sanitizeBundleOutput(value, forbiddenOutputValues) {
501
+ return replaceForbiddenValues(
502
+ cloneSerializable(value),
503
+ forbiddenOutputValues.filter((entry) => entry.length > 0)
504
+ );
505
+ }
506
+ function replaceForbiddenValues(value, forbiddenValues) {
507
+ if (typeof value === "string") {
508
+ return forbiddenValues.reduce(
509
+ (current, forbidden) => current.split(forbidden).join("[REDACTED]"),
510
+ value
511
+ );
512
+ }
513
+ if (value === null || typeof value !== "object" || value instanceof Date) {
514
+ return value;
515
+ }
516
+ if (Array.isArray(value)) {
517
+ return value.map((entry) => replaceForbiddenValues(entry, forbiddenValues));
518
+ }
519
+ return Object.fromEntries(
520
+ Object.entries(value).map(([key, entry]) => [
521
+ key,
522
+ replaceForbiddenValues(entry, forbiddenValues)
523
+ ])
524
+ );
525
+ }
526
+ function cloneSerializable(value) {
527
+ if (value === void 0) {
528
+ return value;
529
+ }
530
+ return JSON.parse(JSON.stringify(value));
531
+ }
532
+ function formatValidationErrors(errors) {
533
+ return errors.map((error) => `${error.path}: ${error.message}`).join("; ");
534
+ }
535
+ function formatInlineList(values) {
536
+ return values.length > 0 ? values.join(", ") : "none";
537
+ }
538
+ function isRecord(value) {
539
+ return !!value && typeof value === "object" && !Array.isArray(value);
540
+ }
541
+
542
+ export {
543
+ PROVIDER_CATALOG_POLICY_BUNDLE_SCHEMA_VERSION,
544
+ createProviderCatalogPolicyBundle,
545
+ validateProviderCatalogPolicyBundle,
546
+ assertProviderCatalogPolicyBundle,
547
+ formatProviderCatalogPolicyBundle,
548
+ verifyProviderCatalogPolicyBundleRuntime
549
+ };
550
+ //# sourceMappingURL=chunk-CXZOO3U4.js.map