@wtfalch/foundry 0.31.0 → 0.33.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apply.d.ts +6 -1
- package/dist/bootstrap/bootstrap.d.ts +18 -1
- package/dist/bootstrap/bootstrap.js +167 -28
- package/dist/bootstrap/declare.d.ts +5 -1
- package/dist/bootstrap/declare.js +3 -1
- package/dist/bootstrap/index.d.ts +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.js +2 -1
- package/dist/org.d.ts +12 -3
- package/dist/org.js +19 -3
- package/dist/plan/boule.d.ts +24 -1
- package/dist/plan/boule.js +29 -1
- package/dist/plan/confirm-upgrade.d.ts +17 -0
- package/dist/plan/confirm-upgrade.js +47 -0
- package/dist/plan/diff.d.ts +3 -1
- package/dist/plan/diff.js +174 -12
- package/dist/plan/executor.d.ts +65 -7
- package/dist/plan/executor.js +164 -45
- package/dist/plan/health-targets.js +1 -1
- package/dist/plan/index.d.ts +5 -2
- package/dist/plan/index.js +2 -1
- package/dist/plan/plan-apply.d.ts +40 -2
- package/dist/plan/plan-apply.js +43 -2
- package/dist/plan/platform-diff.d.ts +39 -10
- package/dist/plan/platform-diff.js +135 -33
- package/dist/plan/platform-org.d.ts +2 -0
- package/dist/plan/platform-org.js +2 -0
- package/dist/plan/platform-providers.d.ts +53 -7
- package/dist/plan/platform-providers.js +351 -99
- package/dist/plan/sign-in-org.d.ts +99 -0
- package/dist/plan/sign-in-org.js +133 -0
- package/dist/plan/version-status.d.ts +1 -2
- package/dist/plan.d.ts +30 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DeclaredOrg, EnvSharedSecret, HostingEntry, OrgId } from '../org.js';
|
|
2
|
-
import { type Plan, type UnmanagedItem, type VersionChangeItem } from '../plan.js';
|
|
2
|
+
import { type Plan, type PlanNote, type UnmanagedItem, type VersionChangeItem } from '../plan.js';
|
|
3
3
|
import type { DeclaredPlatform } from '../platform.js';
|
|
4
4
|
import type { PlannedStep } from './diff.js';
|
|
5
5
|
import type { LiveResource } from './live.js';
|
|
@@ -16,6 +16,8 @@ export interface PlatformPlanDetail {
|
|
|
16
16
|
unmanaged: UnmanagedItem[];
|
|
17
17
|
/** #251: see {@link VersionChangeItem}. Never folded into `plannedSteps`. */
|
|
18
18
|
versionChanges: VersionChangeItem[];
|
|
19
|
+
/** Advisory lines that block no step; see {@link PlanNote}. */
|
|
20
|
+
notes: PlanNote[];
|
|
19
21
|
}
|
|
20
22
|
/**
|
|
21
23
|
* The `Plan` (#19's public contract) a {@link PlatformPlanDetail} carries,
|
|
@@ -161,12 +163,11 @@ export declare const PLATFORM_ARCHON_DEPLOYMENT_SCOPE_KEY = "archon_deployment";
|
|
|
161
163
|
*/
|
|
162
164
|
export declare const PLATFORM_ARCHON_APPLIED_BROKER_SCOPE_KEY = "archon_applied_broker_app";
|
|
163
165
|
/**
|
|
164
|
-
* The
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
* has recorded it.
|
|
166
|
+
* The sign-in org id the last Archon apply set as `AUTH_ORGANIZATION_ID` and
|
|
167
|
+
* registered its broker entry under. `planArchon` plans the step again when
|
|
168
|
+
* {@link archonAuthOrganizationId} differs from it.
|
|
168
169
|
*/
|
|
169
|
-
export declare const
|
|
170
|
+
export declare const PLATFORM_ARCHON_APPLIED_AUTH_ORG_SCOPE_KEY = "archon_applied_auth_org";
|
|
170
171
|
/**
|
|
171
172
|
* #475: whether the last successful Archon apply patched the app with
|
|
172
173
|
* `custom_network_aliases` and `is_consistent_container_name_enabled: false`
|
|
@@ -183,11 +184,11 @@ export declare const PLATFORM_ARCHON_APPLIED_OPERATOR_SCOPE_KEY = "archon_applie
|
|
|
183
184
|
*/
|
|
184
185
|
export declare const PLATFORM_ARCHON_APPLIED_ROLLING_UPDATE_SCOPE_KEY = "archon_applied_rolling_update";
|
|
185
186
|
/**
|
|
186
|
-
* The
|
|
187
|
-
* {@link
|
|
188
|
-
*
|
|
187
|
+
* The sign-in org Archon accepts: the platform owner company's own
|
|
188
|
+
* ({@link PLATFORM_OWNER_ORG_SCOPE_KEY}), else the platform's `foundry` org for
|
|
189
|
+
* a platform with no owner company declared. Undefined when neither is recorded.
|
|
189
190
|
*/
|
|
190
|
-
export declare function
|
|
191
|
+
export declare function archonAuthOrganizationId(recorded: Readonly<Record<string, string>>): string | undefined;
|
|
191
192
|
/**
|
|
192
193
|
* #175: set to '1' before the step points the tunnel at `http_status:404`
|
|
193
194
|
* (Access app rebuild), cleared to '' once the real ingress is written back.
|
|
@@ -207,6 +208,26 @@ export declare const PLATFORM_AUTH_SMTP_SCOPE_KEY = "zitadel_platform_smtp_provi
|
|
|
207
208
|
* requested, so the invite goes out once. `none` when no owner is declared.
|
|
208
209
|
*/
|
|
209
210
|
export declare const PLATFORM_AUTH_OWNER_INVITE_SCOPE_KEY = "zitadel_platform_owner_invite_user_id";
|
|
211
|
+
/** The platform's own ZITADEL org (`foundry`, the one `provisionPlatformAuth` mints its admin user in). */
|
|
212
|
+
export declare const PLATFORM_ZITADEL_ORG_SCOPE_KEY = "zitadel_platform_org";
|
|
213
|
+
/**
|
|
214
|
+
* The id of the platform owner company's own sign-in organisation, made by
|
|
215
|
+
* `platform:auth` with the same name and primary domain a company apply uses,
|
|
216
|
+
* so that apply finds this org and makes no second one. `none` when the owner
|
|
217
|
+
* company is not declared. Archon signs people in from this org; the
|
|
218
|
+
* `foundry` org ({@link PLATFORM_ZITADEL_ORG_SCOPE_KEY}) holds no people.
|
|
219
|
+
*/
|
|
220
|
+
export declare const PLATFORM_OWNER_ORG_SCOPE_KEY = "zitadel_platform_owner_org";
|
|
221
|
+
/** The primary domain `platform:auth` registered on the owner company's sign-in org. */
|
|
222
|
+
export declare const PLATFORM_OWNER_ORG_DOMAIN_SCOPE_KEY = "zitadel_platform_owner_org_domain";
|
|
223
|
+
/** The owner org's sign-in domain the sign-in server refused to make primary; set instead of failing, reported as blocked. */
|
|
224
|
+
export declare const PLATFORM_OWNER_ORG_DOMAIN_BLOCKED_SCOPE_KEY = "zitadel_platform_owner_org_domain_blocked";
|
|
225
|
+
/**
|
|
226
|
+
* The sign-in org the recorded owner invite ({@link PLATFORM_AUTH_OWNER_INVITE_SCOPE_KEY})
|
|
227
|
+
* was made in. An invite recorded against another org (the `foundry` org, on a
|
|
228
|
+
* platform applied before the owner moved) plans the auth step again.
|
|
229
|
+
*/
|
|
230
|
+
export declare const PLATFORM_AUTH_OWNER_INVITE_ORG_SCOPE_KEY = "zitadel_platform_owner_invite_org";
|
|
210
231
|
/**
|
|
211
232
|
* #394: the id of the role-less ZITADEL machine user that reserves the
|
|
212
233
|
* username `admin` in the platform's own org, so nobody can sign up under a
|
|
@@ -972,6 +993,8 @@ export interface PlanPlatformOptions {
|
|
|
972
993
|
* these. Default `[]`.
|
|
973
994
|
*/
|
|
974
995
|
authOtherInputsMissing?: string[];
|
|
996
|
+
/** C3: why the owner's invite cannot be made (no work address, no mail port). The rest of the step still plans. */
|
|
997
|
+
authOwnerInvite?: string;
|
|
975
998
|
files?: string;
|
|
976
999
|
integrations?: string;
|
|
977
1000
|
ai?: string;
|
|
@@ -1038,6 +1061,12 @@ export interface PlanPlatformOptions {
|
|
|
1038
1061
|
* repair step is not planned.
|
|
1039
1062
|
*/
|
|
1040
1063
|
archonIdTokenUserinfo?: boolean;
|
|
1064
|
+
/**
|
|
1065
|
+
* The executor has the platform's sign-in dependencies and a ZITADEL
|
|
1066
|
+
* client for its instance. Not a block: without it the sign-in policy
|
|
1067
|
+
* step is not planned.
|
|
1068
|
+
*/
|
|
1069
|
+
authSignInPolicy?: boolean;
|
|
1041
1070
|
};
|
|
1042
1071
|
/**
|
|
1043
1072
|
* Steps whose live state differs from the declared one in a way the recorded
|
|
@@ -2,9 +2,11 @@ import { createHash } from 'node:crypto';
|
|
|
2
2
|
import { VERSIONS } from '../bootstrap/versions.js';
|
|
3
3
|
import { APP_ENTRY_KEY } from '../org.js';
|
|
4
4
|
import { VERSION_CHANGE_KIND, } from '../plan.js';
|
|
5
|
+
import { versionChangeNeedsConfirmation } from './confirm-upgrade.js';
|
|
5
6
|
import { ACCESS_PROVIDER_RECORD_KEY } from './gates.js';
|
|
6
7
|
import { legacyAppHostname } from './hostnames.js';
|
|
7
8
|
import { callsSfuAppliedFingerprint } from './platform-sfu.js';
|
|
9
|
+
import { ZITADEL_ORG_DOMAIN_BLOCKED_SCOPE_KEY, signInDomainBlockedText } from './sign-in-org.js';
|
|
8
10
|
import { withStepSystem } from './step-system.js';
|
|
9
11
|
/**
|
|
10
12
|
* The `Plan` (#19's public contract) a {@link PlatformPlanDetail} carries,
|
|
@@ -21,6 +23,7 @@ export function toPlatformPlan(detail, ownerOrgId) {
|
|
|
21
23
|
steps: detail.plannedSteps.map((p) => p.step),
|
|
22
24
|
unmanaged: detail.unmanaged,
|
|
23
25
|
versionChanges: detail.versionChanges,
|
|
26
|
+
notes: detail.notes,
|
|
24
27
|
};
|
|
25
28
|
}
|
|
26
29
|
function resourceKey(system, kind, key) {
|
|
@@ -78,6 +81,9 @@ export function versionChangeLine(service, from, to, note) {
|
|
|
78
81
|
kind: VERSION_CHANGE_KIND,
|
|
79
82
|
service,
|
|
80
83
|
description: `${service}: ${from} -> ${to} (${note})`,
|
|
84
|
+
from,
|
|
85
|
+
to,
|
|
86
|
+
needsConfirmation: versionChangeNeedsConfirmation(service, from, to),
|
|
81
87
|
};
|
|
82
88
|
}
|
|
83
89
|
/**
|
|
@@ -99,6 +105,8 @@ export function versionNotAppliedLine(service, appLive, applied, pinned) {
|
|
|
99
105
|
kind: VERSION_CHANGE_KIND,
|
|
100
106
|
service,
|
|
101
107
|
description: `${service}: pinned ${pinned}, running tag unknown`,
|
|
108
|
+
to: pinned,
|
|
109
|
+
needsConfirmation: false,
|
|
102
110
|
};
|
|
103
111
|
}
|
|
104
112
|
if (applied === pinned)
|
|
@@ -107,6 +115,10 @@ export function versionNotAppliedLine(service, appLive, applied, pinned) {
|
|
|
107
115
|
kind: VERSION_CHANGE_KIND,
|
|
108
116
|
service,
|
|
109
117
|
description: `${service}: pinned ${pinned}, running ${applied} (not applied by foundry)`,
|
|
118
|
+
from: applied,
|
|
119
|
+
to: pinned,
|
|
120
|
+
// #254: no apply acts on this line, so there is no upgrade to confirm.
|
|
121
|
+
needsConfirmation: false,
|
|
110
122
|
};
|
|
111
123
|
}
|
|
112
124
|
/**
|
|
@@ -185,12 +197,11 @@ export const PLATFORM_ARCHON_DEPLOYMENT_SCOPE_KEY = 'archon_deployment';
|
|
|
185
197
|
*/
|
|
186
198
|
export const PLATFORM_ARCHON_APPLIED_BROKER_SCOPE_KEY = 'archon_applied_broker_app';
|
|
187
199
|
/**
|
|
188
|
-
* The
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
* has recorded it.
|
|
200
|
+
* The sign-in org id the last Archon apply set as `AUTH_ORGANIZATION_ID` and
|
|
201
|
+
* registered its broker entry under. `planArchon` plans the step again when
|
|
202
|
+
* {@link archonAuthOrganizationId} differs from it.
|
|
192
203
|
*/
|
|
193
|
-
export const
|
|
204
|
+
export const PLATFORM_ARCHON_APPLIED_AUTH_ORG_SCOPE_KEY = 'archon_applied_auth_org';
|
|
194
205
|
/**
|
|
195
206
|
* #475: whether the last successful Archon apply patched the app with
|
|
196
207
|
* `custom_network_aliases` and `is_consistent_container_name_enabled: false`
|
|
@@ -207,13 +218,15 @@ export const PLATFORM_ARCHON_APPLIED_OPERATOR_SCOPE_KEY = 'archon_applied_bootst
|
|
|
207
218
|
*/
|
|
208
219
|
export const PLATFORM_ARCHON_APPLIED_ROLLING_UPDATE_SCOPE_KEY = 'archon_applied_rolling_update';
|
|
209
220
|
/**
|
|
210
|
-
* The
|
|
211
|
-
* {@link
|
|
212
|
-
*
|
|
221
|
+
* The sign-in org Archon accepts: the platform owner company's own
|
|
222
|
+
* ({@link PLATFORM_OWNER_ORG_SCOPE_KEY}), else the platform's `foundry` org for
|
|
223
|
+
* a platform with no owner company declared. Undefined when neither is recorded.
|
|
213
224
|
*/
|
|
214
|
-
export function
|
|
215
|
-
const
|
|
216
|
-
|
|
225
|
+
export function archonAuthOrganizationId(recorded) {
|
|
226
|
+
const owner = recorded[PLATFORM_OWNER_ORG_SCOPE_KEY];
|
|
227
|
+
if (owner && owner !== 'none')
|
|
228
|
+
return owner;
|
|
229
|
+
return recorded[PLATFORM_ZITADEL_ORG_SCOPE_KEY] || undefined;
|
|
217
230
|
}
|
|
218
231
|
/**
|
|
219
232
|
* #175: set to '1' before the step points the tunnel at `http_status:404`
|
|
@@ -234,6 +247,26 @@ export const PLATFORM_AUTH_SMTP_SCOPE_KEY = 'zitadel_platform_smtp_provider_id';
|
|
|
234
247
|
* requested, so the invite goes out once. `none` when no owner is declared.
|
|
235
248
|
*/
|
|
236
249
|
export const PLATFORM_AUTH_OWNER_INVITE_SCOPE_KEY = 'zitadel_platform_owner_invite_user_id';
|
|
250
|
+
/** The platform's own ZITADEL org (`foundry`, the one `provisionPlatformAuth` mints its admin user in). */
|
|
251
|
+
export const PLATFORM_ZITADEL_ORG_SCOPE_KEY = 'zitadel_platform_org';
|
|
252
|
+
/**
|
|
253
|
+
* The id of the platform owner company's own sign-in organisation, made by
|
|
254
|
+
* `platform:auth` with the same name and primary domain a company apply uses,
|
|
255
|
+
* so that apply finds this org and makes no second one. `none` when the owner
|
|
256
|
+
* company is not declared. Archon signs people in from this org; the
|
|
257
|
+
* `foundry` org ({@link PLATFORM_ZITADEL_ORG_SCOPE_KEY}) holds no people.
|
|
258
|
+
*/
|
|
259
|
+
export const PLATFORM_OWNER_ORG_SCOPE_KEY = 'zitadel_platform_owner_org';
|
|
260
|
+
/** The primary domain `platform:auth` registered on the owner company's sign-in org. */
|
|
261
|
+
export const PLATFORM_OWNER_ORG_DOMAIN_SCOPE_KEY = 'zitadel_platform_owner_org_domain';
|
|
262
|
+
/** The owner org's sign-in domain the sign-in server refused to make primary; set instead of failing, reported as blocked. */
|
|
263
|
+
export const PLATFORM_OWNER_ORG_DOMAIN_BLOCKED_SCOPE_KEY = 'zitadel_platform_owner_org_domain_blocked';
|
|
264
|
+
/**
|
|
265
|
+
* The sign-in org the recorded owner invite ({@link PLATFORM_AUTH_OWNER_INVITE_SCOPE_KEY})
|
|
266
|
+
* was made in. An invite recorded against another org (the `foundry` org, on a
|
|
267
|
+
* platform applied before the owner moved) plans the auth step again.
|
|
268
|
+
*/
|
|
269
|
+
export const PLATFORM_AUTH_OWNER_INVITE_ORG_SCOPE_KEY = 'zitadel_platform_owner_invite_org';
|
|
237
270
|
/**
|
|
238
271
|
* #394: the id of the role-less ZITADEL machine user that reserves the
|
|
239
272
|
* username `admin` in the platform's own org, so nobody can sign up under a
|
|
@@ -1126,7 +1159,7 @@ export function planPlatform(platform, live, options = {}) {
|
|
|
1126
1159
|
// reconcile below can be planned in the *same* round hc first comes up,
|
|
1127
1160
|
// the same way files/mail/archon are planned in auth's own first round.
|
|
1128
1161
|
const hcReady = hc.step !== null || Boolean(recordedIds[resourceKey('coolify', 'app', PLATFORM_HC_KEY)]);
|
|
1129
|
-
const auth = planAuth(platform, recordedIds, blocked.auth ?? dnsBlocked?.('sign-in'), blocked.authExecutorMissing ?? false, drifted.auth ?? false, blocked.authOtherInputsMissing ?? []);
|
|
1162
|
+
const auth = planAuth(platform, recordedIds, blocked.auth ?? dnsBlocked?.('sign-in'), blocked.authExecutorMissing ?? false, drifted.auth ?? false, blocked.authOtherInputsMissing ?? [], blocked.authOwnerInvite);
|
|
1130
1163
|
if (auth.step)
|
|
1131
1164
|
plannedSteps.push(auth.step);
|
|
1132
1165
|
// #174: the integrations host. Planned after auth; neither step reads the
|
|
@@ -1183,6 +1216,10 @@ export function planPlatform(platform, live, options = {}) {
|
|
|
1183
1216
|
const idTokenUserinfo = planArchonIdTokenUserinfo(platform, recordedIds, blocked.archonIdTokenUserinfo ?? false);
|
|
1184
1217
|
if (idTokenUserinfo)
|
|
1185
1218
|
plannedSteps.push(idTokenUserinfo);
|
|
1219
|
+
// #669: after the ID token repair too, which is proven; a policy call that fails every time holds up nothing.
|
|
1220
|
+
const signInPolicy = planAuthSignInPolicy(platform, recordedIds, blocked.authSignInPolicy ?? false);
|
|
1221
|
+
if (signInPolicy)
|
|
1222
|
+
plannedSteps.push(signInPolicy);
|
|
1186
1223
|
// #251: one line per service whose recorded applied ref no longer matches
|
|
1187
1224
|
// what the next apply would use (or, for zitadel, what is actually live).
|
|
1188
1225
|
// Never pushed into `plannedSteps` -- see `VersionChangeItem`'s own doc
|
|
@@ -1227,6 +1264,12 @@ export function planPlatform(platform, live, options = {}) {
|
|
|
1227
1264
|
// A blocked jobs scheduler is reported here, not planned: a step that
|
|
1228
1265
|
// throws every apply, or that can never be seen live and so re-plans
|
|
1229
1266
|
// forever, is worse than none.
|
|
1267
|
+
if (!platform.ownerOrgId) {
|
|
1268
|
+
unmanaged.push({
|
|
1269
|
+
description: "platform.ownerOrgId is not declared, so no org is the platform's own: no peer password or bridge secret is minted for any Boule and Archon reads no people",
|
|
1270
|
+
key: 'owner-org',
|
|
1271
|
+
});
|
|
1272
|
+
}
|
|
1230
1273
|
if (jobs.blocked)
|
|
1231
1274
|
unmanaged.push({ description: jobs.blocked, key: 'jobs' });
|
|
1232
1275
|
if (platform.sfu.enabled && sfuBlocked) {
|
|
@@ -1268,7 +1311,12 @@ export function planPlatform(platform, live, options = {}) {
|
|
|
1268
1311
|
unmanaged.push({ description: heartbeats.blocked, key: 'heartbeats' });
|
|
1269
1312
|
for (const description of uptime.blocked)
|
|
1270
1313
|
unmanaged.push({ description, key: 'uptime' });
|
|
1271
|
-
return {
|
|
1314
|
+
return {
|
|
1315
|
+
plannedSteps: plannedSteps.map(withStepSystem),
|
|
1316
|
+
unmanaged,
|
|
1317
|
+
versionChanges,
|
|
1318
|
+
notes: uptime.notes,
|
|
1319
|
+
};
|
|
1272
1320
|
}
|
|
1273
1321
|
/**
|
|
1274
1322
|
* The platform's own Cloudflare zone for its shared apex (`platform.ts`'s
|
|
@@ -1687,9 +1735,12 @@ function planSfu(platform, callsOrgSlugs, recordedIds) {
|
|
|
1687
1735
|
* promising "this apply re-mints" while one of those is still missing would
|
|
1688
1736
|
* be wrong the moment it is read.
|
|
1689
1737
|
*/
|
|
1690
|
-
function planAuth(platform, recordedIds, executorBlocked, executorMissing, authDrifted, otherInputsMissing = []) {
|
|
1738
|
+
function planAuth(platform, recordedIds, executorBlocked, executorMissing, authDrifted, otherInputsMissing = [], ownerInviteBlocked) {
|
|
1691
1739
|
if (!platform.auth.enabled)
|
|
1692
1740
|
return { step: null, blocked: null };
|
|
1741
|
+
// C3/S2: standing notes. The invite and the domain wait on a person; they hold nothing else back.
|
|
1742
|
+
const standing = [ownerInviteBlocked, ownerDomainBlockedText(recordedIds)].filter((t) => Boolean(t));
|
|
1743
|
+
const standingNote = standing.length > 0 ? standing.join('; ') : null;
|
|
1693
1744
|
const key = resourceKey('coolify', 'app', PLATFORM_AUTH_KEY);
|
|
1694
1745
|
const connectorApplied = Boolean(recordedIds[PLATFORM_AUTH_CONNECTOR_APP_SCOPE_KEY]);
|
|
1695
1746
|
// #211: a recorded app and connector with no recorded broker id is a
|
|
@@ -1723,14 +1774,18 @@ function planAuth(platform, recordedIds, executorBlocked, executorMissing, authD
|
|
|
1723
1774
|
// Mail and the owner's invite: a platform applied before they existed
|
|
1724
1775
|
// plans the step again, which only adds them.
|
|
1725
1776
|
Boolean(recordedIds[PLATFORM_AUTH_SMTP_SCOPE_KEY]) &&
|
|
1726
|
-
Boolean(recordedIds[PLATFORM_AUTH_OWNER_INVITE_SCOPE_KEY]) &&
|
|
1777
|
+
(Boolean(recordedIds[PLATFORM_AUTH_OWNER_INVITE_SCOPE_KEY]) || Boolean(ownerInviteBlocked)) &&
|
|
1778
|
+
// The owner company's own sign-in org, and an invite made in it: a
|
|
1779
|
+
// platform whose owner was invited into the `foundry` org plans the step again.
|
|
1780
|
+
Boolean(recordedIds[PLATFORM_OWNER_ORG_SCOPE_KEY]) &&
|
|
1781
|
+
(Boolean(ownerInviteBlocked) ||
|
|
1782
|
+
recordedIds[PLATFORM_AUTH_OWNER_INVITE_SCOPE_KEY] === 'none' ||
|
|
1783
|
+
recordedIds[PLATFORM_AUTH_OWNER_INVITE_ORG_SCOPE_KEY] ===
|
|
1784
|
+
recordedIds[PLATFORM_OWNER_ORG_SCOPE_KEY]) &&
|
|
1727
1785
|
// The ZITADEL run options reach the container only through the auth
|
|
1728
1786
|
// step's redeploy, so a platform recorded before them still plans it.
|
|
1729
|
-
recordedIds[PLATFORM_AUTH_ZITADEL_RUN_OPTIONS_SCOPE_KEY] === AUTH_ZITADEL_RUN_OPTIONS
|
|
1730
|
-
|
|
1731
|
-
Boolean(recordedIds[PLATFORM_AUTH_RESERVED_ADMIN_USERNAME_SCOPE_KEY]) &&
|
|
1732
|
-
Boolean(recordedIds[PLATFORM_AUTH_REGISTRATION_CLOSED_SCOPE_KEY])) {
|
|
1733
|
-
return { step: null, blocked: null };
|
|
1787
|
+
recordedIds[PLATFORM_AUTH_ZITADEL_RUN_OPTIONS_SCOPE_KEY] === AUTH_ZITADEL_RUN_OPTIONS) {
|
|
1788
|
+
return { step: null, blocked: standingNote };
|
|
1734
1789
|
}
|
|
1735
1790
|
// The admin key was minted but never reached the host. ZITADEL shows a
|
|
1736
1791
|
// token once, so it is lost: minting another would hide that, and skipping
|
|
@@ -1801,6 +1856,7 @@ function planAuth(platform, recordedIds, executorBlocked, executorMissing, authD
|
|
|
1801
1856
|
// 5: and only claim "this apply re-mints" when `otherInputsMissing` is
|
|
1802
1857
|
// actually empty -- see this function's own doc comment.
|
|
1803
1858
|
blocked: executorBlocked ??
|
|
1859
|
+
standingNote ??
|
|
1804
1860
|
loginClientNeedsMintNote(loginClientUndelivered, loginClientApplied, authDrifted, loginClientRecord, otherInputsMissing),
|
|
1805
1861
|
};
|
|
1806
1862
|
}
|
|
@@ -2249,6 +2305,31 @@ function planArchonIdTokenUserinfo(platform, recordedIds, wired) {
|
|
|
2249
2305
|
},
|
|
2250
2306
|
};
|
|
2251
2307
|
}
|
|
2308
|
+
/**
|
|
2309
|
+
* #394, #669: the platform's sign-in org reserves the username `admin` and
|
|
2310
|
+
* switches self-registration off. One `zitadel:sign-in-policy` step keyed
|
|
2311
|
+
* {@link PLATFORM_AUTH_KEY}, planned while either recorded key is missing and
|
|
2312
|
+
* the sign-in's ZITADEL org is recorded. Not planned before that, and not
|
|
2313
|
+
* blocked: nothing is owed until the sign-in exists.
|
|
2314
|
+
*/
|
|
2315
|
+
function planAuthSignInPolicy(platform, recordedIds, wired) {
|
|
2316
|
+
if (!wired || !platform.auth.enabled)
|
|
2317
|
+
return null;
|
|
2318
|
+
if (!recordedIds[PLATFORM_ZITADEL_ORG_SCOPE_KEY])
|
|
2319
|
+
return null;
|
|
2320
|
+
if (recordedIds[PLATFORM_AUTH_RESERVED_ADMIN_USERNAME_SCOPE_KEY] &&
|
|
2321
|
+
recordedIds[PLATFORM_AUTH_REGISTRATION_CLOSED_SCOPE_KEY]) {
|
|
2322
|
+
return null;
|
|
2323
|
+
}
|
|
2324
|
+
return {
|
|
2325
|
+
action: { system: 'zitadel', kind: 'sign-in-policy', key: PLATFORM_AUTH_KEY, desired: {} },
|
|
2326
|
+
step: {
|
|
2327
|
+
description: "reserve the username 'admin' and switch self-registration off on the platform's sign-in org",
|
|
2328
|
+
destroys: false,
|
|
2329
|
+
migrates: false,
|
|
2330
|
+
},
|
|
2331
|
+
};
|
|
2332
|
+
}
|
|
2252
2333
|
/**
|
|
2253
2334
|
* #604: the platform's ZITADEL as a sign-in provider in Cloudflare Access: a
|
|
2254
2335
|
* ZITADEL client for Cloudflare, then edge's `ensureProvider`. One
|
|
@@ -2449,9 +2530,9 @@ function planHeartbeats(platform, recordedIds, hcReady, executorMissing, apiKeyM
|
|
|
2449
2530
|
* destructive step removes whatever of it is recorded (edge removes its KV
|
|
2450
2531
|
* namespace with the script).
|
|
2451
2532
|
*
|
|
2452
|
-
* The returned `blocked` lines are reported in `unmanaged
|
|
2453
|
-
*
|
|
2454
|
-
*
|
|
2533
|
+
* The returned `blocked` lines are reported in `unmanaged`. A secret whose
|
|
2534
|
+
* source does not exist yet blocks nothing: the step still delivers
|
|
2535
|
+
* everything that exists, so it comes back in `notes`.
|
|
2455
2536
|
*/
|
|
2456
2537
|
function planUptime(platform, recordedIds, executorBlocked, heldOptional, archonApplied, uptimeHeld = {
|
|
2457
2538
|
token: true,
|
|
@@ -2469,9 +2550,9 @@ function planUptime(platform, recordedIds, executorBlocked, heldOptional, archon
|
|
|
2469
2550
|
});
|
|
2470
2551
|
if (!uptime.enabled) {
|
|
2471
2552
|
if (!uptimeRecorded(recordedIds))
|
|
2472
|
-
return { step: null, blocked: [] };
|
|
2553
|
+
return { step: null, blocked: [], notes: [] };
|
|
2473
2554
|
if (executorBlocked)
|
|
2474
|
-
return { step: null, blocked: [executorBlocked] };
|
|
2555
|
+
return { step: null, blocked: [executorBlocked], notes: [] };
|
|
2475
2556
|
return {
|
|
2476
2557
|
step: {
|
|
2477
2558
|
action: action({ remove: true }),
|
|
@@ -2482,6 +2563,7 @@ function planUptime(platform, recordedIds, executorBlocked, heldOptional, archon
|
|
|
2482
2563
|
},
|
|
2483
2564
|
},
|
|
2484
2565
|
blocked: [],
|
|
2566
|
+
notes: [],
|
|
2485
2567
|
};
|
|
2486
2568
|
}
|
|
2487
2569
|
if (!uptime.tag || !uptime.sha256) {
|
|
@@ -2490,6 +2572,7 @@ function planUptime(platform, recordedIds, executorBlocked, heldOptional, archon
|
|
|
2490
2572
|
blocked: [
|
|
2491
2573
|
'the uptime Worker is blocked, not planned: no artifact is pinned; declare uptime.tag (an Archon release tag) and uptime.sha256 (the digest of archon-uptime-worker.js at that tag)',
|
|
2492
2574
|
],
|
|
2575
|
+
notes: [],
|
|
2493
2576
|
};
|
|
2494
2577
|
}
|
|
2495
2578
|
if (!archonApplied) {
|
|
@@ -2498,16 +2581,25 @@ function planUptime(platform, recordedIds, executorBlocked, heldOptional, archon
|
|
|
2498
2581
|
blocked: [
|
|
2499
2582
|
'the uptime Worker is blocked, not planned: platform:archon has not been applied yet',
|
|
2500
2583
|
],
|
|
2584
|
+
notes: [],
|
|
2501
2585
|
};
|
|
2502
2586
|
}
|
|
2503
2587
|
if (executorBlocked)
|
|
2504
|
-
return { step: null, blocked: [executorBlocked] };
|
|
2505
|
-
const
|
|
2588
|
+
return { step: null, blocked: [executorBlocked], notes: [] };
|
|
2589
|
+
const notes = [];
|
|
2506
2590
|
if (!heldOptional.includes('CHAT_ACCESS_TOKEN')) {
|
|
2507
|
-
|
|
2591
|
+
notes.push({
|
|
2592
|
+
key: 'uptime:CHAT_ACCESS_TOKEN',
|
|
2593
|
+
service: 'uptime',
|
|
2594
|
+
description: `the uptime Worker has no chat credential (CHAT_ACCESS_TOKEN): hold one under ${PLATFORM_UPTIME_CHAT_TOKEN_REF} and it is set on the next apply; until then it sends no chat alerts`,
|
|
2595
|
+
});
|
|
2508
2596
|
}
|
|
2509
2597
|
if (!heldOptional.includes('MAIL_API_KEY')) {
|
|
2510
|
-
|
|
2598
|
+
notes.push({
|
|
2599
|
+
key: 'uptime:MAIL_API_KEY',
|
|
2600
|
+
service: 'uptime',
|
|
2601
|
+
description: `the uptime Worker has no mail API key (MAIL_API_KEY): hold one under ${PLATFORM_UPTIME_MAIL_KEY_REF} and it is set on the next apply; until then it sends no alert email`,
|
|
2602
|
+
});
|
|
2511
2603
|
}
|
|
2512
2604
|
const hostname = platform.archon.hostname;
|
|
2513
2605
|
// Applied only once a run got to its end and recorded these: a Worker that
|
|
@@ -2523,7 +2615,7 @@ function planUptime(platform, recordedIds, executorBlocked, heldOptional, archon
|
|
|
2523
2615
|
(recordedIds[PLATFORM_UPTIME_APPLIED_VARS_SCOPE_KEY] ?? '') === uptimeHeld.vars &&
|
|
2524
2616
|
recordedIds[PLATFORM_UPTIME_APPLIED_SECRETS_SCOPE_KEY] === uptimeSecretNames(heldOptional);
|
|
2525
2617
|
if (applied)
|
|
2526
|
-
return { step: null, blocked:
|
|
2618
|
+
return { step: null, blocked: [], notes };
|
|
2527
2619
|
return {
|
|
2528
2620
|
step: {
|
|
2529
2621
|
action: action({ hostname, gitRef: uptime.tag, sha256: uptime.sha256 }),
|
|
@@ -2533,7 +2625,8 @@ function planUptime(platform, recordedIds, executorBlocked, heldOptional, archon
|
|
|
2533
2625
|
migrates: false,
|
|
2534
2626
|
},
|
|
2535
2627
|
},
|
|
2536
|
-
blocked:
|
|
2628
|
+
blocked: [],
|
|
2629
|
+
notes,
|
|
2537
2630
|
};
|
|
2538
2631
|
}
|
|
2539
2632
|
/**
|
|
@@ -2671,8 +2764,8 @@ function planArchon(platform, recordedIds, executorBlocked, authReady, drifted,
|
|
|
2671
2764
|
Boolean(recordedIds[PLATFORM_ARCHON_APPLIED_BROKER_SCOPE_KEY]) &&
|
|
2672
2765
|
recordedIds[PLATFORM_ARCHON_APPLIED_BROKER_SCOPE_KEY] ===
|
|
2673
2766
|
recordedIds[PLATFORM_AUTH_BROKER_SCOPE_KEY] &&
|
|
2674
|
-
|
|
2675
|
-
(
|
|
2767
|
+
recordedIds[PLATFORM_ARCHON_APPLIED_AUTH_ORG_SCOPE_KEY] ===
|
|
2768
|
+
archonAuthOrganizationId(recordedIds) &&
|
|
2676
2769
|
// #475: a platform applied before the rolling-update fix keeps planning
|
|
2677
2770
|
// this step until a confirmed redeploy has cleared it. #480: this marker
|
|
2678
2771
|
// alone does not catch the live app's settings changing back afterward
|
|
@@ -2737,3 +2830,12 @@ function planArchon(platform, recordedIds, executorBlocked, authReady, drifted,
|
|
|
2737
2830
|
blocked: null,
|
|
2738
2831
|
};
|
|
2739
2832
|
}
|
|
2833
|
+
/** The blocked text for a refused owner-org sign-in domain, while it is recorded and not yet primary. */
|
|
2834
|
+
function ownerDomainBlockedText(recordedIds) {
|
|
2835
|
+
const blockedDomain = recordedIds[PLATFORM_OWNER_ORG_DOMAIN_BLOCKED_SCOPE_KEY];
|
|
2836
|
+
if (!blockedDomain)
|
|
2837
|
+
return null;
|
|
2838
|
+
if (recordedIds[PLATFORM_OWNER_ORG_DOMAIN_SCOPE_KEY] === blockedDomain)
|
|
2839
|
+
return null;
|
|
2840
|
+
return signInDomainBlockedText('the platform owner', blockedDomain).replace(ZITADEL_ORG_DOMAIN_BLOCKED_SCOPE_KEY, PLATFORM_OWNER_ORG_DOMAIN_BLOCKED_SCOPE_KEY);
|
|
2841
|
+
}
|
|
@@ -61,6 +61,8 @@ export interface OrgPlatformReadiness {
|
|
|
61
61
|
* while `MAIL_DOMAIN_SCOPE_KEY` was still recorded as the apex.
|
|
62
62
|
*/
|
|
63
63
|
platformApex: string | null;
|
|
64
|
+
/** `DeclaredPlatform.ownerOrgId`, or `null` when no platform is declared or it is empty. The one fact "this is the platform's own org" rests on. */
|
|
65
|
+
platformOwnerOrgId: string | null;
|
|
64
66
|
/** `DeclaredPlatform.mail.lettermintProjectId`, `null` when undeclared or when no platform is declared. See {@link platformApex}'s own doc comment for why this is unconditional too. */
|
|
65
67
|
platformLettermintProjectId: string | null;
|
|
66
68
|
/** The files host (#171). Files is always on for every org (#80), so `false` always blocks rather than only mattering when a flag is set. */
|
|
@@ -27,6 +27,7 @@ export const NO_DOMAIN_MAIL_APEX = 'oikos.host';
|
|
|
27
27
|
export const DEFAULT_ORG_PLATFORM_READINESS = {
|
|
28
28
|
mailHost: null,
|
|
29
29
|
platformApex: null,
|
|
30
|
+
platformOwnerOrgId: null,
|
|
30
31
|
platformLettermintProjectId: null,
|
|
31
32
|
filesReady: false,
|
|
32
33
|
aiReady: false,
|
|
@@ -124,6 +125,7 @@ edgePortPresent = false) {
|
|
|
124
125
|
// mail.lettermintProjectId are facts regardless of whether mail itself is
|
|
125
126
|
// enabled or applied.
|
|
126
127
|
platformApex: platform.apex,
|
|
128
|
+
platformOwnerOrgId: platform.ownerOrgId || null,
|
|
127
129
|
platformLettermintProjectId: platform.mail.lettermintProjectId ?? null,
|
|
128
130
|
filesReady: filesApplied && missingKeys.files === null,
|
|
129
131
|
filesUrl: filesApplied
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CloudflareClient } from '@wtfalch/providers/cloudflare';
|
|
2
|
-
import type
|
|
2
|
+
import { type DeclaredOrg } from '../org.js';
|
|
3
3
|
import type { DeclaredPlatform } from '../platform.js';
|
|
4
4
|
import type { DeclaredOrgStore, PlatformStore } from '../store.js';
|
|
5
5
|
import { type DeployHealthRuntime } from './deploy-health.js';
|
|
@@ -10,7 +10,8 @@ import type { TunnelPort } from './edge-tunnels.js';
|
|
|
10
10
|
import type { CloudflarePort, CoolifyPort, FoundryStepExecutorPorts, ZitadelPort } from './executor.js';
|
|
11
11
|
import type { LiveResource, PlatformCloudflareReader, PlatformCoolifyReader } from './live.js';
|
|
12
12
|
import type { PlatformDriftedSteps, PlatformStepExecutionContext, PlatformStepExecutor } from './plan-apply.js';
|
|
13
|
-
import { type BrokerDeployRecord } from './platform-diff.js';
|
|
13
|
+
import { type BrokerDeployRecord, PLATFORM_ZITADEL_ORG_SCOPE_KEY } from './platform-diff.js';
|
|
14
|
+
export { PLATFORM_ZITADEL_ORG_SCOPE_KEY };
|
|
14
15
|
import { type CallsSfuPlatformDeps } from './platform-sfu.js';
|
|
15
16
|
import { type PlatformUptimeDeps } from './uptime-worker.js';
|
|
16
17
|
/**
|
|
@@ -90,7 +91,14 @@ export interface PlatformAuthDeps {
|
|
|
90
91
|
tunnels: PlatformTunnelsFactory;
|
|
91
92
|
cloudflare: Pick<CloudflarePort, 'findZoneByApex'>;
|
|
92
93
|
/** Must target the platform's own new instance (its issuer), or `zitadelForInstance` must be set. */
|
|
93
|
-
zitadel: Pick<ZitadelPort, 'findOrCreateOrg' | 'mintAdminMachineUser' | 'mintLoginClientMachineUser' | 'listLoginClientPats' | 'reserveUserName' | 'closeSelfRegistration' | 'inviteOrgOwner'> & PlatformZitadelSmtp;
|
|
94
|
+
zitadel: Pick<ZitadelPort, 'findOrCreateOrg' | 'mintAdminMachineUser' | 'mintLoginClientMachineUser' | 'listLoginClientPats' | 'reserveUserName' | 'closeSelfRegistration' | 'inviteOrgOwner' | 'addOrgDomain' | 'setPrimaryOrgDomain' | 'setUserMetadata' | 'getUserMetadata'> & PlatformZitadelSmtp;
|
|
95
|
+
/**
|
|
96
|
+
* Mails the owner's first-sign-in link to their personal address (the same
|
|
97
|
+
* port as `FoundryStepExecutorPorts.ownerInviteMail`). The link carries the
|
|
98
|
+
* invite code, so `send` must not log it or put it in an error. Without it
|
|
99
|
+
* the owner invite cannot run and the step stops there with a fixed message.
|
|
100
|
+
*/
|
|
101
|
+
ownerInviteMail?: FoundryStepExecutorPorts['ownerInviteMail'];
|
|
94
102
|
/**
|
|
95
103
|
* Builds the ZITADEL port for the new instance from its issuer URL
|
|
96
104
|
* (`https://<auth.hostname>`). When set it is used instead of
|
|
@@ -315,6 +323,7 @@ export declare class FoundryPlatformStepExecutor implements PlatformStepExecutor
|
|
|
315
323
|
auth?: string;
|
|
316
324
|
authExecutorMissing?: boolean;
|
|
317
325
|
authOtherInputsMissing?: string[];
|
|
326
|
+
authOwnerInvite?: string;
|
|
318
327
|
files?: string;
|
|
319
328
|
integrations?: string;
|
|
320
329
|
ai?: string;
|
|
@@ -336,6 +345,7 @@ export declare class FoundryPlatformStepExecutor implements PlatformStepExecutor
|
|
|
336
345
|
archonRunsInsideApp?: boolean;
|
|
337
346
|
archonDeployRunning?: string;
|
|
338
347
|
archonIdTokenUserinfo?: boolean;
|
|
348
|
+
authSignInPolicy?: boolean;
|
|
339
349
|
}>;
|
|
340
350
|
/**
|
|
341
351
|
* foundry#542: why the uptime Worker cannot run yet, which optional secrets
|
|
@@ -519,12 +529,51 @@ export interface PlatformMailRuntime {
|
|
|
519
529
|
/** Tries at handing the admin key to the host (default 3). */
|
|
520
530
|
deliverAttempts?: number;
|
|
521
531
|
}
|
|
532
|
+
/**
|
|
533
|
+
* #211: the broker cannot start without `ZITADEL_SERVICE_USER_TOKEN`/`_FILE`,
|
|
534
|
+
* `LETTERMINT_API_TOKEN` and `AUTH_APPS`. `provisionPlatformAuth` already
|
|
535
|
+
* skips deploying the broker while any is missing
|
|
536
|
+
* ({@link missingBrokerInputs}); this is the same check surfaced through
|
|
537
|
+
* `blockedSteps`, so a plan says why, by name, rather than the broker simply
|
|
538
|
+
* sitting undeployed with no explanation. `null` while there is no broker
|
|
539
|
+
* app id recorded yet (nothing to check) or every input is present.
|
|
540
|
+
*
|
|
541
|
+
* #211 round 3: wraps the live read the way {@link mailBlockedReason} wraps
|
|
542
|
+
* its own Coolify call -- a transient `listEnvs` failure must report a
|
|
543
|
+
* blocked reason naming the broker app id, never throw out of
|
|
544
|
+
* `blockedSteps` and take the rest of the plan down with it.
|
|
545
|
+
*
|
|
546
|
+
* #211 round 5 addendum: when `AUTH_APPS` is the reason, names which problem
|
|
547
|
+
* it actually is ({@link authAppsProblem}) instead of always saying "it has
|
|
548
|
+
* no ... AUTH_APPS yet" -- that wording is only true when nothing has been
|
|
549
|
+
* set; a present-but-invalid value is a different failure (a person needs to
|
|
550
|
+
* go fix an entry, not merely wait for one of #209/#210/Archon's own
|
|
551
|
+
* registration to supply one), and reporting it identically hid which one
|
|
552
|
+
* was true.
|
|
553
|
+
*
|
|
554
|
+
* #210: `LETTERMINT_API_TOKEN` joins `ZITADEL_SERVICE_USER_TOKEN` in being
|
|
555
|
+
* excluded from `otherInputsMissing` -- but only while `auth.heldKeys`
|
|
556
|
+
* actually resolves {@link PLATFORM_AUTH_BROKER_MAIL_KEY_REF} right now.
|
|
557
|
+
* `planAuth`'s own "loop fix" stops planning this step the moment every
|
|
558
|
+
* `otherInputsMissing` entry looks like something only another run can
|
|
559
|
+
* supply; excluding `LETTERMINT_API_TOKEN` unconditionally (the way
|
|
560
|
+
* `ZITADEL_SERVICE_USER_TOKEN` is, since foundry can always eventually mint
|
|
561
|
+
* that one) would keep the step planned, and `provisionPlatformAuth`
|
|
562
|
+
* running its full body, forever on a host that never wires `heldKeys` or
|
|
563
|
+
* whose operator has not put a Lettermint key there yet -- exactly the
|
|
564
|
+
* wasteful-replan bug #211 round 5 fixed for the broker deploy itself. Once
|
|
565
|
+
* the key *is* held, excluding it lets this run's `provisionPlatformAuth`
|
|
566
|
+
* push it (see that function's own `heldMailKey` read) and clears the gap
|
|
567
|
+
* for good.
|
|
568
|
+
*/
|
|
569
|
+
/** Why the platform owner cannot be invited yet, or `null`. Fixed text: names no address. */
|
|
570
|
+
export declare function ownerInviteBlockedReason(ownerCompany: DeclaredOrg | null, hasInviteMail: boolean): string | null;
|
|
522
571
|
/**
|
|
523
572
|
* #175: everything {@link provisionPlatformArchon} needs beyond
|
|
524
573
|
* {@link PlatformStepExecutionContext}, bundled like {@link PlatformAuthDeps}.
|
|
525
574
|
*/
|
|
526
575
|
export interface PlatformArchonDeps {
|
|
527
|
-
coolify: Pick<CoolifyPort, 'findProjectByName' | 'createProject' | 'findOrCreateEnvironment' | 'listServers' | 'findApplicationByName' | 'getApplication' | 'requireGithubApp' | 'createGithubAppApplication' | 'createDockerfileApplication' | 'listDatabases' | 'createPostgresDatabase' | 'getDatabase' | 'raw' | 'bulkUpsertEnvs' | 'listEnvs' | 'deleteEnv' | 'updateApplication' | 'deploy' | 'deployAndWait' | 'getDeployment'>;
|
|
576
|
+
coolify: Pick<CoolifyPort, 'findProjectByName' | 'listEnvironments' | 'createProject' | 'findOrCreateEnvironment' | 'listServers' | 'findApplicationByName' | 'getApplication' | 'requireGithubApp' | 'createGithubAppApplication' | 'createDockerfileApplication' | 'listDatabases' | 'createPostgresDatabase' | 'getDatabase' | 'raw' | 'bulkUpsertEnvs' | 'listEnvs' | 'deleteEnv' | 'updateApplication' | 'deploy' | 'deployAndWait' | 'getDeployment'>;
|
|
528
577
|
/** F4.dns: every DNS record call, through edge at its recorded address (see {@link PlatformDnsFactory}). */
|
|
529
578
|
dns: PlatformDnsFactory;
|
|
530
579
|
/** F4.tunnels: every tunnel call, through edge at its recorded address (see {@link PlatformTunnelsFactory}). */
|
|
@@ -603,8 +652,6 @@ export interface PlatformArchonRuntime {
|
|
|
603
652
|
* org (`foundry:<orgId>`), with the platform's step key in the org id's place.
|
|
604
653
|
*/
|
|
605
654
|
export declare const PLATFORM_ARCHON_ACCESS_APP_NAME = "foundry:platform:archon";
|
|
606
|
-
/** The platform's own ZITADEL org (`foundry`, the one `provisionPlatformAuth` mints its admin user in). */
|
|
607
|
-
export declare const PLATFORM_ZITADEL_ORG_SCOPE_KEY = "zitadel_platform_org";
|
|
608
655
|
/** Archon's OIDC client id: public, not a secret, so a plain scope id. */
|
|
609
656
|
export declare const PLATFORM_ARCHON_CLIENT_ID_SCOPE_KEY = "zitadel_platform_archon_client_id";
|
|
610
657
|
/**
|
|
@@ -1246,4 +1293,3 @@ export declare function filesPublicHostsValue(publicHosts: string | undefined, s
|
|
|
1246
1293
|
* from the declared orgs, for its apply and its drift check alike.
|
|
1247
1294
|
*/
|
|
1248
1295
|
export declare function filesShareDomains(orgs: readonly DeclaredOrg[]): string[];
|
|
1249
|
-
export {};
|