@caelo-cms/provisioning 0.11.10 → 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 (212) hide show
  1. package/dist/adapter.d.ts +6 -0
  2. package/dist/adapter.d.ts.map +1 -1
  3. package/dist/adopt-existing.d.ts +6 -2
  4. package/dist/adopt-existing.d.ts.map +1 -1
  5. package/dist/adopt-existing.js +57 -0
  6. package/dist/adopt-existing.js.map +1 -1
  7. package/dist/agent/command.d.ts +5 -2
  8. package/dist/agent/command.d.ts.map +1 -1
  9. package/dist/agent/command.js +1 -1
  10. package/dist/agent/command.js.map +1 -1
  11. package/dist/agent-db.js +25 -8
  12. package/dist/cli-routing.js +1 -1
  13. package/dist/cli-routing.js.map +1 -1
  14. package/dist/cli.js +59 -7
  15. package/dist/cli.js.map +1 -1
  16. package/dist/cloudsql-tls.d.ts +30 -0
  17. package/dist/cloudsql-tls.d.ts.map +1 -1
  18. package/dist/cloudsql-tls.js +7 -1
  19. package/dist/cloudsql-tls.js.map +1 -1
  20. package/dist/compose.d.ts +14 -0
  21. package/dist/compose.d.ts.map +1 -1
  22. package/dist/compose.js +54 -1
  23. package/dist/compose.js.map +1 -1
  24. package/dist/converge-db-trust.d.ts +44 -0
  25. package/dist/converge-db-trust.d.ts.map +1 -0
  26. package/dist/converge-db-trust.js +158 -0
  27. package/dist/converge-db-trust.js.map +1 -0
  28. package/dist/converge-job-gcp.d.ts +5 -2
  29. package/dist/converge-job-gcp.d.ts.map +1 -1
  30. package/dist/converge-job-gcp.js +9 -2
  31. package/dist/converge-job-gcp.js.map +1 -1
  32. package/dist/converge-job-preflight.d.ts.map +1 -1
  33. package/dist/converge-job-preflight.js +8 -0
  34. package/dist/converge-job-preflight.js.map +1 -1
  35. package/dist/converge-job.d.ts +17 -0
  36. package/dist/converge-job.d.ts.map +1 -1
  37. package/dist/converge-job.js +12 -0
  38. package/dist/converge-job.js.map +1 -1
  39. package/dist/gcp-names.d.ts +13 -0
  40. package/dist/gcp-names.d.ts.map +1 -1
  41. package/dist/gcp-names.js +21 -0
  42. package/dist/gcp-names.js.map +1 -1
  43. package/dist/index.d.ts +2 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +1 -0
  46. package/dist/index.js.map +1 -1
  47. package/dist/infra-contract.d.ts +1 -1
  48. package/dist/infra-contract.d.ts.map +1 -1
  49. package/dist/infra-contract.js +22 -1
  50. package/dist/infra-contract.js.map +1 -1
  51. package/dist/install-job.d.ts +4 -2
  52. package/dist/install-job.d.ts.map +1 -1
  53. package/dist/install-job.js +4 -1
  54. package/dist/install-job.js.map +1 -1
  55. package/dist/install-state.d.ts +7 -0
  56. package/dist/install-state.d.ts.map +1 -1
  57. package/dist/install-state.js.map +1 -1
  58. package/dist/lifecycle.d.ts.map +1 -1
  59. package/dist/lifecycle.js +3 -0
  60. package/dist/lifecycle.js.map +1 -1
  61. package/dist/migration-runner.d.ts.map +1 -1
  62. package/dist/migration-runner.js +8 -3
  63. package/dist/migration-runner.js.map +1 -1
  64. package/dist/migration-targets.d.ts +11 -0
  65. package/dist/migration-targets.d.ts.map +1 -0
  66. package/dist/migration-targets.js +12 -0
  67. package/dist/migration-targets.js.map +1 -0
  68. package/dist/operator-access.d.ts +10 -0
  69. package/dist/operator-access.d.ts.map +1 -1
  70. package/dist/operator-access.js +5 -0
  71. package/dist/operator-access.js.map +1 -1
  72. package/dist/pool-budget-stack.d.ts +13 -1
  73. package/dist/pool-budget-stack.d.ts.map +1 -1
  74. package/dist/pool-budget-stack.js +11 -1
  75. package/dist/pool-budget-stack.js.map +1 -1
  76. package/dist/public-role-isolation.d.ts +7 -3
  77. package/dist/public-role-isolation.d.ts.map +1 -1
  78. package/dist/public-role-isolation.js +25 -13
  79. package/dist/public-role-isolation.js.map +1 -1
  80. package/dist/release-contract.d.ts.map +1 -1
  81. package/dist/release-contract.js +3 -0
  82. package/dist/release-contract.js.map +1 -1
  83. package/dist/runtime-secrets.d.ts +2 -0
  84. package/dist/runtime-secrets.d.ts.map +1 -1
  85. package/dist/runtime-secrets.js +19 -15
  86. package/dist/runtime-secrets.js.map +1 -1
  87. package/dist/scheduler-setup.d.ts +75 -0
  88. package/dist/scheduler-setup.d.ts.map +1 -0
  89. package/dist/scheduler-setup.js +331 -0
  90. package/dist/scheduler-setup.js.map +1 -0
  91. package/dist/self-hosted-roles.d.ts +16 -9
  92. package/dist/self-hosted-roles.d.ts.map +1 -1
  93. package/dist/self-hosted-roles.js +49 -15
  94. package/dist/self-hosted-roles.js.map +1 -1
  95. package/dist/self-hosted-scheduler-interval.d.ts +21 -0
  96. package/dist/self-hosted-scheduler-interval.d.ts.map +1 -0
  97. package/dist/self-hosted-scheduler-interval.js +68 -0
  98. package/dist/self-hosted-scheduler-interval.js.map +1 -0
  99. package/dist/self-hosted-upgrade.d.ts +7 -4
  100. package/dist/self-hosted-upgrade.d.ts.map +1 -1
  101. package/dist/self-hosted-upgrade.js +9 -5
  102. package/dist/self-hosted-upgrade.js.map +1 -1
  103. package/dist/stack-contract.d.ts +67 -6
  104. package/dist/stack-contract.d.ts.map +1 -1
  105. package/dist/stack-contract.js +87 -6
  106. package/dist/stack-contract.js.map +1 -1
  107. package/dist/staging-database.d.ts +22 -0
  108. package/dist/staging-database.d.ts.map +1 -0
  109. package/dist/staging-database.js +117 -0
  110. package/dist/staging-database.js.map +1 -0
  111. package/dist/upgrade/converge.d.ts +5 -0
  112. package/dist/upgrade/converge.d.ts.map +1 -1
  113. package/dist/upgrade/converge.js +110 -10
  114. package/dist/upgrade/converge.js.map +1 -1
  115. package/dist/upgrade/upgrade.d.ts +6 -0
  116. package/dist/upgrade/upgrade.d.ts.map +1 -1
  117. package/dist/upgrade/upgrade.js +3 -0
  118. package/dist/upgrade/upgrade.js.map +1 -1
  119. package/dist/upgrader-gcp.d.ts +5 -4
  120. package/dist/upgrader-gcp.d.ts.map +1 -1
  121. package/dist/upgrader-gcp.js +5 -4
  122. package/dist/upgrader-gcp.js.map +1 -1
  123. package/dist/wizard.d.ts +7 -0
  124. package/dist/wizard.d.ts.map +1 -1
  125. package/dist/wizard.js +11 -0
  126. package/dist/wizard.js.map +1 -1
  127. package/dist/wizards/gcp-cost.d.ts +31 -0
  128. package/dist/wizards/gcp-cost.d.ts.map +1 -1
  129. package/dist/wizards/gcp-cost.js +81 -11
  130. package/dist/wizards/gcp-cost.js.map +1 -1
  131. package/dist/wizards/gcp.d.ts.map +1 -1
  132. package/dist/wizards/gcp.js +87 -11
  133. package/dist/wizards/gcp.js.map +1 -1
  134. package/package.json +2 -2
  135. package/src/adapter.ts +6 -0
  136. package/src/admin-memory.test.ts +1 -1
  137. package/src/adopt-existing.test.ts +46 -0
  138. package/src/adopt-existing.ts +58 -2
  139. package/src/agent/command.ts +6 -3
  140. package/src/caddy-redirects.test.ts +1 -1
  141. package/src/cli-routing.test.ts +1 -1
  142. package/src/cli-routing.ts +1 -1
  143. package/src/cli.ts +63 -8
  144. package/src/cloudsql-tls.test.ts +30 -0
  145. package/src/cloudsql-tls.ts +10 -3
  146. package/src/compose.ts +68 -0
  147. package/src/converge-db-trust.test.ts +237 -0
  148. package/src/converge-db-trust.ts +212 -0
  149. package/src/converge-job-gcp.ts +9 -1
  150. package/src/converge-job-preflight.test.ts +5 -0
  151. package/src/converge-job-preflight.ts +8 -0
  152. package/src/converge-job.test.ts +70 -0
  153. package/src/converge-job.ts +32 -0
  154. package/src/database-tls-builders.test.ts +3 -2
  155. package/src/deployed-release.test.ts +3 -0
  156. package/src/gateway-env-isolation.test.ts +40 -7
  157. package/src/gcp-names.ts +25 -0
  158. package/src/index.test.ts +3 -3
  159. package/src/index.ts +6 -0
  160. package/src/infra-contract.test.ts +5 -3
  161. package/src/infra-contract.ts +22 -1
  162. package/src/install-job.ts +4 -1
  163. package/src/install-state.ts +7 -0
  164. package/src/lifecycle.ts +3 -0
  165. package/src/migration-runner.ts +14 -9
  166. package/src/migration-targets.ts +12 -0
  167. package/src/operator-access.test.ts +15 -0
  168. package/src/operator-access.ts +14 -0
  169. package/src/pool-budget-stack.ts +15 -0
  170. package/src/pool-budget-stacks.test.ts +38 -13
  171. package/src/public-role-isolation.test.ts +18 -8
  172. package/src/public-role-isolation.ts +31 -17
  173. package/src/release-contract.ts +3 -0
  174. package/src/runtime-secrets.test.ts +18 -8
  175. package/src/runtime-secrets.ts +37 -18
  176. package/src/scheduler-setup.test.ts +201 -0
  177. package/src/scheduler-setup.ts +375 -0
  178. package/src/self-hosted-backup.test.ts +1 -0
  179. package/src/self-hosted-compose.test.ts +72 -1
  180. package/src/self-hosted-roles.integration.test.ts +2 -0
  181. package/src/self-hosted-roles.test.ts +49 -19
  182. package/src/self-hosted-roles.ts +60 -20
  183. package/src/self-hosted-scheduler-interval.test.ts +66 -0
  184. package/src/self-hosted-scheduler-interval.ts +79 -0
  185. package/src/self-hosted-start.test.ts +1 -0
  186. package/src/self-hosted-upgrade.test.ts +2 -1
  187. package/src/self-hosted-upgrade.ts +14 -8
  188. package/src/stack-contract.test.ts +31 -3
  189. package/src/stack-contract.ts +113 -6
  190. package/src/stack-converge-secrets.test.ts +2 -0
  191. package/src/stack-converge.test.ts +6 -4
  192. package/src/staging-database.test.ts +114 -0
  193. package/src/staging-database.ts +148 -0
  194. package/src/upgrade/converge.ts +130 -9
  195. package/src/upgrade/upgrade.test.ts +85 -2
  196. package/src/upgrade/upgrade.ts +9 -0
  197. package/src/upgrader-gcp.ts +5 -4
  198. package/src/wizard.ts +19 -0
  199. package/src/wizards/gcp-cost.test.ts +54 -1
  200. package/src/wizards/gcp-cost.ts +101 -11
  201. package/src/wizards/gcp.ts +109 -8
  202. package/stacks/aws/Pulumi.yaml +1 -1
  203. package/stacks/aws/index.ts +41 -1
  204. package/stacks/azure/index.ts +51 -3
  205. package/stacks/gcp/Pulumi.yaml +1 -1
  206. package/stacks/gcp/README.md +1 -0
  207. package/stacks/gcp/index.ts +50 -1
  208. package/stacks/gcp-firebase/Pulumi.yaml +1 -1
  209. package/stacks/gcp-firebase/index.ts +50 -1
  210. package/stacks/self-hosted/Pulumi.yaml +3 -0
  211. package/stacks/self-hosted/README.md +4 -0
  212. package/stacks/self-hosted/index.ts +29 -4
@@ -0,0 +1,331 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ /**
3
+ * #1140 — set up (and converge) the scheduler tick on a Google Cloud install
4
+ * (`gcp`, `gcp-firebase`): the ONE Cloud Scheduler job that calls the
5
+ * admin's `/api/internal/scheduler/tick` every `schedulerIntervalMinutes`
6
+ * (1–15, default 5). Each task's own cadence lives in the admin's
7
+ * due-table; the tick only says "run what is due now". Run by the wizard
8
+ * after migrations and by `cms-provision upgrade`'s converge (and the
9
+ * converge job), as the operator's or the provisioner's identity.
10
+ *
11
+ * Why not Cloud Scheduler → admin directly. The admin sits behind IAP, and
12
+ * IAP accepts a service account's OIDC ID token only when its `aud` is an
13
+ * OAuth client allowlisted for programmatic access; an install on the
14
+ * Google-managed IAP client has none (cloud.google.com/iap/docs/
15
+ * authentication-howto). Cloud Scheduler's other credential, an OAuth
16
+ * access token, it sends only to `*.googleapis.com` (cloud.google.com/
17
+ * scheduler/docs/http-target-auth). What passes IAP for a service account
18
+ * on every install is a self-signed service-account JWT with `aud` =
19
+ * `<admin origin>/*` — the path caelo-mcp and admin-internal-google.ts
20
+ * take. Cloud Scheduler cannot sign one, so the job starts a Cloud
21
+ * Workflows execution (a googleapis.com target, OAuth), and the workflow
22
+ * signs the JWT as the scheduler account through the IAM Credentials API
23
+ * and POSTs the tick. No container per tick and no image to keep in step
24
+ * with the app-roll; cents a month (wizards/gcp-cost.ts).
25
+ *
26
+ * Why the CLI owns it and not the stacks: the same as audit-job-setup.ts —
27
+ * `upgrade` never runs Pulumi, and existing installs get the tick from here.
28
+ *
29
+ * Trust boundary. The scheduler's identity, `caelo-<env>-scheduler`, holds:
30
+ *
31
+ * - `roles/iam.serviceAccountTokenCreator` on ITSELF only (signJwt);
32
+ * - `roles/iap.httpsResourceAccessor` on the admin's IAP resource (the
33
+ * operator-access sync job keeps it there, operator-access.ts);
34
+ * - `roles/workflows.invoker` on the project (Cloud Scheduler starts the
35
+ * workflow as it; Workflows has no per-workflow IAM policy to bind to);
36
+ * - `roles/logging.logWriter` (the workflow's error call logs).
37
+ *
38
+ * Nothing else: no Secret Manager, no Cloud SQL, no Cloud Run rights. What
39
+ * it can do with the admin is the admin's to decide: the tick endpoint
40
+ * accepts exactly this account's IAP identity (`CAELO_SCHEDULER_SERVICE_
41
+ * ACCOUNT` on the admin) and only ever runs the due-table, never a build
42
+ * or a publish (scripts/no-automatic-production-deploy.test.ts).
43
+ * {@link SCHEDULER_FORBIDDEN_ROLES} names that line; the tests assert no
44
+ * grant crosses it.
45
+ */
46
+ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
47
+ import { tmpdir } from "node:os";
48
+ import { join } from "node:path";
49
+ import { gcloud as defaultGcloud } from "./gcloud.js";
50
+ import { realSleep, runWithRetry } from "./gcloud-retry.js";
51
+ import { schedulerJobName, schedulerServiceAccountEmail, schedulerServiceAccountId, schedulerWorkflowName, } from "./gcp-names.js";
52
+ import { iapResourceArgs } from "./mcp-iap.js";
53
+ import { schedulerCron } from "./stack-contract.js";
54
+ /** The admin path the workflow calls (apps/admin `api/internal/scheduler/tick`). */
55
+ export const SCHEDULER_TICK_PATH = "/api/internal/scheduler/tick";
56
+ /**
57
+ * How long the workflow waits for the admin's answer, in seconds: Workflows'
58
+ * maximum (cloud.google.com/workflows/docs/reference/stdlib/http/post). The
59
+ * admin holds the request until the tick's work is done: it claims tasks for
60
+ * at most its budget (4 minutes, admin-core scheduler/tick.ts) and then waits
61
+ * at most one task's lease (10 minutes) for the last one, so 14 minutes in
62
+ * the worst case, inside the admin's own 3600 s request timeout.
63
+ */
64
+ export const SCHEDULER_TICK_TIMEOUT_SECONDS = 1800;
65
+ /** Lifetime of the IAP credential the workflow signs per tick. */
66
+ const JWT_LIFETIME_SECONDS = 600;
67
+ /** APIs the tick needs on the project. */
68
+ export const SCHEDULER_APIS = [
69
+ "cloudscheduler.googleapis.com",
70
+ "workflows.googleapis.com",
71
+ "iamcredentials.googleapis.com",
72
+ ];
73
+ /**
74
+ * Roles the scheduler's identity must never hold anywhere. Prefix matches
75
+ * (`roles/secretmanager.` = every Secret Manager role).
76
+ */
77
+ export const SCHEDULER_FORBIDDEN_ROLES = [
78
+ "roles/owner",
79
+ "roles/editor",
80
+ "roles/viewer",
81
+ "roles/run.",
82
+ "roles/iam.serviceAccountUser",
83
+ "roles/iam.serviceAccountAdmin",
84
+ "roles/iam.securityAdmin",
85
+ "roles/iap.admin",
86
+ "roles/iap.settingsAdmin",
87
+ "roles/secretmanager.",
88
+ "roles/cloudsql.",
89
+ "roles/compute.",
90
+ "roles/storage.",
91
+ "roles/resourcemanager.",
92
+ "roles/workflows.admin",
93
+ "roles/workflows.editor",
94
+ "roles/cloudscheduler.",
95
+ ];
96
+ /**
97
+ * The tick's admin origin, or an error naming why it is not one: an https
98
+ * origin without path, query or credentials (it is written into the
99
+ * workflow's source, so nothing but an origin may get there).
100
+ */
101
+ export function tickOrigin(adminUrl) {
102
+ let u;
103
+ try {
104
+ u = new URL(adminUrl);
105
+ }
106
+ catch {
107
+ return { ok: false, error: `the admin URL ${JSON.stringify(adminUrl)} is not a URL` };
108
+ }
109
+ if (u.protocol !== "https:" ||
110
+ u.username ||
111
+ u.password ||
112
+ (u.pathname !== "/" && u.pathname !== "") ||
113
+ u.search ||
114
+ u.hash ||
115
+ !/^[a-z0-9.-]+$/.test(u.hostname)) {
116
+ return {
117
+ ok: false,
118
+ error: `the admin URL ${JSON.stringify(adminUrl)} is not a plain https origin`,
119
+ };
120
+ }
121
+ return { ok: true, origin: u.origin };
122
+ }
123
+ /**
124
+ * The workflow one tick runs (Cloud Workflows YAML): sign a service-account
125
+ * JWT for the admin's IAP as the scheduler account itself (the IAM
126
+ * Credentials API, authenticated with the workflow's own OAuth token), then
127
+ * POST the tick with it. A refused or failed tick (HTTP ≥ 400) fails the
128
+ * execution, so it shows in the workflow's execution history and logs.
129
+ */
130
+ export function schedulerWorkflowSource(opts) {
131
+ const { serviceAccount: sa, origin } = opts;
132
+ return `# Caelo scheduler tick (#1140) — generated by cms-provision, do not edit.
133
+ main:
134
+ steps:
135
+ - claims:
136
+ assign:
137
+ - now: \${int(sys.now())}
138
+ - jwtClaims:
139
+ iss: "${sa}"
140
+ sub: "${sa}"
141
+ aud: "${origin}/*"
142
+ iat: \${now}
143
+ exp: \${now + ${JWT_LIFETIME_SECONDS}}
144
+ - sign:
145
+ call: http.post
146
+ args:
147
+ url: "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${sa}:signJwt"
148
+ auth:
149
+ type: OAuth2
150
+ body:
151
+ payload: \${json.encode_to_string(jwtClaims)}
152
+ result: signed
153
+ - tick:
154
+ call: http.post
155
+ args:
156
+ url: "${origin}${SCHEDULER_TICK_PATH}"
157
+ headers:
158
+ Authorization: \${"Bearer " + signed.body.signedJwt}
159
+ timeout: ${SCHEDULER_TICK_TIMEOUT_SECONDS}
160
+ result: answer
161
+ - done:
162
+ return: \${answer.code}
163
+ `;
164
+ }
165
+ /** Ensure the scheduler tick and everything it needs. Never throws for a gcloud failure. */
166
+ export async function ensureSchedulerTick(target, deps = {}) {
167
+ const run = deps.run ?? defaultGcloud;
168
+ const sleep = deps.sleep ?? realSleep;
169
+ const retry = (args) => runWithRetry(run, sleep, args);
170
+ const { projectId, region, env } = target;
171
+ const project = `--project=${projectId}`;
172
+ const sa = schedulerServiceAccountEmail(projectId, env);
173
+ const member = `serviceAccount:${sa}`;
174
+ const workflow = schedulerWorkflowName(env);
175
+ const job = schedulerJobName(env);
176
+ const done = [];
177
+ const fail = (step, r) => ({
178
+ ok: false,
179
+ done,
180
+ error: `${step}: ${r.stderr.trim()}`,
181
+ });
182
+ const origin = tickOrigin(target.adminUrl);
183
+ if (!origin.ok)
184
+ return { ok: false, done, error: origin.error };
185
+ let cron;
186
+ try {
187
+ cron = schedulerCron(target.intervalMinutes);
188
+ }
189
+ catch (e) {
190
+ return { ok: false, done, error: e.message };
191
+ }
192
+ // 1. APIs.
193
+ const api = await run(["services", "enable", ...SCHEDULER_APIS, project, "--quiet"]);
194
+ if (!api.ok)
195
+ return fail(`enable ${SCHEDULER_APIS.join(", ")}`, api);
196
+ done.push(`APIs enabled (${SCHEDULER_APIS.join(", ")})`);
197
+ // 2. The scheduler's own service account.
198
+ const describe = await run([
199
+ "iam",
200
+ "service-accounts",
201
+ "describe",
202
+ sa,
203
+ project,
204
+ "--format=value(email)",
205
+ ]);
206
+ if (!describe.ok) {
207
+ const create = await run([
208
+ "iam",
209
+ "service-accounts",
210
+ "create",
211
+ schedulerServiceAccountId(env),
212
+ "--display-name=Caelo scheduler tick",
213
+ "--description=Calls the admin's scheduler tick through IAP every few minutes; signs its own IAP credential, nothing else.",
214
+ project,
215
+ ]);
216
+ if (!create.ok && !/already exists/i.test(create.stderr))
217
+ return fail(`create ${sa}`, create);
218
+ }
219
+ done.push(`service account ${sa}`);
220
+ // 3. Its grants (see the file comment).
221
+ const self = await retry([
222
+ "iam",
223
+ "service-accounts",
224
+ "add-iam-policy-binding",
225
+ sa,
226
+ `--member=${member}`,
227
+ "--role=roles/iam.serviceAccountTokenCreator",
228
+ "--condition=None",
229
+ project,
230
+ "--quiet",
231
+ "--format=none",
232
+ ]);
233
+ if (!self.ok)
234
+ return fail("let the scheduler sign its IAP credential as itself", self);
235
+ done.push(`scheduler: roles/iam.serviceAccountTokenCreator on ${sa} (itself, signJwt)`);
236
+ for (const g of [
237
+ { role: "roles/workflows.invoker", why: "Cloud Scheduler starts the tick workflow as it" },
238
+ { role: "roles/logging.logWriter", why: "the workflow logs failed calls" },
239
+ ]) {
240
+ const r = await retry([
241
+ "projects",
242
+ "add-iam-policy-binding",
243
+ projectId,
244
+ `--member=${member}`,
245
+ `--role=${g.role}`,
246
+ "--condition=None",
247
+ "--quiet",
248
+ "--format=none",
249
+ ]);
250
+ if (!r.ok)
251
+ return fail(`grant the scheduler ${g.role} (${g.why})`, r);
252
+ done.push(`scheduler: ${g.role} on the project`);
253
+ }
254
+ const iap = await retry([
255
+ "iap",
256
+ "web",
257
+ "add-iam-policy-binding",
258
+ ...iapResourceArgs(target.resource),
259
+ `--member=${member}`,
260
+ "--role=roles/iap.httpsResourceAccessor",
261
+ "--condition=None",
262
+ project,
263
+ "--quiet",
264
+ ]);
265
+ if (!iap.ok)
266
+ return fail("let the scheduler pass the admin's IAP", iap);
267
+ done.push(`scheduler: roles/iap.httpsResourceAccessor on the admin (${target.resource.service})`);
268
+ // 4. The workflow. A private directory (mkdtemp, mode 700): no other local
269
+ // user can swap the file between write and read.
270
+ const dir = mkdtempSync(join(tmpdir(), "caelo-scheduler-"));
271
+ try {
272
+ const file = join(dir, "tick.yaml");
273
+ writeFileSync(file, schedulerWorkflowSource({ serviceAccount: sa, origin: origin.origin }), {
274
+ mode: 0o600,
275
+ });
276
+ const deploy = await retry([
277
+ "workflows",
278
+ "deploy",
279
+ workflow,
280
+ `--source=${file}`,
281
+ `--location=${region}`,
282
+ `--service-account=${sa}`,
283
+ "--call-log-level=log-errors-only",
284
+ `--description=Caelo scheduler tick (#1140): calls ${origin.origin}${SCHEDULER_TICK_PATH}`,
285
+ project,
286
+ "--quiet",
287
+ ]);
288
+ if (!deploy.ok)
289
+ return fail(`deploy workflow ${workflow}`, deploy);
290
+ }
291
+ finally {
292
+ rmSync(dir, { recursive: true, force: true });
293
+ }
294
+ done.push(`workflow ${workflow} (calls ${origin.origin}${SCHEDULER_TICK_PATH})`);
295
+ // 5. The one Cloud Scheduler job.
296
+ const scheduleArgs = [
297
+ job,
298
+ `--location=${region}`,
299
+ project,
300
+ `--schedule=${cron}`,
301
+ "--time-zone=Etc/UTC",
302
+ `--uri=https://workflowexecutions.googleapis.com/v1/projects/${projectId}/locations/${region}/workflows/${workflow}/executions`,
303
+ "--http-method=POST",
304
+ `--oauth-service-account-email=${sa}`,
305
+ // A tick that has not answered when the next one is due is the admin's
306
+ // lease to sort out (its due-table), not a reason to retry this one.
307
+ "--max-retry-attempts=0",
308
+ "--quiet",
309
+ ];
310
+ const existing = await run([
311
+ "scheduler",
312
+ "jobs",
313
+ "describe",
314
+ job,
315
+ `--location=${region}`,
316
+ project,
317
+ "--format=value(name)",
318
+ ]);
319
+ const sched = await retry([
320
+ "scheduler",
321
+ "jobs",
322
+ existing.ok ? "update" : "create",
323
+ "http",
324
+ ...scheduleArgs,
325
+ ]);
326
+ if (!sched.ok)
327
+ return fail(`schedule ${job}`, sched);
328
+ done.push(`Cloud Scheduler job ${job} (${cron}, UTC)`);
329
+ return { ok: true, done, serviceAccount: sa };
330
+ }
331
+ //# sourceMappingURL=scheduler-setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler-setup.js","sourceRoot":"","sources":["../src/scheduler-setup.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
  */
