@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.
Files changed (352) hide show
  1. package/dist/adapter.d.ts +6 -0
  2. package/dist/adapter.d.ts.map +1 -1
  3. package/dist/admin-domain.d.ts +10 -1
  4. package/dist/admin-domain.d.ts.map +1 -1
  5. package/dist/admin-domain.js +13 -3
  6. package/dist/admin-domain.js.map +1 -1
  7. package/dist/adopt-existing.d.ts +12 -3
  8. package/dist/adopt-existing.d.ts.map +1 -1
  9. package/dist/adopt-existing.js +143 -0
  10. package/dist/adopt-existing.js.map +1 -1
  11. package/dist/agent/command.d.ts +23 -0
  12. package/dist/agent/command.d.ts.map +1 -1
  13. package/dist/agent/command.js +32 -9
  14. package/dist/agent/command.js.map +1 -1
  15. package/dist/agent/run.d.ts +2 -0
  16. package/dist/agent/run.d.ts.map +1 -1
  17. package/dist/agent/run.js +5 -1
  18. package/dist/agent/run.js.map +1 -1
  19. package/dist/agent-db.js +69 -10
  20. package/dist/aws-task-roles.d.ts +4 -2
  21. package/dist/aws-task-roles.d.ts.map +1 -1
  22. package/dist/aws-task-roles.js +4 -1
  23. package/dist/aws-task-roles.js.map +1 -1
  24. package/dist/caddy.d.ts +21 -4
  25. package/dist/caddy.d.ts.map +1 -1
  26. package/dist/caddy.js +27 -3
  27. package/dist/caddy.js.map +1 -1
  28. package/dist/cli-routing.js +1 -1
  29. package/dist/cli-routing.js.map +1 -1
  30. package/dist/cli.js +68 -7
  31. package/dist/cli.js.map +1 -1
  32. package/dist/cloudsql-tls.d.ts +93 -0
  33. package/dist/cloudsql-tls.d.ts.map +1 -0
  34. package/dist/cloudsql-tls.js +295 -0
  35. package/dist/cloudsql-tls.js.map +1 -0
  36. package/dist/compose.d.ts +43 -6
  37. package/dist/compose.d.ts.map +1 -1
  38. package/dist/compose.js +148 -23
  39. package/dist/compose.js.map +1 -1
  40. package/dist/converge-checkpoint.d.ts +1 -0
  41. package/dist/converge-checkpoint.d.ts.map +1 -1
  42. package/dist/converge-checkpoint.js +8 -1
  43. package/dist/converge-checkpoint.js.map +1 -1
  44. package/dist/converge-db-trust.d.ts +44 -0
  45. package/dist/converge-db-trust.d.ts.map +1 -0
  46. package/dist/converge-db-trust.js +158 -0
  47. package/dist/converge-db-trust.js.map +1 -0
  48. package/dist/converge-job-gcp.d.ts +5 -2
  49. package/dist/converge-job-gcp.d.ts.map +1 -1
  50. package/dist/converge-job-gcp.js +11 -13
  51. package/dist/converge-job-gcp.js.map +1 -1
  52. package/dist/converge-job-preflight.d.ts.map +1 -1
  53. package/dist/converge-job-preflight.js +8 -0
  54. package/dist/converge-job-preflight.js.map +1 -1
  55. package/dist/converge-job.d.ts +17 -0
  56. package/dist/converge-job.d.ts.map +1 -1
  57. package/dist/converge-job.js +12 -0
  58. package/dist/converge-job.js.map +1 -1
  59. package/dist/deployed-release.d.ts +4 -1
  60. package/dist/deployed-release.d.ts.map +1 -1
  61. package/dist/deployed-release.js +18 -8
  62. package/dist/deployed-release.js.map +1 -1
  63. package/dist/gcp-names.d.ts +34 -0
  64. package/dist/gcp-names.d.ts.map +1 -1
  65. package/dist/gcp-names.js +45 -0
  66. package/dist/gcp-names.js.map +1 -1
  67. package/dist/gcp-url-map.d.ts.map +1 -1
  68. package/dist/gcp-url-map.js +6 -2
  69. package/dist/gcp-url-map.js.map +1 -1
  70. package/dist/index.d.ts +3 -2
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +2 -1
  73. package/dist/index.js.map +1 -1
  74. package/dist/infra-contract.d.ts +1 -1
  75. package/dist/infra-contract.d.ts.map +1 -1
  76. package/dist/infra-contract.js +45 -1
  77. package/dist/infra-contract.js.map +1 -1
  78. package/dist/install-job.d.ts +4 -2
  79. package/dist/install-job.d.ts.map +1 -1
  80. package/dist/install-job.js +4 -1
  81. package/dist/install-job.js.map +1 -1
  82. package/dist/install-state.d.ts +13 -0
  83. package/dist/install-state.d.ts.map +1 -1
  84. package/dist/install-state.js +17 -4
  85. package/dist/install-state.js.map +1 -1
  86. package/dist/lifecycle.d.ts.map +1 -1
  87. package/dist/lifecycle.js +20 -8
  88. package/dist/lifecycle.js.map +1 -1
  89. package/dist/mcp-auth-proxy-setup.d.ts +48 -0
  90. package/dist/mcp-auth-proxy-setup.d.ts.map +1 -0
  91. package/dist/mcp-auth-proxy-setup.js +280 -0
  92. package/dist/mcp-auth-proxy-setup.js.map +1 -0
  93. package/dist/migration-runner.d.ts.map +1 -1
  94. package/dist/migration-runner.js +8 -3
  95. package/dist/migration-runner.js.map +1 -1
  96. package/dist/migration-targets.d.ts +11 -0
  97. package/dist/migration-targets.d.ts.map +1 -0
  98. package/dist/migration-targets.js +12 -0
  99. package/dist/migration-targets.js.map +1 -0
  100. package/dist/operator-access.d.ts +10 -0
  101. package/dist/operator-access.d.ts.map +1 -1
  102. package/dist/operator-access.js +5 -0
  103. package/dist/operator-access.js.map +1 -1
  104. package/dist/pool-budget-stack.d.ts +13 -1
  105. package/dist/pool-budget-stack.d.ts.map +1 -1
  106. package/dist/pool-budget-stack.js +11 -1
  107. package/dist/pool-budget-stack.js.map +1 -1
  108. package/dist/public-role-isolation.d.ts +7 -3
  109. package/dist/public-role-isolation.d.ts.map +1 -1
  110. package/dist/public-role-isolation.js +25 -13
  111. package/dist/public-role-isolation.js.map +1 -1
  112. package/dist/release-contract.d.ts.map +1 -1
  113. package/dist/release-contract.js +3 -0
  114. package/dist/release-contract.js.map +1 -1
  115. package/dist/release-manifest.d.ts +25 -1
  116. package/dist/release-manifest.d.ts.map +1 -1
  117. package/dist/release-manifest.js +36 -3
  118. package/dist/release-manifest.js.map +1 -1
  119. package/dist/remote-mcp.d.ts +55 -18
  120. package/dist/remote-mcp.d.ts.map +1 -1
  121. package/dist/remote-mcp.js +307 -77
  122. package/dist/remote-mcp.js.map +1 -1
  123. package/dist/runtime-secrets.d.ts +11 -0
  124. package/dist/runtime-secrets.d.ts.map +1 -1
  125. package/dist/runtime-secrets.js +40 -25
  126. package/dist/runtime-secrets.js.map +1 -1
  127. package/dist/scheduler-setup.d.ts +75 -0
  128. package/dist/scheduler-setup.d.ts.map +1 -0
  129. package/dist/scheduler-setup.js +331 -0
  130. package/dist/scheduler-setup.js.map +1 -0
  131. package/dist/seal-key-rotation.d.ts +7 -7
  132. package/dist/seal-key-rotation.d.ts.map +1 -1
  133. package/dist/seal-key-rotation.js +22 -22
  134. package/dist/seal-key-rotation.js.map +1 -1
  135. package/dist/self-hosted-db-tls.d.ts +37 -0
  136. package/dist/self-hosted-db-tls.d.ts.map +1 -0
  137. package/dist/self-hosted-db-tls.js +220 -0
  138. package/dist/self-hosted-db-tls.js.map +1 -0
  139. package/dist/self-hosted-release.d.ts +3 -1
  140. package/dist/self-hosted-release.d.ts.map +1 -1
  141. package/dist/self-hosted-release.js +33 -9
  142. package/dist/self-hosted-release.js.map +1 -1
  143. package/dist/self-hosted-roles.d.ts +43 -2
  144. package/dist/self-hosted-roles.d.ts.map +1 -1
  145. package/dist/self-hosted-roles.js +87 -1
  146. package/dist/self-hosted-roles.js.map +1 -1
  147. package/dist/self-hosted-scheduler-interval.d.ts +21 -0
  148. package/dist/self-hosted-scheduler-interval.d.ts.map +1 -0
  149. package/dist/self-hosted-scheduler-interval.js +68 -0
  150. package/dist/self-hosted-scheduler-interval.js.map +1 -0
  151. package/dist/self-hosted-start.d.ts +0 -21
  152. package/dist/self-hosted-start.d.ts.map +1 -1
  153. package/dist/self-hosted-start.js +39 -1
  154. package/dist/self-hosted-start.js.map +1 -1
  155. package/dist/self-hosted-upgrade.d.ts +19 -7
  156. package/dist/self-hosted-upgrade.d.ts.map +1 -1
  157. package/dist/self-hosted-upgrade.js +78 -25
  158. package/dist/self-hosted-upgrade.js.map +1 -1
  159. package/dist/stack-contract.d.ts +234 -28
  160. package/dist/stack-contract.d.ts.map +1 -1
  161. package/dist/stack-contract.js +397 -39
  162. package/dist/stack-contract.js.map +1 -1
  163. package/dist/stack-converge.d.ts +31 -0
  164. package/dist/stack-converge.d.ts.map +1 -1
  165. package/dist/stack-converge.js +71 -30
  166. package/dist/stack-converge.js.map +1 -1
  167. package/dist/staging-database.d.ts +22 -0
  168. package/dist/staging-database.d.ts.map +1 -0
  169. package/dist/staging-database.js +117 -0
  170. package/dist/staging-database.js.map +1 -0
  171. package/dist/upgrade/app-roll.d.ts +25 -4
  172. package/dist/upgrade/app-roll.d.ts.map +1 -1
  173. package/dist/upgrade/app-roll.js +63 -17
  174. package/dist/upgrade/app-roll.js.map +1 -1
  175. package/dist/upgrade/converge.d.ts +5 -0
  176. package/dist/upgrade/converge.d.ts.map +1 -1
  177. package/dist/upgrade/converge.js +207 -20
  178. package/dist/upgrade/converge.js.map +1 -1
  179. package/dist/upgrade/health.d.ts +31 -7
  180. package/dist/upgrade/health.d.ts.map +1 -1
  181. package/dist/upgrade/health.js +41 -17
  182. package/dist/upgrade/health.js.map +1 -1
  183. package/dist/upgrade/image-forms.d.ts +1 -1
  184. package/dist/upgrade/image-forms.d.ts.map +1 -1
  185. package/dist/upgrade/image-forms.js +24 -7
  186. package/dist/upgrade/image-forms.js.map +1 -1
  187. package/dist/upgrade/release-images.d.ts +12 -3
  188. package/dist/upgrade/release-images.d.ts.map +1 -1
  189. package/dist/upgrade/release-images.js +13 -4
  190. package/dist/upgrade/release-images.js.map +1 -1
  191. package/dist/upgrade/upgrade.d.ts +19 -3
  192. package/dist/upgrade/upgrade.d.ts.map +1 -1
  193. package/dist/upgrade/upgrade.js +37 -2
  194. package/dist/upgrade/upgrade.js.map +1 -1
  195. package/dist/upgrader-gcp.d.ts +13 -0
  196. package/dist/upgrader-gcp.d.ts.map +1 -1
  197. package/dist/upgrader-gcp.js +50 -1
  198. package/dist/upgrader-gcp.js.map +1 -1
  199. package/dist/upgrader-iam-preflight.d.ts.map +1 -1
  200. package/dist/upgrader-iam-preflight.js +6 -1
  201. package/dist/upgrader-iam-preflight.js.map +1 -1
  202. package/dist/upgrader-job.d.ts +1 -1
  203. package/dist/upgrader-job.d.ts.map +1 -1
  204. package/dist/upgrader-job.js +20 -14
  205. package/dist/upgrader-job.js.map +1 -1
  206. package/dist/upgrader-records.d.ts +1 -1
  207. package/dist/upgrader-records.d.ts.map +1 -1
  208. package/dist/upgrader-records.js +26 -7
  209. package/dist/upgrader-records.js.map +1 -1
  210. package/dist/upgrader-setup.d.ts.map +1 -1
  211. package/dist/upgrader-setup.js +10 -5
  212. package/dist/upgrader-setup.js.map +1 -1
  213. package/dist/wizard.d.ts +7 -0
  214. package/dist/wizard.d.ts.map +1 -1
  215. package/dist/wizard.js +11 -0
  216. package/dist/wizard.js.map +1 -1
  217. package/dist/wizards/gcp-cost.d.ts +31 -0
  218. package/dist/wizards/gcp-cost.d.ts.map +1 -1
  219. package/dist/wizards/gcp-cost.js +103 -18
  220. package/dist/wizards/gcp-cost.js.map +1 -1
  221. package/dist/wizards/gcp.d.ts.map +1 -1
  222. package/dist/wizards/gcp.js +129 -27
  223. package/dist/wizards/gcp.js.map +1 -1
  224. package/package.json +2 -2
  225. package/src/adapter.ts +6 -0
  226. package/src/admin-domain.test.ts +9 -8
  227. package/src/admin-domain.ts +13 -3
  228. package/src/admin-memory.test.ts +2 -1
  229. package/src/adopt-existing.test.ts +85 -0
  230. package/src/adopt-existing.ts +141 -3
  231. package/src/agent/command.test.ts +49 -1
  232. package/src/agent/command.ts +39 -9
  233. package/src/agent/run.test.ts +19 -0
  234. package/src/agent/run.ts +11 -2
  235. package/src/aws-task-roles.ts +5 -2
  236. package/src/caddy-redirects.docker.test.ts +2 -0
  237. package/src/caddy-redirects.test.ts +4 -1
  238. package/src/caddy-validate.test.ts +7 -1
  239. package/src/caddy.test.ts +39 -1
  240. package/src/caddy.ts +36 -4
  241. package/src/checkpoint-secrets.test.ts +14 -6
  242. package/src/cli-routing.test.ts +1 -1
  243. package/src/cli-routing.ts +1 -1
  244. package/src/cli.ts +71 -5
  245. package/src/cloudsql-tls.test.ts +255 -0
  246. package/src/cloudsql-tls.ts +359 -0
  247. package/src/compose.ts +193 -24
  248. package/src/converge-checkpoint.ts +8 -1
  249. package/src/converge-db-trust.test.ts +237 -0
  250. package/src/converge-db-trust.ts +212 -0
  251. package/src/converge-job-gcp.ts +11 -12
  252. package/src/converge-job-preflight.test.ts +5 -0
  253. package/src/converge-job-preflight.ts +8 -0
  254. package/src/converge-job.test.ts +70 -0
  255. package/src/converge-job.ts +32 -0
  256. package/src/database-tls-builders.test.ts +56 -0
  257. package/src/deployed-release.test.ts +107 -40
  258. package/src/deployed-release.ts +30 -9
  259. package/src/gateway-env-isolation.test.ts +50 -12
  260. package/src/gcp-names.ts +56 -0
  261. package/src/gcp-url-map.test.ts +6 -8
  262. package/src/gcp-url-map.ts +6 -2
  263. package/src/index.test.ts +10 -4
  264. package/src/index.ts +7 -0
  265. package/src/infra-contract.test.ts +7 -3
  266. package/src/infra-contract.ts +45 -1
  267. package/src/install-job.ts +4 -1
  268. package/src/install-state.ts +33 -4
  269. package/src/lifecycle.ts +23 -11
  270. package/src/mcp-auth-proxy-setup.test.ts +305 -0
  271. package/src/mcp-auth-proxy-setup.ts +374 -0
  272. package/src/mcp-iap-stacks.test.ts +1 -1
  273. package/src/media-volume.test.ts +1 -1
  274. package/src/migration-runner.ts +14 -9
  275. package/src/migration-targets.ts +12 -0
  276. package/src/operator-access-stacks.test.ts +1 -1
  277. package/src/operator-access.test.ts +20 -4
  278. package/src/operator-access.ts +14 -0
  279. package/src/pool-budget-stack.ts +15 -0
  280. package/src/pool-budget-stacks.test.ts +39 -14
  281. package/src/public-role-isolation.test.ts +18 -8
  282. package/src/public-role-isolation.ts +31 -17
  283. package/src/release-contract.ts +3 -0
  284. package/src/release-manifest.test.ts +25 -0
  285. package/src/release-manifest.ts +59 -4
  286. package/src/remote-mcp-stack-config.test.ts +19 -9
  287. package/src/remote-mcp.test.ts +252 -57
  288. package/src/remote-mcp.ts +336 -77
  289. package/src/runtime-secrets.test.ts +37 -14
  290. package/src/runtime-secrets.ts +87 -27
  291. package/src/scheduler-setup.test.ts +201 -0
  292. package/src/scheduler-setup.ts +375 -0
  293. package/src/seal-key-rotation.test.ts +2 -2
  294. package/src/seal-key-rotation.ts +25 -25
  295. package/src/self-hosted-backup.test.ts +1 -0
  296. package/src/self-hosted-compose.test.ts +180 -6
  297. package/src/self-hosted-db-tls.test.ts +111 -0
  298. package/src/self-hosted-db-tls.ts +287 -0
  299. package/src/self-hosted-release-resolve.test.ts +71 -0
  300. package/src/self-hosted-release.ts +41 -11
  301. package/src/self-hosted-roles.integration.test.ts +2 -0
  302. package/src/self-hosted-roles.test.ts +87 -3
  303. package/src/self-hosted-roles.ts +101 -3
  304. package/src/self-hosted-scheduler-interval.test.ts +66 -0
  305. package/src/self-hosted-scheduler-interval.ts +79 -0
  306. package/src/self-hosted-start.test.ts +35 -2
  307. package/src/self-hosted-start.ts +20 -2
  308. package/src/self-hosted-upgrade.test.ts +104 -14
  309. package/src/self-hosted-upgrade.ts +123 -31
  310. package/src/stack-contract-parity.test.ts +79 -12
  311. package/src/stack-contract.test.ts +199 -31
  312. package/src/stack-contract.ts +472 -45
  313. package/src/stack-converge-secrets.test.ts +28 -13
  314. package/src/stack-converge.test.ts +203 -28
  315. package/src/stack-converge.ts +92 -30
  316. package/src/staging-database.test.ts +114 -0
  317. package/src/staging-database.ts +148 -0
  318. package/src/state-store.test.ts +2 -1
  319. package/src/upgrade/app-roll.ts +97 -19
  320. package/src/upgrade/converge.ts +249 -19
  321. package/src/upgrade/health.test.ts +63 -25
  322. package/src/upgrade/health.ts +54 -22
  323. package/src/upgrade/image-forms.test.ts +34 -0
  324. package/src/upgrade/image-forms.ts +23 -8
  325. package/src/upgrade/release-images.test.ts +5 -1
  326. package/src/upgrade/release-images.ts +22 -6
  327. package/src/upgrade/upgrade.test.ts +438 -46
  328. package/src/upgrade/upgrade.ts +64 -6
  329. package/src/upgrader-gcp.ts +66 -3
  330. package/src/upgrader-iam-preflight.test.ts +19 -0
  331. package/src/upgrader-iam-preflight.ts +6 -0
  332. package/src/upgrader-job.test.ts +101 -27
  333. package/src/upgrader-job.ts +27 -14
  334. package/src/upgrader-records.test.ts +97 -12
  335. package/src/upgrader-records.ts +28 -11
  336. package/src/upgrader-setup.test.ts +2 -0
  337. package/src/upgrader-setup.ts +10 -4
  338. package/src/wizard.ts +19 -0
  339. package/src/wizards/gcp-cost.test.ts +103 -0
  340. package/src/wizards/gcp-cost.ts +125 -18
  341. package/src/wizards/gcp.ts +164 -22
  342. package/stacks/aws/Pulumi.yaml +1 -1
  343. package/stacks/aws/index.ts +72 -14
  344. package/stacks/azure/index.ts +108 -21
  345. package/stacks/gcp/Pulumi.yaml +1 -1
  346. package/stacks/gcp/README.md +1 -0
  347. package/stacks/gcp/index.ts +133 -24
  348. package/stacks/gcp-firebase/Pulumi.yaml +1 -1
  349. package/stacks/gcp-firebase/index.ts +212 -34
  350. package/stacks/self-hosted/Pulumi.yaml +3 -0
  351. package/stacks/self-hosted/README.md +6 -1
  352. package/stacks/self-hosted/index.ts +40 -5
