Skip to content

chore(repo): sync develop into next - #7294

Merged
supabase-cli-releaser[bot] merged 25 commits into
nextfrom
sync/develop-into-next
Oct 23, 2026
Merged

supabase-cli-releaser[bot] merged 25 commits into
nextfrom
sync/develop-into-next

Conversation

@supabase-cli-releaser

Copy link
Copy Markdown
Contributor

Merging develop into next conflicts. This branch starts at the tip of develop (531c926); next is at 1fa6164.

Conflicting files:

  • apps/cli-go/api/v1-openapi.yaml
  • apps/cli-go/cmd/db.go
  • apps/cli-go/cmd/root.go
  • apps/cli-go/cmd/root_test.go
  • apps/cli-go/internal/telemetry/project.go
  • apps/cli-go/internal/telemetry/project_test.go
  • apps/cli-go/internal/utils/flags/project_ref.go
  • apps/cli-go/internal/utils/flags/project_ref_test.go
  • apps/cli-go/pkg/api/types.gen.go
  • apps/cli-go/pkg/config/config.go
  • apps/cli-go/pkg/config/config_test.go
  • apps/cli-go/pkg/config/templates/Dockerfile
  • apps/cli-go/pkg/config/templates/config.toml
  • apps/cli-go/pkg/config/utils.go
  • apps/cli/docs/go-cli-divergences.md
  • apps/cli/docs/go-cli-porting-status.md
  • apps/cli/docs/stack-commands.md
  • apps/cli/src/cli/complete.ts
  • apps/cli/src/cli/main.ts
  • apps/cli/src/cli/root.ts
  • apps/cli/src/command-internal/db-bootstrap/bootstrap-config.ts
  • apps/cli/src/command-internal/db-bootstrap/reset-local-database.ts
  • apps/cli/src/command-internal/db-config.integration.test.ts
  • apps/cli/src/command-internal/db-config.layer.ts
  • apps/cli/src/command-internal/db-config.service.ts
  • apps/cli/src/command-internal/db-config.toml-read.ts
  • apps/cli/src/command-internal/db-config.toml-read.unit.test.ts
  • apps/cli/src/command-internal/db-config.types.ts
  • apps/cli/src/command-internal/db-pull-run.ts
  • apps/cli/src/command-internal/go-proxy.layer.ts
  • apps/cli/src/command-internal/go-proxy.layer.unit.test.ts
  • apps/cli/src/command-internal/legacy-project-state.unit.test.ts
  • apps/cli/src/command-internal/link-services-core.ts
  • apps/cli/src/command-internal/linked-state.ts
  • apps/cli/src/command-internal/local-project-context.ts
  • apps/cli/src/command-internal/local-project-context.unit.test.ts
  • apps/cli/src/command-internal/management-api-runtime.layer.ts
  • apps/cli/src/command-internal/migration-fetch-run.ts
  • apps/cli/src/command-internal/parent-project-ref.ts
  • apps/cli/src/command-internal/pgdelta.paths.ts
  • apps/cli/src/command-internal/project-create-core.ts
  • apps/cli/src/command-internal/project-target.ts
  • apps/cli/src/command-internal/seed-buckets.ts
  • apps/cli/src/command-internal/service-version-overrides.ts
  • apps/cli/src/command-internal/stack-backend.ts
  • apps/cli/src/command-internal/stack-config.ts
  • apps/cli/src/command-internal/test-db.native.integration.test.ts
  • apps/cli/src/command-internal/upgrade-notice.integration.test.ts
  • apps/cli/src/command-internal/upgrade-notice.ts
  • apps/cli/src/commands/backups/list/list.handler.ts
  • apps/cli/src/commands/backups/restore/restore.handler.ts
  • apps/cli/src/commands/bootstrap/SIDE_EFFECTS.md
  • apps/cli/src/commands/bootstrap/bootstrap.handler.ts
  • apps/cli/src/commands/bootstrap/bootstrap.integration.test.ts
  • apps/cli/src/commands/bootstrap/bootstrap.layers.unit.test.ts
  • apps/cli/src/commands/bootstrap/bootstrap.workdir-cache.integration.test.ts
  • apps/cli/src/commands/branches/create/create.handler.ts
  • apps/cli/src/commands/branches/delete/delete.handler.ts
  • apps/cli/src/commands/branches/disable/disable.handler.ts
  • apps/cli/src/commands/branches/get/get.handler.ts
  • apps/cli/src/commands/branches/list/SIDE_EFFECTS.md
  • apps/cli/src/commands/branches/list/list.handler.ts
  • apps/cli/src/commands/branches/pause/pause.handler.ts
  • apps/cli/src/commands/branches/unpause/unpause.handler.ts
  • apps/cli/src/commands/branches/update/update.handler.ts
  • apps/cli/src/commands/config/config.load.ts
  • apps/cli/src/commands/config/diff/diff.command.ts
  • apps/cli/src/commands/config/pull/pull.command.ts
  • apps/cli/src/commands/config/push/push.branch-target.ts
  • apps/cli/src/commands/config/push/push.command.ts
  • apps/cli/src/commands/config/push/push.handler.ts
  • apps/cli/src/commands/db/advisors/SIDE_EFFECTS.md
  • apps/cli/src/commands/db/advisors/advisors.handler.ts
  • apps/cli/src/commands/db/advisors/advisors.integration.test.ts
  • apps/cli/src/commands/db/advisors/advisors.layers.ts
  • apps/cli/src/commands/db/diff/SIDE_EFFECTS.md
  • apps/cli/src/commands/db/diff/diff.handler.ts
  • apps/cli/src/commands/db/diff/diff.integration.test.ts
  • apps/cli/src/commands/db/dump/SIDE_EFFECTS.md
  • apps/cli/src/commands/db/dump/dump.handler.ts
  • apps/cli/src/commands/db/dump/dump.integration.test.ts
  • apps/cli/src/commands/db/dump/dump.layers.ts
  • apps/cli/src/commands/db/lint/SIDE_EFFECTS.md
  • apps/cli/src/commands/db/lint/lint.handler.ts
  • apps/cli/src/commands/db/lint/lint.integration.test.ts
  • apps/cli/src/commands/db/lint/lint.layers.unit.test.ts
  • apps/cli/src/commands/db/pull/SIDE_EFFECTS.md
  • apps/cli/src/commands/db/pull/pull.handler.ts
  • apps/cli/src/commands/db/pull/pull.integration.test.ts
  • apps/cli/src/commands/db/push/SIDE_EFFECTS.md
  • apps/cli/src/commands/db/push/push.command.ts
  • apps/cli/src/commands/db/push/push.handler.ts
  • apps/cli/src/commands/db/push/push.integration.test.ts
  • apps/cli/src/commands/db/query/SIDE_EFFECTS.md
  • apps/cli/src/commands/db/query/query.handler.ts
  • apps/cli/src/commands/db/query/query.integration.test.ts
  • apps/cli/src/commands/db/remote/changes/SIDE_EFFECTS.md
  • apps/cli/src/commands/db/remote/changes/changes.handler.ts
  • apps/cli/src/commands/db/reset/SIDE_EFFECTS.md
  • apps/cli/src/commands/db/reset/reset.handler.ts
  • apps/cli/src/commands/db/reset/reset.integration.test.ts
  • apps/cli/src/commands/db/schema/declarative/declarative.orchestrate.integration.test.ts
  • apps/cli/src/commands/db/schema/declarative/declarative.smart-target.ts
  • apps/cli/src/commands/db/schema/declarative/generate/SIDE_EFFECTS.md
  • apps/cli/src/commands/db/schema/declarative/generate/generate.handler.ts
  • apps/cli/src/commands/db/schema/declarative/generate/generate.integration.test.ts
  • apps/cli/src/commands/db/schema/declarative/sync/sync.handler.ts
  • apps/cli/src/commands/db/schema/declarative/sync/sync.integration.test.ts
  • apps/cli/src/commands/db/shared/pgdelta-engine.next.layer.integration.test.ts
  • apps/cli/src/commands/db/shared/pgdelta-next-shadow.stack.integration.test.ts
  • apps/cli/src/commands/domains/activate/activate.handler.ts
  • apps/cli/src/commands/domains/create/create.handler.ts
  • apps/cli/src/commands/domains/delete/delete.handler.ts
  • apps/cli/src/commands/domains/get/get.handler.ts
  • apps/cli/src/commands/domains/reverify/reverify.handler.ts
  • apps/cli/src/commands/encryption/get-root-key/get-root-key.handler.ts
  • apps/cli/src/commands/encryption/update-root-key/update-root-key.handler.ts
  • apps/cli/src/commands/experimental/compute/compute.output.ts
  • apps/cli/src/commands/experimental/compute/delete/delete.handler.ts
  • apps/cli/src/commands/experimental/compute/list/list.handler.ts
  • apps/cli/src/commands/experimental/compute/logs/logs.handler.ts
  • apps/cli/src/commands/experimental/compute/push/push.handler.ts
  • apps/cli/src/commands/experimental/compute/status/status.handler.ts
  • apps/cli/src/commands/experimental/stack/prepare/prepare.command.ts
  • apps/cli/src/commands/experimental/stack/prepare/prepare.integration.test.ts
  • apps/cli/src/commands/experimental/stack/stack-backend.integration.test.ts
  • apps/cli/src/commands/experimental/stack/stack-config-environment.integration.test.ts
  • apps/cli/src/commands/experimental/stack/stack-config.integration.test.ts
  • apps/cli/src/commands/experimental/stack/stack-forwarding.integration.test.ts
  • apps/cli/src/commands/experimental/stack/start/start.handler.ts
  • apps/cli/src/commands/experimental/stack/start/start.integration.test.ts
  • apps/cli/src/commands/experimental/stack/status/status.integration.test.ts
  • apps/cli/src/commands/feedback/add/add.integration.test.ts
  • apps/cli/src/commands/feedback/feedback-project-ref.ts
  • apps/cli/src/commands/functions/delete/delete.handler.ts
  • apps/cli/src/commands/functions/deploy/deploy.command.ts
  • apps/cli/src/commands/functions/deploy/deploy.handler.ts
  • apps/cli/src/commands/functions/deploy/deploy.integration.test.ts
  • apps/cli/src/commands/functions/download/SIDE_EFFECTS.md
  • apps/cli/src/commands/functions/download/download.command.ts
  • apps/cli/src/commands/functions/download/download.handler.ts
  • apps/cli/src/commands/functions/download/download.integration.test.ts
  • apps/cli/src/commands/functions/list/list.handler.ts
  • apps/cli/src/commands/functions/list/list.integration.test.ts
  • apps/cli/src/commands/functions/serve/serve.stack.integration.test.ts
  • apps/cli/src/commands/gen/bearer-jwt/SIDE_EFFECTS.md
  • apps/cli/src/commands/gen/gen.signing-keys-config.ts
  • apps/cli/src/commands/gen/keys/SIDE_EFFECTS.md
  • apps/cli/src/commands/gen/keys/keys.handler.ts
  • apps/cli/src/commands/gen/types/SIDE_EFFECTS.md
  • apps/cli/src/commands/gen/types/types.command.ts
  • apps/cli/src/commands/gen/types/types.handler.ts
  • apps/cli/src/commands/gen/types/types.integration.test.ts
  • apps/cli/src/commands/gen/types/types.layers.unit.test.ts
  • apps/cli/src/commands/inspect/db/SIDE_EFFECTS.md
  • apps/cli/src/commands/inspect/db/inspect-deprecated.integration.test.ts
  • apps/cli/src/commands/inspect/db/inspect-query.integration.test.ts
  • apps/cli/src/commands/inspect/db/inspect-query.ts
  • apps/cli/src/commands/inspect/db/inspect-specs.integration.test.ts
  • apps/cli/src/commands/inspect/report/SIDE_EFFECTS.md
  • apps/cli/src/commands/inspect/report/report.config.ts
  • apps/cli/src/commands/inspect/report/report.handler.ts
  • apps/cli/src/commands/inspect/report/report.integration.test.ts
  • apps/cli/src/commands/link/SIDE_EFFECTS.md
  • apps/cli/src/commands/link/link.command.ts
  • apps/cli/src/commands/link/link.handler.ts
  • apps/cli/src/commands/link/link.integration.test.ts
  • apps/cli/src/commands/migration/down/SIDE_EFFECTS.md
  • apps/cli/src/commands/migration/down/down.handler.ts
  • apps/cli/src/commands/migration/down/down.integration.test.ts
  • apps/cli/src/commands/migration/fetch/SIDE_EFFECTS.md
  • apps/cli/src/commands/migration/fetch/fetch.handler.ts
  • apps/cli/src/commands/migration/fetch/fetch.integration.test.ts
  • apps/cli/src/commands/migration/list/SIDE_EFFECTS.md
  • apps/cli/src/commands/migration/list/list.handler.ts
  • apps/cli/src/commands/migration/list/list.integration.test.ts
  • apps/cli/src/commands/migration/repair/SIDE_EFFECTS.md
  • apps/cli/src/commands/migration/repair/repair.handler.ts
  • apps/cli/src/commands/migration/repair/repair.integration.test.ts
  • apps/cli/src/commands/migration/squash/SIDE_EFFECTS.md
  • apps/cli/src/commands/migration/squash/squash.handler.ts
  • apps/cli/src/commands/migration/squash/squash.integration.test.ts
  • apps/cli/src/commands/migration/squash/squash.native.integration.test.ts
  • apps/cli/src/commands/migration/up/SIDE_EFFECTS.md
  • apps/cli/src/commands/migration/up/up.handler.ts
  • apps/cli/src/commands/migration/up/up.integration.test.ts
  • apps/cli/src/commands/network-bans/get/get.command.ts
  • apps/cli/src/commands/network-bans/get/get.handler.ts
  • apps/cli/src/commands/network-bans/remove/remove.command.ts
  • apps/cli/src/commands/network-bans/remove/remove.handler.ts
  • apps/cli/src/commands/network-restrictions/get/get.command.ts
  • apps/cli/src/commands/network-restrictions/get/get.handler.ts
  • apps/cli/src/commands/network-restrictions/update/update.command.ts
  • apps/cli/src/commands/network-restrictions/update/update.handler.ts
  • apps/cli/src/commands/notebooks/pull/pull.command.ts
  • apps/cli/src/commands/notebooks/pull/pull.handler.ts
  • apps/cli/src/commands/notebooks/push/push.command.ts
  • apps/cli/src/commands/notebooks/push/push.handler.ts
  • apps/cli/src/commands/postgres-config/delete/delete.command.ts
  • apps/cli/src/commands/postgres-config/delete/delete.handler.ts
  • apps/cli/src/commands/postgres-config/get/get.command.ts
  • apps/cli/src/commands/postgres-config/get/get.handler.ts
  • apps/cli/src/commands/postgres-config/update/update.command.ts
  • apps/cli/src/commands/postgres-config/update/update.handler.ts
  • apps/cli/src/commands/projects/api-keys/api-keys.handler.ts
  • apps/cli/src/commands/projects/delete/SIDE_EFFECTS.md
  • apps/cli/src/commands/projects/delete/delete.handler.ts
  • apps/cli/src/commands/projects/delete/delete.integration.test.ts
  • apps/cli/src/commands/projects/list/list.handler.ts
  • apps/cli/src/commands/pull/SIDE_EFFECTS.md
  • apps/cli/src/commands/pull/pull.command.ts
  • apps/cli/src/commands/secrets/list/list.command.ts
  • apps/cli/src/commands/secrets/list/list.handler.ts
  • apps/cli/src/commands/secrets/set/set.command.ts
  • apps/cli/src/commands/secrets/set/set.handler.ts
  • apps/cli/src/commands/secrets/unset/unset.command.ts
  • apps/cli/src/commands/secrets/unset/unset.handler.ts
  • apps/cli/src/commands/seed/buckets/buckets.handler.ts
  • apps/cli/src/commands/seed/buckets/buckets.integration.test.ts
  • apps/cli/src/commands/services/SIDE_EFFECTS.md
  • apps/cli/src/commands/services/services-local-stack.ts
  • apps/cli/src/commands/services/services.integration.test.ts
  • apps/cli/src/commands/snippets/download/download.command.ts
  • apps/cli/src/commands/snippets/download/download.handler.ts
  • apps/cli/src/commands/snippets/list/list.command.ts
  • apps/cli/src/commands/snippets/list/list.handler.ts
  • apps/cli/src/commands/ssl-enforcement/get/get.command.ts
  • apps/cli/src/commands/ssl-enforcement/get/get.handler.ts
  • apps/cli/src/commands/ssl-enforcement/update/update.command.ts
  • apps/cli/src/commands/ssl-enforcement/update/update.handler.ts
  • apps/cli/src/commands/sso/add/add.command.ts
  • apps/cli/src/commands/sso/add/add.handler.ts
  • apps/cli/src/commands/sso/info/info.command.ts
  • apps/cli/src/commands/sso/info/info.handler.ts
  • apps/cli/src/commands/sso/list/list.command.ts
  • apps/cli/src/commands/sso/list/list.handler.ts
  • apps/cli/src/commands/sso/remove/remove.command.ts
  • apps/cli/src/commands/sso/remove/remove.handler.ts
  • apps/cli/src/commands/sso/show/show.command.ts
  • apps/cli/src/commands/sso/show/show.handler.ts
  • apps/cli/src/commands/sso/update/update.command.ts
  • apps/cli/src/commands/sso/update/update.handler.ts
  • apps/cli/src/commands/status/status.integration.test.ts
  • apps/cli/src/commands/stop/SIDE_EFFECTS.md
  • apps/cli/src/commands/storage/cp/cp.command.ts
  • apps/cli/src/commands/storage/cp/cp.handler.ts
  • apps/cli/src/commands/storage/ls/ls.command.ts
  • apps/cli/src/commands/storage/ls/ls.handler.ts
  • apps/cli/src/commands/storage/mv/mv.command.ts
  • apps/cli/src/commands/storage/mv/mv.handler.ts
  • apps/cli/src/commands/storage/rm/rm.command.ts
  • apps/cli/src/commands/storage/rm/rm.handler.ts
  • apps/cli/src/commands/storage/storage.flags.ts
  • apps/cli/src/commands/storage/storage.frame.ts
  • apps/cli/src/commands/test/db/SIDE_EFFECTS.md
  • apps/cli/src/commands/unlink/SIDE_EFFECTS.md
  • apps/cli/src/commands/unlink/unlink.handler.ts
  • apps/cli/src/commands/vanity-subdomains/activate/activate.command.ts
  • apps/cli/src/commands/vanity-subdomains/activate/activate.handler.ts
  • apps/cli/src/commands/vanity-subdomains/check-availability/check-availability.command.ts
  • apps/cli/src/commands/vanity-subdomains/check-availability/check-availability.handler.ts
  • apps/cli/src/commands/vanity-subdomains/delete/delete.command.ts
  • apps/cli/src/commands/vanity-subdomains/delete/delete.handler.ts
  • apps/cli/src/commands/vanity-subdomains/get/get.command.ts
  • apps/cli/src/commands/vanity-subdomains/get/get.handler.ts
  • apps/cli/src/config/project-ref.layer.integration.test.ts
  • apps/cli/src/config/project-ref.layer.ts
  • apps/cli/src/config/project-ref.service.ts
  • apps/cli/src/config/remote-target.layer.unit.test.ts
  • apps/cli/src/shared/cli/hidden-flag.unit.test.ts
  • apps/cli/src/shared/config/temp-paths.ts
  • apps/cli/src/shared/output/json-formatter.ts
  • apps/cli/src/shared/output/text-formatter.ts
  • apps/cli/src/telemetry/linked-project-cache.layer.ts
  • apps/cli/tests/helpers/command-mocks.ts
  • apps/cli/tests/helpers/compute.ts
  • apps/cli/tests/helpers/notebooks.ts
  • apps/cli/tests/helpers/permission-real-layers.ts
  • apps/cli/tests/helpers/storage.ts
  • packages/config/src/io.ts
  • packages/config/src/io.unit.test.ts
  • packages/config/src/project-config/hosted-sections.ts
  • packages/config/src/project.unit.test.ts

