settld 0.1.1 → 0.1.5

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 (441) hide show
  1. package/README.md +61 -3
  2. package/SETTLD_VERSION +1 -1
  3. package/bin/settld-mcp +2 -0
  4. package/bin/settld.js +13 -0
  5. package/conformance/kernel-v0/README.md +7 -0
  6. package/conformance/kernel-v0/run.mjs +292 -4
  7. package/docs/ACCESS.md +57 -0
  8. package/docs/ADOPTION_CHECKLIST.md +44 -0
  9. package/docs/ALERTS.md +198 -0
  10. package/docs/ARCHITECTURE.md +69 -0
  11. package/docs/ARCHITECTURE_FOUNDER_GUIDE.md +284 -0
  12. package/docs/ARTIFACTS.md +60 -0
  13. package/docs/CERTIFICATION_CHECKLIST.md +33 -0
  14. package/docs/CIRCLE_SANDBOX_E2E.md +140 -0
  15. package/docs/CONFIG.md +297 -0
  16. package/docs/CONTRACTS_APIS.md +23 -0
  17. package/docs/DEPRECATION.md +31 -0
  18. package/docs/DOMAIN_MODEL.md +92 -0
  19. package/docs/EVENT_ENVELOPE.md +53 -0
  20. package/docs/FINANCE_PACK_FORMAT.md +53 -0
  21. package/docs/INCIDENT_TAXONOMY.md +30 -0
  22. package/docs/JOB_STATE_MACHINE.md +66 -0
  23. package/docs/KERNEL_COMPATIBLE.md +60 -0
  24. package/docs/KERNEL_V0.md +40 -0
  25. package/docs/KEY_ROTATION.md +80 -0
  26. package/docs/LEDGER.md +82 -0
  27. package/docs/LIVENESS.md +76 -0
  28. package/docs/MVP_BUILD_ORDER.md +36 -0
  29. package/docs/ONCALL_PLAYBOOK.md +39 -0
  30. package/docs/OPERATIONS_SIGNING.md +20 -0
  31. package/docs/OVERVIEW.md +190 -0
  32. package/docs/PERF_BASELINE.md +85 -0
  33. package/docs/PRD.md +77 -0
  34. package/docs/QUICKSTART_KERNEL_V0.md +96 -0
  35. package/docs/QUICKSTART_MCP.md +337 -0
  36. package/docs/QUICKSTART_MCP_HOSTS.md +143 -0
  37. package/docs/QUICKSTART_PRODUCE.md +61 -0
  38. package/docs/QUICKSTART_RELEASE_VERIFY.md +39 -0
  39. package/docs/QUICKSTART_SDK.md +125 -0
  40. package/docs/QUICKSTART_SDK_PYTHON.md +111 -0
  41. package/docs/QUICKSTART_VERIFY.md +54 -0
  42. package/docs/QUICKSTART_X402_GATEWAY.md +317 -0
  43. package/docs/README.md +15 -0
  44. package/docs/RELEASE_CHECKLIST.md +156 -0
  45. package/docs/RELEASING.md +81 -0
  46. package/docs/REPO_SETTINGS.md +37 -0
  47. package/docs/RUNBOOK.md +86 -0
  48. package/docs/SKILLS.md +42 -0
  49. package/docs/SKILL_BUNDLE_FORMAT.md +48 -0
  50. package/docs/SLO.md +70 -0
  51. package/docs/SUMMARY.md +16 -0
  52. package/docs/SUPPORT.md +31 -0
  53. package/docs/THREAT_MODEL.md +36 -0
  54. package/docs/TRUST.md +59 -0
  55. package/docs/WORKFLOW.md +35 -0
  56. package/docs/X402_BATCH_SETTLEMENT.md +126 -0
  57. package/docs/blog/2026-02-14-your-ai-agent-just-spent-500-where-is-the-receipt.md +73 -0
  58. package/docs/examples/x402-provider-payout-registry.example.json +14 -0
  59. package/docs/gitbook/README.md +52 -0
  60. package/docs/gitbook/SETUP.md +25 -0
  61. package/docs/gitbook/SUMMARY.md +15 -0
  62. package/docs/gitbook/api-reference.md +73 -0
  63. package/docs/gitbook/closepacks.md +55 -0
  64. package/docs/gitbook/conformance.md +59 -0
  65. package/docs/gitbook/core-primitives.md +85 -0
  66. package/docs/gitbook/dispute-lifecycle.md +33 -0
  67. package/docs/gitbook/faq.md +21 -0
  68. package/docs/gitbook/guides.md +49 -0
  69. package/docs/gitbook/operations-runbook.md +36 -0
  70. package/docs/gitbook/quickstart.md +104 -0
  71. package/docs/gitbook/replay-and-audit.md +30 -0
  72. package/docs/gitbook/sdk-reference.md +35 -0
  73. package/docs/gitbook/security-model.md +58 -0
  74. package/docs/integrations/README.md +14 -0
  75. package/docs/integrations/github-actions-verify.yml +31 -0
  76. package/docs/integrations/github-actions.md +34 -0
  77. package/docs/integrations/openclaw/CLAWHUB_PUBLISH_CHECKLIST.md +65 -0
  78. package/docs/integrations/openclaw/settld-mcp-skill/SKILL.md +69 -0
  79. package/docs/integrations/openclaw/settld-mcp-skill/mcp-server.example.json +12 -0
  80. package/docs/kernel-compatible/capabilities.json +36 -0
  81. package/docs/marketing/agent-commerce-substrate.md +78 -0
  82. package/docs/marketing/hn-repost-2026-02-17.md +102 -0
  83. package/docs/marketing/show-hn-post.md +45 -0
  84. package/docs/ops/ARTIFACT_VERIFICATION_STATUS.md +43 -0
  85. package/docs/ops/BILLING_WEBHOOK_REPLAY.md +105 -0
  86. package/docs/ops/CI_FLAKE_BUDGET.md +31 -0
  87. package/docs/ops/GO_LIVE_GATE_S13.md +27 -0
  88. package/docs/ops/HOSTED_BASELINE_R2.md +129 -0
  89. package/docs/ops/KERNEL_V0_SHIP_GATE.md +67 -0
  90. package/docs/ops/LIGHTHOUSE_PRODUCTION_CLOSE.md +51 -0
  91. package/docs/ops/MCP_COMPATIBILITY_MATRIX.md +28 -0
  92. package/docs/ops/MINIMUM_PRODUCTION_TOPOLOGY.md +89 -0
  93. package/docs/ops/P0_BACKEND_PROGRESS.md +150 -0
  94. package/docs/ops/PAYMENTS_ALPHA_R5.md +105 -0
  95. package/docs/ops/PILOT_ONBOARDING_RUNBOOK.md +112 -0
  96. package/docs/ops/PRODUCTION_DEPLOYMENT_CHECKLIST.md +103 -0
  97. package/docs/ops/R1_SLOS.md +66 -0
  98. package/docs/ops/RELEASE_SIGNING_INCIDENT.md +58 -0
  99. package/docs/ops/SELF_SERVE_LAUNCH_AUTOMATION.md +89 -0
  100. package/docs/ops/THROUGHPUT_DRILL_10X.md +48 -0
  101. package/docs/ops/TRUST_CONFIG_WIZARD.md +47 -0
  102. package/docs/ops/X402_PILOT_WEEKLY_METRICS.md +76 -0
  103. package/docs/ops/tool-call-disputes-holdback.md +52 -0
  104. package/docs/pilot-kit/PILOT_PACKAGE_SCORECARD_X402.md +46 -0
  105. package/docs/pilot-kit/README.md +29 -0
  106. package/docs/pilot-kit/architecture-one-pager.md +48 -0
  107. package/docs/pilot-kit/buyer-email.txt +19 -0
  108. package/docs/pilot-kit/buyer-one-pager.md +31 -0
  109. package/docs/pilot-kit/gtm-pilot-playbook.md +182 -0
  110. package/docs/pilot-kit/offline-verify.md +33 -0
  111. package/docs/pilot-kit/procurement-one-pager.md +50 -0
  112. package/docs/pilot-kit/rfp-clause.md +46 -0
  113. package/docs/pilot-kit/roi-calculator-template.csv +2 -0
  114. package/docs/pilot-kit/security-qa.md +153 -0
  115. package/docs/pilot-kit/security-summary.md +35 -0
  116. package/docs/plans/2026-02-13-mcp-spike-design.md +113 -0
  117. package/docs/spec/AcceptanceCriteria.v1.md +17 -0
  118. package/docs/spec/AcceptanceEvaluation.v1.md +10 -0
  119. package/docs/spec/AgentEvent.v1.md +47 -0
  120. package/docs/spec/AgentIdentity.v1.md +62 -0
  121. package/docs/spec/AgentPassport.v1.md +95 -0
  122. package/docs/spec/AgentReputation.v1.md +59 -0
  123. package/docs/spec/AgentReputation.v2.md +52 -0
  124. package/docs/spec/AgentRun.v1.md +47 -0
  125. package/docs/spec/AgentRunSettlement.v1.md +52 -0
  126. package/docs/spec/AgentWallet.v1.md +43 -0
  127. package/docs/spec/AgreementDelegation.v1.md +109 -0
  128. package/docs/spec/ArbitrationCase.v1.md +67 -0
  129. package/docs/spec/ArbitrationVerdict.v1.md +60 -0
  130. package/docs/spec/BundleHeadAttestation.v1.md +32 -0
  131. package/docs/spec/CANONICAL_JSON.md +31 -0
  132. package/docs/spec/CRYPTOGRAPHY.md +61 -0
  133. package/docs/spec/ClosePack.v1.md +49 -0
  134. package/docs/spec/ClosePackManifest.v1.md +24 -0
  135. package/docs/spec/DelegationGrant.v1.md +90 -0
  136. package/docs/spec/DisputeOpenEnvelope.v1.md +43 -0
  137. package/docs/spec/ERRORS.md +76 -0
  138. package/docs/spec/ESCROW_NETTING_INVARIANTS.md +71 -0
  139. package/docs/spec/EvidenceIndex.v1.md +20 -0
  140. package/docs/spec/ExecutionIntent.v1.md +90 -0
  141. package/docs/spec/FinancePackBundleManifest.v1.md +24 -0
  142. package/docs/spec/FundingHold.v1.md +60 -0
  143. package/docs/spec/GovernancePolicy.v1.md +34 -0
  144. package/docs/spec/GovernancePolicy.v2.md +30 -0
  145. package/docs/spec/INVARIANTS.md +389 -0
  146. package/docs/spec/InteractionDirectionMatrix.v1.md +30 -0
  147. package/docs/spec/InvoiceBundleManifest.v1.md +24 -0
  148. package/docs/spec/InvoiceClaim.v1.md +11 -0
  149. package/docs/spec/MONEY_RAIL_STATE_MACHINE.md +58 -0
  150. package/docs/spec/MarketplaceAcceptance.v2.md +46 -0
  151. package/docs/spec/MarketplaceOffer.v2.md +54 -0
  152. package/docs/spec/MeteringReport.v1.md +18 -0
  153. package/docs/spec/PRODUCER_ERRORS.md +42 -0
  154. package/docs/spec/PricingMatrix.v1.md +20 -0
  155. package/docs/spec/PricingMatrixSignatures.v1.md +30 -0
  156. package/docs/spec/PricingMatrixSignatures.v2.md +29 -0
  157. package/docs/spec/ProduceCliOutput.v1.md +46 -0
  158. package/docs/spec/ProofBundleManifest.v1.md +24 -0
  159. package/docs/spec/README.md +104 -0
  160. package/docs/spec/REFERENCE_IMPLEMENTATIONS.md +29 -0
  161. package/docs/spec/REFERENCE_VERIFIER_BEHAVIOR.md +68 -0
  162. package/docs/spec/REMOTE_SIGNER.md +66 -0
  163. package/docs/spec/ReleaseIndex.v1.md +32 -0
  164. package/docs/spec/ReleaseIndexSignatures.v1.md +17 -0
  165. package/docs/spec/ReleaseTrust.v1.md +13 -0
  166. package/docs/spec/ReleaseTrust.v2.md +26 -0
  167. package/docs/spec/RemoteSignerRequest.v1.md +21 -0
  168. package/docs/spec/RemoteSignerResponse.v1.md +16 -0
  169. package/docs/spec/ReputationEvent.v1.md +63 -0
  170. package/docs/spec/RevocationList.v1.md +28 -0
  171. package/docs/spec/SIGNER_PROVIDER_PLUGIN.md +32 -0
  172. package/docs/spec/STRICTNESS.md +68 -0
  173. package/docs/spec/SUPPLY_CHAIN.md +33 -0
  174. package/docs/spec/SettlementAdjustment.v1.md +45 -0
  175. package/docs/spec/SettlementDecisionRecord.v1.md +48 -0
  176. package/docs/spec/SettlementDecisionRecord.v2.md +51 -0
  177. package/docs/spec/SettlementDecisionReport.v1.md +44 -0
  178. package/docs/spec/SettlementKernel.v1.md +59 -0
  179. package/docs/spec/SettlementReceipt.v1.md +63 -0
  180. package/docs/spec/SlaDefinition.v1.md +24 -0
  181. package/docs/spec/SlaEvaluation.v1.md +12 -0
  182. package/docs/spec/THREAT_MODEL.md +113 -0
  183. package/docs/spec/TOOL_PROVENANCE.md +30 -0
  184. package/docs/spec/TRUST_ANCHORS.md +84 -0
  185. package/docs/spec/TenantSettings.v1.md +90 -0
  186. package/docs/spec/TenantSettings.v2.md +99 -0
  187. package/docs/spec/TimestampProof.v1.md +25 -0
  188. package/docs/spec/ToolCallAgreement.v1.md +34 -0
  189. package/docs/spec/ToolCallEvidence.v1.md +47 -0
  190. package/docs/spec/ToolManifest.v1.md +47 -0
  191. package/docs/spec/VERIFIER_ENVIRONMENT.md +38 -0
  192. package/docs/spec/VERSIONING.md +107 -0
  193. package/docs/spec/VerificationReport.v1.md +50 -0
  194. package/docs/spec/VerifyAboutOutput.v1.md +10 -0
  195. package/docs/spec/VerifyCliOutput.v1.md +28 -0
  196. package/docs/spec/WARNINGS.md +83 -0
  197. package/docs/spec/error-codes.v1.txt +285 -0
  198. package/docs/spec/examples/agreement_delegation_v1.example.json +21 -0
  199. package/docs/spec/examples/arbitration_case_v1.example.json +26 -0
  200. package/docs/spec/examples/arbitration_verdict_v1.example.json +32 -0
  201. package/docs/spec/examples/dispute_open_envelope_v1.example.json +18 -0
  202. package/docs/spec/examples/produce_cli_output_v1.example.json +32 -0
  203. package/docs/spec/examples/release_index_signature_v1.example.json +9 -0
  204. package/docs/spec/examples/release_index_signatures_v1.example.json +14 -0
  205. package/docs/spec/examples/release_index_v1.example.json +15 -0
  206. package/docs/spec/examples/release_trust_v1.example.json +7 -0
  207. package/docs/spec/examples/release_trust_v2.example.json +22 -0
  208. package/docs/spec/examples/remote_signer_request_v1.example.json +18 -0
  209. package/docs/spec/examples/remote_signer_response_v1.example.json +8 -0
  210. package/docs/spec/examples/reputation_event_v1.example.json +29 -0
  211. package/docs/spec/examples/verification_report_v1.example.json +24 -0
  212. package/docs/spec/examples/verify_about_output_v1.example.json +29 -0
  213. package/docs/spec/examples/verify_cli_output_v1.example.json +13 -0
  214. package/docs/spec/legacy/MarketplaceAcceptance.v1.md +48 -0
  215. package/docs/spec/legacy/MarketplaceOffer.v1.md +56 -0
  216. package/docs/spec/legacy/schemas/MarketplaceAcceptance.v1.schema.json +53 -0
  217. package/docs/spec/legacy/schemas/MarketplaceOffer.v1.schema.json +61 -0
  218. package/docs/spec/producer-error-codes.v1.txt +14 -0
  219. package/docs/spec/schemas/AcceptanceCriteria.v1.schema.json +24 -0
  220. package/docs/spec/schemas/AcceptanceEvaluation.v1.schema.json +26 -0
  221. package/docs/spec/schemas/AgentEvent.v1.schema.json +49 -0
  222. package/docs/spec/schemas/AgentIdentity.v1.schema.json +129 -0
  223. package/docs/spec/schemas/AgentPassport.v1.schema.json +112 -0
  224. package/docs/spec/schemas/AgentReputation.v1.schema.json +151 -0
  225. package/docs/spec/schemas/AgentReputation.v2.schema.json +120 -0
  226. package/docs/spec/schemas/AgentRun.v1.schema.json +71 -0
  227. package/docs/spec/schemas/AgentRunSettlement.v1.schema.json +75 -0
  228. package/docs/spec/schemas/AgentWallet.v1.schema.json +54 -0
  229. package/docs/spec/schemas/AgreementDelegation.v1.schema.json +50 -0
  230. package/docs/spec/schemas/ArbitrationCase.v1.schema.json +133 -0
  231. package/docs/spec/schemas/ArbitrationVerdict.v1.schema.json +149 -0
  232. package/docs/spec/schemas/BundleHeadAttestation.v1.schema.json +21 -0
  233. package/docs/spec/schemas/ClosePackManifest.v1.schema.json +38 -0
  234. package/docs/spec/schemas/DelegationGrant.v1.schema.json +102 -0
  235. package/docs/spec/schemas/DisputeOpenEnvelope.v1.schema.json +78 -0
  236. package/docs/spec/schemas/EvidenceIndex.v1.schema.json +41 -0
  237. package/docs/spec/schemas/ExecutionIntent.v1.schema.json +85 -0
  238. package/docs/spec/schemas/FinancePackBundleManifest.v1.schema.json +38 -0
  239. package/docs/spec/schemas/FundingHold.v1.schema.json +46 -0
  240. package/docs/spec/schemas/GovernancePolicy.v1.schema.json +45 -0
  241. package/docs/spec/schemas/GovernancePolicy.v2.schema.json +70 -0
  242. package/docs/spec/schemas/InteractionDirectionMatrix.v1.schema.json +43 -0
  243. package/docs/spec/schemas/InvoiceBundleManifest.v1.schema.json +38 -0
  244. package/docs/spec/schemas/InvoiceClaim.v1.schema.json +39 -0
  245. package/docs/spec/schemas/MarketplaceAcceptance.v2.schema.json +53 -0
  246. package/docs/spec/schemas/MarketplaceOffer.v2.schema.json +61 -0
  247. package/docs/spec/schemas/MeteringReport.v1.schema.json +45 -0
  248. package/docs/spec/schemas/PricingMatrix.v1.schema.json +24 -0
  249. package/docs/spec/schemas/PricingMatrixSignatures.v1.schema.json +24 -0
  250. package/docs/spec/schemas/PricingMatrixSignatures.v2.schema.json +24 -0
  251. package/docs/spec/schemas/ProduceCliOutput.v1.schema.json +107 -0
  252. package/docs/spec/schemas/ProofBundleManifest.v1.schema.json +37 -0
  253. package/docs/spec/schemas/PublicKeys.v1.schema.json +33 -0
  254. package/docs/spec/schemas/ReleaseIndex.v1.schema.json +45 -0
  255. package/docs/spec/schemas/ReleaseIndexSignature.v1.schema.json +16 -0
  256. package/docs/spec/schemas/ReleaseIndexSignatures.v1.schema.json +16 -0
  257. package/docs/spec/schemas/ReleaseTrust.v1.schema.json +15 -0
  258. package/docs/spec/schemas/ReleaseTrust.v2.schema.json +37 -0
  259. package/docs/spec/schemas/RemoteSignerPublicKeyResponse.v1.schema.json +14 -0
  260. package/docs/spec/schemas/RemoteSignerRequest.v1.schema.json +24 -0
  261. package/docs/spec/schemas/RemoteSignerResponse.v1.schema.json +10 -0
  262. package/docs/spec/schemas/RemoteSignerSignRequest.v1.schema.json +27 -0
  263. package/docs/spec/schemas/RemoteSignerSignResponse.v1.schema.json +16 -0
  264. package/docs/spec/schemas/ReputationEvent.v1.schema.json +164 -0
  265. package/docs/spec/schemas/RevocationList.v1.schema.json +51 -0
  266. package/docs/spec/schemas/SettlementAdjustment.v1.schema.json +44 -0
  267. package/docs/spec/schemas/SettlementDecisionRecord.v1.schema.json +66 -0
  268. package/docs/spec/schemas/SettlementDecisionRecord.v2.schema.json +148 -0
  269. package/docs/spec/schemas/SettlementDecisionReport.v1.schema.json +61 -0
  270. package/docs/spec/schemas/SettlementReceipt.v1.schema.json +135 -0
  271. package/docs/spec/schemas/SlaDefinition.v1.schema.json +33 -0
  272. package/docs/spec/schemas/SlaEvaluation.v1.schema.json +26 -0
  273. package/docs/spec/schemas/TenantSettings.v1.schema.json +90 -0
  274. package/docs/spec/schemas/TenantSettings.v2.schema.json +161 -0
  275. package/docs/spec/schemas/TimestampProof.v1.schema.json +17 -0
  276. package/docs/spec/schemas/ToolCallAgreement.v1.schema.json +34 -0
  277. package/docs/spec/schemas/ToolCallEvidence.v1.schema.json +45 -0
  278. package/docs/spec/schemas/ToolManifest.v1.schema.json +54 -0
  279. package/docs/spec/schemas/VerificationReport.v1.schema.json +83 -0
  280. package/docs/spec/schemas/VerifyAboutOutput.v1.schema.json +54 -0
  281. package/docs/spec/schemas/VerifyCliOutput.v1.schema.json +75 -0
  282. package/docs/spec/schemas/VerifyReleaseOutput.v1.schema.json +47 -0
  283. package/docs/spec/x402-error-codes.v1.txt +21 -0
  284. package/docs/templates/buyer-email.txt +18 -0
  285. package/docs/templates/buyer-one-pager.md +24 -0
  286. package/package.json +40 -6
  287. package/scripts/acceptance/full-stack.mjs +734 -0
  288. package/scripts/acceptance/full-stack.sh +99 -0
  289. package/scripts/audit/build-audit-packet.mjs +242 -0
  290. package/scripts/backup-pg.sh +45 -0
  291. package/scripts/backup-restore/README.md +18 -0
  292. package/scripts/backup-restore/capture-state.mjs +130 -0
  293. package/scripts/backup-restore/client.mjs +97 -0
  294. package/scripts/backup-restore/seed-workload.mjs +235 -0
  295. package/scripts/backup-restore/verify-state.mjs +139 -0
  296. package/scripts/backup-restore-test.sh +217 -0
  297. package/scripts/chaos.js +221 -0
  298. package/scripts/ci/build-launch-cutover-packet.mjs +148 -0
  299. package/scripts/ci/build-self-serve-benchmark-report.mjs +122 -0
  300. package/scripts/ci/changelog-guard.mjs +145 -0
  301. package/scripts/ci/check-kernel-v0-launch-gate.mjs +233 -0
  302. package/scripts/ci/check-secret-hygiene.mjs +78 -0
  303. package/scripts/ci/check-version-consistency.mjs +42 -0
  304. package/scripts/ci/cli-pack-smoke.mjs +160 -0
  305. package/scripts/ci/flake-budget-guard.mjs +68 -0
  306. package/scripts/ci/generate-error-codes.mjs +54 -0
  307. package/scripts/ci/lib/lighthouse-tracker.mjs +90 -0
  308. package/scripts/ci/lib/self-serve-launch-gate.mjs +89 -0
  309. package/scripts/ci/npm-pack-smoke.mjs +454 -0
  310. package/scripts/ci/run-10x-throughput-drill.mjs +246 -0
  311. package/scripts/ci/run-10x-throughput-incident-rehearsal.mjs +325 -0
  312. package/scripts/ci/run-arbitration-workspace-browser-e2e.sh +22 -0
  313. package/scripts/ci/run-circle-sandbox-smoke.mjs +237 -0
  314. package/scripts/ci/run-go-live-gate.mjs +150 -0
  315. package/scripts/ci/run-kernel-v0-ship-gate.mjs +97 -0
  316. package/scripts/ci/run-mcp-host-smoke.mjs +275 -0
  317. package/scripts/ci/run-self-serve-launch-gate.mjs +56 -0
  318. package/scripts/ci/runtime-import-smoke.mjs +58 -0
  319. package/scripts/ci/update-lighthouse-tracker.mjs +112 -0
  320. package/scripts/closepack/lib.mjs +286 -0
  321. package/scripts/collect-debug.sh +263 -0
  322. package/scripts/demo/compositional-settlement-3hop.mjs +237 -0
  323. package/scripts/demo/delivery-robot/export-ui-fixture.mjs +188 -0
  324. package/scripts/demo/delivery-robot/generate.mjs +377 -0
  325. package/scripts/demo/kernel-agent-goes-shopping.mjs +202 -0
  326. package/scripts/demo/magic-link-first-green.mjs +118 -0
  327. package/scripts/demo/magic-link-kind-smoke.mjs +577 -0
  328. package/scripts/demo/mcp-paid-exa.mjs +1110 -0
  329. package/scripts/dev/billing-doctor.sh +145 -0
  330. package/scripts/dev/billing-smoke-prod.sh +219 -0
  331. package/scripts/dev/billing-webhook-replay.sh +161 -0
  332. package/scripts/dev/env.dev.example +29 -0
  333. package/scripts/dev/env.sh +37 -0
  334. package/scripts/dev/new-sdk-key.sh +81 -0
  335. package/scripts/dev/sdk-first-run.sh +21 -0
  336. package/scripts/dev/smoke-x402-gateway.sh +115 -0
  337. package/scripts/dev/start-api.sh +24 -0
  338. package/scripts/examples/produce-and-verify-jobproof.mjs +191 -0
  339. package/scripts/examples/sdk-first-paid-rfq.py +105 -0
  340. package/scripts/examples/sdk-first-verified-run.mjs +85 -0
  341. package/scripts/examples/sdk-first-verified-run.py +99 -0
  342. package/scripts/examples/sdk-tenant-analytics.mjs +103 -0
  343. package/scripts/examples/sdk-tenant-analytics.py +118 -0
  344. package/scripts/finance-pack/bundle.mjs +284 -0
  345. package/scripts/fixtures/generate-bundle-fixtures.mjs +877 -0
  346. package/scripts/governance/export.mjs +169 -0
  347. package/scripts/load/delivery-stress.k6.js +183 -0
  348. package/scripts/load/ingest-burst.k6.js +236 -0
  349. package/scripts/load/run-delivery-load.js +66 -0
  350. package/scripts/load/webhook-receiver.js +131 -0
  351. package/scripts/magic-link/migrate-run-records-to-db.mjs +35 -0
  352. package/scripts/mcp/probe.mjs +238 -0
  353. package/scripts/mcp/settld-mcp-http-gateway.mjs +178 -0
  354. package/scripts/mcp/settld-mcp-server.mjs +1201 -0
  355. package/scripts/openapi/write.mjs +13 -0
  356. package/scripts/ops/bootstrap-tenant-conformance.mjs +185 -0
  357. package/scripts/ops/build-x402-pilot-reliability-report.mjs +489 -0
  358. package/scripts/ops/check-x402-receipt-sample.mjs +181 -0
  359. package/scripts/ops/design-partner-run-packet.mjs +466 -0
  360. package/scripts/ops/hosted-baseline-evidence.mjs +681 -0
  361. package/scripts/ops/money-rails-chargeback-evidence.mjs +509 -0
  362. package/scripts/ops/money-rails-reconcile-evidence.mjs +180 -0
  363. package/scripts/ops/p0-seed-money-rail-operation.mjs +432 -0
  364. package/scripts/pilot/finance-pack.mjs +495 -0
  365. package/scripts/pilot/fixtures/robot-keypair.json +4 -0
  366. package/scripts/pilot/fixtures/server-signer.json +4 -0
  367. package/scripts/proof-bundle/job.mjs +109 -0
  368. package/scripts/proof-bundle/lib.mjs +92 -0
  369. package/scripts/proof-bundle/month.mjs +103 -0
  370. package/scripts/provider/conformance-run.mjs +159 -0
  371. package/scripts/provider/keys-generate.mjs +135 -0
  372. package/scripts/provider/publish.mjs +420 -0
  373. package/scripts/quickstart/x402.mjs +334 -0
  374. package/scripts/release/build-artifacts.mjs +181 -0
  375. package/scripts/release/generate-release-index.mjs +112 -0
  376. package/scripts/release/release-index-lib.mjs +232 -0
  377. package/scripts/release/sign-release-index.mjs +85 -0
  378. package/scripts/release/validate-release-assets.mjs +170 -0
  379. package/scripts/release/verify-release.mjs +261 -0
  380. package/scripts/restore-pg.sh +34 -0
  381. package/scripts/scaffold/create-settld-paid-tool.mjs +19 -0
  382. package/scripts/sdk/smoke-python.py +30 -0
  383. package/scripts/sdk/smoke.mjs +16 -0
  384. package/scripts/settlement/x402-batch-worker.mjs +1091 -0
  385. package/scripts/slo/check.mjs +178 -0
  386. package/scripts/smoke/k8s-smoke.mjs +214 -0
  387. package/scripts/spec/generate-protocol-vectors.mjs +931 -0
  388. package/scripts/test/check-no-generated-artifacts.sh +12 -0
  389. package/scripts/test/run.sh +45 -0
  390. package/scripts/trust/validate-trust-file.mjs +57 -0
  391. package/scripts/trust-config/rotate-settld-pay.mjs +277 -0
  392. package/scripts/trust-config/wizard.mjs +161 -0
  393. package/scripts/vendor-contract-test-lib.mjs +182 -0
  394. package/scripts/vendor-contract-test.mjs +55 -0
  395. package/scripts/vercel/build-mkdocs.sh +9 -0
  396. package/scripts/vercel/ignore-mkdocs.sh +25 -0
  397. package/scripts/vercel/install-mkdocs.sh +6 -0
  398. package/scripts/verify-pg.js +217 -0
  399. package/scripts/x402/receipt-verify.mjs +289 -0
  400. package/services/finance-sink/src/dedupe-store.js +29 -6
  401. package/services/receiver/src/dedupe-store.js +29 -5
  402. package/services/x402-gateway/Dockerfile +13 -0
  403. package/services/x402-gateway/README.md +58 -0
  404. package/services/x402-gateway/examples/upstream-mock.js +337 -0
  405. package/services/x402-gateway/src/server.js +947 -0
  406. package/src/api/app.js +32517 -16877
  407. package/src/api/maintenance.js +70 -0
  408. package/src/api/openapi.js +1130 -17
  409. package/src/api/persistence.js +272 -0
  410. package/src/api/server.js +81 -5
  411. package/src/api/store.js +1248 -6
  412. package/src/api/workers/deliveries.js +99 -4
  413. package/src/api/workers/insolvency-sweep.js +159 -0
  414. package/src/core/agent-card.js +69 -0
  415. package/src/core/agent-wallets.js +97 -0
  416. package/src/core/agreement-delegation.js +549 -0
  417. package/src/core/billing-plans.js +40 -6
  418. package/src/core/circle-reserve-adapter.js +845 -0
  419. package/src/core/maintenance-locks.js +1 -0
  420. package/src/core/paid-tool-manifest.js +318 -0
  421. package/src/core/provider-publish-conformance.js +525 -0
  422. package/src/core/provider-publish-proof.js +396 -0
  423. package/src/core/provider-quote-signature.js +170 -0
  424. package/src/core/settld-keys.js +112 -0
  425. package/src/core/settld-pay-token.js +344 -0
  426. package/src/core/settlement-kernel.js +213 -2
  427. package/src/core/settlement-verifier.js +335 -0
  428. package/src/core/tool-call-agreement.js +112 -0
  429. package/src/core/tool-call-evidence.js +144 -0
  430. package/src/core/tool-provider-signature.js +98 -0
  431. package/src/core/x402-escalation-override.js +258 -0
  432. package/src/core/x402-gate.js +118 -0
  433. package/src/core/x402-provider-refund-decision.js +220 -0
  434. package/src/core/x402-receipt-verifier.js +708 -0
  435. package/src/core/x402-reversal-command.js +251 -0
  436. package/src/core/x402-wallet-issuer-decision.js +252 -0
  437. package/src/core/zk-verifier.js +300 -0
  438. package/src/db/migrations/029_reputation_event_index.sql +54 -0
  439. package/src/db/migrations/030_artifacts_source_event_unique_job_only.sql +15 -0
  440. package/src/db/pg.js +18 -7
  441. package/src/db/store-pg.js +838 -72
