@caelo-cms/provisioning 0.11.9 → 0.11.11
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/adapter.d.ts +6 -0
- package/dist/adapter.d.ts.map +1 -1
- package/dist/admin-domain.d.ts +10 -1
- package/dist/admin-domain.d.ts.map +1 -1
- package/dist/admin-domain.js +13 -3
- package/dist/admin-domain.js.map +1 -1
- package/dist/adopt-existing.d.ts +12 -3
- package/dist/adopt-existing.d.ts.map +1 -1
- package/dist/adopt-existing.js +143 -0
- package/dist/adopt-existing.js.map +1 -1
- package/dist/agent/command.d.ts +23 -0
- package/dist/agent/command.d.ts.map +1 -1
- package/dist/agent/command.js +32 -9
- package/dist/agent/command.js.map +1 -1
- package/dist/agent/run.d.ts +2 -0
- package/dist/agent/run.d.ts.map +1 -1
- package/dist/agent/run.js +5 -1
- package/dist/agent/run.js.map +1 -1
- package/dist/agent-db.js +69 -10
- package/dist/aws-task-roles.d.ts +4 -2
- package/dist/aws-task-roles.d.ts.map +1 -1
- package/dist/aws-task-roles.js +4 -1
- package/dist/aws-task-roles.js.map +1 -1
- package/dist/caddy.d.ts +21 -4
- package/dist/caddy.d.ts.map +1 -1
- package/dist/caddy.js +27 -3
- package/dist/caddy.js.map +1 -1
- package/dist/cli-routing.js +1 -1
- package/dist/cli-routing.js.map +1 -1
- package/dist/cli.js +68 -7
- package/dist/cli.js.map +1 -1
- package/dist/cloudsql-tls.d.ts +93 -0
- package/dist/cloudsql-tls.d.ts.map +1 -0
- package/dist/cloudsql-tls.js +295 -0
- package/dist/cloudsql-tls.js.map +1 -0
- package/dist/compose.d.ts +43 -6
- package/dist/compose.d.ts.map +1 -1
- package/dist/compose.js +148 -23
- package/dist/compose.js.map +1 -1
- package/dist/converge-checkpoint.d.ts +1 -0
- package/dist/converge-checkpoint.d.ts.map +1 -1
- package/dist/converge-checkpoint.js +8 -1
- package/dist/converge-checkpoint.js.map +1 -1
- package/dist/converge-db-trust.d.ts +44 -0
- package/dist/converge-db-trust.d.ts.map +1 -0
- package/dist/converge-db-trust.js +158 -0
- package/dist/converge-db-trust.js.map +1 -0
- package/dist/converge-job-gcp.d.ts +5 -2
- package/dist/converge-job-gcp.d.ts.map +1 -1
- package/dist/converge-job-gcp.js +11 -13
- package/dist/converge-job-gcp.js.map +1 -1
- package/dist/converge-job-preflight.d.ts.map +1 -1
- package/dist/converge-job-preflight.js +8 -0
- package/dist/converge-job-preflight.js.map +1 -1
- package/dist/converge-job.d.ts +17 -0
- package/dist/converge-job.d.ts.map +1 -1
- package/dist/converge-job.js +12 -0
- package/dist/converge-job.js.map +1 -1
- package/dist/deployed-release.d.ts +4 -1
- package/dist/deployed-release.d.ts.map +1 -1
- package/dist/deployed-release.js +18 -8
- package/dist/deployed-release.js.map +1 -1
- package/dist/gcp-names.d.ts +34 -0
- package/dist/gcp-names.d.ts.map +1 -1
- package/dist/gcp-names.js +45 -0
- package/dist/gcp-names.js.map +1 -1
- package/dist/gcp-url-map.d.ts.map +1 -1
- package/dist/gcp-url-map.js +6 -2
- package/dist/gcp-url-map.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.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 +45 -1
- package/dist/infra-contract.js.map +1 -1
- package/dist/install-job.d.ts +4 -2
- package/dist/install-job.d.ts.map +1 -1
- package/dist/install-job.js +4 -1
- package/dist/install-job.js.map +1 -1
- package/dist/install-state.d.ts +13 -0
- package/dist/install-state.d.ts.map +1 -1
- package/dist/install-state.js +17 -4
- package/dist/install-state.js.map +1 -1
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +20 -8
- package/dist/lifecycle.js.map +1 -1
- package/dist/mcp-auth-proxy-setup.d.ts +48 -0
- package/dist/mcp-auth-proxy-setup.d.ts.map +1 -0
- package/dist/mcp-auth-proxy-setup.js +280 -0
- package/dist/mcp-auth-proxy-setup.js.map +1 -0
- package/dist/migration-runner.d.ts.map +1 -1
- package/dist/migration-runner.js +8 -3
- package/dist/migration-runner.js.map +1 -1
- package/dist/migration-targets.d.ts +11 -0
- package/dist/migration-targets.d.ts.map +1 -0
- package/dist/migration-targets.js +12 -0
- package/dist/migration-targets.js.map +1 -0
- package/dist/operator-access.d.ts +10 -0
- package/dist/operator-access.d.ts.map +1 -1
- package/dist/operator-access.js +5 -0
- package/dist/operator-access.js.map +1 -1
- package/dist/pool-budget-stack.d.ts +13 -1
- package/dist/pool-budget-stack.d.ts.map +1 -1
- package/dist/pool-budget-stack.js +11 -1
- package/dist/pool-budget-stack.js.map +1 -1
- package/dist/public-role-isolation.d.ts +7 -3
- package/dist/public-role-isolation.d.ts.map +1 -1
- package/dist/public-role-isolation.js +25 -13
- package/dist/public-role-isolation.js.map +1 -1
- 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/release-manifest.d.ts +25 -1
- package/dist/release-manifest.d.ts.map +1 -1
- package/dist/release-manifest.js +36 -3
- package/dist/release-manifest.js.map +1 -1
- package/dist/remote-mcp.d.ts +55 -18
- package/dist/remote-mcp.d.ts.map +1 -1
- package/dist/remote-mcp.js +307 -77
- package/dist/remote-mcp.js.map +1 -1
- package/dist/runtime-secrets.d.ts +11 -0
- package/dist/runtime-secrets.d.ts.map +1 -1
- package/dist/runtime-secrets.js +40 -25
- package/dist/runtime-secrets.js.map +1 -1
- package/dist/scheduler-setup.d.ts +75 -0
- package/dist/scheduler-setup.d.ts.map +1 -0
- package/dist/scheduler-setup.js +331 -0
- package/dist/scheduler-setup.js.map +1 -0
- package/dist/seal-key-rotation.d.ts +7 -7
- package/dist/seal-key-rotation.d.ts.map +1 -1
- package/dist/seal-key-rotation.js +22 -22
- package/dist/seal-key-rotation.js.map +1 -1
- package/dist/self-hosted-db-tls.d.ts +37 -0
- package/dist/self-hosted-db-tls.d.ts.map +1 -0
- package/dist/self-hosted-db-tls.js +220 -0
- package/dist/self-hosted-db-tls.js.map +1 -0
- package/dist/self-hosted-release.d.ts +3 -1
- package/dist/self-hosted-release.d.ts.map +1 -1
- package/dist/self-hosted-release.js +33 -9
- package/dist/self-hosted-release.js.map +1 -1
- package/dist/self-hosted-roles.d.ts +43 -2
- package/dist/self-hosted-roles.d.ts.map +1 -1
- package/dist/self-hosted-roles.js +87 -1
- package/dist/self-hosted-roles.js.map +1 -1
- package/dist/self-hosted-scheduler-interval.d.ts +21 -0
- package/dist/self-hosted-scheduler-interval.d.ts.map +1 -0
- package/dist/self-hosted-scheduler-interval.js +68 -0
- package/dist/self-hosted-scheduler-interval.js.map +1 -0
- package/dist/self-hosted-start.d.ts +0 -21
- package/dist/self-hosted-start.d.ts.map +1 -1
- package/dist/self-hosted-start.js +39 -1
- package/dist/self-hosted-start.js.map +1 -1
- package/dist/self-hosted-upgrade.d.ts +19 -7
- package/dist/self-hosted-upgrade.d.ts.map +1 -1
- package/dist/self-hosted-upgrade.js +78 -25
- package/dist/self-hosted-upgrade.js.map +1 -1
- package/dist/stack-contract.d.ts +234 -28
- package/dist/stack-contract.d.ts.map +1 -1
- package/dist/stack-contract.js +397 -39
- package/dist/stack-contract.js.map +1 -1
- package/dist/stack-converge.d.ts +31 -0
- package/dist/stack-converge.d.ts.map +1 -1
- package/dist/stack-converge.js +71 -30
- package/dist/stack-converge.js.map +1 -1
- package/dist/staging-database.d.ts +22 -0
- package/dist/staging-database.d.ts.map +1 -0
- package/dist/staging-database.js +117 -0
- package/dist/staging-database.js.map +1 -0
- package/dist/upgrade/app-roll.d.ts +25 -4
- package/dist/upgrade/app-roll.d.ts.map +1 -1
- package/dist/upgrade/app-roll.js +63 -17
- package/dist/upgrade/app-roll.js.map +1 -1
- package/dist/upgrade/converge.d.ts +5 -0
- package/dist/upgrade/converge.d.ts.map +1 -1
- package/dist/upgrade/converge.js +207 -20
- package/dist/upgrade/converge.js.map +1 -1
- package/dist/upgrade/health.d.ts +31 -7
- package/dist/upgrade/health.d.ts.map +1 -1
- package/dist/upgrade/health.js +41 -17
- package/dist/upgrade/health.js.map +1 -1
- package/dist/upgrade/image-forms.d.ts +1 -1
- package/dist/upgrade/image-forms.d.ts.map +1 -1
- package/dist/upgrade/image-forms.js +24 -7
- package/dist/upgrade/image-forms.js.map +1 -1
- package/dist/upgrade/release-images.d.ts +12 -3
- package/dist/upgrade/release-images.d.ts.map +1 -1
- package/dist/upgrade/release-images.js +13 -4
- package/dist/upgrade/release-images.js.map +1 -1
- package/dist/upgrade/upgrade.d.ts +19 -3
- package/dist/upgrade/upgrade.d.ts.map +1 -1
- package/dist/upgrade/upgrade.js +37 -2
- package/dist/upgrade/upgrade.js.map +1 -1
- package/dist/upgrader-gcp.d.ts +13 -0
- package/dist/upgrader-gcp.d.ts.map +1 -1
- package/dist/upgrader-gcp.js +50 -1
- package/dist/upgrader-gcp.js.map +1 -1
- package/dist/upgrader-iam-preflight.d.ts.map +1 -1
- package/dist/upgrader-iam-preflight.js +6 -1
- package/dist/upgrader-iam-preflight.js.map +1 -1
- package/dist/upgrader-job.d.ts +1 -1
- package/dist/upgrader-job.d.ts.map +1 -1
- package/dist/upgrader-job.js +20 -14
- package/dist/upgrader-job.js.map +1 -1
- package/dist/upgrader-records.d.ts +1 -1
- package/dist/upgrader-records.d.ts.map +1 -1
- package/dist/upgrader-records.js +26 -7
- package/dist/upgrader-records.js.map +1 -1
- package/dist/upgrader-setup.d.ts.map +1 -1
- package/dist/upgrader-setup.js +10 -5
- package/dist/upgrader-setup.js.map +1 -1
- package/dist/wizard.d.ts +7 -0
- package/dist/wizard.d.ts.map +1 -1
- package/dist/wizard.js +11 -0
- package/dist/wizard.js.map +1 -1
- package/dist/wizards/gcp-cost.d.ts +31 -0
- package/dist/wizards/gcp-cost.d.ts.map +1 -1
- package/dist/wizards/gcp-cost.js +103 -18
- package/dist/wizards/gcp-cost.js.map +1 -1
- package/dist/wizards/gcp.d.ts.map +1 -1
- package/dist/wizards/gcp.js +129 -27
- package/dist/wizards/gcp.js.map +1 -1
- package/package.json +2 -2
- package/src/adapter.ts +6 -0
- package/src/admin-domain.test.ts +9 -8
- package/src/admin-domain.ts +13 -3
- package/src/admin-memory.test.ts +2 -1
- package/src/adopt-existing.test.ts +85 -0
- package/src/adopt-existing.ts +141 -3
- package/src/agent/command.test.ts +49 -1
- package/src/agent/command.ts +39 -9
- package/src/agent/run.test.ts +19 -0
- package/src/agent/run.ts +11 -2
- package/src/aws-task-roles.ts +5 -2
- package/src/caddy-redirects.docker.test.ts +2 -0
- package/src/caddy-redirects.test.ts +4 -1
- package/src/caddy-validate.test.ts +7 -1
- package/src/caddy.test.ts +39 -1
- package/src/caddy.ts +36 -4
- package/src/checkpoint-secrets.test.ts +14 -6
- package/src/cli-routing.test.ts +1 -1
- package/src/cli-routing.ts +1 -1
- package/src/cli.ts +71 -5
- package/src/cloudsql-tls.test.ts +255 -0
- package/src/cloudsql-tls.ts +359 -0
- package/src/compose.ts +193 -24
- package/src/converge-checkpoint.ts +8 -1
- package/src/converge-db-trust.test.ts +237 -0
- package/src/converge-db-trust.ts +212 -0
- package/src/converge-job-gcp.ts +11 -12
- package/src/converge-job-preflight.test.ts +5 -0
- package/src/converge-job-preflight.ts +8 -0
- package/src/converge-job.test.ts +70 -0
- package/src/converge-job.ts +32 -0
- package/src/database-tls-builders.test.ts +56 -0
- package/src/deployed-release.test.ts +107 -40
- package/src/deployed-release.ts +30 -9
- package/src/gateway-env-isolation.test.ts +50 -12
- package/src/gcp-names.ts +56 -0
- package/src/gcp-url-map.test.ts +6 -8
- package/src/gcp-url-map.ts +6 -2
- package/src/index.test.ts +10 -4
- package/src/index.ts +7 -0
- package/src/infra-contract.test.ts +7 -3
- package/src/infra-contract.ts +45 -1
- package/src/install-job.ts +4 -1
- package/src/install-state.ts +33 -4
- package/src/lifecycle.ts +23 -11
- package/src/mcp-auth-proxy-setup.test.ts +305 -0
- package/src/mcp-auth-proxy-setup.ts +374 -0
- package/src/mcp-iap-stacks.test.ts +1 -1
- package/src/media-volume.test.ts +1 -1
- package/src/migration-runner.ts +14 -9
- package/src/migration-targets.ts +12 -0
- package/src/operator-access-stacks.test.ts +1 -1
- package/src/operator-access.test.ts +20 -4
- package/src/operator-access.ts +14 -0
- package/src/pool-budget-stack.ts +15 -0
- package/src/pool-budget-stacks.test.ts +39 -14
- package/src/public-role-isolation.test.ts +18 -8
- package/src/public-role-isolation.ts +31 -17
- package/src/release-contract.ts +3 -0
- package/src/release-manifest.test.ts +25 -0
- package/src/release-manifest.ts +59 -4
- package/src/remote-mcp-stack-config.test.ts +19 -9
- package/src/remote-mcp.test.ts +252 -57
- package/src/remote-mcp.ts +336 -77
- package/src/runtime-secrets.test.ts +37 -14
- package/src/runtime-secrets.ts +87 -27
- package/src/scheduler-setup.test.ts +201 -0
- package/src/scheduler-setup.ts +375 -0
- package/src/seal-key-rotation.test.ts +2 -2
- package/src/seal-key-rotation.ts +25 -25
- package/src/self-hosted-backup.test.ts +1 -0
- package/src/self-hosted-compose.test.ts +180 -6
- package/src/self-hosted-db-tls.test.ts +111 -0
- package/src/self-hosted-db-tls.ts +287 -0
- package/src/self-hosted-release-resolve.test.ts +71 -0
- package/src/self-hosted-release.ts +41 -11
- package/src/self-hosted-roles.integration.test.ts +2 -0
- package/src/self-hosted-roles.test.ts +87 -3
- package/src/self-hosted-roles.ts +101 -3
- package/src/self-hosted-scheduler-interval.test.ts +66 -0
- package/src/self-hosted-scheduler-interval.ts +79 -0
- package/src/self-hosted-start.test.ts +35 -2
- package/src/self-hosted-start.ts +20 -2
- package/src/self-hosted-upgrade.test.ts +104 -14
- package/src/self-hosted-upgrade.ts +123 -31
- package/src/stack-contract-parity.test.ts +79 -12
- package/src/stack-contract.test.ts +199 -31
- package/src/stack-contract.ts +472 -45
- package/src/stack-converge-secrets.test.ts +28 -13
- package/src/stack-converge.test.ts +203 -28
- package/src/stack-converge.ts +92 -30
- package/src/staging-database.test.ts +114 -0
- package/src/staging-database.ts +148 -0
- package/src/state-store.test.ts +2 -1
- package/src/upgrade/app-roll.ts +97 -19
- package/src/upgrade/converge.ts +249 -19
- package/src/upgrade/health.test.ts +63 -25
- package/src/upgrade/health.ts +54 -22
- package/src/upgrade/image-forms.test.ts +34 -0
- package/src/upgrade/image-forms.ts +23 -8
- package/src/upgrade/release-images.test.ts +5 -1
- package/src/upgrade/release-images.ts +22 -6
- package/src/upgrade/upgrade.test.ts +438 -46
- package/src/upgrade/upgrade.ts +64 -6
- package/src/upgrader-gcp.ts +66 -3
- package/src/upgrader-iam-preflight.test.ts +19 -0
- package/src/upgrader-iam-preflight.ts +6 -0
- package/src/upgrader-job.test.ts +101 -27
- package/src/upgrader-job.ts +27 -14
- package/src/upgrader-records.test.ts +97 -12
- package/src/upgrader-records.ts +28 -11
- package/src/upgrader-setup.test.ts +2 -0
- package/src/upgrader-setup.ts +10 -4
- package/src/wizard.ts +19 -0
- package/src/wizards/gcp-cost.test.ts +103 -0
- package/src/wizards/gcp-cost.ts +125 -18
- package/src/wizards/gcp.ts +164 -22
- package/stacks/aws/Pulumi.yaml +1 -1
- package/stacks/aws/index.ts +72 -14
- package/stacks/azure/index.ts +108 -21
- package/stacks/gcp/Pulumi.yaml +1 -1
- package/stacks/gcp/README.md +1 -0
- package/stacks/gcp/index.ts +133 -24
- package/stacks/gcp-firebase/Pulumi.yaml +1 -1
- package/stacks/gcp-firebase/index.ts +212 -34
- package/stacks/self-hosted/Pulumi.yaml +3 -0
- package/stacks/self-hosted/README.md +6 -1
- package/stacks/self-hosted/index.ts +40 -5
package/src/index.test.ts
CHANGED
|
@@ -22,6 +22,7 @@ describe("Caddyfile generator", () => {
|
|
|
22
22
|
tls: "acme",
|
|
23
23
|
adminUpstream: "caelo-admin:5173",
|
|
24
24
|
gatewayUpstream: "caelo-gateway:8090",
|
|
25
|
+
mcpAuthProxyUpstream: "caelo-mcp-auth-proxy:8095",
|
|
25
26
|
domains: [
|
|
26
27
|
{ hostname: "example.com", kind: "public", env: "production" },
|
|
27
28
|
{ hostname: "staging.example.com", kind: "public", env: "staging" },
|
|
@@ -49,6 +50,7 @@ describe("Caddyfile generator", () => {
|
|
|
49
50
|
tls: "acme",
|
|
50
51
|
adminUpstream: "caelo-admin:5173",
|
|
51
52
|
gatewayUpstream: "caelo-gateway:8090",
|
|
53
|
+
mcpAuthProxyUpstream: "caelo-mcp-auth-proxy:8095",
|
|
52
54
|
domains: [],
|
|
53
55
|
});
|
|
54
56
|
expect(out).toContain(":8081 {");
|
|
@@ -64,6 +66,7 @@ describe("Caddy cache policy for content-hashed assets", () => {
|
|
|
64
66
|
tls: "acme",
|
|
65
67
|
adminUpstream: "caelo-admin:5173",
|
|
66
68
|
gatewayUpstream: "caelo-gateway:8090",
|
|
69
|
+
mcpAuthProxyUpstream: "caelo-mcp-auth-proxy:8095",
|
|
67
70
|
domains: [
|
|
68
71
|
{ hostname: "example.com", kind: "public", env: "production" },
|
|
69
72
|
{ hostname: "admin.example.com", kind: "admin", env: "production" },
|
|
@@ -149,8 +152,9 @@ describe("docker-compose generator", () => {
|
|
|
149
152
|
const out = generateDockerCompose({
|
|
150
153
|
domain: "example.com",
|
|
151
154
|
postgresPassword: "supersecret",
|
|
152
|
-
rolePasswords: { admin: "adminpw", public: "publicpw" },
|
|
155
|
+
rolePasswords: { admin: "adminpw", public: "publicpw", publicStaging: "ps" },
|
|
153
156
|
caeloSecretKek: "0".repeat(64),
|
|
157
|
+
dbTlsServerCertSha256: "abababababababababababababababababababababababababababababababab",
|
|
154
158
|
internalSecret: "i".repeat(48),
|
|
155
159
|
anthropicApiKey: "sk-ant-…",
|
|
156
160
|
diskSize: "20Gi",
|
|
@@ -171,8 +175,9 @@ describe("docker-compose generator", () => {
|
|
|
171
175
|
const out = generateDockerCompose({
|
|
172
176
|
domain: "example.com",
|
|
173
177
|
postgresPassword: "supersecret",
|
|
174
|
-
rolePasswords: { admin: "adminpw", public: "publicpw" },
|
|
178
|
+
rolePasswords: { admin: "adminpw", public: "publicpw", publicStaging: "ps" },
|
|
175
179
|
caeloSecretKek: "0".repeat(64),
|
|
180
|
+
dbTlsServerCertSha256: "abababababababababababababababababababababababababababababababab",
|
|
176
181
|
internalSecret: "i".repeat(48),
|
|
177
182
|
diskSize: "20Gi",
|
|
178
183
|
images: RELEASE_IMAGES,
|
|
@@ -181,7 +186,7 @@ describe("docker-compose generator", () => {
|
|
|
181
186
|
});
|
|
182
187
|
const gateway = out.slice(out.indexOf("caelo-gateway:"), out.indexOf("\nvolumes:"));
|
|
183
188
|
expect(gateway).toContain(
|
|
184
|
-
'PUBLIC_DATABASE_URL: "postgres://public_role:publicpw@postgres:5432/cms_public"',
|
|
189
|
+
'PUBLIC_DATABASE_URL: "postgres://public_role:publicpw@postgres:5432/cms_public?sslmode=verify-full&sslrootcert=/etc/caelo/db-ca/self-hosted-ca.pem"',
|
|
185
190
|
);
|
|
186
191
|
expect(gateway).not.toMatch(
|
|
187
192
|
/ADMIN_DATABASE|GATEWAY_DATABASE|cms_admin|admin_role|gateway_role|adminpw|gatewaypw|supersecret|CAELO_SECRET_KEK/,
|
|
@@ -196,8 +201,9 @@ describe("docker-compose generator", () => {
|
|
|
196
201
|
const out = generateDockerCompose({
|
|
197
202
|
domain: "example.com",
|
|
198
203
|
postgresPassword: 'pa"ss',
|
|
199
|
-
rolePasswords: { admin: "a", public: "b" },
|
|
204
|
+
rolePasswords: { admin: "a", public: "b", publicStaging: "ps" },
|
|
200
205
|
caeloSecretKek: "0".repeat(64),
|
|
206
|
+
dbTlsServerCertSha256: "abababababababababababababababababababababababababababababababab",
|
|
201
207
|
internalSecret: "i".repeat(48),
|
|
202
208
|
diskSize: "1Gi",
|
|
203
209
|
images: RELEASE_IMAGES,
|
package/src/index.ts
CHANGED
|
@@ -46,12 +46,18 @@ export {
|
|
|
46
46
|
selfHostedCdnCopy,
|
|
47
47
|
} from "./cdn-copy.js";
|
|
48
48
|
export { type ComposeSpec, generateDockerCompose, type RolePasswords } from "./compose.js";
|
|
49
|
+
export {
|
|
50
|
+
type ConvergeDatabaseTarget,
|
|
51
|
+
convergeDatabaseTarget,
|
|
52
|
+
serverIdentityProblem,
|
|
53
|
+
} from "./converge-db-trust.js";
|
|
49
54
|
export {
|
|
50
55
|
type ConvergeClaim,
|
|
51
56
|
type ConvergeJobDeps,
|
|
52
57
|
type ConvergeQueue,
|
|
53
58
|
type ConvergeUpgradeOutcome,
|
|
54
59
|
runConvergeJob,
|
|
60
|
+
type SecureDatabaseResult,
|
|
55
61
|
} from "./converge-job.js";
|
|
56
62
|
export { convergeExecutionNameError, gcpConvergeDeps } from "./converge-job-gcp.js";
|
|
57
63
|
export { INFRA_CONTRACT_VERSION } from "./infra-contract.js";
|
|
@@ -96,6 +102,7 @@ export {
|
|
|
96
102
|
type RequestDecision,
|
|
97
103
|
} from "./upgrader-assess.js";
|
|
98
104
|
export {
|
|
105
|
+
convergeDatabaseHost,
|
|
99
106
|
gcpUpgraderDeps,
|
|
100
107
|
type UpgraderPlacement,
|
|
101
108
|
upgraderDatabaseHost,
|
|
@@ -20,8 +20,8 @@ describe("infrastructure contract steps", () => {
|
|
|
20
20
|
);
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
-
it("is at
|
|
24
|
-
expect(INFRA_CONTRACT_VERSION).toBe(
|
|
23
|
+
it("is at 18: public_role revoke (3), URL-map redirects role (4), no gateway cms_admin login (5), ops-bucket list (6), gateway proxy hops (7), quality-audit job (8), converge job (9), remote MCP (10), Google sign-in (11), project-level sign-in client (12), edge security headers (13), capture job (14), database verify-full TLS (15), MCP-Auth-Proxy (16), staging database (17), scheduler tick (18)", () => {
|
|
24
|
+
expect(INFRA_CONTRACT_VERSION).toBe(18);
|
|
25
25
|
expect(INFRA_CONTRACT_STEPS[3]).toContain("#633");
|
|
26
26
|
expect(INFRA_CONTRACT_STEPS[4]).toContain("#587");
|
|
27
27
|
expect(INFRA_CONTRACT_STEPS[5]).toContain("#635");
|
|
@@ -34,6 +34,10 @@ describe("infrastructure contract steps", () => {
|
|
|
34
34
|
expect(INFRA_CONTRACT_STEPS[12]).toContain("project's IAP settings");
|
|
35
35
|
expect(INFRA_CONTRACT_STEPS[13]).toContain("#891");
|
|
36
36
|
expect(INFRA_CONTRACT_STEPS[14]).toContain("#1217");
|
|
37
|
+
expect(INFRA_CONTRACT_STEPS[15]).toContain("#1338");
|
|
38
|
+
expect(INFRA_CONTRACT_STEPS[16]).toContain("#1328");
|
|
39
|
+
expect(INFRA_CONTRACT_STEPS[17]).toContain("#1329");
|
|
40
|
+
expect(INFRA_CONTRACT_STEPS[18]).toContain("#1140");
|
|
37
41
|
});
|
|
38
42
|
|
|
39
43
|
it("lists the pending steps oldest first", () => {
|
|
@@ -44,6 +48,6 @@ describe("infrastructure contract steps", () => {
|
|
|
44
48
|
});
|
|
45
49
|
|
|
46
50
|
it("names a version a newer release added by number", () => {
|
|
47
|
-
expect(infraStepsText(
|
|
51
|
+
expect(infraStepsText(18, 19)).toBe("infrastructure step 19 (see that release's notes)");
|
|
48
52
|
});
|
|
49
53
|
});
|
package/src/infra-contract.ts
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* whose app-roll references infrastructure an install does not have yet fails
|
|
23
23
|
* at roll time, after migrations ran.
|
|
24
24
|
*/
|
|
25
|
-
export const INFRA_CONTRACT_VERSION =
|
|
25
|
+
export const INFRA_CONTRACT_VERSION = 18;
|
|
26
26
|
|
|
27
27
|
// History (why each bump happened — an install below a number needs the
|
|
28
28
|
// converge that introduced it):
|
|
@@ -110,6 +110,46 @@ export const INFRA_CONTRACT_VERSION = 14;
|
|
|
110
110
|
// CAELO_CAPTURE_BUCKET / CAELO_MEDIA_BUCKET on the admin. The new admin
|
|
111
111
|
// runs no browser itself on GCP and the app-roll moves the job's image,
|
|
112
112
|
// so it must exist before an in-cloud upgrader rolls onto it.
|
|
113
|
+
// 15 — #1338: verify-full TLS to Cloud SQL. The instance moves to the
|
|
114
|
+
// shared server CA (a patch plus a server-certificate rotation) and
|
|
115
|
+
// refuses plaintext, a private Cloud DNS zone resolves its DNS name in
|
|
116
|
+
// the VPC, and the services dial that name (cloudsql-tls.ts). The new
|
|
117
|
+
// images refuse any database URL weaker than verify-full, and the
|
|
118
|
+
// in-cloud upgrader may neither patch the instance nor create a DNS
|
|
119
|
+
// zone, so it must not roll an install onto them first.
|
|
120
|
+
// 16 — #1328: the MCP-Auth-Proxy, remote MCP's broker as a service of its
|
|
121
|
+
// own (no database, its own image). Its service account with
|
|
122
|
+
// secretAccessor on exactly the Google sign-in client and the seal
|
|
123
|
+
// key, and the upgrader's actAs on it. On `gcp-firebase` the visitor
|
|
124
|
+
// gateway moves to a new Cloud Run service (`caelo-<env>-data-gateway`,
|
|
125
|
+
// public invoker, the admin's run.viewer for the Firebase rewrite) and
|
|
126
|
+
// the old `gateway` service, whose run.app URL every connector holds
|
|
127
|
+
// (E13 a), becomes the proxy: new image, new account, no VPC, no
|
|
128
|
+
// database env. On `gcp` the proxy is a new service behind its own
|
|
129
|
+
// serverless NEG, backend service and Cloud Armor policy (the MCP rule
|
|
130
|
+
// moves there) and the URL map sends the MCP paths to it. New
|
|
131
|
+
// services, accounts, IAM and load-balancer resources — none of which
|
|
132
|
+
// the in-cloud upgrader may create, and the app-roll rolls three
|
|
133
|
+
// services from now on.
|
|
134
|
+
// 17 — #1329: staging's own database. The Cloud SQL database
|
|
135
|
+
// `cms_public_staging`, the Admin API user `public_staging_role` (its
|
|
136
|
+
// password the new CLI-generated secret `public-staging-role-password`)
|
|
137
|
+
// and its membership revoke; the admin's PUBLIC_STAGING_ADMIN_DATABASE_URL
|
|
138
|
+
// and the gateway's CAELO_GATEWAY_ENVIRONMENT. The in-cloud upgrader
|
|
139
|
+
// may create no database, user or secret, and the new admin and
|
|
140
|
+
// gateway refuse to start without them. Additive only (converge
|
|
141
|
+
// release 1 of the gateway hardening): nothing is served from the
|
|
142
|
+
// staging database yet, so rolling back stays harmless.
|
|
143
|
+
// 18 — #1140: the scheduler tick (scheduler-setup.ts). Its service account
|
|
144
|
+
// (token creator on itself, workflows.invoker, logWriter, IAP access to
|
|
145
|
+
// the admin), the Cloud Workflows workflow that signs its IAP JWT and
|
|
146
|
+
// calls the admin's /api/internal/scheduler/tick, the one Cloud
|
|
147
|
+
// Scheduler job that starts it every schedulerIntervalMinutes, the
|
|
148
|
+
// operator-access job's CAELO_OPERATOR_ACCESS_IAP_SERVICE_ACCOUNTS (so
|
|
149
|
+
// its sync keeps the account on IAP) and CAELO_SCHEDULER_SERVICE_ACCOUNT
|
|
150
|
+
// on the admin. The new admin runs its periodic work and plugin workers
|
|
151
|
+
// only on that tick, so an in-cloud upgrader must not roll an install
|
|
152
|
+
// onto it before the tick exists.
|
|
113
153
|
|
|
114
154
|
/**
|
|
115
155
|
* What each contract version adds, in operator terms — the upgrader's
|
|
@@ -131,6 +171,10 @@ export const INFRA_CONTRACT_STEPS: Readonly<Record<number, string>> = {
|
|
|
131
171
|
12: "Google sign-in at project level: the operator-access job's permission to set the sign-in client in the project's IAP settings (#914)",
|
|
132
172
|
13: "the public site's security headers at the edge: nosniff on every file, uploaded SVGs no longer run as documents on the site's origin, and a one-time CDN purge (#891)",
|
|
133
173
|
14: "the capture job that takes server-side screenshots outside the admin, its service account, bucket and grants (#1217)",
|
|
174
|
+
15: "verified TLS to the database: Cloud SQL's shared server CA, encrypted connections only, and a private DNS name the services dial (#1338)",
|
|
175
|
+
16: "the MCP sign-in service as its own Cloud Run service with its own account (no database access), the visitor gateway as its own service on Firebase installs, and on Google Cloud load-balancer installs the sign-in service's backend and Cloud Armor rule (#1328)",
|
|
176
|
+
17: "the staging site's own database and its gateway login, kept apart from the live data (#1329)",
|
|
177
|
+
18: "the scheduler tick that runs the admin's periodic work and plugin workers every few minutes: its service account, workflow and Cloud Scheduler job, and its IAP access (#1140)",
|
|
134
178
|
};
|
|
135
179
|
|
|
136
180
|
/**
|
package/src/install-job.ts
CHANGED
|
@@ -65,13 +65,16 @@ export const OPS_IMAGE_REPOSITORY =
|
|
|
65
65
|
* Roles the provisioner needs on top of {@link PROVISIONER_ROLE_LIST} when it
|
|
66
66
|
* runs the install job instead of the operator: the operator-access sync job
|
|
67
67
|
* creates a project custom role and a Cloud Scheduler job (operator-access.ts),
|
|
68
|
-
*
|
|
68
|
+
* the scheduler tick deploys a Cloud Workflows workflow (scheduler-setup.ts,
|
|
69
|
+
* #1140; the converge job gets the same roles, converge-job-setup.ts), and
|
|
70
|
+
* the job's own output has to reach Cloud Logging so the terminal can
|
|
69
71
|
* tail it. Granted only to installs that use the job. Not an escalation: the
|
|
70
72
|
* provisioner already holds `resourcemanager.projectIamAdmin`.
|
|
71
73
|
*/
|
|
72
74
|
export const INSTALL_JOB_ROLES = [
|
|
73
75
|
"roles/iam.roleAdmin",
|
|
74
76
|
"roles/cloudscheduler.admin",
|
|
77
|
+
"roles/workflows.editor",
|
|
75
78
|
"roles/logging.logWriter",
|
|
76
79
|
] as const;
|
|
77
80
|
|
package/src/install-state.ts
CHANGED
|
@@ -115,6 +115,13 @@ export interface InstallMetadata {
|
|
|
115
115
|
* run while it is lower than the release's (upgrade/converge.ts).
|
|
116
116
|
*/
|
|
117
117
|
infraContractVersion?: number;
|
|
118
|
+
/**
|
|
119
|
+
* #1140 — the `schedulerIntervalMinutes` knob: how often the one Cloud
|
|
120
|
+
* Scheduler job calls the admin's tick (1–15 minutes; `--scheduler-
|
|
121
|
+
* interval-minutes` on the wizard). Absent: the default (5,
|
|
122
|
+
* stack-contract.ts SCHEDULER_INTERVAL_MINUTES).
|
|
123
|
+
*/
|
|
124
|
+
schedulerIntervalMinutes?: number;
|
|
118
125
|
}
|
|
119
126
|
|
|
120
127
|
/** The install's staging host: its recorded setting, else the default. */
|
|
@@ -155,10 +162,25 @@ export function recordableStagingHost(host: string): string | null {
|
|
|
155
162
|
export interface ImageDigests {
|
|
156
163
|
readonly admin: string;
|
|
157
164
|
readonly gateway: string;
|
|
165
|
+
/**
|
|
166
|
+
* #1328 — the MCP-Auth-Proxy's. Absent on installs recorded before it
|
|
167
|
+
* existed: their first upgrade to a release with it records it, and a
|
|
168
|
+
* stack run without it deploys the release tag's proxy image.
|
|
169
|
+
*/
|
|
170
|
+
readonly "mcp-auth-proxy"?: string;
|
|
158
171
|
}
|
|
159
172
|
|
|
160
173
|
const DIGEST = /^sha256:[0-9a-f]{64}$/;
|
|
161
174
|
|
|
175
|
+
/** {@link ImageDigests} without the keys that are absent (a JSON-stable copy). */
|
|
176
|
+
function imageDigestsRecord(d: ImageDigests): ImageDigests {
|
|
177
|
+
return {
|
|
178
|
+
admin: d.admin,
|
|
179
|
+
gateway: d.gateway,
|
|
180
|
+
...(d["mcp-auth-proxy"] ? { "mcp-auth-proxy": d["mcp-auth-proxy"] } : {}),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
162
184
|
/**
|
|
163
185
|
* The image digests recorded for an install, or null when none are. Throws
|
|
164
186
|
* on a malformed record rather than deploying a guess.
|
|
@@ -166,7 +188,12 @@ const DIGEST = /^sha256:[0-9a-f]{64}$/;
|
|
|
166
188
|
export function recordedImageDigests(meta: InstallMetadata): ImageDigests | null {
|
|
167
189
|
const d = meta.imageDigests;
|
|
168
190
|
if (d === undefined) return null;
|
|
169
|
-
|
|
191
|
+
const proxy = d["mcp-auth-proxy"];
|
|
192
|
+
if (
|
|
193
|
+
!DIGEST.test(d.admin ?? "") ||
|
|
194
|
+
!DIGEST.test(d.gateway ?? "") ||
|
|
195
|
+
(proxy !== undefined && !DIGEST.test(proxy))
|
|
196
|
+
) {
|
|
170
197
|
throw new Error(
|
|
171
198
|
`install.json imageDigests is malformed (${JSON.stringify(d)}); fix or remove it, then re-run.`,
|
|
172
199
|
);
|
|
@@ -211,15 +238,17 @@ export function recordImageDigests(
|
|
|
211
238
|
// drop it — a stale one would be worse than none (the upgrader job
|
|
212
239
|
// refuses on none and judges downgrades by it).
|
|
213
240
|
const same =
|
|
214
|
-
meta.imageDigests?.admin === digests.admin &&
|
|
241
|
+
meta.imageDigests?.admin === digests.admin &&
|
|
242
|
+
meta.imageDigests?.gateway === digests.gateway &&
|
|
243
|
+
meta.imageDigests?.["mcp-auth-proxy"] === digests["mcp-auth-proxy"];
|
|
215
244
|
const { releaseVersion: previous, platformDigests: previousPlatform, ...rest } = meta;
|
|
216
245
|
const version = releaseVersion ?? (same ? previous : undefined);
|
|
217
246
|
// The platform forms belong to their indexes just as the version does.
|
|
218
247
|
const platform = platformDigests ?? (same ? previousPlatform : undefined);
|
|
219
248
|
writeMetadata(installId, {
|
|
220
249
|
...rest,
|
|
221
|
-
imageDigests:
|
|
222
|
-
...(platform ? { platformDigests:
|
|
250
|
+
imageDigests: imageDigestsRecord(digests),
|
|
251
|
+
...(platform ? { platformDigests: imageDigestsRecord(platform) } : {}),
|
|
223
252
|
...(version ? { releaseVersion: version } : {}),
|
|
224
253
|
});
|
|
225
254
|
}
|
package/src/lifecycle.ts
CHANGED
|
@@ -60,6 +60,7 @@ import {
|
|
|
60
60
|
} from "./runtime-secrets.js";
|
|
61
61
|
import { finishSealKeyRotation, startSealKeyRotation } from "./seal-key-rotation.js";
|
|
62
62
|
import { selfCommand } from "./self-command.js";
|
|
63
|
+
import { CLOUD_RUN_SLUGS, type CloudRunSlug, cloudRunServicePrefix } from "./stack-contract.js";
|
|
63
64
|
import {
|
|
64
65
|
backendShellEnv,
|
|
65
66
|
localStateNotice,
|
|
@@ -640,6 +641,9 @@ async function upgradeLockedInstall(
|
|
|
640
641
|
domain: meta.domain,
|
|
641
642
|
stagingHost,
|
|
642
643
|
ownerEmail: meta.ownerEmail,
|
|
644
|
+
...(meta.schedulerIntervalMinutes !== undefined
|
|
645
|
+
? { schedulerIntervalMinutes: meta.schedulerIntervalMinutes }
|
|
646
|
+
: {}),
|
|
643
647
|
targetTag,
|
|
644
648
|
infraContractVersion: INFRA_CONTRACT_VERSION,
|
|
645
649
|
skipVerify: opts.skipVerify === true,
|
|
@@ -720,6 +724,7 @@ async function gcpHealthProbe(
|
|
|
720
724
|
domain: install.domain,
|
|
721
725
|
adminServiceUrl: urls.admin as string,
|
|
722
726
|
gatewayServiceUrl: urls.gateway as string,
|
|
727
|
+
mcpAuthProxyServiceUrl: urls["mcp-auth-proxy"] as string,
|
|
723
728
|
},
|
|
724
729
|
{ run, http, sleep: realSleep, accessJustChanged: context.accessJustChanged },
|
|
725
730
|
),
|
|
@@ -880,23 +885,29 @@ export async function rotateSecretCommand(
|
|
|
880
885
|
}
|
|
881
886
|
|
|
882
887
|
if (name === SEAL_KEY_SECRET) {
|
|
883
|
-
|
|
888
|
+
// #1328 — the broker, and with it the seal key, lives in the MCP-Auth-Proxy.
|
|
889
|
+
const proxyPrefix = cloudRunServicePrefix(meta.provider, GCP_STACK_ENV, "mcp-auth-proxy");
|
|
890
|
+
const proxy = await resolveGcpResourceName(
|
|
884
891
|
gcloud,
|
|
885
892
|
"run-service",
|
|
886
|
-
|
|
893
|
+
proxyPrefix,
|
|
887
894
|
meta.projectId,
|
|
888
895
|
region,
|
|
889
896
|
);
|
|
890
|
-
if (
|
|
897
|
+
if (proxy.status !== "found") {
|
|
891
898
|
log.error(
|
|
892
899
|
red(
|
|
893
|
-
`${lookupFailure(
|
|
900
|
+
`${lookupFailure(proxy, `${proxyPrefix}* Cloud Run service`, "operator")} — nothing rotated`,
|
|
894
901
|
),
|
|
895
902
|
);
|
|
896
903
|
return;
|
|
897
904
|
}
|
|
898
|
-
const
|
|
899
|
-
|
|
905
|
+
const target = {
|
|
906
|
+
projectId: meta.projectId,
|
|
907
|
+
region,
|
|
908
|
+
env: GCP_STACK_ENV,
|
|
909
|
+
proxyService: proxy.name,
|
|
910
|
+
};
|
|
900
911
|
const report = opts.finish
|
|
901
912
|
? await finishSealKeyRotation(target, {}, { now: opts.now === true })
|
|
902
913
|
: await startSealKeyRotation(target);
|
|
@@ -910,19 +921,20 @@ export async function rotateSecretCommand(
|
|
|
910
921
|
|
|
911
922
|
const s = spinner();
|
|
912
923
|
s.start(`Rotating ${secret}...`);
|
|
913
|
-
const services: Partial<Record<
|
|
914
|
-
for (const slug of
|
|
924
|
+
const services: Partial<Record<CloudRunSlug, string>> = {};
|
|
925
|
+
for (const slug of CLOUD_RUN_SLUGS) {
|
|
926
|
+
const prefix = cloudRunServicePrefix(meta.provider, GCP_STACK_ENV, slug);
|
|
915
927
|
const service = await resolveGcpResourceName(
|
|
916
928
|
gcloud,
|
|
917
929
|
"run-service",
|
|
918
|
-
|
|
930
|
+
prefix,
|
|
919
931
|
meta.projectId,
|
|
920
932
|
region,
|
|
921
933
|
);
|
|
922
934
|
if (service.status !== "found") {
|
|
923
935
|
s.stop(
|
|
924
936
|
red(
|
|
925
|
-
`${lookupFailure(service,
|
|
937
|
+
`${lookupFailure(service, `${prefix}* Cloud Run service`, "operator")} — nothing rotated`,
|
|
926
938
|
),
|
|
927
939
|
);
|
|
928
940
|
return;
|
|
@@ -952,7 +964,7 @@ export async function rotateSecretCommand(
|
|
|
952
964
|
projectId: meta.projectId,
|
|
953
965
|
region,
|
|
954
966
|
env: GCP_STACK_ENV,
|
|
955
|
-
services: services as Record<
|
|
967
|
+
services: services as Record<CloudRunSlug, string>,
|
|
956
968
|
...(sqlInstance ? { sqlInstance } : {}),
|
|
957
969
|
},
|
|
958
970
|
secret,
|