To resolve:

git fetch origin
git switch sync/develop-into-next
git merge origin/next
# resolve the conflicts, then commit
git push origin sync/develop-into-next

Approve to fast-forward next; do not use the merge button.

jgoux and others added 23 commits October 20, 2026 10:14
## Summary

Stack mode can now:

- run any service version that slim-services has published;
- match the hosted project's versions after `supabase link`;
- reproduce the whole local stack from one committed file,
`supabase/supabase.lock`.

Before this change, every service version was compiled into the CLI. You
couldn't try a hotfix, match production, or keep a team on the same
builds without everyone running the same CLI release.

Legacy (docker-compose) mode does not change, except for one fix: a
`SUPABASE_PROJECT_ID` naming another project than the linked one now
gets its pooler URL from the Management API, as `--project-ref` already
did, instead of reusing the linked project's saved
`supabase/.temp/pooler-url`. Everything below applies only to stack mode
(`SUPABASE_EXPERIMENTAL_STACK=1` or `[experimental] stack = true`).

> Version numbers and project refs in the examples are illustrative.

---

## The mental model: it works like a package manager

If you know `package.json` + `pnpm-lock.yaml`, or `Cargo.toml` +
`Cargo.lock`, you already know this.

| Package manager | Supabase stack mode | Committed? | Purpose |
| --- | --- | --- | --- |
| `package.json` | `[local.services]` in `supabase/config.toml` | ✅ |
What you **ask for**: `linked`, `bundled`, `v2.197.0`, `v2.197.0-r1` |
| `pnpm-lock.yaml` | `supabase/supabase.lock` | ✅ | What you **got**:
the exact build of every service, pinned by digest and checksum |
| — | `supabase/.link.json` | ❌ (gitignored) | Which hosted project or
branch *this checkout* targets |
| `pnpm install` | `supabase start` / `supabase stack install` | |
Resolves what changed, then runs or downloads the locked builds |
| `pnpm update` | `supabase stack update [svc…]` | | Re-resolves on
purpose and rewrites the lock |
| `pnpm outdated` | `supabase stack outdated` | | Read-only report of
what an update would change |
| `pnpm install --frozen-lockfile` | `supabase start --frozen` /
`supabase stack install --frozen` (implied when `CI` is set and a lock
exists) | | Fails instead of changing the lock |

