@wtfalch/foundry 0.16.0 → 0.16.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.
@@ -26,9 +26,9 @@ export declare const mintChatMatrixSecrets: typeof mintCallsMatrixSecrets;
26
26
  /** The chat repo: the Synapse module and the chat service are both built from it. */
27
27
  export declare const CHAT_REPO = "wtfalch/chat";
28
28
  /** Synapse plus the `wtfalch_chat_gate` module; built from the repo root. */
29
- export declare const CHAT_SYNAPSE_DOCKERFILE = "apps/chat-service/synapse-module/Dockerfile";
29
+ export declare const CHAT_SYNAPSE_DOCKERFILE = "/apps/chat-service/synapse-module/Dockerfile";
30
30
  /** The chat service, built from the repo root (that Dockerfile's own top comment). */
31
- export declare const CHAT_SERVICE_DOCKERFILE = "apps/chat-service/Dockerfile";
31
+ export declare const CHAT_SERVICE_DOCKERFILE = "/apps/chat-service/Dockerfile";
32
32
  export declare const CHAT_SYNAPSE_PORT = "8008";
33
33
  export declare const CHAT_MAS_PORT = "8080";
34
34
  export declare const CHAT_SERVICE_PORT = "8080";
@@ -3,9 +3,9 @@ export const mintChatMatrixSecrets = mintCallsMatrixSecrets;
3
3
  /** The chat repo: the Synapse module and the chat service are both built from it. */
4
4
  export const CHAT_REPO = 'wtfalch/chat';
5
5
  /** Synapse plus the `wtfalch_chat_gate` module; built from the repo root. */
6
- export const CHAT_SYNAPSE_DOCKERFILE = 'apps/chat-service/synapse-module/Dockerfile';
6
+ export const CHAT_SYNAPSE_DOCKERFILE = '/apps/chat-service/synapse-module/Dockerfile';
7
7
  /** The chat service, built from the repo root (that Dockerfile's own top comment). */
8
- export const CHAT_SERVICE_DOCKERFILE = 'apps/chat-service/Dockerfile';
8
+ export const CHAT_SERVICE_DOCKERFILE = '/apps/chat-service/Dockerfile';
9
9
  export const CHAT_SYNAPSE_PORT = '8008';
10
10
  export const CHAT_MAS_PORT = '8080';
11
11
  export const CHAT_SERVICE_PORT = '8080';
