@caelo-cms/provisioning 0.10.52 → 0.10.55

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 (145) hide show
  1. package/dist/agent/command.js +1 -0
  2. package/dist/agent/command.js.map +1 -1
  3. package/dist/agent-db.js +198 -102
  4. package/dist/audit-job-setup.d.ts +69 -0
  5. package/dist/audit-job-setup.d.ts.map +1 -0
  6. package/dist/audit-job-setup.js +317 -0
  7. package/dist/audit-job-setup.js.map +1 -0
  8. package/dist/aws-task-roles.d.ts +1 -1
  9. package/dist/aws-task-roles.d.ts.map +1 -1
  10. package/dist/aws-task-roles.js +0 -1
  11. package/dist/aws-task-roles.js.map +1 -1
  12. package/dist/caddy.d.ts +9 -0
  13. package/dist/caddy.d.ts.map +1 -1
  14. package/dist/caddy.js +38 -0
  15. package/dist/caddy.js.map +1 -1
  16. package/dist/cli-routing.d.ts +20 -0
  17. package/dist/cli-routing.d.ts.map +1 -1
  18. package/dist/cli-routing.js +106 -0
  19. package/dist/cli-routing.js.map +1 -1
  20. package/dist/cli.js +37 -14
  21. package/dist/cli.js.map +1 -1
  22. package/dist/compose.d.ts +4 -3
  23. package/dist/compose.d.ts.map +1 -1
  24. package/dist/compose.js +3 -2
  25. package/dist/compose.js.map +1 -1
  26. package/dist/gateway-credentials.d.ts +3 -5
  27. package/dist/gateway-credentials.d.ts.map +1 -1
  28. package/dist/gateway-credentials.js +8 -18
  29. package/dist/gateway-credentials.js.map +1 -1
  30. package/dist/gcp-names.d.ts +16 -1
  31. package/dist/gcp-names.d.ts.map +1 -1
  32. package/dist/gcp-names.js +23 -0
  33. package/dist/gcp-names.js.map +1 -1
  34. package/dist/infra-contract.d.ts +1 -1
  35. package/dist/infra-contract.d.ts.map +1 -1
  36. package/dist/infra-contract.js +14 -1
  37. package/dist/infra-contract.js.map +1 -1
  38. package/dist/private-file.d.ts +26 -0
  39. package/dist/private-file.d.ts.map +1 -0
  40. package/dist/private-file.js +49 -0
  41. package/dist/private-file.js.map +1 -0
  42. package/dist/release-contract.d.ts.map +1 -1
  43. package/dist/release-contract.js +3 -0
  44. package/dist/release-contract.js.map +1 -1
  45. package/dist/runtime-secrets.d.ts +1 -3
  46. package/dist/runtime-secrets.d.ts.map +1 -1
  47. package/dist/runtime-secrets.js +2 -6
  48. package/dist/runtime-secrets.js.map +1 -1
  49. package/dist/self-hosted-roles.d.ts +9 -8
  50. package/dist/self-hosted-roles.d.ts.map +1 -1
  51. package/dist/self-hosted-roles.js +9 -9
  52. package/dist/self-hosted-roles.js.map +1 -1
  53. package/dist/self-hosted-upgrade.d.ts +7 -1
  54. package/dist/self-hosted-upgrade.d.ts.map +1 -1
  55. package/dist/self-hosted-upgrade.js +17 -4
  56. package/dist/self-hosted-upgrade.js.map +1 -1
  57. package/dist/stack-contract.d.ts +60 -3
  58. package/dist/stack-contract.d.ts.map +1 -1
  59. package/dist/stack-contract.js +49 -37
  60. package/dist/stack-contract.js.map +1 -1
  61. package/dist/tar-entries.d.ts.map +1 -1
  62. package/dist/tar-entries.js +84 -9
  63. package/dist/tar-entries.js.map +1 -1
  64. package/dist/upgrade/app-roll.d.ts.map +1 -1
  65. package/dist/upgrade/app-roll.js +35 -0
  66. package/dist/upgrade/app-roll.js.map +1 -1
  67. package/dist/upgrade/audit-job-roll.d.ts +38 -0
  68. package/dist/upgrade/audit-job-roll.d.ts.map +1 -0
  69. package/dist/upgrade/audit-job-roll.js +43 -0
  70. package/dist/upgrade/audit-job-roll.js.map +1 -0
  71. package/dist/upgrade/converge.d.ts.map +1 -1
  72. package/dist/upgrade/converge.js +38 -15
  73. package/dist/upgrade/converge.js.map +1 -1
  74. package/dist/upgrader-setup.d.ts.map +1 -1
  75. package/dist/upgrader-setup.js +9 -3
  76. package/dist/upgrader-setup.js.map +1 -1
  77. package/dist/wizards/gcp-cost.js +3 -3
  78. package/dist/wizards/gcp-cost.js.map +1 -1
  79. package/dist/wizards/gcp-pulumi.d.ts +6 -0
  80. package/dist/wizards/gcp-pulumi.d.ts.map +1 -1
  81. package/dist/wizards/gcp-pulumi.js +7 -0
  82. package/dist/wizards/gcp-pulumi.js.map +1 -1
  83. package/dist/wizards/gcp.d.ts.map +1 -1
  84. package/dist/wizards/gcp.js +32 -30
  85. package/dist/wizards/gcp.js.map +1 -1
  86. package/package.json +4 -4
  87. package/src/admin-memory.test.ts +1 -1
  88. package/src/agent/command.ts +1 -0
  89. package/src/agent/run.test.ts +1 -0
  90. package/src/audit-job-setup.test.ts +234 -0
  91. package/src/audit-job-setup.ts +360 -0
  92. package/src/aws-task-roles.ts +0 -2
  93. package/src/caddy-redirects.docker.test.ts +19 -6
  94. package/src/caddy-redirects.test.ts +1 -1
  95. package/src/caddy.test.ts +30 -0
  96. package/src/caddy.ts +43 -0
  97. package/src/checkpoint-secrets.test.ts +0 -2
  98. package/src/cli-init-validation.test.ts +44 -0
  99. package/src/cli-routing.test.ts +27 -1
  100. package/src/cli-routing.ts +131 -0
  101. package/src/cli.ts +41 -15
  102. package/src/compose.ts +13 -5
  103. package/src/gateway-credentials.test.ts +0 -29
  104. package/src/gateway-credentials.ts +11 -25
  105. package/src/gateway-env-isolation.test.ts +7 -2
  106. package/src/gcp-names.ts +28 -1
  107. package/src/index.test.ts +7 -6
  108. package/src/infra-contract.test.ts +4 -3
  109. package/src/infra-contract.ts +14 -1
  110. package/src/private-file.test.ts +80 -0
  111. package/src/private-file.ts +50 -0
  112. package/src/release-contract.ts +3 -0
  113. package/src/runtime-secrets.test.ts +9 -81
  114. package/src/runtime-secrets.ts +2 -6
  115. package/src/self-hosted-compose.test.ts +1 -1
  116. package/src/self-hosted-roles.integration.test.ts +23 -38
  117. package/src/self-hosted-roles.test.ts +11 -7
  118. package/src/self-hosted-roles.ts +17 -16
  119. package/src/self-hosted-upgrade.test.ts +28 -1
  120. package/src/self-hosted-upgrade.ts +29 -4
  121. package/src/stack-contract.test.ts +19 -11
  122. package/src/stack-contract.ts +54 -5
  123. package/src/stack-converge-secrets.test.ts +2 -0
  124. package/src/stack-converge.test.ts +3 -1
  125. package/src/tar-entries.test.ts +149 -7
  126. package/src/tar-entries.ts +90 -9
  127. package/src/upgrade/app-roll.ts +39 -0
  128. package/src/upgrade/audit-job-roll.ts +68 -0
  129. package/src/upgrade/converge.ts +47 -20
  130. package/src/upgrade/upgrade.test.ts +76 -2
  131. package/src/upgrader-assess.test.ts +1 -0
  132. package/src/upgrader-job.test.ts +1 -0
  133. package/src/upgrader-setup.test.ts +1 -0
  134. package/src/upgrader-setup.ts +9 -2
  135. package/src/wizards/gcp-cost.ts +3 -3
  136. package/src/wizards/gcp-pulumi.ts +7 -0
  137. package/src/wizards/gcp.ts +38 -31
  138. package/stacks/aws/README.md +1 -1
  139. package/stacks/aws/index.ts +9 -6
  140. package/stacks/azure/README.md +1 -1
  141. package/stacks/azure/index.ts +18 -6
  142. package/stacks/gcp/README.md +1 -1
  143. package/stacks/gcp/index.ts +14 -4
  144. package/stacks/gcp-firebase/index.ts +14 -4
  145. package/stacks/self-hosted/index.ts +4 -11
