@caelo-cms/provisioning 0.11.9 → 0.11.10

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 (261) hide show
  1. package/dist/admin-domain.d.ts +10 -1
  2. package/dist/admin-domain.d.ts.map +1 -1
  3. package/dist/admin-domain.js +13 -3
  4. package/dist/admin-domain.js.map +1 -1
  5. package/dist/adopt-existing.d.ts +6 -1
  6. package/dist/adopt-existing.d.ts.map +1 -1
  7. package/dist/adopt-existing.js +86 -0
  8. package/dist/adopt-existing.js.map +1 -1
  9. package/dist/agent/command.d.ts +20 -0
  10. package/dist/agent/command.d.ts.map +1 -1
  11. package/dist/agent/command.js +32 -9
  12. package/dist/agent/command.js.map +1 -1
  13. package/dist/agent/run.d.ts +2 -0
  14. package/dist/agent/run.d.ts.map +1 -1
  15. package/dist/agent/run.js +5 -1
  16. package/dist/agent/run.js.map +1 -1
  17. package/dist/agent-db.js +44 -2
  18. package/dist/aws-task-roles.d.ts +4 -2
  19. package/dist/aws-task-roles.d.ts.map +1 -1
  20. package/dist/aws-task-roles.js +4 -1
  21. package/dist/aws-task-roles.js.map +1 -1
  22. package/dist/caddy.d.ts +21 -4
  23. package/dist/caddy.d.ts.map +1 -1
  24. package/dist/caddy.js +27 -3
  25. package/dist/caddy.js.map +1 -1
  26. package/dist/cli.js +12 -3
  27. package/dist/cli.js.map +1 -1
  28. package/dist/cloudsql-tls.d.ts +63 -0
  29. package/dist/cloudsql-tls.d.ts.map +1 -0
  30. package/dist/cloudsql-tls.js +289 -0
  31. package/dist/cloudsql-tls.js.map +1 -0
  32. package/dist/compose.d.ts +29 -6
  33. package/dist/compose.d.ts.map +1 -1
  34. package/dist/compose.js +95 -23
  35. package/dist/compose.js.map +1 -1
  36. package/dist/converge-checkpoint.d.ts +1 -0
  37. package/dist/converge-checkpoint.d.ts.map +1 -1
  38. package/dist/converge-checkpoint.js +8 -1
  39. package/dist/converge-checkpoint.js.map +1 -1
  40. package/dist/converge-job-gcp.d.ts.map +1 -1
  41. package/dist/converge-job-gcp.js +2 -11
  42. package/dist/converge-job-gcp.js.map +1 -1
  43. package/dist/deployed-release.d.ts +4 -1
  44. package/dist/deployed-release.d.ts.map +1 -1
  45. package/dist/deployed-release.js +18 -8
  46. package/dist/deployed-release.js.map +1 -1
  47. package/dist/gcp-names.d.ts +21 -0
  48. package/dist/gcp-names.d.ts.map +1 -1
  49. package/dist/gcp-names.js +24 -0
  50. package/dist/gcp-names.js.map +1 -1
  51. package/dist/gcp-url-map.d.ts.map +1 -1
  52. package/dist/gcp-url-map.js +6 -2
  53. package/dist/gcp-url-map.js.map +1 -1
  54. package/dist/index.d.ts +1 -1
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +1 -1
  57. package/dist/index.js.map +1 -1
  58. package/dist/infra-contract.d.ts +1 -1
  59. package/dist/infra-contract.d.ts.map +1 -1
  60. package/dist/infra-contract.js +24 -1
  61. package/dist/infra-contract.js.map +1 -1
  62. package/dist/install-state.d.ts +6 -0
  63. package/dist/install-state.d.ts.map +1 -1
  64. package/dist/install-state.js +17 -4
  65. package/dist/install-state.js.map +1 -1
  66. package/dist/lifecycle.d.ts.map +1 -1
  67. package/dist/lifecycle.js +17 -8
  68. package/dist/lifecycle.js.map +1 -1
  69. package/dist/mcp-auth-proxy-setup.d.ts +48 -0
  70. package/dist/mcp-auth-proxy-setup.d.ts.map +1 -0
  71. package/dist/mcp-auth-proxy-setup.js +280 -0
  72. package/dist/mcp-auth-proxy-setup.js.map +1 -0
  73. package/dist/release-manifest.d.ts +25 -1
  74. package/dist/release-manifest.d.ts.map +1 -1
  75. package/dist/release-manifest.js +36 -3
  76. package/dist/release-manifest.js.map +1 -1
  77. package/dist/remote-mcp.d.ts +55 -18
  78. package/dist/remote-mcp.d.ts.map +1 -1
  79. package/dist/remote-mcp.js +307 -77
  80. package/dist/remote-mcp.js.map +1 -1
  81. package/dist/runtime-secrets.d.ts +9 -0
  82. package/dist/runtime-secrets.d.ts.map +1 -1
  83. package/dist/runtime-secrets.js +21 -10
  84. package/dist/runtime-secrets.js.map +1 -1
  85. package/dist/seal-key-rotation.d.ts +7 -7
  86. package/dist/seal-key-rotation.d.ts.map +1 -1
  87. package/dist/seal-key-rotation.js +22 -22
  88. package/dist/seal-key-rotation.js.map +1 -1
  89. package/dist/self-hosted-db-tls.d.ts +37 -0
  90. package/dist/self-hosted-db-tls.d.ts.map +1 -0
  91. package/dist/self-hosted-db-tls.js +220 -0
  92. package/dist/self-hosted-db-tls.js.map +1 -0
  93. package/dist/self-hosted-release.d.ts +3 -1
  94. package/dist/self-hosted-release.d.ts.map +1 -1
  95. package/dist/self-hosted-release.js +33 -9
  96. package/dist/self-hosted-release.js.map +1 -1
  97. package/dist/self-hosted-roles.d.ts +34 -0
  98. package/dist/self-hosted-roles.d.ts.map +1 -1
  99. package/dist/self-hosted-roles.js +52 -0
  100. package/dist/self-hosted-roles.js.map +1 -1
  101. package/dist/self-hosted-start.d.ts +0 -21
  102. package/dist/self-hosted-start.d.ts.map +1 -1
  103. package/dist/self-hosted-start.js +39 -1
  104. package/dist/self-hosted-start.js.map +1 -1
  105. package/dist/self-hosted-upgrade.d.ts +15 -6
  106. package/dist/self-hosted-upgrade.d.ts.map +1 -1
  107. package/dist/self-hosted-upgrade.js +72 -23
  108. package/dist/self-hosted-upgrade.js.map +1 -1
  109. package/dist/stack-contract.d.ts +170 -25
  110. package/dist/stack-contract.d.ts.map +1 -1
  111. package/dist/stack-contract.js +314 -37
  112. package/dist/stack-contract.js.map +1 -1
  113. package/dist/stack-converge.d.ts +31 -0
  114. package/dist/stack-converge.d.ts.map +1 -1
  115. package/dist/stack-converge.js +71 -30
  116. package/dist/stack-converge.js.map +1 -1
  117. package/dist/upgrade/app-roll.d.ts +25 -4
  118. package/dist/upgrade/app-roll.d.ts.map +1 -1
  119. package/dist/upgrade/app-roll.js +63 -17
  120. package/dist/upgrade/app-roll.js.map +1 -1
  121. package/dist/upgrade/converge.d.ts.map +1 -1
  122. package/dist/upgrade/converge.js +99 -12
  123. package/dist/upgrade/converge.js.map +1 -1
  124. package/dist/upgrade/health.d.ts +31 -7
  125. package/dist/upgrade/health.d.ts.map +1 -1
  126. package/dist/upgrade/health.js +41 -17
  127. package/dist/upgrade/health.js.map +1 -1
  128. package/dist/upgrade/image-forms.d.ts +1 -1
  129. package/dist/upgrade/image-forms.d.ts.map +1 -1
  130. package/dist/upgrade/image-forms.js +24 -7
  131. package/dist/upgrade/image-forms.js.map +1 -1
  132. package/dist/upgrade/release-images.d.ts +12 -3
  133. package/dist/upgrade/release-images.d.ts.map +1 -1
  134. package/dist/upgrade/release-images.js +13 -4
  135. package/dist/upgrade/release-images.js.map +1 -1
  136. package/dist/upgrade/upgrade.d.ts +13 -3
  137. package/dist/upgrade/upgrade.d.ts.map +1 -1
  138. package/dist/upgrade/upgrade.js +34 -2
  139. package/dist/upgrade/upgrade.js.map +1 -1
  140. package/dist/upgrader-gcp.d.ts +12 -0
  141. package/dist/upgrader-gcp.d.ts.map +1 -1
  142. package/dist/upgrader-gcp.js +49 -1
  143. package/dist/upgrader-gcp.js.map +1 -1
  144. package/dist/upgrader-iam-preflight.d.ts.map +1 -1
  145. package/dist/upgrader-iam-preflight.js +6 -1
  146. package/dist/upgrader-iam-preflight.js.map +1 -1
  147. package/dist/upgrader-job.d.ts +1 -1
  148. package/dist/upgrader-job.d.ts.map +1 -1
  149. package/dist/upgrader-job.js +20 -14
  150. package/dist/upgrader-job.js.map +1 -1
  151. package/dist/upgrader-records.d.ts +1 -1
  152. package/dist/upgrader-records.d.ts.map +1 -1
  153. package/dist/upgrader-records.js +26 -7
  154. package/dist/upgrader-records.js.map +1 -1
  155. package/dist/upgrader-setup.d.ts.map +1 -1
  156. package/dist/upgrader-setup.js +10 -5
  157. package/dist/upgrader-setup.js.map +1 -1
  158. package/dist/wizards/gcp-cost.d.ts.map +1 -1
  159. package/dist/wizards/gcp-cost.js +22 -7
  160. package/dist/wizards/gcp-cost.js.map +1 -1
  161. package/dist/wizards/gcp.d.ts.map +1 -1
  162. package/dist/wizards/gcp.js +43 -17
  163. package/dist/wizards/gcp.js.map +1 -1
  164. package/package.json +2 -2
  165. package/src/admin-domain.test.ts +9 -8
  166. package/src/admin-domain.ts +13 -3
  167. package/src/admin-memory.test.ts +1 -0
  168. package/src/adopt-existing.test.ts +39 -0
  169. package/src/adopt-existing.ts +83 -1
  170. package/src/agent/command.test.ts +49 -1
  171. package/src/agent/command.ts +36 -9
  172. package/src/agent/run.test.ts +19 -0
  173. package/src/agent/run.ts +11 -2
  174. package/src/aws-task-roles.ts +5 -2
  175. package/src/caddy-redirects.docker.test.ts +2 -0
  176. package/src/caddy-redirects.test.ts +3 -0
  177. package/src/caddy-validate.test.ts +7 -1
  178. package/src/caddy.test.ts +39 -1
  179. package/src/caddy.ts +36 -4
  180. package/src/checkpoint-secrets.test.ts +14 -6
  181. package/src/cli.ts +12 -1
  182. package/src/cloudsql-tls.test.ts +225 -0
  183. package/src/cloudsql-tls.ts +352 -0
  184. package/src/compose.ts +125 -24
  185. package/src/converge-checkpoint.ts +8 -1
  186. package/src/converge-job-gcp.ts +2 -11
  187. package/src/database-tls-builders.test.ts +55 -0
  188. package/src/deployed-release.test.ts +104 -40
  189. package/src/deployed-release.ts +30 -9
  190. package/src/gateway-env-isolation.test.ts +10 -5
  191. package/src/gcp-names.ts +31 -0
  192. package/src/gcp-url-map.test.ts +6 -8
  193. package/src/gcp-url-map.ts +6 -2
  194. package/src/index.test.ts +7 -1
  195. package/src/index.ts +1 -0
  196. package/src/infra-contract.test.ts +5 -3
  197. package/src/infra-contract.ts +24 -1
  198. package/src/install-state.ts +26 -4
  199. package/src/lifecycle.ts +20 -11
  200. package/src/mcp-auth-proxy-setup.test.ts +305 -0
  201. package/src/mcp-auth-proxy-setup.ts +374 -0
  202. package/src/mcp-iap-stacks.test.ts +1 -1
  203. package/src/media-volume.test.ts +1 -1
  204. package/src/operator-access-stacks.test.ts +1 -1
  205. package/src/operator-access.test.ts +5 -4
  206. package/src/pool-budget-stacks.test.ts +1 -1
  207. package/src/release-manifest.test.ts +25 -0
  208. package/src/release-manifest.ts +59 -4
  209. package/src/remote-mcp-stack-config.test.ts +19 -9
  210. package/src/remote-mcp.test.ts +252 -57
  211. package/src/remote-mcp.ts +336 -77
  212. package/src/runtime-secrets.test.ts +20 -7
  213. package/src/runtime-secrets.ts +50 -9
  214. package/src/seal-key-rotation.test.ts +2 -2
  215. package/src/seal-key-rotation.ts +25 -25
  216. package/src/self-hosted-compose.test.ts +108 -5
  217. package/src/self-hosted-db-tls.test.ts +111 -0
  218. package/src/self-hosted-db-tls.ts +287 -0
  219. package/src/self-hosted-release-resolve.test.ts +71 -0
  220. package/src/self-hosted-release.ts +41 -11
  221. package/src/self-hosted-roles.test.ts +54 -0
  222. package/src/self-hosted-roles.ts +58 -0
  223. package/src/self-hosted-start.test.ts +34 -2
  224. package/src/self-hosted-start.ts +20 -2
  225. package/src/self-hosted-upgrade.test.ts +103 -14
  226. package/src/self-hosted-upgrade.ts +115 -29
  227. package/src/stack-contract-parity.test.ts +79 -12
  228. package/src/stack-contract.test.ts +169 -29
  229. package/src/stack-contract.ts +362 -42
  230. package/src/stack-converge-secrets.test.ts +26 -13
  231. package/src/stack-converge.test.ts +199 -26
  232. package/src/stack-converge.ts +92 -30
  233. package/src/state-store.test.ts +2 -1
  234. package/src/upgrade/app-roll.ts +97 -19
  235. package/src/upgrade/converge.ts +120 -11
  236. package/src/upgrade/health.test.ts +63 -25
  237. package/src/upgrade/health.ts +54 -22
  238. package/src/upgrade/image-forms.test.ts +34 -0
  239. package/src/upgrade/image-forms.ts +23 -8
  240. package/src/upgrade/release-images.test.ts +5 -1
  241. package/src/upgrade/release-images.ts +22 -6
  242. package/src/upgrade/upgrade.test.ts +353 -44
  243. package/src/upgrade/upgrade.ts +55 -6
  244. package/src/upgrader-gcp.ts +65 -3
  245. package/src/upgrader-iam-preflight.test.ts +19 -0
  246. package/src/upgrader-iam-preflight.ts +6 -0
  247. package/src/upgrader-job.test.ts +101 -27
  248. package/src/upgrader-job.ts +27 -14
  249. package/src/upgrader-records.test.ts +97 -12
  250. package/src/upgrader-records.ts +28 -11
  251. package/src/upgrader-setup.test.ts +2 -0
  252. package/src/upgrader-setup.ts +10 -4
  253. package/src/wizards/gcp-cost.test.ts +50 -0
  254. package/src/wizards/gcp-cost.ts +24 -7
  255. package/src/wizards/gcp.ts +55 -14
  256. package/stacks/aws/index.ts +32 -14
  257. package/stacks/azure/index.ts +57 -18
  258. package/stacks/gcp/index.ts +83 -23
  259. package/stacks/gcp-firebase/index.ts +162 -33
  260. package/stacks/self-hosted/README.md +2 -1
  261. package/stacks/self-hosted/index.ts +11 -1
