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,99 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
+ cd "$ROOT_DIR"
6
+
7
+ ACCEPTANCE_CLEAN="${ACCEPTANCE_CLEAN:-1}"
8
+ ACCEPTANCE_PROFILE="${ACCEPTANCE_PROFILE:-app}"
9
+
10
+ if ! docker info >/dev/null 2>&1; then
11
+ echo "acceptance: docker is not available (is the daemon running, and do you have socket access?)" >&2
12
+ exit 2
13
+ fi
14
+
15
+ RUN_ID="${ACCEPTANCE_RUN_ID:-$(date +%s)_$RANDOM}"
16
+ PROJECT="${ACCEPTANCE_PROJECT_NAME:-settld_acc_${RUN_ID}}"
17
+ SCHEMA="${ACCEPTANCE_PG_SCHEMA:-acc_${RUN_ID}}"
18
+ ART_DIR="${ACCEPTANCE_ARTIFACT_DIR:-$(mktemp -d)}"
19
+
20
+ pick_port() {
21
+ node --input-type=module -e "import net from 'node:net'; const s=net.createServer(); s.listen(0,'127.0.0.1',()=>{console.log(s.address().port); s.close();});"
22
+ }
23
+
24
+ API_PORT="${ACCEPTANCE_API_PORT:-$(pick_port)}"
25
+ RECEIVER_PORT="${ACCEPTANCE_RECEIVER_PORT:-$(pick_port)}"
26
+ MINIO_PORT="${ACCEPTANCE_MINIO_PORT:-$(pick_port)}"
27
+ MINIO_CONSOLE_PORT="${ACCEPTANCE_MINIO_CONSOLE_PORT:-$(pick_port)}"
28
+
29
+ export COMPOSE_PROJECT_NAME="${PROJECT}"
30
+ export PROXY_PG_SCHEMA="${SCHEMA}"
31
+ export PROXY_API_PORT="${API_PORT}"
32
+ export PROXY_RECEIVER_PORT="${RECEIVER_PORT}"
33
+ export PROXY_MINIO_PORT="${MINIO_PORT}"
34
+ export PROXY_MINIO_CONSOLE_PORT="${MINIO_CONSOLE_PORT}"
35
+ export ACCEPTANCE_ARTIFACT_DIR="${ART_DIR}"
36
+ export ACCEPTANCE_API_BASE_URL="${ACCEPTANCE_API_BASE_URL:-http://127.0.0.1:${API_PORT}}"
37
+ export ACCEPTANCE_RECEIVER_BASE_URL="${ACCEPTANCE_RECEIVER_BASE_URL:-http://127.0.0.1:${RECEIVER_PORT}}"
38
+ export ACCEPTANCE_MINIO_ENDPOINT="${ACCEPTANCE_MINIO_ENDPOINT:-http://127.0.0.1:${MINIO_PORT}}"
39
+
40
+ mkdir -p "${ART_DIR}"
41
+ echo "acceptance: artifacts dir: ${ART_DIR}"
42
+ echo "acceptance: COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME}"
43
+ echo "acceptance: PROXY_PG_SCHEMA=${PROXY_PG_SCHEMA}"
44
+ echo "acceptance: PROXY_API_PORT=${PROXY_API_PORT}"
45
+ echo "acceptance: PROXY_RECEIVER_PORT=${PROXY_RECEIVER_PORT}"
46
+ echo "acceptance: PROXY_MINIO_PORT=${PROXY_MINIO_PORT}"
47
+ echo "acceptance: PROXY_MINIO_CONSOLE_PORT=${PROXY_MINIO_CONSOLE_PORT}"
48
+ echo "acceptance: ACCEPTANCE_API_BASE_URL=${ACCEPTANCE_API_BASE_URL}"
49
+ echo "acceptance: ACCEPTANCE_RECEIVER_BASE_URL=${ACCEPTANCE_RECEIVER_BASE_URL}"
50
+ echo "acceptance: ACCEPTANCE_MINIO_ENDPOINT=${ACCEPTANCE_MINIO_ENDPOINT}"
51
+
52
+ compose_down() {
53
+ local profile_args=(--profile "${ACCEPTANCE_PROFILE}")
54
+ local exit_code="${1:-0}"
55
+ if [[ "${exit_code}" != "0" ]]; then
56
+ echo "acceptance: failure diagnostics"
57
+ docker compose "${profile_args[@]}" ps || true
58
+ docker compose "${profile_args[@]}" logs --no-color --tail=400 >"${ART_DIR}/compose.logs.tail.txt" 2>&1 || true
59
+ cat "${ART_DIR}/compose.logs.tail.txt" || true
60
+
61
+ # Best-effort: if context exists, snapshot key ops endpoints for debugging.
62
+ if [[ -f "${ART_DIR}/context.json" ]]; then
63
+ node --input-type=module -e "import fs from 'node:fs'; const c=JSON.parse(fs.readFileSync(process.env.ACCEPTANCE_ARTIFACT_DIR + '/context.json','utf8')); console.log(c?.bearer ?? '');" \
64
+ >"${ART_DIR}/bearer.txt" 2>/dev/null || true
65
+ BEARER="$(cat "${ART_DIR}/bearer.txt" 2>/dev/null || true)"
66
+ if [[ -n "${BEARER}" ]]; then
67
+ BEARER="${BEARER}" TENANT="${ACCEPTANCE_TENANT_ID:-tenant_default}" PROTO="${ACCEPTANCE_PROTOCOL:-1.0}" API="${ACCEPTANCE_API_BASE_URL:-http://127.0.0.1:3000}" \
68
+ node --input-type=module -e "const b=process.env.BEARER; const t=process.env.TENANT; const p=process.env.PROTO; const base=process.env.API; async function get(path){const r=await fetch(base+path,{headers:{authorization:b,'x-proxy-tenant-id':t,'x-settld-protocol':p}}).catch(()=>null); if(!r){console.log(path, 'fetch_failed'); return;} const txt=await r.text(); console.log(path, r.status); console.log(txt.slice(0, 4000));} await get('/ops/status'); await get('/ops/deliveries?limit=50'); await get('/ops/dlq?type=delivery&limit=50');" \
69
+ >"${ART_DIR}/ops.snapshots.txt" 2>&1 || true
70
+ cat "${ART_DIR}/ops.snapshots.txt" || true
71
+ fi
72
+ fi
73
+ fi
74
+
75
+ if [[ "${ACCEPTANCE_CLEAN}" == "1" ]]; then
76
+ docker compose --profile "${ACCEPTANCE_PROFILE}" down -v --remove-orphans >/dev/null 2>&1 || true
77
+ else
78
+ docker compose --profile "${ACCEPTANCE_PROFILE}" down --remove-orphans >/dev/null 2>&1 || true
79
+ fi
80
+ }
81
+
82
+ cleanup() {
83
+ local code="$?"
84
+ compose_down "${code}"
85
+ }
86
+ trap cleanup EXIT
87
+
88
+ compose_down 0
89
+
90
+ echo "acceptance: starting docker compose (profile=${ACCEPTANCE_PROFILE})"
91
+ docker compose --profile "${ACCEPTANCE_PROFILE}" up -d --build
92
+
93
+ echo "acceptance: seeding minio buckets"
94
+ docker compose --profile init run --rm minio-init
95
+
96
+ echo "acceptance: running full-stack checks"
97
+ node scripts/acceptance/full-stack.mjs
98
+
99
+ echo "acceptance: OK"
@@ -0,0 +1,242 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import crypto from "node:crypto";
3
+ import fs from "node:fs/promises";
4
+ import path from "node:path";
5
+
6
+ function sh(cmd, args, { cwd, env, stdin } = {}) {
7
+ const res = spawnSync(cmd, args, { cwd, env, input: stdin, encoding: "utf8" });
8
+ if (res.status !== 0) {
9
+ const err = (res.stderr || res.stdout || "").trim();
10
+ throw new Error(`${cmd} ${args.join(" ")} failed (exit ${res.status})${err ? `: ${err}` : ""}`);
11
+ }
12
+ return res.stdout;
13
+ }
14
+
15
+ async function sha256FileHex(fp) {
16
+ const h = crypto.createHash("sha256");
17
+ const f = await fs.open(fp, "r");
18
+ try {
19
+ const buf = Buffer.alloc(1024 * 1024);
20
+ while (true) {
21
+ // eslint-disable-next-line no-await-in-loop
22
+ const { bytesRead } = await f.read(buf, 0, buf.length, null);
23
+ if (bytesRead === 0) break;
24
+ h.update(buf.subarray(0, bytesRead));
25
+ }
26
+ } finally {
27
+ await f.close();
28
+ }
29
+ return h.digest("hex");
30
+ }
31
+
32
+ function parseArgs(argv) {
33
+ let outDir = path.resolve(process.cwd(), "dist", "audit");
34
+ let version = "v1";
35
+ for (let i = 0; i < argv.length; i += 1) {
36
+ const a = argv[i];
37
+ if (a === "--out") {
38
+ outDir = path.resolve(process.cwd(), String(argv[i + 1] ?? ""));
39
+ i += 1;
40
+ continue;
41
+ }
42
+ if (a === "--packet-version") {
43
+ version = String(argv[i + 1] ?? "v1");
44
+ i += 1;
45
+ continue;
46
+ }
47
+ if (a === "--help" || a === "-h") {
48
+ // eslint-disable-next-line no-console
49
+ console.error("usage: node scripts/audit/build-audit-packet.mjs [--out <dir>] [--packet-version v1]");
50
+ process.exit(2);
51
+ }
52
+ // eslint-disable-next-line no-console
53
+ console.error(`unknown arg: ${a}`);
54
+ process.exit(2);
55
+ }
56
+ return { outDir, version };
57
+ }
58
+
59
+ async function listFilesRecursive(root) {
60
+ const out = [];
61
+ async function walk(cur) {
62
+ const entries = await fs.readdir(cur, { withFileTypes: true });
63
+ for (const e of entries) {
64
+ const fp = path.join(cur, e.name);
65
+ if (e.isDirectory()) {
66
+ // eslint-disable-next-line no-await-in-loop
67
+ await walk(fp);
68
+ } else if (e.isFile()) out.push(fp);
69
+ }
70
+ }
71
+ await walk(root);
72
+ out.sort();
73
+ return out;
74
+ }
75
+
76
+ async function writeReadme({ dst, packetName, tool }) {
77
+ const text = `# Settld Audit Packet (${packetName})
78
+
79
+ This archive is intended to be a self-contained “evidence bundle” for a hostile/skeptical reader.
80
+
81
+ ## Contents
82
+
83
+ - \`spec/\` — protocol specs (including threat model + invariants checklist)
84
+ - \`protocol-vectors/\` — canonical protocol vectors
85
+ - \`conformance/\` — the conformance pack tarball + checksums
86
+ - \`tool.json\` — tool provenance summary for the build that produced this packet
87
+ - \`SHA256SUMS\` — checksums for files in this packet
88
+
89
+ ## How to validate (minimum)
90
+
91
+ 1. Verify checksums (example):
92
+
93
+ \`\`\`sh
94
+ (cd ${packetName} && sha256sum -c SHA256SUMS)
95
+ \`\`\`
96
+
97
+ 2. Install the released verifier CLI (\`settld-verify\`).
98
+
99
+ - If published to npm, install a pinned version.
100
+ - Otherwise, download the release npm tarball for \`settld-artifact-verify\` and install it locally.
101
+
102
+ 3. Run conformance pack (requires \`settld-verify\` in PATH):
103
+
104
+ \`\`\`sh
105
+ tar -xzf conformance/conformance-v1.tar.gz
106
+ node conformance-v1/run.mjs
107
+ \`\`\`
108
+
109
+ ## Tool provenance
110
+
111
+ This packet was built from:
112
+
113
+ \`\`\`json
114
+ ${JSON.stringify(tool, null, 2)}
115
+ \`\`\`
116
+ `;
117
+ await fs.writeFile(dst, text, "utf8");
118
+ }
119
+
120
+ async function main() {
121
+ const { outDir, version } = parseArgs(process.argv.slice(2));
122
+ await fs.mkdir(outDir, { recursive: true });
123
+
124
+ const repoRoot = process.cwd();
125
+
126
+ const toolVersion = (() => {
127
+ try {
128
+ const v = String((sh(process.execPath, ["-e", "const fs=require('fs'); console.log(String(fs.readFileSync('SETTLD_VERSION','utf8')).trim())"]).trim()) ?? "");
129
+ return v || null;
130
+ } catch {
131
+ return null;
132
+ }
133
+ })();
134
+ const toolCommit = (() => {
135
+ try {
136
+ const v = sh("git", ["rev-parse", "HEAD"], { cwd: repoRoot }).trim();
137
+ return v || null;
138
+ } catch {
139
+ return null;
140
+ }
141
+ })();
142
+
143
+ const packetName = `settld-audit-packet-${version}`;
144
+ const stagingRoot = await fs.mkdtemp(path.join(outDir, `${packetName}-staging-`));
145
+ const packetRoot = path.join(stagingRoot, packetName);
146
+ await fs.mkdir(packetRoot, { recursive: true });
147
+
148
+ try {
149
+ // 1) Copy specs (docs/spec/*)
150
+ await fs.cp(path.join(repoRoot, "docs", "spec"), path.join(packetRoot, "spec"), { recursive: true });
151
+
152
+ // 2) Copy protocol vectors
153
+ await fs.mkdir(path.join(packetRoot, "protocol-vectors"), { recursive: true });
154
+ await fs.copyFile(
155
+ path.join(repoRoot, "test", "fixtures", "protocol-vectors", "v1.json"),
156
+ path.join(packetRoot, "protocol-vectors", "v1.json")
157
+ );
158
+
159
+ // 3) Build conformance pack tarball and checksum
160
+ const conformanceOutDir = path.join(packetRoot, "conformance");
161
+ await fs.mkdir(conformanceOutDir, { recursive: true });
162
+ await fs.rm(path.join(stagingRoot, "conformance-v1"), { recursive: true, force: true });
163
+ await fs.mkdir(path.join(stagingRoot, "conformance-v1"), { recursive: true });
164
+ await fs.cp(path.join(repoRoot, "conformance", "v1"), path.join(stagingRoot, "conformance-v1"), { recursive: true });
165
+ const conformanceTgz = path.join(conformanceOutDir, "conformance-v1.tar.gz");
166
+ {
167
+ const tarPath = path.join(conformanceOutDir, "conformance-v1.tar");
168
+ sh("tar", ["--sort=name", "--mtime=2026-02-02 00:00:00Z", "--owner=0", "--group=0", "--numeric-owner", "-cf", tarPath, "-C", stagingRoot, "conformance-v1"]);
169
+ const res = spawnSync("gzip", ["-n", "-9", "-c", tarPath]);
170
+ if (res.status !== 0) throw new Error("gzip failed");
171
+ await fs.writeFile(conformanceTgz, res.stdout);
172
+ await fs.rm(tarPath, { force: true });
173
+ }
174
+ const conformanceSum = await sha256FileHex(conformanceTgz);
175
+ await fs.writeFile(path.join(conformanceOutDir, "conformance-v1-SHA256SUMS"), `${conformanceSum} conformance-v1.tar.gz\n`, "utf8");
176
+
177
+ // 4) Tool provenance summary
178
+ const tool = {
179
+ schemaVersion: "AuditToolSummary.v1",
180
+ tool: { name: "settld-verify", version: toolVersion, commit: toolCommit },
181
+ repo: { commit: toolCommit }
182
+ };
183
+ await fs.writeFile(path.join(packetRoot, "tool.json"), JSON.stringify(tool, null, 2) + "\n", "utf8");
184
+
185
+ // 5) Packet README
186
+ await writeReadme({
187
+ dst: path.join(packetRoot, "README.md"),
188
+ packetName,
189
+ tool
190
+ });
191
+
192
+ // 6) SHA256SUMS for all files in packet (excluding SHA256SUMS itself)
193
+ const files = (await listFilesRecursive(packetRoot)).filter((fp) => path.basename(fp) !== "SHA256SUMS");
194
+ const lines = [];
195
+ for (const fp of files) {
196
+ // eslint-disable-next-line no-await-in-loop
197
+ const sum = await sha256FileHex(fp);
198
+ const rel = path.relative(packetRoot, fp).replaceAll(path.sep, "/");
199
+ lines.push(`${sum} ${rel}`);
200
+ }
201
+ await fs.writeFile(path.join(packetRoot, "SHA256SUMS"), lines.join("\n") + "\n", "utf8");
202
+
203
+ // 7) Deterministic zip build (sorted entries, fixed timestamp)
204
+ const zipPath = path.join(outDir, `${packetName}.zip`);
205
+ const py = `
206
+ import os, sys, zipfile
207
+ from datetime import datetime
208
+
209
+ root = sys.argv[1]
210
+ out = sys.argv[2]
211
+
212
+ fixed = (2026, 2, 2, 0, 0, 0)
213
+
214
+ paths = []
215
+ for dirpath, dirnames, filenames in os.walk(root):
216
+ dirnames.sort()
217
+ filenames.sort()
218
+ for fn in filenames:
219
+ fp = os.path.join(dirpath, fn)
220
+ rel = os.path.relpath(fp, root).replace(os.sep, "/")
221
+ paths.append((fp, rel))
222
+
223
+ with zipfile.ZipFile(out, "w", compression=zipfile.ZIP_DEFLATED, compresslevel=9) as z:
224
+ for fp, rel in paths:
225
+ zi = zipfile.ZipInfo(rel, date_time=fixed)
226
+ # Normalize perms to 0644 for determinism.
227
+ zi.external_attr = (0o100644 << 16)
228
+ with open(fp, "rb") as f:
229
+ z.writestr(zi, f.read())
230
+ `;
231
+ sh("python3", ["-c", py, packetRoot, zipPath]);
232
+ const zipSum = await sha256FileHex(zipPath);
233
+ await fs.writeFile(path.join(outDir, `${packetName}.zip.sha256`), `${zipSum} ${path.basename(zipPath)}\n`, "utf8");
234
+
235
+ // eslint-disable-next-line no-console
236
+ console.log(`wrote ${zipPath}`);
237
+ } finally {
238
+ await fs.rm(stagingRoot, { recursive: true, force: true });
239
+ }
240
+ }
241
+
242
+ await main();
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ if [[ -z "${DATABASE_URL:-}" ]]; then
5
+ echo "DATABASE_URL is required" >&2
6
+ exit 2
7
+ fi
8
+
9
+ OUT_DIR="${OUT_DIR:-./backups}"
10
+ TS="$(date -u +%Y%m%dT%H%M%SZ)"
11
+ DEST="${OUT_DIR%/}/backup_${TS}"
12
+
13
+ mkdir -p "$DEST"
14
+
15
+ sanitize_url() {
16
+ # Best-effort: redact password in postgres://user:pass@host/db
17
+ local url="$1"
18
+ if [[ "$url" =~ ^([^:]+://[^:@]+):[^@]+@(.*)$ ]]; then
19
+ echo "${BASH_REMATCH[1]}:[REDACTED]@${BASH_REMATCH[2]}"
20
+ else
21
+ echo "[REDACTED]"
22
+ fi
23
+ }
24
+
25
+ echo "Backing up to $DEST" >&2
26
+
27
+ pg_dump --format=custom --no-owner --no-privileges --file "$DEST/db.dump" "$DATABASE_URL"
28
+
29
+ if command -v shasum >/dev/null 2>&1; then
30
+ shasum -a 256 "$DEST/db.dump" >"$DEST/db.dump.sha256"
31
+ elif command -v sha256sum >/dev/null 2>&1; then
32
+ sha256sum "$DEST/db.dump" >"$DEST/db.dump.sha256"
33
+ fi
34
+
35
+ cat >"$DEST/meta.json" <<EOF
36
+ {
37
+ "createdAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
38
+ "databaseUrl": "$(sanitize_url "$DATABASE_URL")",
39
+ "pgSchema": "${PROXY_PG_SCHEMA:-public}",
40
+ "notes": "pg_dump custom format; restore with scripts/restore-pg.sh"
41
+ }
42
+ EOF
43
+
44
+ echo "Done: $DEST" >&2
45
+
@@ -0,0 +1,18 @@
1
+ # Backup/Restore verification (PG)
2
+
3
+ This folder contains a deterministic backup/restore drill:
4
+
5
+ - Seed a known workload into Postgres (PG store).
6
+ - Capture a small set of state digests (counts + stable hashes).
7
+ - Take a logical backup (`pg_dump`).
8
+ - Restore into a fresh database.
9
+ - Recompute state digests and compare.
10
+
11
+ Entry point: `scripts/backup-restore-test.sh`.
12
+
13
+ Requirements:
14
+
15
+ - `STORE=pg`
16
+ - `DATABASE_URL` and `RESTORE_DATABASE_URL` set
17
+ - `pg_dump` and `psql` available on PATH
18
+
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Captures a small, stable digest of Postgres state for backup/restore verification.
3
+ *
4
+ * Prints JSON to stdout.
5
+ */
6
+ import pg from "pg";
7
+ import { canonicalJsonStringify } from "../../src/core/canonical-json.js";
8
+ import { sha256Hex } from "../../src/core/crypto.js";
9
+ import { normalizeTenantId } from "../../src/core/tenancy.js";
10
+
11
+ const DATABASE_URL = process.env.DATABASE_URL;
12
+ if (!DATABASE_URL) throw new Error("DATABASE_URL is required");
13
+ const TENANT_ID = normalizeTenantId(process.env.TENANT_ID ?? "tenant_default");
14
+ const SCHEMA = (() => {
15
+ const raw = String(process.env.PROXY_PG_SCHEMA ?? "public").trim();
16
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(raw)) {
17
+ throw new Error("PROXY_PG_SCHEMA must match [A-Za-z_][A-Za-z0-9_]*");
18
+ }
19
+ return raw;
20
+ })();
21
+
22
+ function digestRows(rows) {
23
+ return sha256Hex(canonicalJsonStringify(rows));
24
+ }
25
+
26
+ const { Client } = pg;
27
+ const client = new Client({ connectionString: DATABASE_URL });
28
+ await client.connect();
29
+ await client.query(`SET search_path TO "${SCHEMA}", public`);
30
+
31
+ const tenantCountRes = await client.query("SELECT COUNT(DISTINCT tenant_id)::int AS n FROM snapshots");
32
+ const jobCountRes = await client.query("SELECT COUNT(*)::int AS n FROM snapshots WHERE tenant_id = $1 AND aggregate_type = 'job'", [TENANT_ID]);
33
+ const ledgerEntryCountRes = await client.query("SELECT COUNT(*)::int AS n FROM ledger_entries WHERE tenant_id = $1", [TENANT_ID]);
34
+ const allocationCountRes = await client.query("SELECT COUNT(*)::int AS n FROM ledger_allocations WHERE tenant_id = $1", [TENANT_ID]);
35
+ const artifactCountRes = await client.query("SELECT COUNT(*)::int AS n FROM artifacts WHERE tenant_id = $1", [TENANT_ID]);
36
+ const partyStatementCountRes = await client.query("SELECT COUNT(*)::int AS n FROM party_statements WHERE tenant_id = $1", [TENANT_ID]);
37
+
38
+ const artifactsRes = await client.query(
39
+ `
40
+ SELECT artifact_id, artifact_type, artifact_hash
41
+ FROM artifacts
42
+ WHERE tenant_id = $1
43
+ AND artifact_type IN ('SettlementStatement.v1','MonthlyStatement.v1','PartyStatement.v1','PayoutInstruction.v1')
44
+ ORDER BY artifact_type ASC, artifact_id ASC
45
+ `,
46
+ [TENANT_ID]
47
+ );
48
+ const artifactsDigest = digestRows(
49
+ artifactsRes.rows.map((r) => ({
50
+ artifactId: String(r.artifact_id),
51
+ artifactType: String(r.artifact_type),
52
+ artifactHash: String(r.artifact_hash)
53
+ }))
54
+ );
55
+
56
+ const ledgerEntriesRes = await client.query(
57
+ `
58
+ SELECT entry_id, entry_json
59
+ FROM ledger_entries
60
+ WHERE tenant_id = $1
61
+ ORDER BY entry_id ASC
62
+ `,
63
+ [TENANT_ID]
64
+ );
65
+ const ledgerDigest = digestRows(
66
+ ledgerEntriesRes.rows.map((r) => ({
67
+ entryId: String(r.entry_id),
68
+ entry: r.entry_json ?? null
69
+ }))
70
+ );
71
+
72
+ const allocRes = await client.query(
73
+ `
74
+ SELECT entry_id, posting_id, account_id, party_id, party_role, currency, amount_cents
75
+ FROM ledger_allocations
76
+ WHERE tenant_id = $1
77
+ ORDER BY entry_id ASC, posting_id ASC, party_id ASC
78
+ `,
79
+ [TENANT_ID]
80
+ );
81
+ const allocationsDigest = digestRows(
82
+ allocRes.rows.map((r) => ({
83
+ entryId: String(r.entry_id),
84
+ postingId: String(r.posting_id),
85
+ accountId: r.account_id === null ? null : String(r.account_id),
86
+ partyId: String(r.party_id),
87
+ partyRole: String(r.party_role),
88
+ currency: String(r.currency),
89
+ amountCents: Number(r.amount_cents)
90
+ }))
91
+ );
92
+
93
+ const monthEventsRes = await client.query(
94
+ `
95
+ SELECT aggregate_id, seq, event_json
96
+ FROM events
97
+ WHERE tenant_id = $1 AND aggregate_type = 'month'
98
+ ORDER BY aggregate_id ASC, seq ASC
99
+ `,
100
+ [TENANT_ID]
101
+ );
102
+ const monthEventsDigest = digestRows(
103
+ monthEventsRes.rows.map((r) => ({
104
+ monthId: String(r.aggregate_id),
105
+ seq: Number(r.seq),
106
+ event: r.event_json ?? null
107
+ }))
108
+ );
109
+
110
+ await client.end();
111
+
112
+ const state = {
113
+ tenantId: TENANT_ID,
114
+ counts: {
115
+ tenants: Number(tenantCountRes.rows?.[0]?.n ?? 0),
116
+ jobs: Number(jobCountRes.rows?.[0]?.n ?? 0),
117
+ ledgerEntries: Number(ledgerEntryCountRes.rows?.[0]?.n ?? 0),
118
+ allocations: Number(allocationCountRes.rows?.[0]?.n ?? 0),
119
+ artifacts: Number(artifactCountRes.rows?.[0]?.n ?? 0),
120
+ partyStatements: Number(partyStatementCountRes.rows?.[0]?.n ?? 0)
121
+ },
122
+ digests: {
123
+ artifacts: artifactsDigest,
124
+ ledgerEntries: ledgerDigest,
125
+ allocations: allocationsDigest,
126
+ monthEvents: monthEventsDigest
127
+ }
128
+ };
129
+
130
+ process.stdout.write(JSON.stringify(state, null, 2) + "\n");
@@ -0,0 +1,97 @@
1
+ import { Readable } from "node:stream";
2
+
3
+ import { createApi } from "../../src/api/app.js";
4
+ import { createPgStore } from "../../src/db/store-pg.js";
5
+ import { authKeyId, authKeySecret, hashAuthKeySecretLegacy } from "../../src/core/auth.js";
6
+ import { DEFAULT_TENANT_ID, normalizeTenantId } from "../../src/core/tenancy.js";
7
+
8
+ function makeReq({ method, path, headers, body }) {
9
+ const chunks = body === undefined ? [] : [Buffer.from(JSON.stringify(body), "utf8")];
10
+ const req = Readable.from(chunks);
11
+ req.method = method;
12
+ req.url = path;
13
+ req.headers = headers ?? {};
14
+ return req;
15
+ }
16
+
17
+ function makeRes() {
18
+ const headers = new Map();
19
+ return {
20
+ statusCode: 200,
21
+ setHeader(name, value) {
22
+ headers.set(String(name).toLowerCase(), String(value));
23
+ },
24
+ end(payload) {
25
+ this.body = payload ?? "";
26
+ this.headers = headers;
27
+ this.ended = true;
28
+ }
29
+ };
30
+ }
31
+
32
+ function hasAuthHeader(headers) {
33
+ const keys = Object.keys(headers ?? {});
34
+ for (const k of keys) {
35
+ const key = String(k).toLowerCase();
36
+ if (key === "authorization" || key === "x-proxy-api-key" || key === "x-proxy-ops-token") return true;
37
+ }
38
+ return false;
39
+ }
40
+
41
+ async function ensureAuth({ store, tenantId, scopes }) {
42
+ tenantId = normalizeTenantId(tenantId ?? DEFAULT_TENANT_ID);
43
+ const keyId = authKeyId();
44
+ const secret = authKeySecret();
45
+ const secretHash = hashAuthKeySecretLegacy(secret);
46
+ const createdAt = new Date().toISOString();
47
+ await store.putAuthKey({
48
+ tenantId,
49
+ authKey: { keyId, secretHash, scopes, status: "active", description: "backup-restore-drill", createdAt }
50
+ });
51
+ const token = `${keyId}.${secret}`;
52
+ return { token, authorization: `Bearer ${token}` };
53
+ }
54
+
55
+ export async function createBackupRestoreApiClient({
56
+ databaseUrl,
57
+ schema = null,
58
+ tenantId = DEFAULT_TENANT_ID,
59
+ scopes = ["ops_write", "finance_write", "audit_read"],
60
+ protocol = "1.0",
61
+ now = null
62
+ } = {}) {
63
+ if (!databaseUrl) throw new Error("databaseUrl is required");
64
+ tenantId = normalizeTenantId(tenantId ?? DEFAULT_TENANT_ID);
65
+ const store = await createPgStore({
66
+ databaseUrl,
67
+ schema: schema ?? (process.env.PROXY_PG_SCHEMA ?? "public"),
68
+ migrateOnStartup: true
69
+ });
70
+ const api = createApi({ store, ...(typeof now === "function" ? { now } : null) });
71
+
72
+ const auth = await ensureAuth({ store, tenantId, scopes });
73
+
74
+ async function request({ method, path, headers = {}, body } = {}) {
75
+ const reqHeaders = {
76
+ "x-proxy-tenant-id": tenantId,
77
+ "x-settld-protocol": protocol,
78
+ ...(headers ?? {})
79
+ };
80
+ if (body !== undefined) reqHeaders["content-type"] = "application/json";
81
+ if (!hasAuthHeader(reqHeaders)) reqHeaders.authorization = auth.authorization;
82
+ const req = makeReq({ method, path, headers: reqHeaders, body });
83
+ const res = makeRes();
84
+ await api.handle(req, res);
85
+ const text = typeof res.body === "string" ? res.body : Buffer.from(res.body ?? "").toString("utf8");
86
+ const contentType = res.headers?.get?.("content-type") ? String(res.headers.get("content-type")) : "";
87
+ const isJson = contentType.includes("application/json") || contentType.includes("+json");
88
+ const json = isJson && text ? JSON.parse(text) : null;
89
+ return { statusCode: res.statusCode, json, body: text, headers: res.headers };
90
+ }
91
+
92
+ async function close() {
93
+ await store.close?.();
94
+ }
95
+
96
+ return { store, api, request, close, tenantId };
97
+ }