@caelo-cms/provisioning 0.1.1 → 0.2.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.
Files changed (65) hide show
  1. package/dist/cli.js +92 -7
  2. package/dist/cli.js.map +1 -1
  3. package/dist/compose.d.ts +7 -0
  4. package/dist/compose.d.ts.map +1 -1
  5. package/dist/compose.js +10 -9
  6. package/dist/compose.js.map +1 -1
  7. package/dist/dns/cloudflare.d.ts +9 -0
  8. package/dist/dns/cloudflare.d.ts.map +1 -0
  9. package/dist/dns/cloudflare.js +160 -0
  10. package/dist/dns/cloudflare.js.map +1 -0
  11. package/dist/dns/index.d.ts +12 -0
  12. package/dist/dns/index.d.ts.map +1 -0
  13. package/dist/dns/index.js +42 -0
  14. package/dist/dns/index.js.map +1 -0
  15. package/dist/dns/manual.d.ts +5 -0
  16. package/dist/dns/manual.d.ts.map +1 -0
  17. package/dist/dns/manual.js +96 -0
  18. package/dist/dns/manual.js.map +1 -0
  19. package/dist/dns/types.d.ts +23 -0
  20. package/dist/dns/types.d.ts.map +1 -0
  21. package/dist/dns/types.js +3 -0
  22. package/dist/dns/types.js.map +1 -0
  23. package/dist/gcloud.d.ts +42 -0
  24. package/dist/gcloud.d.ts.map +1 -0
  25. package/dist/gcloud.js +187 -0
  26. package/dist/gcloud.js.map +1 -0
  27. package/dist/install-state.d.ts +54 -0
  28. package/dist/install-state.d.ts.map +1 -0
  29. package/dist/install-state.js +118 -0
  30. package/dist/install-state.js.map +1 -0
  31. package/dist/lifecycle.d.ts +19 -0
  32. package/dist/lifecycle.d.ts.map +1 -0
  33. package/dist/lifecycle.js +589 -0
  34. package/dist/lifecycle.js.map +1 -0
  35. package/dist/migration-runner.d.ts +15 -0
  36. package/dist/migration-runner.d.ts.map +1 -0
  37. package/dist/migration-runner.js +174 -0
  38. package/dist/migration-runner.js.map +1 -0
  39. package/dist/redirects-emit.d.ts.map +1 -1
  40. package/dist/redirects-emit.js +4 -1
  41. package/dist/redirects-emit.js.map +1 -1
  42. package/dist/wizard.d.ts +35 -0
  43. package/dist/wizard.d.ts.map +1 -0
  44. package/dist/wizard.js +160 -0
  45. package/dist/wizard.js.map +1 -0
  46. package/dist/wizards/gcp-cost.d.ts +27 -0
  47. package/dist/wizards/gcp-cost.d.ts.map +1 -0
  48. package/dist/wizards/gcp-cost.js +77 -0
  49. package/dist/wizards/gcp-cost.js.map +1 -0
  50. package/dist/wizards/gcp-pulumi.d.ts +37 -0
  51. package/dist/wizards/gcp-pulumi.d.ts.map +1 -0
  52. package/dist/wizards/gcp-pulumi.js +100 -0
  53. package/dist/wizards/gcp-pulumi.js.map +1 -0
  54. package/dist/wizards/gcp.d.ts +9 -0
  55. package/dist/wizards/gcp.d.ts.map +1 -0
  56. package/dist/wizards/gcp.js +895 -0
  57. package/dist/wizards/gcp.js.map +1 -0
  58. package/package.json +13 -2
  59. package/stacks/aws/index.ts +6 -7
  60. package/stacks/azure/index.ts +11 -11
  61. package/stacks/gcp/Pulumi.production.yaml +16 -0
  62. package/stacks/gcp/Pulumi.yaml +52 -6
  63. package/stacks/gcp/index.ts +569 -188
  64. package/stacks/self-hosted/index.ts +3 -3
  65. package/static/welcome.html +155 -0