@@ -9,7 +9,7 @@ import { CHAT_REPO, CHAT_SERVICE_DOCKERFILE, CHAT_SERVICE_PORT, CHAT_SYNAPSE_DOC
9
9
  import { ensureCloudflaredConnector } from './cloudflared-connector.js';
10
10
  import { AI_ENTRY_RENEW_WINDOW_DAYS, entryAiAppliedScopeKey, entryAiClampedScopeKey, entryAiExpiresScopeKey, entryAiPendingExpiresScopeKey, entryAiRetiredScopeKey, entryAiUndeliveredScopeKey, entryAiUnrevokedScopeKey, entryAiWebhookPendingScopeKey, entryAiWrittenScopeKey, parseIdList, } from './entry-ai-key.js';
11
11
  import { FILES_AGORA_KEY_SCOPE_KEY, FILES_AGORA_UNDELIVERED_SCOPE_KEY, FILES_KEY_DAYS, FILES_KEY_RENEW_WINDOW_DAYS, FILES_ORG_OWNER_SCOPE_KEY, FILES_ROOT_EXPIRES_SCOPE_KEY, FILES_ROOT_PREVIOUS_SCOPE_KEY, FILES_ROOT_UNDELIVERED_SCOPE_KEY, FILES_ROOT_UNREVOKED_SCOPE_KEY, entryFilesAppliedScopeKey, entryFilesExpiresScopeKey, entryFilesMinterScopeKey, entryFilesPendingExpiresScopeKey, entryFilesRetiredScopeKey, entryFilesUndeliveredScopeKey, entryFilesUnrevokedScopeKey, entryFilesWrittenScopeKey, filesOwnerUserId, parseIdList as parseFilesIdList, } from './entry-files-key.js';
12
- import { appHostname, entryHostnames, tunnelDnsHostnames, tunnelIngressHostnames, } from './hostnames.js';
12
+ import { appHostname, coolifyDomains, entryHostnames, tunnelDnsHostnames, tunnelIngressHostnames, } from './hostnames.js';
13
13
  import { LOGIN_BINDING_SCOPE_KEY, LOGIN_HOST_PENDING_REMOVAL_SCOPE_KEY, loginBindingState, loginHostClientIds, pendingRemovalHosts, pendingRemovalState, } from './login-host.js';
14
14
  import { MAIL_COPY_COMPLETED_SCOPE_KEY, MAIL_COPY_DONE_SCOPE_KEY, parseMailCopyCompleted, runMailCopyStep, } from './mail-copy.js';
15
15
  import { CALLS_MAS_APPLIED_IMAGE_TAG_SCOPE_KEY, CALLS_SYNAPSE_APPLIED_IMAGE_TAG_SCOPE_KEY, ORG_MAIL_APPLIED_APEX_SCOPE_KEY, ORG_MAIL_APPLIED_HOST_SCOPE_KEY, appDomainsAppliedScopeKey, appEnvAppliedScopeKey, appNameFor, appSettingsAppliedScopeKey, appSettingsOf, appStepKey, appliedAppDomains, appliedAppSettings, dbEnvAppliedScopeKey, resolveAppEnv, } from './platform-diff.js';
@@ -193,7 +193,7 @@ const RATE_LIMIT_REQUESTS_PER_PERIOD = 10;
193
193
  * multiple-apps shape `cmsSite`/`CMS_APP_DOCKERFILE` already use below.
194
194
  */
195
195
  const DEFAULT_APP_REPO = 'wtfalch/foundry';
196
- const DEFAULT_APP_DOCKERFILE = 'apps/hestia/Dockerfile';
196
+ const DEFAULT_APP_DOCKERFILE = '/apps/hestia/Dockerfile';
197
197
  /**
198
198
  * The one repo `cmsSite` builds both of its apps from
199
199
  * (https://github.com/wtfalch/cms) -- the 2026-09-25 decision this campaign
@@ -205,8 +205,8 @@ const DEFAULT_APP_DOCKERFILE = 'apps/hestia/Dockerfile';
205
205
  * is `apps/site`'s own Dockerfile (the reference renderer).
206
206
  */
207
207
  const CMS_REPO = 'wtfalch/cms';
208
- const CMS_APP_DOCKERFILE = 'Dockerfile';
209
- const CMS_SITE_APP_DOCKERFILE = 'apps/site/Dockerfile';
208
+ const CMS_APP_DOCKERFILE = '/Dockerfile';
209
+ const CMS_SITE_APP_DOCKERFILE = '/apps/site/Dockerfile';
210
210
  /**
211
211
  * #164: the repo `coolifyAgora` builds the org's Agora from
212
212
  * (https://github.com/wtfalch/agora) -- the issue's own "How" names this
@@ -225,7 +225,7 @@ const CMS_SITE_APP_DOCKERFILE = 'apps/site/Dockerfile';
225
225
  * way it does for `cmsSite`'s two apps above.
226
226
  */
227
227
  const AGORA_REPO = 'wtfalch/agora';
228
- const AGORA_APP_DOCKERFILE = 'apps/agora/Dockerfile';
228
+ const AGORA_APP_DOCKERFILE = '/apps/agora/Dockerfile';
229
229
  /**
230
230
  * Every app foundry deploys keeps its own logs across a redeploy, so a
231
231
  * database outage does not also erase the only other copy of the evidence
@@ -534,7 +534,7 @@ const CALLS_SERVICE_DB_SCOPE_KEY = 'coolify_calls_service_database';
534
534
  /** `wtfalch/calls`'s own repo -- `coolifyCallsService` deploys its `packages/service` (#145, part 2 of #128). */
535
535
  const CALLS_SERVICE_REPO = 'wtfalch/calls';
536
536
  /** `packages/service/Dockerfile`, built from the repo root (that Dockerfile's own top comment). */
537
- const CALLS_SERVICE_DOCKERFILE = 'packages/service/Dockerfile';
537
+ const CALLS_SERVICE_DOCKERFILE = '/packages/service/Dockerfile';
538
538
  /**
539
539
  * Whether an application's own Coolify `status` (`` `running:healthy`,
540
540
  * `exited:unhealthy` `` -- `@wtfalch/providers`' own doc comment) means it is
@@ -1208,7 +1208,7 @@ export class FoundryStepExecutor {
1208
1208
  git_branch: entry.branch,
1209
1209
  build_pack: entry.buildPack,
1210
1210
  name: appNameFor(org, entry),
1211
- domains: names.length > 0 ? names.join(',') : undefined,
1211
+ domains: names.length > 0 ? coolifyDomains(names) : undefined,
1212
1212
  autogenerate_domain: names.length > 0 ? undefined : false,
1213
1213
  // A static site is served by Coolify's own web server on port 80.
1214
1214
  ports_exposes: isStatic ? '80' : entry.port === null ? undefined : String(entry.port),
@@ -1239,7 +1239,7 @@ export class FoundryStepExecutor {
1239
1239
  // here (rule 3). The internal name is set after create, as the calls
1240
1240
  // stack's apps do.
1241
1241
  if (JSON.stringify(names) !== JSON.stringify(haveNames))
1242
- patch.domains = names.join(',');
1242
+ patch.domains = coolifyDomains(names);
1243
1243
  if (names.length === 0 && (!existing || patch.domains !== undefined)) {
1244
1244
  patch.custom_internal_name = appNameFor(org, entry);
1245
1245
  }
@@ -2178,7 +2178,7 @@ export class FoundryStepExecutor {
2178
2178
  git_branch: 'main',
2179
2179
  build_pack: 'dockerfile',
2180
2180
  name: input.name,
2181
- domains: input.domain,
2181
+ domains: coolifyDomains([input.domain]),
2182
2182
  dockerfile_location: input.dockerfileLocation,
2183
2183
  });
2184
2184
  return { appId: created.uuid, existed: false };
@@ -2708,7 +2708,7 @@ export class FoundryStepExecutor {
2708
2708
  git_branch: 'main',
2709
2709
  build_pack: 'dockerfile',
2710
2710
  name,
2711
- domains: callsHostnameFor(org),
2711
+ domains: coolifyDomains([callsHostnameFor(org)]),
2712
2712
  dockerfile_location: CALLS_SERVICE_DOCKERFILE,
2713
2713
  }));
2714
2714
  // A fixed internal name, like Synapse and MAS above, so the org's Agora
@@ -2936,7 +2936,7 @@ export class FoundryStepExecutor {
2936
2936
  git_branch: 'main',
2937
2937
  build_pack: 'dockerfile',
2938
2938
  name,
2939
- domains: agoraHostnameFor(org),
2939
+ domains: coolifyDomains([agoraHostnameFor(org)]),
2940
2940
  dockerfile_location: AGORA_APP_DOCKERFILE,
2941
2941
  }));
2942
2942
  // Every app foundry deploys keeps its own logs (#75), reused as-is here.
@@ -18,6 +18,12 @@ export declare function wildcardHostname(org: DeclaredOrg): string | null;
18
18
  * and the jobs registration read it.
19
19
  */
20
20
  export declare function appHostname(org: DeclaredOrg): string;
21
+ /**
22
+ * Coolify's `domains` field: comma-separated full URLs. A bare hostname is a
23
+ * 422 ("Invalid URL"), so every write names each host as `https://<host>`.
24
+ * Foundry's own records and proxy labels keep the bare names.
25
+ */
26
+ export declare function coolifyDomains(names: readonly string[]): string;
21
27
  /** What `domains` held on an `app` entry's Coolify app before entries had hostnames. */
22
28
  export declare function legacyAppHostname(org: DeclaredOrg): string;
23
29
  /**
@@ -34,6 +34,14 @@ export function appHostname(org) {
34
34
  const first = entry ? entryHostnames(org, entry)[0] : undefined;
35
35
  return first ?? legacyAppHostname(org);
36
36
  }
37
+ /**
38
+ * Coolify's `domains` field: comma-separated full URLs. A bare hostname is a
39
+ * 422 ("Invalid URL"), so every write names each host as `https://<host>`.
40
+ * Foundry's own records and proxy labels keep the bare names.
41
+ */
42
+ export function coolifyDomains(names) {
43
+ return names.map((name) => `https://${name}`).join(',');
44
+ }
37
45
  /** What `domains` held on an `app` entry's Coolify app before entries had hostnames. */
38
46
  export function legacyAppHostname(org) {
39
47
  return org.hosting.usesDomain && org.domain ? org.domain : `${org.slug}.oikos.host`;
@@ -5,6 +5,7 @@ import { VERSIONS, floatingTagBlocked } from '../bootstrap/versions.js';
5
5
  import { redactSecrets } from '../calls-sfu-deploy-support.js';
6
6
  import { ensureCloudflaredConnector } from './cloudflared-connector.js';
7
7
  import { ACCESS_POLICY_NAME, isNotFoundError, isRunningOrStarting } from './executor.js';
8
+ import { coolifyDomains } from './hostnames.js';
8
9
  import { JOBS_SCHEDULER_KEY, PLATFORM_AI_APPLIED_GITREF_SCOPE_KEY, PLATFORM_AI_APPLIED_HOSTNAME_SCOPE_KEY, PLATFORM_AI_DEPLOY_PENDING_SCOPE_KEY, PLATFORM_AI_INTERNAL_URL_SCOPE_KEY, PLATFORM_AI_KEY, PLATFORM_AI_MANAGEMENT_KEY_CONFLICT_SCOPE_KEY, PLATFORM_AI_MANAGEMENT_KEY_SCOPE_KEY, PLATFORM_AI_MANAGEMENT_KEY_UNDELIVERED_SCOPE_KEY, PLATFORM_AI_MIGRATE_BLOCKED_SCOPE_KEY, PLATFORM_AI_ORGANISATION_SCOPE_KEY, PLATFORM_AI_SIGNING_KEY_SET_SCOPE_KEY, PLATFORM_AI_SIGNING_KEY_UNDELIVERED_SCOPE_KEY, PLATFORM_ARCHON_APPLIED_BROKER_SCOPE_KEY, PLATFORM_ARCHON_APPLIED_GIT_REF_SCOPE_KEY, PLATFORM_ARCHON_APPLIED_HOSTNAME_SCOPE_KEY, PLATFORM_ARCHON_CONNECTOR_APP_SCOPE_KEY, PLATFORM_ARCHON_GATE_CLOSED_SCOPE_KEY, PLATFORM_ARCHON_KEY, PLATFORM_ARCHON_MASTER_CLOUDFLARE_TOKEN_REF, PLATFORM_ARCHON_MASTER_COOLIFY_TOKEN_REF, PLATFORM_ARCHON_MASTER_COOLIFY_URL_REF, PLATFORM_AUTH_ADMIN_UNDELIVERED_SCOPE_KEY, PLATFORM_AUTH_ADMIN_USER_SCOPE_KEY, PLATFORM_AUTH_BROKER_DEPLOYED_SCOPE_KEY, PLATFORM_AUTH_BROKER_SCOPE_KEY, PLATFORM_AUTH_CONNECTOR_APP_SCOPE_KEY, PLATFORM_AUTH_INSTANCE_SCOPE_KEY, PLATFORM_AUTH_INSTANCE_UNDELIVERED_SCOPE_KEY, PLATFORM_AUTH_KEY, PLATFORM_AUTH_LOGIN_CLIENT_UNDELIVERED_SCOPE_KEY, PLATFORM_AUTH_LOGIN_CLIENT_USER_SCOPE_KEY, PLATFORM_AUTH_ZITADEL_APPLIED_IMAGE_TAG_SCOPE_KEY, PLATFORM_BACKUP_DATABASE_SCOPE_KEYS, PLATFORM_BACKUP_SERVICE_KEYS, PLATFORM_FILES_APPLIED_GIT_REF_SCOPE_KEY, PLATFORM_FILES_APPLIED_HOSTNAME_SCOPE_KEY, PLATFORM_FILES_INTERNAL_URL_SCOPE_KEY, PLATFORM_FILES_INTROSPECTION_SCOPE_KEY, PLATFORM_FILES_INTROSPECTION_UNDELIVERED_SCOPE_KEY, PLATFORM_FILES_KEY, PLATFORM_FILES_MANAGEMENT_KEY_SCOPE_KEY, PLATFORM_FILES_MANAGEMENT_UNDELIVERED_SCOPE_KEY, PLATFORM_FILES_ZITADEL_PROJECT_SCOPE_KEY, PLATFORM_INTEGRATIONS_APPLIED_GITREF_SCOPE_KEY, PLATFORM_INTEGRATIONS_APPLIED_HOSTNAME_SCOPE_KEY, PLATFORM_INTEGRATIONS_KEY, PLATFORM_INTEGRATIONS_KEY_SET_SCOPE_KEY, PLATFORM_INTEGRATIONS_KEY_UNDELIVERED_SCOPE_KEY, PLATFORM_MAIL_ADMIN_KEY_SCOPE_KEY, PLATFORM_MAIL_ADMIN_UNDELIVERED_SCOPE_KEY, PLATFORM_MAIL_APPLIED_GIT_REF_SCOPE_KEY, PLATFORM_MAIL_APPLIED_HOSTNAME_SCOPE_KEY, PLATFORM_MAIL_CONNECTOR_APP_SCOPE_KEY, PLATFORM_MAIL_INTERNAL_URL_SCOPE_KEY, PLATFORM_MAIL_KEY, PLATFORM_MAIL_ZITADEL_PROJECT_SCOPE_KEY, parseBrokerDeployRecord, parseLoginClientRecord, platformMailMxHost, } from './platform-diff.js';
9
10
  import { applyCallsSfuPlatformStep } from './platform-sfu.js';
10
11
  import { CreateInstanceError, createZitadelInstance, generateSystemApiKeypair, instanceWithoutBearerMessage, systemApiUsersEnv, } from './zitadel-system-api.js';
@@ -424,7 +425,7 @@ export class FoundryPlatformStepExecutor {
424
425
  git_branch: gitRef,
425
426
  build_pack: 'dockerfile',
426
427
  name: JOBS_SCHEDULER_KEY,
427
- domains: hostname,
428
+ domains: coolifyDomains([hostname]),
428
429
  });
429
430
  appId = created.uuid;
430
431
  }
