thevoidforge 21.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/scripts/vault-read.d.ts +11 -0
- package/dist/scripts/vault-read.js +89 -0
- package/dist/scripts/voidforge.d.ts +20 -0
- package/dist/scripts/voidforge.js +404 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/wizard/api/auth.d.ts +5 -0
- package/dist/wizard/api/auth.js +133 -0
- package/dist/wizard/api/blueprint.d.ts +45 -0
- package/dist/wizard/api/blueprint.js +184 -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 +258 -0
- package/dist/wizard/api/danger-room.d.ts +18 -0
- package/dist/wizard/api/danger-room.js +401 -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 +239 -0
- package/dist/wizard/api/projects.d.ts +6 -0
- package/dist/wizard/api/projects.js +648 -0
- package/dist/wizard/api/provision.d.ts +4 -0
- package/dist/wizard/api/provision.js +535 -0
- package/dist/wizard/api/terminal.d.ts +25 -0
- package/dist/wizard/api/terminal.js +241 -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 +14 -0
- package/dist/wizard/api/war-room.js +45 -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/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 +183 -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 +180 -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 +151 -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 +71 -0
- package/dist/wizard/lib/daemon-aggregator.js +204 -0
- package/dist/wizard/lib/daemon-core.d.ts +6 -0
- package/dist/wizard/lib/daemon-core.js +5 -0
- package/dist/wizard/lib/dashboard-data.d.ts +132 -0
- package/dist/wizard/lib/dashboard-data.js +336 -0
- package/dist/wizard/lib/dashboard-ws.d.ts +25 -0
- package/dist/wizard/lib/dashboard-ws.js +91 -0
- package/dist/wizard/lib/deep-current.d.ts +77 -0
- package/dist/wizard/lib/deep-current.js +234 -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/google-campaign.d.ts +42 -0
- package/dist/wizard/lib/financial/campaign/google-campaign.js +388 -0
- package/dist/wizard/lib/financial/campaign/meta-campaign.d.ts +41 -0
- package/dist/wizard/lib/financial/campaign/meta-campaign.js +311 -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-campaign.d.ts +40 -0
- package/dist/wizard/lib/financial/campaign/tiktok-campaign.js +350 -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 +199 -0
- package/dist/wizard/lib/frontmatter.d.ts +30 -0
- package/dist/wizard/lib/frontmatter.js +96 -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.d.ts +15 -0
- package/dist/wizard/lib/heartbeat.js +827 -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 +161 -0
- package/dist/wizard/lib/patterns/financial-transaction.js +132 -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 +193 -0
- package/dist/wizard/lib/project-registry.d.ts +86 -0
- package/dist/wizard/lib/project-registry.js +359 -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-vps.d.ts +6 -0
- package/dist/wizard/lib/provisioners/aws-vps.js +643 -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.d.ts +6 -0
- package/dist/wizard/lib/provisioners/railway.js +413 -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 +231 -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 +276 -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 +126 -0
- package/dist/wizard/lib/treasury-heartbeat.d.ts +82 -0
- package/dist/wizard/lib/treasury-heartbeat.js +1104 -0
- package/dist/wizard/lib/updater.d.ts +29 -0
- package/dist/wizard/lib/updater.js +190 -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 +5 -0
- package/dist/wizard/router.js +15 -0
- package/dist/wizard/server.d.ts +18 -0
- package/dist/wizard/server.js +436 -0
- package/package.json +59 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Deploy Provisioner — deploys VoidForge itself to a remote VPS.
|
|
3
|
+
*
|
|
4
|
+
* Usage: npx voidforge deploy --self
|
|
5
|
+
*
|
|
6
|
+
* Steps:
|
|
7
|
+
* 1. Connect to VPS via SSH (EC2 or manual target)
|
|
8
|
+
* 2. Install: Node.js, Git, PM2, Caddy, Claude Code
|
|
9
|
+
* 3. Clone VoidForge, configure Caddy for HTTPS
|
|
10
|
+
* 4. Create forge-user (non-root PTY execution)
|
|
11
|
+
* 5. Generate initial admin credentials + TOTP secret
|
|
12
|
+
* 6. Start VoidForge as PM2-managed service
|
|
13
|
+
* 7. Report public URL + TOTP QR setup instructions
|
|
14
|
+
*/
|
|
15
|
+
/** Shell-escape a value to prevent command injection. */
|
|
16
|
+
function shellEscape(value) {
|
|
17
|
+
// Reject any value containing shell metacharacters
|
|
18
|
+
if (/[;&|`$(){}\\!#\n\r]/.test(value)) {
|
|
19
|
+
throw new Error(`Unsafe value for shell interpolation: ${value.slice(0, 20)}...`);
|
|
20
|
+
}
|
|
21
|
+
// Wrap in single quotes for extra safety (single quotes prevent all expansion)
|
|
22
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
23
|
+
}
|
|
24
|
+
/** Validate a domain name. */
|
|
25
|
+
function isValidDomain(domain) {
|
|
26
|
+
return /^[a-zA-Z0-9][a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(domain);
|
|
27
|
+
}
|
|
28
|
+
const DEFAULT_CONFIG = {
|
|
29
|
+
nodeVersion: '22',
|
|
30
|
+
voidforgeRepo: 'https://github.com/tmcleod3/voidforge.git',
|
|
31
|
+
voidforgeBranch: 'main',
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Generate the provision script that runs on the remote VPS.
|
|
35
|
+
* This script is piped over SSH — no files need to exist on the remote first.
|
|
36
|
+
*/
|
|
37
|
+
export function generateProvisionScript(config) {
|
|
38
|
+
// Validate all inputs before shell interpolation
|
|
39
|
+
if (!isValidDomain(config.domain)) {
|
|
40
|
+
throw new Error(`Invalid domain: ${config.domain}`);
|
|
41
|
+
}
|
|
42
|
+
const safeDomain = shellEscape(config.domain);
|
|
43
|
+
const safeRepo = shellEscape(config.voidforgeRepo);
|
|
44
|
+
const safeBranch = shellEscape(config.voidforgeBranch);
|
|
45
|
+
const safeNodeVersion = shellEscape(config.nodeVersion);
|
|
46
|
+
return `#!/bin/bash
|
|
47
|
+
set -euo pipefail
|
|
48
|
+
|
|
49
|
+
echo "=== VoidForge Self-Deploy ==="
|
|
50
|
+
echo "Domain: ${safeDomain}"
|
|
51
|
+
echo ""
|
|
52
|
+
|
|
53
|
+
# 1. System packages
|
|
54
|
+
echo "[1/7] Installing system packages..."
|
|
55
|
+
sudo apt-get update -qq
|
|
56
|
+
sudo apt-get install -y -qq curl git build-essential
|
|
57
|
+
|
|
58
|
+
# 2. Node.js
|
|
59
|
+
echo "[2/7] Installing Node.js ${safeNodeVersion}..."
|
|
60
|
+
if ! command -v node &>/dev/null; then
|
|
61
|
+
curl -fsSL https://deb.nodesource.com/setup_${safeNodeVersion}.x | sudo -E bash -
|
|
62
|
+
sudo apt-get install -y -qq nodejs
|
|
63
|
+
fi
|
|
64
|
+
echo " Node $(node --version)"
|
|
65
|
+
|
|
66
|
+
# 3. PM2 + Caddy
|
|
67
|
+
echo "[3/7] Installing PM2 and Caddy..."
|
|
68
|
+
sudo npm install -g pm2 2>/dev/null || true
|
|
69
|
+
sudo apt-get install -y -qq debian-keyring debian-archive-keyring apt-transport-https
|
|
70
|
+
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg 2>/dev/null || true
|
|
71
|
+
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list >/dev/null
|
|
72
|
+
sudo apt-get update -qq
|
|
73
|
+
sudo apt-get install -y -qq caddy
|
|
74
|
+
|
|
75
|
+
# 4. forge-user (non-root PTY execution)
|
|
76
|
+
echo "[4/7] Creating forge-user..."
|
|
77
|
+
if ! id forge-user &>/dev/null; then
|
|
78
|
+
sudo useradd -m -s /bin/bash forge-user
|
|
79
|
+
fi
|
|
80
|
+
sudo mkdir -p /home/forge-user/projects
|
|
81
|
+
sudo chown -R forge-user:forge-user /home/forge-user
|
|
82
|
+
|
|
83
|
+
# 5. Clone VoidForge
|
|
84
|
+
echo "[5/7] Cloning VoidForge..."
|
|
85
|
+
VOIDFORGE_DIR="/opt/voidforge"
|
|
86
|
+
sudo mkdir -p "$VOIDFORGE_DIR"
|
|
87
|
+
sudo chown $(whoami) "$VOIDFORGE_DIR"
|
|
88
|
+
if [ -d "$VOIDFORGE_DIR/.git" ]; then
|
|
89
|
+
cd "$VOIDFORGE_DIR" && git pull origin ${safeBranch}
|
|
90
|
+
else
|
|
91
|
+
git clone --branch ${safeBranch} ${safeRepo} "$VOIDFORGE_DIR"
|
|
92
|
+
fi
|
|
93
|
+
cd "$VOIDFORGE_DIR" && npm install --production 2>/dev/null || true
|
|
94
|
+
|
|
95
|
+
# 6. Caddy config
|
|
96
|
+
echo "[6/7] Configuring Caddy for ${safeDomain}..."
|
|
97
|
+
sudo tee /etc/caddy/Caddyfile > /dev/null << CADDY
|
|
98
|
+
${config.domain} {
|
|
99
|
+
# Rate limiting on login endpoint
|
|
100
|
+
@login path /api/auth/login
|
|
101
|
+
handle @login {
|
|
102
|
+
reverse_proxy localhost:3141
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
# WebSocket upgrade for terminal
|
|
106
|
+
@ws {
|
|
107
|
+
path /ws/terminal
|
|
108
|
+
header Connection *Upgrade*
|
|
109
|
+
header Upgrade websocket
|
|
110
|
+
}
|
|
111
|
+
handle @ws {
|
|
112
|
+
reverse_proxy localhost:3141
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
# All other traffic
|
|
116
|
+
reverse_proxy localhost:3141
|
|
117
|
+
|
|
118
|
+
# Security headers (supplementing VoidForge's own headers)
|
|
119
|
+
header {
|
|
120
|
+
Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
CADDY
|
|
124
|
+
sudo systemctl reload caddy
|
|
125
|
+
|
|
126
|
+
# 7. Start VoidForge
|
|
127
|
+
echo "[7/7] Starting VoidForge..."
|
|
128
|
+
cd "$VOIDFORGE_DIR"
|
|
129
|
+
pm2 delete voidforge 2>/dev/null || true
|
|
130
|
+
pm2 start "npx tsx scripts/voidforge.ts init --remote" --name voidforge --cwd "$VOIDFORGE_DIR"
|
|
131
|
+
pm2 save
|
|
132
|
+
|
|
133
|
+
echo ""
|
|
134
|
+
echo "═══════════════════════════════════════════"
|
|
135
|
+
echo " VoidForge deployed!"
|
|
136
|
+
echo "═══════════════════════════════════════════"
|
|
137
|
+
echo " URL: https://${config.domain}"
|
|
138
|
+
echo ""
|
|
139
|
+
echo " Open the URL above to create your admin"
|
|
140
|
+
echo " account (username + password + TOTP 2FA)."
|
|
141
|
+
echo "═══════════════════════════════════════════"
|
|
142
|
+
`;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Generate the Caddy config template for manual setup.
|
|
146
|
+
* Used when the user wants to configure Caddy themselves.
|
|
147
|
+
*/
|
|
148
|
+
export function generateCaddyTemplate(domain) {
|
|
149
|
+
return `# VoidForge Avengers Tower Remote — Caddy Configuration
|
|
150
|
+
# Save to /etc/caddy/Caddyfile and run: sudo systemctl reload caddy
|
|
151
|
+
|
|
152
|
+
${domain} {
|
|
153
|
+
# Optional: IP allowlist (uncomment and set your IPs)
|
|
154
|
+
# @blocked not remote_ip <your-ip>/32 <vpn-cidr>/24
|
|
155
|
+
# respond @blocked 403
|
|
156
|
+
|
|
157
|
+
# Rate limiting on login (requires caddy-ratelimit plugin)
|
|
158
|
+
# rate_limit {
|
|
159
|
+
# zone forge_login {
|
|
160
|
+
# key {remote_host}
|
|
161
|
+
# events 5
|
|
162
|
+
# window 1m
|
|
163
|
+
# }
|
|
164
|
+
# }
|
|
165
|
+
|
|
166
|
+
# WebSocket upgrade for terminal connections
|
|
167
|
+
@ws {
|
|
168
|
+
path /ws/terminal
|
|
169
|
+
header Connection *Upgrade*
|
|
170
|
+
header Upgrade websocket
|
|
171
|
+
}
|
|
172
|
+
handle @ws {
|
|
173
|
+
reverse_proxy localhost:3141
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
# All other traffic
|
|
177
|
+
reverse_proxy localhost:3141
|
|
178
|
+
|
|
179
|
+
# HSTS (Caddy auto-provisions TLS certificates)
|
|
180
|
+
header {
|
|
181
|
+
Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
`;
|
|
185
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static S3 provisioner — creates real S3 bucket configured for static hosting + deploy script.
|
|
3
|
+
* Reuses the same AWS credentials as the VPS provisioner.
|
|
4
|
+
*/
|
|
5
|
+
import type { Provisioner } from './types.js';
|
|
6
|
+
export declare const staticS3Provisioner: Provisioner;
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static S3 provisioner — creates real S3 bucket configured for static hosting + deploy script.
|
|
3
|
+
* Reuses the same AWS credentials as the VPS provisioner.
|
|
4
|
+
*/
|
|
5
|
+
import { writeFile, mkdir } from 'node:fs/promises';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { recordResourcePending, recordResourceCreated } from '../provision-manifest.js';
|
|
8
|
+
import { slugify } from './http-client.js';
|
|
9
|
+
import { appendEnvSection } from '../env-writer.js';
|
|
10
|
+
export const staticS3Provisioner = {
|
|
11
|
+
async validate(ctx) {
|
|
12
|
+
const errors = [];
|
|
13
|
+
if (!ctx.projectDir)
|
|
14
|
+
errors.push('Project directory is required');
|
|
15
|
+
if (!ctx.credentials['aws-access-key-id'])
|
|
16
|
+
errors.push('AWS Access Key ID is required');
|
|
17
|
+
if (!ctx.credentials['aws-secret-access-key'])
|
|
18
|
+
errors.push('AWS Secret Access Key is required');
|
|
19
|
+
return errors;
|
|
20
|
+
},
|
|
21
|
+
async provision(ctx, emit) {
|
|
22
|
+
const files = [];
|
|
23
|
+
const resources = [];
|
|
24
|
+
const outputs = {};
|
|
25
|
+
const region = ctx.credentials['aws-region'] || 'us-east-1';
|
|
26
|
+
const slug = slugify(ctx.projectName);
|
|
27
|
+
const bucketName = `${slug}-site`;
|
|
28
|
+
// Dynamic import of AWS SDK
|
|
29
|
+
let S3Client;
|
|
30
|
+
let s3Commands;
|
|
31
|
+
let STSClient;
|
|
32
|
+
let GetCallerIdentityCommand;
|
|
33
|
+
try {
|
|
34
|
+
const s3Mod = await import('@aws-sdk/client-s3');
|
|
35
|
+
const stsMod = await import('@aws-sdk/client-sts');
|
|
36
|
+
S3Client = s3Mod.S3Client;
|
|
37
|
+
s3Commands = s3Mod;
|
|
38
|
+
STSClient = stsMod.STSClient;
|
|
39
|
+
GetCallerIdentityCommand = stsMod.GetCallerIdentityCommand;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return {
|
|
43
|
+
success: false, resources, outputs, files,
|
|
44
|
+
error: 'AWS SDK not installed. Run: npm install @aws-sdk/client-s3 @aws-sdk/client-sts',
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const awsConfig = {
|
|
48
|
+
region,
|
|
49
|
+
credentials: {
|
|
50
|
+
accessKeyId: ctx.credentials['aws-access-key-id'],
|
|
51
|
+
secretAccessKey: ctx.credentials['aws-secret-access-key'],
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
const s3 = new S3Client(awsConfig);
|
|
55
|
+
const sts = new STSClient(awsConfig);
|
|
56
|
+
// Step 1: Validate credentials
|
|
57
|
+
emit({ step: 'validate-creds', status: 'started', message: 'Validating AWS credentials' });
|
|
58
|
+
try {
|
|
59
|
+
const identity = await sts.send(new GetCallerIdentityCommand({}));
|
|
60
|
+
emit({ step: 'validate-creds', status: 'done', message: `Authenticated as ${identity.Arn}` });
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
emit({ step: 'validate-creds', status: 'error', message: 'Invalid AWS credentials', detail: err.message });
|
|
64
|
+
return { success: false, resources, outputs, files, error: 'AWS credential validation failed' };
|
|
65
|
+
}
|
|
66
|
+
// Step 2: Create S3 bucket
|
|
67
|
+
emit({ step: 's3-bucket', status: 'started', message: `Creating S3 bucket "${bucketName}"` });
|
|
68
|
+
try {
|
|
69
|
+
await recordResourcePending(ctx.runId, 's3-bucket', bucketName, region);
|
|
70
|
+
// us-east-1 doesn't accept LocationConstraint
|
|
71
|
+
const createInput = { Bucket: bucketName };
|
|
72
|
+
if (region !== 'us-east-1') {
|
|
73
|
+
createInput.CreateBucketConfiguration = {
|
|
74
|
+
LocationConstraint: region, // Cast to enum — SDK accepts any valid region string at runtime
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
await s3.send(new s3Commands.CreateBucketCommand(createInput));
|
|
78
|
+
resources.push({ type: 's3-bucket', id: bucketName, region });
|
|
79
|
+
await recordResourceCreated(ctx.runId, 's3-bucket', bucketName, region);
|
|
80
|
+
emit({ step: 's3-bucket', status: 'done', message: `Bucket "${bucketName}" created` });
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
const msg = err.message || '';
|
|
84
|
+
if (msg.includes('BucketAlreadyOwnedByYou')) {
|
|
85
|
+
emit({ step: 's3-bucket', status: 'done', message: `Bucket "${bucketName}" already exists — using it` });
|
|
86
|
+
resources.push({ type: 's3-bucket', id: bucketName, region });
|
|
87
|
+
await recordResourceCreated(ctx.runId, 's3-bucket', bucketName, region);
|
|
88
|
+
}
|
|
89
|
+
else if (msg.includes('BucketAlreadyExists')) {
|
|
90
|
+
emit({ step: 's3-bucket', status: 'error', message: `Bucket name "${bucketName}" is taken by another AWS account`, detail: 'Use a more unique project name to generate a different bucket name' });
|
|
91
|
+
return { success: false, resources, outputs, files, error: `S3 bucket name "${bucketName}" is globally taken` };
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
emit({ step: 's3-bucket', status: 'error', message: 'Failed to create S3 bucket', detail: msg });
|
|
95
|
+
return { success: false, resources, outputs, files, error: msg };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Step 3: Configure bucket for static website hosting
|
|
99
|
+
emit({ step: 's3-website', status: 'started', message: 'Configuring static website hosting' });
|
|
100
|
+
try {
|
|
101
|
+
await s3.send(new s3Commands.PutBucketWebsiteCommand({
|
|
102
|
+
Bucket: bucketName,
|
|
103
|
+
WebsiteConfiguration: {
|
|
104
|
+
IndexDocument: { Suffix: 'index.html' },
|
|
105
|
+
ErrorDocument: { Key: 'index.html' }, // SPA fallback
|
|
106
|
+
},
|
|
107
|
+
}));
|
|
108
|
+
// Set public access policy
|
|
109
|
+
await s3.send(new s3Commands.DeletePublicAccessBlockCommand({ Bucket: bucketName }));
|
|
110
|
+
await s3.send(new s3Commands.PutBucketPolicyCommand({
|
|
111
|
+
Bucket: bucketName,
|
|
112
|
+
Policy: JSON.stringify({
|
|
113
|
+
Version: '2012-10-17',
|
|
114
|
+
Statement: [{
|
|
115
|
+
Sid: 'PublicReadGetObject',
|
|
116
|
+
Effect: 'Allow',
|
|
117
|
+
Principal: '*',
|
|
118
|
+
Action: 's3:GetObject',
|
|
119
|
+
Resource: `arn:aws:s3:::${bucketName}/*`,
|
|
120
|
+
}],
|
|
121
|
+
}),
|
|
122
|
+
}));
|
|
123
|
+
const websiteUrl = region === 'us-east-1'
|
|
124
|
+
? `http://${bucketName}.s3-website-${region}.amazonaws.com`
|
|
125
|
+
: `http://${bucketName}.s3-website.${region}.amazonaws.com`;
|
|
126
|
+
outputs['S3_BUCKET'] = bucketName;
|
|
127
|
+
outputs['S3_WEBSITE_URL'] = websiteUrl;
|
|
128
|
+
emit({ step: 's3-website', status: 'done', message: `Static hosting enabled — ${websiteUrl}` });
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
emit({ step: 's3-website', status: 'error', message: 'Failed to configure website hosting', detail: err.message });
|
|
132
|
+
// Non-fatal — bucket exists, user can configure manually
|
|
133
|
+
}
|
|
134
|
+
// Step 4: Generate deploy script
|
|
135
|
+
emit({ step: 's3-script', status: 'started', message: 'Generating deploy script' });
|
|
136
|
+
try {
|
|
137
|
+
const infraDir = join(ctx.projectDir, 'infra');
|
|
138
|
+
await mkdir(infraDir, { recursive: true });
|
|
139
|
+
const deployScript = `#!/usr/bin/env bash
|
|
140
|
+
# deploy-s3.sh — Deploy static site to S3
|
|
141
|
+
# Generated by VoidForge
|
|
142
|
+
set -euo pipefail
|
|
143
|
+
|
|
144
|
+
BUCKET="\${S3_BUCKET:-${bucketName}}"
|
|
145
|
+
BUILD_DIR="\${BUILD_DIR:-dist}"
|
|
146
|
+
|
|
147
|
+
echo "=== Deploying to S3 bucket: $BUCKET ==="
|
|
148
|
+
|
|
149
|
+
# Sync build output to S3
|
|
150
|
+
aws s3 sync "$BUILD_DIR" "s3://$BUCKET" \\
|
|
151
|
+
--delete \\
|
|
152
|
+
--cache-control "public, max-age=31536000, immutable" \\
|
|
153
|
+
--exclude "*.html" \\
|
|
154
|
+
--exclude "sw.js" \\
|
|
155
|
+
--exclude "manifest.json"
|
|
156
|
+
|
|
157
|
+
# HTML and service worker files with short cache
|
|
158
|
+
aws s3 sync "$BUILD_DIR" "s3://$BUCKET" \\
|
|
159
|
+
--cache-control "public, max-age=0, must-revalidate" \\
|
|
160
|
+
--exclude '*' \\
|
|
161
|
+
--include "*.html" \\
|
|
162
|
+
--include "sw.js" \\
|
|
163
|
+
--include "manifest.json"
|
|
164
|
+
|
|
165
|
+
echo ""
|
|
166
|
+
echo "=== Deploy complete ==="
|
|
167
|
+
echo "Site: ${outputs['S3_WEBSITE_URL'] || `http://$BUCKET.s3-website.amazonaws.com`}"
|
|
168
|
+
`;
|
|
169
|
+
await writeFile(join(infraDir, 'deploy-s3.sh'), deployScript, { mode: 0o755 });
|
|
170
|
+
files.push('infra/deploy-s3.sh');
|
|
171
|
+
emit({ step: 's3-script', status: 'done', message: 'Generated infra/deploy-s3.sh' });
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
emit({ step: 's3-script', status: 'error', message: 'Failed to generate deploy script', detail: err.message });
|
|
175
|
+
}
|
|
176
|
+
// Step 5: Write .env
|
|
177
|
+
emit({ step: 's3-env', status: 'started', message: 'Writing S3 config to .env' });
|
|
178
|
+
try {
|
|
179
|
+
const envLines = [
|
|
180
|
+
`# VoidForge Static S3 — generated ${new Date().toISOString()}`,
|
|
181
|
+
`S3_BUCKET=${bucketName}`,
|
|
182
|
+
];
|
|
183
|
+
if (outputs['S3_WEBSITE_URL'])
|
|
184
|
+
envLines.push(`S3_WEBSITE_URL=${outputs['S3_WEBSITE_URL']}`);
|
|
185
|
+
envLines.push('# Deploy with: ./infra/deploy-s3.sh (or auto-deploys via Haku wizard)');
|
|
186
|
+
await appendEnvSection(ctx.projectDir, envLines);
|
|
187
|
+
emit({ step: 's3-env', status: 'done', message: 'S3 config written to .env' });
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
emit({ step: 's3-env', status: 'error', message: 'Failed to write .env', detail: err.message });
|
|
191
|
+
}
|
|
192
|
+
return { success: true, resources, outputs, files };
|
|
193
|
+
},
|
|
194
|
+
async cleanup(resources, credentials) {
|
|
195
|
+
if (resources.length === 0)
|
|
196
|
+
return;
|
|
197
|
+
const region = resources[0].region;
|
|
198
|
+
const awsConfig = {
|
|
199
|
+
region,
|
|
200
|
+
credentials: {
|
|
201
|
+
accessKeyId: credentials['aws-access-key-id'] ?? '',
|
|
202
|
+
secretAccessKey: credentials['aws-secret-access-key'] ?? '',
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
for (const resource of [...resources].reverse()) {
|
|
206
|
+
if (resource.type === 's3-bucket') {
|
|
207
|
+
try {
|
|
208
|
+
const { S3Client, DeleteBucketCommand, ListObjectsV2Command, DeleteObjectsCommand } = await import('@aws-sdk/client-s3');
|
|
209
|
+
const s3 = new S3Client(awsConfig);
|
|
210
|
+
// Must empty bucket before deleting — paginate to handle >1000 objects
|
|
211
|
+
let continuationToken;
|
|
212
|
+
do {
|
|
213
|
+
const listRes = await s3.send(new ListObjectsV2Command({
|
|
214
|
+
Bucket: resource.id,
|
|
215
|
+
ContinuationToken: continuationToken,
|
|
216
|
+
}));
|
|
217
|
+
if (listRes.Contents && listRes.Contents.length > 0) {
|
|
218
|
+
await s3.send(new DeleteObjectsCommand({
|
|
219
|
+
Bucket: resource.id,
|
|
220
|
+
Delete: {
|
|
221
|
+
Objects: listRes.Contents.map((obj) => ({ Key: obj.Key })),
|
|
222
|
+
},
|
|
223
|
+
}));
|
|
224
|
+
}
|
|
225
|
+
continuationToken = listRes.IsTruncated ? listRes.NextContinuationToken : undefined;
|
|
226
|
+
} while (continuationToken);
|
|
227
|
+
await s3.send(new DeleteBucketCommand({ Bucket: resource.id }));
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
console.error(`Failed to cleanup S3 bucket ${resource.id}:`, err.message);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provisioner interfaces — shared across all deploy targets.
|
|
3
|
+
*/
|
|
4
|
+
export interface ProvisionContext {
|
|
5
|
+
runId: string;
|
|
6
|
+
projectDir: string;
|
|
7
|
+
projectName: string;
|
|
8
|
+
deployTarget: string;
|
|
9
|
+
framework: string;
|
|
10
|
+
database: string;
|
|
11
|
+
cache: string;
|
|
12
|
+
instanceType: string;
|
|
13
|
+
hostname: string;
|
|
14
|
+
credentials: Record<string, string>;
|
|
15
|
+
abortSignal?: AbortSignal;
|
|
16
|
+
}
|
|
17
|
+
export interface ProvisionEvent {
|
|
18
|
+
step: string;
|
|
19
|
+
status: 'started' | 'done' | 'error' | 'skipped' | 'warning';
|
|
20
|
+
message: string;
|
|
21
|
+
detail?: string;
|
|
22
|
+
}
|
|
23
|
+
export type ProvisionEmitter = (event: ProvisionEvent) => void;
|
|
24
|
+
export interface CreatedResource {
|
|
25
|
+
type: string;
|
|
26
|
+
id: string;
|
|
27
|
+
region: string;
|
|
28
|
+
}
|
|
29
|
+
export interface ProvisionResult {
|
|
30
|
+
success: boolean;
|
|
31
|
+
resources: CreatedResource[];
|
|
32
|
+
outputs: Record<string, string>;
|
|
33
|
+
files: string[];
|
|
34
|
+
error?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface Provisioner {
|
|
37
|
+
validate(ctx: ProvisionContext): Promise<string[]>;
|
|
38
|
+
provision(ctx: ProvisionContext, emit: ProvisionEmitter): Promise<ProvisionResult>;
|
|
39
|
+
cleanup(resources: CreatedResource[], credentials: Record<string, string>): Promise<void>;
|
|
40
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vercel provisioner — creates a real Vercel project via API + generates vercel.json.
|
|
3
|
+
* v3.8.0: Links GitHub repo, sets env vars, polls deploy (ADR-015).
|
|
4
|
+
*/
|
|
5
|
+
import type { Provisioner } from './types.js';
|
|
6
|
+
export declare const vercelProvisioner: Provisioner;
|