Skip to content

chore: production deploy - #7340

Open
supabase-cli-releaser[bot] wants to merge 33 commits into
mainfrom
develop
Open

supabase-cli-releaser[bot] wants to merge 33 commits into
mainfrom
develop

Conversation

@supabase-cli-releaser

Copy link
Copy Markdown
Contributor

supabase-cli-releaser Bot and others added 24 commits October 23, 2026 11:42
This bumps storage from v1.84.19-r0 to v1.84.20-r0.


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

Planned after supabase/slim-services published v1.84.20-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.20-r0 to v1.84.21-r0.


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

Planned after supabase/slim-services published v1.84.21-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>
## Toolchain bumps

- Bumps pnpm, node, bun, and mise. `mise.lock` and `pnpm-lock.yaml` are
updated to match.
- Updates the mise version pinned in each GitHub Actions workflow.
- Drops `pnpm exec` from `bun` commands. The toolchain setup already
puts bun on `PATH`, so running it through pnpm only added a process hop
and a pnpm lookup. Calling bun directly removes that overhead and
complexity.

## Workflow changes

### flaky-check installs bun with `oven-sh/setup-bun`

Its plan and report jobs only need bun. setup-bun restores a 34 MB cache
with just the bun binary. mise-action restored a 68 MB mise data
directory and then ran a locked install and a listing on top, which took
about twice as long on a cache hit. Every other bun-only step in the
repository already uses setup-bun, so this makes them consistent.

### `jdx/mise-action` moves from v4.3.0 to v5.2.2

What we gain:

- **The mise binary is verified before it runs.** A downloaded binary is
checked against the release's signed manifest, and a binary restored
from cache is checked against the signed release checksums. Before, a
cached binary could run unchecked.
- **The job's GitHub token stays inside the action.** v4 wrote it to the
environment of every later step. Now only the action sees it.
- **Caches rebuild every 30 days.** GitHub never evicts a cache that
keeps getting hits, so a busy repository could keep the same tools for
months. The default key now rolls over on a schedule.

What does not change for us: every step pins a mise version, so the new
release-age default does not apply, and the pinned mise ships the signed
manifest the action now requires.

One thing to expect: the default cache key format changed, so each mise
cache misses once after this lands. The sync check job runs `mise
install` in a later step. It no longer gets the token, but it fetches
release metadata through mise's own relay and downloads assets directly
from GitHub releases, so it never used the token.

### The shared setup action drops its custom `cache_key`

The custom key hashed `mise.toml`, `mise.lock`, `.node-version`,
`.bun-version`, and `package.json`. mise-action's default key already
covers `mise.toml` and `mise.lock`, plus the requested tool subset, the
runner image, and the mise version. The lockfile pins the node, bun, and
pnpm versions the version files select, and a locked install refuses any
version the lockfile does not have. So the extra hashes could not catch
anything the lockfile hash misses, and the default key is strictly
better.

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

---------

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

## Bump

