@codespar/cli 0.17.0 → 0.18.1

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 (482) hide show
  1. package/README.md +1 -0
  2. package/dist/surface.js +53 -1
  3. package/dist/surface.js.map +1 -1
  4. package/package.json +1 -1
  5. package/templates/bills-agent/README.md +1 -1
  6. package/templates/bills-agent/agents/bills-agent/AGENTS.md +1 -1
  7. package/templates/bills-agent/agents/bills-agent/CLAUDE.md +1 -1
  8. package/templates/bills-agent/agents/bills-agent/README.md +6 -5
  9. package/templates/bills-agent/agents/bills-agent/src/modules/embedded-consent.ts +5 -4
  10. package/templates/bills-agent/packages/agent-core/README.md +14 -1
  11. package/templates/bills-agent/packages/agent-core/package.json +1 -1
  12. package/templates/bills-agent/packages/agent-core/src/agent.ts +39 -1
  13. package/templates/bills-agent/packages/agent-core/src/api/charge-rail.ts +54 -34
  14. package/templates/bills-agent/packages/agent-core/src/api/client.ts +28 -5
  15. package/templates/bills-agent/packages/agent-core/src/api/mandate-status.ts +28 -12
  16. package/templates/bills-agent/packages/agent-core/src/api/rail.ts +62 -26
  17. package/templates/bills-agent/packages/agent-core/src/api/sandbox-payer.ts +3 -18
  18. package/templates/bills-agent/packages/agent-core/src/approval.ts +14 -2
  19. package/templates/bills-agent/packages/agent-core/src/bundle.ts +35 -3
  20. package/templates/bills-agent/packages/agent-core/src/channels.ts +49 -3
  21. package/templates/bills-agent/packages/agent-core/src/check.ts +25 -2
  22. package/templates/bills-agent/packages/agent-core/src/engine.ts +235 -46
  23. package/templates/bills-agent/packages/agent-core/src/hash.ts +57 -1
  24. package/templates/bills-agent/packages/agent-core/src/index.ts +2 -0
  25. package/templates/bills-agent/packages/agent-core/src/quote.ts +50 -0
  26. package/templates/bills-agent/packages/agent-core/src/rail.ts +89 -4
  27. package/templates/bills-agent/packages/agent-core/src/receipt-chain.ts +270 -0
  28. package/templates/bills-agent/packages/agent-core/src/receipt-verification.ts +194 -18
  29. package/templates/bills-agent/packages/agent-core/src/revocation.ts +1 -1
  30. package/templates/bills-agent/packages/agent-core/src/state-machine.ts +10 -1
  31. package/templates/bills-agent/packages/agent-core/src/stubs/mandate-status.ts +4 -3
  32. package/templates/bills-agent/packages/agent-core/src/stubs/rail.ts +100 -32
  33. package/templates/bills-agent/packages/agent-core/src/tools.ts +17 -6
  34. package/templates/bills-agent/packages/agent-core/src/types.ts +54 -1
  35. package/templates/bills-agent/packages/agent-core/test/approval-seal.test.ts +233 -0
  36. package/templates/bills-agent/packages/agent-core/test/attempt-replay.test.ts +265 -0
  37. package/templates/bills-agent/packages/agent-core/test/composition.test.ts +204 -0
  38. package/templates/bills-agent/packages/agent-core/test/fixtures/production-receipt-keys.json +1 -0
  39. package/templates/bills-agent/packages/agent-core/test/helpers.ts +4 -1
  40. package/templates/bills-agent/packages/agent-core/test/mandate-status.test.ts +85 -9
  41. package/templates/bills-agent/packages/agent-core/test/quote.test.ts +198 -0
  42. package/templates/bills-agent/packages/agent-core/test/receipt-chain.test.ts +220 -0
  43. package/templates/bills-agent/packages/agent-core/test/receipt-read-verification.test.ts +197 -0
  44. package/templates/bills-agent/packages/agent-core/test/receivables.test.ts +103 -3
  45. package/templates/bills-agent/packages/agent-runtime/README.md +12 -0
  46. package/templates/bills-agent/packages/agent-runtime/src/adversarial.ts +32 -2
  47. package/templates/bills-agent/packages/agent-runtime/src/channels/types.ts +53 -4
  48. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +123 -22
  49. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +30 -20
  50. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +146 -21
  51. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +40 -3
  52. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -1
  53. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +16 -2
  54. package/templates/bills-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +70 -20
  55. package/templates/bills-agent/packages/agent-runtime/src/commands/poll.ts +2 -1
  56. package/templates/bills-agent/packages/agent-runtime/src/commands/resume.ts +8 -2
  57. package/templates/bills-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +3 -0
  58. package/templates/bills-agent/packages/agent-runtime/src/commands/start.ts +6 -3
  59. package/templates/bills-agent/packages/agent-runtime/src/commands/verify.ts +239 -38
  60. package/templates/bills-agent/packages/agent-runtime/src/commands/webhook.ts +3 -2
  61. package/templates/bills-agent/packages/agent-runtime/src/index.ts +1 -0
  62. package/templates/bills-agent/packages/agent-runtime/src/inspect.ts +5 -1
  63. package/templates/bills-agent/packages/agent-runtime/src/kit.ts +25 -2
  64. package/templates/bills-agent/packages/agent-runtime/src/scenarios.ts +8 -2
  65. package/templates/bills-agent/packages/agent-runtime/src/setup.ts +13 -3
  66. package/templates/bills-agent/packages/agent-runtime/src/terminal.ts +127 -18
  67. package/templates/bills-agent/packages/agent-runtime/test/verify-cli.test.ts +211 -9
  68. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +45 -0
  69. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-session.test.ts +32 -0
  70. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +182 -0
  71. package/templates/checkout-agent/LICENSE +21 -0
  72. package/templates/checkout-agent/README.md +28 -0
  73. package/templates/checkout-agent/_gitignore +10 -0
  74. package/templates/checkout-agent/agents/checkout-agent/.env.example +5 -0
  75. package/templates/checkout-agent/agents/checkout-agent/AGENTS.md +20 -0
  76. package/templates/checkout-agent/agents/checkout-agent/CLAUDE.md +20 -0
  77. package/templates/checkout-agent/agents/checkout-agent/README.md +94 -0
  78. package/templates/checkout-agent/agents/checkout-agent/SYSTEM_PROMPT.md +36 -0
  79. package/templates/checkout-agent/agents/checkout-agent/agent.yaml +30 -0
  80. package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/README.md +28 -0
  81. package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/pedido-beatriz.json +11 -0
  82. package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/pedido-marina-retomada.json +10 -0
  83. package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/pedido-marina.json +11 -0
  84. package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/templates.json +49 -0
  85. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/beneficiary-swap-human.json +12 -0
  86. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/beneficiary-swap.json +11 -0
  87. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/beneficiary-swap.transcript.jsonl +5 -0
  88. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/coupon-unknown.json +13 -0
  89. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/coupon-unknown.transcript.jsonl +4 -0
  90. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/exfiltration.json +26 -0
  91. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/exfiltration.transcript.jsonl +3 -0
  92. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/false-authority.json +11 -0
  93. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/false-authority.transcript.jsonl +5 -0
  94. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/fractioning.json +12 -0
  95. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/fractioning.transcript.jsonl +5 -0
  96. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/model-total.json +13 -0
  97. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/model-total.transcript.jsonl +5 -0
  98. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/payment-claimed.json +15 -0
  99. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/payment-claimed.transcript.jsonl +7 -0
  100. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/price-injected.json +12 -0
  101. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/price-injected.transcript.jsonl +5 -0
  102. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/prompt-injection.json +13 -0
  103. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/prompt-injection.transcript.jsonl +4 -0
  104. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/quantity-swapped-human.json +16 -0
  105. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/quantity-swapped-human.transcript.jsonl +9 -0
  106. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/quantity-swapped.json +15 -0
  107. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/quantity-swapped.transcript.jsonl +8 -0
  108. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/webhook-replay.json +11 -0
  109. package/templates/checkout-agent/agents/checkout-agent/evals/eval.yaml +11 -0
  110. package/templates/checkout-agent/agents/checkout-agent/guardrails.json +25 -0
  111. package/templates/checkout-agent/agents/checkout-agent/mandate.example.json +28 -0
  112. package/templates/checkout-agent/agents/checkout-agent/package.json +33 -0
  113. package/templates/checkout-agent/agents/checkout-agent/runbook.md +19 -0
  114. package/templates/checkout-agent/agents/checkout-agent/scenarios/beneficiary-not-allowed.json +42 -0
  115. package/templates/checkout-agent/agents/checkout-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +4 -0
  116. package/templates/checkout-agent/agents/checkout-agent/scenarios/cap-exceeded.json +32 -0
  117. package/templates/checkout-agent/agents/checkout-agent/scenarios/cap-exceeded.transcript.jsonl +4 -0
  118. package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-recomposed.json +61 -0
  119. package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-recomposed.transcript.jsonl +9 -0
  120. package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-replaced.json +61 -0
  121. package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-replaced.transcript.jsonl +9 -0
  122. package/templates/checkout-agent/agents/checkout-agent/scenarios/charge-expired.json +36 -0
  123. package/templates/checkout-agent/agents/checkout-agent/scenarios/charge-expired.transcript.jsonl +6 -0
  124. package/templates/checkout-agent/agents/checkout-agent/scenarios/coupon-unknown.json +23 -0
  125. package/templates/checkout-agent/agents/checkout-agent/scenarios/coupon-unknown.transcript.jsonl +4 -0
  126. package/templates/checkout-agent/agents/checkout-agent/scenarios/escalated-above-threshold.json +72 -0
  127. package/templates/checkout-agent/agents/checkout-agent/scenarios/escalated-above-threshold.transcript.jsonl +9 -0
  128. package/templates/checkout-agent/agents/checkout-agent/scenarios/happy-path.json +15 -0
  129. package/templates/checkout-agent/agents/checkout-agent/scenarios/happy-path.transcript.jsonl +6 -0
  130. package/templates/checkout-agent/agents/checkout-agent/scenarios/item-unavailable.json +23 -0
  131. package/templates/checkout-agent/agents/checkout-agent/scenarios/item-unavailable.transcript.jsonl +3 -0
  132. package/templates/checkout-agent/agents/checkout-agent/scenarios/mandate-revoked.json +42 -0
  133. package/templates/checkout-agent/agents/checkout-agent/scenarios/mandate-revoked.transcript.jsonl +12 -0
  134. package/templates/checkout-agent/agents/checkout-agent/scenarios/nfse-failed.json +14 -0
  135. package/templates/checkout-agent/agents/checkout-agent/scenarios/nfse-failed.transcript.jsonl +9 -0
  136. package/templates/checkout-agent/agents/checkout-agent/scenarios/payment-claimed.json +34 -0
  137. package/templates/checkout-agent/agents/checkout-agent/scenarios/payment-claimed.transcript.jsonl +7 -0
  138. package/templates/checkout-agent/agents/checkout-agent/scenarios/price-injected.json +33 -0
  139. package/templates/checkout-agent/agents/checkout-agent/scenarios/price-injected.transcript.jsonl +4 -0
  140. package/templates/checkout-agent/agents/checkout-agent/scenarios/prompt-injection.json +32 -0
  141. package/templates/checkout-agent/agents/checkout-agent/scenarios/prompt-injection.transcript.jsonl +4 -0
  142. package/templates/checkout-agent/agents/checkout-agent/src/catalog.ts +92 -0
  143. package/templates/checkout-agent/agents/checkout-agent/src/kit.ts +338 -0
  144. package/templates/checkout-agent/agents/checkout-agent/src/modules/bolepix-receivables.ts +179 -0
  145. package/templates/checkout-agent/agents/checkout-agent/src/modules/nfse-invoice.ts +374 -0
  146. package/templates/checkout-agent/agents/checkout-agent/src/modules/storefront-cart.ts +220 -0
  147. package/templates/checkout-agent/agents/checkout-agent/src/pricing.ts +297 -0
  148. package/templates/checkout-agent/agents/checkout-agent/test/adversarial.test.ts +117 -0
  149. package/templates/checkout-agent/agents/checkout-agent/test/check.test.ts +67 -0
  150. package/templates/checkout-agent/agents/checkout-agent/test/cli.test.ts +169 -0
  151. package/templates/checkout-agent/agents/checkout-agent/test/fixtures/order-marina.transcript.jsonl +5 -0
  152. package/templates/checkout-agent/agents/checkout-agent/test/fixtures/ordered-marina-awaiting-payer.transcript.jsonl +6 -0
  153. package/templates/checkout-agent/agents/checkout-agent/test/fixtures/tap-falar-agora-marina.transcript.jsonl +2 -0
  154. package/templates/checkout-agent/agents/checkout-agent/test/nfse.test.ts +170 -0
  155. package/templates/checkout-agent/agents/checkout-agent/test/pricing.test.ts +138 -0
  156. package/templates/checkout-agent/agents/checkout-agent/test/scenarios.test.ts +113 -0
  157. package/templates/checkout-agent/agents/checkout-agent/test/whatsapp.test.ts +171 -0
  158. package/templates/checkout-agent/agents/checkout-agent/tools.json +68 -0
  159. package/templates/checkout-agent/agents/checkout-agent/tsconfig.json +10 -0
  160. package/templates/checkout-agent/package.json +38 -0
  161. package/templates/checkout-agent/packages/agent-core/README.md +34 -0
  162. package/templates/checkout-agent/packages/agent-core/package.json +24 -0
  163. package/templates/checkout-agent/packages/agent-core/src/agent.ts +163 -0
  164. package/templates/checkout-agent/packages/agent-core/src/api/charge-rail.ts +195 -0
  165. package/templates/checkout-agent/packages/agent-core/src/api/client.ts +76 -0
  166. package/templates/checkout-agent/packages/agent-core/src/api/mandate-status.ts +74 -0
  167. package/templates/checkout-agent/packages/agent-core/src/api/rail.ts +153 -0
  168. package/templates/checkout-agent/packages/agent-core/src/api/sandbox-payer.ts +43 -0
  169. package/templates/checkout-agent/packages/agent-core/src/approval.ts +135 -0
  170. package/templates/checkout-agent/packages/agent-core/src/bundle.ts +191 -0
  171. package/templates/checkout-agent/packages/agent-core/src/channels.ts +186 -0
  172. package/templates/checkout-agent/packages/agent-core/src/check.ts +276 -0
  173. package/templates/checkout-agent/packages/agent-core/src/clock.ts +42 -0
  174. package/templates/checkout-agent/packages/agent-core/src/engine.ts +1074 -0
  175. package/templates/checkout-agent/packages/agent-core/src/escalate.ts +85 -0
  176. package/templates/checkout-agent/packages/agent-core/src/events.ts +40 -0
  177. package/templates/checkout-agent/packages/agent-core/src/guardrails.ts +45 -0
  178. package/templates/checkout-agent/packages/agent-core/src/hash.ts +118 -0
  179. package/templates/checkout-agent/packages/agent-core/src/ids.ts +10 -0
  180. package/templates/checkout-agent/packages/agent-core/src/index.ts +34 -0
  181. package/templates/checkout-agent/packages/agent-core/src/mandate.ts +100 -0
  182. package/templates/checkout-agent/packages/agent-core/src/manifest.ts +76 -0
  183. package/templates/checkout-agent/packages/agent-core/src/providers/anthropic.ts +76 -0
  184. package/templates/checkout-agent/packages/agent-core/src/providers/replay.ts +63 -0
  185. package/templates/checkout-agent/packages/agent-core/src/providers/types.ts +39 -0
  186. package/templates/checkout-agent/packages/agent-core/src/quote.ts +50 -0
  187. package/templates/checkout-agent/packages/agent-core/src/rail.ts +186 -0
  188. package/templates/checkout-agent/packages/agent-core/src/receipt-chain.ts +270 -0
  189. package/templates/checkout-agent/packages/agent-core/src/receipt-verification.ts +577 -0
  190. package/templates/checkout-agent/packages/agent-core/src/revocation.ts +30 -0
  191. package/templates/checkout-agent/packages/agent-core/src/secrets.ts +30 -0
  192. package/templates/checkout-agent/packages/agent-core/src/state/store.ts +307 -0
  193. package/templates/checkout-agent/packages/agent-core/src/state-machine.ts +157 -0
  194. package/templates/checkout-agent/packages/agent-core/src/stubs/charge-rail.ts +195 -0
  195. package/templates/checkout-agent/packages/agent-core/src/stubs/mandate-status.ts +58 -0
  196. package/templates/checkout-agent/packages/agent-core/src/stubs/rail.ts +209 -0
  197. package/templates/checkout-agent/packages/agent-core/src/tools.ts +66 -0
  198. package/templates/checkout-agent/packages/agent-core/src/types.ts +187 -0
  199. package/templates/checkout-agent/packages/agent-core/test/approval-seal.test.ts +233 -0
  200. package/templates/checkout-agent/packages/agent-core/test/approval.test.ts +117 -0
  201. package/templates/checkout-agent/packages/agent-core/test/attempt-replay.test.ts +265 -0
  202. package/templates/checkout-agent/packages/agent-core/test/bundle.test.ts +85 -0
  203. package/templates/checkout-agent/packages/agent-core/test/clock.test.ts +25 -0
  204. package/templates/checkout-agent/packages/agent-core/test/composition.test.ts +204 -0
  205. package/templates/checkout-agent/packages/agent-core/test/engine.test.ts +596 -0
  206. package/templates/checkout-agent/packages/agent-core/test/escalate.test.ts +42 -0
  207. package/templates/checkout-agent/packages/agent-core/test/fixtures/production-receipt-keys.json +1 -0
  208. package/templates/checkout-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  209. package/templates/checkout-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  210. package/templates/checkout-agent/packages/agent-core/test/helpers.ts +142 -0
  211. package/templates/checkout-agent/packages/agent-core/test/mandate-status.test.ts +229 -0
  212. package/templates/checkout-agent/packages/agent-core/test/manifest.test.ts +45 -0
  213. package/templates/checkout-agent/packages/agent-core/test/quote.test.ts +198 -0
  214. package/templates/checkout-agent/packages/agent-core/test/receipt-chain.test.ts +220 -0
  215. package/templates/checkout-agent/packages/agent-core/test/receipt-read-verification.test.ts +197 -0
  216. package/templates/checkout-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  217. package/templates/checkout-agent/packages/agent-core/test/receivables.test.ts +416 -0
  218. package/templates/checkout-agent/packages/agent-core/test/secrets.test.ts +28 -0
  219. package/templates/checkout-agent/packages/agent-core/test/state-machine.test.ts +67 -0
  220. package/templates/checkout-agent/packages/agent-core/test/transitions.type-test.ts +59 -0
  221. package/templates/checkout-agent/packages/agent-core/tsconfig.json +10 -0
  222. package/templates/checkout-agent/packages/agent-runtime/README.md +80 -0
  223. package/templates/checkout-agent/packages/agent-runtime/bin.mjs +32 -0
  224. package/templates/checkout-agent/packages/agent-runtime/package.json +23 -0
  225. package/templates/checkout-agent/packages/agent-runtime/src/adversarial.ts +199 -0
  226. package/templates/checkout-agent/packages/agent-runtime/src/agent.ts +68 -0
  227. package/templates/checkout-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  228. package/templates/checkout-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  229. package/templates/checkout-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  230. package/templates/checkout-agent/packages/agent-runtime/src/channels/types.ts +173 -0
  231. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +459 -0
  232. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +216 -0
  233. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  234. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +350 -0
  235. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +180 -0
  236. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  237. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +120 -0
  238. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +127 -0
  239. package/templates/checkout-agent/packages/agent-runtime/src/cli.ts +98 -0
  240. package/templates/checkout-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  241. package/templates/checkout-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  242. package/templates/checkout-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  243. package/templates/checkout-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  244. package/templates/checkout-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +367 -0
  245. package/templates/checkout-agent/packages/agent-runtime/src/commands/poll.ts +145 -0
  246. package/templates/checkout-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  247. package/templates/checkout-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  248. package/templates/checkout-agent/packages/agent-runtime/src/commands/resume.ts +49 -0
  249. package/templates/checkout-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +134 -0
  250. package/templates/checkout-agent/packages/agent-runtime/src/commands/start.ts +248 -0
  251. package/templates/checkout-agent/packages/agent-runtime/src/commands/verify.ts +330 -0
  252. package/templates/checkout-agent/packages/agent-runtime/src/commands/webhook.ts +40 -0
  253. package/templates/checkout-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  254. package/templates/checkout-agent/packages/agent-runtime/src/index.ts +13 -0
  255. package/templates/checkout-agent/packages/agent-runtime/src/inspect.ts +801 -0
  256. package/templates/checkout-agent/packages/agent-runtime/src/kit.ts +229 -0
  257. package/templates/checkout-agent/packages/agent-runtime/src/poll.ts +105 -0
  258. package/templates/checkout-agent/packages/agent-runtime/src/scenarios.ts +274 -0
  259. package/templates/checkout-agent/packages/agent-runtime/src/setup.ts +239 -0
  260. package/templates/checkout-agent/packages/agent-runtime/src/terminal.ts +263 -0
  261. package/templates/checkout-agent/packages/agent-runtime/src/webhook.ts +131 -0
  262. package/templates/checkout-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  263. package/templates/checkout-agent/packages/agent-runtime/test/verify-cli.test.ts +329 -0
  264. package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +277 -0
  265. package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  266. package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  267. package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-session.test.ts +167 -0
  268. package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +182 -0
  269. package/templates/checkout-agent/packages/agent-runtime/tsconfig.json +9 -0
  270. package/templates/checkout-agent/scripts/whatsapp-emulator.mjs +84 -0
  271. package/templates/checkout-agent/tsconfig.base.json +16 -0
  272. package/templates/checkout-agent/vitest.config.ts +12 -0
  273. package/templates/collections-agent/README.md +6 -1
  274. package/templates/collections-agent/agents/collections-agent/README.md +12 -8
  275. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/README.md +8 -0
  276. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/acordo-1042-retomada.json +10 -0
  277. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/templates.json +27 -1
  278. package/templates/collections-agent/agents/collections-agent/src/kit.ts +2 -0
  279. package/templates/collections-agent/agents/collections-agent/src/modules/bolepix-receivables.ts +12 -2
  280. package/templates/collections-agent/agents/collections-agent/test/ambiguous-charge.test.ts +55 -0
  281. package/templates/collections-agent/agents/collections-agent/test/fixtures/tap-emitir-nova-1042.transcript.jsonl +2 -0
  282. package/templates/collections-agent/agents/collections-agent/test/whatsapp-poll.test.ts +12 -6
  283. package/templates/collections-agent/agents/collections-agent/test/whatsapp-status-replies.test.ts +148 -0
  284. package/templates/collections-agent/agents/collections-agent/test/whatsapp.test.ts +5 -0
  285. package/templates/collections-agent/package.json +1 -0
  286. package/templates/collections-agent/packages/agent-core/README.md +14 -1
  287. package/templates/collections-agent/packages/agent-core/package.json +1 -1
  288. package/templates/collections-agent/packages/agent-core/src/agent.ts +39 -1
  289. package/templates/collections-agent/packages/agent-core/src/api/charge-rail.ts +54 -34
  290. package/templates/collections-agent/packages/agent-core/src/api/client.ts +28 -5
  291. package/templates/collections-agent/packages/agent-core/src/api/mandate-status.ts +28 -12
  292. package/templates/collections-agent/packages/agent-core/src/api/rail.ts +62 -26
  293. package/templates/collections-agent/packages/agent-core/src/api/sandbox-payer.ts +3 -18
  294. package/templates/collections-agent/packages/agent-core/src/approval.ts +14 -2
  295. package/templates/collections-agent/packages/agent-core/src/bundle.ts +35 -3
  296. package/templates/collections-agent/packages/agent-core/src/channels.ts +49 -3
  297. package/templates/collections-agent/packages/agent-core/src/check.ts +25 -2
  298. package/templates/collections-agent/packages/agent-core/src/engine.ts +235 -46
  299. package/templates/collections-agent/packages/agent-core/src/hash.ts +57 -1
  300. package/templates/collections-agent/packages/agent-core/src/index.ts +2 -0
  301. package/templates/collections-agent/packages/agent-core/src/quote.ts +50 -0
  302. package/templates/collections-agent/packages/agent-core/src/rail.ts +89 -4
  303. package/templates/collections-agent/packages/agent-core/src/receipt-chain.ts +270 -0
  304. package/templates/collections-agent/packages/agent-core/src/receipt-verification.ts +194 -18
  305. package/templates/collections-agent/packages/agent-core/src/revocation.ts +1 -1
  306. package/templates/collections-agent/packages/agent-core/src/state-machine.ts +10 -1
  307. package/templates/collections-agent/packages/agent-core/src/stubs/mandate-status.ts +4 -3
  308. package/templates/collections-agent/packages/agent-core/src/stubs/rail.ts +100 -32
  309. package/templates/collections-agent/packages/agent-core/src/tools.ts +17 -6
  310. package/templates/collections-agent/packages/agent-core/src/types.ts +54 -1
  311. package/templates/collections-agent/packages/agent-core/test/approval-seal.test.ts +233 -0
  312. package/templates/collections-agent/packages/agent-core/test/attempt-replay.test.ts +265 -0
  313. package/templates/collections-agent/packages/agent-core/test/composition.test.ts +204 -0
  314. package/templates/collections-agent/packages/agent-core/test/fixtures/production-receipt-keys.json +1 -0
  315. package/templates/collections-agent/packages/agent-core/test/helpers.ts +4 -1
  316. package/templates/collections-agent/packages/agent-core/test/mandate-status.test.ts +85 -9
  317. package/templates/collections-agent/packages/agent-core/test/quote.test.ts +198 -0
  318. package/templates/collections-agent/packages/agent-core/test/receipt-chain.test.ts +220 -0
  319. package/templates/collections-agent/packages/agent-core/test/receipt-read-verification.test.ts +197 -0
  320. package/templates/collections-agent/packages/agent-core/test/receivables.test.ts +103 -3
  321. package/templates/collections-agent/packages/agent-runtime/README.md +12 -0
  322. package/templates/collections-agent/packages/agent-runtime/src/adversarial.ts +32 -2
  323. package/templates/collections-agent/packages/agent-runtime/src/channels/types.ts +53 -4
  324. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +123 -22
  325. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +30 -20
  326. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +146 -21
  327. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +40 -3
  328. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -1
  329. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +16 -2
  330. package/templates/collections-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +70 -20
  331. package/templates/collections-agent/packages/agent-runtime/src/commands/poll.ts +2 -1
  332. package/templates/collections-agent/packages/agent-runtime/src/commands/resume.ts +8 -2
  333. package/templates/collections-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +3 -0
  334. package/templates/collections-agent/packages/agent-runtime/src/commands/start.ts +6 -3
  335. package/templates/collections-agent/packages/agent-runtime/src/commands/verify.ts +239 -38
  336. package/templates/collections-agent/packages/agent-runtime/src/commands/webhook.ts +3 -2
  337. package/templates/collections-agent/packages/agent-runtime/src/index.ts +1 -0
  338. package/templates/collections-agent/packages/agent-runtime/src/inspect.ts +5 -1
  339. package/templates/collections-agent/packages/agent-runtime/src/kit.ts +25 -2
  340. package/templates/collections-agent/packages/agent-runtime/src/scenarios.ts +8 -2
  341. package/templates/collections-agent/packages/agent-runtime/src/setup.ts +13 -3
  342. package/templates/collections-agent/packages/agent-runtime/src/terminal.ts +127 -18
  343. package/templates/collections-agent/packages/agent-runtime/test/verify-cli.test.ts +211 -9
  344. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +45 -0
  345. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-session.test.ts +32 -0
  346. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +182 -0
  347. package/templates/collections-agent/scripts/whatsapp-emulator.mjs +84 -0
  348. package/templates/hello-agent/README.md +1 -1
  349. package/templates/hello-agent/packages/agent-core/README.md +14 -1
  350. package/templates/hello-agent/packages/agent-core/package.json +1 -1
  351. package/templates/hello-agent/packages/agent-core/src/agent.ts +39 -1
  352. package/templates/hello-agent/packages/agent-core/src/api/charge-rail.ts +54 -34
  353. package/templates/hello-agent/packages/agent-core/src/api/client.ts +28 -5
  354. package/templates/hello-agent/packages/agent-core/src/api/mandate-status.ts +28 -12
  355. package/templates/hello-agent/packages/agent-core/src/api/rail.ts +62 -26
  356. package/templates/hello-agent/packages/agent-core/src/api/sandbox-payer.ts +3 -18
  357. package/templates/hello-agent/packages/agent-core/src/approval.ts +14 -2
  358. package/templates/hello-agent/packages/agent-core/src/bundle.ts +35 -3
  359. package/templates/hello-agent/packages/agent-core/src/channels.ts +49 -3
  360. package/templates/hello-agent/packages/agent-core/src/check.ts +25 -2
  361. package/templates/hello-agent/packages/agent-core/src/engine.ts +235 -46
  362. package/templates/hello-agent/packages/agent-core/src/hash.ts +57 -1
  363. package/templates/hello-agent/packages/agent-core/src/index.ts +2 -0
  364. package/templates/hello-agent/packages/agent-core/src/quote.ts +50 -0
  365. package/templates/hello-agent/packages/agent-core/src/rail.ts +89 -4
  366. package/templates/hello-agent/packages/agent-core/src/receipt-chain.ts +270 -0
  367. package/templates/hello-agent/packages/agent-core/src/receipt-verification.ts +194 -18
  368. package/templates/hello-agent/packages/agent-core/src/revocation.ts +1 -1
  369. package/templates/hello-agent/packages/agent-core/src/state-machine.ts +10 -1
  370. package/templates/hello-agent/packages/agent-core/src/stubs/mandate-status.ts +4 -3
  371. package/templates/hello-agent/packages/agent-core/src/stubs/rail.ts +100 -32
  372. package/templates/hello-agent/packages/agent-core/src/tools.ts +17 -6
  373. package/templates/hello-agent/packages/agent-core/src/types.ts +54 -1
  374. package/templates/hello-agent/packages/agent-core/test/approval-seal.test.ts +233 -0
  375. package/templates/hello-agent/packages/agent-core/test/attempt-replay.test.ts +265 -0
  376. package/templates/hello-agent/packages/agent-core/test/composition.test.ts +204 -0
  377. package/templates/hello-agent/packages/agent-core/test/fixtures/production-receipt-keys.json +1 -0
  378. package/templates/hello-agent/packages/agent-core/test/helpers.ts +4 -1
  379. package/templates/hello-agent/packages/agent-core/test/mandate-status.test.ts +85 -9
  380. package/templates/hello-agent/packages/agent-core/test/quote.test.ts +198 -0
  381. package/templates/hello-agent/packages/agent-core/test/receipt-chain.test.ts +220 -0
  382. package/templates/hello-agent/packages/agent-core/test/receipt-read-verification.test.ts +197 -0
  383. package/templates/hello-agent/packages/agent-core/test/receivables.test.ts +103 -3
  384. package/templates/hello-agent/packages/agent-runtime/README.md +12 -0
  385. package/templates/hello-agent/packages/agent-runtime/src/adversarial.ts +32 -2
  386. package/templates/hello-agent/packages/agent-runtime/src/channels/types.ts +53 -4
  387. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +123 -22
  388. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +30 -20
  389. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +146 -21
  390. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +40 -3
  391. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -1
  392. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +16 -2
  393. package/templates/hello-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +70 -20
  394. package/templates/hello-agent/packages/agent-runtime/src/commands/poll.ts +2 -1
  395. package/templates/hello-agent/packages/agent-runtime/src/commands/resume.ts +8 -2
  396. package/templates/hello-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +3 -0
  397. package/templates/hello-agent/packages/agent-runtime/src/commands/start.ts +6 -3
  398. package/templates/hello-agent/packages/agent-runtime/src/commands/verify.ts +239 -38
  399. package/templates/hello-agent/packages/agent-runtime/src/commands/webhook.ts +3 -2
  400. package/templates/hello-agent/packages/agent-runtime/src/index.ts +1 -0
  401. package/templates/hello-agent/packages/agent-runtime/src/inspect.ts +5 -1
  402. package/templates/hello-agent/packages/agent-runtime/src/kit.ts +25 -2
  403. package/templates/hello-agent/packages/agent-runtime/src/scenarios.ts +8 -2
  404. package/templates/hello-agent/packages/agent-runtime/src/setup.ts +13 -3
  405. package/templates/hello-agent/packages/agent-runtime/src/terminal.ts +127 -18
  406. package/templates/hello-agent/packages/agent-runtime/test/verify-cli.test.ts +211 -9
  407. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +45 -0
  408. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-session.test.ts +32 -0
  409. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +182 -0
  410. package/templates/kits.lock.json +29 -6
  411. package/templates/supplier-payments-agent/README.md +1 -1
  412. package/templates/supplier-payments-agent/agents/supplier-payments-agent/AGENTS.md +1 -1
  413. package/templates/supplier-payments-agent/agents/supplier-payments-agent/CLAUDE.md +1 -1
  414. package/templates/supplier-payments-agent/agents/supplier-payments-agent/README.md +11 -9
  415. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/kit.ts +1 -1
  416. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/batch-payout.ts +67 -20
  417. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/batch.test.ts +504 -5
  418. package/templates/supplier-payments-agent/packages/agent-core/README.md +14 -1
  419. package/templates/supplier-payments-agent/packages/agent-core/package.json +1 -1
  420. package/templates/supplier-payments-agent/packages/agent-core/src/agent.ts +39 -1
  421. package/templates/supplier-payments-agent/packages/agent-core/src/api/charge-rail.ts +54 -34
  422. package/templates/supplier-payments-agent/packages/agent-core/src/api/client.ts +28 -5
  423. package/templates/supplier-payments-agent/packages/agent-core/src/api/mandate-status.ts +28 -12
  424. package/templates/supplier-payments-agent/packages/agent-core/src/api/rail.ts +62 -26
  425. package/templates/supplier-payments-agent/packages/agent-core/src/api/sandbox-payer.ts +3 -18
  426. package/templates/supplier-payments-agent/packages/agent-core/src/approval.ts +14 -2
  427. package/templates/supplier-payments-agent/packages/agent-core/src/bundle.ts +35 -3
  428. package/templates/supplier-payments-agent/packages/agent-core/src/channels.ts +49 -3
  429. package/templates/supplier-payments-agent/packages/agent-core/src/check.ts +25 -2
  430. package/templates/supplier-payments-agent/packages/agent-core/src/engine.ts +235 -46
  431. package/templates/supplier-payments-agent/packages/agent-core/src/hash.ts +57 -1
  432. package/templates/supplier-payments-agent/packages/agent-core/src/index.ts +2 -0
  433. package/templates/supplier-payments-agent/packages/agent-core/src/quote.ts +50 -0
  434. package/templates/supplier-payments-agent/packages/agent-core/src/rail.ts +89 -4
  435. package/templates/supplier-payments-agent/packages/agent-core/src/receipt-chain.ts +270 -0
  436. package/templates/supplier-payments-agent/packages/agent-core/src/receipt-verification.ts +194 -18
  437. package/templates/supplier-payments-agent/packages/agent-core/src/revocation.ts +1 -1
  438. package/templates/supplier-payments-agent/packages/agent-core/src/state-machine.ts +10 -1
  439. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/mandate-status.ts +4 -3
  440. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/rail.ts +100 -32
  441. package/templates/supplier-payments-agent/packages/agent-core/src/tools.ts +17 -6
  442. package/templates/supplier-payments-agent/packages/agent-core/src/types.ts +54 -1
  443. package/templates/supplier-payments-agent/packages/agent-core/test/approval-seal.test.ts +233 -0
  444. package/templates/supplier-payments-agent/packages/agent-core/test/attempt-replay.test.ts +265 -0
  445. package/templates/supplier-payments-agent/packages/agent-core/test/composition.test.ts +204 -0
  446. package/templates/supplier-payments-agent/packages/agent-core/test/fixtures/production-receipt-keys.json +1 -0
  447. package/templates/supplier-payments-agent/packages/agent-core/test/helpers.ts +4 -1
  448. package/templates/supplier-payments-agent/packages/agent-core/test/mandate-status.test.ts +85 -9
  449. package/templates/supplier-payments-agent/packages/agent-core/test/quote.test.ts +198 -0
  450. package/templates/supplier-payments-agent/packages/agent-core/test/receipt-chain.test.ts +220 -0
  451. package/templates/supplier-payments-agent/packages/agent-core/test/receipt-read-verification.test.ts +197 -0
  452. package/templates/supplier-payments-agent/packages/agent-core/test/receivables.test.ts +103 -3
  453. package/templates/supplier-payments-agent/packages/agent-runtime/README.md +12 -0
  454. package/templates/supplier-payments-agent/packages/agent-runtime/src/adversarial.ts +32 -2
  455. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/types.ts +53 -4
  456. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +123 -22
  457. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +30 -20
  458. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +146 -21
  459. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +40 -3
  460. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -1
  461. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +16 -2
  462. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +70 -20
  463. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll.ts +2 -1
  464. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/resume.ts +8 -2
  465. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +3 -0
  466. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start.ts +6 -3
  467. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/verify.ts +239 -38
  468. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/webhook.ts +3 -2
  469. package/templates/supplier-payments-agent/packages/agent-runtime/src/index.ts +1 -0
  470. package/templates/supplier-payments-agent/packages/agent-runtime/src/inspect.ts +5 -1
  471. package/templates/supplier-payments-agent/packages/agent-runtime/src/kit.ts +25 -2
  472. package/templates/supplier-payments-agent/packages/agent-runtime/src/scenarios.ts +8 -2
  473. package/templates/supplier-payments-agent/packages/agent-runtime/src/setup.ts +13 -3
  474. package/templates/supplier-payments-agent/packages/agent-runtime/src/terminal.ts +127 -18
  475. package/templates/supplier-payments-agent/packages/agent-runtime/test/verify-cli.test.ts +211 -9
  476. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +45 -0
  477. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-session.test.ts +32 -0
  478. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +182 -0
  479. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +0 -204
  480. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +0 -204
  481. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +0 -204
  482. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +0 -204
