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
@@ -33,13 +33,22 @@ const OPERATOR_SIGNED_TYPES = new Set([
33
33
  "OPERATOR_SHIFT_CLOSED"
34
34
  ]);
35
35
 
36
+ const OPERATOR_EMERGENCY_SIGNED_TYPES = new Set([
37
+ "OPERATOR_EMERGENCY_PAUSE",
38
+ "OPERATOR_EMERGENCY_QUARANTINE",
39
+ "OPERATOR_EMERGENCY_REVOKE",
40
+ "OPERATOR_EMERGENCY_REVOKE_DELEGATION",
41
+ "OPERATOR_EMERGENCY_KILL_SWITCH",
42
+ "OPERATOR_EMERGENCY_RESUME"
43
+ ]);
44
+
36
45
  const ROBOT_OR_OPERATOR_SIGNED_TYPES = new Set(["ACCESS_GRANTED", "ACCESS_DENIED", "SKILL_USED", "ZONE_COVERAGE_REPORTED"]);
37
46
 
38
47
  const SERVER_OR_OPERATOR_SIGNED_TYPES = new Set(["INCIDENT_REPORTED", "CLAIM_TRIAGED"]);
39
48
 
40
49
  const SERVER_OR_ROBOT_SIGNED_TYPES = new Set(["EVIDENCE_CAPTURED", "JOB_EXECUTION_ABORTED", "JOB_EXECUTION_RESUMED", "ROBOT_UNHEALTHY"]);
41
50
 