```mermaid
flowchart LR
  subgraph git["Committed to git"]
    CFG["supabase/config.toml<br/>[local.services]<br/><i>what you ask for</i>"]
    LOCK["supabase/supabase.lock<br/><i>what you got</i>"]
  end
  subgraph checkout["This checkout only"]
    LINK["supabase/.link.json<br/><i>target hosted project</i>"]
  end
  HOSTED[("Hosted project")]
  RELEASES[("slim-services releases")]

  CFG -->|specifiers| START["supabase start<br/>stack install / stack update"]
  RELEASES -->|published builds + checksums| START
  START -->|writes when stale| LOCK
  HOSTED -->|versions it runs| LINKCMD["supabase link"]
  LINKCMD --> LINK
  LINKCMD -->|records observations,<br/>resolves 'linked'| LOCK
  LOCK -->|exact pins| STACK[("Local stack")]
```

---

## How a version is asked for

```toml
[local.services]
default = { version = "linked" }  # the default: follow the linked hosted project

[local.services.auth]
version = "v2.197.0"              # an upstream version: its highest published revision

[local.services.realtime]
version = "v2.144.2-r1"           # exactly revision 1 of that upstream version
```

`bundled` means "the version this CLI ships with". `[db]
orioledb_version` is shorthand for the database specifier, and a
database version must match `db.major_version`.

