Skip to content

feat(cli): add SUPABASE_USE_SLIM_IMAGES flag for slim ghcr images - #6329

Closed
avallete wants to merge 26 commits into
developfrom
avallete/supabase-slim-images-flag-c95c16
Closed

feat(cli): add SUPABASE_USE_SLIM_IMAGES flag for slim ghcr images#6329
avallete wants to merge 26 commits into
developfrom
avallete/supabase-slim-images-flag-c95c16

Conversation

@avallete

@avallete avallete commented Aug 25, 2026

Copy link
Copy Markdown
Member

Summary

Adds an opt-in env feature flag SUPABASE_USE_SLIM_IMAGES ("true" or "1", read from the ambient process env per call) that makes the legacy shell resolve its local-stack Docker images from the slim ghcr.io/supabase/cli/<service> builds instead of the docker.io images pinned in the embedded Dockerfile manifest — so the slim images can be exercised through the stable CLI. With the flag unset, behavior is byte-identical.

Commit 1 — flag plumbing

  • apps/cli/src/shared/services/slim-images.ts owns the gate and the pure translation: Dockerfile alias → stack-catalog service, keeping the Dockerfile's pinned version translated into the slim tag scheme via dockerImageForService from a new lightweight @supabase/stack/versions export (supavisor:2.9.7pooler:v2.9.7, logflare:1.50.4analytics:v1.50.4, vector's docker.io-only -alpine suffix stripped).
  • dockerfileServiceImage(alias) is the single flag-translated choke point for default images; dockerfileServiceImageRaw remains for identity contracts. Pinned-version paths (legacyResolvePinnedImage, services listings, gen types) go through the catalog so tag-scheme differences normalize correctly.
  • Slim refs bypass the SUPABASE_INTERNAL_IMAGE_REGISTRY/ECR mirror rewrite entirely (single pull candidate) — they are published only at ghcr.io/supabase/cli, so any rewrite would silently pull the non-slim mirror.

Commit 2 — slim postgres container support (start + shadow)

The slim postgres image has a different runtime contract from docker.io (non-root uid 65532, its own entry.sh, postgres under /opt/postgres, no docker-entrypoint.sh). When the resolved ref is slim, the main-db and shadow-db specs switch to it:

  • The image entrypoint is kept — entry.sh self-initializes on first boot (initdb, config, bundled supabase migrations) and passes container argv through to postgres, so [db.settings] travel as -c key=value argv pairs.
  • The CLI's bootstrap schema (schema.sql + webhook.sql + _supabase.sql) and the deterministic pgsodium root key are staged via the existing secret-file docker cp; the image's bundled migrate.sh executes /etc/postgresql.schema.sql as its first-boot postinit — the same hook the docker.io image runs — giving exactly-once semantics across container restarts with no CLI-side marker. PGSODIUM_KEY_FILE points the image's getkey script at the CLI's root key.
  • start --from-backup refuses a slim resolved ref with a typed, classified error until the restore flow learns the slim contract (a registry override landing back on docker.io still restores).
  • Verified against a real slim db start: healthy container, settings applied via argv, all three schema templates present exactly once across restarts, root key loaded, shadow spec exercised by hand.

Deliberately unchanged even with the flag on

  • kong and the differ/migra/pgprove job images (no slim builds)
  • pg 13/14/15 major-version fallback images and OrioleDB overrides
  • the deno_version = 1 edge-runtime image (supabase/edge-runtime:v1.68.4)
  • status/--exclude short names and services image overrides

Reviewer notes

  • The flag reads the ambient process env only — values set solely in supabase/.env are not honored. SIDE_EFFECTS.md rows were added for every command whose image resolution the flag reaches.
  • The shared choke point also affects the functions deploy/download/serve Docker paths in both shells; intentional for an opt-in flag.
  • The earlier slim-image supautils gap (empty GUCs blocking create extension pg_net in shadow flows) is fixed by the 17.6.1.166 slim build; the Dockerfile postgres pin is bumped to it (docker.io publishes the same tag), verified live with a slim db diff end to end. The bundle demotes postgres on both image families, so the slim-only CLI postinit re-promotion was dropped (see the parity round below).

Dogfooding round — full supabase start on slim images

  • Distroless service images (realtime/storage/auth one-shot jobs, studio, vector) get slim-aware container wiring where their docker.io contracts assumed root or different filesystem layouts.
  • The realtime and storage one-shot migrate jobs are skipped on slim refs (their slim images self-migrate); auth's runs as migrate.
  • Slim edge-runtime runs from /tmp (read-only rootfs) and slim storage mounts its volume at /home/nonroot.
  • Dockerfile supavisor pin bumped 2.9.7 → 2.9.10 (the slim pooler build exists at v2.9.10).

Dogfooding round — config-recipe parity and full service matrix

Ran the slim-services shared-config-recipe postgres build (slim-services#264) plus every other slim service through the full CLI flow matrix (start/status/restart, both db diff engines, db dump, declarative sync, db reset, migration squash, seed buckets, negative guards), then functionally exercised each service: REST, GraphQL, auth + Mailpit SMTP, storage upload/download/TUS, imgproxy render, vector buckets, edge function invoke, realtime broadcast + postgres_changes, pooler connections, Studio (Advisors, Table Editor, Logs), and the vector → analytics logs pipeline. Fixes that came out of it:

  • Dropped the slim-only postgres postinit (ALTER ROLE postgres WITH SUPERUSER; CREATE EXTENSION vector). Its premise was wrong: docker.io also demotes postgres (verified rolsuper = f on a fresh flag-off 17.6.1.166 stack), and storage-api creates vector itself in its own storage_vectors database via the supautils allowlist. A same-release parity diff between slim and docker.io stacks (pg_settings / pg_roles / pg_extension as supabase_admin) now shows empty roles and extensions diffs, and the settings diff reduces entirely to the slim bundle's documented local-dev profile, layout paths, and shared_buffers-derived values.
  • Pooler under the flag was unbootable: the healthcheck exec'd curl, which the distroless slim supavisor image doesn't ship, so [db.pooler] enabled = true failed start outright. It now probes with the image's /bin/busybox wget (the realtime/analytics pattern).
  • Connection budget: supavisor's internal metadata pool defaults to 25 connections — half of the slim local-dev max_connections=50 — which saturated the database and starved realtime. The CLI now sets DB_POOL_SIZE=5.
  • Image transformation was silently off on slim: the slim storage image bakes IMAGE_TRANSFORMATION_ENABLED=false as an image ENV default and storage-api prefers that key over the ENABLE_IMAGE_TRANSFORMATION the CLI set. The CLI now sets both keys from config.
  • Storage pin bumped v1.70.3 → v1.71.0 (published on docker.io/ECR and ghcr): the slim v1.71.0 build also fixes the storage volume root perms (/home/nonroot 0700 → 0711) that blocked imgproxy (uid 999) from reading uploads. Verified on a fresh stack: upload, public download, render, vector buckets, and TUS create all pass with no manual intervention. Full methodology and results: feat(cli): add SUPABASE_USE_SLIM_IMAGES flag for slim ghcr images #6329 (comment)

Linked issue

Closes #

  • The linked issue is open and carries the open-for-contribution label (or I'm a Supabase maintainer).

Checklist

  • The PR title follows Conventional Commits (e.g. fix(cli): …).
  • Tests added or updated for the change.
  • pnpm check:all and pnpm test pass for the workspace(s) I touched.

🤖 Generated with Claude Code

When SUPABASE_USE_SLIM_IMAGES is "true" or "1", the legacy shell resolves
its local-stack Docker images from the slim ghcr.io/supabase/cli/<service>
builds instead of the docker.io images pinned in the embedded Dockerfile
manifest, keeping the Dockerfile version pins translated into the slim tag
scheme via @supabase/stack's catalog (new "./versions" package export).

Services with no slim build keep their docker.io reference: kong, the
differ/migra/pgprove job images, the pg 13/14/15 major-version fallbacks,
OrioleDB overrides, and the deno_version = 1 edge-runtime pin. Slim refs
bypass the SUPABASE_INTERNAL_IMAGE_REGISTRY/ECR rewrite (they exist only at
ghcr.io/supabase/cli), status/--exclude short names stay flag-invariant,
services-command image overrides are never translated, and the declarative
stale-container guard now rejects slim/non-slim family mismatches. With the
flag unset, behavior is byte-identical.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@avallete
avallete requested a review from a team as a code owner August 25, 2026 16:51

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 92576b1233

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/shared/services/slim-images.ts
@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Supabase CLI preview

npx --yes https://pkg.pr.new/supabase/cli/supabase@6c57060f76adaacd20590de6a68ace93277a5478

Preview package for commit 6c57060.

With SUPABASE_USE_SLIM_IMAGES on and a resolved ghcr.io/supabase/cli/postgres
ref, the main-db and shadow-db container specs switch to the slim image's
contract: the image entrypoint is kept (entry.sh self-initializes and passes
container argv through to postgres), config.toml db settings travel as -c
argv pairs, and the CLI's bootstrap schema plus pgsodium root key are staged
via the existing secret-file docker cp — the image's bundled migrate.sh runs
/etc/postgresql.schema.sql as its first-boot postinit, giving exactly-once
semantics without any CLI-side marker. PGSODIUM_KEY_FILE keeps the root key
deterministic for the non-root (uid 65532) image user.

start --from-backup refuses a slim resolved ref with a typed error until the
restore flow learns the slim contract. Flag off (or a registry override
landing on docker.io) stays byte-identical.

Verified against a real slim db start: healthy container, settings applied,
all three schema templates present exactly once across restarts, root key
loaded, shadow spec exercised. Shadow flows additionally need a slim-services
image fix (empty supautils GUCs block "create extension pg_net").

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: efba3aa535

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/shared/services/dockerfile-images.ts
Comment thread apps/cli/src/legacy/shared/db-bootstrap/postgres.service.ts Outdated
…slim-images-flag-c95c16

# Conflicts:
#	apps/cli/src/legacy/commands/start/SIDE_EFFECTS.md
#	apps/cli/src/legacy/shared/db-bootstrap/postgres.service.unit.test.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cbb49da949

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/shared/functions/functions.shared.ts
Reusing a named database volume initialized by the docker.io postgres image
under SUPABASE_USE_SLIM_IMAGES crash-loops the slim image's non-root user
against the 700-mode PGDATA until the health check times out. Before creating
the container on an existing volume, a cheap docker-run probe now checks that
the slim image's own user can read PG_VERSION and fails fast with remediation
(stop --no-backup to reset, or unset the flag) when it cannot.

Also documents the flag in the SIDE_EFFECTS of db pull, services, and the
declarative schema commands, and records why the deno1 edge-runtime tag check
intentionally also covers an explicit pin of that tag.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 429bad2c79

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/db-bootstrap/postgres.service.ts Outdated
Comment thread apps/cli/src/legacy/shared/db-bootstrap/postgres.service.ts Outdated
Comment thread apps/cli/src/shared/services/slim-images.ts
…slim contract

The slim entrypoint runs a temporary server during first-boot init, so the
slim specs' healthcheck now requires PID 1 to be the final postgres process
before pg_isready counts (same gate the stack's docker path uses); docker.io
keeps the plain pg_isready test byte-identically. The pg_dump one-shot runner
(db dump, db pull, migration squash) now overrides the entrypoint to bash on
slim refs — the slim entrypoint would otherwise initdb an empty cluster and
hand the dump command to postgres. Also rewords a settings-renderer comment
off Go-authority framing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89b4e15a33

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/commands/db/start/start.integration.test.ts Outdated
Comment thread apps/cli/src/legacy/shared/db-bootstrap/container-lifecycle.ts Outdated
…t coupling

Postgres must write postmaster.pid and WAL under PGDATA, so the reused-volume
guard now also requires write access (test -w on the mount) — a read-only-
accessible volume previously slipped past the guard into the same crash-loop
it exists to prevent. The error and probe naming follow (Inaccessible /
AccessibleToImage). The new integration tests narrow errors with instanceof
on the exported classes instead of asserting the _tag field through casts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 235924d28f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/legacy-edge-runtime-image.ts Outdated
avallete and others added 2 commits August 25, 2026 21:35
…y resolver

The legacy resolver and the functions-path edgeRuntimeImage read the same
.temp/edge-runtime-version pin but disagreed under the slim flag: a stale
v1.68.4 pin (left by an earlier deno_version = 1 run) tag-swapped onto the
slim base yields an unpullable ref, since no slim build of that tag exists.
Both resolvers now apply the same docker.io exception from one shared
constant.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Docker CLI healthchecks are always CMD-SHELL, so distroless slim
auth/storage/studio/pg-meta cannot probe via wget/node. Slim realtime
one-shot jobs must override entry.sh, auth migrate argv drops the
binary name, storage skips migrate-call.js, and vector/edge-runtime
keep the image entrypoint instead of a shell wrapper.

Co-authored-by: Andrew Valleteau <avallete@users.noreply.github.com>
avallete and others added 6 commits August 26, 2026 04:18
Co-authored-by: Andrew Valleteau <avallete@users.noreply.github.com>
Slim realtime already migrates and seeds from entry.sh
(SEED_SELF_HOST=true). The docker.io eval health_check starts a
second BEAM against Postgres and fails under a slow daemon.

Co-authored-by: Andrew Valleteau <avallete@users.noreply.github.com>
Slim edge-runtime runs as uid 65532 and cannot read /root, so copy the
main-service template to /tmp. Slim postgres leaves the postgres role as
a non-superuser, so grant SUPERUSER and create the vector extension before
storage-api's vector-bucket migrations run.

Co-authored-by: Andrew Valleteau <avallete@users.noreply.github.com>
The postgres session cannot ALTER ROLE itself after the slim image demotes
it. Append SUPERUSER plus CREATE EXTENSION vector to the migrate.sh postinit
schema so supabase_admin applies it before the CLI connects.

Co-authored-by: Andrew Valleteau <avallete@users.noreply.github.com>
Distroless storage runs as uid 65532. A named volume at /mnt is created
root-owned because that path is missing from the image, so mkdir /mnt/stub
fails with EACCES. /home/nonroot is owned by the image user and Docker
copies that ownership into an empty volume.

Co-authored-by: Andrew Valleteau <avallete@users.noreply.github.com>
Align the embedded pooler pin with the stack catalog and the oldest
published slim ghcr.io/supabase/cli/pooler tag.

Co-authored-by: Andrew Valleteau <avallete@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 01e32ba4c2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli-go/pkg/config/templates/Dockerfile
Comment thread apps/cli/src/shared/services/slim-images.ts
Comment thread apps/cli/src/shared/functions/serve.ts Outdated
Comment thread apps/cli/src/legacy/commands/start/services/storage.service.ts Outdated
… seeding

Three slim-runtime gaps from PR review, each verified against the real ghcr
images (both distroless: no sh/busybox anywhere in their layers):

- The pg-delta legacy engine's edge-runtime script runner replaces the
  entrypoint with sh to heredoc its files, which cannot run on the slim
  edge-runtime image — it now resolves through a docker.io-pinned variant of
  the shared resolver (version pin still honored), the same locked-exception
  shape as the deno1 tag.
- The slim storage image cannot carry a docker healthcheck, so bulk readiness
  accepted it at Running and bucket seeding raced its migrations — the health
  wait now probes HEAD /storage/v1/status through Kong on the slim path
  (including the --ignore-health-check storage recheck), skipped when kong is
  excluded; docker.io keeps the container healthcheck byte-identically.
- The slim functions-serve multiline-secret rejection was a bare Error; it is
  now an exported tagged error classified invalidConfig, failing through the
  Effect channel.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a83e369fe8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/db-bootstrap/db-setup.ts Outdated
Comment thread apps/cli/src/legacy/commands/start/services/gotrue.service.ts
Comment thread apps/cli/src/shared/services/slim-images.ts
The 17.6.1.166 slim build ships the full supautils policy (privileged
extensions allowlist incl. pg_net and vector, privileged_extensions_superuser
= supabase_admin), unblocking the shadow-database flows under
SUPABASE_USE_SLIM_IMAGES — verified live: create extension pg_net succeeds as
the demoted postgres role, and db diff runs its slim shadow end to end. The
postgres demote is still present in the bundle migrations, so the CLI postinit
re-promotion stays. docker.io publishes the same tag, so the flag-off pin
moves in lockstep.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
avallete and others added 2 commits August 27, 2026 11:24
Both image families run the same bundled migrations, including the
unconditional postgres demotion, so re-promoting postgres on slim made the
two families diverge (rolsuper=t on slim vs f on docker.io). The vector
pre-create it carried was never needed either: storage-api creates the
extension itself in its own storage_vectors database through the supautils
allowlist, which the shared config recipe now ships on slim.

Verified by a full pg_settings/pg_roles/pg_extension parity diff between a
slim and a docker.io stack of the same release: roles and extensions diff
empty, postgres rolsuper=f on both, cron/vault custom-script grants intact.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two fixes for `[db.pooler] enabled = true`:

- The healthcheck exec'd curl, which the distroless slim supavisor image
  does not ship, so the container could never turn healthy and `start`
  failed outright under SUPABASE_USE_SLIM_IMAGES. Probe with the image's
  /bin/busybox wget instead, the same pattern realtime and analytics use.

- Supavisor's internal metadata Ecto pool defaults to 25 connections, half
  of the slim local-dev max_connections=50. With every service enabled the
  database saturated at 50/50 and realtime failed with
  DatabaseLackOfConnections. Cap the meta pool at 5, which is plenty for
  the single local tenant and also stops wasting 25 of docker.io's 100.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ge to v1.71.0

storage-api prefers IMAGE_TRANSFORMATION_ENABLED over the legacy
ENABLE_IMAGE_TRANSFORMATION key the CLI sets, and the slim storage image
bakes IMAGE_TRANSFORMATION_ENABLED=false as an image ENV default, silently
disabling transforms regardless of config.toml. Set the modern key
explicitly so the config value wins on both image families.

storage-api v1.71.0 also fixes the slim image's /home/nonroot volume-root
mode (0700 -> 0711 65532), which blocked imgproxy (uid 999) from traversing
the shared storage volume. Verified on a fresh stack: upload, public
download, 32x32 render, vector buckets, and TUS create all green with no
manual intervention.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@avallete

avallete commented Aug 27, 2026

Copy link
Copy Markdown
Member Author

Dogfood report — slim images through the full CLI surface

Local end-to-end validation behind this PR's last five commits, run on macOS/OrbStack (arm64) from this branch's checkout. Documented here since PR descriptions stay validation-free by repo convention.

Images under test

Service Image Provenance
postgres ghcr.io/supabase/cli/postgres:17.6.1.166 (local tag) built from the supabase/slim-services#264 shared-config-recipe branch (0910b0c) CI artifact, sources 17.6.1.158; retagged locally over the pin
storage ghcr.io/supabase/cli/storage@sha256:f7d43115… (= v1.71.0) published release, retagged locally over the then-pinned v1.70.3
everything else published ghcr.io/supabase/cli/* at the pinned versions registry

The postgres parity comparison (below) was run same-release — slim-from-#264 vs docker.io supabase/postgres:17.6.1.158 — so it isolates the config recipe from upstream drift between .158 and .166. ⚠️ The published ghcr slim 17.6.1.166 predates the #264 recipe; slim-services needs to land #264 with SOURCE_REF=17.6.1.166 and republish before this PR ships.

Round 1 — CLI flow matrix, flag on (fresh volumes per run)

Flow Result
full start (webhooks enabled) all services healthy, exactly one portable bundle init + one migrate pass; container restart → no re-init
db diff, pg-delta next engine clean (shadow flow, the historical pg_net blocker)
db diff, legacy engine (SUPABASE_USE_PG_DELTA_NEXT=false) clean
db dump --local 1128-line dump via the slim one-shot job
declarative sync (db schema declarative sync --yes) migration generated + applied through the shadow flow (first attempt correctly rejected by the legacy-export gate until the tree declared pg_net)
db reset re-init correct; bucket seeding hit the known storage-readiness race on the reset path once (storage came up seconds later; retry succeeded) — pre-existing CLI gap, not image-related
migration squash --local clean
logical replication slot create/drop as supabase_admin works (max_wal_senders=10, was 0 before the recipe)
guard: flag-on start over a docker.io-initialized volume fail-fast LegacySlimImageVolumeInaccessibleError with remediation, no containers created
guard: db start --from-backup under the flag typed LegacySlimImagesBackupUnsupportedError
guard: flag-off stack zero ghcr.io images in docker ps

Skipped: db pull (no linked project), gen types under the flag (known argv bug, tracked separately).

Round 2 — postinit removal (commit 59e3368ec)

With LEGACY_POSTGRES_SLIM_POSTINIT_SQL deleted, on a fresh slim stack:

  • postgres role is rolsuper = f, surviving db reset — matching flag-off docker.io (verified f there too; the "docker.io keeps postgres a superuser" premise was wrong).
  • storage-api created vector 0.8.2 itself in its own storage_vectors database via the supautils allowlist during start — the deleted pre-create only ever created it in the postgres database, which isn't where storage needs it.
  • Repeated matrix rows (start / diff / reset / vector buckets) all pass.

Round 3 — the parity diff (same release, both families, fresh stacks)

As supabase_admin on both: pg_settings, pg_roles (+flags), pg_extension.

  • Roles diff: empty. Extensions diff: empty.
  • Settings residual after the documented allowed deltas: empty. Every differing key classifies as (a) the slim bundle's local-dev.conf profile (shared_buffers, max_connections, jit, max_wal_size, bgwriter_delay, wal_writer_delay, checkpoint_completion_target, maintenance_work_mem, unix_socket_directories), (b) values Postgres derives from shared_buffers (wal_buffers, transaction/subtransaction/commit_timestamp_buffers, shared_memory_size*), or (c) layout paths (config/hba/ident_file, pgsodium/vault.getkey_script, both supautils.*custom_scripts_path).
  • Previously-broken spot checks, now equal on both families: session_preload_libraries=supautils; the full 11-library shared_preload_libraries; supautils.privileged_extensions_superuser=supabase_admin; pg_net.username=postgres; max_wal_senders/max_replication_slots = 10/5; lc_messages=en_US.UTF-8; locale provider i; postgres rolsuper=f; after CREATE EXTENSION pg_cron/supabase_vault as postgres: cron USAGE grant and vault.secrets SELECT grant both t.
  • Idle db RSS: slim 101.5 MiB vs docker.io 133.4 MiB (full preload set on both). Slim postgres image 494 MB vs 753 MB previous slim tag vs 1.76 GB docker.io.

Round 4 — functional service matrix (every service enabled, incl. pooler + image transformation)

Service Test Result
PostgREST insert + select /rest/v1
GraphQL pg_graphql query (extension created as demoted postgres via allowlist; not pre-created on either family)
Auth signup + password recover
Mailpit recovery email via API ✅ delivered
Storage upload + public download ✅ byte-identical
Imgproxy /render/image/…?width=32 ✅ after the two storage fixes below
Vector buckets create + ListVectorBuckets
Edge functions functions new template served by slim edge-runtime v1.74.3 via Kong {"message":"Hello slim!"}
Realtime broadcast round-trip and postgres_changes INSERT delivery ✅ (an initial "failure" was the test inserting before the async Subscribed to PostgreSQL ack — test race, not a bug)
Pooler psql through supavisor transaction port 54329 ✅ after the healthcheck fix
Studio home + Advisors, Table Editor rendering live rows, Logs page ✅ in-browser
Logs pipeline vector → analytics → Studio postgres logs ✅ 100 entries

Findings from this round map to commits 94cd3a42e (pooler healthcheck + DB_POOL_SIZE=5; the db had saturated at 50/50 connections with supavisor_meta holding 25) and 691ff6b4f (IMAGE_TRANSFORMATION_ENABLED + storage bump).

Round 5 — storage v1.71.0 (published release, immutable digest)

Fresh project, fresh volume, zero manual intervention:

  • volume root inherits 711 65532:65532 from the image (the v1.70.x slim image baked 0700, which blocked imgproxy uid 999 — the one finding that needed an image-side fix);
  • upload → public download (byte-identical) → 32×32 render all 200;
  • vector bucket + TUS resumable create (201) pass; storage logs show zero warn/error lines;
  • re-validated the pooler healthcheck and transformation-env fixes on a clean slate.

Known notes for reviewers

  • Slim pooler/realtime/analytics ship /bin/busybox; auth/pg-meta/studio remain probe-less on slim (pre-existing, unchanged here).
  • packages/stack/src/ServiceCatalog.ts pins drift from the Dockerfile template by design (postgres .165 vs .166 predates this PR); not touched.
  • The supavisor DB_POOL_SIZE=5 cap applies to both image families intentionally — docker.io was also spending 25 of its 100 connections on the meta pool.

Round 6 — shadow-baseline cache (SUPABASE_SHADOW_CACHE=1) on slim

The tar pool (~/.supabase/cache/shadow-baseline/) exports/restores initialized PGDATA, which is exactly the kind of path the slim image's non-root (uid 65532) contract could break. Verified on both families:

Check Result
slim db diff cold → warm 21.2s → 3.3s; tars exported on miss, restored on hit
correctness against a cached baseline a live CREATE TABLE made after caching is correctly emitted by the next diff
db reset / fresh-project start under the flag always first-boot (init line present, rolsuper=f after) — the pool is consumed by shadow flows only, main db never restores from tar
cross-family key isolation flag-off db diff minted a distinct tar key (the cache key embeds postgres_image=<ref>); no slim/docker.io reuse in either direction
docker.io db diff cold → warm 22.9s → 3.4s — cache behavior identical across families

No code changes needed — the existing cache seam works with the slim postgres image as-is.
🤖 Generated with Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 691ff6b4fd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/commands/start/services/storage.service.ts Outdated
Comment thread apps/cli/src/shared/services/slim-images.ts
Comment thread apps/cli/src/legacy/commands/start/SIDE_EFFECTS.md Outdated
Comment thread apps/cli/src/legacy/commands/db/reset/SIDE_EFFECTS.md
Comment thread apps/cli-go/pkg/config/templates/Dockerfile
Slim-services #280 ships pg_dumpall/uniq, max_connections=100, /mnt
owned by uid 65532, and exec-form HEALTHCHECKs. Drop the CLI
workarounds those images replace and fix the remaining orchestration:
omit the extra gen-types node argv, mount functions off /root, restore
the realtime one-shot before user migrations, slim-translate only the
current Dockerfile pin, remount storage at /mnt with a family write
probe, and remove the unconditional DB_POOL_SIZE=5 cap.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0bede57286

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/shared/functions/download.ts Outdated
Comment thread apps/cli/src/shared/functions/download.ts Outdated
The slim edge-runtime image runs as uid 65532 (distroless nonroot), which
breaks two docker.io-root assumptions in the functions Docker paths on
native Linux / WSL2:

- functions download --use-docker extracted straight into the host
  supabase/functions bind, which uid 65532 cannot write when the host
  directory belongs to a different uid (EACCES). The slim flow now keeps
  the unbundle output container-local (/tmp/unbundle/<slug>, eszip bound
  read-only under /tmp/eszips) via a create -> start --attach -> cp ->
  rm --force lifecycle, and the CLI writes the copied files host-side as
  the invoking user, with the same path-containment checks the multipart
  downloader applies.

- The shared supabase_edge_runtime_<id> Deno-cache volume mounts at
  /root/.cache/deno, which the slim runtime neither reaches (0700 /root)
  nor uses (Deno caches under $HOME=/home/nonroot), and a docker.io-seeded
  volume is root-owned and can never be made writable by uid 65532 by
  remounting it. Slim runs (download/deploy/serve/start) now use their own
  supabase_edge_runtime_slim_<id> volume mounted over /home/nonroot, which
  Docker seeds from the image's 65532-owned home — same pattern as the slim
  Storage volume. Both volume families carry the project label that
  supabase stop --no-backup prunes by.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DrSmrBgbWfva1KbYWGMV4c
Comment thread apps/cli/src/shared/functions/download.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c0b20cd2a3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/shared/functions/serve.ts Outdated
Comment thread apps/cli/src/legacy/commands/functions/download/download.integration.test.ts Outdated
Branch-local workflow_dispatch job that pulls the released slim
edge-runtime image and validates it against this branch's slim
functions Docker flows on a native Linux runner (CLI uid 1001 vs
container uid 65532 — the condition the original EACCES reports came
from): image layout smoke (0755 /root, busybox sh+cat, nonroot home),
a negative control reproducing the pre-fix direct-bind EACCES, slim
download via cp-out staging, slim deploy from a /root checkout, the
slim-only Deno-cache volume, and the docker.io baseline.

To be removed once the image + CLI pairing is validated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DrSmrBgbWfva1KbYWGMV4c
@avallete
avallete force-pushed the avallete/supabase-slim-images-flag-c95c16 branch from 45dac45 to 9b2bcba Compare August 28, 2026 08:10
Validation run passed against the released slim edge-runtime v1.74.3
image (supabase/cli actions run 33154293277): image layout smoke,
pre-fix EACCES negative control, slim download cp-out staging, slim
deploy from a /root checkout, slim-only Deno-cache volume, and the
docker.io baseline.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DrSmrBgbWfva1KbYWGMV4c

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9b2bcba950

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/shared/functions/download.ts Outdated
Comment thread .github/workflows/slim-edge-runtime-validation.yml Outdated
Comment thread apps/cli/src/legacy/shared/legacy-edge-runtime-image.ts
Comment thread apps/cli/src/legacy/commands/functions/download/SIDE_EFFECTS.md Outdated
Comment thread apps/cli/src/legacy/commands/functions/serve/SIDE_EFFECTS.md
Comment thread apps/cli/src/legacy/commands/db/dump/SIDE_EFFECTS.md
Comment thread apps/cli/src/shared/functions/download.ts Outdated
avallete and others added 2 commits August 28, 2026 11:53
…-runtime tag

A missing Postgres volume used to mark the run fresh, so leftover
docker.io data was pruned on rollback. Probe those volumes first, skip
freshness on slim --from-backup, and take the Dockerfile tag from the
last colon so slim GHCR refs do not resolve to the registry host.

Co-authored-by: Cursor <cursoragent@cursor.com>
…cker.io

Rebuilt ghcr postgres/storage/auth/edge-runtime pins start as root, ship
sh/wget, and restore after bundle migrate. The flag is only an image-name
rewrite; leftover 65532/volume/boot/--from-backup/dump-bash/migrate forks
are gone. Storage pin is v1.72.1 to match the rebuilt slim tag.

Co-authored-by: Cursor <cursoragent@cursor.com>
@avallete

Copy link
Copy Markdown
Member Author

Landed: slim images are docker.io-shaped

SUPABASE_USE_SLIM_IMAGES is now image-name rewrite only. The published ghcr.io/supabase/cli/{postgres,storage,auth,edge-runtime} pins start as root, ship sh/wget, listen on /run/postgresql, and run CLI --from-backup after bundle migrate. CLI leftover forks (65532 volumes, slim boot, dump-bash, migrate argv, --from-backup refuse) are deleted. Storage pin is v1.72.1.

Watch for later

  • Cached tags are not auto-refreshed — pull after a slim-services rebuild of the same tag.
  • Pre-rebuild uid 65532 volumes are still incompatible; stop --no-backup and start fresh. No family-switch chown.
  • functions download --use-docker writes as container root on rootful Linux Docker.
  • Corpus samples on major_version = 15 do not exercise slim postgres 17.
  • Kong and job images (differ/migra/pgprove) stay non-slim.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: be0af52024

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/db-bootstrap/pinned-image.ts
Comment thread apps/cli/src/legacy/commands/bootstrap/SIDE_EFFECTS.md
Comment thread apps/cli/src/legacy/shared/db-bootstrap/db-setup.unit.test.ts
@avallete

Copy link
Copy Markdown
Member Author

/ai-review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6c57060f76

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


const rawTag = image.slice(tagSeparator + 1);
const tag = alias === "vector" ? rawTag.replace(/-alpine$/, "") : rawTag;
return dockerImageForService(service, tag);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Route vector and pooler to the slim CLI repositories

When SUPABASE_USE_SLIM_IMAGES is enabled and start includes Vector or Supavisor, dockerImageForService honors the existing ServiceCatalog.ts artifact overrides, producing ghcr.io/supabase/vector:<tag> and ghcr.io/supabase/supavisor:<tag> rather than the intended ghcr.io/supabase/cli/vector:<tag> and ghcr.io/supabase/cli/pooler:v<tag>. These references then fail isSlimImageRef, so the newly added slim-specific Vector and Pooler container wiring is skipped; Vector additionally has -alpine stripped before the unrelated image is pulled. Construct these two CLI slim repository identities explicitly instead of delegating them to the general stack artifact resolver.

Useful? React with 👍 / 👎.

@avallete

Copy link
Copy Markdown
Member Author

Split into a stacked review so code and docs no longer share one diff:

Closing this PR in favor of that stack. The original branch avallete/supabase-slim-images-flag-c95c16 is unchanged if anyone still needs the mixed history.

@avallete avallete closed this Aug 28, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Superseded by a newer AI review

🤖 AI Review

The 11 reported items deduplicate to 8 findings. Five major runtime/test/version issues, two minor readiness/documentation concerns, and one nit were confirmed against the checked-out code. The most consequential defects are the broken Pooler/Vector slim resolution, incompatible slim one-shot migration commands, unsynchronized service pins, and a guaranteed failing pg-delta test.

Findings

Severity Location Category Sources Claim
🟠 MAJOR apps/cli/src/shared/services/slim-images.ts:61 image-resolution claude+codex Pooler and Vector resolve through catalog entries for upstream mirrors instead of the intended CLI slim repositories, so their slim runtime adaptations never activate and the new assertions fail.
🟠 MAJOR apps/cli-go/pkg/config/templates/Dockerfile:14 dependency-management claude The manifest downgrades Realtime and Logflare and leaves the stack catalog unsynchronized with all five changed service pins.
🟠 MAJOR apps/cli/src/legacy/commands/db/shared/legacy-pgdelta.seam.integration.test.ts:309 test-correctness claude The new pg-delta image-current tests hardcode the old Postgres tag, making the success case fail and preventing the family-mismatch case from isolating the behavior named by the test.
🟠 MAJOR apps/cli/src/legacy/shared/db-bootstrap/db-setup.ts:24 runtime-compatibility claude+codex The slim one-shot migration implementation contradicts its declared image contracts: Storage still runs migrate-call.js in the slim image said not to contain it, and Auth retains the docker.io gotrue argv despite documenting a baked auth entrypoint.
🟠 MAJOR apps/cli/src/legacy/commands/start/services/gotrue.service.ts:657 readiness codex Slim Auth, pg-meta, and Studio lose their application-level readiness checks and are treated as ready as soon as their processes are running.
🟡 MINOR apps/cli/src/legacy/shared/legacy-edge-runtime-image.ts:68 documentation claude+codex The pg-delta shell runner is slim-aware even though its call-site comment and multiple SIDE_EFFECTS documents say it remains on docker.io.
🟡 MINOR apps/cli/src/legacy/commands/start/services/vector.service.ts:351 startup-ordering claude The intended slim Vector branch removes the existing wait-for-Logflare gate before starting Vector.
⚪ NIT apps/cli/src/legacy/commands/start/services/storage.service.ts:210 dead-code claude The change leaves unnecessary single-consumer abstractions and a no-op object spread from reverted slim variants.

Stats

Claude findings: 7 · Codex findings: 4 · Confirmed: 8 · Refuted: 0 · Uncertain: 0


Models: claude-opus-5 + gpt-5.6-sol · Trigger: manual · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.


const rawTag = image.slice(tagSeparator + 1);
const tag = alias === "vector" ? rawTag.replace(/-alpine$/, "") : rawTag;
return dockerImageForService(service, tag);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 MAJOR · image-resolution · source: claude+codex

Pooler and Vector resolve through catalog entries for upstream mirrors instead of the intended CLI slim repositories, so their slim runtime adaptations never activate and the new assertions fail.

Evidence: slim-images.ts:21-22 maps the aliases to pooler/vector and :61 calls dockerImageForService. ServiceCatalog.ts:295 and :307 resolve those services as ghcr.io/supabase/vector and ghcr.io/supabase/supavisor, while slim-images.ts:120 recognizes only ghcr.io/supabase/cli/. slim-images.unit.test.ts:36-37 expects CLI pooler/vector repositories.

Suggested fix: Model the slim repository and tag scheme explicitly instead of reusing the upstream-mirror catalog entries, then retain Vector's intended tag normalization and update the tests accordingly.

Comment on lines +14 to +16
FROM supabase/realtime:v2.129.3 AS realtime
FROM supabase/storage-api:v1.72.1 AS storage
FROM supabase/logflare:1.50.4 AS logflare

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 MAJOR · dependency-management · source: claude

The manifest downgrades Realtime and Logflare and leaves the stack catalog unsynchronized with all five changed service pins.

Evidence: Dockerfile:14 and :16 contain realtime v2.129.3 and logflare 1.50.4, whereas the diff removes v2.129.9 and 1.50.6. Dockerfile:2, :12, and :15 also change Postgres, Pooler, and Storage, but ServiceCatalog.ts still declares 17.6.1.165, 2.9.7, and v1.71.0 along with the removed Realtime/Logflare versions.

Suggested fix: Resolve whether the two downgrades are intentional, restore the current pins if not, and run the repository's sync:versions script so ServiceCatalog.ts matches the Dockerfile manifest.

Comment on lines +309 to +315
const { layer } = setup(dir, { dbInspectImage: "supabase/postgres:17.6.1.165" });
return Effect.gen(function* () {
const seam = yield* LegacyDeclarativeSeam;
const exit = yield* seam.ensureLocalPostgresImageCurrent().pipe(Effect.exit);
expect(Exit.isSuccess(exit)).toBe(true);
rmSync(dir, { recursive: true, force: true });
}).pipe(Effect.provide(layer));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 MAJOR · test-correctness · source: claude

The new pg-delta image-current tests hardcode the old Postgres tag, making the success case fail and preventing the family-mismatch case from isolating the behavior named by the test.

Evidence: legacy-pgdelta.seam.integration.test.ts:292 and :309 use 17.6.1.165, while Dockerfile:2 now pins 17.6.1.166. The default major version is 17, legacyResolveDbImage selects the Dockerfile image, and legacy-pgdelta.seam.layer.ts:270-273 requires matching tags.

Suggested fix: Build both fixtures from dockerfileServiceImageRaw("pg") and change only the image family in the family-mismatch case.

Comment on lines +24 to +26
* Slim Storage has no `migrate-call.js`, so that job uses the docker.io
* storage image. Slim Auth still runs a one-shot `migrate` under the baked
* `auth` ENTRYPOINT.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 MAJOR · runtime-compatibility · source: claude+codex

The slim one-shot migration implementation contradicts its declared image contracts: Storage still runs migrate-call.js in the slim image said not to contain it, and Auth retains the docker.io gotrue argv despite documenting a baked auth entrypoint.

Evidence: db-setup.ts:24-26 declares the Storage docker.io fallback and Auth entrypoint behavior, but :865 uses input.images.storage with ["node","dist/scripts/migrate-call.js"] at :871, while :876 uses input.images.auth with ["gotrue","migrate"] at :889. db-setup.unit.test.ts:392-399 explicitly locks in those contradictory slim-image commands.

Suggested fix: Use the corresponding docker.io Storage image for that one-shot, and provide the slim Auth entrypoint only the migrate argument if that is its actual contract. Update the unit test to assert the compatible variants.

Comment on lines +657 to +660
// Distroless slim auth has no wget/curl/sh. Omitting the Docker healthcheck
// makes `legacyCheckContainerReady` treat `Running` as ready (same as PostgREST).
...(slim
? {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 MAJOR · readiness · source: codex

Slim Auth, pg-meta, and Studio lose their application-level readiness checks and are treated as ready as soon as their processes are running.

Evidence: gotrue.service.ts:657-660, pg-meta.service.ts:68-71, and studio.service.ts:190-193 omit healthchecks for slim references. health-check.ts:225-233 accepts any running container with no health state, while its HTTP gateway exceptions at :354-361 cover only PostgREST and Edge Runtime.

Suggested fix: Add host- or gateway-based HTTP readiness probes for the three distroless services instead of relying solely on container process state.

* Same resolution as {@link legacyResolveEdgeRuntimeImage}. The slim image now
* ships `sh`, so shell-entrypoint callers no longer need a docker.io pin.
*/
export const legacyResolveEdgeRuntimeShellImage = legacyResolveEdgeRuntimeImage;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MINOR · documentation · source: claude+codex

The pg-delta shell runner is slim-aware even though its call-site comment and multiple SIDE_EFFECTS documents say it remains on docker.io.

Evidence: legacy-edge-runtime-image.ts:68 aliases the shell resolver to the slim-aware resolver, and legacy-edge-runtime-script.layer.ts:107 uses it. bootstrap/SIDE_EFFECTS.md:83, db/push/SIDE_EFFECTS.md:57, db/reset/SIDE_EFFECTS.md:143, and start/SIDE_EFFECTS.md:180 state that the runner stays on docker.io.

Suggested fix: Determine the actual slim Edge Runtime shell contract, then either keep the slim-aware resolver and correct the stale comments/docs or restore a docker.io-only shell resolver.

Comment on lines +351 to +365
return legacyUsesSlimRuntime(input.image)
? {
image: input.image,
containerName: input.containerName,
env: input.dockerSocketPlan.env,
cmd: ["--config", "/etc/vector/vector.yaml"],
secretFiles: [{ containerPath: "/etc/vector/vector.yaml", content: vectorYaml }],
binds: input.dockerSocketPlan.binds,
healthcheck: legacySlimBusyboxWgetHealthcheck("http://127.0.0.1:9001/health"),
restartPolicy: "unless-stopped",
securityOpt: input.dockerSocketPlan.securityOpt,
networkId: input.networkId,
networkAliases: LEGACY_VECTOR_NETWORK_ALIASES,
labels: {},
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MINOR · startup-ordering · source: claude

The intended slim Vector branch removes the existing wait-for-Logflare gate before starting Vector.

Evidence: vector.service.ts:291-298 builds the docker.io entrypoint with an until-wget loop against Logflare. The slim branch at :351-365 starts Vector directly with its config and contains no equivalent gate; start.handler.ts creates Logflare immediately before Vector without an intervening readiness wait.

Suggested fix: Retain an equivalent Logflare readiness gate for the slim path, or establish and document that Vector's sink retry behavior makes it unnecessary.

Comment on lines +210 to +228
const env = {
...legacyBuildStorageEnv({
targetMigration: input.targetMigration,
anonKey: input.anonKey,
serviceRoleKey: input.serviceRoleKey,
jwtSecret: input.jwtSecret,
jwks: input.jwks,
dbHost: legacyServiceContainerName("db", input.projectId),
dbPassword: legacyStartInternalDbPassword(input.dbUrl),
fileSizeLimit: input.fileSizeLimit,
s3Region: input.s3Region,
s3AccessKeyId: input.s3AccessKeyId,
s3SecretAccessKey: input.s3SecretAccessKey,
imageTransformationEnabled: input.imageTransformationEnabled,
imgproxyHost: legacyServiceContainerName("imgproxy", input.projectId),
s3ProtocolEnabled: input.s3ProtocolEnabled,
vectorBucketsEnabled: input.vectorBucketsEnabled,
projectEnvValues: input.projectEnvValues,
}),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚪ NIT · dead-code · source: claude

The change leaves unnecessary single-consumer abstractions and a no-op object spread from reverted slim variants.

Evidence: storage.service.ts:210-228 spreads the sole legacyBuildStorageEnv result into a new object without modifying it. postgres.service.ts:467-475 introduces an argv constant used only to join one exported string, and functions-docker.ts:149-156 delegates a fixed ["run","--rm"] prefix through a private helper with no other caller.

Suggested fix: Use legacyBuildStorageEnv directly and collapse the single-consumer wrappers unless a second variant is actually required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants