@paybond/kit 0.9.8 → 0.11.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 (368) hide show
  1. package/completion-presets/catalog.json +1187 -0
  2. package/completion-presets/catalog.sha256 +1 -0
  3. package/dev/trace-ui/dashboard.html +617 -0
  4. package/dist/agent/adapter.d.ts +51 -0
  5. package/dist/agent/adapter.js +66 -0
  6. package/dist/agent/attach-bundle.d.ts +37 -0
  7. package/dist/agent/attach-bundle.js +118 -0
  8. package/dist/agent/authorization-cache.d.ts +22 -0
  9. package/dist/agent/authorization-cache.js +36 -0
  10. package/dist/agent/deferred-tools.d.ts +11 -0
  11. package/dist/agent/deferred-tools.js +62 -0
  12. package/dist/agent/discover.d.ts +41 -0
  13. package/dist/agent/discover.js +147 -0
  14. package/dist/agent/evidence.d.ts +9 -0
  15. package/dist/agent/evidence.js +28 -0
  16. package/dist/agent/facade.d.ts +48 -0
  17. package/dist/agent/facade.js +112 -0
  18. package/dist/agent/gateway-trace-reporter.d.ts +28 -0
  19. package/dist/agent/gateway-trace-reporter.js +49 -0
  20. package/dist/agent/generic-runner.d.ts +14 -0
  21. package/dist/agent/generic-runner.js +49 -0
  22. package/dist/agent/generic-sandbox-demo.d.ts +36 -0
  23. package/dist/agent/generic-sandbox-demo.js +82 -0
  24. package/dist/agent/guarded-agent.d.ts +49 -0
  25. package/dist/agent/guarded-agent.js +100 -0
  26. package/dist/agent/index.d.ts +13 -0
  27. package/dist/agent/index.js +13 -0
  28. package/dist/agent/instrument.d.ts +156 -0
  29. package/dist/agent/instrument.js +442 -0
  30. package/dist/agent/interceptor.d.ts +24 -0
  31. package/dist/agent/interceptor.js +440 -0
  32. package/dist/agent/lazy-context-tools.d.ts +15 -0
  33. package/dist/agent/lazy-context-tools.js +81 -0
  34. package/dist/agent/registry-file.d.ts +39 -0
  35. package/dist/agent/registry-file.js +219 -0
  36. package/dist/agent/registry.d.ts +37 -0
  37. package/dist/agent/registry.js +128 -0
  38. package/dist/agent/run.d.ts +124 -0
  39. package/dist/agent/run.js +301 -0
  40. package/dist/agent/types.d.ts +318 -0
  41. package/dist/agent/types.js +42 -0
  42. package/dist/agent-recognition.d.ts +72 -0
  43. package/dist/agent-recognition.js +165 -0
  44. package/dist/bincode-wire.d.ts +18 -0
  45. package/dist/bincode-wire.js +93 -0
  46. package/dist/claude-agents/config.d.ts +21 -0
  47. package/dist/claude-agents/config.js +145 -0
  48. package/dist/claude-agents/index.d.ts +2 -0
  49. package/dist/claude-agents/index.js +2 -0
  50. package/dist/claude-agents/sandbox-demo.d.ts +30 -0
  51. package/dist/claude-agents/sandbox-demo.js +91 -0
  52. package/dist/cli/agent/env-quote.d.ts +1 -0
  53. package/dist/cli/agent/env-quote.js +6 -0
  54. package/dist/cli/agent/env-write.d.ts +8 -0
  55. package/dist/cli/agent/env-write.js +47 -0
  56. package/dist/cli/agent/paybond.d.ts +16 -0
  57. package/dist/cli/agent/paybond.js +55 -0
  58. package/dist/cli/agent/policy-file.d.ts +29 -0
  59. package/dist/cli/agent/policy-file.js +61 -0
  60. package/dist/cli/agent/production-evidence.d.ts +24 -0
  61. package/dist/cli/agent/production-evidence.js +98 -0
  62. package/dist/cli/agent/run-store.d.ts +30 -0
  63. package/dist/cli/agent/run-store.js +42 -0
  64. package/dist/cli/agent/run-trace-store.d.ts +39 -0
  65. package/dist/cli/agent/run-trace-store.js +143 -0
  66. package/dist/cli/agent-run-trace-table.d.ts +9 -0
  67. package/dist/cli/agent-run-trace-table.js +24 -0
  68. package/dist/cli/agent-sandbox-smoke-checklist.d.ts +9 -0
  69. package/dist/cli/agent-sandbox-smoke-checklist.js +50 -0
  70. package/dist/cli/audit-export.d.ts +7 -0
  71. package/dist/cli/audit-export.js +120 -0
  72. package/dist/cli/automation.d.ts +25 -0
  73. package/dist/cli/automation.js +297 -0
  74. package/dist/cli/body.d.ts +7 -0
  75. package/dist/cli/body.js +22 -0
  76. package/dist/cli/color.d.ts +15 -0
  77. package/dist/cli/color.js +39 -0
  78. package/dist/cli/command-spec.d.ts +13 -0
  79. package/dist/cli/command-spec.js +611 -0
  80. package/dist/cli/commands/agent.d.ts +16 -0
  81. package/dist/cli/commands/agent.js +1135 -0
  82. package/dist/cli/commands/dev.d.ts +7 -0
  83. package/dist/cli/commands/dev.js +348 -0
  84. package/dist/cli/commands/discovery.d.ts +8 -0
  85. package/dist/cli/commands/discovery.js +194 -0
  86. package/dist/cli/commands/policy.d.ts +13 -0
  87. package/dist/cli/commands/policy.js +769 -0
  88. package/dist/cli/commands/setup.d.ts +18 -0
  89. package/dist/cli/commands/setup.js +513 -0
  90. package/dist/cli/commands/workflows.d.ts +7 -0
  91. package/dist/cli/commands/workflows.js +214 -0
  92. package/dist/cli/config.d.ts +16 -0
  93. package/dist/cli/config.js +98 -0
  94. package/dist/cli/context.d.ts +22 -0
  95. package/dist/cli/context.js +110 -0
  96. package/dist/cli/credentials.d.ts +21 -0
  97. package/dist/cli/credentials.js +141 -0
  98. package/dist/cli/doctor-agent-middleware.d.ts +5 -0
  99. package/dist/cli/doctor-agent-middleware.js +49 -0
  100. package/dist/cli/doctor-agent.d.ts +15 -0
  101. package/dist/cli/doctor-agent.js +311 -0
  102. package/dist/cli/envelope.d.ts +14 -0
  103. package/dist/cli/envelope.js +46 -0
  104. package/dist/cli/globals.d.ts +23 -0
  105. package/dist/cli/globals.js +248 -0
  106. package/dist/cli/help.d.ts +3 -0
  107. package/dist/cli/help.js +83 -0
  108. package/dist/cli/mcp-install.d.ts +41 -0
  109. package/dist/cli/mcp-install.js +95 -0
  110. package/dist/cli/mcp-policy.d.ts +26 -0
  111. package/dist/cli/mcp-policy.js +110 -0
  112. package/dist/cli/mcp-verify-config.d.ts +37 -0
  113. package/dist/cli/mcp-verify-config.js +172 -0
  114. package/dist/cli/redact.d.ts +4 -0
  115. package/dist/cli/redact.js +88 -0
  116. package/dist/cli/request-id.d.ts +2 -0
  117. package/dist/cli/request-id.js +5 -0
  118. package/dist/cli/router.d.ts +2 -0
  119. package/dist/cli/router.js +378 -0
  120. package/dist/cli/smoke-deep-links.d.ts +15 -0
  121. package/dist/cli/smoke-deep-links.js +63 -0
  122. package/dist/cli/suggest.d.ts +4 -0
  123. package/dist/cli/suggest.js +58 -0
  124. package/dist/cli/support-diagnostics.d.ts +19 -0
  125. package/dist/cli/support-diagnostics.js +47 -0
  126. package/dist/cli/telemetry.d.ts +17 -0
  127. package/dist/cli/telemetry.js +94 -0
  128. package/dist/cli/types.d.ts +72 -0
  129. package/dist/cli/types.js +60 -0
  130. package/dist/cli/ux.d.ts +8 -0
  131. package/dist/cli/ux.js +164 -0
  132. package/dist/cli.d.ts +2 -0
  133. package/dist/cli.js +38 -0
  134. package/dist/completion-catalog-digest.d.ts +2 -0
  135. package/dist/completion-catalog-digest.js +2 -0
  136. package/dist/completion-catalog-integrity.d.ts +2 -0
  137. package/dist/completion-catalog-integrity.js +17 -0
  138. package/dist/completion-catalog.d.ts +49 -0
  139. package/dist/completion-catalog.js +62 -0
  140. package/dist/completion-contract-digest.d.ts +37 -0
  141. package/dist/completion-contract-digest.js +73 -0
  142. package/dist/completion-forbidden-fields.d.ts +5 -0
  143. package/dist/completion-forbidden-fields.js +26 -0
  144. package/dist/completion-init.d.ts +8 -0
  145. package/dist/completion-init.js +334 -0
  146. package/dist/completion-resolve.d.ts +21 -0
  147. package/dist/completion-resolve.js +86 -0
  148. package/dist/completion-validate-evidence.d.ts +24 -0
  149. package/dist/completion-validate-evidence.js +145 -0
  150. package/dist/dev/offline-gateway.d.ts +24 -0
  151. package/dist/dev/offline-gateway.js +102 -0
  152. package/dist/dev/trace-buffer.d.ts +61 -0
  153. package/dist/dev/trace-buffer.js +330 -0
  154. package/dist/dev/trace-security-headers.d.ts +11 -0
  155. package/dist/dev/trace-security-headers.js +16 -0
  156. package/dist/dev/trace-server.d.ts +8 -0
  157. package/dist/dev/trace-server.js +38 -0
  158. package/dist/dev/trace-ui.d.ts +4 -0
  159. package/dist/dev/trace-ui.js +25 -0
  160. package/dist/dev/wiremock-up.d.ts +15 -0
  161. package/dist/dev/wiremock-up.js +118 -0
  162. package/dist/doctor-completion.d.ts +17 -0
  163. package/dist/doctor-completion.js +428 -0
  164. package/dist/gateway-url.d.ts +7 -0
  165. package/dist/gateway-url.js +69 -0
  166. package/dist/index.d.ts +119 -2
  167. package/dist/index.js +267 -6
  168. package/dist/init.js +380 -68
  169. package/dist/langgraph/awrap-tool-call.d.ts +25 -0
  170. package/dist/langgraph/awrap-tool-call.js +81 -0
  171. package/dist/langgraph/config.d.ts +13 -0
  172. package/dist/langgraph/config.js +11 -0
  173. package/dist/langgraph/index.d.ts +4 -0
  174. package/dist/langgraph/index.js +4 -0
  175. package/dist/langgraph/sandbox-demo.d.ts +40 -0
  176. package/dist/langgraph/sandbox-demo.js +96 -0
  177. package/dist/langgraph/tool-node.d.ts +10 -0
  178. package/dist/langgraph/tool-node.js +38 -0
  179. package/dist/login.d.ts +14 -1
  180. package/dist/login.js +130 -63
  181. package/dist/mcp/index.d.ts +1 -0
  182. package/dist/mcp/index.js +1 -0
  183. package/dist/mcp/tool-surface.d.ts +25 -0
  184. package/dist/mcp/tool-surface.js +17 -0
  185. package/dist/mcp-capability-token-cache.d.ts +24 -0
  186. package/dist/mcp-capability-token-cache.js +101 -0
  187. package/dist/mcp-evidence-policy.d.ts +48 -0
  188. package/dist/mcp-evidence-policy.js +117 -0
  189. package/dist/mcp-policy-reload.d.ts +79 -0
  190. package/dist/mcp-policy-reload.js +200 -0
  191. package/dist/mcp-sep2828-evidence.d.ts +36 -0
  192. package/dist/mcp-sep2828-evidence.js +65 -0
  193. package/dist/mcp-server.d.ts +10 -0
  194. package/dist/mcp-server.js +423 -115
  195. package/dist/openai-agents/index.d.ts +40 -0
  196. package/dist/openai-agents/index.js +151 -0
  197. package/dist/openai-agents/sandbox-demo.d.ts +34 -0
  198. package/dist/openai-agents/sandbox-demo.js +118 -0
  199. package/dist/payee-evidence.js +2 -29
  200. package/dist/policy/catalog.d.ts +31 -0
  201. package/dist/policy/catalog.js +48 -0
  202. package/dist/policy/compose-utils.d.ts +3 -0
  203. package/dist/policy/compose-utils.js +4 -0
  204. package/dist/policy/compose.d.ts +20 -0
  205. package/dist/policy/compose.js +240 -0
  206. package/dist/policy/digest.d.ts +7 -0
  207. package/dist/policy/digest.js +75 -0
  208. package/dist/policy/domain.d.ts +15 -0
  209. package/dist/policy/domain.js +28 -0
  210. package/dist/policy/guardrail-spec.d.ts +17 -0
  211. package/dist/policy/guardrail-spec.js +140 -0
  212. package/dist/policy/guardrails.d.ts +48 -0
  213. package/dist/policy/guardrails.js +72 -0
  214. package/dist/policy/index.d.ts +21 -0
  215. package/dist/policy/index.js +21 -0
  216. package/dist/policy/init.d.ts +102 -0
  217. package/dist/policy/init.js +351 -0
  218. package/dist/policy/intent-spec.d.ts +52 -0
  219. package/dist/policy/intent-spec.js +176 -0
  220. package/dist/policy/json-path.d.ts +4 -0
  221. package/dist/policy/json-path.js +23 -0
  222. package/dist/policy/layers-io.d.ts +7 -0
  223. package/dist/policy/layers-io.js +28 -0
  224. package/dist/policy/load-effective.d.ts +22 -0
  225. package/dist/policy/load-effective.js +77 -0
  226. package/dist/policy/load.d.ts +85 -0
  227. package/dist/policy/load.js +164 -0
  228. package/dist/policy/merge.d.ts +29 -0
  229. package/dist/policy/merge.js +297 -0
  230. package/dist/policy/parse-text.d.ts +2 -0
  231. package/dist/policy/parse-text.js +126 -0
  232. package/dist/policy/policy-api.d.ts +45 -0
  233. package/dist/policy/policy-api.js +61 -0
  234. package/dist/policy/presets.d.ts +19 -0
  235. package/dist/policy/presets.js +66 -0
  236. package/dist/policy/registry.d.ts +7 -0
  237. package/dist/policy/registry.js +33 -0
  238. package/dist/policy/reload.d.ts +86 -0
  239. package/dist/policy/reload.js +233 -0
  240. package/dist/policy/render-yaml.d.ts +3 -0
  241. package/dist/policy/render-yaml.js +69 -0
  242. package/dist/policy/sandbox-bootstrap.d.ts +19 -0
  243. package/dist/policy/sandbox-bootstrap.js +66 -0
  244. package/dist/policy/schema.d.ts +204 -0
  245. package/dist/policy/schema.js +255 -0
  246. package/dist/policy/snapshot.d.ts +33 -0
  247. package/dist/policy/snapshot.js +23 -0
  248. package/dist/policy/validate-remote.d.ts +43 -0
  249. package/dist/policy/validate-remote.js +104 -0
  250. package/dist/policy/validate.d.ts +36 -0
  251. package/dist/policy/validate.js +150 -0
  252. package/dist/policy/watcher.d.ts +29 -0
  253. package/dist/policy/watcher.js +112 -0
  254. package/dist/principal-intent.d.ts +52 -0
  255. package/dist/principal-intent.js +193 -37
  256. package/dist/project-init.d.ts +34 -0
  257. package/dist/project-init.js +898 -0
  258. package/dist/sep2828-signature.d.ts +10 -0
  259. package/dist/sep2828-signature.js +134 -0
  260. package/dist/solutions/api.d.ts +22 -0
  261. package/dist/solutions/api.js +40 -0
  262. package/dist/solutions/catalog.d.ts +34 -0
  263. package/dist/solutions/catalog.js +129 -0
  264. package/dist/solutions/index.d.ts +2 -0
  265. package/dist/solutions/index.js +2 -0
  266. package/dist/template-init.d.ts +54 -0
  267. package/dist/template-init.js +203 -0
  268. package/dist/vercel-ai/config.d.ts +15 -0
  269. package/dist/vercel-ai/config.js +13 -0
  270. package/dist/vercel-ai/index.d.ts +4 -0
  271. package/dist/vercel-ai/index.js +4 -0
  272. package/dist/vercel-ai/sandbox-demo.d.ts +44 -0
  273. package/dist/vercel-ai/sandbox-demo.js +153 -0
  274. package/dist/vercel-ai/tool-approval.d.ts +16 -0
  275. package/dist/vercel-ai/tool-approval.js +41 -0
  276. package/dist/vercel-ai/wrap-tools.d.ts +9 -0
  277. package/dist/vercel-ai/wrap-tools.js +40 -0
  278. package/dist/x402-receipt-evidence.d.ts +29 -0
  279. package/dist/x402-receipt-evidence.js +97 -0
  280. package/dist/x402-receipt-signature.d.ts +12 -0
  281. package/dist/x402-receipt-signature.js +211 -0
  282. package/package.json +79 -4
  283. package/solutions/aws.json +17 -0
  284. package/solutions/saas.json +17 -0
  285. package/solutions/shopping.json +17 -0
  286. package/solutions/travel.json +18 -0
  287. package/templates/manifest.json +169 -0
  288. package/templates/openai-shopping-agent/.env.example +3 -0
  289. package/templates/openai-shopping-agent/.github/workflows/smoke.yml +20 -0
  290. package/templates/openai-shopping-agent/LICENSE +201 -0
  291. package/templates/openai-shopping-agent/README.md +29 -0
  292. package/templates/openai-shopping-agent/package.json +22 -0
  293. package/templates/openai-shopping-agent/paybond.policy.yaml +22 -0
  294. package/templates/openai-shopping-agent/src/index.ts +22 -0
  295. package/templates/openai-shopping-agent/src/paybond.config.ts +51 -0
  296. package/templates/openai-shopping-agent/tsconfig.json +13 -0
  297. package/templates/paybond-aws-operator/.env.example +3 -0
  298. package/templates/paybond-aws-operator/.github/workflows/smoke.yml +20 -0
  299. package/templates/paybond-aws-operator/LICENSE +201 -0
  300. package/templates/paybond-aws-operator/README.md +29 -0
  301. package/templates/paybond-aws-operator/package.json +20 -0
  302. package/templates/paybond-aws-operator/paybond.policy.yaml +22 -0
  303. package/templates/paybond-aws-operator/src/index.ts +54 -0
  304. package/templates/paybond-aws-operator/src/paybond.config.ts +51 -0
  305. package/templates/paybond-aws-operator/tsconfig.json +13 -0
  306. package/templates/paybond-claude-agents-demo/.env.example +3 -0
  307. package/templates/paybond-claude-agents-demo/.github/workflows/smoke.yml +20 -0
  308. package/templates/paybond-claude-agents-demo/LICENSE +201 -0
  309. package/templates/paybond-claude-agents-demo/README.md +29 -0
  310. package/templates/paybond-claude-agents-demo/package.json +22 -0
  311. package/templates/paybond-claude-agents-demo/paybond.policy.yaml +22 -0
  312. package/templates/paybond-claude-agents-demo/src/index.ts +22 -0
  313. package/templates/paybond-claude-agents-demo/src/paybond.config.ts +51 -0
  314. package/templates/paybond-claude-agents-demo/tsconfig.json +13 -0
  315. package/templates/paybond-invoice-agent/.env.example +3 -0
  316. package/templates/paybond-invoice-agent/.github/workflows/smoke.yml +19 -0
  317. package/templates/paybond-invoice-agent/LICENSE +201 -0
  318. package/templates/paybond-invoice-agent/README.md +29 -0
  319. package/templates/paybond-invoice-agent/app.py +27 -0
  320. package/templates/paybond-invoice-agent/package.json +6 -0
  321. package/templates/paybond-invoice-agent/paybond.policy.yaml +22 -0
  322. package/templates/paybond-invoice-agent/paybond_config.py +45 -0
  323. package/templates/paybond-invoice-agent/requirements.txt +2 -0
  324. package/templates/paybond-mcp-coding-agent/.env.example +3 -0
  325. package/templates/paybond-mcp-coding-agent/.github/workflows/smoke.yml +20 -0
  326. package/templates/paybond-mcp-coding-agent/LICENSE +201 -0
  327. package/templates/paybond-mcp-coding-agent/README.md +39 -0
  328. package/templates/paybond-mcp-coding-agent/package.json +20 -0
  329. package/templates/paybond-mcp-coding-agent/paybond.policy.yaml +25 -0
  330. package/templates/paybond-mcp-coding-agent/src/index.ts +40 -0
  331. package/templates/paybond-mcp-coding-agent/src/paybond.config.ts +51 -0
  332. package/templates/paybond-mcp-coding-agent/tsconfig.json +13 -0
  333. package/templates/paybond-openai-agents-demo/.env.example +3 -0
  334. package/templates/paybond-openai-agents-demo/.github/workflows/smoke.yml +20 -0
  335. package/templates/paybond-openai-agents-demo/LICENSE +201 -0
  336. package/templates/paybond-openai-agents-demo/README.md +29 -0
  337. package/templates/paybond-openai-agents-demo/package.json +22 -0
  338. package/templates/paybond-openai-agents-demo/paybond.policy.yaml +22 -0
  339. package/templates/paybond-openai-agents-demo/src/index.ts +22 -0
  340. package/templates/paybond-openai-agents-demo/src/paybond.config.ts +51 -0
  341. package/templates/paybond-openai-agents-demo/tsconfig.json +13 -0
  342. package/templates/paybond-procurement-agent/.env.example +3 -0
  343. package/templates/paybond-procurement-agent/.github/workflows/smoke.yml +20 -0
  344. package/templates/paybond-procurement-agent/LICENSE +201 -0
  345. package/templates/paybond-procurement-agent/README.md +29 -0
  346. package/templates/paybond-procurement-agent/package.json +20 -0
  347. package/templates/paybond-procurement-agent/paybond.policy.yaml +25 -0
  348. package/templates/paybond-procurement-agent/src/index.ts +54 -0
  349. package/templates/paybond-procurement-agent/src/paybond.config.ts +51 -0
  350. package/templates/paybond-procurement-agent/tsconfig.json +13 -0
  351. package/templates/paybond-travel-agent/.env.example +3 -0
  352. package/templates/paybond-travel-agent/.github/workflows/smoke.yml +20 -0
  353. package/templates/paybond-travel-agent/LICENSE +201 -0
  354. package/templates/paybond-travel-agent/README.md +29 -0
  355. package/templates/paybond-travel-agent/package.json +23 -0
  356. package/templates/paybond-travel-agent/paybond.policy.yaml +22 -0
  357. package/templates/paybond-travel-agent/src/index.ts +22 -0
  358. package/templates/paybond-travel-agent/src/paybond.config.ts +51 -0
  359. package/templates/paybond-travel-agent/tsconfig.json +13 -0
  360. package/templates/paybond-vercel-shopping-agent/.env.example +3 -0
  361. package/templates/paybond-vercel-shopping-agent/.github/workflows/smoke.yml +20 -0
  362. package/templates/paybond-vercel-shopping-agent/LICENSE +201 -0
  363. package/templates/paybond-vercel-shopping-agent/README.md +29 -0
  364. package/templates/paybond-vercel-shopping-agent/package.json +22 -0
  365. package/templates/paybond-vercel-shopping-agent/paybond.policy.yaml +22 -0
  366. package/templates/paybond-vercel-shopping-agent/src/index.ts +22 -0
  367. package/templates/paybond-vercel-shopping-agent/src/paybond.config.ts +51 -0
  368. package/templates/paybond-vercel-shopping-agent/tsconfig.json +13 -0
