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
@@ -0,0 +1,549 @@
1
+ import { canonicalJsonStringify, normalizeForCanonicalJson } from "./canonical-json.js";
2
+ import { sha256Hex } from "./crypto.js";
3
+
4
+ export const AGREEMENT_DELEGATION_SCHEMA_VERSION = "AgreementDelegation.v1";
5
+
6
+ export const AGREEMENT_DELEGATION_STATUS = Object.freeze({
7
+ ACTIVE: "active",
8
+ SETTLED: "settled",
9
+ REVOKED: "revoked"
10
+ });
11
+
12
+ function assertPlainObject(value, name) {
13
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError(`${name} must be an object`);
14
+ if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
15
+ throw new TypeError(`${name} must be a plain object`);
16
+ }
17
+ }
18
+
19
+ function assertNonEmptyString(value, name) {
20
+ if (typeof value !== "string" || value.trim() === "") throw new TypeError(`${name} must be a non-empty string`);
21
+ }
22
+
23
+ function assertIsoDate(value, name, { allowNull = false } = {}) {
24
+ if (allowNull && (value === null || value === undefined)) return;
25
+ assertNonEmptyString(value, name);
26
+ if (!Number.isFinite(Date.parse(value))) throw new TypeError(`${name} must be an ISO date string`);
27
+ }
28
+
29
+ function normalizeId(value, name, { min = 1, max = 200 } = {}) {
30
+ assertNonEmptyString(value, name);
31
+ const out = String(value).trim();
32
+ if (out.length < min || out.length > max) throw new TypeError(`${name} must be length ${min}..${max}`);
33
+ if (!/^[A-Za-z0-9:_-]+$/.test(out)) throw new TypeError(`${name} must match ^[A-Za-z0-9:_-]+$`);
34
+ return out;
35
+ }
36
+
37
+ function normalizeHexHash(value, name) {
38
+ assertNonEmptyString(value, name);
39
+ const out = String(value).trim().toLowerCase();
40
+ if (!/^[0-9a-f]{64}$/.test(out)) throw new TypeError(`${name} must be a 64-hex sha256`);
41
+ return out;
42
+ }
43
+
44
+ function normalizeCurrency(value, name) {
45
+ const raw = typeof value === "string" && value.trim() !== "" ? value : "USD";
46
+ const out = raw.trim().toUpperCase();
47
+ if (!/^[A-Z][A-Z0-9_]{2,11}$/.test(out)) throw new TypeError(`${name} must match ^[A-Z][A-Z0-9_]{2,11}$`);
48
+ return out;
49
+ }
50
+
51
+ function assertPositiveSafeInt(value, name) {
52
+ const n = Number(value);
53
+ if (!Number.isSafeInteger(n) || n <= 0) throw new TypeError(`${name} must be a positive safe integer`);
54
+ return n;
55
+ }
56
+
57
+ function assertNonNegativeSafeInt(value, name) {
58
+ const n = Number(value);
59
+ if (!Number.isSafeInteger(n) || n < 0) throw new TypeError(`${name} must be a non-negative safe integer`);
60
+ return n;
61
+ }
62
+
63
+ function normalizeStatus(value, name) {
64
+ const normalized = typeof value === "string" ? value.trim().toLowerCase() : "";
65
+ if (!Object.values(AGREEMENT_DELEGATION_STATUS).includes(normalized)) {
66
+ throw new TypeError(`${name} must be one of: ${Object.values(AGREEMENT_DELEGATION_STATUS).join("|")}`);
67
+ }
68
+ return normalized;
69
+ }
70
+
71
+ function normalizeAncestorChain(value, { name = "ancestorChain", requiredDepth = null, expectedParentHash = null } = {}) {
72
+ if (value === null || value === undefined) return undefined;
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 h = normalizeHexHash(value[i], `${name}[${i}]`);
78
+ if (seen.has(h)) throw new TypeError(`${name} must not contain duplicates`);
79
+ seen.add(h);
80
+ out.push(h);
81
+ }
82
+ if (requiredDepth !== null && out.length !== requiredDepth) {
83
+ throw new TypeError(`${name} length must equal delegationDepth`);
84
+ }
85
+ if (expectedParentHash && out.length && out[out.length - 1] !== expectedParentHash) {
86
+ throw new TypeError(`${name} last element must equal parentAgreementHash`);
87
+ }
88
+ return out;
89
+ }
90
+
91
+ export function computeAgreementDelegationHashV1(delegationCore) {
92
+ assertPlainObject(delegationCore, "delegationCore");
93
+ const copy = { ...delegationCore };
94
+ delete copy.delegationHash;
95
+ delete copy.status;
96
+ delete copy.resolvedAt;
97
+ delete copy.updatedAt;
98
+ delete copy.revision;
99
+ delete copy.metadata;
100
+ const normalized = normalizeForCanonicalJson(copy, { path: "$" });
101
+ return sha256Hex(canonicalJsonStringify(normalized));
102
+ }
103
+
104
+ export function buildAgreementDelegationV1({
105
+ delegationId,
106
+ tenantId,
107
+ parentAgreementHash,
108
+ childAgreementHash,
109
+ delegatorAgentId,
110
+ delegateeAgentId,
111
+ budgetCapCents,
112
+ currency,
113
+ delegationDepth,
114
+ maxDelegationDepth,
115
+ ancestorChain,
116
+ createdAt
117
+ } = {}) {
118
+ const at = createdAt ?? new Date().toISOString();
119
+ assertIsoDate(at, "createdAt");
120
+
121
+ const parentHash = normalizeHexHash(parentAgreementHash, "parentAgreementHash");
122
+ const depth = assertNonNegativeSafeInt(delegationDepth, "delegationDepth");
123
+ const normalizedAncestorChain = normalizeAncestorChain(ancestorChain, {
124
+ name: "ancestorChain",
125
+ requiredDepth: ancestorChain === undefined || ancestorChain === null ? null : depth,
126
+ expectedParentHash: parentHash
127
+ });
128
+
129
+ const normalized = normalizeForCanonicalJson(
130
+ {
131
+ schemaVersion: AGREEMENT_DELEGATION_SCHEMA_VERSION,
132
+ delegationId: normalizeId(delegationId, "delegationId", { min: 3, max: 240 }),
133
+ tenantId: normalizeId(tenantId, "tenantId", { min: 1, max: 128 }),
134
+ parentAgreementHash: parentHash,
135
+ childAgreementHash: normalizeHexHash(childAgreementHash, "childAgreementHash"),
136
+ delegatorAgentId: normalizeId(delegatorAgentId, "delegatorAgentId", { min: 3, max: 128 }),
137
+ delegateeAgentId: normalizeId(delegateeAgentId, "delegateeAgentId", { min: 3, max: 128 }),
138
+ budgetCapCents: assertPositiveSafeInt(budgetCapCents, "budgetCapCents"),
139
+ currency: normalizeCurrency(currency, "currency"),
140
+ delegationDepth: depth,
141
+ maxDelegationDepth: assertNonNegativeSafeInt(maxDelegationDepth, "maxDelegationDepth"),
142
+ createdAt: at,
143
+ ...(normalizedAncestorChain ? { ancestorChain: normalizedAncestorChain } : {})
144
+ },
145
+ { path: "$" }
146
+ );
147
+
148
+ if (normalized.delegationDepth > normalized.maxDelegationDepth) {
149
+ throw new TypeError("delegationDepth must be <= maxDelegationDepth");
150
+ }
151
+ if (normalized.parentAgreementHash === normalized.childAgreementHash) {
152
+ throw new TypeError("parentAgreementHash must differ from childAgreementHash");
153
+ }
154
+
155
+ const delegationHash = computeAgreementDelegationHashV1(normalized);
156
+ return normalizeForCanonicalJson(
157
+ {
158
+ ...normalized,
159
+ delegationHash,
160
+ status: AGREEMENT_DELEGATION_STATUS.ACTIVE,
161
+ revision: 0,
162
+ updatedAt: at
163
+ },
164
+ { path: "$" }
165
+ );
166
+ }
167
+
168
+ export function validateAgreementDelegationV1(delegation) {
169
+ assertPlainObject(delegation, "delegation");
170
+ if (delegation.schemaVersion !== AGREEMENT_DELEGATION_SCHEMA_VERSION) {
171
+ throw new TypeError(`delegation.schemaVersion must be ${AGREEMENT_DELEGATION_SCHEMA_VERSION}`);
172
+ }
173
+ normalizeId(delegation.delegationId, "delegation.delegationId", { min: 3, max: 240 });
174
+ normalizeId(delegation.tenantId, "delegation.tenantId", { min: 1, max: 128 });
175
+ const parentHash = normalizeHexHash(delegation.parentAgreementHash, "delegation.parentAgreementHash");
176
+ const childHash = normalizeHexHash(delegation.childAgreementHash, "delegation.childAgreementHash");
177
+ if (parentHash === childHash) throw new TypeError("delegation.parentAgreementHash must differ from delegation.childAgreementHash");
178
+ normalizeId(delegation.delegatorAgentId, "delegation.delegatorAgentId", { min: 3, max: 128 });
179
+ normalizeId(delegation.delegateeAgentId, "delegation.delegateeAgentId", { min: 3, max: 128 });
180
+ assertPositiveSafeInt(delegation.budgetCapCents, "delegation.budgetCapCents");
181
+ normalizeCurrency(delegation.currency, "delegation.currency");
182
+ const depth = assertNonNegativeSafeInt(delegation.delegationDepth, "delegation.delegationDepth");
183
+ const maxDepth = assertNonNegativeSafeInt(delegation.maxDelegationDepth, "delegation.maxDelegationDepth");
184
+ if (depth > maxDepth) throw new TypeError("delegation.delegationDepth must be <= delegation.maxDelegationDepth");
185
+ assertIsoDate(delegation.createdAt, "delegation.createdAt");
186
+ if (Object.prototype.hasOwnProperty.call(delegation, "ancestorChain")) {
187
+ normalizeAncestorChain(delegation.ancestorChain ?? null, {
188
+ name: "delegation.ancestorChain",
189
+ requiredDepth: delegation.ancestorChain === null ? null : depth,
190
+ expectedParentHash: parentHash
191
+ });
192
+ }
193
+ normalizeHexHash(delegation.delegationHash, "delegation.delegationHash");
194
+ normalizeStatus(delegation.status, "delegation.status");
195
+ const revision = Number(delegation.revision ?? 0);
196
+ if (!Number.isSafeInteger(revision) || revision < 0) throw new TypeError("delegation.revision must be a non-negative safe integer");
197
+ assertIsoDate(delegation.updatedAt, "delegation.updatedAt");
198
+ if (Object.prototype.hasOwnProperty.call(delegation, "resolvedAt")) {
199
+ assertIsoDate(delegation.resolvedAt ?? null, "delegation.resolvedAt", { allowNull: true });
200
+ }
201
+
202
+ const computed = computeAgreementDelegationHashV1(delegation);
203
+ if (computed !== String(delegation.delegationHash).toLowerCase()) throw new TypeError("delegationHash mismatch");
204
+ return true;
205
+ }
206
+
207
+ export function resolveAgreementDelegationV1({ delegation, status, resolvedAt = null, metadata = null } = {}) {
208
+ validateAgreementDelegationV1(delegation);
209
+ const nextStatus = normalizeStatus(status, "status");
210
+ const at = resolvedAt ?? new Date().toISOString();
211
+ assertIsoDate(at, "resolvedAt");
212
+ if (nextStatus === AGREEMENT_DELEGATION_STATUS.ACTIVE) throw new TypeError("cannot resolve delegation to active");
213
+ const currentStatus = String(delegation.status ?? "").toLowerCase();
214
+ if (currentStatus !== AGREEMENT_DELEGATION_STATUS.ACTIVE) return delegation;
215
+
216
+ const meta = metadata && typeof metadata === "object" && !Array.isArray(metadata) ? metadata : null;
217
+ const next = {
218
+ ...delegation,
219
+ status: nextStatus,
220
+ resolvedAt: at,
221
+ revision: Number(delegation.revision ?? 0) + 1,
222
+ updatedAt: at
223
+ };
224
+ if (meta) next.metadata = normalizeForCanonicalJson(meta, { path: "$.metadata" });
225
+ return normalizeForCanonicalJson(next, { path: "$" });
226
+ }
227
+
228
+ function indexDelegations(delegations) {
229
+ const byChild = new Map();
230
+ const childrenByParent = new Map();
231
+ for (const d of Array.isArray(delegations) ? delegations : []) {
232
+ if (!d || typeof d !== "object" || Array.isArray(d)) continue;
233
+ const status = String(d.status ?? "").toLowerCase();
234
+ if (status === AGREEMENT_DELEGATION_STATUS.REVOKED) continue;
235
+ const parent = typeof d.parentAgreementHash === "string" ? d.parentAgreementHash.toLowerCase() : null;
236
+ const child = typeof d.childAgreementHash === "string" ? d.childAgreementHash.toLowerCase() : null;
237
+ if (!parent || !child) continue;
238
+
239
+ if (byChild.has(child) && byChild.get(child)?.parentAgreementHash !== parent) {
240
+ const err = new Error("multiple parents found for childAgreementHash");
241
+ err.code = "AGREEMENT_DELEGATION_MULTIPLE_PARENTS";
242
+ err.childAgreementHash = child;
243
+ throw err;
244
+ }
245
+ byChild.set(child, { delegationId: d.delegationId ?? null, parentAgreementHash: parent, childAgreementHash: child });
246
+
247
+ const list = childrenByParent.get(parent) ?? [];
248
+ list.push({ delegationId: d.delegationId ?? null, parentAgreementHash: parent, childAgreementHash: child });
249
+ childrenByParent.set(parent, list);
250
+ }
251
+ for (const [p, list] of childrenByParent.entries()) {
252
+ list.sort((a, b) => String(a.childAgreementHash).localeCompare(String(b.childAgreementHash)));
253
+ childrenByParent.set(p, list);
254
+ }
255
+ return { byChild, childrenByParent };
256
+ }
257
+
258
+ function indexDelegationsById(delegations) {
259
+ const byId = new Map();
260
+ for (const delegation of Array.isArray(delegations) ? delegations : []) {
261
+ if (!delegation || typeof delegation !== "object" || Array.isArray(delegation)) continue;
262
+ const delegationId = typeof delegation.delegationId === "string" ? delegation.delegationId.trim() : "";
263
+ if (!delegationId) continue;
264
+ if (byId.has(delegationId)) {
265
+ const err = new Error("duplicate delegationId in input set");
266
+ err.code = "AGREEMENT_DELEGATION_DUPLICATE_ID";
267
+ err.delegationId = delegationId;
268
+ throw err;
269
+ }
270
+ byId.set(delegationId, delegation);
271
+ }
272
+ return byId;
273
+ }
274
+
275
+ export function summarizeAgreementDelegationLedgerV1({ delegations } = {}) {
276
+ const summary = {
277
+ schemaVersion: "AgreementDelegationLedger.v1",
278
+ totalDelegations: 0,
279
+ activeCount: 0,
280
+ settledCount: 0,
281
+ revokedCount: 0,
282
+ terminalCount: 0,
283
+ unresolvedCount: 0,
284
+ countsByStatus: {
285
+ [AGREEMENT_DELEGATION_STATUS.ACTIVE]: 0,
286
+ [AGREEMENT_DELEGATION_STATUS.SETTLED]: 0,
287
+ [AGREEMENT_DELEGATION_STATUS.REVOKED]: 0
288
+ },
289
+ invariant: {
290
+ ok: true,
291
+ code: "AGREEMENT_DELEGATION_LEDGER_INVARIANT_OK",
292
+ message: "active+settled+revoked equals total"
293
+ }
294
+ };
295
+ for (const delegation of Array.isArray(delegations) ? delegations : []) {
296
+ if (!delegation || typeof delegation !== "object" || Array.isArray(delegation)) continue;
297
+ summary.totalDelegations += 1;
298
+ const status = String(delegation.status ?? "").trim().toLowerCase();
299
+ if (status === AGREEMENT_DELEGATION_STATUS.ACTIVE) {
300
+ summary.activeCount += 1;
301
+ summary.unresolvedCount += 1;
302
+ summary.countsByStatus[AGREEMENT_DELEGATION_STATUS.ACTIVE] += 1;
303
+ } else if (status === AGREEMENT_DELEGATION_STATUS.SETTLED) {
304
+ summary.settledCount += 1;
305
+ summary.terminalCount += 1;
306
+ summary.countsByStatus[AGREEMENT_DELEGATION_STATUS.SETTLED] += 1;
307
+ } else if (status === AGREEMENT_DELEGATION_STATUS.REVOKED) {
308
+ summary.revokedCount += 1;
309
+ summary.terminalCount += 1;
310
+ summary.countsByStatus[AGREEMENT_DELEGATION_STATUS.REVOKED] += 1;
311
+ } else {
312
+ summary.invariant = {
313
+ ok: false,
314
+ code: "AGREEMENT_DELEGATION_STATUS_UNKNOWN",
315
+ message: "delegation has unsupported status"
316
+ };
317
+ }
318
+ }
319
+ if (summary.totalDelegations !== summary.activeCount + summary.settledCount + summary.revokedCount) {
320
+ summary.invariant = {
321
+ ok: false,
322
+ code: "AGREEMENT_DELEGATION_LEDGER_IMBALANCED",
323
+ message: "active+settled+revoked must equal totalDelegations"
324
+ };
325
+ }
326
+ return normalizeForCanonicalJson(summary, { path: "$" });
327
+ }
328
+
329
+ function applyDelegationResolutionPlan({
330
+ delegations,
331
+ edges,
332
+ targetStatus,
333
+ resolvedAt = null,
334
+ metadata = null,
335
+ resultKind
336
+ } = {}) {
337
+ const nextStatus = normalizeStatus(targetStatus, "targetStatus");
338
+ if (nextStatus === AGREEMENT_DELEGATION_STATUS.ACTIVE) {
339
+ throw new TypeError("targetStatus must be settled|revoked");
340
+ }
341
+ const byId = indexDelegationsById(delegations);
342
+ const updates = new Map();
343
+ const operations = [];
344
+ const at = resolvedAt ?? new Date().toISOString();
345
+ assertIsoDate(at, "resolvedAt");
346
+
347
+ for (const edge of Array.isArray(edges) ? edges : []) {
348
+ const delegationId = typeof edge?.delegationId === "string" ? edge.delegationId.trim() : "";
349
+ if (!delegationId) {
350
+ const err = new Error("delegationId is required on plan edge");
351
+ err.code = "AGREEMENT_DELEGATION_PLAN_EDGE_ID_REQUIRED";
352
+ throw err;
353
+ }
354
+ const current = updates.get(delegationId) ?? byId.get(delegationId) ?? null;
355
+ if (!current) {
356
+ const err = new Error("plan references unknown delegationId");
357
+ err.code = "AGREEMENT_DELEGATION_PLAN_EDGE_NOT_FOUND";
358
+ err.delegationId = delegationId;
359
+ throw err;
360
+ }
361
+ const currentStatus = String(current.status ?? "").trim().toLowerCase();
362
+ if (currentStatus !== AGREEMENT_DELEGATION_STATUS.ACTIVE && currentStatus !== nextStatus) {
363
+ const err = new Error("delegation already resolved with conflicting terminal status");
364
+ err.code = "AGREEMENT_DELEGATION_TERMINAL_CONFLICT";
365
+ err.delegationId = delegationId;
366
+ err.currentStatus = currentStatus;
367
+ err.targetStatus = nextStatus;
368
+ throw err;
369
+ }
370
+
371
+ if (currentStatus === nextStatus) {
372
+ operations.push({
373
+ delegationId,
374
+ result: "noop",
375
+ fromStatus: currentStatus,
376
+ toStatus: nextStatus
377
+ });
378
+ continue;
379
+ }
380
+
381
+ const nextDelegation = resolveAgreementDelegationV1({
382
+ delegation: current,
383
+ status: nextStatus,
384
+ resolvedAt: at,
385
+ metadata
386
+ });
387
+ updates.set(delegationId, nextDelegation);
388
+ operations.push({
389
+ delegationId,
390
+ result: "applied",
391
+ fromStatus: currentStatus,
392
+ toStatus: nextStatus
393
+ });
394
+ }
395
+
396
+ const nextDelegations = [];
397
+ for (const delegation of Array.isArray(delegations) ? delegations : []) {
398
+ if (!delegation || typeof delegation !== "object" || Array.isArray(delegation)) continue;
399
+ const delegationId = typeof delegation.delegationId === "string" ? delegation.delegationId.trim() : "";
400
+ if (!delegationId) continue;
401
+ nextDelegations.push(updates.get(delegationId) ?? delegation);
402
+ }
403
+
404
+ const applied = operations.filter((row) => row.result === "applied").length;
405
+ const noop = operations.filter((row) => row.result === "noop").length;
406
+ const ledger = summarizeAgreementDelegationLedgerV1({ delegations: nextDelegations });
407
+
408
+ return normalizeForCanonicalJson(
409
+ {
410
+ ok: true,
411
+ kind: resultKind,
412
+ targetStatus: nextStatus,
413
+ resolvedAt: at,
414
+ operations,
415
+ stats: {
416
+ attempted: operations.length,
417
+ applied,
418
+ noop
419
+ },
420
+ ledger,
421
+ delegations: nextDelegations
422
+ },
423
+ { path: "$" }
424
+ );
425
+ }
426
+
427
+ // Read-only: returns a deterministic "plan" for the caller to execute.
428
+ export function cascadeSettlementCheck({ delegations, fromChildHash } = {}) {
429
+ const start = normalizeHexHash(fromChildHash, "fromChildHash");
430
+ const { byChild } = indexDelegations(delegations);
431
+ const parents = [];
432
+ const edges = [];
433
+ const seen = new Set([start]);
434
+ let cursor = start;
435
+ while (true) {
436
+ const link = byChild.get(cursor) ?? null;
437
+ if (!link) break;
438
+ const parent = link.parentAgreementHash;
439
+ if (seen.has(parent)) {
440
+ const err = new Error("cycle detected in delegation graph");
441
+ err.code = "AGREEMENT_DELEGATION_CYCLE";
442
+ err.agreementHash = parent;
443
+ throw err;
444
+ }
445
+ seen.add(parent);
446
+ edges.push({ delegationId: link.delegationId ?? null, childAgreementHash: cursor, parentAgreementHash: parent });
447
+ parents.push(parent);
448
+ cursor = parent;
449
+ }
450
+ return normalizeForCanonicalJson(
451
+ {
452
+ ok: true,
453
+ kind: "cascade_settlement_check_v1",
454
+ fromChildHash: start,
455
+ parentAgreementHashes: parents,
456
+ edges
457
+ },
458
+ { path: "$" }
459
+ );
460
+ }
461
+
462
+ // Read-only: returns a deterministic "plan" for the caller to execute.
463
+ export function refundUnwindCheck({ delegations, fromParentHash } = {}) {
464
+ const start = normalizeHexHash(fromParentHash, "fromParentHash");
465
+ const { childrenByParent } = indexDelegations(delegations);
466
+ const orderedChildren = [];
467
+ const edges = [];
468
+ const seen = new Set([start]);
469
+ const queue = [start];
470
+ while (queue.length) {
471
+ const parent = queue.shift();
472
+ const children = childrenByParent.get(parent) ?? [];
473
+ for (const link of children) {
474
+ const child = link.childAgreementHash;
475
+ edges.push({ delegationId: link.delegationId ?? null, parentAgreementHash: parent, childAgreementHash: child });
476
+ if (seen.has(child)) continue;
477
+ seen.add(child);
478
+ orderedChildren.push(child);
479
+ queue.push(child);
480
+ }
481
+ }
482
+ return normalizeForCanonicalJson(
483
+ {
484
+ ok: true,
485
+ kind: "refund_unwind_check_v1",
486
+ fromParentHash: start,
487
+ childAgreementHashes: orderedChildren,
488
+ edges
489
+ },
490
+ { path: "$" }
491
+ );
492
+ }
493
+
494
+ export function cascadeSettlementExecute({ delegations, fromChildHash, resolvedAt = null, metadata = null } = {}) {
495
+ const plan = cascadeSettlementCheck({ delegations, fromChildHash });
496
+ const result = applyDelegationResolutionPlan({
497
+ delegations,
498
+ edges: plan.edges,
499
+ targetStatus: AGREEMENT_DELEGATION_STATUS.SETTLED,
500
+ resolvedAt,
501
+ metadata,
502
+ resultKind: "cascade_settlement_execute_v1"
503
+ });
504
+ return normalizeForCanonicalJson(
505
+ {
506
+ ...result,
507
+ plan
508
+ },
509
+ { path: "$" }
510
+ );
511
+ }
512
+
513
+ export function cascadeUnwindExecute({ delegations, fromChildHash, resolvedAt = null, metadata = null } = {}) {
514
+ const plan = cascadeSettlementCheck({ delegations, fromChildHash });
515
+ const result = applyDelegationResolutionPlan({
516
+ delegations,
517
+ edges: plan.edges,
518
+ targetStatus: AGREEMENT_DELEGATION_STATUS.REVOKED,
519
+ resolvedAt,
520
+ metadata,
521
+ resultKind: "cascade_unwind_execute_v1"
522
+ });
523
+ return normalizeForCanonicalJson(
524
+ {
525
+ ...result,
526
+ plan
527
+ },
528
+ { path: "$" }
529
+ );
530
+ }
531
+
532
+ export function refundUnwindExecute({ delegations, fromParentHash, resolvedAt = null, metadata = null } = {}) {
533
+ const plan = refundUnwindCheck({ delegations, fromParentHash });
534
+ const result = applyDelegationResolutionPlan({
535
+ delegations,
536
+ edges: plan.edges,
537
+ targetStatus: AGREEMENT_DELEGATION_STATUS.REVOKED,
538
+ resolvedAt,
539
+ metadata,
540
+ resultKind: "refund_unwind_execute_v1"
541
+ });
542
+ return normalizeForCanonicalJson(
543
+ {
544
+ ...result,
545
+ plan
546
+ },
547
+ { path: "$" }
548
+ );
549
+ }
@@ -12,6 +12,7 @@ const BILLING_PLAN_CATALOG = Object.freeze({
12
12
  subscriptionCents: 0,
13
13
  includedVerifiedRunsPerMonth: 1000,
14
14
  verifiedRunOverageCents: 0,
15
+ verifiedRunOverageMilliCents: 0,
15
16
  settledVolumeFeeBps: 0,
16
17
  arbitrationCaseFeeCents: 0,
17
18
  hardLimitVerifiedRunsPerMonth: 1000
@@ -22,6 +23,7 @@ const BILLING_PLAN_CATALOG = Object.freeze({
22
23
  subscriptionCents: 9900,
23
24
  includedVerifiedRunsPerMonth: 10_000,
24
25
  verifiedRunOverageCents: 1,
26
+ verifiedRunOverageMilliCents: 1000,
25
27
  settledVolumeFeeBps: 75,
26
28
  arbitrationCaseFeeCents: 200,
27
29
  hardLimitVerifiedRunsPerMonth: 0
@@ -31,7 +33,8 @@ const BILLING_PLAN_CATALOG = Object.freeze({
31
33
  displayName: "Growth",
32
34
  subscriptionCents: 59_900,
33
35
  includedVerifiedRunsPerMonth: 100_000,
34
- verifiedRunOverageCents: 1,
36
+ verifiedRunOverageCents: 0.7,
37
+ verifiedRunOverageMilliCents: 700,
35
38
  settledVolumeFeeBps: 45,
36
39
  arbitrationCaseFeeCents: 100,
37
40
  hardLimitVerifiedRunsPerMonth: 0
@@ -42,6 +45,7 @@ const BILLING_PLAN_CATALOG = Object.freeze({
42
45
  subscriptionCents: 0,
43
46
  includedVerifiedRunsPerMonth: 0,
44
47
  verifiedRunOverageCents: 0,
48
+ verifiedRunOverageMilliCents: 0,
45
49
  settledVolumeFeeBps: 35,
46
50
  arbitrationCaseFeeCents: 0,
47
51
  hardLimitVerifiedRunsPerMonth: 0
@@ -56,6 +60,22 @@ function assertNonNegativeSafeInt(value, fieldName) {
56
60
  return n;
57
61
  }
58
62
 
63
+ function assertNonNegativeCentsRate(value, fieldName) {
64
+ const n = Number(value);
65
+ if (!Number.isFinite(n) || n < 0) {
66
+ throw new TypeError(`${fieldName} must be a non-negative finite number`);
67
+ }
68
+ const rounded = Math.round(n * 1000) / 1000;
69
+ if (Math.abs(rounded - n) > 1e-9) {
70
+ throw new TypeError(`${fieldName} must use at most 3 decimal places`);
71
+ }
72
+ return rounded;
73
+ }
74
+
75
+ function toMilliCentsFromCentsRate(centsRate) {
76
+ return Math.round(assertNonNegativeCentsRate(centsRate, "plan.verifiedRunOverageCents") * 1000);
77
+ }
78
+
59
79
  export function normalizeBillingPlanId(value, { allowNull = false, defaultPlan = BILLING_PLAN_ID.FREE } = {}) {
60
80
  if (value === null || value === undefined || String(value).trim() === "") {
61
81
  if (allowNull) return null;
@@ -96,11 +116,17 @@ export function normalizeBillingPlanOverrides(input, { allowNull = true } = {})
96
116
  );
97
117
  }
98
118
  if (Object.prototype.hasOwnProperty.call(input, "verifiedRunOverageCents")) {
99
- out.verifiedRunOverageCents = assertNonNegativeSafeInt(
119
+ out.verifiedRunOverageCents = assertNonNegativeCentsRate(
100
120
  input.verifiedRunOverageCents,
101
121
  "billing.overrides.verifiedRunOverageCents"
102
122
  );
103
123
  }
124
+ if (Object.prototype.hasOwnProperty.call(input, "verifiedRunOverageMilliCents")) {
125
+ out.verifiedRunOverageMilliCents = assertNonNegativeSafeInt(
126
+ input.verifiedRunOverageMilliCents,
127
+ "billing.overrides.verifiedRunOverageMilliCents"
128
+ );
129
+ }
104
130
  if (Object.prototype.hasOwnProperty.call(input, "settledVolumeFeeBps")) {
105
131
  const bps = assertNonNegativeSafeInt(input.settledVolumeFeeBps, "billing.overrides.settledVolumeFeeBps");
106
132
  if (bps > 10_000) throw new TypeError("billing.overrides.settledVolumeFeeBps must be within 0..10000");
@@ -144,10 +170,16 @@ export function computeBillingEstimate({
144
170
  plan?.includedVerifiedRunsPerMonth ?? normalizedPlan.includedVerifiedRunsPerMonth ?? 0,
145
171
  "plan.includedVerifiedRunsPerMonth"
146
172
  );
147
- const verifiedRunOverageCentsPerUnit = assertNonNegativeSafeInt(
173
+ const verifiedRunOverageCentsPerUnit = assertNonNegativeCentsRate(
148
174
  plan?.verifiedRunOverageCents ?? normalizedPlan.verifiedRunOverageCents ?? 0,
149
175
  "plan.verifiedRunOverageCents"
150
176
  );
177
+ const verifiedRunOverageMilliCentsPerUnit = assertNonNegativeSafeInt(
178
+ plan?.verifiedRunOverageMilliCents ??
179
+ normalizedPlan.verifiedRunOverageMilliCents ??
180
+ toMilliCentsFromCentsRate(verifiedRunOverageCentsPerUnit),
181
+ "plan.verifiedRunOverageMilliCents"
182
+ );
151
183
  const settledVolumeFeeBps = assertNonNegativeSafeInt(
152
184
  plan?.settledVolumeFeeBps ?? normalizedPlan.settledVolumeFeeBps ?? 0,
153
185
  "plan.settledVolumeFeeBps"
@@ -165,9 +197,9 @@ export function computeBillingEstimate({
165
197
  const settledVolumeCents = assertNonNegativeSafeInt(usage?.settledVolumeCents ?? 0, "usage.settledVolumeCents");
166
198
  const arbitrationCases = assertNonNegativeSafeInt(usage?.arbitrationCases ?? 0, "usage.arbitrationCases");
167
199
 
168
- const verifiedRunOverageUnits =
169
- includedVerifiedRunsPerMonth > 0 ? Math.max(0, verifiedRuns - includedVerifiedRunsPerMonth) : 0;
170
- const verifiedRunOverageCents = verifiedRunOverageUnits * verifiedRunOverageCentsPerUnit;
200
+ const verifiedRunOverageUnits = Math.max(0, verifiedRuns - includedVerifiedRunsPerMonth);
201
+ const verifiedRunOverageMilliCents = verifiedRunOverageUnits * verifiedRunOverageMilliCentsPerUnit;
202
+ const verifiedRunOverageCents = Math.round(verifiedRunOverageMilliCents / 1000);
171
203
  const settledVolumeFeeCents = Math.floor((settledVolumeCents * settledVolumeFeeBps) / 10_000);
172
204
  const arbitrationFeeCents = arbitrationCases * arbitrationCaseFeeCents;
173
205
  const totalEstimatedCents = subscriptionCents + verifiedRunOverageCents + settledVolumeFeeCents + arbitrationFeeCents;
@@ -177,7 +209,9 @@ export function computeBillingEstimate({
177
209
  includedVerifiedRunsPerMonth,
178
210
  verifiedRunOverageUnits,
179
211
  verifiedRunOverageCents,
212
+ verifiedRunOverageMilliCents,
180
213
  verifiedRunOverageCentsPerUnit,
214
+ verifiedRunOverageMilliCentsPerUnit,
181
215
  settledVolumeFeeBps,
182
216
  settledVolumeFeeCents,
183
217
  arbitrationCaseFeeCents,