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,377 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+
4
+ import { createApi } from "../../../src/api/app.js";
5
+ import { createEd25519Keypair, keyIdFromPublicKeyPem } from "../../../src/core/crypto.js";
6
+ import { createChainedEvent, finalizeChainedEvent } from "../../../src/core/event-chain.js";
7
+
8
+ import { request } from "../../../test/api-test-harness.js";
9
+
10
+ function isoFromMs(ms) {
11
+ return new Date(ms).toISOString();
12
+ }
13
+
14
+ async function writeJson(filepath, value) {
15
+ const dir = path.dirname(filepath);
16
+ await fs.mkdir(dir, { recursive: true });
17
+ await fs.writeFile(filepath, JSON.stringify(value, null, 2) + "\n", "utf8");
18
+ }
19
+
20
+ function safeJson(res) {
21
+ return res?.json ?? (res?.body ? JSON.parse(res.body) : null);
22
+ }
23
+
24
+ async function main() {
25
+ const runId = new Date().toISOString().replaceAll(":", "").replaceAll(".", "").replaceAll("-", "");
26
+ const root = path.resolve("demo/delivery-robot/output", runId);
27
+ const latest = path.resolve("demo/delivery-robot/output/latest");
28
+
29
+ let nowMs = Date.parse("2026-01-20T09:50:00.000Z");
30
+ const nowIso = () => isoFromMs(nowMs);
31
+
32
+ const api = createApi({ now: nowIso, ingestToken: "ingest_tok" });
33
+
34
+ const protocolHeaders = { "x-settld-protocol": "1.0" };
35
+
36
+ const steps = [];
37
+ const recordStep = (name, res, extra = null) => {
38
+ const json = safeJson(res);
39
+ steps.push({
40
+ name,
41
+ statusCode: res?.statusCode ?? null,
42
+ code: res?.headers?.get?.("x-proxy-error-code") ?? null,
43
+ body: json ?? res?.body ?? null,
44
+ ...(extra ? { extra } : null)
45
+ });
46
+ };
47
+
48
+ // 0) Register a robot key (for client-finalized telemetry).
49
+ const { publicKeyPem: robotPublicKeyPem, privateKeyPem: robotPrivateKeyPem } = createEd25519Keypair();
50
+ const robotId = "rob_demo_delivery";
51
+ const robotKeyId = keyIdFromPublicKeyPem(robotPublicKeyPem);
52
+
53
+ const robotReg = await request(api, {
54
+ method: "POST",
55
+ path: "/robots/register",
56
+ headers: { ...protocolHeaders, "x-idempotency-key": "demo_robot_reg" },
57
+ body: { robotId, publicKeyPem: robotPublicKeyPem }
58
+ });
59
+ recordStep("robot.register", robotReg);
60
+ if (robotReg.statusCode !== 201) throw new Error("robot.register failed");
61
+
62
+ const robotAvail = await request(api, {
63
+ method: "POST",
64
+ path: `/robots/${robotId}/availability`,
65
+ headers: { ...protocolHeaders, "x-idempotency-key": "demo_robot_avail", "x-proxy-expected-prev-chain-hash": robotReg.json.robot.lastChainHash },
66
+ body: { availability: [{ startAt: "2026-01-01T00:00:00.000Z", endAt: "2026-03-01T00:00:00.000Z" }] }
67
+ });
68
+ recordStep("robot.availability", robotAvail);
69
+ if (robotAvail.statusCode !== 201) throw new Error("robot.availability failed");
70
+
71
+ // 1) Create a contract with credits enabled (to show SLA -> CreditMemo).
72
+ const contractId = "c_demo_delivery";
73
+ const contractCreate = await request(api, {
74
+ method: "POST",
75
+ path: "/ops/contracts",
76
+ headers: protocolHeaders,
77
+ body: {
78
+ contractId,
79
+ name: "Demo Contract (delivery)",
80
+ isDefault: false,
81
+ policies: {
82
+ creditPolicy: {
83
+ enabled: true,
84
+ defaultAmountCents: 1250,
85
+ maxAmountCents: 1250,
86
+ currency: "USD"
87
+ },
88
+ evidencePolicy: { retentionDays: 30 },
89
+ coveragePolicy: {
90
+ required: true,
91
+ feeModel: "PER_JOB",
92
+ feeCentsPerJob: 1650,
93
+ creditFundingModel: "PLATFORM_EXPENSE",
94
+ reserveFundPercent: 100,
95
+ insurerId: null,
96
+ recoverablePercent: 100,
97
+ recoverableTerms: null,
98
+ responseSlaSeconds: 0,
99
+ includedAssistSeconds: 0,
100
+ overageRateCentsPerMinute: 0
101
+ }
102
+ }
103
+ }
104
+ });
105
+ recordStep("ops.contracts.create", contractCreate);
106
+ if (contractCreate.statusCode !== 201) throw new Error("ops.contracts.create failed");
107
+
108
+ // 2) Create + quote + book a job.
109
+ const created = await request(api, {
110
+ method: "POST",
111
+ path: "/jobs",
112
+ headers: { ...protocolHeaders, "x-idempotency-key": "demo_job_create" },
113
+ body: { templateId: "reset_standard", customerId: "cust_demo", siteId: "site_demo", contractId, constraints: {} }
114
+ });
115
+ recordStep("jobs.create", created);
116
+ if (created.statusCode !== 201) throw new Error("jobs.create failed");
117
+ const jobId = created.json.job.id;
118
+ let lastChainHash = created.json.job.lastChainHash;
119
+
120
+ // 15 minute SLA window for the demo story (startAt → endAt).
121
+ const bookingStartAt = "2026-01-20T10:00:00.000Z";
122
+ const bookingEndAt = "2026-01-20T10:15:00.000Z";
123
+ // Allow late starts in the access plan window; SLA window is still the booking window.
124
+ const accessValidTo = "2026-01-20T10:45:00.000Z";
125
+
126
+ const quote = await request(api, {
127
+ method: "POST",
128
+ path: `/jobs/${jobId}/quote`,
129
+ headers: { ...protocolHeaders, "x-idempotency-key": "demo_job_quote", "x-proxy-expected-prev-chain-hash": lastChainHash },
130
+ body: {
131
+ startAt: bookingStartAt,
132
+ endAt: bookingEndAt,
133
+ environmentTier: "ENV_HOSPITALITY",
134
+ requiresOperatorCoverage: false,
135
+ customerId: "cust_demo",
136
+ siteId: "site_demo",
137
+ contractId
138
+ }
139
+ });
140
+ recordStep("jobs.quote", quote);
141
+ if (quote.statusCode !== 201) throw new Error("jobs.quote failed");
142
+ lastChainHash = quote.json.job.lastChainHash;
143
+
144
+ const book = await request(api, {
145
+ method: "POST",
146
+ path: `/jobs/${jobId}/book`,
147
+ headers: { ...protocolHeaders, "x-idempotency-key": "demo_job_book", "x-proxy-expected-prev-chain-hash": lastChainHash },
148
+ body: {
149
+ paymentHoldId: `hold_${jobId}`,
150
+ startAt: bookingStartAt,
151
+ endAt: bookingEndAt,
152
+ environmentTier: "ENV_HOSPITALITY",
153
+ requiresOperatorCoverage: false,
154
+ customerId: "cust_demo",
155
+ siteId: "site_demo",
156
+ contractId
157
+ }
158
+ });
159
+ recordStep("jobs.book", book);
160
+ if (book.statusCode !== 201) throw new Error("jobs.book failed");
161
+ lastChainHash = book.json.job.lastChainHash;
162
+ const bookedPolicyHash = book.json.event?.payload?.policyHash ?? null;
163
+
164
+ // 3) Update the contract post-booking to demonstrate pinning (policyHash is immutable per job).
165
+ const contractUpdate = await request(api, {
166
+ method: "POST",
167
+ path: "/ops/contracts",
168
+ headers: protocolHeaders,
169
+ body: { contractId, policies: { creditPolicy: { enabled: true, defaultAmountCents: 9000, maxAmountCents: 9000, currency: "USD" } } }
170
+ });
171
+ recordStep("ops.contracts.update", contractUpdate);
172
+ if (contractUpdate.statusCode !== 201) throw new Error("ops.contracts.update failed");
173
+
174
+ // 4) Correlation + ingest sample telemetry from an upstream ops platform.
175
+ // Advance time so ingest events aren't rejected as "future timestamp" (max skew is small).
176
+ nowMs = Date.parse("2026-01-20T10:06:00.000Z");
177
+ const correlationKey = "ext_delivery_412";
178
+ const link = await request(api, {
179
+ method: "POST",
180
+ path: "/ops/correlations/link",
181
+ headers: protocolHeaders,
182
+ body: { jobId, siteId: "site_demo", correlationKey }
183
+ });
184
+ recordStep("ops.correlations.link", link);
185
+ if (link.statusCode !== 201) throw new Error("ops.correlations.link failed");
186
+
187
+ const ingestRequest = {
188
+ source: "demo_dispatch",
189
+ siteId: "site_demo",
190
+ correlationKey,
191
+ events: [
192
+ {
193
+ externalEventId: "ext_evt_dispatch_eval_1",
194
+ type: "DISPATCH_EVALUATED",
195
+ at: "2026-01-20T10:05:00.000Z",
196
+ payload: {
197
+ jobId,
198
+ evaluatedAt: "2026-01-20T10:05:00.000Z",
199
+ window: { startAt: bookingStartAt, endAt: bookingEndAt },
200
+ zoneId: "default",
201
+ requiresOperatorCoverage: false,
202
+ candidates: [],
203
+ selected: null
204
+ }
205
+ }
206
+ ]
207
+ };
208
+ const ingest = await request(api, {
209
+ method: "POST",
210
+ path: "/ingest/proxy",
211
+ auth: "none",
212
+ headers: { ...protocolHeaders, "x-proxy-ingest-token": "ingest_tok", "x-idempotency-key": "demo_ingest_1" },
213
+ body: ingestRequest
214
+ });
215
+ recordStep("ingest.proxy", ingest, { ingestRequest });
216
+ if (ingest.statusCode !== 200) throw new Error(`ingest.proxy failed (status ${ingest.statusCode})`);
217
+ if ((ingest.json?.results?.[0]?.status ?? null) !== "accepted") {
218
+ throw new Error(`ingest.proxy rejected: ${ingest.json?.results?.[0]?.reasonCode ?? "UNKNOWN"}`);
219
+ }
220
+ if (Array.isArray(ingest.json?.events) && ingest.json.events.length) {
221
+ const head = ingest.json.events[ingest.json.events.length - 1];
222
+ if (head?.chainHash) lastChainHash = head.chainHash;
223
+ }
224
+
225
+ // Helpers to append job events.
226
+ const postServerEvent = async (type, payload, idempotencyKey) => {
227
+ const res = await request(api, {
228
+ method: "POST",
229
+ path: `/jobs/${jobId}/events`,
230
+ headers: {
231
+ ...protocolHeaders,
232
+ ...(idempotencyKey ? { "x-idempotency-key": idempotencyKey } : {}),
233
+ "x-proxy-expected-prev-chain-hash": lastChainHash
234
+ },
235
+ body: { type, actor: { type: "system", id: "proxy" }, payload }
236
+ });
237
+ recordStep(`jobs.events.${type}`, res);
238
+ if (res.statusCode !== 201) throw new Error(`jobs.events.${type} failed (status ${res.statusCode}): ${res.body ?? ""}`);
239
+ lastChainHash = res.json.job.lastChainHash;
240
+ return res;
241
+ };
242
+
243
+ const postRobotEvent = async (type, payload) => {
244
+ const at = nowIso();
245
+ const draft = createChainedEvent({ streamId: jobId, type, actor: { type: "robot", id: robotId }, payload, at });
246
+ const finalized = finalizeChainedEvent({
247
+ event: draft,
248
+ prevChainHash: lastChainHash,
249
+ signer: { keyId: robotKeyId, privateKeyPem: robotPrivateKeyPem }
250
+ });
251
+ const res = await request(api, { method: "POST", path: `/jobs/${jobId}/events`, headers: protocolHeaders, body: finalized });
252
+ recordStep(`jobs.events.${type}.robot`, res);
253
+ if (res.statusCode !== 201) throw new Error(`jobs.events.${type} (robot) failed (status ${res.statusCode}): ${res.body ?? ""}`);
254
+ lastChainHash = res.json.job.lastChainHash;
255
+ return res;
256
+ };
257
+
258
+ // 5) Match/reserve + access.
259
+ await postServerEvent("MATCHED", { robotId }, "demo_match");
260
+ await postServerEvent("RESERVED", { robotId, startAt: bookingStartAt, endAt: bookingEndAt, reservationId: `rsv_${jobId}` }, "demo_reserve");
261
+
262
+ const accessPlanId = `ap_${jobId}`;
263
+ await postServerEvent(
264
+ "ACCESS_PLAN_ISSUED",
265
+ {
266
+ jobId,
267
+ accessPlanId,
268
+ method: "DOCKED_IN_BUILDING",
269
+ credentialRef: `vault://access/${accessPlanId}/v1`,
270
+ scope: { areas: ["LOADING_DOCK"], noGo: [] },
271
+ validFrom: bookingStartAt,
272
+ validTo: accessValidTo,
273
+ revocable: true,
274
+ requestedBy: "system"
275
+ },
276
+ "demo_access_plan"
277
+ );
278
+
279
+ // 6) Robot telemetry (late start -> SLA breach -> credit).
280
+ nowMs = Date.parse("2026-01-20T09:58:00.000Z");
281
+ await postRobotEvent("EN_ROUTE", { etaSeconds: 60 });
282
+ nowMs = Date.parse("2026-01-20T10:01:00.000Z");
283
+ await postRobotEvent("ACCESS_GRANTED", { jobId, accessPlanId, method: "DOCKED_IN_BUILDING" });
284
+ nowMs = Date.parse("2026-01-20T10:18:00.000Z"); // after SLA window end
285
+ await postRobotEvent("EXECUTION_STARTED", { plan: ["deliver"], destination: "room_412" });
286
+ nowMs = Date.parse("2026-01-20T10:18:32.000Z");
287
+ await postRobotEvent("EXECUTION_COMPLETED", { report: { durationSeconds: 32 }, deliveredTo: "room_412" });
288
+
289
+ nowMs += 60_000;
290
+ await postServerEvent("SETTLED", { settlement: "demo" }, "demo_settle");
291
+
292
+ const accounting = await api.tickJobAccounting({ maxMessages: 50 });
293
+ steps.push({ name: "tick.jobAccounting", result: accounting });
294
+
295
+ const artifactsTick = await api.tickArtifacts({ maxMessages: 200 });
296
+ steps.push({ name: "tick.artifacts", result: artifactsTick });
297
+
298
+ const timeline = await request(api, { method: "GET", path: `/ops/jobs/${jobId}/timeline`, headers: protocolHeaders });
299
+ recordStep("ops.jobs.timeline", timeline);
300
+
301
+ const artifactsRes = await request(api, { method: "GET", path: `/jobs/${jobId}/artifacts`, headers: protocolHeaders });
302
+ recordStep("jobs.artifacts", artifactsRes);
303
+
304
+ const artifacts = await api.store.listArtifacts({ tenantId: "tenant_default", jobId });
305
+ const latestByType = new Map();
306
+ for (const a of artifacts) {
307
+ const t = a?.artifactType ?? a?.schemaVersion ?? null;
308
+ if (!t) continue;
309
+ const prev = latestByType.get(t) ?? null;
310
+ const at = Date.parse(a?.generatedAt ?? a?.createdAt ?? 0);
311
+ const bt = Date.parse(prev?.generatedAt ?? prev?.createdAt ?? 0);
312
+ if (!prev || (Number.isFinite(at) && Number.isFinite(bt) && at > bt)) latestByType.set(t, a);
313
+ }
314
+ const artifactsByType = Object.fromEntries(Array.from(latestByType.entries()).sort((a, b) => String(a[0]).localeCompare(String(b[0]))));
315
+
316
+ const output = {
317
+ runId,
318
+ scenario: "delivery_robot_late",
319
+ tenantId: "tenant_default",
320
+ jobId,
321
+ bookedPolicyHash,
322
+ contractId,
323
+ contractVersionAtBooking: book.json.event?.payload?.contractVersion ?? null,
324
+ contractVersionAfterUpdate: contractUpdate.json.contract?.contractVersion ?? null,
325
+ artifacts: Object.keys(artifactsByType).sort(),
326
+ notes: [
327
+ "Booking pins policyHash; later contract updates do not change bookedPolicyHash.",
328
+ "Robot starts after booking window end -> SLA_BREACH_DETECTED, then SLA_CREDIT_ISSUED (creditPolicy enabled)."
329
+ ]
330
+ };
331
+
332
+ // Write outputs.
333
+ await fs.rm(latest, { recursive: true, force: true });
334
+ await fs.mkdir(latest, { recursive: true });
335
+
336
+ await writeJson(path.join(root, "run.json"), output);
337
+ await writeJson(path.join(latest, "run.json"), output);
338
+
339
+ await writeJson(path.join(root, "sample_ingest_request.json"), ingestRequest);
340
+ await writeJson(path.join(latest, "sample_ingest_request.json"), ingestRequest);
341
+
342
+ await writeJson(path.join(root, "sample_ingest_response.json"), ingest.json);
343
+ await writeJson(path.join(latest, "sample_ingest_response.json"), ingest.json);
344
+
345
+ await writeJson(path.join(root, "timeline.json"), timeline.json);
346
+ await writeJson(path.join(latest, "timeline.json"), timeline.json);
347
+
348
+ await writeJson(path.join(root, "artifacts_index.json"), { artifacts });
349
+ await writeJson(path.join(latest, "artifacts_index.json"), { artifacts });
350
+
351
+ for (const [artifactType, artifact] of Object.entries(artifactsByType)) {
352
+ const filename = `${artifactType}.json`;
353
+ await writeJson(path.join(root, filename), artifact);
354
+ await writeJson(path.join(latest, filename), artifact);
355
+ }
356
+
357
+ await writeJson(path.join(root, "steps.json"), { steps });
358
+ await writeJson(path.join(latest, "steps.json"), { steps });
359
+
360
+ // Console summary (for 30-second demo).
361
+ // Keep output stable and readable.
362
+ process.stdout.write(
363
+ [
364
+ "Demo generated.",
365
+ `- Job: ${jobId}`,
366
+ `- Booked policyHash: ${bookedPolicyHash}`,
367
+ `- Artifacts: ${Object.keys(artifactsByType).sort().join(", ") || "(none)"}`,
368
+ `- Output: demo/delivery-robot/output/${runId}/`,
369
+ "Open demo/delivery-robot/output/latest/ for the most recent run."
370
+ ].join("\n") + "\n"
371
+ );
372
+ }
373
+
374
+ main().catch((err) => {
375
+ console.error(err);
376
+ process.exitCode = 1;
377
+ });
@@ -0,0 +1,202 @@
1
+ import { SettldClient } from "../../packages/api-sdk/src/index.js";
2
+
3
+ import { canonicalJsonStringify, normalizeForCanonicalJson } from "../../src/core/canonical-json.js";
4
+ import { createEd25519Keypair, sha256Hex, signHashHexEd25519 } from "../../src/core/crypto.js";
5
+
6
+ function uniqueSuffix() {
7
+ return `${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
8
+ }
9
+
10
+ function sleep(ms) {
11
+ return new Promise((resolve) => setTimeout(resolve, ms));
12
+ }
13
+
14
+ function generateAgentRegistration({ agentId, displayName, capability }) {
15
+ const { publicKeyPem, privateKeyPem } = createEd25519Keypair();
16
+ return {
17
+ agent: {
18
+ agentId,
19
+ displayName,
20
+ owner: { ownerType: "service", ownerId: "svc_demo" },
21
+ capabilities: capability ? [capability] : [],
22
+ publicKeyPem
23
+ },
24
+ privateKeyPem
25
+ };
26
+ }
27
+
28
+ function buildSignedArbitrationVerdictV1({
29
+ tenantId,
30
+ runId,
31
+ settlementId,
32
+ disputeId,
33
+ caseId,
34
+ arbiterAgentId,
35
+ signerKeyId,
36
+ signerPrivateKeyPem,
37
+ outcome,
38
+ releaseRatePct,
39
+ rationale,
40
+ evidenceRefs = [],
41
+ issuedAt = new Date().toISOString()
42
+ }) {
43
+ const core = normalizeForCanonicalJson(
44
+ {
45
+ schemaVersion: "ArbitrationVerdict.v1",
46
+ verdictId: `avd_${sha256Hex(`demo:verdict:${caseId}:${issuedAt}`).slice(0, 16)}`,
47
+ caseId,
48
+ tenantId,
49
+ runId,
50
+ settlementId,
51
+ disputeId,
52
+ arbiterAgentId,
53
+ outcome,
54
+ releaseRatePct,
55
+ rationale,
56
+ evidenceRefs,
57
+ issuedAt,
58
+ appealRef: null
59
+ },
60
+ { path: "$" }
61
+ );
62
+ const verdictHash = sha256Hex(canonicalJsonStringify(core));
63
+ const signature = signHashHexEd25519(verdictHash, signerPrivateKeyPem);
64
+ return { ...core, signerKeyId, signature };
65
+ }
66
+
67
+ async function main() {
68
+ const baseUrl = process.env.SETTLD_BASE_URL ?? "http://127.0.0.1:3000";
69
+ const tenantId = process.env.SETTLD_TENANT_ID ?? "tenant_default";
70
+ const apiKey = process.env.SETTLD_API_KEY ?? "";
71
+
72
+ if (!apiKey) {
73
+ // eslint-disable-next-line no-console
74
+ console.error("SETTLD_API_KEY is not set; this demo will only work if API auth is disabled.");
75
+ }
76
+
77
+ const client = new SettldClient({
78
+ baseUrl,
79
+ tenantId,
80
+ apiKey: apiKey || undefined
81
+ });
82
+
83
+ const suffix = uniqueSuffix();
84
+ const payerAgentId = `agt_demo_payer_${suffix}`;
85
+ const payeeAgentId = `agt_demo_payee_${suffix}`;
86
+ const arbiterAgentId = `agt_demo_arbiter_${suffix}`;
87
+
88
+ // Tool-call holdback + dispute loop demo.
89
+ // Note: agreementHash/receiptHash are modeled as sha256 hex bindings; this demo computes them deterministically from local strings.
90
+ const agreementHash = sha256Hex(`demo:tool_call:agreement:${suffix}`);
91
+ const receiptHash = sha256Hex(`demo:tool_call:receipt:${suffix}`);
92
+
93
+ const payerReg = generateAgentRegistration({ agentId: payerAgentId, displayName: "Demo Payer", capability: "buyer" });
94
+ const payeeReg = generateAgentRegistration({ agentId: payeeAgentId, displayName: "Demo Payee", capability: "seller" });
95
+ const arbiterReg = generateAgentRegistration({ agentId: arbiterAgentId, displayName: "Demo Arbiter", capability: "arbiter" });
96
+
97
+ const payerIdentity = await client.registerAgent(payerReg.agent, { idempotencyKey: `demo_${suffix}_register_payer` });
98
+ const payeeIdentity = await client.registerAgent(payeeReg.agent, { idempotencyKey: `demo_${suffix}_register_payee` });
99
+ const arbiterIdentity = await client.registerAgent(arbiterReg.agent, { idempotencyKey: `demo_${suffix}_register_arbiter` });
100
+ const arbiterSignerKeyId = arbiterIdentity?.body?.keyId ?? arbiterIdentity?.body?.agentIdentity?.keys?.keyId ?? null;
101
+
102
+ await client.creditAgentWallet(payerAgentId, { amountCents: 50_000, currency: "USD" }, { idempotencyKey: `demo_${suffix}_fund_payer` });
103
+
104
+ const holdLock = await client.opsLockToolCallHold(
105
+ {
106
+ agreementHash,
107
+ receiptHash,
108
+ payerAgentId,
109
+ payeeAgentId,
110
+ amountCents: 10_000,
111
+ currency: "USD",
112
+ holdbackBps: 2_000,
113
+ challengeWindowMs: 2_000
114
+ },
115
+ { idempotencyKey: `demo_${suffix}_hold_lock` }
116
+ );
117
+
118
+ const hold = holdLock?.body?.hold ?? null;
119
+ const holdHash = hold?.holdHash ?? null;
120
+ if (!holdHash) throw new Error("hold lock response missing hold.holdHash");
121
+
122
+ const open = await client.toolCallOpenArbitration(
123
+ {
124
+ agreementHash,
125
+ receiptHash,
126
+ holdHash,
127
+ openedByAgentId: payerAgentId,
128
+ arbiterAgentId,
129
+ summary: "Dispute: output does not meet acceptance criteria",
130
+ evidenceRefs: []
131
+ },
132
+ { idempotencyKey: `demo_${suffix}_tc_open` }
133
+ );
134
+
135
+ const arbitrationCase = open?.body?.arbitrationCase ?? null;
136
+ const caseId = arbitrationCase?.caseId ?? null;
137
+ const disputeId = arbitrationCase?.disputeId ?? null;
138
+ const settlementId = arbitrationCase?.settlementId ?? null;
139
+ const runId = arbitrationCase?.runId ?? null;
140
+ if (!caseId || !disputeId || !settlementId || !runId) throw new Error("open arbitration response missing required fields");
141
+
142
+ // Let the dispute window elapse, then demonstrate that the holdback tick refuses to auto-release while a case is open.
143
+ await sleep(2500);
144
+ const blockedTick = await client.opsRunToolCallHoldbackMaintenance({ dryRun: true, limit: 50 }, { requestId: `demo_${suffix}_tick_blocked` });
145
+
146
+ if (!arbiterSignerKeyId) throw new Error("arbiter registration did not return a keyId for signing verdicts");
147
+
148
+ const signedVerdict = buildSignedArbitrationVerdictV1({
149
+ tenantId,
150
+ runId,
151
+ settlementId,
152
+ disputeId,
153
+ caseId,
154
+ arbiterAgentId,
155
+ signerKeyId: arbiterSignerKeyId,
156
+ signerPrivateKeyPem: arbiterReg.privateKeyPem,
157
+ outcome: "accepted",
158
+ releaseRatePct: 100,
159
+ rationale: "Payee delivered acceptable work; release holdback."
160
+ });
161
+
162
+ const verdict = await client.toolCallSubmitArbitrationVerdict(
163
+ { caseId, arbitrationVerdict: signedVerdict },
164
+ { idempotencyKey: `demo_${suffix}_tc_verdict` }
165
+ );
166
+
167
+ const adjustmentId = `sadj_agmt_${agreementHash}_holdback`;
168
+ const adjustment = await client.opsGetSettlementAdjustment(adjustmentId, { requestId: `demo_${suffix}_get_adj` });
169
+
170
+ const summary = {
171
+ demo: "tool_call_holdback_dispute_loop",
172
+ ids: {
173
+ tenantId,
174
+ agreementHash,
175
+ receiptHash,
176
+ holdHash,
177
+ caseId,
178
+ disputeId,
179
+ runId,
180
+ settlementId,
181
+ adjustmentId
182
+ },
183
+ agents: {
184
+ payerAgentId,
185
+ payeeAgentId,
186
+ arbiterAgentId
187
+ },
188
+ notes: {
189
+ kernelExplorer: `/ops/kernel/workspace?tenantId=${encodeURIComponent(tenantId)}&agreementHash=${encodeURIComponent(agreementHash)}`,
190
+ blockedTick: blockedTick?.body ?? null,
191
+ verdict: verdict?.body ?? null,
192
+ adjustment: adjustment?.body ?? null,
193
+ payerIdentity: payerIdentity?.body?.agentIdentity ?? null,
194
+ payeeIdentity: payeeIdentity?.body?.agentIdentity ?? null
195
+ }
196
+ };
197
+
198
+ process.stdout.write(`${JSON.stringify(summary, null, 2)}\n`);
199
+ }
200
+
201
+ await main();
202
+
@@ -0,0 +1,118 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import http from "node:http";
4
+ import assert from "node:assert/strict";
5
+
6
+ import { buildDeterministicZipStore } from "../../src/core/deterministic-zip.js";
7
+
8
+ const baseUrl = process.env.MAGIC_LINK_DEMO_URL ?? "http://127.0.0.1:8787";
9
+ const apiKey = process.env.MAGIC_LINK_DEMO_API_KEY ?? "dev_key";
10
+ const tenantId = process.env.MAGIC_LINK_DEMO_TENANT_ID ?? "tenant_example";
11
+
12
+ async function listFilesRecursive(dir) {
13
+ const out = [];
14
+ async function walk(cur) {
15
+ const entries = await fs.readdir(cur, { withFileTypes: true });
16
+ for (const e of entries) {
17
+ const fp = path.join(cur, e.name);
18
+ if (e.isDirectory()) {
19
+ // eslint-disable-next-line no-await-in-loop
20
+ await walk(fp);
21
+ } else if (e.isFile()) {
22
+ out.push(fp);
23
+ }
24
+ }
25
+ }
26
+ await walk(dir);
27
+ out.sort();
28
+ return out;
29
+ }
30
+
31
+ async function zipDir(dir) {
32
+ const files = new Map();
33
+ const fps = await listFilesRecursive(dir);
34
+ for (const fp of fps) {
35
+ const rel = path.relative(dir, fp).split(path.sep).join("/");
36
+ // eslint-disable-next-line no-await-in-loop
37
+ const bytes = await fs.readFile(fp);
38
+ files.set(rel, bytes);
39
+ }
40
+ const zip = buildDeterministicZipStore({ files, mtime: new Date("2000-01-01T00:00:00.000Z") });
41
+ return Buffer.from(zip);
42
+ }
43
+
44
+ function requestJson({ method, url, headers, body }) {
45
+ return new Promise((resolve, reject) => {
46
+ const u = new URL(url);
47
+ const req = http.request(
48
+ {
49
+ method,
50
+ hostname: u.hostname,
51
+ port: u.port || 80,
52
+ path: u.pathname + u.search,
53
+ headers
54
+ },
55
+ (res) => {
56
+ const chunks = [];
57
+ res.on("data", (d) => chunks.push(d));
58
+ res.on("end", () => {
59
+ const text = Buffer.concat(chunks).toString("utf8");
60
+ try {
61
+ resolve({ statusCode: res.statusCode ?? 0, json: text ? JSON.parse(text) : null, text });
62
+ } catch (err) {
63
+ reject(new Error(`invalid json response status=${res.statusCode}: ${text.slice(0, 500)}`));
64
+ }
65
+ });
66
+ }
67
+ );
68
+ req.on("error", reject);
69
+ if (body) req.write(body);
70
+ req.end();
71
+ });
72
+ }
73
+
74
+ async function main() {
75
+ const fixtureDir = "test/fixtures/bundles/v1/closepack/strict-pass";
76
+ const zipBuf = await zipDir(fixtureDir);
77
+
78
+ const upload = await requestJson({
79
+ method: "POST",
80
+ url: `${baseUrl}/v1/upload?mode=auto`,
81
+ headers: {
82
+ "x-api-key": apiKey,
83
+ "x-tenant-id": tenantId,
84
+ "content-type": "application/zip",
85
+ "content-length": String(zipBuf.length)
86
+ },
87
+ body: zipBuf
88
+ });
89
+ assert.equal(upload.statusCode, 200, upload.text);
90
+ assert.equal(upload.json?.ok, true, upload.text);
91
+ const token = upload.json.token;
92
+ assert.match(String(token), /^ml_[0-9a-f]{48}$/);
93
+
94
+ const inbox = await requestJson({
95
+ method: "GET",
96
+ url: `${baseUrl}/v1/inbox?status=green&limit=50`,
97
+ headers: {
98
+ "x-api-key": apiKey,
99
+ "x-tenant-id": tenantId
100
+ }
101
+ });
102
+ assert.equal(inbox.statusCode, 200, inbox.text);
103
+ assert.equal(inbox.json?.ok, true, inbox.text);
104
+ const rows = Array.isArray(inbox.json?.rows) ? inbox.json.rows : [];
105
+ if (!rows.some((r) => String(r?.token ?? "") === token)) {
106
+ throw new Error(`uploaded token not found in green inbox: token=${token}`);
107
+ }
108
+
109
+ // eslint-disable-next-line no-console
110
+ console.log(JSON.stringify({ ok: true, token, baseUrl, tenantId }, null, 2));
111
+ }
112
+
113
+ main().catch((err) => {
114
+ // eslint-disable-next-line no-console
115
+ console.error(err?.stack ?? String(err ?? ""));
116
+ process.exit(1);
117
+ });
118
+