```mermaid
flowchart TD
  SPEC["specifier of a service"] --> KIND{"which kind?"}
  KIND -->|"linked (default)"| LINKED{"is the project linked,<br/>and does it report a version?"}
  LINKED -->|never linked| B1["bundled pin<br/>unlinked"]
  LINKED -->|service not reported| B2["bundled pin<br/>unobserved"]
  LINKED -->|reported| PUB{"published by<br/>slim-services?"}
  PUB -->|no| B3["bundled pin<br/>unpublished"]
  PUB -->|yes| R1["the hosted release<br/>resolved"]
  KIND -->|bundled| R2["this CLI's bundled pin"]
  KIND -->|"v2.197.0"| R3["highest published revision<br/>of v2.197.0"]
  KIND -->|"v2.197.0-r1"| R4["exactly v2.197.0-r1"]
```

The fallback reasons (`unlinked`, `unobserved`, `unpublished`) are
recorded in the lock, so nobody has to guess why a service isn't running
the hosted version.

## What the lock contains

One entry per service (database, rest, auth, realtime, storage,
imgproxy, functions, studio, pgmeta, mail, analytics, pooler). Keys are
sorted and the document is written atomically, so diffs and merge
conflicts stay readable.

```jsonc
{
  "$schema": "https://supabase.com/docs/cli/supabase-lock/v1.schema.json",
  "lockfileVersion": 1,
  "linked": {                                   // the remote the observations came from
    "project": "abcdefghijklmnopqrst",
    "branch": { "ref": "abcdefghijklmnopqrst", "isDefault": true },
    "observedAt": "2026-10-16T09:12:44.000Z"
  },
  "services": {
    "auth": {
      "specifier": "linked",                    // what config.toml asked for
      "linked": { "raw": "v2.196.1", "version": "v2.196.1" },  // what the hosted project reported
      "resolution": "resolved",                 // or unlinked / unobserved / unpublished
      "resolved": {                             // the exact build that runs
        "upstreamVersion": "v2.196.1",
        "revision": 0,
        "upstreamImage": "supabase/gotrue:v2.196.1",
        "image": "ghcr.io/supabase/cli/gotrue:v2.196.1-r0@sha256:…",
        "natives": { "darwin-arm64": { "archive": "…", "manifest": "…" }, "…": {} }
      }
    },
    "database": { "majorVersion": 17, "line": "stock", "…": "…" }
    // …one entry per service
  }
}
```

---

## What `supabase start` does with the lock

```mermaid
flowchart TD
  S["supabase start"] --> FRESH{"lock exists, and every entry<br/>still matches config.toml?"}
  FRESH -->|yes| RUN["run the locked builds<br/>(no network, no Management API)"]
  FRESH -->|"no (missing or stale)"| FROZEN{"frozen?<br/>--frozen, or CI with a lock"}
  FROZEN -->|yes| FAIL["fail: lock missing or stale<br/>→ run supabase start locally and commit it"]
  FROZEN -->|no| LEASE["take the project lease<br/>(serializes concurrent starts)"]
  LEASE --> RESOLVE["re-resolve only the services<br/>whose specifier changed"]
  RESOLVE --> WRITE["write supabase.lock atomically"]
  WRITE --> RUN
```

A start never calls the Management API and needs no login. It only warns
when:

- `.link.json` targets another project or branch than the lock observed
(run `supabase stack update`);
- this CLI bundles a newer revision of a locked version.

---

## Typical workflows

### 1. New project, never linked

```console
$ supabase start
Resolved service versions:
  database  17.11.0.004-r0  (specifier linked; unlinked)
  auth      v2.197.0-r0  (specifier linked; unlinked)
  realtime  v2.144.2-r0  (specifier linked; unlinked)
  …
Created supabase/supabase.lock.
```

Nothing is linked yet, so `linked` falls back to the bundled builds and
says so. Commit `supabase/supabase.lock`, and every teammate and CI job
now runs exactly these builds, whatever CLI version they have.

### 2. Match production: `supabase link`

```console
$ supabase link --project-ref abcdefghijklmnopqrst
Hosted versions:
  service   hosted       locked          resolution
  database  17.6.1.011   17.6.1.011-r0   resolved
  auth      v2.196.1     v2.196.1-r0     resolved
  realtime  v2.143.0     v2.143.0-r2     resolved
  studio    -            2026.10.12-…    unobserved
  …
Updated supabase/supabase.lock: now observing abcdefghijklmnopqrst (5 version changes). Review and commit it.
Finished supabase link.
```

`link` probes the hosted project, or the branch, and records what it
runs. Every `linked` service moves to that release. `link` writes
`.link.json` and the lock together, under the same project lease as
`start`. The next `supabase start` runs the hosted versions.

Linking a preview branch works the same way. The lock records which
project and branch it observed, so `start` warns if the checkout's link
later points elsewhere.

### 3. Try one specific version, or a hotfix revision

```toml
[local.services.auth]
version = "v2.198.0"
```

```console
$ supabase start
Resolved service versions:
  auth      v2.196.1-r0 → v2.198.0-r0  (specifier v2.198.0 ≠ locked linked)
Updated supabase/supabase.lock.
```

Only the changed entry is re-resolved, and every other pin stays where
it was. Remove the override to go back to `linked`. Pinning
`v2.198.0-r1` selects exactly that revision.

### 4. A teammate clones the repo, and CI

```console
$ git clone … && cd my-app
$ supabase start          # the lock is fresh: runs the committed builds, no resolution
```

In CI (`CI` set and a lock present), `start`, `stack install` and `link`
are frozen: a stale or missing lock fails instead of being rewritten.