@@ -0,0 +1,174 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ /**
3
+ * P21 ship 3 — shared migration runner. Used by both the GCP wizard
4
+ * (apps/admin/scripts/wizards/gcp.ts) AND the lifecycle `upgrade`
5
+ * command (lifecycle.ts).
6
+ *
7
+ * Spawns a one-shot Cloud Run Job that invokes
8
+ * `bun /app/packages/migrations/src/migrate.ts <target>` against the
9
+ * private-IP Cloud SQL instance. The job inherits the running admin
10
+ * Cloud Run's image (so it always carries the matching migration set)
11
+ * + its DB URLs + its network/subnet.
12
+ *
13
+ * Idempotent: drizzle's `__drizzle_migrations` table tracks applied
14
+ * versions, so re-runs only apply NEW migrations. Returns `{ok}` so
15
+ * callers (especially `upgrade`) can abort cleanly when a migration
16
+ * fails BEFORE traffic shifts to the new revision.
17
+ */
18
+ import { spinner } from "@clack/prompts";
19
+ import { green, red } from "kleur/colors";
20
+ import { gcloud } from "./gcloud.js";
21
+ /**
22
+ * Resolve the running admin Cloud Run service's image + DB URLs +
23
+ * VPC config. Returns null on any failure; caller surfaces the error.
24
+ */
25
+ async function readAdminConfig(opts) {
26
+ // Find the actual deployed service name (Pulumi appends a 7-char
27
+ // suffix; hardcoding the bare name 404s).
28
+ const list = await gcloud([
29
+ "run",
30
+ "services",
31
+ "list",
32
+ "--region",
33
+ opts.region,
34
+ "--project",
35
+ opts.projectId,
36
+ "--filter",
37
+ "metadata.name~^caelo-production-admin",
38
+ "--format=value(metadata.name)",
39
+ ]);
40
+ if (!list.ok)
41
+ return null;
42
+ const serviceName = list.stdout.trim().split("\n")[0]?.trim();
43
+ if (!serviceName)
44
+ return null;
45
+ const descr = await gcloud([
46
+ "run",
47
+ "services",
48
+ "describe",
49
+ serviceName,
50
+ "--region",
51
+ opts.region,
52
+ "--project",
53
+ opts.projectId,
54
+ "--format=json",
55
+ ]);
56
+ if (!descr.ok)
57
+ return null;
58
+ try {
59
+ const d = JSON.parse(descr.stdout);
60
+ const c = d.spec.template.spec.containers[0];
61
+ const imageRef = c?.image ?? "";
62
+ let adminUrl = "";
63
+ let publicUrl = "";
64
+ for (const e of c?.env ?? []) {
65
+ if (e.name === "ADMIN_DATABASE_URL")
66
+ adminUrl = e.value ?? "";
67
+ if (e.name === "PUBLIC_ADMIN_DATABASE_URL")
68
+ publicUrl = e.value ?? "";
69
+ }
70
+ let networkRef = "";
71
+ let subnetRef = "";
72
+ const niAnnotation = d.spec.template.metadata?.annotations?.["run.googleapis.com/network-interfaces"];
73
+ if (niAnnotation) {
74
+ try {
75
+ const parsed = JSON.parse(niAnnotation);
76
+ networkRef = parsed[0]?.network ?? "";
77
+ subnetRef = parsed[0]?.subnetwork ?? "";
78
+ }
79
+ catch {
80
+ // fall through
81
+ }
82
+ }
83
+ if (!networkRef || !subnetRef) {
84
+ const ni = d.spec.template.spec.vpcAccess?.networkInterfaces?.[0];
85
+ networkRef ||= ni?.network ?? "";
86
+ subnetRef ||= ni?.subnetwork ?? "";
87
+ }
88
+ if (!imageRef || !adminUrl || !publicUrl || !networkRef || !subnetRef)
89
+ return null;
90
+ return { imageRef, adminUrl, publicUrl, networkRef, subnetRef };
91
+ }
92
+ catch {
93
+ return null;
94
+ }
95
+ }
96
+ /**
97
+ * Run admin + public migrations against Cloud SQL. Returns `{ok}` so
98
+ * callers can decide what to do on failure (the wizard exits the
99
+ * process; upgrade aborts before rolling Cloud Run).
100
+ */
101
+ export async function runMigrationsViaCloudRunJob(opts) {
102
+ const sAdmin = spinner();
103
+ sAdmin.start("Reading admin Cloud Run config for migration job...");
104
+ const cfg = await readAdminConfig(opts);
105
+ if (!cfg) {
106
+ sAdmin.stop(red("Couldn't resolve admin config — admin may not be deployed yet"));
107
+ return { ok: false, error: "admin-config-unresolved" };
108
+ }
109
+ sAdmin.stop(green(`Admin config resolved (${cfg.imageRef.slice(-19)})`));
110
+ for (const target of ["admin", "public"]) {
111
+ const s = spinner();
112
+ s.start(`Applying ${target} migrations via one-shot Cloud Run Job...`);
113
+ // Delete-then-create so each invocation runs with the freshest
114
+ // image + env (no stale job specs).
115
+ await gcloud([
116
+ "run",
117
+ "jobs",
118
+ "delete",
119
+ `caelo-migrate-${target}`,
120
+ "--region",
121
+ opts.region,
122
+ "--project",
123
+ opts.projectId,
124
+ "--quiet",
125
+ ]);
126
+ const create = await gcloud([
127
+ "run",
128
+ "jobs",
129
+ "create",
130
+ `caelo-migrate-${target}`,
131
+ `--image=${cfg.imageRef}`,
132
+ "--region",
133
+ opts.region,
134
+ "--project",
135
+ opts.projectId,
136
+ "--service-account",
137
+ `caelo-production-run-sa@${opts.projectId}.iam.gserviceaccount.com`,
138
+ "--network",
139
+ cfg.networkRef.split("/").pop() ?? cfg.networkRef,
140
+ "--subnet",
141
+ cfg.subnetRef.split("/").pop() ?? cfg.subnetRef,
142
+ "--vpc-egress=private-ranges-only",
143
+ "--command=bun",
144
+ `--args=--bun,/app/packages/migrations/src/migrate.ts,${target}`,
145
+ "--set-env-vars",
146
+ `ADMIN_DATABASE_URL=${cfg.adminUrl},PUBLIC_ADMIN_DATABASE_URL=${cfg.publicUrl}`,
147
+ "--max-retries=0",
148
+ "--task-timeout=10m",
149
+ "--quiet",
150
+ ]);
151
+ if (!create.ok) {
152
+ s.stop(red(`Job create failed: ${create.stderr.trim()}`));
153
+ return { ok: false, error: `migrate-${target}-create: ${create.stderr.trim()}` };
154
+ }
155
+ const exec = await gcloud([
156
+ "run",
157
+ "jobs",
158
+ "execute",
159
+ `caelo-migrate-${target}`,
160
+ "--region",
161
+ opts.region,
162
+ "--project",
163
+ opts.projectId,
164
+ "--wait",
165
+ ]);
166
+ if (!exec.ok) {
167
+ s.stop(red(`${target} migrations failed: ${exec.stderr.trim()}`));
168
+ return { ok: false, error: `migrate-${target}-exec: ${exec.stderr.trim()}` };
169
+ }
170
+ s.stop(green(`${target} migrations applied`));
171
+ }
172
+ return { ok: true };
173
+ }
174
+ //# sourceMappingURL=migration-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-runner.js","sourceRoot":"","sources":["../src/migration-runner.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"redirects-emit.d.ts","sourceRoot":"","sources":["../src/redirects-emit.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,kBAAkB,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAEvD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;CACzC;AA0BD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,MAAM,CAKhF;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,aAAa,CAAC,WAAW,CAAC,GAC/B,0BAA0B,CAwB5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;QACjC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;QAC5B,QAAQ,CAAC,UAAU,EAAE;YACnB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;YAC3B,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;SAC7C,CAAC;KACH,CAAC,CAAC;IACH,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;QAC9B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;QAC7B,QAAQ,CAAC,UAAU,EAAE;YACnB,QAAQ,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,GAAG,mBAAmB,GAAG,mBAAmB,CAAC;YACrF,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;SAClC,CAAC;KACH,CAAC,CAAC;CACJ;AAED,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,aAAa,CAAC,WAAW,CAAC,GAC/B,aAAa,CAAC,aAAa,CAAC,CAqB9B"}
1
+ {"version":3,"file":"redirects-emit.d.ts","sourceRoot":"","sources":["../src/redirects-emit.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,kBAAkB,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAEvD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;CACzC;AA6BD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,MAAM,CAKhF;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,aAAa,CAAC,WAAW,CAAC,GAC/B,0BAA0B,CAwB5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;QACjC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;QAC5B,QAAQ,CAAC,UAAU,EAAE;YACnB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;YAC3B,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;SAC7C,CAAC;KACH,CAAC,CAAC;IACH,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;QAC9B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;QAC7B,QAAQ,CAAC,UAAU,EAAE;YACnB,QAAQ,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,GAAG,mBAAmB,GAAG,mBAAmB,CAAC;YACrF,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;SAClC,CAAC;KACH,CAAC,CAAC;CACJ;AAED,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,aAAa,CAAC,WAAW,CAAC,GAC/B,aAAa,CAAC,aAAa,CAAC,CAqB9B"}
@@ -9,7 +9,10 @@
9
9
  * defend their own contract.
10
10
  */
11
11
  function assertPathClean(label, path) {
12
- if (/[\s\x00-\x1f]/.test(path)) {
12
+ // \p{Cc} matches the Unicode control category (U+0000–U+001F + U+007F–U+009F);
13
+ // the linter rejects literal \x00-\x1f ranges in regex, but the intent — defending
14
+ // emitter contracts against control chars — is the explicit reason for this check.
15
+ if (/[\s\p{Cc}]/u.test(path)) {
13
16
  throw new Error(`redirects-emit: ${label}=${JSON.stringify(path)} contains whitespace or control chars; reject upstream`);
14
17
  }
15
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"redirects-emit.js","sourceRoot":"","sources":["../src/redirects-emit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"redirects-emit.js","sourceRoot":"","sources":["../src/redirects-emit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * `bunx @caelo-cms/provisioning` — interactive wizard.
3
+ *
4
+ * Per CLAUDE.md §11.C, this is the primary surface OSS users interact
5
+ * with: one command, end-to-end, < 20 min, on the user's own cloud.
6
+ *
7
+ * Top-level shape:
8
+ * 1. Pick provider (gcp / aws / azure / self-hosted)
9
+ * 2. Detect existing install at `~/.caelo-<id>/` and offer to resume
10
+ * 3. Prompt for the few inputs the provider needs (domain, owner email,
11
+ * project id, Anthropic key — input-hidden)
12
+ * 4. Show cost estimate + final confirm
13
+ * 5. Delegate to the provider-specific wizard which handles project
14
+ * bootstrap → Pulumi up → DNS → cert → IAP enable → bootstrap URL
15
+ *
16
+ * Each provider wizard is a separate file under `wizards/<provider>.ts`
17
+ * so adding a new provider is one new file, not a sprawling switch.
18
+ */
19
+ import { spinner } from "@clack/prompts";
20
+ import { type Provider } from "./install-state.js";
21
+ export interface WizardOptions {
22
+ /** Skip prompts; require all inputs via flags. CI-friendly. */
23
+ nonInteractive?: boolean;
24
+ /** Pre-supplied provider — skips the picker. */
25
+ provider?: Provider;
26
+ /** Pre-supplied domain — skips the prompt. */
27
+ domain?: string;
28
+ /** Pre-supplied owner email — skips the prompt. */
29
+ ownerEmail?: string;
30
+ /** Pre-supplied GCP project id — skips the prompt for gcp. */
31
+ projectId?: string;
32
+ }
33
+ export declare function runWizard(opts?: WizardOptions): Promise<void>;
34
+ export { spinner };
35
+ //# sourceMappingURL=wizard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wizard.d.ts","sourceRoot":"","sources":["../src/wizard.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAmD,OAAO,EAAQ,MAAM,gBAAgB,CAAC;AAEhG,OAAO,EAGL,KAAK,QAAQ,EAGd,MAAM,oBAAoB,CAAC;AAG5B,MAAM,WAAW,aAAa;IAC5B,+DAA+D;IAC/D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,SAAS,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyEvE;AA0ED,OAAO,EAAE,OAAO,EAAE,CAAC"}
package/dist/wizard.js ADDED
@@ -0,0 +1,160 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ /**
3
+ * `bunx @caelo-cms/provisioning` — interactive wizard.
4
+ *
5
+ * Per CLAUDE.md §11.C, this is the primary surface OSS users interact
6
+ * with: one command, end-to-end, < 20 min, on the user's own cloud.
7
+ *
8
+ * Top-level shape:
9
+ * 1. Pick provider (gcp / aws / azure / self-hosted)
10
+ * 2. Detect existing install at `~/.caelo-<id>/` and offer to resume
11
+ * 3. Prompt for the few inputs the provider needs (domain, owner email,
12
+ * project id, Anthropic key — input-hidden)
13
+ * 4. Show cost estimate + final confirm
14
+ * 5. Delegate to the provider-specific wizard which handles project
15
+ * bootstrap → Pulumi up → DNS → cert → IAP enable → bootstrap URL
16
+ *
17
+ * Each provider wizard is a separate file under `wizards/<provider>.ts`
18
+ * so adding a new provider is one new file, not a sprawling switch.
19
+ */
20
+ import { cancel, confirm, intro, isCancel, outro, select, spinner, text } from "@clack/prompts";
21
+ import { bold, cyan, dim } from "kleur/colors";
22
+ import { deriveInstallId, ensureInstallDir, readMetadata, writeMetadata, } from "./install-state.js";
23
+ import { runGcpWizard } from "./wizards/gcp.js";
24
+ export async function runWizard(opts = {}) {
25
+ intro(bold(cyan("Caelo CMS provisioner")) + dim(" — one-command deploy"));
26
+ // 1. Provider — pre-supplied via flag OR picker.
27
+ const provider = opts.provider ?? (await pickProvider());
28
+ // 2. Common inputs the provider wizard always needs. Provider-specific
29
+ // inputs (GCP project id, AWS region, etc.) are prompted inside the
30
+ // per-provider wizard.
31
+ const domain = opts.domain ?? (await promptDomain());
32
+ const ownerEmail = opts.ownerEmail ?? (await promptOwnerEmail());
33
+ // 3. Per-install state directory + resume detection. The install id is
34
+ // derived from (provider, projectId-or-domain) so re-runs land here.
35
+ // For GCP we don't have the project id yet (it's the next prompt);
36
+ // use domain as the seed, then rewrite metadata once project id is
37
+ // set in the GCP wizard.
38
+ const installId = deriveInstallId(provider, opts.projectId ?? domain);
39
+ ensureInstallDir(installId);
40
+ const existing = readMetadata(installId);
41
+ if (existing && !opts.nonInteractive) {
42
+ const resume = await confirm({
43
+ message: `Existing install '${installId}' detected (created ${dim(existing.createdAt)}). Resume?`,
44
+ initialValue: true,
45
+ });
46
+ if (isCancel(resume)) {
47
+ cancel("Cancelled.");
48
+ process.exit(0);
49
+ }
50
+ if (!resume) {
51
+ cancel(`Aborted. Run with a different domain or remove ~/.caelo-${installId}/ first.`);
52
+ process.exit(0);
53
+ }
54
+ }
55
+ else {
56
+ writeMetadata(installId, {
57
+ installId,
58
+ provider,
59
+ projectId: opts.projectId ?? null,
60
+ domain,
61
+ ownerEmail,
62
+ region: null,
63
+ createdAt: new Date().toISOString(),
64
+ });
65
+ }
66
+ // 4. Delegate to the provider-specific wizard.
67
+ switch (provider) {
68
+ case "gcp":
69
+ await runGcpWizard({
70
+ installId,
71
+ domain,
72
+ ownerEmail,
73
+ projectId: opts.projectId ?? null,
74
+ nonInteractive: opts.nonInteractive ?? false,
75
+ });
76
+ break;
77
+ case "self-hosted":
78
+ cancel("Self-hosted wizard is the existing `cms-provision init` flow. Run `bunx @caelo-cms/provisioning init --domain ... --owner-email ...` for now; wizard polish lands in a follow-up commit.");
79
+ process.exit(0);
80
+ break;
81
+ case "aws":
82
+ case "azure":
83
+ cancel(`${provider.toUpperCase()} provider wizard not yet implemented. GCP is the first cloud target; AWS + Azure follow the same shape and land in upcoming commits.`);
84
+ process.exit(0);
85
+ break;
86
+ }
87
+ outro(bold("Done. Welcome to Caelo CMS."));
88
+ }
89
+ async function pickProvider() {
90
+ const choice = await select({
91
+ message: "Where do you want to deploy?",
92
+ options: [
93
+ {
94
+ value: "gcp",
95
+ label: "Google Cloud Platform",
96
+ hint: "Cloud Run + Cloud SQL + Cloud Storage + Cloud CDN. Default for v0.1.",
97
+ },
98
+ {
99
+ value: "self-hosted",
100
+ label: "Self-hosted (Docker Compose)",
101
+ hint: "Single Linux box. Postgres + Caddy + the admin + the gateway.",
102
+ },
103
+ {
104
+ value: "aws",
105
+ label: "Amazon Web Services",
106
+ hint: "Lambda + RDS + S3 + CloudFront. Lands in a follow-up commit.",
107
+ },
108
+ {
109
+ value: "azure",
110
+ label: "Microsoft Azure",
111
+ hint: "Container Apps + Azure DB + Blob + Front Door. Lands in a follow-up commit.",
112
+ },
113
+ ],
114
+ });
115
+ if (isCancel(choice)) {
116
+ cancel("Cancelled.");
117
+ process.exit(0);
118
+ }
119
+ return choice;
120
+ }
121
+ async function promptDomain() {
122
+ const value = await text({
123
+ message: "Domain you'd like to use",
124
+ placeholder: "mysite.com",
125
+ validate: (v) => {
126
+ if (!v || v.length === 0)
127
+ return "Domain is required";
128
+ if (!/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)+$/.test(v)) {
129
+ return "Looks like an invalid domain (e.g. mysite.com)";
130
+ }
131
+ return undefined;
132
+ },
133
+ });
134
+ if (isCancel(value)) {
135
+ cancel("Cancelled.");
136
+ process.exit(0);
137
+ }
138
+ return value;
139
+ }
140
+ async function promptOwnerEmail() {
141
+ const value = await text({
142
+ message: "Owner email (you'll be the IAP allowlisted Owner; can add more later)",
143
+ placeholder: "you@example.com",
144
+ validate: (v) => {
145
+ if (!v || v.length === 0)
146
+ return "Email is required";
147
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v))
148
+ return "Looks like an invalid email";
149
+ return undefined;
150
+ },
151
+ });
152
+ if (isCancel(value)) {
153
+ cancel("Cancelled.");
154
+ process.exit(0);
155
+ }
156
+ return value;
157
+ }
158
+ // Re-export the spinner factory so per-provider wizards use a consistent UX.
159
+ export { spinner };
160
+ //# sourceMappingURL=wizard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wizard.js","sourceRoot":"","sources":["../src/wizard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Per-resource static price table for the GCP stack — used by the
3
+ * wizard's pre-flight cost estimate. Prices are EUR/USD per month at
4
+ * `europe-west1` list rates as of 2026-05; ship updates with each
5
+ * Caelo release.
6
+ *
7
+ * The estimate is intentionally OVER-conservative — it shows the
8
+ * floor cost (idle + scale-to-zero traffic). Real usage adds egress
9
+ * + AI calls + storage growth on top.
10
+ */
11
+ export interface CostLine {
12
+ name: string;
13
+ monthlyUsd: number;
14
+ notes?: string;
15
+ }
16
+ export interface CostEstimateInputs {
17
+ cloudSqlTier: string;
18
+ cloudSqlHa: boolean;
19
+ adminMinInstances: number;
20
+ gatewayMinInstances: number;
21
+ wafAdaptiveProtection: boolean;
22
+ }
23
+ export declare function estimateGcpCost(inputs: CostEstimateInputs): {
24
+ lines: CostLine[];
25
+ totalUsd: number;
26
+ };
27
+ //# sourceMappingURL=gcp-cost.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcp-cost.d.ts","sourceRoot":"","sources":["../../src/wizards/gcp-cost.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAgBD,wBAAgB,eAAe,CAAC,MAAM,EAAE,kBAAkB,GAAG;IAC3D,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAiEA"}
@@ -0,0 +1,77 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ const SQL_TIER_USD = {
3
+ // Shared-core legacy tiers, ENTERPRISE edition
4
+ "db-f1-micro": 9.5,
5
+ "db-g1-small": 30,
6
+ // Per-N tiers (ENTERPRISE_PLUS only)
7
+ "db-perf-optimized-N-2": 50,
8
+ "db-perf-optimized-N-4": 95,
9
+ "db-perf-optimized-N-8": 180,
10
+ // Custom-machine fallback (rough)
11
+ "db-custom-1-3840": 35,
12
+ "db-custom-2-7680": 65,
13
+ "db-custom-4-15360": 130,
14
+ };
15
+ export function estimateGcpCost(inputs) {
16
+ const sqlBase = SQL_TIER_USD[inputs.cloudSqlTier] ?? 30;
17
+ const sqlMultiplier = inputs.cloudSqlHa ? 2.0 : 1.0;
18
+ const sqlMonthly = Math.round(sqlBase * sqlMultiplier);
19
+ const lines = [
20
+ {
21
+ name: `Cloud SQL Postgres (${inputs.cloudSqlTier}${inputs.cloudSqlHa ? ", HA" : ""})`,
22
+ monthlyUsd: sqlMonthly,
23
+ notes: inputs.cloudSqlHa
24
+ ? "REGIONAL availability (synchronous replica)"
25
+ : "ZONAL — single zone, automated backups",
26
+ },
27
+ {
28
+ name: "Cloud Run admin",
29
+ monthlyUsd: inputs.adminMinInstances === 0 ? 1 : 1 + inputs.adminMinInstances * 15,
30
+ notes: inputs.adminMinInstances === 0
31
+ ? "scale-to-zero; ~$1/mo light editorial use"
32
+ : `${inputs.adminMinInstances} min-instance${inputs.adminMinInstances > 1 ? "s" : ""} (no cold start)`,
33
+ },
34
+ {
35
+ name: "Cloud Run gateway",
36
+ monthlyUsd: inputs.gatewayMinInstances === 0 ? 1 : 1 + inputs.gatewayMinInstances * 15,
37
+ notes: inputs.gatewayMinInstances === 0
38
+ ? "scale-to-zero; ~$1/mo light traffic"
39
+ : `${inputs.gatewayMinInstances} min-instance${inputs.gatewayMinInstances > 1 ? "s" : ""}`,
40
+ },
41
+ {
42
+ name: "Load balancer + managed SSL cert",
43
+ monthlyUsd: 18,
44
+ notes: "Global LB base fee + cert (free) — flat",
45
+ },
46
+ {
47
+ name: "Cloud Storage (static + media)",
48
+ monthlyUsd: 1,
49
+ notes: "~5 GB storage + low egress; growth roughly $0.02/GB",
50
+ },
51
+ {
52
+ name: "Cloud CDN cache",
53
+ monthlyUsd: 1,
54
+ notes: "Free egress at edge cache hits",
55
+ },
56
+ {
57
+ name: "Cloud Armor WAF",
58
+ monthlyUsd: inputs.wafAdaptiveProtection ? 5 : 0,
59
+ notes: inputs.wafAdaptiveProtection
60
+ ? "Adaptive protection (ML-based bot mitigation)"
61
+ : "Free tier — rate limit + OWASP basic rules",
62
+ },
63
+ {
64
+ name: "Secret Manager (5 secrets)",
65
+ monthlyUsd: 0,
66
+ notes: "Free tier",
67
+ },
68
+ {
69
+ name: "BigQuery edge log sink",
70
+ monthlyUsd: 0,
71
+ notes: "Free tier — pay only on >1 TB/mo query",
72
+ },
73
+ ];
74
+ const totalUsd = lines.reduce((sum, l) => sum + l.monthlyUsd, 0);
75
+ return { lines, totalUsd };
76
+ }
77
+ //# sourceMappingURL=gcp-cost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcp-cost.js","sourceRoot":"","sources":["../../src/wizards/gcp-cost.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ export interface PulumiUpInputs {
2
+ installId: string;
3
+ installRoot: string;
4
+ secretsDir: string;
5
+ projectId: string;
6
+ domain: string;
7
+ ownerEmail: string;
8
+ region: string;
9
+ saKeyPath: string;
10
+ pulumiPassphrase: string;
11
+ anthropicApiKey: string;
12
+ cloudSqlTier: string;
13
+ cloudSqlHa: boolean;
14
+ adminMinInstances: number;
15
+ gatewayMinInstances: number;
16
+ wafAdaptiveProtection: boolean;
17
+ iapAllowlist: string[];
18
+ /** Resolved sha256 digests per service (admin, gateway). The wizard
19
+ * pre-resolves the floating `:main` tag to a fixed digest so each
20
+ * pulumi up rolls Cloud Run to the freshest published image. */
21
+ imageDigests: Record<string, string>;
22
+ }
23
+ export interface PulumiUpResult {
24
+ outputs: Record<string, unknown>;
25
+ resourceCount: {
26
+ created: number;
27
+ updated: number;
28
+ deleted: number;
29
+ };
30
+ }
31
+ /**
32
+ * Run `pulumi up` against the GCP stack via the Automation SDK.
33
+ * Streams resource-create events to the supplied onEvent callback so
34
+ * the wizard can render a live progress bar.
35
+ */
36
+ export declare function pulumiUpGcp(inputs: PulumiUpInputs, onEvent: (kind: "resource" | "error" | "log", message: string) => void): Promise<PulumiUpResult>;
37
+ //# sourceMappingURL=gcp-pulumi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcp-pulumi.d.ts","sourceRoot":"","sources":["../../src/wizards/gcp-pulumi.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB;;qEAEiE;IACjE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,aAAa,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACtE;AAeD;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GACrE,OAAO,CAAC,cAAc,CAAC,CAmFzB"}