@@ -0,0 +1,289 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ /**
3
+ * #1338 (gateway hardening L6) — converge a Cloud SQL install to
4
+ * `sslmode=verify-full` through gcloud, the way `cms-provision upgrade`
5
+ * converges everything else (stack-converge.ts; it never runs Pulumi).
6
+ *
7
+ * Verify-full checks the server certificate's chain AND that it names the
8
+ * host the client dialled. On Cloud SQL that needs three things the stacks
9
+ * declare for a new install (stacks/gcp, stacks/gcp-firebase) and this
10
+ * module brings an existing one to:
11
+ *
12
+ * 1. The shared server CA (`GOOGLE_MANAGED_CAS_CA`): "The SAN field
13
+ * contains the hostname (DNS name of the instance) for all types of
14
+ * instances", while the default per-instance CA names one "only for
15
+ * instances enabled with Private Service Connect"
16
+ * (docs.cloud.google.com/sql/docs/postgres/authorize-ssl). An instance
17
+ * may move from per-instance to shared, not back. After the move the
18
+ * instance needs a server certificate from the new CA: "create a new
19
+ * server certificate with `gcloud sql ssl server-certs create`", then
20
+ * "complete the rotation with `gcloud sql ssl server-certs rotate`"
21
+ * (docs.cloud.google.com/sql/docs/postgres/manage-ssl-instance). The
22
+ * rotation restarts nothing a client keeps: open connections drop and
23
+ * reconnect; every client already uses TLS (`sslmode=require` before).
24
+ * `sslMode=ENCRYPTED_ONLY` refuses plaintext from then on.
25
+ * 2. Resolution of the instance's DNS name (`dnsNames`, the
26
+ * PRIVATE_SERVICES_ACCESS entry, `….sql-psa.goog`) inside the VPC:
27
+ * "create the DNS record in a private DNS zone in the corresponding
28
+ * Virtual Private Cloud (VPC) network"
29
+ * (docs.cloud.google.com/sql/docs/postgres/configure-ssl-instance).
30
+ * 3. The services dialling that name. They read it from their own
31
+ * `*_DATABASE_URL`, and so does every job the upgrade derives from the
32
+ * admin's (migrations, upgrader, operator access): {@link
33
+ * moveServicesToDnsHost} switches the host of the live URLs first,
34
+ * keeping their current `sslmode`, so the old image keeps working until
35
+ * the roll sets verify-full with the image that carries the CA bundle.
36
+ *
37
+ * The CA the clients trust is Google's published shared-CA bundle, shipped
38
+ * in every image (shared database-tls.ts `CLOUD_SQL_CA_BUNDLE`): it covers
39
+ * the root and every regional CA, so a server-certificate rotation needs no
40
+ * change on the client side.
41
+ *
42
+ * Every step reads before it writes and is a no-op when already in shape,
43
+ * so a re-run after a failure picks up where the last one stopped.
44
+ */
45
+ import { isIpLiteral } from "@caelo-cms/shared";
46
+ import { realSleep, runWithRetry } from "./gcloud-retry.js";
47
+ import { CLOUD_SQL_SERVER_CA_MODE, CLOUD_SQL_SSL_MODE, cloudSqlDnsZoneName, cloudSqlPrivateDnsName, } from "./stack-contract.js";
48
+ const NOT_FOUND = /NOT_FOUND|not found|does not exist|404/i;
49
+ const SQL_ADMIN = "https://sqladmin.googleapis.com/v1";
50
+ async function describeInstance(t, run) {
51
+ const r = await run([
52
+ "sql",
53
+ "instances",
54
+ "describe",
55
+ t.sqlInstance,
56
+ `--project=${t.projectId}`,
57
+ "--format=json",
58
+ ]);
59
+ if (!r.ok)
60
+ return { ok: false, error: `describe ${t.sqlInstance}: ${r.stderr.trim()}` };
61
+ try {
62
+ return { ok: true, d: JSON.parse(r.stdout) };
63
+ }
64
+ catch {
65
+ return { ok: false, error: `describe ${t.sqlInstance}: gcloud printed no JSON` };
66
+ }
67
+ }
68
+ /** The instance's server certificates and which one is active (Cloud SQL Admin API). */
69
+ async function listServerCertificates(t, run, http) {
70
+ const token = await run(["auth", "print-access-token"]);
71
+ const bearer = token.ok ? token.stdout.trim() : "";
72
+ if (!bearer)
73
+ return { ok: false, error: `gcloud auth print-access-token: ${token.stderr.trim()}` };
74
+ const res = await http(`${SQL_ADMIN}/projects/${encodeURIComponent(t.projectId)}/instances/${encodeURIComponent(t.sqlInstance)}/listServerCertificates`, { method: "GET", headers: { Authorization: `Bearer ${bearer}` } });
75
+ const text = await res.text();
76
+ if (!res.ok) {
77
+ return {
78
+ ok: false,
79
+ error: `list server certificates: HTTP ${res.status} ${text.slice(0, 300)}`,
80
+ };
81
+ }
82
+ const body = JSON.parse(text);
83
+ return {
84
+ ok: true,
85
+ activeVersion: body.activeVersion ?? null,
86
+ fingerprints: (body.serverCerts ?? []).map((c) => c.sha1Fingerprint ?? "").filter(Boolean),
87
+ };
88
+ }
89
+ /**
90
+ * Bring the instance to verify-full: shared CA with an active server
91
+ * certificate from it, encrypted connections only, its DNS name resolving
92
+ * in the VPC. Returns the host every client must dial.
93
+ */
94
+ export async function ensureCloudSqlVerifyFull(t, deps) {
95
+ const sleep = deps.sleep ?? realSleep;
96
+ const run = (args) => runWithRetry(deps.run, sleep, args);
97
+ const http = deps.http ?? fetch;
98
+ const done = [];
99
+ const fail = (error) => ({ ok: false, error, done });
100
+ const project = `--project=${t.projectId}`;
101
+ let described = await describeInstance(t, run);
102
+ if (!described.ok)
103
+ return fail(described.error);
104
+ const ip = described.d.settings?.ipConfiguration;
105
+ const patch = [];
106
+ if (ip?.serverCaMode !== CLOUD_SQL_SERVER_CA_MODE) {
107
+ patch.push(`--server-ca-mode=${CLOUD_SQL_SERVER_CA_MODE}`);
108
+ }
109
+ if (ip?.sslMode !== CLOUD_SQL_SSL_MODE)
110
+ patch.push(`--ssl-mode=${CLOUD_SQL_SSL_MODE}`);
111
+ if (patch.length > 0) {
112
+ const r = await run(["sql", "instances", "patch", t.sqlInstance, project, ...patch, "--quiet"]);
113
+ if (!r.ok)
114
+ return fail(`patch ${t.sqlInstance} (${patch.join(" ")}): ${r.stderr.trim()}`);
115
+ done.push(`Cloud SQL ${t.sqlInstance}: ${patch.join(" ")}`);
116
+ }
117
+ // The active server certificate must come from the shared CA. Before the
118
+ // move there is none in the list the shared CA keeps; after an
119
+ // interrupted run there may be an upcoming one that was never rotated in.
120
+ const certs = await listServerCertificates(t, run, http);
121
+ if (!certs.ok)
122
+ return fail(certs.error);
123
+ const activeShared = certs.activeVersion !== null && certs.fingerprints.includes(certs.activeVersion);
124
+ if (!activeShared) {
125
+ const upcoming = certs.fingerprints.filter((f) => f !== certs.activeVersion);
126
+ if (upcoming.length === 0) {
127
+ const c = await run([
128
+ "sql",
129
+ "ssl",
130
+ "server-certs",
131
+ "create",
132
+ `--instance=${t.sqlInstance}`,
133
+ project,
134
+ ]);
135
+ if (!c.ok)
136
+ return fail(`create a server certificate: ${c.stderr.trim()}`);
137
+ done.push(`Cloud SQL ${t.sqlInstance}: server certificate from the shared CA created`);
138
+ }
139
+ const rot = await run([
140
+ "sql",
141
+ "ssl",
142
+ "server-certs",
143
+ "rotate",
144
+ `--instance=${t.sqlInstance}`,
145
+ project,
146
+ "--quiet",
147
+ ]);
148
+ if (!rot.ok)
149
+ return fail(`rotate to the shared-CA server certificate: ${rot.stderr.trim()}`);
150
+ done.push(`Cloud SQL ${t.sqlInstance}: rotated onto the shared-CA server certificate`);
151
+ described = await describeInstance(t, run);
152
+ if (!described.ok)
153
+ return fail(described.error);
154
+ }
155
+ const host = cloudSqlPrivateDnsName(described.d.dnsNames);
156
+ if (!host) {
157
+ return fail(`${t.sqlInstance} reports no PRIVATE_SERVICES_ACCESS DNS name (dnsNames) although it uses the shared CA; verify-full needs it. Check the instance's private IP configuration and re-run.`);
158
+ }
159
+ const privateIp = described.d.ipAddresses?.find((a) => a.type === "PRIVATE")?.ipAddress;
160
+ if (!privateIp)
161
+ return fail(`${t.sqlInstance} has no private IP address`);
162
+ const network = ip?.privateNetwork?.split("/").pop();
163
+ if (!network)
164
+ return fail(`${t.sqlInstance} names no private network`);
165
+ const zone = cloudSqlDnsZoneName(t.env);
166
+ const fqdn = `${host}.`;
167
+ const z = await run(["dns", "managed-zones", "describe", zone, project, "--format=json"]);
168
+ if (z.ok) {
169
+ const existing = JSON.parse(z.stdout).dnsName?.toLowerCase();
170
+ if (existing !== fqdn) {
171
+ return fail(`the private DNS zone ${zone} serves ${existing ?? "(no name)"}, not the instance's DNS name ${fqdn}. If the instance was replaced, delete the zone (gcloud dns managed-zones delete ${zone} ${project}) after removing its records, then re-run.`);
172
+ }
173
+ }
174
+ else if (NOT_FOUND.test(z.stderr)) {
175
+ const c = await run([
176
+ "dns",
177
+ "managed-zones",
178
+ "create",
179
+ zone,
180
+ project,
181
+ `--dns-name=${fqdn}`,
182
+ "--visibility=private",
183
+ `--networks=${network}`,
184
+ `--description=Caelo ${t.env}: the Cloud SQL instance's DNS name inside the VPC (#1338)`,
185
+ ]);
186
+ if (!c.ok)
187
+ return fail(`create the private DNS zone ${zone}: ${c.stderr.trim()}`);
188
+ done.push(`private DNS zone ${zone} (${fqdn}) on network ${network}`);
189
+ }
190
+ else {
191
+ return fail(`describe the private DNS zone ${zone}: ${z.stderr.trim()}`);
192
+ }
193
+ const rec = ["dns", "record-sets"];
194
+ const where = [fqdn, `--zone=${zone}`, "--type=A", project];
195
+ const a = await run([...rec, "describe", ...where, "--format=json"]);
196
+ if (a.ok) {
197
+ const rrdatas = JSON.parse(a.stdout).rrdatas ?? [];
198
+ if (rrdatas.length !== 1 || rrdatas[0] !== privateIp) {
199
+ const u = await run([...rec, "update", ...where, "--ttl=300", `--rrdatas=${privateIp}`]);
200
+ if (!u.ok)
201
+ return fail(`update the A record of ${fqdn}: ${u.stderr.trim()}`);
202
+ done.push(`DNS ${fqdn} A ${rrdatas.join(",") || "(none)"} → ${privateIp}`);
203
+ }
204
+ }
205
+ else if (NOT_FOUND.test(a.stderr)) {
206
+ const c = await run([...rec, "create", ...where, "--ttl=300", `--rrdatas=${privateIp}`]);
207
+ if (!c.ok)
208
+ return fail(`create the A record of ${fqdn}: ${c.stderr.trim()}`);
209
+ done.push(`DNS ${fqdn} A ${privateIp}`);
210
+ }
211
+ else {
212
+ return fail(`describe the A record of ${fqdn}: ${a.stderr.trim()}`);
213
+ }
214
+ return { ok: true, host, done };
215
+ }
216
+ /** The plain values of `names` in a service's live env (secret refs and unset vars skipped). */
217
+ export function liveDatabaseUrls(liveEnv, names) {
218
+ const out = {};
219
+ for (const name of names) {
220
+ const v = liveEnv.get(name);
221
+ if (v?.kind === "value" && v.value)
222
+ out[name] = v.value;
223
+ }
224
+ return out;
225
+ }
226
+ /** Whether a database URL dials an IP literal (an unparsable one does not). */
227
+ export function dialsIpAddress(url) {
228
+ try {
229
+ return isIpLiteral(new URL(url).hostname);
230
+ }
231
+ catch {
232
+ return false;
233
+ }
234
+ }
235
+ /**
236
+ * `url` with its host replaced by `host`, everything else kept — or null
237
+ * when it already dials a host name (nothing to move).
238
+ */
239
+ export function urlOnDnsHost(url, host) {
240
+ const parsed = new URL(url);
241
+ if (!isIpLiteral(parsed.hostname))
242
+ return null;
243
+ parsed.hostname = host;
244
+ return parsed.toString();
245
+ }
246
+ /**
247
+ * Switch the live database URLs of `services` from the instance's IP to
248
+ * `host`, keeping their `sslmode` (the running image may not carry the CA
249
+ * bundle yet; the roll sets verify-full with the image that does). Every
250
+ * reader of the database host — the rolls, the migration job, the upgrader
251
+ * and operator-access jobs — takes it from these URLs, so after this they
252
+ * all dial the name the server's certificate carries.
253
+ *
254
+ * @param liveUrls the plain URL values each service carries now
255
+ */
256
+ export async function moveServicesToDnsHost(target, services, host, deps) {
257
+ const sleep = deps.sleep ?? realSleep;
258
+ const done = [];
259
+ for (const s of services) {
260
+ const moved = Object.entries(s.liveUrls)
261
+ .map(([name, url]) => [name, urlOnDnsHost(url, host)])
262
+ .filter((e) => e[1] !== null);
263
+ if (moved.length === 0)
264
+ continue;
265
+ const r = await runWithRetry(deps.run, sleep, [
266
+ "run",
267
+ "services",
268
+ "update",
269
+ s.serviceName,
270
+ "--region",
271
+ target.region,
272
+ `--project=${target.projectId}`,
273
+ // ^|^ — the values carry `&` and `=`; a custom delimiter keeps gcloud
274
+ // from splitting them.
275
+ `--update-env-vars=^|^${moved.map(([n, u]) => `${n}=${u}`).join("|")}`,
276
+ "--quiet",
277
+ ]);
278
+ if (!r.ok) {
279
+ return {
280
+ ok: false,
281
+ error: `move ${s.serviceName} onto the database's DNS name: ${r.stderr.trim()}`,
282
+ done,
283
+ };
284
+ }
285
+ done.push(`${s.serviceName}: ${moved.map(([n]) => n).join(", ")} → ${host}`);
286
+ }
287
+ return { ok: true, done };
288
+ }
289
+ //# sourceMappingURL=cloudsql-tls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudsql-tls.js","sourceRoot":"","sources":["../src/cloudsql-tls.ts"],"names":[],"mappings":"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"}
package/dist/compose.d.ts CHANGED
@@ -1,9 +1,15 @@
1
1
  import { type ReleaseService } from "./upgrade/release-images.js";