- `jactionlint` moves from 1.8.2 to 2.3.0 (`"2"` in mise.toml, pinned in
`mise.lock`).
- The config's deprecated `require-commit-hash` key becomes `rules:
unpinned-uses: error`, the vendored `.repos/**` submodules are excluded,
and the `missing-timeout` and `concurrency-limits` policy rules are
turned off.

## Fixes, one commit per rule

- **excessive-permissions**: single-job workflows grant their write
scopes on the job instead of the workflow. contribution-gate grants both
jobs the scopes its script needs. release-smoke-test's caller job keeps
the four scopes release-shared's job tree declares.
- **github-app**: the three release-notes App tokens request only the
permissions their jobs use, confirmed against GitHub's REST permission
tables.
- **superfluous-actions**: both `softprops/action-gh-release` steps
become `gh release create`, skipping when the release already exists and
verifying the tag the earlier step pushed.
- **pipeline-without-pipefail**, **github-env**, **artipacked**,
**unused-job-output**: small mechanical fixes.

## Accepted findings, one commit per rule

Each carries an inline `# jactionlint ignore=` comment with a
plain-English reason: `dangerous-triggers`, `adhoc-packages`,
`unverified-download`, `cache-poisoning` (run-scoped key),
`unpinned-images` (smoke-test container), `bot-conditions` (the author
check is already present), and `issues: write` on reopen-stale-issue.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
This bumps storage from v1.84.21-r0 to v1.84.22-r0.


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

Planned after supabase/slim-services published v1.84.22-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.22-r0 to v1.84.23-r0.


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

Planned after supabase/slim-services published v1.84.23-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 realtime from v2.147.1-r0 to v2.147.2-r0.


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

Planned after supabase/slim-services published v2.147.2-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>
This bumps realtime from v2.147.2-r0 to v2.147.3-r0.


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

Planned after supabase/slim-services published v2.147.3-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 studio from 2026.10.19-sha-b375769-r0 to
2026.10.26-sha-478bd88-r0.


https://github.com/supabase/slim-services/releases/tag/studio-2026.10.26-sha-478bd88-r0

Planned after supabase/slim-services published
2026.10.26-sha-478bd88-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>
Plan-gated Management API denials already return `{ error: { code:
"entitlement_required", feature, upgrade_url } }`. In `--output-format
json` and `stream-json` that signal only survives as escaped text inside
`error.message`, so an agent has to parse prose to learn that an upgrade
is needed and where. I added a structured `entitlement` to the
machine-mode error object for every command whose status errors go
through `mapHttpError`.

```json
{"_tag":"Error","error":{"code":"DomainsUnexpectedStatusError","message":"...","entitlement":{"feature":"custom_domain","upgrade_url":"https://supabase.com/dashboard/org/<slug>/billing"}}}
```

**Changed:**
- **Machine-mode errors carry the plan gate**: on a 4xx, `mapHttpError`
decodes the untruncated body and, when it is the plan-gate envelope,
attaches `entitlement: { feature, upgrade_url }` to the status error.
`normalizeCliError` passes it into the json and stream-json error
object, so commands with no per-command upgrade wiring (`branches
unpause`) get it too.
- **Handlers that rebuild a mapped error keep it**: `branches
create`/`update`, `vanity-subdomains activate`/`check-availability` and
`sso list`/`add`/`update`/`remove` forward the field, and `Output.fail`
declares it in its type.
- **Envelope values are validated in one place**: I moved the parser
into `http-errors.ts` and `suggestUpgrade` reuses it. `feature` must be
a plain key and `upgrade_url` an http(s) URL without credentials,
emitted as the parsed URL so control and bidi characters arrive
percent-encoded; anything else counts as no envelope.

**Note:** text output and `cli_upgrade_suggested` are unchanged for
well-formed envelopes. The per-command text hint stays until I move the
hint and the event onto the same central path in a follow-up.

## Linear
- part of GROWTH-1050
<!--
Before opening this PR, confirm the linked issue is open and carries the
`open-for-contribution` label. PRs from external contributors that don't
follow
the workflow in CONTRIBUTING.md are closed automatically.
@supabase members working from Linear tickets are exempt.
-->

## Summary

Adds a SECURITY.md file so we can get better signal on our security
reports.

## Linked issue

[Linear
Issue](https://linear.app/supabase/issue/SEC-993/securitymd-to-guide-researchers)

- [x] The linked issue is **open** and carries the
`open-for-contribution` label (or I'm a Supabase maintainer).

## Checklist

- [x] The PR title follows [Conventional
Commits](https://www.conventionalcommits.org/) (e.g. `fix(cli): …`).
- [ ] Tests added or updated for the change.
- [ ] From the repository root, `pnpm check:all` passes; relevant
package tests pass for every touched workspace, and `pnpm types:check`
passes for each touched TypeScript workspace (or workspace declaring
it).

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
This bumps postgres from 17.11.0.006-r0 to 17.11.0.007-r0.


https://github.com/supabase/slim-services/releases/tag/postgres-17.11.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>
This bumps realtime from v2.147.3-r0 to v2.147.4-r0.


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

Planned after supabase/slim-services published v2.147.4-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>
…#7320)

## TL;DR

fixes restoring a `supabase db dump --role-only` file as `postgres`
failing on a parameter grant to a reserved role

## whats improved/fixed?

`supabase db dump --role-only` already comments out create, alter and
membership grant lines for reserved roles, but parameter grants like
`GRANT SET ON PARAMETER "log_min_messages" TO
"supabase_realtime_admin";` passed through

linked and local projects whose realtime setup grants this get that line
in `roles.sql`, so restoring it as `postgres` aborted with `permission
denied for parameter log_min_messages`

## how?

a new rule anchored to the start of the line comments out parameter
grants to reserved roles, in both the dump script and the in-process
filter the local stack uses

grants to other roles and grant text inside role setting values stay as
they are

## ref:

- closes: #7315
…LI-2837) (#7300)

## TL;DR

the delegated binary lookup and the project link writes run through
effect, ready for the effect lint

## whats improved/fixed?

- the binary lookup checks its paths through `FileSystem` and reads its
override env var through `Config`
- `.link.json` is written through schema json instead of
`JSON.stringify`
- the lookup and the permissions help tests run as effects with typed
errors

## how?

- the lookup keeps the same search order and the same not found message
- the link file keeps the same pretty printed bytes

> [!NOTE]
> nothing changes for users, the same binary is found and `.link.json`
is exactly the same
> these files join the effect lint in the last page of this stack.

## ref:

- related: CLI-2837
…7301)

## TL;DR

local config values, config validation and path containment run through
effect, so the effect lint now covers `apps/cli/src`

## whats improved/fixed?

- they read env through `Config` and files through `FileSystem`, and
fail with typed errors instead of throwing
- the config value tests pin env through a config provider instead of
editing `process.env`, so a shell override can no longer skew them
- the effect lint allow list swaps its per-file `command-internal`
entries for one `!apps/cli/src/**` entry

## how?

- `start`, `status`, `stop`, `services`, `notebooks`, `config push` and
`stack start`
yield the converted helpers and map failures with the same messages they
used to catch
- the error classes keep their names, so error codes and telemetry
fingerprints match develop.
- `SIDE_EFFECTS.md` notes now say `fs.realPath` where they said
`realpathSync`
> [!NOTE]
> (same here) nothing changes for users, 
> every command prints the same output and exits with the same codes and
errors.
>
> `local-db-running` stays excluded, it talks to the docker socket or
named pipe over node http and needs a windows check first.


## ref:

- closes: CLI-2837
…7309)

## TL;DR

brings `packages/api/src` and its tests under the effect lint

## whats introduced?

- `packages/api/src/**` joins the allow list, and the generated
`contracts.ts` stays out
- `SupabaseApiConfigError` and `SupabaseApiInputError` move to
`Data.TaggedError` with the same message, name, cause, json and printed
output, pinned by a new test, so two `apps/cli` call sites whose
failures include them now yield them directly
- `createApiClient` in `bun.ts` and `node.ts` chains its promise instead
of being `async`, still disposing the runtime before it rejects
- the src tests move to effect: `FileSystem` and `Path`, schema json
codecs, and `Effect.runPromise` bodies instead of `async` callbacks

## ref

- closes: CLI-2841
#7310)

## TL;DR

brings the `packages/api` generator scripts and their tests under the
effect lint, which completes the package

## whats introduced?

- the allow list entry widens to `packages/api/**`
- `download-openapi.ts` and `generate.ts` run as effect programs on
`FileSystem`, `HttpClient`, `Config` and `Console`, with the same
requests, console output, generated files and exit codes
- a failed run still prints the original error and exits 1, with effect
frames in the stack, and an empty `SUPABASE_API_URL` now reports
effect's `UrlError`
- the scripts tests move to effect, spawning turbo and oxfmt through
`ChildProcess`, and the `openapi.json` sync test now checks the
generator's own serializer

## ref

- closes: CLI-2842
- closes: CLI-2840
## TL;DR

brings `apps/cli/tests` and `apps/cli/vitest.config.ts` under the effect
lint

## whats introduced?

- `apps/cli/tests/**` and `apps/cli/vitest.config.ts` join the allow
list, replacing the seven per-file `tests/helpers` entries
- the test helpers, smoke tests and vitest config run on `FileSystem`,
`Path`, `Config` and `ChildProcess`, and promise helpers like
`runSupabase` keep their call shape and reject with the same values
- `spawnSupabase` and `makeTempHome` become scoped effects, and
`seedLegacyStateDecoys` and `setLinkedRefFile` become effects, so their
e2e and integration call sites yield them
- a timed out `until` run now kills its child and removes its temp home
instead of leaving both behind

## ref

- closes: CLI-2852
## Summary

`secret()` and `env({ secret: true })` mark config fields with
`x-secret`, but the published `config.schema.json` never carried it,
because the JSON Schema generator only emits standard keywords. The only
hint a field held a secret was the "do not commit" note in its
description, which tools can't act on.

The published CLI config schema now has `"x-secret": true` on every
field the schema marks secret. That includes the `remotes.*` copies and
the values of `db.vault` and `edge_runtime.secrets`. Editors ignore
unknown keywords, so validation and completion behave the same, and
nothing changes in how config is loaded.

- `toPublishedJsonSchemaDocument` now generates both published schemas
itself and lets only `x-secret` through, so internal annotations like
`x-env-deferred` stay out
- `project-config.schema.json` doesn't change, since it already leaves
secret fields out altogether
- `apps/docs/public/cli/config.schema.json` is regenerated, and the only
change is the added markers

## Linked issue

Closes CLI-2858
This bumps realtime from v2.147.4-r0 to v2.148.0-r0.


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

Planned after supabase/slim-services published v2.148.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.23-r0 to v1.84.25-r0.


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

Planned after supabase/slim-services published v1.84.25-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 realtime from v2.148.0-r0 to v2.148.1-r0.


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

Planned after supabase/slim-services published v2.148.1-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 27, 2026 02:25
@supabase-cli-releaser supabase-cli-releaser Bot added the do not merge Approve to apply; do not merge. label Oct 27, 2026
supabase-cli-releaser Bot and others added 2 commits October 27, 2026 03:47
This bumps realtime from v2.148.1-r0 to v2.148.2-r0.


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

Planned after supabase/slim-services published v2.148.2-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>
## TL;DR

unblocks go ci `Test`, red since #7287, by listing the nested `pkg`
module with `go list -C pkg` so pkg coverage returns and the coveralls
total drops

## ref:

<details>
<summary>as seen in:</summary>

<img width="529" height="751" alt="image"
src="https://github.com/user-attachments/assets/753837cc-7656-449c-ba53-525dbed7f385"
/>

</details>
const char = line[i];
const next = line[i + 1];
if (quote !== "") {
if (char === quote) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Severity: MEDIUM

Multiline, database-controlled E-strings can contain \', which this scanner mistakes for a closing quote. That can leave quote set for a later GRANT SET ON PARAMETER session_replication_role TO authenticated, bypassing the reserved-role filter; restored users could then disable triggers and bypass constraints (PostgreSQL docs).
Helpful? Add 👍 / 👎

💡 Fix Suggestion

Suggestion: Make the quote scanner aware of PostgreSQL E-strings (escape strings). When a single quote is opened with an E or e prefix, for example E'...', treat backslash as an escape character. Skip the character after each \, so \' and \\ never close the string. A doubled '' should still count as an escaped quote. Track this as a separate state, for example quote = "E'" or an isEString flag. Detect it when opening a quote: char === "'" && /[Ee]/.test(line[i - 1] ?? "") && !/[\w$]/.test(line[i - 2] ?? ""). Inside the string, use if (isEString && char === "\\") { i++; continue; } before the closing-quote check. Reset the flag when the string closes. inQuotedSql can stay quote !== "". As defense in depth, make the reserved-role GRANT ... ON PARAMETER filter not depend only on the multiline quote state. For example, also match lines that start with GRANT at column 0, since a pg_dumpall statement always begins a line.

…7336)

## TL;DR

brings `apps/cli/scripts` under the effect lint, so the allow list
collapses into one `!apps/cli/**` entry

## whats introduced?

- `apps/cli/scripts/**` joins the allow list, and the `src`, `tests` and
`vitest.config.ts` entries collapse into `!apps/cli/**`
- the build, release, publish and docs scripts run as effect programs on
`FileSystem`, `HttpClient` and `Config`, with the same arguments,
output, error messages, generated files and exit codes
- a failed run still crashes with the original error, so malformed json
keeps its native `SyntaxError`, and a signal during
`refresh-e2e-timings` still waits for its cleanup
- the scripts tests move to `it.effect` and `it.live` with the same
names and assertions

## ref

- closes: CLI-2853
- closes: CLI-2851
Comment thread apps/cli/scripts/generate-docs.ts Dismissed
supabase-cli-releaser Bot and others added 3 commits October 27, 2026 11:43
This bumps storage from v1.84.25-r0 to v1.84.28-r0.


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

Planned after supabase/slim-services published v1.84.27-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>
…7347)

## Summary

In stack mode, Edge Functions that boot at the same time can fail with
`503 BOOT_ERROR`. The logs show `Failed caching npm package … File
exists (os error 17)`, or `No such file or directory` when reading a
cached package file. This sets `noModuleCache: false` when the stack
bootstrap creates user workers, which is what classic `functions serve`
already does.

### What's going on

`noModuleCache: true` puts the worker's Deno cache into reload mode.
Each worker builds its own npm cache, so nothing is shared between
workers, and each one downloads every npm package it imports again. When
that package is already in the shared `DENO_DIR`, Deno extracts it again
in place, over the live copy, deleting and recreating each file. Two
workers doing that at the same time collide, and a worker that reads a
file in the middle of it finds it missing.

```mermaid
flowchart TD
  boot["Worker boots and imports npm:pkg"] --> flag{"noModuleCache"}
  flag -- "false" --> cached{"pkg in the cache?"}
  cached -- "yes" --> reuse["Reuse it"]
  cached -- "no" --> temp["Extract to a temp dir,<br/>then rename into place"]
  flag -- "true" --> cached2{"pkg in the cache?"}
  cached2 -- "no" --> temp
  cached2 -- "yes" --> inplace["Extract again in place,<br/>over the live copy"]
  inplace --> fail["Concurrent boots collide<br/>503 BOOT_ERROR"]
```

```mermaid
sequenceDiagram
  participant A as Worker A
  participant C as Shared Deno cache
  participant B as Worker B
  A->>C: create pkg/README.md (exists, so delete it)
  B->>C: create pkg/README.md (succeeds)
  A->>C: create pkg/README.md
  C-->>A: File exists (os error 17)
  Note over A: 503 BOOT_ERROR
```

This explains the odd parts of the report:

- A package that isn't cached yet goes through the temp dir and rename,
which is safe. That's why a cold first round often passes, and why a
warm-up request doesn't help.
- Native keeps its cache across `stop` and `start`, so it fails much
more often than Docker, whose new container starts with an empty cache.
- `forceCreate: true` boots a new worker for every request, so every
request goes down this path. I've left it as it is, because it's what
makes edits show up without a restart.

Against Edge Runtime directly, with only this flag changed, 40 of 64
concurrent boots failed with it on and none of 112 failed with it off.

### What changes

- npm packages and remote modules are reused from the cache instead of
being downloaded and extracted on every boot, so boots are quicker too.
- An exact version that isn't cached yet still resolves, because Deno
fetches package info again when resolution fails. Floating versions like
`npm:x@latest` stay on the cached version until the cache resets (a new
container on Docker, `stack destroy` on native). That matches classic
`functions serve` and `deno run`.
- Local function code is still read from disk on every boot, so edits
show up straight away.
- A new integration test serves a package from a local npm registry,
warms the cache, then boots several workers at once. It checks that they
all succeed and that the package is downloaded only once.

Earlier bootstraps and classic `functions serve` use `false`. If `true`
was there for something I've missed, I'm happy to talk it through.

## Linked issue

Closes #7321 (CLI-2850)
…n the config schema (#7333)

## Summary

The config loader resolves `env(VAR)` on any field and then coerces it
to the field's type, but the published `config.schema.json` typed
number, integer, boolean, enum and string-list fields strictly. So
`max_rows = "env(MAX_ROWS)"` loads fine but shows as an error in the
editor.

Those fields now accept either their usual value or a string matching
the loader's `env()` syntax. A mistyped literal like `max_rows = "1000"`
or `pool_mode = "statement"` still fails.

- `toPublishedJsonSchemaDocument` takes an `acceptEnvReferences` option,
and the CLI config schema turns it on. Each affected field becomes an
`anyOf` of its original type and an `env()` string, with `description`,
`default` and `examples` kept on the outer node so hover docs look the
same
- String lists such as `auth.additional_redirect_urls` accept an `env()`
string in place of the whole list, since the CLI splits the resolved
value on commas. Lists of enums don't, as the loader doesn't split those
- Fields that are already a union (e.g. `storage.file_size_limit`) get
one extra `env()` branch rather than a nested one
- `project-config.schema.json` doesn't change, since it describes values
after `env()` has been resolved
- `apps/docs/public/cli/config.schema.json` is regenerated
- `ajv` is added as a dev dependency of `@supabase/config` so tests can
check the published schema against what the loader accepts

## Schema shape change

If you generate types or other tooling from `config.schema.json`, the
affected fields now read as a union: their `type` moves from the field
itself into the first `anyOf` branch, next to the `env()` branch.
Configs that validated before still validate.

## Linked issue

Closes CLI-2857
7ttp added 3 commits October 27, 2026 17:18
## TL;DR

adds an ECR Public fallback for slim images, so a GHCR rate limit no
longer fails `supabase start`

## whats introduced?

with `SUPABASE_USE_SLIM_IMAGES` on, slim images only came from GHCR, so
a `toomanyrequests` burst failed the command

a failed GHCR pull now falls back to the same tag and digest on
`public.ecr.aws/supabase/cli`,
the mirror the stack already uses
ps: containers started from the mirror keep their slim healthchecks and
pass the `db` stale image guard

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

```mermaid
flowchart LR
    pull["slim image pull"] --> ghcr["ghcr.io/supabase/cli"]
    ghcr -->|ok| run["container starts"]
    ghcr -->|"fails 3 times"| ecr["public.ecr.aws/supabase/cli<br/>same tag and digest"]
    ecr --> run
```

</details>

## ref

- closes: #7338
…7345)

## TL;DR

adds `X-Forwarded-For` and `X-Real-IP` to what the stack gateway sends
upstream, so edge functions can see who is calling them

## whats introduced?

the gateway now appends the client address to any incoming
`X-Forwarded-For` chain and sets
 `X-Real-IP` to the client address, the same way the legacy backend does

both the http path and the websocket upgrade path send them

a client sent `X-Real-IP` is always replaced or dropped, so callers cant
spoof it through the gateway

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

```mermaid
flowchart LR
  subgraph before
    A1[client] --> B1[stack gateway]
    B1 --> C1[edge function sees no client address]
  end
  subgraph now
    A2[client] --> B2[stack gateway]
    B2 --> D2{peer address known}
    D2 -->|yes| E2["append client to X-Forwarded-For<br/>set X-Real-IP to client"]
    D2 -->|no| F2[drop client sent X-Real-IP]
    E2 --> G2[http and websocket upstreams]
    F2 --> G2
    G2 --> H2[edge function sees the caller]
  end
```

</details>

## ref

- closes: #7275
…h effect lint (CLI-2881) (#7348)

## TL;DR

brings `tools`, `apps/docs` and `packages/cli-test-helpers` under the
effect lint

## whats introduced?

- `apps/docs/**`, `packages/cli-test-helpers/**` and `tools/**` join the
allow list
- the release and config tools run as effect programs on `FileSystem`
and `HttpClient`, with the same requests, console output, files written
and exit codes, so the root gains `effect` and `@effect/platform-bun`
dev dependencies
- the test harness runs on effect too, so `cli-test-helpers` gains the
same two as dependencies, and `makeTempDir` returns a promise of an
async disposable dir, so its two `apps/cli-e2e` call sites await it
- the docs page swaps its `async` functions for promise chains and
renders the same pages
- `local-registry.ts` adds one `oxlint-disable` for the `openSync` log
descriptor Verdaccio shares across stdout and stderr, which effect's
`ChildProcess` cannot hand over
- a failed run prints the same error, with effect frames in the stack

## ref

- closes: CLI-2881

This branch was successfully deployed

1 active (outdated) deployment
config-release — 3507dba6 Deployed Oct 27, 2026 by github-merge-queue[bot] via Publish #45
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.

6 participants