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,29 @@
1
+ /**
2
+ * Update mechanisms — methodology update (replaces /void git-fetch),
3
+ * self-update, and extension update.
4
+ */
5
+ export interface UpdatePlan {
6
+ added: string[];
7
+ modified: string[];
8
+ removed: string[];
9
+ unchanged: number;
10
+ }
11
+ export interface UpdateResult {
12
+ applied: boolean;
13
+ plan: UpdatePlan;
14
+ newVersion: string;
15
+ }
16
+ /**
17
+ * Diff methodology source against project files.
18
+ * Returns a plan showing what would change.
19
+ */
20
+ export declare function diffMethodology(projectDir: string): Promise<UpdatePlan>;
21
+ /**
22
+ * Apply the update plan — copy new/modified files from source to project.
23
+ * Does NOT delete removed files (user may have customizations).
24
+ */
25
+ export declare function applyUpdate(projectDir: string): Promise<UpdateResult>;
26
+ export declare function selfUpdate(): {
27
+ success: boolean;
28
+ message: string;
29
+ };
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Update mechanisms — methodology update (replaces /void git-fetch),
3
+ * self-update, and extension update.
4
+ */
5
+ import { readFile, readdir, cp } from 'node:fs/promises';
6
+ import { existsSync } from 'node:fs';
7
+ import { join } from 'node:path';
8
+ import { execSync } from 'node:child_process';
9
+ import { readMarker, writeMarker } from './marker.js';
10
+ // ── Methodology Source Resolution ────────────────────────
11
+ async function resolveMethodologySource() {
12
+ const dir = import.meta.dirname ?? new URL('.', import.meta.url).pathname;
13
+ let current = dir;
14
+ for (let i = 0; i < 10; i++) {
15
+ if (existsSync(join(current, 'CLAUDE.md')) && existsSync(join(current, '.claude', 'commands'))) {
16
+ return current;
17
+ }
18
+ const { resolve } = await import('node:path');
19
+ current = resolve(current, '..');
20
+ }
21
+ try {
22
+ const { createRequire } = await import('node:module');
23
+ const require_ = createRequire(import.meta.url);
24
+ const pkgPath = require_.resolve('@voidforge/methodology/package.json');
25
+ const { resolve } = await import('node:path');
26
+ return resolve(pkgPath, '..');
27
+ }
28
+ catch {
29
+ // Not installed
30
+ }
31
+ throw new Error('Cannot find methodology source for update.');
32
+ }
33
+ // ── Diff ─────────────────────────────────────────────────
34
+ async function collectFiles(dir, base = '') {
35
+ if (!existsSync(dir))
36
+ return [];
37
+ const files = [];
38
+ const entries = await readdir(dir, { withFileTypes: true });
39
+ for (const entry of entries) {
40
+ const rel = base ? `${base}/${entry.name}` : entry.name;
41
+ if (entry.isDirectory()) {
42
+ files.push(...await collectFiles(join(dir, entry.name), rel));
43
+ }
44
+ else {
45
+ files.push(rel);
46
+ }
47
+ }
48
+ return files;
49
+ }
50
+ /**
51
+ * Diff methodology source against project files.
52
+ * Returns a plan showing what would change.
53
+ */
54
+ export async function diffMethodology(projectDir) {
55
+ const sourceRoot = await resolveMethodologySource();
56
+ const plan = { added: [], modified: [], removed: [], unchanged: 0 };
57
+ // Directories to compare
58
+ const dirs = [
59
+ { src: '.claude/commands', dest: '.claude/commands' },
60
+ { src: 'docs/methods', dest: 'docs/methods' },
61
+ { src: 'docs/patterns', dest: 'docs/patterns' },
62
+ { src: 'scripts/thumper', dest: 'scripts/thumper' },
63
+ ];
64
+ // Single files to compare
65
+ const singleFiles = ['CLAUDE.md', 'HOLOCRON.md', 'VERSION.md'];
66
+ // Check single files
67
+ for (const file of singleFiles) {
68
+ const srcPath = join(sourceRoot, file);
69
+ const destPath = join(projectDir, file);
70
+ if (!existsSync(srcPath))
71
+ continue;
72
+ if (!existsSync(destPath)) {
73
+ plan.added.push(file);
74
+ }
75
+ else {
76
+ const srcContent = await readFile(srcPath, 'utf-8');
77
+ const destContent = await readFile(destPath, 'utf-8');
78
+ // Skip CLAUDE.md first 10 lines (project identity) when comparing
79
+ if (file === 'CLAUDE.md') {
80
+ const srcLines = srcContent.split('\n').slice(10).join('\n');
81
+ const destLines = destContent.split('\n').slice(10).join('\n');
82
+ if (srcLines !== destLines)
83
+ plan.modified.push(file);
84
+ else
85
+ plan.unchanged++;
86
+ }
87
+ else {
88
+ if (srcContent !== destContent)
89
+ plan.modified.push(file);
90
+ else
91
+ plan.unchanged++;
92
+ }
93
+ }
94
+ }
95
+ // Check directories
96
+ for (const { src, dest } of dirs) {
97
+ const srcDir = join(sourceRoot, src);
98
+ const destDir = join(projectDir, dest);
99
+ const srcFiles = await collectFiles(srcDir);
100
+ const destFiles = await collectFiles(destDir);
101
+ const srcSet = new Set(srcFiles);
102
+ const destSet = new Set(destFiles);
103
+ for (const file of srcFiles) {
104
+ const fullDest = join(destDir, file);
105
+ if (!destSet.has(file)) {
106
+ plan.added.push(`${dest}/${file}`);
107
+ }
108
+ else {
109
+ const srcContent = await readFile(join(srcDir, file), 'utf-8');
110
+ const destContent = await readFile(fullDest, 'utf-8');
111
+ if (srcContent !== destContent) {
112
+ plan.modified.push(`${dest}/${file}`);
113
+ }
114
+ else {
115
+ plan.unchanged++;
116
+ }
117
+ }
118
+ }
119
+ // Files in project but not in source (removed upstream)
120
+ for (const file of destFiles) {
121
+ if (!srcSet.has(file)) {
122
+ plan.removed.push(`${dest}/${file}`);
123
+ }
124
+ }
125
+ }
126
+ return plan;
127
+ }
128
+ // ── Apply Update ─────────────────────────────────────────
129
+ /**
130
+ * Apply the update plan — copy new/modified files from source to project.
131
+ * Does NOT delete removed files (user may have customizations).
132
+ */
133
+ export async function applyUpdate(projectDir) {
134
+ const sourceRoot = await resolveMethodologySource();
135
+ const plan = await diffMethodology(projectDir);
136
+ // Read source VERSION.md for new version
137
+ let newVersion = 'unknown';
138
+ const versionPath = join(sourceRoot, 'VERSION.md');
139
+ if (existsSync(versionPath)) {
140
+ const content = await readFile(versionPath, 'utf-8');
141
+ const match = content.match(/(\d+\.\d+\.\d+)/);
142
+ if (match)
143
+ newVersion = match[1];
144
+ }
145
+ if (plan.added.length === 0 && plan.modified.length === 0) {
146
+ return { applied: false, plan, newVersion };
147
+ }
148
+ // Copy added + modified files
149
+ const { mkdir } = await import('node:fs/promises');
150
+ for (const file of [...plan.added, ...plan.modified]) {
151
+ // Special handling for CLAUDE.md: preserve project identity (first 10 lines)
152
+ if (file === 'CLAUDE.md') {
153
+ const srcContent = await readFile(join(sourceRoot, file), 'utf-8');
154
+ const destPath = join(projectDir, file);
155
+ if (existsSync(destPath)) {
156
+ const destContent = await readFile(destPath, 'utf-8');
157
+ const destIdentity = destContent.split('\n').slice(0, 10).join('\n');
158
+ const srcBody = srcContent.split('\n').slice(10).join('\n');
159
+ await import('node:fs/promises').then(fs => fs.writeFile(destPath, destIdentity + '\n' + srcBody, 'utf-8'));
160
+ }
161
+ else {
162
+ await cp(join(sourceRoot, file), destPath);
163
+ }
164
+ continue;
165
+ }
166
+ const srcPath = join(sourceRoot, file);
167
+ const destPath = join(projectDir, file);
168
+ const destDir = join(destPath, '..');
169
+ await mkdir(destDir, { recursive: true });
170
+ await cp(srcPath, destPath);
171
+ }
172
+ // Update marker version
173
+ const marker = await readMarker(projectDir);
174
+ if (marker) {
175
+ marker.version = newVersion;
176
+ await writeMarker(projectDir, marker);
177
+ }
178
+ return { applied: true, plan, newVersion };
179
+ }
180
+ // ── Self-Update ──────────────────────────────────────────
181
+ export function selfUpdate() {
182
+ try {
183
+ execSync('npm update -g voidforge', { stdio: 'pipe' });
184
+ return { success: true, message: 'VoidForge updated successfully.' };
185
+ }
186
+ catch (err) {
187
+ const msg = err instanceof Error ? err.message : String(err);
188
+ return { success: false, message: `Self-update failed: ${msg}` };
189
+ }
190
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * User Manager — Multi-user RBAC for Avengers Tower v7.0.
3
+ *
4
+ * Invitation-only user creation. No self-registration.
5
+ * Three roles: admin (full), deployer (build/deploy), viewer (read-only).
6
+ * Invite tokens: cryptographically random, single-use, 24h expiry.
7
+ */
8
+ import { removeUser, updateUserRole, listUsers, getUserRole, type UserRole, type SessionInfo } from './tower-auth.js';
9
+ export declare function isValidRole(role: string): role is UserRole;
10
+ /**
11
+ * Check if a session has the required role.
12
+ * Role hierarchy: admin > deployer > viewer.
13
+ */
14
+ export declare function hasRole(session: SessionInfo, requiredRole: UserRole): boolean;
15
+ /**
16
+ * Create an invitation token for a new user.
17
+ * Only admins can create invites.
18
+ */
19
+ export declare function createInvite(role: UserRole, callerSession: SessionInfo, ip: string): Promise<{
20
+ token: string;
21
+ expiresAt: number;
22
+ }>;
23
+ /**
24
+ * Complete an invitation — new user sets username, password, and gets TOTP secret.
25
+ * The invite token is consumed (single-use). If user creation fails, the invite
26
+ * is restored so it can be retried.
27
+ */
28
+ export declare function completeInvite(inviteToken: string, username: string, password: string, ip: string): Promise<{
29
+ totpSecret: string;
30
+ totpUri: string;
31
+ role: UserRole;
32
+ }>;
33
+ /**
34
+ * Check if a session has the required access level for a project.
35
+ * Admins have implicit access to all projects. Owners have full access.
36
+ * Others need an explicit access list entry with sufficient role.
37
+ */
38
+ export declare function hasProjectAccess(session: SessionInfo, projectId: string, requiredRole: 'admin' | 'deployer' | 'viewer'): Promise<boolean>;
39
+ export { removeUser, updateUserRole, listUsers, getUserRole, type UserRole, type SessionInfo, };
@@ -0,0 +1,182 @@
1
+ /**
2
+ * User Manager — Multi-user RBAC for Avengers Tower v7.0.
3
+ *
4
+ * Invitation-only user creation. No self-registration.
5
+ * Three roles: admin (full), deployer (build/deploy), viewer (read-only).
6
+ * Invite tokens: cryptographically random, single-use, 24h expiry.
7
+ */
8
+ import { randomBytes, timingSafeEqual } from 'node:crypto';
9
+ import { readFile, mkdir, open, rename } from 'node:fs/promises';
10
+ import { join } from 'node:path';
11
+ import { homedir } from 'node:os';
12
+ import { createUser, removeUser, updateUserRole, listUsers, getUserRole, } from './tower-auth.js';
13
+ import { audit } from './audit-log.js';
14
+ const VOIDFORGE_DIR = join(homedir(), '.voidforge');
15
+ const INVITES_PATH = join(VOIDFORGE_DIR, 'invites.json');
16
+ const INVITE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
17
+ const MAX_PENDING_INVITES = 50;
18
+ // ── Write serialization ────────────────────────────
19
+ let writeQueue = Promise.resolve();
20
+ function serialized(fn) {
21
+ const result = writeQueue.then(fn, () => fn());
22
+ writeQueue = result.then(() => { }, () => { });
23
+ return result;
24
+ }
25
+ // ── Invite store I/O ───────────────────────────────
26
+ async function readInviteStore() {
27
+ try {
28
+ const raw = await readFile(INVITES_PATH, 'utf-8');
29
+ const parsed = JSON.parse(raw);
30
+ if (typeof parsed !== 'object' || !Array.isArray(parsed.invites)) {
31
+ throw new Error('Invalid invite store format');
32
+ }
33
+ return parsed;
34
+ }
35
+ catch (err) {
36
+ if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {
37
+ return { invites: [] };
38
+ }
39
+ throw err;
40
+ }
41
+ }
42
+ async function writeInviteStore(store) {
43
+ await mkdir(VOIDFORGE_DIR, { recursive: true });
44
+ const data = JSON.stringify(store, null, 2);
45
+ const tmpPath = INVITES_PATH + '.tmp';
46
+ const fh = await open(tmpPath, 'w', 0o600);
47
+ try {
48
+ await fh.writeFile(data);
49
+ await fh.sync();
50
+ }
51
+ finally {
52
+ await fh.close();
53
+ }
54
+ await rename(tmpPath, INVITES_PATH);
55
+ }
56
+ // ── Role validation ────────────────────────────────
57
+ const VALID_ROLES = new Set(['admin', 'deployer', 'viewer']);
58
+ export function isValidRole(role) {
59
+ return VALID_ROLES.has(role);
60
+ }
61
+ /**
62
+ * Check if a session has the required role.
63
+ * Role hierarchy: admin > deployer > viewer.
64
+ */
65
+ export function hasRole(session, requiredRole) {
66
+ if (session.role === 'admin')
67
+ return true;
68
+ if (session.role === 'deployer')
69
+ return requiredRole !== 'admin';
70
+ return requiredRole === 'viewer';
71
+ }
72
+ // ── Invite management ──────────────────────────────
73
+ /**
74
+ * Create an invitation token for a new user.
75
+ * Only admins can create invites.
76
+ */
77
+ export async function createInvite(role, callerSession, ip) {
78
+ if (!hasRole(callerSession, 'admin')) {
79
+ await audit('access_denied', ip, callerSession.username, {
80
+ action: 'create_invite',
81
+ reason: 'insufficient_role',
82
+ });
83
+ throw new Error('Admin role required');
84
+ }
85
+ if (!isValidRole(role)) {
86
+ throw new Error('Invalid role');
87
+ }
88
+ return serialized(async () => {
89
+ const store = await readInviteStore();
90
+ // Purge expired invites
91
+ const now = Date.now();
92
+ store.invites = store.invites.filter((inv) => inv.expiresAt > now);
93
+ if (store.invites.length >= MAX_PENDING_INVITES) {
94
+ throw new Error('Too many pending invites');
95
+ }
96
+ const token = randomBytes(32).toString('hex');
97
+ const invite = {
98
+ token,
99
+ role,
100
+ createdBy: callerSession.username,
101
+ createdAt: new Date().toISOString(),
102
+ expiresAt: now + INVITE_TTL_MS,
103
+ };
104
+ store.invites.push(invite);
105
+ await writeInviteStore(store);
106
+ await audit('invite_create', ip, callerSession.username, {
107
+ role,
108
+ expiresIn: '24h',
109
+ });
110
+ return { token, expiresAt: invite.expiresAt };
111
+ });
112
+ }
113
+ /**
114
+ * Complete an invitation — new user sets username, password, and gets TOTP secret.
115
+ * The invite token is consumed (single-use). If user creation fails, the invite
116
+ * is restored so it can be retried.
117
+ */
118
+ export async function completeInvite(inviteToken, username, password, ip) {
119
+ // Validate and consume the invite token (timing-safe comparison)
120
+ const invite = await serialized(async () => {
121
+ const store = await readInviteStore();
122
+ const now = Date.now();
123
+ // Purge expired
124
+ store.invites = store.invites.filter((inv) => inv.expiresAt > now);
125
+ // Timing-safe token lookup — prevent timing side-channel on public endpoint
126
+ const tokenBuf = Buffer.from(inviteToken);
127
+ let matchIdx = -1;
128
+ for (let i = 0; i < store.invites.length; i++) {
129
+ const storedBuf = Buffer.from(store.invites[i].token);
130
+ if (tokenBuf.length === storedBuf.length && timingSafeEqual(tokenBuf, storedBuf)) {
131
+ matchIdx = i;
132
+ }
133
+ }
134
+ if (matchIdx === -1) {
135
+ throw new Error('Invalid or expired invite');
136
+ }
137
+ const found = store.invites[matchIdx];
138
+ store.invites.splice(matchIdx, 1); // Consume the token
139
+ await writeInviteStore(store);
140
+ return found;
141
+ });
142
+ // Create the user via tower-auth (handles password hashing, TOTP generation)
143
+ // If creation fails, restore the invite so it can be retried
144
+ let result;
145
+ try {
146
+ result = await createUser(username, password, invite.role);
147
+ }
148
+ catch (err) {
149
+ // Rollback: re-insert the invite token
150
+ await serialized(async () => {
151
+ const store = await readInviteStore();
152
+ store.invites.push(invite);
153
+ await writeInviteStore(store);
154
+ });
155
+ throw err;
156
+ }
157
+ await audit('invite_complete', ip, username, {
158
+ role: invite.role,
159
+ invitedBy: invite.createdBy,
160
+ });
161
+ return { ...result, role: invite.role };
162
+ }
163
+ // ── Per-project access checking ────────────────────
164
+ import { checkProjectAccess } from './project-registry.js';
165
+ /**
166
+ * Check if a session has the required access level for a project.
167
+ * Admins have implicit access to all projects. Owners have full access.
168
+ * Others need an explicit access list entry with sufficient role.
169
+ */
170
+ export async function hasProjectAccess(session, projectId, requiredRole) {
171
+ const effectiveRole = await checkProjectAccess(projectId, session.username, session.role);
172
+ if (!effectiveRole)
173
+ return false;
174
+ // Check hierarchy: admin > deployer > viewer
175
+ if (effectiveRole === 'admin')
176
+ return true;
177
+ if (effectiveRole === 'deployer')
178
+ return requiredRole !== 'admin';
179
+ return requiredRole === 'viewer';
180
+ }
181
+ // ── Re-exports for convenience ─────────────────────
182
+ export { removeUser, updateUserRole, listUsers, getUserRole, };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Password-encrypted credential vault using Node.js built-in crypto.
3
+ *
4
+ * - AES-256-GCM encryption
5
+ * - PBKDF2 key derivation (100k iterations, SHA-512)
6
+ * - Stored at ~/.voidforge/vault.enc
7
+ * - Works on macOS, Linux, Windows — zero dependencies
8
+ * - User provides the password; they can store it however they want
9
+ * (memory, 1Password, macOS Keychain, etc.)
10
+ */
11
+ /** Store a credential in the encrypted vault */
12
+ export declare function vaultSet(password: string, key: string, value: string): Promise<void>;
13
+ /** Retrieve a credential from the encrypted vault */
14
+ export declare function vaultGet(password: string, key: string): Promise<string | null>;
15
+ /** Delete a credential from the vault */
16
+ export declare function vaultDelete(password: string, key: string): Promise<void>;
17
+ /** Check if a vault file exists (doesn't need password) */
18
+ export declare function vaultExists(): boolean;
19
+ /** Check if the password can decrypt the vault (password verification) */
20
+ export declare function vaultUnlock(password: string): Promise<boolean>;
21
+ /** List which keys are stored (requires password) */
22
+ export declare function vaultKeys(password: string): Promise<string[]>;
23
+ /** Clear the in-memory session cache */
24
+ export declare function vaultLock(): void;
25
+ /** Return the vault file path (for display purposes) */
26
+ export declare function vaultPath(): string;
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Password-encrypted credential vault using Node.js built-in crypto.
3
+ *
4
+ * - AES-256-GCM encryption
5
+ * - PBKDF2 key derivation (100k iterations, SHA-512)
6
+ * - Stored at ~/.voidforge/vault.enc
7
+ * - Works on macOS, Linux, Windows — zero dependencies
8
+ * - User provides the password; they can store it however they want
9
+ * (memory, 1Password, macOS Keychain, etc.)
10
+ */
11
+ import { createCipheriv, createDecipheriv, pbkdf2, randomBytes, timingSafeEqual } from 'node:crypto';
12
+ import { readFile, rename, mkdir, open } from 'node:fs/promises';
13
+ import { join } from 'node:path';
14
+ import { existsSync } from 'node:fs';
15
+ import { homedir } from 'node:os';
16
+ const VAULT_DIR = join(homedir(), '.voidforge');
17
+ const VAULT_PATH = join(VAULT_DIR, 'vault.enc');
18
+ const ALGORITHM = 'aes-256-gcm';
19
+ const KEY_LENGTH = 32;
20
+ const IV_LENGTH = 16;
21
+ const SALT_LENGTH = 32;
22
+ const AUTH_TAG_LENGTH = 16;
23
+ const PBKDF2_ITERATIONS = 100_000;
24
+ const PBKDF2_DIGEST = 'sha512';
25
+ const MAX_PASSWORD_LENGTH = 256;
26
+ /** In-memory cache so we don't re-read the file on every call within a session */
27
+ let sessionCache = null;
28
+ /** Write queue to serialize all vault operations and prevent race conditions */
29
+ let writeQueue = Promise.resolve();
30
+ function serialized(fn) {
31
+ const result = writeQueue.then(fn, () => fn());
32
+ // Keep the chain going even if this operation fails
33
+ writeQueue = result.then(() => { }, () => { });
34
+ return result;
35
+ }
36
+ async function deriveKey(password, salt) {
37
+ const capped = password.slice(0, MAX_PASSWORD_LENGTH);
38
+ return new Promise((resolve, reject) => {
39
+ pbkdf2(capped, salt, PBKDF2_ITERATIONS, KEY_LENGTH, PBKDF2_DIGEST, (err, key) => {
40
+ if (err)
41
+ reject(err);
42
+ else
43
+ resolve(key);
44
+ });
45
+ });
46
+ }
47
+ async function encrypt(plaintext, password) {
48
+ const salt = randomBytes(SALT_LENGTH);
49
+ const iv = randomBytes(IV_LENGTH);
50
+ const key = await deriveKey(password, salt);
51
+ const cipher = createCipheriv(ALGORITHM, key, iv);
52
+ const encrypted = Buffer.concat([cipher.update(plaintext, 'utf-8'), cipher.final()]);
53
+ const authTag = cipher.getAuthTag();
54
+ // Format: salt (32) + iv (16) + authTag (16) + ciphertext
55
+ return Buffer.concat([salt, iv, authTag, encrypted]);
56
+ }
57
+ async function decrypt(data, password) {
58
+ const salt = data.subarray(0, SALT_LENGTH);
59
+ const iv = data.subarray(SALT_LENGTH, SALT_LENGTH + IV_LENGTH);
60
+ const authTag = data.subarray(SALT_LENGTH + IV_LENGTH, SALT_LENGTH + IV_LENGTH + AUTH_TAG_LENGTH);
61
+ const ciphertext = data.subarray(SALT_LENGTH + IV_LENGTH + AUTH_TAG_LENGTH);
62
+ const key = await deriveKey(password, salt);
63
+ const decipher = createDecipheriv(ALGORITHM, key, iv);
64
+ decipher.setAuthTag(authTag);
65
+ const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
66
+ return decrypted.toString('utf-8');
67
+ }
68
+ async function readVault(password) {
69
+ // QA-R2-002: Use timing-safe comparison for cache password check
70
+ // IG-R2: Return a shallow copy from cache to prevent caller mutation from corrupting the cache
71
+ if (sessionCache) {
72
+ const a = Buffer.from(sessionCache.password, 'utf-8');
73
+ const b = Buffer.from(password, 'utf-8');
74
+ if (a.length === b.length && timingSafeEqual(a, b)) {
75
+ return { ...sessionCache.data };
76
+ }
77
+ }
78
+ if (!existsSync(VAULT_PATH)) {
79
+ return {};
80
+ }
81
+ const raw = await readFile(VAULT_PATH);
82
+ const json = await decrypt(raw, password);
83
+ const data = JSON.parse(json);
84
+ sessionCache = { password, data };
85
+ return { ...data };
86
+ }
87
+ async function writeVault(password, data) {
88
+ await mkdir(VAULT_DIR, { recursive: true });
89
+ const json = JSON.stringify(data);
90
+ const encrypted = await encrypt(json, password);
91
+ // Atomic write: write to temp file, fsync, then rename over the real file.
92
+ // This prevents corruption if the process crashes mid-write.
93
+ const tmpPath = VAULT_PATH + '.tmp';
94
+ const fh = await open(tmpPath, 'w', 0o600);
95
+ try {
96
+ await fh.writeFile(encrypted);
97
+ await fh.sync();
98
+ }
99
+ finally {
100
+ await fh.close();
101
+ }
102
+ await rename(tmpPath, VAULT_PATH);
103
+ sessionCache = { password, data };
104
+ }
105
+ /** Store a credential in the encrypted vault */
106
+ export function vaultSet(password, key, value) {
107
+ return serialized(async () => {
108
+ const data = await readVault(password);
109
+ data[key] = value;
110
+ await writeVault(password, data);
111
+ });
112
+ }
113
+ /** Retrieve a credential from the encrypted vault */
114
+ export function vaultGet(password, key) {
115
+ return serialized(async () => {
116
+ const data = await readVault(password);
117
+ return data[key] ?? null;
118
+ });
119
+ }
120
+ /** Delete a credential from the vault */
121
+ export function vaultDelete(password, key) {
122
+ return serialized(async () => {
123
+ const data = await readVault(password);
124
+ delete data[key];
125
+ await writeVault(password, data);
126
+ });
127
+ }
128
+ /** Check if a vault file exists (doesn't need password) */
129
+ export function vaultExists() {
130
+ return existsSync(VAULT_PATH);
131
+ }
132
+ /** Check if the password can decrypt the vault (password verification) */
133
+ export function vaultUnlock(password) {
134
+ if (!existsSync(VAULT_PATH)) {
135
+ return Promise.resolve(true);
136
+ }
137
+ return serialized(async () => {
138
+ try {
139
+ await readVault(password);
140
+ return true;
141
+ }
142
+ catch {
143
+ return false;
144
+ }
145
+ });
146
+ }
147
+ /** List which keys are stored (requires password) */
148
+ export function vaultKeys(password) {
149
+ return serialized(async () => {
150
+ const data = await readVault(password);
151
+ return Object.keys(data);
152
+ });
153
+ }
154
+ /** Clear the in-memory session cache */
155
+ export function vaultLock() {
156
+ sessionCache = null;
157
+ }
158
+ /** Return the vault file path (for display purposes) */
159
+ export function vaultPath() {
160
+ return VAULT_PATH;
161
+ }
@@ -0,0 +1,5 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ type Handler = (req: IncomingMessage, res: ServerResponse) => Promise<void>;
3
+ export declare function addRoute(method: string, path: string, handler: Handler): void;
4
+ export declare function route(req: IncomingMessage, res: ServerResponse): Handler | null;
5
+ export {};
@@ -0,0 +1,15 @@
1
+ const routes = [];
2
+ export function addRoute(method, path, handler) {
3
+ routes.push({ method: method.toUpperCase(), path, handler });
4
+ }
5
+ export function route(req, res) {
6
+ const method = req.method?.toUpperCase() ?? 'GET';
7
+ const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);
8
+ const path = url.pathname;
9
+ for (const r of routes) {
10
+ if (r.method === method && r.path === path) {
11
+ return r.handler;
12
+ }
13
+ }
14
+ return null;
15
+ }
@@ -0,0 +1,18 @@
1
+ import './api/credentials.js';
2
+ import './api/cloud-providers.js';
3
+ import './api/prd.js';
4
+ import './api/project.js';
5
+ import './api/provision.js';
6
+ import './api/deploy.js';
7
+ import './api/projects.js';
8
+ import './api/auth.js';
9
+ import './api/users.js';
10
+ import './api/blueprint.js';
11
+ import './api/danger-room.js';
12
+ import './api/war-room.js';
13
+ export declare function checkNativeModulesChanged(): Promise<boolean>;
14
+ export declare function startServer(port: number, options?: {
15
+ remote?: boolean;
16
+ lan?: boolean;
17
+ host?: string;
18
+ }): Promise<void>;