@wtfalch/foundry 0.34.0 → 0.35.2
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/bootstrap/bootstrap.d.ts +1 -1
- package/dist/bootstrap/bootstrap.js +49 -11
- package/dist/bootstrap/declare.d.ts +12 -5
- package/dist/bootstrap/declare.js +33 -18
- package/dist/bootstrap/versions.d.ts +20 -0
- package/dist/bootstrap/versions.js +46 -0
- package/dist/calls-sfu.js +3 -3
- package/dist/index.d.ts +9 -4
- package/dist/index.js +5 -2
- package/dist/migrations/0053_heartbeats_provider.sql +9 -0
- package/dist/migrations/0053_org_version_pin.sql +6 -0
- package/dist/org.d.ts +60 -14
- package/dist/org.js +118 -28
- package/dist/plan/backup-gate.d.ts +93 -0
- package/dist/plan/backup-gate.js +261 -0
- package/dist/plan/broker-entries.d.ts +9 -1
- package/dist/plan/broker-entries.js +20 -3
- package/dist/plan/build-record.d.ts +56 -0
- package/dist/plan/build-record.js +109 -0
- package/dist/plan/calls-matrix.js +3 -3
- package/dist/plan/cloudflared-connector.js +2 -2
- package/dist/plan/company-backups.d.ts +31 -0
- package/dist/plan/company-backups.js +101 -0
- package/dist/plan/deploy-health.d.ts +12 -2
- package/dist/plan/deploy-health.js +3 -1
- package/dist/plan/destinations.d.ts +73 -0
- package/dist/plan/destinations.js +217 -0
- package/dist/plan/diff.d.ts +17 -8
- package/dist/plan/diff.js +131 -131
- package/dist/plan/edge-access.d.ts +15 -0
- package/dist/plan/edge-access.js +21 -2
- package/dist/plan/executor.d.ts +166 -7
- package/dist/plan/executor.js +547 -106
- package/dist/plan/health-targets.d.ts +1 -3
- package/dist/plan/health-targets.js +36 -36
- package/dist/plan/held-key-refs.d.ts +5 -0
- package/dist/plan/held-key-refs.js +5 -0
- package/dist/plan/hostnames.d.ts +10 -0
- package/dist/plan/hostnames.js +14 -0
- package/dist/plan/index.d.ts +5 -0
- package/dist/plan/index.js +3 -0
- package/dist/plan/live.d.ts +6 -0
- package/dist/plan/live.js +3 -2
- package/dist/plan/locked-hostnames.d.ts +2 -1
- package/dist/plan/locked-hostnames.js +16 -3
- package/dist/plan/login-host.d.ts +9 -20
- package/dist/plan/login-host.js +10 -25
- package/dist/plan/mail-relay.d.ts +48 -29
- package/dist/plan/mail-relay.js +145 -68
- package/dist/plan/network-move.d.ts +20 -0
- package/dist/plan/network-move.js +41 -0
- package/dist/plan/oikos-ingress.d.ts +111 -0
- package/dist/plan/oikos-ingress.js +231 -0
- package/dist/plan/org-names.d.ts +8 -2
- package/dist/plan/org-names.js +57 -1
- package/dist/plan/own-diff.d.ts +9 -8
- package/dist/plan/own-diff.js +42 -34
- package/dist/plan/own-hostnames.d.ts +27 -0
- package/dist/plan/own-hostnames.js +24 -0
- package/dist/plan/own-limits.d.ts +198 -7
- package/dist/plan/own-limits.js +163 -32
- package/dist/plan/own-services.js +3 -1
- package/dist/plan/own-sfu.js +3 -2
- package/dist/plan/plan-apply.d.ts +47 -7
- package/dist/plan/plan-apply.js +184 -38
- package/dist/plan/platform-diff.d.ts +133 -17
- package/dist/plan/platform-diff.js +231 -68
- package/dist/plan/platform-org.d.ts +79 -10
- package/dist/plan/platform-org.js +93 -13
- package/dist/plan/platform-providers.d.ts +118 -73
- package/dist/plan/platform-providers.js +799 -241
- package/dist/plan/proxy-labels.d.ts +57 -11
- package/dist/plan/proxy-labels.js +94 -14
- package/dist/plan/run-options.d.ts +19 -0
- package/dist/plan/run-options.js +46 -0
- package/dist/plan/zitadel-login-policy.d.ts +1 -1
- package/dist/plan/zitadel-login-policy.js +76 -8
- package/dist/platform.d.ts +32 -0
- package/dist/platform.js +16 -0
- package/dist/provision.d.ts +2 -0
- package/dist/provision.js +3 -1
- package/dist/slug.d.ts +3 -1
- package/dist/slug.js +25 -3
- package/dist/store/postgres.js +43 -1
- package/dist/store/schema.d.ts +36 -0
- package/dist/store/schema.js +4 -0
- package/package.json +3 -3
- package/versions.digests.json +11 -0
package/dist/plan/edge-access.js
CHANGED
|
@@ -31,6 +31,7 @@ export function createEdgeAccess(client, options = {}) {
|
|
|
31
31
|
adopt: (input) => retrying(() => client.adopt(input)),
|
|
32
32
|
readiness: () => retrying(() => client.readiness()),
|
|
33
33
|
ensureProvider: (input) => retrying(() => client.ensureProvider(input)),
|
|
34
|
+
oneTimePinProvider: () => retrying(() => client.oneTimePinProvider()),
|
|
34
35
|
createGate: (input) => retrying(() => client.createGate(input)),
|
|
35
36
|
replaceGateHostnames: (id, input) => retrying(() => client.replaceGateHostnames(id, input)),
|
|
36
37
|
deleteGate: (id) => retrying(() => client.deleteGate(id)),
|
|
@@ -80,13 +81,27 @@ export function createEdgeAccess(client, options = {}) {
|
|
|
80
81
|
const listAccessApps = async () => {
|
|
81
82
|
const { apps } = await access.list();
|
|
82
83
|
remember(apps);
|
|
83
|
-
return apps.map((a) => ({
|
|
84
|
+
return apps.map((a) => ({
|
|
85
|
+
id: a.id,
|
|
86
|
+
name: a.name,
|
|
87
|
+
domain: a.domain,
|
|
88
|
+
allowedIdps: a.allowedIdps,
|
|
89
|
+
autoRedirectToIdentity: a.autoRedirectToIdentity,
|
|
90
|
+
}));
|
|
84
91
|
};
|
|
85
92
|
return {
|
|
86
93
|
listAccessApps,
|
|
87
94
|
async createAccessApp(app) {
|
|
88
95
|
try {
|
|
89
|
-
const created = await writeSlot(() => access.create({
|
|
96
|
+
const created = await writeSlot(() => access.create({
|
|
97
|
+
name: app.name,
|
|
98
|
+
domain: app.domain,
|
|
99
|
+
type: app.type,
|
|
100
|
+
...(app.allowedIdps === undefined ? {} : { allowedIdps: app.allowedIdps }),
|
|
101
|
+
...(app.autoRedirectToIdentity === undefined
|
|
102
|
+
? {}
|
|
103
|
+
: { autoRedirectToIdentity: app.autoRedirectToIdentity }),
|
|
104
|
+
}));
|
|
90
105
|
return { id: created.id };
|
|
91
106
|
}
|
|
92
107
|
catch (error) {
|
|
@@ -155,6 +170,10 @@ export function createEdgeAccess(client, options = {}) {
|
|
|
155
170
|
const { authDomain } = await access.readiness();
|
|
156
171
|
return { authDomain };
|
|
157
172
|
},
|
|
173
|
+
async ensureOneTimePinProvider() {
|
|
174
|
+
const { id } = await access.oneTimePinProvider();
|
|
175
|
+
return { id };
|
|
176
|
+
},
|
|
158
177
|
async ensureProvider(input) {
|
|
159
178
|
const { id } = await writeSlot(() => access.ensureProvider(input));
|
|
160
179
|
return { id };
|
package/dist/plan/executor.d.ts
CHANGED
|
@@ -54,6 +54,8 @@ export interface CoolifyPort {
|
|
|
54
54
|
*/
|
|
55
55
|
listResources?(projectUuid: string): Promise<Array<{
|
|
56
56
|
kind: string;
|
|
57
|
+
key?: string;
|
|
58
|
+
config?: Record<string, unknown>;
|
|
57
59
|
}>>;
|
|
58
60
|
findOrCreateEnvironment(projectUuid: string, name: string): Promise<{
|
|
59
61
|
environment: {
|
|
@@ -111,10 +113,16 @@ export interface CoolifyPort {
|
|
|
111
113
|
/** Coolify's own record of the resource limits (`plan/own-limits.ts`). */
|
|
112
114
|
limits_memory?: string;
|
|
113
115
|
limits_cpus?: string;
|
|
116
|
+
git_repository?: string;
|
|
117
|
+
is_auto_deploy_enabled?: boolean;
|
|
118
|
+
/** Coolify's record of the run options, where the capability options live (`plan/run-options.ts`). */
|
|
119
|
+
custom_docker_run_options?: string | null;
|
|
114
120
|
}>;
|
|
115
121
|
createGithubAppApplication(input: {
|
|
116
122
|
project_uuid: string;
|
|
117
123
|
server_uuid: string;
|
|
124
|
+
/** The Docker network the app joins (`plan/destinations.ts`); absent: the server's default. */
|
|
125
|
+
destination_uuid?: string;
|
|
118
126
|
environment_name: string;
|
|
119
127
|
environment_uuid: string;
|
|
120
128
|
github_app_uuid: string;
|
|
@@ -125,6 +133,8 @@ export interface CoolifyPort {
|
|
|
125
133
|
domains?: string;
|
|
126
134
|
/** Selects which of two Dockerfiles in one repo to build (`cmsSite`'s own site/cms apps). */
|
|
127
135
|
dockerfile_location?: string;
|
|
136
|
+
/** Extra `docker run` options; the capability options are added by `plan/own-limits.ts`. */
|
|
137
|
+
custom_docker_run_options?: string;
|
|
128
138
|
/** The port the app listens on (`HostingEntry.port`). */
|
|
129
139
|
ports_exposes?: string;
|
|
130
140
|
/** `false` for an internal entry: Coolify makes no domain for it. */
|
|
@@ -142,6 +152,7 @@ export interface CoolifyPort {
|
|
|
142
152
|
createPostgresDatabase(input: {
|
|
143
153
|
project_uuid: string;
|
|
144
154
|
server_uuid: string;
|
|
155
|
+
destination_uuid?: string;
|
|
145
156
|
environment_name: string;
|
|
146
157
|
environment_uuid: string;
|
|
147
158
|
name: string;
|
|
@@ -223,6 +234,16 @@ export interface CoolifyPort {
|
|
|
223
234
|
deleteEnv(applicationUuid: string, envUuid: string): Promise<unknown>;
|
|
224
235
|
/** Escape hatch (`CoolifyClient.raw`) — used for stop/start, which have no typed method yet. */
|
|
225
236
|
raw(method: string, path: string, body?: unknown): Promise<unknown>;
|
|
237
|
+
/**
|
|
238
|
+
* F6: the dumps one scheduled backup has run, newest first. A host may wrap
|
|
239
|
+
* `raw('GET', '/databases/{uuid}/backups/{backup}/executions')`; absent, the
|
|
240
|
+
* backup gate (`backup-gate.ts`) makes that call through `raw` itself.
|
|
241
|
+
*/
|
|
242
|
+
listDatabaseBackupExecutions?(databaseUuid: string, backupUuid: string): Promise<Array<{
|
|
243
|
+
uuid: string;
|
|
244
|
+
status: string;
|
|
245
|
+
created_at: string;
|
|
246
|
+
}>>;
|
|
226
247
|
/**
|
|
227
248
|
* Persistent (named volume) and file storages already attached to an
|
|
228
249
|
* application (#75) — `ensureLogVolume` reads this before creating one, so
|
|
@@ -263,6 +284,7 @@ export interface CoolifyPort {
|
|
|
263
284
|
createDockerImageApplication(input: {
|
|
264
285
|
project_uuid: string;
|
|
265
286
|
server_uuid: string;
|
|
287
|
+
destination_uuid?: string;
|
|
266
288
|
environment_name: string;
|
|
267
289
|
environment_uuid: string;
|
|
268
290
|
docker_registry_image_name: string;
|
|
@@ -294,12 +316,14 @@ export interface CoolifyPort {
|
|
|
294
316
|
createDockerfileApplication(input: {
|
|
295
317
|
project_uuid: string;
|
|
296
318
|
server_uuid: string;
|
|
319
|
+
destination_uuid?: string;
|
|
297
320
|
environment_name: string;
|
|
298
321
|
environment_uuid: string;
|
|
299
322
|
dockerfile: string;
|
|
300
323
|
name?: string;
|
|
301
324
|
description?: string;
|
|
302
325
|
instant_deploy?: boolean;
|
|
326
|
+
custom_docker_run_options?: string;
|
|
303
327
|
}): Promise<{
|
|
304
328
|
uuid: string;
|
|
305
329
|
}>;
|
|
@@ -431,6 +455,17 @@ export interface CoolifyPort {
|
|
|
431
455
|
getDeployment(deploymentUuid: string): Promise<{
|
|
432
456
|
status: string;
|
|
433
457
|
}>;
|
|
458
|
+
/**
|
|
459
|
+
* An application's deployment history, newest first -- matches
|
|
460
|
+
* `CoolifyClient.listApplicationDeployments`. `build-record.ts` finds the
|
|
461
|
+
* deployment a deploy started by its uuid and records its commit. Optional:
|
|
462
|
+
* a port without it records no built commit.
|
|
463
|
+
*/
|
|
464
|
+
listApplicationDeployments?(uuid: string, take?: number): Promise<Array<{
|
|
465
|
+
deployment_uuid: string;
|
|
466
|
+
commit?: string;
|
|
467
|
+
status: string;
|
|
468
|
+
}>>;
|
|
434
469
|
}
|
|
435
470
|
/**
|
|
436
471
|
* The Cloudflare zone calls the platform steps make directly, shaped to match
|
|
@@ -939,6 +974,21 @@ export interface ZitadelPort {
|
|
|
939
974
|
closeSelfRegistration(orgId: string): Promise<{
|
|
940
975
|
changed: boolean;
|
|
941
976
|
}>;
|
|
977
|
+
/**
|
|
978
|
+
* Makes the org require a second factor at sign-in: `forceMfa` on, no
|
|
979
|
+
* registration, no external identity provider, username and password kept
|
|
980
|
+
* (the invite and a password reset need them), passkeys allowed, and
|
|
981
|
+
* `mfaInitSkipLifetime` zero so enrolment cannot be skipped. The second
|
|
982
|
+
* factors are an authenticator app and a security key, the multi factor a
|
|
983
|
+
* user-verified passkey; every other factor (email or SMS code) is removed.
|
|
984
|
+
* An org on the instance default gets its own policy. Idempotent: a policy
|
|
985
|
+
* already so set is no write. A failure halfway is repaired by a repeat,
|
|
986
|
+
* which reads the policy again. `zitadel-login-policy.ts` is the real
|
|
987
|
+
* implementation.
|
|
988
|
+
*/
|
|
989
|
+
enforceSecondFactor(orgId: string): Promise<{
|
|
990
|
+
changed: boolean;
|
|
991
|
+
}>;
|
|
942
992
|
/** Grants another ZITADEL org access to a project (plan gap A9). Idempotent. */
|
|
943
993
|
findOrCreateProjectGrant(orgId: string, projectId: string, grantedOrgId: string): Promise<{
|
|
944
994
|
created: boolean;
|
|
@@ -1596,7 +1646,7 @@ export interface FoundryStepExecutorPorts {
|
|
|
1596
1646
|
deliverSecret(ref: string, secret: string): Promise<void>;
|
|
1597
1647
|
/**
|
|
1598
1648
|
* Archon's held keys, for an entry env from `sharedSecret` (read, else
|
|
1599
|
-
* generate and `put`)
|
|
1649
|
+
* generate and `put`). Optional: without
|
|
1600
1650
|
* it, or without `put`, such an env is omitted and the plan reports it
|
|
1601
1651
|
* blocked. A value goes to the entry's env and nowhere else.
|
|
1602
1652
|
*/
|
|
@@ -1612,6 +1662,27 @@ export interface FoundryStepExecutorPorts {
|
|
|
1612
1662
|
* passes the same store instance it constructs `FoundryPlanApply` with.
|
|
1613
1663
|
*/
|
|
1614
1664
|
declaredOrgStore: Pick<DeclaredOrgStore, 'findOrgIdForZone'>;
|
|
1665
|
+
/**
|
|
1666
|
+
* The `<host>:<port>` the shared mail relay dials for a company's mail server, given the Coolify
|
|
1667
|
+
* server's address and the host port the server publishes. Absent: `<server address>:<port>`. A
|
|
1668
|
+
* host whose containers cannot reach the server by its address (the local stack, where it is a
|
|
1669
|
+
* loopback address) supplies its own. The answer is checked like any relay target
|
|
1670
|
+
* (`normalizeMailTarget`): a host name or an IPv4 address and a port, nothing else.
|
|
1671
|
+
*/
|
|
1672
|
+
mailRelayTarget?(input: {
|
|
1673
|
+
serverAddress: string | undefined;
|
|
1674
|
+
port: number;
|
|
1675
|
+
}): string;
|
|
1676
|
+
/**
|
|
1677
|
+
* The address of the server's Docker bridge gateway (an IPv4 address, `172.17.0.1` unless the
|
|
1678
|
+
* daemon's `bip` says otherwise). With it a company's Stalwart publishes SMTP as
|
|
1679
|
+
* `<address>:<port>:25`, which Coolify 4.3.23 passes to Docker unchanged, so the port is reachable
|
|
1680
|
+
* from containers on the server but not on the server's public address; the relay is given
|
|
1681
|
+
* `<address>:<port>` unless `mailRelayTarget` says otherwise. Absent: `<port>:25` on every interface,
|
|
1682
|
+
* and the host firewall must close the range (`docs/runbooks/network-move.md`). The local stack
|
|
1683
|
+
* leaves it unset.
|
|
1684
|
+
*/
|
|
1685
|
+
mailBindAddress?: string;
|
|
1615
1686
|
/**
|
|
1616
1687
|
* #543: clock, sleep and `fetch` for the health-check wait every company
|
|
1617
1688
|
* app's own redeploy now goes through (`deploy-health.ts`'s
|
|
@@ -1638,9 +1709,8 @@ export declare class NotBuiltError extends Error {
|
|
|
1638
1709
|
* `cms.<domain>` -- the cms studio's own hostname (`cmsSite` below), apart
|
|
1639
1710
|
* from the public site itself at `org.domain` (used directly there). Called
|
|
1640
1711
|
* from `cmsSite` and from `zitadelApp` for the fixed `cms` client (#139),
|
|
1641
|
-
* both of which only run once `org.site.enabled` is true
|
|
1642
|
-
*
|
|
1643
|
-
* {@link tunnelIngressHostnames}'s own doc comment cites.
|
|
1712
|
+
* both of which only run once `org.site.enabled` is true. A company without
|
|
1713
|
+
* a domain has its studio at `<slug>-cms.oikos.host` (`cmsStudioHostnameFor`).
|
|
1644
1714
|
*/
|
|
1645
1715
|
export declare function cmsHostnameFor(org: DeclaredOrg): string;
|
|
1646
1716
|
/**
|
|
@@ -1663,8 +1733,24 @@ export declare function callsHostnameFor(org: DeclaredOrg): string;
|
|
|
1663
1733
|
* this file's hostname rules.
|
|
1664
1734
|
*/
|
|
1665
1735
|
export declare function healthUrls(org: DeclaredOrg): string[];
|
|
1736
|
+
/**
|
|
1737
|
+
* Every app on the Coolify box shares one Traefik reverse proxy, and Coolify
|
|
1738
|
+
* itself points that proxy's routing at whatever `domains` an application
|
|
1739
|
+
* declares (`coolifyApp`'s `appHostname(org)`) -- so a tunnel's ingress only
|
|
1740
|
+
* has to reach the proxy, never a specific app container.
|
|
1741
|
+
* `wtfalch/app-template`'s bootstrap (`bootstrap/steps/cf-tunnel.ts`, prior
|
|
1742
|
+
* art for the exact org this file's `cloudflareTunnel` implements, cited by
|
|
1743
|
+
* https://github.com/wtfalch/foundry/issues/71) names this same constant and
|
|
1744
|
+
* value.
|
|
1745
|
+
*/
|
|
1746
|
+
export declare const COOLIFY_PROXY_ORIGIN = "http://coolify-proxy:80";
|
|
1666
1747
|
/** The one Access policy foundry puts on a platform Access app (#84). */
|
|
1667
1748
|
export declare const ACCESS_POLICY_NAME = "foundry: allowed emails";
|
|
1749
|
+
export declare const LOG_DIR = "/app/logs";
|
|
1750
|
+
/** The company's Coolify destination (its Docker network `co-<slug>`), recorded when its first resource is created. */
|
|
1751
|
+
export declare const COOLIFY_DESTINATION_SCOPE_KEY = "coolify_destination";
|
|
1752
|
+
export declare const CHAT_REKEY_SYNAPSE_DB_SCOPE_KEY = "coolify_chat_rekey_synapse_database";
|
|
1753
|
+
export declare const CHAT_REKEY_MAS_DB_SCOPE_KEY = "coolify_chat_rekey_mas_database";
|
|
1668
1754
|
/**
|
|
1669
1755
|
* Whether an application's own Coolify `status` (`` `running:healthy`,
|
|
1670
1756
|
* `exited:unhealthy` `` -- `@wtfalch/providers`' own doc comment) means it is
|
|
@@ -1705,7 +1791,6 @@ export declare const databaseStartWait: {
|
|
|
1705
1791
|
graceMs: number;
|
|
1706
1792
|
};
|
|
1707
1793
|
export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer {
|
|
1708
|
-
private readonly ports;
|
|
1709
1794
|
private edgeDns;
|
|
1710
1795
|
private edgeTunnels;
|
|
1711
1796
|
private edgeAccess;
|
|
@@ -1714,6 +1799,8 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
1714
1799
|
private edgeWriteSlot;
|
|
1715
1800
|
/** Secrets this executor minted or was handed; see `StepExecutor.secretsHandled`. */
|
|
1716
1801
|
private readonly handledSecrets;
|
|
1802
|
+
private readonly ports;
|
|
1803
|
+
private get rawCoolify();
|
|
1717
1804
|
constructor(ports: FoundryStepExecutorPorts);
|
|
1718
1805
|
secretsHandled(): readonly string[];
|
|
1719
1806
|
/**
|
|
@@ -1736,12 +1823,26 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
1736
1823
|
}>;
|
|
1737
1824
|
/** Whether the host's scoped ports for this own org include a files-organisation port. A held key still missing counts as no port. */
|
|
1738
1825
|
ownFilesOrganisationPort(org: DeclaredOrg, recordedIds: Readonly<Record<string, string>>): Promise<boolean>;
|
|
1826
|
+
/** Whether the host's scoped ports for this own org include a broker port: the company's own broker, which its broker entries are written to. */
|
|
1827
|
+
ownBrokerPort(org: DeclaredOrg, recordedIds: Readonly<Record<string, string>>): Promise<boolean>;
|
|
1739
1828
|
/** #555: the edge-routed ports this executor was built with itself (they win over edge). */
|
|
1740
1829
|
ownEdgePorts(): Partial<Record<EdgePortName, boolean>>;
|
|
1741
1830
|
execute(action: StepAction, context: StepExecutionContext): Promise<{
|
|
1742
1831
|
resourceId?: string;
|
|
1743
1832
|
} | undefined>;
|
|
1744
1833
|
private run;
|
|
1834
|
+
/**
|
|
1835
|
+
* The company's destination on `serverUuid`: its Docker network `co-<slug>`, made when absent and
|
|
1836
|
+
* recorded as {@link COOLIFY_DESTINATION_SCOPE_KEY}. Called before the first create of a step;
|
|
1837
|
+
* a server that already holds too many networks fails here (`DestinationCapacityError`), before
|
|
1838
|
+
* the destination or the resource exists. A crash after the destination is made and before it is
|
|
1839
|
+
* recorded leaves a destination the next run finds by its network name, so a re-run converges.
|
|
1840
|
+
* Each Coolify call has a 60 second timeout (`destinations.ts`).
|
|
1841
|
+
*/
|
|
1842
|
+
private companyDestination;
|
|
1843
|
+
/** `coolify` for an own-services step: its creates go to the company's destination. */
|
|
1844
|
+
private placedForCompany;
|
|
1845
|
+
private dispatch;
|
|
1745
1846
|
/**
|
|
1746
1847
|
* `plan/diff.ts`'s `planAccess` (#246): puts a `hosting.access` rule's
|
|
1747
1848
|
* hostname behind a Cloudflare Access app named
|
|
@@ -1965,6 +2066,17 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
1965
2066
|
private findRecreatedApp;
|
|
1966
2067
|
private ensureZitadelProject;
|
|
1967
2068
|
private ensureCoolifyProject;
|
|
2069
|
+
/**
|
|
2070
|
+
* `plan/network-move.ts`'s `planNetworkMove`: a company built on the shared network is moved to its
|
|
2071
|
+
* own. Coolify cannot move a resource in production, so every application and database in the
|
|
2072
|
+
* company's project that foundry did not adopt is deleted, applications first, and the ids recorded
|
|
2073
|
+
* for them are forgotten; the next apply builds them again on `co-<slug>`. Apply has already asked
|
|
2074
|
+
* for the typed company name and checked a fresh backup of every database. A failure part way
|
|
2075
|
+
* leaves what is left recorded and the marker unset, so the same step is planned again and goes on
|
|
2076
|
+
* from there (a 404 counts as deleted). The marker is recorded last. No new timeout: each delete
|
|
2077
|
+
* has the Coolify port's own.
|
|
2078
|
+
*/
|
|
2079
|
+
private coolifyNetwork;
|
|
1968
2080
|
/**
|
|
1969
2081
|
* #445: one company lands on one Coolify server. The first call for an
|
|
1970
2082
|
* org picks a usable, reachable server and records it
|
|
@@ -2003,6 +2115,15 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
2003
2115
|
* one).
|
|
2004
2116
|
*/
|
|
2005
2117
|
private ensureLogVolume;
|
|
2118
|
+
/**
|
|
2119
|
+
* F6: a nightly dump of one of the company's databases to the platform's
|
|
2120
|
+
* backup bucket. The schedule is found before it is created
|
|
2121
|
+
* (`provisionDatabaseBackup`), so a run that died after the create and
|
|
2122
|
+
* before `backup_<db>` was recorded reuses the schedule on the next apply
|
|
2123
|
+
* instead of adding a second. The error carries the database's name, never
|
|
2124
|
+
* the connection URL or a response body.
|
|
2125
|
+
*/
|
|
2126
|
+
private coolifyBackup;
|
|
2006
2127
|
private coolifyDatabase;
|
|
2007
2128
|
/**
|
|
2008
2129
|
* Pushes the database's connection string into the app's environment,
|
|
@@ -2055,6 +2176,19 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
2055
2176
|
* provisioned, where this one is unconditional (#239).
|
|
2056
2177
|
*/
|
|
2057
2178
|
private pushAppEnv;
|
|
2179
|
+
/**
|
|
2180
|
+
* The install's edge label token: read from the held keys, else minted and held first, so a crash
|
|
2181
|
+
* after the `put` hands the same value out on the next apply. Read once more after the `put`, so two
|
|
2182
|
+
* runs that mint at the same moment end on the value that was held last. An error names the ref,
|
|
2183
|
+
* never a value.
|
|
2184
|
+
*/
|
|
2185
|
+
private edgeLabelToken;
|
|
2186
|
+
/**
|
|
2187
|
+
* The `custom_labels` patch of an app foundry routes through Traefik at `hostname`: the same http
|
|
2188
|
+
* router a `domains` entry gets, plus the edge token. Coolify uses these instead of the labels it
|
|
2189
|
+
* generates from `domains`. The router names use the app's own name, which is unique per company.
|
|
2190
|
+
*/
|
|
2191
|
+
private routedLabels;
|
|
2058
2192
|
/**
|
|
2059
2193
|
* The org's shared secret `name`: read from the held keys, else generated
|
|
2060
2194
|
* and held first, so a crash after the `put` and before the env write
|
|
@@ -2779,8 +2913,9 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
2779
2913
|
private ownAuth;
|
|
2780
2914
|
/**
|
|
2781
2915
|
* `plan/own-diff.ts`'s `planOwnMail`: the org's own Stalwart in the org's own
|
|
2782
|
-
* project,
|
|
2783
|
-
*
|
|
2916
|
+
* project, publishing its port 25 on one host port of the server (the shared
|
|
2917
|
+
* relay is on another network and dials the server's address) and a directory
|
|
2918
|
+
* that trusts the org's own sign-in. The admin key goes to
|
|
2784
2919
|
* `orgTarget(org).refs.mailAdminKey` and nowhere else. The address the relay
|
|
2785
2920
|
* routes to is recorded last, and the step's marker after it.
|
|
2786
2921
|
*/
|
|
@@ -2795,6 +2930,17 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
2795
2930
|
/** `deliverSecret`, tried up to {@link JOBS_DELIVERY_ATTEMPTS} times; true once one attempt succeeds. */
|
|
2796
2931
|
private deliverWithRetry;
|
|
2797
2932
|
private cloudflareTunnel;
|
|
2933
|
+
/**
|
|
2934
|
+
* The entry names a company has in the platform's `oikos.host` zone (a company with no domain of its own):
|
|
2935
|
+
* one proxied CNAME each, to this company's tunnel, which routes them straight to the entry container. A
|
|
2936
|
+
* specific record beats the shared `*.oikos.host` wildcard, so the shared ingress stops carrying the name
|
|
2937
|
+
* without being edited. The company writes only its own `<slug>.oikos.host` ({@link ownsOikosName}); an
|
|
2938
|
+
* A or AAAA record, or a CNAME that points anywhere but this tunnel, an earlier id of it or the shared
|
|
2939
|
+
* wildcard's target, blocks the step. A name the company no longer declares has its record deleted when
|
|
2940
|
+
* it still points at this tunnel. The names are recorded only after every record is in place, so a failure
|
|
2941
|
+
* halfway is planned again.
|
|
2942
|
+
*/
|
|
2943
|
+
private publishOikosEntryRecords;
|
|
2798
2944
|
/**
|
|
2799
2945
|
* #236: when this tunnel's DNS was last published under a domain that
|
|
2800
2946
|
* differs from the one `org` now declares, deletes every CNAME in the
|
|
@@ -3007,6 +3153,19 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
|
|
|
3007
3153
|
* publishes it.
|
|
3008
3154
|
*/
|
|
3009
3155
|
private publishMailDnsRecords;
|
|
3156
|
+
/**
|
|
3157
|
+
* A company without a domain keeps its web address at `<slug>.oikos.host`,
|
|
3158
|
+
* which only the shared `*.oikos.host` wildcard answers. A wildcard applies
|
|
3159
|
+
* only to a name that holds no record of its own, so the MX and TXT records
|
|
3160
|
+
* of the company's mail domain on that same name would take the web address
|
|
3161
|
+
* away. This writes the name's own proxied CNAME, to wherever the wildcard
|
|
3162
|
+
* points, before any mail record. Found by name and type, so a rerun after a
|
|
3163
|
+
* half-finished apply never doubles it. Cloudflare lists only A, AAAA and
|
|
3164
|
+
* CNAME as clashing with a CNAME, so MX and TXT sit beside it.
|
|
3165
|
+
* https://developers.cloudflare.com/dns/manage-dns-records/reference/wildcard-dns-records/
|
|
3166
|
+
* https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/records-with-same-name/
|
|
3167
|
+
*/
|
|
3168
|
+
private ensureOwnWebAddressRecord;
|
|
3010
3169
|
/**
|
|
3011
3170
|
* Creates or updates one mail record (Stalwart's or Lettermint's).
|
|
3012
3171
|
*
|