@@ -0,0 +1,214 @@
1
+ import { resolveJsonBody } from "../body.js";
2
+ import { buildListQueryParams, extractNextCursor, partialResultsWarning, } from "../automation.js";
3
+ import { commandPath, requireConfirmation, withGateway } from "../context.js";
4
+ import { consumeFlag, parseOptionalNonNegativeInt, parseRequiredNonNegativeInt } from "../globals.js";
5
+ import { maskApiKey, redactSensitiveFields } from "../redact.js";
6
+ import { CliError } from "../types.js";
7
+ export async function handleKeys(ctx, subcommand, argv) {
8
+ return withGateway(ctx, async (gateway) => {
9
+ if (subcommand === "list") {
10
+ const limitFlag = consumeFlag(argv, "--limit");
11
+ const cursorFlag = consumeFlag(argv, "--cursor");
12
+ const params = buildListQueryParams(limitFlag.value, cursorFlag.value, { limit: "50" });
13
+ const body = await gateway.getJson(`/v1/admin/api-keys?${params.toString()}`);
14
+ const items = Array.isArray(body.items) ? body.items : [];
15
+ const keys = items.map((item) => {
16
+ const row = item;
17
+ return {
18
+ key_id: String(row.key_id ?? row.id ?? ""),
19
+ key_masked: maskApiKey(`paybond_sk_${String(row.environment ?? "sandbox")}_${String(row.key_id ?? "redacted")}_redacted`),
20
+ role: String(row.service_account_role ?? ""),
21
+ created_at: String(row.created_at ?? ""),
22
+ expires_at: row.expires_at ? String(row.expires_at) : null,
23
+ status: row.revoked_at ? "revoked" : "active",
24
+ };
25
+ });
26
+ const nextCursor = extractNextCursor(body);
27
+ const warnings = partialResultsWarning(nextCursor) ? [partialResultsWarning(nextCursor)] : undefined;
28
+ const data = { keys };
29
+ if (nextCursor) {
30
+ data.next_cursor = nextCursor;
31
+ }
32
+ return { data, warnings };
33
+ }
34
+ if (subcommand === "create") {
35
+ const nameFlag = consumeFlag(argv, "--name");
36
+ const roleFlag = consumeFlag(argv, "--role");
37
+ const labelFlag = consumeFlag(argv, "--label");
38
+ if (!nameFlag.value || !roleFlag.value) {
39
+ throw new CliError("keys create requires --name and --role", { category: "usage", code: "cli.usage.missing_args" });
40
+ }
41
+ const body = await gateway.postJson("/v1/admin/api-keys", {
42
+ service_account_name: nameFlag.value,
43
+ service_account_role: roleFlag.value,
44
+ label: labelFlag.value ?? "",
45
+ });
46
+ const item = (body.item ?? {});
47
+ const rawApiKey = typeof body.api_key === "string" ? body.api_key : "";
48
+ const data = {
49
+ key_id: String(item.key_id ?? item.id ?? ""),
50
+ key_masked: rawApiKey ? maskApiKey(rawApiKey) : maskApiKey(""),
51
+ role: String(item.service_account_role ?? roleFlag.value),
52
+ created_at: String(item.created_at ?? ""),
53
+ status: "active",
54
+ };
55
+ if (rawApiKey) {
56
+ data.api_key = rawApiKey;
57
+ }
58
+ return { data };
59
+ }
60
+ const keyId = argv[0];
61
+ if (!keyId) {
62
+ throw new CliError(`keys ${subcommand} requires <key_id>`, { category: "usage", code: "cli.usage.missing_key_id" });
63
+ }
64
+ if (subcommand === "rotate") {
65
+ requireConfirmation(ctx.globals, "rotate API key");
66
+ const body = await gateway.postJson(`/v1/admin/api-keys/${encodeURIComponent(keyId)}/rotate`);
67
+ const item = (body.item ?? {});
68
+ const rawApiKey = typeof body.api_key === "string" ? body.api_key : "";
69
+ const data = {
70
+ key_id: String(item.key_id ?? keyId),
71
+ key_masked: rawApiKey ? maskApiKey(rawApiKey) : maskApiKey(""),
72
+ rotated: true,
73
+ };
74
+ if (rawApiKey) {
75
+ data.api_key = rawApiKey;
76
+ }
77
+ return { data };
78
+ }
79
+ if (subcommand === "revoke") {
80
+ requireConfirmation(ctx.globals, "revoke API key");
81
+ await gateway.deleteJson(`/v1/admin/api-keys/${encodeURIComponent(keyId)}`);
82
+ return { data: { key_id: keyId, revoked: true } };
83
+ }
84
+ throw new CliError(`unknown keys subcommand: ${subcommand}`, { category: "usage", code: "cli.usage.unknown_command" });
85
+ });
86
+ }
87
+ export async function handleIntents(ctx, subcommand, argv) {
88
+ return withGateway(ctx, async (gateway) => {
89
+ if (subcommand === "list") {
90
+ const statusFlag = consumeFlag(argv, "--status");
91
+ const limitFlag = consumeFlag(argv, "--limit");
92
+ const cursorFlag = consumeFlag(argv, "--cursor");
93
+ const params = buildListQueryParams(limitFlag.value, cursorFlag.value);
94
+ if (statusFlag.value) {
95
+ params.set("status", statusFlag.value);
96
+ }
97
+ const body = await gateway.getJson(`/harbor/operator/v1/intents?${params.toString()}`);
98
+ const redacted = redactSensitiveFields(body);
99
+ const nextCursor = extractNextCursor(redacted);
100
+ const warnings = partialResultsWarning(nextCursor) ? [partialResultsWarning(nextCursor)] : undefined;
101
+ if (nextCursor && !redacted.next_cursor) {
102
+ redacted.next_cursor = nextCursor;
103
+ }
104
+ return { data: redacted, warnings };
105
+ }
106
+ const intentId = argv[0];
107
+ if (subcommand === "get") {
108
+ if (!intentId) {
109
+ throw new CliError("intents get requires <intent_id>", { category: "usage", code: "cli.usage.missing_intent_id" });
110
+ }
111
+ const body = await gateway.getJson(`/harbor/operator/v1/intents/${encodeURIComponent(intentId)}`);
112
+ return { data: redactSensitiveFields(body) };
113
+ }
114
+ if (subcommand === "create") {
115
+ const { payload } = await resolveJsonBody(argv, {
116
+ missingMessage: "intents create requires --body <json-file> or --stdin",
117
+ });
118
+ const body = await gateway.postJson("/harbor/intents", payload);
119
+ return { data: redactSensitiveFields(body) };
120
+ }
121
+ if (!intentId) {
122
+ throw new CliError(`intents ${subcommand} requires <intent_id>`, { category: "usage", code: "cli.usage.missing_intent_id" });
123
+ }
124
+ if (subcommand === "fund") {
125
+ const { payload } = await resolveJsonBody(argv, { required: false });
126
+ const body = await gateway.postJson(`/harbor/intents/${encodeURIComponent(intentId)}/fund`, payload);
127
+ return { data: redactSensitiveFields(body) };
128
+ }
129
+ if (subcommand === "evidence") {
130
+ const { payload } = await resolveJsonBody(argv, {
131
+ missingMessage: "intents evidence requires --body <json-file> or --stdin",
132
+ });
133
+ const body = await gateway.postJson(`/harbor/intents/${encodeURIComponent(intentId)}/evidence`, payload);
134
+ return { data: redactSensitiveFields(body) };
135
+ }
136
+ if (subcommand === "settlement-confirm") {
137
+ const { payload } = await resolveJsonBody(argv, { required: false });
138
+ const body = await gateway.postJson(`/harbor/intents/${encodeURIComponent(intentId)}/settlement/confirm`, payload);
139
+ return { data: redactSensitiveFields(body) };
140
+ }
141
+ throw new CliError(`unknown intents subcommand: ${subcommand}`, { category: "usage", code: "cli.usage.unknown_command" });
142
+ });
143
+ }
144
+ export async function handleGuardrails(ctx, subcommand, argv) {
145
+ return withGateway(ctx, async (gateway) => {
146
+ if (subcommand === "bootstrap") {
147
+ const operationFlag = consumeFlag(argv, "--operation");
148
+ const spendFlag = consumeFlag(argv, "--requested-spend-cents");
149
+ const presetFlag = consumeFlag(argv, "--completion-preset");
150
+ if (!operationFlag.value || !spendFlag.value) {
151
+ throw new CliError("guardrails bootstrap requires --operation and --requested-spend-cents", { category: "usage", code: "cli.usage.missing_args" });
152
+ }
153
+ const spendCents = parseRequiredNonNegativeInt(spendFlag.value, "--requested-spend-cents");
154
+ const bodyPayload = {
155
+ operation: operationFlag.value,
156
+ requested_spend_cents: spendCents,
157
+ };
158
+ if (presetFlag.value) {
159
+ bodyPayload.completion_preset = presetFlag.value;
160
+ }
161
+ const body = await gateway.postJson("/v1/sandbox/guardrails/bootstrap", bodyPayload);
162
+ return {
163
+ data: redactSensitiveFields({
164
+ tenant_id: String(body.tenant_id ?? ""),
165
+ intent_id: String(body.intent_id ?? ""),
166
+ capability_token: String(body.capability_token ?? ""),
167
+ operation: String(body.operation ?? operationFlag.value),
168
+ requested_spend_cents: Number(body.requested_spend_cents ?? spendCents),
169
+ sandbox_lifecycle_status: String(body.sandbox_lifecycle_status ?? ""),
170
+ }),
171
+ };
172
+ }
173
+ if (subcommand === "evidence") {
174
+ const intentFlag = consumeFlag(argv, "--intent-id");
175
+ if (!intentFlag.value) {
176
+ throw new CliError("guardrails evidence requires --intent-id and --body <json-file>", { category: "usage", code: "cli.usage.missing_args" });
177
+ }
178
+ const { payload } = await resolveJsonBody(argv, {
179
+ missingMessage: "guardrails evidence requires --intent-id and --body <json-file> or --stdin",
180
+ });
181
+ const body = await gateway.postJson(`/v1/sandbox/guardrails/${encodeURIComponent(intentFlag.value)}/evidence`, payload);
182
+ return { data: body };
183
+ }
184
+ throw new CliError(`unknown guardrails subcommand: ${subcommand}`, { category: "usage", code: "cli.usage.unknown_command" });
185
+ });
186
+ }
187
+ export async function handleSpendAuthorize(ctx, argv) {
188
+ return withGateway(ctx, async (gateway) => {
189
+ const intentFlag = consumeFlag(argv, "--intent-id");
190
+ const tokenFlag = consumeFlag(argv, "--token");
191
+ const operationFlag = consumeFlag(argv, "--operation");
192
+ const spendFlag = consumeFlag(argv, "--requested-spend-cents");
193
+ if (!intentFlag.value || !tokenFlag.value || !operationFlag.value) {
194
+ throw new CliError("spend authorize requires --intent-id, --token, and --operation", { category: "usage", code: "cli.usage.missing_args" });
195
+ }
196
+ const spendCents = parseOptionalNonNegativeInt(spendFlag.value, "--requested-spend-cents");
197
+ const body = await gateway.postJson("/verify", {
198
+ intent_id: intentFlag.value,
199
+ token: tokenFlag.value,
200
+ operation: operationFlag.value,
201
+ requested_spend_cents: spendCents,
202
+ });
203
+ return {
204
+ data: {
205
+ authorized: Boolean(body.allow),
206
+ intent_id: String(body.intent_id ?? intentFlag.value),
207
+ operation: operationFlag.value,
208
+ requested_spend_cents: spendCents,
209
+ deny_reason: body.allow ? undefined : String(body.message ?? body.code ?? "denied"),
210
+ },
211
+ };
212
+ });
213
+ }
214
+ export { commandPath };
@@ -0,0 +1,16 @@
1
+ export type CliConfigFile = {
2
+ install_id?: string;
3
+ telemetry?: boolean;
4
+ profiles?: Record<string, {
5
+ env_file?: string;
6
+ gateway?: string;
7
+ }>;
8
+ values?: Record<string, string>;
9
+ };
10
+ export declare function configFilePath(): string;
11
+ export declare function loadConfigFile(): Promise<CliConfigFile>;
12
+ export declare function saveConfigFile(config: CliConfigFile): Promise<void>;
13
+ export declare function resolveConfigValue(key: string, profile?: string): Promise<string | undefined>;
14
+ export declare function setConfigValue(key: string, value: string, profile?: string): Promise<void>;
15
+ export declare function unsetConfigValue(key: string, profile?: string): Promise<boolean>;
16
+ export declare function listConfigEntries(profile?: string): Promise<Record<string, string>>;
@@ -0,0 +1,98 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { redactConfigValue } from "./redact.js";
3
+ import { validateCliGateway } from "./globals.js";
4
+ import { CliError } from "./types.js";
5
+ export function configFilePath() {
6
+ const home = process.env.HOME?.trim() || process.env.USERPROFILE?.trim() || "";
7
+ const base = process.env.XDG_CONFIG_HOME?.trim() || (home ? `${home}/.config` : ".config");
8
+ return `${base.replace(/\/+$/, "")}/paybond/config.json`;
9
+ }
10
+ export async function loadConfigFile() {
11
+ try {
12
+ const raw = await readFile(configFilePath(), "utf8");
13
+ const parsed = JSON.parse(raw);
14
+ return parsed && typeof parsed === "object" ? parsed : {};
15
+ }
16
+ catch (err) {
17
+ if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
18
+ return {};
19
+ }
20
+ throw new CliError(`unable to read CLI config: ${err instanceof Error ? err.message : String(err)}`, {
21
+ category: "environment",
22
+ code: "cli.environment.config_read_failed",
23
+ });
24
+ }
25
+ }
26
+ export async function saveConfigFile(config) {
27
+ const configPath = configFilePath();
28
+ const dir = configPath.replace(/\/[^/]+$/, "");
29
+ await mkdir(dir, { recursive: true });
30
+ await writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
31
+ }
32
+ export async function resolveConfigValue(key, profile) {
33
+ const config = await loadConfigFile();
34
+ if (profile) {
35
+ const profileValues = config.profiles?.[profile];
36
+ if (profileValues && key in profileValues) {
37
+ const value = profileValues[key];
38
+ return typeof value === "string" ? value : undefined;
39
+ }
40
+ }
41
+ return config.values?.[key];
42
+ }
43
+ export async function setConfigValue(key, value, profile) {
44
+ const storedValue = key.toLowerCase() === "gateway" ? validateCliGateway(value) : value;
45
+ const config = await loadConfigFile();
46
+ if (profile) {
47
+ config.profiles ??= {};
48
+ config.profiles[profile] ??= {};
49
+ config.profiles[profile][key] = storedValue;
50
+ }
51
+ else {
52
+ config.values ??= {};
53
+ config.values[key] = storedValue;
54
+ }
55
+ await saveConfigFile(config);
56
+ }
57
+ export async function unsetConfigValue(key, profile) {
58
+ const config = await loadConfigFile();
59
+ if (profile) {
60
+ const profileValues = config.profiles?.[profile];
61
+ if (!profileValues || !(key in profileValues)) {
62
+ return false;
63
+ }
64
+ delete profileValues[key];
65
+ await saveConfigFile(config);
66
+ return true;
67
+ }
68
+ if (!config.values || !(key in config.values)) {
69
+ return false;
70
+ }
71
+ delete config.values[key];
72
+ await saveConfigFile(config);
73
+ return true;
74
+ }
75
+ export async function listConfigEntries(profile) {
76
+ const config = await loadConfigFile();
77
+ const entries = {};
78
+ if (profile) {
79
+ const profileValues = config.profiles?.[profile] ?? {};
80
+ for (const [key, value] of Object.entries(profileValues)) {
81
+ if (typeof value === "string") {
82
+ entries[key] = redactConfigValue(key, value);
83
+ }
84
+ }
85
+ return entries;
86
+ }
87
+ for (const [key, value] of Object.entries(config.values ?? {})) {
88
+ entries[key] = redactConfigValue(key, value);
89
+ }
90
+ for (const [profileName, profileValues] of Object.entries(config.profiles ?? {})) {
91
+ for (const [key, value] of Object.entries(profileValues ?? {})) {
92
+ if (typeof value === "string") {
93
+ entries[`profiles.${profileName}.${key}`] = redactConfigValue(key, value);
94
+ }
95
+ }
96
+ }
97
+ return entries;
98
+ }
@@ -0,0 +1,22 @@
1
+ import { type CliDependencies, type CommandResult, type GlobalOptions, type Writable } from "./types.js";
2
+ export type GatewayJson = Record<string, unknown>;
3
+ export type GatewayClient = {
4
+ getJson(path: string): Promise<GatewayJson>;
5
+ postJson(path: string, body?: GatewayJson): Promise<GatewayJson>;
6
+ deleteJson(path: string): Promise<GatewayJson>;
7
+ };
8
+ export declare function gatewayUrl(base: string, path: string): string;
9
+ export declare function createGatewayClient(globals: GlobalOptions, apiKey: string, fetchFn: typeof fetch, extraHeaders?: Record<string, string>): GatewayClient;
10
+ export type CliContext = {
11
+ globals: GlobalOptions;
12
+ cwd: string;
13
+ stdout: Writable;
14
+ stderr: Writable;
15
+ fetch: typeof fetch;
16
+ deps: CliDependencies;
17
+ gateway?: GatewayClient;
18
+ };
19
+ export declare function withGateway(ctx: CliContext, handler: (gateway: GatewayClient, apiKey: string) => Promise<CommandResult>, extraHeaders?: Record<string, string>): Promise<CommandResult>;
20
+ export declare function requireConfirmation(globals: GlobalOptions, action: string): void;
21
+ export declare function commandPath(parts: string[]): string;
22
+ export declare function createContext(globals: GlobalOptions, deps?: CliDependencies): CliContext;
@@ -0,0 +1,110 @@
1
+ import { resolveApiKeyWithMeta } from "./credentials.js";
2
+ import { requireSecureGatewayUrl } from "../gateway-url.js";
3
+ import { CliError, exitCodeForHttpStatus, } from "./types.js";
4
+ export function gatewayUrl(base, path) {
5
+ return `${requireSecureGatewayUrl(base)}${path.startsWith("/") ? path : `/${path}`}`;
6
+ }
7
+ function parseGatewayErrorBody(body, status) {
8
+ const nested = body.error;
9
+ const gatewayCode = nested && typeof nested === "object" && !Array.isArray(nested)
10
+ ? String(nested.code ?? "")
11
+ : String(body.code ?? "");
12
+ const gatewayMessage = nested && typeof nested === "object" && !Array.isArray(nested)
13
+ ? String(nested.message ?? "")
14
+ : String(body.message ?? body.error_description ?? "gateway request failed");
15
+ const mapped = exitCodeForHttpStatus(status);
16
+ return new CliError(gatewayMessage || `Gateway HTTP ${status}`, {
17
+ category: mapped.category,
18
+ code: gatewayCode || `cli.gateway.http_${status}`,
19
+ exitCode: mapped.exitCode,
20
+ details: {
21
+ gateway_status: status,
22
+ gateway_code: gatewayCode || undefined,
23
+ },
24
+ });
25
+ }
26
+ async function parseJsonResponse(response) {
27
+ const text = await response.text();
28
+ if (!text.trim()) {
29
+ return {};
30
+ }
31
+ try {
32
+ const parsed = JSON.parse(text);
33
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
34
+ return parsed;
35
+ }
36
+ }
37
+ catch {
38
+ // fall through
39
+ }
40
+ throw new CliError(`Gateway returned non-JSON response (${response.status}).`, {
41
+ category: "gateway",
42
+ code: "cli.gateway.non_json",
43
+ exitCode: 5,
44
+ details: { gateway_status: response.status },
45
+ });
46
+ }
47
+ export function createGatewayClient(globals, apiKey, fetchFn, extraHeaders = {}) {
48
+ const headers = {
49
+ authorization: `Bearer ${apiKey}`,
50
+ "content-type": "application/json",
51
+ "x-request-id": globals.requestId,
52
+ ...extraHeaders,
53
+ };
54
+ async function request(method, path, body) {
55
+ let response;
56
+ try {
57
+ response = await fetchFn(gatewayUrl(globals.gateway, path), {
58
+ method,
59
+ headers,
60
+ body: body ? JSON.stringify(body) : undefined,
61
+ });
62
+ }
63
+ catch (err) {
64
+ throw new CliError(err instanceof Error ? err.message : String(err), {
65
+ category: "network",
66
+ code: "cli.network.request_failed",
67
+ exitCode: 5,
68
+ });
69
+ }
70
+ const parsed = await parseJsonResponse(response);
71
+ if (!response.ok) {
72
+ throw parseGatewayErrorBody(parsed, response.status);
73
+ }
74
+ return parsed;
75
+ }
76
+ return {
77
+ getJson: (path) => request("GET", path),
78
+ postJson: (path, body) => request("POST", path, body),
79
+ deleteJson: (path) => request("DELETE", path),
80
+ };
81
+ }
82
+ export async function withGateway(ctx, handler, extraHeaders = {}) {
83
+ const resolved = await resolveApiKeyWithMeta(ctx.globals, ctx.cwd);
84
+ const gateway = createGatewayClient(ctx.globals, resolved.apiKey, ctx.fetch, extraHeaders);
85
+ const result = await handler(gateway, resolved.apiKey);
86
+ const warnings = [...(result.warnings ?? []), ...resolved.warnings];
87
+ return warnings.length ? { ...result, warnings } : result;
88
+ }
89
+ export function requireConfirmation(globals, action) {
90
+ if (!globals.yes) {
91
+ throw new CliError(`confirmation required; re-run with --yes to ${action}`, {
92
+ category: "confirmation_required",
93
+ code: "cli.confirmation.required",
94
+ exitCode: 4,
95
+ });
96
+ }
97
+ }
98
+ export function commandPath(parts) {
99
+ return parts.join(" ");
100
+ }
101
+ export function createContext(globals, deps = {}) {
102
+ return {
103
+ globals,
104
+ cwd: deps.cwd ?? process.cwd(),
105
+ stdout: deps.stdout ?? process.stdout,
106
+ stderr: deps.stderr ?? process.stderr,
107
+ fetch: deps.fetch ?? fetch,
108
+ deps,
109
+ };
110
+ }
@@ -0,0 +1,21 @@
1
+ import { type GlobalOptions } from "./types.js";
2
+ export declare function readEnvFileValue(body: string, key: string): string | undefined;
3
+ export declare function loadEnvFile(envFile: string, cwd: string): Promise<string | undefined>;
4
+ export type ResolvedApiKey = {
5
+ apiKey: string;
6
+ warnings: string[];
7
+ };
8
+ export declare function resolveApiKeyWithMeta(globals: GlobalOptions, cwd: string): Promise<ResolvedApiKey>;
9
+ export declare function resolveApiKey(globals: GlobalOptions, cwd: string): Promise<string>;
10
+ export type CredentialSourceDescription = {
11
+ source: "process_env" | "env_file" | "missing";
12
+ env_file?: string;
13
+ profile?: string;
14
+ key_masked?: string;
15
+ };
16
+ export declare function describeCredentialSource(globals: GlobalOptions, cwd: string): Promise<CredentialSourceDescription>;
17
+ export declare function assertApiKeyShape(apiKey: string): void;
18
+ export declare function resolvedDefaultsForDoctor(globals: GlobalOptions): {
19
+ gateway: string;
20
+ envFile: string;
21
+ };
@@ -0,0 +1,141 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { resolveConfigValue } from "./config.js";
4
+ import { CLI_WARN_ENV_FALLBACK, formatWarning } from "./automation.js";
5
+ import { DEFAULT_ENV_FILE, DEFAULT_GATEWAY, validateCliGateway } from "./globals.js";
6
+ import { CliError } from "./types.js";
7
+ function resolvePath(cwd, envFile) {
8
+ return path.isAbsolute(envFile) ? path.resolve(envFile) : path.resolve(cwd, envFile);
9
+ }
10
+ function quoteTrim(value) {
11
+ const trimmed = value.trim();
12
+ if ((trimmed.startsWith('"') && trimmed.endsWith('"')) || (trimmed.startsWith("'") && trimmed.endsWith("'"))) {
13
+ return trimmed.slice(1, -1);
14
+ }
15
+ return trimmed;
16
+ }
17
+ export function readEnvFileValue(body, key) {
18
+ const prefix = `${key}=`;
19
+ const exportPrefix = `export ${key}=`;
20
+ for (const rawLine of body.split(/\r?\n/)) {
21
+ const line = rawLine.trim();
22
+ let value = "";
23
+ if (line.startsWith(exportPrefix)) {
24
+ value = line.slice(exportPrefix.length).trim();
25
+ }
26
+ else if (line.startsWith(prefix)) {
27
+ value = line.slice(prefix.length).trim();
28
+ }
29
+ else {
30
+ continue;
31
+ }
32
+ const unquoted = quoteTrim(value);
33
+ return unquoted || undefined;
34
+ }
35
+ return undefined;
36
+ }
37
+ export async function loadEnvFile(envFile, cwd) {
38
+ const envPath = resolvePath(cwd, envFile);
39
+ try {
40
+ const body = await readFile(envPath, "utf8");
41
+ return readEnvFileValue(body, "PAYBOND_API_KEY");
42
+ }
43
+ catch (err) {
44
+ if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
45
+ return undefined;
46
+ }
47
+ throw new CliError(`unable to read env file ${envPath}`, {
48
+ category: "environment",
49
+ code: "cli.environment.env_file_read_failed",
50
+ details: { env_file: envPath },
51
+ });
52
+ }
53
+ }
54
+ export async function resolveApiKeyWithMeta(globals, cwd) {
55
+ const warnings = [];
56
+ const fromProcess = process.env.PAYBOND_API_KEY?.trim();
57
+ if (fromProcess) {
58
+ warnings.push(formatWarning(CLI_WARN_ENV_FALLBACK, "using PAYBOND_API_KEY from process environment"));
59
+ return { apiKey: fromProcess, warnings };
60
+ }
61
+ let envFile = globals.envFile;
62
+ let gateway = globals.gateway;
63
+ if (globals.profile) {
64
+ const profileEnvFile = await resolveConfigValue("env_file", globals.profile);
65
+ const profileGateway = await resolveConfigValue("gateway", globals.profile);
66
+ if (profileEnvFile) {
67
+ envFile = profileEnvFile;
68
+ warnings.push(formatWarning(CLI_WARN_ENV_FALLBACK, `using profile ${globals.profile} env_file`));
69
+ }
70
+ if (profileGateway) {
71
+ gateway = validateCliGateway(profileGateway);
72
+ warnings.push(formatWarning(CLI_WARN_ENV_FALLBACK, `using profile ${globals.profile} gateway`));
73
+ }
74
+ }
75
+ globals.envFile = envFile;
76
+ globals.gateway = gateway;
77
+ const fromFile = await loadEnvFile(envFile, cwd);
78
+ if (fromFile) {
79
+ return { apiKey: fromFile, warnings };
80
+ }
81
+ throw new CliError("missing PAYBOND_API_KEY; run paybond login or set PAYBOND_API_KEY", {
82
+ category: "auth",
83
+ code: "cli.auth.missing_api_key",
84
+ exitCode: 2,
85
+ details: { env_file: resolvePath(cwd, envFile) },
86
+ });
87
+ }
88
+ export async function resolveApiKey(globals, cwd) {
89
+ const resolved = await resolveApiKeyWithMeta(globals, cwd);
90
+ return resolved.apiKey;
91
+ }
92
+ export async function describeCredentialSource(globals, cwd) {
93
+ const { maskApiKey } = await import("./redact.js");
94
+ const fromProcess = process.env.PAYBOND_API_KEY?.trim();
95
+ if (fromProcess) {
96
+ return { source: "process_env", key_masked: maskApiKey(fromProcess) };
97
+ }
98
+ let envFile = globals.envFile;
99
+ const profile = globals.profile;
100
+ if (globals.profile) {
101
+ const profileEnvFile = await resolveConfigValue("env_file", globals.profile);
102
+ if (profileEnvFile) {
103
+ envFile = profileEnvFile;
104
+ }
105
+ }
106
+ const envPath = resolvePath(cwd, envFile);
107
+ try {
108
+ const fromFile = await loadEnvFile(envFile, cwd);
109
+ if (fromFile) {
110
+ return {
111
+ source: "env_file",
112
+ env_file: envPath,
113
+ profile: profile ?? undefined,
114
+ key_masked: maskApiKey(fromFile),
115
+ };
116
+ }
117
+ }
118
+ catch {
119
+ // fall through to missing
120
+ }
121
+ return {
122
+ source: "missing",
123
+ env_file: envPath,
124
+ profile: profile ?? undefined,
125
+ };
126
+ }
127
+ export function assertApiKeyShape(apiKey) {
128
+ if (!apiKey.startsWith("paybond_sk_")) {
129
+ throw new CliError("PAYBOND_API_KEY has an unexpected shape", {
130
+ category: "auth",
131
+ code: "cli.auth.invalid_api_key_shape",
132
+ exitCode: 2,
133
+ });
134
+ }
135
+ }
136
+ export function resolvedDefaultsForDoctor(globals) {
137
+ return {
138
+ gateway: globals.gateway || DEFAULT_GATEWAY,
139
+ envFile: globals.envFile || DEFAULT_ENV_FILE,
140
+ };
141
+ }
@@ -0,0 +1,5 @@
1
+ import type { CliContext } from "./context.js";
2
+ import type { DoctorCheck } from "./doctor-agent.js";
3
+ export declare const AGENT_MIDDLEWARE_SMOKE_NEXT = "paybond agent sandbox smoke --operation paid-tool --requested-spend-cents 100 --evidence-preset cost_and_completion --result-body '{\"status\":\"ok\",\"cost_cents\":100}' --format json";
4
+ /** Run sandbox middleware smoke as a doctor --agent check (uses ctx.fetch / project cwd). */
5
+ export declare function runAgentMiddlewareDoctorCheck(ctx: CliContext, apiKey: string): Promise<DoctorCheck>;