```console
$ CI=1 supabase start
supabase/supabase.lock is stale for: auth (specifier v2.198.0 ≠ locked linked); run supabase start locally and commit the updated lock
```

`supabase stack install --frozen --runtime native` downloads everything
the lock pins without creating a stack, which makes it handy as a cached
CI warm-up step.

### 5. Upgrading the CLI

Upgrading never changes locked versions. If the new CLI bundles a newer
revision of a version you locked, `start` mentions it:

```console
$ supabase start
This CLI bundles newer revisions of locked versions: realtime v2.144.2-r0 → v2.144.2-r1. Run supabase stack outdated to review, supabase stack update to adopt them.
```

```console
$ supabase stack outdated
   SERVICE  | SPECIFIER | HOSTED   | LOCKED      | UPDATE      | BUNDLED     | STATUS           
  ----------|-----------|----------|-------------|-------------|-------------|------------------
   auth     | linked    | v2.196.1 | v2.196.1-r0 | -           | v2.197.0-r0 | up to date       
   realtime | bundled   | -        | v2.144.2-r0 | v2.144.2-r1 | v2.144.2-r1 | update available 
   …
Run supabase stack update to adopt the updates.

$ supabase stack update realtime     # or no argument for every service
```

`stack outdated` is read-only. `stack update` re-resolves the named
services even when the lock is fresh:

- an upstream version moves to its newest revision;
- `bundled` moves to the version this CLI bundles;
- `linked` probes the hosted project again;
- an exact `-rN` pin stays.

### 6. Unlinking

`supabase unlink` removes `.link.json` and the stored credential under
the project lease. The lock is not touched: it stays a valid, reviewed
lock, and its `linked` entry still shows where the observations came
from.

---

## Your local data is protected when versions change

Changing a version must never silently corrupt a local database.

| Change | What happens |
| --- | --- |
| A new revision of the same database build | Accepted |
| Any other database build (another upstream version or Postgres major,
or switching between stock and OrioleDB) with initialized data |
Refused. The advice offers pinning the recorded build under
`[local.services.database]` to keep the data (setting `[db]
major_version` back or removing `[db] orioledb_version` where they would
conflict with that pin), or `supabase stack destroy --stack-id …` (this
deletes the local data) |
| The same change on a database that never initialized | Adopted |
| Moving auth, storage or realtime **back** to a version older than one
that already migrated this database | Refused: a downgrade doesn't
restore the old schema |

`link` and `stack update` still move `linked` pins, but they warn when a
saved stack's data would refuse the new pins.

The database records the build that initialized it. Each schema-owning
service records the newest version that migrated it. Snapshots, restores
and `db reset` carry and respect both records.

---

## Stack mode no longer uses `supabase/.temp`

| Before (`supabase/.temp`) | Now in stack mode |
| --- | --- |
| Project ref, pooler URL, branch | `supabase/.link.json` (gitignored) |
| Postgres and edge-runtime versions | `supabase/supabase.lock` |
| Storage uploads | `$SUPABASE_HOME/stacks/<id>/uploads`, removed by
`stack destroy` |
| Scratch files (pgdelta debug bundles, Functions bundling) |
`$SUPABASE_HOME/tmp` |
| Release-check cache | `$SUPABASE_HOME/cli-latest` |

Delegated Go commands skip `.temp` too. Remote commands resolve the
hosted target once per command, in this order:

1. the `--project-ref` flag;
2. `SUPABASE_PROJECT_ID`;
3. the link;
4. the interactive picker.

Three commands change with this beyond the `.temp` move:

- `gen keys` resolves its project this way, picker included, and passes
it to the delegated command;
- the upgrade notice picks its release-check cache by the project's
mode, read from the working directory it was handed;
- `db pull` builds its shadow database from the locked pins, falling
back to the bundled database pin of the major a `[remotes]` block
selects.

`supabase stack install` replaces the experimental `supabase stack
prepare`.

---

## Reading this PR

There is one commit per chunk, in dependency order; each builds on the
previous one.

| Commit | What it adds |
| --- | --- |
| `docs(stack)` | ADRs 0026 and 0017: the lock-based version model |
| `feat(config)` | `[local.services]` specifiers in the config schema |
| `feat(stack)` resolve pins | Resolving slim-services releases with
checksum, manifest and provenance verification |
| `refactor(cli)` `.temp` layout | One owner for every legacy `.temp`
path |
| `feat(stack)` explicit pin | Every service creation carries the exact
pin it runs |
| `feat(cli)` `.link.json` | The hosted link file in stack mode |
| `feat(stack)` lock format | The `supabase.lock` schema, deterministic
write, typed read errors |
| `feat(stack)` test stacks | `@supabase/stack` test stacks run the
project lock |
| `feat(stack)` database build guard | Initialized data is tied to its
build |
| `feat(cli)` hosted target | One hosted-target resolution per command |
| `feat(stack)` schema writers | Refuses older schema writers on
migrated databases |
| `feat(cli)` lock at start | Resolve and lock at `start`; `--frozen`
and CI behavior |
| `feat(cli)` install | `stack install`, `stack prepare` removed |
| `feat(cli)` update/outdated | `stack update` and `stack outdated` |
| `feat(cli)` linked versions | `link` observes hosted versions and
resolves `linked` |
| `feat(cli)` no `.temp` | Stack mode leaves `supabase/.temp` alone |
| `feat(cli)` Go off `.temp` | Delegated Go commands do the same |
| `test(cli)` | Explicit timeouts on owner-spawning destroy tests |

Review fixes and merges from `develop` follow these commits.