42
- const SERVER_SIGNED_TYPES = new Set([
51
+ const SERVER_SIGNED_TYPES = new Set([
43
52
  "JOB_CREATED",
44
53
  "QUOTE_PROPOSED",
45
54
  "RISK_SCORED",
@@ -104,6 +113,8 @@ const SERVER_OR_ROBOT_SIGNED_TYPES = new Set(["EVIDENCE_CAPTURED", "JOB_EXECUTIO
104
113
  export function requiredSignerKindForEventType(eventType) {
105
114
  if (ROBOT_SIGNED_TYPES.has(eventType)) return SIGNER_KIND.ROBOT;
106
115
  if (OPERATOR_SIGNED_TYPES.has(eventType)) return SIGNER_KIND.OPERATOR;
116
+ if (OPERATOR_EMERGENCY_SIGNED_TYPES.has(eventType)) return SIGNER_KIND.OPERATOR;
117
+ if (typeof eventType === "string" && eventType.startsWith("OPERATOR_EMERGENCY_")) return SIGNER_KIND.OPERATOR;
107
118
  if (ROBOT_OR_OPERATOR_SIGNED_TYPES.has(eventType)) return SIGNER_KIND.ROBOT_OR_OPERATOR;
108
119
  if (SERVER_OR_OPERATOR_SIGNED_TYPES.has(eventType)) return SIGNER_KIND.SERVER_OR_OPERATOR;
109
120
  if (SERVER_OR_ROBOT_SIGNED_TYPES.has(eventType)) return SIGNER_KIND.SERVER_OR_ROBOT;
@@ -113,7 +124,15 @@ export function requiredSignerKindForEventType(eventType) {
113
124
 
114
125
  export function listKnownEventTypes() {
115
126
  const all = new Set();
116
- for (const s of [ROBOT_SIGNED_TYPES, OPERATOR_SIGNED_TYPES, ROBOT_OR_OPERATOR_SIGNED_TYPES, SERVER_OR_OPERATOR_SIGNED_TYPES, SERVER_OR_ROBOT_SIGNED_TYPES, SERVER_SIGNED_TYPES]) {
127
+ for (const s of [
128
+ ROBOT_SIGNED_TYPES,
129
+ OPERATOR_SIGNED_TYPES,
130
+ OPERATOR_EMERGENCY_SIGNED_TYPES,
131
+ ROBOT_OR_OPERATOR_SIGNED_TYPES,
132
+ SERVER_OR_OPERATOR_SIGNED_TYPES,
133
+ SERVER_OR_ROBOT_SIGNED_TYPES,
134
+ SERVER_SIGNED_TYPES
135
+ ]) {
117
136
  for (const t of s) all.add(t);
118
137
  }
119
138
  return Array.from(all).sort();
@@ -1,3 +1,4 @@
1
1
  export const RETENTION_CLEANUP_ADVISORY_LOCK_KEY = "settld:maintenance:retention_cleanup:v1";
2
2
  export const FINANCE_RECONCILE_ADVISORY_LOCK_KEY = "settld:maintenance:finance_reconcile:v1";
3
+ export const MONEY_RAIL_RECONCILE_ADVISORY_LOCK_KEY = "settld:maintenance:money_rail_reconcile:v1";
3
4
  export const MIGRATIONS_ADVISORY_LOCK_KEY = "settld:migrations:v1";
@@ -0,0 +1,303 @@
1
+ import { canonicalJsonStringify, normalizeForCanonicalJson } from "./canonical-json.js";
2
+ import { keyIdFromPublicKeyPem, sha256Hex, signHashHexEd25519, verifyHashHexEd25519 } from "./crypto.js";
3
+
4
+ export const OPERATOR_ACTION_SCHEMA_VERSION = "OperatorAction.v1";
5
+ export const OPERATOR_ACTION_SIGNATURE_SCHEMA_VERSION = "OperatorActionSignature.v1";
6
+
7
+ const ALLOWED_CASE_KINDS = new Set(["challenge", "dispute", "escalation"]);
8
+ const ALLOWED_ACTIONS = new Set(["APPROVE", "REJECT", "REQUEST_INFO", "OVERRIDE_ALLOW", "OVERRIDE_DENY"]);
9
+
10
+ function assertPlainObject(value, name) {
11
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError(`${name} must be an object`);
12
+ if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
13
+ throw new TypeError(`${name} must be a plain object`);
14
+ }
15
+ }
16
+
17
+ function assertNonEmptyString(value, name) {
18
+ if (typeof value !== "string" || value.trim() === "") throw new TypeError(`${name} must be a non-empty string`);
19
+ return String(value).trim();
20
+ }
21
+
22
+ function assertIsoDateTime(value, name) {
23
+ const out = assertNonEmptyString(value, name);
24
+ if (!/^\d{4}-\d{2}-\d{2}T/.test(out)) throw new TypeError(`${name} must be an ISO date-time`);
25
+ if (!Number.isFinite(Date.parse(out))) throw new TypeError(`${name} must be an ISO date-time`);
26
+ return new Date(out).toISOString();
27
+ }
28
+
29
+ function assertPemString(value, name) {
30
+ if (typeof value !== "string" || value.trim() === "") throw new TypeError(`${name} must be a non-empty PEM string`);
31
+ return value;
32
+ }
33
+
34
+ function assertId(value, name, { max = 200 } = {}) {
35
+ const out = assertNonEmptyString(value, name);
36
+ if (out.length > max) throw new TypeError(`${name} must be <= ${max} chars`);
37
+ if (!/^[A-Za-z0-9:._/-]+$/.test(out)) throw new TypeError(`${name} must match ^[A-Za-z0-9:._/-]+$`);
38
+ return out;
39
+ }
40
+
41
+ function assertOptionalId(value, name, { max = 200 } = {}) {
42
+ if (value === null || value === undefined || String(value).trim() === "") return null;
43
+ return assertId(value, name, { max });
44
+ }
45
+
46
+ function assertSha256Hex(value, name) {
47
+ const out = assertNonEmptyString(value, name).toLowerCase();
48
+ if (!/^[0-9a-f]{64}$/.test(out)) throw new TypeError(`${name} must be sha256 hex`);
49
+ return out;
50
+ }
51
+
52
+ function assertAction(value, name = "action.action") {
53
+ const out = assertNonEmptyString(value, name).toUpperCase();
54
+ if (!ALLOWED_ACTIONS.has(out)) {
55
+ throw new TypeError(`${name} must be APPROVE|REJECT|REQUEST_INFO|OVERRIDE_ALLOW|OVERRIDE_DENY`);
56
+ }
57
+ return out;
58
+ }
59
+
60
+ function assertJustificationCode(value, name = "action.justificationCode") {
61
+ const out = assertNonEmptyString(value, name).toUpperCase();
62
+ if (out.length > 128) throw new TypeError(`${name} must be <= 128 chars`);
63
+ if (!/^[A-Z][A-Z0-9._:-]*$/.test(out)) throw new TypeError(`${name} must match ^[A-Z][A-Z0-9._:-]*$`);
64
+ return out;
65
+ }
66
+
67
+ function assertOptionalJustificationText(value, name = "action.justification", { max = 2000 } = {}) {
68
+ if (value === null || value === undefined || String(value).trim() === "") return null;
69
+ const out = String(value).trim();
70
+ if (out.length > max) throw new TypeError(`${name} must be <= ${max} chars`);
71
+ return out;
72
+ }
73
+
74
+ function assertOptionalToken(value, name, { max = 128 } = {}) {
75
+ if (value === null || value === undefined || String(value).trim() === "") return null;
76
+ const out = String(value).trim().toLowerCase();
77
+ if (out.length > max) throw new TypeError(`${name} must be <= ${max} chars`);
78
+ if (!/^[a-z0-9._:-]+$/.test(out)) throw new TypeError(`${name} must match ^[a-z0-9._:-]+$`);
79
+ return out;
80
+ }
81
+
82
+ function normalizeCaseRef(action) {
83
+ const caseRefRaw = action.caseRef;
84
+ if (!caseRefRaw || typeof caseRefRaw !== "object" || Array.isArray(caseRefRaw)) {
85
+ throw new TypeError("action.caseRef must be an object");
86
+ }
87
+ const caseKind = assertNonEmptyString(caseRefRaw.kind, "action.caseRef.kind").toLowerCase();
88
+ if (!ALLOWED_CASE_KINDS.has(caseKind)) {
89
+ throw new TypeError("action.caseRef.kind must be challenge|dispute|escalation");
90
+ }
91
+ return normalizeForCanonicalJson(
92
+ {
93
+ kind: caseKind,
94
+ caseId: assertId(caseRefRaw.caseId, "action.caseRef.caseId", { max: 240 })
95
+ },
96
+ { path: "$.caseRef" }
97
+ );
98
+ }
99
+
100
+ function normalizeActor(actor) {
101
+ assertPlainObject(actor, "action.actor");
102
+ const operatorId = assertOptionalId(actor.operatorId ?? actor.id, "action.actor.operatorId", { max: 200 });
103
+ if (!operatorId) throw new TypeError("action.actor.operatorId is required");
104
+ const role = assertOptionalToken(actor.role, "action.actor.role", { max: 128 });
105
+ const tenantId = assertOptionalId(actor.tenantId, "action.actor.tenantId", { max: 128 });
106
+ const sessionId = assertOptionalId(actor.sessionId, "action.actor.sessionId", { max: 256 });
107
+ let metadata = null;
108
+ if (Object.prototype.hasOwnProperty.call(actor, "metadata")) {
109
+ assertPlainObject(actor.metadata, "action.actor.metadata");
110
+ metadata = normalizeForCanonicalJson(actor.metadata, { path: "$.actor.metadata" });
111
+ }
112
+ return normalizeForCanonicalJson(
113
+ {
114
+ operatorId,
115
+ ...(role ? { role } : {}),
116
+ ...(tenantId ? { tenantId } : {}),
117
+ ...(sessionId ? { sessionId } : {}),
118
+ ...(metadata ? { metadata } : {})
119
+ },
120
+ { path: "$.actor" }
121
+ );
122
+ }
123
+
124
+ function normalizeOperatorActionSignature(signature) {
125
+ assertPlainObject(signature, "action.signature");
126
+ return normalizeForCanonicalJson(
127
+ {
128
+ schemaVersion: (() => {
129
+ const schemaVersion = assertNonEmptyString(signature.schemaVersion, "action.signature.schemaVersion");
130
+ if (schemaVersion !== OPERATOR_ACTION_SIGNATURE_SCHEMA_VERSION) {
131
+ throw new TypeError(`action.signature.schemaVersion must be ${OPERATOR_ACTION_SIGNATURE_SCHEMA_VERSION}`);
132
+ }
133
+ return schemaVersion;
134
+ })(),
135
+ algorithm: (() => {
136
+ const algorithm = assertNonEmptyString(signature.algorithm, "action.signature.algorithm").toLowerCase();
137
+ if (algorithm !== "ed25519") throw new TypeError("action.signature.algorithm must be ed25519");
138
+ return "ed25519";
139
+ })(),
140
+ keyId: assertId(signature.keyId, "action.signature.keyId", { max: 256 }),
141
+ signedAt: assertIsoDateTime(signature.signedAt, "action.signature.signedAt"),
142
+ actionHash: assertSha256Hex(signature.actionHash, "action.signature.actionHash"),
143
+ signatureBase64: assertNonEmptyString(signature.signatureBase64, "action.signature.signatureBase64")
144
+ },
145
+ { path: "$.signature" }
146
+ );
147
+ }
148
+
149
+ export function buildOperatorActionV1(action = {}) {
150
+ assertPlainObject(action, "action");
151
+ if (action.schemaVersion !== undefined && action.schemaVersion !== null) {
152
+ const schemaVersion = assertNonEmptyString(action.schemaVersion, "action.schemaVersion");
153
+ if (schemaVersion !== OPERATOR_ACTION_SCHEMA_VERSION) {
154
+ throw new TypeError(`action.schemaVersion must be ${OPERATOR_ACTION_SCHEMA_VERSION}`);
155
+ }
156
+ }
157
+
158
+ let metadata = null;
159
+ if (Object.prototype.hasOwnProperty.call(action, "metadata")) {
160
+ assertPlainObject(action.metadata, "action.metadata");
161
+ metadata = normalizeForCanonicalJson(action.metadata, { path: "$.metadata" });
162
+ }
163
+
164
+ const normalized = normalizeForCanonicalJson(
165
+ {
166
+ schemaVersion: OPERATOR_ACTION_SCHEMA_VERSION,
167
+ ...(assertOptionalId(action.actionId, "action.actionId", { max: 240 })
168
+ ? { actionId: assertOptionalId(action.actionId, "action.actionId", { max: 240 }) }
169
+ : {}),
170
+ caseRef: normalizeCaseRef(action),
171
+ action: assertAction(action.action),
172
+ justificationCode: assertJustificationCode(action.justificationCode),
173
+ ...(assertOptionalJustificationText(action.justification) ? { justification: assertOptionalJustificationText(action.justification) } : {}),
174
+ actor: normalizeActor(action.actor),
175
+ actedAt: assertIsoDateTime(action.actedAt, "action.actedAt"),
176
+ ...(metadata ? { metadata } : {})
177
+ },
178
+ { path: "$" }
179
+ );
180
+
181
+ return normalized;
182
+ }
183
+
184
+ function normalizeSignedOperatorActionV1(action = {}) {
185
+ const normalizedAction = buildOperatorActionV1(action);
186
+ const signature = normalizeOperatorActionSignature(action.signature);
187
+ return normalizeForCanonicalJson(
188
+ {
189
+ ...normalizedAction,
190
+ signature
191
+ },
192
+ { path: "$" }
193
+ );
194
+ }
195
+
196
+ export function computeOperatorActionHashV1({ action } = {}) {
197
+ const normalizedAction = buildOperatorActionV1(action ?? {});
198
+ return sha256Hex(canonicalJsonStringify(normalizedAction));
199
+ }
200
+
201
+ export function signOperatorActionV1({ action, signedAt, publicKeyPem, privateKeyPem } = {}) {
202
+ const normalizedAction = buildOperatorActionV1(action ?? {});
203
+ const signerPublicKeyPem = assertPemString(publicKeyPem, "publicKeyPem");
204
+ const signerPrivateKeyPem = assertPemString(privateKeyPem, "privateKeyPem");
205
+ const actionHash = computeOperatorActionHashV1({ action: normalizedAction });
206
+ const signatureBase64 = signHashHexEd25519(actionHash, signerPrivateKeyPem);
207
+ return normalizeForCanonicalJson(
208
+ {
209
+ ...normalizedAction,
210
+ signature: {
211
+ schemaVersion: OPERATOR_ACTION_SIGNATURE_SCHEMA_VERSION,
212
+ algorithm: "ed25519",
213
+ keyId: keyIdFromPublicKeyPem(signerPublicKeyPem),
214
+ signedAt: assertIsoDateTime(signedAt ?? normalizedAction.actedAt, "signedAt"),
215
+ actionHash,
216
+ signatureBase64
217
+ }
218
+ },
219
+ { path: "$" }
220
+ );
221
+ }
222
+
223
+ export function verifyOperatorActionV1({ action, publicKeyPem } = {}) {
224
+ try {
225
+ const signerPublicKeyPem = assertPemString(publicKeyPem, "publicKeyPem");
226
+ assertPlainObject(action, "action");
227
+
228
+ const schemaVersion = assertNonEmptyString(action.schemaVersion, "action.schemaVersion");
229
+ if (schemaVersion !== OPERATOR_ACTION_SCHEMA_VERSION) {
230
+ return {
231
+ ok: false,
232
+ code: "OPERATOR_ACTION_SCHEMA_MISMATCH",
233
+ error: `action.schemaVersion must be ${OPERATOR_ACTION_SCHEMA_VERSION}`
234
+ };
235
+ }
236
+
237
+ if (!action.signature || typeof action.signature !== "object" || Array.isArray(action.signature)) {
238
+ return {
239
+ ok: false,
240
+ code: "OPERATOR_ACTION_SCHEMA_INVALID",
241
+ error: "action.signature must be an object"
242
+ };
243
+ }
244
+
245
+ if (String(action.signature.schemaVersion ?? "") !== OPERATOR_ACTION_SIGNATURE_SCHEMA_VERSION) {
246
+ return {
247
+ ok: false,
248
+ code: "OPERATOR_ACTION_SIGNATURE_SCHEMA_MISMATCH",
249
+ error: `action.signature.schemaVersion must be ${OPERATOR_ACTION_SIGNATURE_SCHEMA_VERSION}`
250
+ };
251
+ }
252
+
253
+ const normalized = normalizeSignedOperatorActionV1(action);
254
+
255
+ const expectedKeyId = keyIdFromPublicKeyPem(signerPublicKeyPem);
256
+ if (normalized.signature.keyId !== expectedKeyId) {
257
+ return {
258
+ ok: false,
259
+ code: "OPERATOR_ACTION_KEY_ID_MISMATCH",
260
+ error: "signature keyId mismatch"
261
+ };
262
+ }
263
+
264
+ const actionHash = computeOperatorActionHashV1({ action: normalized });
265
+ if (normalized.signature.actionHash !== actionHash) {
266
+ return {
267
+ ok: false,
268
+ code: "OPERATOR_ACTION_HASH_MISMATCH",
269
+ error: "action hash mismatch"
270
+ };
271
+ }
272
+
273
+ const signatureValid = verifyHashHexEd25519({
274
+ hashHex: actionHash,
275
+ signatureBase64: normalized.signature.signatureBase64,
276
+ publicKeyPem: signerPublicKeyPem
277
+ });
278
+ if (!signatureValid) {
279
+ return {
280
+ ok: false,
281
+ code: "OPERATOR_ACTION_SIGNATURE_INVALID",
282
+ error: "signature invalid"
283
+ };
284
+ }
285
+
286
+ const normalizedAction = buildOperatorActionV1(normalized);
287
+ return {
288
+ ok: true,
289
+ code: null,
290
+ error: null,
291
+ actionHash,
292
+ keyId: normalized.signature.keyId,
293
+ action: normalizedAction,
294
+ signedAction: normalized
295
+ };
296
+ } catch (err) {
297
+ return {
298
+ ok: false,
299
+ code: "OPERATOR_ACTION_SCHEMA_INVALID",
300
+ error: err?.message ?? String(err ?? "")
301
+ };
302
+ }
303
+ }
@@ -0,0 +1,318 @@
1
+ import { canonicalJsonStringify, normalizeForCanonicalJson } from "./canonical-json.js";
2
+ import { sha256Hex } from "./crypto.js";
3
+
4
+ export const PAID_TOOL_MANIFEST_SCHEMA_VERSION_V1 = "PaidToolManifest.v1";
5
+ export const PAID_TOOL_MANIFEST_SCHEMA_VERSION_V2 = "PaidToolManifest.v2";
6
+ export const PAID_TOOL_MANIFEST_SCHEMA_VERSION = PAID_TOOL_MANIFEST_SCHEMA_VERSION_V1;
7
+
8
+ function assertPlainObject(value, name) {
9
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
10
+ throw new TypeError(`${name} must be an object`);
11
+ }
12
+ }
13
+
14
+ function normalizeNonEmptyString(value, name, { max = 256 } = {}) {
15
+ const text = typeof value === "string" ? value.trim() : "";
16
+ if (!text) throw new TypeError(`${name} is required`);
17
+ if (text.length > max) throw new TypeError(`${name} must be <= ${max} chars`);
18
+ return text;
19
+ }
20
+
21
+ function normalizeOptionalString(value, name, { max = 2048 } = {}) {
22
+ if (value === null || value === undefined || String(value).trim() === "") return null;
23
+ const text = String(value).trim();
24
+ if (text.length > max) throw new TypeError(`${name} must be <= ${max} chars`);
25
+ return text;
26
+ }
27
+
28
+ function normalizeOptionalAbsoluteHttpUrl(value, name) {
29
+ const raw = normalizeOptionalString(value, name, { max: 2048 });
30
+ if (!raw) return null;
31
+ let parsed = null;
32
+ try {
33
+ parsed = new URL(raw);
34
+ } catch {
35
+ throw new TypeError(`${name} must be an absolute URL`);
36
+ }
37
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
38
+ throw new TypeError(`${name} must use http or https`);
39
+ }
40
+ return parsed.toString();
41
+ }
42
+
43
+ function normalizeManifestSchemaVersion(value) {
44
+ const text = normalizeNonEmptyString(value, "manifest.schemaVersion", { max: 64 });
45
+ if (text === PAID_TOOL_MANIFEST_SCHEMA_VERSION_V1 || text === PAID_TOOL_MANIFEST_SCHEMA_VERSION_V2) return text;
46
+ throw new TypeError(
47
+ `manifest.schemaVersion must be ${PAID_TOOL_MANIFEST_SCHEMA_VERSION_V1} or ${PAID_TOOL_MANIFEST_SCHEMA_VERSION_V2}`
48
+ );
49
+ }
50
+
51
+ function normalizeToolClass(value, name) {
52
+ const raw = normalizeOptionalString(value, name, { max: 32 });
53
+ const normalized = raw ? raw.toLowerCase() : null;
54
+ if (normalized === null) return null;
55
+ if (!["read", "compute", "action"].includes(normalized)) {
56
+ throw new TypeError(`${name} must be read|compute|action`);
57
+ }
58
+ return normalized;
59
+ }
60
+
61
+ function normalizeRiskLevel(value, name) {
62
+ const raw = normalizeOptionalString(value, name, { max: 32 });
63
+ if (!raw) return null;
64
+ const normalized = raw.toLowerCase() === "med" ? "medium" : raw.toLowerCase();
65
+ if (!["low", "medium", "high"].includes(normalized)) {
66
+ throw new TypeError(`${name} must be low|medium|high`);
67
+ }
68
+ return normalized;
69
+ }
70
+
71
+ function normalizeStringArray(value, name, { maxItems = 32, maxLen = 64 } = {}) {
72
+ if (value === null || value === undefined) return [];
73
+ if (!Array.isArray(value)) throw new TypeError(`${name} must be an array`);
74
+ const out = [];
75
+ const seen = new Set();
76
+ for (let i = 0; i < value.length; i += 1) {
77
+ const row = normalizeNonEmptyString(value[i], `${name}[${i}]`, { max: maxLen }).toLowerCase();
78
+ if (seen.has(row)) continue;
79
+ seen.add(row);
80
+ out.push(row);
81
+ if (out.length > maxItems) throw new TypeError(`${name} must contain <= ${maxItems} items`);
82
+ }
83
+ return out;
84
+ }
85
+
86
+ function normalizeRequiredSignatures(value, name) {
87
+ const allowed = new Set(["quote", "output", "refund_decision"]);
88
+ const out = normalizeStringArray(value, name, { maxItems: 8, maxLen: 32 });
89
+ for (const item of out) {
90
+ if (!allowed.has(item)) throw new TypeError(`${name} contains unsupported value: ${item}`);
91
+ }
92
+ return out;
93
+ }
94
+
95
+ function normalizeRequestBinding(value, name) {
96
+ const raw = normalizeOptionalString(value, name, { max: 32 });
97
+ if (!raw) return null;
98
+ const normalized = raw.toLowerCase();
99
+ if (!["strict", "recommended", "none"].includes(normalized)) {
100
+ throw new TypeError(`${name} must be strict|recommended|none`);
101
+ }
102
+ return normalized;
103
+ }
104
+
105
+ function normalizeHttpMethod(value, name) {
106
+ const method = normalizeNonEmptyString(value ?? "GET", name, { max: 16 }).toUpperCase();
107
+ if (!["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"].includes(method)) {
108
+ throw new TypeError(`${name} must be GET|POST|PUT|PATCH|DELETE|HEAD`);
109
+ }
110
+ return method;
111
+ }
112
+
113
+ function normalizeCurrency(value, name) {
114
+ const raw = typeof value === "string" && value.trim() !== "" ? value.trim().toUpperCase() : "USD";
115
+ if (!/^[A-Z][A-Z0-9_]{2,11}$/.test(raw)) throw new TypeError(`${name} must match ^[A-Z][A-Z0-9_]{2,11}$`);
116
+ return raw;
117
+ }
118
+
119
+ function normalizePositiveSafeInt(value, name) {
120
+ const n = Number(value);
121
+ if (!Number.isSafeInteger(n) || n <= 0) throw new TypeError(`${name} must be a positive safe integer`);
122
+ return n;
123
+ }
124
+
125
+ function normalizeRoutePath(value, name) {
126
+ const text = normalizeNonEmptyString(value, name, { max: 1024 });
127
+ if (!text.startsWith("/")) throw new TypeError(`${name} must start with /`);
128
+ if (text.includes("..")) throw new TypeError(`${name} must not contain path traversal`);
129
+ return text;
130
+ }
131
+
132
+ function normalizePricing(rawPricing, defaults, fieldPath) {
133
+ const pricing = rawPricing && typeof rawPricing === "object" && !Array.isArray(rawPricing) ? rawPricing : {};
134
+ const amountCents = normalizePositiveSafeInt(pricing.amountCents ?? defaults.amountCents ?? 500, `${fieldPath}.amountCents`);
135
+ const currency = normalizeCurrency(pricing.currency ?? defaults.currency ?? "USD", `${fieldPath}.currency`);
136
+ return normalizeForCanonicalJson({ amountCents, currency }, { path: "$" });
137
+ }
138
+
139
+ function normalizeToolSecurity(rawSecurity, defaults, fieldPath) {
140
+ const security = rawSecurity && typeof rawSecurity === "object" && !Array.isArray(rawSecurity) ? rawSecurity : {};
141
+ const requiredSignatures = normalizeRequiredSignatures(
142
+ security.requiredSignatures ?? security.required_signatures ?? defaults.requiredSignatures ?? [],
143
+ `${fieldPath}.requiredSignatures`
144
+ );
145
+ const requestBinding =
146
+ normalizeRequestBinding(security.requestBinding ?? security.request_binding ?? defaults.requestBinding, `${fieldPath}.requestBinding`) ??
147
+ "recommended";
148
+ return normalizeForCanonicalJson(
149
+ {
150
+ requiredSignatures,
151
+ requestBinding
152
+ },
153
+ { path: "$" }
154
+ );
155
+ }
156
+
157
+ function normalizeTool(rawTool, defaults, { index, schemaVersion }) {
158
+ assertPlainObject(rawTool, `tools[${index}]`);
159
+ const toolId = normalizeNonEmptyString(rawTool.toolId, `tools[${index}].toolId`, { max: 128 });
160
+ const mcpToolName = normalizeOptionalString(rawTool.mcpToolName, `tools[${index}].mcpToolName`, { max: 180 });
161
+ const description = normalizeOptionalString(rawTool.description, `tools[${index}].description`, { max: 1000 });
162
+ const method = normalizeHttpMethod(rawTool.method ?? "GET", `tools[${index}].method`);
163
+ const upstreamPath = normalizeOptionalString(rawTool.upstreamPath, `tools[${index}].upstreamPath`, { max: 1024 });
164
+ const paidPath = normalizeRoutePath(rawTool.paidPath, `tools[${index}].paidPath`);
165
+ const idempotency = normalizeOptionalString(rawTool.idempotency, `tools[${index}].idempotency`, { max: 64 }) ?? defaults.idempotency ?? "idempotent";
166
+ const signatureMode = normalizeOptionalString(rawTool.signatureMode, `tools[${index}].signatureMode`, { max: 64 }) ?? defaults.signatureMode ?? "required";
167
+ if (!["idempotent", "non_idempotent", "side_effecting"].includes(String(idempotency))) {
168
+ throw new TypeError(`tools[${index}].idempotency must be idempotent|non_idempotent|side_effecting`);
169
+ }
170
+ if (!["required", "optional"].includes(String(signatureMode))) {
171
+ throw new TypeError(`tools[${index}].signatureMode must be required|optional`);
172
+ }
173
+ const pricing = normalizePricing(rawTool.pricing, defaults, `tools[${index}].pricing`);
174
+ const auth =
175
+ rawTool.auth && typeof rawTool.auth === "object" && !Array.isArray(rawTool.auth)
176
+ ? normalizeForCanonicalJson(rawTool.auth, { path: "$" })
177
+ : normalizeForCanonicalJson({ mode: "none" }, { path: "$" });
178
+ const metadata =
179
+ rawTool.metadata && typeof rawTool.metadata === "object" && !Array.isArray(rawTool.metadata)
180
+ ? normalizeForCanonicalJson(rawTool.metadata, { path: "$" })
181
+ : null;
182
+
183
+ const isV2 = schemaVersion === PAID_TOOL_MANIFEST_SCHEMA_VERSION_V2;
184
+ const toolClass = normalizeToolClass(
185
+ rawTool.toolClass ?? rawTool.tool_class ?? defaults.toolClass ?? null,
186
+ `tools[${index}].toolClass`
187
+ );
188
+ const riskLevel = normalizeRiskLevel(
189
+ rawTool.riskLevel ?? rawTool.risk_level ?? defaults.riskLevel ?? null,
190
+ `tools[${index}].riskLevel`
191
+ );
192
+ const capabilityTags = normalizeStringArray(
193
+ rawTool.capabilityTags ?? rawTool.capability_tags ?? rawTool.tags ?? [],
194
+ `tools[${index}].capabilityTags`,
195
+ { maxItems: 64, maxLen: 80 }
196
+ );
197
+ const security = normalizeToolSecurity(rawTool.security ?? null, defaults, `tools[${index}].security`);
198
+
199
+ return normalizeForCanonicalJson(
200
+ {
201
+ toolId,
202
+ mcpToolName,
203
+ description,
204
+ method,
205
+ upstreamPath,
206
+ paidPath,
207
+ pricing,
208
+ idempotency,
209
+ signatureMode,
210
+ auth,
211
+ metadata,
212
+ ...(isV2
213
+ ? {
214
+ toolClass: toolClass ?? "read",
215
+ riskLevel: riskLevel ?? "low",
216
+ capabilityTags,
217
+ security
218
+ }
219
+ : {})
220
+ },
221
+ { path: "$" }
222
+ );
223
+ }
224
+
225
+ export function normalizePaidToolManifestV1(manifestInput) {
226
+ assertPlainObject(manifestInput, "manifest");
227
+ const schemaVersion = normalizeManifestSchemaVersion(manifestInput.schemaVersion);
228
+ const isV2 = schemaVersion === PAID_TOOL_MANIFEST_SCHEMA_VERSION_V2;
229
+ const providerId = normalizeNonEmptyString(manifestInput.providerId, "manifest.providerId", { max: 160 });
230
+ const upstreamBaseUrl = normalizeOptionalString(manifestInput.upstreamBaseUrl, "manifest.upstreamBaseUrl", { max: 2048 });
231
+ const publishProofJwksUrl = normalizeOptionalAbsoluteHttpUrl(
232
+ manifestInput.publishProofJwksUrl,
233
+ "manifest.publishProofJwksUrl"
234
+ );
235
+ const sourceOpenApiPath = normalizeOptionalString(manifestInput.sourceOpenApiPath, "manifest.sourceOpenApiPath", { max: 2048 });
236
+
237
+ const defaultsRaw =
238
+ manifestInput.defaults && typeof manifestInput.defaults === "object" && !Array.isArray(manifestInput.defaults)
239
+ ? manifestInput.defaults
240
+ : {};
241
+ const defaults = normalizeForCanonicalJson(
242
+ {
243
+ amountCents: normalizePositiveSafeInt(defaultsRaw.amountCents ?? 500, "manifest.defaults.amountCents"),
244
+ currency: normalizeCurrency(defaultsRaw.currency ?? "USD", "manifest.defaults.currency"),
245
+ idempotency: normalizeOptionalString(defaultsRaw.idempotency, "manifest.defaults.idempotency", { max: 64 }) ?? "idempotent",
246
+ signatureMode: normalizeOptionalString(defaultsRaw.signatureMode, "manifest.defaults.signatureMode", { max: 64 }) ?? "required",
247
+ ...(isV2
248
+ ? {
249
+ toolClass: normalizeToolClass(defaultsRaw.toolClass ?? defaultsRaw.tool_class ?? null, "manifest.defaults.toolClass") ?? "read",
250
+ riskLevel: normalizeRiskLevel(defaultsRaw.riskLevel ?? defaultsRaw.risk_level ?? null, "manifest.defaults.riskLevel") ?? "low",
251
+ requiredSignatures: normalizeRequiredSignatures(
252
+ defaultsRaw.requiredSignatures ?? defaultsRaw.required_signatures ?? ["output"],
253
+ "manifest.defaults.requiredSignatures"
254
+ ),
255
+ requestBinding:
256
+ normalizeRequestBinding(
257
+ defaultsRaw.requestBinding ?? defaultsRaw.request_binding ?? null,
258
+ "manifest.defaults.requestBinding"
259
+ ) ?? "recommended"
260
+ }
261
+ : {})
262
+ },
263
+ { path: "$" }
264
+ );
265
+ if (!["idempotent", "non_idempotent", "side_effecting"].includes(String(defaults.idempotency))) {
266
+ throw new TypeError("manifest.defaults.idempotency must be idempotent|non_idempotent|side_effecting");
267
+ }
268
+ if (!["required", "optional"].includes(String(defaults.signatureMode))) {
269
+ throw new TypeError("manifest.defaults.signatureMode must be required|optional");
270
+ }
271
+
272
+ if (!Array.isArray(manifestInput.tools) || manifestInput.tools.length === 0) {
273
+ throw new TypeError("manifest.tools must be a non-empty array");
274
+ }
275
+ const tools = manifestInput.tools.map((row, index) => normalizeTool(row, defaults, { index, schemaVersion }));
276
+ const seenToolIds = new Set();
277
+ const seenPaidPaths = new Set();
278
+ for (const tool of tools) {
279
+ if (seenToolIds.has(tool.toolId)) throw new TypeError(`manifest.tools contains duplicate toolId: ${tool.toolId}`);
280
+ if (seenPaidPaths.has(tool.paidPath)) throw new TypeError(`manifest.tools contains duplicate paidPath: ${tool.paidPath}`);
281
+ seenToolIds.add(tool.toolId);
282
+ seenPaidPaths.add(tool.paidPath);
283
+ }
284
+
285
+ const capabilityTags = normalizeStringArray(
286
+ manifestInput.capabilityTags ?? manifestInput.capability_tags ?? manifestInput.tags ?? [],
287
+ "manifest.capabilityTags",
288
+ { maxItems: 64, maxLen: 80 }
289
+ );
290
+
291
+ return normalizeForCanonicalJson(
292
+ {
293
+ schemaVersion,
294
+ providerId,
295
+ upstreamBaseUrl,
296
+ publishProofJwksUrl,
297
+ sourceOpenApiPath,
298
+ defaults,
299
+ tools,
300
+ ...(isV2 ? { capabilityTags } : {})
301
+ },
302
+ { path: "$" }
303
+ );
304
+ }
305
+
306
+ export function validatePaidToolManifestV1(manifestInput) {
307
+ try {
308
+ const manifest = normalizePaidToolManifestV1(manifestInput);
309
+ return { ok: true, manifest };
310
+ } catch (err) {
311
+ return { ok: false, code: "PAID_TOOL_MANIFEST_INVALID", message: err?.message ?? String(err ?? "") };
312
+ }
313
+ }
314
+
315
+ export function computePaidToolManifestHashV1(manifestInput) {
316
+ const manifest = normalizePaidToolManifestV1(manifestInput);
317
+ return sha256Hex(canonicalJsonStringify(manifest));
318
+ }