thevoidforge 21.0.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 (328) hide show
  1. package/dist/scripts/vault-read.d.ts +11 -0
  2. package/dist/scripts/vault-read.js +89 -0
  3. package/dist/scripts/voidforge.d.ts +20 -0
  4. package/dist/scripts/voidforge.js +404 -0
  5. package/dist/tsconfig.tsbuildinfo +1 -0
  6. package/dist/wizard/api/auth.d.ts +5 -0
  7. package/dist/wizard/api/auth.js +133 -0
  8. package/dist/wizard/api/blueprint.d.ts +45 -0
  9. package/dist/wizard/api/blueprint.js +184 -0
  10. package/dist/wizard/api/cloud-providers.d.ts +16 -0
  11. package/dist/wizard/api/cloud-providers.js +363 -0
  12. package/dist/wizard/api/credentials.d.ts +1 -0
  13. package/dist/wizard/api/credentials.js +258 -0
  14. package/dist/wizard/api/danger-room.d.ts +18 -0
  15. package/dist/wizard/api/danger-room.js +401 -0
  16. package/dist/wizard/api/deploy.d.ts +4 -0
  17. package/dist/wizard/api/deploy.js +164 -0
  18. package/dist/wizard/api/prd.d.ts +1 -0
  19. package/dist/wizard/api/prd.js +363 -0
  20. package/dist/wizard/api/project.d.ts +1 -0
  21. package/dist/wizard/api/project.js +239 -0
  22. package/dist/wizard/api/projects.d.ts +6 -0
  23. package/dist/wizard/api/projects.js +648 -0
  24. package/dist/wizard/api/provision.d.ts +4 -0
  25. package/dist/wizard/api/provision.js +535 -0
  26. package/dist/wizard/api/terminal.d.ts +25 -0
  27. package/dist/wizard/api/terminal.js +241 -0
  28. package/dist/wizard/api/users.d.ts +6 -0
  29. package/dist/wizard/api/users.js +244 -0
  30. package/dist/wizard/api/war-room.d.ts +14 -0
  31. package/dist/wizard/api/war-room.js +45 -0
  32. package/dist/wizard/lib/ad-platform-core.d.ts +6 -0
  33. package/dist/wizard/lib/ad-platform-core.js +1 -0
  34. package/dist/wizard/lib/adapters/index.d.ts +52 -0
  35. package/dist/wizard/lib/adapters/index.js +38 -0
  36. package/dist/wizard/lib/adapters/sandbox-bank.d.ts +17 -0
  37. package/dist/wizard/lib/adapters/sandbox-bank.js +77 -0
  38. package/dist/wizard/lib/adapters/sandbox.d.ts +39 -0
  39. package/dist/wizard/lib/adapters/sandbox.js +174 -0
  40. package/dist/wizard/lib/adapters/stripe.d.ts +19 -0
  41. package/dist/wizard/lib/adapters/stripe.js +143 -0
  42. package/dist/wizard/lib/adapters/types.d.ts +9 -0
  43. package/dist/wizard/lib/adapters/types.js +10 -0
  44. package/dist/wizard/lib/agent-memory.d.ts +36 -0
  45. package/dist/wizard/lib/agent-memory.js +114 -0
  46. package/dist/wizard/lib/anomaly-detection.d.ts +59 -0
  47. package/dist/wizard/lib/anomaly-detection.js +122 -0
  48. package/dist/wizard/lib/anthropic.d.ts +21 -0
  49. package/dist/wizard/lib/anthropic.js +105 -0
  50. package/dist/wizard/lib/asset-scanner.d.ts +23 -0
  51. package/dist/wizard/lib/asset-scanner.js +107 -0
  52. package/dist/wizard/lib/audit-log.d.ts +23 -0
  53. package/dist/wizard/lib/audit-log.js +70 -0
  54. package/dist/wizard/lib/autonomy-controller.d.ts +76 -0
  55. package/dist/wizard/lib/autonomy-controller.js +183 -0
  56. package/dist/wizard/lib/body-parser.d.ts +2 -0
  57. package/dist/wizard/lib/body-parser.js +36 -0
  58. package/dist/wizard/lib/build-analytics.d.ts +39 -0
  59. package/dist/wizard/lib/build-analytics.js +91 -0
  60. package/dist/wizard/lib/build-step.d.ts +21 -0
  61. package/dist/wizard/lib/build-step.js +104 -0
  62. package/dist/wizard/lib/campaign-proposer.d.ts +39 -0
  63. package/dist/wizard/lib/campaign-proposer.js +180 -0
  64. package/dist/wizard/lib/campaign-state-machine.d.ts +63 -0
  65. package/dist/wizard/lib/campaign-state-machine.js +114 -0
  66. package/dist/wizard/lib/ci-generator.d.ts +14 -0
  67. package/dist/wizard/lib/ci-generator.js +187 -0
  68. package/dist/wizard/lib/claude-merge.d.ts +38 -0
  69. package/dist/wizard/lib/claude-merge.js +115 -0
  70. package/dist/wizard/lib/codegen/erd-gen.d.ts +16 -0
  71. package/dist/wizard/lib/codegen/erd-gen.js +98 -0
  72. package/dist/wizard/lib/codegen/integrations.d.ts +18 -0
  73. package/dist/wizard/lib/codegen/integrations.js +189 -0
  74. package/dist/wizard/lib/codegen/openapi-gen.d.ts +15 -0
  75. package/dist/wizard/lib/codegen/openapi-gen.js +79 -0
  76. package/dist/wizard/lib/codegen/prisma-types.d.ts +15 -0
  77. package/dist/wizard/lib/codegen/prisma-types.js +44 -0
  78. package/dist/wizard/lib/codegen/seed-gen.d.ts +16 -0
  79. package/dist/wizard/lib/codegen/seed-gen.js +128 -0
  80. package/dist/wizard/lib/compliance.d.ts +51 -0
  81. package/dist/wizard/lib/compliance.js +112 -0
  82. package/dist/wizard/lib/correlation-engine.d.ts +59 -0
  83. package/dist/wizard/lib/correlation-engine.js +151 -0
  84. package/dist/wizard/lib/cost-estimator.d.ts +22 -0
  85. package/dist/wizard/lib/cost-estimator.js +72 -0
  86. package/dist/wizard/lib/cost-tracker.d.ts +27 -0
  87. package/dist/wizard/lib/cost-tracker.js +37 -0
  88. package/dist/wizard/lib/daemon-aggregator.d.ts +71 -0
  89. package/dist/wizard/lib/daemon-aggregator.js +204 -0
  90. package/dist/wizard/lib/daemon-core.d.ts +6 -0
  91. package/dist/wizard/lib/daemon-core.js +5 -0
  92. package/dist/wizard/lib/dashboard-data.d.ts +132 -0
  93. package/dist/wizard/lib/dashboard-data.js +336 -0
  94. package/dist/wizard/lib/dashboard-ws.d.ts +25 -0
  95. package/dist/wizard/lib/dashboard-ws.js +91 -0
  96. package/dist/wizard/lib/deep-current.d.ts +77 -0
  97. package/dist/wizard/lib/deep-current.js +234 -0
  98. package/dist/wizard/lib/deploy-coordinator.d.ts +40 -0
  99. package/dist/wizard/lib/deploy-coordinator.js +86 -0
  100. package/dist/wizard/lib/deploy-log.d.ts +28 -0
  101. package/dist/wizard/lib/deploy-log.js +52 -0
  102. package/dist/wizard/lib/desktop-notify.d.ts +27 -0
  103. package/dist/wizard/lib/desktop-notify.js +98 -0
  104. package/dist/wizard/lib/dns/cloudflare-dns.d.ts +35 -0
  105. package/dist/wizard/lib/dns/cloudflare-dns.js +216 -0
  106. package/dist/wizard/lib/dns/cloudflare-registrar.d.ts +31 -0
  107. package/dist/wizard/lib/dns/cloudflare-registrar.js +148 -0
  108. package/dist/wizard/lib/dns/types.d.ts +22 -0
  109. package/dist/wizard/lib/dns/types.js +4 -0
  110. package/dist/wizard/lib/document-discovery.d.ts +33 -0
  111. package/dist/wizard/lib/document-discovery.js +145 -0
  112. package/dist/wizard/lib/env-validator.d.ts +14 -0
  113. package/dist/wizard/lib/env-validator.js +205 -0
  114. package/dist/wizard/lib/env-writer.d.ts +13 -0
  115. package/dist/wizard/lib/env-writer.js +26 -0
  116. package/dist/wizard/lib/exec.d.ts +30 -0
  117. package/dist/wizard/lib/exec.js +52 -0
  118. package/dist/wizard/lib/experiment.d.ts +70 -0
  119. package/dist/wizard/lib/experiment.js +169 -0
  120. package/dist/wizard/lib/extensions.d.ts +20 -0
  121. package/dist/wizard/lib/extensions.js +183 -0
  122. package/dist/wizard/lib/financial/adapter-factory.d.ts +47 -0
  123. package/dist/wizard/lib/financial/adapter-factory.js +225 -0
  124. package/dist/wizard/lib/financial/billing/base.d.ts +6 -0
  125. package/dist/wizard/lib/financial/billing/base.js +1 -0
  126. package/dist/wizard/lib/financial/billing/google-billing.d.ts +56 -0
  127. package/dist/wizard/lib/financial/billing/google-billing.js +298 -0
  128. package/dist/wizard/lib/financial/billing/meta-billing.d.ts +54 -0
  129. package/dist/wizard/lib/financial/billing/meta-billing.js +243 -0
  130. package/dist/wizard/lib/financial/billing/tiktok-billing.d.ts +54 -0
  131. package/dist/wizard/lib/financial/billing/tiktok-billing.js +260 -0
  132. package/dist/wizard/lib/financial/campaign/base.d.ts +13 -0
  133. package/dist/wizard/lib/financial/campaign/base.js +1 -0
  134. package/dist/wizard/lib/financial/campaign/google-campaign.d.ts +42 -0
  135. package/dist/wizard/lib/financial/campaign/google-campaign.js +388 -0
  136. package/dist/wizard/lib/financial/campaign/meta-campaign.d.ts +41 -0
  137. package/dist/wizard/lib/financial/campaign/meta-campaign.js +311 -0
  138. package/dist/wizard/lib/financial/campaign/sandbox-campaign.d.ts +45 -0
  139. package/dist/wizard/lib/financial/campaign/sandbox-campaign.js +261 -0
  140. package/dist/wizard/lib/financial/campaign/tiktok-campaign.d.ts +40 -0
  141. package/dist/wizard/lib/financial/campaign/tiktok-campaign.js +350 -0
  142. package/dist/wizard/lib/financial/funding-auto.d.ts +44 -0
  143. package/dist/wizard/lib/financial/funding-auto.js +52 -0
  144. package/dist/wizard/lib/financial/funding-policy.d.ts +60 -0
  145. package/dist/wizard/lib/financial/funding-policy.js +179 -0
  146. package/dist/wizard/lib/financial/platform-planner.d.ts +47 -0
  147. package/dist/wizard/lib/financial/platform-planner.js +134 -0
  148. package/dist/wizard/lib/financial/reconciliation-engine.d.ts +78 -0
  149. package/dist/wizard/lib/financial/reconciliation-engine.js +193 -0
  150. package/dist/wizard/lib/financial/registry.d.ts +22 -0
  151. package/dist/wizard/lib/financial/registry.js +26 -0
  152. package/dist/wizard/lib/financial/reporting.d.ts +96 -0
  153. package/dist/wizard/lib/financial/reporting.js +198 -0
  154. package/dist/wizard/lib/financial/stablecoin/base.d.ts +6 -0
  155. package/dist/wizard/lib/financial/stablecoin/base.js +1 -0
  156. package/dist/wizard/lib/financial/stablecoin/circle.d.ts +54 -0
  157. package/dist/wizard/lib/financial/stablecoin/circle.js +367 -0
  158. package/dist/wizard/lib/financial/stablecoin/mercury.d.ts +24 -0
  159. package/dist/wizard/lib/financial/stablecoin/mercury.js +171 -0
  160. package/dist/wizard/lib/financial/stablecoin/sandbox-stablecoin.d.ts +47 -0
  161. package/dist/wizard/lib/financial/stablecoin/sandbox-stablecoin.js +202 -0
  162. package/dist/wizard/lib/financial/treasury-planner.d.ts +52 -0
  163. package/dist/wizard/lib/financial/treasury-planner.js +128 -0
  164. package/dist/wizard/lib/financial-core.d.ts +6 -0
  165. package/dist/wizard/lib/financial-core.js +5 -0
  166. package/dist/wizard/lib/financial-vault.d.ts +34 -0
  167. package/dist/wizard/lib/financial-vault.js +199 -0
  168. package/dist/wizard/lib/frontmatter.d.ts +30 -0
  169. package/dist/wizard/lib/frontmatter.js +96 -0
  170. package/dist/wizard/lib/gap-analysis.d.ts +37 -0
  171. package/dist/wizard/lib/gap-analysis.js +218 -0
  172. package/dist/wizard/lib/github.d.ts +22 -0
  173. package/dist/wizard/lib/github.js +261 -0
  174. package/dist/wizard/lib/headless-deploy.d.ts +14 -0
  175. package/dist/wizard/lib/headless-deploy.js +452 -0
  176. package/dist/wizard/lib/health-monitor.d.ts +15 -0
  177. package/dist/wizard/lib/health-monitor.js +91 -0
  178. package/dist/wizard/lib/health-poller.d.ts +9 -0
  179. package/dist/wizard/lib/health-poller.js +123 -0
  180. package/dist/wizard/lib/heartbeat.d.ts +15 -0
  181. package/dist/wizard/lib/heartbeat.js +827 -0
  182. package/dist/wizard/lib/http-helpers.d.ts +9 -0
  183. package/dist/wizard/lib/http-helpers.js +24 -0
  184. package/dist/wizard/lib/image-gen.d.ts +56 -0
  185. package/dist/wizard/lib/image-gen.js +159 -0
  186. package/dist/wizard/lib/instance-sizing.d.ts +26 -0
  187. package/dist/wizard/lib/instance-sizing.js +51 -0
  188. package/dist/wizard/lib/kongo/analytics.d.ts +29 -0
  189. package/dist/wizard/lib/kongo/analytics.js +179 -0
  190. package/dist/wizard/lib/kongo/campaigns.d.ts +52 -0
  191. package/dist/wizard/lib/kongo/campaigns.js +91 -0
  192. package/dist/wizard/lib/kongo/client.d.ts +58 -0
  193. package/dist/wizard/lib/kongo/client.js +221 -0
  194. package/dist/wizard/lib/kongo/jobs.d.ts +57 -0
  195. package/dist/wizard/lib/kongo/jobs.js +122 -0
  196. package/dist/wizard/lib/kongo/pages.d.ts +60 -0
  197. package/dist/wizard/lib/kongo/pages.js +150 -0
  198. package/dist/wizard/lib/kongo/provisioner.d.ts +64 -0
  199. package/dist/wizard/lib/kongo/provisioner.js +116 -0
  200. package/dist/wizard/lib/kongo/seed.d.ts +49 -0
  201. package/dist/wizard/lib/kongo/seed.js +237 -0
  202. package/dist/wizard/lib/kongo/types.d.ts +323 -0
  203. package/dist/wizard/lib/kongo/types.js +11 -0
  204. package/dist/wizard/lib/kongo/variants.d.ts +57 -0
  205. package/dist/wizard/lib/kongo/variants.js +88 -0
  206. package/dist/wizard/lib/kongo/webhooks.d.ts +41 -0
  207. package/dist/wizard/lib/kongo/webhooks.js +112 -0
  208. package/dist/wizard/lib/marker.d.ts +28 -0
  209. package/dist/wizard/lib/marker.js +79 -0
  210. package/dist/wizard/lib/migrator.d.ts +35 -0
  211. package/dist/wizard/lib/migrator.js +190 -0
  212. package/dist/wizard/lib/natural-language-deploy.d.ts +30 -0
  213. package/dist/wizard/lib/natural-language-deploy.js +186 -0
  214. package/dist/wizard/lib/network.d.ts +22 -0
  215. package/dist/wizard/lib/network.js +72 -0
  216. package/dist/wizard/lib/oauth-core.d.ts +6 -0
  217. package/dist/wizard/lib/oauth-core.js +5 -0
  218. package/dist/wizard/lib/open-browser.d.ts +1 -0
  219. package/dist/wizard/lib/open-browser.js +26 -0
  220. package/dist/wizard/lib/patterns/ad-billing-adapter.d.ts +209 -0
  221. package/dist/wizard/lib/patterns/ad-billing-adapter.js +269 -0
  222. package/dist/wizard/lib/patterns/ad-platform-adapter.d.ts +200 -0
  223. package/dist/wizard/lib/patterns/ad-platform-adapter.js +212 -0
  224. package/dist/wizard/lib/patterns/daemon-process.d.ts +88 -0
  225. package/dist/wizard/lib/patterns/daemon-process.js +271 -0
  226. package/dist/wizard/lib/patterns/financial-transaction.d.ts +161 -0
  227. package/dist/wizard/lib/patterns/financial-transaction.js +132 -0
  228. package/dist/wizard/lib/patterns/funding-plan.d.ts +136 -0
  229. package/dist/wizard/lib/patterns/funding-plan.js +200 -0
  230. package/dist/wizard/lib/patterns/oauth-token-lifecycle.d.ts +94 -0
  231. package/dist/wizard/lib/patterns/oauth-token-lifecycle.js +139 -0
  232. package/dist/wizard/lib/patterns/outbound-rate-limiter.d.ts +67 -0
  233. package/dist/wizard/lib/patterns/outbound-rate-limiter.js +216 -0
  234. package/dist/wizard/lib/patterns/revenue-source-adapter.d.ts +96 -0
  235. package/dist/wizard/lib/patterns/revenue-source-adapter.js +182 -0
  236. package/dist/wizard/lib/patterns/stablecoin-adapter.d.ts +218 -0
  237. package/dist/wizard/lib/patterns/stablecoin-adapter.js +264 -0
  238. package/dist/wizard/lib/prd-validator.d.ts +39 -0
  239. package/dist/wizard/lib/prd-validator.js +137 -0
  240. package/dist/wizard/lib/project-init.d.ts +24 -0
  241. package/dist/wizard/lib/project-init.js +193 -0
  242. package/dist/wizard/lib/project-registry.d.ts +86 -0
  243. package/dist/wizard/lib/project-registry.js +359 -0
  244. package/dist/wizard/lib/provision-manifest.d.ts +44 -0
  245. package/dist/wizard/lib/provision-manifest.js +164 -0
  246. package/dist/wizard/lib/provisioner-registry.d.ts +15 -0
  247. package/dist/wizard/lib/provisioner-registry.js +34 -0
  248. package/dist/wizard/lib/provisioners/aws-vps.d.ts +6 -0
  249. package/dist/wizard/lib/provisioners/aws-vps.js +643 -0
  250. package/dist/wizard/lib/provisioners/cloudflare.d.ts +6 -0
  251. package/dist/wizard/lib/provisioners/cloudflare.js +300 -0
  252. package/dist/wizard/lib/provisioners/docker.d.ts +6 -0
  253. package/dist/wizard/lib/provisioners/docker.js +75 -0
  254. package/dist/wizard/lib/provisioners/http-client.d.ts +20 -0
  255. package/dist/wizard/lib/provisioners/http-client.js +79 -0
  256. package/dist/wizard/lib/provisioners/railway.d.ts +6 -0
  257. package/dist/wizard/lib/provisioners/railway.js +413 -0
  258. package/dist/wizard/lib/provisioners/scripts/caddyfile.d.ts +10 -0
  259. package/dist/wizard/lib/provisioners/scripts/caddyfile.js +54 -0
  260. package/dist/wizard/lib/provisioners/scripts/deploy-vps.d.ts +10 -0
  261. package/dist/wizard/lib/provisioners/scripts/deploy-vps.js +112 -0
  262. package/dist/wizard/lib/provisioners/scripts/docker-compose.d.ts +11 -0
  263. package/dist/wizard/lib/provisioners/scripts/docker-compose.js +91 -0
  264. package/dist/wizard/lib/provisioners/scripts/dockerfile.d.ts +5 -0
  265. package/dist/wizard/lib/provisioners/scripts/dockerfile.js +185 -0
  266. package/dist/wizard/lib/provisioners/scripts/ecosystem-config.d.ts +10 -0
  267. package/dist/wizard/lib/provisioners/scripts/ecosystem-config.js +36 -0
  268. package/dist/wizard/lib/provisioners/scripts/provision-vps.d.ts +14 -0
  269. package/dist/wizard/lib/provisioners/scripts/provision-vps.js +202 -0
  270. package/dist/wizard/lib/provisioners/scripts/rollback-vps.d.ts +10 -0
  271. package/dist/wizard/lib/provisioners/scripts/rollback-vps.js +67 -0
  272. package/dist/wizard/lib/provisioners/self-deploy.d.ts +41 -0
  273. package/dist/wizard/lib/provisioners/self-deploy.js +185 -0
  274. package/dist/wizard/lib/provisioners/static-s3.d.ts +6 -0
  275. package/dist/wizard/lib/provisioners/static-s3.js +235 -0
  276. package/dist/wizard/lib/provisioners/types.d.ts +40 -0
  277. package/dist/wizard/lib/provisioners/types.js +4 -0
  278. package/dist/wizard/lib/provisioners/vercel.d.ts +6 -0
  279. package/dist/wizard/lib/provisioners/vercel.js +287 -0
  280. package/dist/wizard/lib/pty-manager.d.ts +42 -0
  281. package/dist/wizard/lib/pty-manager.js +231 -0
  282. package/dist/wizard/lib/rate-limiter-core.d.ts +5 -0
  283. package/dist/wizard/lib/rate-limiter-core.js +5 -0
  284. package/dist/wizard/lib/reconciliation.d.ts +43 -0
  285. package/dist/wizard/lib/reconciliation.js +173 -0
  286. package/dist/wizard/lib/revenue-types.d.ts +5 -0
  287. package/dist/wizard/lib/revenue-types.js +1 -0
  288. package/dist/wizard/lib/route-optimizer.d.ts +28 -0
  289. package/dist/wizard/lib/route-optimizer.js +93 -0
  290. package/dist/wizard/lib/s3-deploy.d.ts +19 -0
  291. package/dist/wizard/lib/s3-deploy.js +156 -0
  292. package/dist/wizard/lib/safety-tiers.d.ts +76 -0
  293. package/dist/wizard/lib/safety-tiers.js +134 -0
  294. package/dist/wizard/lib/sentry-generator.d.ts +15 -0
  295. package/dist/wizard/lib/sentry-generator.js +116 -0
  296. package/dist/wizard/lib/server-config.d.ts +13 -0
  297. package/dist/wizard/lib/server-config.js +23 -0
  298. package/dist/wizard/lib/service-install.d.ts +18 -0
  299. package/dist/wizard/lib/service-install.js +182 -0
  300. package/dist/wizard/lib/site-scanner.d.ts +80 -0
  301. package/dist/wizard/lib/site-scanner.js +262 -0
  302. package/dist/wizard/lib/ssh-deploy.d.ts +25 -0
  303. package/dist/wizard/lib/ssh-deploy.js +225 -0
  304. package/dist/wizard/lib/templates.d.ts +24 -0
  305. package/dist/wizard/lib/templates.js +219 -0
  306. package/dist/wizard/lib/totp.d.ts +35 -0
  307. package/dist/wizard/lib/totp.js +276 -0
  308. package/dist/wizard/lib/tower-auth.d.ts +43 -0
  309. package/dist/wizard/lib/tower-auth.js +352 -0
  310. package/dist/wizard/lib/tower-rate-limit.d.ts +14 -0
  311. package/dist/wizard/lib/tower-rate-limit.js +61 -0
  312. package/dist/wizard/lib/tower-session.d.ts +28 -0
  313. package/dist/wizard/lib/tower-session.js +119 -0
  314. package/dist/wizard/lib/treasury-backup.d.ts +23 -0
  315. package/dist/wizard/lib/treasury-backup.js +126 -0
  316. package/dist/wizard/lib/treasury-heartbeat.d.ts +82 -0
  317. package/dist/wizard/lib/treasury-heartbeat.js +1104 -0
  318. package/dist/wizard/lib/updater.d.ts +29 -0
  319. package/dist/wizard/lib/updater.js +190 -0
  320. package/dist/wizard/lib/user-manager.d.ts +39 -0
  321. package/dist/wizard/lib/user-manager.js +182 -0
  322. package/dist/wizard/lib/vault.d.ts +26 -0
  323. package/dist/wizard/lib/vault.js +161 -0
  324. package/dist/wizard/router.d.ts +5 -0
  325. package/dist/wizard/router.js +15 -0
  326. package/dist/wizard/server.d.ts +18 -0
  327. package/dist/wizard/server.js +436 -0
  328. package/package.json +59 -0
