@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,145 @@
1
+ import { Ajv2020 } from "ajv/dist/2020.js";
2
+ import { getCompletionPreset } from "./completion-catalog.js";
3
+ import { forbiddenFieldsInEvidence, forbiddenFieldsInVendorPayload, } from "./completion-forbidden-fields.js";
4
+ import { isVendorPack, mapVendorEvidenceToCanonical, resolveCompletionPreset, vendorEvidenceSchema, } from "./completion-resolve.js";
5
+ function pushDriftKind(kinds, kind) {
6
+ if (!kinds.includes(kind)) {
7
+ kinds.push(kind);
8
+ }
9
+ }
10
+ function classifyAjvError(error) {
11
+ const message = error.message ?? "";
12
+ if (!error.instancePath && message.includes("required")) {
13
+ return "missing_field";
14
+ }
15
+ if (message.includes("required")) {
16
+ return "missing_field";
17
+ }
18
+ return "type_mismatch";
19
+ }
20
+ function validateJsonSchema(schema, instance) {
21
+ const ajv = new Ajv2020({ allErrors: true, strict: false });
22
+ const validate = ajv.compile(schema);
23
+ if (validate(instance)) {
24
+ return [];
25
+ }
26
+ const kinds = [];
27
+ for (const error of validate.errors ?? []) {
28
+ pushDriftKind(kinds, classifyAjvError(error));
29
+ }
30
+ return kinds.length > 0 ? kinds : ["type_mismatch"];
31
+ }
32
+ function missingQualityFields(payload, qualityFields) {
33
+ if (!qualityFields?.length) {
34
+ return [];
35
+ }
36
+ return qualityFields.filter((field) => {
37
+ const value = payload[field];
38
+ return value === undefined || value === null;
39
+ });
40
+ }
41
+ /**
42
+ * Validates vendor and canonical completion evidence against catalog JSON Schemas.
43
+ * Signal-only: returns drift metadata without throwing on schema mismatch.
44
+ */
45
+ export function validateCompletionEvidence(input) {
46
+ const preset = getCompletionPreset(input.presetId);
47
+ const resolved = resolveCompletionPreset(input.presetId);
48
+ const contract = preset.vendor_contract;
49
+ const driftKinds = [];
50
+ let vendorSchemaOk = true;
51
+ let canonicalSchemaOk = true;
52
+ let canonicalPayload = input.canonicalPayload;
53
+ if (!canonicalPayload && input.vendorPayload && isVendorPack(preset)) {
54
+ canonicalPayload = mapVendorEvidenceToCanonical(preset, input.vendorPayload);
55
+ }
56
+ if (!canonicalPayload && !isVendorPack(preset) && input.vendorPayload) {
57
+ canonicalPayload = input.vendorPayload;
58
+ }
59
+ let packStale = false;
60
+ if (input.frozenVendorApiVersion && contract?.api_version && input.frozenVendorApiVersion !== contract.api_version) {
61
+ packStale = true;
62
+ pushDriftKind(driftKinds, "pack_stale");
63
+ }
64
+ if (input.frozenVendorSchemaDigestHex &&
65
+ contract?.schema_digest_hex &&
66
+ input.frozenVendorSchemaDigestHex !== contract.schema_digest_hex) {
67
+ packStale = true;
68
+ pushDriftKind(driftKinds, "pack_stale");
69
+ }
70
+ if (input.frozenCanonicalSchemaDigestHex &&
71
+ contract?.canonical_schema_digest_hex &&
72
+ input.frozenCanonicalSchemaDigestHex !== contract.canonical_schema_digest_hex) {
73
+ packStale = true;
74
+ pushDriftKind(driftKinds, "pack_stale");
75
+ }
76
+ if (canonicalPayload) {
77
+ const canonicalKinds = validateJsonSchema(resolved.evidenceSchema, canonicalPayload);
78
+ if (canonicalKinds.length > 0) {
79
+ canonicalSchemaOk = false;
80
+ for (const kind of canonicalKinds) {
81
+ pushDriftKind(driftKinds, kind);
82
+ }
83
+ }
84
+ }
85
+ else if (!isVendorPack(preset)) {
86
+ canonicalSchemaOk = false;
87
+ pushDriftKind(driftKinds, "missing_field");
88
+ }
89
+ const vendorSchema = vendorEvidenceSchema(preset);
90
+ if (isVendorPack(preset)) {
91
+ if (input.vendorPayload && vendorSchema && !packStale) {
92
+ const vendorKinds = validateJsonSchema(vendorSchema, input.vendorPayload);
93
+ if (vendorKinds.length > 0) {
94
+ vendorSchemaOk = false;
95
+ for (const kind of vendorKinds) {
96
+ pushDriftKind(driftKinds, kind);
97
+ }
98
+ }
99
+ }
100
+ else if (!input.vendorPayload) {
101
+ vendorSchemaOk = false;
102
+ pushDriftKind(driftKinds, "missing_field");
103
+ }
104
+ }
105
+ const qualityTarget = input.vendorPayload ?? canonicalPayload;
106
+ const qualityMissing = qualityTarget && contract?.quality_fields
107
+ ? missingQualityFields(qualityTarget, contract.quality_fields)
108
+ : [];
109
+ for (const _field of qualityMissing) {
110
+ pushDriftKind(driftKinds, "quality_field_missing");
111
+ }
112
+ const forbidden = preset.forbidden_evidence_fields;
113
+ const forbiddenHits = [];
114
+ if (forbidden?.length) {
115
+ if (input.vendorPayload) {
116
+ forbiddenHits.push(...forbiddenFieldsInVendorPayload(preset, input.vendorPayload, forbidden));
117
+ }
118
+ if (canonicalPayload) {
119
+ for (const field of forbiddenFieldsInEvidence(canonicalPayload, forbidden)) {
120
+ if (!forbiddenHits.includes(field)) {
121
+ forbiddenHits.push(field);
122
+ }
123
+ }
124
+ }
125
+ }
126
+ for (const _field of forbiddenHits) {
127
+ if (isVendorPack(preset) && input.vendorPayload) {
128
+ vendorSchemaOk = false;
129
+ }
130
+ if (canonicalPayload) {
131
+ canonicalSchemaOk = false;
132
+ }
133
+ pushDriftKind(driftKinds, "forbidden_field_present");
134
+ }
135
+ return {
136
+ preset_id: input.presetId,
137
+ vendor_schema_ok: vendorSchemaOk,
138
+ canonical_schema_ok: canonicalSchemaOk,
139
+ quality_fields_missing: qualityMissing,
140
+ forbidden_fields_present: forbiddenHits,
141
+ pack_stale: packStale,
142
+ drift_kinds: driftKinds,
143
+ canonical_payload: canonicalPayload,
144
+ };
145
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * In-process offline Gateway mock for `paybond dev --offline`.
3
+ * Simulates sandbox capability bootstrap, verify, evidence, and settlement completion.
4
+ */
5
+ export declare const OFFLINE_DEV_INTENT_ID = "00000000-0000-4000-8000-000000000001";
6
+ export declare const OFFLINE_DEV_TENANT_ID = "tenant-dev-offline";
7
+ /** Synthetic sandbox API key shape accepted by offline mocks (never validated remotely). */
8
+ export declare const OFFLINE_SANDBOX_API_KEY: string;
9
+ /** Visible prefix for production service-account API keys. */
10
+ export declare const LIVE_API_KEY_PREFIX: "paybond_sk_live_";
11
+ /** Return true when `apiKey` is a production (`paybond_sk_live_…`) service-account key. */
12
+ export declare function isProductionApiKey(apiKey: string): boolean;
13
+ export declare const DEV_WIREMOCK_DEFAULT_PORT = 18089;
14
+ export declare const DEV_WIREMOCK_CONTAINER_NAME = "paybond-dev-wiremock";
15
+ export type OfflineGatewayMockOptions = {
16
+ allowVerify?: boolean;
17
+ denyMessage?: string;
18
+ };
19
+ /** Build a fetch implementation that stubs Gateway routes for local dev smoke. */
20
+ export declare function createOfflineDevGatewayFetch(options?: OfflineGatewayMockOptions): typeof fetch;
21
+ /** Apply offline dev credentials and fetch mock; returns a restore function. */
22
+ export declare function activateOfflineDevMode(): {
23
+ restore: () => void;
24
+ };
@@ -0,0 +1,102 @@
1
+ /**
2
+ * In-process offline Gateway mock for `paybond dev --offline`.
3
+ * Simulates sandbox capability bootstrap, verify, evidence, and settlement completion.
4
+ */
5
+ export const OFFLINE_DEV_INTENT_ID = "00000000-0000-4000-8000-000000000001";
6
+ export const OFFLINE_DEV_TENANT_ID = "tenant-dev-offline";
7
+ /** Synthetic sandbox API key shape accepted by offline mocks (never validated remotely). */
8
+ export const OFFLINE_SANDBOX_API_KEY = "paybond_sk_sandbox_0123456789abcdef0123456789abcdef_" +
9
+ "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
10
+ /** Visible prefix for production service-account API keys. */
11
+ export const LIVE_API_KEY_PREFIX = "paybond_sk_live_";
12
+ /** Return true when `apiKey` is a production (`paybond_sk_live_…`) service-account key. */
13
+ export function isProductionApiKey(apiKey) {
14
+ return apiKey.startsWith(LIVE_API_KEY_PREFIX);
15
+ }
16
+ export const DEV_WIREMOCK_DEFAULT_PORT = 18089;
17
+ export const DEV_WIREMOCK_CONTAINER_NAME = "paybond-dev-wiremock";
18
+ function jsonResponse(body, status = 200) {
19
+ return new Response(JSON.stringify(body), {
20
+ status,
21
+ headers: { "content-type": "application/json" },
22
+ });
23
+ }
24
+ /** Build a fetch implementation that stubs Gateway routes for local dev smoke. */
25
+ export function createOfflineDevGatewayFetch(options = {}) {
26
+ const allowVerify = options.allowVerify ?? true;
27
+ return (async (input, init) => {
28
+ const url = input.toString();
29
+ const body = init?.body ? JSON.parse(String(init.body)) : {};
30
+ if (url.endsWith("/v1/auth/principal")) {
31
+ return jsonResponse({
32
+ tenant_id: OFFLINE_DEV_TENANT_ID,
33
+ tenant_uuid: "550e8400-e29b-41d4-a716-446655440000",
34
+ environment: "sandbox",
35
+ service_account_role: "operator",
36
+ });
37
+ }
38
+ if (url.endsWith("/v1/sandbox/guardrails/bootstrap")) {
39
+ return jsonResponse({
40
+ tenant_id: OFFLINE_DEV_TENANT_ID,
41
+ intent_id: OFFLINE_DEV_INTENT_ID,
42
+ capability_token: "cap-dev-offline-1",
43
+ operation: body.operation,
44
+ requested_spend_cents: body.requested_spend_cents,
45
+ sandbox_lifecycle_status: "funded",
46
+ });
47
+ }
48
+ if (url.endsWith("/verify")) {
49
+ if (!allowVerify) {
50
+ return jsonResponse({
51
+ allow: false,
52
+ tenant: OFFLINE_DEV_TENANT_ID,
53
+ intent_id: OFFLINE_DEV_INTENT_ID,
54
+ audit_id: "audit-deny",
55
+ decision_id: "decision-deny",
56
+ message: options.denyMessage ?? "spend denied",
57
+ });
58
+ }
59
+ return jsonResponse({
60
+ allow: true,
61
+ tenant: OFFLINE_DEV_TENANT_ID,
62
+ intent_id: OFFLINE_DEV_INTENT_ID,
63
+ audit_id: "00000000-0000-4000-8000-000000000002",
64
+ decision_id: "00000000-0000-4000-8000-000000000003",
65
+ });
66
+ }
67
+ if (url.endsWith(`/v1/sandbox/guardrails/${OFFLINE_DEV_INTENT_ID}/evidence`)) {
68
+ return jsonResponse({
69
+ tenant_id: OFFLINE_DEV_TENANT_ID,
70
+ intent_id: OFFLINE_DEV_INTENT_ID,
71
+ operation: body.operation ?? "paid-tool",
72
+ requested_spend_cents: body.requested_spend_cents ?? 100,
73
+ sandbox_lifecycle_status: "released",
74
+ predicate_passed: true,
75
+ settlement_mode: "simulated",
76
+ });
77
+ }
78
+ if (url.includes("/v1/spend/decisions/") && url.endsWith("/complete")) {
79
+ return jsonResponse({ settlement_mode: "simulated" });
80
+ }
81
+ return jsonResponse({}, 404);
82
+ });
83
+ }
84
+ /** Apply offline dev credentials and fetch mock; returns a restore function. */
85
+ export function activateOfflineDevMode() {
86
+ const previousApiKey = process.env.PAYBOND_API_KEY;
87
+ const trimmedPrevious = previousApiKey?.trim();
88
+ if (trimmedPrevious && isProductionApiKey(trimmedPrevious)) {
89
+ throw new Error("offline dev mode cannot be used with production API keys (paybond_sk_live_...); unset PAYBOND_API_KEY or use a sandbox key");
90
+ }
91
+ process.env.PAYBOND_API_KEY = OFFLINE_SANDBOX_API_KEY;
92
+ return {
93
+ restore() {
94
+ if (previousApiKey === undefined) {
95
+ delete process.env.PAYBOND_API_KEY;
96
+ }
97
+ else {
98
+ process.env.PAYBOND_API_KEY = previousApiKey;
99
+ }
100
+ },
101
+ };
102
+ }
@@ -0,0 +1,61 @@
1
+ import type { PaybondTraceEvent, PaybondTraceSink } from "../agent/types.js";
2
+ export declare const DEV_TRACE_DEFAULT_PORT = 9477;
3
+ export declare const DEV_AUDIT_DIR = ".paybond";
4
+ export declare const DEV_AUDIT_FILE: string;
5
+ export declare const DEV_TRACE_FILE: string;
6
+ export declare const DEV_DEFAULT_POLICY_FILE = "paybond.policy.yaml";
7
+ export declare const DEV_DEFAULT_PRESET = "travel";
8
+ export type DevTraceStepPhase = "agent" | "tool" | "authorize" | "evidence" | "result";
9
+ export type DevTraceStep = {
10
+ phase: DevTraceStepPhase;
11
+ label: string;
12
+ recorded_at: string;
13
+ detail?: Record<string, unknown>;
14
+ };
15
+ export type DevTraceEvent = {
16
+ id: string;
17
+ recorded_at: string;
18
+ preset: string;
19
+ operation: string;
20
+ intent_id?: string;
21
+ run_id?: string;
22
+ requested_spend_cents?: number;
23
+ authorized: boolean;
24
+ evidence_submitted: boolean;
25
+ sandbox_lifecycle_status?: string;
26
+ result_status?: string;
27
+ cost_cents?: number;
28
+ steps?: DevTraceStep[];
29
+ trace_events?: PaybondTraceEvent[];
30
+ };
31
+ /** Read persisted dev trace events from `.paybond/dev-trace.jsonl`. */
32
+ export declare function readDevTraceEventsFromDisk(cwd: string): DevTraceEvent[];
33
+ /** List dev trace events from disk (when `cwd` is set) and the in-process ring buffer. */
34
+ export declare function listDevTraceEvents(cwd?: string): DevTraceEvent[];
35
+ /** Find the most recent in-memory dev trace event for a run id (same-process fallback). */
36
+ export declare function findDevTraceEventForRun(runId: string): DevTraceEvent | undefined;
37
+ export declare function appendDevTraceEvent(event: DevTraceEvent, cwd?: string): void;
38
+ export declare function devTraceUrl(port?: number, runId?: string): string;
39
+ /** User-facing startup banner lines for `paybond dev loop`. */
40
+ export declare function buildDevStartupBannerLines(port?: number): string[];
41
+ export declare function devTraceHasCredentials(): boolean;
42
+ export declare function appendDevAuditLog(cwd: string, entry: Record<string, unknown>): Promise<string>;
43
+ export declare function devTraceStepsFromEvents(events: readonly PaybondTraceEvent[]): DevTraceStep[];
44
+ /** Reset in-memory dev trace state (tests and local dashboard restarts). */
45
+ export declare function clearDevTraceEvents(): void;
46
+ /** Activate an in-process dev trace collector for the next bind/execute cycle. */
47
+ export declare function activateDevTraceCollector(options: {
48
+ preset: string;
49
+ intentId?: string;
50
+ cwd?: string;
51
+ }): void;
52
+ /** Resolve the active dev trace sink for {@link PaybondAgentRun.bind}. */
53
+ export declare function resolveDevTraceSink(): PaybondTraceSink | undefined;
54
+ /** Finalize and persist the active dev trace collector as a dashboard event. */
55
+ export declare function finalizeDevTraceCollector(resultBody?: Record<string, unknown>, cwd?: string): DevTraceEvent | undefined;
56
+ export declare function recordSmokeTraceEvent(input: {
57
+ preset: string;
58
+ bind: Record<string, unknown>;
59
+ execute: Record<string, unknown>;
60
+ resultBody: Record<string, unknown>;
61
+ }, cwd?: string): DevTraceEvent;
@@ -0,0 +1,330 @@
1
+ import { appendFile, mkdir } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
3
+ import { appendFileSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ export const DEV_TRACE_DEFAULT_PORT = 9477;
6
+ export const DEV_AUDIT_DIR = ".paybond";
7
+ export const DEV_AUDIT_FILE = join(DEV_AUDIT_DIR, "dev-audit.jsonl");
8
+ export const DEV_TRACE_FILE = join(DEV_AUDIT_DIR, "dev-trace.jsonl");
9
+ export const DEV_DEFAULT_POLICY_FILE = "paybond.policy.yaml";
10
+ export const DEV_DEFAULT_PRESET = "travel";
11
+ const MAX_TRACE_EVENTS = 100;
12
+ const traceEvents = [];
13
+ /** Read persisted dev trace events from `.paybond/dev-trace.jsonl`. */
14
+ export function readDevTraceEventsFromDisk(cwd) {
15
+ const path = join(cwd, DEV_TRACE_FILE);
16
+ if (!existsSync(path)) {
17
+ return [];
18
+ }
19
+ return readFileSync(path, "utf8")
20
+ .split("\n")
21
+ .filter((line) => line.trim().length > 0)
22
+ .map((line) => JSON.parse(line));
23
+ }
24
+ function mergeDevTraceEvents(fromDisk, fromMemory) {
25
+ const byId = new Map();
26
+ for (const event of fromDisk) {
27
+ byId.set(event.id, event);
28
+ }
29
+ for (const event of fromMemory) {
30
+ byId.set(event.id, event);
31
+ }
32
+ return [...byId.values()].sort((left, right) => left.recorded_at.localeCompare(right.recorded_at));
33
+ }
34
+ /** List dev trace events from disk (when `cwd` is set) and the in-process ring buffer. */
35
+ export function listDevTraceEvents(cwd) {
36
+ const memory = [...traceEvents];
37
+ if (!cwd) {
38
+ return memory;
39
+ }
40
+ return mergeDevTraceEvents(readDevTraceEventsFromDisk(cwd), memory);
41
+ }
42
+ function trimDevTraceFileSync(path) {
43
+ if (!existsSync(path)) {
44
+ return;
45
+ }
46
+ const lines = readFileSync(path, "utf8").split("\n").filter((line) => line.trim().length > 0);
47
+ if (lines.length <= MAX_TRACE_EVENTS) {
48
+ return;
49
+ }
50
+ writeFileSync(path, `${lines.slice(-MAX_TRACE_EVENTS).join("\n")}\n`, "utf8");
51
+ }
52
+ function persistDevTraceEventSync(cwd, event) {
53
+ const dir = join(cwd, DEV_AUDIT_DIR);
54
+ mkdirSync(dir, { recursive: true });
55
+ const path = join(cwd, DEV_TRACE_FILE);
56
+ appendFileSync(path, `${JSON.stringify(event)}\n`, "utf8");
57
+ trimDevTraceFileSync(path);
58
+ }
59
+ /** Find the most recent in-memory dev trace event for a run id (same-process fallback). */
60
+ export function findDevTraceEventForRun(runId) {
61
+ const normalized = runId.trim();
62
+ for (let index = traceEvents.length - 1; index >= 0; index -= 1) {
63
+ const event = traceEvents[index];
64
+ if (event?.run_id === normalized || event?.id === normalized) {
65
+ return event;
66
+ }
67
+ }
68
+ return undefined;
69
+ }
70
+ export function appendDevTraceEvent(event, cwd) {
71
+ traceEvents.push(event);
72
+ while (traceEvents.length > MAX_TRACE_EVENTS) {
73
+ traceEvents.shift();
74
+ }
75
+ if (cwd) {
76
+ persistDevTraceEventSync(cwd, event);
77
+ }
78
+ }
79
+ export function devTraceUrl(port = DEV_TRACE_DEFAULT_PORT, runId) {
80
+ const base = `http://localhost:${port}`;
81
+ return runId ? `${base}/runs/${encodeURIComponent(runId)}` : base;
82
+ }
83
+ /** User-facing startup banner lines for `paybond dev loop`. */
84
+ export function buildDevStartupBannerLines(port = DEV_TRACE_DEFAULT_PORT) {
85
+ return [
86
+ "✓ Sandbox capability (or: offline mock)",
87
+ "✓ Settlement simulator",
88
+ `✓ Trace dashboard → ${devTraceUrl(port)}`,
89
+ `✓ Audit log → ${DEV_AUDIT_FILE}`,
90
+ ];
91
+ }
92
+ export function devTraceHasCredentials() {
93
+ return Boolean(process.env.PAYBOND_API_KEY?.trim());
94
+ }
95
+ export async function appendDevAuditLog(cwd, entry) {
96
+ const dir = join(cwd, DEV_AUDIT_DIR);
97
+ await mkdir(dir, { recursive: true });
98
+ const path = join(cwd, DEV_AUDIT_FILE);
99
+ await appendFile(path, `${JSON.stringify(entry)}\n`, "utf8");
100
+ return path;
101
+ }
102
+ export function devTraceStepsFromEvents(events) {
103
+ const steps = [];
104
+ for (const event of events) {
105
+ switch (event.type) {
106
+ case "tool_selected":
107
+ steps.push({
108
+ phase: "tool",
109
+ label: `Tool call: ${event.toolName}`,
110
+ recorded_at: event.recordedAt,
111
+ detail: { operation: event.operation, tool_call_id: event.toolCallId },
112
+ });
113
+ break;
114
+ case "spend_authorized":
115
+ steps.push({
116
+ phase: "authorize",
117
+ label: `Paybond approved $${(event.amountCents / 100).toFixed(2)}`,
118
+ recorded_at: event.recordedAt,
119
+ detail: {
120
+ audit_id: event.auditId,
121
+ decision_id: event.decisionId,
122
+ amount_cents: event.amountCents,
123
+ },
124
+ });
125
+ break;
126
+ case "spend_denied":
127
+ steps.push({
128
+ phase: "authorize",
129
+ label: `Spend denied: ${event.message}`,
130
+ recorded_at: event.recordedAt,
131
+ detail: { audit_id: event.auditId, code: event.code },
132
+ });
133
+ break;
134
+ case "approval_required":
135
+ steps.push({
136
+ phase: "authorize",
137
+ label: `Approval required: ${event.message}`,
138
+ recorded_at: event.recordedAt,
139
+ detail: { audit_id: event.auditId, code: event.code },
140
+ });
141
+ break;
142
+ case "tool_executed":
143
+ steps.push({
144
+ phase: "result",
145
+ label: `Tool executed (${event.durationMs}ms)`,
146
+ recorded_at: event.recordedAt,
147
+ detail: { duration_ms: event.durationMs },
148
+ });
149
+ break;
150
+ case "evidence_submitted":
151
+ steps.push({
152
+ phase: "evidence",
153
+ label: event.predicatePassed === false ? "Evidence submitted (predicate failed)" : "Evidence submitted",
154
+ recorded_at: event.recordedAt,
155
+ detail: {
156
+ evidence_id: event.evidenceId,
157
+ preset_id: event.presetId,
158
+ evidence_preset: event.evidencePreset ?? event.presetId,
159
+ sandbox_lifecycle_status: event.sandboxLifecycleStatus,
160
+ predicate_passed: event.predicatePassed,
161
+ },
162
+ });
163
+ if (event.sandboxLifecycleStatus) {
164
+ steps.push({
165
+ phase: "result",
166
+ label: `Settlement: ${event.sandboxLifecycleStatus}`,
167
+ recorded_at: event.recordedAt,
168
+ detail: { sandbox_lifecycle_status: event.sandboxLifecycleStatus },
169
+ });
170
+ }
171
+ break;
172
+ case "spend_finalized":
173
+ if (event.status === "consumed") {
174
+ steps.push({
175
+ phase: "result",
176
+ label: "Spend authorization consumed",
177
+ recorded_at: event.recordedAt,
178
+ detail: { status: event.status },
179
+ });
180
+ }
181
+ break;
182
+ default:
183
+ break;
184
+ }
185
+ }
186
+ return steps;
187
+ }
188
+ function summarizeTraceEvents(events) {
189
+ const toolSelected = events.find((event) => event.type === "tool_selected");
190
+ const spendAuthorized = events.find((event) => event.type === "spend_authorized");
191
+ const evidenceSubmitted = events.find((event) => event.type === "evidence_submitted");
192
+ const spendDenied = events.some((event) => event.type === "spend_denied" || event.type === "approval_required");
193
+ return {
194
+ operation: toolSelected?.operation ?? spendAuthorized?.operation ?? "",
195
+ runId: toolSelected?.runId ?? spendAuthorized?.runId ?? `trace-${Date.now()}`,
196
+ requestedSpendCents: spendAuthorized?.amountCents,
197
+ authorized: Boolean(spendAuthorized) && !spendDenied,
198
+ evidenceSubmitted: Boolean(evidenceSubmitted),
199
+ sandboxLifecycleStatus: evidenceSubmitted?.sandboxLifecycleStatus,
200
+ };
201
+ }
202
+ class DevTraceCollector {
203
+ options;
204
+ events = [];
205
+ constructor(options) {
206
+ this.options = options;
207
+ }
208
+ sink = (event) => {
209
+ this.events.push(event);
210
+ };
211
+ finalize(resultBody, cwd) {
212
+ if (this.events.length === 0) {
213
+ return undefined;
214
+ }
215
+ const summary = summarizeTraceEvents(this.events);
216
+ const event = {
217
+ id: summary.runId,
218
+ recorded_at: this.events.at(-1)?.recordedAt ?? new Date().toISOString(),
219
+ preset: this.options.preset,
220
+ operation: summary.operation,
221
+ intent_id: this.options.intentId,
222
+ run_id: summary.runId,
223
+ requested_spend_cents: summary.requestedSpendCents,
224
+ authorized: summary.authorized,
225
+ evidence_submitted: summary.evidenceSubmitted,
226
+ sandbox_lifecycle_status: summary.sandboxLifecycleStatus,
227
+ result_status: typeof resultBody?.status === "string" ? resultBody.status : undefined,
228
+ cost_cents: typeof resultBody?.cost_cents === "number" ? resultBody.cost_cents : undefined,
229
+ steps: devTraceStepsFromEvents(this.events),
230
+ trace_events: [...this.events],
231
+ };
232
+ appendDevTraceEvent(event, cwd);
233
+ return event;
234
+ }
235
+ }
236
+ let activeDevTraceCollector;
237
+ let activeDevTraceCollectorCwd;
238
+ /** Reset in-memory dev trace state (tests and local dashboard restarts). */
239
+ export function clearDevTraceEvents() {
240
+ traceEvents.length = 0;
241
+ activeDevTraceCollector = undefined;
242
+ activeDevTraceCollectorCwd = undefined;
243
+ }
244
+ /** Activate an in-process dev trace collector for the next bind/execute cycle. */
245
+ export function activateDevTraceCollector(options) {
246
+ activeDevTraceCollector = new DevTraceCollector(options);
247
+ activeDevTraceCollectorCwd = options.cwd;
248
+ }
249
+ /** Resolve the active dev trace sink for {@link PaybondAgentRun.bind}. */
250
+ export function resolveDevTraceSink() {
251
+ return activeDevTraceCollector?.sink;
252
+ }
253
+ /** Finalize and persist the active dev trace collector as a dashboard event. */
254
+ export function finalizeDevTraceCollector(resultBody, cwd) {
255
+ const event = activeDevTraceCollector?.finalize(resultBody, cwd ?? activeDevTraceCollectorCwd);
256
+ activeDevTraceCollector = undefined;
257
+ activeDevTraceCollectorCwd = undefined;
258
+ return event;
259
+ }
260
+ export function recordSmokeTraceEvent(input, cwd) {
261
+ const runId = String(input.bind.run_id ?? "smoke-1");
262
+ const event = {
263
+ id: runId,
264
+ recorded_at: new Date().toISOString(),
265
+ preset: input.preset,
266
+ operation: String(input.bind.operation ?? ""),
267
+ intent_id: typeof input.bind.intent_id === "string" ? input.bind.intent_id : undefined,
268
+ run_id: runId,
269
+ requested_spend_cents: typeof input.bind.requested_spend_cents === "number"
270
+ ? input.bind.requested_spend_cents
271
+ : undefined,
272
+ authorized: true,
273
+ evidence_submitted: Boolean(input.execute.evidence_submitted ?? input.execute.evidence),
274
+ sandbox_lifecycle_status: typeof input.execute.sandbox_lifecycle_status === "string"
275
+ ? input.execute.sandbox_lifecycle_status
276
+ : typeof input.bind.sandbox_lifecycle_status === "string"
277
+ ? input.bind.sandbox_lifecycle_status
278
+ : undefined,
279
+ result_status: typeof input.resultBody.status === "string" ? input.resultBody.status : undefined,
280
+ cost_cents: typeof input.resultBody.cost_cents === "number" ? input.resultBody.cost_cents : undefined,
281
+ steps: devTraceStepsFromEvents([
282
+ {
283
+ type: "tool_selected",
284
+ runId,
285
+ toolName: String(input.bind.operation ?? "tool"),
286
+ toolCallId: "smoke-1",
287
+ operation: String(input.bind.operation ?? ""),
288
+ recordedAt: new Date().toISOString(),
289
+ },
290
+ {
291
+ type: "spend_authorized",
292
+ runId,
293
+ toolCallId: "smoke-1",
294
+ operation: String(input.bind.operation ?? ""),
295
+ auditId: "smoke",
296
+ amountCents: typeof input.bind.requested_spend_cents === "number"
297
+ ? input.bind.requested_spend_cents
298
+ : 0,
299
+ recordedAt: new Date().toISOString(),
300
+ },
301
+ {
302
+ type: "tool_executed",
303
+ runId,
304
+ toolCallId: "smoke-1",
305
+ operation: String(input.bind.operation ?? ""),
306
+ durationMs: 0,
307
+ recordedAt: new Date().toISOString(),
308
+ },
309
+ ...((input.execute.evidence_submitted ?? input.execute.evidence)
310
+ ? [
311
+ {
312
+ type: "evidence_submitted",
313
+ runId,
314
+ toolCallId: "smoke-1",
315
+ operation: String(input.bind.operation ?? ""),
316
+ evidenceId: `evidence:${String(input.bind.intent_id ?? "smoke")}:smoke-1`,
317
+ presetId: input.preset,
318
+ evidencePreset: input.preset,
319
+ sandboxLifecycleStatus: typeof input.execute.sandbox_lifecycle_status === "string"
320
+ ? input.execute.sandbox_lifecycle_status
321
+ : undefined,
322
+ recordedAt: new Date().toISOString(),
323
+ },
324
+ ]
325
+ : []),
326
+ ]),
327
+ };
328
+ appendDevTraceEvent(event, cwd);
329
+ return event;
330
+ }
@@ -0,0 +1,11 @@
1
+ /** Security headers applied to every dev trace dashboard HTTP response. */
2
+ export declare const DEV_TRACE_SECURITY_HEADERS: {
3
+ readonly "cache-control": "no-store";
4
+ readonly "content-security-policy": "default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; connect-src 'self'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'";
5
+ readonly "permissions-policy": "camera=(), microphone=(), geolocation=(), payment=()";
6
+ readonly "referrer-policy": "no-referrer";
7
+ readonly "x-content-type-options": "nosniff";
8
+ readonly "x-frame-options": "DENY";
9
+ };
10
+ /** Merge dev trace security headers with a response content type. */
11
+ export declare function devTraceResponseHeaders(contentType: string): Record<string, string>;