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,182 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+
5
+ import { canonicalJsonStringify } from "../packages/artifact-verify/src/canonical-json.js";
6
+ import { sha256HexUtf8, verifyHashHexEd25519 } from "../packages/artifact-verify/src/crypto.js";
7
+ import { unzipToTempSafe } from "../packages/artifact-verify/src/safe-unzip.js";
8
+ import { verifyClosePackBundleDir, verifyInvoiceBundleDir } from "../packages/artifact-verify/src/index.js";
9
+
10
+ function isPlainObject(v) {
11
+ return Boolean(v && typeof v === "object" && !Array.isArray(v) && (Object.getPrototypeOf(v) === Object.prototype || Object.getPrototypeOf(v) === null));
12
+ }
13
+
14
+ function sha256Hex(bytes) {
15
+ return crypto.createHash("sha256").update(bytes).digest("hex");
16
+ }
17
+
18
+ function cmpString(a, b) {
19
+ const aa = String(a ?? "");
20
+ const bb = String(b ?? "");
21
+ if (aa < bb) return -1;
22
+ if (aa > bb) return 1;
23
+ return 0;
24
+ }
25
+
26
+ function normalizeCodeList(list) {
27
+ const out = [];
28
+ for (const it of Array.isArray(list) ? list : []) {
29
+ if (!it || typeof it !== "object") continue;
30
+ const code = typeof it.code === "string" ? it.code : null;
31
+ if (!code) continue;
32
+ out.push(code);
33
+ }
34
+ return [...new Set(out)].sort(cmpString);
35
+ }
36
+
37
+ function trustToEnv(trustJson) {
38
+ if (!isPlainObject(trustJson)) return { ok: false, error: "trust must be an object" };
39
+ const governanceRoots = isPlainObject(trustJson.governanceRoots) ? trustJson.governanceRoots : {};
40
+ const pricingSigners = isPlainObject(trustJson.pricingSigners) ? trustJson.pricingSigners : {};
41
+ const timeAuthorities = isPlainObject(trustJson.timeAuthorities) ? trustJson.timeAuthorities : {};
42
+
43
+ return {
44
+ ok: true,
45
+ trust: { governanceRoots, pricingSigners, timeAuthorities },
46
+ env: {
47
+ SETTLD_TRUSTED_GOVERNANCE_ROOT_KEYS_JSON: JSON.stringify(governanceRoots),
48
+ SETTLD_TRUSTED_PRICING_SIGNER_KEYS_JSON: JSON.stringify(pricingSigners),
49
+ SETTLD_TRUSTED_TIME_AUTHORITY_KEYS_JSON: JSON.stringify(timeAuthorities)
50
+ }
51
+ };
52
+ }
53
+
54
+ async function readJsonBestEffort(fp) {
55
+ try {
56
+ return JSON.parse(await fs.readFile(fp, "utf8"));
57
+ } catch {
58
+ return null;
59
+ }
60
+ }
61
+
62
+ async function pricingSignatureV2Check({ bundleDir, bundleType, trust }) {
63
+ const invoiceRoot = bundleType === "ClosePack.v1" ? path.join(bundleDir, "payload", "invoice_bundle") : bundleDir;
64
+ const sigPath = path.join(invoiceRoot, "pricing", "pricing_matrix_signatures.json");
65
+ const pricingPath = path.join(invoiceRoot, "pricing", "pricing_matrix.json");
66
+
67
+ const sigJson = await readJsonBestEffort(sigPath);
68
+ if (!sigJson) return { ok: false, code: "PRICING_MATRIX_SIGNATURE_MISSING", detail: { path: "pricing/pricing_matrix_signatures.json" } };
69
+
70
+ const schemaVersion = String(sigJson.schemaVersion ?? "");
71
+ if (schemaVersion !== "PricingMatrixSignatures.v2") {
72
+ return { ok: false, code: "PRICING_MATRIX_SIGNATURE_SCHEMA_UNEXPECTED", detail: { schemaVersion: sigJson.schemaVersion ?? null } };
73
+ }
74
+ const declaredHash = typeof sigJson.pricingMatrixCanonicalHash === "string" ? sigJson.pricingMatrixCanonicalHash : null;
75
+ if (!declaredHash || !/^[0-9a-f]{64}$/.test(declaredHash)) {
76
+ return { ok: false, code: "PRICING_MATRIX_SIGNATURE_HASH_INVALID", detail: { pricingMatrixCanonicalHash: sigJson.pricingMatrixCanonicalHash ?? null } };
77
+ }
78
+
79
+ const pricingJson = await readJsonBestEffort(pricingPath);
80
+ if (!pricingJson) return { ok: false, code: "PRICING_MATRIX_MISSING", detail: { path: "pricing/pricing_matrix.json" } };
81
+ const actualHash = sha256HexUtf8(canonicalJsonStringify(pricingJson));
82
+ if (actualHash !== declaredHash) {
83
+ return { ok: false, code: "PRICING_MATRIX_SIGNATURE_PAYLOAD_MISMATCH", detail: { expected: actualHash, actual: declaredHash } };
84
+ }
85
+
86
+ const signatures = Array.isArray(sigJson.signatures) ? sigJson.signatures : [];
87
+ const trustedPricingSigners = trust && isPlainObject(trust.pricingSigners) ? trust.pricingSigners : {};
88
+
89
+ const signerKeyIds = [];
90
+ let validCount = 0;
91
+ for (const s of signatures) {
92
+ if (!s || typeof s !== "object") continue;
93
+ const signerKeyId = typeof s.signerKeyId === "string" ? s.signerKeyId : null;
94
+ const signatureBase64 = typeof s.signature === "string" ? s.signature : null;
95
+ if (!signerKeyId || !signatureBase64) continue;
96
+ signerKeyIds.push(signerKeyId);
97
+ const publicKeyPem = typeof trustedPricingSigners[signerKeyId] === "string" ? trustedPricingSigners[signerKeyId] : null;
98
+ if (!publicKeyPem) continue;
99
+ if (verifyHashHexEd25519({ hashHex: actualHash, signatureBase64, publicKeyPem })) validCount += 1;
100
+ }
101
+ signerKeyIds.sort(cmpString);
102
+
103
+ if (validCount < 1) {
104
+ return { ok: false, code: "PRICING_MATRIX_SIGNATURE_INVALID", detail: { signerKeyIds: [...new Set(signerKeyIds)] } };
105
+ }
106
+
107
+ return { ok: true, schemaVersion, signerKeyIds: [...new Set(signerKeyIds)], validCount };
108
+ }
109
+
110
+ export async function runVendorContractTest({ bundlePath, trustPath, expect }) {
111
+ if (!bundlePath || typeof bundlePath !== "string") throw new TypeError("bundlePath is required");
112
+ if (!trustPath || typeof trustPath !== "string") throw new TypeError("trustPath is required");
113
+ if (expect !== "strict-pass") throw new Error("unsupported expect (only strict-pass)");
114
+
115
+ const trustRaw = JSON.parse(await fs.readFile(trustPath, "utf8"));
116
+ const trustParsed = trustToEnv(trustRaw);
117
+ if (!trustParsed.ok) {
118
+ return { schemaVersion: "VendorContractTest.v1", ok: false, code: "INVALID_TRUST_FILE", detail: trustParsed };
119
+ }
120
+
121
+ const zipBytes = await fs.readFile(bundlePath);
122
+ const zipSha256 = sha256Hex(zipBytes);
123
+
124
+ const unzip = await unzipToTempSafe({ zipPath: path.resolve(process.cwd(), bundlePath) });
125
+ if (!unzip.ok) return { schemaVersion: "VendorContractTest.v1", ok: false, code: "ZIP_REJECTED", detail: unzip };
126
+
127
+ let bundleType = null;
128
+ let manifestHash = null;
129
+ let verifyRes = null;
130
+ let pricingCheck = null;
131
+
132
+ try {
133
+ const header = await readJsonBestEffort(path.join(unzip.dir, "settld.json"));
134
+ bundleType = typeof header?.type === "string" ? header.type : null;
135
+
136
+ const envKeys = [
137
+ "SETTLD_TRUSTED_GOVERNANCE_ROOT_KEYS_JSON",
138
+ "SETTLD_TRUSTED_PRICING_SIGNER_KEYS_JSON",
139
+ "SETTLD_TRUSTED_TIME_AUTHORITY_KEYS_JSON"
140
+ ];
141
+ const old = {};
142
+ for (const k of envKeys) old[k] = process.env[k];
143
+ process.env.SETTLD_TRUSTED_GOVERNANCE_ROOT_KEYS_JSON = trustParsed.env.SETTLD_TRUSTED_GOVERNANCE_ROOT_KEYS_JSON;
144
+ process.env.SETTLD_TRUSTED_PRICING_SIGNER_KEYS_JSON = trustParsed.env.SETTLD_TRUSTED_PRICING_SIGNER_KEYS_JSON;
145
+ process.env.SETTLD_TRUSTED_TIME_AUTHORITY_KEYS_JSON = trustParsed.env.SETTLD_TRUSTED_TIME_AUTHORITY_KEYS_JSON;
146
+ try {
147
+ if (bundleType === "ClosePack.v1") verifyRes = await verifyClosePackBundleDir({ dir: unzip.dir, strict: true, hashConcurrency: 16 });
148
+ else if (bundleType === "InvoiceBundle.v1") verifyRes = await verifyInvoiceBundleDir({ dir: unzip.dir, strict: true, hashConcurrency: 16 });
149
+ else verifyRes = { ok: false, error: "unsupported bundle type", type: bundleType, warnings: [] };
150
+ } finally {
151
+ for (const k of envKeys) {
152
+ if (old[k] === undefined) delete process.env[k];
153
+ else process.env[k] = old[k];
154
+ }
155
+ }
156
+
157
+ manifestHash = typeof verifyRes?.manifestHash === "string" ? verifyRes.manifestHash : null;
158
+ if (verifyRes && verifyRes.ok === true) pricingCheck = await pricingSignatureV2Check({ bundleDir: unzip.dir, bundleType, trust: trustParsed.trust });
159
+ } finally {
160
+ await fs.rm(unzip.dir, { recursive: true, force: true });
161
+ }
162
+
163
+ const warnings = normalizeCodeList(verifyRes?.warnings ?? []);
164
+ const strictVerifyOk = Boolean(verifyRes && verifyRes.ok === true) && warnings.length === 0;
165
+ const pricingOk = Boolean(pricingCheck && pricingCheck.ok === true);
166
+ const ok = strictVerifyOk && pricingOk;
167
+
168
+ return {
169
+ schemaVersion: "VendorContractTest.v1",
170
+ ok,
171
+ expect,
172
+ bundle: { type: bundleType, zipSha256, zipBytes: zipBytes.length, manifestHash },
173
+ strict: {
174
+ ok: strictVerifyOk,
175
+ verificationOk: Boolean(verifyRes && verifyRes.ok === true),
176
+ error: verifyRes && verifyRes.ok === false ? verifyRes.error ?? "FAILED" : null,
177
+ warnings
178
+ },
179
+ pricingSignatureV2: pricingCheck
180
+ };
181
+ }
182
+
@@ -0,0 +1,55 @@
1
+ import { runVendorContractTest } from "./vendor-contract-test-lib.mjs";
2
+
3
+ // `node --test` treats `**/*test*.mjs` as a test file. This script is a CLI,
4
+ // so bail out early when invoked without CLI flags.
5
+ if (!process.argv.includes("--bundle") && !process.argv.includes("--trust")) process.exit(0);
6
+
7
+ function usage() {
8
+ // eslint-disable-next-line no-console
9
+ console.error(
10
+ [
11
+ "usage:",
12
+ " node scripts/vendor-contract-test.mjs --bundle <bundle.zip> --trust <trust.json> --expect strict-pass",
13
+ "",
14
+ "outputs:",
15
+ " deterministic JSON to stdout; exit code 0 on expectation match."
16
+ ].join("\n")
17
+ );
18
+ process.exit(2);
19
+ }
20
+
21
+ function parse(argv) {
22
+ const out = { bundlePath: null, trustPath: null, expect: null };
23
+ for (let i = 0; i < argv.length; i += 1) {
24
+ const a = argv[i];
25
+ if (a === "--bundle") {
26
+ out.bundlePath = argv[i + 1] ?? null;
27
+ i += 1;
28
+ continue;
29
+ }
30
+ if (a === "--trust") {
31
+ out.trustPath = argv[i + 1] ?? null;
32
+ i += 1;
33
+ continue;
34
+ }
35
+ if (a === "--expect") {
36
+ out.expect = argv[i + 1] ?? null;
37
+ i += 1;
38
+ continue;
39
+ }
40
+ if (a === "--help" || a === "-h") usage();
41
+ usage();
42
+ }
43
+ if (!out.bundlePath || !out.trustPath || !out.expect) usage();
44
+ if (out.expect !== "strict-pass") usage();
45
+ return out;
46
+ }
47
+
48
+ async function main() {
49
+ const args = parse(process.argv.slice(2));
50
+ const out = await runVendorContractTest({ bundlePath: args.bundlePath, trustPath: args.trustPath, expect: args.expect });
51
+ process.stdout.write(JSON.stringify(out, null, 2) + "\n");
52
+ process.exit(out.ok ? 0 : 1);
53
+ }
54
+
55
+ await main();
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ if [ ! -x ".vercel-venv/bin/mkdocs" ]; then
5
+ echo "MkDocs venv not found; running install step first..."
6
+ bash scripts/vercel/install-mkdocs.sh
7
+ fi
8
+
9
+ .vercel-venv/bin/mkdocs build --strict --config-file mkdocs.yml
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Vercel "ignoreCommand" contract:
5
+ # - exit 0 => skip deployment
6
+ # - exit 1 => continue with deployment
7
+
8
+ if ! git rev-parse --verify HEAD^ >/dev/null 2>&1; then
9
+ # No parent commit context available; build to stay safe.
10
+ exit 1
11
+ fi
12
+
13
+ if git diff --quiet HEAD^ HEAD -- \
14
+ docs/ \
15
+ mkdocs.yml \
16
+ scripts/vercel/ \
17
+ .github/workflows/release.yml \
18
+ .github/workflows/tests.yml \
19
+ .github/pull_request_template.md; then
20
+ # No docs/mkdocs pipeline changes; skip root docs deployment.
21
+ exit 0
22
+ fi
23
+
24
+ # Relevant docs/deploy files changed; run deployment.
25
+ exit 1
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ python3 -m venv .vercel-venv
5
+ .vercel-venv/bin/python -m pip install --upgrade pip setuptools wheel
6
+ .vercel-venv/bin/pip install mkdocs mkdocs-material
@@ -0,0 +1,217 @@
1
+ import { logger } from "../src/core/log.js";
2
+ import { createPgPool } from "../src/db/pg.js";
3
+ import { keyIdFromPublicKeyPem } from "../src/core/crypto.js";
4
+ import { verifyChainedEvents } from "../src/core/event-chain.js";
5
+ import { verifyArtifactHash, verifySettlementBalances } from "../packages/artifact-verify/src/index.js";
6
+
7
+ function parsePositiveIntEnv(name, fallback) {
8
+ const raw = process.env[name] ?? null;
9
+ if (raw === null || raw === undefined || String(raw).trim() === "") return fallback;
10
+ const n = Number(raw);
11
+ if (!Number.isFinite(n) || !Number.isSafeInteger(n) || n <= 0) throw new TypeError(`${name} must be a positive safe integer`);
12
+ return n;
13
+ }
14
+
15
+ function parseNonNegativeIntEnv(name, fallback) {
16
+ const raw = process.env[name] ?? null;
17
+ if (raw === null || raw === undefined || String(raw).trim() === "") return fallback;
18
+ const n = Number(raw);
19
+ if (!Number.isFinite(n) || !Number.isSafeInteger(n) || n < 0) throw new TypeError(`${name} must be a non-negative safe integer`);
20
+ return n;
21
+ }
22
+
23
+ const databaseUrl = process.env.DATABASE_URL ?? null;
24
+ if (!databaseUrl) {
25
+ process.stderr.write("DATABASE_URL is required\n");
26
+ process.exit(2);
27
+ }
28
+
29
+ const schema = process.env.PROXY_PG_SCHEMA ?? "public";
30
+ const maxStreams = parsePositiveIntEnv("VERIFY_MAX_STREAMS", 100);
31
+ const maxArtifacts = parsePositiveIntEnv("VERIFY_MAX_ARTIFACTS", 100);
32
+ const maxLedgerEntries = parseNonNegativeIntEnv("VERIFY_MAX_LEDGER_ENTRIES", 0); // 0 = all
33
+
34
+ const pool = await createPgPool({ databaseUrl, schema });
35
+
36
+ async function loadPublicKeyByKeyId() {
37
+ const map = new Map();
38
+
39
+ try {
40
+ const signer = await pool.query("SELECT public_key_pem FROM server_signer WHERE id = 1");
41
+ if (signer.rows.length) {
42
+ const publicKeyPem = String(signer.rows[0].public_key_pem);
43
+ const keyId = keyIdFromPublicKeyPem(publicKeyPem);
44
+ map.set(keyId, publicKeyPem);
45
+ }
46
+ } catch {
47
+ // ignore
48
+ }
49
+
50
+ try {
51
+ const res = await pool.query("SELECT key_id, public_key_pem FROM public_keys");
52
+ for (const row of res.rows) {
53
+ if (!row?.key_id || !row?.public_key_pem) continue;
54
+ map.set(String(row.key_id), String(row.public_key_pem));
55
+ }
56
+ } catch {
57
+ // ignore
58
+ }
59
+
60
+ try {
61
+ const res = await pool.query("SELECT key_id, public_key_pem FROM signer_keys");
62
+ for (const row of res.rows) {
63
+ if (!row?.key_id || !row?.public_key_pem) continue;
64
+ map.set(String(row.key_id), String(row.public_key_pem));
65
+ }
66
+ } catch {
67
+ // ignore
68
+ }
69
+
70
+ return map;
71
+ }
72
+
73
+ function journalEntryBalances(entry) {
74
+ const postings = Array.isArray(entry?.postings) ? entry.postings : [];
75
+ let sum = 0;
76
+ for (const p of postings) {
77
+ const amt = p?.amountCents;
78
+ if (!Number.isFinite(amt) || !Number.isSafeInteger(amt)) return { ok: false, error: "invalid posting amount" };
79
+ sum += amt;
80
+ }
81
+ if (sum !== 0) return { ok: false, error: "unbalanced", sum };
82
+ return { ok: true };
83
+ }
84
+
85
+ async function verifyLedger() {
86
+ const balancesByTenant = new Map(); // tenantId -> Map(accountId -> balance)
87
+ let checked = 0;
88
+
89
+ const limitClause = maxLedgerEntries > 0 ? "LIMIT $1" : "";
90
+ const args = maxLedgerEntries > 0 ? [maxLedgerEntries] : [];
91
+ const res = await pool.query(
92
+ `
93
+ SELECT tenant_id, entry_id, entry_json
94
+ FROM ledger_entries
95
+ ORDER BY tenant_id ASC, entry_id ASC
96
+ ${limitClause}
97
+ `,
98
+ args
99
+ );
100
+
101
+ for (const row of res.rows) {
102
+ const tenantId = String(row.tenant_id ?? "tenant_default");
103
+ const entryId = String(row.entry_id ?? "");
104
+ const entry = row.entry_json ?? null;
105
+ const ok = journalEntryBalances(entry);
106
+ if (!ok.ok) {
107
+ throw new Error(`ledger entry ${tenantId}:${entryId} invalid: ${ok.error}${ok.sum !== undefined ? ` sum=${ok.sum}` : ""}`);
108
+ }
109
+ checked += 1;
110
+
111
+ if (!balancesByTenant.has(tenantId)) balancesByTenant.set(tenantId, new Map());
112
+ const b = balancesByTenant.get(tenantId);
113
+ for (const p of entry.postings) {
114
+ const accountId = String(p.accountId);
115
+ b.set(accountId, (b.get(accountId) ?? 0) + p.amountCents);
116
+ }
117
+ }
118
+
119
+ const balances = await pool.query("SELECT tenant_id, account_id, balance_cents FROM ledger_balances");
120
+ for (const row of balances.rows) {
121
+ const tenantId = String(row.tenant_id ?? "tenant_default");
122
+ const accountId = String(row.account_id ?? "");
123
+ const db = Number(row.balance_cents ?? 0);
124
+ const expected = balancesByTenant.get(tenantId)?.get(accountId) ?? 0;
125
+ if (db !== expected) {
126
+ throw new Error(`ledger_balances mismatch ${tenantId}:${accountId}: expected ${expected}, got ${db}`);
127
+ }
128
+ }
129
+
130
+ return { checked };
131
+ }
132
+
133
+ async function verifyArtifacts() {
134
+ const res = await pool.query(
135
+ `
136
+ SELECT tenant_id, artifact_id, artifact_hash, artifact_json
137
+ FROM artifacts
138
+ ORDER BY created_at DESC
139
+ LIMIT $1
140
+ `,
141
+ [maxArtifacts]
142
+ );
143
+
144
+ let checked = 0;
145
+ for (const row of res.rows) {
146
+ const tenantId = String(row.tenant_id ?? "tenant_default");
147
+ const artifactId = String(row.artifact_id ?? "");
148
+ const artifactHash = row.artifact_hash ? String(row.artifact_hash) : null;
149
+ const artifact = row.artifact_json ?? null;
150
+ if (!artifact || typeof artifact !== "object") throw new Error(`artifact ${tenantId}:${artifactId} missing artifact_json`);
151
+ if (artifactHash && String(artifact.artifactHash ?? "") !== artifactHash) {
152
+ throw new Error(`artifact hash column mismatch for ${tenantId}:${artifactId}`);
153
+ }
154
+ const h = verifyArtifactHash(artifact);
155
+ if (!h.ok) throw new Error(`artifact ${tenantId}:${artifactId} hash verify failed: ${h.error}`);
156
+ const s = verifySettlementBalances(artifact);
157
+ if (!s.ok) throw new Error(`artifact ${tenantId}:${artifactId} settlement verify failed: ${s.error}`);
158
+ checked += 1;
159
+ }
160
+
161
+ return { checked };
162
+ }
163
+
164
+ async function verifyStreams() {
165
+ const publicKeyByKeyId = await loadPublicKeyByKeyId();
166
+
167
+ const streams = await pool.query(
168
+ `
169
+ SELECT tenant_id, aggregate_type, aggregate_id
170
+ FROM snapshots
171
+ ORDER BY tenant_id ASC, aggregate_type ASC, aggregate_id ASC
172
+ LIMIT $1
173
+ `,
174
+ [maxStreams]
175
+ );
176
+
177
+ let checked = 0;
178
+ for (const row of streams.rows) {
179
+ const tenantId = String(row.tenant_id ?? "tenant_default");
180
+ const aggregateType = String(row.aggregate_type ?? "");
181
+ const aggregateId = String(row.aggregate_id ?? "");
182
+
183
+ const res = await pool.query(
184
+ `
185
+ SELECT event_json
186
+ FROM events
187
+ WHERE tenant_id = $1 AND aggregate_type = $2 AND aggregate_id = $3
188
+ ORDER BY seq ASC
189
+ `,
190
+ [tenantId, aggregateType, aggregateId]
191
+ );
192
+ const events = res.rows.map((r) => r.event_json).filter(Boolean);
193
+ const verify = verifyChainedEvents(events, { publicKeyByKeyId });
194
+ if (!verify.ok) throw new Error(`chain verify failed for ${tenantId}:${aggregateType}:${aggregateId}: ${verify.error}`);
195
+ checked += 1;
196
+ }
197
+
198
+ return { checked };
199
+ }
200
+
201
+ const startedMs = Date.now();
202
+ try {
203
+ const ledger = await verifyLedger();
204
+ const artifacts = await verifyArtifacts();
205
+ const streams = await verifyStreams();
206
+
207
+ const runtimeMs = Date.now() - startedMs;
208
+ logger.info("verify.pg.ok", { schema, runtimeMs, ledger, artifacts, streams });
209
+ process.exit(0);
210
+ } catch (err) {
211
+ const runtimeMs = Date.now() - startedMs;
212
+ logger.error("verify.pg.failed", { schema, runtimeMs, err });
213
+ process.exit(1);
214
+ } finally {
215
+ await pool.end();
216
+ }
217
+