@@ -0,0 +1,344 @@
1
+ import { canonicalJsonStringify, normalizeForCanonicalJson } from "./canonical-json.js";
2
+ import { keyIdFromPublicKeyPem, sha256Hex, signHashHexEd25519, verifyHashHexEd25519 } from "./crypto.js";
3
+ import { keyMapFromSettldKeyset } from "./settld-keys.js";
4
+
5
+ export const SETTLD_PAY_TOKEN_VERSION = 1;
6
+ export const SETTLD_PAY_TOKEN_TTL_SECONDS = 300;
7
+
8
+ function assertNonEmptyString(value, name) {
9
+ if (typeof value !== "string" || value.trim() === "") throw new TypeError(`${name} must be a non-empty string`);
10
+ return String(value).trim();
11
+ }
12
+
13
+ function normalizeCurrency(value, name) {
14
+ const raw = typeof value === "string" && value.trim() !== "" ? value : "USD";
15
+ const out = raw.trim().toUpperCase();
16
+ if (!/^[A-Z][A-Z0-9_]{2,11}$/.test(out)) throw new TypeError(`${name} must match ^[A-Z][A-Z0-9_]{2,11}$`);
17
+ return out;
18
+ }
19
+
20
+ function normalizePositiveSafeInt(value, name) {
21
+ const n = Number(value);
22
+ if (!Number.isSafeInteger(n) || n <= 0) throw new TypeError(`${name} must be a positive safe integer`);
23
+ return n;
24
+ }
25
+
26
+ function normalizeUnixSeconds(value, name) {
27
+ const n = Number(value);
28
+ if (!Number.isSafeInteger(n) || n <= 0) throw new TypeError(`${name} must be a positive safe integer unix timestamp`);
29
+ return n;
30
+ }
31
+
32
+ function normalizeHexHash(value, name) {
33
+ const s = assertNonEmptyString(value, name).toLowerCase();
34
+ if (!/^[0-9a-f]{64}$/.test(s)) throw new TypeError(`${name} must be a 64-hex sha256`);
35
+ return s;
36
+ }
37
+
38
+ function normalizeOptionalHexHash(value, name) {
39
+ if (value === null || value === undefined || String(value).trim() === "") return null;
40
+ return normalizeHexHash(value, name);
41
+ }
42
+
43
+ function normalizeOptionalRequestBindingMode(value, name) {
44
+ if (value === null || value === undefined || String(value).trim() === "") return null;
45
+ const mode = String(value).trim().toLowerCase();
46
+ if (mode !== "strict") throw new TypeError(`${name} must be strict when provided`);
47
+ return mode;
48
+ }
49
+
50
+ function normalizeOptionalId(value, name, { max = 200 } = {}) {
51
+ if (value === null || value === undefined || String(value).trim() === "") return null;
52
+ const out = String(value).trim();
53
+ if (out.length > max) throw new TypeError(`${name} must be <= ${max} chars`);
54
+ if (!/^[A-Za-z0-9:_-]+$/.test(out)) throw new TypeError(`${name} must match ^[A-Za-z0-9:_-]+$`);
55
+ return out;
56
+ }
57
+
58
+ function normalizeOptionalString(value, name, { max = 256 } = {}) {
59
+ if (value === null || value === undefined || String(value).trim() === "") return null;
60
+ const out = String(value).trim();
61
+ if (out.length > max) throw new TypeError(`${name} must be <= ${max} chars`);
62
+ return out;
63
+ }
64
+
65
+ function normalizeOptionalPositiveSafeInt(value, name) {
66
+ if (value === null || value === undefined || String(value).trim() === "") return null;
67
+ return normalizePositiveSafeInt(value, name);
68
+ }
69
+
70
+ function decodeEnvelope(token) {
71
+ const raw = assertNonEmptyString(token, "token");
72
+ let decoded = null;
73
+ try {
74
+ decoded = Buffer.from(raw, "base64url").toString("utf8");
75
+ } catch (err) {
76
+ throw new TypeError(`token is not valid base64url: ${err?.message ?? String(err ?? "")}`);
77
+ }
78
+ let parsed;
79
+ try {
80
+ parsed = JSON.parse(decoded);
81
+ } catch (err) {
82
+ throw new TypeError(`token is not valid JSON envelope: ${err?.message ?? String(err ?? "")}`);
83
+ }
84
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new TypeError("token envelope must be an object");
85
+ if (Number(parsed.v) !== SETTLD_PAY_TOKEN_VERSION) throw new TypeError(`token envelope version must be ${SETTLD_PAY_TOKEN_VERSION}`);
86
+ const kid = assertNonEmptyString(parsed.kid, "token.kid");
87
+ if (!parsed.payload || typeof parsed.payload !== "object" || Array.isArray(parsed.payload)) {
88
+ throw new TypeError("token.payload must be an object");
89
+ }
90
+ const sig = assertNonEmptyString(parsed.sig, "token.sig");
91
+ return { envelope: parsed, kid, payload: parsed.payload, sig };
92
+ }
93
+
94
+ export function buildSettldPayPayloadV1({
95
+ iss = "settld",
96
+ aud,
97
+ gateId,
98
+ authorizationRef,
99
+ amountCents,
100
+ currency = "USD",
101
+ payeeProviderId,
102
+ requestBindingMode = null,
103
+ requestBindingSha256 = null,
104
+ quoteId = null,
105
+ quoteSha256 = null,
106
+ idempotencyKey = null,
107
+ nonce = null,
108
+ sponsorRef = null,
109
+ sponsorWalletRef = null,
110
+ agentKeyId = null,
111
+ delegationRef = null,
112
+ rootDelegationRef = null,
113
+ rootDelegationHash = null,
114
+ effectiveDelegationRef = null,
115
+ effectiveDelegationHash = null,
116
+ policyVersion = null,
117
+ policyFingerprint = null,
118
+ spendAuthorizationVersion = null,
119
+ iat,
120
+ exp
121
+ } = {}) {
122
+ const normalizedIat = normalizeUnixSeconds(iat, "iat");
123
+ const normalizedExp = normalizeUnixSeconds(exp, "exp");
124
+ if (normalizedExp <= normalizedIat) throw new TypeError("exp must be greater than iat");
125
+ const normalizedRequestBindingSha256 = normalizeOptionalHexHash(requestBindingSha256, "requestBindingSha256");
126
+ const normalizedRequestBindingMode =
127
+ normalizeOptionalRequestBindingMode(requestBindingMode, "requestBindingMode") ??
128
+ (normalizedRequestBindingSha256 ? "strict" : null);
129
+ if (normalizedRequestBindingMode === "strict" && !normalizedRequestBindingSha256) {
130
+ throw new TypeError("requestBindingSha256 is required when requestBindingMode=strict");
131
+ }
132
+ const normalizedQuoteId = normalizeOptionalId(quoteId, "quoteId", { max: 200 });
133
+ const normalizedQuoteSha256 = normalizeOptionalHexHash(quoteSha256, "quoteSha256");
134
+ const normalizedIdempotencyKey = normalizeOptionalString(idempotencyKey, "idempotencyKey", { max: 256 });
135
+ const normalizedNonce = normalizeOptionalString(nonce, "nonce", { max: 256 });
136
+ const normalizedSponsorRef = normalizeOptionalId(sponsorRef, "sponsorRef", { max: 200 });
137
+ const normalizedSponsorWalletRef = normalizeOptionalId(sponsorWalletRef, "sponsorWalletRef", { max: 200 });
138
+ const normalizedAgentKeyId = normalizeOptionalId(agentKeyId, "agentKeyId", { max: 200 });
139
+ const normalizedDelegationRef = normalizeOptionalId(delegationRef, "delegationRef", { max: 200 });
140
+ const normalizedRootDelegationRef = normalizeOptionalId(rootDelegationRef, "rootDelegationRef", { max: 200 });
141
+ const normalizedRootDelegationHash = normalizeOptionalHexHash(rootDelegationHash, "rootDelegationHash");
142
+ const normalizedEffectiveDelegationRef = normalizeOptionalId(effectiveDelegationRef, "effectiveDelegationRef", { max: 200 });
143
+ const normalizedEffectiveDelegationHash = normalizeOptionalHexHash(effectiveDelegationHash, "effectiveDelegationHash");
144
+ const normalizedPolicyVersion = normalizeOptionalPositiveSafeInt(policyVersion, "policyVersion");
145
+ const normalizedPolicyFingerprint = normalizeOptionalHexHash(policyFingerprint, "policyFingerprint");
146
+ const normalizedSpendAuthorizationVersion = normalizeOptionalString(spendAuthorizationVersion, "spendAuthorizationVersion", {
147
+ max: 64
148
+ });
149
+ const hasSpendAuthorizationClaims =
150
+ normalizedQuoteId !== null ||
151
+ normalizedQuoteSha256 !== null ||
152
+ normalizedIdempotencyKey !== null ||
153
+ normalizedNonce !== null ||
154
+ normalizedSponsorRef !== null ||
155
+ normalizedSponsorWalletRef !== null ||
156
+ normalizedAgentKeyId !== null ||
157
+ normalizedDelegationRef !== null ||
158
+ normalizedRootDelegationRef !== null ||
159
+ normalizedRootDelegationHash !== null ||
160
+ normalizedEffectiveDelegationRef !== null ||
161
+ normalizedEffectiveDelegationHash !== null ||
162
+ normalizedPolicyVersion !== null ||
163
+ normalizedPolicyFingerprint !== null ||
164
+ normalizedSpendAuthorizationVersion !== null;
165
+ const spendAuthorizationVersionOut = hasSpendAuthorizationClaims
166
+ ? normalizedSpendAuthorizationVersion ?? "SpendAuthorization.v1"
167
+ : null;
168
+
169
+ return normalizeForCanonicalJson(
170
+ {
171
+ iss: assertNonEmptyString(iss, "iss"),
172
+ aud: assertNonEmptyString(aud, "aud"),
173
+ gateId: assertNonEmptyString(gateId, "gateId"),
174
+ authorizationRef: assertNonEmptyString(authorizationRef, "authorizationRef"),
175
+ amountCents: normalizePositiveSafeInt(amountCents, "amountCents"),
176
+ currency: normalizeCurrency(currency, "currency"),
177
+ payeeProviderId: assertNonEmptyString(payeeProviderId, "payeeProviderId"),
178
+ ...(normalizedRequestBindingMode ? { requestBindingMode: normalizedRequestBindingMode } : {}),
179
+ ...(normalizedRequestBindingSha256 ? { requestBindingSha256: normalizedRequestBindingSha256 } : {}),
180
+ ...(normalizedQuoteId ? { quoteId: normalizedQuoteId } : {}),
181
+ ...(normalizedQuoteSha256 ? { quoteSha256: normalizedQuoteSha256 } : {}),
182
+ ...(normalizedIdempotencyKey ? { idempotencyKey: normalizedIdempotencyKey } : {}),
183
+ ...(normalizedNonce ? { nonce: normalizedNonce } : {}),
184
+ ...(normalizedSponsorRef ? { sponsorRef: normalizedSponsorRef } : {}),
185
+ ...(normalizedSponsorWalletRef ? { sponsorWalletRef: normalizedSponsorWalletRef } : {}),
186
+ ...(normalizedAgentKeyId ? { agentKeyId: normalizedAgentKeyId } : {}),
187
+ ...(normalizedDelegationRef ? { delegationRef: normalizedDelegationRef } : {}),
188
+ ...(normalizedRootDelegationRef ? { rootDelegationRef: normalizedRootDelegationRef } : {}),
189
+ ...(normalizedRootDelegationHash ? { rootDelegationHash: normalizedRootDelegationHash } : {}),
190
+ ...(normalizedEffectiveDelegationRef ? { effectiveDelegationRef: normalizedEffectiveDelegationRef } : {}),
191
+ ...(normalizedEffectiveDelegationHash ? { effectiveDelegationHash: normalizedEffectiveDelegationHash } : {}),
192
+ ...(normalizedPolicyVersion ? { policyVersion: normalizedPolicyVersion } : {}),
193
+ ...(normalizedPolicyFingerprint ? { policyFingerprint: normalizedPolicyFingerprint } : {}),
194
+ ...(spendAuthorizationVersionOut ? { spendAuthorizationVersion: spendAuthorizationVersionOut } : {}),
195
+ iat: normalizedIat,
196
+ exp: normalizedExp
197
+ },
198
+ { path: "$" }
199
+ );
200
+ }
201
+
202
+ export function computeSettldPayRequestBindingSha256V1({ method, host, pathWithQuery, bodySha256 } = {}) {
203
+ const normalizedMethod = assertNonEmptyString(method, "method").toUpperCase();
204
+ const normalizedHost = assertNonEmptyString(host, "host").toLowerCase();
205
+ const normalizedPathWithQuery = assertNonEmptyString(pathWithQuery, "pathWithQuery");
206
+ if (!normalizedPathWithQuery.startsWith("/")) {
207
+ throw new TypeError("pathWithQuery must start with /");
208
+ }
209
+ const normalizedBodySha256 = normalizeHexHash(bodySha256, "bodySha256");
210
+ return sha256Hex(`${normalizedMethod}\n${normalizedHost}\n${normalizedPathWithQuery}\n${normalizedBodySha256}`);
211
+ }
212
+
213
+ export function computeSettldPayPayloadHashV1(payload) {
214
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) throw new TypeError("payload must be an object");
215
+ return sha256Hex(canonicalJsonStringify(payload));
216
+ }
217
+
218
+ export function computeSettldPayTokenSha256(token) {
219
+ return sha256Hex(assertNonEmptyString(token, "token"));
220
+ }
221
+
222
+ export function mintSettldPayTokenV1({ payload, keyId = null, publicKeyPem = null, privateKeyPem } = {}) {
223
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) throw new TypeError("payload must be an object");
224
+ const normalizedPayload = normalizeForCanonicalJson(payload, { path: "$" });
225
+ const privatePem = assertNonEmptyString(privateKeyPem, "privateKeyPem");
226
+ const publicPem = (() => {
227
+ if (publicKeyPem === null || publicKeyPem === undefined) return null;
228
+ if (typeof publicKeyPem !== "string" || publicKeyPem.trim() === "") throw new TypeError("publicKeyPem must be a non-empty string");
229
+ return publicKeyPem;
230
+ })();
231
+ const derivedKeyId = publicPem ? keyIdFromPublicKeyPem(publicPem) : null;
232
+ const normalizedKeyId = keyId === null || keyId === undefined || String(keyId).trim() === "" ? derivedKeyId : String(keyId).trim();
233
+ if (!normalizedKeyId) throw new TypeError("keyId is required (or provide publicKeyPem)");
234
+ if (derivedKeyId && normalizedKeyId !== derivedKeyId) throw new TypeError("keyId does not match publicKeyPem");
235
+
236
+ const payloadHashHex = computeSettldPayPayloadHashV1(normalizedPayload);
237
+ const signatureBase64 = signHashHexEd25519(payloadHashHex, privatePem);
238
+ const envelope = normalizeForCanonicalJson(
239
+ {
240
+ v: SETTLD_PAY_TOKEN_VERSION,
241
+ kid: normalizedKeyId,
242
+ payload: normalizedPayload,
243
+ sig: Buffer.from(signatureBase64, "base64").toString("base64url")
244
+ },
245
+ { path: "$" }
246
+ );
247
+ const token = Buffer.from(canonicalJsonStringify(envelope), "utf8").toString("base64url");
248
+ return {
249
+ token,
250
+ envelope,
251
+ kid: normalizedKeyId,
252
+ payloadHashHex,
253
+ tokenSha256: computeSettldPayTokenSha256(token)
254
+ };
255
+ }
256
+
257
+ export function parseSettldPayTokenV1(token) {
258
+ const { envelope, kid, payload, sig } = decodeEnvelope(token);
259
+ return { envelope, kid, payload, sig };
260
+ }
261
+
262
+ export function verifySettldPayTokenV1({
263
+ token,
264
+ keyset,
265
+ nowUnixSeconds = Math.floor(Date.now() / 1000),
266
+ expectedAudience = null,
267
+ expectedPayeeProviderId = null,
268
+ expectedRequestBindingSha256 = null
269
+ } = {}) {
270
+ const { envelope, kid, payload, sig } = decodeEnvelope(token);
271
+ const keyMap = keyMapFromSettldKeyset(keyset);
272
+ const keyEntry = keyMap.get(kid) ?? null;
273
+ if (!keyEntry?.publicKeyPem) return { ok: false, code: "SETTLD_PAY_UNKNOWN_KID", kid };
274
+
275
+ const payloadHashHex = computeSettldPayPayloadHashV1(payload);
276
+ const signatureBase64 = (() => {
277
+ try {
278
+ return Buffer.from(sig, "base64url").toString("base64");
279
+ } catch {
280
+ return null;
281
+ }
282
+ })();
283
+ if (!signatureBase64) return { ok: false, code: "SETTLD_PAY_SIGNATURE_INVALID", kid };
284
+
285
+ let signatureValid = false;
286
+ try {
287
+ signatureValid = verifyHashHexEd25519({ hashHex: payloadHashHex, signatureBase64, publicKeyPem: keyEntry.publicKeyPem });
288
+ } catch {
289
+ signatureValid = false;
290
+ }
291
+ if (!signatureValid) return { ok: false, code: "SETTLD_PAY_SIGNATURE_INVALID", kid };
292
+
293
+ let normalizedPayload;
294
+ try {
295
+ normalizedPayload = buildSettldPayPayloadV1(payload);
296
+ } catch (err) {
297
+ return { ok: false, code: "SETTLD_PAY_PAYLOAD_INVALID", kid, message: err?.message ?? String(err ?? "") };
298
+ }
299
+
300
+ const nowSec = normalizeUnixSeconds(nowUnixSeconds, "nowUnixSeconds");
301
+ if (nowSec > Number(normalizedPayload.exp)) return { ok: false, code: "SETTLD_PAY_EXPIRED", kid, payload: normalizedPayload };
302
+ if (expectedAudience !== null && expectedAudience !== undefined && String(expectedAudience) !== String(normalizedPayload.aud)) {
303
+ return { ok: false, code: "SETTLD_PAY_AUDIENCE_MISMATCH", kid, payload: normalizedPayload };
304
+ }
305
+ if (
306
+ expectedPayeeProviderId !== null &&
307
+ expectedPayeeProviderId !== undefined &&
308
+ String(expectedPayeeProviderId) !== String(normalizedPayload.payeeProviderId)
309
+ ) {
310
+ return { ok: false, code: "SETTLD_PAY_PAYEE_MISMATCH", kid, payload: normalizedPayload };
311
+ }
312
+
313
+ const expectedRequestBinding =
314
+ expectedRequestBindingSha256 === null || expectedRequestBindingSha256 === undefined || String(expectedRequestBindingSha256).trim() === ""
315
+ ? null
316
+ : normalizeHexHash(expectedRequestBindingSha256, "expectedRequestBindingSha256");
317
+ const payloadRequestBindingMode =
318
+ typeof normalizedPayload.requestBindingMode === "string" ? String(normalizedPayload.requestBindingMode).trim().toLowerCase() : null;
319
+ const payloadRequestBindingSha256 =
320
+ typeof normalizedPayload.requestBindingSha256 === "string" ? String(normalizedPayload.requestBindingSha256).trim().toLowerCase() : null;
321
+ if (payloadRequestBindingMode === "strict") {
322
+ if (!payloadRequestBindingSha256 || !/^[0-9a-f]{64}$/.test(payloadRequestBindingSha256)) {
323
+ return { ok: false, code: "SETTLD_PAY_REQUEST_BINDING_MISSING", kid, payload: normalizedPayload };
324
+ }
325
+ if (!expectedRequestBinding) {
326
+ return { ok: false, code: "SETTLD_PAY_REQUEST_BINDING_REQUIRED", kid, payload: normalizedPayload };
327
+ }
328
+ if (payloadRequestBindingSha256 !== expectedRequestBinding) {
329
+ return { ok: false, code: "SETTLD_PAY_REQUEST_BINDING_MISMATCH", kid, payload: normalizedPayload };
330
+ }
331
+ } else if (expectedRequestBinding && payloadRequestBindingSha256 && payloadRequestBindingSha256 !== expectedRequestBinding) {
332
+ return { ok: false, code: "SETTLD_PAY_REQUEST_BINDING_MISMATCH", kid, payload: normalizedPayload };
333
+ }
334
+
335
+ return {
336
+ ok: true,
337
+ kid,
338
+ payload: normalizedPayload,
339
+ envelope,
340
+ payloadHashHex: normalizeHexHash(payloadHashHex, "payloadHashHex"),
341
+ tokenSha256: computeSettldPayTokenSha256(token),
342
+ key: keyEntry
343
+ };
344
+ }
@@ -84,6 +84,213 @@ function normalizeHexHash(value, name, { allowNull = false } = {}) {
84
84
  return out;
85
85
  }
