voidforge-build 23.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.claude/agents/adolin-brand.md +40 -0
- package/dist/.claude/agents/ahsoka-access-control.md +56 -0
- package/dist/.claude/agents/alfred-dependencies.md +43 -0
- package/dist/.claude/agents/alia-threat-detect.md +40 -0
- package/dist/.claude/agents/anakin-dark-side.md +41 -0
- package/dist/.claude/agents/aquaman-deep-dive.md +43 -0
- package/dist/.claude/agents/aragorn-orchestration.md +39 -0
- package/dist/.claude/agents/archer-greenfield.md +48 -0
- package/dist/.claude/agents/armin-clever.md +39 -0
- package/dist/.claude/agents/arwen-ui-polish.md +42 -0
- package/dist/.claude/agents/ashitaka-tech-debt.md +39 -0
- package/dist/.claude/agents/asuka-performance.md +39 -0
- package/dist/.claude/agents/bail-organa-governance.md +37 -0
- package/dist/.claude/agents/banner-database.md +44 -0
- package/dist/.claude/agents/barton-smoke-test.md +59 -0
- package/dist/.claude/agents/bashir-field-medic.md +63 -0
- package/dist/.claude/agents/batgirl-detail.md +43 -0
- package/dist/.claude/agents/batman-qa.md +73 -0
- package/dist/.claude/agents/bayta-evals.md +41 -0
- package/dist/.claude/agents/beast-boy-cross-env.md +43 -0
- package/dist/.claude/agents/beerus-destroyer.md +39 -0
- package/dist/.claude/agents/bel-riose-orchestration.md +40 -0
- package/dist/.claude/agents/beru-subprocess.md +37 -0
- package/dist/.claude/agents/bilbo-microcopy.md +43 -0
- package/dist/.claude/agents/black-canary-monitoring.md +43 -0
- package/dist/.claude/agents/bliss-ai-safety.md +40 -0
- package/dist/.claude/agents/bo-katan-perimeter.md +40 -0
- package/dist/.claude/agents/bombadil-forge-sync.md +62 -0
- package/dist/.claude/agents/boromir-hubris.md +40 -0
- package/dist/.claude/agents/breeze-platform-relations.md +40 -0
- package/dist/.claude/agents/bucky-legacy.md +43 -0
- package/dist/.claude/agents/bulma-engineering.md +40 -0
- package/dist/.claude/agents/calcifer-daemon.md +39 -0
- package/dist/.claude/agents/cara-dune-enforcement.md +37 -0
- package/dist/.claude/agents/cassian-recon.md +37 -0
- package/dist/.claude/agents/cc-persistent-process.md +39 -0
- package/dist/.claude/agents/celeborn-design-system.md +40 -0
- package/dist/.claude/agents/celebrimbor-forge-artist.md +62 -0
- package/dist/.claude/agents/chakotay-bridge.md +47 -0
- package/dist/.claude/agents/chani-worm-rider.md +61 -0
- package/dist/.claude/agents/chewie-dependency-audit.md +41 -0
- package/dist/.claude/agents/chrome-discovery.md +37 -0
- package/dist/.claude/agents/constantine-cursed-code.md +59 -0
- package/dist/.claude/agents/coulson-release.md +64 -0
- package/dist/.claude/agents/crusher-diagnostics.md +48 -0
- package/dist/.claude/agents/cyborg-system-integration.md +43 -0
- package/dist/.claude/agents/dalinar-positioning.md +40 -0
- package/dist/.claude/agents/daneel-model-migration.md +40 -0
- package/dist/.claude/agents/data-tech-debt.md +48 -0
- package/dist/.claude/agents/dax-legacy-wisdom.md +48 -0
- package/dist/.claude/agents/deathstroke-adversarial.md +59 -0
- package/dist/.claude/agents/denji-determination.md +39 -0
- package/dist/.claude/agents/din-djarin-bounty.md +42 -0
- package/dist/.claude/agents/dockson-treasury.md +67 -0
- package/dist/.claude/agents/dori-integration-check.md +37 -0
- package/dist/.claude/agents/dors-observability.md +40 -0
- package/dist/.claude/agents/drax-exact-match.md +42 -0
- package/dist/.claude/agents/ducem-token-economics.md +41 -0
- package/dist/.claude/agents/duncan-relay.md +40 -0
- package/dist/.claude/agents/duo-teardown.md +38 -0
- package/dist/.claude/agents/ed-network-scan.md +38 -0
- package/dist/.claude/agents/elrond-ux-strategy.md +39 -0
- package/dist/.claude/agents/eowyn-delight.md +56 -0
- package/dist/.claude/agents/erwin-strategy.md +39 -0
- package/dist/.claude/agents/ezra-catches-missed.md +40 -0
- package/dist/.claude/agents/ezri-session-analyst.md +45 -0
- package/dist/.claude/agents/falcon-migration.md +43 -0
- package/dist/.claude/agents/faramir-judgment.md +40 -0
- package/dist/.claude/agents/faye-resourceful.md +39 -0
- package/dist/.claude/agents/fenring-passive-monitor.md +37 -0
- package/dist/.claude/agents/fern-protocol.md +37 -0
- package/dist/.claude/agents/feyd-adversarial.md +41 -0
- package/dist/.claude/agents/flash-rapid-test.md +43 -0
- package/dist/.claude/agents/friday-automation.md +42 -0
- package/dist/.claude/agents/frieren-long-term.md +39 -0
- package/dist/.claude/agents/frodo-critical-path.md +40 -0
- package/dist/.claude/agents/fury-initiative.md +65 -0
- package/dist/.claude/agents/gaal-prompt-arch.md +41 -0
- package/dist/.claude/agents/galadriel-frontend.md +69 -0
- package/dist/.claude/agents/gamora-perf-assassin.md +43 -0
- package/dist/.claude/agents/gandalf-setup-wizard.md +63 -0
- package/dist/.claude/agents/gen-docs.md +37 -0
- package/dist/.claude/agents/ghanima-paired-monitor.md +37 -0
- package/dist/.claude/agents/gimli-performance.md +41 -0
- package/dist/.claude/agents/giyu-silent-guard.md +39 -0
- package/dist/.claude/agents/glorfindel-rendering.md +40 -0
- package/dist/.claude/agents/gohan-hidden-power.md +39 -0
- package/dist/.claude/agents/gojo-infinite-scale.md +39 -0
- package/dist/.claude/agents/goku-scaling.md +39 -0
- package/dist/.claude/agents/goldberry-change-detect.md +37 -0
- package/dist/.claude/agents/gordon-escalation.md +42 -0
- package/dist/.claude/agents/green-arrow-precision.md +43 -0
- package/dist/.claude/agents/green-lantern-scenarios.md +43 -0
- package/dist/.claude/agents/grogu-tiny-vulns.md +38 -0
- package/dist/.claude/agents/groot-caching.md +43 -0
- package/dist/.claude/agents/gurney-delivery.md +40 -0
- package/dist/.claude/agents/haku-deploy-wizard.md +65 -0
- package/dist/.claude/agents/haldir-boundaries.md +40 -0
- package/dist/.claude/agents/han-vuln-hunter.md +40 -0
- package/dist/.claude/agents/hange-experimentation.md +39 -0
- package/dist/.claude/agents/harah-protocol.md +38 -0
- package/dist/.claude/agents/hawkgirl-regression-sweep.md +43 -0
- package/dist/.claude/agents/heero-mission-deploy.md +39 -0
- package/dist/.claude/agents/hera-navigation.md +41 -0
- package/dist/.claude/agents/hill-mission-control.md +43 -0
- package/dist/.claude/agents/himmel-legacy.md +37 -0
- package/dist/.claude/agents/hober-tool-schema.md +40 -0
- package/dist/.claude/agents/hoid-copywriting.md +40 -0
- package/dist/.claude/agents/howl-migration.md +39 -0
- package/dist/.claude/agents/hughes-observability.md +37 -0
- package/dist/.claude/agents/huntress-flaky-bugs.md +42 -0
- package/dist/.claude/agents/irulan-historian.md +37 -0
- package/dist/.claude/agents/jake-reporter.md +45 -0
- package/dist/.claude/agents/janeway-novel-arch.md +48 -0
- package/dist/.claude/agents/janov-context-eng.md +40 -0
- package/dist/.claude/agents/jarvis-status.md +42 -0
- package/dist/.claude/agents/jean-pragmatic.md +39 -0
- package/dist/.claude/agents/jessica-voice.md +40 -0
- package/dist/.claude/agents/jet-maintenance.md +39 -0
- package/dist/.claude/agents/jin-disciplined-adv.md +39 -0
- package/dist/.claude/agents/kaji-intelligence.md +39 -0
- package/dist/.claude/agents/kaladin-organic-growth.md +40 -0
- package/dist/.claude/agents/kallen-hard-deploy.md +39 -0
- package/dist/.claude/agents/kanan-intuitive.md +41 -0
- package/dist/.claude/agents/kaoru-harmony.md +37 -0
- package/dist/.claude/agents/kaworu-solver.md +39 -0
- package/dist/.claude/agents/kelsier-growth.md +64 -0
- package/dist/.claude/agents/kenobi-security.md +70 -0
- package/dist/.claude/agents/kim-api-design.md +49 -0
- package/dist/.claude/agents/kira-pragmatic.md +48 -0
- package/dist/.claude/agents/kishibe-hardening.md +39 -0
- package/dist/.claude/agents/kohaku-rapid-response.md +36 -0
- package/dist/.claude/agents/krillin-support.md +36 -0
- package/dist/.claude/agents/kusanagi-devops.md +70 -0
- package/dist/.claude/agents/la-forge-reliability.md +63 -0
- package/dist/.claude/agents/lang-micro-changes.md +43 -0
- package/dist/.claude/agents/legolas-precision.md +42 -0
- package/dist/.claude/agents/leia-secrets.md +41 -0
- package/dist/.claude/agents/lelouch-orchestration.md +39 -0
- package/dist/.claude/agents/leto-ii-persistence.md +40 -0
- package/dist/.claude/agents/leto-protection.md +40 -0
- package/dist/.claude/agents/levi-deploy.md +40 -0
- package/dist/.claude/agents/liet-kynes-deep-system.md +40 -0
- package/dist/.claude/agents/lift-social-media.md +40 -0
- package/dist/.claude/agents/loki-chaos.md +58 -0
- package/dist/.claude/agents/lucius-config.md +43 -0
- package/dist/.claude/agents/luke-audit-journey.md +41 -0
- package/dist/.claude/agents/manhunter-shapeshifting.md +43 -0
- package/dist/.claude/agents/marsh-competitive-intel.md +41 -0
- package/dist/.claude/agents/maul-red-team.md +57 -0
- package/dist/.claude/agents/merry-pair-review.md +40 -0
- package/dist/.claude/agents/mikasa-protection.md +39 -0
- package/dist/.claude/agents/miles-teg-perf.md +40 -0
- package/dist/.claude/agents/milim-load-test.md +39 -0
- package/dist/.claude/agents/misato-operations.md +39 -0
- package/dist/.claude/agents/mob-capacity.md +39 -0
- package/dist/.claude/agents/mohiam-authentication.md +40 -0
- package/dist/.claude/agents/mon-mothma-security-mgmt.md +41 -0
- package/dist/.claude/agents/mugen-chaos.md +39 -0
- package/dist/.claude/agents/mule-adversarial-ai.md +41 -0
- package/dist/.claude/agents/mustang-cleanup.md +39 -0
- package/dist/.claude/agents/nanami-structured-ops.md +39 -0
- package/dist/.claude/agents/nausicaa-resources.md +39 -0
- package/dist/.claude/agents/navani-technical-seo.md +40 -0
- package/dist/.claude/agents/nebula-optimization.md +43 -0
- package/dist/.claude/agents/nightwing-regression.md +59 -0
- package/dist/.claude/agents/nobara-direct-fix.md +39 -0
- package/dist/.claude/agents/nog-solutions.md +48 -0
- package/dist/.claude/agents/nori-asset-scanner.md +37 -0
- package/dist/.claude/agents/obrien-root-cause.md +48 -0
- package/dist/.claude/agents/odo-structural-anomaly.md +48 -0
- package/dist/.claude/agents/okoye-data-integrity.md +43 -0
- package/dist/.claude/agents/olivier-hardening.md +39 -0
- package/dist/.claude/agents/oracle-static-analysis.md +59 -0
- package/dist/.claude/agents/ori-prompt-crafter.md +37 -0
- package/dist/.claude/agents/padme-data-protection.md +42 -0
- package/dist/.claude/agents/paris-route-planner.md +47 -0
- package/dist/.claude/agents/parker-connections.md +43 -0
- package/dist/.claude/agents/paul-orchestration.md +40 -0
- package/dist/.claude/agents/picard-architecture.md +64 -0
- package/dist/.claude/agents/piccolo-tactics.md +39 -0
- package/dist/.claude/agents/pike-bold-decisions.md +48 -0
- package/dist/.claude/agents/pippin-discovery.md +40 -0
- package/dist/.claude/agents/plo-koon-edge-cases.md +37 -0
- package/dist/.claude/agents/power-chaotic.md +39 -0
- package/dist/.claude/agents/qui-gon-subtle-vulns.md +40 -0
- package/dist/.claude/agents/radagast-edge-cases.md +41 -0
- package/dist/.claude/agents/raoden-conversion.md +41 -0
- package/dist/.claude/agents/raven-deep-analysis.md +43 -0
- package/dist/.claude/agents/red-hood-aggressive.md +47 -0
- package/dist/.claude/agents/rei-dangerous-tasks.md +39 -0
- package/dist/.claude/agents/reigen-debugger.md +39 -0
- package/dist/.claude/agents/rengoku-intense-monitor.md +39 -0
- package/dist/.claude/agents/rex-infrastructure.md +41 -0
- package/dist/.claude/agents/rhodes-production.md +43 -0
- package/dist/.claude/agents/riker-review.md +62 -0
- package/dist/.claude/agents/rimuru-adapter.md +39 -0
- package/dist/.claude/agents/riza-backup.md +39 -0
- package/dist/.claude/agents/robin-apprentice.md +42 -0
- package/dist/.claude/agents/rocket-scrappy.md +43 -0
- package/dist/.claude/agents/rogers-api-design.md +43 -0
- package/dist/.claude/agents/romanoff-integrations.md +44 -0
- package/dist/.claude/agents/sabine-unconventional.md +40 -0
- package/dist/.claude/agents/salvor-model-selection.md +42 -0
- package/dist/.claude/agents/samwise-accessibility.md +43 -0
- package/dist/.claude/agents/sarene-outreach.md +40 -0
- package/dist/.claude/agents/sasha-resources.md +37 -0
- package/dist/.claude/agents/scotty-infrastructure.md +48 -0
- package/dist/.claude/agents/seldon-ai.md +67 -0
- package/dist/.claude/agents/senku-provisioning.md +40 -0
- package/dist/.claude/agents/sentaro-scheduling.md +37 -0
- package/dist/.claude/agents/seven-optimization.md +48 -0
- package/dist/.claude/agents/shallan-creative.md +40 -0
- package/dist/.claude/agents/sheeana-transport.md +40 -0
- package/dist/.claude/agents/shuri-innovation.md +43 -0
- package/dist/.claude/agents/silver-surfer-herald.md +90 -0
- package/dist/.claude/agents/siona-evasion.md +41 -0
- package/dist/.claude/agents/sisko-campaign.md +68 -0
- package/dist/.claude/agents/spike-routing.md +40 -0
- package/dist/.claude/agents/spock-schema.md +62 -0
- package/dist/.claude/agents/starfire-brute-force.md +43 -0
- package/dist/.claude/agents/stark-backend.md +71 -0
- package/dist/.claude/agents/steris-budget.md +41 -0
- package/dist/.claude/agents/stilgar-channel-security.md +40 -0
- package/dist/.claude/agents/strange-service-arch.md +44 -0
- package/dist/.claude/agents/sung-workers.md +39 -0
- package/dist/.claude/agents/superman-strength-test.md +43 -0
- package/dist/.claude/agents/suzaku-execution.md +39 -0
- package/dist/.claude/agents/szeth-compliance.md +40 -0
- package/dist/.claude/agents/tanjiro-persistent.md +39 -0
- package/dist/.claude/agents/tchalla-quality.md +43 -0
- package/dist/.claude/agents/thanos-gauntlet.md +68 -0
- package/dist/.claude/agents/theoden-rally.md +40 -0
- package/dist/.claude/agents/thor-queues.md +44 -0
- package/dist/.claude/agents/thufir-protocol-parsing.md +40 -0
- package/dist/.claude/agents/todo-brute-force.md +39 -0
- package/dist/.claude/agents/torres-site-scanner.md +47 -0
- package/dist/.claude/agents/totoro-guardian.md +39 -0
- package/dist/.claude/agents/tpol-disciplined.md +48 -0
- package/dist/.claude/agents/treebeard-deliberation.md +41 -0
- package/dist/.claude/agents/troi-prd-compliance.md +64 -0
- package/dist/.claude/agents/trunks-rollback.md +39 -0
- package/dist/.claude/agents/tuvok-deep-current.md +63 -0
- package/dist/.claude/agents/uhura-integration.md +47 -0
- package/dist/.claude/agents/valkyrie-recovery.md +43 -0
- package/dist/.claude/agents/vegeta-monitoring.md +39 -0
- package/dist/.claude/agents/veldora-dormant.md +37 -0
- package/dist/.claude/agents/vin-analytics.md +41 -0
- package/dist/.claude/agents/vision-data-analysis.md +43 -0
- package/dist/.claude/agents/wanda-seldon-validation.md +38 -0
- package/dist/.claude/agents/wanda-state.md +43 -0
- package/dist/.claude/agents/wax-paid-ads.md +40 -0
- package/dist/.claude/agents/wayne-ab-testing.md +40 -0
- package/dist/.claude/agents/whis-precision.md +39 -0
- package/dist/.claude/agents/windu-input-validation.md +41 -0
- package/dist/.claude/agents/winry-maintenance.md +39 -0
- package/dist/.claude/agents/wonder-woman-truth.md +43 -0
- package/dist/.claude/agents/wong-documentation.md +58 -0
- package/dist/.claude/agents/worf-security-arch.md +49 -0
- package/dist/.claude/agents/yoda-auth.md +57 -0
- package/dist/.claude/agents/yueh-trust-verify.md +40 -0
- package/dist/.claude/agents/zatanna-impossible.md +43 -0
- package/dist/.claude/agents/zechs-rival.md +39 -0
- package/dist/.claude/agents/zenitsu-alerts.md +37 -0
- package/dist/.claude/commands/ai.md +84 -0
- package/dist/.claude/commands/architect.md +107 -0
- package/dist/.claude/commands/assemble.md +223 -0
- package/dist/.claude/commands/assess.md +86 -0
- package/dist/.claude/commands/blueprint.md +135 -0
- package/dist/.claude/commands/build.md +138 -0
- package/dist/.claude/commands/campaign.md +224 -0
- package/dist/.claude/commands/cultivation.md +184 -0
- package/dist/.claude/commands/current.md +128 -0
- package/dist/.claude/commands/dangerroom.md +74 -0
- package/dist/.claude/commands/debrief.md +180 -0
- package/dist/.claude/commands/deploy.md +108 -0
- package/dist/.claude/commands/devops.md +160 -0
- package/dist/.claude/commands/engage.md +135 -0
- package/dist/.claude/commands/gauntlet.md +179 -0
- package/dist/.claude/commands/git.md +104 -0
- package/dist/.claude/commands/grow.md +160 -0
- package/dist/.claude/commands/imagine.md +126 -0
- package/dist/.claude/commands/portfolio.md +51 -0
- package/dist/.claude/commands/prd.md +113 -0
- package/dist/.claude/commands/qa.md +130 -0
- package/dist/.claude/commands/review.md +9 -0
- package/dist/.claude/commands/security.md +9 -0
- package/dist/.claude/commands/sentinel.md +90 -0
- package/dist/.claude/commands/test.md +114 -0
- package/dist/.claude/commands/thumper.md +116 -0
- package/dist/.claude/commands/treasury.md +117 -0
- package/dist/.claude/commands/ux.md +132 -0
- package/dist/.claude/commands/vault.md +198 -0
- package/dist/.claude/commands/void.md +148 -0
- package/dist/CHANGELOG.md +2621 -0
- package/dist/CLAUDE.md +292 -0
- package/dist/HOLOCRON.md +859 -0
- package/dist/VERSION.md +149 -0
- package/dist/docs/NAMING_REGISTRY.md +479 -0
- package/dist/docs/methods/AI_INTELLIGENCE.md +276 -0
- package/dist/docs/methods/ASSEMBLER.md +142 -0
- package/dist/docs/methods/BACKEND_ENGINEER.md +165 -0
- package/dist/docs/methods/BUILD_JOURNAL.md +214 -0
- package/dist/docs/methods/BUILD_PROTOCOL.md +436 -0
- package/dist/docs/methods/CAMPAIGN.md +569 -0
- package/dist/docs/methods/CONTEXT_MANAGEMENT.md +189 -0
- package/dist/docs/methods/DEEP_CURRENT.md +184 -0
- package/dist/docs/methods/DEVOPS_ENGINEER.md +297 -0
- package/dist/docs/methods/FIELD_MEDIC.md +265 -0
- package/dist/docs/methods/FORGE_ARTIST.md +108 -0
- package/dist/docs/methods/FORGE_KEEPER.md +270 -0
- package/dist/docs/methods/GAUNTLET.md +364 -0
- package/dist/docs/methods/GROWTH_STRATEGIST.md +466 -0
- package/dist/docs/methods/HEARTBEAT.md +168 -0
- package/dist/docs/methods/MCP_INTEGRATION.md +139 -0
- package/dist/docs/methods/MUSTER.md +152 -0
- package/dist/docs/methods/PRD_GENERATOR.md +186 -0
- package/dist/docs/methods/PRODUCT_DESIGN_FRONTEND.md +252 -0
- package/dist/docs/methods/QA_ENGINEER.md +360 -0
- package/dist/docs/methods/RELEASE_MANAGER.md +145 -0
- package/dist/docs/methods/SECURITY_AUDITOR.md +328 -0
- package/dist/docs/methods/SUB_AGENTS.md +375 -0
- package/dist/docs/methods/SYSTEMS_ARCHITECT.md +180 -0
- package/dist/docs/methods/TESTING.md +359 -0
- package/dist/docs/methods/THUMPER.md +175 -0
- package/dist/docs/methods/TIME_VAULT.md +120 -0
- package/dist/docs/methods/TREASURY.md +184 -0
- package/dist/docs/methods/TROUBLESHOOTING.md +265 -0
- package/dist/docs/patterns/README.md +52 -0
- package/dist/docs/patterns/ad-billing-adapter.ts +537 -0
- package/dist/docs/patterns/ad-platform-adapter.ts +421 -0
- package/dist/docs/patterns/ai-classifier.ts +195 -0
- package/dist/docs/patterns/ai-eval.ts +272 -0
- package/dist/docs/patterns/ai-orchestrator.ts +341 -0
- package/dist/docs/patterns/ai-router.ts +194 -0
- package/dist/docs/patterns/ai-tool-schema.ts +237 -0
- package/dist/docs/patterns/api-route.ts +241 -0
- package/dist/docs/patterns/backtest-engine.ts +499 -0
- package/dist/docs/patterns/browser-review.ts +292 -0
- package/dist/docs/patterns/combobox.tsx +300 -0
- package/dist/docs/patterns/component.tsx +262 -0
- package/dist/docs/patterns/daemon-process.ts +338 -0
- package/dist/docs/patterns/data-pipeline.ts +297 -0
- package/dist/docs/patterns/database-migration.ts +466 -0
- package/dist/docs/patterns/e2e-test.ts +629 -0
- package/dist/docs/patterns/error-handling.ts +312 -0
- package/dist/docs/patterns/execution-safety.ts +601 -0
- package/dist/docs/patterns/financial-transaction.ts +366 -0
- package/dist/docs/patterns/funding-plan.ts +462 -0
- package/dist/docs/patterns/game-entity.ts +137 -0
- package/dist/docs/patterns/game-loop.ts +113 -0
- package/dist/docs/patterns/game-state.ts +143 -0
- package/dist/docs/patterns/job-queue.ts +225 -0
- package/dist/docs/patterns/kongo-integration.ts +164 -0
- package/dist/docs/patterns/middleware.ts +363 -0
- package/dist/docs/patterns/mobile-screen.tsx +139 -0
- package/dist/docs/patterns/mobile-service.ts +167 -0
- package/dist/docs/patterns/multi-tenant.ts +382 -0
- package/dist/docs/patterns/oauth-token-lifecycle.ts +223 -0
- package/dist/docs/patterns/outbound-rate-limiter.ts +260 -0
- package/dist/docs/patterns/prompt-template.ts +195 -0
- package/dist/docs/patterns/revenue-source-adapter.ts +311 -0
- package/dist/docs/patterns/service.ts +224 -0
- package/dist/docs/patterns/sse-endpoint.ts +118 -0
- package/dist/docs/patterns/stablecoin-adapter.ts +511 -0
- package/dist/docs/patterns/third-party-script.ts +68 -0
- package/dist/scripts/thumper/gom-jabbar.sh +241 -0
- package/dist/scripts/thumper/relay.sh +610 -0
- package/dist/scripts/thumper/scan.sh +359 -0
- package/dist/scripts/thumper/thumper.sh +190 -0
- package/dist/scripts/thumper/water-rings.sh +76 -0
- package/dist/scripts/vault-read.d.ts +11 -0
- package/dist/scripts/vault-read.js +89 -0
- package/dist/scripts/voidforge.d.ts +21 -0
- package/dist/scripts/voidforge.js +614 -0
- package/dist/wizard/api/auth.d.ts +5 -0
- package/dist/wizard/api/auth.js +139 -0
- package/dist/wizard/api/blueprint.d.ts +34 -0
- package/dist/wizard/api/blueprint.js +161 -0
- package/dist/wizard/api/cloud-providers.d.ts +16 -0
- package/dist/wizard/api/cloud-providers.js +363 -0
- package/dist/wizard/api/credentials.d.ts +1 -0
- package/dist/wizard/api/credentials.js +265 -0
- package/dist/wizard/api/danger-room.d.ts +24 -0
- package/dist/wizard/api/danger-room.js +274 -0
- package/dist/wizard/api/deploy.d.ts +4 -0
- package/dist/wizard/api/deploy.js +164 -0
- package/dist/wizard/api/prd.d.ts +1 -0
- package/dist/wizard/api/prd.js +363 -0
- package/dist/wizard/api/project.d.ts +1 -0
- package/dist/wizard/api/project.js +241 -0
- package/dist/wizard/api/projects-data.d.ts +5 -0
- package/dist/wizard/api/projects-data.js +234 -0
- package/dist/wizard/api/projects-list.d.ts +5 -0
- package/dist/wizard/api/projects-list.js +227 -0
- package/dist/wizard/api/projects.d.ts +7 -0
- package/dist/wizard/api/projects.js +273 -0
- package/dist/wizard/api/provision-status.d.ts +5 -0
- package/dist/wizard/api/provision-status.js +47 -0
- package/dist/wizard/api/provision-steps.d.ts +21 -0
- package/dist/wizard/api/provision-steps.js +44 -0
- package/dist/wizard/api/provision-validate.d.ts +22 -0
- package/dist/wizard/api/provision-validate.js +164 -0
- package/dist/wizard/api/provision.d.ts +2 -0
- package/dist/wizard/api/provision.js +239 -0
- package/dist/wizard/api/terminal.d.ts +25 -0
- package/dist/wizard/api/terminal.js +246 -0
- package/dist/wizard/api/users.d.ts +6 -0
- package/dist/wizard/api/users.js +244 -0
- package/dist/wizard/api/war-room.d.ts +16 -0
- package/dist/wizard/api/war-room.js +70 -0
- package/dist/wizard/danger-room.config.json +5 -0
- package/dist/wizard/lib/ad-platform-core.d.ts +6 -0
- package/dist/wizard/lib/ad-platform-core.js +1 -0
- package/dist/wizard/lib/adapters/index.d.ts +52 -0
- package/dist/wizard/lib/adapters/index.js +38 -0
- package/dist/wizard/lib/adapters/sandbox-bank.d.ts +17 -0
- package/dist/wizard/lib/adapters/sandbox-bank.js +77 -0
- package/dist/wizard/lib/adapters/sandbox.d.ts +39 -0
- package/dist/wizard/lib/adapters/sandbox.js +174 -0
- package/dist/wizard/lib/adapters/stripe.d.ts +19 -0
- package/dist/wizard/lib/adapters/stripe.js +143 -0
- package/dist/wizard/lib/adapters/types.d.ts +9 -0
- package/dist/wizard/lib/adapters/types.js +10 -0
- package/dist/wizard/lib/agent-memory.d.ts +36 -0
- package/dist/wizard/lib/agent-memory.js +114 -0
- package/dist/wizard/lib/agent-registry.d.ts +21 -0
- package/dist/wizard/lib/agent-registry.js +105 -0
- package/dist/wizard/lib/anomaly-detection.d.ts +59 -0
- package/dist/wizard/lib/anomaly-detection.js +122 -0
- package/dist/wizard/lib/anthropic.d.ts +21 -0
- package/dist/wizard/lib/anthropic.js +105 -0
- package/dist/wizard/lib/asset-scanner.d.ts +23 -0
- package/dist/wizard/lib/asset-scanner.js +107 -0
- package/dist/wizard/lib/audit-log.d.ts +23 -0
- package/dist/wizard/lib/audit-log.js +70 -0
- package/dist/wizard/lib/autonomy-controller.d.ts +76 -0
- package/dist/wizard/lib/autonomy-controller.js +184 -0
- package/dist/wizard/lib/body-parser.d.ts +2 -0
- package/dist/wizard/lib/body-parser.js +36 -0
- package/dist/wizard/lib/build-analytics.d.ts +39 -0
- package/dist/wizard/lib/build-analytics.js +91 -0
- package/dist/wizard/lib/build-step.d.ts +21 -0
- package/dist/wizard/lib/build-step.js +104 -0
- package/dist/wizard/lib/campaign-proposer.d.ts +39 -0
- package/dist/wizard/lib/campaign-proposer.js +181 -0
- package/dist/wizard/lib/campaign-state-machine.d.ts +63 -0
- package/dist/wizard/lib/campaign-state-machine.js +114 -0
- package/dist/wizard/lib/ci-generator.d.ts +14 -0
- package/dist/wizard/lib/ci-generator.js +187 -0
- package/dist/wizard/lib/claude-merge.d.ts +38 -0
- package/dist/wizard/lib/claude-merge.js +115 -0
- package/dist/wizard/lib/codegen/erd-gen.d.ts +16 -0
- package/dist/wizard/lib/codegen/erd-gen.js +98 -0
- package/dist/wizard/lib/codegen/integrations.d.ts +18 -0
- package/dist/wizard/lib/codegen/integrations.js +189 -0
- package/dist/wizard/lib/codegen/openapi-gen.d.ts +15 -0
- package/dist/wizard/lib/codegen/openapi-gen.js +79 -0
- package/dist/wizard/lib/codegen/prisma-types.d.ts +15 -0
- package/dist/wizard/lib/codegen/prisma-types.js +44 -0
- package/dist/wizard/lib/codegen/seed-gen.d.ts +16 -0
- package/dist/wizard/lib/codegen/seed-gen.js +128 -0
- package/dist/wizard/lib/compliance.d.ts +51 -0
- package/dist/wizard/lib/compliance.js +112 -0
- package/dist/wizard/lib/correlation-engine.d.ts +59 -0
- package/dist/wizard/lib/correlation-engine.js +152 -0
- package/dist/wizard/lib/cost-estimator.d.ts +22 -0
- package/dist/wizard/lib/cost-estimator.js +72 -0
- package/dist/wizard/lib/cost-tracker.d.ts +27 -0
- package/dist/wizard/lib/cost-tracker.js +37 -0
- package/dist/wizard/lib/daemon-aggregator.d.ts +76 -0
- package/dist/wizard/lib/daemon-aggregator.js +241 -0
- package/dist/wizard/lib/daemon-core.d.ts +16 -0
- package/dist/wizard/lib/daemon-core.js +39 -0
- package/dist/wizard/lib/dashboard-data.d.ts +123 -0
- package/dist/wizard/lib/dashboard-data.js +314 -0
- package/dist/wizard/lib/dashboard-ws.d.ts +28 -0
- package/dist/wizard/lib/dashboard-ws.js +117 -0
- package/dist/wizard/lib/deep-current.d.ts +77 -0
- package/dist/wizard/lib/deep-current.js +247 -0
- package/dist/wizard/lib/deploy-coordinator.d.ts +40 -0
- package/dist/wizard/lib/deploy-coordinator.js +86 -0
- package/dist/wizard/lib/deploy-log.d.ts +28 -0
- package/dist/wizard/lib/deploy-log.js +52 -0
- package/dist/wizard/lib/desktop-notify.d.ts +27 -0
- package/dist/wizard/lib/desktop-notify.js +98 -0
- package/dist/wizard/lib/dns/cloudflare-dns.d.ts +35 -0
- package/dist/wizard/lib/dns/cloudflare-dns.js +216 -0
- package/dist/wizard/lib/dns/cloudflare-registrar.d.ts +31 -0
- package/dist/wizard/lib/dns/cloudflare-registrar.js +148 -0
- package/dist/wizard/lib/dns/types.d.ts +22 -0
- package/dist/wizard/lib/dns/types.js +4 -0
- package/dist/wizard/lib/document-discovery.d.ts +33 -0
- package/dist/wizard/lib/document-discovery.js +145 -0
- package/dist/wizard/lib/env-validator.d.ts +14 -0
- package/dist/wizard/lib/env-validator.js +205 -0
- package/dist/wizard/lib/env-writer.d.ts +13 -0
- package/dist/wizard/lib/env-writer.js +26 -0
- package/dist/wizard/lib/exec.d.ts +30 -0
- package/dist/wizard/lib/exec.js +52 -0
- package/dist/wizard/lib/experiment.d.ts +70 -0
- package/dist/wizard/lib/experiment.js +169 -0
- package/dist/wizard/lib/extensions.d.ts +20 -0
- package/dist/wizard/lib/extensions.js +183 -0
- package/dist/wizard/lib/financial/adapter-factory.d.ts +47 -0
- package/dist/wizard/lib/financial/adapter-factory.js +225 -0
- package/dist/wizard/lib/financial/billing/base.d.ts +6 -0
- package/dist/wizard/lib/financial/billing/base.js +1 -0
- package/dist/wizard/lib/financial/billing/google-billing.d.ts +56 -0
- package/dist/wizard/lib/financial/billing/google-billing.js +298 -0
- package/dist/wizard/lib/financial/billing/meta-billing.d.ts +54 -0
- package/dist/wizard/lib/financial/billing/meta-billing.js +243 -0
- package/dist/wizard/lib/financial/billing/tiktok-billing.d.ts +54 -0
- package/dist/wizard/lib/financial/billing/tiktok-billing.js +260 -0
- package/dist/wizard/lib/financial/campaign/base.d.ts +13 -0
- package/dist/wizard/lib/financial/campaign/base.js +1 -0
- package/dist/wizard/lib/financial/campaign/campaign-common.d.ts +21 -0
- package/dist/wizard/lib/financial/campaign/campaign-common.js +58 -0
- package/dist/wizard/lib/financial/campaign/google-api.d.ts +35 -0
- package/dist/wizard/lib/financial/campaign/google-api.js +118 -0
- package/dist/wizard/lib/financial/campaign/google-campaign.d.ts +38 -0
- package/dist/wizard/lib/financial/campaign/google-campaign.js +186 -0
- package/dist/wizard/lib/financial/campaign/meta-api.d.ts +28 -0
- package/dist/wizard/lib/financial/campaign/meta-api.js +93 -0
- package/dist/wizard/lib/financial/campaign/meta-campaign.d.ts +32 -0
- package/dist/wizard/lib/financial/campaign/meta-campaign.js +189 -0
- package/dist/wizard/lib/financial/campaign/sandbox-campaign.d.ts +45 -0
- package/dist/wizard/lib/financial/campaign/sandbox-campaign.js +261 -0
- package/dist/wizard/lib/financial/campaign/tiktok-api.d.ts +25 -0
- package/dist/wizard/lib/financial/campaign/tiktok-api.js +81 -0
- package/dist/wizard/lib/financial/campaign/tiktok-campaign.d.ts +37 -0
- package/dist/wizard/lib/financial/campaign/tiktok-campaign.js +155 -0
- package/dist/wizard/lib/financial/funding-auto.d.ts +44 -0
- package/dist/wizard/lib/financial/funding-auto.js +52 -0
- package/dist/wizard/lib/financial/funding-policy.d.ts +60 -0
- package/dist/wizard/lib/financial/funding-policy.js +179 -0
- package/dist/wizard/lib/financial/platform-planner.d.ts +47 -0
- package/dist/wizard/lib/financial/platform-planner.js +134 -0
- package/dist/wizard/lib/financial/reconciliation-engine.d.ts +78 -0
- package/dist/wizard/lib/financial/reconciliation-engine.js +193 -0
- package/dist/wizard/lib/financial/registry.d.ts +22 -0
- package/dist/wizard/lib/financial/registry.js +26 -0
- package/dist/wizard/lib/financial/reporting.d.ts +96 -0
- package/dist/wizard/lib/financial/reporting.js +198 -0
- package/dist/wizard/lib/financial/stablecoin/base.d.ts +6 -0
- package/dist/wizard/lib/financial/stablecoin/base.js +1 -0
- package/dist/wizard/lib/financial/stablecoin/circle.d.ts +54 -0
- package/dist/wizard/lib/financial/stablecoin/circle.js +367 -0
- package/dist/wizard/lib/financial/stablecoin/mercury.d.ts +24 -0
- package/dist/wizard/lib/financial/stablecoin/mercury.js +171 -0
- package/dist/wizard/lib/financial/stablecoin/sandbox-stablecoin.d.ts +47 -0
- package/dist/wizard/lib/financial/stablecoin/sandbox-stablecoin.js +202 -0
- package/dist/wizard/lib/financial/treasury-planner.d.ts +52 -0
- package/dist/wizard/lib/financial/treasury-planner.js +128 -0
- package/dist/wizard/lib/financial-core.d.ts +6 -0
- package/dist/wizard/lib/financial-core.js +5 -0
- package/dist/wizard/lib/financial-vault.d.ts +34 -0
- package/dist/wizard/lib/financial-vault.js +200 -0
- package/dist/wizard/lib/frontmatter.d.ts +30 -0
- package/dist/wizard/lib/frontmatter.js +99 -0
- package/dist/wizard/lib/gap-analysis.d.ts +37 -0
- package/dist/wizard/lib/gap-analysis.js +218 -0
- package/dist/wizard/lib/github.d.ts +22 -0
- package/dist/wizard/lib/github.js +261 -0
- package/dist/wizard/lib/headless-deploy.d.ts +14 -0
- package/dist/wizard/lib/headless-deploy.js +452 -0
- package/dist/wizard/lib/health-monitor.d.ts +15 -0
- package/dist/wizard/lib/health-monitor.js +91 -0
- package/dist/wizard/lib/health-poller.d.ts +9 -0
- package/dist/wizard/lib/health-poller.js +123 -0
- package/dist/wizard/lib/heartbeat-lifecycle.d.ts +71 -0
- package/dist/wizard/lib/heartbeat-lifecycle.js +107 -0
- package/dist/wizard/lib/heartbeat-scheduler.d.ts +26 -0
- package/dist/wizard/lib/heartbeat-scheduler.js +155 -0
- package/dist/wizard/lib/heartbeat.d.ts +22 -0
- package/dist/wizard/lib/heartbeat.js +538 -0
- package/dist/wizard/lib/herald.d.ts +28 -0
- package/dist/wizard/lib/herald.js +167 -0
- package/dist/wizard/lib/http-helpers.d.ts +9 -0
- package/dist/wizard/lib/http-helpers.js +24 -0
- package/dist/wizard/lib/image-gen.d.ts +56 -0
- package/dist/wizard/lib/image-gen.js +159 -0
- package/dist/wizard/lib/instance-sizing.d.ts +26 -0
- package/dist/wizard/lib/instance-sizing.js +51 -0
- package/dist/wizard/lib/kongo/analytics.d.ts +29 -0
- package/dist/wizard/lib/kongo/analytics.js +179 -0
- package/dist/wizard/lib/kongo/campaigns.d.ts +52 -0
- package/dist/wizard/lib/kongo/campaigns.js +91 -0
- package/dist/wizard/lib/kongo/client.d.ts +58 -0
- package/dist/wizard/lib/kongo/client.js +221 -0
- package/dist/wizard/lib/kongo/jobs.d.ts +57 -0
- package/dist/wizard/lib/kongo/jobs.js +122 -0
- package/dist/wizard/lib/kongo/pages.d.ts +60 -0
- package/dist/wizard/lib/kongo/pages.js +150 -0
- package/dist/wizard/lib/kongo/provisioner.d.ts +64 -0
- package/dist/wizard/lib/kongo/provisioner.js +116 -0
- package/dist/wizard/lib/kongo/seed.d.ts +49 -0
- package/dist/wizard/lib/kongo/seed.js +237 -0
- package/dist/wizard/lib/kongo/types.d.ts +323 -0
- package/dist/wizard/lib/kongo/types.js +11 -0
- package/dist/wizard/lib/kongo/variants.d.ts +57 -0
- package/dist/wizard/lib/kongo/variants.js +88 -0
- package/dist/wizard/lib/kongo/webhooks.d.ts +41 -0
- package/dist/wizard/lib/kongo/webhooks.js +112 -0
- package/dist/wizard/lib/marker.d.ts +28 -0
- package/dist/wizard/lib/marker.js +79 -0
- package/dist/wizard/lib/migrator.d.ts +35 -0
- package/dist/wizard/lib/migrator.js +190 -0
- package/dist/wizard/lib/natural-language-deploy.d.ts +30 -0
- package/dist/wizard/lib/natural-language-deploy.js +186 -0
- package/dist/wizard/lib/network.d.ts +22 -0
- package/dist/wizard/lib/network.js +72 -0
- package/dist/wizard/lib/oauth-core.d.ts +6 -0
- package/dist/wizard/lib/oauth-core.js +5 -0
- package/dist/wizard/lib/open-browser.d.ts +1 -0
- package/dist/wizard/lib/open-browser.js +26 -0
- package/dist/wizard/lib/patterns/ad-billing-adapter.d.ts +209 -0
- package/dist/wizard/lib/patterns/ad-billing-adapter.js +269 -0
- package/dist/wizard/lib/patterns/ad-platform-adapter.d.ts +200 -0
- package/dist/wizard/lib/patterns/ad-platform-adapter.js +212 -0
- package/dist/wizard/lib/patterns/daemon-process.d.ts +88 -0
- package/dist/wizard/lib/patterns/daemon-process.js +271 -0
- package/dist/wizard/lib/patterns/financial-transaction.d.ts +171 -0
- package/dist/wizard/lib/patterns/financial-transaction.js +154 -0
- package/dist/wizard/lib/patterns/funding-plan.d.ts +136 -0
- package/dist/wizard/lib/patterns/funding-plan.js +200 -0
- package/dist/wizard/lib/patterns/oauth-token-lifecycle.d.ts +94 -0
- package/dist/wizard/lib/patterns/oauth-token-lifecycle.js +139 -0
- package/dist/wizard/lib/patterns/outbound-rate-limiter.d.ts +67 -0
- package/dist/wizard/lib/patterns/outbound-rate-limiter.js +216 -0
- package/dist/wizard/lib/patterns/revenue-source-adapter.d.ts +96 -0
- package/dist/wizard/lib/patterns/revenue-source-adapter.js +182 -0
- package/dist/wizard/lib/patterns/stablecoin-adapter.d.ts +218 -0
- package/dist/wizard/lib/patterns/stablecoin-adapter.js +264 -0
- package/dist/wizard/lib/prd-validator.d.ts +39 -0
- package/dist/wizard/lib/prd-validator.js +137 -0
- package/dist/wizard/lib/project-init.d.ts +24 -0
- package/dist/wizard/lib/project-init.js +228 -0
- package/dist/wizard/lib/project-registry.d.ts +86 -0
- package/dist/wizard/lib/project-registry.js +359 -0
- package/dist/wizard/lib/project-scope.d.ts +64 -0
- package/dist/wizard/lib/project-scope.js +96 -0
- package/dist/wizard/lib/project-vault.d.ts +47 -0
- package/dist/wizard/lib/project-vault.js +221 -0
- package/dist/wizard/lib/provision-manifest.d.ts +44 -0
- package/dist/wizard/lib/provision-manifest.js +164 -0
- package/dist/wizard/lib/provisioner-registry.d.ts +15 -0
- package/dist/wizard/lib/provisioner-registry.js +34 -0
- package/dist/wizard/lib/provisioners/aws-config.d.ts +36 -0
- package/dist/wizard/lib/provisioners/aws-config.js +56 -0
- package/dist/wizard/lib/provisioners/aws-ec2.d.ts +19 -0
- package/dist/wizard/lib/provisioners/aws-ec2.js +241 -0
- package/dist/wizard/lib/provisioners/aws-rds.d.ts +10 -0
- package/dist/wizard/lib/provisioners/aws-rds.js +199 -0
- package/dist/wizard/lib/provisioners/aws-vps.d.ts +6 -0
- package/dist/wizard/lib/provisioners/aws-vps.js +231 -0
- package/dist/wizard/lib/provisioners/cloudflare.d.ts +6 -0
- package/dist/wizard/lib/provisioners/cloudflare.js +300 -0
- package/dist/wizard/lib/provisioners/docker.d.ts +6 -0
- package/dist/wizard/lib/provisioners/docker.js +75 -0
- package/dist/wizard/lib/provisioners/http-client.d.ts +20 -0
- package/dist/wizard/lib/provisioners/http-client.js +79 -0
- package/dist/wizard/lib/provisioners/railway-config.d.ts +24 -0
- package/dist/wizard/lib/provisioners/railway-config.js +220 -0
- package/dist/wizard/lib/provisioners/railway-deploy.d.ts +19 -0
- package/dist/wizard/lib/provisioners/railway-deploy.js +205 -0
- package/dist/wizard/lib/provisioners/railway.d.ts +6 -0
- package/dist/wizard/lib/provisioners/railway.js +45 -0
- package/dist/wizard/lib/provisioners/scripts/caddyfile.d.ts +10 -0
- package/dist/wizard/lib/provisioners/scripts/caddyfile.js +54 -0
- package/dist/wizard/lib/provisioners/scripts/deploy-vps.d.ts +10 -0
- package/dist/wizard/lib/provisioners/scripts/deploy-vps.js +112 -0
- package/dist/wizard/lib/provisioners/scripts/docker-compose.d.ts +11 -0
- package/dist/wizard/lib/provisioners/scripts/docker-compose.js +91 -0
- package/dist/wizard/lib/provisioners/scripts/dockerfile.d.ts +5 -0
- package/dist/wizard/lib/provisioners/scripts/dockerfile.js +185 -0
- package/dist/wizard/lib/provisioners/scripts/ecosystem-config.d.ts +10 -0
- package/dist/wizard/lib/provisioners/scripts/ecosystem-config.js +36 -0
- package/dist/wizard/lib/provisioners/scripts/provision-vps.d.ts +14 -0
- package/dist/wizard/lib/provisioners/scripts/provision-vps.js +202 -0
- package/dist/wizard/lib/provisioners/scripts/rollback-vps.d.ts +10 -0
- package/dist/wizard/lib/provisioners/scripts/rollback-vps.js +67 -0
- package/dist/wizard/lib/provisioners/self-deploy.d.ts +41 -0
- package/dist/wizard/lib/provisioners/self-deploy.js +185 -0
- package/dist/wizard/lib/provisioners/static-s3.d.ts +6 -0
- package/dist/wizard/lib/provisioners/static-s3.js +235 -0
- package/dist/wizard/lib/provisioners/types.d.ts +40 -0
- package/dist/wizard/lib/provisioners/types.js +4 -0
- package/dist/wizard/lib/provisioners/vercel.d.ts +6 -0
- package/dist/wizard/lib/provisioners/vercel.js +287 -0
- package/dist/wizard/lib/pty-manager.d.ts +42 -0
- package/dist/wizard/lib/pty-manager.js +244 -0
- package/dist/wizard/lib/rate-limiter-core.d.ts +5 -0
- package/dist/wizard/lib/rate-limiter-core.js +5 -0
- package/dist/wizard/lib/reconciliation.d.ts +43 -0
- package/dist/wizard/lib/reconciliation.js +173 -0
- package/dist/wizard/lib/revenue-types.d.ts +5 -0
- package/dist/wizard/lib/revenue-types.js +1 -0
- package/dist/wizard/lib/route-optimizer.d.ts +28 -0
- package/dist/wizard/lib/route-optimizer.js +93 -0
- package/dist/wizard/lib/s3-deploy.d.ts +19 -0
- package/dist/wizard/lib/s3-deploy.js +156 -0
- package/dist/wizard/lib/safety-tiers.d.ts +76 -0
- package/dist/wizard/lib/safety-tiers.js +134 -0
- package/dist/wizard/lib/sentry-generator.d.ts +15 -0
- package/dist/wizard/lib/sentry-generator.js +116 -0
- package/dist/wizard/lib/server-config.d.ts +13 -0
- package/dist/wizard/lib/server-config.js +23 -0
- package/dist/wizard/lib/service-install.d.ts +18 -0
- package/dist/wizard/lib/service-install.js +182 -0
- package/dist/wizard/lib/site-scanner.d.ts +80 -0
- package/dist/wizard/lib/site-scanner.js +262 -0
- package/dist/wizard/lib/ssh-deploy.d.ts +25 -0
- package/dist/wizard/lib/ssh-deploy.js +225 -0
- package/dist/wizard/lib/templates.d.ts +24 -0
- package/dist/wizard/lib/templates.js +219 -0
- package/dist/wizard/lib/totp.d.ts +35 -0
- package/dist/wizard/lib/totp.js +277 -0
- package/dist/wizard/lib/tower-auth.d.ts +43 -0
- package/dist/wizard/lib/tower-auth.js +352 -0
- package/dist/wizard/lib/tower-rate-limit.d.ts +14 -0
- package/dist/wizard/lib/tower-rate-limit.js +61 -0
- package/dist/wizard/lib/tower-session.d.ts +28 -0
- package/dist/wizard/lib/tower-session.js +119 -0
- package/dist/wizard/lib/treasury-backup.d.ts +23 -0
- package/dist/wizard/lib/treasury-backup.js +127 -0
- package/dist/wizard/lib/treasury-circuit-breakers.d.ts +28 -0
- package/dist/wizard/lib/treasury-circuit-breakers.js +74 -0
- package/dist/wizard/lib/treasury-handlers.d.ts +21 -0
- package/dist/wizard/lib/treasury-handlers.js +281 -0
- package/dist/wizard/lib/treasury-heartbeat.d.ts +18 -0
- package/dist/wizard/lib/treasury-heartbeat.js +20 -0
- package/dist/wizard/lib/treasury-io.d.ts +107 -0
- package/dist/wizard/lib/treasury-io.js +254 -0
- package/dist/wizard/lib/treasury-jobs.d.ts +14 -0
- package/dist/wizard/lib/treasury-jobs.js +589 -0
- package/dist/wizard/lib/treasury-migrator.d.ts +59 -0
- package/dist/wizard/lib/treasury-migrator.js +227 -0
- package/dist/wizard/lib/treasury-reader.d.ts +52 -0
- package/dist/wizard/lib/treasury-reader.js +235 -0
- package/dist/wizard/lib/updater.d.ts +29 -0
- package/dist/wizard/lib/updater.js +203 -0
- package/dist/wizard/lib/user-manager.d.ts +39 -0
- package/dist/wizard/lib/user-manager.js +182 -0
- package/dist/wizard/lib/vault.d.ts +26 -0
- package/dist/wizard/lib/vault.js +161 -0
- package/dist/wizard/router.d.ts +12 -0
- package/dist/wizard/router.js +58 -0
- package/dist/wizard/server.d.ts +18 -0
- package/dist/wizard/server.js +427 -0
- package/dist/wizard/ui/app.js +1357 -0
- package/dist/wizard/ui/danger-room-prophecy.js +217 -0
- package/dist/wizard/ui/danger-room.html +27 -0
- package/dist/wizard/ui/danger-room.js +29 -0
- package/dist/wizard/ui/deploy.html +181 -0
- package/dist/wizard/ui/deploy.js +616 -0
- package/dist/wizard/ui/favicon.svg +11 -0
- package/dist/wizard/ui/index.html +407 -0
- package/dist/wizard/ui/lobby.html +235 -0
- package/dist/wizard/ui/lobby.js +843 -0
- package/dist/wizard/ui/login.html +111 -0
- package/dist/wizard/ui/login.js +199 -0
- package/dist/wizard/ui/project.html +285 -0
- package/dist/wizard/ui/project.js +324 -0
- package/dist/wizard/ui/rollback.js +107 -0
- package/dist/wizard/ui/styles.css +1040 -0
- package/dist/wizard/ui/tower.html +177 -0
- package/dist/wizard/ui/tower.js +445 -0
- package/dist/wizard/ui/war-room-prophecy.js +217 -0
- package/dist/wizard/ui/war-room.html +27 -0
- package/dist/wizard/ui/war-room.js +29 -0
- package/package.json +60 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project Scope — ProjectContext type and resolveProject() middleware.
|
|
3
|
+
*
|
|
4
|
+
* Provides the core abstraction for v22.0 project-scoped operations:
|
|
5
|
+
* - ProjectContext: immutable object with all derived paths for a project
|
|
6
|
+
* - resolveProject(): middleware that extracts project ID, validates access, returns context
|
|
7
|
+
*
|
|
8
|
+
* ADR-040 (project-scoped dashboards), ADR-041 (Muster amendments)
|
|
9
|
+
*/
|
|
10
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
11
|
+
import { type Project } from './project-registry.js';
|
|
12
|
+
export interface ProjectContext {
|
|
13
|
+
/** Project ID from projects.json registry */
|
|
14
|
+
readonly id: string;
|
|
15
|
+
/** Human-readable name */
|
|
16
|
+
readonly name: string;
|
|
17
|
+
/** Absolute path to project root (contains CLAUDE.md) */
|
|
18
|
+
readonly directory: string;
|
|
19
|
+
/** The full Project record from registry */
|
|
20
|
+
readonly project: Project;
|
|
21
|
+
/** {directory}/logs/ */
|
|
22
|
+
readonly logsDir: string;
|
|
23
|
+
/** {directory}/cultivation/ */
|
|
24
|
+
readonly cultivationDir: string;
|
|
25
|
+
/** {directory}/cultivation/treasury/ */
|
|
26
|
+
readonly treasuryDir: string;
|
|
27
|
+
/** {directory}/cultivation/treasury/spend-log.jsonl */
|
|
28
|
+
readonly spendLog: string;
|
|
29
|
+
/** {directory}/cultivation/treasury/revenue-log.jsonl */
|
|
30
|
+
readonly revenueLog: string;
|
|
31
|
+
/** {directory}/cultivation/treasury/pending-ops.jsonl */
|
|
32
|
+
readonly pendingOps: string;
|
|
33
|
+
/** {directory}/cultivation/treasury/budgets.json */
|
|
34
|
+
readonly budgetsFile: string;
|
|
35
|
+
/** {directory}/cultivation/treasury/campaigns/ */
|
|
36
|
+
readonly campaignsDir: string;
|
|
37
|
+
/** {directory}/cultivation/heartbeat.pid */
|
|
38
|
+
readonly pidFile: string;
|
|
39
|
+
/** {directory}/cultivation/heartbeat.sock */
|
|
40
|
+
readonly socketPath: string;
|
|
41
|
+
/** {directory}/cultivation/heartbeat.json */
|
|
42
|
+
readonly stateFile: string;
|
|
43
|
+
/** {directory}/cultivation/heartbeat.log */
|
|
44
|
+
readonly logFile: string;
|
|
45
|
+
/** {directory}/cultivation/heartbeat.token */
|
|
46
|
+
readonly tokenFile: string;
|
|
47
|
+
}
|
|
48
|
+
/** Construct a ProjectContext from a registry Project. */
|
|
49
|
+
export declare function createProjectContext(project: Project): ProjectContext;
|
|
50
|
+
export interface ResolvedProject {
|
|
51
|
+
context: ProjectContext;
|
|
52
|
+
role: 'admin' | 'deployer' | 'viewer';
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Extract project ID from route params or query string, validate access, return ProjectContext.
|
|
56
|
+
*
|
|
57
|
+
* Checks (in order):
|
|
58
|
+
* 1. Route param :id (from parameterized routes like /api/projects/:id/...)
|
|
59
|
+
* 2. Query param ?project=<id>
|
|
60
|
+
*
|
|
61
|
+
* Returns null if the response was already sent (error path).
|
|
62
|
+
* In local mode, all projects are accessible as admin.
|
|
63
|
+
*/
|
|
64
|
+
export declare function resolveProject(req: IncomingMessage, res: ServerResponse): Promise<ResolvedProject | null>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project Scope — ProjectContext type and resolveProject() middleware.
|
|
3
|
+
*
|
|
4
|
+
* Provides the core abstraction for v22.0 project-scoped operations:
|
|
5
|
+
* - ProjectContext: immutable object with all derived paths for a project
|
|
6
|
+
* - resolveProject(): middleware that extracts project ID, validates access, returns context
|
|
7
|
+
*
|
|
8
|
+
* ADR-040 (project-scoped dashboards), ADR-041 (Muster amendments)
|
|
9
|
+
*/
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
import { existsSync } from 'node:fs';
|
|
12
|
+
import { getProject, checkProjectAccess } from './project-registry.js';
|
|
13
|
+
import { isRemoteMode, isLanMode, validateSession, parseSessionCookie, getClientIp } from './tower-auth.js';
|
|
14
|
+
import { sendJson } from './http-helpers.js';
|
|
15
|
+
import { getRouteParams } from '../router.js';
|
|
16
|
+
/** Construct a ProjectContext from a registry Project. */
|
|
17
|
+
export function createProjectContext(project) {
|
|
18
|
+
const dir = project.directory;
|
|
19
|
+
const cultivationDir = join(dir, 'cultivation');
|
|
20
|
+
const treasuryDir = join(cultivationDir, 'treasury');
|
|
21
|
+
return {
|
|
22
|
+
id: project.id,
|
|
23
|
+
name: project.name,
|
|
24
|
+
directory: dir,
|
|
25
|
+
project,
|
|
26
|
+
logsDir: join(dir, 'logs'),
|
|
27
|
+
cultivationDir,
|
|
28
|
+
treasuryDir,
|
|
29
|
+
spendLog: join(treasuryDir, 'spend-log.jsonl'),
|
|
30
|
+
revenueLog: join(treasuryDir, 'revenue-log.jsonl'),
|
|
31
|
+
pendingOps: join(treasuryDir, 'pending-ops.jsonl'),
|
|
32
|
+
budgetsFile: join(treasuryDir, 'budgets.json'),
|
|
33
|
+
campaignsDir: join(treasuryDir, 'campaigns'),
|
|
34
|
+
pidFile: join(cultivationDir, 'heartbeat.pid'),
|
|
35
|
+
socketPath: join(cultivationDir, 'heartbeat.sock'),
|
|
36
|
+
stateFile: join(cultivationDir, 'heartbeat.json'),
|
|
37
|
+
logFile: join(cultivationDir, 'heartbeat.log'),
|
|
38
|
+
tokenFile: join(cultivationDir, 'heartbeat.token'),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Extract project ID from route params or query string, validate access, return ProjectContext.
|
|
43
|
+
*
|
|
44
|
+
* Checks (in order):
|
|
45
|
+
* 1. Route param :id (from parameterized routes like /api/projects/:id/...)
|
|
46
|
+
* 2. Query param ?project=<id>
|
|
47
|
+
*
|
|
48
|
+
* Returns null if the response was already sent (error path).
|
|
49
|
+
* In local mode, all projects are accessible as admin.
|
|
50
|
+
*/
|
|
51
|
+
export async function resolveProject(req, res) {
|
|
52
|
+
// Extract project ID from route params or query string
|
|
53
|
+
const params = getRouteParams(req);
|
|
54
|
+
const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);
|
|
55
|
+
const projectId = params.id || url.searchParams.get('project');
|
|
56
|
+
if (!projectId) {
|
|
57
|
+
sendJson(res, 400, { success: false, error: 'project parameter is required' });
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
// Look up project in registry
|
|
61
|
+
const project = await getProject(projectId);
|
|
62
|
+
if (!project) {
|
|
63
|
+
sendJson(res, 404, { success: false, error: 'Not found' });
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
// Verify project directory still exists (stale registry detection — Batman M2 finding)
|
|
67
|
+
if (!existsSync(project.directory)) {
|
|
68
|
+
sendJson(res, 404, { success: false, error: 'Not found' });
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
// In local mode, no auth — full access
|
|
72
|
+
if (!isRemoteMode() && !isLanMode()) {
|
|
73
|
+
return {
|
|
74
|
+
context: createProjectContext(project),
|
|
75
|
+
role: 'admin',
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// Remote/LAN mode: validate session and project access
|
|
79
|
+
const token = parseSessionCookie(req.headers.cookie);
|
|
80
|
+
const ip = getClientIp(req);
|
|
81
|
+
const session = token ? validateSession(token, ip) : null;
|
|
82
|
+
if (!session) {
|
|
83
|
+
sendJson(res, 401, { success: false, error: 'Authentication required' });
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
const role = await checkProjectAccess(projectId, session.username, session.role);
|
|
87
|
+
if (!role) {
|
|
88
|
+
// 404 not 403 — no information leakage (per CLAUDE.md)
|
|
89
|
+
sendJson(res, 404, { success: false, error: 'Not found' });
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
context: createProjectContext(project),
|
|
94
|
+
role,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-Project Vault — HKDF-derived encryption for project-scoped secrets.
|
|
3
|
+
*
|
|
4
|
+
* Derives a unique encryption key per project from the global vault password
|
|
5
|
+
* using HKDF (RFC 5869). Each project's vault.enc is encrypted with its own
|
|
6
|
+
* key, so compromising one project's vault doesn't expose another's secrets.
|
|
7
|
+
*
|
|
8
|
+
* Key derivation: HKDF-SHA256(masterKey, projectId, 'voidforge-project-vault') → 256-bit key
|
|
9
|
+
*
|
|
10
|
+
* The global financial vault (~/.voidforge/treasury/vault.enc) stays global
|
|
11
|
+
* for cross-project credentials (API keys shared across projects). Per-project
|
|
12
|
+
* vaults store project-specific secrets (campaign configs, scoped platform tokens).
|
|
13
|
+
*
|
|
14
|
+
* v22.1 Mission 3 — Campaign 30
|
|
15
|
+
* PRD Reference: §9.11 (Financial Security), ADR-040 (project scoping)
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Derive a per-project encryption key using HKDF (RFC 5869).
|
|
19
|
+
*
|
|
20
|
+
* HKDF extracts a pseudorandom key from the master password + salt,
|
|
21
|
+
* then expands it with the project ID as context info. This ensures
|
|
22
|
+
* each project gets a cryptographically independent key.
|
|
23
|
+
*
|
|
24
|
+
* @param password — The global vault password (IKM)
|
|
25
|
+
* @param salt — Random salt stored alongside the ciphertext
|
|
26
|
+
* @param projectId — Project identifier used as HKDF info context
|
|
27
|
+
*/
|
|
28
|
+
declare function deriveProjectKey(password: string, salt: Buffer, projectId: string): Promise<Buffer>;
|
|
29
|
+
/** Store a project-specific credential. */
|
|
30
|
+
export declare function projectVaultSet(password: string, projectId: string, projectDir: string, key: string, value: string): Promise<void>;
|
|
31
|
+
/** Retrieve a project-specific credential. */
|
|
32
|
+
export declare function projectVaultGet(password: string, projectId: string, projectDir: string, key: string): Promise<string | null>;
|
|
33
|
+
/** Delete a project-specific credential. */
|
|
34
|
+
export declare function projectVaultDelete(password: string, projectId: string, projectDir: string, key: string): Promise<void>;
|
|
35
|
+
/** Check if a per-project vault exists. */
|
|
36
|
+
export declare function projectVaultExists(projectDir: string): boolean;
|
|
37
|
+
/** Verify password can decrypt the project vault. */
|
|
38
|
+
export declare function projectVaultUnlock(password: string, projectId: string, projectDir: string): Promise<boolean>;
|
|
39
|
+
/** List stored keys in a project vault (requires password). */
|
|
40
|
+
export declare function projectVaultKeys(password: string, projectId: string, projectDir: string): Promise<string[]>;
|
|
41
|
+
/** Clear the in-memory cache for a specific project vault. */
|
|
42
|
+
export declare function projectVaultLock(projectDir: string): void;
|
|
43
|
+
/** Clear ALL per-project vault caches — call on daemon shutdown. */
|
|
44
|
+
export declare function projectVaultLockAll(): void;
|
|
45
|
+
/** Return the vault file path for a project directory. */
|
|
46
|
+
export declare function projectVaultPath(projectDir: string): string;
|
|
47
|
+
export { deriveProjectKey as _deriveProjectKey };
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-Project Vault — HKDF-derived encryption for project-scoped secrets.
|
|
3
|
+
*
|
|
4
|
+
* Derives a unique encryption key per project from the global vault password
|
|
5
|
+
* using HKDF (RFC 5869). Each project's vault.enc is encrypted with its own
|
|
6
|
+
* key, so compromising one project's vault doesn't expose another's secrets.
|
|
7
|
+
*
|
|
8
|
+
* Key derivation: HKDF-SHA256(masterKey, projectId, 'voidforge-project-vault') → 256-bit key
|
|
9
|
+
*
|
|
10
|
+
* The global financial vault (~/.voidforge/treasury/vault.enc) stays global
|
|
11
|
+
* for cross-project credentials (API keys shared across projects). Per-project
|
|
12
|
+
* vaults store project-specific secrets (campaign configs, scoped platform tokens).
|
|
13
|
+
*
|
|
14
|
+
* v22.1 Mission 3 — Campaign 30
|
|
15
|
+
* PRD Reference: §9.11 (Financial Security), ADR-040 (project scoping)
|
|
16
|
+
*/
|
|
17
|
+
import { createCipheriv, createDecipheriv, hkdf, randomBytes, timingSafeEqual } from 'node:crypto';
|
|
18
|
+
import { readFile, mkdir, open, rename } from 'node:fs/promises';
|
|
19
|
+
import { join } from 'node:path';
|
|
20
|
+
import { existsSync } from 'node:fs';
|
|
21
|
+
import { platform } from 'node:os';
|
|
22
|
+
// ── Constants ────────────────────────────────────────────
|
|
23
|
+
const VAULT_FILENAME = 'vault.enc';
|
|
24
|
+
const ALGORITHM = 'aes-256-gcm';
|
|
25
|
+
const KEY_LENGTH = 32; // 256 bits
|
|
26
|
+
const IV_LENGTH = 16;
|
|
27
|
+
const SALT_LENGTH = 32; // Random salt per encryption (stored in file)
|
|
28
|
+
const AUTH_TAG_LENGTH = 16;
|
|
29
|
+
const MAX_PASSWORD_LENGTH = 256;
|
|
30
|
+
// HKDF parameters
|
|
31
|
+
const HKDF_HASH = 'sha256';
|
|
32
|
+
const HKDF_INFO = 'voidforge-project-vault';
|
|
33
|
+
// Per-project session caches keyed by vault path
|
|
34
|
+
const sessionCaches = new Map();
|
|
35
|
+
// Write queues per vault path
|
|
36
|
+
const writeQueues = new Map();
|
|
37
|
+
// ── HKDF Key Derivation ──────────────────────────────────
|
|
38
|
+
/**
|
|
39
|
+
* Derive a per-project encryption key using HKDF (RFC 5869).
|
|
40
|
+
*
|
|
41
|
+
* HKDF extracts a pseudorandom key from the master password + salt,
|
|
42
|
+
* then expands it with the project ID as context info. This ensures
|
|
43
|
+
* each project gets a cryptographically independent key.
|
|
44
|
+
*
|
|
45
|
+
* @param password — The global vault password (IKM)
|
|
46
|
+
* @param salt — Random salt stored alongside the ciphertext
|
|
47
|
+
* @param projectId — Project identifier used as HKDF info context
|
|
48
|
+
*/
|
|
49
|
+
async function deriveProjectKey(password, salt, projectId) {
|
|
50
|
+
const capped = password.slice(0, MAX_PASSWORD_LENGTH);
|
|
51
|
+
const info = `${HKDF_INFO}:${projectId}`;
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
hkdf(HKDF_HASH, capped, salt, info, KEY_LENGTH, (err, derivedKey) => {
|
|
54
|
+
if (err)
|
|
55
|
+
reject(err);
|
|
56
|
+
else
|
|
57
|
+
resolve(Buffer.from(derivedKey));
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// ── Encrypt / Decrypt ────────────────────────────────────
|
|
62
|
+
async function encrypt(plaintext, password, projectId) {
|
|
63
|
+
const salt = randomBytes(SALT_LENGTH);
|
|
64
|
+
const iv = randomBytes(IV_LENGTH);
|
|
65
|
+
const key = await deriveProjectKey(password, salt, projectId);
|
|
66
|
+
const cipher = createCipheriv(ALGORITHM, key, iv);
|
|
67
|
+
const encrypted = Buffer.concat([cipher.update(plaintext, 'utf-8'), cipher.final()]);
|
|
68
|
+
const authTag = cipher.getAuthTag();
|
|
69
|
+
// Format: salt (32) + iv (16) + authTag (16) + ciphertext
|
|
70
|
+
return Buffer.concat([salt, iv, authTag, encrypted]);
|
|
71
|
+
}
|
|
72
|
+
async function decrypt(data, password, projectId) {
|
|
73
|
+
if (data.length < SALT_LENGTH + IV_LENGTH + AUTH_TAG_LENGTH + 1) {
|
|
74
|
+
throw new Error('Project vault data is corrupted or empty');
|
|
75
|
+
}
|
|
76
|
+
const salt = data.subarray(0, SALT_LENGTH);
|
|
77
|
+
const iv = data.subarray(SALT_LENGTH, SALT_LENGTH + IV_LENGTH);
|
|
78
|
+
const authTag = data.subarray(SALT_LENGTH + IV_LENGTH, SALT_LENGTH + IV_LENGTH + AUTH_TAG_LENGTH);
|
|
79
|
+
const ciphertext = data.subarray(SALT_LENGTH + IV_LENGTH + AUTH_TAG_LENGTH);
|
|
80
|
+
const key = await deriveProjectKey(password, salt, projectId);
|
|
81
|
+
const decipher = createDecipheriv(ALGORITHM, key, iv);
|
|
82
|
+
decipher.setAuthTag(authTag);
|
|
83
|
+
const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
84
|
+
return decrypted.toString('utf-8');
|
|
85
|
+
}
|
|
86
|
+
// ── Serialization ────────────────────────────────────────
|
|
87
|
+
function serialized(vaultPath, fn) {
|
|
88
|
+
const queue = writeQueues.get(vaultPath) ?? Promise.resolve();
|
|
89
|
+
const result = queue.then(fn, () => fn());
|
|
90
|
+
writeQueues.set(vaultPath, result.then(() => { }, () => { }));
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
// ── Internal Read/Write ──────────────────────────────────
|
|
94
|
+
function getVaultPath(projectDir) {
|
|
95
|
+
return join(projectDir, 'cultivation', 'treasury', VAULT_FILENAME);
|
|
96
|
+
}
|
|
97
|
+
async function readVault(password, projectId, vaultPath) {
|
|
98
|
+
const cache = sessionCaches.get(vaultPath);
|
|
99
|
+
if (cache && cache.projectId === projectId) {
|
|
100
|
+
const a = Buffer.from(cache.password, 'utf-8');
|
|
101
|
+
const b = Buffer.from(password, 'utf-8');
|
|
102
|
+
if (a.length === b.length && timingSafeEqual(a, b)) {
|
|
103
|
+
return { ...cache.data };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (!existsSync(vaultPath)) {
|
|
107
|
+
return {};
|
|
108
|
+
}
|
|
109
|
+
const raw = await readFile(vaultPath);
|
|
110
|
+
const json = await decrypt(raw, password, projectId);
|
|
111
|
+
const data = JSON.parse(json);
|
|
112
|
+
sessionCaches.set(vaultPath, { password, projectId, data });
|
|
113
|
+
return { ...data };
|
|
114
|
+
}
|
|
115
|
+
async function writeVault(password, projectId, vaultPath, data) {
|
|
116
|
+
const dir = join(vaultPath, '..');
|
|
117
|
+
await mkdir(dir, { recursive: true });
|
|
118
|
+
const json = JSON.stringify(data);
|
|
119
|
+
const encrypted = await encrypt(json, password, projectId);
|
|
120
|
+
// Atomic write: temp → datasync/sync → rename (per ADR-1)
|
|
121
|
+
const tmpPath = vaultPath + '.tmp.' + process.pid;
|
|
122
|
+
const fh = await open(tmpPath, 'w', 0o600);
|
|
123
|
+
try {
|
|
124
|
+
await fh.writeFile(encrypted);
|
|
125
|
+
if (platform() === 'darwin') {
|
|
126
|
+
await fh.datasync();
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
await fh.sync();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
await fh.close();
|
|
134
|
+
}
|
|
135
|
+
await rename(tmpPath, vaultPath);
|
|
136
|
+
sessionCaches.set(vaultPath, { password, projectId, data: { ...data } });
|
|
137
|
+
}
|
|
138
|
+
// ── Public API ───────────────────────────────────────────
|
|
139
|
+
const MIN_PASSWORD_LENGTH = 12;
|
|
140
|
+
function validatePassword(password) {
|
|
141
|
+
if (password.length < MIN_PASSWORD_LENGTH) {
|
|
142
|
+
throw new Error(`Vault password must be at least ${MIN_PASSWORD_LENGTH} characters`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/** Store a project-specific credential. */
|
|
146
|
+
export function projectVaultSet(password, projectId, projectDir, key, value) {
|
|
147
|
+
validatePassword(password);
|
|
148
|
+
const vaultPath = getVaultPath(projectDir);
|
|
149
|
+
return serialized(vaultPath, async () => {
|
|
150
|
+
const data = await readVault(password, projectId, vaultPath);
|
|
151
|
+
data[key] = value;
|
|
152
|
+
await writeVault(password, projectId, vaultPath, data);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/** Retrieve a project-specific credential. */
|
|
156
|
+
export function projectVaultGet(password, projectId, projectDir, key) {
|
|
157
|
+
const vaultPath = getVaultPath(projectDir);
|
|
158
|
+
return serialized(vaultPath, async () => {
|
|
159
|
+
const data = await readVault(password, projectId, vaultPath);
|
|
160
|
+
return data[key] ?? null;
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/** Delete a project-specific credential. */
|
|
164
|
+
export function projectVaultDelete(password, projectId, projectDir, key) {
|
|
165
|
+
const vaultPath = getVaultPath(projectDir);
|
|
166
|
+
return serialized(vaultPath, async () => {
|
|
167
|
+
const data = await readVault(password, projectId, vaultPath);
|
|
168
|
+
delete data[key];
|
|
169
|
+
await writeVault(password, projectId, vaultPath, data);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/** Check if a per-project vault exists. */
|
|
173
|
+
export function projectVaultExists(projectDir) {
|
|
174
|
+
return existsSync(getVaultPath(projectDir));
|
|
175
|
+
}
|
|
176
|
+
/** Verify password can decrypt the project vault. */
|
|
177
|
+
export function projectVaultUnlock(password, projectId, projectDir) {
|
|
178
|
+
const vaultPath = getVaultPath(projectDir);
|
|
179
|
+
if (!existsSync(vaultPath)) {
|
|
180
|
+
return Promise.resolve(true); // No vault yet = password is for creation
|
|
181
|
+
}
|
|
182
|
+
return serialized(vaultPath, async () => {
|
|
183
|
+
try {
|
|
184
|
+
await readVault(password, projectId, vaultPath);
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
/** List stored keys in a project vault (requires password). */
|
|
193
|
+
export function projectVaultKeys(password, projectId, projectDir) {
|
|
194
|
+
const vaultPath = getVaultPath(projectDir);
|
|
195
|
+
return serialized(vaultPath, async () => {
|
|
196
|
+
const data = await readVault(password, projectId, vaultPath);
|
|
197
|
+
return Object.keys(data);
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
/** Clear the in-memory cache for a specific project vault. */
|
|
201
|
+
export function projectVaultLock(projectDir) {
|
|
202
|
+
const vaultPath = getVaultPath(projectDir);
|
|
203
|
+
const cache = sessionCaches.get(vaultPath);
|
|
204
|
+
if (cache) {
|
|
205
|
+
cache.password = '\0'.repeat(cache.password.length);
|
|
206
|
+
sessionCaches.delete(vaultPath);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/** Clear ALL per-project vault caches — call on daemon shutdown. */
|
|
210
|
+
export function projectVaultLockAll() {
|
|
211
|
+
for (const [, cache] of sessionCaches) {
|
|
212
|
+
cache.password = '\0'.repeat(cache.password.length);
|
|
213
|
+
}
|
|
214
|
+
sessionCaches.clear();
|
|
215
|
+
}
|
|
216
|
+
/** Return the vault file path for a project directory. */
|
|
217
|
+
export function projectVaultPath(projectDir) {
|
|
218
|
+
return getVaultPath(projectDir);
|
|
219
|
+
}
|
|
220
|
+
// Export for testing
|
|
221
|
+
export { deriveProjectKey as _deriveProjectKey };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provision manifest — persists resource state to disk for crash recovery.
|
|
3
|
+
*
|
|
4
|
+
* Before each AWS resource creation, the intended action is recorded.
|
|
5
|
+
* After creation, the resource ID is written. On cleanup, the manifest
|
|
6
|
+
* is read and resources deleted in reverse. On wizard startup, incomplete
|
|
7
|
+
* manifests can be detected and cleaned up.
|
|
8
|
+
*
|
|
9
|
+
* Stored at ~/.voidforge/runs/<runId>.json
|
|
10
|
+
*/
|
|
11
|
+
import type { CreatedResource } from './provisioners/types.js';
|
|
12
|
+
export interface ManifestResource {
|
|
13
|
+
type: string;
|
|
14
|
+
id: string;
|
|
15
|
+
region: string;
|
|
16
|
+
status: 'pending' | 'created' | 'cleaned' | 'failed';
|
|
17
|
+
}
|
|
18
|
+
export interface ProvisionManifest {
|
|
19
|
+
runId: string;
|
|
20
|
+
startedAt: string;
|
|
21
|
+
target: string;
|
|
22
|
+
region: string;
|
|
23
|
+
projectName: string;
|
|
24
|
+
status: 'in-progress' | 'complete' | 'failed' | 'cleaned';
|
|
25
|
+
resources: ManifestResource[];
|
|
26
|
+
}
|
|
27
|
+
/** Create a new manifest for a provisioning run. */
|
|
28
|
+
export declare function createManifest(runId: string, target: string, region: string, projectName: string): Promise<ProvisionManifest>;
|
|
29
|
+
/** Record that a resource is about to be created (write-ahead). */
|
|
30
|
+
export declare function recordResourcePending(runId: string, type: string, id: string, region: string): Promise<void>;
|
|
31
|
+
/** Record that a resource was successfully created. */
|
|
32
|
+
export declare function recordResourceCreated(runId: string, type: string, id: string, region: string): Promise<void>;
|
|
33
|
+
/** Mark the overall run status. */
|
|
34
|
+
export declare function updateManifestStatus(runId: string, status: ProvisionManifest['status']): Promise<void>;
|
|
35
|
+
/** Mark a resource as cleaned up. */
|
|
36
|
+
export declare function recordResourceCleaned(runId: string, type: string, id: string): Promise<void>;
|
|
37
|
+
/** Read a manifest by run ID. Returns null if not found. */
|
|
38
|
+
export declare function readManifest(runId: string): Promise<ProvisionManifest | null>;
|
|
39
|
+
/** Delete a manifest file (after successful cleanup). */
|
|
40
|
+
export declare function deleteManifest(runId: string): Promise<void>;
|
|
41
|
+
/** List all incomplete manifests (for recovery on startup). */
|
|
42
|
+
export declare function listIncompleteRuns(): Promise<ProvisionManifest[]>;
|
|
43
|
+
/** Convert manifest resources to the CreatedResource[] format used by provisioners. */
|
|
44
|
+
export declare function manifestToCreatedResources(manifest: ProvisionManifest): CreatedResource[];
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provision manifest — persists resource state to disk for crash recovery.
|
|
3
|
+
*
|
|
4
|
+
* Before each AWS resource creation, the intended action is recorded.
|
|
5
|
+
* After creation, the resource ID is written. On cleanup, the manifest
|
|
6
|
+
* is read and resources deleted in reverse. On wizard startup, incomplete
|
|
7
|
+
* manifests can be detected and cleaned up.
|
|
8
|
+
*
|
|
9
|
+
* Stored at ~/.voidforge/runs/<runId>.json
|
|
10
|
+
*/
|
|
11
|
+
import { readFile, readdir, unlink, mkdir, open, rename } from 'node:fs/promises';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import { existsSync } from 'node:fs';
|
|
14
|
+
import { homedir } from 'node:os';
|
|
15
|
+
const RUNS_DIR = join(homedir(), '.voidforge', 'runs');
|
|
16
|
+
/** QA-R2-004: Write queue to serialize manifest mutations and prevent race conditions */
|
|
17
|
+
let writeQueue = Promise.resolve();
|
|
18
|
+
function serialized(fn) {
|
|
19
|
+
const result = writeQueue.then(fn, () => fn());
|
|
20
|
+
writeQueue = result.then(() => { }, () => { });
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
// IG-R4 LOKI-003: Atomic write with fsync — crash-recovery manifests must survive crashes
|
|
24
|
+
async function atomicWriteManifest(runId, manifest) {
|
|
25
|
+
const filePath = manifestPath(runId);
|
|
26
|
+
const tmpPath = filePath + '.tmp';
|
|
27
|
+
const fh = await open(tmpPath, 'w', 0o600);
|
|
28
|
+
try {
|
|
29
|
+
await fh.writeFile(JSON.stringify(manifest, null, 2));
|
|
30
|
+
await fh.sync();
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
await fh.close();
|
|
34
|
+
}
|
|
35
|
+
await rename(tmpPath, filePath);
|
|
36
|
+
}
|
|
37
|
+
async function ensureDir() {
|
|
38
|
+
await mkdir(RUNS_DIR, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
// SEC-R3-013: Validate runId is a UUID to prevent path traversal
|
|
41
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
42
|
+
function manifestPath(runId) {
|
|
43
|
+
if (!UUID_RE.test(runId))
|
|
44
|
+
throw new Error('Invalid runId format');
|
|
45
|
+
return join(RUNS_DIR, `${runId}.json`);
|
|
46
|
+
}
|
|
47
|
+
/** Create a new manifest for a provisioning run. */
|
|
48
|
+
export function createManifest(runId, target, region, projectName) {
|
|
49
|
+
// QA-R3-004: Wrap in serialized() for consistency with other mutation functions
|
|
50
|
+
return serialized(async () => {
|
|
51
|
+
await ensureDir();
|
|
52
|
+
const manifest = {
|
|
53
|
+
runId,
|
|
54
|
+
startedAt: new Date().toISOString(),
|
|
55
|
+
target,
|
|
56
|
+
region,
|
|
57
|
+
projectName,
|
|
58
|
+
status: 'in-progress',
|
|
59
|
+
resources: [],
|
|
60
|
+
};
|
|
61
|
+
await atomicWriteManifest(runId, manifest);
|
|
62
|
+
return manifest;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/** Record that a resource is about to be created (write-ahead). */
|
|
66
|
+
export function recordResourcePending(runId, type, id, region) {
|
|
67
|
+
return serialized(async () => {
|
|
68
|
+
const manifest = await readManifest(runId);
|
|
69
|
+
if (!manifest)
|
|
70
|
+
return;
|
|
71
|
+
manifest.resources.push({ type, id, region, status: 'pending' });
|
|
72
|
+
await atomicWriteManifest(runId, manifest);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/** Record that a resource was successfully created. */
|
|
76
|
+
export function recordResourceCreated(runId, type, id, region) {
|
|
77
|
+
return serialized(async () => {
|
|
78
|
+
const manifest = await readManifest(runId);
|
|
79
|
+
if (!manifest)
|
|
80
|
+
return;
|
|
81
|
+
const existing = manifest.resources.find((r) => r.type === type && r.id === id);
|
|
82
|
+
if (existing) {
|
|
83
|
+
existing.status = 'created';
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
manifest.resources.push({ type, id, region, status: 'created' });
|
|
87
|
+
}
|
|
88
|
+
await atomicWriteManifest(runId, manifest);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/** Mark the overall run status. */
|
|
92
|
+
export function updateManifestStatus(runId, status) {
|
|
93
|
+
return serialized(async () => {
|
|
94
|
+
const manifest = await readManifest(runId);
|
|
95
|
+
if (!manifest)
|
|
96
|
+
return;
|
|
97
|
+
manifest.status = status;
|
|
98
|
+
await atomicWriteManifest(runId, manifest);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/** Mark a resource as cleaned up. */
|
|
102
|
+
export function recordResourceCleaned(runId, type, id) {
|
|
103
|
+
return serialized(async () => {
|
|
104
|
+
const manifest = await readManifest(runId);
|
|
105
|
+
if (!manifest)
|
|
106
|
+
return;
|
|
107
|
+
const resource = manifest.resources.find((r) => r.type === type && r.id === id);
|
|
108
|
+
if (resource)
|
|
109
|
+
resource.status = 'cleaned';
|
|
110
|
+
await atomicWriteManifest(runId, manifest);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/** Read a manifest by run ID. Returns null if not found. */
|
|
114
|
+
export async function readManifest(runId) {
|
|
115
|
+
const path = manifestPath(runId);
|
|
116
|
+
if (!existsSync(path))
|
|
117
|
+
return null;
|
|
118
|
+
try {
|
|
119
|
+
const raw = await readFile(path, 'utf-8');
|
|
120
|
+
return JSON.parse(raw);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/** Delete a manifest file (after successful cleanup). */
|
|
127
|
+
export async function deleteManifest(runId) {
|
|
128
|
+
const path = manifestPath(runId);
|
|
129
|
+
try {
|
|
130
|
+
await unlink(path);
|
|
131
|
+
}
|
|
132
|
+
catch { /* already gone */ }
|
|
133
|
+
}
|
|
134
|
+
/** List all incomplete manifests (for recovery on startup). */
|
|
135
|
+
export async function listIncompleteRuns() {
|
|
136
|
+
await ensureDir();
|
|
137
|
+
const incomplete = [];
|
|
138
|
+
try {
|
|
139
|
+
const files = await readdir(RUNS_DIR);
|
|
140
|
+
for (const file of files) {
|
|
141
|
+
if (!file.endsWith('.json'))
|
|
142
|
+
continue;
|
|
143
|
+
try {
|
|
144
|
+
const raw = await readFile(join(RUNS_DIR, file), 'utf-8');
|
|
145
|
+
const manifest = JSON.parse(raw);
|
|
146
|
+
if (manifest.status === 'in-progress' || manifest.status === 'failed') {
|
|
147
|
+
const hasCreatedResources = manifest.resources.some((r) => r.status === 'created');
|
|
148
|
+
if (hasCreatedResources) {
|
|
149
|
+
incomplete.push(manifest);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch { /* skip corrupt files */ }
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch { /* directory might not exist */ }
|
|
157
|
+
return incomplete;
|
|
158
|
+
}
|
|
159
|
+
/** Convert manifest resources to the CreatedResource[] format used by provisioners. */
|
|
160
|
+
export function manifestToCreatedResources(manifest) {
|
|
161
|
+
return manifest.resources
|
|
162
|
+
.filter((r) => r.status === 'created')
|
|
163
|
+
.map((r) => ({ type: r.type, id: r.id, region: r.region }));
|
|
164
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provisioner Registry — single source of truth for provisioner map,
|
|
3
|
+
* credential scoping, and GitHub-linked target constants.
|
|
4
|
+
*
|
|
5
|
+
* ARCH-R2-002: Extracted from provision.ts + headless-deploy.ts to prevent drift.
|
|
6
|
+
*/
|
|
7
|
+
import type { Provisioner } from './provisioners/types.js';
|
|
8
|
+
/** All available provisioners keyed by deploy target name. */
|
|
9
|
+
export declare const provisioners: Record<string, Provisioner>;
|
|
10
|
+
/** Credential scoping — each provisioner only receives vault keys it needs (ADR-020). */
|
|
11
|
+
export declare const provisionKeys: Record<string, string[]>;
|
|
12
|
+
/** Deploy targets that benefit from GitHub repo linking (ADR-015). */
|
|
13
|
+
export declare const GITHUB_LINKED_TARGETS: string[];
|
|
14
|
+
/** Deploy targets where GitHub push is optional (deploy via SSH/SDK instead). */
|
|
15
|
+
export declare const GITHUB_OPTIONAL_TARGETS: string[];
|