@wtfalch/foundry 0.16.16 → 0.17.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.
- package/dist/apply.d.ts +22 -1
- package/dist/bootstrap/bootstrap.d.ts +6 -1
- package/dist/bootstrap/bootstrap.js +26 -3
- package/dist/bootstrap/declare.d.ts +11 -1
- package/dist/bootstrap/declare.js +12 -2
- package/dist/index.d.ts +9 -4
- package/dist/index.js +7 -0
- package/dist/migrations/0038_calls_version_pin.sql +8 -0
- package/dist/migrations/0039_destroy_record.sql +7 -0
- package/dist/migrations/0040_company_included_uuid.sql +72 -0
- package/dist/migrations/0041_company_included_uuid_keys.sql +132 -0
- package/dist/migrations/0042_mutation_leases.sql +12 -0
- package/dist/org.d.ts +54 -0
- package/dist/org.js +43 -1
- package/dist/plan/adopt.d.ts +76 -0
- package/dist/plan/adopt.js +184 -0
- package/dist/plan/agora.d.ts +21 -0
- package/dist/plan/agora.js +37 -0
- package/dist/plan/broker-entries.d.ts +9 -1
- package/dist/plan/broker-entries.js +13 -5
- package/dist/plan/chat-matrix.d.ts +1 -1
- package/dist/plan/chat-matrix.js +11 -3
- package/dist/plan/core-files.d.ts +25 -0
- package/dist/plan/core-files.js +25 -0
- package/dist/plan/diff.d.ts +11 -3
- package/dist/plan/diff.js +27 -62
- package/dist/plan/entry-ai-key.d.ts +3 -3
- package/dist/plan/entry-files-key.d.ts +3 -3
- package/dist/plan/executor.d.ts +57 -23
- package/dist/plan/executor.js +134 -50
- package/dist/plan/index.d.ts +4 -0
- package/dist/plan/index.js +2 -0
- package/dist/plan/live.d.ts +5 -0
- package/dist/plan/login-host.d.ts +1 -1
- package/dist/plan/login-host.js +6 -5
- package/dist/plan/plan-apply.d.ts +139 -6
- package/dist/plan/plan-apply.js +546 -76
- package/dist/plan/platform-diff.d.ts +14 -0
- package/dist/plan/platform-diff.js +16 -1
- package/dist/plan/platform-org.d.ts +16 -0
- package/dist/plan/platform-org.js +17 -1
- package/dist/plan/platform-providers.d.ts +1 -1
- package/dist/plan/platform-providers.js +73 -11
- package/dist/plan/providers-readers.d.ts +2 -0
- package/dist/plan/providers-readers.js +4 -0
- package/dist/plan/rollout.d.ts +52 -0
- package/dist/plan/rollout.js +37 -0
- package/dist/plan/step-system.d.ts +22 -0
- package/dist/plan/step-system.js +37 -0
- package/dist/plan.d.ts +3 -0
- package/dist/state.d.ts +13 -0
- package/dist/store/audit.js +15 -1
- package/dist/store/postgres.d.ts +1 -1
- package/dist/store/postgres.js +127 -14
- package/dist/store/schema.d.ts +134 -5
- package/dist/store/schema.js +12 -1
- package/dist/store.d.ts +47 -4
- package/dist/store.js +9 -1
- package/package.json +1 -1
package/dist/plan/diff.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { VERSIONS, floatingTagBlocked } from '../bootstrap/versions.js';
|
|
2
2
|
import { APP_ENTRY_KEY, ownerMailboxRecorded, ownerMailboxes } from '../org.js';
|
|
3
|
-
import { CALLS_INTROSPECTION_SCOPE_KEY, CALLS_INTROSPECTION_UNDELIVERED_SCOPE_KEY, NO_AGORA_HOST_VALUES, ZITADEL_ORG_SCOPE_KEY, agoraEnvDrift, agoraHostMissing, agoraHostnameFor, callsServiceHasName, callsServiceHasTokenEnv, callsTokenEnvMovedMessage, callsTokenHostFrom, desiredAgoraEnv, withRecordedMessagingProject, } from './agora.js';
|
|
3
|
+
import { AGORA_ACTIVATED_ENV_SCOPE_KEY, CALLS_INTROSPECTION_SCOPE_KEY, CALLS_INTROSPECTION_UNDELIVERED_SCOPE_KEY, NO_AGORA_HOST_VALUES, ZITADEL_ORG_SCOPE_KEY, agoraEnvDrift, agoraEnvRevision, agoraHostMissing, agoraHostnameFor, callsServiceHasName, callsServiceHasTokenEnv, callsTokenEnvMovedMessage, callsTokenHostFrom, desiredAgoraEnv, withRecordedMessagingProject, } from './agora.js';
|
|
4
4
|
import { BOULE_BROKER_ENTRY_KEY, bouleEnvDrift, desiredBouleEnv, wantedBouleBrokerEntry, } from './boule.js';
|
|
5
5
|
import { brokerEntryAppliedScopeKey, brokerEntryWarningsScopeKey, entryAuthEnv, entryAuthEnvAppliedScopeKey, wantedBrokerEntry, } from './broker-entries.js';
|
|
6
6
|
import { planEntryAiKeys } from './entry-ai-key.js';
|
|
@@ -12,6 +12,7 @@ import { CALLS_MAS_APPLIED_IMAGE_TAG_SCOPE_KEY, CALLS_SYNAPSE_APPLIED_IMAGE_TAG_
|
|
|
12
12
|
import { DEFAULT_ORG_PLATFORM_READINESS } from './platform-org.js';
|
|
13
13
|
import { PLATFORM_AUTH_BROKER_MAIL_KEY_REF } from './platform-providers.js';
|
|
14
14
|
import { appLabelsAppliedScopeKey, entryLabelHash, entryLabelSpec } from './proxy-labels.js';
|
|
15
|
+
import { withStepSystem } from './step-system.js';
|
|
15
16
|
/** The `Plan` (#19's public contract) a `PlanDetail` carries. */
|
|
16
17
|
export function toPlan(detail) {
|
|
17
18
|
return {
|
|
@@ -42,9 +43,8 @@ function resourceKey(system, kind, key) {
|
|
|
42
43
|
* `hosting.issuerApps[]` entry rather than a single singleton, since an org
|
|
43
44
|
* can declare more than one ZITADEL app. #80 adds two more singletons,
|
|
44
45
|
* modeled on {@link planIssuer}: `planFilesOrganisation` and
|
|
45
|
-
* `planAiOrganisation`,
|
|
46
|
-
*
|
|
47
|
-
* limit to land, and AI use is switched on, before either limit is ever set.
|
|
46
|
+
* `planAiOrganisation`, the second planned before {@link planAiBudget} so AI
|
|
47
|
+
* use is switched on before its own limit is ever set.
|
|
48
48
|
* `planOwners` below adds one more singleton, in a different shape from the
|
|
49
49
|
* rest: the org's owner, invited by ZITADEL email, idempotent on the
|
|
50
50
|
* *recorded* resource id (`recordedIds`, sourced from
|
|
@@ -142,9 +142,6 @@ export function computePlanDetail(org, live, recordedIds = {}, agoraHost = NO_AG
|
|
|
142
142
|
const filesOrganisation = planFilesOrganisation(org, byKey, claimed, platformReadiness.filesReady, platformReadiness.missingKeys.files, platformReadiness.noKeyReader);
|
|
143
143
|
if (filesOrganisation.step)
|
|
144
144
|
plannedSteps.push(filesOrganisation.step);
|
|
145
|
-
const storage = planStorage(org, byKey, claimed, platformReadiness.filesReady, platformReadiness.missingKeys.files, platformReadiness.noKeyReader);
|
|
146
|
-
if (storage.step)
|
|
147
|
-
plannedSteps.push(storage.step);
|
|
148
145
|
const aiOrganisation = planAiOrganisation(org, byKey, claimed, platformReadiness.aiReady, platformReadiness.missingKeys.ai, platformReadiness.noKeyReader);
|
|
149
146
|
if (aiOrganisation.step)
|
|
150
147
|
plannedSteps.push(aiOrganisation.step);
|
|
@@ -313,8 +310,6 @@ export function computePlanDetail(org, live, recordedIds = {}, agoraHost = NO_AG
|
|
|
313
310
|
if (aiOrganisation.blocked) {
|
|
314
311
|
unmanaged.push({ description: aiOrganisation.blocked, key: 'ai:organisation' });
|
|
315
312
|
}
|
|
316
|
-
if (storage.blocked)
|
|
317
|
-
unmanaged.push({ description: storage.blocked, key: 'files:storage' });
|
|
318
313
|
if (aiBudget.blocked)
|
|
319
314
|
unmanaged.push({ description: aiBudget.blocked, key: 'ai:budget' });
|
|
320
315
|
// #238: a pending zone, reported here with its nameservers rather than
|
|
@@ -326,7 +321,12 @@ export function computePlanDetail(org, live, recordedIds = {}, agoraHost = NO_AG
|
|
|
326
321
|
unmanaged.push(...app.blocked);
|
|
327
322
|
unmanaged.push(...brokerEntries.blocked);
|
|
328
323
|
unmanaged.push(...bouleBroker.blocked);
|
|
329
|
-
return {
|
|
324
|
+
return {
|
|
325
|
+
orgId: org.id,
|
|
326
|
+
plannedSteps: plannedSteps.map(withStepSystem),
|
|
327
|
+
unmanaged,
|
|
328
|
+
versionChanges,
|
|
329
|
+
};
|
|
330
330
|
}
|
|
331
331
|
/**
|
|
332
332
|
* The org's own ZITADEL org (issuer), a per-org singleton like every other
|
|
@@ -990,11 +990,8 @@ function notReadyReason(service, keyName, missingKeyRef, noKeyReader) {
|
|
|
990
990
|
: `the platform's ${service} host is off or not yet applied`;
|
|
991
991
|
}
|
|
992
992
|
/**
|
|
993
|
-
* #80: every org's own organisation on Files, a per-org singleton resource
|
|
994
|
-
*
|
|
995
|
-
* org Files has never provisioned (`files/packages/sdk/src/client.ts`'s
|
|
996
|
-
* tenant routes need the row `provisionOrganisation` creates). Modeled on
|
|
997
|
-
* {@link planIssuer}: nothing to diff once it exists -- Files' own
|
|
993
|
+
* #80: every org's own organisation on Files, a per-org singleton resource.
|
|
994
|
+
* Modeled on {@link planIssuer}: nothing to diff once it exists -- Files' own
|
|
998
995
|
* `provisionOrganisation` is safely repeatable (`executor.ts`'s
|
|
999
996
|
* `filesOrganisation` calls it every time regardless), so the only planned
|
|
1000
997
|
* state is "not provisioned yet". The operator-driven `ceilingBytes`/
|
|
@@ -1117,53 +1114,9 @@ function planAiOrganisation(org, byKey, claimed, aiReady, missingKeyRef, noKeyRe
|
|
|
1117
1114
|
blocked: null,
|
|
1118
1115
|
};
|
|
1119
1116
|
}
|
|
1120
|
-
/**
|
|
1121
|
-
* #27: the org's own spend limit on Files, a per-org singleton resource in
|
|
1122
|
-
* the same shape as issuer/mail/chat above. Setting a limit is a config
|
|
1123
|
-
* write, never destructive or migrating (#27 "Notes": "safe, idempotent and
|
|
1124
|
-
* reversible"). A missing live resource reads as uncapped (`null`), the same
|
|
1125
|
-
* value a freshly-declared org's `storage` starts at, so a brand new org with
|
|
1126
|
-
* no limits declared produces no step.
|
|
1127
|
-
*
|
|
1128
|
-
* #177: silently plans nothing while there is no organisation to size a limit
|
|
1129
|
-
* on yet and `filesReady` is false -- {@link planFilesOrganisation} already
|
|
1130
|
-
* reports the platform's files host as missing once.
|
|
1131
|
-
*/
|
|
1132
|
-
function planStorage(org, byKey, claimed, filesReady, missingKeyRef, noKeyReader = false) {
|
|
1133
|
-
const key = resourceKey('files', 'storage', org.id);
|
|
1134
|
-
const live = byKey.get(key);
|
|
1135
|
-
if (live)
|
|
1136
|
-
claimed.add(key);
|
|
1137
|
-
if (!filesReady && !live)
|
|
1138
|
-
return { step: null, blocked: null };
|
|
1139
|
-
const desired = { limitBytes: org.storage.limitBytes, limitMicros: org.storage.limitMicros };
|
|
1140
|
-
const liveLimitBytes = live ? (live.config.limitBytes ?? null) : null;
|
|
1141
|
-
const liveLimitMicros = live ? (live.config.limitMicros ?? null) : null;
|
|
1142
|
-
if (liveLimitBytes === desired.limitBytes && liveLimitMicros === desired.limitMicros) {
|
|
1143
|
-
return { step: null, blocked: null };
|
|
1144
|
-
}
|
|
1145
|
-
// A live resource with drift needs the platform's key to change; blocked, not planned to throw at apply.
|
|
1146
|
-
if (!filesReady) {
|
|
1147
|
-
return {
|
|
1148
|
-
step: null,
|
|
1149
|
-
blocked: `${org.slug}'s storage limit change is blocked, not planned: ${notReadyReason('files', 'files management key', missingKeyRef, noKeyReader)}`,
|
|
1150
|
-
};
|
|
1151
|
-
}
|
|
1152
|
-
return {
|
|
1153
|
-
blocked: null,
|
|
1154
|
-
step: {
|
|
1155
|
-
action: { system: 'files', kind: 'storage', key: org.id, desired },
|
|
1156
|
-
step: {
|
|
1157
|
-
description: `set ${org.slug}'s storage limit to ${desired.limitBytes ?? 'uncapped'} bytes / ${desired.limitMicros ?? 'uncapped'} micros`,
|
|
1158
|
-
destroys: false,
|
|
1159
|
-
migrates: false,
|
|
1160
|
-
},
|
|
1161
|
-
},
|
|
1162
|
-
};
|
|
1163
|
-
}
|
|
1164
1117
|
/**
|
|
1165
1118
|
* #27: the org's own spend limit on AI, a per-org singleton resource in the
|
|
1166
|
-
* same shape as
|
|
1119
|
+
* same singleton shape as issuer/mail/chat above. Planned after {@link planAiOrganisation}
|
|
1167
1120
|
* (#80), which already seeds a brand new org's first budget row from this
|
|
1168
1121
|
* same `org.ai.limitMicros` -- this planner only fires again once that row's
|
|
1169
1122
|
* live value has drifted from what is declared.
|
|
@@ -1469,13 +1422,25 @@ function planAgora(org, byKey, claimed, recordedIds, reading) {
|
|
|
1469
1422
|
if (liveEnv.AGORA_CONFIG === undefined && !drift.includes('AGORA_CONFIG')) {
|
|
1470
1423
|
drift.push('AGORA_CONFIG');
|
|
1471
1424
|
}
|
|
1472
|
-
|
|
1425
|
+
// #442: `drift` alone, once this step has ever run, is comparing `env`
|
|
1426
|
+
// against Coolify's own env store -- which the executor's `bulkUpsertEnvs`
|
|
1427
|
+
// leaves matching `env` the moment the write succeeds, restarted or not.
|
|
1428
|
+
// So once applied, drift reads empty forever even if the running process
|
|
1429
|
+
// was never restarted onto it (a crash between the write and the restart,
|
|
1430
|
+
// or simply never restarting at all). `AGORA_ACTIVATED_ENV_SCOPE_KEY` is
|
|
1431
|
+
// the executor's own record that a restart confirmed the process is
|
|
1432
|
+
// actually serving this exact `env`; while it disagrees, the step stays
|
|
1433
|
+
// planned no matter what Coolify's env store already shows.
|
|
1434
|
+
const activated = recordedIds[AGORA_ACTIVATED_ENV_SCOPE_KEY] === agoraEnvRevision(env);
|
|
1435
|
+
if (drift.length === 0 && activated)
|
|
1473
1436
|
return { step: null, blocked: null };
|
|
1474
1437
|
return {
|
|
1475
1438
|
step: {
|
|
1476
1439
|
action,
|
|
1477
1440
|
step: {
|
|
1478
|
-
description:
|
|
1441
|
+
description: drift.length > 0
|
|
1442
|
+
? `update ${org.slug}'s Agora config (${drift.join(', ')} missing or different)`
|
|
1443
|
+
: `activate ${org.slug}'s Agora config -- written but not yet confirmed restarted`,
|
|
1479
1444
|
destroys: false,
|
|
1480
1445
|
migrates: false,
|
|
1481
1446
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type DeclaredOrg, type HostingEntry } from '../org.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { DraftStep } from './diff.js';
|
|
3
3
|
import type { OrgPlatformReadiness } from './platform-org.js';
|
|
4
4
|
/**
|
|
5
5
|
* F6a: one ai key per entry with `uses.ai`, minted below the org's own ai key
|
|
@@ -49,8 +49,8 @@ export type EntryAiMode = 'mint' | 'renew' | 'settings' | 'finish' | 'retire';
|
|
|
49
49
|
* entry's app or the ai address is not recorded, or after a mint whose
|
|
50
50
|
* delivery failed: a second mint would leave two live keys.
|
|
51
51
|
*/
|
|
52
|
-
export declare function planEntryAiKeys(org: DeclaredOrg, recordedIds: Readonly<Record<string, string>>, plannedSteps: readonly
|
|
53
|
-
steps:
|
|
52
|
+
export declare function planEntryAiKeys(org: DeclaredOrg, recordedIds: Readonly<Record<string, string>>, plannedSteps: readonly DraftStep[], readiness: OrgPlatformReadiness, now: number): {
|
|
53
|
+
steps: DraftStep[];
|
|
54
54
|
blocked: Array<{
|
|
55
55
|
description: string;
|
|
56
56
|
key: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type DeclaredOrg, type HostingEntry } from '../org.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { DraftStep } from './diff.js';
|
|
3
3
|
import type { OrgPlatformReadiness } from './platform-org.js';
|
|
4
4
|
/**
|
|
5
5
|
* F6b: the org's own files key, minted below the files organisation's
|
|
@@ -77,8 +77,8 @@ type Blocked = Array<{
|
|
|
77
77
|
* it by its own `renew` step, and only then does `revoke-previous` revoke the
|
|
78
78
|
* old org key, which revokes everything still below it.
|
|
79
79
|
*/
|
|
80
|
-
export declare function planFilesKeys(org: DeclaredOrg, recordedIds: Readonly<Record<string, string>>, plannedSteps: readonly
|
|
81
|
-
steps:
|
|
80
|
+
export declare function planFilesKeys(org: DeclaredOrg, recordedIds: Readonly<Record<string, string>>, plannedSteps: readonly DraftStep[], readiness: OrgPlatformReadiness, now: number): {
|
|
81
|
+
steps: DraftStep[];
|
|
82
82
|
blocked: Blocked;
|
|
83
83
|
};
|
|
84
84
|
export {};
|
package/dist/plan/executor.d.ts
CHANGED
|
@@ -183,10 +183,19 @@ export interface CoolifyPort {
|
|
|
183
183
|
* `is_preview === false` the same way a deployed-config reader must.
|
|
184
184
|
*/
|
|
185
185
|
listEnvs(applicationUuid: string): Promise<Array<{
|
|
186
|
+
uuid?: string;
|
|
186
187
|
key: string;
|
|
187
188
|
value: string;
|
|
188
189
|
is_preview: boolean;
|
|
189
190
|
}>>;
|
|
191
|
+
/**
|
|
192
|
+
* #436 round 2: removes one environment variable row by the `uuid`
|
|
193
|
+
* `listEnvs` names it under -- `bulkUpsertEnvs` only adds or updates, so
|
|
194
|
+
* this is the only way to make a var foundry wrote in an earlier release
|
|
195
|
+
* actually go away, rather than leaving it set to a value nothing reads
|
|
196
|
+
* any more (`provisionPlatformArchon`'s stale `FILES_MANAGEMENT_KEY`).
|
|
197
|
+
*/
|
|
198
|
+
deleteEnv(applicationUuid: string, envUuid: string): Promise<unknown>;
|
|
190
199
|
/** Escape hatch (`CoolifyClient.raw`) — used for stop/start, which have no typed method yet. */
|
|
191
200
|
raw(method: string, path: string, body?: unknown): Promise<unknown>;
|
|
192
201
|
/**
|
|
@@ -1049,16 +1058,6 @@ export interface ZitadelListAppsRawApp {
|
|
|
1049
1058
|
* `signManagementRequest`/`AssertionTrust`). A host can construct this without
|
|
1050
1059
|
* any human session: it only needs the Ed25519 private key (`SigningIdentity`)
|
|
1051
1060
|
* an operator's `MANAGEMENT_PUBLIC_KEYS`/`MANAGEMENT_ISSUER` pins.
|
|
1052
|
-
*
|
|
1053
|
-
* #177: `setQuota`/`setBudget` (`files/packages/sdk/src/client.ts:154-166`)
|
|
1054
|
-
* used to live on a separate `FilesOrgLimits` a host built per org through a
|
|
1055
|
-
* `filesLimitsFor(orgId)` factory on `FoundryStepExecutorPorts` — ceremony
|
|
1056
|
-
* left over from nothing but currying an id this port's own callers already
|
|
1057
|
-
* have in hand. The signed claim's `organisation` field selects the org per
|
|
1058
|
-
* call, so one shared keypair signs for every org already, the same signer
|
|
1059
|
-
* `provisionOrganisation` uses; there was never a per-org client to build,
|
|
1060
|
-
* only an org id to pass. Both methods now take it explicitly, like
|
|
1061
|
-
* `provisionOrganisation` always did, and `filesLimitsFor` is gone.
|
|
1062
1061
|
*/
|
|
1063
1062
|
export interface FilesOrganisationPort {
|
|
1064
1063
|
provisionOrganisation(input: {
|
|
@@ -1088,9 +1087,6 @@ export interface FilesOrganisationPort {
|
|
|
1088
1087
|
secret: string;
|
|
1089
1088
|
};
|
|
1090
1089
|
}>;
|
|
1091
|
-
/** #27, #177: the org's own spend limit on Files -- see this interface's own doc comment for why `organisationId` is explicit here. */
|
|
1092
|
-
setQuota(organisationId: string, limitBytes: string | null): Promise<unknown>;
|
|
1093
|
-
setBudget(organisationId: string, limitMicros: string | null): Promise<unknown>;
|
|
1094
1090
|
/**
|
|
1095
1091
|
* F6b: mints the organisation's own key, matching files'
|
|
1096
1092
|
* `POST /v1/manage/organisations/:organisationId/keys` (SDK
|
|
@@ -1251,10 +1247,10 @@ export interface AiOrganisationPort {
|
|
|
1251
1247
|
* `ai/packages/sdk/src/client.ts:94-101`'s `updateBudget` (`UpdateBudget`
|
|
1252
1248
|
* from `ai/packages/sdk/src/types.ts:134-137`). Used to live on a separate
|
|
1253
1249
|
* `AiOrgLimits` a host built per org through an `aiLimitsFor(orgId)`
|
|
1254
|
-
* factory on `FoundryStepExecutorPorts` --
|
|
1255
|
-
*
|
|
1256
|
-
* `
|
|
1257
|
-
*
|
|
1250
|
+
* factory on `FoundryStepExecutorPorts` -- ceremony left over from nothing
|
|
1251
|
+
* but currying an id this port's own callers already have in hand.
|
|
1252
|
+
* `organisationId` is explicit here now, like every other method on this
|
|
1253
|
+
* port.
|
|
1258
1254
|
*/
|
|
1259
1255
|
updateBudget(organisationId: string, input: {
|
|
1260
1256
|
keyId: string | null;
|
|
@@ -1594,6 +1590,20 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
1594
1590
|
private findRecreatedApp;
|
|
1595
1591
|
private ensureZitadelProject;
|
|
1596
1592
|
private ensureCoolifyProject;
|
|
1593
|
+
/**
|
|
1594
|
+
* #445: one company lands on one Coolify server. The first call for an
|
|
1595
|
+
* org picks a usable, reachable server and records it
|
|
1596
|
+
* ({@link COOLIFY_SERVER_SCOPE_KEY}); every later call -- this apply, or a
|
|
1597
|
+
* later one -- reads that recording back and returns the same server,
|
|
1598
|
+
* regardless of what the pool's order or health looks like by then. A
|
|
1599
|
+
* recorded server that has gone unusable or unreachable is reported
|
|
1600
|
+
* blocked (never silently replaced with a second host, which would split
|
|
1601
|
+
* the org's resources across servers and break their internal container
|
|
1602
|
+
* URLs); a recorded server no longer registered at all is the same.
|
|
1603
|
+
* Deliberately no fallback to `servers[0]` when nothing is usable: an
|
|
1604
|
+
* unusable server picked blind is not a server anyone's resources could
|
|
1605
|
+
* actually be created on.
|
|
1606
|
+
*/
|
|
1597
1607
|
private resolveServer;
|
|
1598
1608
|
private coolifyApp;
|
|
1599
1609
|
/**
|
|
@@ -1938,6 +1948,10 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
1938
1948
|
* `coolifyApp`'s own analogous gap (it never restarted a found-but-stopped
|
|
1939
1949
|
* app either) has since closed the same way, inline in that method (#130);
|
|
1940
1950
|
* this method is `cmsSite`'s only caller.
|
|
1951
|
+
*
|
|
1952
|
+
* `repo` (#245) lets the site app build from an org's own skin repo
|
|
1953
|
+
* (`org.site.repo`) instead of the shared `CMS_REPO`; `cmsSite` always
|
|
1954
|
+
* passes `CMS_REPO` for the cms admin app, which is never org-specific.
|
|
1941
1955
|
*/
|
|
1942
1956
|
private findOrCreateCmsApp;
|
|
1943
1957
|
/**
|
|
@@ -2091,6 +2105,19 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
2091
2105
|
* pushed once calls are on and this org's calls service app carries its
|
|
2092
2106
|
* internal name (`desiredAgoraEnv` reads that marker from the recorded ids,
|
|
2093
2107
|
* not the host values).
|
|
2108
|
+
*
|
|
2109
|
+
* #442: a found-but-already-running app's container binds env only at
|
|
2110
|
+
* start, so writing it alone leaves that process on its old config --
|
|
2111
|
+
* restarted (never redeployed: no new image, so `restart` is the same
|
|
2112
|
+
* primitive `ensureLogVolume`'s own restart uses) whenever the live env
|
|
2113
|
+
* actually differs, or whenever the last restart this step confirmed
|
|
2114
|
+
* ({@link AGORA_ACTIVATED_ENV_SCOPE_KEY}) is not this exact env (an org
|
|
2115
|
+
* applied before this existed, whose live env already matched desired
|
|
2116
|
+
* with nothing ever confirmed running it). A brand new app has nothing
|
|
2117
|
+
* running yet to restart. The activation marker is recorded last, after
|
|
2118
|
+
* the restart (if any) returns without throwing, so a failed restart
|
|
2119
|
+
* leaves it stale and the next plan replans this step even though
|
|
2120
|
+
* Coolify's own env store already matches desired.
|
|
2094
2121
|
*/
|
|
2095
2122
|
private coolifyAgora;
|
|
2096
2123
|
/**
|
|
@@ -2395,11 +2422,11 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
2395
2422
|
*/
|
|
2396
2423
|
private ensureLettermintDmarcRecord;
|
|
2397
2424
|
/**
|
|
2398
|
-
* #80: provisions the org's own organisation on Files
|
|
2399
|
-
*
|
|
2400
|
-
*
|
|
2401
|
-
*
|
|
2402
|
-
*
|
|
2425
|
+
* #80: provisions the org's own organisation on Files.
|
|
2426
|
+
* `provisionOrganisation` is safely repeatable on its own
|
|
2427
|
+
* (`FilesOrganisationPort`'s doc comment), so this is called every time
|
|
2428
|
+
* regardless of whether it already ran -- idempotent by find-or-create,
|
|
2429
|
+
* not by checking `recordedIds` first.
|
|
2403
2430
|
*
|
|
2404
2431
|
* F6b: `action.desired.shareHost` (`diff.ts`'s `planFilesOrganisation`) is
|
|
2405
2432
|
* passed through every time, even though `entry-files-key.ts` reports the
|
|
@@ -2412,6 +2439,14 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
2412
2439
|
* repeat-is-a-no-op shape as `provisionOrganisation` itself -- every org
|
|
2413
2440
|
* gets an Agora (#164), so `diff.ts`'s `planFilesOrganisation` always sets
|
|
2414
2441
|
* `desired.agoraOrigin`.
|
|
2442
|
+
*
|
|
2443
|
+
* #437: the owner member/name, the core ZITADEL files project and the core
|
|
2444
|
+
* collection (`core-files.ts`) are no longer conditioned on a hosting entry
|
|
2445
|
+
* declaring `uses.files` -- the core bundle (Agora's own uploads) needs
|
|
2446
|
+
* all three just as much as a bespoke entry does, and withholding them
|
|
2447
|
+
* until one existed is why a plain Agora/Boule org never got a usable
|
|
2448
|
+
* Files setup at all. Both the project and the collection are idempotent
|
|
2449
|
+
* by name, so a re-run that already created either finds it instead.
|
|
2415
2450
|
*/
|
|
2416
2451
|
private filesOrganisation;
|
|
2417
2452
|
/**
|
|
@@ -2422,7 +2457,6 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
2422
2457
|
* that fails revokes the key again instead of leaving a live key nobody holds.
|
|
2423
2458
|
*/
|
|
2424
2459
|
private deliverFilesAgoraKey;
|
|
2425
|
-
private filesStorage;
|
|
2426
2460
|
/**
|
|
2427
2461
|
* #80: provisions the org's own organisation on AI and switches its AI use
|
|
2428
2462
|
* on, before {@link aiBudget} can set its own spend limit. Both
|