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,322 @@
1
+ import { canonicalJsonStringify, normalizeForCanonicalJson } from "./canonical-json.js";
2
+ import { sha256Hex, signHashHexEd25519 } from "./crypto.js";
3
+
4
+ export const POLICY_DECISION_SCHEMA_VERSION = "PolicyDecision.v1";
5
+ export const POLICY_DECISION_FINGERPRINT_VERSION = "PolicyDecisionFingerprint.v1";
6
+ export const POLICY_DECISION_EVALUATION_INPUT_SCHEMA_VERSION = "PolicyDecisionEvaluationInput.v1";
7
+
8
+ function assertPlainObject(value, name) {
9
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError(`${name} must be an object`);
10
+ if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
11
+ throw new TypeError(`${name} must be a plain object`);
12
+ }
13
+ }
14
+
15
+ function assertNonEmptyString(value, name) {
16
+ if (typeof value !== "string" || value.trim() === "") throw new TypeError(`${name} must be a non-empty string`);
17
+ return String(value).trim();
18
+ }
19
+
20
+ function assertIsoDate(value, name) {
21
+ const out = assertNonEmptyString(value, name);
22
+ if (!Number.isFinite(Date.parse(out))) throw new TypeError(`${name} must be an ISO date string`);
23
+ return new Date(Date.parse(out)).toISOString();
24
+ }
25
+
26
+ function normalizeId(value, name, { min = 1, max = 200 } = {}) {
27
+ const out = assertNonEmptyString(value, name);
28
+ if (out.length < min || out.length > max) throw new TypeError(`${name} must be length ${min}..${max}`);
29
+ if (!/^[A-Za-z0-9:_-]+$/.test(out)) throw new TypeError(`${name} must match ^[A-Za-z0-9:_-]+$`);
30
+ return out;
31
+ }
32
+
33
+ function normalizeOptionalPolicyId(value) {
34
+ if (value === null || value === undefined) return null;
35
+ const out = String(value).trim();
36
+ if (!out) return null;
37
+ if (!/^[A-Za-z0-9._:-]{1,128}$/.test(out)) return null;
38
+ return out;
39
+ }
40
+
41
+ function normalizeSha256(value, name, { allowNull = false } = {}) {
42
+ if (value === null || value === undefined || value === "") {
43
+ if (allowNull) return null;
44
+ throw new TypeError(`${name} is required`);
45
+ }
46
+ if (typeof value !== "string") throw new TypeError(`${name} must be a 64-hex sha256`);
47
+ const out = value.trim().toLowerCase();
48
+ if (!/^[0-9a-f]{64}$/.test(out)) throw new TypeError(`${name} must be a 64-hex sha256`);
49
+ return out;
50
+ }
51
+
52
+ function normalizeSha256OrNull(value) {
53
+ if (typeof value !== "string") return null;
54
+ const out = value.trim().toLowerCase();
55
+ if (!/^[0-9a-f]{64}$/.test(out)) return null;
56
+ return out;
57
+ }
58
+
59
+ function normalizeSafeIntOrNull(value, { min = 0, max = Number.MAX_SAFE_INTEGER } = {}) {
60
+ if (value === null || value === undefined || value === "") return null;
61
+ const n = Number(value);
62
+ if (!Number.isSafeInteger(n) || n < min || n > max) return null;
63
+ return n;
64
+ }
65
+
66
+ function normalizeDecisionMode(value, name) {
67
+ const out = assertNonEmptyString(value, name).toLowerCase();
68
+ if (out !== "automatic" && out !== "manual-review") {
69
+ throw new TypeError(`${name} must be automatic|manual-review`);
70
+ }
71
+ return out;
72
+ }
73
+
74
+ function normalizeLowerToken(value, name, { max = 64 } = {}) {
75
+ const out = assertNonEmptyString(value, name).toLowerCase();
76
+ if (out.length > max) throw new TypeError(`${name} must be <= ${max} chars`);
77
+ if (!/^[a-z0-9_-]+$/.test(out)) throw new TypeError(`${name} must match ^[a-z0-9_-]+$`);
78
+ return out;
79
+ }
80
+
81
+ export function normalizeReasonCodes(value, name = "reasonCodes") {
82
+ const items = Array.isArray(value) ? value : [];
83
+ const out = [];
84
+ const seen = new Set();
85
+ for (const item of items) {
86
+ if (typeof item !== "string") continue;
87
+ const code = item.trim();
88
+ if (!code) continue;
89
+ if (code.length > 128) throw new TypeError(`${name} entries must be <= 128 chars`);
90
+ if (!/^[A-Za-z0-9._:-]+$/.test(code)) throw new TypeError(`${name} entries must match ^[A-Za-z0-9._:-]+$`);
91
+ if (seen.has(code)) continue;
92
+ seen.add(code);
93
+ out.push(code);
94
+ }
95
+ out.sort((left, right) => left.localeCompare(right));
96
+ return out;
97
+ }
98
+
99
+ export function computePolicyDecisionEvaluationHashV1({
100
+ policyHashUsed = null,
101
+ verificationMethodHashUsed = null,
102
+ policyDecision = null
103
+ } = {}) {
104
+ const payload = normalizeForCanonicalJson(
105
+ {
106
+ schemaVersion: POLICY_DECISION_EVALUATION_INPUT_SCHEMA_VERSION,
107
+ policyHash: normalizeSha256OrNull(policyHashUsed),
108
+ verificationMethodHash: normalizeSha256OrNull(verificationMethodHashUsed),
109
+ verificationStatus: typeof policyDecision?.verificationStatus === "string" ? policyDecision.verificationStatus.trim().toLowerCase() : null,
110
+ runStatus: typeof policyDecision?.runStatus === "string" ? policyDecision.runStatus.trim().toLowerCase() : null,
111
+ shouldAutoResolve: policyDecision?.shouldAutoResolve === true,
112
+ releaseRatePct: normalizeSafeIntOrNull(policyDecision?.releaseRatePct, { min: 0, max: 100 }),
113
+ releaseAmountCents: normalizeSafeIntOrNull(policyDecision?.releaseAmountCents, { min: 0 }),
114
+ refundAmountCents: normalizeSafeIntOrNull(policyDecision?.refundAmountCents, { min: 0 }),
115
+ settlementStatus: typeof policyDecision?.settlementStatus === "string" ? policyDecision.settlementStatus.trim().toLowerCase() : null,
116
+ reasons: normalizeReasonCodes(policyDecision?.reasonCodes)
117
+ },
118
+ { path: "$" }
119
+ );
120
+ return sha256Hex(canonicalJsonStringify(payload));
121
+ }
122
+
123
+ export function buildPolicyDecisionFingerprintV1({
124
+ policyInput = null,
125
+ policyHashUsed = null,
126
+ verificationMethodHashUsed = null,
127
+ policyDecision = null
128
+ } = {}) {
129
+ const rawPolicy = policyInput && typeof policyInput === "object" && !Array.isArray(policyInput) ? policyInput : {};
130
+ const policyVersion =
131
+ normalizeSafeIntOrNull(policyDecision?.policy?.policyVersion, { min: 1 }) ??
132
+ normalizeSafeIntOrNull(rawPolicy.policyVersion, { min: 1 }) ??
133
+ null;
134
+ const policyId = normalizeOptionalPolicyId(rawPolicy.policyId) ?? normalizeOptionalPolicyId(rawPolicy.id);
135
+ const normalizedPolicyHash = normalizeSha256OrNull(policyHashUsed);
136
+ const normalizedVerificationMethodHash = normalizeSha256OrNull(verificationMethodHashUsed);
137
+ return normalizeForCanonicalJson(
138
+ {
139
+ fingerprintVersion: POLICY_DECISION_FINGERPRINT_VERSION,
140
+ policyId,
141
+ policyVersion,
142
+ policyHash: normalizedPolicyHash,
143
+ verificationMethodHash: normalizedVerificationMethodHash,
144
+ evaluationHash: computePolicyDecisionEvaluationHashV1({
145
+ policyHashUsed: normalizedPolicyHash,
146
+ verificationMethodHashUsed: normalizedVerificationMethodHash,
147
+ policyDecision
148
+ })
149
+ },
150
+ { path: "$" }
151
+ );
152
+ }
153
+
154
+ export function computePolicyDecisionHashV1(policyDecisionCore) {
155
+ assertPlainObject(policyDecisionCore, "policyDecisionCore");
156
+ const copy = { ...policyDecisionCore };
157
+ delete copy.policyDecisionHash;
158
+ delete copy.signature;
159
+ const normalized = normalizeForCanonicalJson(copy, { path: "$" });
160
+ return sha256Hex(canonicalJsonStringify(normalized));
161
+ }
162
+
163
+ export function buildPolicyDecisionV1({
164
+ decisionId,
165
+ tenantId,
166
+ runId,
167
+ settlementId,
168
+ gateId = null,
169
+ policyInput = null,
170
+ policyHashUsed = null,
171
+ verificationMethodHashUsed = null,
172
+ policyDecision = null,
173
+ reasonCodes = null,
174
+ metadata = undefined,
175
+ createdAt = new Date().toISOString(),
176
+ requireSignature = false,
177
+ signerKeyId = null,
178
+ signerPrivateKeyPem = null
179
+ } = {}) {
180
+ const rawPolicy = policyInput && typeof policyInput === "object" && !Array.isArray(policyInput) ? policyInput : {};
181
+ const normalizedPolicyHash = normalizeSha256(policyHashUsed, "policyHashUsed", { allowNull: false });
182
+ const normalizedVerificationMethodHash = normalizeSha256(verificationMethodHashUsed, "verificationMethodHashUsed", {
183
+ allowNull: false
184
+ });
185
+ const normalizedPolicyVersion =
186
+ normalizeSafeIntOrNull(policyDecision?.policy?.policyVersion, { min: 1 }) ??
187
+ normalizeSafeIntOrNull(rawPolicy.policyVersion, { min: 1 }) ??
188
+ null;
189
+ const normalizedPolicyId = normalizeOptionalPolicyId(rawPolicy.policyId) ?? normalizeOptionalPolicyId(rawPolicy.id);
190
+ const normalizedReasonCodes = normalizeReasonCodes(reasonCodes ?? policyDecision?.reasonCodes);
191
+ const createdAtIso = assertIsoDate(createdAt, "createdAt");
192
+ const normalized = normalizeForCanonicalJson(
193
+ {
194
+ schemaVersion: POLICY_DECISION_SCHEMA_VERSION,
195
+ decisionId: normalizeId(decisionId, "decisionId", { min: 1, max: 240 }),
196
+ tenantId: normalizeId(tenantId, "tenantId", { min: 1, max: 128 }),
197
+ runId: normalizeId(runId, "runId", { min: 1, max: 128 }),
198
+ settlementId: normalizeId(settlementId, "settlementId", { min: 1, max: 200 }),
199
+ ...(gateId === null || gateId === undefined ? {} : { gateId: normalizeId(gateId, "gateId", { min: 1, max: 240 }) }),
200
+ policyRef: {
201
+ policyId: normalizedPolicyId,
202
+ policyVersion: normalizedPolicyVersion,
203
+ policyHash: normalizedPolicyHash,
204
+ verificationMethodHash: normalizedVerificationMethodHash
205
+ },
206
+ decisionMode: normalizeDecisionMode(policyDecision?.decisionMode, "policyDecision.decisionMode"),
207
+ verificationStatus: normalizeLowerToken(policyDecision?.verificationStatus, "policyDecision.verificationStatus", { max: 32 }),
208
+ runStatus: normalizeLowerToken(policyDecision?.runStatus, "policyDecision.runStatus", { max: 32 }),
209
+ shouldAutoResolve: policyDecision?.shouldAutoResolve === true,
210
+ settlementStatus: normalizeLowerToken(policyDecision?.settlementStatus, "policyDecision.settlementStatus"),
211
+ releaseRatePct: normalizeSafeIntOrNull(policyDecision?.releaseRatePct, { min: 0, max: 100 }) ?? 0,
212
+ releaseAmountCents: normalizeSafeIntOrNull(policyDecision?.releaseAmountCents, { min: 0 }) ?? 0,
213
+ refundAmountCents: normalizeSafeIntOrNull(policyDecision?.refundAmountCents, { min: 0 }) ?? 0,
214
+ reasonCodes: normalizedReasonCodes,
215
+ evaluationHash: computePolicyDecisionEvaluationHashV1({
216
+ policyHashUsed: normalizedPolicyHash,
217
+ verificationMethodHashUsed: normalizedVerificationMethodHash,
218
+ policyDecision: {
219
+ ...policyDecision,
220
+ reasonCodes: normalizedReasonCodes
221
+ }
222
+ }),
223
+ createdAt: createdAtIso,
224
+ ...(metadata && typeof metadata === "object" && !Array.isArray(metadata)
225
+ ? { metadata: normalizeForCanonicalJson(metadata, { path: "$.metadata" }) }
226
+ : {})
227
+ },
228
+ { path: "$" }
229
+ );
230
+ const policyDecisionHash = computePolicyDecisionHashV1(normalized);
231
+
232
+ const signerKeyIdText = signerKeyId === null || signerKeyId === undefined ? "" : String(signerKeyId).trim();
233
+ const signerPrivateKeyText = signerPrivateKeyPem === null || signerPrivateKeyPem === undefined ? "" : String(signerPrivateKeyPem).trim();
234
+ if (requireSignature === true && (!signerKeyIdText || !signerPrivateKeyText)) {
235
+ throw new TypeError("policy decision signature is required");
236
+ }
237
+ if (signerKeyIdText && !signerPrivateKeyText) {
238
+ throw new TypeError("signerPrivateKeyPem is required when signerKeyId is provided");
239
+ }
240
+
241
+ let signature = null;
242
+ if (signerPrivateKeyText) {
243
+ const keyId = normalizeId(signerKeyIdText, "signerKeyId", { min: 1, max: 256 });
244
+ signature = {
245
+ algorithm: "ed25519",
246
+ signerKeyId: keyId,
247
+ policyDecisionHash,
248
+ signature: signHashHexEd25519(policyDecisionHash, signerPrivateKeyText)
249
+ };
250
+ }
251
+
252
+ return normalizeForCanonicalJson({ ...normalized, policyDecisionHash, ...(signature ? { signature } : {}) }, { path: "$" });
253
+ }
254
+
255
+ export function validatePolicyDecisionV1(policyDecision) {
256
+ assertPlainObject(policyDecision, "policyDecision");
257
+ if (policyDecision.schemaVersion !== POLICY_DECISION_SCHEMA_VERSION) {
258
+ throw new TypeError(`policyDecision.schemaVersion must be ${POLICY_DECISION_SCHEMA_VERSION}`);
259
+ }
260
+ normalizeId(policyDecision.decisionId, "policyDecision.decisionId", { min: 1, max: 240 });
261
+ normalizeId(policyDecision.tenantId, "policyDecision.tenantId", { min: 1, max: 128 });
262
+ normalizeId(policyDecision.runId, "policyDecision.runId", { min: 1, max: 128 });
263
+ normalizeId(policyDecision.settlementId, "policyDecision.settlementId", { min: 1, max: 200 });
264
+ if (Object.prototype.hasOwnProperty.call(policyDecision, "gateId")) {
265
+ if (policyDecision.gateId !== null && policyDecision.gateId !== undefined) {
266
+ normalizeId(policyDecision.gateId, "policyDecision.gateId", { min: 1, max: 240 });
267
+ }
268
+ }
269
+ assertPlainObject(policyDecision.policyRef, "policyDecision.policyRef");
270
+ if (Object.prototype.hasOwnProperty.call(policyDecision.policyRef, "policyId")) {
271
+ const policyId = normalizeOptionalPolicyId(policyDecision.policyRef.policyId);
272
+ if (policyDecision.policyRef.policyId !== null && policyId === null) {
273
+ throw new TypeError("policyDecision.policyRef.policyId must match ^[A-Za-z0-9._:-]{1,128}$ when present");
274
+ }
275
+ }
276
+ if (Object.prototype.hasOwnProperty.call(policyDecision.policyRef, "policyVersion")) {
277
+ const policyVersion = policyDecision.policyRef.policyVersion;
278
+ if (policyVersion !== null && normalizeSafeIntOrNull(policyVersion, { min: 1 }) === null) {
279
+ throw new TypeError("policyDecision.policyRef.policyVersion must be a positive safe integer or null");
280
+ }
281
+ }
282
+ normalizeSha256(policyDecision.policyRef.policyHash, "policyDecision.policyRef.policyHash", { allowNull: false });
283
+ normalizeSha256(policyDecision.policyRef.verificationMethodHash, "policyDecision.policyRef.verificationMethodHash", { allowNull: false });
284
+
285
+ normalizeDecisionMode(policyDecision.decisionMode, "policyDecision.decisionMode");
286
+ normalizeLowerToken(policyDecision.verificationStatus, "policyDecision.verificationStatus", { max: 32 });
287
+ normalizeLowerToken(policyDecision.runStatus, "policyDecision.runStatus", { max: 32 });
288
+ if (typeof policyDecision.shouldAutoResolve !== "boolean") {
289
+ throw new TypeError("policyDecision.shouldAutoResolve must be a boolean");
290
+ }
291
+ normalizeLowerToken(policyDecision.settlementStatus, "policyDecision.settlementStatus");
292
+ if (normalizeSafeIntOrNull(policyDecision.releaseRatePct, { min: 0, max: 100 }) === null) {
293
+ throw new TypeError("policyDecision.releaseRatePct must be an integer in range 0..100");
294
+ }
295
+ if (normalizeSafeIntOrNull(policyDecision.releaseAmountCents, { min: 0 }) === null) {
296
+ throw new TypeError("policyDecision.releaseAmountCents must be a non-negative safe integer");
297
+ }
298
+ if (normalizeSafeIntOrNull(policyDecision.refundAmountCents, { min: 0 }) === null) {
299
+ throw new TypeError("policyDecision.refundAmountCents must be a non-negative safe integer");
300
+ }
301
+ normalizeReasonCodes(policyDecision.reasonCodes, "policyDecision.reasonCodes");
302
+ normalizeSha256(policyDecision.evaluationHash, "policyDecision.evaluationHash", { allowNull: false });
303
+ assertIsoDate(policyDecision.createdAt, "policyDecision.createdAt");
304
+
305
+ const policyDecisionHash = normalizeSha256(policyDecision.policyDecisionHash, "policyDecision.policyDecisionHash", {
306
+ allowNull: false
307
+ });
308
+ const computedHash = computePolicyDecisionHashV1(policyDecision);
309
+ if (computedHash !== policyDecisionHash) throw new TypeError("policyDecisionHash mismatch");
310
+
311
+ if (Object.prototype.hasOwnProperty.call(policyDecision, "signature") && policyDecision.signature !== null && policyDecision.signature !== undefined) {
312
+ const sig = policyDecision.signature;
313
+ assertPlainObject(sig, "policyDecision.signature");
314
+ if (sig.algorithm !== "ed25519") throw new TypeError("policyDecision.signature.algorithm must be ed25519");
315
+ normalizeId(sig.signerKeyId, "policyDecision.signature.signerKeyId", { min: 1, max: 256 });
316
+ const signatureHash = normalizeSha256(sig.policyDecisionHash, "policyDecision.signature.policyDecisionHash", { allowNull: false });
317
+ if (signatureHash !== policyDecisionHash) throw new TypeError("policyDecision.signature.policyDecisionHash mismatch");
318
+ assertNonEmptyString(sig.signature, "policyDecision.signature.signature");
319
+ }
320
+
321
+ return true;
322
+ }
@@ -0,0 +1,207 @@
1
+ export const POLICY_PACK_SCHEMA_VERSION = "SettldPolicyPack.v1";
2
+ export const POLICY_PACK_TEMPLATE_CATALOG_VERSION = "SettldPolicyPackTemplateCatalog.v1";
3
+
4
+ const STARTER_POLICY_PACKS = Object.freeze([
5
+ Object.freeze({
6
+ packId: "engineering-spend",
7
+ metadata: Object.freeze({
8
+ name: "Engineering Spend Guardrails",
9
+ vertical: "engineering",
10
+ description: "Balanced defaults for software and AI tool spend with tiered approvals."
11
+ }),
12
+ policyDefaults: Object.freeze({
13
+ currency: "USD",
14
+ limits: Object.freeze({
15
+ perRequestUsdCents: 300_000,
16
+ monthlyUsdCents: 1_500_000
17
+ }),
18
+ allowlists: Object.freeze({
19
+ providers: Object.freeze(["anthropic", "aws", "openai"]),
20
+ tools: Object.freeze(["ci.compute", "llm.inference", "observability.logs"])
21
+ }),
22
+ approvals: Object.freeze([
23
+ Object.freeze({ tierId: "auto", maxAmountUsdCents: 50_000, requiredApprovers: 0, approverRole: "none" }),
24
+ Object.freeze({ tierId: "manager", maxAmountUsdCents: 150_000, requiredApprovers: 1, approverRole: "engineering_manager" }),
25
+ Object.freeze({ tierId: "director", maxAmountUsdCents: 300_000, requiredApprovers: 2, approverRole: "engineering_director" })
26
+ ]),
27
+ enforcement: Object.freeze({
28
+ enforceProviderAllowlist: true,
29
+ requireReceiptSignature: true,
30
+ requireToolManifestHash: true,
31
+ allowUnknownToolVersion: false
32
+ }),
33
+ disputeDefaults: Object.freeze({
34
+ responseWindowHours: 72,
35
+ autoOpenIfReceiptMissing: true,
36
+ evidenceChecklist: Object.freeze(["approval_log", "policy_trace", "receipt"])
37
+ })
38
+ })
39
+ }),
40
+ Object.freeze({
41
+ packId: "procurement-enterprise",
42
+ metadata: Object.freeze({
43
+ name: "Procurement Enterprise",
44
+ vertical: "procurement",
45
+ description: "Conservative purchasing controls for enterprise procurement teams."
46
+ }),
47
+ policyDefaults: Object.freeze({
48
+ currency: "USD",
49
+ limits: Object.freeze({
50
+ perRequestUsdCents: 500_000,
51
+ monthlyUsdCents: 4_000_000
52
+ }),
53
+ allowlists: Object.freeze({
54
+ providers: Object.freeze(["aws", "azure", "gcp", "stripe"]),
55
+ tools: Object.freeze(["data.warehouse", "erp.connector", "invoice.automation"])
56
+ }),
57
+ approvals: Object.freeze([
58
+ Object.freeze({ tierId: "analyst", maxAmountUsdCents: 100_000, requiredApprovers: 1, approverRole: "procurement_analyst" }),
59
+ Object.freeze({ tierId: "manager", maxAmountUsdCents: 300_000, requiredApprovers: 2, approverRole: "procurement_manager" }),
60
+ Object.freeze({ tierId: "director", maxAmountUsdCents: 500_000, requiredApprovers: 3, approverRole: "finance_director" })
61
+ ]),
62
+ enforcement: Object.freeze({
63
+ enforceProviderAllowlist: true,
64
+ requireReceiptSignature: true,
65
+ requireToolManifestHash: true,
66
+ allowUnknownToolVersion: false
67
+ }),
68
+ disputeDefaults: Object.freeze({
69
+ responseWindowHours: 96,
70
+ autoOpenIfReceiptMissing: true,
71
+ evidenceChecklist: Object.freeze(["approval_log", "purchase_order", "receipt", "vendor_contract"])
72
+ })
73
+ })
74
+ }),
75
+ Object.freeze({
76
+ packId: "data-api-buyer",
77
+ metadata: Object.freeze({
78
+ name: "Data API Buyer",
79
+ vertical: "data",
80
+ description: "Usage-metered API and data acquisition controls for product teams."
81
+ }),
82
+ policyDefaults: Object.freeze({
83
+ currency: "USD",
84
+ limits: Object.freeze({
85
+ perRequestUsdCents: 120_000,
86
+ monthlyUsdCents: 900_000
87
+ }),
88
+ allowlists: Object.freeze({
89
+ providers: Object.freeze(["exa", "openai", "serpapi"]),
90
+ tools: Object.freeze(["data.extract", "search.query", "summarize.batch"])
91
+ }),
92
+ approvals: Object.freeze([
93
+ Object.freeze({ tierId: "auto", maxAmountUsdCents: 25_000, requiredApprovers: 0, approverRole: "none" }),
94
+ Object.freeze({ tierId: "owner", maxAmountUsdCents: 80_000, requiredApprovers: 1, approverRole: "data_product_owner" }),
95
+ Object.freeze({ tierId: "exec", maxAmountUsdCents: 120_000, requiredApprovers: 2, approverRole: "business_owner" })
96
+ ]),
97
+ enforcement: Object.freeze({
98
+ enforceProviderAllowlist: true,
99
+ requireReceiptSignature: true,
100
+ requireToolManifestHash: true,
101
+ allowUnknownToolVersion: false
102
+ }),
103
+ disputeDefaults: Object.freeze({
104
+ responseWindowHours: 48,
105
+ autoOpenIfReceiptMissing: true,
106
+ evidenceChecklist: Object.freeze(["approval_log", "receipt", "usage_export"])
107
+ })
108
+ })
109
+ }),
110
+ Object.freeze({
111
+ packId: "support-automation",
112
+ metadata: Object.freeze({
113
+ name: "Support Automation",
114
+ vertical: "support",
115
+ description: "Fast-path support tooling policy with strict monthly caps and receipt evidence."
116
+ }),
117
+ policyDefaults: Object.freeze({
118
+ currency: "USD",
119
+ limits: Object.freeze({
120
+ perRequestUsdCents: 40_000,
121
+ monthlyUsdCents: 400_000
122
+ }),
123
+ allowlists: Object.freeze({
124
+ providers: Object.freeze(["openai", "zendesk"]),
125
+ tools: Object.freeze(["ticket.triage", "response.draft", "knowledge.search"])
126
+ }),
127
+ approvals: Object.freeze([
128
+ Object.freeze({ tierId: "auto", maxAmountUsdCents: 10_000, requiredApprovers: 0, approverRole: "none" }),
129
+ Object.freeze({ tierId: "lead", maxAmountUsdCents: 25_000, requiredApprovers: 1, approverRole: "support_lead" }),
130
+ Object.freeze({ tierId: "director", maxAmountUsdCents: 40_000, requiredApprovers: 2, approverRole: "support_director" })
131
+ ]),
132
+ enforcement: Object.freeze({
133
+ enforceProviderAllowlist: true,
134
+ requireReceiptSignature: true,
135
+ requireToolManifestHash: true,
136
+ allowUnknownToolVersion: false
137
+ }),
138
+ disputeDefaults: Object.freeze({
139
+ responseWindowHours: 48,
140
+ autoOpenIfReceiptMissing: true,
141
+ evidenceChecklist: Object.freeze(["approval_log", "receipt", "ticket_export"])
142
+ })
143
+ })
144
+ }),
145
+ Object.freeze({
146
+ packId: "finance-controls",
147
+ metadata: Object.freeze({
148
+ name: "Finance Controls",
149
+ vertical: "finance",
150
+ description: "Strict finance pack for settlement-sensitive workflows and audit controls."
151
+ }),
152
+ policyDefaults: Object.freeze({
153
+ currency: "USD",
154
+ limits: Object.freeze({
155
+ perRequestUsdCents: 750_000,
156
+ monthlyUsdCents: 7_500_000
157
+ }),
158
+ allowlists: Object.freeze({
159
+ providers: Object.freeze(["circle", "stripe", "treasury"]),
160
+ tools: Object.freeze(["ledger.posting", "payout.batch", "reconciliation.run"])
161
+ }),
162
+ approvals: Object.freeze([
163
+ Object.freeze({ tierId: "analyst", maxAmountUsdCents: 150_000, requiredApprovers: 1, approverRole: "finance_analyst" }),
164
+ Object.freeze({ tierId: "controller", maxAmountUsdCents: 400_000, requiredApprovers: 2, approverRole: "finance_controller" }),
165
+ Object.freeze({ tierId: "cfo", maxAmountUsdCents: 750_000, requiredApprovers: 3, approverRole: "cfo" })
166
+ ]),
167
+ enforcement: Object.freeze({
168
+ enforceProviderAllowlist: true,
169
+ requireReceiptSignature: true,
170
+ requireToolManifestHash: true,
171
+ allowUnknownToolVersion: false
172
+ }),
173
+ disputeDefaults: Object.freeze({
174
+ responseWindowHours: 120,
175
+ autoOpenIfReceiptMissing: true,
176
+ evidenceChecklist: Object.freeze(["approval_log", "receipt", "journal_export", "reconcile_report"])
177
+ })
178
+ })
179
+ })
180
+ ]);
181
+
182
+ function deepClone(value) {
183
+ if (value === null || value === undefined) return value;
184
+ return JSON.parse(JSON.stringify(value));
185
+ }
186
+
187
+ export function listPolicyPackTemplates() {
188
+ return STARTER_POLICY_PACKS.map((pack) => deepClone(pack));
189
+ }
190
+
191
+ export function getPolicyPackTemplate({ packId } = {}) {
192
+ const id = String(packId ?? "").trim();
193
+ if (!id) throw new TypeError("packId is required");
194
+ const pack = STARTER_POLICY_PACKS.find((item) => item.packId === id) ?? null;
195
+ return pack ? deepClone(pack) : null;
196
+ }
197
+
198
+ export function createStarterPolicyPack({ packId } = {}) {
199
+ const template = getPolicyPackTemplate({ packId });
200
+ if (!template) return null;
201
+ return {
202
+ schemaVersion: POLICY_PACK_SCHEMA_VERSION,
203
+ packId: template.packId,
204
+ metadata: template.metadata,
205
+ policy: template.policyDefaults
206
+ };
207
+ }
@@ -0,0 +1,27 @@
1
+ import { canonicalJsonStringify, normalizeForCanonicalJson } from "./canonical-json.js";
2
+ import { sha256Hex } from "./crypto.js";
3
+
4
+ export const PROFILE_FINGERPRINT_SCHEMA_VERSION = "SettldProfileFingerprint.v1";
5
+
6
+ function assertPlainObject(value, name) {
7
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
8
+ throw new TypeError(`${name} must be a plain object`);
9
+ }
10
+ const proto = Object.getPrototypeOf(value);
11
+ if (proto !== Object.prototype && proto !== null) {
12
+ throw new TypeError(`${name} must be a plain object`);
13
+ }
14
+ }
15
+
16
+ export function computeProfileFingerprint(profile) {
17
+ assertPlainObject(profile, "profile");
18
+ const canonicalProfile = normalizeForCanonicalJson(profile, { path: "$" });
19
+ const profileCanonicalJson = canonicalJsonStringify(canonicalProfile);
20
+ const profileFingerprint = sha256Hex(profileCanonicalJson);
21
+ return {
22
+ schemaVersion: PROFILE_FINGERPRINT_SCHEMA_VERSION,
23
+ profileId: typeof profile.profileId === "string" ? profile.profileId : null,
24
+ profileSchemaVersion: typeof profile.schemaVersion === "string" ? profile.schemaVersion : null,
25
+ profileFingerprint
26
+ };
27
+ }
@@ -0,0 +1,84 @@
1
+ export const PROFILE_SIMULATION_REASON_REGISTRY_VERSION = "SettldProfileSimulationReasonRegistry.v1";
2
+
3
+ const REASON_DEFINITIONS = Object.freeze({
4
+ provider_allowlisted: Object.freeze({
5
+ code: "PROFILE_PROVIDER_NOT_ALLOWLISTED",
6
+ severity: "error",
7
+ remediationHint: "Add the provider to policy.allowlists.providers or disable vendor allowlist enforcement."
8
+ }),
9
+ tool_allowlisted: Object.freeze({
10
+ code: "PROFILE_TOOL_NOT_ALLOWLISTED",
11
+ severity: "error",
12
+ remediationHint: "Add the tool to policy.allowlists.tools before allowing execution."
13
+ }),
14
+ per_request_limit: Object.freeze({
15
+ code: "PROFILE_PER_REQUEST_LIMIT_EXCEEDED",
16
+ severity: "error",
17
+ remediationHint: "Increase policy.limits.perRequestUsdCents or lower the requested amount."
18
+ }),
19
+ monthly_limit: Object.freeze({
20
+ code: "PROFILE_MONTHLY_LIMIT_EXCEEDED",
21
+ severity: "error",
22
+ remediationHint: "Increase policy.limits.monthlyUsdCents or wait for budget reset."
23
+ }),
24
+ receipt_signature: Object.freeze({
25
+ code: "PROFILE_RECEIPT_SIGNATURE_REQUIRED",
26
+ severity: "error",
27
+ remediationHint: "Require signed receipts from the provider or disable signature requirement."
28
+ }),
29
+ tool_manifest_hash: Object.freeze({
30
+ code: "PROFILE_TOOL_MANIFEST_HASH_REQUIRED",
31
+ severity: "error",
32
+ remediationHint: "Provide a tool manifest hash with the execution request."
33
+ }),
34
+ tool_version_known: Object.freeze({
35
+ code: "PROFILE_TOOL_VERSION_UNKNOWN",
36
+ severity: "error",
37
+ remediationHint: "Pin a known tool version or allow unknown versions in policy.compliance."
38
+ }),
39
+ approval_required: Object.freeze({
40
+ code: "PROFILE_APPROVAL_REQUIRED",
41
+ severity: "warning",
42
+ remediationHint: "Collect the required approvals for the selected amount tier."
43
+ })
44
+ });
45
+
46
+ function uniqueTrimmedReasonIds(reasonIds) {
47
+ const out = [];
48
+ const seen = new Set();
49
+ for (const reasonId of Array.isArray(reasonIds) ? reasonIds : []) {
50
+ if (typeof reasonId !== "string") continue;
51
+ const normalized = reasonId.trim();
52
+ if (!normalized || seen.has(normalized)) continue;
53
+ seen.add(normalized);
54
+ out.push(normalized);
55
+ }
56
+ return out;
57
+ }
58
+
59
+ export function listProfileSimulationReasonDefinitions() {
60
+ return Object.entries(REASON_DEFINITIONS).map(([checkId, value]) => ({
61
+ checkId,
62
+ code: value.code,
63
+ severity: value.severity,
64
+ remediationHint: value.remediationHint
65
+ }));
66
+ }
67
+
68
+ export function mapProfileSimulationReasons(reasonIds, { failOnUnknown = true } = {}) {
69
+ const resolved = [];
70
+ for (const reasonId of uniqueTrimmedReasonIds(reasonIds)) {
71
+ const entry = REASON_DEFINITIONS[reasonId];
72
+ if (!entry) {
73
+ if (failOnUnknown) throw new TypeError(`unknown profile simulation reason id: ${reasonId}`);
74
+ continue;
75
+ }
76
+ resolved.push({
77
+ checkId: reasonId,
78
+ code: entry.code,
79
+ severity: entry.severity,
80
+ remediationHint: entry.remediationHint
81
+ });
82
+ }
83
+ return resolved;
84
+ }