@@ -5,8 +5,8 @@
5
5
  *
6
6
  * `.caelo/release.json` is the install metadata for self-hosted (the cloud
7
7
  * providers keep theirs in `~/.caelo-<id>/install.json`): the release
8
- * version, the digest-pinned admin + gateway image references the Compose
9
- * file runs, and a short history of installs/upgrades/rollbacks. It holds no
8
+ * version, the digest-pinned image references the Compose file runs (admin,
9
+ * gateway, and since #1328 the MCP-Auth-Proxy), and a short history of installs/upgrades/rollbacks. It holds no
10
10
  * secrets (config.json does), so it is safe to read from tooling and
11
11
  * backups; writes refuse secret material like install.json's do.
12
12
  *
@@ -52,7 +52,16 @@ export function releasePath(caeloDir) {
52
52
  }
53
53
  /** The images of a recorded release, as the Compose generator takes them. */
54
54
  export function releaseImages(release) {
55
- return { mode: "release", admin: release.images.admin, gateway: release.images.gateway };
55
+ return { mode: "release", ...release.images };
56
+ }
57
+ /** The image references of `images`, as release.json stores them. */
58
+ function recordedImages(images) {
59
+ const proxy = images["mcp-auth-proxy"];
60
+ return {
61
+ admin: images.admin,
62
+ gateway: images.gateway,
63
+ ...(proxy !== undefined ? { "mcp-auth-proxy": proxy } : {}),
64
+ };
56
65
  }
57
66
  /**
58
67
  * The install's recorded release, or null when none is recorded (a dev-mode
@@ -66,14 +75,16 @@ export function readRelease(caeloDir) {
66
75
  const raw = JSON.parse(readFileSync(path, "utf8"));
67
76
  const admin = raw.images?.admin ?? "";
68
77
  const gateway = raw.images?.gateway ?? "";
78
+ const proxy = raw.images?.["mcp-auth-proxy"];
69
79
  if (typeof raw.version !== "string" ||
70
80
  !ghcrImageDigest("admin", admin) ||
71
- !ghcrImageDigest("gateway", gateway)) {
81
+ !ghcrImageDigest("gateway", gateway) ||
82
+ (proxy !== undefined && !ghcrImageDigest("mcp-auth-proxy", proxy))) {
72
83
  throw new Error(`${path} is malformed (needs version + digest-pinned ghcr.io/caelo-cms images); fix it or re-run \`${selfCommand("upgrade", "--version", "<x.y.z>")}\`.`);
73
84
  }
74
85
  return {
75
86
  version: raw.version,
76
- images: { admin, gateway },
87
+ images: { admin, gateway, ...(proxy !== undefined ? { "mcp-auth-proxy": proxy } : {}) },
77
88
  installedAt: raw.installedAt ?? "",
78
89
  history: Array.isArray(raw.history) ? raw.history : [],
79
90
  };
@@ -87,7 +98,7 @@ export function recordRelease(caeloDir, next, entry, now = new Date()) {
87
98
  const at = now.toISOString();
88
99
  const record = {
89
100
  version: next.version,
90
- images: { admin: next.images.admin, gateway: next.images.gateway },
101
+ images: recordedImages(next.images),
91
102
  installedAt: prior && prior.version === next.version && entry.outcome === "rolled-back"
92
103
  ? prior.installedAt
93
104
  : at,
@@ -102,7 +113,7 @@ export function recordRollback(caeloDir, current, attempted, detail, now = new D
102
113
  recordRelease(caeloDir, { version: current.version, images: releaseImages(current) }, { from: current.version, to: attempted, outcome: "rolled-back", detail }, now);
103
114
  }
104
115
  /**
105
- * Resolve the admin + gateway images of release `tag` in GHCR to digests,
116
+ * Resolve every release image of `tag` (RELEASE_SERVICES) in GHCR to digests,
106
117
  * then cosign-verify each digest against the Caelo release workflow
107
118
  * identity (unless `skipVerify`, the escape hatch for forks). The returned
108
119
  * references are digest-pinned, so what was verified is exactly what runs.
@@ -112,6 +123,14 @@ export async function resolveVerifiedRelease(tag, deps) {
112
123
  for (const service of RELEASE_SERVICES) {
113
124
  deps.onProgress?.(`Resolving ${GHCR_REGISTRY}/${GHCR_NAMESPACE}/${service}:${tag}`);
114
125
  const r = await resolveRegistryDigest(GHCR_REGISTRY, `${GHCR_NAMESPACE}/${service}`, tag, deps.fetchImpl);
126
+ if (!r.ok && r.notFound && service === "mcp-auth-proxy") {
127
+ // #1328 — releases from before the MCP-Auth-Proxy ship no image of it,
128
+ // and they stay installable and rollback targets: their Compose file
129
+ // simply has no proxy (ReleaseImages models the absence). Only a
130
+ // registry verdict that the tag does not exist means that; an outage
131
+ // still fails below, never silently installs a release without it.
132
+ continue;
133
+ }
115
134
  if (!r.ok) {
116
135
  return {
117
136
  ok: false,
@@ -121,10 +140,12 @@ export async function resolveVerifiedRelease(tag, deps) {
121
140
  }
122
141
  refs[service] = ghcrImageRef(service, r.digest);
123
142
  }
143
+ const proxy = refs["mcp-auth-proxy"];
124
144
  const images = {
125
145
  mode: "release",
126
146
  admin: refs.admin ?? "",
127
147
  gateway: refs.gateway ?? "",
148
+ ...(proxy ? { "mcp-auth-proxy": proxy } : {}),
128
149
  };
129
150
  if (deps.skipVerify)
130
151
  return { ok: true, images };
@@ -138,12 +159,15 @@ export async function resolveVerifiedRelease(tag, deps) {
138
159
  };
139
160
  }
140
161
  for (const service of RELEASE_SERVICES) {
162
+ const ref = images[service];
163
+ if (ref === undefined)
164
+ continue;
141
165
  deps.onProgress?.(`Verifying the signature of ${service}`);
142
- const v = await deps.runner.run(cosignVerifyArgv(images[service]));
166
+ const v = await deps.runner.run(cosignVerifyArgv(ref));
143
167
  if (v.exitCode !== 0) {
144
168
  return {
145
169
  ok: false,
146
- error: `cosign verify FAILED for ${images[service]}: its signature does not match the Caelo release workflow.\n` +
170
+ error: `cosign verify FAILED for ${ref}: its signature does not match the Caelo release workflow.\n` +
147
171
  "Either the registry was compromised, the image is a fork's, or sigstore had an outage (retry).\n" +
148
172
  `cosign: ${v.stderr.trim().slice(0, 500)}`,
149
173
  };
@@ -1 +1 @@
1
- {"version":3,"file":"self-hosted-release.js","sourceRoot":"","sources":["../src/self-hosted-release.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"self-hosted-release.js","sourceRoot":"","sources":["../src/self-hosted-release.ts"],"names":[],"mappings":"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"}
@@ -11,8 +11,10 @@
11
11
  * as the Postgres superuser BEFORE it writes the new Compose file: it
12
12
  * creates missing roles and databases and sets each role's password to the
13
13
  * configured one. It also drops the former `gateway_role` (#635: the
14
- * gateway has no cms_admin login), with whatever it still holds. Every
15
- * statement is idempotent.
14
+ * gateway has no cms_admin login), with whatever it still holds, and
15
+ * (#1329) creates the staging database `cms_public_staging` with the
16
+ * staging gateway's login `public_staging_role` on an install from before
17
+ * it. Every statement is idempotent.
16
18
  *
17
19
  * Passwords travel on psql's stdin, never on argv.
18
20
  */
@@ -24,6 +26,34 @@ import type { RolePasswords } from "./compose.js";
24
26
  * append events, write the heartbeat (0270) and its own audit rows.
25
27
  */
26
28
  export declare const AGENT_DB_ROLE = "caelo_agent";
29
+ /**
30
+ * #1338 (gateway hardening H3) — what bounds public_role, the gateway's
31
+ * login, on the database: at most this many connections, no statement or
32
+ * idle transaction that runs away, little sort memory per query. The same
33
+ * values as packages/migrations/src/bootstrap.sh and the cms_admin
34
+ * migration that sets them where admin_role may (Cloud SQL); the role audit
35
+ * (packages/migrations role-audit.ts) refuses an install without them.
36
+ * Self-hosted admin_role has no CREATEROLE, so the superuser applies them
37
+ * here — on the volume's first start (bootstrap.sh), on every `up`, and
38
+ * before the migrations of every upgrade ({@link preMigrationRolesScript}).
39
+ * Since #1329 the staging gateway's public_staging_role carries the same.
40
+ */
41
+ export declare const PUBLIC_ROLE_LIMITS: {
42
+ readonly connectionLimit: 30;
43
+ readonly statementTimeout: "5s";
44
+ readonly idleInTransactionSessionTimeout: "15s";
45
+ readonly workMem: "1MB";
46
+ };
47
+ /**
48
+ * The psql script (superuser) the self-hosted upgrade runs BEFORE the
49
+ * migrations: the gateway logins' {@link PUBLIC_ROLE_LIMITS} (#1338) and
50
+ * (#1329) the staging database with its login. The migrations' role audit
51
+ * refuses either gateway login without its limits, and the
52
+ * cms_public_staging run needs the database; the full convergence must
53
+ * wait until after them (it drops roles a migration retired). Fails when
54
+ * public_role does not exist — the install's roles were never created.
55
+ */
56
+ export declare function preMigrationRolesScript(stagingPassword: string): string;
27
57
  /**
28
58
  * The psql script (run as the superuser, connected to any database) that
29
59
  * brings roles and databases to the configured state.
@@ -47,6 +77,17 @@ export type SuperuserPsql = (script: string) => Promise<{
47
77
  exitCode: number;
48
78
  stderr: string;
49
79
  }>;
80
+ /**
81
+ * Apply {@link preMigrationRolesScript} through the running Postgres
82
+ * container. Unlike {@link convergeSelfHostedRoles} a stopped database is a
83
+ * failure: the upgrade runs it right before migrations that need it.
84
+ */
85
+ export declare function applyPreMigrationRoles(deps: {
86
+ readonly probe: () => Promise<boolean>;
87
+ readonly psql: SuperuserPsql;
88
+ /** #1329 — public_staging_role's password from `.caelo/config.json`. */
89
+ readonly stagingPassword: string;
90
+ }): Promise<ConvergeOutcome>;
50
91
  export type ConvergeOutcome = {
51
92
  readonly ok: true;
52
93
  }
@@ -1 +1 @@
1
- {"version":3,"file":"self-hosted-roles.d.ts","sourceRoot":"","sources":["../src/self-hosted-roles.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAOlD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,gBAAgB,CAAC;AAqD3C;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,aAAa,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAS9F;AASD;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAqBnF;AAED,kFAAkF;AAClF,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE9F,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;CAAE;AACvB,+EAA+E;GAC7E;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhF;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,aAAa,EACxB,IAAI,EAAE;IACJ,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC,GACA,OAAO,CAAC,eAAe,CAAC,CAO1B;AAED,+DAA+D;AAC/D,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACxF;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,GAAG,UAAU,CAoBtF"}
1
+ {"version":3,"file":"self-hosted-roles.d.ts","sourceRoot":"","sources":["../src/self-hosted-roles.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAOlD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,gBAAgB,CAAC;AAS3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB;;;;;CAKrB,CAAC;AAmCX;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAOvE;AAmDD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,aAAa,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAU9F;AAUD;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAqBnF;AAED,kFAAkF;AAClF,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE9F;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,wEAAwE;IACxE,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC,GAAG,OAAO,CAAC,eAAe,CAAC,CAO3B;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;CAAE;AACvB,+EAA+E;GAC7E;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhF;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,aAAa,EACxB,IAAI,EAAE;IACJ,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC,GACA,OAAO,CAAC,eAAe,CAAC,CAO1B;AAED,+DAA+D;AAC/D,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACxF;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,GAAG,UAAU,CAoBtF"}
@@ -11,7 +11,72 @@ function literal(s) {
11
11
  */
12
12
  export const AGENT_DB_ROLE = "caelo_agent";
13
13
  /** The application roles bootstrap.sh and the convergence create. */
14
- const APP_ROLES = ["admin_role", "public_role"];
14
+ const APP_ROLES = ["admin_role", "public_role", "public_staging_role"];
15
+ /** #1329 — the gateway logins that carry {@link PUBLIC_ROLE_LIMITS}: the live and the staging one. */
16
+ const GATEWAY_LOGINS = ["public_role", "public_staging_role"];
17
+ /**
18
+ * #1338 (gateway hardening H3) — what bounds public_role, the gateway's
19
+ * login, on the database: at most this many connections, no statement or
20
+ * idle transaction that runs away, little sort memory per query. The same
21
+ * values as packages/migrations/src/bootstrap.sh and the cms_admin
22
+ * migration that sets them where admin_role may (Cloud SQL); the role audit
23
+ * (packages/migrations role-audit.ts) refuses an install without them.
24
+ * Self-hosted admin_role has no CREATEROLE, so the superuser applies them
25
+ * here — on the volume's first start (bootstrap.sh), on every `up`, and
26
+ * before the migrations of every upgrade ({@link preMigrationRolesScript}).
27
+ * Since #1329 the staging gateway's public_staging_role carries the same.
28
+ */
29
+ export const PUBLIC_ROLE_LIMITS = {
30
+ connectionLimit: 30,
31
+ statementTimeout: "5s",
32
+ idleInTransactionSessionTimeout: "15s",
33
+ workMem: "1MB",
34
+ };
35
+ /** The statements that apply {@link PUBLIC_ROLE_LIMITS} to both gateway logins (idempotent). */
36
+ function publicRoleLimitsSql() {
37
+ const l = PUBLIC_ROLE_LIMITS;
38
+ return GATEWAY_LOGINS.flatMap((role) => [
39
+ `ALTER ROLE ${role} CONNECTION LIMIT ${l.connectionLimit};`,
40
+ `ALTER ROLE ${role} SET statement_timeout = '${l.statementTimeout}';`,
41
+ `ALTER ROLE ${role} SET idle_in_transaction_session_timeout = '${l.idleInTransactionSessionTimeout}';`,
42
+ `ALTER ROLE ${role} SET work_mem = '${l.workMem}';`,
43
+ ]);
44
+ }
45
+ /**
46
+ * #1329 — the staging database and its gateway login, with each gateway
47
+ * login on its own database only (the same as bootstrap.sh and cms_admin
48
+ * migration 0530). Idempotent: an install from before #1329 gets both, an
49
+ * install that has them gets the password re-applied.
50
+ */
51
+ function stagingDatabaseSql(password) {
52
+ return [
53
+ "SELECT 'CREATE ROLE public_staging_role NOINHERIT LOGIN' WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'public_staging_role') \\gexec",
54
+ `ALTER ROLE public_staging_role WITH LOGIN PASSWORD ${password("public_staging_role")};`,
55
+ "SELECT 'CREATE DATABASE cms_public_staging OWNER admin_role' WHERE NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = 'cms_public_staging') \\gexec",
56
+ "REVOKE ALL ON DATABASE cms_public_staging FROM PUBLIC;",
57
+ "GRANT CONNECT ON DATABASE cms_public_staging TO public_staging_role, admin_role;",
58
+ "REVOKE ALL ON DATABASE cms_public_staging FROM public_role;",
59
+ "REVOKE ALL ON DATABASE cms_public FROM public_staging_role;",
60
+ "REVOKE ALL ON DATABASE cms_admin FROM public_staging_role;",
61
+ ];
62
+ }
63
+ /**
64
+ * The psql script (superuser) the self-hosted upgrade runs BEFORE the
65
+ * migrations: the gateway logins' {@link PUBLIC_ROLE_LIMITS} (#1338) and
66
+ * (#1329) the staging database with its login. The migrations' role audit
67
+ * refuses either gateway login without its limits, and the
68
+ * cms_public_staging run needs the database; the full convergence must
69
+ * wait until after them (it drops roles a migration retired). Fails when
70
+ * public_role does not exist — the install's roles were never created.
71
+ */
72
+ export function preMigrationRolesScript(stagingPassword) {
73
+ return [
74
+ "\\set ON_ERROR_STOP on",
75
+ ...stagingDatabaseSql(() => literal(stagingPassword)),
76
+ ...publicRoleLimitsSql(),
77
+ "",
78
+ ].join("\n");
79
+ }
15
80
  /**
16
81
  * The convergence SQL (psql, as the superuser, connected to any database).
17
82
  * `password` renders each role's password; `agent` adds the agent's login.
@@ -23,6 +88,7 @@ function convergenceSql(password, agent) {
23
88
  `SELECT 'CREATE ROLE ${role} NOINHERIT LOGIN' WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '${role}') \\gexec`,
24
89
  `ALTER ROLE ${role} WITH LOGIN PASSWORD ${password(role)};`,
25
90
  ]),
91
+ ...publicRoleLimitsSql(),
26
92
  // The upgrader's role (migration 0267 creates it only with CREATEROLE,
27
93
  // which the self-hosted admin_role lacks).
28
94
  "SELECT 'CREATE ROLE platform_updater NOLOGIN' WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'platform_updater') \\gexec",
@@ -41,11 +107,15 @@ function convergenceSql(password, agent) {
41
107
  "REVOKE ALL ON DATABASE cms_public FROM PUBLIC;",
42
108
  "GRANT CONNECT ON DATABASE cms_admin TO admin_role;",
43
109
  "GRANT CONNECT ON DATABASE cms_public TO public_role, admin_role;",
110
+ // #1329 — after the other two databases exist: its revokes name them.
111
+ ...stagingDatabaseSql(password),
44
112
  // #635 — the gateway's former cms_admin login goes, with whatever it
45
113
  // still holds in either database (the superuser may drop what
46
114
  // migration 0285 could only revoke).
47
115
  "\\connect cms_public",
48
116
  "DO $$ BEGIN IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'gateway_role') THEN DROP OWNED BY gateway_role; END IF; END $$;",
117
+ "\\connect cms_public_staging",
118
+ "DO $$ BEGIN IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'gateway_role') THEN DROP OWNED BY gateway_role; END IF; END $$;",
49
119
  "\\connect cms_admin",
50
120
  "DO $$ BEGIN IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'gateway_role') THEN DROP OWNED BY gateway_role; END IF; END $$;",
51
121
  "DO $$ BEGIN IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'gateway_role') THEN DROP ROLE gateway_role; END IF; END $$;",
@@ -65,6 +135,7 @@ export function roleConvergenceScript(passwords, agentPassword) {
65
135
  const byRole = {
66
136
  admin_role: passwords.admin,
67
137
  public_role: passwords.public,
138
+ public_staging_role: passwords.publicStaging,
68
139
  };
69
140
  return convergenceSql((role) => literal(role === AGENT_DB_ROLE ? (agentPassword ?? "") : byRole[role]), agentPassword !== undefined);
70
141
  }
@@ -72,6 +143,7 @@ export function roleConvergenceScript(passwords, agentPassword) {
72
143
  const PASSWORD_ENV = {
73
144
  admin_role: "ADMIN_ROLE_PASSWORD",
74
145
  public_role: "PUBLIC_ROLE_PASSWORD",
146
+ public_staging_role: "PUBLIC_STAGING_ROLE_PASSWORD",
75
147
  [AGENT_DB_ROLE]: "AGENT_ROLE_PASSWORD",
76
148
  };
77
149
  /**
@@ -104,6 +176,20 @@ ${variables}
104
176
  ${convergenceSql((role) => `:'${role}_pw'`, opts.agent)}CAELO_SQL
105
177
  `;
106
178
  }
179
+ /**
180
+ * Apply {@link preMigrationRolesScript} through the running Postgres
181
+ * container. Unlike {@link convergeSelfHostedRoles} a stopped database is a
182
+ * failure: the upgrade runs it right before migrations that need it.
183
+ */
184
+ export async function applyPreMigrationRoles(deps) {
185
+ if (!(await deps.probe())) {
186
+ return { ok: false, reachable: false, error: "the Postgres container is not running" };
187
+ }
188
+ const r = await deps.psql(preMigrationRolesScript(deps.stagingPassword));
189
+ if (r.exitCode === 0)
190
+ return { ok: true };
191
+ return { ok: false, reachable: true, error: r.stderr.trim() || `psql exited ${r.exitCode}` };
192
+ }
107
193
  /**
108
194
  * Apply {@link roleConvergenceScript}. `probe` says whether the database is
109
195
  * up; when it is not, nothing is attempted and the caller decides whether
@@ -1 +1 @@
1
- {"version":3,"file":"self-hosted-roles.js","sourceRoot":"","sources":["../src/self-hosted-roles.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"self-hosted-roles.js","sourceRoot":"","sources":["../src/self-hosted-roles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Read the interval `init` recorded in a `.caelo/config.json`.
3
+ *
4
+ * @param configPath - the install's `config.json`.
5
+ * @returns the recorded minutes, or undefined when there is no config.json
6
+ * (a Pulumi-only install) or it records no interval (the default).
7
+ * @throws when the file is not JSON or the recorded value is out of bounds.
8
+ */
9
+ export declare function recordedSchedulerIntervalMinutes(configPath: string): number | undefined;
10
+ /**
11
+ * The interval the self-hosted Pulumi stack renders into the Compose file.
12
+ *
13
+ * @param pulumiValue - `caelo-self-hosted:schedulerIntervalMinutes`, if set.
14
+ * @param recorded - what {@link recordedSchedulerIntervalMinutes} read.
15
+ * @param configPath - named in the refusal.
16
+ * @returns the minutes to render; undefined means neither source sets one
17
+ * (the generator's default).
18
+ * @throws when both are set and differ.
19
+ */
20
+ export declare function selfHostedSchedulerIntervalMinutes(pulumiValue: number | undefined, recorded: number | undefined, configPath: string): number | undefined;
21
+ //# sourceMappingURL=self-hosted-scheduler-interval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-hosted-scheduler-interval.d.ts","sourceRoot":"","sources":["../src/self-hosted-scheduler-interval.ts"],"names":[],"mappings":"AAqBA;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAmBvF;AAED;;;;;;;;;GASG;AACH,wBAAgB,kCAAkC,CAChD,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,UAAU,EAAE,MAAM,GACjB,MAAM,GAAG,SAAS,CAcpB"}
@@ -0,0 +1,68 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ /**
3
+ * #1140 — the self-hosted scheduler interval has two places it can be set:
4
+ * `cms-provision init --scheduler-interval-minutes` records it in
5
+ * `.caelo/config.json` (which every CLI render — `up`, `upgrade`, agent
6
+ * apply — reads), and the Pulumi stack has the config key
7
+ * `caelo-self-hosted:schedulerIntervalMinutes`. Both rewrite the same
8
+ * `docker-compose.yml`, so if each read only its own source a `pulumi up`
9
+ * over a CLI install would silently put the interval back to the default,
10
+ * and the next CLI `upgrade` would undo a Pulumi-only value the same way.
11
+ *
12
+ * The recorded `.caelo/config.json` is the install's one record (the CLI
13
+ * renders from nothing else), so the stack takes the interval from it; the
14
+ * Pulumi key may restate it but a different value is refused rather than
15
+ * one side winning silently (CLAUDE.md §2: no fallbacks).
16
+ */
17
+ import { existsSync, readFileSync } from "node:fs";
18
+ import { parseSchedulerIntervalMinutes } from "./stack-contract.js";
19
+ /**
20
+ * Read the interval `init` recorded in a `.caelo/config.json`.
21
+ *
22
+ * @param configPath - the install's `config.json`.
23
+ * @returns the recorded minutes, or undefined when there is no config.json
24
+ * (a Pulumi-only install) or it records no interval (the default).
25
+ * @throws when the file is not JSON or the recorded value is out of bounds.
26
+ */
27
+ export function recordedSchedulerIntervalMinutes(configPath) {
28
+ if (!existsSync(configPath))
29
+ return undefined;
30
+ let parsed;
31
+ try {
32
+ parsed = JSON.parse(readFileSync(configPath, "utf8"));
33
+ }
34
+ catch (e) {
35
+ throw new Error(`${configPath} is not valid JSON: ${e.message}`);
36
+ }
37
+ const raw = parsed !== null && typeof parsed === "object"
38
+ ? parsed.schedulerIntervalMinutes
39
+ : undefined;
40
+ if (raw === undefined)
41
+ return undefined;
42
+ if (typeof raw !== "number") {
43
+ throw new Error(`${configPath}: schedulerIntervalMinutes ${JSON.stringify(raw)} is not a number of minutes`);
44
+ }
45
+ return parseSchedulerIntervalMinutes(raw, `${configPath}: schedulerIntervalMinutes`);
46
+ }
47
+ /**
48
+ * The interval the self-hosted Pulumi stack renders into the Compose file.
49
+ *
50
+ * @param pulumiValue - `caelo-self-hosted:schedulerIntervalMinutes`, if set.
51
+ * @param recorded - what {@link recordedSchedulerIntervalMinutes} read.
52
+ * @param configPath - named in the refusal.
53
+ * @returns the minutes to render; undefined means neither source sets one
54
+ * (the generator's default).
55
+ * @throws when both are set and differ.
56
+ */
57
+ export function selfHostedSchedulerIntervalMinutes(pulumiValue, recorded, configPath) {
58
+ if (pulumiValue === undefined)
59
+ return recorded;
60
+ const minutes = parseSchedulerIntervalMinutes(pulumiValue, "caelo-self-hosted:schedulerIntervalMinutes");
61
+ if (recorded !== undefined && recorded !== minutes) {
62
+ throw new Error(`caelo-self-hosted:schedulerIntervalMinutes is ${minutes} but ${configPath} records ${recorded}; ` +
63
+ "the CLI renders the Compose file from config.json, so the two must agree. " +
64
+ `Set the Pulumi key to ${recorded}, or remove it (\`pulumi config rm caelo-self-hosted:schedulerIntervalMinutes\`) to use the recorded value.`);
65
+ }
66
+ return minutes;
67
+ }
68
+ //# sourceMappingURL=self-hosted-scheduler-interval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-hosted-scheduler-interval.js","sourceRoot":"","sources":["../src/self-hosted-scheduler-interval.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAEnC;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AAEpE;;;;;;;GAOG;AACH,MAAM,UAAU,gCAAgC,CAAC,UAAkB;IACjE,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9C,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,uBAAwB,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,MAAM,GAAG,GACP,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ;QAC3C,CAAC,CAAE,MAAiD,CAAC,wBAAwB;QAC7E,CAAC,CAAC,SAAS,CAAC;IAChB,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACxC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACb,GAAG,UAAU,8BAA8B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,6BAA6B,CAC5F,CAAC;IACJ,CAAC;IACD,OAAO,6BAA6B,CAAC,GAAG,EAAE,GAAG,UAAU,4BAA4B,CAAC,CAAC;AACvF,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,kCAAkC,CAChD,WAA+B,EAC/B,QAA4B,EAC5B,UAAkB;IAElB,IAAI,WAAW,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAC/C,MAAM,OAAO,GAAG,6BAA6B,CAC3C,WAAW,EACX,4CAA4C,CAC7C,CAAC;IACF,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CACb,iDAAiD,OAAO,QAAQ,UAAU,YAAY,QAAQ,IAAI;YAChG,4EAA4E;YAC5E,yBAAyB,QAAQ,6GAA6G,CACjJ,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -1,24 +1,3 @@
1
- /**
2
- * Start (or converge) a self-hosted Compose install — what `init` and `up`
3
- * run after writing `.caelo/`, so one command ends with a serving install
4
- * (CLAUDE.md §11.C, issue #707) instead of printing steps to copy.
5
- *
6
- * Order, and why:
7
- * 1. pull every image, with the progress on the terminal (the admin image
8
- * is large; a silent multi-minute step reads as a hang);
9
- * 2. start Postgres and wait for its health check — on a fresh volume its
10
- * first start runs bootstrap.sh (roles + databases);
11
- * 3. apply the migrations with the install's admin image;
12
- * 4. start everything (`--remove-orphans` drops services an older Compose
13
- * file had, e.g. the pgBackRest sidecar);
14
- * 5. health-check the admin (`/_caelo/health` proves the DB pool and its
15
- * role) and the gateway;
16
- * 6. reload Caddy — Compose does not restart a running Caddy when only
17
- * its bind-mounted Caddyfile changed, so a re-run `up` would otherwise
18
- * keep serving the old vhosts.
19
- * Every step converges, so a re-run after a failure picks up where it
20
- * stopped.
21
- */
22
1
  import type { HostRunner } from "./self-hosted-release.js";
23
2
  export interface StartDeps {
24
3
  readonly caeloDir: string;
@@ -1 +1 @@
1
- {"version":3,"file":"self-hosted-start.d.ts","sourceRoot":"","sources":["../src/self-hosted-start.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAG3D,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,oEAAoE;IACpE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;CAAE,GACrB;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/E,KAAK,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEjF,sGAAsG;AACtG,wBAAsB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAgD3E;AAED,gFAAgF;AAChF,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAoBtD"}
1
+ {"version":3,"file":"self-hosted-start.d.ts","sourceRoot":"","sources":["../src/self-hosted-start.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAI3D,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,oEAAoE;IACpE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;CAAE,GACrB;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/E,KAAK,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEjF,sGAAsG;AACtG,wBAAsB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CA+D3E;AAED,gFAAgF;AAChF,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAoBtD"}
@@ -1,4 +1,27 @@
1
1
  // SPDX-License-Identifier: MPL-2.0
2
+ /**
3
+ * Start (or converge) a self-hosted Compose install — what `init` and `up`
4
+ * run after writing `.caelo/`, so one command ends with a serving install
5
+ * (CLAUDE.md §11.C, issue #707) instead of printing steps to copy.
6
+ *
7
+ * Order, and why:
8
+ * 1. pull every image, with the progress on the terminal (the admin image
9
+ * is large; a silent multi-minute step reads as a hang);
10
+ * 2. start Postgres and wait for its health check — on a fresh volume its
11
+ * first start runs bootstrap.sh (roles + databases);
12
+ * 3. apply the migrations with the install's admin image;
13
+ * 4. start everything (`--remove-orphans` drops services an older Compose
14
+ * file had, e.g. the pgBackRest sidecar);
15
+ * 5. health-check the admin (`/_caelo/health` proves the DB pool and its
16
+ * role), the gateway and — when the release has one — the
17
+ * MCP-Auth-Proxy (#1328);
18
+ * 6. reload Caddy — Compose does not restart a running Caddy when only
19
+ * its bind-mounted Caddyfile changed, so a re-run `up` would otherwise
20
+ * keep serving the old vhosts.
21
+ * Every step converges, so a re-run after a failure picks up where it
22
+ * stopped.
23
+ */
24
+ import { COMPOSE_MCP_AUTH_PROXY_SERVICE } from "./compose.js";
2
25
  import { compose, runMigrations, waitHealthy } from "./self-hosted-upgrade.js";
3
26
  /** Bring the install's Compose stack up and prove it serves. Never throws for an expected failure. */
4
27
  export async function startSelfHosted(deps) {
@@ -25,7 +48,22 @@ export async function startSelfHosted(deps) {
25
48
  });
26
49
  if (up.exitCode !== 0)
27
50
  return fail("start", "docker compose up failed (see above).");
28
- for (const service of ["admin", "gateway"]) {
51
+ // #1328 — the MCP-Auth-Proxy too, when the release this file runs has one
52
+ // (a release from before it has none; Compose knows which).
53
+ const listed = await runner.run(compose(caeloDir, "config", "--services"));
54
+ if (listed.exitCode !== 0) {
55
+ return fail("start", `docker compose config --services failed: ${listed.stderr.trim()}`);
56
+ }
57
+ const runsProxy = listed.stdout
58
+ .split("\n")
59
+ .map((s) => s.trim())
60
+ .includes(COMPOSE_MCP_AUTH_PROXY_SERVICE);
61
+ const services = [
62
+ "admin",
63
+ "gateway",
64
+ ...(runsProxy ? ["mcp-auth-proxy"] : []),
65
+ ];
66
+ for (const service of services) {
29
67
  log(`Waiting for the ${service} to answer its health check …`);
30
68
  const healthy = await waitHealthy(service, caeloDir, {
31
69
  runner,
@@ -1 +1 @@
1
- {"version":3,"file":"self-hosted-start.js","sourceRoot":"","sources":["../src/self-hosted-start.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"self-hosted-start.js","sourceRoot":"","sources":["../src/self-hosted-start.ts"],"names":[],"mappings":"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"}