User-facing reference:
[`apps/cli/docs/stack-commands.md`](https://github.com/supabase/cli/blob/juliengoux/cli-2688-stack-mode-lockable-service-versions-with-hosted-parity-via/apps/cli/docs/stack-commands.md#service-versions)
and the [`start` side
effects](https://github.com/supabase/cli/blob/juliengoux/cli-2688-stack-mode-lockable-service-versions-with-hosted-parity-via/apps/cli/src/commands/experimental/stack/start/SIDE_EFFECTS.md#service-versions-and-the-lock).

---------

Co-authored-by: Colum Ferry <cferry09@gmail.com>
## Summary

The `link` and `bootstrap` integration tests picked out Management API
requests with `url.startsWith("https://api.supabase.com")`, which CodeQL
reports as incomplete URL substring sanitization (code scanning alerts
#59 and #60). They now parse each request URL and compare its origin.
The alerts also fail the CodeQL check on unrelated PRs whenever a diff
shifts those lines.
## Summary

v3 (CLI-2695, landing on `next`) makes the local stack the default
target for every command that can run against either the local stack or
a hosted project, with one `--remote` flag to reach a project. Today
nothing tells you that's coming. This adds a warning on develop, without
changing any default:

```
Warning: supabase db push will target the local database by default in the next major version. Pass --linked to keep targeting the linked project.
```

- Printed on stderr, once, when one of these commands runs with no
target selector and goes to the linked project: `db push`, `db pull`,
`db dump`, `migration fetch`, `migration list`, `migration repair`,
`inspect db *` (including the deprecated aliases, named as typed),
`inspect report`, `gen types`, `storage ls/cp/mv/rm`. Storage says "the
local Storage API".
- Any of `--linked`, `--local`, `--db-url`, `--project-ref` (or `gen
types --project-id`) silences it, in any form including
`--linked=false`. `SUPABASE_PROJECT_ID` doesn't, since it won't select
the project in v3.
- `gen types` warns only once a project ref has resolved, so an unlinked
run still prints just the existing "Must specify one of" error.
- stdout, exit codes and the target itself are unchanged in every output
format.

The opt-in `target` config key and `SUPABASE_TARGET` this PR previously
added are gone; the v3 design drops them in favour of `--remote`.

## Linked issue

Part of CLI-2695 (the non-breaking half for the current major).

## Checklist

- [x] The PR title follows Conventional Commits.
- [x] Tests added or updated for the change.
- [x] From the repository root, `pnpm check:all` passes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
…nts (#7211)

## TL;DR

Two `stack start` failure fingerprints each covered many unrelated
causes, so telemetry could not say what failed. Each start configuration
check now has its own fingerprint, and an unclassified stack failure
names the stack operation that failed.

## What changes

- `tag:ExperimentalStackStartError:invalid_config` splits by check:
`project_config`, `service_config`, `functions_env`,
`saved_stack_changes`, `credentials_conflict`, `missing_database`,
`missing_credentials`.
- Failing to create the Storage uploads, Functions, or Studio snippets
directory is classified by its file-system cause (`filesystem`
permission, else `filesystem_io`) instead of as a user config error.
- A stack failure with no known kind or reason reports
`unclassified_<operation>` for the operations `stack start` runs (for
example `unclassified_start_composition`, `unclassified_start_service`,
`unclassified_ready_service`), covering both the client and the stack
owner side. Other operations keep `unclassified`. This applies to every
stack command wrapper and `functions serve`.

Error messages and output are unchanged. A wrapper that keeps its own
fallback for an unclassified stack failure still does.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Stacked on #7211.

## TL;DR

Every experimental stack command reported every target-resolution
failure under one `invalid_config` fingerprint. That covers reading
saved stack state, decoding a saved stack, and resolving the project
root, so telemetry could not tell these causes apart. Each failed step
now has its own fingerprint in every stack command.

## Before

```mermaid
flowchart LR
  A["stack discovery fails"] --> X["&lt;command&gt;:invalid_config"]
  B["stack lookup fails"] --> X
  C["prefix match unreadable"] --> X
  D["project root unresolvable"] --> X
```

## After

```mermaid
flowchart LR
  A["stack discovery fails"] --> A2["&lt;command&gt;:stack_discovery"]
  B["stack lookup fails"] --> B2["&lt;command&gt;:stack_lookup"]
  C["prefix match unreadable"] --> C2["&lt;command&gt;:unreadable_stack"]
  D["project root unresolvable"] --> D2["&lt;command&gt;:project_root"]
```

## Why

Review on #7211 pointed out that the only remaining `invalid_config`
path in `stack start` is target resolution. That path is shared by all
stack commands, so it was left for a follow-up.

## What changed

- `StackTargetError` carries a closed `targetIssue` that the resolver
sets where each failure occurs.
- `mapTargetError` carries it into the start, stop, restart, status,
destroy, prepare, and logs errors. They report `stack_discovery`,
`stack_lookup`, `unreadable_stack`, or `project_root` instead of
`invalid_config`. In `stack start`, a configuration check's own
fingerprint still takes priority.
- prepare, restart, logs, and stop now use the shared `mapTargetError`
instead of local copies that would drop the new field.
- An invalid-config error without a `targetIssue` still reports
`invalid_config`. Error tags, messages, and output are unchanged.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
## TL;DR

`supabase db push --linked` stops silently dropping `PGSSLMODE` and
`PGSSLROOTCERT` when the direct host answers

## whats introduced?

`--linked` commands that connect from the CLI itself (`db push`,
`migration` commands, `inspect db`, …
now read `PGSSLMODE`, `PGSSLROOTCERT` and `PGSSLCERT`/`PGSSLKEY` from
the shell on the direct host, the way the pooler fallback already did.

ps: the `pg_dump` steps in `db dump`, `db pull` and `migration squash`
still don't forward them.

`PGSERVICE` and `PGCONNECT_TIMEOUT` apply too, and a missing
`PGSSLROOTCERT` file now fails instead of being ignored.

host, role and database stay pinned. an invalid mode fails naming the
vars on either route, and `sslmode=disable` now dials plaintext without
reading cert files.

<details>
<summary>visual rep</summary>

| `supabase db push --linked` | before | now |
| ------------------------------------ | -------------------- |
---------------------------- |
| direct host | `PGSSL*` ignored | read from the shell |
| pooler fallback | read from the shell | unchanged |
| invalid `PGSSLMODE` | ignored / IPv6 error | fails naming the vars |

</details>

## why this?

`--db-url` and the pooler fallback already read these vars.

the linked direct host was skipped by mistake during the port, so it now
reads them too

## ref:

- closes: CLI-2753
- broken/missed in: #5715
This bumps edge-runtime from v1.77.6-r0 to v1.77.8-r0.


https://github.com/supabase/slim-services/releases/tag/edge-runtime-v1.77.8-r0

Planned after supabase/slim-services published v1.77.8-r0. This branch
is rewritten from develop whenever a newer relevant release arrives.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…7262)

## TL;DR

brings `io.ts` and its tests under the effect lint

## whats introduced?

- `packages/config/src/io.*` joins the allow list
- `writeFileAtomic` reads the temp suffix time from the effect `Clock`,
the same value `Date.now()` gave
- `io.unit.test.ts` moves to effect: `FileSystem` and `Path`, scoped
temp dirs, schema json codecs, and `vi.stubEnv` inside a scoped acquire
and release instead of writing `process.env`

## ref

- related: CLI-2756
…I-2756) (#7263)

## TL;DR

brings the rest of `packages/config/src` under the effect lint
## whats introduced?

- `packages/config/src/**` joins the allow list, and the `schema-number`
modules stay out until the schema fix on top
- `project.ts` yields its parse error directly instead of through
`Effect.fail`
- the `./io` methods are plain promise returning functions behind
`Effect.suspend` instead of `async`, so they resolve and reject exactly
as before and never throw synchronously, only `isAsyncFunction` flips
- the src tests move to effect, and the entrypoint purity and import
contract walkers run on `FileSystem`, skipping entries that vanish mid
scan

## ref

- related: CLI-2756
#7265)

## TL;DR

brings the `packages/config` build and release scripts under the effect
lint

## whats introduced?

- the allow list widens to `packages/config/**`
- `build.ts`, `release-plan.ts` and the semantic release path filter run
as effect programs with the same output, exit codes, release outputs and
temp dir cleanup
- a malformed `package.json` now reports a schema decode message instead
of the native json parse one, same exit code

## ref

- closes: CLI-2757
#7267)

## TL;DR

a broken config now says what is wrong and where, and `inf` or `nan`
numbers no longer load

## whats hurting the user?

`supabase start`, `status`, `stop` and `functions serve` print a bare
`CliConfigParseError` for any broken config.

`config push`, `gen types`, `seed buckets` and the rest print the raw
parser output, which quotes nearby lines of the file, secrets included.

`max_rows = inf` or a `nan` rate limit loads quietly and reaches the
containers as `Infinity`

## now fixed by?

every command prints the field path or the line and column, never the
file contents.

number fields only take finite values, so the json schema post
processing that hid the `inf` and `nan` variants goes away.

> [!NOTE]
> a config with `inf` or `nan` in a number field used to load and now
fails, so set a real number instead.

## ref:

- closes: CLI-2756
- closes: CLI-2755
Adds a PERMISSIONS section to `--help` for every command, listing the
personal access token permissions it needs.

Every command already declares the Management API operations it may
call. The help section resolves those declarations against the
permissions the API spec lists for each operation, so users can see
which token to create before running a command.

- Permissions come from a generated `operationId` to `x-fga-permissions`
/ `x-oauth-scope` table in `@supabase/api/permissions`.
- Conditions are worded against the command's own flags: a flag the
command lacks is never named, equivalent cases merge, and a permission
already shown under a broader condition is not repeated. Requirements
that depend on something other than a flag show as "May be required",
without a reason.
- `--output-format json` help carries the same section under a top-level
`permissions` field, with each group's flag conditions as data. The raw
permission declaration is no longer serialized into `doc.annotations`.
- Each permission scheme is resolved and rendered on its own, so OAuth
scopes can be added later by registering one more scheme.

Output sample:
```
$ supabase projects api-keys --help
DESCRIPTION
  List all API keys for a Supabase project.
... rest of the content ...
PERMISSIONS
  Personal access token (FGA):
    Required with --reveal:
      api_gateway_keys_read + api_gateway_keys_secret_read
    Required without --reveal:
      api_gateway_keys_read
    May be required (without --project-ref):
      projects_read
    Optional (command still runs without these):
      project_admin_read
```

```
$ supabase projects api-keys --help --output-format json
...
 "permissions": {
        "status": "mapped",
        "schemes": [
            {
                "scheme": "fga",
                "title": "Personal access token (FGA)",
                "groups": [
                    {
                        "heading": "Required with --reveal",
                        "need": "required",
                        "when": [
                            {
                                "all": [
                                    {
                                        "flag": "reveal",
                                        "values": [
                                            "true"
                                        ]
                                    }
                                ]
                            }
                        ],
                        "rows": [
                            {
                                "anyOf": [
                                    [
                                        "api_gateway_keys_read",
                                        "api_gateway_keys_secret_read"
                                    ]
                                ]
                            }
                        ]
                    },
                    {
                        "heading": "Required without --reveal",
                        "need": "required",
                        "when": [
                            {
                                "all": [
                                    {
                                        "flag": "reveal",
                                        "values": [
                                            "false"
                                        ]
                                    }
                                ]
                            }
                        ],
                        "rows": [
                            {
                                "anyOf": [
                                    [
                                        "api_gateway_keys_read"
                                    ]
                                ]
                            }
                        ]
                    },
                    {
                        "heading": "May be required (without --project-ref)",
                        "need": "maybe",
                        "when": [
                            {
                                "all": [
                                    {
                                        "flag": "project-ref",
                                        "values": [
                                            "unset",
                                            "empty"
                                        ]
                                    }
                                ]
                            }
                        ],
                        "rows": [
                            {
                                "anyOf": [
                                    [
                                        "projects_read"
                                    ]
                                ]
                            }
                        ]
                    },
                    {
                        "heading": "Optional (command still runs without these)",
                        "need": "optional",
                        "rows": [
                            {
                                "anyOf": [
                                    [
                                        "project_admin_read"
                                    ]
                                ]
                            }
                        ]
                    }
                ]
            }
        ]
    }
...
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
This bumps realtime from v2.145.5-r0 to v2.147.1-r0.


https://github.com/supabase/slim-services/releases/tag/realtime-v2.147.1-r0

Planned after supabase/slim-services published v2.147.0-r0. This branch
is rewritten from develop whenever a newer relevant release arrives.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This bumps storage from v1.84.0-r0 to v1.84.17-r0.


https://github.com/supabase/slim-services/releases/tag/storage-v1.84.17-r0

Planned after supabase/slim-services published v1.84.17-r0. This branch
is rewritten from develop whenever a newer relevant release arrives.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This PR was automatically created to sync API types from the
infrastructure repository.

Changes were detected after refreshing `apps/cli-go/api/v1-openapi.yaml`
from the latest spec from infrastructure, and `apps/cli-go/pkg/api` is
regenerated from it. The snapshot diff is the upstream API change and is
worth reading: it is marked `linguist-generated`, so GitHub collapses it
behind a "Load diff" click rather than hiding it.

Co-authored-by: supabase-cli-releaser[bot] <246109035+supabase-cli-releaser[bot]@users.noreply.github.com>
## TL;DR

fixes `supabase start` and `supabase stop` failing every few runs on
podman machine

## whats hurting the user?

on macOS with podman machine and no `docker` on PATH, `supabase start`
fails every few runs with `failed to inspect docker image` and `ssh:
handshake failed: EOF`

`supabase stop` fails the same way with `failed to stop container: exit
125` and leaves the stack behind

both fire one `podman` call per image or container all at once, and each
call opens its own ssh session into the VM, whose sshd drops new ones
once ten are still in the handshake

## now fixed by?

capping those calls at 8 in flight so every handshake gets accepted,
rather than retrying, which would only hide the drops and add delay

> [!NOTE]
> docker shares the same cap, so stopping more than 8 containers that
ignore their stop signal, so it can take an extra smol grace period...

<details><summary>visual rep:</summary>

```mermaid
flowchart LR
  subgraph before["before"]
    A["start / stop"] --> B["one podman call per image or container, all at once"]
    B --> C["sshd drops past ten handshakes"]
    C --> D["start / stop fail"]
  end
  subgraph now["now"]
    E["start / stop"] --> F["at most 8 podman calls in flight"]
    F --> G["all handshakes accepted"]
  end
```

</details>

## ref:

- broken/missed in: #5847
- spotted while working on: #7089
…7279)

## TL;DR

fixes the `[auth.sms.test_otp]` example that `supabase init` writes, so
its phone gets the test code instead of a real SMS

## whats hurts?

`supabase init` writes `4152127777 = "123456"` as the test OTP example,
without the country code

auth strips the leading `+` from the phone and looks it up as an exact
key, so `+14152127777` never matches `4152127777`

uncommenting the example and sending that phone calls the configured SMS
provider instead of returning the test code

## now fixed by?

the example key is now `14152127777` with a comment saying keys are the
phone number with country code and without the `+` prefix, so
`+14152127777` gets `123456`

## ref:

- closes: CLI-2820
- related: supabase/supabase#52118
## TL;DR
`functions deploy --use-api` now uploads modules behind dynamic imports
written across lines or with import attributes, so the deployed function
no longer throws `Module not found`
## whats improved/fixed?

the deploy only uploads files its import scanner finds, and that scanner
skipped any `import()` where `)` didn't follow the closing quote right
away

so a specifier on its own line, a trailing comma, or `{ with: { type:
"json" } }` left the module out while the deploy still exited 0...

## how?

the `import()` branch now allows whitespace and `,` after the specifier
and pairs its quotes,
so a concatenated path like `"./locales/" + lang + ".json"` is never
read as a file that fails `functions serve`

## ref:

- closes: #7280
Updates `@supabase/pg-delta` to `1.0.0-alpha.60` and moves its
`minimumReleaseAgeExclude` entry to the new version.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This bumps storage from v1.84.17-r0 to v1.84.19-r0.


https://github.com/supabase/slim-services/releases/tag/storage-v1.84.19-r0

Planned after supabase/slim-services published v1.84.19-r0. This branch
is rewritten from develop whenever a newer relevant release arrives.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
… images (#7289)

The mirror-template-images detect step checks public.ecr.aws
anonymously, and the shared per-IP quota can answer `429 Too Many
Requests`, which aborted the run.

Rate-limited probes now retry with backoff (10s, 30s, 60s) before
failing with the registry error; other failures still abort immediately.
This avoids giving the detect job, which installs npm dependencies, the
production AWS role.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
## TL;DR

remote `db dump` and the first `db pull` seed now pass the resolved TLS
settings to `pg_dump`
## whats introduced?

`pg_dump` only got host, port, user, password and database, so a
container dump ignored `PGSSLMODE=verify-full`, trusted any CA, and got
turned away by servers that require a client cert.

for the linked project and a remote `--db-url`, it now gets the resolved
`sslmode` and connect timeout, the root cert under `require` or
`verify-*`, and the client cert unless the key needs `sslpassword`
In a container the cert files are mounted read only, and a missing one
fails before docker runs

> [!NOTE]
> a remote dump that only worked because verification was skipped now
fails. local targets and runs without TLS or timeout settings are
unchanged

<details>
<summary>visual rep:</summary>

```mermaid
flowchart TD
  conn["resolved connection"] --> remote{"remote target?"}
  remote -- no --> plain["host, port, user, password, database"]
  remote -- yes --> tls["+ sslmode and connect timeout<br/>+ root cert under require or verify-*<br/>+ system root cert forces verify-full<br/>+ client cert unless the key needs sslpassword"]
  tls --> where{"where pg_dump runs"}
  where -- container --> box["cert files checked, then mounted read only<br/>key copied to a private file<br/>verify-* without root cert, or system, uses the image CA bundle"]
  where -- native --> host["host paths kept<br/>verify-* without root cert uses ~/.postgresql/root.crt, else the host CA bundle<br/>system uses the host CA bundle"]
  plain --> dump["pg_dump"]
  box --> dump
  host --> dump
```

</details>

## ref

- spotted while working on: #7261
- related: CLI-2753
This bumps postgres from 15.19.0.006-r0 to 15.19.0.007-r0.


https://github.com/supabase/slim-services/releases/tag/postgres-15.19.0.007-r0

Planned after supabase/slim-services published 17.11.0.007-r0. This
branch is rewritten from develop whenever a newer relevant release
arrives.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@supabase-cli-releaser
supabase-cli-releaser Bot requested review from a team and supabase-oss as code owners October 23, 2026 08:27
@supabase-cli-releaser supabase-cli-releaser Bot added the do not merge Approve to apply; do not merge. label Oct 23, 2026
@avallete

Copy link
Copy Markdown
Member

@supabase/cli Claude could not resolve this merge: This merge can't be resolved mechanically. Both branches redesigned how the CLI picks a project, in incompatible ways, and combining them is a design decision for a maintainer.

  • develop: removed config/project-ref.{service,layer}.ts and shared/config/temp-paths.ts. In their place it added RemoteTarget (config/remote-target.*), which resolves to { ref, parentRef, branchName, poolerUrl, source }. It has load/parent/resolveParentScoped methods and reads the link through link-snapshot.ts, which supports both the legacy supabase/.temp files and the new stack-mode supabase/.link.json.
  • next: built the ADR 0033 target system on top of the old ProjectRefResolver and temp-paths.ts (command-internal/target/*, resolveProjectTarget, --remote=<ref|branch>, CommandTarget announcements, matchesLinkedRef, and a linkedRef field on the parent resolution). It also removed the Go CLI (apps/cli-go, go-proxy, project-target.ts).

Why I stopped: about 210 files use develop's API and about 160 use next's. Next's non-conflicted target/* modules import files that develop deleted, and develop's link-snapshot/legacy-project-state code depends on RemoteTarget.

What a correct merge needs: one resolver that keeps next's target selection, announcements and branch resolution, and reads develop's legacy-or-.link.json link state, including load (no picker), poolerUrl and branchName. That resolver then has to be applied by hand across 613 conflict hunks in 245 files. Choosing that resolver's design is the part that needs a maintainer, and without a type-check run I can't check a hand-port of this size.

I edited no files and left the tree as the merge produced it.

Resolve it by hand as described above (workflow run).

Keeps next's target selection (ProjectRefResolver, target/*, --remote) and
develop's on-disk link state (link snapshot over .temp or .link.json), now
under shared/config. Ports develop's stack-mode version locking, PGSSL/TLS
handling, config parse errors and token-permission help onto next's APIs,
and drops develop's v3 local-default warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@avallete

Copy link
Copy Markdown
Member

/ai-review

@github-actions

Copy link
Copy Markdown
Contributor

Not fast-forwarding next: required checks are not green on 968b41d.

Check State
Run end-to-end tests missing
Run unit and integration tests failure

Once they pass (re-run or push as needed), re-approve.

@avallete
avallete self-requested a review October 23, 2026 10:54

@avallete avallete left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

bad approval

The merged resolver reads the pooler URL from the target, not the TOML reader.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@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.

🤖 AI Review

Verified all four Claude findings against the checkout and sync-resolution diff; Codex reported no findings. Confirmed stale snapshots that will fail 14 tests and deletion of direct legacy-state coverage. Refuted two findings because they concern behavior or wording already present on next, outside the requested sync-review scope. Tests were not run because dependencies are absent.

Findings

Severity Location Category Sources Claim
🟠 MAJOR apps/cli/src/command-internal/testdata/config-precedence/db-toml/a-base-only.json:25 merge-resolution claude Removing poolerConnectionString from the db-toml reader without updating its 14 precedence goldens makes all 14 snapshot comparisons fail.
🟡 MINOR apps/cli/src/shared/config/legacy-project-state.layer.ts:10 merge-resolution claude The resolution deletes both direct legacy-state test suites without preserving their blank-ref, permission-classification, and isCheckoutLinked regression cases.

Findings outside the diff

  • 🟠 MAJOR apps/cli/src/command-internal/testdata/config-precedence/db-toml/a-base-only.json:25 — Removing poolerConnectionString from the db-toml reader without updating its 14 precedence goldens makes all 14 snapshot comparisons fail.
Refuted findings (kept for transparency, not posted as review comments)
  • apps/cli/src/config/project-ref.layer.ts:150 (merge-resolution): Replacing develop's cached RemoteTarget with ProjectRefResolver loses the resolve-once guarantee and permits repeated resolutions to observe a relink.
    Refuted: The lack of memoization is real but already existed on next. The sync diff shows the existing uncached readRefFile path being replaced with snapshot reads, rather than a cache being removed from ProjectRefResolver. Under the requested branch-sync rule, retaining next's existing behavior is not a new sync finding.
  • apps/cli/src/commands/projects/list/list.handler.ts:129 (merge-resolution): The projects-list parent-chain comment describes only legacy files and omits stack-mode .link.json resolution.
    Refuted: The wording is incomplete for stack mode, but it was already present on next and does not reference a removed or renamed API. The requested sync-review rule excludes findings about wording either branch already had.

Stats

Claude findings: 4 · Codex findings: 0 · Confirmed: 2 · Refuted: 2 · Uncertain: 0


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

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

Comment thread apps/cli/src/shared/config/legacy-project-state.layer.ts
Comment thread apps/cli/src/command-internal/scratch-paths.ts
@avallete
avallete self-requested a review October 23, 2026 11:02
@supabase-cli-releaser
supabase-cli-releaser Bot merged commit c3d6a6d into next Oct 23, 2026
52 of 53 checks passed
@supabase-cli-releaser
supabase-cli-releaser Bot deleted the sync/develop-into-next branch October 23, 2026 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do not merge Approve to apply; do not merge.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants