Skip to content

chore: production deploy - #6416

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

chore: production deploy#6416
supabase-cli-releaser[bot] wants to merge 85 commits into
mainfrom
develop

Conversation

@supabase-cli-releaser

Copy link
Copy Markdown
Contributor

johnstonmatt and others added 30 commits August 26, 2026 20:17
## Summary

Adds `supabase workers new`, plus the project layout and `config.toml`
editing the
whole command family builds on:

- `shared/workers/` — worker path resolution, `config.toml` section
reading and
patching (`toml-section.ts` preserves surrounding formatting), the
runtime/size
  envelope, and the starter files.
- Starter files live as ordinary files under
`shared/workers/stacks/<runtime>/`
rather than string literals, and are embedded into the compiled binary
through a
  Bun macro — the directory is expanded at transpile time and inlined.
A completeness check inside the macro fails the build if
`WORKER_RUNTIMES` and
  the directory drift apart.

**Stack 2 of 4**, on top of the config schema (#6260).

Reviewer note: the third commit is where the embedding mechanism is
explained; the
starters are deliberately kept out of the type program (a `deno` starter
is not
valid under this workspace's Bun types), which is why `tsconfig.json`
excludes the
directory and nothing imports the files.

## Linked issue

FUNC-753 (Linear). Supabase maintainer, exempt from the
`open-for-contribution` flow.

## Checklist

- [x] The PR title follows [Conventional
Commits](https://www.conventionalcommits.org/)

---------

Co-authored-by: Kanad Gupta <git@kanad.dev>
## Summary

Adds `supabase workers push` (aliased `deploy`) and the machinery it
needs:

- `workers-api.ts` — the typed Workers Management API client.
- `tar.ts` / `worker-package.ts` — packaging a worker directory into the
build
  context that gets uploaded.
- `worker-classify.ts` — best-effort runtime detection from marker
files, so a
directory with no `[workers.<name>] runtime` can still deploy. The guess
is
  always reported with a nudge to pin it down, never applied silently.

**Stack 3 of 4**, on top of `workers new` (#6261).

## Linked issue

FUNC-753 (Linear). Supabase maintainer, exempt from the
`open-for-contribution` flow.

## Checklist

- [x] The PR title follows [Conventional
Commits](https://www.conventionalcommits.org/)
…te (#6350)

Bumps the go-minor group with 1 update in the /apps/cli-go directory:
[google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the go-minor group with 1 update in the /apps/cli-go/pkg
directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).

Updates `google.golang.org/grpc` from 1.83.0 to 1.83.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/grpc/grpc-go/releases">google.golang.org/grpc's
releases</a>.</em></p>
<blockquote>
<h2>Release 1.83.1</h2>
<h1>Security</h1>
<ul>
<li>xds/rbac: Fix a bug where nested <code>Principal</code> or
<code>Permission</code> rules with <code>:scheme</code> or
<code>grpc-</code> prefixed header matchers were not rejected, which
could cause DENY rules to fail open. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9258">#9258</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/nvxbug"><code>@​nvxbug</code></a></li>
</ul>
</li>
<li>xds/rbac: Fix a bug where the <code>host</code> header matcher was
not being replaced with <code>:authority</code> in nested
<code>Principal</code> or <code>Permission</code> rules. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9258">#9258</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/nvxbug"><code>@​nvxbug</code></a></li>
</ul>
</li>
<li>xds/rbac: Fix a bug where a header matcher whose name was not
lowercase, such as <code>X-Role</code>, matched no header, which could
cause DENY rules to fail open. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/alimony"><code>@​alimony</code></a></li>
</ul>
</li>
<li>xds/rbac: Fix a bug where a <code>:scheme</code> or
<code>grpc-</code> prefixed header matcher was accepted when its name
was not lowercase. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/alimony"><code>@​alimony</code></a></li>
</ul>
</li>
<li>xds/rbac: Fix a bug where a <code>Host</code> header matcher was not
replaced with <code>:authority</code>. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/alimony"><code>@​alimony</code></a></li>
</ul>
</li>
</ul>
<h1>Performance</h1>
<ul>
<li>transport: Restrict memory overhead of buffering small data frames.
(<a
href="https://redirect.github.com/grpc/grpc-go/issues/9331">#9331</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/grpc/grpc-go/commit/1550d9e0cddb30ce99e61a2102e8294a49461e5e"><code>1550d9e</code></a>
Change version to 1.83.1 (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9336">#9336</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/ebba6f3f1b206e2b4dc4d1d5a96d18430302c2fe"><code>ebba6f3</code></a>
Cherry-pick <a
href="https://redirect.github.com/grpc/grpc-go/issues/9258">#9258</a>
and <a
href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>
into v1.83.x (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9335">#9335</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/8cfeca0e1ee5ea0980dcc320e20240fa1079ec77"><code>8cfeca0</code></a>
Cherry-pick <a
href="https://redirect.github.com/grpc/grpc-go/issues/9331">#9331</a> to
v1.83.x (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9333">#9333</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/dec6951305e88906696f1d0a00dd2439363bc708"><code>dec6951</code></a>
Change version to 1.83.1-dev (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9229">#9229</a>)</li>
<li>See full diff in <a
href="https://github.com/grpc/grpc-go/compare/v1.83.0...v1.83.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `google.golang.org/grpc` from 1.83.0 to 1.83.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/grpc/grpc-go/releases">google.golang.org/grpc's
releases</a>.</em></p>
<blockquote>
<h2>Release 1.83.1</h2>
<h1>Security</h1>
<ul>
<li>xds/rbac: Fix a bug where nested <code>Principal</code> or
<code>Permission</code> rules with <code>:scheme</code> or
<code>grpc-</code> prefixed header matchers were not rejected, which
could cause DENY rules to fail open. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9258">#9258</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/nvxbug"><code>@​nvxbug</code></a></li>
</ul>
</li>
<li>xds/rbac: Fix a bug where the <code>host</code> header matcher was
not being replaced with <code>:authority</code> in nested
<code>Principal</code> or <code>Permission</code> rules. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9258">#9258</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/nvxbug"><code>@​nvxbug</code></a></li>
</ul>
</li>
<li>xds/rbac: Fix a bug where a header matcher whose name was not
lowercase, such as <code>X-Role</code>, matched no header, which could
cause DENY rules to fail open. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/alimony"><code>@​alimony</code></a></li>
</ul>
</li>
<li>xds/rbac: Fix a bug where a <code>:scheme</code> or
<code>grpc-</code> prefixed header matcher was accepted when its name
was not lowercase. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/alimony"><code>@​alimony</code></a></li>
</ul>
</li>
<li>xds/rbac: Fix a bug where a <code>Host</code> header matcher was not
replaced with <code>:authority</code>. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/alimony"><code>@​alimony</code></a></li>
</ul>
</li>
</ul>
<h1>Performance</h1>
<ul>
<li>transport: Restrict memory overhead of buffering small data frames.
(<a
href="https://redirect.github.com/grpc/grpc-go/issues/9331">#9331</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/grpc/grpc-go/commit/1550d9e0cddb30ce99e61a2102e8294a49461e5e"><code>1550d9e</code></a>
Change version to 1.83.1 (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9336">#9336</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/ebba6f3f1b206e2b4dc4d1d5a96d18430302c2fe"><code>ebba6f3</code></a>
Cherry-pick <a
href="https://redirect.github.com/grpc/grpc-go/issues/9258">#9258</a>
and <a
href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>
into v1.83.x (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9335">#9335</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/8cfeca0e1ee5ea0980dcc320e20240fa1079ec77"><code>8cfeca0</code></a>
Cherry-pick <a
href="https://redirect.github.com/grpc/grpc-go/issues/9331">#9331</a> to
v1.83.x (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9333">#9333</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/dec6951305e88906696f1d0a00dd2439363bc708"><code>dec6951</code></a>
Change version to 1.83.1-dev (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9229">#9229</a>)</li>
<li>See full diff in <a
href="https://github.com/grpc/grpc-go/compare/v1.83.0...v1.83.1">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

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

Changes were detected in the generated API code after syncing with the
latest spec from infrastructure.

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

- Replace the runtime REST and SSE daemon protocol with a static control
plane exposing owner discovery, session-fenced shutdown, and
same-version Effect RPC over HTTP and NDJSON.
- Use the immutable, unique CLI version as the sole runtime
compatibility identity; source execution uses the explicit 0.0.0-dev
development sentinel.
- Make an incompatible CLI version an explicit parent-owned full stack
stop/start authorized only by supabase start; connect-only and ordinary
child paths report the typed upgrade requirement without restarting the
live owner.
- Preserve managed data, document and launch metadata, runtime
selection, pinned service versions, raw exclusions, and sticky ports
across the upgrade restart.
- Serialize startup, runtime scope ownership, terminal persistence, and
shutdown through one Effect Queue-backed SupervisorSession actor,
releasing the control listener last across Node, Bun, and compiled Bun
runtimes.
- Update CLI consumers, error reporting, integration helpers, targeted
process coverage, and durable architecture documentation for the
single-protocol cutover.

## Linked issue

None.

## Reviewer context

This intentionally has no legacy protocol window, compatibility adapter,
adoption path, or in-place supervisor swap. Runtime RPC is a
same-version boundary; owner discovery and session-fenced shutdown
remain the stable cross-build protocol. Upgrading through supabase start
restarts the complete stack, so active application connections and
tooling streams disconnect briefly while durable state and launch
selections remain intact.
## Summary

- remove the remaining Nx configuration, package metadata, inference
plugin workspace, dependencies, cache ignores, and lockfile graph
- update current contributor guidance to use package scripts and
root-owned Turbo tasks for execution and dependency inspection
- preserve the build, generation, quality, live, auxiliary, and test
graphs established by the preceding Turborepo migrations

## Context

PR #6343 merged while this change was in progress, so this branch was
rebased onto the updated `develop` branch containing its final live and
auxiliary task migration. Task execution is now owned entirely by
package scripts and Turbo.

Affected execution, persistent cache storage, and remote caching remain
separate follow-up optimizations.
This PR was automatically created to sync the generated `@supabase/api`
package with the latest Management API OpenAPI document.

Changes were detected in the upstream OpenAPI documents exposed by
`https://api.supabase.com/api/v1-json` and
`https://api.supabase.com/api/v2-json`.

Co-authored-by: jgoux <1443499+jgoux@users.noreply.github.com>
…dates (#6320)

Bumps the docker-minor group with 5 updates in the
/apps/cli-go/pkg/config/templates directory:

| Package | From | To |
| --- | --- | --- |
| postgrest/postgrest | `v16.1` | `v16.2` |
| supabase/studio | `2026.08.17-sha-0c1da8f` | `2026.08.24-sha-8ec45b2`
|
| supabase/realtime | `v2.129.3` | `v2.129.9` |
| supabase/storage-api | `v1.70.3` | `v1.71.0` |
| supabase/logflare | `1.50.4` | `1.50.6` |


Updates `postgrest/postgrest` from v16.1 to v16.2

Updates `supabase/studio` from 2026.08.17-sha-0c1da8f to
2026.08.24-sha-8ec45b2

Updates `supabase/realtime` from v2.129.3 to v2.129.9

Updates `supabase/storage-api` from v1.70.3 to v1.71.0

Updates `supabase/logflare` from 1.50.4 to 1.50.6


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Julien Goux <hi@jgoux.dev>
This PR was automatically created to sync the generated `@supabase/api`
package with the latest Management API OpenAPI document.

Changes were detected in the upstream OpenAPI documents exposed by
`https://api.supabase.com/api/v1-json` and
`https://api.supabase.com/api/v2-json`.

Co-authored-by: jgoux <1443499+jgoux@users.noreply.github.com>
This PR was automatically created to sync API types from the
infrastructure repository.

Changes were detected in the generated API code after syncing with the
latest spec from infrastructure.

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

Defense-in-depth hardening for the automated release-notes generator
(`propose-release-notes.yml` →
`apps/cli/scripts/propose-release-notes.ts`), which runs the Claude
Agent SDK with `Bash` + `WebFetch`/`WebSearch` and feeds it the
semantic-release changelog block (built from contributor commit subjects
/ PR titles) plus PR bodies and linked issues it fetches at runtime —
all attacker-influenceable content, previously with no injection guard.

This PR adds an explicit **trust boundary** to
`tools/release/release-notes-prompt.md`:

- A top-of-file section establishing that the changelog block and all
fetched PR/issue/web content are **untrusted data to be summarized,
never instructions to obey**.
- Rules that override embedded instructions: don't act on injected
commands; never disclose env vars / secrets / tokens; restrict `Bash` to
read-only `gh` GETs on `supabase/cli`; restrict `WebFetch`/`WebSearch`
to `github.com/supabase/cli`; produce only the release-notes markdown.
- Inline reminders at the two points where untrusted content enters (the
changelog block and the PR-investigation step).

The `{{PASTE_SEMANTIC_RELEASE_BLOCK_HERE}}` placeholder is unchanged, so
the generator's template check and output contract are unaffected.

## Scope / follow-up

This is **defense-in-depth only** — prompt guards are best-effort
against a determined injection. The stronger, structural containment is
deliberately **left for a follow-up**:

1. Separate the write-capable GitHub App token (`GH_TOKEN`,
`contents`/`pull-requests: write` on the protected default branch) from
the agent's process — generate notes in an agent-only step with no GH
token, then push/open the PR in a separate step that runs no model.
2. Drop `Bash` (and ideally `WebFetch`) from the agent's `allowedTools`,
pre-fetching the PR/issue data with trusted code instead — removing the
shell/network exfiltration primitive.

Context: surfaced during the security review of the AI-review pipeline
(#6358); the release-notes workflow shares the "untrusted content +
secrets in an agentic CI job" class of exposure, gated behind a
maintainer-cut stable release rather than per-PR.
… (CLI-2230) (#6339)

## What changed

Implements
[CLI-2230](https://linear.app/supabase/issue/CLI-2230/create-a-toprojectconfig-function-that-is-exported-from-the-config):
the hosted-project subset type `ProjectConfig` and its normalizers,
exported from `@supabase/config`'s pure (browser-safe) entrypoint so the
CLI and Studio share one mapper.

- **`fromConfigDocument(config)`** — projection of a `CliConfig`
document (or any `EffectiveConfig`) down to the hosted sections (`api`,
`auth`, `db`, `realtime`, `storage`, `workers`, `experimental`).
- **`fromApiProjectConfig(input)`** — translation of a Management API v2
project-config response (full envelope, `data` object, or bare
`data.attributes`). Registry-driven: 233 mapping rows mined from the
legacy `config push` sync mappers (`config-sync/*.sync.ts`), covering
renames (`rate_limit_otp` → `sign_in_sign_ups`), boolean inversions
(`disable_signup`, `mailer_autoconfirm`), unit conversions
(seconds/hours → Go duration strings, int64 bytes → BytesSize), the
GoTrue key table (19 OAuth providers, 6 hooks, 5 SMS providers), and
`x-secret` omission (the API only reports HMAC digests). Decode is
lenient per ADR 0019 — unknown/API-ahead keys never fail; the raw
attributes ride along as a **non-enumerable `_apiResponse`** (invisible
to encodes, spreads, and structural walks; never persisted), with a
registry-derived `unmappedApiFields()` reader.
- **`toProjectConfig(source)`** — thin dispatcher over both (`{
cliConfig }` / `{ apiResponse }`).

### Operand widening (ruling on CLI-2230)

`ProjectConfig` is deliberately **sparse** — an API response never
mentions sections it doesn't manage, and flooding in schema defaults
would fabricate drift. To make it a first-class operand of the
comparison core, `BaseCliConfig` is replaced by the family-neutral
`EffectiveConfig = DeepPartial<Omit<CliConfig, "remotes">>` on
`subtractCliConfig`/`omitDefaultValues`. No runtime change — the
subtraction walk already had the right absence semantics. Recorded in
ADR 0018's 2026-08-26 addendum; the naming-rule generalization lands
separately with CLI-2238 (#6335).

### apps/cli

- A type-drift guard (`project-config-api-drift.unit.test.ts`) pins the
generated `V2GetProjectConfigOutput` attributes against the package's
lenient input schema: assignability (catches type widening) plus
per-section key-set assertions (catch added/removed/renamed fields) — so
OpenAPI drift fails compile before it can silently break the mapping. No
runtime dependency on `packages/api` was added.
- `ProjectConfigParseError` registered in the error-actionability table
as `apiStatus` (a malformed platform response, not a user config
mistake).

### Reviewer notes

- Deliberate divergences from the legacy apply semantics are documented
inline where they occur: API `null` → omit (sparse output has no local
document to fall back to), `uri_allow_list` trimming, `smtp_host: ""`
treated as disabled, `sms_autoconfirm` **not** inverted (matches
`auth.sync.ts:1677/:2485` — only the mailer counterpart inverts).
- An explicit `db_schema: ""` maps to `{ api: { enabled: false } }`
only, mirroring `applyRemoteApiConfig`'s early return; an *absent*
`db_schema` doesn't gate the sibling fields.
- Follow-up candidate deliberately not in this PR: a parity test pinning
the replicated legacy helpers
(duration/BytesSize/parseUint16/envToMap/password charsets) against
their `apps/cli` originals. (ADR 0019's attach helper *did* land in the
second round below, as `attachApiResponse`.)

### Second review round (commit 93b4679) — adjudication record

A two-set review (architect/engineer/security/DX + adversarial
execution) ran against bdd607f. The registry mapping itself survived
three independent verification passes with zero defects; every accepted
finding about the surrounding surface is fixed in 93b4679:

- **Secrets**: `fromConfigDocument` now deep-copies and omits every
`x-secret` leaf (schema-derived, `lib/secret-paths.ts`) — decoded
documents hold plaintext credentials, and the subtract composition
rendered them as drift.
- **Spelling convergence**: new registry `normalizeDocument` column
canonicalizes document-side duration and byte-size spellings so both
normalizers emit one form for one logical value.
- **Leniency**: the mirror schema types every never-mapped field
`Schema.Unknown`, so a platform type change on a field nothing reads can
no longer fail every decode.
- **Errors**: `ProjectConfigParseError` gained
`message`/`detail`/`suggestion` (upgrade-then-report), schema-issue
paths lift into `apiPath`, telemetry adds `fingerprint_suffix:
"api_response"` + `has_suggestion`.
- **Type-mismatch unification**: string rows, `smtp_host`/`smtp_port`,
and CIDR entries now throw typed errors instead of fabricating values
(`enabled: false`), vanishing silently, or partially filtering a
security allowlist; `expectNumber` rejects non-finite.
- **`_apiResponse`**: cloned + deep-frozen at attach (no caller
aliasing); `attachApiResponse` export restores it across spread/clone
round-trips; invisibility claim narrowed (serializers and walks — debug
inspectors like Bun's `console.log` still print it; never log an
API-sourced config).
- **`unmappedApiFields`**: recursion depth cap; `unmappedSecretApiPaths`
deny list (`external_figma_secret` — the one genuine orphan digest; the
review's other two candidates don't exist in the legacy source).
- **New guards/exports**: `registry-integrity.unit.test.ts` (all 233
rows' paths resolve against the schema ASTs, 470 generated cases);
drift-guard key-set levels completed;
`comparableProjectConfigPaths`/`isComparableProjectConfigPath` so diff
consumers never hand-maintain field lists; `inverse` implementations
dropped until the push mapper derives them.

**Explicit rejections** (reviewed, not silently deferred):
1. *`alsoConsumes` static consumed-set*: "consumed" means
known-to-this-registry-version, not mapped-on-this-run — an
`alsoConsumes` sibling whose anchor didn't run stays suppressed by
design and remains in `_apiResponse`. Documented in `walkUnmapped`.
2. *WeakMap sidecar for `_apiResponse`*: deferred — clone+freeze
resolves the aliasing hazard and the narrowed docstring is honest;
revisit if CLI-2156 consumption shows inspectors bite (ADR 0019 records
the alternative).
3. *`fromCliConfig`/`fromApiResponse` renaming*: the shipped names are
already recorded in ADR 0020 (#6335), Linear, and coordinated docs —
symmetry isn't worth re-coordinating three artifacts.
4. *Branding `EffectiveConfig`*: took the ADR 0018 consequence note
instead (widening removes the static every-section guarantee; callers
own operand completeness).
5. *`ProjectConfigApiAttributes` placement* and *`"sideEffects":
false`*: deferred to their owning issues with notes filed — CLI-2234
(export-surface audit) and CLI-2232 (verify the bundler claim against a
built artifact).

### Verification round (commits 5f389c9 + 0424ac7)

An executed verification pass over 93b4679 re-ran all prior attacks
(10/10 now pass) and surfaced residuals, fixed in 0424ac7:

- **Orphan digests were 3, not 1** — the generated
`V1GetAuthServiceConfigOutput` contract (not the legacy interface) is
the authority; `external_slack_secret`,
`hook_after_user_created_secrets`, and `nimbus_oauth_client_secret` join
the deny list, and a new apps/cli **contract-guard test** cross-checks
every auth apiPath + secret-suffixed contract key against the registry
(also closing the open-Record vacuity in the integrity test's auth
checks). Registry rows are now exported from the package root to serve
it.
- **Clone/freeze regression fixed**: deep/cyclic/non-cloneable payloads
now throw `ProjectConfigParseError` instead of raw
`RangeError`/`DOMException` (depth-capped pre-walk, wrapped clone,
cycle-guarded `deepFreeze`).
- **README example rewritten and executed** (the previous snippet
self-subtracted and filtered section names — always empty);
secret-stripped projections prune emptied containers; a real
phantom-drift pin replaces an agreeing-case test;
`comparableProjectConfigPaths`' docstring narrowed to the section-level
claim it delivers; ADR 0019 gained a dated addendum (attach helper,
structural "verbatim", debug-inspector caveat).
- **Documented-not-changed**: byte-size canonicalization quantizes at 4
significant digits symmetrically on both arms — sub-0.1% differences
comparing equal is a deliberate property (user-authored spellings are
exact).

The merge commit resolves the pre-agreed README conflict with #6335
(their `## Naming` section wins, its "in flight" sentence flipped) and
de-stales ADR 0020's phrasing, per the coordinated rebase checklist.
Known external: root `check:all` fails on `@supabase/cli-go#lint:check`
(5 gosec findings in Go files byte-identical to develop —
develop-side/toolchain, not this PR).

### Drift-audit round (commit 492ee25)

A 2026-08-27 audit compared the post-codex state against CLI-2230's
design intent. All eight structural commitments verified intact (pure
entrypoint, no `packages/api` dependency, sparse output +
`EffectiveConfig`, ADR 0019 guardrails, registry-driven with `inverse`
unimplemented, purity graph, naming, secret stripping). Three executed
repros surfaced semantic drift introduced by the codex rounds; fixed
here:

- **Leniency**: `JSON.parse('{"x":1e400}')` yields `Infinity`, so the
round-12 non-finite pre-decode rejection hard-failed a real JSON payload
on an *unknown* field (mis-bucketed as `caller_misuse`). The walk now
rejects only bigint/`undefined`/`NaN` (values `JSON.parse` cannot
produce); non-finite values decode and surface as `null` from
`unmappedApiFields` (scalars and inside array leaves, identity preserved
for all-finite arrays). ADR 0019 gains a dated leniency-boundary
addendum.
- **SMTP absence semantics**: an absent `smtp_host` previously counted
as the disabled sentinel, silently dropping
`smtp_user`/`smtp_admin_email`/`rate_limit.email_sent` from both the
output and `unmappedApiFields` — contradicting the SMS
absent-vs-sentinel rule beside it. Absence now says nothing; only the
explicit `""`/`null` legacy sentinel disables (three-state, extended to
the `email_sent` cross-section rule).
- **Convergence-predictor ruling (ADR 0021)**: the codex rounds had
incrementally turned both normalizers into *post-push convergence
predictors* (SMS provider precedence flips extra enabled providers,
disabled-sentinel pruning, `null`-gated booleans, CSV/uint/duration
canonicalization) — defensible (it kills phantom drift for CLI-2156) but
never adjudicated or documented. Ruling: **accepted**, now recorded in
ADR 0021, the
`ProjectConfig`/`fromConfigDocument`/`fromApiProjectConfig` docstrings,
and the README ("not a verbatim representation" caveat).
- **Guards**: the three hand-written sentinel/precedence tables
(`DISABLED_SENTINEL_PRUNES`, `DISABLED_SENTINEL_ENTRY_SWEEPS`,
`SMS_PROVIDER_PUSH_PRECEDENCE`) now resolve every path/key against the
schema ASTs in `registry-integrity` — previously a schema rename
silently no-opped them — and the SMS precedence order is pinned against
the legacy push switch (`auth.sync.ts:2498-2539`).
- Residual cleanups: the stale `Math.trunc` comment above the fraction
arithmetic (round-11/14 artifact the round-20 revert missed),
`ReadonlyJsonValue` exported (it appears in public types),
`smtpExplicitlyDisabledInAttributes` simplified to mirror
`smsProviderExplicitlyUnset`, ADR index gains 0020/0021.

An engineer-review pass over the fix diff verified every change; its
findings (the `email_sent` asymmetry, stale ADR citations, formatter
gate, doc phrasing) are folded in. 984/984 package tests, 461/461
apps/cli guard tests, typechecks clean both packages.

Follow-ups filed so they survive CLI-2230 closing:
[CLI-2266](https://linear.app/supabase/issue/CLI-2266/derive-the-config-push-mapper-from-the-projectconfig-mapping-registry)
(registry-derived push mapper — carries the three requirements
previously parked as CLI-2230 comments) and
[CLI-2267](https://linear.app/supabase/issue/CLI-2267/pin-supabaseconfigs-replicated-legacy-parsers-with-parity-fixtures-in)
(parity fixtures pinning the replicated legacy parsers against
`config-sync/*`).

Fixes CLI-2230

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

Replaces the Codex GitHub App's per-push auto-review churn (often 30–40
short rounds per PR) with an in-repo pipeline that reviews each PR
**exactly once**, unless a maintainer explicitly re-runs it.

**Pipeline** (`.github/workflows/ai-review.yml`; full design + security
model in `.github/ai-review/README.md`):

1. **resolve** — decides whether to run: once-per-PR dedup (bot-authored
marker), draft/bot/fork skips for auto triggers, `/ai-review`
authorization (requires repo **write/admin** via effective-permission
lookup), diff-size guard. Runs only trusted default-branch code.
2. **claude-review** — Claude Code headless (`claude-fable-5`), one
exhaustive pass, read-only tools, JSON validated against
`findings.schema.json`.
3. **codex-review** — `openai/codex-action` (`gpt-5.6-sol`, drop-sudo +
read-only sandbox): independent review **plus** adjudication of every
Claude finding (confirmed / refuted-with-evidence / uncertain), merged
into `merged-review.schema.json`.
4. **post-review** — deterministic Bun script posts **one** consolidated
PR review (`COMMENT`, advisory only): inline comments for anchorable
findings, refuted findings preserved in a collapsed section (never
silently dropped), verdict counts computed locally (not trusted from the
model). Re-runs supersede the prior review.

**Once-per-PR**: no `synchronize` trigger, bot-authored marker dedup,
per-PR concurrency (non-command comments can't cancel an in-flight run).
Re-run only via `/ai-review` (maintainers) or `workflow_dispatch`.

## Security model

This ran through security + engineering review (twice). A critical
secret-exfiltration path was found and closed; the design now enforces:

- **Model jobs never execute PR-authored code.** The PR head is checked
out only as read-only review subject matter (`claude` reads it with
Read/Grep/Glob under `--bare`/`--strict-mcp-config`); every executed
file — prompts, schemas, the validator script — comes from a separate
trusted default-branch checkout, and no `bun` process ever runs with a
cwd inside the PR checkout (so a PR-authored `bunfig.toml`/`.env` can't
preload code). npm installs are config-isolated and version-pinned;
Codex reviews from `/tmp` with no PR checkout at all.
- **Least privilege**: top-level `permissions: {}`; model jobs hold no
write scope; the only write-capable job (`post-review`) runs base-branch
code exclusively. All actions SHA-pinned.
- **Output is scrubbed**: model-provided text is sanitized
(mentions/refs/HTML neutralized, `file` field guarded against markdown
breakout) and secret-pattern-redacted before it's posted or uploaded as
an artifact (defense-in-depth; a dedicated rotatable key is the real
containment — see README).
- Advisory-only (`COMMENT`), never a required check, never runs in the
merge queue.

## Rollout (shadow mode)

The `pull_request` trigger ships **commented out**. Plan: add a
dedicated `OPENAI_API_KEY` secret (and ideally a dedicated
`ANTHROPIC_API_KEY` rather than the shared release-notes key), tune
prompts against real PRs via `workflow_dispatch`, then enable the
trigger and switch the Codex app to manual-only simultaneously. Steps +
caveats in the README.

## Notes for reviewers

- New `.github/workflows/github-scripts-ci.yml` finally runs the
`.github/scripts` test suites + type-check in CI (they ran nowhere
before — this also covers the pre-existing `contribution-gate` tests).
- Requires a new `OPENAI_API_KEY` repo secret; `ANTHROPIC_API_KEY`
already exists.
Two CI fixes for the AI-review pipeline (#6358), both surfaced
immediately after merge.

## 1. `Claude review` job fails at "Fetch PR diff and metadata"

The first live `/ai-review` run failed with `fatal: not a git
repository`. The `claude-review` job checks out into **subdirectories**
(`pr/` for the PR head, `trusted/` for the base), so `$GITHUB_WORKSPACE`
itself isn't a git repo — and `gh pr diff`/`gh pr view` infer the repo
from the current directory's git remote. Fix: pass `--repo
"$GITHUB_REPOSITORY"` explicitly at both `gh` call sites (claude-review
and, defensively, codex-review) so `gh` never depends on cwd.

## 2. `Test and type-check` (github-scripts-ci) times out

The shared `./.github/actions/setup` installs the full workspace + Go
toolchain via mise (~9–10 min), which raced the job's `timeout-minutes:
10` and got cancelled on a cold cache (the setup step never finished;
tests/type-check never ran). Raised to 20 min. Noted inline that the
check is heavier than it needs to be for two scripts — slimming the
setup is a possible follow-up.
## Summary

Completes the command family with the three remaining subcommands:

- `workers list` — this project's workers.
- `workers status` — one worker in detail.
- `workers delete` — remove a worker, with confirmation.

All three reuse the API client and output helpers introduced in #6262,
so this is
the smallest layer of the stack.

**Stack 4 of 4**, on top of `workers push` (#6262).

## Linked issue

FUNC-753 (Linear). Supabase maintainer, exempt from the
`open-for-contribution` flow.

## Checklist

- [x] The PR title follows [Conventional
Commits](https://www.conventionalcommits.org/)
## Summary

Set up Effect-aware Oxlint for `packages/stack` and
`packages/process-compose` using the Effect-recommended Oxlint preset
and TypeScript plugin. The scoped check is wired into the monorepo task
graph and denies warnings, matching the global Oxlint policy. The
generic pass excludes these two packages while the scoped config extends
the generic ruleset, so generic and Effect rules each run exactly once
without bringing Effect lint into `apps/cli`.

Remediate the existing scoped diagnostics in reviewable waves: typed
Effect failures and schema decoding, reusable Effect and Stream service
values, lifecycle-safe transport cleanup, and focused test-boundary
cleanup. Persisted managed-stack documents and identity markers now
encode through the same schemas used to read them. The merged #6303
transport architecture remains authoritative. Exact `apps/cli` callsites
were updated where the stack Effect service API changed, but CLI code is
intentionally not an Effect-lint target yet.

Native Node, Bun, Deno, and Promise boundaries retain narrow documented
suppressions where replacing the host API or dependency-ordered layer
provisioning would worsen lifecycle semantics.

Supersedes #6304
This PR was automatically created to sync API types from the
infrastructure repository.

Changes were detected in the generated API code after syncing with the
latest spec from infrastructure.

Co-authored-by: supabase-cli-releaser[bot] <246109035+supabase-cli-releaser[bot]@users.noreply.github.com>
… cap (#6365)

Refines the AI review pipeline (built in #6358) into its intended shape,
and removes the size limit. Validated end-to-end via a temporary
self-test trigger during development (now removed — the pipeline ships
in shadow mode).

## What changed

- **Parallel independent reviews + a dedicated adjudicator.**
`claude-review` and `codex-review` now run **in parallel** (Codex no
longer depends on Claude); a new **`adjudicate`** job then reconciles
both finding sets, verifying each finding by **reading the real code**
(PR head checked out read-only), and `post-review` posts the merged
result. This replaces the old single Codex job that did both an
independent pass and adjudication sequentially — cutting the critical
path and giving each job its own timeout.
- **No size cap.** Removed the preemptive "too large" guard. The models
review agentically (reading the diff and files via their own tools over
many turns, like the local CLI), so PRs of any size are reviewed — very
large diffs best-effort within the model's context/turn budget.
- **Runtime fixes** surfaced by real runs: `gh pr diff --repo` (subdir
checkouts), npm config isolation for the Claude CLI install, `set +e` so
the Claude retry loop isn't killed by `bash -e`, and the reviewer model
set to `claude-opus-5` (the account's API key returns 404 for
`claude-fable-5`).

Workflow + prompts only for the split (no TS/schema changes — Codex's
independent findings reuse `findings.schema.json`; the adjudicator still
emits `merged-review.json`). Ships in **shadow mode**: no `pull_request`
trigger, only `workflow_dispatch` / maintainer `/ai-review`.

## Notes for reviewers

- Two first-run unknowns for the adjudicator (can't verify offline):
whether Codex's read-only sandbox can read the `pr/` subtree, and
whether it picks up a nested `pr/AGENTS.md` (guarded in the prompt;
blast radius bounded — read-only + no network + key-proxied +
output-redacted).
- Requires the org's Anthropic/OpenAI spend limit to be sufficient, or
the model jobs 429.

---------

Co-authored-by: Julien Goux <hi@jgoux.dev>
…e on >=1 review (#6380)

Follow-up to the AI-review pipeline. Two changes.

## 1. Downgrade `codex-action` v1.12 → v1.11

On the large PR (#6366, ~130k-token diff) the `codex-review` step ran to
completion — Codex finished the turn, wrote its output file, printed its
final message and token count — then **sat idle until the 45-minute job
timeout**, discarding a completed review. That is a confirmed v1.12
regression: **openai/codex-action#150** ("v1.12: Linux run never returns
after the turn completes; job dies on timeout with the output file
already written"). The reporter confirms **v1.11 handles the same heavy
workload cleanly**, and there is no released fix above v1.12.

v1.11 (`52fe01ec…`) supports every input we use (`safety-strategy`,
`sandbox`, `output-schema-file`, `output-file`, `codex-version`,
`working-directory`, `effort`), so this is a drop-in pin change in both
Codex jobs.

## 2. Adjudicate on ≥1 independent review (graceful degradation)

Previously `adjudicate` required BOTH `claude-review` and `codex-review`
to succeed, so one flaky model job sank the whole review. Now it runs
when **at least one** independent pass succeeded: each findings download
is guarded by its job's result, and the stage step substitutes an empty
findings set for any review that didn't complete, so the adjudicator
reconciles one or two. The prompt notes the one-review case and records
it in its summary.

Together: a Codex hiccup no longer wastes a 45-minute run or blocks
Claude's (working) review from being posted.
## Summary

- prepare `/run/postgresql` for the Linux host UID/GID before the Docker
stack drops privileges
- preserve the existing root and non-Linux startup paths
- cover the privilege-drop ordering with a Linux-specific regression
test

## Context

The refreshed slim Postgres image listens on a Unix socket under
`/run/postgresql`. The stack wrapper bypassed the image root setup when
switching to the host user on Linux, so Postgres restarted with a socket
lock-file permission error. That readiness failure cascaded into the
three e2e startup timeouts visible on #6400.
This PR was automatically created to sync API types from the
infrastructure repository.

Changes were detected in the generated API code after syncing with the
latest spec from infrastructure.

Co-authored-by: supabase-cli-releaser[bot] <246109035+supabase-cli-releaser[bot]@users.noreply.github.com>
Co-authored-by: Andrew Valleteau <avallete@users.noreply.github.com>
## Summary

- consolidate fragmented Docker coverage into one public 13-service
stack journey
- verify canonical slim images, representative product behavior, and
restart persistence
- prove two automatically allocated sibling stacks keep ports, data,
ownership, and cleanup isolated

## Context

This is a test-only qualification change for CLI-2113. The existing
stack implementation already satisfied the complete Docker graph and
sibling-isolation contracts; the new journey makes those
release-critical guarantees observable through the public package
surface.
## TL;DR

fixes the CLI rejecting dashboard issued `sbp_v0_` access tokens with
`LegacyInvalidAccessTokenError` which was caused by the access token
regex pattern only

matching the `sbp_` and `sbp_oauth_` prefixes and 
is now fixed by widening the legacy validator to also accept the
`sbp_v0_` prefix...

## ref:
- closes: #6348

---------

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

Qualifies the first Dockerless native vertical slice through the public
`@supabase/stack` surface: isolated native prefetch, lazy and eager
activation, real Auth and PostgREST flows, PostgreSQL extensions,
restart preservation, retryable typed preparation failure, and exact
resource cleanup.

Adds a consumer-selected cache root to Promise-based prefetch, exposes
the public stack error type, and preserves lazy proxy activation across
a whole-stack restart without weakening explicit per-service stops.
## TL;DR

fixes `db reset, db lint, db diff`, and `migration down` silently
skipping a user schema when its oid also appears in another catalog
which was caused by joining `pg_depend` on objid without the `classid`
that scopes `oids` to a single catalog

now fixed by constraining the join to `pg_catalog.pg_namespace` rows in
every copy of the query.
Resets now drop schemas that earlier versions silently skipped....

## ref:
- closes: #6375
Adds one sentence to the Pull Requests section of `AGENTS.md`: this repo
is public, so PR descriptions, issues, and code comments keep internal
content out: absolute production metrics (percentages, ratios, or
relative change instead), internal decision detail (vendor, legal,
pricing, or strategy discussions), and competitor names (protocol
identifiers such as user-agent strings are fine). That context goes in
the linked Linear issue. Same rule as the supabase monorepo's agent
instructions (supabase/supabase#49750); an agent-authored PR there had
quoted absolute internal event volumes in its description.
## TL;DR

adds live e2e coverage for the `services` command and `storage mv`

## whats introduced?

- `services`: links the project and proves the postgres remote version
lands in the json output
proves the table renders that value in the LINKED cell, where a plain
substring match would pass vacuously
- `storage mv`: uploads an object, moves it through the real move
endpoint, and proves via the listing that the destination exists and the
source is gone
closes the storage family, since ls, cp and rm already have coverage
- `db pull`: deflakes the shipped live test, pull exits nonzero when
nothing changed by design, so the test now seeds remote-only schema
through db query and proves the initial pull writes it back as a
migration

## ref:
- closes: CLI-2263 CLI-2264 CLI-2278
## TL;DR

adds live e2e coverage for `migration up` and `migration repair`,
closing the migration family...

## whats introduced?

- `migration up`: applies a test written migration to the remote
database, proven by the apply banner and the history row migration list
reads back
- `migration repair`: inserts a history row with status applied, proves
it through migration list, then removes it with status reverted and
proves the absence

## ref:
- closes: CLI-2269
This PR was automatically created to sync API types from the
infrastructure repository.

Changes were detected in the generated API code after syncing with the
latest spec from infrastructure.

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

## Summary

Adds an opt-in ambient env flag `SUPABASE_USE_SLIM_IMAGES` (`true` or
`1`) that rewrites local-stack Docker image names from the embedded
Dockerfile pins to the slim `ghcr.io/supabase/cli/` builds.

Published slim postgres/storage/auth/edge-runtime images now match the
docker.io contracts (root start, `sh`/`wget`), so the flag is an
image-name rewrite rather than a second runtime. Spec builders still
branch for services that remain distroless (auth/studio/pg-meta
healthchecks, pooler/realtime/analytics busybox wget, Vector
`secretFiles`). Kong, the `differ`/`migra`/`pgprove` job images, PG14,
OrioleDB, historical 15.x pins, and `deno_version = 1` stay on
docker.io. Slim refs skip `SUPABASE_INTERNAL_IMAGE_REGISTRY`. With the
flag unset, image *names* stay on docker.io.

This PR also bumps the shared Dockerfile pins (flag-off and flag-on use
the same versions) and syncs stack `DEFAULT_VERSIONS`:

- postgres `17.6.1.165` → `17.6.1.167`
- postgres 15 fallback `15.8.1.085` → `15.14.1.167` (slim-services
[#290](supabase/slim-services#290); published as
`ghcr.io/supabase/cli/postgres:15.14.1.167`)
- pooler `2.9.7` → `2.9.12`
- realtime `v2.129.9` → `v2.130.0`
- storage `v1.71.0` → `v1.72.1`

Majors 13/15 slim-translate that current PG15 pin when the flag is on.
Storage `v1.72.1` prefers `IMAGE_TRANSFORMATION_ENABLED` over
`ENABLE_IMAGE_TRANSFORMATION`, so the CLI now emits both keys on every
Storage spec (not slim-only).

The rewrite always targets `ghcr.io/supabase/cli/`. The stack catalog's
vector/pooler mirrors (`ghcr.io/supabase/{vector,supavisor}`) are not
used.

This is the code layer of a stack that splits the previous mixed review
on #6329. Docs live in #6383.

## Linked issue

Closes #

- [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): …`).
- [x] 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: Cursor <cursoragent@cursor.com>
dependabot Bot and others added 2 commits September 3, 2026 00:15
…6442)

Bumps the go-minor group with 2 updates in the /apps/cli-go directory:
[github.com/getsentry/sentry-go](https://github.com/getsentry/sentry-go)
and
[github.com/posthog/posthog-go](https://github.com/posthog/posthog-go).

Updates `github.com/getsentry/sentry-go` from 0.48.0 to 0.49.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/getsentry/sentry-go/releases">github.com/getsentry/sentry-go's
releases</a>.</em></p>
<blockquote>
<h2>0.49.0</h2>
<h3>Breaking Changes 🛠</h3>
<ul>
<li>removing DisableLogs and DisableMetrics client options. Sending
metrics and logs is already gated by the usage of our APIs already, so
having a global kill switch is counter intuitive. Users that won't to
opt out should just not call the relevant APIs or setup the
integrations. by <a
href="https://github.com/giortzisg"><code>@​giortzisg</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1392">#1392</a></li>
</ul>
<h3>New Features ✨</h3>
<ul>
<li>add <code>WithProxy</code>option for OTLP. This allows setting an
<code>otlptracehttp.HTTPTransportProxyFunc</code> for the span exporter
by <a href="https://github.com/pierrre"><code>@​pierrre</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1377">#1377</a></li>
</ul>
<h3>Bug Fixes 🐛</h3>
<ul>
<li>(echo) Propagate span through request context by <a
href="https://github.com/EricGusmao"><code>@​EricGusmao</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1385">#1385</a></li>
<li>Skip recover frames on panic. This changes stacktrace behavior for
captured panics, removing <code>sentry.Recover</code> frames to focus on
the actual panic frames. The changes might affect issue grouping. by <a
href="https://github.com/giortzisg"><code>@​giortzisg</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1364">#1364</a></li>
</ul>
<h3>Internal Changes 🔧</h3>
<h4>Deps</h4>
<ul>
<li>Bump github.com/labstack/echo/v5 from 5.0.3 to 5.2.0 in /echo by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1399">#1399</a></li>
<li>Bump github.com/gorilla/websocket from 1.5.1 to 1.5.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1397">#1397</a></li>
<li>Bump getsentry/craft from 2.26.6 to 2.27.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1381">#1381</a></li>
<li>Bump actions/setup-go from 6.4.0 to 7.0.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1382">#1382</a></li>
<li>Bump actions/checkout from 6.0.3 to 7.0.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1380">#1380</a></li>
<li>Bump google.golang.org/grpc to 1.82.1 and golang.org/x/sys to 0.46.0
by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>
in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1375">#1375</a></li>
<li>Bump golang.org/x/text to v0.39.0 and x/net to v0.56.0 by <a
href="https://github.com/giortzisg"><code>@​giortzisg</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1374">#1374</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/getsentry/sentry-go/blob/master/CHANGELOG.md">github.com/getsentry/sentry-go's
changelog</a>.</em></p>
<blockquote>
<h2>0.49.0</h2>
<h3>Breaking Changes 🛠</h3>
<ul>
<li>removing DisableLogs and DisableMetrics client options. Sending
metrics and logs is already gated by the usage of our APIs already, so
having a global kill switch is counter intuitive. Users that won't to
opt out should just not call the relevant APIs or setup the
integrations. by <a
href="https://github.com/giortzisg"><code>@​giortzisg</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1392">#1392</a></li>
</ul>
<h3>New Features ✨</h3>
<ul>
<li>add <code>WithProxy</code>option for OTLP. This allows setting an
<code>otlptracehttp.HTTPTransportProxyFunc</code> for the span exporter
by <a href="https://github.com/pierrre"><code>@​pierrre</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1377">#1377</a></li>
</ul>
<h3>Bug Fixes 🐛</h3>
<ul>
<li>(echo) Propagate span through request context by <a
href="https://github.com/EricGusmao"><code>@​EricGusmao</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1385">#1385</a></li>
<li>Skip recover frames on panic. This changes stacktrace behavior for
captured panics, removing <code>sentry.Recover</code> frames to focus on
the actual panic frames. The changes might affect issue grouping. by <a
href="https://github.com/giortzisg"><code>@​giortzisg</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1364">#1364</a></li>
</ul>
<h3>Internal Changes 🔧</h3>
<h4>Deps</h4>
<ul>
<li>Bump github.com/labstack/echo/v5 from 5.0.3 to 5.2.0 in /echo by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1399">#1399</a></li>
<li>Bump github.com/gorilla/websocket from 1.5.1 to 1.5.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1397">#1397</a></li>
<li>Bump getsentry/craft from 2.26.6 to 2.27.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1381">#1381</a></li>
<li>Bump actions/setup-go from 6.4.0 to 7.0.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1382">#1382</a></li>
<li>Bump actions/checkout from 6.0.3 to 7.0.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1380">#1380</a></li>
<li>Bump google.golang.org/grpc to 1.82.1 and golang.org/x/sys to 0.46.0
by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>
in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1375">#1375</a></li>
<li>Bump golang.org/x/text to v0.39.0 and x/net to v0.56.0 by <a
href="https://github.com/giortzisg"><code>@​giortzisg</code></a> in <a
href="https://redirect.github.com/getsentry/sentry-go/pull/1374">#1374</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/getsentry/sentry-go/commit/78b09d19307aafb162cd57838bd5c72055b14c8c"><code>78b09d1</code></a>
release: 0.49.0</li>
<li><a
href="https://github.com/getsentry/sentry-go/commit/eff9f377d6f5c6cd17d981a503d9c4efa863471f"><code>eff9f37</code></a>
build(deps): bump github.com/labstack/echo/v5 from 5.0.3 to 5.2.0 in
/echo (#...</li>
<li><a
href="https://github.com/getsentry/sentry-go/commit/c60a2f6f2f70c818795c3b9f064e5d507483f23d"><code>c60a2f6</code></a>
feat!: remove DisableLogs and DisableMetrics options (<a
href="https://redirect.github.com/getsentry/sentry-go/issues/1392">#1392</a>)</li>
<li><a
href="https://github.com/getsentry/sentry-go/commit/c3f2330e3b2e508df29de709f9c88e79a6acd2a8"><code>c3f2330</code></a>
build(deps): bump github.com/gorilla/websocket from 1.5.1 to 1.5.3 (<a
href="https://redirect.github.com/getsentry/sentry-go/issues/1397">#1397</a>)</li>
<li><a
href="https://github.com/getsentry/sentry-go/commit/9bb14a7138ebe6ddf1c3fb9ced5c7874f7e338ca"><code>9bb14a7</code></a>
fix(echo): propagate span through request context (<a
href="https://redirect.github.com/getsentry/sentry-go/issues/1385">#1385</a>)</li>
<li><a
href="https://github.com/getsentry/sentry-go/commit/fb9acd84b1dfc91073c046e9c5612faf3422d749"><code>fb9acd8</code></a>
build(deps): bump getsentry/craft from 2.26.6 to 2.27.2 (<a
href="https://redirect.github.com/getsentry/sentry-go/issues/1381">#1381</a>)</li>
<li><a
href="https://github.com/getsentry/sentry-go/commit/17f540e8a47f9af562099008fdb0f5f45a54954c"><code>17f540e</code></a>
feat(otel/otlp): add WithProxy option to span exporter (<a
href="https://redirect.github.com/getsentry/sentry-go/issues/1377">#1377</a>)</li>
<li><a
href="https://github.com/getsentry/sentry-go/commit/ed9834eec263025a1d099e41adfff2d738d2ac57"><code>ed9834e</code></a>
build(deps): bump actions/setup-go from 6.4.0 to 7.0.0 (<a
href="https://redirect.github.com/getsentry/sentry-go/issues/1382">#1382</a>)</li>
<li><a
href="https://github.com/getsentry/sentry-go/commit/af6d9dbfd0dbe4836896717ec59732ddd75979dc"><code>af6d9db</code></a>
build(deps): bump actions/checkout from 6.0.3 to 7.0.1 (<a
href="https://redirect.github.com/getsentry/sentry-go/issues/1380">#1380</a>)</li>
<li><a
href="https://github.com/getsentry/sentry-go/commit/93223f752b00e794aacd0b87b4d86b220af06081"><code>93223f7</code></a>
build(deps): bump google.golang.org/grpc to 1.82.1 and golang.org/x/sys
to 0....</li>
<li>Additional commits viewable in <a
href="https://github.com/getsentry/sentry-go/compare/v0.48.0...v0.49.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `github.com/posthog/posthog-go` from 1.24.1 to 1.24.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/posthog/posthog-go/releases">github.com/posthog/posthog-go's
releases</a>.</em></p>
<blockquote>
<h2>1.24.2</h2>
<h2>Unreleased</h2>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/PostHog/posthog-go/blob/main/CHANGELOG.md">github.com/posthog/posthog-go's
changelog</a>.</em></p>
<blockquote>
<h2>1.24.2</h2>
<h3>Patch Changes</h3>
<ul>
<li>360bc8d: Align local <code>is_set</code> and <code>is_not_set</code>
evaluation with partial property context.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/PostHog/posthog-go/commit/5e7fa9819ff248a3696c478a1691bb50755d9ea9"><code>5e7fa98</code></a>
chore: release v1.24.2 [version bump] [skip ci]</li>
<li><a
href="https://github.com/PostHog/posthog-go/commit/360bc8d46821cdbd5b443b690a8b51a08677c53d"><code>360bc8d</code></a>
fix(flags): align presence operator semantics (<a
href="https://redirect.github.com/posthog/posthog-go/issues/297">#297</a>)</li>
<li>See full diff in <a
href="https://github.com/posthog/posthog-go/compare/v1.24.1...v1.24.2">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
## Summary

Makes the `name` argument to `supabase experimental workers new`
optional and prompts for it
when it is omitted, so a bare `supabase experimental workers new` walks
through name, runtime
and size rather than failing the parse.

The name is the one input this command cannot default — it is the
directory, the
`[workers.<name>]` key and the hostname all at once. So where the
runtime and
size prompts fall back to a default when there is nowhere to ask, the
name
prompt has nothing to fall back to: with `-o json|yaml|toml|env` or no
interactive terminal, the command fails with a new
`MissingWorkerNameError`
pointing at `supabase experimental workers new api`.

The prompt validates against everything the command would otherwise
refuse a
moment later — a non-DNS-label name, and a name `config.toml` already
records —
so a typo is corrected in place instead of ending the run. That also
means the
project has to be loaded before the first prompt, and the machine-output
check
moves up with it: `-o` leaves `output.format` as `text`, and Clack
writes its
terminal UI to stdout, so a name prompt would land in front of the
payload for
the same reason the runtime prompt would.

The handler's inline name validation is replaced by the shared
`legacyValidateWorkerName`, which the rest of the command family already
uses,
so an explicitly-passed name and a prompted one are refused on identical
terms.

`mockOutput` now records `promptTextCalls` so tests can assert on the
prompt's
message and exercise its `validate` callback.

## Stack

Bottom of the workers stack, on `develop`. Above it: output polish
(#6389), `workers logs` (#6410), and `push --wait` (#6371).

## Linked issue

FUNC-840 (Linear). Supabase maintainer, exempt from the
`open-for-contribution` flow.

## Checklist

- [x] The PR title follows [Conventional
Commits](https://www.conventionalcommits.org/)
# heavy workload cleanly. There is no released fix above v1.12 yet.
uses: openai/codex-action@52fe01ec70a42f454c9d2ebd47598f9fd6893d56 # v1.11
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}

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

On a maintainer-requested review of a fork, this adjudication job feeds untrusted PR files to Codex while providing OPENAI_API_KEY. Prompt-injected PR content can direct Codex to read its process environment, encode the key, and return it through the merged-review artifact or public review.
Helpful? Add 👍 / 👎

💡 Fix Suggestion

Suggestion: Apply a two-layer defence: (1) At line 500, replace the shared OPENAI_API_KEY with a dedicated, spend-capped OpenAI Project API key stored as a separate secret (e.g. OPENAI_ADJUDICATE_API_KEY). A Project key can be scoped to a single model with a hard spend cap, so even if it is exfiltrated through encoded Codex output the blast radius is isolated to this job and the key is cheap to rotate. (2) In .github/scripts/ai-review/post-review.ts, extend redactSecretsDeep / redactSecrets to also detect and redact base64- and hex-encoded variants of each secret pattern: after the normal regex pass, base64-decode every ≥20-char base64 token and re-apply SECRET_PATTERNS, and similarly hex-decode even-length hex runs; remove any token that matched. This closes the encoding bypass that lets prompt-injected Codex smuggle an encoded key through the artifact redaction step. Until encoding-aware redaction is in place, consider adding a field-length cap and a non-ASCII reject gate in the assertMergedReview validator so suspiciously long or non-printable strings fail validation before the artifact is uploaded.

⚠️ Experimental Feature: This code suggestion is automatically generated. Please review carefully.

Suggested change
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
openai-api-key: ${{ secrets.OPENAI_ADJUDICATE_API_KEY }}

Comment thread apps/cli/src/legacy/auth/legacy-http-debug.layer.ts
johnstonmatt and others added 13 commits September 3, 2026 05:32
## Summary

The workers commands each grew their own way of saying "here is what
happened" and "here is what to run next". This settles them on the
shapes the rest of the legacy shell already uses. **No command changes
what it does** — this is output, plus the coverage that pins it.

- **Success trailers.** "What to run next" lines in `new`, `push`,
`delete` and `status` move to `emitSuccessTrailer`, the way `stop`,
`bootstrap`, `migration repair` and `gen signing-key` already emit
theirs: printed once at the end of the run rather than inline, so a
multi-worker push does not bury each worker's hint under the next
worker's output. The commands within them are aqua'd.
- **`list` advisories.** Both take the yellow `WARNING:` prefix and the
two-line consequence shape `start`'s Docker notice uses. Each was one
long sentence that re-flowed at a different width, directly under a
table that lines its columns up.
- **`list` drops the URL column.** Every worker's URL is the same host
and prefix with the name on the end, and carrying it pushed the table
past 130 columns for one derivable field — `renderGlamourTable` sizes
each column to its widest cell and never wraps. `status` still renders
it vertically, and every machine format still carries `url` per worker.
- **`push` progress.** Per-worker announcements are counted (`Deploying
Worker 1/2:`) and a multi-worker run closes with a summary. Each worker
takes minutes; the name alone said nothing about how much of the run was
left.
- **`push` names what it never attempted.** The loop stops at the first
failure and the error only names the worker that broke, leaving the rest
to be reconstructed from argument order. On stderr in every format,
machine ones included: that run is a CI run.
- **`--project-ref` survives into `push`'s retry suggestions**, via the
`legacyWorkersProjectRefSuffix` helper `status` and `delete` already
use. A suggestion is copy-pasted verbatim, so one that dropped it
re-resolved against whatever this checkout was linked to.

Also adds unit coverage for `legacyRenderWorkerDetails`, pins the shared
`-o env` refusal, and adds a guard (own commit) asserting no legacy
boolean flag ships required — `Flag.boolean` alone builds a *required*
param, and nothing in the existing suites notices.

## Stack

On top of the `workers new` name prompt (#6349). Above it: `workers
logs` (#6410), then `push --wait` (#6371) last, so the output work can
ship independently of both.

## Linked issue


[FUNC-851](https://linear.app/supabase/issue/FUNC-851/general-output-polish).
Supabase maintainer, exempt from the `open-for-contribution` flow.

## Checklist

- [x] The PR title follows [Conventional
Commits](https://www.conventionalcommits.org/)

---------

Co-authored-by: kanad <git@kanad.dev>
<!--
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

- upgrades mise lockfile using `mise lock --upgrade` (and bumps `mise`
minimum version + github action accordingly)
- upgrades `pnpm` to v12
- enables pnpm global store to speed up installation time in worktrees
(and makes a few updates in our `pnpm-workspace` file so types and tests
work properly)
- upgrades node.js to latest v24 channel (24.18.0 => 24.20.0)
- moves our node.js source-of-truth to `.node-version` — tiny and
hopefully harmless change to better indicate to agents/etc. that we
treat node and bun equally in this repo

this PR was inspired by [these
changes](https://supabase.slack.com/archives/C09PB9QMQG2/p1788257957531829)

## Checklist

- [x] The PR title follows [Conventional
Commits](https://www.conventionalcommits.org/) (e.g. `fix(cli): …`).
- [x] Tests added or updated for the change.
- [x] 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 Fable 5 <noreply@anthropic.com>
## TL;DR

fixes the `config diff` live test failing on every CI run since it
landed, which was caused by asserting a fresh `supabase init` config has
no auth drift against a fresh project whose platform defaults
legitimately differ from the local template.

 now fixed by:
pinning only the auth paths the registry declares baselines for,
requiring the auth block in the comparison scope so the pin cannot pass
vacuously, and stripping the spinner's ANSI from stdout before
matching...

## ref:
- closes: CLI-2294
- broken by: #6295
- spotted in:
https://github.com/supabase/cli/actions/runs/33633309281/job/100257915846
- passed here:
https://github.com/supabase/cli/actions/runs/33643747588/job/100293154783
## TL;DR
adds live e2e coverage for `ssl-enforcement get` and `update`, covering
the ssl-enforcement command family

## whats introduced?
- `ssl-enforcement get`: reads the target project's posture and proves
the json payload carries `currentConfig.database` and
`appliedSuccessfully`
- `ssl-enforcement update`: captures the current posture, toggles it,
proves the flip in its own output and through get, then restores the
captured posture in the same test


## ref:
- closes: CLI-2270
## What

Adds `supabase config pull` (CLI-2064): fetches the config the
Management API reports for a target project or branch (`GET
/v2/projects/{ref}/config`) and applies it to the local
`config.toml`/`config.json`, reusing the `config diff` comparison core
(CLI-2156) for classification and `--dry-run`.

```
supabase config pull                       # linked project → config root
supabase config pull --project-ref staging # branch → [remotes.staging]
supabase config pull --dry-run             # preview, equivalent to config diff
supabase config pull --yes                 # skip confirmation (CI)
```

## How it writes

- **Scope resolution** (ADR 0023): reuse the `[remotes.*]` block whose
raw `project_id` literal matches the resolved ref (the same rule the
loader's overlay uses, so pull and push stay inverses); else a
branch-named target creates `[remotes.<branch-name>]` (`--remote-label`
overrides; label collisions error rather than silently retargeting an
existing block); else the config root, with warnings on `dualScope`
properties (new registry metadata) that also configure `supabase start`.
- **Surgical writes**: a new format-preserving editor in
`@supabase/config` (`config-edit.ts`) splices values into the raw TOML
text — comments, blank lines, ordering, and quote style survive. Every
edit is verified by re-parsing and deep-comparing against the
independently computed expected document before an atomic temp+rename
write; anything the editor can't handle safely is a typed refusal, never
a best-effort splice. JSON configs are re-serialized with detected
indent and preserved key order.
- **Never harms the file**: pull never removes properties;
`local_only`/unmanaged paths are untouched; `env()` references are never
replaced with literals (reported with the variable name); masked
credentials are never written; a plan fixpoint + pre-write
schema-validation gate guarantee the written file always re-loads (see
below). Uncommitted/untracked changes to the config abort
non-interactive runs unless `--force`; `--yes` answers the prompt but
never bypasses that guard.
- **Convergence**: running pull twice against an unchanged remote writes
nothing the second time and leaves the file byte-identical — verified
live against staging.

## Notable decisions (details in ADR 0023 and the Linear issue)

- Single `--project-ref` flag accepting ref/branch/UUID per the settled
CLI-2167 vocabulary (the issue text's separate `--target` was dropped).
- An `[remotes.*].project_id` spelled as `env(...)` that resolves to the
target is a hard error: the loader matches raw literals, so writing
there would never take effect and pull would never converge.
`--remote-label` is the escape hatch; CLI-2291 tracks a load-time
warning.
- ADR-0021 "unpushable" families are written, with a note that `config
push` cannot send them back.
- No `go-cli-porting-status.md` row: the file now records only the
residual Go delegation surface, and this command is net-new TS. User
docs live at `apps/cli/docs/supabase/config/pull.md`.

## Found while dogfooding against staging

Pulling `auth.sms.twilio.enabled = true` while the required sibling
`account_sid` stayed gated (declared-but-unpushable against the
pre-write state) produced a config that failed every subsequent schema
load. Fixed with two layers: the plan expands to a fixpoint
(re-classifying after projecting writes, so un-gated siblings get pulled
too), and a pre-write validation gate decodes the projected document
with the real schema and drops any family that would not re-load (skip
reason `would_invalidate`, naming the missing fields) instead of writing
it. Both layers verified live: the same scenario now withholds the
twilio family with an actionable note while the other changes apply, and
the file always re-loads.

## Also in this PR

- Fixes CLI-2287: the `[remotes.*]` matching rule is now exported once
from `@supabase/config` (`remoteNameForProjectRef`, raw-literal
semantics) and `config diff`'s reload precheck uses it — an
`env()`-valued `project_id` no longer triggers a wasted reload with
duplicated deprecation warnings. Diff's behavior is otherwise
byte-identical (its full suite passes unchanged).
- Hoists diff's target resolution and shared formatters to the config
family root (`config.target.ts`, `config.format.ts`) with per-command
error constructors, per the Hoist-Before-You-Duplicate rule.
- New `dualScope` registry metadata (36 paths, snapshot-pinned),
`writeCliConfigDocumentText` atomic writer, and a git dirty-check
helper.

## Reviewer notes

- The handler is callable as a library (`legacyRunConfigPull` with an
injected target and a constructor-produced source) for the planned
`supabase pull` orchestrator.
- Docs-site follow-up (not in this repo): `supabase/supabase`'s
`common-cli-sections.json` needs a `config pull` entry when the CLI docs
next sync.
- Follow-ups filed: CLI-2289 (push branch-name vocabulary so the
pull/push round trip has no manual step), CLI-2290 (`--only` subset
pulls), CLI-2291 (load-time env()-project_id warning), CLI-2292 (config
family cleanup). Pre-existing CLI-2285 (`--workdir` climb) applies to
pull the same way it does to diff/push and stays a separate fix.

Fixes CLI-2064
## Summary

Reads the project's unified logs stream rather than a worker route —
there is no worker-scoped log endpoint — via `v1GetProjectLogs`, which
the generated client already carries. `--kind app|requests|builds`
narrows to one of the three streams; without it all three are returned,
tagged per line. `--tail` caps the rows. `--follow` keeps printing until
interrupted.

## Three non-obvious things about that endpoint

Each is documented at its call site, because none is guessable from the
API surface:

- **The filter is `log_attributes`, not the `source` column.** Worker
rows carry an empty top-level `source`, because the Workers Logflare
source is not enrolled as a category in the generic logs path, so `where
source = 'worker_guest_logs'` matches nothing. The `in (...)` list over
the three known streams is a tenancy guard rather than a convenience —
with `source` empty it is the only thing excluding a non-worker row that
happens to carry a `worker` attribute.
- **Both timestamp bounds are always sent, spanning under 24h.** One
bound alone yields a one-minute window, silently; neither is an outright
error; and a span over 24h is clamped to `start + 24h`, returning an
*older* slice than the one asked for rather than a truncated one.
- **A failed query can arrive as HTTP 200** with a populated `error`, so
the envelope is checked before `result`.

The response is decoded against a local schema rather than the generated
`V1GetProjectLogsOutput`: that schema marks `result`/`error` optional
but permits neither to be `null`, while the endpoint always sends one of
them as an explicit `null`. Decoding a real response against it always
fails — worth fixing in the spec separately.

## Rendering

Per-stream, because `event_message` differs in kind: on the request
stream it is only `"GET /"`, with status and duration in
`log_attributes`, so the request line is composed. `severity_text` is
ignored — it is `INFO` on every row of every stream — so the level is
derived, and app lines report none rather than a guess. An app message
is tenant-controlled bytes, so escape sequences are stripped before it
reaches a terminal while a stack trace's newlines and indentation
survive.

## `--follow`

The poll interval is set by the rate limit, not by responsiveness: the
v1 analytics endpoints allow 10 requests per 60 seconds, so the
two-second poll a live tail suggests would spend the whole allowance in
ten seconds. It polls every 10 seconds, measured at ~7 requests in the
worst 60-second window.

The cursor deliberately lags 60 seconds behind the newest line printed.
Guest lines are relayed CloudWatch → subscription filter → Lambda →
Logflare and arrive late and out of order, so a cursor sitting on the
newest timestamp would drop every straggler permanently. Overlap is
therefore guaranteed; dedupe on the Logflare-minted `id` is what makes
it invisible.

`-o json|yaml|toml` and `--output-format json` are refused up front —
each promises one terminal payload and a tail has no last element.
`--output-format stream-json` emits one `log-entry` event per line.
SIGINT exits 130.

## Stack

On top of the workers output polish (#6389), with `push --wait` (#6371)
stacked above so it can be rejected independently. Below those: the
`workers new` name prompt (#6349).

## Note

Replaces #6408, which GitHub marked merged during a stack reorder. It
was never merged to `develop`; the branch and its commits are intact
here.
…#6371)

## Summary

`supabase experimental workers push` blocks on the server-side container
build. That build routinely runs for minutes, so the common case — a
deploy that builds fine — is the slowest thing in the loop.

`--no-wait` returns once the platform accepts the deploy, which is the
last thing the command can learn without waiting: the deploy response
arrives only after the spec and the uploaded context are accepted, and
it carries the accepted spec back. Waiting stays the default, so a plain
push still reports the build's verdict and existing invocations are
unchanged.

- Under `--no-wait` the details block leads with a `State` row — the one
row that says the worker is not serving yet — and drops `Image`, since
no image exists until the build produces one.
- A success trailer then points at `experimental workers status` for the
build's outcome. Text output only; machine callers read `build_state`
from the payload.
- A deploy answered with a spec already in `failed` is reported as a
failure whether or not the build was waited on, rather than exiting zero
on a worker that will never come up.

The second commit is a separate fix that fell out of the review: the
wait now runs only when the deploy response left `build_state` at
`building`. `V2DeployAWorkerOutput` permits a terminal `active` or
`failed` on the deploy response itself, and polling on top of that could
only contradict it — `awaitWorkerBuild` reads a post-deploy 404 as
"still building", so an already-failed deploy could burn the full poll
budget and surface as a timeout rather than the failure the platform had
already reported.

## Stack

Top of the workers stack, on top of `workers logs` (#6410). Everything
below it — the name prompt (#6349), the output polish (#6389) and
`workers logs` — is independent of this flag, so this PR can be rejected
on its own without holding any of them up.

## Linked issue

FUNC-848 (Linear). Supabase maintainer, exempt from the
`open-for-contribution` flow.

## Checklist

- [x] The PR title follows [Conventional
Commits](https://www.conventionalcommits.org/)
#6458)

Bumps the go-minor group with 2 updates in the /apps/cli-go directory:
[github.com/andybalholm/brotli](https://github.com/andybalholm/brotli)
and
[github.com/posthog/posthog-go](https://github.com/posthog/posthog-go).
Bumps the go-minor group with 1 update in the /apps/cli-go/pkg
directory:
[github.com/andybalholm/brotli](https://github.com/andybalholm/brotli).

Updates `github.com/andybalholm/brotli` from 1.2.2 to 1.2.3
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/andybalholm/brotli/commit/6b8aef6ece266fa87b925ce3a913bc30dc4b7b70"><code>6b8aef6</code></a>
HTTPCompressor: don't use V2</li>
<li>See full diff in <a
href="https://github.com/andybalholm/brotli/compare/v1.2.2...v1.2.3">compare
view</a></li>
</ul>
</details>
<br />

Updates `github.com/posthog/posthog-go` from 1.24.2 to 1.24.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/posthog/posthog-go/releases">github.com/posthog/posthog-go's
releases</a>.</em></p>
<blockquote>
<h2>1.24.3</h2>
<h2>Unreleased</h2>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/PostHog/posthog-go/blob/main/CHANGELOG.md">github.com/posthog/posthog-go's
changelog</a>.</em></p>
<blockquote>
<h2>1.24.3</h2>
<h3>Patch Changes</h3>
<ul>
<li>749f1e8: Fix <code>exact</code>/<code>is_not</code> local flag
evaluation to match case-insensitively and after string coercion,
consistent with the other string operators here and the reference SDKs.
A plain Go <code>==</code> made them case- and type-sensitive, so e.g.
<code>exact &quot;US&quot;</code> did not match a
<code>&quot;us&quot;</code> property value and <code>exact 1</code> did
not match a <code>&quot;1&quot;</code> property value.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/PostHog/posthog-go/commit/0b4046e2e31a300f9cd08ffbc7bd4b8b9be92c4e"><code>0b4046e</code></a>
chore: release v1.24.3 [version bump] [skip ci]</li>
<li><a
href="https://github.com/PostHog/posthog-go/commit/749f1e88cdbdd28407a40c558f4a5a97ad1560db"><code>749f1e8</code></a>
fix: match exact/is_not case-insensitively and after string coercion (<a
href="https://redirect.github.com/posthog/posthog-go/issues/299">#299</a>)</li>
<li>See full diff in <a
href="https://github.com/posthog/posthog-go/compare/v1.24.2...v1.24.3">compare
view</a></li>
</ul>
</details>
<br />

Updates `github.com/andybalholm/brotli` from 1.2.2 to 1.2.3
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/andybalholm/brotli/commit/6b8aef6ece266fa87b925ce3a913bc30dc4b7b70"><code>6b8aef6</code></a>
HTTPCompressor: don't use V2</li>
<li>See full diff in <a
href="https://github.com/andybalholm/brotli/compare/v1.2.2...v1.2.3">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
<!--
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

In #6424, I added a strict `onFail:
'error'` property so any time someone uses `npm`, `yarn,` or an
incorrect `pnpm` version, those CLIs error out.

This was a bit aggressive — we use the `npm` CLI for a variety of things
related to our release process. Rather than backport all of those `npm`
usages to `pnpm`, I opted to update `onFail` to be `warn`.

That should unblock one error in our release process, hopefully that's
all of them? I'm not sure what to make of [this
error](https://github.com/supabase/cli/actions/runs/33785688700/job/100750659098)
🤔
## What

Adds a root `.gitattributes` that pins `patches/*.patch` to LF line
endings on checkout.

## Why

The Windows `smoke-test` job in the Release workflow has failed on every
release attempt since #6424 bumped pnpm from 11.4.0 to 12.3.0 (first
failure: [run
33785688700](https://github.com/supabase/cli/actions/runs/33785688700/job/100750659098)):

```
ERR_PNPM_INVALID_PATCH
Applying patch "patches/@libpg-query__parser@17.6.10.patch" failed:
error parsing patch: invalid char in unquoted filename
```

pnpm 12 is the Rust CLI and parses `patchedDependencies` files with the
[`diffy`](https://github.com/bmwill/diffy) crate. The pinned version
(0.5.1) splits the `---`/`+++` header lines at `\n` only, so a CRLF file
leaves a carriage return attached to the filename and the parser rejects
it. Git for Windows defaults to `core.autocrlf=true` and this repo had
no `.gitattributes`, so the patch file was checked out as CRLF on the
Windows runner. pnpm 11's JavaScript parser tolerated this, which is why
the same job passed before the bump.

Reproduced locally with a minimal project and a fresh store: pnpm 12.3.0
fails on a CRLF patch and succeeds on the same file with LF; pnpm 11.4.0
accepts both.

`diffy` fixed this in 0.5.2
([bmwill/diffy#87](bmwill/diffy#87)), but pnpm
12.3.0, 12.3.1, and `main` still pin 0.5.1, so a pnpm bump does not help
yet. Forcing LF for patch files fixes the checkout on every platform,
including contributors on Windows.

Because the smoke-test gates `publish`, this failure has also blocked
the last three feature releases.

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

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
## What changed

`supabase config push` now always reports the project or branch it
resolved before doing anything — by name when known, e.g. `Pushing
config to project: My App (abcdefghijklmnopqrst)` or `Pushing config to
branch: feat-x (bbbb…)` plus its parent project. When the resolved
target is a preview branch that was only *inferred* (from a prior
`supabase link <branch>`, `SUPABASE_PROJECT_ID`, or the linked-ref cache
— not named on this invocation), it gates behind a confirmation before
any network mutation, skippable via the existing global
`--yes`/`SUPABASE_YES` (CLI-2168).

`--project-ref` also now accepts a branch name or UUID, not just a raw
ref, matching `config diff`'s existing CLI-2167 vocabulary — so a
`config pull --project-ref <branch>`/`config push --project-ref
<branch>` round-trip no longer requires manually looking up the branch's
raw ref (CLI-2289).

## Why

`config push` gave no indication of whether the resolved ref was the
main project or one of its branches, so a user linked to a branch (or
overriding via env/flag) had no on-screen signal before mutating it. The
confirmation defaults to decline in every non-interactive context
without `--yes` (`--output-format json`/`stream-json`, a non-TTY with no
piped answer) — fails the command rather than silently proceeding or
silently no-opping, matching the existing `projects delete`/`db reset`
convention for this shape of gate. An explicit `--project-ref
<name-or-uuid>` this invocation skips the prompt entirely (the echo
still prints) — same-invocation intent is treated as confirmation.

## Notes for reviewers

The branch/project detection shared by `link` and `status` is hoisted
into `legacy-branch-target.ts`; the `--project-ref` branch-name/UUID
resolution shared by `config diff` and `config push` is hoisted into
`config.branch-target.ts` — both existing commands are refactored onto
the shared code in this same change, per this repo's hoisting policy.
Neither command's own established behavior changes; their existing test
suites are unmodified and green.
)

## What changed

`diffProjectConfig` and its supporting types (`ConfigChange`,
`ConfigChangeClass`, `ConfigChangeCounts`, `ConfigChangeSet`,
`DiffProjectConfigOptions`) move from `@supabase/config/internal` to the
package's public `.` entrypoint.

## Why

ADR 0022 deliberately deferred exporting the config-diff classification
engine publicly until a second real consumer needed it, rather than
exporting it speculatively. Studio is now that second consumer, so this
promotes the (already pure/synchronous) engine to the public surface
`apps/cli` and Studio can both read.

## Notes for reviewers

- `config-diff.ts` itself is newly added to `index.ts`'s pure runtime
graph, but every module it transitively depends on
(`config-document.ts`, `project-config/project-config.ts`,
`project-config/registry.ts`, `sparse.ts`) was already reachable from
that graph, so no new transitive module or bare specifier enters it.
- `apps/cli`'s `config diff` command (`diff.handler.ts`,
`diff.format.ts`, and their test) are updated to import
`diffProjectConfig`/`ConfigChange*` from `@supabase/config` instead of
`@supabase/config/internal`; other internal-only imports in those files
(`loadCliConfig`, `projectConfigApiBlockKeys`) are unaffected.
- `packages/config/AGENTS.md`, `packages/config/README.md`, and ADR 0022
are updated to reflect the new entrypoint.
## Summary

- calculate CLI release significance from the squash commit title only
- keep conventional title semantics for patch, minor, and explicit
breaking changes
- ignore commit bodies when determining versions

## Context

A maintenance commit body was interpreted as a breaking-change note and
incorrectly started a v3 beta line. PR titles are already enforced and
become squash commit titles, so they are the intended versioning
boundary.
jgoux and others added 2 commits September 4, 2026 09:48
## Summary

The Windows release smoke job fails during dependency setup after
restoring the pnpm global virtual-store cache because `effect-tsgo`
cannot resolve its Windows TypeScript binary. The initial cache-miss run
succeeded, while both cache-hit attempts reproduced the failure.

Skip only the pnpm store cache on Windows in the shared setup action so
fresh installs reconstruct the package links. Keep Go caching on Windows
and preserve all dependency caching on other platforms.
…#6451)

## Summary

`ProjectConfig` is meant to describe "what a Supabase project looks like
on the platform." This PR corrects its coverage in both directions,
verified against the actual `config-sync` push code and the
OpenAPI-generated API contracts
(`packages/api/src/generated/contracts.ts`) rather than assumption:

**Removes CLI-only fields that leaked in** (`fromConfigDocument`'s
`DOCUMENT_ONLY_LOCAL_PATHS`): local dev ports (`api.port`, `db.port`,
`db.shadow_port`), `api.tls`/`api.external_url`, `db.health_timeout`,
`db.pooler.{enabled,port}`, `db.migrations`, `db.seed`, all of
`realtime.*`, and most of `experimental.*` (OrioleDB/S3 storage-engine
config, `pgdelta`, `inspect`) — none has any live hosted counterpart
under any CLI command. `db.major_version` and
`db.pooler.{pool_mode,default_pool_size,max_client_conn}` were initially
excluded too but restored after review: they're real fields
`v2GetProjectConfig` genuinely reports, and `ProjectConfig` is consumed
by `config diff`/`config pull` today (not `config push`, which still
runs on legacy v1 endpoints) — excluding them made them permanently
unclassifiable, silently blocking `config pull` from ever syncing them.

**Adds genuinely missing hosted fields** (follow-up audit against a
broader field list): `auth.external.figma` (the schema had no `figma`
provider at all, despite a real `external_figma_*` API surface — already
flagged as a known gap in the registry's own comments),
`auth.sms.otp_length`/`auth.sms.otp_expiry` (new fields for pre-existing
real GoTrue settings neither the legacy shell nor Go's own CLI ever
modeled), and `auth.sms.twilio.content_sid` (same story, Twilio-only).

Everything else audited was either already working correctly (just
needed a gating field like `enabled`/`smtp.enabled` set to observe it)
or is deliberately not hosted, confirmed per-item against the real API:
`skip_nonce_check` has no API field for any provider except google;
plain `slack` (vs. `slack_oidc`) is an existing Go-parity deprecation
this schema intentionally never modeled;
`experimental.s3_host`/`s3_region`/the S3 credential pair have no API
counterpart anywhere. `auth.oauth_server.*` is correctly mapped on the
API arm but unconditionally dropped from the document arm by the
pre-existing `applyPushUnmanagedOmissions` — that's explicitly Linear
CLI-2314's planned scope (retire push-capability pruning), not addressed
here.

Added a standing integrity test asserting no registry-mapped field can
ever land in the CLI-only exclusion list, which would have caught the
`db.major_version`/`db.pooler` regression automatically. ADR 0021/0022
updated to record the corrected family and the invariant.

Linear: CLI-2316
@@ -0,0 +1,515 @@
name: Release Config

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

The existing ownerless /.github/workflows/*.yml CODEOWNERS rule still covers this newly added production release workflow. An unreviewed workflow change could alter the App-token, OIDC, artifact, or npm-publish steps and publish attacker-controlled package contents without required CLI-owner review.
Helpful? Add 👍 / 👎

💡 Fix Suggestion

Suggestion: Add an explicit @supabase/cli ownership entry for release-config.yml in .github/CODEOWNERS, placing it alongside the other sensitive workflow overrides (after line 22, where github-scripts-ci.yml is declared). The ownerless /.github/workflows/*.yml rule (line 6) currently takes precedence via last-match-wins semantics only for patterns listed later — but since lines 21-22 demonstrate the pattern for reasserting ownership, add the following line in that same block:

/.github/workflows/release-config.yml @supabase/cli

This mirrors what was done for ai-review.yml and github-scripts-ci.yml and ensures that any PR modifying the production release workflow — which mints GitHub App tokens and publishes npm packages — requires mandatory review from a CLI maintainer before merging.

@@ -0,0 +1,203 @@
name: Mirror Slim Image

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

This newly added workflow remains covered by the ownerless /.github/workflows/*.yml CODEOWNERS rule despite assuming a production AWS role with id-token: write and copying images into public ECR. An unreviewed workflow modification could bypass digest checks or redirect the mirror, poisoning published runtime images.
Helpful? Add 👍 / 👎

💡 Fix Suggestion

Suggestion: Add an explicit CODEOWNERS ownership override for mirror-slim-image.yml in .github/CODEOWNERS, appended after the existing sensitive-workflow overrides block. Specifically, add the line /.github/workflows/mirror-slim-image.yml @supabase/cli after the /.github/workflows/github-scripts-ci.yml @supabase/cli entry. Because the /.github/workflows/*.yml pattern is intentionally left ownerless to allow Dependabot auto-merges, this new workflow — which assumes a production AWS role (PROD_AWS_ROLE) with id-token: write and publishes to public ECR — falls through to that ownerless rule. The 'last matching pattern wins' CODEOWNERS semantics mean an explicit override at the bottom of the file will restore mandatory maintainer review for this workflow, preventing unauthorized modifications from bypassing digest checks or redirecting the ECR mirror.

Prashansa-K and others added 4 commits September 4, 2026 11:14
## Summary

next version of the CLI is a scraped project at the moment. Thus,
removing these files so as to reduce confusion.
If required in future, we can always access these via git history.

#### Brief of changes
- Restored genuinely-shared infrastructure from `next/` into
`src/shared/` (auth, config, cli/command-docs) with corrected import
paths, since legacy actually depends on it.
- Fixed all downstream breakage: import paths across shared/cli/run.ts,
telemetry layers, test helpers (mocks.ts), and scripts/generate-docs.ts.
- Modified release tooling to drop the next/alpha shell entirely.
- Removed unused dependencies.
- Rewrote a few things so that references of `next` could be removed
from tests, test-helpers or docs.

#### Deliberately left untouched
`apps/cli/AGENTS.md` and `apps/cli/CLAUDE.md` — describes the stale
two-shell architecture
`apps/cli/docs/platform-command-generation.md` — documents supabase api
routes/api request, a feature that only ever existed in `next/`.
`apps/cli/docs/go-cli-divergences.md`
The above documents can be changed later once we shift the legacy CLI
directly under `src`.

## Checklist

- [x] The PR title follows [Conventional
Commits](https://www.conventionalcommits.org/) (e.g. `fix(cli): …`).
- [x] Tests added or updated for the change - NA.
- [x] 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).
…3) (#6454)

## Summary

`supabase config push` is rebuilt as a **diff-first** command. It reads
the project's effective
configuration once (`GET /v2/projects/{ref}/config`), runs the same
`diffProjectConfig` that
`config diff` and `config pull` use, and writes only the properties your
`supabase/config.toml`
declares *and* that differ from the project — as sparse request bodies
to the six existing v1 update
endpoints.

The previous pipeline (six per-service v1 GETs → rebuild each service's
full local subset with
hand-coded presence/enabled gates → TOML unified diff → PUT/PATCH the
whole subset) is deleted:
`push/config-sync/**`, the TOML encoder and diff renderer, and
`push.raw-presence.ts`.

Linear: CLI-2313. The optional follow-up to swap the six v1 writes for
the single v2 PATCH once that
endpoint ships is CLI-2317; the `@supabase/config` cleanup this unblocks
is CLI-2314 (no
`packages/config` changes here).

## What changed

- `push.plan.ts` — routes every comparable `ProjectConfig` path to one
of six write resources
(`api`, `db.settings`, `db.network_restrictions`, `db.ssl_enforcement`,
`auth`, `storage`) or to an
explicit *unsupported* set (`db.major_version`, `db.pooler.*`,
`auth.oauth_server.*`); owns the
resource gates, the MFA add-on gates and the resource→response-block
mapping. A unit test asserts
every registry path is classified, so a new `@supabase/config` row
cannot fall through silently.
- `push.encoders.ts` — six pure encoders turning routed changes into
sparse bodies. Groups the API
requires together still ship whole (CIDR lists, storage feature blocks,
SMTP, captcha, each auth
hook, each OAuth provider, the active SMS provider); **undeclared
members of such a group are sent
with the project's current value read in the same run**, so they do not
change. Only when the API
did not return a member's value is the config default sent, and that is
disclosed in the
confirmation block as `[group-write]`. The storage encoder can emit `{
enabled: false, … }` for
`icebergCatalog`/`vectorBuckets`, which the old builder structurally
could not.
- `push.secrets.ts` — declared secrets are compared as HMAC digests
against what the API reports;
plaintext is sent only when the digest differs or the remote has no
value. Empty values and
unresolved `env(...)` references are never sent and are now disclosed
before the prompt.
- `push.format.ts` — per-service change blocks reuse the family's
per-property renderer
(`config/config.format.ts`), plus the new notes, the machine-readable
summary message and the JSON
  payload.
- `push.handler.ts` — one read, then per-resource encode → confirm →
write in the established order. A
resource whose block the API did not return is reported `unavailable`
and never written; a response
  with no configuration blocks at all is an error (nothing is written).
- Family-root hoists shared by `config diff`, `config pull` and `config
push`:
  `config/config.read-status.ts` (401/403/404 read-status messages) and
`config/config.project-config.ts` (the `ProjectConfigParseError` guard).
Both handlers now use them
  instead of private copies.
- Test infrastructure: `mockLegacyPlatformApiService` gains `executeRaw`
support; the v2 response
fixture is shared between the `config diff` and `config push` suites;
the cli-e2e replay scenarios
  and recorded fixtures reflect the new request sequence.
- `SIDE_EFFECTS.md` rewritten for the new routes, output, statuses and
exit causes.

## Behavior changes (user-visible)

1. **One read instead of six.** `GET /v2/projects/{ref}/config` replaces
the six per-service
`GET /v1/…` calls. `GET /v1/projects/{ref}/billing/addons` is unchanged.
2. **Undeclared properties are left alone.** Previously a property
absent from `config.toml` was
written back with its schema default whenever its service was pushed.
Now only declared, differing
properties are written; members of a required-together group keep their
current project value.
`config diff` shows the remaining drift, and the push output reports how
many remote properties
   were left untouched.
3. **Requests carry only what changed** (plus the required-together
groups above).
4. **Credentials are compared before being sent**; unchanged secrets are
not re-sent, and a credential
that cannot be sent (empty / unresolved `env(...)`) is shown in the
confirmation block.
5. **Per-service change display** is now the same per-property format
`config diff` prints
(`path [update]`, `local:` / `remote:`) instead of a TOML-style unified
diff. Secret values are
   never printed.
6. **New reporting**: a `Comparison scope:` line on every run; notes for
properties with no Management
API field, properties that could not be encoded as written (with the
reason), declared properties
the command does not manage (count), remote-only drift (count), and
group members written at a
   default.
7. **Partial API responses are never written blind.** A resource whose
configuration block was not
returned is reported `unavailable` and skipped; if no blocks are
returned the command exits 1.
8. **JSON / stream-json payload** gains `schema_version: 1`,
`services[].changes`, `unsupported`,
`unencodable`, `forced`, `unmanaged`, `secrets`
(`sent`/`unchanged`/`not_set`/`gated`/`skipped`,
reflecting the write that actually happened), `declined_addons`,
`remote_only`, `scope`, and a
non-empty summary `message`. Existing fields (`project_ref`,
`services[].service`,
`services[].status`) keep their values; `status` gains `unavailable` and
`not_pushable`.
9. **Declining an MFA cost prompt** behaves as before (both
`verify_enabled` and `enroll_enabled` are
sent as `false` when the project has either enabled) and is now recorded
in `declined_addons`.
10. **Command description** now states the hands-off rule and points at
`config diff` as the preview.
11. **Unchanged**: command path and flags, prompt wording, `Pushing
config to project:` /
`Remote <service> config is up to date.` / `Updating <service> service
with config:` /
`Enabling webhooks for project:` lines, exit codes (declining a prompt
still exits 0), files read
    and written, telemetry.

## Reviewer notes

- Storage feature *disable* is encoder-ready but not yet reachable:
`@supabase/config` still prunes a
disabled `storage.analytics`/`storage.vector` from the local projection
(`applyPushUnmanagedOmissions`), so such a change surfaces in the
`unmanaged` count today and starts
  being pushed when CLI-2314 lands.
- The one `Effect.die` arm in `legacyConfigProjectConfigTry` is
unreachable from a JSON-parsed body
(every `@supabase/config` failure is a `ProjectConfigParseError`) and is
covered by its unit test
  rather than the integration suites.
## TL;DR
hardens seven live e2e tests so a real regression fails and a platform
read after write doesn't race
and gives `gen types` the registry fallback every other container
command already has so the suite's recurring ECR rate-limit failure goes
away...

## whats introduced?
- `postgres-config update`: proves the override through `get` by polling
until the platform reports it, instead of a single read that raced the
write
- `postgres-config delete`: the same poll for the seed proof and the
absence proof
- `db dump`: asserts the dump file contains schema DDL instead of only
existing
- `migration list`: asserts the migrations table header renders instead
of only "not Unauthorized"
- `orgs list`: asserts the table header and at least one organization
row
- `functions list`: asserts the functions table header renders instead
of only "not Unauthorized"
- `link`: asserts the cached ref in `linked-project.json` is the linked
project instead of only checking the file exists
- `tests/helpers/live.ts`: `expectPostgresConfigLiveOverride`, a bounded
`expect.poll` over `postgres-config get -o json` whose failure carries
the label, stdout and stderr
- extra, `gen types`: resolves the pg-meta image through the shared
resolver before running it, cached copy first, then ECR, GHCR and Docker
Hub with retries, instead of one `docker run` against a single registry;
the resolve sits outside the pooler fallback so a pull failure is never
mistaken for an IPv6 error

## ref:
- closes: CLI-2315
- extends: #6427
…314) (#6469)

## Summary

`fromConfigDocument` baked the legacy `config push` pipeline's
write-capability envelope into the
shared `ProjectConfig` representation (ADR 0021's original "push
convergence" ruling). That was
right when the CLI's own push command was the only reader; it's wrong
now that Studio reads the
same package for drift detection via the Management API, an actor with
none of push's write-path
limitations. Concretely, this hid real hosted customization from every
consumer — not just push —
behind three families of unconditional/blanket omissions.

Builds on #6454 (CLI-2313, merged into `develop`) — this branch has
already been rebased onto
`develop` post-merge. Nothing here depends on the v2 PATCH endpoint
(BRA-245/CLI-2317); everything
works over the v1 write endpoints #6454 already wired up.

Linear: [CLI-2314](https://linear.app/supabase/issue/CLI-2314).

## What changed

- **`applyPushUnmanagedOmissions` deleted** — this unconditionally
dropped the whole
`auth.oauth_server` subtree and dropped
`storage.analytics`/`storage.vector` entirely whenever
`enabled: false`, because legacy push never sent those shapes. That
pipeline no longer exists
(CLI-2313 deleted `config-sync/*.sync.ts`); push now consumes
`ProjectConfig` directly.
- **`DISABLED_SENTINEL_PRUNES` re-derived from the platform's actual
data model**, not from what
legacy push happened to send. Every surviving entry's docstring now
states a real, verified
reason a sibling field goes inert server-side when its container is off
(e.g. `api.enabled` is
the same wire fact as `db_schema.length > 0`, not an independent field
the API arm doesn't
already gate on its own). A new cross-arm symmetry test makes this
machine-checked: a disabled
document projection and the equivalent disabled API-response projection
must be byte-identical.
- **Deleted the `auth.enabled`/`storage.enabled` blanket
section-prunes.** These had nothing to do
with the platform — `auth.enabled` is literally "Enable the local GoTrue
service" with no
hosted/registry equivalent, yet disabling it wiped the *entire* rest of
the `auth` section (SMTP,
external providers, captcha, everything) from the shared representation
for anyone reading it.
Fixed a real bug this exposed: `push.plan.ts`'s
`legacyPushResourceEnabled` was gating the
*entire* `auth`/`storage` resource dispatch on that same local toggle,
so a declared change could
be silently dropped. `auth`/`storage` now follow the same no-gate
pattern `api`/`db.settings`
already used. No new "default comparison" machinery was needed —
`diffProjectConfig`'s existing
`declared` flag (computed generically from raw TOML presence for every
comparable path) already
keeps an undeclared default value from ever being pushed over a real
hosted customization.
- **`auth.oauth_server.*` wired up as genuinely pushable.** It's
writable via `UpdateAuthConfigBody`
(confirmed against the OpenAPI spec) — push's own `SIDE_EFFECTS.md` had
been carrying it in the
unsupported-prefix list as an explicitly-labeled placeholder for this
exact issue.
- **Named `ConfigAbsencePolicy`** (`"absent-is-default"` /
`"absent-is-hands-off"`) for the two
operand policies `fromConfigDocument` always implicitly implemented
depending on which overload
you called. Documents the one genuinely hazardous cell (an absent field
masquerading as a real
declaration when diffing in dense mode) and the `declaredRoot = {}`
cliff a caller hits by
  omitting `document` — exactly the calling shape Studio would use.
- **Unmanaged caveat reworded** to actor-neutral language ("not managed
while its section is
  disabled" instead of "cannot be pushed").
- **ADR 0021 addendum** reframing `ProjectConfig` as a shared
multi-actor representation, plus
matching touch-ups to ADR 0022/0023 and cleanup of stale references to
the deleted function.

## Verification (post-rebase onto `develop`)

- `packages/config`: `bun --bun vitest run --project unit` — 1264
passed.
- `apps/cli`: `pnpm types:check` clean; `pnpm test:unit` — 5984 passed,
1 skipped;
  `pnpm test:integration` — 3438 passed.

## Follow-ups (out of scope here)

- Consider a `local.auth.enabled`/`local.storage.enabled` namespace so
`supabase start`'s "run this
Docker service" concept is structurally separate from hosted management,
instead of overloading
  `auth.enabled`/`storage.enabled`.
- Audit `LEGACY_PUSH_UNSUPPORTED_PREFIXES`'s remaining `db.pooler` entry
against the OpenAPI spec —
`pool_mode`/`default_pool_size` are writable via
`UpdateSupavisorConfigBody`, only
  `max_client_conn` genuinely isn't.
jgoux and others added 4 commits September 4, 2026 20:02
## Summary

- pin Bun 1.4.1 through mise and refresh the locked runtime artifacts
- replace the Istanbul Vitest coverage provider with the V8 provider
across coverage-enabled workspaces
- remove the unused coverage provider from the CLI e2e workspace and
preserve pnpm global-store peer resolution

[Bun
1.4.1](https://bun.com/blog/bun-v1.4.1#node-js-compatibility-improvements)
fixes the Vitest/c8 V8 coverage merge failure that previously blocked
this migration.

## Binary size impact

Compared locally built Bun 1.4.1 executables with the checksum-verified
[v2.117.0-beta.18 production
artifacts](https://github.com/supabase/cli/releases/tag/v2.117.0-beta.18),
which embed Bun 1.4.0.

| Platform | Production 1.4.0 | Local 1.4.1 | Change |
|---|---:|---:|---:|
| macOS arm64 | 69.52 MiB | 67.53 MiB | -2.86% |
| macOS x64 | 76.00 MiB | 74.20 MiB | -2.37% |
| Linux arm64 | 91.92 MiB | 90.36 MiB | -1.70% |
| Linux x64 | 92.58 MiB | 91.01 MiB | -1.69% |
| Windows arm64 | 84.50 MiB | 83.17 MiB | -1.57% |
| Windows x64 | 94.52 MiB | 91.54 MiB | -3.16% |

The compressed release archives are also 0.37%-1.54% smaller.

The comparison is not fully runtime-isolated: the current source is one
commit beyond the production tag, and the local macOS binaries lack CI
release signing. Linux and Windows provide the cleanest indication of
the Bun upgrade size impact.
## TL;DR

 follow-up to #6290 Piped answers past the 1024th line were dropped. 
stdin is now read one chunk at a time as prompts ask for it, so nothing
is dropped and the rest stays in the pipe...

## what was biting?

Bun reads a pipe as fast as it fills and cannot be paused, so #6290
drained it into a queue of 1024 lines to stop
 `yes | supabase db push` from eating memory. 
Anything past 1024 lines fell off the queue and those prompts took their
default...

## why this approach is better? 

A file stream over fd 0 honours backpressure, so there is no queue and
no cap.
Memory is bounded the same way Go's `bufio.Scanner` did it: a line over
64 KiB ends line reading and every prompt from then on takes its
default...

## ref:
- adds onto issue: #6287
- extends: #6290
)

## Summary

Since #6424 enabled `virtualStoreType: global`, `pnpm store path`
includes `links/`, the global virtual store. It is a tree of directory
links between packages: symlinks on POSIX, NTFS junctions on Windows.
The shared setup action cached that whole directory, and on Windows the
junctions do not survive the actions/cache tar round trip as traversable
directories. pnpm then trusts every restored `links/` directory as
complete and skips relinking, so the first dependency resolved through a
restored junction fails. That is the `DiscoveryError: Unable to resolve
@typescript/typescript-win32-x64` from the root `prepare` script in
[this release
run](https://github.com/supabase/cli/actions/runs/33854068778/job/100967241418).

The failure was deterministic, not transient: every Windows release
smoke-test with a pnpm-store cache hit failed, and the only success with
the new store layout was the cache-miss run that populated the cache.
The earlier Windows failures that week were the unrelated CRLF
patch-file problem fixed in #6461.

## Changes

- Cache only `files/` and the SQLite index of the pnpm store, never
`links/`. pnpm rebuilds the virtual store from the cached files with
hardlinks and no network. The first Linux jobs after #6424 already
demonstrated this path when they restored an older files-only archive
via `restore-keys`.
- Bump the cache key prefix to `pnpm-store-files-…`. actions/cache
restores whatever an archive contains regardless of the current `path`
input, so without the bump Windows would keep restoring the existing
archive that carries `links/` until the lockfile changed.
- Remove the Windows-only cache exclusion from #6464, restoring
dependency caching on the Windows release jobs.

## Reviewer context

The release workflow only runs on `develop`, so PR CI exercises the new
caching on Linux but not the Windows smoke-test job. The first run on
each OS will be a cache miss under the new prefix. The second Windows
release run after merge is the real confirmation, since it is the first
cache hit.

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

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
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.