@wtfalch/foundry 0.4.0 → 0.5.0

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 (66) hide show
  1. package/dist/bootstrap/bootstrap.d.ts +96 -0
  2. package/dist/bootstrap/bootstrap.js +285 -0
  3. package/dist/bootstrap/declare.d.ts +36 -0
  4. package/dist/bootstrap/declare.js +94 -0
  5. package/dist/bootstrap/drive.d.ts +40 -0
  6. package/dist/bootstrap/drive.js +51 -0
  7. package/dist/bootstrap/index.d.ts +3 -0
  8. package/dist/bootstrap/index.js +1 -0
  9. package/dist/calls-sfu-deploy-support.d.ts +9 -6
  10. package/dist/calls-sfu-deploy-support.js +9 -6
  11. package/dist/calls-sfu-keys.d.ts +21 -0
  12. package/dist/calls-sfu-keys.js +27 -0
  13. package/dist/calls-sfu-ssh-adapter.d.ts +55 -0
  14. package/dist/calls-sfu-ssh-adapter.js +78 -0
  15. package/dist/calls-sfu-ssh-client.d.ts +49 -0
  16. package/dist/calls-sfu-ssh-client.js +82 -0
  17. package/dist/calls-sfu.d.ts +5 -4
  18. package/dist/calls-sfu.js +5 -4
  19. package/dist/index.d.ts +31 -6
  20. package/dist/index.js +16 -3
  21. package/dist/migrations/0016_platform.sql +61 -0
  22. package/dist/migrations/0017_requested_changes.sql +42 -0
  23. package/dist/migrations/0018_platform_apply.sql +19 -0
  24. package/dist/org.js +8 -0
  25. package/dist/plan/agora.d.ts +77 -0
  26. package/dist/plan/agora.js +127 -0
  27. package/dist/plan/cloudflared-connector.d.ts +70 -0
  28. package/dist/plan/cloudflared-connector.js +106 -0
  29. package/dist/plan/diff.d.ts +20 -3
  30. package/dist/plan/diff.js +631 -116
  31. package/dist/plan/executor.d.ts +475 -168
  32. package/dist/plan/executor.js +543 -175
  33. package/dist/plan/index.d.ts +22 -5
  34. package/dist/plan/index.js +12 -2
  35. package/dist/plan/jobs-scheduler-http.d.ts +29 -0
  36. package/dist/plan/jobs-scheduler-http.js +50 -0
  37. package/dist/plan/live.d.ts +51 -2
  38. package/dist/plan/live.js +8 -0
  39. package/dist/plan/plan-apply.d.ts +192 -3
  40. package/dist/plan/plan-apply.js +278 -9
  41. package/dist/plan/platform-diff.d.ts +312 -0
  42. package/dist/plan/platform-diff.js +867 -0
  43. package/dist/plan/platform-org-ports.d.ts +50 -0
  44. package/dist/plan/platform-org-ports.js +70 -0
  45. package/dist/plan/platform-org.d.ts +120 -0
  46. package/dist/plan/platform-org.js +115 -0
  47. package/dist/plan/platform-providers.d.ts +501 -0
  48. package/dist/plan/platform-providers.js +3029 -0
  49. package/dist/plan/platform-sfu.d.ts +93 -0
  50. package/dist/plan/platform-sfu.js +100 -0
  51. package/dist/plan/providers-readers.js +22 -1
  52. package/dist/plan/zitadel-machine-user.d.ts +34 -0
  53. package/dist/plan/zitadel-machine-user.js +95 -0
  54. package/dist/plan.d.ts +6 -0
  55. package/dist/platform.d.ts +55 -0
  56. package/dist/platform.js +46 -0
  57. package/dist/requested-changes.d.ts +108 -0
  58. package/dist/requested-changes.js +95 -0
  59. package/dist/slug.js +15 -2
  60. package/dist/store/audit.js +4 -2
  61. package/dist/store/postgres.d.ts +29 -1
  62. package/dist/store/postgres.js +172 -2
  63. package/dist/store/schema.d.ts +683 -0
  64. package/dist/store/schema.js +57 -0
  65. package/dist/store.d.ts +46 -0
  66. package/package.json +1 -1