86
86
 
87
+ function normalizeNullableString(value, name, { max = 256 } = {}) {
88
+ if (value === null || value === undefined) return null;
89
+ const out = String(value);
90
+ if (out.length > max) throw new TypeError(`${name} must be <= ${max} chars`);
91
+ return out;
92
+ }
93
+
94
+ function normalizeNullableBoolean(value, name) {
95
+ if (value === null || value === undefined) return null;
96
+ if (typeof value !== "boolean") throw new TypeError(`${name} must be boolean`);
97
+ return value;
98
+ }
99
+
100
+ function normalizeNullableHttpStatus(value, name) {
101
+ if (value === null || value === undefined) return null;
102
+ const n = Number(value);
103
+ if (!Number.isSafeInteger(n) || n < 100 || n > 999) throw new TypeError(`${name} must be a 3-digit integer status code`);
104
+ return n;
105
+ }
106
+
107
+ function normalizeNullableSafeInt(value, name, { min = 0, max = Number.MAX_SAFE_INTEGER } = {}) {
108
+ if (value === null || value === undefined) return null;
109
+ const n = Number(value);
110
+ if (!Number.isSafeInteger(n) || n < min || n > max) {
111
+ throw new TypeError(`${name} must be an integer in range ${min}..${max}`);
112
+ }
113
+ return n;
114
+ }
115
+
116
+ function normalizeSettlementBindings(value, name, { allowNull = true } = {}) {
117
+ if (value === null || value === undefined) {
118
+ if (allowNull) return null;
119
+ throw new TypeError(`${name} is required`);
120
+ }
121
+ assertPlainObject(value, name);
122
+ return normalizeForCanonicalJson(
123
+ {
124
+ authorizationRef: normalizeNullableString(value.authorizationRef, `${name}.authorizationRef`, { max: 200 }),
125
+ token: value.token
126
+ ? {
127
+ kid: normalizeNullableString(value.token.kid, `${name}.token.kid`, { max: 200 }),
128
+ sha256: normalizeHexHash(value.token.sha256, `${name}.token.sha256`, { allowNull: true }),
129
+ expiresAt: value.token.expiresAt === null || value.token.expiresAt === undefined ? null : String(value.token.expiresAt)
130
+ }
131
+ : null,
132
+ request: value.request
133
+ ? {
134
+ sha256: normalizeHexHash(value.request.sha256, `${name}.request.sha256`, { allowNull: true })
135
+ }
136
+ : null,
137
+ response: value.response
138
+ ? {
139
+ status: normalizeNullableHttpStatus(value.response.status, `${name}.response.status`),
140
+ sha256: normalizeHexHash(value.response.sha256, `${name}.response.sha256`, { allowNull: true })
141
+ }
142
+ : null,
143
+ providerSig: value.providerSig
144
+ ? {
145
+ required: normalizeNullableBoolean(value.providerSig.required, `${name}.providerSig.required`),
146
+ present: normalizeNullableBoolean(value.providerSig.present, `${name}.providerSig.present`),
147
+ verified: normalizeNullableBoolean(value.providerSig.verified, `${name}.providerSig.verified`),
148
+ providerKeyId: normalizeNullableString(value.providerSig.providerKeyId, `${name}.providerSig.providerKeyId`, { max: 200 }),
149
+ keyJwkThumbprintSha256: normalizeHexHash(value.providerSig.keyJwkThumbprintSha256, `${name}.providerSig.keyJwkThumbprintSha256`, {
150
+ allowNull: true
151
+ }),
152
+ error: normalizeNullableString(value.providerSig.error, `${name}.providerSig.error`, { max: 4000 })
153
+ }
154
+ : null,
155
+ providerQuoteSig: value.providerQuoteSig
156
+ ? {
157
+ required: normalizeNullableBoolean(value.providerQuoteSig.required, `${name}.providerQuoteSig.required`),
158
+ present: normalizeNullableBoolean(value.providerQuoteSig.present, `${name}.providerQuoteSig.present`),
159
+ verified: normalizeNullableBoolean(value.providerQuoteSig.verified, `${name}.providerQuoteSig.verified`),
160
+ providerKeyId: normalizeNullableString(value.providerQuoteSig.providerKeyId, `${name}.providerQuoteSig.providerKeyId`, {
161
+ max: 200
162
+ }),
163
+ quoteId: normalizeNullableString(value.providerQuoteSig.quoteId, `${name}.providerQuoteSig.quoteId`, { max: 200 }),
164
+ quoteSha256: normalizeHexHash(value.providerQuoteSig.quoteSha256, `${name}.providerQuoteSig.quoteSha256`, { allowNull: true }),
165
+ keyJwkThumbprintSha256: normalizeHexHash(
166
+ value.providerQuoteSig.keyJwkThumbprintSha256,
167
+ `${name}.providerQuoteSig.keyJwkThumbprintSha256`,
168
+ { allowNull: true }
169
+ ),
170
+ error: normalizeNullableString(value.providerQuoteSig.error, `${name}.providerQuoteSig.error`, { max: 4000 })
171
+ }
172
+ : null,
173
+ reserve: value.reserve
174
+ ? {
175
+ adapter: normalizeNullableString(value.reserve.adapter, `${name}.reserve.adapter`, { max: 200 }),
176
+ mode: normalizeNullableString(value.reserve.mode, `${name}.reserve.mode`, { max: 200 }),
177
+ reserveId: normalizeNullableString(value.reserve.reserveId, `${name}.reserve.reserveId`, { max: 256 }),
178
+ status: normalizeNullableString(value.reserve.status, `${name}.reserve.status`, { max: 64 })
179
+ }
180
+ : null,
181
+ quote: value.quote
182
+ ? {
183
+ quoteId: normalizeNullableString(value.quote.quoteId, `${name}.quote.quoteId`, { max: 200 }),
184
+ quoteSha256: normalizeHexHash(value.quote.quoteSha256, `${name}.quote.quoteSha256`, { allowNull: true }),
185
+ expiresAt: value.quote.expiresAt === null || value.quote.expiresAt === undefined ? null : String(value.quote.expiresAt),
186
+ requestBindingMode: normalizeNullableString(value.quote.requestBindingMode, `${name}.quote.requestBindingMode`, {
187
+ max: 32
188
+ }),
189
+ requestBindingSha256: normalizeHexHash(value.quote.requestBindingSha256, `${name}.quote.requestBindingSha256`, {
190
+ allowNull: true
191
+ })
192
+ }
193
+ : null,
194
+ spendAuthorization: value.spendAuthorization
195
+ ? {
196
+ spendAuthorizationVersion: normalizeNullableString(
197
+ value.spendAuthorization.spendAuthorizationVersion,
198
+ `${name}.spendAuthorization.spendAuthorizationVersion`,
199
+ { max: 64 }
200
+ ),
201
+ idempotencyKey: normalizeNullableString(value.spendAuthorization.idempotencyKey, `${name}.spendAuthorization.idempotencyKey`, {
202
+ max: 256
203
+ }),
204
+ nonce: normalizeNullableString(value.spendAuthorization.nonce, `${name}.spendAuthorization.nonce`, { max: 256 }),
205
+ sponsorRef: normalizeNullableString(value.spendAuthorization.sponsorRef, `${name}.spendAuthorization.sponsorRef`, { max: 200 }),
206
+ sponsorWalletRef: normalizeNullableString(value.spendAuthorization.sponsorWalletRef, `${name}.spendAuthorization.sponsorWalletRef`, {
207
+ max: 200
208
+ }),
209
+ agentKeyId: normalizeNullableString(value.spendAuthorization.agentKeyId, `${name}.spendAuthorization.agentKeyId`, { max: 200 }),
210
+ delegationRef: normalizeNullableString(value.spendAuthorization.delegationRef, `${name}.spendAuthorization.delegationRef`, { max: 200 }),
211
+ rootDelegationRef: normalizeNullableString(value.spendAuthorization.rootDelegationRef, `${name}.spendAuthorization.rootDelegationRef`, {
212
+ max: 200
213
+ }),
214
+ rootDelegationHash: normalizeHexHash(value.spendAuthorization.rootDelegationHash, `${name}.spendAuthorization.rootDelegationHash`, {
215
+ allowNull: true
216
+ }),
217
+ effectiveDelegationRef: normalizeNullableString(
218
+ value.spendAuthorization.effectiveDelegationRef,
219
+ `${name}.spendAuthorization.effectiveDelegationRef`,
220
+ { max: 200 }
221
+ ),
222
+ effectiveDelegationHash: normalizeHexHash(
223
+ value.spendAuthorization.effectiveDelegationHash,
224
+ `${name}.spendAuthorization.effectiveDelegationHash`,
225
+ { allowNull: true }
226
+ ),
227
+ policyVersion: normalizeNullableSafeInt(value.spendAuthorization.policyVersion, `${name}.spendAuthorization.policyVersion`, {
228
+ min: 1,
229
+ max: 1_000_000_000
230
+ }),
231
+ policyFingerprint: normalizeHexHash(value.spendAuthorization.policyFingerprint, `${name}.spendAuthorization.policyFingerprint`, {
232
+ allowNull: true
233
+ })
234
+ }
235
+ : null,
236
+ executionIntent: value.executionIntent
237
+ ? {
238
+ schemaVersion: normalizeNullableString(value.executionIntent.schemaVersion, `${name}.executionIntent.schemaVersion`, { max: 64 }),
239
+ intentId: normalizeNullableString(value.executionIntent.intentId, `${name}.executionIntent.intentId`, { max: 200 }),
240
+ intentHash: normalizeHexHash(value.executionIntent.intentHash, `${name}.executionIntent.intentHash`, { allowNull: true }),
241
+ idempotencyKey: normalizeNullableString(value.executionIntent.idempotencyKey, `${name}.executionIntent.idempotencyKey`, {
242
+ max: 256
243
+ }),
244
+ nonce: normalizeNullableString(value.executionIntent.nonce, `${name}.executionIntent.nonce`, { max: 256 }),
245
+ expiresAt:
246
+ value.executionIntent.expiresAt === null || value.executionIntent.expiresAt === undefined
247
+ ? null
248
+ : String(value.executionIntent.expiresAt),
249
+ requestSha256: normalizeHexHash(value.executionIntent.requestSha256, `${name}.executionIntent.requestSha256`, {
250
+ allowNull: true
251
+ }),
252
+ policyHash: normalizeHexHash(value.executionIntent.policyHash, `${name}.executionIntent.policyHash`, { allowNull: true }),
253
+ verificationMethodHash: normalizeHexHash(
254
+ value.executionIntent.verificationMethodHash,
255
+ `${name}.executionIntent.verificationMethodHash`,
256
+ { allowNull: true }
257
+ )
258
+ }
259
+ : null,
260
+ policyDecisionFingerprint: value.policyDecisionFingerprint
261
+ ? {
262
+ fingerprintVersion: normalizeNullableString(
263
+ value.policyDecisionFingerprint.fingerprintVersion,
264
+ `${name}.policyDecisionFingerprint.fingerprintVersion`,
265
+ { max: 64 }
266
+ ),
267
+ policyId: normalizeNullableString(value.policyDecisionFingerprint.policyId, `${name}.policyDecisionFingerprint.policyId`, {
268
+ max: 200
269
+ }),
270
+ policyVersion: normalizeNullableSafeInt(value.policyDecisionFingerprint.policyVersion, `${name}.policyDecisionFingerprint.policyVersion`, {
271
+ min: 1,
272
+ max: 1_000_000_000
273
+ }),
274
+ policyHash: normalizeHexHash(value.policyDecisionFingerprint.policyHash, `${name}.policyDecisionFingerprint.policyHash`, {
275
+ allowNull: true
276
+ }),
277
+ verificationMethodHash: normalizeHexHash(
278
+ value.policyDecisionFingerprint.verificationMethodHash,
279
+ `${name}.policyDecisionFingerprint.verificationMethodHash`,
280
+ { allowNull: true }
281
+ ),
282
+ evaluationHash: normalizeHexHash(
283
+ value.policyDecisionFingerprint.evaluationHash,
284
+ `${name}.policyDecisionFingerprint.evaluationHash`,
285
+ { allowNull: true }
286
+ )
287
+ }
288
+ : null
289
+ },
290
+ { path: "$" }
291
+ );
292
+ }
293
+
87
294
  function assertNonNegativeSafeInt(value, name, { min = 0 } = {}) {
88
295
  const n = Number(value);
89
296
  if (!Number.isSafeInteger(n) || n < min) throw new TypeError(`${name} must be a safe integer >= ${min}`);
@@ -127,7 +334,8 @@ export function buildSettlementDecisionRecord({
127
334
  runLastEventId = null,
128
335
  runLastChainHash = null,
129
336
  resolutionEventId = null,
130
- decidedAt
337
+ decidedAt,
338
+ bindings = undefined
131
339
  } = {}) {
132
340
  assertIsoDate(decidedAt, "decidedAt");
133
341
  const resolvedSchemaVersion = String(schemaVersion ?? "").trim();
@@ -178,6 +386,7 @@ export function buildSettlementDecisionRecord({
178
386
  runLastChainHash: runLastChainHash === null ? null : String(runLastChainHash),
179
387
  resolutionEventId: resolutionEventId === null ? null : String(resolutionEventId)
180
388
  },
389
+ ...(bindings === null || bindings === undefined ? {} : { bindings: normalizeSettlementBindings(bindings, "bindings", { allowNull: false }) }),
181
390
  decidedAt: String(decidedAt)
182
391
  },
183
392
  { path: "$" }
@@ -212,7 +421,8 @@ export function buildSettlementReceipt({
212
421
  finalityProvider = SETTLEMENT_FINALITY_PROVIDER.INTERNAL_LEDGER,
213
422
  finalityState = undefined,
214
423
  settledAt = null,
215
- createdAt
424
+ createdAt,
425
+ bindings = undefined
216
426
  } = {}) {
217
427
  assertPlainObject(decisionRecord, "decisionRecord");
218
428
  assertIsoDate(createdAt, "createdAt");
@@ -245,6 +455,7 @@ export function buildSettlementReceipt({
245
455
  finalityProvider: String(finalityProvider ?? SETTLEMENT_FINALITY_PROVIDER.INTERNAL_LEDGER),
246
456
  finalityState: resolvedFinalityState,
247
457
  settledAt: settledAt === null ? null : String(settledAt),
458
+ ...(bindings === null || bindings === undefined ? {} : { bindings: normalizeSettlementBindings(bindings, "bindings", { allowNull: false }) }),
248
459
  createdAt: String(createdAt)
249
460
  },
250
461
  { path: "$" }