2
- /** The admin + gateway release images, each `ghcr.io/caelo-cms/<svc>@sha256:…`. */
2
+ /** The release images, each `ghcr.io/caelo-cms/<svc>@sha256:…`. */
3
3
  export interface ReleaseImages {
4
4
  readonly mode: "release";
5
5
  readonly admin: string;
6
6
  readonly gateway: string;
7
+ /**
8
+ * #1328 — the MCP-Auth-Proxy. Absent only for a release recorded before
9
+ * the proxy shipped (a rollback target in release.json): its Compose file
10
+ * then has no proxy service, exactly as that release ran.
11
+ */
12
+ readonly "mcp-auth-proxy"?: string;
7
13
  }
8
14
  /**
9
15
  * Contributor-only: run the admin + gateway from the Caelo checkout the
@@ -44,11 +50,18 @@ export declare const MEDIA_DIR = "media";
44
50
  export declare const MEDIA_ROOT = "/data/media";
45
51
  /** The gateway's HTTP port inside the Compose network. */
46
52
  export declare const COMPOSE_GATEWAY_PORT = 8090;
53
+ /** #1328 — the MCP-Auth-Proxy's HTTP port inside the Compose network. */
54
+ export declare const COMPOSE_MCP_AUTH_PROXY_PORT = 8095;
55
+ /** #1328 — the Compose service name of the MCP-Auth-Proxy. */
56
+ export declare const COMPOSE_MCP_AUTH_PROXY_SERVICE = "caelo-mcp-auth-proxy";
47
57
  /**
48
- * The Compose services that run Caelo code — what `restore` stops while it
49
- * rewrites the databases, and what the health checks probe. Workers run
50
- * inside the admin (CLAUDE.md §11.B Tier 5); there is no orchestrator or
51
- * runner service.
58
+ * The Compose services that touch the databases — what `backup` and
59
+ * `restore` stop while they read or rewrite them. Workers run inside the
60
+ * admin (CLAUDE.md §11.B Tier 5); there is no orchestrator or runner
61
+ * service. The MCP-Auth-Proxy (#1328) is deliberately not here: it holds no
62
+ * database login, so it keeps running, and a release from before it has no
63
+ * such service for `up` to start. Its health is checked wherever the
64
+ * install starts (self-hosted-start.ts) or rolls (self-hosted-upgrade.ts).
52
65
  */
