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,986 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import process from "node:process";
6
+ import { fileURLToPath, pathToFileURL } from "node:url";
7
+ import { createInterface } from "node:readline/promises";
8
+ import { spawn } from "node:child_process";
9
+
10
+ const MODE_OPTIONS = new Set(["local", "manual", "bootstrap"]);
11
+ const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url));
12
+ const REPO_ROOT = path.resolve(SCRIPT_DIR, "..", "..");
13
+ const DEFAULT_HOST_CONFIG_PATH = path.join(SCRIPT_DIR, "host-config.mjs");
14
+ const DEFAULT_PROFILE_ID = "engineering-spend";
15
+ const DEFAULT_SMOKE_TIMEOUT_MS = 30000;
16
+ const X402_AGENT_PASSPORT_SCHEMA_VERSION = "X402AgentPassport.v1";
17
+ const REF_VALUE_PATTERN = /^[A-Za-z0-9:_-]+$/;
18
+
19
+ function usage() {
20
+ const text = [
21
+ "usage:",
22
+ " node scripts/setup/wizard.mjs [--non-interactive] [--mode local|manual|bootstrap] [--host <name>] [--base-url <url>] [--tenant-id <id>] [--api-key <key>] [--magic-link-api-key <key>] [--bootstrap-key-id <id>] [--bootstrap-scopes <csv>] [--idempotency-key <key>] [--config-path <path>] [--dry-run] [--host-config <path>] [--profile-id <id>|--profile-file <path>|--skip-profile-apply] [--smoke] [--smoke-timeout-ms <ms>]"
23
+ ].join("\n");
24
+ process.stderr.write(text + "\n");
25
+ }
26
+
27
+ function readArgValue(argv, index, rawArg) {
28
+ const arg = String(rawArg ?? "");
29
+ const eq = arg.indexOf("=");
30
+ if (eq >= 0) return { value: arg.slice(eq + 1), nextIndex: index };
31
+ return { value: String(argv[index + 1] ?? ""), nextIndex: index + 1 };
32
+ }
33
+
34
+ export function parseArgs(argv) {
35
+ const out = {
36
+ mode: null,
37
+ host: null,
38
+ baseUrl: null,
39
+ tenantId: null,
40
+ apiKey: null,
41
+ magicLinkApiKey: null,
42
+ bootstrapKeyId: null,
43
+ bootstrapScopesRaw: null,
44
+ idempotencyKey: null,
45
+ configPath: null,
46
+ dryRun: false,
47
+ hostConfigPath: DEFAULT_HOST_CONFIG_PATH,
48
+ profileId: null,
49
+ profileFile: null,
50
+ skipProfileApply: false,
51
+ smoke: false,
52
+ smokeTimeoutMs: DEFAULT_SMOKE_TIMEOUT_MS,
53
+ nonInteractive: false,
54
+ help: false
55
+ };
56
+
57
+ for (let i = 0; i < argv.length; i += 1) {
58
+ const arg = String(argv[i] ?? "");
59
+ if (arg === "--help" || arg === "-h") {
60
+ out.help = true;
61
+ continue;
62
+ }
63
+ if (arg === "--non-interactive" || arg === "--yes") {
64
+ out.nonInteractive = true;
65
+ continue;
66
+ }
67
+
68
+ if (arg === "--mode" || arg.startsWith("--mode=")) {
69
+ const parsed = readArgValue(argv, i, arg);
70
+ out.mode = parsed.value.trim().toLowerCase();
71
+ i = parsed.nextIndex;
72
+ continue;
73
+ }
74
+ if (arg === "--host" || arg.startsWith("--host=")) {
75
+ const parsed = readArgValue(argv, i, arg);
76
+ out.host = parsed.value.trim();
77
+ i = parsed.nextIndex;
78
+ continue;
79
+ }
80
+ if (arg === "--base-url" || arg.startsWith("--base-url=")) {
81
+ const parsed = readArgValue(argv, i, arg);
82
+ out.baseUrl = parsed.value.trim();
83
+ i = parsed.nextIndex;
84
+ continue;
85
+ }
86
+ if (arg === "--tenant-id" || arg.startsWith("--tenant-id=")) {
87
+ const parsed = readArgValue(argv, i, arg);
88
+ out.tenantId = parsed.value.trim();
89
+ i = parsed.nextIndex;
90
+ continue;
91
+ }
92
+ if (arg === "--api-key" || arg.startsWith("--api-key=")) {
93
+ const parsed = readArgValue(argv, i, arg);
94
+ out.apiKey = parsed.value;
95
+ i = parsed.nextIndex;
96
+ continue;
97
+ }
98
+ if (arg === "--magic-link-api-key" || arg === "--bootstrap-api-key" || arg.startsWith("--magic-link-api-key=") || arg.startsWith("--bootstrap-api-key=")) {
99
+ const parsed = readArgValue(argv, i, arg);
100
+ out.magicLinkApiKey = parsed.value;
101
+ i = parsed.nextIndex;
102
+ continue;
103
+ }
104
+ if (arg === "--bootstrap-key-id" || arg.startsWith("--bootstrap-key-id=")) {
105
+ const parsed = readArgValue(argv, i, arg);
106
+ out.bootstrapKeyId = parsed.value.trim();
107
+ i = parsed.nextIndex;
108
+ continue;
109
+ }
110
+ if (arg === "--bootstrap-scopes" || arg.startsWith("--bootstrap-scopes=")) {
111
+ const parsed = readArgValue(argv, i, arg);
112
+ out.bootstrapScopesRaw = parsed.value;
113
+ i = parsed.nextIndex;
114
+ continue;
115
+ }
116
+ if (arg === "--idempotency-key" || arg.startsWith("--idempotency-key=")) {
117
+ const parsed = readArgValue(argv, i, arg);
118
+ out.idempotencyKey = parsed.value.trim();
119
+ i = parsed.nextIndex;
120
+ continue;
121
+ }
122
+ if (arg === "--config-path" || arg.startsWith("--config-path=")) {
123
+ const parsed = readArgValue(argv, i, arg);
124
+ out.configPath = parsed.value.trim();
125
+ i = parsed.nextIndex;
126
+ continue;
127
+ }
128
+ if (arg === "--profile-id" || arg === "--profile" || arg.startsWith("--profile-id=") || arg.startsWith("--profile=")) {
129
+ const parsed = readArgValue(argv, i, arg);
130
+ out.profileId = parsed.value.trim();
131
+ i = parsed.nextIndex;
132
+ continue;
133
+ }
134
+ if (arg === "--profile-file" || arg.startsWith("--profile-file=")) {
135
+ const parsed = readArgValue(argv, i, arg);
136
+ out.profileFile = parsed.value.trim();
137
+ i = parsed.nextIndex;
138
+ continue;
139
+ }
140
+ if (arg === "--skip-profile-apply" || arg === "--no-profile") {
141
+ out.skipProfileApply = true;
142
+ continue;
143
+ }
144
+ if (arg === "--smoke") {
145
+ out.smoke = true;
146
+ continue;
147
+ }
148
+ if (arg === "--smoke-timeout-ms" || arg.startsWith("--smoke-timeout-ms=")) {
149
+ const parsed = readArgValue(argv, i, arg);
150
+ out.smokeTimeoutMs = Number(parsed.value);
151
+ i = parsed.nextIndex;
152
+ continue;
153
+ }
154
+ if (arg === "--dry-run") {
155
+ out.dryRun = true;
156
+ continue;
157
+ }
158
+ if (arg === "--host-config" || arg.startsWith("--host-config=")) {
159
+ const parsed = readArgValue(argv, i, arg);
160
+ out.hostConfigPath = parsed.value.trim();
161
+ i = parsed.nextIndex;
162
+ continue;
163
+ }
164
+ throw new Error(`unknown argument: ${arg}`);
165
+ }
166
+
167
+ if (out.mode && !MODE_OPTIONS.has(out.mode)) {
168
+ throw new Error("--mode must be one of: local, manual, bootstrap");
169
+ }
170
+ if (out.hostConfigPath && !path.isAbsolute(out.hostConfigPath)) {
171
+ out.hostConfigPath = path.resolve(process.cwd(), out.hostConfigPath);
172
+ }
173
+ if (out.configPath && !path.isAbsolute(out.configPath)) {
174
+ out.configPath = path.resolve(process.cwd(), out.configPath);
175
+ }
176
+ if (out.profileFile && !path.isAbsolute(out.profileFile)) {
177
+ out.profileFile = path.resolve(process.cwd(), out.profileFile);
178
+ }
179
+ if (out.profileId && out.profileFile) {
180
+ throw new Error("choose one of --profile-id/--profile or --profile-file");
181
+ }
182
+ if (!Number.isSafeInteger(out.smokeTimeoutMs) || out.smokeTimeoutMs < 1000) {
183
+ throw new Error("--smoke-timeout-ms must be an integer >= 1000");
184
+ }
185
+ return out;
186
+ }
187
+
188
+ export function normalizeHttpUrl(value) {
189
+ const raw = String(value ?? "").trim();
190
+ if (!raw) return null;
191
+ let parsed;
192
+ try {
193
+ parsed = new URL(raw);
194
+ } catch {
195
+ return null;
196
+ }
197
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return null;
198
+ const normalized = parsed.toString();
199
+ return normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
200
+ }
201
+
202
+ function parseScopes(raw) {
203
+ if (!raw || !String(raw).trim()) return [];
204
+ const seen = new Set();
205
+ const out = [];
206
+ for (const part of String(raw).split(",")) {
207
+ const scope = part.trim();
208
+ if (!scope || seen.has(scope)) continue;
209
+ seen.add(scope);
210
+ out.push(scope);
211
+ }
212
+ return out;
213
+ }
214
+
215
+ function shellQuote(value) {
216
+ const s = String(value ?? "");
217
+ if (!s) return "''";
218
+ return `'${s.replace(/'/g, `'\\''`)}'`;
219
+ }
220
+
221
+ function normalizeResolvedHostConfig(config, fallbackHost) {
222
+ if (typeof config === "string") {
223
+ return {
224
+ host: fallbackHost,
225
+ baseUrl: normalizeHttpUrl(config),
226
+ magicLinkBaseUrl: normalizeHttpUrl(config),
227
+ raw: { baseUrl: config }
228
+ };
229
+ }
230
+ if (!config || typeof config !== "object" || Array.isArray(config)) {
231
+ throw new Error("host config helper must return an object (or URL string)");
232
+ }
233
+ const host = typeof config.host === "string" && config.host.trim() ? config.host.trim() : fallbackHost;
234
+ const baseUrlCandidate = config.baseUrl ?? config.apiBaseUrl ?? config.settldBaseUrl ?? null;
235
+ const magicLinkCandidate = config.magicLinkBaseUrl ?? config.onboardingBaseUrl ?? config.baseUrl ?? null;
236
+ return {
237
+ host,
238
+ baseUrl: baseUrlCandidate ? normalizeHttpUrl(baseUrlCandidate) : null,
239
+ magicLinkBaseUrl: magicLinkCandidate ? normalizeHttpUrl(magicLinkCandidate) : null,
240
+ raw: config
241
+ };
242
+ }
243
+
244
+ function findHostResolver(mod) {
245
+ const candidates = [
246
+ mod?.resolveHostConfig,
247
+ mod?.resolveHost,
248
+ mod?.default?.resolveHostConfig,
249
+ mod?.default?.resolveHost,
250
+ typeof mod?.default === "function" ? mod.default : null
251
+ ];
252
+ return candidates.find((fn) => typeof fn === "function") ?? null;
253
+ }
254
+
255
+ function findHostSetupRunner(mod) {
256
+ const candidates = [
257
+ mod?.runHostConfigSetup,
258
+ mod?.setupHostConfig,
259
+ mod?.default?.runHostConfigSetup,
260
+ mod?.default?.setupHostConfig
261
+ ];
262
+ return candidates.find((fn) => typeof fn === "function") ?? null;
263
+ }
264
+
265
+ function findHostOptionsGetter(mod) {
266
+ const candidates = [
267
+ mod?.listHosts,
268
+ mod?.listHostOptions,
269
+ mod?.default?.listHosts,
270
+ mod?.default?.listHostOptions
271
+ ];
272
+ return candidates.find((fn) => typeof fn === "function") ?? null;
273
+ }
274
+
275
+ function isMissingModuleError(err) {
276
+ const code = err?.code;
277
+ if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND" || code === "ENOENT") return true;
278
+ const msg = String(err?.message ?? "");
279
+ return msg.includes("Cannot find module") || msg.includes("ERR_MODULE_NOT_FOUND");
280
+ }
281
+
282
+ export async function loadHostConfigHelper(hostConfigPath = DEFAULT_HOST_CONFIG_PATH) {
283
+ const resolvedPath = path.isAbsolute(hostConfigPath) ? hostConfigPath : path.resolve(process.cwd(), hostConfigPath);
284
+ let mod;
285
+ try {
286
+ mod = await import(pathToFileURL(resolvedPath).href);
287
+ } catch (err) {
288
+ if (isMissingModuleError(err)) {
289
+ throw new Error(
290
+ `host config helper missing at ${resolvedPath}. Create scripts/setup/host-config.mjs (default helper) or pass --host-config <path>. Reference: docs/QUICKSTART_MCP_HOSTS.md#6-host-config-helper-customization`
291
+ );
292
+ }
293
+ throw new Error(`failed to load host config helper at ${resolvedPath}: ${err?.message ?? String(err)}`);
294
+ }
295
+
296
+ const resolver = findHostResolver(mod);
297
+ const runHostConfigSetup = findHostSetupRunner(mod);
298
+ const supportedHosts = Array.isArray(mod?.SUPPORTED_HOSTS)
299
+ ? mod.SUPPORTED_HOSTS.map((item) => String(item ?? "").trim()).filter(Boolean)
300
+ : Array.isArray(mod?.default?.SUPPORTED_HOSTS)
301
+ ? mod.default.SUPPORTED_HOSTS.map((item) => String(item ?? "").trim()).filter(Boolean)
302
+ : [];
303
+ if (!resolver && !runHostConfigSetup) {
304
+ throw new Error(
305
+ `invalid host config helper at ${resolvedPath}: export runHostConfigSetup(...) and/or resolveHostConfig(...)`
306
+ );
307
+ }
308
+ const listHostOptions = findHostOptionsGetter(mod);
309
+ return {
310
+ path: resolvedPath,
311
+ supportedHosts,
312
+ async resolveHostConfig({ host, mode }) {
313
+ if (!resolver) {
314
+ return {
315
+ host,
316
+ baseUrl: null,
317
+ magicLinkBaseUrl: null,
318
+ raw: {}
319
+ };
320
+ }
321
+ let resolved;
322
+ try {
323
+ resolved = await resolver({ host, mode });
324
+ } catch {
325
+ resolved = await resolver(host, mode);
326
+ }
327
+ return normalizeResolvedHostConfig(resolved, host);
328
+ },
329
+ async listHosts() {
330
+ if (listHostOptions) {
331
+ const out = await listHostOptions();
332
+ if (Array.isArray(out)) return out.map((item) => String(item ?? "").trim()).filter(Boolean);
333
+ }
334
+ if (supportedHosts.length) return supportedHosts;
335
+ if (Array.isArray(mod?.hosts)) return mod.hosts.map((item) => String(item ?? "").trim()).filter(Boolean);
336
+ if (Array.isArray(mod?.default?.hosts)) return mod.default.hosts.map((item) => String(item ?? "").trim()).filter(Boolean);
337
+ return [];
338
+ },
339
+ async applyHostConfig({ host, env, configPath, dryRun }) {
340
+ if (!runHostConfigSetup) return null;
341
+ const summary = await runHostConfigSetup({
342
+ host,
343
+ env: { ...process.env, ...(env ?? {}) },
344
+ configPath,
345
+ dryRun: Boolean(dryRun)
346
+ });
347
+ if (summary && typeof summary === "object" && summary.ok === false) {
348
+ throw new Error(`host config helper failed: ${summary?.error?.message ?? "setup failed"}`);
349
+ }
350
+ return summary;
351
+ }
352
+ };
353
+ }
354
+
355
+ async function promptLine(rl, label, { required = true, defaultValue = null } = {}) {
356
+ const suffix = defaultValue ? ` [${defaultValue}]` : "";
357
+ const answer = await rl.question(`${label}${suffix}: `);
358
+ const value = answer.trim() || (defaultValue ? String(defaultValue).trim() : "");
359
+ if (!required) return value;
360
+ if (value) return value;
361
+ throw new Error(`${label} is required`);
362
+ }
363
+
364
+ function parseYesNo(value, { defaultValue = true } = {}) {
365
+ const normalized = String(value ?? "").trim().toLowerCase();
366
+ if (!normalized) return defaultValue;
367
+ if (["y", "yes", "true", "1"].includes(normalized)) return true;
368
+ if (["n", "no", "false", "0"].includes(normalized)) return false;
369
+ return defaultValue;
370
+ }
371
+
372
+ async function resolveRuntimeConfig({ args, hostHelper, interactive, stdin = process.stdin, stdout = process.stdout }) {
373
+ const base = {
374
+ mode: args.mode ?? "",
375
+ host: args.host ?? "",
376
+ baseUrl: args.baseUrl ?? "",
377
+ tenantId: args.tenantId ?? "",
378
+ apiKey: args.apiKey ?? "",
379
+ magicLinkApiKey: args.magicLinkApiKey ?? "",
380
+ bootstrapKeyId: args.bootstrapKeyId ?? "",
381
+ bootstrapScopesRaw: args.bootstrapScopesRaw ?? "",
382
+ idempotencyKey: args.idempotencyKey ?? "",
383
+ profileId: args.profileId ?? "",
384
+ profileFile: args.profileFile ?? "",
385
+ skipProfileApply: Boolean(args.skipProfileApply),
386
+ smoke: Boolean(args.smoke),
387
+ smokeTimeoutMs: args.smokeTimeoutMs ?? DEFAULT_SMOKE_TIMEOUT_MS
388
+ };
389
+
390
+ let rl = null;
391
+ try {
392
+ if (interactive) {
393
+ if (!stdin.isTTY || !stdout.isTTY) {
394
+ throw new Error("interactive mode requires a TTY. Re-run with --non-interactive and flags.");
395
+ }
396
+ rl = createInterface({ input: stdin, output: stdout });
397
+ if (!base.mode) {
398
+ base.mode = (await promptLine(rl, "Mode (local/manual/bootstrap)", { defaultValue: "manual" })).toLowerCase();
399
+ }
400
+ if (!MODE_OPTIONS.has(base.mode)) {
401
+ throw new Error("mode must be local, manual, or bootstrap");
402
+ }
403
+
404
+ const hostOptions = await hostHelper.listHosts();
405
+ const hostDefault = hostOptions[0] ?? "local";
406
+ const hostPrompt = hostOptions.length
407
+ ? `Host (${hostOptions.join("/")})`
408
+ : "Host";
409
+ if (!base.host) {
410
+ base.host = await promptLine(rl, hostPrompt, { defaultValue: hostDefault });
411
+ }
412
+ const resolved = await hostHelper.resolveHostConfig({ host: base.host, mode: base.mode });
413
+ base.host = resolved.host || base.host;
414
+ if (!base.baseUrl) {
415
+ base.baseUrl = await promptLine(rl, "Settld base URL", {
416
+ defaultValue: resolved.baseUrl ?? process.env.SETTLD_BASE_URL ?? "http://127.0.0.1:3000"
417
+ });
418
+ }
419
+ if (!base.tenantId) {
420
+ base.tenantId = await promptLine(rl, "Tenant ID", { defaultValue: process.env.SETTLD_TENANT_ID ?? "tenant_default" });
421
+ }
422
+
423
+ if (base.mode === "bootstrap") {
424
+ if (!base.magicLinkApiKey) {
425
+ base.magicLinkApiKey = await promptLine(rl, "Magic Link API key");
426
+ }
427
+ if (!base.bootstrapKeyId) {
428
+ base.bootstrapKeyId = await promptLine(rl, "Bootstrap API key ID (optional)", { required: false });
429
+ }
430
+ if (!base.bootstrapScopesRaw) {
431
+ base.bootstrapScopesRaw = await promptLine(rl, "Bootstrap scopes CSV (optional)", { required: false });
432
+ }
433
+ } else if (!base.apiKey) {
434
+ base.apiKey = await promptLine(rl, "Settld API key");
435
+ }
436
+ if (!base.skipProfileApply && !base.profileFile && !base.profileId) {
437
+ const shouldApply = parseYesNo(
438
+ await promptLine(rl, "Apply starter policy profile now? (y/n)", { required: false, defaultValue: "y" }),
439
+ { defaultValue: true }
440
+ );
441
+ base.skipProfileApply = !shouldApply;
442
+ }
443
+ if (!base.skipProfileApply && !base.profileFile && !base.profileId) {
444
+ base.profileId = await promptLine(rl, "Starter profile ID", {
445
+ required: true,
446
+ defaultValue: DEFAULT_PROFILE_ID
447
+ });
448
+ }
449
+ if (!base.smoke) {
450
+ base.smoke = parseYesNo(await promptLine(rl, "Run MCP smoke check now? (y/n)", { required: false, defaultValue: "y" }), {
451
+ defaultValue: true
452
+ });
453
+ }
454
+ return base;
455
+ }
456
+
457
+ const mode = base.mode;
458
+ if (!MODE_OPTIONS.has(mode)) {
459
+ throw new Error("non-interactive mode requires --mode local|manual|bootstrap");
460
+ }
461
+ if (!base.host) {
462
+ throw new Error("non-interactive mode requires --host");
463
+ }
464
+ const resolved = await hostHelper.resolveHostConfig({ host: base.host, mode });
465
+ base.host = resolved.host || base.host;
466
+ if (!base.baseUrl && resolved.baseUrl) {
467
+ base.baseUrl = resolved.baseUrl;
468
+ }
469
+ if (!base.baseUrl && process.env.SETTLD_BASE_URL) {
470
+ base.baseUrl = String(process.env.SETTLD_BASE_URL).trim();
471
+ }
472
+ if (!base.tenantId && process.env.SETTLD_TENANT_ID) {
473
+ base.tenantId = String(process.env.SETTLD_TENANT_ID).trim();
474
+ }
475
+ const missing = [];
476
+ if (!base.baseUrl) missing.push("--base-url");
477
+ if (!base.tenantId) missing.push("--tenant-id");
478
+ if (mode === "bootstrap") {
479
+ if (!base.magicLinkApiKey) missing.push("--magic-link-api-key");
480
+ } else if (!base.apiKey) {
481
+ missing.push("--api-key");
482
+ }
483
+ if (missing.length) {
484
+ throw new Error(`non-interactive mode missing required flags: ${missing.join(", ")}`);
485
+ }
486
+ return base;
487
+ } finally {
488
+ if (rl) rl.close();
489
+ }
490
+ }
491
+
492
+ function parseJsonOrNull(raw) {
493
+ const text = String(raw ?? "").trim();
494
+ if (!text) return null;
495
+ try {
496
+ return JSON.parse(text);
497
+ } catch {
498
+ return null;
499
+ }
500
+ }
501
+
502
+ function summarizeText(value, max = 500) {
503
+ const text = String(value ?? "").trim();
504
+ if (!text) return "";
505
+ if (text.length <= max) return text;
506
+ return `${text.slice(0, max - 3)}...`;
507
+ }
508
+
509
+ function normalizeRefToken(value) {
510
+ if (value === null || value === undefined) return null;
511
+ const normalized = String(value).trim();
512
+ if (!normalized) return null;
513
+ if (!REF_VALUE_PATTERN.test(normalized)) return null;
514
+ return normalized;
515
+ }
516
+
517
+ function parsePositiveSafeInteger(value) {
518
+ const parsed = Number(value);
519
+ if (!Number.isSafeInteger(parsed) || parsed < 1) return null;
520
+ return parsed;
521
+ }
522
+
523
+ function parseNonNegativeSafeInteger(value) {
524
+ const parsed = Number(value);
525
+ if (!Number.isSafeInteger(parsed) || parsed < 0) return null;
526
+ return parsed;
527
+ }
528
+
529
+ function parseApiKeyId(value) {
530
+ const raw = String(value ?? "").trim();
531
+ if (!raw) return null;
532
+ const dot = raw.indexOf(".");
533
+ const keyId = dot > 0 ? raw.slice(0, dot) : raw;
534
+ return normalizeRefToken(keyId);
535
+ }
536
+
537
+ function parseOptionalPassportObject(value) {
538
+ if (value === null || value === undefined) return null;
539
+ if (typeof value === "string") {
540
+ const raw = value.trim();
541
+ if (!raw) return null;
542
+ let parsed;
543
+ try {
544
+ parsed = JSON.parse(raw);
545
+ } catch {
546
+ return null;
547
+ }
548
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
549
+ return parsed;
550
+ }
551
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
552
+ return value;
553
+ }
554
+
555
+ function pickPassportTarget(profileApplyResult) {
556
+ const target = profileApplyResult?.target;
557
+ if (!target || typeof target !== "object" || Array.isArray(target)) return null;
558
+ return target;
559
+ }
560
+
561
+ function buildPaidToolsAgentPassport({ env, profileApplyResult = null, profileIdHint = null } = {}) {
562
+ const existingPassport = parseOptionalPassportObject(env.SETTLD_PAID_TOOLS_AGENT_PASSPORT ?? null);
563
+ const target = pickPassportTarget(profileApplyResult);
564
+
565
+ const profileRef = normalizeRefToken(target?.policyRef) || normalizeRefToken(profileApplyResult?.profileId) || normalizeRefToken(profileIdHint) || DEFAULT_PROFILE_ID;
566
+ const sponsorRef = normalizeRefToken(target?.sponsorRef) || normalizeRefToken(env.SETTLD_SPONSOR_REF) || normalizeRefToken(existingPassport?.sponsorRef) || "sponsor_default";
567
+ const sponsorWalletRef =
568
+ normalizeRefToken(target?.sponsorWalletRef) ||
569
+ normalizeRefToken(env.SETTLD_SPONSOR_WALLET_REF) ||
570
+ normalizeRefToken(env.SETTLD_RUNTIME_WALLET_REF) ||
571
+ normalizeRefToken(existingPassport?.sponsorWalletRef) ||
572
+ `wallet_${profileRef}`;
573
+ const policyRef = normalizeRefToken(target?.policyRef) || normalizeRefToken(env.SETTLD_POLICY_REF) || normalizeRefToken(existingPassport?.policyRef) || profileRef;
574
+ const policyVersion =
575
+ parsePositiveSafeInteger(target?.policyVersion) ||
576
+ parsePositiveSafeInteger(env.SETTLD_POLICY_VERSION) ||
577
+ parsePositiveSafeInteger(existingPassport?.policyVersion) ||
578
+ 1;
579
+ const agentKeyId =
580
+ normalizeRefToken(env.SETTLD_AGENT_KEY_ID) ||
581
+ normalizeRefToken(existingPassport?.agentKeyId) ||
582
+ parseApiKeyId(env.SETTLD_API_KEY) ||
583
+ "agent_key_default";
584
+ const delegationDepth = parseNonNegativeSafeInteger(existingPassport?.delegationDepth) ?? 0;
585
+
586
+ return JSON.stringify({
587
+ schemaVersion: X402_AGENT_PASSPORT_SCHEMA_VERSION,
588
+ sponsorRef,
589
+ sponsorWalletRef,
590
+ agentKeyId,
591
+ policyRef,
592
+ policyVersion,
593
+ delegationDepth
594
+ });
595
+ }
596
+
597
+ function normalizeBootstrapPassportEnvValue(value) {
598
+ const parsed = parseOptionalPassportObject(value);
599
+ if (!parsed) return null;
600
+ return JSON.stringify(parsed);
601
+ }
602
+
603
+ function extractApplyTarget(parsed) {
604
+ const target = parsed?.target;
605
+ if (!target || typeof target !== "object" || Array.isArray(target)) return null;
606
+ const sponsorRef = normalizeRefToken(target.sponsorRef);
607
+ const sponsorWalletRef = normalizeRefToken(target.sponsorWalletRef);
608
+ const policyRef = normalizeRefToken(target.policyRef);
609
+ const policyVersion = parsePositiveSafeInteger(target.policyVersion);
610
+ if (!sponsorRef && !sponsorWalletRef && !policyRef && !policyVersion) return null;
611
+ return {
612
+ ...(sponsorRef ? { sponsorRef } : {}),
613
+ ...(sponsorWalletRef ? { sponsorWalletRef } : {}),
614
+ ...(policyRef ? { policyRef } : {}),
615
+ ...(policyVersion ? { policyVersion } : {})
616
+ };
617
+ }
618
+
619
+ async function runCommandCapture({ cmd, args = [], cwd = REPO_ROOT, env = process.env } = {}) {
620
+ return await new Promise((resolve, reject) => {
621
+ const child = spawn(cmd, args, {
622
+ cwd,
623
+ env,
624
+ stdio: ["ignore", "pipe", "pipe"]
625
+ });
626
+ const stdoutChunks = [];
627
+ const stderrChunks = [];
628
+ child.stdout.on("data", (chunk) => stdoutChunks.push(chunk));
629
+ child.stderr.on("data", (chunk) => stderrChunks.push(chunk));
630
+ child.on("error", reject);
631
+ child.on("close", (code, signal) => {
632
+ resolve({
633
+ code: typeof code === "number" ? code : 1,
634
+ signal: signal ?? null,
635
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
636
+ stderr: Buffer.concat(stderrChunks).toString("utf8")
637
+ });
638
+ });
639
+ });
640
+ }
641
+
642
+ function buildSettldCliArgs(args) {
643
+ const scriptPath = path.join(REPO_ROOT, "bin", "settld.js");
644
+ return [scriptPath, ...args];
645
+ }
646
+
647
+ async function runSettldCli(args, { env = process.env } = {}) {
648
+ return await runCommandCapture({
649
+ cmd: process.execPath,
650
+ args: buildSettldCliArgs(args),
651
+ cwd: REPO_ROOT,
652
+ env
653
+ });
654
+ }
655
+
656
+ async function runProfileApplyAutomation({
657
+ env,
658
+ profileId,
659
+ profileFile,
660
+ dryRun,
661
+ stdout = process.stdout
662
+ } = {}) {
663
+ let tempDir = null;
664
+ let selectedProfilePath = profileFile ? path.resolve(profileFile) : null;
665
+ let selectedProfileId = profileId || null;
666
+ try {
667
+ if (!selectedProfilePath) {
668
+ selectedProfileId = selectedProfileId || DEFAULT_PROFILE_ID;
669
+ tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "settld-setup-profile-"));
670
+ selectedProfilePath = path.join(tempDir, `${selectedProfileId}.profile.json`);
671
+ const initResult = await runSettldCli(
672
+ ["profile", "init", selectedProfileId, "--out", selectedProfilePath, "--force", "--format", "json"],
673
+ { env: process.env }
674
+ );
675
+ if (initResult.code !== 0) {
676
+ throw new Error(`profile init failed: ${summarizeText(initResult.stderr || initResult.stdout)}`);
677
+ }
678
+ }
679
+
680
+ const applyArgs = [
681
+ "profile",
682
+ "apply",
683
+ selectedProfilePath,
684
+ "--base-url",
685
+ env.SETTLD_BASE_URL,
686
+ "--tenant-id",
687
+ env.SETTLD_TENANT_ID,
688
+ "--api-key",
689
+ env.SETTLD_API_KEY,
690
+ "--format",
691
+ "json"
692
+ ];
693
+ if (dryRun) applyArgs.push("--dry-run");
694
+ const applyResult = await runSettldCli(applyArgs, { env: process.env });
695
+ if (applyResult.code !== 0) {
696
+ throw new Error(`profile apply failed: ${summarizeText(applyResult.stderr || applyResult.stdout)}`);
697
+ }
698
+ const parsed = parseJsonOrNull(applyResult.stdout);
699
+ if (!parsed || typeof parsed !== "object") {
700
+ throw new Error("profile apply did not return valid JSON output");
701
+ }
702
+ const resolvedProfileId = String(parsed.profileId ?? selectedProfileId ?? "").trim() || null;
703
+ if (!resolvedProfileId) {
704
+ throw new Error("profile apply output missing profileId");
705
+ }
706
+ stdout.write(`Profile apply ${dryRun ? "dry-run" : "live"} complete: ${resolvedProfileId}\n`);
707
+ return {
708
+ ran: true,
709
+ dryRun: Boolean(dryRun),
710
+ profileId: resolvedProfileId,
711
+ profilePath: selectedProfilePath,
712
+ ok: parsed.ok === true,
713
+ stepCount: Array.isArray(parsed.steps) ? parsed.steps.length : 0,
714
+ target: extractApplyTarget(parsed)
715
+ };
716
+ } finally {
717
+ if (tempDir) {
718
+ await fs.rm(tempDir, { recursive: true, force: true });
719
+ }
720
+ }
721
+ }
722
+
723
+ async function runMcpSmokeCheck({ env, timeoutMs = DEFAULT_SMOKE_TIMEOUT_MS, stdout = process.stdout } = {}) {
724
+ const scriptPath = path.join(REPO_ROOT, "scripts", "mcp", "probe.mjs");
725
+ const result = await runCommandCapture({
726
+ cmd: process.execPath,
727
+ args: [scriptPath, "--call", "settld.about", "{}"],
728
+ cwd: REPO_ROOT,
729
+ env: {
730
+ ...process.env,
731
+ ...env,
732
+ MCP_PROBE_TIMEOUT_MS: String(timeoutMs)
733
+ }
734
+ });
735
+ if (result.code !== 0) {
736
+ throw new Error(`mcp smoke failed: ${summarizeText(result.stderr || result.stdout)}`);
737
+ }
738
+ stdout.write("MCP smoke check passed: settld.about\n");
739
+ return {
740
+ ran: true,
741
+ ok: true,
742
+ timeoutMs
743
+ };
744
+ }
745
+
746
+ async function requestRuntimeBootstrap({
747
+ baseUrl,
748
+ tenantId,
749
+ magicLinkApiKey,
750
+ bootstrapKeyId,
751
+ bootstrapScopes,
752
+ idempotencyKey,
753
+ fetchImpl = fetch
754
+ }) {
755
+ const normalizedBaseUrl = normalizeHttpUrl(baseUrl);
756
+ if (!normalizedBaseUrl) throw new Error(`invalid runtime bootstrap base URL: ${baseUrl}`);
757
+ const headers = {
758
+ "content-type": "application/json",
759
+ "x-api-key": String(magicLinkApiKey ?? "")
760
+ };
761
+ if (idempotencyKey) headers["x-idempotency-key"] = String(idempotencyKey);
762
+
763
+ const body = {
764
+ apiKey: {
765
+ create: true,
766
+ description: "setup wizard runtime bootstrap"
767
+ }
768
+ };
769
+ if (bootstrapKeyId) body.apiKey.keyId = String(bootstrapKeyId);
770
+ if (Array.isArray(bootstrapScopes) && bootstrapScopes.length) {
771
+ body.apiKey.scopes = bootstrapScopes;
772
+ }
773
+
774
+ const url = new URL(
775
+ `/v1/tenants/${encodeURIComponent(String(tenantId ?? ""))}/onboarding/runtime-bootstrap`,
776
+ normalizedBaseUrl
777
+ );
778
+ const res = await fetchImpl(url.toString(), {
779
+ method: "POST",
780
+ headers,
781
+ body: JSON.stringify(body)
782
+ });
783
+ const text = await res.text();
784
+ let json = null;
785
+ try {
786
+ json = text ? JSON.parse(text) : null;
787
+ } catch {
788
+ json = null;
789
+ }
790
+ if (!res.ok) {
791
+ const message =
792
+ json && typeof json === "object"
793
+ ? json?.message ?? json?.error ?? `HTTP ${res.status}`
794
+ : text || `HTTP ${res.status}`;
795
+ throw new Error(`runtime bootstrap request failed (${res.status}): ${String(message)}`);
796
+ }
797
+ return json;
798
+ }
799
+
800
+ export function extractBootstrapMcpEnv(responseBody) {
801
+ const env = responseBody?.mcp?.env;
802
+ if (!env || typeof env !== "object" || Array.isArray(env)) {
803
+ throw new Error("runtime bootstrap response missing mcp.env object");
804
+ }
805
+ const required = ["SETTLD_BASE_URL", "SETTLD_TENANT_ID", "SETTLD_API_KEY"];
806
+ const out = {};
807
+ for (const key of required) {
808
+ const value = typeof env[key] === "string" ? env[key].trim() : "";
809
+ if (!value) throw new Error(`runtime bootstrap response missing ${key}`);
810
+ out[key] = value;
811
+ }
812
+ const paidToolsBase = typeof env.SETTLD_PAID_TOOLS_BASE_URL === "string" ? env.SETTLD_PAID_TOOLS_BASE_URL.trim() : "";
813
+ if (paidToolsBase) out.SETTLD_PAID_TOOLS_BASE_URL = paidToolsBase;
814
+ const paidToolsPassport = normalizeBootstrapPassportEnvValue(env.SETTLD_PAID_TOOLS_AGENT_PASSPORT ?? null);
815
+ if (paidToolsPassport) out.SETTLD_PAID_TOOLS_AGENT_PASSPORT = paidToolsPassport;
816
+ return out;
817
+ }
818
+
819
+ function buildManualEnv({ baseUrl, tenantId, apiKey }) {
820
+ const normalizedBaseUrl = normalizeHttpUrl(baseUrl);
821
+ if (!normalizedBaseUrl) throw new Error(`invalid --base-url: ${baseUrl}`);
822
+ return {
823
+ SETTLD_BASE_URL: normalizedBaseUrl,
824
+ SETTLD_TENANT_ID: String(tenantId),
825
+ SETTLD_API_KEY: String(apiKey)
826
+ };
827
+ }
828
+
829
+ function formatEnvExportLines(env) {
830
+ const keys = Object.keys(env).sort();
831
+ return keys.map((key) => `export ${key}=${shellQuote(env[key])}`);
832
+ }
833
+
834
+ function printOutput({
835
+ stdout = process.stdout,
836
+ mode,
837
+ host,
838
+ env,
839
+ helperPath,
840
+ hostConfigResult = null,
841
+ profileApplyResult = null,
842
+ smokeResult = null
843
+ }) {
844
+ const lines = [];
845
+ lines.push("Settld setup complete.");
846
+ lines.push(`Mode: ${mode}`);
847
+ lines.push(`Host: ${host}`);
848
+ lines.push(`Host helper: ${helperPath}`);
849
+ if (hostConfigResult && typeof hostConfigResult === "object") {
850
+ lines.push(`Host config: ${String(hostConfigResult.configPath ?? "n/a")}`);
851
+ if (hostConfigResult.dryRun) {
852
+ lines.push("Host config write mode: dry-run (no file changes)");
853
+ }
854
+ }
855
+ lines.push("");
856
+ lines.push("Environment exports:");
857
+ for (const line of formatEnvExportLines(env)) lines.push(line);
858
+ if (profileApplyResult && typeof profileApplyResult === "object" && profileApplyResult.ran) {
859
+ lines.push("");
860
+ lines.push(
861
+ `Profile apply: ${profileApplyResult.ok ? "ok" : "error"} (${profileApplyResult.dryRun ? "dry-run" : "live"}, profile=${profileApplyResult.profileId})`
862
+ );
863
+ }
864
+ if (smokeResult && typeof smokeResult === "object" && smokeResult.ran) {
865
+ lines.push("");
866
+ lines.push(`MCP smoke: ${smokeResult.ok ? "pass" : "fail"} (timeoutMs=${smokeResult.timeoutMs})`);
867
+ }
868
+ lines.push("");
869
+ lines.push("Next steps:");
870
+ lines.push("1. Run the export lines in your shell.");
871
+ lines.push("2. Verify connectivity with: npm run mcp:probe -- --call settld.about '{}'");
872
+ lines.push("3. Optional policy deploy: settld profile apply <profile.json>");
873
+ stdout.write(lines.join("\n") + "\n");
874
+ }
875
+
876
+ export async function runWizard({
877
+ argv = process.argv.slice(2),
878
+ stdin = process.stdin,
879
+ stdout = process.stdout,
880
+ fetchImpl = fetch,
881
+ extraEnv = null
882
+ } = {}) {
883
+ const args = parseArgs(argv);
884
+ if (args.help) {
885
+ usage();
886
+ return { ok: true, code: 0, env: null };
887
+ }
888
+
889
+ const hostHelper = await loadHostConfigHelper(args.hostConfigPath);
890
+ const interactive = !args.nonInteractive;
891
+ const config = await resolveRuntimeConfig({ args, hostHelper, interactive, stdin, stdout });
892
+
893
+ let env;
894
+ if (config.mode === "bootstrap") {
895
+ const bootstrapScopes = parseScopes(config.bootstrapScopesRaw);
896
+ const responseBody = await requestRuntimeBootstrap({
897
+ baseUrl: config.baseUrl,
898
+ tenantId: config.tenantId,
899
+ magicLinkApiKey: config.magicLinkApiKey,
900
+ bootstrapKeyId: config.bootstrapKeyId,
901
+ bootstrapScopes,
902
+ idempotencyKey: config.idempotencyKey,
903
+ fetchImpl
904
+ });
905
+ env = extractBootstrapMcpEnv(responseBody);
906
+ } else {
907
+ env = buildManualEnv({
908
+ baseUrl: config.baseUrl,
909
+ tenantId: config.tenantId,
910
+ apiKey: config.apiKey
911
+ });
912
+ }
913
+ if (extraEnv && typeof extraEnv === "object" && !Array.isArray(extraEnv)) {
914
+ for (const [key, value] of Object.entries(extraEnv)) {
915
+ if (typeof key !== "string") continue;
916
+ const normalizedKey = key.trim();
917
+ if (!normalizedKey) continue;
918
+ if (value === null || value === undefined) continue;
919
+ env[normalizedKey] = String(value);
920
+ }
921
+ }
922
+ let profileApplyResult = null;
923
+ if (!config.skipProfileApply && (config.profileFile || config.profileId)) {
924
+ profileApplyResult = await runProfileApplyAutomation({
925
+ env,
926
+ profileId: config.profileId || null,
927
+ profileFile: config.profileFile || null,
928
+ dryRun: args.dryRun,
929
+ stdout
930
+ });
931
+ }
932
+ env.SETTLD_PAID_TOOLS_AGENT_PASSPORT = buildPaidToolsAgentPassport({
933
+ env,
934
+ profileApplyResult,
935
+ profileIdHint: config.profileId || DEFAULT_PROFILE_ID
936
+ });
937
+ let smokeResult = null;
938
+ if (config.smoke) {
939
+ smokeResult = await runMcpSmokeCheck({
940
+ env,
941
+ timeoutMs: config.smokeTimeoutMs ?? DEFAULT_SMOKE_TIMEOUT_MS,
942
+ stdout
943
+ });
944
+ }
945
+ const hostConfigResult = await hostHelper.applyHostConfig({
946
+ host: config.host,
947
+ env,
948
+ configPath: args.configPath,
949
+ dryRun: args.dryRun
950
+ });
951
+ if (hostConfigResult && typeof hostConfigResult === "object" && hostConfigResult.configPath) {
952
+ if (hostConfigResult.dryRun) {
953
+ stdout.write(`Host config dry-run: ${hostConfigResult.configPath}\n`);
954
+ } else if (hostConfigResult.wroteFile) {
955
+ stdout.write(`Host config updated: ${hostConfigResult.configPath}\n`);
956
+ } else {
957
+ stdout.write(`Host config already up to date: ${hostConfigResult.configPath}\n`);
958
+ }
959
+ }
960
+ printOutput({
961
+ stdout,
962
+ mode: config.mode,
963
+ host: config.host,
964
+ env,
965
+ helperPath: hostHelper.path,
966
+ hostConfigResult,
967
+ profileApplyResult,
968
+ smokeResult
969
+ });
970
+ return { ok: true, code: 0, env, profileApplyResult, smokeResult };
971
+ }
972
+
973
+ export async function main(argv = process.argv.slice(2)) {
974
+ try {
975
+ const result = await runWizard({ argv });
976
+ if (!result.ok) process.exit(result.code ?? 1);
977
+ } catch (err) {
978
+ const message = err?.message ?? String(err);
979
+ process.stderr.write(message + "\n");
980
+ process.exit(1);
981
+ }
982
+ }
983
+
984
+ if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
985
+ main();
986
+ }