settld 0.1.2 → 0.2.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 (483) hide show
  1. package/README.md +93 -3
  2. package/SETTLD_VERSION +1 -1
  3. package/bin/settld-mcp +2 -0
  4. package/bin/settld.js +71 -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 +152 -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 +377 -0
  36. package/docs/QUICKSTART_MCP_HOSTS.md +210 -0
  37. package/docs/QUICKSTART_POLICY_PACKS.md +65 -0
  38. package/docs/QUICKSTART_PRODUCE.md +61 -0
  39. package/docs/QUICKSTART_PROFILES.md +198 -0
  40. package/docs/QUICKSTART_RELEASE_VERIFY.md +39 -0
  41. package/docs/QUICKSTART_SDK.md +125 -0
  42. package/docs/QUICKSTART_SDK_PYTHON.md +111 -0
  43. package/docs/QUICKSTART_VERIFY.md +54 -0
  44. package/docs/QUICKSTART_X402_GATEWAY.md +317 -0
  45. package/docs/README.md +33 -0
  46. package/docs/RELEASE_CHECKLIST.md +182 -0
  47. package/docs/RELEASING.md +82 -0
  48. package/docs/REPO_SETTINGS.md +37 -0
  49. package/docs/RUNBOOK.md +86 -0
  50. package/docs/SKILLS.md +42 -0
  51. package/docs/SKILL_BUNDLE_FORMAT.md +48 -0
  52. package/docs/SLO.md +131 -0
  53. package/docs/SUMMARY.md +17 -0
  54. package/docs/SUPPORT.md +31 -0
  55. package/docs/THREAT_MODEL.md +36 -0
  56. package/docs/TRUST.md +59 -0
  57. package/docs/WORKFLOW.md +35 -0
  58. package/docs/X402_BATCH_SETTLEMENT.md +126 -0
  59. package/docs/blog/2026-02-14-your-ai-agent-just-spent-500-where-is-the-receipt.md +73 -0
  60. package/docs/examples/x402-provider-payout-registry.example.json +14 -0
  61. package/docs/gitbook/README.md +64 -0
  62. package/docs/gitbook/SETUP.md +25 -0
  63. package/docs/gitbook/SUMMARY.md +15 -0
  64. package/docs/gitbook/api-reference.md +73 -0
  65. package/docs/gitbook/closepacks.md +55 -0
  66. package/docs/gitbook/conformance.md +59 -0
  67. package/docs/gitbook/core-primitives.md +85 -0
  68. package/docs/gitbook/dispute-lifecycle.md +33 -0
  69. package/docs/gitbook/faq.md +21 -0
  70. package/docs/gitbook/guides.md +49 -0
  71. package/docs/gitbook/operations-runbook.md +36 -0
  72. package/docs/gitbook/quickstart.md +103 -0
  73. package/docs/gitbook/replay-and-audit.md +30 -0
  74. package/docs/gitbook/sdk-reference.md +35 -0
  75. package/docs/gitbook/security-model.md +58 -0
  76. package/docs/integrations/README.md +15 -0
  77. package/docs/integrations/github-actions-verify.yml +31 -0
  78. package/docs/integrations/github-actions.md +34 -0
  79. package/docs/integrations/openclaw/CLAWHUB_PUBLISH_CHECKLIST.md +65 -0
  80. package/docs/integrations/openclaw/PUBLIC_QUICKSTART.md +95 -0
  81. package/docs/integrations/openclaw/settld-mcp-skill/SKILL.md +69 -0
  82. package/docs/integrations/openclaw/settld-mcp-skill/mcp-server.example.json +12 -0
  83. package/docs/kernel-compatible/capabilities.json +36 -0
  84. package/docs/marketing/agent-commerce-substrate.md +78 -0
  85. package/docs/marketing/hn-repost-2026-02-17.md +102 -0
  86. package/docs/marketing/show-hn-post.md +45 -0
  87. package/docs/ops/ARTIFACT_VERIFICATION_STATUS.md +43 -0
  88. package/docs/ops/BILLING_WEBHOOK_REPLAY.md +105 -0
  89. package/docs/ops/CI_FLAKE_BUDGET.md +31 -0
  90. package/docs/ops/DISPUTE_FINANCE_RECONCILIATION_PACKET.md +56 -0
  91. package/docs/ops/GO_LIVE_GATE_S13.md +27 -0
  92. package/docs/ops/HOSTED_BASELINE_R2.md +129 -0
  93. package/docs/ops/KERNEL_V0_SHIP_GATE.md +69 -0
  94. package/docs/ops/LIGHTHOUSE_PRODUCTION_CLOSE.md +51 -0
  95. package/docs/ops/MCP_COMPATIBILITY_MATRIX.md +30 -0
  96. package/docs/ops/MINIMUM_PRODUCTION_TOPOLOGY.md +89 -0
  97. package/docs/ops/P0_BACKEND_PROGRESS.md +150 -0
  98. package/docs/ops/PAYMENTS_ALPHA_R5.md +105 -0
  99. package/docs/ops/PILOT_ONBOARDING_RUNBOOK.md +112 -0
  100. package/docs/ops/PRODUCTION_DEPLOYMENT_CHECKLIST.md +140 -0
  101. package/docs/ops/R1_SLOS.md +66 -0
  102. package/docs/ops/RELEASE_SIGNING_INCIDENT.md +58 -0
  103. package/docs/ops/SELF_SERVE_LAUNCH_AUTOMATION.md +89 -0
  104. package/docs/ops/THROUGHPUT_DRILL_10X.md +48 -0
  105. package/docs/ops/TRUST_CONFIG_WIZARD.md +60 -0
  106. package/docs/ops/X402_PILOT_WEEKLY_METRICS.md +76 -0
  107. package/docs/ops/tool-call-disputes-holdback.md +52 -0
  108. package/docs/pilot-kit/PILOT_PACKAGE_SCORECARD_X402.md +46 -0
  109. package/docs/pilot-kit/README.md +29 -0
  110. package/docs/pilot-kit/architecture-one-pager.md +48 -0
  111. package/docs/pilot-kit/buyer-email.txt +19 -0
  112. package/docs/pilot-kit/buyer-one-pager.md +31 -0
  113. package/docs/pilot-kit/gtm-pilot-playbook.md +182 -0
  114. package/docs/pilot-kit/offline-verify.md +33 -0
  115. package/docs/pilot-kit/procurement-one-pager.md +50 -0
  116. package/docs/pilot-kit/rfp-clause.md +46 -0
  117. package/docs/pilot-kit/roi-calculator-template.csv +2 -0
  118. package/docs/pilot-kit/security-qa.md +153 -0
  119. package/docs/pilot-kit/security-summary.md +35 -0
  120. package/docs/plans/2026-02-13-mcp-spike-design.md +113 -0
  121. package/docs/plans/2026-02-20-trust-os-v1-jira-backlog.md +348 -0
  122. package/docs/plans/2026-02-21-agent-economic-actor-operating-model.md +169 -0
  123. package/docs/plans/2026-02-21-trust-os-v1-strategy.md +241 -0
  124. package/docs/research/2026-02-21-agent-spend-host-landscape.md +57 -0
  125. package/docs/spec/AcceptanceCriteria.v1.md +17 -0
  126. package/docs/spec/AcceptanceEvaluation.v1.md +10 -0
  127. package/docs/spec/AgentEvent.v1.md +47 -0
  128. package/docs/spec/AgentIdentity.v1.md +62 -0
  129. package/docs/spec/AgentPassport.v1.md +95 -0
  130. package/docs/spec/AgentReputation.v1.md +59 -0
  131. package/docs/spec/AgentReputation.v2.md +52 -0
  132. package/docs/spec/AgentRun.v1.md +47 -0
  133. package/docs/spec/AgentRunSettlement.v1.md +52 -0
  134. package/docs/spec/AgentWallet.v1.md +43 -0
  135. package/docs/spec/AgreementDelegation.v1.md +109 -0
  136. package/docs/spec/ArbitrationCase.v1.md +67 -0
  137. package/docs/spec/ArbitrationOutcomeMapping.v1.md +62 -0
  138. package/docs/spec/ArbitrationVerdict.v1.md +60 -0
  139. package/docs/spec/BundleHeadAttestation.v1.md +32 -0
  140. package/docs/spec/CANONICAL_JSON.md +31 -0
  141. package/docs/spec/CRYPTOGRAPHY.md +61 -0
  142. package/docs/spec/ClosePack.v1.md +49 -0
  143. package/docs/spec/ClosePackManifest.v1.md +24 -0
  144. package/docs/spec/DelegationGrant.v1.md +90 -0
  145. package/docs/spec/DisputeCaseLifecycle.v1.md +51 -0
  146. package/docs/spec/DisputeOpenEnvelope.v1.md +43 -0
  147. package/docs/spec/ERRORS.md +76 -0
  148. package/docs/spec/ESCROW_NETTING_INVARIANTS.md +71 -0
  149. package/docs/spec/EvidenceIndex.v1.md +20 -0
  150. package/docs/spec/ExecutionIntent.v1.md +90 -0
  151. package/docs/spec/FinancePackBundleManifest.v1.md +24 -0
  152. package/docs/spec/FundingHold.v1.md +60 -0
  153. package/docs/spec/GovernancePolicy.v1.md +34 -0
  154. package/docs/spec/GovernancePolicy.v2.md +30 -0
  155. package/docs/spec/INVARIANTS.md +389 -0
  156. package/docs/spec/InteractionDirectionMatrix.v1.md +30 -0
  157. package/docs/spec/InvoiceBundleManifest.v1.md +24 -0
  158. package/docs/spec/InvoiceClaim.v1.md +11 -0
  159. package/docs/spec/MONEY_RAIL_STATE_MACHINE.md +58 -0
  160. package/docs/spec/MarketplaceAcceptance.v2.md +46 -0
  161. package/docs/spec/MarketplaceOffer.v2.md +54 -0
  162. package/docs/spec/MeteringReport.v1.md +18 -0
  163. package/docs/spec/OperatorAction.v1.md +90 -0
  164. package/docs/spec/PRODUCER_ERRORS.md +42 -0
  165. package/docs/spec/PolicyDecision.v1.md +83 -0
  166. package/docs/spec/PricingMatrix.v1.md +20 -0
  167. package/docs/spec/PricingMatrixSignatures.v1.md +30 -0
  168. package/docs/spec/PricingMatrixSignatures.v2.md +29 -0
  169. package/docs/spec/ProduceCliOutput.v1.md +46 -0
  170. package/docs/spec/ProofBundleManifest.v1.md +24 -0
  171. package/docs/spec/README.md +109 -0
  172. package/docs/spec/REFERENCE_IMPLEMENTATIONS.md +29 -0
  173. package/docs/spec/REFERENCE_VERIFIER_BEHAVIOR.md +68 -0
  174. package/docs/spec/REMOTE_SIGNER.md +66 -0
  175. package/docs/spec/ReleaseIndex.v1.md +32 -0
  176. package/docs/spec/ReleaseIndexSignatures.v1.md +17 -0
  177. package/docs/spec/ReleaseTrust.v1.md +13 -0
  178. package/docs/spec/ReleaseTrust.v2.md +26 -0
  179. package/docs/spec/RemoteSignerRequest.v1.md +21 -0
  180. package/docs/spec/RemoteSignerResponse.v1.md +16 -0
  181. package/docs/spec/ReputationEvent.v1.md +63 -0
  182. package/docs/spec/RevocationList.v1.md +28 -0
  183. package/docs/spec/SIGNER_PROVIDER_PLUGIN.md +32 -0
  184. package/docs/spec/STRICTNESS.md +68 -0
  185. package/docs/spec/SUPPLY_CHAIN.md +33 -0
  186. package/docs/spec/SettlementAdjustment.v1.md +45 -0
  187. package/docs/spec/SettlementDecisionRecord.v1.md +48 -0
  188. package/docs/spec/SettlementDecisionRecord.v2.md +53 -0
  189. package/docs/spec/SettlementDecisionReport.v1.md +44 -0
  190. package/docs/spec/SettlementKernel.v1.md +59 -0
  191. package/docs/spec/SettlementReceipt.v1.md +63 -0
  192. package/docs/spec/SlaDefinition.v1.md +24 -0
  193. package/docs/spec/SlaEvaluation.v1.md +12 -0
  194. package/docs/spec/THREAT_MODEL.md +113 -0
  195. package/docs/spec/TOOL_PROVENANCE.md +30 -0
  196. package/docs/spec/TRUST_ANCHORS.md +84 -0
  197. package/docs/spec/TenantSettings.v1.md +90 -0
  198. package/docs/spec/TenantSettings.v2.md +99 -0
  199. package/docs/spec/TimestampProof.v1.md +25 -0
  200. package/docs/spec/ToolCallAgreement.v1.md +34 -0
  201. package/docs/spec/ToolCallEvidence.v1.md +47 -0
  202. package/docs/spec/ToolManifest.v1.md +47 -0
  203. package/docs/spec/VERIFIER_ENVIRONMENT.md +38 -0
  204. package/docs/spec/VERSIONING.md +107 -0
  205. package/docs/spec/VerificationReport.v1.md +50 -0
  206. package/docs/spec/VerifyAboutOutput.v1.md +10 -0
  207. package/docs/spec/VerifyCliOutput.v1.md +28 -0
  208. package/docs/spec/WARNINGS.md +83 -0
  209. package/docs/spec/error-codes.v1.txt +285 -0
  210. package/docs/spec/examples/agreement_delegation_v1.example.json +21 -0
  211. package/docs/spec/examples/arbitration_case_v1.example.json +26 -0
  212. package/docs/spec/examples/arbitration_verdict_v1.example.json +32 -0
  213. package/docs/spec/examples/dispute_open_envelope_v1.example.json +18 -0
  214. package/docs/spec/examples/produce_cli_output_v1.example.json +32 -0
  215. package/docs/spec/examples/release_index_signature_v1.example.json +9 -0
  216. package/docs/spec/examples/release_index_signatures_v1.example.json +14 -0
  217. package/docs/spec/examples/release_index_v1.example.json +15 -0
  218. package/docs/spec/examples/release_trust_v1.example.json +7 -0
  219. package/docs/spec/examples/release_trust_v2.example.json +22 -0
  220. package/docs/spec/examples/remote_signer_request_v1.example.json +18 -0
  221. package/docs/spec/examples/remote_signer_response_v1.example.json +8 -0
  222. package/docs/spec/examples/reputation_event_v1.example.json +29 -0
  223. package/docs/spec/examples/verification_report_v1.example.json +24 -0
  224. package/docs/spec/examples/verify_about_output_v1.example.json +29 -0
  225. package/docs/spec/examples/verify_cli_output_v1.example.json +13 -0
  226. package/docs/spec/legacy/MarketplaceAcceptance.v1.md +48 -0
  227. package/docs/spec/legacy/MarketplaceOffer.v1.md +56 -0
  228. package/docs/spec/legacy/schemas/MarketplaceAcceptance.v1.schema.json +53 -0
  229. package/docs/spec/legacy/schemas/MarketplaceOffer.v1.schema.json +61 -0
  230. package/docs/spec/producer-error-codes.v1.txt +14 -0
  231. package/docs/spec/schemas/AcceptanceCriteria.v1.schema.json +24 -0
  232. package/docs/spec/schemas/AcceptanceEvaluation.v1.schema.json +26 -0
  233. package/docs/spec/schemas/AgentEvent.v1.schema.json +49 -0
  234. package/docs/spec/schemas/AgentIdentity.v1.schema.json +129 -0
  235. package/docs/spec/schemas/AgentPassport.v1.schema.json +112 -0
  236. package/docs/spec/schemas/AgentReputation.v1.schema.json +151 -0
  237. package/docs/spec/schemas/AgentReputation.v2.schema.json +120 -0
  238. package/docs/spec/schemas/AgentRun.v1.schema.json +71 -0
  239. package/docs/spec/schemas/AgentRunSettlement.v1.schema.json +75 -0
  240. package/docs/spec/schemas/AgentWallet.v1.schema.json +54 -0
  241. package/docs/spec/schemas/AgreementDelegation.v1.schema.json +50 -0
  242. package/docs/spec/schemas/ArbitrationCase.v1.schema.json +133 -0
  243. package/docs/spec/schemas/ArbitrationVerdict.v1.schema.json +149 -0
  244. package/docs/spec/schemas/BundleHeadAttestation.v1.schema.json +21 -0
  245. package/docs/spec/schemas/ClosePackManifest.v1.schema.json +38 -0
  246. package/docs/spec/schemas/DelegationGrant.v1.schema.json +102 -0
  247. package/docs/spec/schemas/DisputeOpenEnvelope.v1.schema.json +78 -0
  248. package/docs/spec/schemas/EvidenceIndex.v1.schema.json +41 -0
  249. package/docs/spec/schemas/ExecutionIntent.v1.schema.json +85 -0
  250. package/docs/spec/schemas/FinancePackBundleManifest.v1.schema.json +38 -0
  251. package/docs/spec/schemas/FundingHold.v1.schema.json +46 -0
  252. package/docs/spec/schemas/GovernancePolicy.v1.schema.json +45 -0
  253. package/docs/spec/schemas/GovernancePolicy.v2.schema.json +70 -0
  254. package/docs/spec/schemas/InteractionDirectionMatrix.v1.schema.json +43 -0
  255. package/docs/spec/schemas/InvoiceBundleManifest.v1.schema.json +38 -0
  256. package/docs/spec/schemas/InvoiceClaim.v1.schema.json +39 -0
  257. package/docs/spec/schemas/MarketplaceAcceptance.v2.schema.json +53 -0
  258. package/docs/spec/schemas/MarketplaceOffer.v2.schema.json +61 -0
  259. package/docs/spec/schemas/MeteringReport.v1.schema.json +45 -0
  260. package/docs/spec/schemas/OperatorAction.v1.schema.json +113 -0
  261. package/docs/spec/schemas/PolicyDecision.v1.schema.json +74 -0
  262. package/docs/spec/schemas/PricingMatrix.v1.schema.json +24 -0
  263. package/docs/spec/schemas/PricingMatrixSignatures.v1.schema.json +24 -0
  264. package/docs/spec/schemas/PricingMatrixSignatures.v2.schema.json +24 -0
  265. package/docs/spec/schemas/ProduceCliOutput.v1.schema.json +107 -0
  266. package/docs/spec/schemas/ProofBundleManifest.v1.schema.json +37 -0
  267. package/docs/spec/schemas/PublicKeys.v1.schema.json +33 -0
  268. package/docs/spec/schemas/ReleaseIndex.v1.schema.json +45 -0
  269. package/docs/spec/schemas/ReleaseIndexSignature.v1.schema.json +16 -0
  270. package/docs/spec/schemas/ReleaseIndexSignatures.v1.schema.json +16 -0
  271. package/docs/spec/schemas/ReleaseTrust.v1.schema.json +15 -0
  272. package/docs/spec/schemas/ReleaseTrust.v2.schema.json +37 -0
  273. package/docs/spec/schemas/RemoteSignerPublicKeyResponse.v1.schema.json +14 -0
  274. package/docs/spec/schemas/RemoteSignerRequest.v1.schema.json +24 -0
  275. package/docs/spec/schemas/RemoteSignerResponse.v1.schema.json +10 -0
  276. package/docs/spec/schemas/RemoteSignerSignRequest.v1.schema.json +27 -0
  277. package/docs/spec/schemas/RemoteSignerSignResponse.v1.schema.json +16 -0
  278. package/docs/spec/schemas/ReputationEvent.v1.schema.json +164 -0
  279. package/docs/spec/schemas/RevocationList.v1.schema.json +51 -0
  280. package/docs/spec/schemas/SettlementAdjustment.v1.schema.json +44 -0
  281. package/docs/spec/schemas/SettlementDecisionRecord.v1.schema.json +66 -0
  282. package/docs/spec/schemas/SettlementDecisionRecord.v2.schema.json +149 -0
  283. package/docs/spec/schemas/SettlementDecisionReport.v1.schema.json +61 -0
  284. package/docs/spec/schemas/SettlementReceipt.v1.schema.json +135 -0
  285. package/docs/spec/schemas/SlaDefinition.v1.schema.json +33 -0
  286. package/docs/spec/schemas/SlaEvaluation.v1.schema.json +26 -0
  287. package/docs/spec/schemas/TenantSettings.v1.schema.json +90 -0
  288. package/docs/spec/schemas/TenantSettings.v2.schema.json +161 -0
  289. package/docs/spec/schemas/TimestampProof.v1.schema.json +17 -0
  290. package/docs/spec/schemas/ToolCallAgreement.v1.schema.json +34 -0
  291. package/docs/spec/schemas/ToolCallEvidence.v1.schema.json +45 -0
  292. package/docs/spec/schemas/ToolManifest.v1.schema.json +54 -0
  293. package/docs/spec/schemas/VerificationReport.v1.schema.json +83 -0
  294. package/docs/spec/schemas/VerifyAboutOutput.v1.schema.json +54 -0
  295. package/docs/spec/schemas/VerifyCliOutput.v1.schema.json +75 -0
  296. package/docs/spec/schemas/VerifyReleaseOutput.v1.schema.json +47 -0
  297. package/docs/spec/x402-error-codes.v1.txt +35 -0
  298. package/docs/templates/buyer-email.txt +18 -0
  299. package/docs/templates/buyer-one-pager.md +24 -0
  300. package/package.json +53 -6
  301. package/scripts/acceptance/full-stack.mjs +734 -0
  302. package/scripts/acceptance/full-stack.sh +99 -0
  303. package/scripts/audit/build-audit-packet.mjs +242 -0
  304. package/scripts/backup-pg.sh +45 -0
  305. package/scripts/backup-restore/README.md +18 -0
  306. package/scripts/backup-restore/capture-state.mjs +130 -0
  307. package/scripts/backup-restore/client.mjs +97 -0
  308. package/scripts/backup-restore/seed-workload.mjs +235 -0
  309. package/scripts/backup-restore/verify-state.mjs +139 -0
  310. package/scripts/backup-restore-test.sh +217 -0
  311. package/scripts/chaos.js +221 -0
  312. package/scripts/ci/build-launch-cutover-packet.mjs +304 -0
  313. package/scripts/ci/build-self-serve-benchmark-report.mjs +122 -0
  314. package/scripts/ci/changelog-guard.mjs +145 -0
  315. package/scripts/ci/check-kernel-v0-launch-gate.mjs +233 -0
  316. package/scripts/ci/check-secret-hygiene.mjs +78 -0
  317. package/scripts/ci/check-version-consistency.mjs +42 -0
  318. package/scripts/ci/cli-pack-smoke.mjs +160 -0
  319. package/scripts/ci/flake-budget-guard.mjs +68 -0
  320. package/scripts/ci/generate-error-codes.mjs +54 -0
  321. package/scripts/ci/lib/lighthouse-tracker.mjs +90 -0
  322. package/scripts/ci/lib/self-serve-launch-gate.mjs +89 -0
  323. package/scripts/ci/npm-pack-smoke.mjs +454 -0
  324. package/scripts/ci/run-10x-throughput-drill.mjs +318 -0
  325. package/scripts/ci/run-10x-throughput-incident-rehearsal.mjs +368 -0
  326. package/scripts/ci/run-arbitration-workspace-browser-e2e.sh +22 -0
  327. package/scripts/ci/run-circle-sandbox-smoke.mjs +237 -0
  328. package/scripts/ci/run-go-live-gate.mjs +150 -0
  329. package/scripts/ci/run-kernel-v0-ship-gate.mjs +97 -0
  330. package/scripts/ci/run-mcp-host-cert-matrix.mjs +201 -0
  331. package/scripts/ci/run-mcp-host-smoke.mjs +473 -0
  332. package/scripts/ci/run-offline-verification-parity-gate.mjs +762 -0
  333. package/scripts/ci/run-onboarding-host-success-gate.mjs +516 -0
  334. package/scripts/ci/run-onboarding-policy-slo-gate.mjs +537 -0
  335. package/scripts/ci/run-production-cutover-gate.mjs +540 -0
  336. package/scripts/ci/run-public-openclaw-npx-smoke.mjs +148 -0
  337. package/scripts/ci/run-release-promotion-guard.mjs +756 -0
  338. package/scripts/ci/run-self-serve-launch-gate.mjs +56 -0
  339. package/scripts/ci/runtime-import-smoke.mjs +58 -0
  340. package/scripts/ci/update-lighthouse-tracker.mjs +112 -0
  341. package/scripts/closepack/lib.mjs +286 -0
  342. package/scripts/collect-debug.sh +263 -0
  343. package/scripts/demo/compositional-settlement-3hop.mjs +237 -0
  344. package/scripts/demo/delivery-robot/export-ui-fixture.mjs +188 -0
  345. package/scripts/demo/delivery-robot/generate.mjs +377 -0
  346. package/scripts/demo/kernel-agent-goes-shopping.mjs +202 -0
  347. package/scripts/demo/magic-link-first-green.mjs +118 -0
  348. package/scripts/demo/magic-link-kind-smoke.mjs +577 -0
  349. package/scripts/demo/mcp-paid-exa.mjs +1110 -0
  350. package/scripts/dev/billing-doctor.sh +145 -0
  351. package/scripts/dev/billing-smoke-prod.sh +219 -0
  352. package/scripts/dev/billing-webhook-replay.sh +161 -0
  353. package/scripts/dev/env.dev.example +29 -0
  354. package/scripts/dev/env.sh +37 -0
  355. package/scripts/dev/new-sdk-key.sh +81 -0
  356. package/scripts/dev/sdk-first-run.sh +21 -0
  357. package/scripts/dev/smoke-x402-gateway.sh +115 -0
  358. package/scripts/dev/start-api.sh +24 -0
  359. package/scripts/doctor/mcp-host.mjs +120 -0
  360. package/scripts/examples/produce-and-verify-jobproof.mjs +191 -0
  361. package/scripts/examples/sdk-first-paid-rfq.py +105 -0
  362. package/scripts/examples/sdk-first-verified-run.mjs +85 -0
  363. package/scripts/examples/sdk-first-verified-run.py +99 -0
  364. package/scripts/examples/sdk-tenant-analytics.mjs +103 -0
  365. package/scripts/examples/sdk-tenant-analytics.py +118 -0
  366. package/scripts/finance-pack/bundle.mjs +284 -0
  367. package/scripts/fixtures/generate-bundle-fixtures.mjs +877 -0
  368. package/scripts/governance/export.mjs +169 -0
  369. package/scripts/load/delivery-stress.k6.js +183 -0
  370. package/scripts/load/ingest-burst.k6.js +236 -0
  371. package/scripts/load/run-delivery-load.js +66 -0
  372. package/scripts/load/webhook-receiver.js +131 -0
  373. package/scripts/magic-link/migrate-run-records-to-db.mjs +35 -0
  374. package/scripts/mcp/probe.mjs +238 -0
  375. package/scripts/mcp/settld-mcp-http-gateway.mjs +178 -0
  376. package/scripts/mcp/settld-mcp-server.mjs +1511 -0
  377. package/scripts/openapi/write.mjs +13 -0
  378. package/scripts/ops/bootstrap-tenant-conformance.mjs +185 -0
  379. package/scripts/ops/build-x402-pilot-reliability-report.mjs +489 -0
  380. package/scripts/ops/check-x402-receipt-sample.mjs +181 -0
  381. package/scripts/ops/design-partner-run-packet.mjs +466 -0
  382. package/scripts/ops/dispute-finance-reconciliation-packet.mjs +313 -0
  383. package/scripts/ops/hosted-baseline-evidence.mjs +890 -0
  384. package/scripts/ops/money-rails-chargeback-evidence.mjs +509 -0
  385. package/scripts/ops/money-rails-reconcile-evidence.mjs +180 -0
  386. package/scripts/ops/p0-seed-money-rail-operation.mjs +432 -0
  387. package/scripts/ops/run-x402-hitl-smoke.mjs +607 -0
  388. package/scripts/pilot/finance-pack.mjs +495 -0
  389. package/scripts/pilot/fixtures/robot-keypair.json +4 -0
  390. package/scripts/pilot/fixtures/server-signer.json +4 -0
  391. package/scripts/policy/cli.mjs +600 -0
  392. package/scripts/profile/cli.mjs +1324 -0
  393. package/scripts/proof-bundle/job.mjs +109 -0
  394. package/scripts/proof-bundle/lib.mjs +92 -0
  395. package/scripts/proof-bundle/month.mjs +103 -0
  396. package/scripts/provider/conformance-run.mjs +159 -0
  397. package/scripts/provider/keys-generate.mjs +135 -0
  398. package/scripts/provider/publish.mjs +420 -0
  399. package/scripts/quickstart/x402.mjs +334 -0
  400. package/scripts/register-entity-secret.mjs +102 -0
  401. package/scripts/release/build-artifacts.mjs +181 -0
  402. package/scripts/release/generate-release-index.mjs +112 -0
  403. package/scripts/release/release-index-lib.mjs +232 -0
  404. package/scripts/release/sign-release-index.mjs +85 -0
  405. package/scripts/release/validate-release-assets.mjs +170 -0
  406. package/scripts/release/verify-release.mjs +261 -0
  407. package/scripts/restore-pg.sh +34 -0
  408. package/scripts/scaffold/create-settld-paid-tool.mjs +19 -0
  409. package/scripts/sdk/smoke-python.py +30 -0
  410. package/scripts/sdk/smoke.mjs +16 -0
  411. package/scripts/settlement/x402-batch-worker.mjs +1091 -0
  412. package/scripts/setup/circle-bootstrap.mjs +310 -0
  413. package/scripts/setup/host-config.mjs +617 -0
  414. package/scripts/setup/onboard.mjs +1337 -0
  415. package/scripts/setup/openclaw-onboard.mjs +423 -0
  416. package/scripts/setup/wizard.mjs +986 -0
  417. package/scripts/slo/check.mjs +239 -0
  418. package/scripts/smoke/k8s-smoke.mjs +214 -0
  419. package/scripts/spec/generate-protocol-vectors.mjs +1019 -0
  420. package/scripts/test/check-no-generated-artifacts.sh +12 -0
  421. package/scripts/test/run.sh +59 -0
  422. package/scripts/trust/validate-trust-file.mjs +57 -0
  423. package/scripts/trust-config/rotate-settld-pay.mjs +277 -0
  424. package/scripts/trust-config/wizard.mjs +161 -0
  425. package/scripts/vendor-contract-test-lib.mjs +182 -0
  426. package/scripts/vendor-contract-test.mjs +55 -0
  427. package/scripts/vercel/build-mkdocs.sh +9 -0
  428. package/scripts/vercel/ignore-mkdocs.sh +25 -0
  429. package/scripts/vercel/install-mkdocs.sh +6 -0
  430. package/scripts/verify-pg.js +217 -0
  431. package/scripts/x402/receipt-verify.mjs +289 -0
  432. package/services/finance-sink/src/dedupe-store.js +29 -6
  433. package/services/receiver/src/dedupe-store.js +29 -5
  434. package/services/x402-gateway/Dockerfile +13 -0
  435. package/services/x402-gateway/README.md +58 -0
  436. package/services/x402-gateway/examples/upstream-mock.js +337 -0
  437. package/services/x402-gateway/src/server.js +1058 -0
  438. package/src/api/app.js +34658 -16940
  439. package/src/api/maintenance.js +70 -0
  440. package/src/api/middleware/trust-kernel.js +114 -0
  441. package/src/api/openapi.js +1778 -70
  442. package/src/api/persistence.js +456 -0
  443. package/src/api/server.js +81 -5
  444. package/src/api/store.js +1581 -62
  445. package/src/api/workers/deliveries.js +99 -4
  446. package/src/api/workers/insolvency-sweep.js +159 -0
  447. package/src/core/agent-card.js +69 -0
  448. package/src/core/agent-wallets.js +231 -0
  449. package/src/core/agreement-delegation.js +549 -0
  450. package/src/core/billing-plans.js +40 -6
  451. package/src/core/circle-reserve-adapter.js +845 -0
  452. package/src/core/event-policy.js +21 -2
  453. package/src/core/maintenance-locks.js +1 -0
  454. package/src/core/operator-action.js +303 -0
  455. package/src/core/paid-tool-manifest.js +318 -0
  456. package/src/core/policy-decision.js +322 -0
  457. package/src/core/policy-packs.js +207 -0
  458. package/src/core/profile-fingerprint.js +27 -0
  459. package/src/core/profile-simulation-reasons.js +84 -0
  460. package/src/core/profile-templates.js +242 -0
  461. package/src/core/provider-publish-conformance.js +525 -0
  462. package/src/core/provider-publish-proof.js +396 -0
  463. package/src/core/provider-quote-signature.js +170 -0
  464. package/src/core/settld-keys.js +112 -0
  465. package/src/core/settld-pay-token.js +344 -0
  466. package/src/core/settlement-kernel.js +239 -2
  467. package/src/core/settlement-verifier.js +335 -0
  468. package/src/core/tool-call-agreement.js +112 -0
  469. package/src/core/tool-call-evidence.js +144 -0
  470. package/src/core/tool-provider-signature.js +98 -0
  471. package/src/core/wallet-assignment-resolver.js +129 -0
  472. package/src/core/wallet-provider-bootstrap.js +365 -0
  473. package/src/core/x402-escalation-override.js +258 -0
  474. package/src/core/x402-gate.js +118 -0
  475. package/src/core/x402-provider-refund-decision.js +220 -0
  476. package/src/core/x402-receipt-verifier.js +708 -0
  477. package/src/core/x402-reversal-command.js +251 -0
  478. package/src/core/x402-wallet-issuer-decision.js +252 -0
  479. package/src/core/zk-verifier.js +300 -0
  480. package/src/db/migrations/029_reputation_event_index.sql +54 -0
  481. package/src/db/migrations/030_artifacts_source_event_unique_job_only.sql +15 -0
  482. package/src/db/pg.js +18 -7
  483. package/src/db/store-pg.js +1508 -111
