@wtfalch/foundry 0.16.15 → 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 +82 -5
- package/dist/org.js +62 -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/deploy-health.d.ts +136 -0
- package/dist/plan/deploy-health.js +153 -0
- package/dist/plan/diff.d.ts +11 -3
- package/dist/plan/diff.js +77 -71
- package/dist/plan/entry-ai-key.d.ts +3 -3
- package/dist/plan/entry-files-key.d.ts +6 -4
- package/dist/plan/entry-files-key.js +7 -10
- package/dist/plan/executor.d.ts +109 -28
- package/dist/plan/executor.js +213 -56
- package/dist/plan/hostnames.d.ts +6 -0
- package/dist/plan/hostnames.js +13 -0
- package/dist/plan/index.d.ts +5 -1
- package/dist/plan/index.js +3 -1
- 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 +153 -3
- package/dist/plan/plan-apply.js +584 -69
- package/dist/plan/platform-diff.d.ts +103 -9
- package/dist/plan/platform-diff.js +192 -14
- package/dist/plan/platform-org.d.ts +25 -0
- package/dist/plan/platform-org.js +17 -1
- package/dist/plan/platform-providers.d.ts +38 -5
- package/dist/plan/platform-providers.js +592 -109
- 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 +2 -2
|
@@ -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
|
|
@@ -56,8 +56,10 @@ export interface EntryFilesWant {
|
|
|
56
56
|
permissions: string[];
|
|
57
57
|
collections: string[];
|
|
58
58
|
filesUrl: string;
|
|
59
|
+
/** `https://share.<domain>`, set only when the entry declares `shareHost`. */
|
|
60
|
+
shareOrigin?: string;
|
|
59
61
|
}
|
|
60
|
-
export declare function wantedEntryFiles(entry: HostingEntry, filesUrl: string): EntryFilesWant;
|
|
62
|
+
export declare function wantedEntryFiles(entry: HostingEntry, filesUrl: string, shareHostname?: string | null): EntryFilesWant;
|
|
61
63
|
export type EntryFilesMode = 'mint' | 'renew' | 'settings' | 'finish' | 'retire';
|
|
62
64
|
type Blocked = Array<{
|
|
63
65
|
description: string;
|
|
@@ -75,8 +77,8 @@ type Blocked = Array<{
|
|
|
75
77
|
* it by its own `renew` step, and only then does `revoke-previous` revoke the
|
|
76
78
|
* old org key, which revokes everything still below it.
|
|
77
79
|
*/
|
|
78
|
-
export declare function planFilesKeys(org: DeclaredOrg, recordedIds: Readonly<Record<string, string>>, plannedSteps: readonly
|
|
79
|
-
steps:
|
|
80
|
+
export declare function planFilesKeys(org: DeclaredOrg, recordedIds: Readonly<Record<string, string>>, plannedSteps: readonly DraftStep[], readiness: OrgPlatformReadiness, now: number): {
|
|
81
|
+
steps: DraftStep[];
|
|
80
82
|
blocked: Blocked;
|
|
81
83
|
};
|
|
82
84
|
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FILES_ENTRY_PERMISSIONS } from '../org.js';
|
|
2
|
+
import { filesShareHostname } from './hostnames.js';
|
|
2
3
|
import { appStepKey } from './platform-diff.js';
|
|
3
4
|
/**
|
|
4
5
|
* F6b: the org's own files key, minted below the files organisation's
|
|
@@ -67,12 +68,13 @@ export function filesOwnerUserId(org, recordedIds) {
|
|
|
67
68
|
const first = org.owners[0];
|
|
68
69
|
return first ? recordedIds[`zitadel:owner:${org.id}:${first.email.toLowerCase()}`] : undefined;
|
|
69
70
|
}
|
|
70
|
-
export function wantedEntryFiles(entry, filesUrl) {
|
|
71
|
+
export function wantedEntryFiles(entry, filesUrl, shareHostname = null) {
|
|
71
72
|
const files = entry.uses?.files;
|
|
72
73
|
return {
|
|
73
74
|
permissions: [...(files?.permissions ?? FILES_ENTRY_PERMISSIONS)],
|
|
74
75
|
collections: [...(files?.collections ?? [])],
|
|
75
76
|
filesUrl,
|
|
77
|
+
...(files?.shareHost && shareHostname ? { shareOrigin: `https://${shareHostname}` } : {}),
|
|
76
78
|
};
|
|
77
79
|
}
|
|
78
80
|
/**
|
|
@@ -157,14 +159,9 @@ export function planFilesKeys(org, recordedIds, plannedSteps, readiness, now) {
|
|
|
157
159
|
}
|
|
158
160
|
if (entries.length === 0 || !readiness.filesReady)
|
|
159
161
|
return { steps, blocked };
|
|
160
|
-
for
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
description: `${org.slug}'s ${entry.key} share host is blocked: the platform's files host has no route for share.<domain> yet, so FILES_SHARE_ORIGIN is not delivered`,
|
|
164
|
-
key: `files:share:${org.id}:${entry.key}`,
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
}
|
|
162
|
+
// The route and DNS for share.<domain> are planned with the tunnel; the org
|
|
163
|
+
// apply then gives the platform files runner the host (`FoundryPlanApply.apply`).
|
|
164
|
+
const shareHostname = filesShareHostname(org);
|
|
168
165
|
// The org's own key: minted, or renewed when it is short or its expiry is unknown.
|
|
169
166
|
const rootBlock = (why) => blocked.push({
|
|
170
167
|
description: `${org.slug}'s own files key is blocked: ${why}`,
|
|
@@ -244,7 +241,7 @@ export function planFilesKeys(org, recordedIds, plannedSteps, readiness, now) {
|
|
|
244
241
|
block("the entry's app is not recorded yet");
|
|
245
242
|
continue;
|
|
246
243
|
}
|
|
247
|
-
const want = wantedEntryFiles(entry, readiness.filesUrl);
|
|
244
|
+
const want = wantedEntryFiles(entry, readiness.filesUrl, shareHostname);
|
|
248
245
|
const applied = recordedIds[entryFilesAppliedScopeKey(entry.key)];
|
|
249
246
|
const wantJson = JSON.stringify(want);
|
|
250
247
|
let mode = null;
|
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
|
/**
|
|
@@ -294,10 +303,13 @@ export interface CoolifyPort {
|
|
|
294
303
|
* fresh Synapse/MAS config file, since a file-storage write alone does not
|
|
295
304
|
* reach the running container until its next deploy (issue #128's "a
|
|
296
305
|
* running app is redeployed when its config changed"). Fire-and-forget,
|
|
297
|
-
* like `restart` above:
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
* deploy` method-for-method.
|
|
306
|
+
* like `restart` above: `coolifyCalls` only calls this when the config it
|
|
307
|
+
* just wrote was actually freshly minted, with nothing recorded afterward
|
|
308
|
+
* that depends on the new version actually being live. Matches
|
|
309
|
+
* `CoolifyClient.deploy` method-for-method. A step that records an applied
|
|
310
|
+
* hostname/gitRef after a deploy uses {@link CoolifyPort.deployAndWait}
|
|
311
|
+
* instead (#252) — `deploy-health.ts`'s `waitForNewDeployment` is the one
|
|
312
|
+
* shared helper every such step calls, never this method directly.
|
|
301
313
|
*/
|
|
302
314
|
deploy(uuid: string, force?: boolean): Promise<unknown>;
|
|
303
315
|
/**
|
|
@@ -361,6 +373,27 @@ export interface CoolifyPort {
|
|
|
361
373
|
}): Promise<{
|
|
362
374
|
uuid: string;
|
|
363
375
|
}>;
|
|
376
|
+
/**
|
|
377
|
+
* Deploys and blocks until Coolify's own deployment record reaches a
|
|
378
|
+
* terminal state (#252) — matches `CoolifyClient.deployAndWait`
|
|
379
|
+
* method-for-method. Unlike `deploy` above, or unlike polling
|
|
380
|
+
* `getApplication`'s live `status`, this is the one honest answer to
|
|
381
|
+
* "did the new version actually land": a failed build leaves the previous
|
|
382
|
+
* container running and healthy, so `status` and a served request read
|
|
383
|
+
* identically whether the deploy succeeded or not (`CoolifyDeploymentRecord`'s
|
|
384
|
+
* own doc comment in `@wtfalch/providers`). `force` defaults to `true` on
|
|
385
|
+
* the real client for the same reason its own doc comment gives — every
|
|
386
|
+
* caller here is provisioning or releasing, where a wrong "it's applied"
|
|
387
|
+
* costs more than a warm build cache.
|
|
388
|
+
*/
|
|
389
|
+
deployAndWait(uuid: string, options?: {
|
|
390
|
+
force?: boolean;
|
|
391
|
+
attempts?: number;
|
|
392
|
+
intervalMs?: number;
|
|
393
|
+
}): Promise<{
|
|
394
|
+
deploymentUuid: string;
|
|
395
|
+
status: string;
|
|
396
|
+
}>;
|
|
364
397
|
}
|
|
365
398
|
/**
|
|
366
399
|
* The Cloudflare calls this executor makes, shaped to match
|
|
@@ -812,7 +845,7 @@ export interface ZitadelPort {
|
|
|
812
845
|
givenName: string;
|
|
813
846
|
familyName: string;
|
|
814
847
|
email: string;
|
|
815
|
-
}): Promise<{
|
|
848
|
+
}, urlTemplate?: string): Promise<{
|
|
816
849
|
userId: string;
|
|
817
850
|
created: boolean;
|
|
818
851
|
}>;
|
|
@@ -1025,16 +1058,6 @@ export interface ZitadelListAppsRawApp {
|
|
|
1025
1058
|
* `signManagementRequest`/`AssertionTrust`). A host can construct this without
|
|
1026
1059
|
* any human session: it only needs the Ed25519 private key (`SigningIdentity`)
|
|
1027
1060
|
* an operator's `MANAGEMENT_PUBLIC_KEYS`/`MANAGEMENT_ISSUER` pins.
|
|
1028
|
-
*
|
|
1029
|
-
* #177: `setQuota`/`setBudget` (`files/packages/sdk/src/client.ts:154-166`)
|
|
1030
|
-
* used to live on a separate `FilesOrgLimits` a host built per org through a
|
|
1031
|
-
* `filesLimitsFor(orgId)` factory on `FoundryStepExecutorPorts` — ceremony
|
|
1032
|
-
* left over from nothing but currying an id this port's own callers already
|
|
1033
|
-
* have in hand. The signed claim's `organisation` field selects the org per
|
|
1034
|
-
* call, so one shared keypair signs for every org already, the same signer
|
|
1035
|
-
* `provisionOrganisation` uses; there was never a per-org client to build,
|
|
1036
|
-
* only an org id to pass. Both methods now take it explicitly, like
|
|
1037
|
-
* `provisionOrganisation` always did, and `filesLimitsFor` is gone.
|
|
1038
1061
|
*/
|
|
1039
1062
|
export interface FilesOrganisationPort {
|
|
1040
1063
|
provisionOrganisation(input: {
|
|
@@ -1064,9 +1087,6 @@ export interface FilesOrganisationPort {
|
|
|
1064
1087
|
secret: string;
|
|
1065
1088
|
};
|
|
1066
1089
|
}>;
|
|
1067
|
-
/** #27, #177: the org's own spend limit on Files -- see this interface's own doc comment for why `organisationId` is explicit here. */
|
|
1068
|
-
setQuota(organisationId: string, limitBytes: string | null): Promise<unknown>;
|
|
1069
|
-
setBudget(organisationId: string, limitMicros: string | null): Promise<unknown>;
|
|
1070
1090
|
/**
|
|
1071
1091
|
* F6b: mints the organisation's own key, matching files'
|
|
1072
1092
|
* `POST /v1/manage/organisations/:organisationId/keys` (SDK
|
|
@@ -1227,10 +1247,10 @@ export interface AiOrganisationPort {
|
|
|
1227
1247
|
* `ai/packages/sdk/src/client.ts:94-101`'s `updateBudget` (`UpdateBudget`
|
|
1228
1248
|
* from `ai/packages/sdk/src/types.ts:134-137`). Used to live on a separate
|
|
1229
1249
|
* `AiOrgLimits` a host built per org through an `aiLimitsFor(orgId)`
|
|
1230
|
-
* factory on `FoundryStepExecutorPorts` --
|
|
1231
|
-
*
|
|
1232
|
-
* `
|
|
1233
|
-
*
|
|
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.
|
|
1234
1254
|
*/
|
|
1235
1255
|
updateBudget(organisationId: string, input: {
|
|
1236
1256
|
keyId: string | null;
|
|
@@ -1341,6 +1361,16 @@ export interface FoundryStepExecutorPorts {
|
|
|
1341
1361
|
* themselves.
|
|
1342
1362
|
*/
|
|
1343
1363
|
deliverSecret(ref: string, secret: string): Promise<void>;
|
|
1364
|
+
/**
|
|
1365
|
+
* Archon's held keys, for an entry env from `sharedSecret` (read, else
|
|
1366
|
+
* generate and `put`) and `platformMailKey` (read only). Optional: without
|
|
1367
|
+
* it, or without `put`, such an env is omitted and the plan reports it
|
|
1368
|
+
* blocked. A value goes to the entry's env and nowhere else.
|
|
1369
|
+
*/
|
|
1370
|
+
heldKeys?: {
|
|
1371
|
+
resolve(ref: string): Promise<string | null | undefined>;
|
|
1372
|
+
put?(ref: string, value: string): Promise<void>;
|
|
1373
|
+
};
|
|
1344
1374
|
/**
|
|
1345
1375
|
* Read access to the declared-org store, narrowed to the one query
|
|
1346
1376
|
* `cloudflareZone` needs for its cross-org refusal check (#131) -- see that
|
|
@@ -1560,6 +1590,20 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
1560
1590
|
private findRecreatedApp;
|
|
1561
1591
|
private ensureZitadelProject;
|
|
1562
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
|
+
*/
|
|
1563
1607
|
private resolveServer;
|
|
1564
1608
|
private coolifyApp;
|
|
1565
1609
|
/**
|
|
@@ -1636,6 +1680,13 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
1636
1680
|
* provisioned, where this one is unconditional (#239).
|
|
1637
1681
|
*/
|
|
1638
1682
|
private pushAppEnv;
|
|
1683
|
+
/**
|
|
1684
|
+
* The org's shared secret `name`: read from the held keys, else generated
|
|
1685
|
+
* and held first, so a crash after the `put` and before the env write
|
|
1686
|
+
* hands the same value out on the next apply. Only called when `put` exists.
|
|
1687
|
+
* An error here names the ref, never a value.
|
|
1688
|
+
*/
|
|
1689
|
+
private ensureSharedSecret;
|
|
1639
1690
|
/**
|
|
1640
1691
|
* F5: the app's `AUTH_APP_KEY`, minted once and only when the app has none
|
|
1641
1692
|
* of at least 32 characters (the broker refuses a shorter one). `null` once
|
|
@@ -1897,6 +1948,10 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
1897
1948
|
* `coolifyApp`'s own analogous gap (it never restarted a found-but-stopped
|
|
1898
1949
|
* app either) has since closed the same way, inline in that method (#130);
|
|
1899
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.
|
|
1900
1955
|
*/
|
|
1901
1956
|
private findOrCreateCmsApp;
|
|
1902
1957
|
/**
|
|
@@ -2050,6 +2105,19 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
2050
2105
|
* pushed once calls are on and this org's calls service app carries its
|
|
2051
2106
|
* internal name (`desiredAgoraEnv` reads that marker from the recorded ids,
|
|
2052
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.
|
|
2053
2121
|
*/
|
|
2054
2122
|
private coolifyAgora;
|
|
2055
2123
|
/**
|
|
@@ -2354,17 +2422,31 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
2354
2422
|
*/
|
|
2355
2423
|
private ensureLettermintDmarcRecord;
|
|
2356
2424
|
/**
|
|
2357
|
-
* #80: provisions the org's own organisation on Files
|
|
2358
|
-
*
|
|
2359
|
-
*
|
|
2360
|
-
*
|
|
2361
|
-
*
|
|
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.
|
|
2430
|
+
*
|
|
2431
|
+
* F6b: `action.desired.shareHost` (`diff.ts`'s `planFilesOrganisation`) is
|
|
2432
|
+
* passed through every time, even though `entry-files-key.ts` reports the
|
|
2433
|
+
* route itself as blocked until the platform's files host can serve
|
|
2434
|
+
* `share.<domain>` -- this is the one place the name reaches files at all,
|
|
2435
|
+
* so files can act on it the moment its own route exists.
|
|
2362
2436
|
*
|
|
2363
2437
|
* #273: also ensures the org's Agora origin is on the files host's CORS
|
|
2364
2438
|
* allowlist (`FilesOrganisationPort.ensureAllowedOrigin`), the same
|
|
2365
2439
|
* repeat-is-a-no-op shape as `provisionOrganisation` itself -- every org
|
|
2366
2440
|
* gets an Agora (#164), so `diff.ts`'s `planFilesOrganisation` always sets
|
|
2367
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.
|
|
2368
2450
|
*/
|
|
2369
2451
|
private filesOrganisation;
|
|
2370
2452
|
/**
|
|
@@ -2375,7 +2457,6 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
2375
2457
|
* that fails revokes the key again instead of leaving a live key nobody holds.
|
|
2376
2458
|
*/
|
|
2377
2459
|
private deliverFilesAgoraKey;
|
|
2378
|
-
private filesStorage;
|
|
2379
2460
|
/**
|
|
2380
2461
|
* #80: provisions the org's own organisation on AI and switches its AI use
|
|
2381
2462
|
* on, before {@link aiBudget} can set its own spend limit. Both
|