@@ -0,0 +1,312 @@
1
+ import type { OrgId } from '../org.js';
2
+ import type { Plan, UnmanagedItem } from '../plan.js';
3
+ import type { DeclaredPlatform } from '../platform.js';
4
+ import type { PlannedStep } from './diff.js';
5
+ import type { LiveResource } from './live.js';
6
+ /**
7
+ * The platform's own diff result, the {@link DeclaredPlatform} counterpart to
8
+ * `diff.ts`'s `PlanDetail` -- everything the same, minus the `orgId` an org's
9
+ * plan carries, since a platform is one singleton record, not one per org
10
+ * (`platform.ts`'s own doc comment). {@link toPlatformPlan} below turns this
11
+ * into the public `Plan` (`../plan.ts`) `FoundryPlanApply.planPlatform`
12
+ * returns.
13
+ */
14
+ export interface PlatformPlanDetail {
15
+ plannedSteps: PlannedStep[];
16
+ unmanaged: UnmanagedItem[];
17
+ }
18
+ /**
19
+ * The `Plan` (#19's public contract) a {@link PlatformPlanDetail} carries,
20
+ * mirroring `diff.ts`'s `toPlan`. There is no separate platform-shaped `Plan`
21
+ * type: `orgId` is stamped with the platform's own `ownerOrgId` -- Company
22
+ * Included's own {@link OrgId}, the org whose money and access the platform's
23
+ * resources are billed and owned by (`platform.ts`'s `DeclaredPlatform.ownerOrgId`
24
+ * doc comment) -- so `AuditLog`/`AuthzGate` (`plan-apply.ts`), both keyed by
25
+ * `OrgId`, need no platform-specific shape of their own either.
26
+ */
27
+ export declare function toPlatformPlan(detail: PlatformPlanDetail, ownerOrgId: OrgId): Plan;
28
+ /**
29
+ * #168: the resource key `planAuth` plans under and `FoundryPlatformStepExecutor`
30
+ * (`platform-providers.ts`) dispatches on -- `platform:<service>`, exactly the
31
+ * shape `planPlatform`'s own doc comment above already named as the eventual
32
+ * convention, so a platform service's `coolify:app` step never collides with
33
+ * an org's own (which is keyed by that org's id).
34
+ */
35
+ export declare const PLATFORM_AUTH_KEY = "platform:auth";
36
+ /**
37
+ * Scope keys (colon-free, so never mistaken for a `system:kind:key` resource
38
+ * id) for foundry's ZITADEL admin machine user. The delivered key is the guard
39
+ * that skips the mint, recorded only once the token reached the host. The
40
+ * undelivered key is recorded first, the moment the user is minted: an id
41
+ * under it with no delivered key means the one-time token was lost, and the
42
+ * planner reports that instead of minting again.
43
+ */
44
+ /**
45
+ * #175: the resource key `planArchon` plans under and
46
+ * `FoundryPlatformStepExecutor` (`platform-providers.ts`) dispatches on --
47
+ * the same `platform:<service>` shape as {@link PLATFORM_AUTH_KEY}.
48
+ */
49
+ export declare const PLATFORM_ARCHON_KEY = "platform:archon";
50
+ /**
51
+ * #175: the hostname and `gitRef` the last successful Archon run applied.
52
+ * `planArchon` plans the step again when either differs from the declared
53
+ * value; a re-run patches `git_branch`, `APP_URL` and the sign-in client and
54
+ * redeploys, and mints nothing.
55
+ */
56
+ export declare const PLATFORM_ARCHON_APPLIED_HOSTNAME_SCOPE_KEY = "archon_applied_hostname";
57
+ export declare const PLATFORM_ARCHON_APPLIED_GIT_REF_SCOPE_KEY = "archon_applied_git_ref";
58
+ /**
59
+ * #175: set to '1' before the step points the tunnel at `http_status:404`
60
+ * (Access app rebuild), cleared to '' once the real ingress is written back.
61
+ * While it is non-empty `planArchon` plans the step, so a run that failed in
62
+ * between is repaired by the next one.
63
+ */
64
+ export declare const PLATFORM_ARCHON_GATE_CLOSED_SCOPE_KEY = "archon_gate_closed";
65
+ export declare const PLATFORM_AUTH_ADMIN_USER_SCOPE_KEY = "zitadel_platform_admin_user_id";
66
+ export declare const PLATFORM_AUTH_ADMIN_UNDELIVERED_SCOPE_KEY = "zitadel_platform_admin_user_undelivered";
67
+ /**
68
+ * #197: the `cloudflared` connector app `provisionPlatformAuth` runs for its
69
+ * own tunnel. Consulted by `planAuth` below so that a tunnel recorded with no
70
+ * connector recorded is not treated as fully applied -- the same rule that
71
+ * lets an instance provisioned before #197 shipped pick up a connector on its
72
+ * next apply, without minting anything again.
73
+ */
74
+ export declare const PLATFORM_AUTH_CONNECTOR_APP_SCOPE_KEY = "coolify_platform_auth_connector_app";
75
+ /** #197: the same connector scope id for the mail step's own tunnel, read by `planMail`. */
76
+ export declare const PLATFORM_MAIL_CONNECTOR_APP_SCOPE_KEY = "coolify_platform_mail_connector_app";
77
+ /** #197: the same connector scope id for the Archon step's own tunnel, read by `planArchon`. */
78
+ export declare const PLATFORM_ARCHON_CONNECTOR_APP_SCOPE_KEY = "coolify_platform_archon_connector_app";
79
+ /**
80
+ * #169: `platform:<service>` for the platform's own mail server (Stalwart),
81
+ * mirroring {@link PLATFORM_AUTH_KEY} exactly.
82
+ */
83
+ export declare const PLATFORM_MAIL_KEY = "platform:mail";
84
+ /**
85
+ * Scope keys for Stalwart's admin API key, mirroring
86
+ * {@link PLATFORM_AUTH_ADMIN_USER_SCOPE_KEY}/{@link PLATFORM_AUTH_ADMIN_UNDELIVERED_SCOPE_KEY}
87
+ * -- except `createApiKey` (`@wtfalch/email/postmaster`'s `StalwartClient`)
88
+ * returns only the minted secret, never an id, so there is no id to record
89
+ * the way ZITADEL's `userId` is. `PLATFORM_MAIL_ADMIN_KEY_DESCRIPTION`
90
+ * (`platform-providers.ts`) is recorded instead -- the fixed description the
91
+ * key is minted under, which is what a human revokes it by in Stalwart's own
92
+ * admin UI once it is lost.
93
+ */
94
+ export declare const PLATFORM_MAIL_ADMIN_KEY_SCOPE_KEY = "stalwart_platform_admin_key_delivered";
95
+ export declare const PLATFORM_MAIL_ADMIN_UNDELIVERED_SCOPE_KEY = "stalwart_platform_admin_key_undelivered";
96
+ /**
97
+ * #169: the hostname and `gitRef` (the Stalwart image tag) the last successful
98
+ * mail run applied. `planMail` plans the step again when either differs from
99
+ * the declared value; a re-run patches the image tag and
100
+ * `STALWART_PUBLIC_URL`, redeploys, and mints nothing.
101
+ */
102
+ export declare const PLATFORM_MAIL_APPLIED_HOSTNAME_SCOPE_KEY = "mail_applied_hostname";
103
+ export declare const PLATFORM_MAIL_APPLIED_GIT_REF_SCOPE_KEY = "mail_applied_git_ref";
104
+ /**
105
+ * #177: where the mail server answers on the Coolify network
106
+ * (`http://<custom_internal_name>:<port>`), recorded by the step the same way
107
+ * {@link PLATFORM_FILES_INTERNAL_URL_SCOPE_KEY}/{@link PLATFORM_AI_INTERNAL_URL_SCOPE_KEY}
108
+ * already are -- what an org's own `coolify:mail`/`coolify:agora` steps read
109
+ * for `AGORA_MAIL_UPSTREAM` (`platform-org.ts`'s `agoraHostValuesFromPlatform`)
110
+ * instead of a literal a host used to have to supply. Not a secret: Stalwart's
111
+ * own internal address, never its admin credential.
112
+ */
113
+ export declare const PLATFORM_MAIL_INTERNAL_URL_SCOPE_KEY = "mail_internal_url";
114
+ /**
115
+ * #177: the one host the platform's mail server takes SMTP/MX on, and so the
116
+ * `mailHost` every org's own mail step writes. `provisionPlatformMail` (the
117
+ * DNS record and the server) and `platform-org.ts` (each org's mail step)
118
+ * both call this, so the two cannot name different hosts. Not
119
+ * `platform.mail.hostname`, which is the web (JMAP/admin) host.
120
+ */
121
+ export declare function platformMailMxHost(apex: string): string;
122
+ /**
123
+ * #177: the platform apex and mail host an org's `coolify:mail` step last
124
+ * wrote, recorded in that org's applied state. `diff.ts`'s `planMail` plans
125
+ * the step again when either differs from the platform's current values, so a
126
+ * later platform address change reaches orgs that are already applied.
127
+ */
128
+ export declare const ORG_MAIL_APPLIED_APEX_SCOPE_KEY = "mail_applied_apex";
129
+ export declare const ORG_MAIL_APPLIED_HOST_SCOPE_KEY = "mail_applied_host";
130
+ /**
131
+ * #172: the resource key `planAi` plans under and `FoundryPlatformStepExecutor`
132
+ * dispatches on, the same `platform:<service>` shape as
133
+ * {@link PLATFORM_AUTH_KEY}. The step's own recorded resource id (the ai
134
+ * host's runner app) lands at `coolify:app:platform:ai`.
135
+ */
136
+ export declare const PLATFORM_AI_KEY = "platform:ai";
137
+ /**
138
+ * #172: where the ai host answers on the Coolify network
139
+ * (`http://<custom_internal_name>:<port>`), recorded by the step so a host
140
+ * building `AiOrganisationPort` (`executor.ts`) can reach it without a
141
+ * public hostname. Holds whichever way the public-hostname decision goes.
142
+ */
143
+ export declare const PLATFORM_AI_INTERNAL_URL_SCOPE_KEY = "ai_platform_internal_url";
144
+ /**
145
+ * #172: the same two-key discipline as the ZITADEL admin key above, for
146
+ * foundry's AI management key (the bearer key `ai:organisation`, `ai:budget`
147
+ * and `ai:key` use). The undelivered key holds the credential id the moment
148
+ * it is minted; the delivered key is recorded only once the secret reached
149
+ * the host, and is what skips the mint on a later run.
150
+ */
151
+ export declare const PLATFORM_AI_MANAGEMENT_KEY_SCOPE_KEY = "ai_platform_management_key_id";
152
+ export declare const PLATFORM_AI_MANAGEMENT_KEY_UNDELIVERED_SCOPE_KEY = "ai_platform_management_key_undelivered";
153
+ /**
154
+ * #172: ai's platform (operator) tenant id, which the management key belongs
155
+ * to -- what ai's own README calls `AI_ORGANISATION_ID`. Not a secret.
156
+ */
157
+ export declare const PLATFORM_AI_ORGANISATION_SCOPE_KEY = "ai_platform_organisation_id";
158
+ /**
159
+ * #172: the hostname and gitRef the last apply finished with. A declared
160
+ * value that differs plans the step again (without minting again, the
161
+ * management key's own guard stays set).
162
+ */
163
+ export declare const PLATFORM_AI_APPLIED_HOSTNAME_SCOPE_KEY = "ai_platform_applied_hostname";
164
+ export declare const PLATFORM_AI_APPLIED_GITREF_SCOPE_KEY = "ai_platform_applied_gitref";
165
+ /**
166
+ * #172: set (with the migrate job's last status) when the migrate job did
167
+ * not turn healthy in time. The planner reports it as blocked and plans
168
+ * nothing, so an unhealthy migration is not retried and timed out on every
169
+ * apply. A person fixes the job and removes this recorded key.
170
+ */
171
+ export declare const PLATFORM_AI_MIGRATE_BLOCKED_SCOPE_KEY = "ai_platform_migrate_blocked";
172
+ /**
173
+ * #172: set before an env or branch change is written and cleared once the
174
+ * deploys that carry it finished, so a run that fails halfway (a migrate
175
+ * that throws) is repaired by the next one.
176
+ */
177
+ export declare const PLATFORM_AI_DEPLOY_PENDING_SCOPE_KEY = "ai_platform_deploy_pending";
178
+ /**
179
+ * #172: what the planner says while no AI management key minter is supplied.
180
+ * A fixed text: it is part of the stale-plan comparison. ai issues its first
181
+ * platform credential only through its `keys:issue-archon` script, run
182
+ * against its database with its keys worker credential; it has no HTTP route
183
+ * for that, so foundry cannot build a minter over ai's admin API yet.
184
+ */
185
+ export declare const PLATFORM_AI_MINTER_BLOCKED = "the platform's AI host is blocked, not planned: no AI management key minter was supplied. ai mints its first platform key only through its keys:issue-archon script against its database, so the host must supply PlatformAiDeps.managementKeyMinter";
186
+ /**
187
+ * #171: the resource key `planFiles` plans under and `FoundryPlatformStepExecutor`
188
+ * dispatches on, the {@link PLATFORM_AUTH_KEY} shape for the files host.
189
+ * `runPlatformSteps` records the files runner app's uuid under
190
+ * `coolify:app:platform:files` once the step succeeds, which is what stops
191
+ * `planFiles` planning it again.
192
+ */
193
+ export declare const PLATFORM_FILES_KEY = "platform:files";
194
+ /**
195
+ * #171: scope keys (colon-free) the files step records in the applied
196
+ * platform.
197
+ *
198
+ * - {@link PLATFORM_FILES_INTERNAL_URL_SCOPE_KEY}: the files host's address on
199
+ * the Coolify network (`http://<custom_internal_name>:3000`), the value an
200
+ * Agora's `AGORA_FILES_UPSTREAM` (and a host's `FilesOrganisationPort`
201
+ * client) is read from. Not a secret. The host has no public address.
202
+ * - {@link PLATFORM_FILES_ZITADEL_PROJECT_SCOPE_KEY}: the files ZITADEL
203
+ * project's id in the platform's own sign-in, which is the person-token
204
+ * audience (`AUTH_PERSON_TOKEN_AUDIENCE`) an Agora requests as an extra
205
+ * scope (`urn:zitadel:iam:org:project:id:<id>:aud`).
206
+ */
207
+ export declare const PLATFORM_FILES_INTERNAL_URL_SCOPE_KEY = "files_internal_url";
208
+ export declare const PLATFORM_FILES_ZITADEL_PROJECT_SCOPE_KEY = "zitadel_platform_files_project";
209
+ /**
210
+ * #171: scope keys (colon-free) for the files host's two one-time secrets,
211
+ * the {@link PLATFORM_AUTH_ADMIN_USER_SCOPE_KEY} pattern twice. Each
212
+ * `*_UNDELIVERED_*` key is recorded and persisted the moment its secret is
213
+ * minted, before delivery. Each guard is recorded only once the secret was
214
+ * delivered AND written to the runner's env. An undelivered id with no guard
215
+ * means the secret is lost: the planner reports it and never mints again.
216
+ * None of these holds a secret.
217
+ */
218
+ export declare const PLATFORM_FILES_INTROSPECTION_SCOPE_KEY = "zitadel_platform_files_introspection_app";
219
+ export declare const PLATFORM_FILES_INTROSPECTION_UNDELIVERED_SCOPE_KEY = "zitadel_platform_files_introspection_undelivered";
220
+ export declare const PLATFORM_FILES_MANAGEMENT_KEY_SCOPE_KEY = "files_management_key_id";
221
+ export declare const PLATFORM_FILES_MANAGEMENT_UNDELIVERED_SCOPE_KEY = "files_management_key_undelivered";
222
+ /**
223
+ * #171: the hostname and `gitRef` the last successful files run applied.
224
+ * `planFiles` plans the step again when either differs from the declared
225
+ * value; a re-run updates `git_branch` and the runner env and redeploys,
226
+ * and mints nothing (the guards above hold).
227
+ */
228
+ export declare const PLATFORM_FILES_APPLIED_HOSTNAME_SCOPE_KEY = "files_applied_hostname";
229
+ export declare const PLATFORM_FILES_APPLIED_GIT_REF_SCOPE_KEY = "files_applied_git_ref";
230
+ /**
231
+ * Options for {@link planPlatform}, replacing four positional arguments that
232
+ * shifted on every merge that added a platform service (#186, #187, #188) --
233
+ * see https://github.com/wtfalch/foundry/pull/188#issuecomment-5895935971,
234
+ * the merge comment that named this shape (#189).
235
+ */
236
+ export interface PlanPlatformOptions {
237
+ /** Whether the host supplies a Coolify reader for the platform (default `true`). */
238
+ jobsObservable?: boolean;
239
+ /** Why the shared SFU is blocked, or `null` when it is not (default `null`). */
240
+ sfuBlocked?: string | null;
241
+ /** The platform's recorded resource/scope ids (default `{}`). */
242
+ recordedIds?: Readonly<Record<string, string>>;
243
+ /** Per-step block reasons the executor reports (default `{}`). */
244
+ blocked?: {
245
+ auth?: string;
246
+ files?: string;
247
+ integrations?: string;
248
+ ai?: string;
249
+ archon?: string;
250
+ mail?: string;
251
+ };
252
+ /**
253
+ * Steps whose live state differs from the declared one in a way the recorded
254
+ * ids cannot show (default `{}`). `archon`: the Cloudflare Access policy's
255
+ * include list is not the declared one.
256
+ */
257
+ drifted?: {
258
+ archon?: boolean;
259
+ };
260
+ }
261
+ /**
262
+ * #167: the platform's own diff engine, mirroring `diff.ts`'s
263
+ * `computePlanDetail` for the one shared {@link DeclaredPlatform} record
264
+ * (#166) rather than one `DeclaredOrg` per call. It reuses the same step
265
+ * kinds an org plans against (`coolify:app`, `coolify:database`,
266
+ * `cloudflare:tunnel`, `cloudflare:zone`, `zitadel:app`), keyed under the
267
+ * platform's own resources rather than an org id -- a platform service's
268
+ * eventual `coolify:app` step, for one example, is keyed `platform:<service>`
269
+ * (`platform.ts`'s `PlatformServiceKey`) rather than an `OrgId`, once that
270
+ * step exists.
271
+ *
272
+ * Scope for #167: the frame plus one step, {@link planApexZone}. #173 adds
273
+ * {@link planJobs}, #170 adds {@link planSfu}, #168 adds {@link planAuth},
274
+ * #169 adds {@link planMail}, #174 adds {@link planIntegrations}, #171 adds
275
+ * {@link planFiles}, #172 adds {@link planAi} and #175 adds
276
+ * {@link planArchon}, the same way #19 shipped org plan/apply against
277
+ * three singletons before #27, #71, #80 and the rest added the remaining
278
+ * twelve. Until then, a live resource under one of those eventual keys is
279
+ * reported unmanaged rather than silently ignored (#10's rule, carried over
280
+ * unchanged).
281
+ */
282
+ export declare function planPlatform(platform: DeclaredPlatform, live: LiveResource[], options?: PlanPlatformOptions): PlatformPlanDetail;
283
+ /**
284
+ * The one Coolify application (and key) every recorded jobs-scheduler
285
+ * resource, and its `coolify:jobs` step, is keyed under -- there is exactly
286
+ * one scheduler for the whole platform, so this is a fixed constant rather
287
+ * than something derived from `platform` (`platform-providers.ts`'s
288
+ * `FoundryPlatformStepExecutor`/`ProvidersPlatformCoolifyReader` both import
289
+ * it, so the planner and the executor/reader can never key it apart).
290
+ */
291
+ export declare const JOBS_SCHEDULER_KEY = "jobs";
292
+ /**
293
+ * #174: the resource key the integrations host is planned and recorded under,
294
+ * `platform:integrations`, like {@link PLATFORM_AUTH_KEY}: the step is
295
+ * `coolify:app` keyed by it, and the id `runPlatformSteps` records is
296
+ * `coolify:app:platform:integrations`. The planner and the executor
297
+ * (`platform-providers.ts`) both import this one value.
298
+ */
299
+ export declare const PLATFORM_INTEGRATIONS_KEY = "platform:integrations";
300
+ /**
301
+ * Scope keys (colon-free) for the integrations host's Ed25519 management key.
302
+ * The undelivered key is recorded first, the moment the pair is minted. The
303
+ * set key is the guard, recorded only after the private half was delivered
304
+ * and the public half written to the runner. An id under the undelivered key
305
+ * with no guard means the pair may be lost or half-applied, and the planner
306
+ * reports that instead of minting again.
307
+ */
308
+ export declare const PLATFORM_INTEGRATIONS_KEY_UNDELIVERED_SCOPE_KEY = "integrations_management_key_undelivered";
309
+ export declare const PLATFORM_INTEGRATIONS_KEY_SET_SCOPE_KEY = "integrations_management_key_set";
310
+ /** The hostname and gitRef the last successful apply put live; a difference from the declared ones plans the step again. */
311
+ export declare const PLATFORM_INTEGRATIONS_APPLIED_HOSTNAME_SCOPE_KEY = "integrations_applied_hostname";
312
+ export declare const PLATFORM_INTEGRATIONS_APPLIED_GITREF_SCOPE_KEY = "integrations_applied_gitref";