@@ -496,9 +497,9 @@ const AUTH_ZITADEL_IMAGE = 'ghcr.io/zitadel/zitadel';
496
497
  const AUTH_ZITADEL_IMAGE_TAG = VERSIONS.zitadel;
497
498
  /** `wtfalch/auth`'s own `login/Dockerfile` -- `docs/deploy.md`'s "One compose service, four containers... Two images are built from this repository: the proxy... and the login". */
498
499
  const AUTH_REPO = 'wtfalch/auth';
499
- const AUTH_LOGIN_DOCKERFILE = 'login/Dockerfile';
500
+ const AUTH_LOGIN_DOCKERFILE = '/login/Dockerfile';
500
501
  /** `wtfalch/auth`'s own `broker/Dockerfile` -- built from the repo root so the workspace resolves (#204). */
501
- const AUTH_BROKER_DOCKERFILE = 'broker/Dockerfile';
502
+ const AUTH_BROKER_DOCKERFILE = '/broker/Dockerfile';
502
503
  /**
503
504
  * `wtfalch/auth`'s login app answers on 3000 (its `Dockerfile`'s Next.js
504
505
  * default); ZITADEL answers on 8080 -- both fixed by `docker-compose.yml`'s
@@ -4369,7 +4370,7 @@ async function provisionPlatformIntegrations(action, context, deps) {
4369
4370
  };
4370
4371
  const migrateApp = await findOrCreatePlatformApp(coolify, INTEGRATIONS_MIGRATE_APP.name, environment, createApp(INTEGRATIONS_MIGRATE_APP.name));
4371
4372
  await record(INTEGRATIONS_MIGRATE_APP_SCOPE_KEY, migrateApp.appId);
4372
- const runnerApp = await findOrCreatePlatformApp(coolify, INTEGRATIONS_RUNNER_APP.name, environment, createApp(INTEGRATIONS_RUNNER_APP.name, hostname));
4373
+ const runnerApp = await findOrCreatePlatformApp(coolify, INTEGRATIONS_RUNNER_APP.name, environment, createApp(INTEGRATIONS_RUNNER_APP.name, coolifyDomains([hostname])));
4373
4374
  await record(INTEGRATIONS_RUNNER_APP_SCOPE_KEY, runnerApp.appId);
4374
4375
  const workerApp = await findOrCreatePlatformApp(coolify, INTEGRATIONS_WORKER_APP.name, environment, createApp(INTEGRATIONS_WORKER_APP.name));
4375
4376
  await record(INTEGRATIONS_WORKER_APP_SCOPE_KEY, workerApp.appId);
@@ -4387,7 +4388,7 @@ async function provisionPlatformIntegrations(action, context, deps) {
4387
4388
  dockerfile_target_build: INTEGRATIONS_RUNNER_APP.target,
4388
4389
  ports_exposes: INTEGRATIONS_RUNNER_PORT,
4389
4390
  git_branch: gitRef,
4390
- domains: hostname,
4391
+ domains: coolifyDomains([hostname]),
4391
4392
  });
4392
4393
  await coolify.updateApplication(workerApp.appId, {
4393
4394
  dockerfile_target_build: INTEGRATIONS_WORKER_APP.target,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wtfalch/foundry",
3
- "version": "0.16.0",
3
+ "version": "0.16.2",
4
4
  "description": "Foundry's SDK: the declared org's types, the plan and apply contracts, and the state store's interface.",
5
5
  "repository": {
6
6
  "type": "git",