@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.
- package/dist/agent/command.js +1 -0
- package/dist/agent/command.js.map +1 -1
- package/dist/agent-db.js +198 -102
- package/dist/audit-job-setup.d.ts +69 -0
- package/dist/audit-job-setup.d.ts.map +1 -0
- package/dist/audit-job-setup.js +317 -0
- package/dist/audit-job-setup.js.map +1 -0
- package/dist/aws-task-roles.d.ts +1 -1
- package/dist/aws-task-roles.d.ts.map +1 -1
- package/dist/aws-task-roles.js +0 -1
- package/dist/aws-task-roles.js.map +1 -1
- package/dist/caddy.d.ts +9 -0
- package/dist/caddy.d.ts.map +1 -1
- package/dist/caddy.js +38 -0
- package/dist/caddy.js.map +1 -1
- package/dist/cli-routing.d.ts +20 -0
- package/dist/cli-routing.d.ts.map +1 -1
- package/dist/cli-routing.js +106 -0
- package/dist/cli-routing.js.map +1 -1
- package/dist/cli.js +37 -14
- package/dist/cli.js.map +1 -1
- package/dist/compose.d.ts +4 -3
- package/dist/compose.d.ts.map +1 -1
- package/dist/compose.js +3 -2
- package/dist/compose.js.map +1 -1
- package/dist/gateway-credentials.d.ts +3 -5
- package/dist/gateway-credentials.d.ts.map +1 -1
- package/dist/gateway-credentials.js +8 -18
- package/dist/gateway-credentials.js.map +1 -1
- package/dist/gcp-names.d.ts +16 -1
- package/dist/gcp-names.d.ts.map +1 -1
- package/dist/gcp-names.js +23 -0
- package/dist/gcp-names.js.map +1 -1
- package/dist/infra-contract.d.ts +1 -1
- package/dist/infra-contract.d.ts.map +1 -1
- package/dist/infra-contract.js +14 -1
- package/dist/infra-contract.js.map +1 -1
- package/dist/private-file.d.ts +26 -0
- package/dist/private-file.d.ts.map +1 -0
- package/dist/private-file.js +49 -0
- package/dist/private-file.js.map +1 -0
- package/dist/release-contract.d.ts.map +1 -1
- package/dist/release-contract.js +3 -0
- package/dist/release-contract.js.map +1 -1
- package/dist/runtime-secrets.d.ts +1 -3
- package/dist/runtime-secrets.d.ts.map +1 -1
- package/dist/runtime-secrets.js +2 -6
- package/dist/runtime-secrets.js.map +1 -1
- package/dist/self-hosted-roles.d.ts +9 -8
- package/dist/self-hosted-roles.d.ts.map +1 -1
- package/dist/self-hosted-roles.js +9 -9
- package/dist/self-hosted-roles.js.map +1 -1
- package/dist/self-hosted-upgrade.d.ts +7 -1
- package/dist/self-hosted-upgrade.d.ts.map +1 -1
- package/dist/self-hosted-upgrade.js +17 -4
- package/dist/self-hosted-upgrade.js.map +1 -1
- package/dist/stack-contract.d.ts +60 -3
- package/dist/stack-contract.d.ts.map +1 -1
- package/dist/stack-contract.js +49 -37
- package/dist/stack-contract.js.map +1 -1
- package/dist/tar-entries.d.ts.map +1 -1
- package/dist/tar-entries.js +84 -9
- package/dist/tar-entries.js.map +1 -1
- package/dist/upgrade/app-roll.d.ts.map +1 -1
- package/dist/upgrade/app-roll.js +35 -0
- package/dist/upgrade/app-roll.js.map +1 -1
- package/dist/upgrade/audit-job-roll.d.ts +38 -0
- package/dist/upgrade/audit-job-roll.d.ts.map +1 -0
- package/dist/upgrade/audit-job-roll.js +43 -0
- package/dist/upgrade/audit-job-roll.js.map +1 -0
- package/dist/upgrade/converge.d.ts.map +1 -1
- package/dist/upgrade/converge.js +38 -15
- package/dist/upgrade/converge.js.map +1 -1
- package/dist/upgrader-setup.d.ts.map +1 -1
- package/dist/upgrader-setup.js +9 -3
- package/dist/upgrader-setup.js.map +1 -1
- package/dist/wizards/gcp-cost.js +3 -3
- package/dist/wizards/gcp-cost.js.map +1 -1
- package/dist/wizards/gcp-pulumi.d.ts +6 -0
- package/dist/wizards/gcp-pulumi.d.ts.map +1 -1
- package/dist/wizards/gcp-pulumi.js +7 -0
- package/dist/wizards/gcp-pulumi.js.map +1 -1
- package/dist/wizards/gcp.d.ts.map +1 -1
- package/dist/wizards/gcp.js +32 -30
- package/dist/wizards/gcp.js.map +1 -1
- package/package.json +4 -4
- package/src/admin-memory.test.ts +1 -1
- package/src/agent/command.ts +1 -0
- package/src/agent/run.test.ts +1 -0
- package/src/audit-job-setup.test.ts +234 -0
- package/src/audit-job-setup.ts +360 -0
- package/src/aws-task-roles.ts +0 -2
- package/src/caddy-redirects.docker.test.ts +19 -6
- package/src/caddy-redirects.test.ts +1 -1
- package/src/caddy.test.ts +30 -0
- package/src/caddy.ts +43 -0
- package/src/checkpoint-secrets.test.ts +0 -2
- package/src/cli-init-validation.test.ts +44 -0
- package/src/cli-routing.test.ts +27 -1
- package/src/cli-routing.ts +131 -0
- package/src/cli.ts +41 -15
- package/src/compose.ts +13 -5
- package/src/gateway-credentials.test.ts +0 -29
- package/src/gateway-credentials.ts +11 -25
- package/src/gateway-env-isolation.test.ts +7 -2
- package/src/gcp-names.ts +28 -1
- package/src/index.test.ts +7 -6
- package/src/infra-contract.test.ts +4 -3
- package/src/infra-contract.ts +14 -1
- package/src/private-file.test.ts +80 -0
- package/src/private-file.ts +50 -0
- package/src/release-contract.ts +3 -0
- package/src/runtime-secrets.test.ts +9 -81
- package/src/runtime-secrets.ts +2 -6
- package/src/self-hosted-compose.test.ts +1 -1
- package/src/self-hosted-roles.integration.test.ts +23 -38
- package/src/self-hosted-roles.test.ts +11 -7
- package/src/self-hosted-roles.ts +17 -16
- package/src/self-hosted-upgrade.test.ts +28 -1
- package/src/self-hosted-upgrade.ts +29 -4
- package/src/stack-contract.test.ts +19 -11
- package/src/stack-contract.ts +54 -5
- package/src/stack-converge-secrets.test.ts +2 -0
- package/src/stack-converge.test.ts +3 -1
- package/src/tar-entries.test.ts +149 -7
- package/src/tar-entries.ts +90 -9
- package/src/upgrade/app-roll.ts +39 -0
- package/src/upgrade/audit-job-roll.ts +68 -0
- package/src/upgrade/converge.ts +47 -20
- package/src/upgrade/upgrade.test.ts +76 -2
- package/src/upgrader-assess.test.ts +1 -0
- package/src/upgrader-job.test.ts +1 -0
- package/src/upgrader-setup.test.ts +1 -0
- package/src/upgrader-setup.ts +9 -2
- package/src/wizards/gcp-cost.ts +3 -3
- package/src/wizards/gcp-pulumi.ts +7 -0
- package/src/wizards/gcp.ts +38 -31
- package/stacks/aws/README.md +1 -1
- package/stacks/aws/index.ts +9 -6
- package/stacks/azure/README.md +1 -1
- package/stacks/azure/index.ts +18 -6
- package/stacks/gcp/README.md +1 -1
- package/stacks/gcp/index.ts +14 -4
- package/stacks/gcp-firebase/index.ts +14 -4
- package/stacks/self-hosted/index.ts +4 -11
package/stacks/azure/index.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
// (
|
|
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",
|
package/stacks/gcp/README.md
CHANGED
|
@@ -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
|
|
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.
|
package/stacks/gcp/index.ts
CHANGED
|
@@ -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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
|
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,
|