@@ -33,7 +35,8 @@ export declare const AGENT_DB_ROLE = "caelo_agent";
33
35
  * (packages/migrations role-audit.ts) refuses an install without them.
34
36
  * Self-hosted admin_role has no CREATEROLE, so the superuser applies them
35
37
  * here — on the volume's first start (bootstrap.sh), on every `up`, and
36
- * before the migrations of every upgrade ({@link publicRoleLimitsScript}).
38
+ * before the migrations of every upgrade ({@link preMigrationRolesScript}).
39
+ * Since #1329 the staging gateway's public_staging_role carries the same.
37
40
  */
38
41
  export declare const PUBLIC_ROLE_LIMITS: {
39
42
  readonly connectionLimit: 30;
@@ -42,13 +45,15 @@ export declare const PUBLIC_ROLE_LIMITS: {
42
45
  readonly workMem: "1MB";
43
46
  };
44
47
  /**
45
- * The psql script (superuser) that applies only {@link PUBLIC_ROLE_LIMITS}.
46
- * The self-hosted upgrade runs it BEFORE the migrations: their role audit
47
- * refuses public_role without the limits, and the full convergence must
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
48
53
  * wait until after them (it drops roles a migration retired). Fails when
49
54
  * public_role does not exist — the install's roles were never created.
50
55
  */
51
- export declare function publicRoleLimitsScript(): string;
56
+ export declare function preMigrationRolesScript(stagingPassword: string): string;
52
57
  /**
53
58
  * The psql script (run as the superuser, connected to any database) that
54
59
  * brings roles and databases to the configured state.
@@ -73,13 +78,15 @@ export type SuperuserPsql = (script: string) => Promise<{
73
78
  stderr: string;
74
79
  }>;
75
80
  /**
76
- * Apply {@link publicRoleLimitsScript} through the running Postgres
81
+ * Apply {@link preMigrationRolesScript} through the running Postgres
77
82
  * container. Unlike {@link convergeSelfHostedRoles} a stopped database is a
78
83
  * failure: the upgrade runs it right before migrations that need it.
79
84
  */
80
- export declare function applyPublicRoleLimits(deps: {
85
+ export declare function applyPreMigrationRoles(deps: {
81
86
  readonly probe: () => Promise<boolean>;
82
87
  readonly psql: SuperuserPsql;
88
+ /** #1329 — public_staging_role's password from `.caelo/config.json`. */
89
+ readonly stagingPassword: string;
83
90
  }): Promise<ConvergeOutcome>;
84
91
  export type ConvergeOutcome = {
85
92
  readonly ok: true;
@@ -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;AAM3C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB;;;;;CAKrB,CAAC;AAaX;;;;;;GAMG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAkDD;;;;;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;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;CAC9B,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"}
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,9 @@ 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"];
15
17
  /**
16
18
  * #1338 (gateway hardening H3) — what bounds public_role, the gateway's
17
19
  * login, on the database: at most this many connections, no statement or
@@ -21,7 +23,8 @@ const APP_ROLES = ["admin_role", "public_role"];
21
23
  * (packages/migrations role-audit.ts) refuses an install without them.
22
24
  * Self-hosted admin_role has no CREATEROLE, so the superuser applies them
23
25
  * here — on the volume's first start (bootstrap.sh), on every `up`, and
24
- * before the migrations of every upgrade ({@link publicRoleLimitsScript}).
26
+ * before the migrations of every upgrade ({@link preMigrationRolesScript}).
27
+ * Since #1329 the staging gateway's public_staging_role carries the same.
25
28
  */
26
29
  export const PUBLIC_ROLE_LIMITS = {
27
30
  connectionLimit: 30,
@@ -29,25 +32,50 @@ export const PUBLIC_ROLE_LIMITS = {
29
32
  idleInTransactionSessionTimeout: "15s",
30
33
  workMem: "1MB",
31
34
  };
32
- /** The statements that apply {@link PUBLIC_ROLE_LIMITS} (idempotent). */
35
+ /** The statements that apply {@link PUBLIC_ROLE_LIMITS} to both gateway logins (idempotent). */
33
36
  function publicRoleLimitsSql() {
34
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) {
35
52
  return [
36
- `ALTER ROLE public_role CONNECTION LIMIT ${l.connectionLimit};`,
37
- `ALTER ROLE public_role SET statement_timeout = '${l.statementTimeout}';`,
38
- `ALTER ROLE public_role SET idle_in_transaction_session_timeout = '${l.idleInTransactionSessionTimeout}';`,
39
- `ALTER ROLE public_role SET work_mem = '${l.workMem}';`,
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;",
40
61
  ];
41
62
  }
42
63
  /**
43
- * The psql script (superuser) that applies only {@link PUBLIC_ROLE_LIMITS}.
44
- * The self-hosted upgrade runs it BEFORE the migrations: their role audit
45
- * refuses public_role without the limits, and the full convergence must
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
46
69
  * wait until after them (it drops roles a migration retired). Fails when
47
70
  * public_role does not exist — the install's roles were never created.
48
71
  */
49
- export function publicRoleLimitsScript() {
50
- return ["\\set ON_ERROR_STOP on", ...publicRoleLimitsSql(), ""].join("\n");
72
+ export function preMigrationRolesScript(stagingPassword) {
73
+ return [
74
+ "\\set ON_ERROR_STOP on",
75
+ ...stagingDatabaseSql(() => literal(stagingPassword)),
76
+ ...publicRoleLimitsSql(),
77
+ "",
78
+ ].join("\n");
51
79
  }
52
80
  /**
53
81
  * The convergence SQL (psql, as the superuser, connected to any database).
@@ -79,11 +107,15 @@ function convergenceSql(password, agent) {
79
107
  "REVOKE ALL ON DATABASE cms_public FROM PUBLIC;",
80
108
  "GRANT CONNECT ON DATABASE cms_admin TO admin_role;",
81
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),
82
112
  // #635 — the gateway's former cms_admin login goes, with whatever it
83
113
  // still holds in either database (the superuser may drop what
84
114
  // migration 0285 could only revoke).
85
115
  "\\connect cms_public",
86
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 $$;",
87
119
  "\\connect cms_admin",
88
120
  "DO $$ BEGIN IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'gateway_role') THEN DROP OWNED BY gateway_role; END IF; END $$;",
89
121
  "DO $$ BEGIN IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'gateway_role') THEN DROP ROLE gateway_role; END IF; END $$;",
@@ -103,6 +135,7 @@ export function roleConvergenceScript(passwords, agentPassword) {
103
135
  const byRole = {
104
136
  admin_role: passwords.admin,
105
137
  public_role: passwords.public,
138
+ public_staging_role: passwords.publicStaging,
106
139
  };
107
140
  return convergenceSql((role) => literal(role === AGENT_DB_ROLE ? (agentPassword ?? "") : byRole[role]), agentPassword !== undefined);
108
141
  }
@@ -110,6 +143,7 @@ export function roleConvergenceScript(passwords, agentPassword) {
110
143
  const PASSWORD_ENV = {
111
144
  admin_role: "ADMIN_ROLE_PASSWORD",
112
145
  public_role: "PUBLIC_ROLE_PASSWORD",
146
+ public_staging_role: "PUBLIC_STAGING_ROLE_PASSWORD",
113
147
  [AGENT_DB_ROLE]: "AGENT_ROLE_PASSWORD",
114
148
  };
115
149
  /**
@@ -143,15 +177,15 @@ ${convergenceSql((role) => `:'${role}_pw'`, opts.agent)}CAELO_SQL
143
177
  `;
144
178
  }
145
179
  /**
146
- * Apply {@link publicRoleLimitsScript} through the running Postgres
180
+ * Apply {@link preMigrationRolesScript} through the running Postgres
147
181
  * container. Unlike {@link convergeSelfHostedRoles} a stopped database is a
148
182
  * failure: the upgrade runs it right before migrations that need it.
149
183
  */
150
- export async function applyPublicRoleLimits(deps) {
184
+ export async function applyPreMigrationRoles(deps) {
151
185
  if (!(await deps.probe())) {
152
186
  return { ok: false, reachable: false, error: "the Postgres container is not running" };
153
187
  }
154
- const r = await deps.psql(publicRoleLimitsScript());
188
+ const r = await deps.psql(preMigrationRolesScript(deps.stagingPassword));
155
189
  if (r.exitCode === 0)
156
190
  return { ok: true };
157
191
  return { ok: false, reachable: true, error: r.stderr.trim() || `psql exited ${r.exitCode}` };
@@ -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"}