@@ -39,7 +39,12 @@ import * as pulumi from "@pulumi/pulumi";
39
39
  import type { CloudAdapterOutputs, DnsRecord } from "../../dist/adapter.js";
40
40
  import { azureFrontDoorDnsRecords } from "../../dist/azure-front-door.js";
41
41
  import { generateBootstrapToken } from "../../dist/bootstrap-token.js";
42
- import { ADMIN_MEMORY_DEFAULT, azureContainerAppResources } from "../../dist/stack-contract.js";
42
+ import {
43
+ ADMIN_MEMORY_DEFAULT,
44
+ azureContainerAppResources,
45
+ GATEWAY_TRUSTED_PROXY_HOPS,
46
+ TRUSTED_PROXY_HOPS_ENV,
47
+ } from "../../dist/stack-contract.js";
43
48
 
44
49
  const cfg = new pulumi.Config();
45
50
  const domain = cfg.require("domain");
@@ -83,11 +88,8 @@ function randomHex(bytes: number): string {
83
88
  const postgresPassword = pulumi.secret(randomHex(32));
84
89
  // #613 — one password per database role, so the gateway (public_role only,
85
90
  // #635) never holds admin_role's. bootstrap.sh creates the roles with these
86
- // (PUBLIC_ROLE_PASSWORD / GATEWAY_ROLE_PASSWORD). gateway_role is no longer
87
- // any service's login; its password stays until the contract release that
88
- // drops the role (#635).
91
+ // (ADMIN_ROLE_PASSWORD / PUBLIC_ROLE_PASSWORD).
89
92
  const publicRolePassword = pulumi.secret(randomHex(32));
90
- const gatewayRolePassword = pulumi.secret(randomHex(32));
91
93
  const csrfSecret = pulumi.secret(randomHex(32));
92
94
  const cookieSecret = pulumi.secret(randomHex(32));
93
95
  const anthropicApiKey = pulumi.secret(process.env.ANTHROPIC_API_KEY ?? "");
@@ -117,7 +119,6 @@ function keyVaultSecret(shortName: string, value: pulumi.Output<string>): azure.
117
119
 
118
120
  const _pgSecret = keyVaultSecret("pg-password", postgresPassword);
119
121
  keyVaultSecret("public-role-password", publicRolePassword);
120
- keyVaultSecret("gateway-role-password", gatewayRolePassword);
121
122
  keyVaultSecret("csrf-secret", csrfSecret);
122
123
  keyVaultSecret("cookie-secret", cookieSecret);
123
124
  keyVaultSecret("anthropic-api-key", anthropicApiKey);
@@ -329,6 +330,15 @@ const logWorkspace = new azure.operationalinsights.Workspace(`${namePrefix}-logs
329
330
  });
330
331
 
331
332
  // === 6. Container Apps environment + apps ===
333
+ //
334
+ // FIXME(issue #750): no quality-audit Container Apps job yet. On GCP every
335
+ // Lighthouse run of a Stage audit runs in its own container (#875,
336
+ // src/audit-job-setup.ts); the Azure equivalent is a Container Apps job
337
+ // with one replica per run (admin-core quality/parallel-runner.ts
338
+ // `AuditTaskLauncher`). Until it exists the admin records every Lighthouse
339
+ // audit as failed with that gap (quality/lighthouse-runner-select.ts)
340
+ // instead of measuring on its own shared CPU. Nothing is staged on Azure
341
+ // before #750 either.
332
342
  const cappEnv = new azure.app.ManagedEnvironment(`${namePrefix}-capp-env`, {
333
343
  resourceGroupName: rg.name,
334
344
  environmentName: `${namePrefix}-capp-env`,
@@ -419,6 +429,8 @@ const adminApp = containerApp({
419
429
  const _gatewayApp = containerApp({
420
430
  serviceName: "gateway",
421
431
  databaseEnv: [{ name: "PUBLIC_DATABASE_URL", value: publicDatabaseUrl }],
432
+ // Which X-Forwarded-For entry is the visitor (api-gateway client-ip.ts).
433
+ extraEnv: [{ name: TRUSTED_PROXY_HOPS_ENV, value: String(GATEWAY_TRUSTED_PROXY_HOPS.azure) }],
422
434
  });
423
435
  const _orchestratorApp = containerApp({
424
436
  serviceName: "orchestrator",
@@ -10,7 +10,7 @@ Pulumi stack provisioning Caelo on GCP managed services. Implements the shared `
10
10
  | Blob storage | Two GCS buckets (`<project>-caelo-<env>-media`, `<project>-caelo-<env>-static`) with uniform bucket-level access |
11
11
  | CDN | Global HTTPS load balancer + Cloud CDN backend bucket: `<domain>` serves the static bucket as files, `/api/*` goes to the gateway, `admin.<domain>` to the IAP-gated admin |
12
12
  | Container runtime | Four Cloud Run services (admin / gateway / orchestrator / runner) |
13
- | Secret store | Secret Manager: postgres-password (admin_role) + secret-kek (Pulumi); internal-secret, tool-approval-secret, public-role-password and gateway-role-password (created by the CLI before `pulumi up`, see `src/runtime-secrets.ts`). Cloud Run reads each as a `secretKeyRef`; database URLs carry no password. The gateway's service account reads only `public-role-password` (#613, #635: the gateway has no cms_admin login); `gateway_role`, created by migration 0248, is no service's login any more. |
13
+ | Secret store | Secret Manager: postgres-password (admin_role) + secret-kek (Pulumi); internal-secret, tool-approval-secret and public-role-password (created by the CLI before `pulumi up`, see `src/runtime-secrets.ts`). Cloud Run reads each as a `secretKeyRef`; database URLs carry no password. The gateway's service account reads only `public-role-password` (#613, #635: the gateway has no cms_admin login). |
14
14
  | Edge-log sink | Cloud Logging project sink → BigQuery dataset `<env>_edge_logs` (queryable by P12A analytics plugin) |
15
15
 
16
16
  The Caelo runtime never knows it's on GCP — every Cloud Run service consumes plain `DATABASE_URL` / `MEDIA_STORAGE_URL` / `SECRETS_PROVIDER` env vars.
@@ -251,14 +251,11 @@ const runtimeSecretIds: Record<RuntimeSecret, pulumi.Input<string>> = {
251
251
  "tool-approval-secret": gcpSecretId(env, "tool-approval-secret"),
252
252
  "staging-gate-secret": gcpSecretId(env, "staging-gate-secret"),
253
253
  "public-role-password": gcpSecretId(env, "public-role-password"),
254
- "gateway-role-password": gcpSecretId(env, "gateway-role-password"),
255
254
  };
256
255
 
257
256
  // #613 — public_role's own password (CLI-generated, stack-contract.ts
258
257
  // DATABASE_ROLE_SECRET), so the gateway, which reads it, never holds
259
- // admin_role's. gateway_role is not declared here: migration 0248 creates
260
- // it in SQL (an API-created user would join cloudsqlsuperuser) and the CLI
261
- // sets its password after migrations.
258
+ // admin_role's. The gateway has no other database login (#635).
262
259
  const publicRolePassword = pulumi.secret(
263
260
  gcp.secretmanager.getSecretVersionOutput(
264
261
  { project, secret: gcpSecretId(env, "public-role-password") },
@@ -987,6 +984,19 @@ new gcp.iap.WebBackendServiceIamMember(
987
984
  opts,
988
985
  );
989
986
 
987
+ // =========================================================================
988
+ // Quality-audit job — deliberately NOT here
989
+ // =========================================================================
990
+ //
991
+ // #875 — every Stage audit's Lighthouse runs execute in parallel in a Cloud
992
+ // Run job, one task per run, under its own service account (results bucket
993
+ // create-only, staged build read-only, no secrets, no VPC). The CLI owns the
994
+ // job, its account, the results bucket and the grants
995
+ // (packages/provisioning/src/audit-job-setup.ts, run by the wizard after
996
+ // `pulumi up` and by `upgrade`), because `upgrade` never runs Pulumi: a
997
+ // bucket or job both this program and `upgrade` created would collide on
998
+ // the next wizard run. The app-roll moves the job's image with the admin's.
999
+
990
1000
  // =========================================================================
991
1001
  // Operator access — deliberately NOT here
992
1002
  // =========================================================================
@@ -224,14 +224,11 @@ const runtimeSecretIds: Record<RuntimeSecret, pulumi.Input<string>> = {
224
224
  "tool-approval-secret": gcpSecretId(env, "tool-approval-secret"),
225
225
  "staging-gate-secret": gcpSecretId(env, "staging-gate-secret"),
226
226
  "public-role-password": gcpSecretId(env, "public-role-password"),
227
- "gateway-role-password": gcpSecretId(env, "gateway-role-password"),
228
227
  };
229
228
 
230
229
  // #613 — public_role's own password (CLI-generated, stack-contract.ts
231
230
  // DATABASE_ROLE_SECRET), so the gateway, which reads it, never holds
232
- // admin_role's. gateway_role is not declared here: migration 0248 creates
233
- // it in SQL (an API-created user would join cloudsqlsuperuser) and the CLI
234
- // sets its password after migrations.
231
+ // admin_role's. The gateway has no other database login (#635).
235
232
  const publicRolePassword = pulumi.secret(
236
233
  gcp.secretmanager.getSecretVersionOutput(
237
234
  { project, secret: gcpSecretId(env, "public-role-password") },
@@ -903,6 +900,19 @@ new gcp.iap.WebCloudRunServiceIamMember(
903
900
  opts,
904
901
  );
905
902
 
903
+ // =========================================================================
904
+ // Quality-audit job — deliberately NOT here
905
+ // =========================================================================
906
+ //
907
+ // #875 — every Stage audit's Lighthouse runs execute in parallel in a Cloud
908
+ // Run job, one task per run, under its own service account (results bucket
909
+ // create-only, staged build read-only, no secrets, no VPC). The CLI owns the
910
+ // job, its account, the results bucket and the grants
911
+ // (packages/provisioning/src/audit-job-setup.ts, run by the wizard after
912
+ // `pulumi up` and by `upgrade`), because `upgrade` never runs Pulumi: a
913
+ // bucket or job both this program and `upgrade` created would collide on
914
+ // the next wizard run. The app-roll moves the job's image with the admin's.
915
+
906
916
  // =========================================================================
907
917
  // Operator access — deliberately NOT here
908
918
  // =========================================================================
@@ -62,26 +62,19 @@ const tokenPath = resolve(caeloDir, "bootstrap", "pending-token.json");
62
62
  // is the operator's recovery path.
63
63
  const postgresPassword = pulumi.secret(randomHex(32));
64
64
  // #613 — one password per application role; the gateway gets only the
65
- // public_role and gateway_role ones.
65
+ // public_role one (#635: no cms_admin login).
66
66
  const adminRolePassword = pulumi.secret(randomHex(32));
67
67
  const publicRolePassword = pulumi.secret(randomHex(32));
68
- const gatewayRolePassword = pulumi.secret(randomHex(32));
69
68
  // P18 — the KEK that encrypts stored provider keys.
70
69
  const caeloSecretKek = pulumi.secret(randomHex(32));
71
70
 
72
71
  const composeYaml = pulumi
73
- .all([
74
- postgresPassword,
75
- adminRolePassword,
76
- publicRolePassword,
77
- gatewayRolePassword,
78
- caeloSecretKek,
79
- ])
80
- .apply(([pgPw, adminPw, publicPw, gatewayPw, kek]) =>
72
+ .all([postgresPassword, adminRolePassword, publicRolePassword, caeloSecretKek])
73
+ .apply(([pgPw, adminPw, publicPw, kek]) =>
81
74
  generateDockerCompose({
82
75
  domain,
83
76
  postgresPassword: pgPw,
84
- rolePasswords: { admin: adminPw, public: publicPw, gateway: gatewayPw },
77
+ rolePasswords: { admin: adminPw, public: publicPw },
85
78
  caeloSecretKek: kek,
86
79
  anthropicApiKey: process.env.ANTHROPIC_API_KEY,
87
80
  resendApiKey: process.env.RESEND_API_KEY,