@@ -0,0 +1,350 @@
1
+ /**
2
+ * TikTok Marketing Campaign Adapter — real implementation via node:https (zero new dependencies).
3
+ *
4
+ * Implements AdPlatformAdapter for TikTok Marketing API v1.3.
5
+ *
6
+ * TikTok Marketing API v1.3:
7
+ * Base URL: https://business-api.tiktok.com/open_api/v1.3
8
+ * Auth: Access-Token header
9
+ * Campaign CRUD via campaign/create, campaign/update
10
+ * Reporting via report/integrated/get
11
+ * Rate limit: 10 calls/sec
12
+ *
13
+ * PRD Reference: §9.5, §9.19.10, §9.20.4
14
+ * No Stubs Doctrine: every method makes a real API call or returns documented empty.
15
+ */
16
+ import { request as httpsRequest } from 'node:https';
17
+ import { toCents, toDollars, TokenBucketLimiter } from './base.js';
18
+ const TIKTOK_HOST = 'business-api.tiktok.com';
19
+ // ── HTTP helpers ─────────────────────────────────────
20
+ async function tiktokGet(path, accessToken, params) {
21
+ const query = params
22
+ ? '?' + new URLSearchParams(params).toString()
23
+ : '';
24
+ return new Promise((resolve, reject) => {
25
+ const req = httpsRequest({
26
+ hostname: TIKTOK_HOST,
27
+ path: `/open_api/v1.3${path}${query}`,
28
+ method: 'GET',
29
+ headers: {
30
+ 'Access-Token': accessToken,
31
+ 'Accept': 'application/json',
32
+ },
33
+ timeout: 15000,
34
+ }, (res) => {
35
+ let data = '';
36
+ res.on('data', (chunk) => { data += chunk.toString(); });
37
+ res.on('end', () => resolve({ status: res.statusCode ?? 500, body: data }));
38
+ });
39
+ req.on('error', reject);
40
+ req.on('timeout', () => { req.destroy(); reject(new Error('TikTok API timeout')); });
41
+ req.end();
42
+ });
43
+ }
44
+ async function tiktokPost(path, accessToken, body) {
45
+ const payload = JSON.stringify(body);
46
+ return new Promise((resolve, reject) => {
47
+ const req = httpsRequest({
48
+ hostname: TIKTOK_HOST,
49
+ path: `/open_api/v1.3${path}`,
50
+ method: 'POST',
51
+ headers: {
52
+ 'Access-Token': accessToken,
53
+ 'Content-Type': 'application/json',
54
+ 'Accept': 'application/json',
55
+ },
56
+ timeout: 15000,
57
+ }, (res) => {
58
+ let data = '';
59
+ res.on('data', (chunk) => { data += chunk.toString(); });
60
+ res.on('end', () => resolve({ status: res.statusCode ?? 500, body: data }));
61
+ });
62
+ req.on('error', reject);
63
+ req.on('timeout', () => { req.destroy(); reject(new Error('TikTok API timeout')); });
64
+ req.write(payload);
65
+ req.end();
66
+ });
67
+ }
68
+ function safeParseJson(body) {
69
+ try {
70
+ return JSON.parse(body);
71
+ }
72
+ catch {
73
+ return { message: 'Non-JSON response from TikTok API' };
74
+ }
75
+ }
76
+ function makePlatformError(code, originalCode, message, retryable = false, retryAfter) {
77
+ return { platform: 'tiktok', code, originalCode, message, retryable, retryAfter };
78
+ }
79
+ function mapObjective(obj) {
80
+ const map = {
81
+ awareness: 'REACH',
82
+ traffic: 'TRAFFIC',
83
+ conversions: 'CONVERSIONS',
84
+ };
85
+ return map[obj];
86
+ }
87
+ // ── TikTok API response handling ────────────────────
88
+ function requireSuccess(parsed, context) {
89
+ const code = parsed.code;
90
+ const message = parsed.message ?? 'Unknown error';
91
+ if (code !== 0) {
92
+ if (code === 40100) {
93
+ throw makePlatformError('AUTH_EXPIRED', code, `${context}: ${message}`);
94
+ }
95
+ if (code === 40002 || code === 40003) {
96
+ throw makePlatformError('RATE_LIMITED', code, `${context}: ${message}`, true, 1);
97
+ }
98
+ if (code === 40101 || code === 40201 || message.toLowerCase().includes('budget')) {
99
+ throw makePlatformError('BUDGET_EXCEEDED', code ?? 400, `${context}: ${message}`);
100
+ }
101
+ throw makePlatformError('UNKNOWN', code ?? 500, `${context}: ${message}`);
102
+ }
103
+ return parsed.data ?? {};
104
+ }
105
+ // ── Adapter Implementation ──────────────────────────
106
+ export class TikTokCampaignAdapter {
107
+ config;
108
+ rateLimiter;
109
+ constructor(config) {
110
+ this.config = config;
111
+ // TikTok: 10 calls/sec
112
+ this.rateLimiter = new TokenBucketLimiter({ capacity: 10, refillRate: 10 });
113
+ }
114
+ async refreshToken(token) {
115
+ // TikTok uses long-lived tokens that don't need frequent refresh.
116
+ // When they expire, re-authenticate through the OAuth flow.
117
+ // For now, return the same token — heartbeat will detect expiry.
118
+ return {
119
+ ...token,
120
+ expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
121
+ };
122
+ }
123
+ async createCampaign(config) {
124
+ if (config.complianceStatus !== 'passed') {
125
+ throw makePlatformError('UNKNOWN', 400, 'Campaign compliance not passed — cannot create');
126
+ }
127
+ await this.rateLimiter.acquire();
128
+ const { status, body } = await tiktokPost('/campaign/create/', this.config.accessToken, {
129
+ advertiser_id: this.config.appId,
130
+ campaign_name: config.name,
131
+ objective_type: mapObjective(config.objective),
132
+ budget_mode: 'BUDGET_MODE_DAY',
133
+ budget: toDollars(config.dailyBudget),
134
+ operation_status: 'DISABLE', // Create paused
135
+ // Idempotency per ADR-3: TikTok supports request_id for dedup
136
+ request_id: config.idempotencyKey,
137
+ });
138
+ if (status !== 200) {
139
+ throw makePlatformError('UNKNOWN', status, `TikTok campaign create failed: HTTP ${status}`);
140
+ }
141
+ const parsed = safeParseJson(body);
142
+ const data = requireSuccess(parsed, 'createCampaign');
143
+ const externalId = String(data.campaign_id ?? '');
144
+ return {
145
+ externalId,
146
+ platform: 'tiktok',
147
+ status: 'created',
148
+ dashboardUrl: `https://ads.tiktok.com/i18n/perf/campaign?aadvid=${this.config.appId}&campaign_id=${externalId}`,
149
+ };
150
+ }
151
+ async updateCampaign(id, changes) {
152
+ await this.rateLimiter.acquire();
153
+ const updateBody = {
154
+ advertiser_id: this.config.appId,
155
+ campaign_id: id,
156
+ };
157
+ if (changes.name !== undefined)
158
+ updateBody.campaign_name = changes.name;
159
+ if (changes.dailyBudget !== undefined)
160
+ updateBody.budget = toDollars(changes.dailyBudget);
161
+ const { status, body } = await tiktokPost('/campaign/update/', this.config.accessToken, updateBody);
162
+ if (status !== 200) {
163
+ throw makePlatformError('UNKNOWN', status, `TikTok campaign update failed: HTTP ${status}`);
164
+ }
165
+ const parsed = safeParseJson(body);
166
+ requireSuccess(parsed, 'updateCampaign');
167
+ }
168
+ async pauseCampaign(id) {
169
+ await this.rateLimiter.acquire();
170
+ const { status, body } = await tiktokPost('/campaign/status/update/', this.config.accessToken, {
171
+ advertiser_id: this.config.appId,
172
+ campaign_ids: [id],
173
+ opt_status: 'DISABLE',
174
+ });
175
+ if (status !== 200) {
176
+ throw makePlatformError('UNKNOWN', status, `TikTok campaign pause failed: HTTP ${status}`);
177
+ }
178
+ const parsed = safeParseJson(body);
179
+ requireSuccess(parsed, 'pauseCampaign');
180
+ }
181
+ async resumeCampaign(id) {
182
+ await this.rateLimiter.acquire();
183
+ const { status, body } = await tiktokPost('/campaign/status/update/', this.config.accessToken, {
184
+ advertiser_id: this.config.appId,
185
+ campaign_ids: [id],
186
+ opt_status: 'ENABLE',
187
+ });
188
+ if (status !== 200) {
189
+ throw makePlatformError('UNKNOWN', status, `TikTok campaign resume failed: HTTP ${status}`);
190
+ }
191
+ const parsed = safeParseJson(body);
192
+ requireSuccess(parsed, 'resumeCampaign');
193
+ }
194
+ async deleteCampaign(id) {
195
+ await this.rateLimiter.acquire();
196
+ const { status, body } = await tiktokPost('/campaign/status/update/', this.config.accessToken, {
197
+ advertiser_id: this.config.appId,
198
+ campaign_ids: [id],
199
+ opt_status: 'DELETE',
200
+ });
201
+ if (status !== 200) {
202
+ throw makePlatformError('UNKNOWN', status, `TikTok campaign delete failed: HTTP ${status}`);
203
+ }
204
+ const parsed = safeParseJson(body);
205
+ requireSuccess(parsed, 'deleteCampaign');
206
+ }
207
+ async updateBudget(id, dailyBudget) {
208
+ await this.rateLimiter.acquire();
209
+ const { status, body } = await tiktokPost('/campaign/update/', this.config.accessToken, {
210
+ advertiser_id: this.config.appId,
211
+ campaign_id: id,
212
+ budget: toDollars(dailyBudget),
213
+ });
214
+ if (status !== 200) {
215
+ throw makePlatformError('UNKNOWN', status, `TikTok budget update failed: HTTP ${status}`);
216
+ }
217
+ const parsed = safeParseJson(body);
218
+ requireSuccess(parsed, 'updateBudget');
219
+ }
220
+ async updateCreative(id, creative) {
221
+ await this.rateLimiter.acquire();
222
+ // TikTok creative updates go through ad objects, not campaigns
223
+ // Query the first ad under this campaign's ad groups
224
+ const { status: queryStatus, body: queryBody } = await tiktokGet('/ad/get/', this.config.accessToken, {
225
+ advertiser_id: this.config.appId,
226
+ filtering: JSON.stringify({ campaign_ids: [id] }),
227
+ page_size: '1',
228
+ });
229
+ if (queryStatus !== 200) {
230
+ throw makePlatformError('UNKNOWN', queryStatus, 'TikTok ad query failed');
231
+ }
232
+ const queryParsed = safeParseJson(queryBody);
233
+ const queryData = requireSuccess(queryParsed, 'updateCreative.query');
234
+ const ads = queryData.list ?? [];
235
+ if (ads.length === 0) {
236
+ throw makePlatformError('CREATIVE_REJECTED', 404, `No ads found for campaign ${id}`);
237
+ }
238
+ const adId = String(ads[0].ad_id ?? '');
239
+ const updateBody = {
240
+ advertiser_id: this.config.appId,
241
+ ad_id: adId,
242
+ };
243
+ if (creative.landingUrl)
244
+ updateBody.landing_page_url = creative.landingUrl;
245
+ if (creative.headlines?.[0])
246
+ updateBody.ad_name = creative.headlines[0];
247
+ if (creative.descriptions?.[0])
248
+ updateBody.ad_text = creative.descriptions[0];
249
+ if (creative.callToAction)
250
+ updateBody.call_to_action = creative.callToAction;
251
+ const { status, body } = await tiktokPost('/ad/update/', this.config.accessToken, updateBody);
252
+ if (status !== 200) {
253
+ throw makePlatformError('UNKNOWN', status, 'TikTok creative update failed');
254
+ }
255
+ const parsed = safeParseJson(body);
256
+ requireSuccess(parsed, 'updateCreative');
257
+ }
258
+ async getSpend(dateRange) {
259
+ await this.rateLimiter.acquire();
260
+ const { status, body } = await tiktokPost('/report/integrated/get/', this.config.accessToken, {
261
+ advertiser_id: this.config.appId,
262
+ report_type: 'BASIC',
263
+ dimensions: ['campaign_id'],
264
+ metrics: ['spend', 'impressions', 'clicks', 'conversion'],
265
+ data_level: 'AUCTION_CAMPAIGN',
266
+ start_date: dateRange.start.slice(0, 10),
267
+ end_date: dateRange.end.slice(0, 10),
268
+ page_size: 1000,
269
+ });
270
+ if (status !== 200) {
271
+ throw makePlatformError('UNKNOWN', status, 'TikTok spend report failed');
272
+ }
273
+ const parsed = safeParseJson(body);
274
+ const data = requireSuccess(parsed, 'getSpend');
275
+ const list = data.list ?? [];
276
+ const campaigns = list.map(row => {
277
+ const dims = row.dimensions ?? {};
278
+ const metrics = row.metrics ?? {};
279
+ return {
280
+ externalId: dims.campaign_id ?? '',
281
+ spend: toCents(parseFloat(metrics.spend ?? '0')),
282
+ impressions: parseInt(metrics.impressions ?? '0'),
283
+ clicks: parseInt(metrics.clicks ?? '0'),
284
+ conversions: parseInt(metrics.conversion ?? '0'),
285
+ };
286
+ });
287
+ const totalSpend = campaigns.reduce((sum, c) => (sum + c.spend), 0);
288
+ return { platform: 'tiktok', dateRange, totalSpend, campaigns };
289
+ }
290
+ async getPerformance(campaignId) {
291
+ await this.rateLimiter.acquire();
292
+ const today = new Date().toISOString().slice(0, 10);
293
+ const { status, body } = await tiktokPost('/report/integrated/get/', this.config.accessToken, {
294
+ advertiser_id: this.config.appId,
295
+ report_type: 'BASIC',
296
+ dimensions: ['campaign_id'],
297
+ metrics: ['spend', 'impressions', 'clicks', 'conversion', 'ctr', 'cpc'],
298
+ data_level: 'AUCTION_CAMPAIGN',
299
+ start_date: today,
300
+ end_date: today,
301
+ filtering: [{ field_name: 'campaign_ids', filter_type: 'IN', filter_value: JSON.stringify([campaignId]) }],
302
+ page_size: 1,
303
+ });
304
+ if (status !== 200) {
305
+ throw makePlatformError('UNKNOWN', status, 'TikTok performance report failed');
306
+ }
307
+ const parsed = safeParseJson(body);
308
+ const data = requireSuccess(parsed, 'getPerformance');
309
+ const list = data.list ?? [];
310
+ const metrics = list[0]?.metrics ?? {};
311
+ const spend = toCents(parseFloat(metrics.spend ?? '0'));
312
+ return {
313
+ campaignId,
314
+ impressions: parseInt(metrics.impressions ?? '0'),
315
+ clicks: parseInt(metrics.clicks ?? '0'),
316
+ conversions: parseInt(metrics.conversion ?? '0'),
317
+ spend,
318
+ ctr: parseFloat(metrics.ctr ?? '0'),
319
+ cpc: toCents(parseFloat(metrics.cpc ?? '0')),
320
+ roas: (spend > 0 ? 0 : 0), // Revenue from Stripe, not ad platform
321
+ };
322
+ }
323
+ async getInsights(campaignId, metrics) {
324
+ await this.rateLimiter.acquire();
325
+ const today = new Date().toISOString().slice(0, 10);
326
+ const { status, body } = await tiktokPost('/report/integrated/get/', this.config.accessToken, {
327
+ advertiser_id: this.config.appId,
328
+ report_type: 'BASIC',
329
+ dimensions: ['campaign_id'],
330
+ metrics,
331
+ data_level: 'AUCTION_CAMPAIGN',
332
+ start_date: today,
333
+ end_date: today,
334
+ filtering: [{ field_name: 'campaign_ids', filter_type: 'IN', filter_value: JSON.stringify([campaignId]) }],
335
+ page_size: 1,
336
+ });
337
+ if (status !== 200) {
338
+ throw makePlatformError('UNKNOWN', status, 'TikTok insights report failed');
339
+ }
340
+ const parsed = safeParseJson(body);
341
+ const data = requireSuccess(parsed, 'getInsights');
342
+ const list = data.list ?? [];
343
+ const row = list[0]?.metrics ?? {};
344
+ const result = {};
345
+ for (const metric of metrics) {
346
+ result[metric] = parseFloat(row[metric] ?? '0');
347
+ }
348
+ return { campaignId, metrics: result };
349
+ }
350
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Auto-Funding Module — bridges treasury-planner and funding-policy
3
+ * for the heartbeat daemon's runway-forecast job.
4
+ *
5
+ * Pure logic — no API calls, no file I/O, fully testable.
6
+ * Called by the heartbeat's `runway-forecast` job every 6 hours.
7
+ * If both the planner says "off-ramp needed" and the policy says "allow",
8
+ * generates a FundingPlan for the daemon to execute.
9
+ *
10
+ * PRD Reference: §15 (Rules Engine), §12.4 (FundingPlan)
11
+ * Agents: Dockson (treasury), Heartbeat daemon
12
+ */
13
+ import type { Cents, FundingPlan, StablecoinFundingSource, OperatingBankAccount } from '../patterns/funding-plan.js';
14
+ import type { FundingPlanConfig, ObligationInput } from './treasury-planner.js';
15
+ import type { PolicyDecision } from './funding-policy.js';
16
+ interface AutoFundingConfig {
17
+ source: StablecoinFundingSource;
18
+ bank: OperatingBankAccount;
19
+ planConfig: FundingPlanConfig;
20
+ /** Current pending spend across all platforms */
21
+ pendingSpendCents: Cents;
22
+ /** Current obligations (invoices, debits, buffer needs) */
23
+ obligations: ObligationInput[];
24
+ /** Whether a Google invoice is due within the threshold window */
25
+ googleInvoiceDueSoon: boolean;
26
+ /** Google invoice amount in cents */
27
+ googleInvoiceCents: Cents;
28
+ /** Whether Meta uses direct debit billing */
29
+ metaUsesDirectDebit: boolean;
30
+ /** Meta forecasted 7-day spend in cents */
31
+ metaForecast7DayCents: Cents;
32
+ /** Current debit protection buffer in cents */
33
+ debitProtectionBufferCents: Cents;
34
+ /** Whether a reconciliation discrepancy currently exists */
35
+ discrepancyExists: boolean;
36
+ /** Previous hash for chain continuity */
37
+ previousHash: string;
38
+ }
39
+ interface AutoFundingResult {
40
+ plan: FundingPlan;
41
+ policyDecisions: PolicyDecision[];
42
+ }
43
+ export declare function evaluateAutoFunding(config: AutoFundingConfig): AutoFundingResult | null;
44
+ export type { AutoFundingConfig, AutoFundingResult };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Auto-Funding Module — bridges treasury-planner and funding-policy
3
+ * for the heartbeat daemon's runway-forecast job.
4
+ *
5
+ * Pure logic — no API calls, no file I/O, fully testable.
6
+ * Called by the heartbeat's `runway-forecast` job every 6 hours.
7
+ * If both the planner says "off-ramp needed" and the policy says "allow",
8
+ * generates a FundingPlan for the daemon to execute.
9
+ *
10
+ * PRD Reference: §15 (Rules Engine), §12.4 (FundingPlan)
11
+ * Agents: Dockson (treasury), Heartbeat daemon
12
+ */
13
+ import { shouldTriggerOfframp, generateFundingPlan } from './treasury-planner.js';
14
+ import { evaluatePolicy, aggregateDecisions } from './funding-policy.js';
15
+ // ── Evaluate Auto-Funding ────────────────────────────
16
+ // Returns a FundingPlan if both planner and policy approve, null otherwise.
17
+ export function evaluateAutoFunding(config) {
18
+ // Step 1: Ask the planner if an off-ramp is even needed
19
+ const offrampCheck = shouldTriggerOfframp(config.bank.availableBalanceCents, config.planConfig.bufferTargetCents, config.pendingSpendCents);
20
+ if (!offrampCheck.shouldOfframp) {
21
+ return null;
22
+ }
23
+ // Step 2: Generate a candidate funding plan
24
+ const plan = generateFundingPlan(config.source, config.bank, config.obligations, config.planConfig, config.previousHash);
25
+ if (!plan) {
26
+ return null;
27
+ }
28
+ // Step 3: Evaluate policy against all 7 rules
29
+ const policyState = {
30
+ bankBalanceCents: config.bank.availableBalanceCents,
31
+ minimumBufferCents: config.bank.minimumBufferCents,
32
+ reservedCents: config.bank.reservedBalanceCents,
33
+ proposedOfframpCents: plan.requiredCents,
34
+ maxDailyMovementCents: config.planConfig.maxDailyOfframpCents,
35
+ googleInvoiceDueSoon: config.googleInvoiceDueSoon,
36
+ googleInvoiceCents: config.googleInvoiceCents,
37
+ metaUsesDirectDebit: config.metaUsesDirectDebit,
38
+ metaForecast7DayCents: config.metaForecast7DayCents,
39
+ debitProtectionBufferCents: config.debitProtectionBufferCents,
40
+ discrepancyExists: config.discrepancyExists,
41
+ proposingBudgetRaise: false, // auto-funding never raises budgets
42
+ platformCapability: 'FULLY_FUNDABLE', // auto-funding targets funded platforms
43
+ claimingAutonomousFunding: true, // this IS autonomous funding
44
+ };
45
+ const decisions = evaluatePolicy(policyState);
46
+ const aggregate = aggregateDecisions(decisions);
47
+ // Step 4: Block if any rule denies or freezes
48
+ if (aggregate.action === 'deny' || aggregate.action === 'freeze') {
49
+ return null;
50
+ }
51
+ return { plan, policyDecisions: decisions };
52
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Funding Policy — the 7 deterministic rules from PRD Section 15.
3
+ *
4
+ * Pure logic — no API calls, no file I/O, fully testable.
5
+ * Each rule evaluates independently and returns an allow/deny/freeze decision.
6
+ * All rules are evaluated on every cycle; the most restrictive decision wins.
7
+ *
8
+ * PRD Reference: §15 (Rules Engine V1)
9
+ * Agents: Dockson (treasury), Heartbeat daemon
10
+ */
11
+ import type { Cents, CapabilityState } from '../patterns/funding-plan.js';
12
+ interface TreasuryState {
13
+ /** Current bank available balance in cents */
14
+ bankBalanceCents: Cents;
15
+ /** Minimum operating buffer floor in cents */
16
+ minimumBufferCents: Cents;
17
+ /** Reserved balance (earmarked for pending settlements) */
18
+ reservedCents: Cents;
19
+ /** Proposed off-ramp amount in cents (0 if no off-ramp proposed) */
20
+ proposedOfframpCents: Cents;
21
+ /** Maximum allowed daily treasury movement in cents */
22
+ maxDailyMovementCents: Cents;
23
+ /** Whether a Google invoice is due within the threshold window */
24
+ googleInvoiceDueSoon: boolean;
25
+ /** Google invoice amount in cents (0 if none) */
26
+ googleInvoiceCents: Cents;
27
+ /** Whether Meta uses direct debit billing */
28
+ metaUsesDirectDebit: boolean;
29
+ /** Meta forecasted 7-day spend in cents */
30
+ metaForecast7DayCents: Cents;
31
+ /** Current debit protection buffer in cents */
32
+ debitProtectionBufferCents: Cents;
33
+ /** Whether a reconciliation discrepancy currently exists */
34
+ discrepancyExists: boolean;
35
+ /** Whether a platform budget raise is being proposed */
36
+ proposingBudgetRaise: boolean;
37
+ /** Capability state of the platform being funded */
38
+ platformCapability: CapabilityState;
39
+ /** Whether autonomous funding is being claimed */
40
+ claimingAutonomousFunding: boolean;
41
+ }
42
+ interface PolicyDecision {
43
+ rule: number;
44
+ action: 'allow' | 'deny' | 'freeze';
45
+ reason: string;
46
+ }
47
+ interface PolicyThresholds {
48
+ /** Days before Google invoice due date to start prioritizing */
49
+ googleInvoiceWindowDays: number;
50
+ /** Multiplier for debit protection buffer over forecast */
51
+ debitProtectionMultiplier: number;
52
+ }
53
+ declare const DEFAULT_THRESHOLDS: PolicyThresholds;
54
+ export declare function evaluatePolicy(state: TreasuryState, _thresholds?: PolicyThresholds): PolicyDecision[];
55
+ export declare function aggregateDecisions(decisions: PolicyDecision[]): {
56
+ action: 'allow' | 'deny' | 'freeze';
57
+ blockingRules: PolicyDecision[];
58
+ };
59
+ export type { TreasuryState, PolicyDecision, PolicyThresholds };
60
+ export { DEFAULT_THRESHOLDS };
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Funding Policy — the 7 deterministic rules from PRD Section 15.
3
+ *
4
+ * Pure logic — no API calls, no file I/O, fully testable.
5
+ * Each rule evaluates independently and returns an allow/deny/freeze decision.
6
+ * All rules are evaluated on every cycle; the most restrictive decision wins.
7
+ *
8
+ * PRD Reference: §15 (Rules Engine V1)
9
+ * Agents: Dockson (treasury), Heartbeat daemon
10
+ */
11
+ const DEFAULT_THRESHOLDS = {
12
+ googleInvoiceWindowDays: 7,
13
+ debitProtectionMultiplier: 1.0,
14
+ };
15
+ // ── Rule Evaluators ──────────────────────────────────
16
+ function evaluateRule1(state) {
17
+ // Rule 1: Maintain minimum operating buffer
18
+ const balanceAfterReserve = (state.bankBalanceCents - state.reservedCents);
19
+ if (balanceAfterReserve < state.minimumBufferCents) {
20
+ return {
21
+ rule: 1,
22
+ action: 'deny',
23
+ reason: `Balance after reserves ($${(balanceAfterReserve / 100).toFixed(2)}) below minimum buffer ($${(state.minimumBufferCents / 100).toFixed(2)}) — deny non-essential spend`,
24
+ };
25
+ }
26
+ return {
27
+ rule: 1,
28
+ action: 'allow',
29
+ reason: `Balance after reserves ($${(balanceAfterReserve / 100).toFixed(2)}) above minimum buffer ($${(state.minimumBufferCents / 100).toFixed(2)})`,
30
+ };
31
+ }
32
+ function evaluateRule2(state) {
33
+ // Rule 2: Never off-ramp more than max daily treasury movement
34
+ if (state.proposedOfframpCents > state.maxDailyMovementCents) {
35
+ return {
36
+ rule: 2,
37
+ action: 'deny',
38
+ reason: `Proposed off-ramp ($${(state.proposedOfframpCents / 100).toFixed(2)}) exceeds max daily movement ($${(state.maxDailyMovementCents / 100).toFixed(2)})`,
39
+ };
40
+ }
41
+ return {
42
+ rule: 2,
43
+ action: 'allow',
44
+ reason: `Proposed off-ramp ($${(state.proposedOfframpCents / 100).toFixed(2)}) within max daily movement ($${(state.maxDailyMovementCents / 100).toFixed(2)})`,
45
+ };
46
+ }
47
+ function evaluateRule3(state) {
48
+ // Rule 3: Never raise platform budget if bank balance after reserve falls below floor
49
+ if (!state.proposingBudgetRaise) {
50
+ return {
51
+ rule: 3,
52
+ action: 'allow',
53
+ reason: 'No budget raise proposed',
54
+ };
55
+ }
56
+ const balanceAfterReserve = (state.bankBalanceCents - state.reservedCents);
57
+ if (balanceAfterReserve < state.minimumBufferCents) {
58
+ return {
59
+ rule: 3,
60
+ action: 'deny',
61
+ reason: `Cannot raise platform budget — balance after reserve ($${(balanceAfterReserve / 100).toFixed(2)}) below floor ($${(state.minimumBufferCents / 100).toFixed(2)})`,
62
+ };
63
+ }
64
+ return {
65
+ rule: 3,
66
+ action: 'allow',
67
+ reason: `Budget raise permitted — balance after reserve ($${(balanceAfterReserve / 100).toFixed(2)}) above floor ($${(state.minimumBufferCents / 100).toFixed(2)})`,
68
+ };
69
+ }
70
+ function evaluateRule4(state) {
71
+ // Rule 4: If Google invoice due within threshold, prioritize invoice coverage
72
+ if (!state.googleInvoiceDueSoon) {
73
+ return {
74
+ rule: 4,
75
+ action: 'allow',
76
+ reason: 'No Google invoice due soon',
77
+ };
78
+ }
79
+ const availableForInvoice = (state.bankBalanceCents - state.reservedCents - state.minimumBufferCents);
80
+ if (availableForInvoice < state.googleInvoiceCents) {
81
+ return {
82
+ rule: 4,
83
+ action: 'deny',
84
+ reason: `Google invoice ($${(state.googleInvoiceCents / 100).toFixed(2)}) due soon but only $${(availableForInvoice / 100).toFixed(2)} available after reserves and buffer — prioritize invoice coverage over new expansion`,
85
+ };
86
+ }
87
+ return {
88
+ rule: 4,
89
+ action: 'allow',
90
+ reason: `Google invoice ($${(state.googleInvoiceCents / 100).toFixed(2)}) due soon — sufficient funds available ($${(availableForInvoice / 100).toFixed(2)})`,
91
+ };
92
+ }
93
+ function evaluateRule5(state) {
94
+ // Rule 5: If Meta uses direct debit, maintain debit protection buffer above 7-day forecast
95
+ if (!state.metaUsesDirectDebit) {
96
+ return {
97
+ rule: 5,
98
+ action: 'allow',
99
+ reason: 'Meta does not use direct debit',
100
+ };
101
+ }
102
+ if (state.debitProtectionBufferCents < state.metaForecast7DayCents) {
103
+ return {
104
+ rule: 5,
105
+ action: 'deny',
106
+ reason: `Debit protection buffer ($${(state.debitProtectionBufferCents / 100).toFixed(2)}) below Meta 7-day forecast ($${(state.metaForecast7DayCents / 100).toFixed(2)}) — maintain buffer before other operations`,
107
+ };
108
+ }
109
+ return {
110
+ rule: 5,
111
+ action: 'allow',
112
+ reason: `Debit protection buffer ($${(state.debitProtectionBufferCents / 100).toFixed(2)}) above Meta 7-day forecast ($${(state.metaForecast7DayCents / 100).toFixed(2)})`,
113
+ };
114
+ }
115
+ function evaluateRule6(state) {
116
+ // Rule 6: If discrepancy exists, freeze spend increases but allow monitoring
117
+ if (!state.discrepancyExists) {
118
+ return {
119
+ rule: 6,
120
+ action: 'allow',
121
+ reason: 'No reconciliation discrepancy detected',
122
+ };
123
+ }
124
+ return {
125
+ rule: 6,
126
+ action: 'freeze',
127
+ reason: 'Reconciliation discrepancy detected — freeze spend increases, allow read-only monitoring',
128
+ };
129
+ }
130
+ function evaluateRule7(state) {
131
+ // Rule 7: If platform capability is MONITORED_ONLY, never claim autonomous funding
132
+ if (state.platformCapability !== 'MONITORED_ONLY') {
133
+ return {
134
+ rule: 7,
135
+ action: 'allow',
136
+ reason: `Platform capability is ${state.platformCapability} — autonomous funding rules apply normally`,
137
+ };
138
+ }
139
+ if (state.claimingAutonomousFunding) {
140
+ return {
141
+ rule: 7,
142
+ action: 'deny',
143
+ reason: 'Platform capability is MONITORED_ONLY — cannot claim autonomous funding support',
144
+ };
145
+ }
146
+ return {
147
+ rule: 7,
148
+ action: 'allow',
149
+ reason: 'Platform is MONITORED_ONLY but no autonomous funding claimed — monitoring allowed',
150
+ };
151
+ }
152
+ // ── Main Policy Evaluator ────────────────────────────
153
+ // Evaluates all 7 rules and returns all decisions.
154
+ // The caller should enforce the most restrictive: freeze > deny > allow.
155
+ export function evaluatePolicy(state, _thresholds = DEFAULT_THRESHOLDS) {
156
+ return [
157
+ evaluateRule1(state),
158
+ evaluateRule2(state),
159
+ evaluateRule3(state),
160
+ evaluateRule4(state),
161
+ evaluateRule5(state),
162
+ evaluateRule6(state),
163
+ evaluateRule7(state),
164
+ ];
165
+ }
166
+ // ── Decision Aggregator ──────────────────────────────
167
+ // Reduces a list of decisions to a single most-restrictive action.
168
+ export function aggregateDecisions(decisions) {
169
+ const freezeRules = decisions.filter(d => d.action === 'freeze');
170
+ if (freezeRules.length > 0) {
171
+ return { action: 'freeze', blockingRules: freezeRules };
172
+ }
173
+ const denyRules = decisions.filter(d => d.action === 'deny');
174
+ if (denyRules.length > 0) {
175
+ return { action: 'deny', blockingRules: denyRules };
176
+ }
177
+ return { action: 'allow', blockingRules: [] };
178
+ }
179
+ export { DEFAULT_THRESHOLDS };