@@ -0,0 +1,316 @@
1
+ /**
2
+ * The wave-5 contract: a party with the receipt JSON and the published key set
3
+ * reaches the right answer, and the wrong answers stay apart from each other.
4
+ *
5
+ * The signatures here are made with stock `node:crypto` and a key generated in
6
+ * the test, never with the module under test: a test that signed with the
7
+ * verifier's own helper would prove the helper agrees with itself. The signed
8
+ * string is written out literally for the same reason — if the enterprise ever
9
+ * changes the shape, this line fails rather than following it.
10
+ *
11
+ * No network: the key set is a document, or a fetcher the test supplies.
12
+ */
13
+ import { createPublicKey, generateKeyPairSync, sign as signDetached, verify as nodeVerify, type KeyObject } from "node:crypto";
14
+ import { readFileSync } from "node:fs";
15
+ import { join } from "node:path";
16
+ import { describe, expect, it } from "vitest";
17
+ import {
18
+ DEFAULT_RECEIPT_KEYS_URL,
19
+ RECEIPT_SIGNATURE_DOMAIN,
20
+ VERDICT_EXIT_CODES,
21
+ receiptKeysUrl,
22
+ receiptSigningString,
23
+ verifyReceipt,
24
+ verifyReceiptWithKeys,
25
+ type PublishedReceiptKey,
26
+ } from "../src/receipt-verification.js";
27
+
28
+ const KID = "did:web:id.codespar.dev#1";
29
+ const CHAIN = "9f2c4a1b6d0e8f3a5c7b9d1e2f4a6b8c0d2e4f6a8b0c2d4e6f8a0b2c4d6e8f01";
30
+ const RECEIPT_ID = "rcpt_V1StGXR8Z5jdHi6BmyT0sw";
31
+
32
+ function keypair() {
33
+ const { privateKey, publicKey } = generateKeyPairSync("ed25519");
34
+ const raw = publicKey.export({ format: "der", type: "spki" }).subarray(-32);
35
+ return { privateKey, x: Buffer.from(raw).toString("base64url") };
36
+ }
37
+
38
+ function publishedKey(x: string, over: Partial<PublishedReceiptKey> = {}): PublishedReceiptKey {
39
+ return { kid: KID, kty: "OKP", crv: "Ed25519", x, alg: "EdDSA", use: "sig", status: "active", ...over };
40
+ }
41
+
42
+ function keySet(...keys: PublishedReceiptKey[]) {
43
+ return { issuer: "did:web:id.codespar.dev", algorithm: "Ed25519", signing_string: `${RECEIPT_SIGNATURE_DOMAIN}:<receipt_id>:<chain>`, keys };
44
+ }
45
+
46
+ function seal(privateKey: KeyObject, receiptId = RECEIPT_ID, chain = CHAIN): string {
47
+ return signDetached(null, Buffer.from(`codespar-receipt:v1:${receiptId}:${chain}`, "utf8"), privateKey).toString("base64url");
48
+ }
49
+
50
+ function receipt(over: Record<string, unknown> = {}) {
51
+ return {
52
+ receipt_id: RECEIPT_ID,
53
+ state: "paid",
54
+ mandate: { id: "mnd_1" },
55
+ payment: { amount_minor: 12345, payee: "es***@exemplo.com.br", attempt_id: "att_1", money_moved: false, sandbox: true, at: "2026-09-24T12:00:00.000Z" },
56
+ chain: CHAIN,
57
+ receipt_sig: "hmac-half-not-read-here",
58
+ receipt_sig_ed25519: null,
59
+ receipt_sig_kid: null,
60
+ ...over,
61
+ };
62
+ }
63
+
64
+ describe("the signed string", () => {
65
+ it("is the enterprise's, byte for byte", () => {
66
+ expect(receiptSigningString(RECEIPT_ID, CHAIN)).toBe(`codespar-receipt:v1:${RECEIPT_ID}:${CHAIN}`);
67
+ expect(RECEIPT_SIGNATURE_DOMAIN).toBe("codespar-receipt:v1");
68
+ });
69
+
70
+ it("names the key set of a deployment from its base url", () => {
71
+ expect(receiptKeysUrl("https://api.codespar.dev")).toBe(DEFAULT_RECEIPT_KEYS_URL);
72
+ expect(receiptKeysUrl("https://staging.example/v1/anything")).toBe("https://staging.example/.well-known/codespar-receipt-keys.json");
73
+ });
74
+ });
75
+
76
+ describe("verified", () => {
77
+ it("accepts a receipt CodeSpar sealed, and says which key signed it", () => {
78
+ const { privateKey, x } = keypair();
79
+ const report = verifyReceiptWithKeys(receipt({ receipt_sig_ed25519: seal(privateKey), receipt_sig_kid: KID }), keySet(publishedKey(x)));
80
+ expect(report.verdict).toBe("verified");
81
+ expect(report.receipt_id).toBe(RECEIPT_ID);
82
+ expect(report.kid).toBe(KID);
83
+ expect(report.key_status).toBe("active");
84
+ expect(report.signing_string).toBe(`codespar-receipt:v1:${RECEIPT_ID}:${CHAIN}`);
85
+ });
86
+
87
+ it("accepts a signature made by a RETIRED key: rotation retires, it does not revoke", () => {
88
+ const { privateKey, x } = keypair();
89
+ const retired = publishedKey(x, { status: "retired", retired_at: "2026-09-01T00:00:00.000Z" });
90
+ const report = verifyReceiptWithKeys(receipt({ receipt_sig_ed25519: seal(privateKey), receipt_sig_kid: KID }), keySet(retired, publishedKey("ignored", { kid: "did:web:id.codespar.dev#2" })));
91
+ expect(report.verdict).toBe("verified");
92
+ expect(report.key_status).toBe("retired");
93
+ });
94
+
95
+ it("still verifies the proof bundle's masked copy: the signature covers the id and the chain, not the body", () => {
96
+ const { privateKey, x } = keypair();
97
+ const sealed = receipt({ receipt_sig_ed25519: seal(privateKey), receipt_sig_kid: KID });
98
+ const masked = { ...sealed, payment: { ...sealed.payment, payee: "es***@exemplo.com.br" }, raw: undefined };
99
+ expect(verifyReceiptWithKeys(masked, keySet(publishedKey(x))).verdict).toBe("verified");
100
+ });
101
+ });
102
+
103
+ describe("tampered", () => {
104
+ it("refuses a receipt whose chain was changed after it was sealed", () => {
105
+ const { privateKey, x } = keypair();
106
+ const report = verifyReceiptWithKeys(receipt({ receipt_sig_ed25519: seal(privateKey), receipt_sig_kid: KID, chain: CHAIN.replace(/^9/, "8") }), keySet(publishedKey(x)));
107
+ expect(report.verdict).toBe("tampered");
108
+ expect(report.reason).toBe("signature_does_not_match");
109
+ });
110
+
111
+ it("refuses a signature lifted from another receipt: the id is in the signed string", () => {
112
+ const { privateKey, x } = keypair();
113
+ const other = seal(privateKey, "rcpt_somebodyelsesreceipt", CHAIN);
114
+ const report = verifyReceiptWithKeys(receipt({ receipt_sig_ed25519: other, receipt_sig_kid: KID }), keySet(publishedKey(x)));
115
+ expect(report.verdict).toBe("tampered");
116
+ });
117
+
118
+ it("refuses a signature made by a key that is not the published one, and names the deployment case", () => {
119
+ const { privateKey } = keypair();
120
+ const other = keypair();
121
+ // The shape of the staging-receipt-against-production-keys mistake: both
122
+ // deployments publish a key called `did:web:id.codespar.dev#1` and the two
123
+ // are not the same key, so the message has to offer that reading.
124
+ const report = verifyReceiptWithKeys(receipt({ receipt_sig_ed25519: seal(privateKey), receipt_sig_kid: KID }), keySet(publishedKey(other.x)));
125
+ expect(report.verdict).toBe("tampered");
126
+ expect(report.message).toContain("deployment");
127
+ });
128
+
129
+ it("refuses a signature that is not 64 base64url bytes", () => {
130
+ const { x } = keypair();
131
+ const report = verifyReceiptWithKeys(receipt({ receipt_sig_ed25519: "not-a-signature", receipt_sig_kid: KID }), keySet(publishedKey(x)));
132
+ expect(report.verdict).toBe("tampered");
133
+ expect(report.reason).toBe("signature_malformed");
134
+ });
135
+ });
136
+
137
+ describe("unsigned", () => {
138
+ it("is not a failure: it says the receipt predates the capability, and that the HMAC is unaffected", () => {
139
+ const report = verifyReceiptWithKeys(receipt(), keySet());
140
+ expect(report.verdict).toBe("unsigned");
141
+ expect(report.message).toContain("never will");
142
+ expect(report.message).toContain("HMAC");
143
+ expect(report.kid).toBeNull();
144
+ });
145
+
146
+ it("answers the same when the two fields are absent rather than null", () => {
147
+ const { receipt_sig_ed25519: _sig, receipt_sig_kid: _kid, ...older } = receipt();
148
+ expect(verifyReceiptWithKeys(older, keySet()).verdict).toBe("unsigned");
149
+ });
150
+
151
+ it("answers without a key set at all, and without fetching one", async () => {
152
+ let fetched = 0;
153
+ const report = await verifyReceipt(receipt(), {
154
+ url: "https://example.invalid/keys.json",
155
+ fetch: async () => {
156
+ fetched += 1;
157
+ return keySet();
158
+ },
159
+ });
160
+ expect(report.verdict).toBe("unsigned");
161
+ expect(fetched).toBe(0);
162
+ });
163
+
164
+ it("covers a paid charge, which the API seals nothing for", () => {
165
+ const charge = { receipt_id: "chg_1", kind: "charge", state: "paid", chain: null, receipt_sig: null, receipt_sig_ed25519: null, receipt_sig_kid: null };
166
+ expect(verifyReceiptWithKeys(charge, keySet()).verdict).toBe("unsigned");
167
+ });
168
+ });
169
+
170
+ describe("unknown_key", () => {
171
+ it("refuses to guess when the kid is not published", () => {
172
+ const { privateKey, x } = keypair();
173
+ const report = verifyReceiptWithKeys(receipt({ receipt_sig_ed25519: seal(privateKey), receipt_sig_kid: "did:web:id.codespar.dev#9" }), keySet(publishedKey(x)));
174
+ expect(report.verdict).toBe("unknown_key");
175
+ expect(report.kid).toBe("did:web:id.codespar.dev#9");
176
+ expect(report.message).toContain("retired keys published");
177
+ });
178
+
179
+ it("does not fall back to the only key in the set", () => {
180
+ const { privateKey, x } = keypair();
181
+ const report = verifyReceiptWithKeys(receipt({ receipt_sig_ed25519: seal(privateKey), receipt_sig_kid: "did:web:other.example#1" }), keySet(publishedKey(x)));
182
+ expect(report.verdict).toBe("unknown_key");
183
+ });
184
+ });
185
+
186
+ describe("unreachable", () => {
187
+ it("is what a failed fetch answers — never `tampered`", async () => {
188
+ const { privateKey } = keypair();
189
+ const report = await verifyReceipt(receipt({ receipt_sig_ed25519: seal(privateKey), receipt_sig_kid: KID }), {
190
+ url: "https://example.invalid/keys.json",
191
+ fetch: async () => {
192
+ throw new Error("getaddrinfo ENOTFOUND example.invalid");
193
+ },
194
+ });
195
+ expect(report.verdict).toBe("unreachable");
196
+ expect(report.reason).toBe("fetch_failed");
197
+ expect(report.message).toContain("Nothing is proved and nothing is disproved");
198
+ });
199
+
200
+ it("is what a document that is not a key set answers", () => {
201
+ const { privateKey } = keypair();
202
+ const report = verifyReceiptWithKeys(receipt({ receipt_sig_ed25519: seal(privateKey), receipt_sig_kid: KID }), { error: "not found" });
203
+ expect(report.verdict).toBe("unreachable");
204
+ expect(report.reason).toBe("key_document_unreadable");
205
+ });
206
+
207
+ it("is what an unusable published key answers: a key we cannot read tells us nothing about the signature", () => {
208
+ const { privateKey } = keypair();
209
+ const report = verifyReceiptWithKeys(receipt({ receipt_sig_ed25519: seal(privateKey), receipt_sig_kid: KID }), keySet(publishedKey("AAAA")));
210
+ expect(report.verdict).toBe("unreachable");
211
+ expect(report.reason).toBe("key_unusable");
212
+ });
213
+
214
+ it("fetches the published set and verifies against it when the fetch works", async () => {
215
+ const { privateKey, x } = keypair();
216
+ const seen: string[] = [];
217
+ const report = await verifyReceipt(receipt({ receipt_sig_ed25519: seal(privateKey), receipt_sig_kid: KID }), {
218
+ fetch: async (url) => {
219
+ seen.push(url);
220
+ return keySet(publishedKey(x));
221
+ },
222
+ });
223
+ expect(seen).toEqual([DEFAULT_RECEIPT_KEYS_URL]);
224
+ expect(report.verdict).toBe("verified");
225
+ });
226
+ });
227
+
228
+ describe("malformed", () => {
229
+ it("does not call an arbitrary JSON file an unsigned receipt", () => {
230
+ const report = verifyReceiptWithKeys({ hello: "world" }, keySet());
231
+ expect(report.verdict).toBe("malformed");
232
+ expect(report.reason).toBe("receipt_id_missing");
233
+ });
234
+
235
+ it("refuses a signature whose kid was deleted, instead of reading it as unsigned", () => {
236
+ const { privateKey } = keypair();
237
+ const report = verifyReceiptWithKeys(receipt({ receipt_sig_ed25519: seal(privateKey), receipt_sig_kid: null }), keySet());
238
+ expect(report.verdict).toBe("malformed");
239
+ expect(report.reason).toBe("kid_missing");
240
+ });
241
+
242
+ it("refuses a kid whose signature was deleted", () => {
243
+ const report = verifyReceiptWithKeys(receipt({ receipt_sig_kid: KID }), keySet());
244
+ expect(report.verdict).toBe("malformed");
245
+ expect(report.reason).toBe("signature_missing");
246
+ });
247
+
248
+ it("refuses a signed receipt whose chain was deleted: the signed string cannot be rebuilt", () => {
249
+ const { privateKey } = keypair();
250
+ const report = verifyReceiptWithKeys(receipt({ receipt_sig_ed25519: seal(privateKey), receipt_sig_kid: KID, chain: null }), keySet());
251
+ expect(report.verdict).toBe("malformed");
252
+ expect(report.reason).toBe("chain_missing");
253
+ });
254
+
255
+ it("refuses a JSON array or a string", () => {
256
+ expect(verifyReceiptWithKeys([], keySet()).verdict).toBe("malformed");
257
+ expect(verifyReceiptWithKeys("rcpt_1", keySet()).verdict).toBe("malformed");
258
+ });
259
+ });
260
+
261
+ describe("the exit codes", () => {
262
+ it("keep every verdict apart, and do not call an unsigned receipt a success", () => {
263
+ expect(VERDICT_EXIT_CODES.verified).toBe(0);
264
+ expect(new Set(Object.values(VERDICT_EXIT_CODES)).size).toBe(Object.keys(VERDICT_EXIT_CODES).length);
265
+ expect(Object.values(VERDICT_EXIT_CODES)).not.toContain(2); // 2 is the usage error every other command uses
266
+ });
267
+ });
268
+
269
+ describe("the check a third party reimplements", () => {
270
+ it("is four lines of node:crypto over the published JWK", () => {
271
+ const { privateKey, x } = keypair();
272
+ const signature = seal(privateKey);
273
+ // Exactly what someone outside CodeSpar writes, with no code of ours.
274
+ const ok = nodeVerify(
275
+ null,
276
+ Buffer.from(`codespar-receipt:v1:${RECEIPT_ID}:${CHAIN}`, "utf8"),
277
+ createPublicKey({ key: { kty: "OKP", crv: "Ed25519", x }, format: "jwk" }),
278
+ Buffer.from(signature, "base64url"),
279
+ );
280
+ expect(ok).toBe(true);
281
+ expect(verifyReceiptWithKeys(receipt({ receipt_sig_ed25519: signature, receipt_sig_kid: KID }), keySet(publishedKey(x))).verdict).toBe("verified");
282
+ });
283
+ });
284
+
285
+ /**
286
+ * The one fixture that is not this test's own: a receipt the CodeSpar sandbox
287
+ * actually sealed (bills-agent, staging, 2026-09-24), as the proof bundle
288
+ * wrote it, and the key set that deployment publishes, as it was served. Every
289
+ * other case here signs with a key the test made, which proves the module is
290
+ * self-consistent; this one proves it agrees with the signer.
291
+ *
292
+ * Offline: both are files. If the API ever changes the signed string, this is
293
+ * the case that fails.
294
+ */
295
+ describe("a receipt the sandbox really sealed", () => {
296
+ const dir = join(import.meta.dirname, "fixtures");
297
+ const real = JSON.parse(readFileSync(join(dir, "staging-receipt.json"), "utf8")) as Record<string, unknown>;
298
+ const realKeys = JSON.parse(readFileSync(join(dir, "staging-receipt-keys.json"), "utf8")) as unknown;
299
+
300
+ it("verifies against the key set that deployment publishes", () => {
301
+ const report = verifyReceiptWithKeys(real, realKeys, "staging");
302
+ expect(report.verdict).toBe("verified");
303
+ expect(report.kid).toBe("did:web:id.codespar.dev#1");
304
+ expect(report.signing_string).toBe(`codespar-receipt:v1:${real["receipt_id"] as string}:${real["chain"] as string}`);
305
+ });
306
+
307
+ it("is refused when one character of the chain changes", () => {
308
+ const chain = real["chain"] as string;
309
+ const edited = { ...real, chain: chain.slice(0, -1) + (chain.endsWith("0") ? "1" : "0") };
310
+ expect(verifyReceiptWithKeys(edited, realKeys, "staging").verdict).toBe("tampered");
311
+ });
312
+
313
+ it("is refused when the receipt id changes, which is why the id is in the signed string", () => {
314
+ expect(verifyReceiptWithKeys({ ...real, receipt_id: "rcpt_0000000000000000000000" }, realKeys, "staging").verdict).toBe("tampered");
315
+ });
316
+ });