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,34 @@
|
|
|
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 { dockerProvisioner } from './provisioners/docker.js';
|
|
8
|
+
import { awsVpsProvisioner } from './provisioners/aws-vps.js';
|
|
9
|
+
import { vercelProvisioner } from './provisioners/vercel.js';
|
|
10
|
+
import { railwayProvisioner } from './provisioners/railway.js';
|
|
11
|
+
import { cloudflareProvisioner } from './provisioners/cloudflare.js';
|
|
12
|
+
import { staticS3Provisioner } from './provisioners/static-s3.js';
|
|
13
|
+
/** All available provisioners keyed by deploy target name. */
|
|
14
|
+
export const provisioners = {
|
|
15
|
+
docker: dockerProvisioner,
|
|
16
|
+
vps: awsVpsProvisioner,
|
|
17
|
+
vercel: vercelProvisioner,
|
|
18
|
+
railway: railwayProvisioner,
|
|
19
|
+
cloudflare: cloudflareProvisioner,
|
|
20
|
+
static: staticS3Provisioner,
|
|
21
|
+
};
|
|
22
|
+
/** Credential scoping — each provisioner only receives vault keys it needs (ADR-020). */
|
|
23
|
+
export const provisionKeys = {
|
|
24
|
+
vps: ['aws-access-key-id', 'aws-secret-access-key', 'aws-region'],
|
|
25
|
+
static: ['aws-access-key-id', 'aws-secret-access-key', 'aws-region'],
|
|
26
|
+
vercel: ['vercel-token'],
|
|
27
|
+
railway: ['railway-token'],
|
|
28
|
+
cloudflare: ['cloudflare-api-token', 'cloudflare-account-id'],
|
|
29
|
+
docker: [],
|
|
30
|
+
};
|
|
31
|
+
/** Deploy targets that benefit from GitHub repo linking (ADR-015). */
|
|
32
|
+
export const GITHUB_LINKED_TARGETS = ['vercel', 'cloudflare', 'railway'];
|
|
33
|
+
/** Deploy targets where GitHub push is optional (deploy via SSH/SDK instead). */
|
|
34
|
+
export const GITHUB_OPTIONAL_TARGETS = ['vps', 'static'];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS provisioner — shared configuration, utilities, and SDK loading.
|
|
3
|
+
*/
|
|
4
|
+
import type { ProvisionContext, CreatedResource } from './types.js';
|
|
5
|
+
export declare const POLL_INTERVAL_MS = 5000;
|
|
6
|
+
export declare const MAX_POLL_MS = 300000;
|
|
7
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
8
|
+
export declare function cancellableSleep(ms: number, signal?: AbortSignal): Promise<void>;
|
|
9
|
+
export interface AwsConfig {
|
|
10
|
+
region: string;
|
|
11
|
+
credentials: {
|
|
12
|
+
accessKeyId: string;
|
|
13
|
+
secretAccessKey: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export declare function buildAwsConfig(ctx: ProvisionContext): AwsConfig;
|
|
17
|
+
export declare function validateAwsContext(ctx: ProvisionContext): string[];
|
|
18
|
+
/** Dynamic import of AWS EC2 + STS SDK modules. Returns null with error message on failure. */
|
|
19
|
+
export declare function loadAwsSdk(): Promise<{
|
|
20
|
+
ec2Mod: typeof import('@aws-sdk/client-ec2');
|
|
21
|
+
stsMod: typeof import('@aws-sdk/client-sts');
|
|
22
|
+
} | {
|
|
23
|
+
error: string;
|
|
24
|
+
}>;
|
|
25
|
+
/** Result bag passed between provisioning phases. */
|
|
26
|
+
export interface AwsProvisionState {
|
|
27
|
+
resources: CreatedResource[];
|
|
28
|
+
outputs: Record<string, string>;
|
|
29
|
+
files: string[];
|
|
30
|
+
region: string;
|
|
31
|
+
slug: string;
|
|
32
|
+
sgId: string;
|
|
33
|
+
instanceId: string;
|
|
34
|
+
publicIp: string;
|
|
35
|
+
awsConfig: AwsConfig;
|
|
36
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS provisioner — shared configuration, utilities, and SDK loading.
|
|
3
|
+
*/
|
|
4
|
+
import { isValidInstanceType } from '../instance-sizing.js';
|
|
5
|
+
export const POLL_INTERVAL_MS = 5000;
|
|
6
|
+
export const MAX_POLL_MS = 300000; // 5 minutes
|
|
7
|
+
export function sleep(ms) {
|
|
8
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
9
|
+
}
|
|
10
|
+
export function cancellableSleep(ms, signal) {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
if (signal?.aborted) {
|
|
13
|
+
reject(new Error('Aborted'));
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const timer = setTimeout(resolve, ms);
|
|
17
|
+
signal?.addEventListener('abort', () => { clearTimeout(timer); reject(new Error('Aborted')); }, { once: true });
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export function buildAwsConfig(ctx) {
|
|
21
|
+
return {
|
|
22
|
+
region: ctx.credentials['aws-region'] || 'us-east-1',
|
|
23
|
+
credentials: {
|
|
24
|
+
accessKeyId: ctx.credentials['aws-access-key-id'],
|
|
25
|
+
secretAccessKey: ctx.credentials['aws-secret-access-key'],
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function validateAwsContext(ctx) {
|
|
30
|
+
const errors = [];
|
|
31
|
+
if (!ctx.projectDir)
|
|
32
|
+
errors.push('Project directory is required');
|
|
33
|
+
if (!ctx.projectName)
|
|
34
|
+
errors.push('Project name is required');
|
|
35
|
+
if (!ctx.credentials['aws-access-key-id'])
|
|
36
|
+
errors.push('AWS Access Key ID is required');
|
|
37
|
+
if (!ctx.credentials['aws-secret-access-key'])
|
|
38
|
+
errors.push('AWS Secret Access Key is required');
|
|
39
|
+
if (ctx.instanceType && !isValidInstanceType(ctx.instanceType)) {
|
|
40
|
+
errors.push(`Invalid instance type: "${ctx.instanceType}". Must be one of: t3.micro, t3.small, t3.medium, t3.large`);
|
|
41
|
+
}
|
|
42
|
+
return errors;
|
|
43
|
+
}
|
|
44
|
+
/** Dynamic import of AWS EC2 + STS SDK modules. Returns null with error message on failure. */
|
|
45
|
+
export async function loadAwsSdk() {
|
|
46
|
+
try {
|
|
47
|
+
const ec2Mod = await import('@aws-sdk/client-ec2');
|
|
48
|
+
const stsMod = await import('@aws-sdk/client-sts');
|
|
49
|
+
return { ec2Mod, stsMod };
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return {
|
|
53
|
+
error: 'AWS SDK not installed. Run: npm install @aws-sdk/client-ec2 @aws-sdk/client-sts @aws-sdk/client-rds @aws-sdk/client-elasticache',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS EC2 provisioning — credential validation, key pair, security group,
|
|
3
|
+
* AMI lookup, instance launch, polling, and SSH restriction.
|
|
4
|
+
*/
|
|
5
|
+
import type { ProvisionContext, ProvisionEmitter } from './types.js';
|
|
6
|
+
import type { InstanceType } from '../instance-sizing.js';
|
|
7
|
+
import type { AwsProvisionState } from './aws-config.js';
|
|
8
|
+
/** Step 1: Validate AWS credentials via STS. */
|
|
9
|
+
export declare function validateCredentials(state: AwsProvisionState, stsMod: typeof import('@aws-sdk/client-sts'), emit: ProvisionEmitter): Promise<boolean>;
|
|
10
|
+
/** Step 2: Create SSH key pair. */
|
|
11
|
+
export declare function createKeyPair(state: AwsProvisionState, ctx: ProvisionContext, ec2Mod: typeof import('@aws-sdk/client-ec2'), emit: ProvisionEmitter): Promise<boolean>;
|
|
12
|
+
/** Step 3: Create security group with ingress rules. */
|
|
13
|
+
export declare function createSecurityGroup(state: AwsProvisionState, ctx: ProvisionContext, ec2Mod: typeof import('@aws-sdk/client-ec2'), emit: ProvisionEmitter): Promise<boolean>;
|
|
14
|
+
/** Step 4: Find latest Amazon Linux 2023 AMI. */
|
|
15
|
+
export declare function findAmi(state: AwsProvisionState, ec2Mod: typeof import('@aws-sdk/client-ec2'), emit: ProvisionEmitter): Promise<string | null>;
|
|
16
|
+
/** Steps 5-6: Launch EC2 instance and wait for it to be running. */
|
|
17
|
+
export declare function launchAndWaitEc2(state: AwsProvisionState, ctx: ProvisionContext, ec2Mod: typeof import('@aws-sdk/client-ec2'), amiId: string, ec2InstanceType: InstanceType, emit: ProvisionEmitter): Promise<boolean>;
|
|
18
|
+
/** DEVOPS-R2-001: Restrict SSH from 0.0.0.0/0 to deployer's IP after provisioning. */
|
|
19
|
+
export declare function restrictSsh(state: AwsProvisionState, emit: ProvisionEmitter): Promise<void>;
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS EC2 provisioning — credential validation, key pair, security group,
|
|
3
|
+
* AMI lookup, instance launch, polling, and SSH restriction.
|
|
4
|
+
*/
|
|
5
|
+
import { writeFile, mkdir, chmod } from 'node:fs/promises';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { POLL_INTERVAL_MS, MAX_POLL_MS, cancellableSleep } from './aws-config.js';
|
|
8
|
+
import { recordResourcePending, recordResourceCreated } from '../provision-manifest.js';
|
|
9
|
+
/** Step 1: Validate AWS credentials via STS. */
|
|
10
|
+
export async function validateCredentials(state, stsMod, emit) {
|
|
11
|
+
emit({ step: 'validate-creds', status: 'started', message: 'Validating AWS credentials' });
|
|
12
|
+
try {
|
|
13
|
+
const sts = new stsMod.STSClient(state.awsConfig);
|
|
14
|
+
const identity = await sts.send(new stsMod.GetCallerIdentityCommand({}));
|
|
15
|
+
const entityName = (identity.Arn ?? 'unknown').split(/[/:]/).pop() ?? 'unknown';
|
|
16
|
+
emit({ step: 'validate-creds', status: 'done', message: `Authenticated as ${entityName}` });
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
console.error('AWS credential validation error:', err.message);
|
|
21
|
+
emit({ step: 'validate-creds', status: 'error', message: 'Invalid AWS credentials', detail: 'Check AWS Console for details' });
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** Step 2: Create SSH key pair. */
|
|
26
|
+
export async function createKeyPair(state, ctx, ec2Mod, emit) {
|
|
27
|
+
emit({ step: 'key-pair', status: 'started', message: 'Creating SSH key pair' });
|
|
28
|
+
const keyName = `${state.slug}-deploy`;
|
|
29
|
+
try {
|
|
30
|
+
const ec2 = new ec2Mod.EC2Client(state.awsConfig);
|
|
31
|
+
await recordResourcePending(ctx.runId, 'key-pair', keyName, state.region);
|
|
32
|
+
const keyResult = await ec2.send(new ec2Mod.CreateKeyPairCommand({
|
|
33
|
+
KeyName: keyName,
|
|
34
|
+
KeyType: 'ed25519',
|
|
35
|
+
}));
|
|
36
|
+
if (!keyResult.KeyMaterial) {
|
|
37
|
+
throw new Error('AWS returned no key material — key pair may already exist');
|
|
38
|
+
}
|
|
39
|
+
const sshDir = join(ctx.projectDir, '.ssh');
|
|
40
|
+
await mkdir(sshDir, { recursive: true });
|
|
41
|
+
const keyPath = join(sshDir, 'deploy-key.pem');
|
|
42
|
+
await writeFile(keyPath, keyResult.KeyMaterial, 'utf-8');
|
|
43
|
+
await chmod(keyPath, 0o600);
|
|
44
|
+
state.files.push('.ssh/deploy-key.pem');
|
|
45
|
+
state.resources.push({ type: 'key-pair', id: keyName, region: state.region });
|
|
46
|
+
await recordResourceCreated(ctx.runId, 'key-pair', keyName, state.region);
|
|
47
|
+
state.outputs['SSH_KEY_PATH'] = '.ssh/deploy-key.pem';
|
|
48
|
+
emit({ step: 'key-pair', status: 'done', message: `Key pair "${keyName}" created` });
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
console.error('Key pair creation error:', err.message);
|
|
53
|
+
emit({ step: 'key-pair', status: 'error', message: 'Failed to create key pair', detail: 'Check AWS Console for details' });
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Step 3: Create security group with ingress rules. */
|
|
58
|
+
export async function createSecurityGroup(state, ctx, ec2Mod, emit) {
|
|
59
|
+
emit({ step: 'security-group', status: 'started', message: 'Creating security group' });
|
|
60
|
+
try {
|
|
61
|
+
const ec2 = new ec2Mod.EC2Client(state.awsConfig);
|
|
62
|
+
await recordResourcePending(ctx.runId, 'security-group', `${state.slug}-sg`, state.region);
|
|
63
|
+
const sgResult = await ec2.send(new ec2Mod.CreateSecurityGroupCommand({
|
|
64
|
+
GroupName: `${state.slug}-sg`,
|
|
65
|
+
Description: `VoidForge security group for ${ctx.projectName}`,
|
|
66
|
+
}));
|
|
67
|
+
state.sgId = sgResult.GroupId ?? '';
|
|
68
|
+
state.resources.push({ type: 'security-group', id: state.sgId, region: state.region });
|
|
69
|
+
await recordResourceCreated(ctx.runId, 'security-group', state.sgId, state.region);
|
|
70
|
+
// Authorize inbound: SSH (22), HTTP (80), HTTPS (443)
|
|
71
|
+
// SSH initially open to 0.0.0.0/0 for provisioning — restricted to deployer IP at end (DEVOPS-R2-001).
|
|
72
|
+
const ingressRules = [
|
|
73
|
+
{ IpProtocol: 'tcp', FromPort: 22, ToPort: 22, IpRanges: [{ CidrIp: '0.0.0.0/0', Description: 'SSH' }] },
|
|
74
|
+
{ IpProtocol: 'tcp', FromPort: 80, ToPort: 80, IpRanges: [{ CidrIp: '0.0.0.0/0', Description: 'HTTP' }] },
|
|
75
|
+
{ IpProtocol: 'tcp', FromPort: 443, ToPort: 443, IpRanges: [{ CidrIp: '0.0.0.0/0', Description: 'HTTPS' }] },
|
|
76
|
+
];
|
|
77
|
+
// Allow DB port within the SG (self-referencing) so EC2 can reach RDS
|
|
78
|
+
if (ctx.database === 'postgres') {
|
|
79
|
+
ingressRules.push({ IpProtocol: 'tcp', FromPort: 5432, ToPort: 5432, UserIdGroupPairs: [{ GroupId: state.sgId, Description: 'PostgreSQL (SG-only)' }] });
|
|
80
|
+
}
|
|
81
|
+
else if (ctx.database === 'mysql') {
|
|
82
|
+
ingressRules.push({ IpProtocol: 'tcp', FromPort: 3306, ToPort: 3306, UserIdGroupPairs: [{ GroupId: state.sgId, Description: 'MySQL (SG-only)' }] });
|
|
83
|
+
}
|
|
84
|
+
// Allow Redis port if cache requested
|
|
85
|
+
if (ctx.cache === 'redis') {
|
|
86
|
+
ingressRules.push({ IpProtocol: 'tcp', FromPort: 6379, ToPort: 6379, UserIdGroupPairs: [{ GroupId: state.sgId, Description: 'Redis (SG-only)' }] });
|
|
87
|
+
}
|
|
88
|
+
await ec2.send(new ec2Mod.AuthorizeSecurityGroupIngressCommand({
|
|
89
|
+
GroupId: state.sgId,
|
|
90
|
+
IpPermissions: ingressRules,
|
|
91
|
+
}));
|
|
92
|
+
const portList = ingressRules.map((r) => r.FromPort).join(', ');
|
|
93
|
+
emit({ step: 'security-group', status: 'done', message: `Security group "${state.slug}-sg" created (ports ${portList})` });
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
console.error('Security group creation error:', err.message);
|
|
98
|
+
emit({ step: 'security-group', status: 'error', message: 'Failed to create security group', detail: 'Check AWS Console for details' });
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** Step 4: Find latest Amazon Linux 2023 AMI. */
|
|
103
|
+
export async function findAmi(state, ec2Mod, emit) {
|
|
104
|
+
emit({ step: 'ami-lookup', status: 'started', message: 'Finding latest Amazon Linux 2023 AMI' });
|
|
105
|
+
try {
|
|
106
|
+
const ec2 = new ec2Mod.EC2Client(state.awsConfig);
|
|
107
|
+
const amiResult = await ec2.send(new ec2Mod.DescribeImagesCommand({
|
|
108
|
+
Owners: ['amazon'],
|
|
109
|
+
Filters: [
|
|
110
|
+
{ Name: 'name', Values: ['al2023-ami-*-x86_64'] },
|
|
111
|
+
{ Name: 'state', Values: ['available'] },
|
|
112
|
+
{ Name: 'architecture', Values: ['x86_64'] },
|
|
113
|
+
],
|
|
114
|
+
}));
|
|
115
|
+
const images = (amiResult.Images ?? [])
|
|
116
|
+
.filter((img) => img.ImageId && img.CreationDate)
|
|
117
|
+
.sort((a, b) => (b.CreationDate ?? '').localeCompare(a.CreationDate ?? ''));
|
|
118
|
+
if (images.length === 0) {
|
|
119
|
+
throw new Error('No Amazon Linux 2023 AMI found in this region');
|
|
120
|
+
}
|
|
121
|
+
const amiId = images[0].ImageId;
|
|
122
|
+
emit({ step: 'ami-lookup', status: 'done', message: `AMI: ${amiId}` });
|
|
123
|
+
return amiId;
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
console.error('AMI lookup error:', err.message);
|
|
127
|
+
emit({ step: 'ami-lookup', status: 'error', message: 'AMI lookup failed', detail: 'Check AWS Console for details' });
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/** Steps 5-6: Launch EC2 instance and wait for it to be running. */
|
|
132
|
+
export async function launchAndWaitEc2(state, ctx, ec2Mod, amiId, ec2InstanceType, emit) {
|
|
133
|
+
// Step 5: Launch
|
|
134
|
+
emit({ step: 'launch-ec2', status: 'started', message: `Launching EC2 instance (${ec2InstanceType})` });
|
|
135
|
+
try {
|
|
136
|
+
const ec2 = new ec2Mod.EC2Client(state.awsConfig);
|
|
137
|
+
const keyName = `${state.slug}-deploy`;
|
|
138
|
+
const userDataScript = `#!/bin/bash
|
|
139
|
+
dnf update -y
|
|
140
|
+
dnf install -y git curl`;
|
|
141
|
+
await recordResourcePending(ctx.runId, 'ec2-instance', 'pending', state.region);
|
|
142
|
+
const runResult = await ec2.send(new ec2Mod.RunInstancesCommand({
|
|
143
|
+
ImageId: amiId,
|
|
144
|
+
InstanceType: ec2InstanceType,
|
|
145
|
+
MinCount: 1,
|
|
146
|
+
MaxCount: 1,
|
|
147
|
+
KeyName: keyName,
|
|
148
|
+
SecurityGroupIds: [state.sgId],
|
|
149
|
+
UserData: Buffer.from(userDataScript).toString('base64'),
|
|
150
|
+
TagSpecifications: [{
|
|
151
|
+
ResourceType: 'instance',
|
|
152
|
+
Tags: [
|
|
153
|
+
{ Key: 'Name', Value: ctx.projectName },
|
|
154
|
+
{ Key: 'ManagedBy', Value: 'VoidForge' },
|
|
155
|
+
],
|
|
156
|
+
}],
|
|
157
|
+
}));
|
|
158
|
+
state.instanceId = runResult.Instances?.[0]?.InstanceId ?? '';
|
|
159
|
+
if (!state.instanceId)
|
|
160
|
+
throw new Error('No instance ID returned');
|
|
161
|
+
state.resources.push({ type: 'ec2-instance', id: state.instanceId, region: state.region });
|
|
162
|
+
await recordResourceCreated(ctx.runId, 'ec2-instance', state.instanceId, state.region);
|
|
163
|
+
emit({ step: 'launch-ec2', status: 'done', message: `Instance ${state.instanceId} launched` });
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
console.error('EC2 launch error:', err.message);
|
|
167
|
+
emit({ step: 'launch-ec2', status: 'error', message: 'Failed to launch EC2', detail: 'Check AWS Console for details' });
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
// Step 6: Wait for running
|
|
171
|
+
emit({ step: 'wait-running', status: 'started', message: 'Waiting for instance to start...' });
|
|
172
|
+
try {
|
|
173
|
+
const ec2 = new ec2Mod.EC2Client(state.awsConfig);
|
|
174
|
+
const start = Date.now();
|
|
175
|
+
while (Date.now() - start < MAX_POLL_MS) {
|
|
176
|
+
await cancellableSleep(POLL_INTERVAL_MS + Math.random() * 1000, ctx.abortSignal);
|
|
177
|
+
const desc = await ec2.send(new ec2Mod.DescribeInstancesCommand({
|
|
178
|
+
InstanceIds: [state.instanceId],
|
|
179
|
+
}));
|
|
180
|
+
const instance = desc.Reservations?.[0]?.Instances?.[0];
|
|
181
|
+
const instanceState = instance?.State?.Name;
|
|
182
|
+
if (instanceState === 'running') {
|
|
183
|
+
state.publicIp = instance?.PublicIpAddress ?? '';
|
|
184
|
+
if (state.publicIp)
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
if (instanceState === 'terminated' || instanceState === 'shutting-down') {
|
|
188
|
+
throw new Error(`Instance entered state: ${instanceState}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (!state.publicIp)
|
|
192
|
+
throw new Error('Instance did not get a public IP within timeout');
|
|
193
|
+
state.outputs['SSH_HOST'] = state.publicIp;
|
|
194
|
+
state.outputs['SSH_USER'] = 'ec2-user';
|
|
195
|
+
emit({ step: 'wait-running', status: 'done', message: `Instance running at ${state.publicIp}` });
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
if (err.message === 'Aborted') {
|
|
200
|
+
emit({ step: 'wait-running', status: 'skipped', message: 'EC2 polling cancelled' });
|
|
201
|
+
return true; // Non-fatal abort
|
|
202
|
+
}
|
|
203
|
+
console.error('EC2 wait error:', err.message);
|
|
204
|
+
emit({ step: 'wait-running', status: 'error', message: 'Instance failed to start', detail: 'Check AWS Console for details' });
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/** DEVOPS-R2-001: Restrict SSH from 0.0.0.0/0 to deployer's IP after provisioning. */
|
|
209
|
+
export async function restrictSsh(state, emit) {
|
|
210
|
+
try {
|
|
211
|
+
const { EC2Client, RevokeSecurityGroupIngressCommand, AuthorizeSecurityGroupIngressCommand } = await import('@aws-sdk/client-ec2');
|
|
212
|
+
const ec2Restrict = new EC2Client(state.awsConfig);
|
|
213
|
+
// Detect deployer's public IP via checkip.amazonaws.com
|
|
214
|
+
let deployerIp = null;
|
|
215
|
+
try {
|
|
216
|
+
const ipRes = await fetch('https://checkip.amazonaws.com', { signal: AbortSignal.timeout(5000) });
|
|
217
|
+
if (ipRes.ok)
|
|
218
|
+
deployerIp = (await ipRes.text()).trim();
|
|
219
|
+
}
|
|
220
|
+
catch { /* non-fatal — keep 0.0.0.0/0 if detection fails */ }
|
|
221
|
+
if (deployerIp && /^\d+\.\d+\.\d+\.\d+$/.test(deployerIp)) {
|
|
222
|
+
// Revoke the wide-open SSH rule
|
|
223
|
+
await ec2Restrict.send(new RevokeSecurityGroupIngressCommand({
|
|
224
|
+
GroupId: state.sgId,
|
|
225
|
+
IpPermissions: [{ IpProtocol: 'tcp', FromPort: 22, ToPort: 22, IpRanges: [{ CidrIp: '0.0.0.0/0' }] }],
|
|
226
|
+
}));
|
|
227
|
+
// Add restricted SSH rule for deployer's IP only
|
|
228
|
+
await ec2Restrict.send(new AuthorizeSecurityGroupIngressCommand({
|
|
229
|
+
GroupId: state.sgId,
|
|
230
|
+
IpPermissions: [{ IpProtocol: 'tcp', FromPort: 22, ToPort: 22, IpRanges: [{ CidrIp: `${deployerIp}/32`, Description: 'SSH (deployer IP)' }] }],
|
|
231
|
+
}));
|
|
232
|
+
emit({ step: 'ssh-restrict', status: 'done', message: `SSH restricted to ${deployerIp}/32 (was 0.0.0.0/0)` });
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
emit({ step: 'ssh-restrict', status: 'warning', message: 'Could not detect public IP — SSH remains open to 0.0.0.0/0. Restrict manually in AWS Console.' });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
emit({ step: 'ssh-restrict', status: 'warning', message: 'SSH restriction failed (non-fatal). Restrict port 22 manually.', detail: err.message });
|
|
240
|
+
}
|
|
241
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS RDS + ElastiCache provisioning — database and cache service creation with polling.
|
|
3
|
+
*/
|
|
4
|
+
import type { ProvisionContext, ProvisionEmitter } from './types.js';
|
|
5
|
+
import type { InstanceType as Ec2InstanceType } from '../instance-sizing.js';
|
|
6
|
+
import type { AwsProvisionState } from './aws-config.js';
|
|
7
|
+
/** Step 7: Provision RDS database (postgres or mysql). Non-fatal on failure. */
|
|
8
|
+
export declare function provisionRds(state: AwsProvisionState, ctx: ProvisionContext, ec2InstanceType: Ec2InstanceType, emit: ProvisionEmitter): Promise<void>;
|
|
9
|
+
/** Step 8: Provision ElastiCache Redis cluster. Non-fatal on failure. */
|
|
10
|
+
export declare function provisionElastiCache(state: AwsProvisionState, ctx: ProvisionContext, ec2InstanceType: Ec2InstanceType, emit: ProvisionEmitter): Promise<void>;
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS RDS + ElastiCache provisioning — database and cache service creation with polling.
|
|
3
|
+
*/
|
|
4
|
+
import { randomBytes } from 'node:crypto';
|
|
5
|
+
import { cancellableSleep } from './aws-config.js';
|
|
6
|
+
import { rdsInstanceClass, cacheNodeType } from '../instance-sizing.js';
|
|
7
|
+
import { recordResourcePending, recordResourceCreated } from '../provision-manifest.js';
|
|
8
|
+
/** Step 7: Provision RDS database (postgres or mysql). Non-fatal on failure. */
|
|
9
|
+
export async function provisionRds(state, ctx, ec2InstanceType, emit) {
|
|
10
|
+
if (ctx.database !== 'postgres' && ctx.database !== 'mysql') {
|
|
11
|
+
emit({ step: 'rds', status: 'skipped', message: 'No database requested' });
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
emit({ step: 'rds', status: 'started', message: `Creating RDS instance (${ctx.database})` });
|
|
15
|
+
try {
|
|
16
|
+
const { RDSClient, CreateDBInstanceCommand, DescribeDBInstancesCommand } = await import('@aws-sdk/client-rds');
|
|
17
|
+
const rds = new RDSClient(state.awsConfig);
|
|
18
|
+
const engine = ctx.database === 'postgres' ? 'postgres' : 'mysql';
|
|
19
|
+
const port = ctx.database === 'postgres' ? 5432 : 3306;
|
|
20
|
+
const dbInstanceId = `${state.slug}-db`;
|
|
21
|
+
// IG-R2: Random username instead of hardcoded 'admin'
|
|
22
|
+
const dbUsername = `vf_${randomBytes(4).toString('hex')}`;
|
|
23
|
+
const specials = '!@#$%^&*';
|
|
24
|
+
const suffix = String.fromCharCode(65 + Math.floor(Math.random() * 26)) + Math.floor(Math.random() * 10) + specials[Math.floor(Math.random() * specials.length)];
|
|
25
|
+
const dbPassword = randomBytes(16).toString('hex') + suffix;
|
|
26
|
+
await recordResourcePending(ctx.runId, 'rds-instance', dbInstanceId, state.region);
|
|
27
|
+
await rds.send(new CreateDBInstanceCommand({
|
|
28
|
+
DBInstanceIdentifier: dbInstanceId,
|
|
29
|
+
DBInstanceClass: rdsInstanceClass(ec2InstanceType),
|
|
30
|
+
Engine: engine,
|
|
31
|
+
MasterUsername: dbUsername,
|
|
32
|
+
MasterUserPassword: dbPassword,
|
|
33
|
+
AllocatedStorage: 20,
|
|
34
|
+
PubliclyAccessible: false,
|
|
35
|
+
VpcSecurityGroupIds: [state.sgId],
|
|
36
|
+
Tags: [
|
|
37
|
+
{ Key: 'Name', Value: `${ctx.projectName}-db` },
|
|
38
|
+
{ Key: 'ManagedBy', Value: 'VoidForge' },
|
|
39
|
+
],
|
|
40
|
+
}));
|
|
41
|
+
state.resources.push({ type: 'rds-instance', id: dbInstanceId, region: state.region });
|
|
42
|
+
await recordResourceCreated(ctx.runId, 'rds-instance', dbInstanceId, state.region);
|
|
43
|
+
state.outputs['DB_ENGINE'] = engine;
|
|
44
|
+
state.outputs['DB_PORT'] = String(port);
|
|
45
|
+
state.outputs['DB_INSTANCE_ID'] = dbInstanceId;
|
|
46
|
+
state.outputs['DB_USERNAME'] = dbUsername;
|
|
47
|
+
state.outputs['DB_PASSWORD'] = dbPassword;
|
|
48
|
+
emit({ step: 'rds', status: 'done', message: `RDS instance "${dbInstanceId}" created — waiting for endpoint` });
|
|
49
|
+
// Step 7b: Poll RDS until available (non-fatal on timeout)
|
|
50
|
+
await pollRdsEndpoint(state, ctx, rds, DescribeDBInstancesCommand, dbInstanceId, emit);
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
console.error('RDS creation error:', err.message);
|
|
54
|
+
emit({ step: 'rds', status: 'error', message: 'Failed to create RDS instance', detail: 'Check AWS Console for details' });
|
|
55
|
+
// Non-fatal — continue without DB
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function pollRdsEndpoint(state, ctx, rds, DescribeDBInstancesCommand, dbInstanceId, emit) {
|
|
59
|
+
const RDS_POLL_MS = 10000;
|
|
60
|
+
const RDS_TIMEOUT_MS = 900000; // 15 minutes
|
|
61
|
+
const RDS_PROGRESS_MS = 30000;
|
|
62
|
+
emit({ step: 'rds-wait', status: 'started', message: 'Waiting for RDS to become available (5-10 minutes)...' });
|
|
63
|
+
try {
|
|
64
|
+
const rdsStart = Date.now();
|
|
65
|
+
let lastProgress = rdsStart;
|
|
66
|
+
let dbHost = '';
|
|
67
|
+
while (Date.now() - rdsStart < RDS_TIMEOUT_MS) {
|
|
68
|
+
await cancellableSleep(RDS_POLL_MS + Math.random() * 2000, ctx.abortSignal);
|
|
69
|
+
const desc = await rds.send(new DescribeDBInstancesCommand({
|
|
70
|
+
DBInstanceIdentifier: dbInstanceId,
|
|
71
|
+
}));
|
|
72
|
+
const instance = desc.DBInstances?.[0];
|
|
73
|
+
const status = instance?.DBInstanceStatus;
|
|
74
|
+
if (status === 'available') {
|
|
75
|
+
dbHost = instance?.Endpoint?.Address ?? '';
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
// Check for terminal failure states
|
|
79
|
+
const rdsTerminalStates = ['failed', 'deleting', 'deleted', 'incompatible-parameters', 'incompatible-restore', 'storage-full'];
|
|
80
|
+
if (status && rdsTerminalStates.includes(status)) {
|
|
81
|
+
emit({ step: 'rds-wait', status: 'error', message: `RDS entered terminal state: ${status}`, detail: 'Check AWS Console for details' });
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
// Emit progress every 30 seconds
|
|
85
|
+
if (Date.now() - lastProgress >= RDS_PROGRESS_MS) {
|
|
86
|
+
const elapsed = Math.round((Date.now() - rdsStart) / 1000);
|
|
87
|
+
emit({ step: 'rds-wait', status: 'started', message: `RDS status: ${status || 'creating'}... (${elapsed}s elapsed)` });
|
|
88
|
+
lastProgress = Date.now();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (dbHost) {
|
|
92
|
+
state.outputs['DB_HOST'] = dbHost;
|
|
93
|
+
emit({ step: 'rds-wait', status: 'done', message: `RDS available at ${dbHost}` });
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
emit({ step: 'rds-wait', status: 'error', message: 'RDS polling timed out after 15 minutes', detail: `Instance "${dbInstanceId}" is still provisioning. Check the AWS Console for the endpoint and add DB_HOST to your .env manually.` });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (pollErr) {
|
|
100
|
+
if (pollErr.message === 'Aborted') {
|
|
101
|
+
emit({ step: 'rds-wait', status: 'skipped', message: 'RDS polling cancelled' });
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
console.error('RDS polling error:', pollErr.message);
|
|
105
|
+
emit({ step: 'rds-wait', status: 'error', message: 'RDS polling failed', detail: 'Check AWS Console for details' });
|
|
106
|
+
}
|
|
107
|
+
// Non-fatal — continue without DB_HOST
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** Step 8: Provision ElastiCache Redis cluster. Non-fatal on failure. */
|
|
111
|
+
export async function provisionElastiCache(state, ctx, ec2InstanceType, emit) {
|
|
112
|
+
if (ctx.cache !== 'redis') {
|
|
113
|
+
emit({ step: 'elasticache', status: 'skipped', message: 'No cache requested' });
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
emit({ step: 'elasticache', status: 'started', message: 'Creating ElastiCache Redis cluster' });
|
|
117
|
+
try {
|
|
118
|
+
const { ElastiCacheClient, CreateCacheClusterCommand, DescribeCacheClustersCommand } = await import('@aws-sdk/client-elasticache');
|
|
119
|
+
const elasticache = new ElastiCacheClient(state.awsConfig);
|
|
120
|
+
const clusterId = `${state.slug}-redis`;
|
|
121
|
+
await recordResourcePending(ctx.runId, 'elasticache-cluster', clusterId, state.region);
|
|
122
|
+
// Note: CreateCacheClusterCommand does not support AuthToken — Redis AUTH requires
|
|
123
|
+
// CreateReplicationGroupCommand with TransitEncryptionEnabled. Security relies on
|
|
124
|
+
// SG isolation (only instances in the same SG can reach the Redis port). (IG-R3)
|
|
125
|
+
await elasticache.send(new CreateCacheClusterCommand({
|
|
126
|
+
CacheClusterId: clusterId,
|
|
127
|
+
CacheNodeType: cacheNodeType(ec2InstanceType),
|
|
128
|
+
Engine: 'redis',
|
|
129
|
+
NumCacheNodes: 1,
|
|
130
|
+
Tags: [
|
|
131
|
+
{ Key: 'Name', Value: `${ctx.projectName}-redis` },
|
|
132
|
+
{ Key: 'ManagedBy', Value: 'VoidForge' },
|
|
133
|
+
],
|
|
134
|
+
}));
|
|
135
|
+
state.resources.push({ type: 'elasticache-cluster', id: clusterId, region: state.region });
|
|
136
|
+
await recordResourceCreated(ctx.runId, 'elasticache-cluster', clusterId, state.region);
|
|
137
|
+
state.outputs['REDIS_CLUSTER_ID'] = clusterId;
|
|
138
|
+
emit({ step: 'elasticache', status: 'done', message: `ElastiCache cluster "${clusterId}" created — waiting for endpoint` });
|
|
139
|
+
// Step 8b: Poll ElastiCache until available
|
|
140
|
+
await pollCacheEndpoint(state, ctx, elasticache, DescribeCacheClustersCommand, clusterId, emit);
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
console.error('ElastiCache creation error:', err.message);
|
|
144
|
+
emit({ step: 'elasticache', status: 'error', message: 'Failed to create ElastiCache cluster', detail: 'Check AWS Console for details' });
|
|
145
|
+
// Non-fatal
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async function pollCacheEndpoint(state, ctx, elasticache, DescribeCacheClustersCommand, clusterId, emit) {
|
|
149
|
+
const CACHE_POLL_MS = 5000;
|
|
150
|
+
const CACHE_TIMEOUT_MS = 300000; // 5 minutes
|
|
151
|
+
const CACHE_PROGRESS_MS = 15000;
|
|
152
|
+
emit({ step: 'cache-wait', status: 'started', message: 'Waiting for Redis to become available (1-2 minutes)...' });
|
|
153
|
+
try {
|
|
154
|
+
const cacheStart = Date.now();
|
|
155
|
+
let lastCacheProgress = cacheStart;
|
|
156
|
+
let redisHost = '';
|
|
157
|
+
while (Date.now() - cacheStart < CACHE_TIMEOUT_MS) {
|
|
158
|
+
await cancellableSleep(CACHE_POLL_MS + Math.random() * 1000, ctx.abortSignal);
|
|
159
|
+
const desc = await elasticache.send(new DescribeCacheClustersCommand({
|
|
160
|
+
CacheClusterId: clusterId,
|
|
161
|
+
ShowCacheNodeInfo: true,
|
|
162
|
+
}));
|
|
163
|
+
const cluster = desc.CacheClusters?.[0];
|
|
164
|
+
const status = cluster?.CacheClusterStatus;
|
|
165
|
+
if (status === 'available') {
|
|
166
|
+
redisHost = cluster?.CacheNodes?.[0]?.Endpoint?.Address ?? '';
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
// Check for terminal failure states
|
|
170
|
+
const cacheTerminalStates = ['deleted', 'deleting', 'create-failed', 'snapshotting'];
|
|
171
|
+
if (status && cacheTerminalStates.includes(status)) {
|
|
172
|
+
emit({ step: 'cache-wait', status: 'error', message: `Redis entered terminal state: ${status}`, detail: 'Check AWS Console for details' });
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
if (Date.now() - lastCacheProgress >= CACHE_PROGRESS_MS) {
|
|
176
|
+
const elapsed = Math.round((Date.now() - cacheStart) / 1000);
|
|
177
|
+
emit({ step: 'cache-wait', status: 'started', message: `Redis status: ${status || 'creating'}... (${elapsed}s elapsed)` });
|
|
178
|
+
lastCacheProgress = Date.now();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (redisHost) {
|
|
182
|
+
state.outputs['REDIS_HOST'] = redisHost;
|
|
183
|
+
state.outputs['REDIS_PORT'] = '6379';
|
|
184
|
+
emit({ step: 'cache-wait', status: 'done', message: `Redis available at ${redisHost}:6379` });
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
emit({ step: 'cache-wait', status: 'error', message: 'Redis polling timed out after 5 minutes', detail: `Cluster "${clusterId}" is still provisioning. Check the AWS Console for the endpoint.` });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch (pollErr) {
|
|
191
|
+
if (pollErr.message === 'Aborted') {
|
|
192
|
+
emit({ step: 'cache-wait', status: 'skipped', message: 'Redis polling cancelled' });
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
console.error('Redis polling error:', pollErr.message);
|
|
196
|
+
emit({ step: 'cache-wait', status: 'error', message: 'Redis polling failed', detail: 'Check AWS Console for details' });
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|