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,12 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd "$(dirname "$0")/../.."
5
+
6
+ bad="$(git ls-files -z -- '*.pyc' '**/__pycache__/**' '.venv/**' | tr '\0' '\n' | sed '/^$/d' || true)"
7
+ if [[ -n "$bad" ]]; then
8
+ echo "generated artifacts are tracked in git (must be removed):" >&2
9
+ echo "$bad" >&2
10
+ exit 1
11
+ fi
12
+
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd "$(dirname "$0")/../.."
5
+
6
+ PROBLEM_TESTS=(
7
+ "test/api-e2e-x402-authorize-payment.test.js"
8
+ "test/api-python-sdk-first-paid-task-smoke.test.js"
9
+ "test/api-python-sdk-first-verified-run-smoke.test.js"
10
+ "test/magic-link-onboarding-live-contract.test.js"
11
+ "test/magic-link-service.test.js"
12
+ "test/mcp-http-gateway.test.js"
13
+ "test/mcp-stdio-spike.test.js"
14
+ "test/payment-triggers.test.js"
15
+ "test/sdk-tenant-analytics-examples-smoke.test.js"
16
+ "test/trust-config-wizard-cli.test.js"
17
+ )
18
+
19
+ NOO_REGRESSION_TEST_FILE="test/api-e2e-x402-authorize-payment.test.js"
20
+ REQUIRED_NOO_REGRESSION_TESTS=(
21
+ "API e2e: x402 authorize-payment and verify fail closed on missing or revoked passport when required"
22
+ "API e2e: x402 authorize-payment requires valid execution intent when enabled"
23
+ "API e2e: verify enforces strict request binding evidence for quote-bound authorization"
24
+ )
25
+
26
+ for test_name in "${REQUIRED_NOO_REGRESSION_TESTS[@]}"; do
27
+ if ! grep -F "test(\"${test_name}\"" "$NOO_REGRESSION_TEST_FILE" >/dev/null; then
28
+ echo "missing required NOO regression test: ${test_name}" >&2
29
+ exit 1
30
+ fi
31
+ done
32
+
33
+ SAFE_TESTS=()
34
+ for fp in $(ls test/*.test.js | sort); do
35
+ is_problem_test=0
36
+ for problem in "${PROBLEM_TESTS[@]}"; do
37
+ if [[ "$fp" == "$problem" ]]; then
38
+ is_problem_test=1
39
+ break
40
+ fi
41
+ done
42
+ if [[ "$is_problem_test" -eq 0 ]]; then
43
+ SAFE_TESTS+=("$fp")
44
+ fi
45
+ done
46
+
47
+ # Phase 1: bulk suite (fast).
48
+ # NOTE: These files sporadically fail when executed *after* a large multi-file
49
+ # `node --test` run (Node 18 test runner multi-file mode), while they pass when
50
+ # run first in a fresh process. Running them first keeps `npm test` stable.
51
+ for fp in "${PROBLEM_TESTS[@]}"; do
52
+ node --test "$fp"
53
+ done
54
+
55
+ # Phase 2: bulk suite (fast).
56
+ node --test "${SAFE_TESTS[@]}"
57
+
58
+ # Post-check: ensure we never accidentally track generated artifacts.
59
+ bash scripts/test/check-no-generated-artifacts.sh
@@ -0,0 +1,57 @@
1
+ import fs from "node:fs/promises";
2
+ import fsSync from "node:fs";
3
+ import path from "node:path";
4
+
5
+ function usage() {
6
+ fsSync.writeFileSync(2, "usage: node scripts/trust/validate-trust-file.mjs <trust.json>\n");
7
+ process.exit(2);
8
+ }
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 validateKeyMap(map, label) {
15
+ if (map === undefined || map === null) return { ok: true, keys: 0 };
16
+ if (!isPlainObject(map)) return { ok: false, error: `${label} must be an object mapping keyId -> publicKeyPem` };
17
+ for (const [k, v] of Object.entries(map)) {
18
+ if (typeof k !== "string" || !k.trim()) return { ok: false, error: `${label} has an invalid keyId` };
19
+ if (typeof v !== "string" || !v.trim()) return { ok: false, error: `${label}[${k}] must be a non-empty PEM string` };
20
+ // Best-effort sanity check (format may evolve, but we at least reject obvious garbage).
21
+ if (!v.includes("BEGIN PUBLIC KEY") || !v.includes("END PUBLIC KEY")) return { ok: false, error: `${label}[${k}] does not look like a public key PEM` };
22
+ }
23
+ return { ok: true, keys: Object.keys(map).length };
24
+ }
25
+
26
+ async function main() {
27
+ const fp = process.argv[2] ?? null;
28
+ if (!fp || fp === "--help" || fp === "-h") usage();
29
+ const abs = path.resolve(process.cwd(), fp);
30
+ const raw = await fs.readFile(abs, "utf8");
31
+ let json;
32
+ try {
33
+ json = JSON.parse(raw);
34
+ } catch (err) {
35
+ fsSync.writeFileSync(2, `invalid JSON: ${err?.message ?? String(err ?? "")}\n`);
36
+ process.exit(2);
37
+ }
38
+ if (!isPlainObject(json)) {
39
+ fsSync.writeFileSync(2, "trust.json must be an object\n");
40
+ process.exit(2);
41
+ }
42
+
43
+ const gov = validateKeyMap(json.governanceRoots, "governanceRoots");
44
+ if (!gov.ok) {
45
+ fsSync.writeFileSync(2, String(gov.error ?? "invalid governanceRoots") + "\n");
46
+ process.exit(2);
47
+ }
48
+ const time = validateKeyMap(json.timeAuthorities, "timeAuthorities");
49
+ if (!time.ok) {
50
+ fsSync.writeFileSync(2, String(time.error ?? "invalid timeAuthorities") + "\n");
51
+ process.exit(2);
52
+ }
53
+
54
+ fsSync.writeFileSync(1, `ok governanceRoots=${gov.keys} timeAuthorities=${time.keys}\n`);
55
+ }
56
+
57
+ await main();
@@ -0,0 +1,277 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import process from "node:process";
7
+
8
+ import { createEd25519Keypair, keyIdFromPublicKeyPem } from "../../src/core/crypto.js";
9
+ import { buildSettldPayKeysetV1 } from "../../src/core/settld-keys.js";
10
+
11
+ const SERVER_SIGNER_FILENAME = "server-signer.json";
12
+ const SETTLD_PAY_KEYSET_STORE_FILENAME = "settld-pay-keyset-store.json";
13
+
14
+ function usage() {
15
+ return [
16
+ "Usage:",
17
+ " node scripts/trust-config/rotate-settld-pay.mjs [--data-dir <path>] [--report <path>] [--keep-previous <n>] [--bootstrap]",
18
+ "",
19
+ "Options:",
20
+ " --data-dir <path> Data directory containing signer material (default: $PROXY_DATA_DIR or ./data)",
21
+ " --report <path> Optional JSON artifact path for rotation report",
22
+ " --keep-previous <n> Number of previous public keys to keep published (default: 2)",
23
+ " --bootstrap Allow creating an initial signer if no existing signer is found",
24
+ " --help Show this help"
25
+ ].join("\n");
26
+ }
27
+
28
+ function parseArgs(argv) {
29
+ const out = {
30
+ dataDir: process.env.PROXY_DATA_DIR && String(process.env.PROXY_DATA_DIR).trim() !== "" ? String(process.env.PROXY_DATA_DIR).trim() : "data",
31
+ reportPath: null,
32
+ keepPrevious: 2,
33
+ bootstrap: false
34
+ };
35
+ for (let i = 0; i < argv.length; i += 1) {
36
+ const a = String(argv[i] ?? "");
37
+ if (a === "--help" || a === "-h") {
38
+ out.help = true;
39
+ continue;
40
+ }
41
+ if (a === "--bootstrap") {
42
+ out.bootstrap = true;
43
+ continue;
44
+ }
45
+ if (a === "--data-dir") {
46
+ const value = argv[i + 1];
47
+ if (!value) throw new Error("--data-dir requires a value");
48
+ out.dataDir = String(value);
49
+ i += 1;
50
+ continue;
51
+ }
52
+ if (a === "--report") {
53
+ const value = argv[i + 1];
54
+ if (!value) throw new Error("--report requires a value");
55
+ out.reportPath = String(value);
56
+ i += 1;
57
+ continue;
58
+ }
59
+ if (a === "--keep-previous") {
60
+ const value = Number(argv[i + 1]);
61
+ if (!Number.isSafeInteger(value) || value < 0) throw new Error("--keep-previous must be a non-negative integer");
62
+ out.keepPrevious = value;
63
+ i += 1;
64
+ continue;
65
+ }
66
+ throw new Error(`unknown argument: ${a}`);
67
+ }
68
+ return out;
69
+ }
70
+
71
+ function normalizeKeyRow(row, { requirePrivate = false, fieldPath = "key" } = {}) {
72
+ if (!row || typeof row !== "object" || Array.isArray(row)) throw new Error(`${fieldPath} must be an object`);
73
+ const publicKeyPem = typeof row.publicKeyPem === "string" && row.publicKeyPem.trim() !== "" ? row.publicKeyPem : null;
74
+ if (!publicKeyPem) throw new Error(`${fieldPath}.publicKeyPem is required`);
75
+ const privateKeyPem = typeof row.privateKeyPem === "string" && row.privateKeyPem.trim() !== "" ? row.privateKeyPem : null;
76
+ if (requirePrivate && !privateKeyPem) throw new Error(`${fieldPath}.privateKeyPem is required`);
77
+ const derivedKeyId = keyIdFromPublicKeyPem(publicKeyPem);
78
+ const keyId = typeof row.keyId === "string" && row.keyId.trim() !== "" ? row.keyId.trim() : derivedKeyId;
79
+ if (keyId !== derivedKeyId) throw new Error(`${fieldPath}.keyId does not match publicKeyPem`);
80
+ return {
81
+ keyId,
82
+ publicKeyPem,
83
+ privateKeyPem,
84
+ rotatedAt: typeof row.rotatedAt === "string" && row.rotatedAt.trim() !== "" ? row.rotatedAt : null
85
+ };
86
+ }
87
+
88
+ function dedupePrevious(rows, { max = 2 } = {}) {
89
+ const out = [];
90
+ const seen = new Set();
91
+ for (const row of rows) {
92
+ if (!row || typeof row !== "object" || Array.isArray(row)) continue;
93
+ const normalized = normalizeKeyRow(row, { requirePrivate: false, fieldPath: "previous[]" });
94
+ if (seen.has(normalized.keyId)) continue;
95
+ seen.add(normalized.keyId);
96
+ out.push({
97
+ keyId: normalized.keyId,
98
+ publicKeyPem: normalized.publicKeyPem,
99
+ rotatedAt: normalized.rotatedAt
100
+ });
101
+ if (out.length >= max) break;
102
+ }
103
+ return out;
104
+ }
105
+
106
+ async function readJsonFileSafe(filePath) {
107
+ if (!fs.existsSync(filePath)) return null;
108
+ const raw = await readFile(filePath, "utf8");
109
+ return JSON.parse(raw);
110
+ }
111
+
112
+ async function loadSignerMaterial({ dataDir }) {
113
+ const keysetStorePath = path.join(dataDir, SETTLD_PAY_KEYSET_STORE_FILENAME);
114
+ const signerPath = path.join(dataDir, SERVER_SIGNER_FILENAME);
115
+ const keysetStore = await readJsonFileSafe(keysetStorePath);
116
+ if (keysetStore) {
117
+ const active = normalizeKeyRow(keysetStore.active, { requirePrivate: true, fieldPath: "active" });
118
+ const previous = Array.isArray(keysetStore.previous)
119
+ ? keysetStore.previous.map((row, idx) => normalizeKeyRow(row, { requirePrivate: false, fieldPath: `previous[${idx}]` }))
120
+ : [];
121
+ return {
122
+ source: "keyset-store",
123
+ active,
124
+ previous
125
+ };
126
+ }
127
+
128
+ const signer = await readJsonFileSafe(signerPath);
129
+ if (signer) {
130
+ const active = normalizeKeyRow(signer, { requirePrivate: true, fieldPath: "server-signer" });
131
+ return { source: "legacy-signer", active, previous: [] };
132
+ }
133
+
134
+ return null;
135
+ }
136
+
137
+ function buildProviderNotificationSnippet({
138
+ keysetUrl = "https://<your-settld-host>/.well-known/settld-keys.json",
139
+ newKeyId,
140
+ previousKeyIds,
141
+ overlapRecommendation
142
+ } = {}) {
143
+ const previous = Array.isArray(previousKeyIds) && previousKeyIds.length > 0 ? previousKeyIds.join(", ") : "none";
144
+ return [
145
+ "Subject: SettldPay signing key rotation notice",
146
+ "",
147
+ `Settld has rotated its SettldPay signing key.`,
148
+ `- New active kid: ${newKeyId}`,
149
+ `- Previous kids still published: ${previous}`,
150
+ `- Keyset URL: ${keysetUrl}`,
151
+ "",
152
+ "Action requested:",
153
+ "1. Keep verifying tokens by resolving kid from the keyset URL.",
154
+ "2. Refresh cached keyset according to Cache-Control (or immediately if pinned).",
155
+ `3. Do not remove previously cached keys before overlap window ends (${overlapRecommendation}).`
156
+ ].join("\n");
157
+ }
158
+
159
+ async function main() {
160
+ let args;
161
+ try {
162
+ args = parseArgs(process.argv.slice(2));
163
+ } catch (err) {
164
+ process.stderr.write(`${err?.message ?? String(err)}\n\n${usage()}\n`);
165
+ process.exitCode = 1;
166
+ return;
167
+ }
168
+ if (args.help) {
169
+ process.stdout.write(usage() + "\n");
170
+ return;
171
+ }
172
+
173
+ const dataDir = path.resolve(process.cwd(), args.dataDir);
174
+ await mkdir(dataDir, { recursive: true });
175
+
176
+ const existing = await loadSignerMaterial({ dataDir });
177
+ if (!existing && !args.bootstrap) {
178
+ throw new Error(
179
+ `no existing signer found in ${dataDir}; rerun with --bootstrap to create the initial signer and keyset store`
180
+ );
181
+ }
182
+
183
+ const nowIso = new Date().toISOString();
184
+ const newKeypair = createEd25519Keypair();
185
+ const newKeyId = keyIdFromPublicKeyPem(newKeypair.publicKeyPem);
186
+ const oldActive = existing?.active ?? null;
187
+
188
+ const previousRows = dedupePrevious(
189
+ [
190
+ ...(oldActive
191
+ ? [
192
+ {
193
+ keyId: oldActive.keyId,
194
+ publicKeyPem: oldActive.publicKeyPem,
195
+ rotatedAt: nowIso
196
+ }
197
+ ]
198
+ : []),
199
+ ...(existing?.previous ?? [])
200
+ ],
201
+ { max: args.keepPrevious }
202
+ );
203
+
204
+ const keysetStore = {
205
+ schemaVersion: "SettldPayKeysetStore.v1",
206
+ updatedAt: nowIso,
207
+ active: {
208
+ keyId: newKeyId,
209
+ publicKeyPem: newKeypair.publicKeyPem,
210
+ privateKeyPem: newKeypair.privateKeyPem,
211
+ rotatedFromKeyId: oldActive?.keyId ?? null
212
+ },
213
+ previous: previousRows
214
+ };
215
+
216
+ const signerCompat = {
217
+ publicKeyPem: newKeypair.publicKeyPem,
218
+ privateKeyPem: newKeypair.privateKeyPem
219
+ };
220
+
221
+ const keysetStorePath = path.join(dataDir, SETTLD_PAY_KEYSET_STORE_FILENAME);
222
+ const signerPath = path.join(dataDir, SERVER_SIGNER_FILENAME);
223
+ await writeFile(keysetStorePath, JSON.stringify(keysetStore, null, 2) + "\n", "utf8");
224
+ await writeFile(signerPath, JSON.stringify(signerCompat, null, 2) + "\n", "utf8");
225
+
226
+ const servedKeyset = buildSettldPayKeysetV1({
227
+ activeKey: { keyId: newKeyId, publicKeyPem: newKeypair.publicKeyPem },
228
+ fallbackKeys: previousRows.map((row) => ({ keyId: row.keyId, publicKeyPem: row.publicKeyPem })),
229
+ refreshedAt: nowIso
230
+ });
231
+ const activeJwksEntry = Array.isArray(servedKeyset.keys) ? servedKeyset.keys.find((row) => row.kid === newKeyId) : null;
232
+ const notification = buildProviderNotificationSnippet({
233
+ newKeyId,
234
+ previousKeyIds: previousRows.map((row) => row.keyId),
235
+ overlapRecommendation: "token TTL + cache max-age safety margin"
236
+ });
237
+
238
+ const report = {
239
+ schemaVersion: "SettldPayKeyRotationReport.v1",
240
+ rotatedAt: nowIso,
241
+ dataDir,
242
+ source: existing?.source ?? "bootstrap",
243
+ oldActiveKeyId: oldActive?.keyId ?? null,
244
+ newActiveKeyId: newKeyId,
245
+ previousKeyIds: previousRows.map((row) => row.keyId),
246
+ files: {
247
+ keysetStorePath,
248
+ signerCompatPath: signerPath
249
+ },
250
+ servedKeyset
251
+ };
252
+
253
+ if (args.reportPath) {
254
+ const reportPath = path.resolve(process.cwd(), args.reportPath);
255
+ await mkdir(path.dirname(reportPath), { recursive: true });
256
+ await writeFile(reportPath, JSON.stringify(report, null, 2) + "\n", "utf8");
257
+ report.reportPath = reportPath;
258
+ }
259
+
260
+ process.stdout.write(`rotated_at=${nowIso}\n`);
261
+ process.stdout.write(`data_dir=${dataDir}\n`);
262
+ process.stdout.write(`old_active_kid=${oldActive?.keyId ?? "none"}\n`);
263
+ process.stdout.write(`new_active_kid=${newKeyId}\n`);
264
+ process.stdout.write(`previous_kids=${previousRows.map((row) => row.keyId).join(",") || "none"}\n`);
265
+ process.stdout.write("\nJWKS active entry:\n");
266
+ process.stdout.write(JSON.stringify(activeJwksEntry ?? null, null, 2) + "\n");
267
+ process.stdout.write("\nProvider notification snippet:\n");
268
+ process.stdout.write(notification + "\n");
269
+ if (report.reportPath) {
270
+ process.stdout.write(`\nrotation_report=${report.reportPath}\n`);
271
+ }
272
+ }
273
+
274
+ main().catch((err) => {
275
+ process.stderr.write(`${err?.stack ?? err?.message ?? String(err)}\n`);
276
+ process.exitCode = 1;
277
+ });
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs/promises";
3
+
4
+ import {
5
+ SLA_POLICY_TEMPLATE_CATALOG_VERSION,
6
+ getSlaPolicyTemplate,
7
+ listSlaPolicyTemplates,
8
+ renderSlaPolicyTemplate
9
+ } from "../../src/core/sla-policy-templates.js";
10
+
11
+ function usage() {
12
+ const text = [
13
+ "usage:",
14
+ " node scripts/trust-config/wizard.mjs list [--vertical delivery|security] [--format json|text]",
15
+ " node scripts/trust-config/wizard.mjs show --template <templateId> [--format json|text]",
16
+ " node scripts/trust-config/wizard.mjs render --template <templateId> [--overrides-json <json>] [--out <path>] [--format json|text]",
17
+ " node scripts/trust-config/wizard.mjs validate --template <templateId> [--overrides-json <json>] [--format json|text]"
18
+ ].join("\n");
19
+ process.stderr.write(text + "\n");
20
+ }
21
+
22
+ function parseArgs(argv) {
23
+ const out = {
24
+ command: argv[0] ?? null,
25
+ templateId: null,
26
+ vertical: null,
27
+ overridesJson: null,
28
+ outPath: null,
29
+ format: "json"
30
+ };
31
+ for (let i = 1; i < argv.length; i += 1) {
32
+ const arg = argv[i];
33
+ if (arg === "--template") {
34
+ out.templateId = String(argv[i + 1] ?? "");
35
+ i += 1;
36
+ continue;
37
+ }
38
+ if (arg === "--vertical") {
39
+ out.vertical = String(argv[i + 1] ?? "");
40
+ i += 1;
41
+ continue;
42
+ }
43
+ if (arg === "--overrides-json") {
44
+ out.overridesJson = String(argv[i + 1] ?? "");
45
+ i += 1;
46
+ continue;
47
+ }
48
+ if (arg === "--out") {
49
+ out.outPath = String(argv[i + 1] ?? "");
50
+ i += 1;
51
+ continue;
52
+ }
53
+ if (arg === "--format") {
54
+ out.format = String(argv[i + 1] ?? "").trim().toLowerCase();
55
+ i += 1;
56
+ continue;
57
+ }
58
+ if (arg === "--help" || arg === "-h") {
59
+ usage();
60
+ process.exit(0);
61
+ }
62
+ throw new Error(`unknown argument: ${arg}`);
63
+ }
64
+ if (!out.command) throw new Error("command is required");
65
+ if (out.format !== "json" && out.format !== "text") throw new Error("format must be json or text");
66
+ return out;
67
+ }
68
+
69
+ function parseOverrides(overridesJson) {
70
+ if (!overridesJson || !String(overridesJson).trim()) return null;
71
+ try {
72
+ return JSON.parse(String(overridesJson));
73
+ } catch (err) {
74
+ throw new Error(`invalid --overrides-json: ${err?.message ?? "parse failed"}`);
75
+ }
76
+ }
77
+
78
+ function renderTextList(templates) {
79
+ const lines = [];
80
+ for (const template of templates) {
81
+ lines.push(`${template.templateId}\t${template.vertical}\t${template.name}`);
82
+ }
83
+ return lines.join("\n") + (lines.length ? "\n" : "");
84
+ }
85
+
86
+ function renderTextShow(template) {
87
+ return [
88
+ `templateId: ${template.templateId}`,
89
+ `vertical: ${template.vertical}`,
90
+ `name: ${template.name}`,
91
+ `description: ${template.description}`
92
+ ].join("\n") + "\n";
93
+ }
94
+
95
+ async function output({ format, payload, text, outPath }) {
96
+ const body = format === "json" ? JSON.stringify(payload, null, 2) + "\n" : text;
97
+ if (outPath) {
98
+ await fs.writeFile(outPath, body, "utf8");
99
+ return;
100
+ }
101
+ process.stdout.write(body);
102
+ }
103
+
104
+ async function main() {
105
+ let parsed;
106
+ try {
107
+ parsed = parseArgs(process.argv.slice(2));
108
+ } catch (err) {
109
+ usage();
110
+ process.stderr.write(`${err?.message ?? "invalid arguments"}\n`);
111
+ process.exit(2);
112
+ }
113
+
114
+ const overrides = parseOverrides(parsed.overridesJson);
115
+
116
+ if (parsed.command === "list") {
117
+ const templates = listSlaPolicyTemplates({ vertical: parsed.vertical });
118
+ const payload = { schemaVersion: SLA_POLICY_TEMPLATE_CATALOG_VERSION, templates };
119
+ await output({ format: parsed.format, payload, text: renderTextList(templates), outPath: parsed.outPath });
120
+ return;
121
+ }
122
+
123
+ if (parsed.command === "show") {
124
+ if (!parsed.templateId) throw new Error("--template is required for show");
125
+ const template = getSlaPolicyTemplate({ templateId: parsed.templateId });
126
+ if (!template) throw new Error("template not found");
127
+ await output({ format: parsed.format, payload: template, text: renderTextShow(template), outPath: parsed.outPath });
128
+ return;
129
+ }
130
+
131
+ if (parsed.command === "render") {
132
+ if (!parsed.templateId) throw new Error("--template is required for render");
133
+ const rendered = renderSlaPolicyTemplate({ templateId: parsed.templateId, overrides });
134
+ if (!rendered) throw new Error("template not found");
135
+ const payload = {
136
+ schemaVersion: "SettldTrustWizardOutput.v1",
137
+ templateId: rendered.templateId,
138
+ config: rendered.defaults
139
+ };
140
+ const text = JSON.stringify(payload.config, null, 2) + "\n";
141
+ await output({ format: parsed.format, payload, text, outPath: parsed.outPath });
142
+ return;
143
+ }
144
+
145
+ if (parsed.command === "validate") {
146
+ if (!parsed.templateId) throw new Error("--template is required for validate");
147
+ const rendered = renderSlaPolicyTemplate({ templateId: parsed.templateId, overrides });
148
+ if (!rendered) throw new Error("template not found");
149
+ const payload = { ok: true, templateId: rendered.templateId };
150
+ const text = "ok\n";
151
+ await output({ format: parsed.format, payload, text, outPath: parsed.outPath });
152
+ return;
153
+ }
154
+
155
+ throw new Error(`unsupported command: ${parsed.command}`);
156
+ }
157
+
158
+ main().catch((err) => {
159
+ process.stderr.write(`${err?.message ?? "error"}\n`);
160
+ process.exit(1);
161
+ });