feat(cli): port db push, db reset, and db start to native TypeScript - #5715
Conversation
Pure 1:1 port of Go's FindPendingMigrations + GetPendingMigrations suggestion strings (internal/migration/up, pkg/migration/apply), the foundation for the native legacy `db push` handler. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nv8pAJ695qfNs5Btbv5v7h
Port Go's GetPendingSeeds/SeedData with a faithful fs.Glob/path.Match matcher, sha256 dirty detection against supabase_migrations.seed_files, and transactional seed application (pkg/migration/seed.go, file.go). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nv8pAJ695qfNs5Btbv5v7h
Port vault.UpsertVaultSecrets (literal/env-skip parity) and the ApplyMigrations / SeedGlobals stderr-emitting loops, extracting a shared transactional batch core from legacyApplyMigrationFile. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nv8pAJ695qfNs5Btbv5v7h
Replace the Go-proxy shim with a native Effect handler porting internal/db/push/push.go: target mutex, config-driven skip messages, pending-migration/seed/roles collection, dry-run, confirm prompts, vault upsert + migration/seed/globals apply, and three output modes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nv8pAJ695qfNs5Btbv5v7h
Cover up-to-date, apply+confirm, decline/cancel, dry-run, missing-local and missing-remote classification, --include-all, config-disabled skips, seed apply/up-to-date/disabled, and custom roles. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nv8pAJ695qfNs5Btbv5v7h
Add vault upsert (update+create), seed dirty/no-table/glob-warning, linked-path, no-target-flag default, apply-error, parse-error, and remotes-override cases. Relocate vault document parsing into the vault module with unit coverage. The lone uncovered branch is Go's unreachable afero.Exists error wrap. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nv8pAJ695qfNs5Btbv5v7h
Rewrite push/SIDE_EFFECTS.md for the native implementation and flip db push to `ported` in go-cli-porting-status.md. De-export internal-only helpers flagged by knip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nv8pAJ695qfNs5Btbv5v7h
Port internal/db/reset/reset.go's remote path: --version/--last validation, drop user schemas (embedded drop.sql), vault upsert, and MigrateAndSeed (partial migrations + seed). The local and --experimental paths delegate to the Go binary (telemetry-disabled) as the documented interim until the container-bootstrap seam lands. 19 integration tests, handler at 98.7% branch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nv8pAJ695qfNs5Btbv5v7h
Rewrite reset/SIDE_EFFECTS.md for the native remote path and the local/experimental Go delegation; mark db reset `partial` in go-cli-porting-status.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nv8pAJ695qfNs5Btbv5v7h
Self-contained handoff covering the container-bootstrap work remaining (hidden __db-bootstrap Go seam + native orchestration), exact Go behavior to match, reusable helpers, build/test commands, and parity gotchas. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nv8pAJ695qfNs5Btbv5v7h
Port `supabase db start` to a native TypeScript handler. The handler validates
config, runs Go's `AssertSupabaseDbIsRunning` check (printing the "already
running" line), and otherwise delegates the container bootstrap to a new hidden
Go `db __db-bootstrap` seam that mirrors `db __shadow`: it exposes the
un-ported container primitives (StartDatabase + DockerRemoveAll cleanup, the
PG14/PG15 reset recreate, and the storage health gate) behind `--mode`.
No status table and no `cli_stack_started` event — those belong to the
top-level `supabase start`, not `db start`. `--output-format json` emits a
structured `{ status }` result; progress stays on stderr.
The TS seam service/layer (`legacy-db-bootstrap.seam.*`) shells out to the
bundled binary with telemetry disabled and stderr inherited. The recreate /
await-storage modes are landed here for the upcoming native db reset --local.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the Go delegation for local `db reset` with a native handler: assert the db container is running, print "Resetting local database…", recreate the container + migrate + seed via the hidden Go `db __db-bootstrap --mode recreate` seam (forwarding `--version`/`--no-seed`), seed buckets through the storage health gate, and print "Finished supabase db reset on branch <branch>.". Extract the seed-buckets local path into `legacySeedBucketsRun` so reset reuses the exact bucket-seed logic Go invokes via `buckets.Run(ctx, "", false, fsys)`, with its machine-summary suppressed for the reset caller. Add a `--no-seed` flag to the recreate seam mode so it disables MigrateAndSeed's seed like `db reset`. Only the niche `--experimental` remote schema-files path still delegates to the Go binary. Reset handler integration coverage is 98.7% branch (one unreachable defensive guard, matching the push/reset precedent). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Real-subprocess golden-path e2e for the native db start / db reset commands, matching the Docker-free convention of the sibling legacy e2e tests (db diff, seed buckets): db reset's pre-split flag validations (mutually-exclusive targets, invalid --version, --version+--last), and db start's config-parse failure that aborts before the running check. Full container behavior is covered by the integration suites with the bootstrap seam mocked. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Stage 3 work (native db start, native db reset --local, the hidden Go db __db-bootstrap seam) is implemented, tested, and documented in the command SIDE_EFFECTS.md files and go-cli-porting-status.md. The handoff note described this as remaining/unvalidated work and is now obsolete. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ocal Covers the one boundary the integration suites mock — the db __db-bootstrap Go seam driving real Docker. Boots an actual local Postgres container and exercises db start (fresh), db start (already-running, exit 0), and db reset --local (recreate + branch line), tearing the stack down in afterAll. Gated behind SUPABASE_E2E_DOCKER=1 (skipped by default) so it never runs in the normal feedback loop / default e2e suite. Validated locally against Docker 29.4.0 (3/3 pass, ~60s with images cached). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…noyce-078f0e # Conflicts: # apps/cli-go/cmd/db.go # apps/cli/docs/go-cli-porting-status.md # apps/cli/src/legacy/commands/db/reset/SIDE_EFFECTS.md # apps/cli/src/legacy/commands/db/reset/reset.handler.ts # apps/cli/src/legacy/commands/db/reset/reset.integration.test.ts
Adds a live-suite test in apps/cli-e2e that boots a real local Postgres container via the compiled CLI and drives db start (fresh), db start (already-running, idempotent), and db reset --local (recreate + branch line), stopping the stack in finally. Runs through the cli-e2e harness against the real Docker socket the live setup wires up, exercising the hidden db __db-bootstrap Go seam end-to-end across the go + ts-legacy targets (skipped for ts-next, which has no db group). Inert on replay/PR runs (testLive skips unless CLI_E2E_MODE=live); runs under pnpm --filter @supabase/cli-e2e test:e2e:live. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the remote (`--db-url` over the staging session pooler) leg of `db reset` to the live suite: drop user schemas → re-apply a local migration → seed against a real Postgres, verified via `migration list`. `db start` has no remote leg. Fold the local-leg coverage (db start / db reset --local, real Docker seam) and the new remote leg into one `db-reset-start.live.e2e.test.ts`, both gated to skip the `ts-next` target (no `db` group there). Remove the `SUPABASE_E2E_DOCKER`-gated apps/cli live test: `*.live` tests belong in the cli-e2e live suite, which already runs only in Docker-available environments (gated by `CLI_E2E_MODE=live`); a separate env flag was the wrong pattern and duplicated this coverage. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@codex review |
`go generate` (oapi-codegen against the live Management API spec) adds the new `storage.purge_cache` entitlement and the `Features.PurgeCache` field on the storage config request/response. Regenerate `pkg/api/types.gen.go` and add the matching `PurgeCache` field to the hand-built `UpdateStorageConfigBody.Features` literal in `pkg/config/storage.go` so the package still compiles. Fixes the Codegen CI check (`go generate` left the committed `pkg` dirty). Pure spec sync — `PurgeCache` is nil + omitempty, so serialized request bodies are unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 73252bd3a5
ℹ️ 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".
- Honor SUPABASE_EXPERIMENTAL (not just --experimental) on db reset via legacyResolveExperimental, and forward --experimental into the db __db-bootstrap seam so the local recreate's MigrateAndSeed takes Go's experimental schema-file path on a versionless reset/start. - Preserve absolute seed paths in legacyGetPendingSeeds/globOne/legacySeedData (Go only prefixes relative patterns with the supabase dir). - Reject a negative --last (Go declares it UintVar; cobra rejects at parse). - Create the supabase_migrations schema before seed_files, matching Go's CreateSeedTable, so seed-only runs don't fail on a missing schema. - Keep bucket seeding non-interactive during db reset (Go's buckets.Run(ctx, "", false, fsys)) via a new interactive flag threaded through legacySeedBucketsRun and legacyPromptYesNo. - Cache the linked project before the delegated --experimental reset (Go's PersistentPostRun runs even though the delegated child has telemetry disabled). - Record --sql-paths in reset telemetry (flags map + value-consuming set). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@codex review again |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
`go generate` adds the `api.members.roles` entitlement and the `DbPoolAcquisitionTimeout` field on the PostgREST config responses. Regenerate `pkg/api/types.gen.go` to keep the Codegen check clean. Additive named-struct fields only — no hand-written literals affected, both Go modules build. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…rom-backup Addresses a Codex review round on the native db reset/start port: - Delegated experimental reset now forwards the target from the resolved connType, so `db reset --experimental --linked=false` (Cobra Changed → linked) delegates with `--linked` instead of letting the Go child fall back to a local reset (P1, wrong-database). - Resolve the experimental gate with the nested project `.env` (legacyResolveExperimentalWithProjectEnv), so `SUPABASE_EXPERIMENTAL` in supabase/.env selects the experimental path like Go's loadNestedEnv. - Pass the project-env-resolved `yes` into legacySeedBucketsRun so local reset's bucket/vector/analytics pruning honors SUPABASE_YES from supabase/.env. - Add `db reset` to run.ts selfManagedSignalCommands so Ctrl-C stays blocked on the bootstrap child instead of racing the global handler. - Treat an empty `db start --from-backup ""` as a no-backup start (Go's len == 0) rather than joining it to the caller cwd. - Attach Go's validateDbResetSeedFlags CmdSuggestion to the --no-seed/--sql-paths seed-flag conflict errors (renderer already prints Suggestion:). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
When config.toml contains [db] password = "secret", Go does not use it for local connections: the db.Password field is tagged json:"-" and config loading uses UnmarshalExact, so this is rejected as an invalid config key rather than changing the local Postgres password. This reader accepts the key and returns it as the local password, so native paths such as db push --local or a passwordless local --db-url can try to authenticate with a password that the Go-started database never used; reject this key like Go or keep the fixed default.
When a migration contains statements such as CREATE INDEX CONCURRENTLY or VACUUM, this branch flushes the current batch and runs the statement outside the transaction, then records the migration. The Go CLI path used by db push/db reset still queues every statement into one pgconn.Batch and relies on ExecBatch being implicitly transactional (apps/cli-go/pkg/migration/file.go:75-88), so the same migration fails and is not recorded. Until the Go side has the same behavior, native push/reset can apply migrations that the legacy CLI would reject, leaving history diverged across implementations.
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7e5c1103bd
ℹ️ 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".
…ject_id
Addresses two Codex findings on the native db reset port:
- Forward the parent's resolved `--yes` into the experimental-reset delegate argv
(`--yes=${yes}`). Go's bound `--yes` beats AutomaticEnv, so `--yes=false` now
overrides an inherited SUPABASE_YES=true and the Go child no longer auto-confirms
a reset the user protected (P1); `--yes=true` is honored even in machine mode.
- Reject an explicit empty top-level `project_id = ""` in legacyCheckDbToml with
Go's "Missing required field in config: project_id" (config.Validate parity), so a
native remote reset aborts before legacyDropUserSchemas instead of dropping on a
config Go rejects. Absent project_id stays tolerated (deferred broader case).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e590ac2ca1
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
cli/apps/cli/src/legacy/shared/legacy-db-config.toml-read.ts
Lines 898 to 900 in cab2170
When an auth validation depends on fields supplied via Go-supported env overrides—for example [auth.captcha] enabled = true with SUPABASE_AUTH_CAPTCHA_PROVIDER and SUPABASE_AUTH_CAPTCHA_SECRET in the shell or supabase/.env—this helper only reads the TOML value and returns empty for absent keys. Go's config.Load uses Viper AutomaticEnv/ExperimentalBindStruct before Validate, so that config loads successfully; the native db push/db reset preflight now fails with Missing required field... and blocks valid projects. Thread the SUPABASE_AUTH_* override lookup through str and the matching gate helper before treating fields as absent.
cli/apps/cli/src/legacy/shared/legacy-migration-apply.ts
Lines 163 to 166 in cab2170
When a migration contains a statement like CREATE INDEX CONCURRENTLY or VACUUM, this branch flushes the current batch and executes that statement outside the surrounding transaction, then later inserts the migration history row. The current Go CLI still queues every statement and the history insert into one pgconn.Batch in MigrationFile.ExecBatch, so those files fail instead of being partially applied or recorded; the native db push/remote reset path can now mutate the database and mark a migration applied that Go would reject. Remove this standalone path unless the Go engine is updated in the same change.
ℹ️ 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".
Manual results
|
…ets hoist merge develop's db push/reset/start port (#5715) hoisted the seed-buckets config load out of buckets.handler.ts and into the shared legacySeedBucketsRun (also used by db reset --local), which superseded the inline goViperCompat opt-in added on this branch. Carry the opt-in over to the new call site so seed buckets and db reset --local keep Go-parity config semantics.
…reate (supabase#5840) ## What changed `supabase db reset --local` now runs full Go-parity config validation (`legacyCheckDbToml`, matching Go's `flags.LoadConfig`) at the top of its local branch, before `AssertSupabaseDbIsRunning`/the destructive container recreate — the same pre-destructive-work gate `db start` and `db push` already have. A broken `supabase/config.toml` (unterminated TOML, an undecryptable `encrypted:` vault secret, an unparseable `env(VAR)` boolean, an explicit empty `project_id`) now aborts before the local database is ever recreated, instead of only surfacing later (or never) during bucket seeding. A genuinely **missing** `config.toml` is still tolerated, unchanged: Go's `Config.Load` defaults `project_id` to the current directory's basename when no config file exists, so `Validate` never rejects it — this is exactly the mechanism the `cli-e2e` parity suite relies on when it runs `db push --local` / `db reset --local` from a project with no `config.toml`. Only a config file that is *present but broken* is now caught earlier. `db reset --local`'s post-recreate bucket-seeding step catches a `LegacySeedConfigLoadError` from its own config reload and warns-and-continues rather than failing the command. An earlier version of this PR removed that fallback (reasoning: Go loads `config.toml` exactly once into memory, so it can never reach "recreate succeeded, then a later reload of the same file fails"). A Codex review on this PR caught that this doesn't transfer to the TS port: the new pre-recreate gate resolves `env(VAR)` via the Go-parity nested-env reader (sees `supabase/.env.development`, the project root, etc.), but the post-recreate reload goes through `@supabase/config`'s narrower loader (`supabase/.env`/`.env.local` only) — so a genuinely Go-valid config can pass the gate and the real recreate, then hard-fail only at the later, narrower reload, after the local database has already been dropped and rebuilt. The fallback is restored, with a comment naming the actual env-file-set gap instead of generic "loader strictness." ## Why Linear [CLI-1877](https://linear.app/supabase/issue/CLI-1877/reject-directlocal-db-push-db-reset-without-project-config-go): a Codex P1 finding on supabase#5715 flagged that the native `db reset`/`db push`/`db start` port tolerates a missing project config more broadly than Go, and that `db reset --local`'s config validation happened too late relative to the destructive recreate. Investigation (via `go-parity-auditor`, cross-checked against the compiled Go binary) found the issue's literal premise — "reject direct/local db push + db reset without project config" — does **not** match current Go behavior: Go tolerates a missing config file by defaulting `project_id` to the cwd basename, and the TS port already matches that. Implementing a hard reject-on-missing-config would have been a *new* divergence from Go and would have broken the currently-green `cli-e2e` parity tests (exactly the regression risk the issue's own "deferred from supabase#5715" note called out). `db start`'s and `db push`'s validation-ordering guarantees were also found to already be correct and already covered by existing tests. The one real, narrow gap was `db reset --local`'s ordering guarantee being implicit — buried inside a config resolver whose test double bypasses it entirely — rather than explicit and independently testable. This PR closes that gap. ## Test plan - Added regression tests in `reset.integration.test.ts` for a local reset: malformed config.toml, an unparseable boolean, an undecryptable vault secret, and an explicit empty `project_id`, all asserting the destructive recreate never runs; a test pinning that a broken config wins over the "not running" error; and a test confirming a genuinely missing config.toml is still tolerated. - `pnpm check:all` and the full `apps/cli` unit + integration suite (4758 tests) pass. - Ran the 4-agent `review-changes` procedure (architect/engineer/security/DX) against the diff and worked every finding; see "Judgement calls" below for what a `review-adjudicator` settled and what remains a documented, deliberate trade-off. ## Judgement calls / open notes - The `review-changes` engineer pass flagged that rewriting a pre-existing test orphaned the bucket-seed warn-and-skip branch, regressing coverage. A `review-adjudicator` pass at the time concluded there was no Go-parity reason to keep that fallback and recommended deleting it (done in the second commit) — a subsequent Codex review on the open PR found a concrete Go-valid config shape (an `env(VAR)` value sourced from `supabase/.env.development`) that the deletion broke, so the fallback was restored with an accurate comment (see "What changed" above). - The new pre-recreate gate is currently unreachable in production (the resolver's own internal read already validates first and would already reject a broken config identically) — it exists for defense-in-depth and so the "validate before destroy" guarantee is enforced directly by the handler and stays covered by a test even if the resolver is ever mocked or refactored to stop validating. Both the architect and DX review passes flagged this as worth calling out explicitly rather than as a blocking issue. - Not addressed here (flagged by review but out of scope): `LegacyDbConfigResolver.resolve` could return the validated config it already reads, so callers stop re-parsing `config.toml` up to 2-3 times on the local reset path. This is a pre-existing, codebase-wide pattern (`db push` does the same double-read), not something introduced by this PR, and is better done as its own resolver-contract refactor. Fixes CLI-1877.
…abled remote precedence (CLI-1878) (supabase#5839) ## What Closes the remaining gaps in [CLI-1878](https://linear.app/supabase/issue/CLI-1878/legacy-shell-full-viper-env-override-semantics-project-env-remote): full viper env-override semantics (project `.env`, remote precedence, malformed bools) in the TS legacy shell. A `go-parity-auditor` pass determined most of the issue's original claims had already been fixed by an earlier PR (supabase#5715) — project-`.env`-aware `SUPABASE_YES`/`SUPABASE_EXPERIMENTAL` resolvers, remote-config precedence, malformed-bool-fails-the-load, explicit-flag-beats-env, and case-agnostic `env(...)` resolution all already exist for `db push`/`db reset`/`db pull`/`config push`/`migration down`/`repair`/declarative-schema. This PR closes the **5 concrete gaps** that pass left open: 1. **`gen signing-key`** — the overwrite-confirmation prompt only consulted the shell env for `SUPABASE_YES`. Go's `flags.LoadConfig` loads the project `.env` before the prompt (`signingkeys.go:99,130`). 2. **`storage rm`** — same gap for the delete-confirmation prompt (both the `--local` and default `--linked` branches of Go's `ParseDatabaseConfig` load the project `.env` first). 3. **`migration fetch`** — same gap for the migrations-dir overwrite prompt (defaults to `--linked`, same `ParseDatabaseConfig` path). 4. **standalone `seed buckets`** — its fallback `yes` resolution (used when `db reset` doesn't pass a pre-resolved value) had the same gap. `db reset`'s own passthrough was already correct. 5. **`[remotes.*].auth.enabled` remote precedence** — this key was missing from `LEGACY_ENV_OVERRIDABLE_KEYS`, so a linked remote's `auth.enabled` TOML value could lose to a `SUPABASE_AUTH_ENABLED` env var instead of winning, unlike every other allowlisted key (Go's `mergeRemoteConfig` applies the whole matched block above `AutomaticEnv`). Each of the 4 handler fixes follows the existing `legacyLoadProjectEnv` + `legacyResolveYesWithProjectEnv` pattern already used by `db push`/`config push`/`migration down`/`repair`. ### Fixed along the way - `migration fetch`'s new project-`.env` load initially ran *before* the `[db-url linked local]` flag-conflict check — an ordering regression relative to Go and sibling `migration down`/`repair` (caught by `architect-reviewer`). Reordered so the flag check runs first; added a regression test that fails without the fix. ## Behavior changes to be aware of - `gen signing-key`, `storage rm`, `migration fetch`, and `seed buckets` now honor `SUPABASE_YES` set only in `supabase/.env`/`.env.local`/`.env.<env>[.local]` (previously they only saw the shell env). This is a pure Go-parity fix, but on an earlier build of this TS legacy shell it was inert — a stale `SUPABASE_YES=true` left in a project's `.env` will now silently auto-confirm these destructive prompts. - A linked project's `[remotes.<name>].auth.enabled` TOML value now correctly beats a `SUPABASE_AUTH_ENABLED` env var (previously the reverse). If anything relied on the env var overriding a remote block's explicit `auth.enabled`, that no longer happens. ## Test plan - `bun run test:core` — all unit + integration tests green (300 tests across the touched files, full suite unaffected). - `bun run check:all` — types/lint/fmt/knip clean. - New regression tests (integration, per this workspace's testing pyramid): - `signing-key.integration.test.ts` — project-`.env` `SUPABASE_YES` auto-confirms the overwrite even with a piped `n` (defensively clears any leaked shell `SUPABASE_YES` first). - `rm.integration.test.ts` — same, for the delete confirmation. - `buckets.integration.test.ts` — same, for the standalone `seed buckets` overwrite prompt. - `fetch.integration.test.ts` — same, for the migrations-dir overwrite prompt; plus a new test locking in the flag-conflict-before-env-read ordering fix (verified it fails without the reorder). - `legacy-db-config.toml-read.unit.test.ts` — 2 new unit tests for `auth.enabled`: a matched remote block beats the env var, and a control case where the env var still wins when the block omits the key. - Relocated one pre-existing test's fixture (`fetch.integration.test.ts`, "reports a write failure"): the file-collision now lives at `<workdir>/supabase/migrations` instead of `<workdir>/supabase` itself, since the latter would break the new project-`.env` read before ever reaching the `mkdir` under test. Verified this preserves the original test's coverage. ## Judgement calls deliberately left open - **`[y/N] y` echo doesn't say *why* it auto-confirmed.** `supabase-dx-reviewer` flagged that the prompt echo is byte-identical whether the answer came from `--yes`, the shell env, or a forgotten project `.env` value — but explicitly recommended *not* annotating it, since that would diverge from Go's byte-identical `console.PromptYesNo` output (this is a strict 1:1 port). Not changed here; a source annotation would need to land in the Go CLI first if ever desired. - **DB-bootstrap seam explicit `--experimental=false` forwarding.** `go-parity-auditor` flagged (but could not fully confirm, since it didn't trace the hidden `db __db-bootstrap` subprocess) that `legacy-db-bootstrap.seam.layer.ts` forwards `--experimental` to the Go child only when true, never an explicit false — for `db reset --experimental=false` with `SUPABASE_EXPERIMENTAL=true` inherited by the child, the child might re-resolve `true` independently. Flagged as a caveat, not a confirmed gap; out of scope here. - **`storage.enabled`/`realtime.enabled` don't read any `SUPABASE_*` env override at all** in `legacy-db-config.toml-read.ts`, unlike `auth.enabled`. This is a latent divergence noted by `go-parity-auditor` but is outside CLI-1878's 5 named items; left as a separate follow-up. 🤖 Generated with the `issue-autopilot` skill.
## TL;DR: Ports the catalog cache to native TS the recent `db push` port supabase#5715 <br>left this Go feature out entirely this restores/extends it.... ## What's Introduced? Basically, we're porting Go's pg-delta migrations-catalog cache to native TS, <br>and for that we've introduced: `legacyTryCacheMigrationsCatalog` in `legacy-pgdelta.cache.ts` (gated on pg-delta being enabled, <br>reusing the `legacyExportCatalogPgDelta` so it can't inherit the `/workspace` mount bug fixed separately on the Go) <br>the corresponding `edge-runtime/docker/ssl-probe` layer wiring in `push.layers.ts`, the actual call site in `push.handler.ts` (after a successful migration apply, warns and never fails the push on error) also added integration + unit test coverage in `push.integration.test.ts` and `legacy-pgdelta.cache.unit.test.ts` <br>for the enabled/disabled/failure paths and the new pure helpers.... ## Ref: * closes supabase#5921 * Followup to: [supabase#5929](<supabase#5929>) * Extends: supabase#5715
Ports the
db push,db reset, anddb startcommands of the legacy CLI shell from Go-binary proxies to native TypeScript (CLI-1325), and introduces a hidden Go seam for the container-bootstrap primitives that aren't ported.What changed
db push— fully native: pending-migration reconciliation, seed-file ops withseed_fileshash tracking,[db.vault]upsert,--include-roles/--include-seed/--dry-run, against local / linked /--db-url.db reset— native on both legs:--linked/ remote--db-url): drop user schemas → vault upsert → migrate + seed,--version/--last, and the Go-parity--sql-pathsseed override (merged from develop, mutually exclusive with--no-seed).--local/ local--db-url): running check,Resetting local database…, container recreate + migrate + seed via the seam, storage-gated bucket seeding (reuses the portedseed bucketscore), and theFinished … on branch <branch>.line.--experimentalremote schema-files path still delegates to the Go binary.db start— native: config validation, theAssertSupabaseDbIsRunningcheck (prints Go's "already running" line), else container bootstrap via the seam. No status table and nocli_stack_started— those belong to the top-levelsupabase start, notdb start.Hidden Go seam (
db __db-bootstrap) — mirrors the existingdb __shadowseam. Exposes the un-ported container primitives (StartDatabase+DockerRemoveAllcleanup, the PG14/PG15 reset recreate, the storage health gate) behind--mode {start|recreate|await-storage}. The TS side orchestrates everything else (messages, version resolution, bucket seeding, the git-branch line, telemetry,--output-formatshaping); the seam runs with telemetry disabled and stderr inherited, like__shadow.Config loading (review follow-ups) —
db push/db reset/db startloadconfig.tomlthrough the legacy Go-parity reader (legacyCheckDbToml, Go'sflags.LoadConfig→config.Load+Validate) rather than@supabase/config, so their config semantics match the Go CLI exactly:[db.seed] enabled = "env(SEED_ENABLED)") load like Go (env-expand →strconv.ParseBool) instead of failing with a parse error.[remotes.<ref>]block'sdb.migrations.enabled/db.seed.enabledbeats theSUPABASE_DB_*_ENABLEDenv var (Go'sv.Setoverride tier sits above AutomaticEnv), closing the last remote-vs-env precedence gap.encrypted:[db.vault]secrets are decrypted at config-load time with the shell and project-.envDOTENV_PRIVATE_KEY*keys and fail fast (before any connect / schema drop) on an undecryptable value, matching Go'sDecryptSecretHookFunc.sql_paths(config and--sql-paths) resolve once to Go's config-load form;db startvalidates config before the already-running check.Malformed config now surfaces the reader's Go message (
failed to load config), consistent withdb diff/dump/pull/migration.Why
db start/db reset --localneed container lifecycle (create/recreate, image pull, health checks, init schema, service restarts) that is impractical to reimplement in TS. The seam keeps that lifecycle in Go while moving orchestration, output parity, telemetry, and--output-formathandling to native TS — matching the approach already used fordb diff/db pull.Reviewer notes
db reset/db startboundary the in-process integration suites mock; it's covered end-to-end by the cli-e2e live suite (db-reset-start.live.e2e.test.ts, run viapnpm --filter @supabase/cli-e2e test:e2e:live), which exercises the local leg against a real Docker socket and the remotedb resetleg against the staging session pooler. Bothdescribes skip thets-nexttarget (the next shell has nodbgroup).db reset --localrecreate forwards--no-seed/--sql-pathsto the seam, which applies them via the sameapplyDbResetSeedFlagshelperdb resetuses, so seed handling stays identical across local and remote.supabase-gobinary must be rebuilt (pnpm build:go-sidecarcopies it intodist/) since the seam adds thedb __db-bootstrapcommand.docs/go-cli-porting-status.mdflipsdb push/db reset/db starttoported; each command'sSIDE_EFFECTS.mddocuments the files, subprocesses, DB mutations, env vars, and exit codes.🤖 Generated with Claude Code