53
66
  export declare const COMPOSE_APP_SERVICES: readonly ["caelo-admin", "caelo-gateway"];
54
67
  /**
@@ -58,6 +71,7 @@ export declare const COMPOSE_APP_SERVICES: readonly ["caelo-admin", "caelo-gatew
58
71
  */
59
72
  export declare const COMPOSE_ADMIN_UPSTREAM = "caelo-admin:5173";
60
73
  export declare const COMPOSE_GATEWAY_UPSTREAM = "caelo-gateway:8090";
74
+ export declare const COMPOSE_MCP_AUTH_PROXY_UPSTREAM = "caelo-mcp-auth-proxy:8095";
61
75
  /**
62
76
  * The Caddy image, pinned to the release the generated Caddyfile is
63
77
  * validated against (caddy-validate.test.ts runs `caddy validate` on this
@@ -125,6 +139,15 @@ export interface ComposeSpec {
125
139
  * the gateway never gets it.
126
140
  */
127
141
  readonly internalSecret: string;
142
+ /**
143
+ * #1338 — SHA-256 (hex) of the database server certificate the Postgres
144
+ * service mounts (`.caelo/postgres-tls/server.crt`). It is part of the
145
+ * service's environment so a renewed certificate changes the service's
146
+ * definition and `docker compose up -d` recreates Postgres: a bind-mounted
147
+ * file whose content changes does not, and Postgres would keep serving
148
+ * the old certificate until verify-full clients refuse it.
149
+ */
150
+ readonly dbTlsServerCertSha256: string;
128
151
  readonly anthropicApiKey?: string;
129
152
  readonly resendApiKey?: string;
130
153
  readonly diskSize: string;
@@ -135,7 +158,7 @@ export interface ComposeSpec {
135
158
  * busy host never OOM-kills the admin at the limit.
136
159
  */
137
160
  readonly adminMemory?: string;
138
- /** Which admin + gateway images run (see {@link ComposeImages}). */
161
+ /** Which Caelo images run (see {@link ComposeImages}). */
139
162
  readonly images: ComposeImages;
140
163
  /**
141
164
  * The host ports Caddy listens on (`80` / `443` for a public install —
@@ -1 +1 @@
1
- {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"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"}
package/dist/compose.js CHANGED
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * P14 — production docker-compose.yml generator.
4
4
  *
5
- * Emits the production stack: Postgres + Caddy + the two Caelo services
6
- * (admin, gateway). Idempotent: same input →
7
- * byte-identical output. The CLI's `init` / `up` / `upgrade` sub-commands
5
+ * Emits the production stack: Postgres + Caddy + the Caelo services
6
+ * (admin, gateway and — #1328 — the MCP-Auth-Proxy). Idempotent: same
7
+ * input → byte-identical output. The CLI's `init` / `up` / `upgrade` sub-commands
8
8
  * write this to `.caelo/docker-compose.yml`.
9
9
  *
10
10
  * #696 — the admin and gateway run the PREBUILT, cosign-verified release
@@ -25,10 +25,11 @@
25
25
  * and its `minio/minio` image is no longer published, so the service made
26
26
  * every fresh `docker compose up` fail.
27
27
  */
28
- import { CADDY_REDIRECTS_FILE } from "@caelo-cms/shared";
28
+ import { CADDY_REDIRECTS_FILE, SELF_HOSTED_CA_FILE, verifyFullQuery } from "@caelo-cms/shared";
29
29
  import { caddyRedirectReloadCommand } from "./caddy-redirects.js";
30
30
  import { DEFAULT_MAX_CONNECTIONS, stackPoolBudget } from "./pool-budget-stack.js";
31
- import { ADMIN_MEMORY_DEFAULT, GATEWAY_TRUSTED_PROXY_HOPS, memoryQuantityMiB, publicSiteUrl, TRUSTED_PROXY_HOPS_ENV, } from "./stack-contract.js";
31
+ import { SELF_HOSTED_DB_HOST, SELF_HOSTED_TLS_DIR, SELF_HOSTED_TLS_FILES, } from "./self-hosted-db-tls.js";
32
+ import { ADMIN_MEMORY_DEFAULT, GATEWAY_TRUSTED_PROXY_HOPS, MCP_AUTH_PROXY_TRUSTED_PROXY_HOPS, memoryQuantityMiB, publicSiteUrl, REMOTE_MCP_MODE, REMOTE_MCP_MODE_ENV, TRUSTED_PROXY_HOPS_ENV, } from "./stack-contract.js";
32
33
  import { ghcrRepository, isImageDigest } from "./upgrade/release-images.js";
33
34
  /** The admin's HTTP port inside the Compose network (the Caddyfile proxies to it). */
34
35
  export const COMPOSE_ADMIN_PORT = 5173;
@@ -68,11 +69,18 @@ export const MEDIA_DIR = "media";
68
69
  export const MEDIA_ROOT = "/data/media";
69
70
  /** The gateway's HTTP port inside the Compose network. */
70
71
  export const COMPOSE_GATEWAY_PORT = 8090;
72
+ /** #1328 — the MCP-Auth-Proxy's HTTP port inside the Compose network. */
73
+ export const COMPOSE_MCP_AUTH_PROXY_PORT = 8095;
74
+ /** #1328 — the Compose service name of the MCP-Auth-Proxy. */
75
+ export const COMPOSE_MCP_AUTH_PROXY_SERVICE = "caelo-mcp-auth-proxy";
71
76
  /**
72
- * The Compose services that run Caelo code — what `restore` stops while it
73
- * rewrites the databases, and what the health checks probe. Workers run
74
- * inside the admin (CLAUDE.md §11.B Tier 5); there is no orchestrator or
75
- * runner service.
77
+ * The Compose services that touch the databases — what `backup` and
78
+ * `restore` stop while they read or rewrite them. Workers run inside the
79
+ * admin (CLAUDE.md §11.B Tier 5); there is no orchestrator or runner
80
+ * service. The MCP-Auth-Proxy (#1328) is deliberately not here: it holds no
81
+ * database login, so it keeps running, and a release from before it has no
82
+ * such service for `up` to start. Its health is checked wherever the
83
+ * install starts (self-hosted-start.ts) or rolls (self-hosted-upgrade.ts).
76
84
  */
77
85
  export const COMPOSE_APP_SERVICES = ["caelo-admin", "caelo-gateway"];
78
86
  /**
@@ -82,6 +90,7 @@ export const COMPOSE_APP_SERVICES = ["caelo-admin", "caelo-gateway"];
82
90
  */
83
91
  export const COMPOSE_ADMIN_UPSTREAM = `caelo-admin:${COMPOSE_ADMIN_PORT}`;
84
92
  export const COMPOSE_GATEWAY_UPSTREAM = `caelo-gateway:${COMPOSE_GATEWAY_PORT}`;
93
+ export const COMPOSE_MCP_AUTH_PROXY_UPSTREAM = `${COMPOSE_MCP_AUTH_PROXY_SERVICE}:${COMPOSE_MCP_AUTH_PROXY_PORT}`;
85
94
  /**
86
95
  * The Caddy image, pinned to the release the generated Caddyfile is
87
96
  * validated against (caddy-validate.test.ts runs `caddy validate` on this
@@ -161,6 +170,9 @@ export function generateDockerCompose(spec) {
161
170
  if (spec.internalSecret.length < 32) {
162
171
  throw new Error("internalSecret is shorter than 32 characters (.caelo/internal-secret.json)");
163
172
  }
173
+ if (!/^[0-9a-f]{64}$/.test(spec.dbTlsServerCertSha256)) {
174
+ throw new Error("dbTlsServerCertSha256 is not a SHA-256 hex digest of .caelo/postgres-tls/server.crt");
175
+ }
164
176
  return `# SPDX-License-Identifier: MPL-2.0
165
177
  # Generated by cms-provision — do not edit; re-run \`bunx cms-provision up\`.
166
178
  # Domain: ${spec.domain}
@@ -168,10 +180,16 @@ export function generateDockerCompose(spec) {
168
180
  name: ${spec.project}
169
181
 
170
182
  services:
171
- postgres:
183
+ ${SELF_HOSTED_DB_HOST}:
172
184
  image: postgres:16-alpine
173
- # The pool budget (COMPOSE_POOL_BUDGET) is computed from this number.
174
- command: ["postgres", "-c", "max_connections=${DEFAULT_MAX_CONNECTIONS["self-hosted"]}"]
185
+ # #1338 — TLS with the install's own certificate for the host name
186
+ # \`${SELF_HOSTED_DB_HOST}\` (self-hosted-db-tls.ts); every client connects with
187
+ # verify-full. Postgres refuses a key file it does not own, and a bind
188
+ # mount keeps the host's owner, so the entrypoint copies the pair to a
189
+ # container-local path owned by postgres first.
190
+ entrypoint: ${POSTGRES_TLS_ENTRYPOINT}
191
+ # The pool budget (COMPOSE_POOL_BUDGET) is computed from max_connections.
192
+ command: ["postgres", "-c", "max_connections=${DEFAULT_MAX_CONNECTIONS["self-hosted"]}", "-c", "ssl=on", "-c", "ssl_cert_file=${POSTGRES_TLS_RUNTIME_DIR}/server.crt", "-c", "ssl_key_file=${POSTGRES_TLS_RUNTIME_DIR}/server.key", "-c", "ssl_min_protocol_version=TLSv1.2"]
175
193
  restart: unless-stopped
176
194
  environment:
177
195
  POSTGRES_PASSWORD: "${escapeYaml(spec.postgresPassword)}"
@@ -179,9 +197,13 @@ services:
179
197
  POSTGRES_DB: caelo
180
198
  ADMIN_ROLE_PASSWORD: "${escapeYaml(spec.rolePasswords.admin)}"
181
199
  PUBLIC_ROLE_PASSWORD: "${escapeYaml(spec.rolePasswords.public)}"
200
+ # Recreates Postgres when its certificate is renewed (see the spec).
201
+ CAELO_DB_TLS_SERVER_CERT_SHA256: "${spec.dbTlsServerCertSha256}"
182
202
  ${postgresAgent(spec.agent)} volumes:
183
203
  - caelo-pg:/var/lib/postgresql/data
184
204
  - ./bootstrap.sh:/docker-entrypoint-initdb.d/00_bootstrap.sh:ro
205
+ - ./${SELF_HOSTED_TLS_DIR}/${SELF_HOSTED_TLS_FILES.serverCert}:${POSTGRES_TLS_MOUNT_DIR}/server.crt:ro
206
+ - ./${SELF_HOSTED_TLS_DIR}/${SELF_HOSTED_TLS_FILES.serverKey}:${POSTGRES_TLS_MOUNT_DIR}/server.key:ro
185
207
  healthcheck:
186
208
  test: ["CMD-SHELL", "pg_isready -U caelo"]
187
209
  interval: 10s
@@ -204,7 +226,7 @@ ${postgresAgent(spec.agent)} volumes:
204
226
  ${adminService(spec, adminMemoryMiB, env)}
205
227
 
206
228
  ${gatewayService(spec)}
207
-
229
+ ${mcpAuthProxyService(spec.images)}
208
230
  volumes:
209
231
  caelo-pg:
210
232
  caelo-caddy-data:
@@ -246,9 +268,10 @@ function serviceRuntime(images, service, devCommand, mounts = []) {
246
268
  ...volumes(["../..:/app", ...mounts]),
247
269
  ].join("\n");
248
270
  }
249
- const digest = ghcrImageDigest(service, images[service]);
271
+ const ref = images[service] ?? "";
272
+ const digest = ghcrImageDigest(service, ref);
250
273
  if (!digest) {
251
- throw new Error(`${service} image ${JSON.stringify(images[service])} is not ${ghcrRepository(service)}@sha256:<digest>`);
274
+ throw new Error(`${service} image ${JSON.stringify(ref)} is not ${ghcrRepository(service)}@sha256:<digest>`);
252
275
  }
253
276
  // The image's own CMD starts the service; no source is mounted.
254
277
  return [` image: ${ghcrImageRef(service, digest)}`, ...volumes(mounts)].join("\n");
@@ -269,6 +292,7 @@ ${serviceRuntime(spec.images, "admin", `sh -c "cd apps/admin && bunx svelte-kit
269
292
  `./${BOOTSTRAP_DIR}:/app/.caelo`,
270
293
  `./output:${SITE_OUTPUT_ROOT}`,
271
294
  `./${MEDIA_DIR}:${MEDIA_ROOT}`,
295
+ DATABASE_CA_MOUNT,
272
296
  ])}
273
297
  restart: unless-stopped
274
298
  depends_on:
@@ -291,7 +315,7 @@ ${env("RESEND_API_KEY", spec.resendApiKey)}`;
291
315
  }
292
316
  function gatewayService(spec) {
293
317
  return ` caelo-gateway:
294
- ${serviceRuntime(spec.images, "gateway", "bun run apps/api-gateway/src/server.ts")}
318
+ ${serviceRuntime(spec.images, "gateway", "bun run apps/api-gateway/src/server.ts", [DATABASE_CA_MOUNT])}
295
319
  restart: unless-stopped
296
320
  depends_on:
297
321
  postgres: { condition: service_healthy }
@@ -303,17 +327,65 @@ ${serviceRuntime(spec.images, "gateway", "bun run apps/api-gateway/src/server.ts
303
327
  # Caddy is the one proxy in front (client-ip.ts in the gateway).
304
328
  ${TRUSTED_PROXY_HOPS_ENV}: "${GATEWAY_TRUSTED_PROXY_HOPS["self-hosted"]}"
305
329
  ${poolEnvLines("gateway")}
306
- # #806 — no remote MCP here: it rides Google IAP, which this install
307
- # does not have. CAELO_ADMIN_URL / CAELO_MCP_PUBLIC_URL /
308
- # CAELO_OPERATOR_OAUTH_CLIENT_FILE stay unset, so the gateway's /api/mcp/*
309
- # answers 503 remote_mcp_not_configured and Settings → MCP says
310
- # "not available on this install".
311
330
  NODE_ENV: production`;
312
331
  }
313
- /** A compose-network database URL, password URL-encoded and YAML-escaped. */
332
+ /**
333
+ * #1328 — the MCP-Auth-Proxy: remote MCP's sign-in broker, its own
334
+ * container so it never shares a process with visitor handlers. Remote MCP
335
+ * needs the admin behind Google IAP, which a Compose install does not have,
336
+ * so it runs with `CAELO_REMOTE_MCP=unavailable` and answers every request
337
+ * but its health check with one fixed 404 (E14 a of #763: the service
338
+ * exists on every provider, its attack surface one branch). Caddy serves it
339
+ * on its own host (`mcp.<domain>`, caddy.ts), never on the site's origin.
340
+ *
341
+ * It gets no database URL, no secret and no mount: there is nothing it
342
+ * could read. The container is locked down on top — read-only root
343
+ * filesystem, every capability dropped, no privilege escalation — because
344
+ * it is the Caelo service that holds operators' Google tokens wherever
345
+ * remote MCP runs. Empty for a release recorded before the proxy shipped
346
+ * ({@link ReleaseImages}).
347
+ */
348
+ function mcpAuthProxyService(images) {
349
+ if (images.mode === "release" && images["mcp-auth-proxy"] === undefined)
350
+ return "";
351
+ return `
352
+ ${COMPOSE_MCP_AUTH_PROXY_SERVICE}:
353
+ ${serviceRuntime(images, "mcp-auth-proxy", "bun run apps/mcp-auth-proxy/src/server.ts")}
354
+ restart: unless-stopped
355
+ read_only: true
356
+ tmpfs: ["/tmp"]
357
+ cap_drop: ["ALL"]
358
+ security_opt: ["no-new-privileges:true"]
359
+ environment:
360
+ CAELO_PROVIDER: "self-hosted"
361
+ ${REMOTE_MCP_MODE_ENV}: "${REMOTE_MCP_MODE["self-hosted"]}"
362
+ MCP_AUTH_PROXY_PORT: "${COMPOSE_MCP_AUTH_PROXY_PORT}"
363
+ # Caddy is the one proxy in front (@caelo-cms/shared client-address.ts).
364
+ ${TRUSTED_PROXY_HOPS_ENV}: "${MCP_AUTH_PROXY_TRUSTED_PROXY_HOPS["self-hosted"]}"
365
+ NODE_ENV: production
366
+ `;
367
+ }
368
+ /**
369
+ * A compose-network database URL, password URL-encoded and YAML-escaped.
370
+ * #1338 — verify-full against the install's own CA (self-hosted-db-tls.ts),
371
+ * mounted at shared `SELF_HOSTED_CA_FILE` ({@link DATABASE_CA_MOUNT}).
372
+ */
314
373
  function dbUrl(role, password, database) {
315
- return escapeYaml(`postgres://${role}:${encodeURIComponent(password)}@postgres:5432/${database}`);
374
+ return escapeYaml(`postgres://${role}:${encodeURIComponent(password)}@${SELF_HOSTED_DB_HOST}:5432/${database}?${verifyFullQuery(SELF_HOSTED_CA_FILE)}`);
316
375
  }
376
+ /** Where the server certificate + key are bind-mounted into Postgres (host-owned). */
377
+ const POSTGRES_TLS_MOUNT_DIR = "/caelo-tls";
378
+ /** Where the entrypoint copies them, owned by postgres (Postgres refuses others' keys). */
379
+ const POSTGRES_TLS_RUNTIME_DIR = "/var/lib/postgresql/caelo-tls";
380
+ /** The Postgres entrypoint: copy the TLS pair into place, then the image's own entrypoint. */
381
+ const POSTGRES_TLS_ENTRYPOINT = JSON.stringify([
382
+ "/bin/sh",
383
+ "-c",
384
+ `install -d -o postgres -g postgres -m 0700 ${POSTGRES_TLS_RUNTIME_DIR} && install -o postgres -g postgres -m 0644 ${POSTGRES_TLS_MOUNT_DIR}/server.crt ${POSTGRES_TLS_RUNTIME_DIR}/server.crt && install -o postgres -g postgres -m 0600 ${POSTGRES_TLS_MOUNT_DIR}/server.key ${POSTGRES_TLS_RUNTIME_DIR}/server.key && exec docker-entrypoint.sh "$$@"`,
385
+ "--",
386
+ ]);
387
+ /** The install's database CA, read-only, where every verify-full URL names it. */
388
+ const DATABASE_CA_MOUNT = `./${SELF_HOSTED_TLS_DIR}/${SELF_HOSTED_TLS_FILES.caCert}:${SELF_HOSTED_CA_FILE}:ro`;
317
389
  function escapeYaml(s) {
318
390
  // Conservative escape for double-quoted YAML strings.
319
391
  return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
@@ -1 +1 @@
1
- {"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"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"}