@@ -9,6 +9,7 @@ import { reduceMonthClose } from "../core/month-close.js";
9
9
  import { AGENT_RUN_EVENT_SCHEMA_VERSION, reduceAgentRun } from "../core/agent-runs.js";
10
10
  import { normalizeInteractionDirection } from "../core/interaction-directions.js";
11
11
  import { DEFAULT_TENANT_ID, normalizeTenantId, makeScopedKey } from "../core/tenancy.js";
12
+ import { canonicalJsonStringify } from "../core/canonical-json.js";
12
13
 
13
14
  export const TX_LOG_VERSION = 1;
14
15
 
@@ -22,6 +23,72 @@ function normalizeMarketplaceDirectionForReplay({ fromType, toType }) {
22
23
  });
23
24
  }
24
25
 
26
+ const EMERGENCY_SCOPE_TYPE = Object.freeze({
27
+ TENANT: "tenant",
28
+ AGENT: "agent",
29
+ ADAPTER: "adapter"
30
+ });
31
+ const EMERGENCY_SCOPE_TYPES = new Set(Object.values(EMERGENCY_SCOPE_TYPE));
32
+ const EMERGENCY_CONTROL_TYPE = Object.freeze({
33
+ PAUSE: "pause",
34
+ QUARANTINE: "quarantine",
35
+ REVOKE: "revoke",
36
+ KILL_SWITCH: "kill-switch"
37
+ });
38
+ const EMERGENCY_CONTROL_TYPES = Object.values(EMERGENCY_CONTROL_TYPE);
39
+ const EMERGENCY_CONTROL_TYPES_SET = new Set(EMERGENCY_CONTROL_TYPES);
40
+ const EMERGENCY_ACTION = Object.freeze({
41
+ PAUSE: "pause",
42
+ QUARANTINE: "quarantine",
43
+ REVOKE: "revoke",
44
+ KILL_SWITCH: "kill-switch",
45
+ RESUME: "resume"
46
+ });
47
+ const EMERGENCY_ACTIONS = new Set(Object.values(EMERGENCY_ACTION));
48
+
49
+ function normalizeEmergencyScopeTypeForReplay(raw) {
50
+ const value = typeof raw === "string" ? raw.trim().toLowerCase() : "";
51
+ if (!EMERGENCY_SCOPE_TYPES.has(value)) throw new TypeError("invalid emergency scope type");
52
+ return value;
53
+ }
54
+
55
+ function normalizeEmergencyScopeIdForReplay(scopeType, raw) {
56
+ if (scopeType === EMERGENCY_SCOPE_TYPE.TENANT) return null;
57
+ const value = typeof raw === "string" ? raw.trim() : "";
58
+ if (!value) throw new TypeError("emergency scope id is required for non-tenant scope");
59
+ return value;
60
+ }
61
+
62
+ function normalizeEmergencyControlTypeForReplay(raw, { allowNull = false } = {}) {
63
+ if (allowNull && (raw === null || raw === undefined || String(raw).trim() === "")) return null;
64
+ const value = typeof raw === "string" ? raw.trim().toLowerCase() : "";
65
+ if (!EMERGENCY_CONTROL_TYPES_SET.has(value)) throw new TypeError("invalid emergency control type");
66
+ return value;
67
+ }
68
+
69
+ function normalizeEmergencyActionForReplay(raw) {
70
+ const value = typeof raw === "string" ? raw.trim().toLowerCase() : "";
71
+ if (!EMERGENCY_ACTIONS.has(value)) throw new TypeError("invalid emergency action");
72
+ return value;
73
+ }
74
+
75
+ function normalizeEmergencyResumeControlTypesForReplay(raw) {
76
+ const values = Array.isArray(raw) ? raw : raw === null || raw === undefined ? EMERGENCY_CONTROL_TYPES : [raw];
77
+ const dedupe = new Set();
78
+ for (const item of values) {
79
+ const controlType = normalizeEmergencyControlTypeForReplay(item, { allowNull: false });
80
+ dedupe.add(controlType);
81
+ }
82
+ const out = Array.from(dedupe.values());
83
+ out.sort((left, right) => left.localeCompare(right));
84
+ return out;
85
+ }
86
+
87
+ function emergencyControlStateStoreKey({ tenantId, scopeType, scopeId, controlType }) {
88
+ const scopeToken = scopeType === EMERGENCY_SCOPE_TYPE.TENANT ? "*" : String(scopeId);
89
+ return makeScopedKey({ tenantId, id: `${scopeType}::${scopeToken}::${controlType}` });
90
+ }
91
+
25
92
  export function createFileTxLog({ dir, filename = "proxy-tx.log" }) {
26
93
  if (typeof dir !== "string" || dir.trim() === "") throw new TypeError("dir must be a non-empty string");
27
94
  fs.mkdirSync(dir, { recursive: true });
@@ -104,6 +171,24 @@ export function applyTxRecord(store, record) {
104
171
  continue;
105
172
  }
106
173
 
174
+ if (kind === "AGENT_PASSPORT_UPSERT") {
175
+ const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
176
+ const agentPassport = op.agentPassport ?? null;
177
+ if (!agentPassport || typeof agentPassport !== "object" || Array.isArray(agentPassport)) {
178
+ throw new TypeError("AGENT_PASSPORT_UPSERT requires agentPassport");
179
+ }
180
+ const agentId = agentPassport.agentId ?? op.agentId ?? null;
181
+ if (!agentId) throw new TypeError("AGENT_PASSPORT_UPSERT requires agentPassport.agentId");
182
+ const status = typeof agentPassport.status === "string" ? agentPassport.status.trim().toLowerCase() : "";
183
+ if (status !== "active" && status !== "suspended" && status !== "revoked") {
184
+ throw new TypeError("AGENT_PASSPORT_UPSERT requires status active|suspended|revoked");
185
+ }
186
+ if (!(store.agentPassports instanceof Map)) store.agentPassports = new Map();
187
+ const key = makeScopedKey({ tenantId, id: String(agentId) });
188
+ store.agentPassports.set(key, { ...agentPassport, tenantId, agentId: String(agentId), status });
189
+ continue;
190
+ }
191
+
107
192
  if (kind === "AGENT_WALLET_UPSERT") {
108
193
  const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
109
194
  const wallet = op.wallet ?? null;
@@ -199,6 +284,106 @@ export function applyTxRecord(store, record) {
199
284
  continue;
200
285
  }
201
286
 
287
+ if (kind === "EMERGENCY_CONTROL_EVENT_APPEND") {
288
+ const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
289
+ const event = op.event ?? null;
290
+ if (!event || typeof event !== "object" || Array.isArray(event)) {
291
+ throw new TypeError("EMERGENCY_CONTROL_EVENT_APPEND requires event");
292
+ }
293
+ const eventIdRaw = event.eventId ?? event.id ?? op.eventId ?? null;
294
+ if (eventIdRaw === null || eventIdRaw === undefined || String(eventIdRaw).trim() === "") {
295
+ throw new TypeError("EMERGENCY_CONTROL_EVENT_APPEND requires event.eventId");
296
+ }
297
+ const eventId = String(eventIdRaw).trim();
298
+ const action = normalizeEmergencyActionForReplay(event.action ?? op.action ?? null);
299
+
300
+ const scopeRaw = event.scope && typeof event.scope === "object" && !Array.isArray(event.scope) ? event.scope : {};
301
+ const scopeType = normalizeEmergencyScopeTypeForReplay(scopeRaw.type ?? event.scopeType ?? EMERGENCY_SCOPE_TYPE.TENANT);
302
+ const scopeId = normalizeEmergencyScopeIdForReplay(scopeType, scopeRaw.id ?? event.scopeId ?? null);
303
+
304
+ const controlType =
305
+ action === EMERGENCY_ACTION.RESUME
306
+ ? normalizeEmergencyControlTypeForReplay(event.controlType ?? op.controlType ?? null, { allowNull: true })
307
+ : normalizeEmergencyControlTypeForReplay(event.controlType ?? action, { allowNull: false });
308
+ const resumeControlTypes =
309
+ action === EMERGENCY_ACTION.RESUME
310
+ ? normalizeEmergencyResumeControlTypesForReplay(event.resumeControlTypes ?? op.resumeControlTypes ?? (controlType ? [controlType] : null))
311
+ : [];
312
+
313
+ const effectiveAt =
314
+ typeof event.effectiveAt === "string" && event.effectiveAt.trim() !== "" ? event.effectiveAt.trim() : record.at ?? new Date().toISOString();
315
+ const createdAt =
316
+ typeof event.createdAt === "string" && event.createdAt.trim() !== "" ? event.createdAt.trim() : effectiveAt;
317
+
318
+ if (!(store.emergencyControlEvents instanceof Map)) store.emergencyControlEvents = new Map();
319
+ if (!(store.emergencyControlState instanceof Map)) store.emergencyControlState = new Map();
320
+
321
+ const eventKey = makeScopedKey({ tenantId, id: eventId });
322
+ const normalizedEvent = {
323
+ ...event,
324
+ schemaVersion:
325
+ typeof event.schemaVersion === "string" && event.schemaVersion.trim() !== ""
326
+ ? event.schemaVersion.trim()
327
+ : "OpsEmergencyControlEvent.v1",
328
+ tenantId,
329
+ eventId,
330
+ action,
331
+ controlType,
332
+ resumeControlTypes,
333
+ scope: { type: scopeType, id: scopeId },
334
+ effectiveAt,
335
+ createdAt
336
+ };
337
+ const existingEvent = store.emergencyControlEvents.get(eventKey) ?? null;
338
+ if (existingEvent) {
339
+ if (canonicalJsonStringify(existingEvent) !== canonicalJsonStringify(normalizedEvent)) {
340
+ const err = new Error("emergency control event conflict");
341
+ err.code = "EMERGENCY_CONTROL_EVENT_CONFLICT";
342
+ err.statusCode = 409;
343
+ throw err;
344
+ }
345
+ continue;
346
+ }
347
+ store.emergencyControlEvents.set(eventKey, normalizedEvent);
348
+
349
+ function putState(nextControlType, nextActive) {
350
+ const stateKey = emergencyControlStateStoreKey({ tenantId, scopeType, scopeId, controlType: nextControlType });
351
+ const existingState = store.emergencyControlState.get(stateKey) ?? null;
352
+ const revision = Number.isSafeInteger(Number(existingState?.revision)) ? Number(existingState.revision) + 1 : 1;
353
+ const next = {
354
+ schemaVersion: "OpsEmergencyControlState.v1",
355
+ tenantId,
356
+ scopeType,
357
+ scopeId,
358
+ controlType: nextControlType,
359
+ active: nextActive === true,
360
+ activatedAt: nextActive === true ? effectiveAt : existingState?.activatedAt ?? null,
361
+ resumedAt: nextActive === true ? null : effectiveAt,
362
+ updatedAt: effectiveAt,
363
+ lastEventId: eventId,
364
+ lastAction: action,
365
+ reasonCode:
366
+ event.reasonCode === null || event.reasonCode === undefined || String(event.reasonCode).trim() === ""
367
+ ? null
368
+ : String(event.reasonCode).trim(),
369
+ reason: event.reason === null || event.reason === undefined || String(event.reason).trim() === "" ? null : String(event.reason).trim(),
370
+ operatorAction:
371
+ event.operatorAction && typeof event.operatorAction === "object" && !Array.isArray(event.operatorAction) ? event.operatorAction : null,
372
+ revision
373
+ };
374
+ store.emergencyControlState.set(stateKey, next);
375
+ }
376
+
377
+ if (action === EMERGENCY_ACTION.RESUME) {
378
+ for (const resumeControlType of resumeControlTypes) {
379
+ putState(resumeControlType, false);
380
+ }
381
+ } else {
382
+ putState(controlType, true);
383
+ }
384
+ continue;
385
+ }
386
+
202
387
  if (kind === "CONTRACT_UPSERT") {
203
388
  const contract = op.contract;
204
389
  if (!contract?.contractId) throw new TypeError("CONTRACT_UPSERT requires contract.contractId");
@@ -411,6 +596,277 @@ export function applyTxRecord(store, record) {
411
596
  continue;
412
597
  }
413
598
 
599
+ if (kind === "AGREEMENT_DELEGATION_UPSERT") {
600
+ const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
601
+ const delegation = op.delegation ?? null;
602
+ if (!delegation || typeof delegation !== "object" || Array.isArray(delegation)) {
603
+ throw new TypeError("AGREEMENT_DELEGATION_UPSERT requires delegation");
604
+ }
605
+ const delegationId = delegation.delegationId ?? op.delegationId ?? null;
606
+ if (!delegationId) throw new TypeError("AGREEMENT_DELEGATION_UPSERT requires delegation.delegationId");
607
+ if (!(store.agreementDelegations instanceof Map)) store.agreementDelegations = new Map();
608
+ const key = makeScopedKey({ tenantId, id: String(delegationId) });
609
+ store.agreementDelegations.set(key, { ...delegation, tenantId, delegationId: String(delegationId) });
610
+ continue;
611
+ }
612
+
613
+ if (kind === "X402_GATE_UPSERT") {
614
+ const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
615
+ const gate = op.gate ?? null;
616
+ if (!gate || typeof gate !== "object" || Array.isArray(gate)) {
617
+ throw new TypeError("X402_GATE_UPSERT requires gate");
618
+ }
619
+ const gateId = gate.gateId ?? gate.id ?? op.gateId ?? null;
620
+ if (!gateId) throw new TypeError("X402_GATE_UPSERT requires gate.gateId");
621
+ if (!(store.x402Gates instanceof Map)) store.x402Gates = new Map();
622
+ const key = makeScopedKey({ tenantId, id: String(gateId) });
623
+ store.x402Gates.set(key, { ...gate, tenantId, gateId: String(gateId) });
624
+ continue;
625
+ }
626
+
627
+ if (kind === "X402_AGENT_LIFECYCLE_UPSERT") {
628
+ const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
629
+ const agentLifecycle = op.agentLifecycle ?? null;
630
+ if (!agentLifecycle || typeof agentLifecycle !== "object" || Array.isArray(agentLifecycle)) {
631
+ throw new TypeError("X402_AGENT_LIFECYCLE_UPSERT requires agentLifecycle");
632
+ }
633
+ const agentId = agentLifecycle.agentId ?? op.agentId ?? null;
634
+ if (!agentId) throw new TypeError("X402_AGENT_LIFECYCLE_UPSERT requires agentLifecycle.agentId");
635
+ const status = typeof agentLifecycle.status === "string" ? agentLifecycle.status.trim().toLowerCase() : "";
636
+ if (status !== "active" && status !== "frozen" && status !== "archived") {
637
+ throw new TypeError("X402_AGENT_LIFECYCLE_UPSERT requires status active|frozen|archived");
638
+ }
639
+ if (!(store.x402AgentLifecycles instanceof Map)) store.x402AgentLifecycles = new Map();
640
+ const key = makeScopedKey({ tenantId, id: String(agentId) });
641
+ store.x402AgentLifecycles.set(key, { ...agentLifecycle, tenantId, agentId: String(agentId), status });
642
+ continue;
643
+ }
644
+
645
+ if (kind === "X402_RECEIPT_PUT") {
646
+ const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
647
+ const receipt = op.receipt ?? null;
648
+ if (!receipt || typeof receipt !== "object" || Array.isArray(receipt)) {
649
+ throw new TypeError("X402_RECEIPT_PUT requires receipt");
650
+ }
651
+ const receiptId = receipt.receiptId ?? op.receiptId ?? null;
652
+ if (!receiptId) throw new TypeError("X402_RECEIPT_PUT requires receipt.receiptId");
653
+ if (!(store.x402Receipts instanceof Map)) store.x402Receipts = new Map();
654
+ const key = makeScopedKey({ tenantId, id: String(receiptId) });
655
+ const normalized = {
656
+ ...receipt,
657
+ tenantId,
658
+ receiptId: String(receiptId),
659
+ reversal: null,
660
+ reversalEvents: []
661
+ };
662
+ const existing = store.x402Receipts.get(key) ?? null;
663
+ if (existing) {
664
+ const existingCanonical = canonicalJsonStringify(existing);
665
+ const incomingCanonical = canonicalJsonStringify(normalized);
666
+ if (existingCanonical !== incomingCanonical) {
667
+ const err = new Error("x402 receipt is immutable and cannot be changed");
668
+ err.code = "X402_RECEIPT_IMMUTABLE";
669
+ err.receiptId = String(receiptId);
670
+ throw err;
671
+ }
672
+ continue;
673
+ }
674
+ store.x402Receipts.set(key, normalized);
675
+ continue;
676
+ }
677
+
678
+ if (kind === "X402_WALLET_POLICY_UPSERT") {
679
+ const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
680
+ const policy = op.policy ?? null;
681
+ if (!policy || typeof policy !== "object" || Array.isArray(policy)) {
682
+ throw new TypeError("X402_WALLET_POLICY_UPSERT requires policy");
683
+ }
684
+ const sponsorWalletRef = typeof policy.sponsorWalletRef === "string" ? policy.sponsorWalletRef.trim() : "";
685
+ const policyRef = typeof policy.policyRef === "string" ? policy.policyRef.trim() : "";
686
+ const policyVersion = Number(policy.policyVersion);
687
+ if (!sponsorWalletRef) throw new TypeError("X402_WALLET_POLICY_UPSERT requires policy.sponsorWalletRef");
688
+ if (!policyRef) throw new TypeError("X402_WALLET_POLICY_UPSERT requires policy.policyRef");
689
+ if (!Number.isSafeInteger(policyVersion) || policyVersion <= 0) {
690
+ throw new TypeError("X402_WALLET_POLICY_UPSERT requires policy.policyVersion >= 1");
691
+ }
692
+ if (!(store.x402WalletPolicies instanceof Map)) store.x402WalletPolicies = new Map();
693
+ const key = makeScopedKey({ tenantId, id: `${sponsorWalletRef}::${policyRef}::${policyVersion}` });
694
+ store.x402WalletPolicies.set(key, {
695
+ ...policy,
696
+ tenantId,
697
+ sponsorWalletRef,
698
+ policyRef,
699
+ policyVersion
700
+ });
701
+ continue;
702
+ }
703
+
704
+ if (kind === "X402_ZK_VERIFICATION_KEY_PUT") {
705
+ const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
706
+ const verificationKey = op.verificationKey ?? null;
707
+ if (!verificationKey || typeof verificationKey !== "object" || Array.isArray(verificationKey)) {
708
+ throw new TypeError("X402_ZK_VERIFICATION_KEY_PUT requires verificationKey");
709
+ }
710
+ const verificationKeyId = verificationKey.verificationKeyId ?? op.verificationKeyId ?? null;
711
+ if (!verificationKeyId) throw new TypeError("X402_ZK_VERIFICATION_KEY_PUT requires verificationKey.verificationKeyId");
712
+ if (!(store.x402ZkVerificationKeys instanceof Map)) store.x402ZkVerificationKeys = new Map();
713
+ const key = makeScopedKey({ tenantId, id: String(verificationKeyId) });
714
+ const normalized = {
715
+ ...verificationKey,
716
+ tenantId,
717
+ verificationKeyId: String(verificationKeyId)
718
+ };
719
+ const existing = store.x402ZkVerificationKeys.get(key) ?? null;
720
+ if (existing) {
721
+ const existingCanonical = canonicalJsonStringify(existing);
722
+ const incomingCanonical = canonicalJsonStringify(normalized);
723
+ if (existingCanonical !== incomingCanonical) {
724
+ const err = new Error("x402 zk verification key is immutable and cannot be changed");
725
+ err.code = "X402_ZK_VERIFICATION_KEY_IMMUTABLE";
726
+ err.verificationKeyId = String(verificationKeyId);
727
+ throw err;
728
+ }
729
+ continue;
730
+ }
731
+ store.x402ZkVerificationKeys.set(key, normalized);
732
+ continue;
733
+ }
734
+
735
+ if (kind === "X402_REVERSAL_EVENT_APPEND") {
736
+ const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
737
+ const event = op.event ?? null;
738
+ if (!event || typeof event !== "object" || Array.isArray(event)) {
739
+ throw new TypeError("X402_REVERSAL_EVENT_APPEND requires event");
740
+ }
741
+ const eventId = op.eventId ?? event.eventId ?? event.id ?? null;
742
+ const gateId = op.gateId ?? event.gateId ?? null;
743
+ if (!eventId) throw new TypeError("X402_REVERSAL_EVENT_APPEND requires event.eventId");
744
+ if (!gateId) throw new TypeError("X402_REVERSAL_EVENT_APPEND requires event.gateId");
745
+ if (!(store.x402ReversalEvents instanceof Map)) store.x402ReversalEvents = new Map();
746
+ const key = makeScopedKey({ tenantId, id: String(eventId) });
747
+ store.x402ReversalEvents.set(key, {
748
+ ...event,
749
+ tenantId,
750
+ eventId: String(eventId),
751
+ gateId: String(gateId)
752
+ });
753
+ continue;
754
+ }
755
+
756
+ if (kind === "X402_REVERSAL_NONCE_PUT") {
757
+ const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
758
+ const usage = op.usage ?? null;
759
+ if (!usage || typeof usage !== "object" || Array.isArray(usage)) {
760
+ throw new TypeError("X402_REVERSAL_NONCE_PUT requires usage");
761
+ }
762
+ const sponsorRef = op.sponsorRef ?? usage.sponsorRef ?? null;
763
+ const nonce = op.nonce ?? usage.nonce ?? null;
764
+ if (!sponsorRef) throw new TypeError("X402_REVERSAL_NONCE_PUT requires sponsorRef");
765
+ if (!nonce) throw new TypeError("X402_REVERSAL_NONCE_PUT requires nonce");
766
+ if (!(store.x402ReversalNonceUsage instanceof Map)) store.x402ReversalNonceUsage = new Map();
767
+ const key = `${tenantId}\n${String(sponsorRef)}\n${String(nonce)}`;
768
+ store.x402ReversalNonceUsage.set(key, {
769
+ ...usage,
770
+ tenantId,
771
+ sponsorRef: String(sponsorRef),
772
+ nonce: String(nonce)
773
+ });
774
+ continue;
775
+ }
776
+
777
+ if (kind === "X402_REVERSAL_COMMAND_PUT") {
778
+ const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
779
+ const usage = op.usage ?? null;
780
+ if (!usage || typeof usage !== "object" || Array.isArray(usage)) {
781
+ throw new TypeError("X402_REVERSAL_COMMAND_PUT requires usage");
782
+ }
783
+ const commandId = op.commandId ?? usage.commandId ?? null;
784
+ if (!commandId) throw new TypeError("X402_REVERSAL_COMMAND_PUT requires commandId");
785
+ if (!(store.x402ReversalCommandUsage instanceof Map)) store.x402ReversalCommandUsage = new Map();
786
+ const key = makeScopedKey({ tenantId, id: String(commandId) });
787
+ store.x402ReversalCommandUsage.set(key, {
788
+ ...usage,
789
+ tenantId,
790
+ commandId: String(commandId)
791
+ });
792
+ continue;
793
+ }
794
+
795
+ if (kind === "X402_ESCALATION_UPSERT") {
796
+ const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
797
+ const escalation = op.escalation ?? null;
798
+ if (!escalation || typeof escalation !== "object" || Array.isArray(escalation)) {
799
+ throw new TypeError("X402_ESCALATION_UPSERT requires escalation");
800
+ }
801
+ const escalationId = escalation.escalationId ?? op.escalationId ?? null;
802
+ if (!escalationId) throw new TypeError("X402_ESCALATION_UPSERT requires escalation.escalationId");
803
+ if (!(store.x402Escalations instanceof Map)) store.x402Escalations = new Map();
804
+ const key = makeScopedKey({ tenantId, id: String(escalationId) });
805
+ store.x402Escalations.set(key, {
806
+ ...escalation,
807
+ tenantId,
808
+ escalationId: String(escalationId)
809
+ });
810
+ continue;
811
+ }
812
+
813
+ if (kind === "X402_ESCALATION_EVENT_APPEND") {
814
+ const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
815
+ const event = op.event ?? null;
816
+ if (!event || typeof event !== "object" || Array.isArray(event)) {
817
+ throw new TypeError("X402_ESCALATION_EVENT_APPEND requires event");
818
+ }
819
+ const eventId = op.eventId ?? event.eventId ?? event.id ?? null;
820
+ const escalationId = op.escalationId ?? event.escalationId ?? null;
821
+ if (!eventId) throw new TypeError("X402_ESCALATION_EVENT_APPEND requires event.eventId");
822
+ if (!escalationId) throw new TypeError("X402_ESCALATION_EVENT_APPEND requires event.escalationId");
823
+ if (!(store.x402EscalationEvents instanceof Map)) store.x402EscalationEvents = new Map();
824
+ const key = makeScopedKey({ tenantId, id: String(eventId) });
825
+ store.x402EscalationEvents.set(key, {
826
+ ...event,
827
+ tenantId,
828
+ eventId: String(eventId),
829
+ escalationId: String(escalationId)
830
+ });
831
+ continue;
832
+ }
833
+
834
+ if (kind === "X402_ESCALATION_OVERRIDE_USAGE_PUT") {
835
+ const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
836
+ const usage = op.usage ?? null;
837
+ if (!usage || typeof usage !== "object" || Array.isArray(usage)) {
838
+ throw new TypeError("X402_ESCALATION_OVERRIDE_USAGE_PUT requires usage");
839
+ }
840
+ const overrideId = op.overrideId ?? usage.overrideId ?? null;
841
+ if (!overrideId) throw new TypeError("X402_ESCALATION_OVERRIDE_USAGE_PUT requires overrideId");
842
+ if (!(store.x402EscalationOverrideUsage instanceof Map)) store.x402EscalationOverrideUsage = new Map();
843
+ const key = makeScopedKey({ tenantId, id: String(overrideId) });
844
+ store.x402EscalationOverrideUsage.set(key, {
845
+ ...usage,
846
+ tenantId,
847
+ overrideId: String(overrideId)
848
+ });
849
+ continue;
850
+ }
851
+
852
+ if (kind === "X402_WEBHOOK_ENDPOINT_UPSERT") {
853
+ const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
854
+ const endpoint = op.endpoint ?? null;
855
+ if (!endpoint || typeof endpoint !== "object" || Array.isArray(endpoint)) {
856
+ throw new TypeError("X402_WEBHOOK_ENDPOINT_UPSERT requires endpoint");
857
+ }
858
+ const endpointId = endpoint.endpointId ?? op.endpointId ?? null;
859
+ if (!endpointId) throw new TypeError("X402_WEBHOOK_ENDPOINT_UPSERT requires endpoint.endpointId");
860
+ if (!(store.x402WebhookEndpoints instanceof Map)) store.x402WebhookEndpoints = new Map();
861
+ const key = makeScopedKey({ tenantId, id: String(endpointId) });
862
+ store.x402WebhookEndpoints.set(key, {
863
+ ...endpoint,
864
+ tenantId,
865
+ endpointId: String(endpointId)
866
+ });
867
+ continue;
868
+ }
869
+
414
870
  if (kind === "TOOL_CALL_HOLD_UPSERT") {
415
871
  const tenantId = normalizeTenantId(op.tenantId ?? DEFAULT_TENANT_ID);
416
872
  const hold = op.hold ?? null;
package/src/api/server.js CHANGED
@@ -8,6 +8,49 @@ import { configForLog, loadConfig } from "../core/config.js";
8
8
  const cfg = loadConfig({ mode: "api" });
9
9
  logger.info("config.effective", { config: configForLog(cfg) });
10
10
 
11
+ const corsAllowOriginsEnv =
12
+ typeof process !== "undefined" && typeof process.env.PROXY_CORS_ALLOW_ORIGINS === "string"
13
+ ? process.env.PROXY_CORS_ALLOW_ORIGINS
14
+ : "";
15
+ const corsAllowOrigins = new Set(
16
+ corsAllowOriginsEnv
17
+ .split(",")
18
+ .map((row) => row.trim())
19
+ .filter((row) => row !== "")
20
+ );
21
+ const DEV_CORS_ORIGIN_RE = /^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;
22
+
23
+ function resolveCorsOrigin(originHeader) {
24
+ if (typeof originHeader !== "string" || originHeader.trim() === "") return null;
25
+ const origin = originHeader.trim();
26
+ if (corsAllowOrigins.has("*")) return "*";
27
+ if (corsAllowOrigins.has(origin)) return origin;
28
+ if (DEV_CORS_ORIGIN_RE.test(origin)) return origin;
29
+ return null;
30
+ }
31
+
32
+ function applyCorsHeaders(req, res) {
33
+ const allowOrigin = resolveCorsOrigin(req.headers?.origin);
34
+ if (!allowOrigin) return false;
35
+ res.setHeader("access-control-allow-origin", allowOrigin);
36
+ res.setHeader("vary", "origin");
37
+ res.setHeader("access-control-allow-methods", "GET,POST,PUT,PATCH,DELETE,OPTIONS");
38
+ res.setHeader(
39
+ "access-control-allow-headers",
40
+ [
41
+ "authorization",
42
+ "content-type",
43
+ "idempotency-key",
44
+ "x-proxy-tenant-id",
45
+ "x-proxy-ops-token",
46
+ "x-request-id",
47
+ "x-settld-protocol"
48
+ ].join(", ")
49
+ );
50
+ res.setHeader("access-control-max-age", "600");
51
+ return true;
52
+ }
53
+
11
54
  let store;
12
55
  if (cfg.store.mode === "pg") {
13
56
  store = await createPgStore({
@@ -22,12 +65,30 @@ const api = createApi({ store });
22
65
  const { handle } = api;
23
66
 
24
67
  const port = cfg.api.port;
25
- const server = http.createServer(handle);
26
- server.listen(port, () => {
27
- const storeDesc =
28
- cfg.store.mode === "pg" ? "(postgres)" : cfg.store.persistenceDir ? `(dataDir=${cfg.store.persistenceDir})` : "(in-memory)";
29
- logger.info("api listening", { port, storeMode: cfg.store.mode, storeDesc });
68
+ const server = http.createServer((req, res) => {
69
+ applyCorsHeaders(req, res);
70
+ if (req.method === "OPTIONS") {
71
+ res.statusCode = 204;
72
+ res.end();
73
+ return;
74
+ }
75
+ return handle(req, res);
30
76
  });
77
+ const bindHostRaw = typeof process !== "undefined" ? (process.env.PROXY_BIND_HOST ?? process.env.BIND_HOST ?? "") : "";
78
+ const bindHost = typeof bindHostRaw === "string" && bindHostRaw.trim() !== "" ? bindHostRaw.trim() : null;
79
+ if (bindHost) {
80
+ server.listen(port, bindHost, () => {
81
+ const storeDesc =
82
+ cfg.store.mode === "pg" ? "(postgres)" : cfg.store.persistenceDir ? `(dataDir=${cfg.store.persistenceDir})` : "(in-memory)";
83
+ logger.info("api listening", { port, host: bindHost, storeMode: cfg.store.mode, storeDesc });
84
+ });
85
+ } else {
86
+ server.listen(port, () => {
87
+ const storeDesc =
88
+ cfg.store.mode === "pg" ? "(postgres)" : cfg.store.persistenceDir ? `(dataDir=${cfg.store.persistenceDir})` : "(in-memory)";
89
+ logger.info("api listening", { port, storeMode: cfg.store.mode, storeDesc });
90
+ });
91
+ }
31
92
 
32
93
  const autotickIntervalMs = cfg.api.autotick.intervalMs;
33
94
  const autotickMaxMessages = cfg.api.autotick.maxMessages;
@@ -48,12 +109,27 @@ async function runAutotickOnce() {
48
109
  if (cfg.store.mode === "pg" && typeof store.processOutbox === "function") {
49
110
  await store.processOutbox({ maxMessages: autotickMaxMessages });
50
111
  }
112
+ if (typeof api.tickDispatch === "function") {
113
+ await api.tickDispatch({ maxMessages: autotickMaxMessages });
114
+ }
115
+ if (typeof api.tickProof === "function") {
116
+ await api.tickProof({ maxMessages: autotickMaxMessages });
117
+ }
51
118
  if (typeof api.tickArtifacts === "function") {
52
119
  await api.tickArtifacts({ maxMessages: autotickMaxMessages });
53
120
  }
54
121
  if (typeof api.tickDeliveries === "function") {
55
122
  await api.tickDeliveries({ maxMessages: autotickMaxMessages });
56
123
  }
124
+ if (typeof api.tickX402Holdbacks === "function") {
125
+ await api.tickX402Holdbacks({ maxMessages: autotickMaxMessages });
126
+ }
127
+ if (typeof api.tickX402InsolvencySweep === "function") {
128
+ await api.tickX402InsolvencySweep({ maxMessages: autotickMaxMessages });
129
+ }
130
+ if (typeof api.tickX402WinddownReversals === "function") {
131
+ await api.tickX402WinddownReversals({ maxMessages: autotickMaxMessages });
132
+ }
57
133
  if (typeof api.tickBillingStripeSync === "function") {
58
134
  await api.tickBillingStripeSync({ maxRows: autotickMaxMessages });
59
135
  }