MOSAIC_TIER is read by nothing — federated-test.stack.yml silently deploys standalone config (keyword memory, no pgvector) #1136

Open
opened 2026-08-09 20:19:01 +00:00 by mos-dt-0 · 1 comment
Collaborator

Found by shaggy while preparing the mosaic.woltje.com stack refresh (2026-08-09); independently verified by fred against origin/next.

Defect

deploy/portainer/federated-test.stack.yml:56 sets MOSAIC_TIER: federated, but the config loader reads MOSAIC_STORAGE_TIER (packages/config/src/mosaic-config.ts detectFromEnv()). Repo-wide grep on origin/next finds MOSAIC_TIER in exactly three places — that template plus tools/federation-harness/docker-compose.two-gateways.yml:116,197 — and zero readers in source.

The gateway runner image carries no mosaic.config.json (the Dockerfile copies only node_modules, package.json, dist), so loadConfig() falls through to detectFromEnv(), where MOSAIC_STORAGE_TIER is unset and DATABASE_URL is set — the documented legacy branch: "DATABASE_URL set without MOSAIC_STORAGE_TIER — treat as standalone."

Effect

The only upstream Swarm template for the federated tier actually deploys DEFAULT_STANDALONE_CONFIGmemory: { type: 'keyword' }, enableVector unset. It boots fine, so nothing alarms; it just is not federated. Anything relying on vector memory in a "federated test" instance has been silently keyword-matching. The template's own header names mos-test-1 / mos-test-2, so live test instances may be affected — worth checking their actual env.

Fix

Rename the variable in both the template and the federation harness to MOSAIC_STORAGE_TIER (or add MOSAIC_TIER as an accepted alias in detectFromEnv() — but a rename is cleaner given zero readers today).

Related template/image defects (same refresh work, minor)

  1. Traefik labels assume an entrypoint that need not exist: the template emits entrypoints=websecure, tls=true, certresolver=letsencrypt. Swarm hosts where TLS terminates at an edge (e.g. w-docker0: single web :80 entrypoint, no certresolver) get a router bound to a nonexistent entrypoint. At minimum document the assumption in the header.
  2. Three disagreeing gateway port declarations: docker/gateway.Dockerfile EXPOSE 4000 vs code default 14242 (apps/gateway/src/main.ts) vs template GATEWAY_PORT: '3000'. Only GATEWAY_PORT is load-bearing; the Dockerfile advertises a port nothing listens on. Reconcile.

Refs: docs/scratchpads/mosaic-woltje-stack-proposal.md §10 in jarvis-brain (shaggy, gated by fred).

Found by shaggy while preparing the mosaic.woltje.com stack refresh (2026-08-09); independently verified by fred against `origin/next`. ## Defect `deploy/portainer/federated-test.stack.yml:56` sets `MOSAIC_TIER: federated`, but the config loader reads **`MOSAIC_STORAGE_TIER`** (`packages/config/src/mosaic-config.ts` `detectFromEnv()`). Repo-wide grep on `origin/next` finds `MOSAIC_TIER` in exactly three places — that template plus `tools/federation-harness/docker-compose.two-gateways.yml:116,197` — and **zero readers in source**. The gateway runner image carries no `mosaic.config.json` (the Dockerfile copies only `node_modules`, `package.json`, `dist`), so `loadConfig()` falls through to `detectFromEnv()`, where `MOSAIC_STORAGE_TIER` is unset and `DATABASE_URL` is set — the documented legacy branch: *"DATABASE_URL set without MOSAIC_STORAGE_TIER — treat as standalone."* ## Effect The only upstream Swarm template for the federated tier actually deploys `DEFAULT_STANDALONE_CONFIG` — `memory: { type: 'keyword' }`, `enableVector` unset. It boots fine, so nothing alarms; it just is not federated. **Anything relying on vector memory in a "federated test" instance has been silently keyword-matching.** The template's own header names mos-test-1 / mos-test-2, so live test instances may be affected — worth checking their actual env. ## Fix Rename the variable in both the template and the federation harness to `MOSAIC_STORAGE_TIER` (or add `MOSAIC_TIER` as an accepted alias in `detectFromEnv()` — but a rename is cleaner given zero readers today). ## Related template/image defects (same refresh work, minor) 1. **Traefik labels assume an entrypoint that need not exist**: the template emits `entrypoints=websecure`, `tls=true`, `certresolver=letsencrypt`. Swarm hosts where TLS terminates at an edge (e.g. w-docker0: single `web :80` entrypoint, no certresolver) get a router bound to a nonexistent entrypoint. At minimum document the assumption in the header. 2. **Three disagreeing gateway port declarations**: `docker/gateway.Dockerfile` `EXPOSE 4000` vs code default `14242` (`apps/gateway/src/main.ts`) vs template `GATEWAY_PORT: '3000'`. Only `GATEWAY_PORT` is load-bearing; the Dockerfile advertises a port nothing listens on. Reconcile. Refs: `docs/scratchpads/mosaic-woltje-stack-proposal.md` §10 in jarvis-brain (shaggy, gated by fred).
Author
Collaborator

Addendum, same class of defect, different trigger (shaggy; verified by fred):

The repo root ships a mosaic.config.json with tier: local, storage.type: pglite. loadConfig() checks process.cwd() and ../../ for that file before consulting env (packages/config/src/mosaic-config.ts:186-193). The gateway runner image carries no config file so it falls to env detection (the bug above), but anyone running the gateway from a checkout gets local/pglite regardless of MOSAIC_STORAGE_TIER/DATABASE_URL — env is silently shadowed by a file intended as a dev default.

Suggested handling alongside the rename: env should win over the discovered file, or the root file should be renamed to an example (mosaic.config.example.json).

Addendum, same class of defect, different trigger (shaggy; verified by fred): The repo root ships a `mosaic.config.json` with `tier: local`, `storage.type: pglite`. `loadConfig()` checks `process.cwd()` and `../../` for that file **before** consulting env (`packages/config/src/mosaic-config.ts:186-193`). The gateway runner *image* carries no config file so it falls to env detection (the bug above), but anyone running the gateway **from a checkout** gets local/pglite regardless of `MOSAIC_STORAGE_TIER`/`DATABASE_URL` — env is silently shadowed by a file intended as a dev default. Suggested handling alongside the rename: env should win over the discovered file, or the root file should be renamed to an example (`mosaic.config.example.json`).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#1136