Commit Graph
38136 Commits
Author SHA1 Message Date
Matt Johnston 04f4cc6c1c fix(studio): correct edge function URL validation for additional project domains
`isValidEdgeFunctionURL` guards the server-side fetch in
`pages/api/edge-functions/test.ts`. When `NIMBUS_PROD_PROJECTS_URL` is set it
built a regex by string concatenation, which had several problems:

- The branch returned early, so a deployment configured with an additional
  projects domain rejected every `*.supabase.co` / `*.supabase.red` URL, and
  rejected self-hosted URLs even when `isPlatform` was false.
- The guard was `!== undefined`, so an env var declared-but-blank took the
  branch and rejected every URL.
- The subdomain pattern `[a-z]*` matched a single label of letters only, so
  refs containing digits, nested subdomains, and explicit ports all failed.
- Only `.` was escaped before interpolation into the regex, so a value without
  the exact `https://*.` prefix or with a trailing slash silently produced a
  pattern that matched nothing.
- Reading `process.env` at module scope made the branch untestable, and it had
  no test coverage.

Parse the URL instead of pattern-matching it, and treat the additional domain
as additive to the default hosts rather than a replacement.

The default `[a-z]{20}.supabase.(co|red)` host check is deliberately unchanged.
This function doubles as an SSRF allowlist for a fetch that carries the
caller's credentials, so the default allowlist is left exactly as it was.
2026-08-25 19:45:17 -03:00
Beth Adele Long 6ea3567948 Add 'Beth Long' to humans.txt (#49561)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Add new employee as part of onboarding.

## What is the current behavior?

N/A

## What is the new behavior?

N/A

## Additional context

N/A


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
  * Added Beth Long to the team listing.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 14:08:30 -07:00
Charis 4dee589735 fix(studio): stop assistant fabricating database_identifier for notebooks (#49558)
## Summary

* Fixes
[FE-4275](https://linear.app/supabase/issue/FE-4275/assistant-always-creates-notebooks-with-wrong-identifier-first-try):
the assistant always created database notebook cells with a fabricated
`database_identifier` (`"primary"`, later observed as `""` /
`"_primary"` under different prompt wording) instead of omitting the key
for the project's primary database, which tripped the tool's
reject-and-retry validation on the very first attempt.
* Prompt wording alone wasn't reliable — live eval runs against the real
model kept substituting a new placeholder every time the prompt was
tightened further.
* Normalizes an empty-string `database_identifier` to absent at the
schema level (`databaseIdentifierSchema` in `notebook-schema.ts`), which
is inherited by every schema built from it — the AI SDK's `inputSchema`
for `create_notebook`/`update_notebook`, and the write-boundary
`writableNotebookSchema` used right before the PUT to the backend.
* Adds an eval case (`evals/dataset.ts`) reproducing the original bug,
plus unit tests covering schema-level and write-boundary normalization.

## Test plan

- [X] `pnpm --filter studio exec tsc --noEmit` passes
- [X] `pnpm exec prettier --check` passes on touched files
- [X] Unit tests pass: `notebook-schema.test.ts`,
`notebook-upsert-mutation.test.ts`, `notebook-tools.test.ts` (104 tests)
- [X] Ran the new eval case against the real model 3x before the code
fix (0% correctness, fabricated `""`/`"_primary"`) and 3x after (100%
correctness)

## Summary by CodeRabbit

* **Bug Fixes**
* Improved notebook handling of empty database identifiers by treating
them as absent.
  * Ensured notebook requests omit unused database identifier fields.
  * Added validation guidance for read-replica database identifiers.
2026-08-25 15:08:28 -04:00
Danny White b5462ee7bb feat(www + studio): promote Select 2026 in www and Dashboard (#49511)
## What kind of change does this PR introduce?

Feature. Promotes Supabase Select 2026 across www and the Dashboard.

## What is the current behavior?

There is no active Select promotion on www or in the Dashboard.

## What is the new behavior?

- Adds a dismissible Select 2026 banner above the www navigation.
- Adds a low-priority Banner Stack card across hosted Studio project
pages.
- Shares a lightweight pixel lockup and CSS-only motion across both
surfaces, with light, dark, and reduced-motion treatments.
- Opens the application page in a new tab and automatically expires both
placements after October 2 in San Francisco.

## To test

- Open `/database` on the www preview. Confirm the banner is legible in
light and dark mode, the complete message remains visible at a phone
width, and the CTA opens `select.supabase.com` in a new tab.
- Dismiss the www banner, then refresh the page. Confirm it stays
dismissed.
- Open any `/project/{ref}` route in the Dashboard preview. Confirm the
Select card appears in the bottom-right Banner Stack behind
higher-priority notices.
- Dismiss the Dashboard card, navigate to another project page, and
confirm it stays dismissed.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a time-limited Select 2026 promotional banner across the website
and Studio.
* Added responsive themed artwork, animated visuals, campaign messaging,
and an external “Apply to attend” CTA.
  * Banner dismissal preferences are saved and respected across visits.
  * Promotion automatically disappears after the campaign ends.

* **Accessibility**
* Improved announcement dismissal controls with semantic buttons and
accessible labels.
  * Added reduced-motion support for promotional artwork.

* **Bug Fixes**
* Improved product-card loading effects to prevent hydration
inconsistencies.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 18:07:38 +01:00
Charis 8f124cd2e5 chore: gitignore personal skills in agents (#49544)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated ignore rules to exclude local agent skill files from version
control.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 12:05:02 -04:00
Charis 632e099487 feat(studio): track assistant notebook divergence (#49539)
## Summary
- record server divergence when an assistant changes a notebook with
local unsaved edits
- clear the session-only marker after a successful save or notebook
removal
- cover update, delete, saved eviction, and lifecycle behavior

## Verification
- pnpm --dir apps/studio exec vitest run
state/notebooks/notebooks-state.test.ts
lib/ai/notebook-cache-invalidation.test.ts
- pnpm --dir apps/studio exec eslint state/notebooks/notebooks-state.ts
state/notebooks/notebooks-state.test.ts
lib/ai/notebook-cache-invalidation.ts
lib/ai/notebook-cache-invalidation.test.ts
- pnpm --dir apps/studio typecheck

Stacked on the approval-warning PR for FE-4255.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Improved handling of server changes to notebooks with unsaved local
edits.
* Server updates and deletions are now tracked as divergences instead of
being silently skipped.
* Divergence indicators are cleared when changes are saved or notebooks
are removed.
  * Unrelated notebook changes no longer create false conflicts.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 11:42:46 -04:00
Joshen Lim 5ab866a36e Assistant notebook confirm button CTAs to have loading states (#49531)
## Context

Sets the loading state for the Assistant's Notebook actions for CTA
button behaviour consistency - currently only gets disabled when
clicked.

<img width="281" height="155" alt="image"
src="https://github.com/user-attachments/assets/c65c267b-9eb4-4669-aae4-e81b574e880c"
/>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* The AI Assistant confirmation button now displays a loading state
while processing, while preserving its disabled behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 23:28:56 +08:00
Joshen Lim 99ebfa733e Remove box shadow on explorer home tab button (#49530)
## Context

Explorer home tab has a box shadow when selected (more visible in light
mode) so this PR removes it

Before:
<img width="237" height="218" alt="image"
src="https://github.com/user-attachments/assets/17abd73b-2328-47ad-bb58-94cb5761dbb1"
/>

After:
<img width="242" height="208" alt="image"
src="https://github.com/user-attachments/assets/ef159dd7-61b9-4027-8b58-25229ae2283a"
/>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Style**
* Updated the active Explorer home tab appearance to remove its default
shadow.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 23:28:39 +08:00
Joshen Lim 15234190f7 Show loader for notebook counts (#49529)
## Context

Shows a loader UI for the notebook count, otherwise it'll incorrectly
show `0` initially

<img width="292" height="117" alt="image"
src="https://github.com/user-attachments/assets/17e3841d-b60b-4869-a0f0-3b44feb461c0"
/>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Added a loading indicator for notebook counts while data is being
retrieved.
* Prevented incomplete or unavailable counts from appearing before
loading finishes.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 23:27:30 +08:00
Ali Waseem bfbe71bc3b Allow pasting multiple redirect URLs at once (#49490)
Redirect URLs had to be added one at a time through the modal, and a
whitespace-separated paste silently saved as a single malformed allow
list entry.

Adds an opt-in `pasteSeparator` prop to `SingleValueFieldArray` that
expands a multi-value paste into one row per value, and wires it up in
the auth redirect URL modal so commas, spaces and line breaks all work.
Each URL lands on its own row, so the existing per-row validation
applies individually.

Fixes FE-4220

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Redirect URL fields now support pasting multiple URLs separated by
commas, spaces, or line breaks.
* Pasted values are automatically split into separate rows for easier
editing and individual validation.
* Supported URL formats are retained, including when multiple values are
pasted together.
  * Existing single-value paste behavior remains unchanged.
* Duplicate values are preserved so they can be reviewed and validated
individually.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 08:59:25 -06:00
Charis b686a72d89 feat(studio): warn on dirty notebook assistant proposals (#49536)
## Summary

* Warn before approving assistant update/delete proposals when the
notebook has unsaved local changes.
* Keep approval available; this is an informed-choice warning.
* Add coverage for dirty, saved, and absent local notebook state.

Towards
[FE-4255](https://linear.app/supabase/issue/FE-4255/assistant-update-notebook-can-silently-overwrite-unsaved-local)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added warnings when approving notebook update or deletion proposals
that could discard unsaved local changes.
  * Warning messages now distinguish between update and delete actions.
* Update proposal approval remains available after the warning is
displayed.

* **Bug Fixes**
* Prevented unnecessary warnings when notebooks have no saved local
changes or are unavailable.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 10:45:47 -04:00
500dddc20c docs(integrations): add Stripe Projects provisioning guide (#49354)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

This PR adds some missing Stripe Projects documentation: a short peer
entry on the Integrations overview (next to the existing Vercel
Marketplace entry) plus a focused guide page.

Closes DOCS-1337.

## What is the current behavior?

- Linear item: `DOCS-1337`: Document programmatic project provisioning,
with Stripe Projects as a partner example
- No page under `apps/docs/content/**` mentions Stripe Projects. The
only existing prose is a blog post and a `/go/` marketing page, neither
indexed as docs nor surfaced in `llms.txt` (which is generated purely
from `content/guides/**` directory names/titles).
- The Studio-side confirmation flow
(`apps/studio/pages/partners/stripe/projects/login.tsx`) already exists
and works; the gap is entirely on the docs side.

## What is the new behavior?

- `apps/docs/content/guides/integrations.mdx`: added a "Stripe Projects"
section, same weight as the existing "Vercel Marketplace" section (short
description + link), so Stripe is presented as one of several
provisioning paths rather than singled out.
- `apps/docs/content/guides/integrations/stripe-projects.mdx` (new):
Overview, Quickstart (CLI commands from the Stripe Projects blog post),
Authorizing the request (the actual Supabase-side confirmation screen
behavior), and Limitations.
-
`apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts`:
added the new page to the Integrations sidebar nav, alongside Vercel
Marketplace.

## Additional context

- Worktree:
`~/GitHub/supabase/supabase/.claude/worktrees/docs-1337-stripe-projects`
- Paired eval issue: `DOCS-1338`: a regression eval to be added/run
separately, before and after this PR, to confirm agent discoverability
actually improves.
- Out of scope: the agent-skills piece (separate `supabase/agent-skills`
repo, federated into docs at `content/guides/ai-tools/ai-skills.mdx`) is
being picked up separately.
- The org-linking limitation is confirmed against
`AccountRequestDetailsDto` and
`AccountRequestsController_confirmAccountRequest` in
`packages/api-types/types/platform.d.ts`: the schema exposes a single
optional `linked_organization`, not a list, and the confirm endpoint
takes no request body, so there's no way for the client to select a
different organization.
- The first Vercel deploy on this branch failed on an invalid `<!-- -->`
HTML comment (not valid MDX); fixed in a follow-up commit to use `{/*
*/}`.
- Heading case (`Stripe Projects`) and the word `proxied` needed
allowlist entries in `supa-mdx-lint/Rule001HeadingCase.toml` and
`supa-mdx-lint/Rule003Spelling.toml`, matching the existing `Vercel
Marketplace` precedent.
- Added a Limitations bullet (per reviewer suggestion from gregorvand)
on accessing the dashboard for a newly provisioned organization via
`stripe projects open supabase` or the reset-password flow.

### Integrations page update ([PR
preview](https://docs-git-nikrichers-docs-1337-document-programm-7b3426-supabase.vercel.app/docs/guides/integrations))


![integrations-after](https://moijyfpvgnmgoxvwcikq.supabase.co/storage/v1/object/public/pr-proof/supabase/supabase/pr49354/integrations-after-44f7cbe0.png)

### Stripe Projects page addition ([PR
preview](https://docs-git-nikrichers-docs-1337-document-programm-7b3426-supabase.vercel.app/docs/guides/integrations/stripe-projects))


![stripe-projects-after](https://moijyfpvgnmgoxvwcikq.supabase.co/storage/v1/object/public/pr-proof/supabase/supabase/pr49354/stripe-projects-after-36c32581.png)

### Test plan

- [x] Confirm the "Stripe Projects" section renders on [the Integrations
overview page
(preview)](https://docs-git-nikrichers-docs-1337-document-programm-7b3426-supabase.vercel.app/docs/guides/integrations)
- [x] Confirm [the new Stripe Projects page
(preview)](https://docs-git-nikrichers-docs-1337-document-programm-7b3426-supabase.vercel.app/docs/guides/integrations/stripe-projects)
renders and appears in the sidebar under Integrations
- [ ] Confirm the new page surfaces in `llms.txt` (directory/title
based)
- [x] Org-linking limitation confirmed via the
`AccountRequestDetailsDto`/confirm-endpoint schema (see Additional
context) rather than a Stripe Projects team conversation
- [x] Re-ran `supa-mdx-lint` allowlist additions locally; heading-case
and spelling findings addressed


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary by CodeRabbit

- **New Features**
  - Added Stripe Projects to the integrations navigation.
- Added guidance for provisioning Supabase projects through the Stripe
CLI, synchronizing environments, accessing dashboards, rotating
credentials, and understanding authorization and organization-linking
limitations.

- **Documentation**
  - Linked the Stripe Projects guide from the integrations overview.
- Updated documentation validation to support Stripe Projects
terminology and capitalization.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Nik Richers <nik@validmind.ai>
Co-authored-by: Gregor <1828888+gregorvand@users.noreply.github.com>
2026-08-25 07:31:07 -07:00
Aaditya BhusalandAli Waseem b9d22fa237 fix(studio): stale table metadata cache invalidation after table edits (#47541)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Bug fix

## What is the current behavior?

Fixes stale table metadata after saving edits from the table editor
drawer.

Previously, metadata-only table changes, such as column updates, primary
key/foreign key changes, table renames, or schema moves, could leave
cached table data stale. This affected the Database tables list, schema
visualizer, and reopening the edit drawer.

Fixes #47540

## What is the new behavior?

Table metadata caches are now invalidated consistently after table
create, update, delete, column delete, and queue table creation flows.

The Database tables list, schema visualizer, table editor drawer, table
definitions, constraints, foreign keys, table columns, rows, and lint
data now refresh correctly after relevant table metadata changes.

## Additional context


https://github.com/user-attachments/assets/de849710-8d7b-4d8b-af3b-5232154e996b


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Table metadata now refreshes consistently after table creation,
updates, duplication, and deletion.

* **Bug Fixes**
* Improved synchronization for table lists, lint results, constraints,
and row counts after changes.
* Renaming or moving tables now refreshes both the previous and updated
locations.
* Column and queue changes now trigger the appropriate table metadata
updates.

* **Tests**
* Added coverage for metadata refresh behavior across edits, moves,
optional lint updates, and row counts.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-08-25 07:43:45 -06:00
Jordi EnricandFrancesco Sansalvadore 509d80c9eb feat(studio): CLI deploy instructions for workers (FE-4191) (#49194)
## What

The surface that shows you how to deploy a worker from the CLI, plus the
product rename and the alpha framing.

- **Compute → Workers.** `PRODUCT_NAME` and `CLI_NAME` now say `Workers`
/ `workers`, so the sidebar, page title, command menu, and every
generated snippet match the CLI. One name, not two.
- **`DeployWorkerDialog`** — scaffold / configure / push, with copyable
`supabase workers` and `config.toml` snippets
- **`WorkersEmptyState`** — an `EmptyStatePresentational` with a
permission-gated deploy action
- **`AlphaNotice`** on the list page, and a **New** badge on the sidebar
entry (`Route.isNew`)
- **`WorkerSnippetTabs`** — CLI, `config.toml`, and curl/JS/Python calls
built from one worker shape. Reused by #49195.

Snippet URLs resolve from the project's `app_config.endpoint`
(`https://<project>/workers/v1/<name>`, the same shape as
`/functions/v1/`), and fall back to `[YOUR WORKER URL]` before settings
load rather than printing a wrong host.

## How to test

Only on the **Mockamaster** project in staging — it is the one project
in the alpha allow-list.

1. Staging dashboard → Mockamaster → **Workers** (the sidebar entry
carries a **New** badge)
2. **Deploy a worker** → step through the tabs; every snippet should
name the real worker URL, not a placeholder
3. Copy the cURL snippet and run it: expect `401`. Reaching a deployed
worker needs a second allow-list (`WORKERS_ALLOWED_PROJECTS` in
api-gateway `customer-router/wrangler.toml`), separate from the flag
that unlocks the dashboard.
4. Open a project with no workers to see the empty state

## Tests

`workerSnippets.test.ts` covers the generated output users copy: worker
URL in all three call snippets, the `[YOUR WORKER URL]` fallback, anon
vs service-role placeholder, empty-name fallback and trimming, runtime
default, and every `config.toml` field.

## Unverified copy

The dialog steps and the `supabase workers <sub>` subcommands come from
the original POC spec, not from the shipped CLI. Same for "Dockerfile,
Node.js and Deno supported" in the empty state — only Deno is confirmed
end to end. Worth a check by someone who knows the CLI surface.

Closes FE-4191

---------

Co-authored-by: Francesco Sansalvadore <f.sansalvadore@gmail.com>
2026-08-25 15:38:57 +02:00
supabase-supabase-autofixer[bot]andmandarini b108c4065c feat: update @supabase/*-js libraries to v2.112.4 (#49474)
This PR updates @supabase/*-js libraries to version 2.112.4.

**Source**: manual

**Changes**:
- Updated @supabase/supabase-js to 2.112.4
- Updated @supabase/auth-js to 2.112.4
- Updated @supabase/realtime-js to 2.112.4
- Updated @supabase/postgest-js to 2.112.4
- Refreshed pnpm-lock.yaml

---

## Release Notes

## v2.112.4

## 2.112.4 (2026-08-24)

### 🩹 Fixes

- **auth:** convert stolen-lock AbortError when acquireTimeout is 0
([#2616](https://github.com/supabase/supabase-js/pull/2616))
- **auth:** warn on deprecated lock option and prevent unhandled refresh
rejection ([#2627](https://github.com/supabase/supabase-js/pull/2627))
- **postgrest:** move override fixtures out of generated types, repair
codegen ([#2605](https://github.com/supabase/supabase-js/pull/2605))
- **realtime:** respect custom logger for send() REST fallback warning
([#2612](https://github.com/supabase/supabase-js/pull/2612))

### ❤️ Thank You

- Katerina Skroumpelou @mandarini
- mmustafasenoglu @mmustafasenoglu

This PR was created automatically.

Co-authored-by: mandarini <6603745+mandarini@users.noreply.github.com>
2026-08-25 15:58:14 +03:00
Ivan Vasilov e10f7cc808 feat: Add a config drift page in Studio (#48906)
## New Features
- Initial work for showing configuration drift in Studio
- This only works for Github-connected projects and it'll show a banner
if the project state differs from the git-tracked `config.toml`
- Currently behind a feature-flag `ConfigDrift`, enabled on local and
staging.
- There might be drift shown without changing any setting, this is
work-in-progress.

<img width="1217" height="1195" alt="Screenshot 2026-08-19 at 23 12 10"
src="https://github.com/user-attachments/assets/fb0b18d8-1a93-4595-85cc-e8b8a3462847"
/>

## How to test
1. Connect a project to a Github repo
2. Resync the branch on `/dashboard/project/_/branches`. This will
trigger deployment of the `config.toml` on your project
3. Change some settings (I recommend
`dashboard/project/_/auth/providers`
4. A banner should appear on all project pages with a link 


## Tests
- Added coverage for configuration conversion, normalization, matching,
drift detection, and unmanaged settings.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 13:56:40 +02:00
Prashansa KulshresthaandIvan Vasilov 0dd7cca4fa chore(docs): add Prashansa Kulshrestha to humans.txt (#49522)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES/NO

## What kind of change does this PR introduce?

Bug fix, feature, docs update, ...

## What is the current behavior?

Please link any relevant issues here.

## What is the new behavior?

Feel free to include screenshots if it includes visual changes.

## Additional context

Add any other context or screenshots.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
  * Added Prashansa Kulshrestha to the alphabetical team member list.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
2026-08-25 09:59:35 +00:00
Ping-Min Lin deebdeacd6 chore: add Ping-Min Lin to humans.txt (#49499)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

humans.txt update

## What is the current behavior?

Please link any relevant issues here.

## What is the new behavior?

Feel free to include screenshots if it includes visual changes.

## Additional context

Add any other context or screenshots.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
  * Added Ping-Min Lin to the team credits.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 11:50:11 +02:00
Alaister YoungandAlaister Young 23949ae633 [MUL-1364] fix(studio): use multipooler copy for dedicated pooler chart on HA (#49525)
The "Dedicated Pooler Client Connections" chart on the Database
observability page labels its series `pgbouncer` and links to PgBouncer
limits docs. High Availability projects run Multigres, whose dedicated
pooler is multipooler, so that copy was misleading. This swaps the copy
for HA projects and drops the docs link until multipooler docs exist
(per the ticket, disabling the link for now is fine).

**Changed:**
- HA projects: legend label `pgbouncer` → `multipooler`, series tooltip
→ "Multipooler connections"
- HA projects: the info icon shows a "docs coming soon" tooltip instead
of linking to the compute-and-disk limits docs
- Non-HA projects are unchanged

**Added:**
- Unit test for `getReportAttributesV2` covering both the PgBouncer and
multipooler branches

Out of scope (flagging for follow-up): the "Max pooler connections"
reference line still uses the PgBouncer value on HA projects, and the
Supavisor chart still renders for HA projects.

Addresses
https://linear.app/supabase/issue/MUL-1364/database-dashboard-update-dedicated-poolers-copy

## To test

- On a High Availability project, open Observability → Database and find
"Dedicated Pooler Client Connections"
- Legend and hover tooltip should say `multipooler`; the info icon
should show a tooltip ending in "(docs coming soon)" with no link
- On a non-HA project, the chart should be unchanged: `pgbouncer` legend
and the info icon links to the compute-and-disk docs

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- High Availability projects now display dedicated connection pooler
charts with multipooler-specific labels and guidance.
- Standard projects continue to show PgBouncer information and
documentation links.
- High Availability charts include a tooltip indicating that
documentation is coming soon.

- **Tests**
- Added coverage to verify the correct chart labels, tooltips, and
documentation behavior for both project types.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-08-25 08:38:41 +00:00
Alaister YoungandAlaister Young 3811e75140 [MUL-1417] feat(studio): show SSL enforcement as always on for HA projects (#49524)
High Availability (Multigres) projects always enforce SSL, and the
management API now rejects any attempt to read or change the setting
(supabase/platform#37484). This makes the Database Settings toggle
reflect that instead of surfacing an error.

**Changed:**
- `SSLConfiguration`: skip the `ssl-enforcement` query for HA projects
(via `useHighAvailability`) and render the "Enforce SSL on incoming
connections" switch checked + disabled with the tooltip "SSL is always
enforced on High Availability projects". Non-HA projects are unchanged.
- `SSLEnforcementConfirmDialog`: add a controlled `open`/`onOpenChange`
mode. The switch now opens the dialog from its own `onCheckedChange`
rather than a wrapping `AlertDialogTrigger`, so a disabled switch can no
longer open the dialog by clicking the row wrapper beside it (this was
reachable for every disabled state, and for HA would have PUT into the
new 400 guardrail). The JIT section's existing trigger-with-children
usage is untouched.

**Added:**
- `SSLConfiguration.test.tsx` (MSW): HA → checked/disabled, tooltip, no
`ssl-enforcement` request, no dialog from switch/wrapper clicks; non-HA
→ reflects fetched config, switch opens the dialog and Cancel leaves it
unchanged.

## To test

On an HA project → Project Settings → Database → SSL configuration:
- Switch is on and disabled, hovering shows "SSL is always enforced on
High Availability projects"
- No request to `/v1/projects/{ref}/ssl-enforcement` fires, no spinner
sticks, no error toast
- Clicking the disabled switch or the empty area beside it does **not**
open the "brief downtime" dialog

On a non-HA project:
- Switch reflects the current config and the GET fires once
- Clicking the switch opens the confirm dialog with Enable/Disable SSL;
Cancel and Escape close it without changing the switch or sending a PUT
- Clicking beside the switch (not on it) does not open the dialog

Linear:
https://linear.app/supabase/issue/MUL-1417/database-settings-disable-ssl-enforcement-toggle

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- High Availability projects now show SSL as always enabled, with an
explanatory tooltip.
- SSL settings are protected from changes on High Availability projects.
- SSL confirmation dialogs now open and close reliably when changing
settings.
- Added accessible announcements for SSL configuration loading and
updates.

- **Bug Fixes**
- Improved SSL state handling for standard and High Availability
projects.
- Prevented unnecessary SSL enforcement checks for High Availability
projects.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-08-25 08:34:24 +00:00
Alaister YoungandAlaister Young 0b37f0edc1 [MUL-1347] fix(studio): hide Disk IO Burst Balance chart for HA projects (#49527)
Hides the Disk IO Burst Balance chart on the Database observability page
for High Availability projects. Their volumes have no burst credit pool,
so the panel had nothing to load and rendered "Unable to load data for
Disk IO Burst Balance".

**Changed:**
- `getReportAttributesV2` now also requires
`!resolveHighAvailability(project)` before showing the
`disk-io-burst-balance` chart – the existing feature flag and
`hasBurstableIO` gating are unchanged for non-HA projects

**Added:**
- Unit tests covering the chart's visibility across HA / flag / compute
size combinations

## To test

- On a High Availability project with the `showDiskIOBurstBalanceChart`
flag on, open `/project/[ref]/observability/database` – the Disk IO
Burst Balance panel should no longer render
- On a non-HA project with a burstable compute size (e.g. micro) and the
flag on, the panel should still render as before

Addresses
https://linear.app/supabase/issue/MUL-1347/remove-panel-from-database-dashboard

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Hid the Disk I/O Burst Balance chart for High Availability projects,
where no burst-credit data is available.
* Continued hiding the chart when burst balancing is unsupported or
disabled.

* **Tests**
* Added coverage for eligible projects and scenarios where the chart
should remain hidden.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-08-25 16:22:25 +08:00
2759b13efc refine display settings ui (#49466)
<img width="392" height="343" alt="image"
src="https://github.com/user-attachments/assets/4a17e3ad-364d-45c6-9770-0f937ad18418"
/>


## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Studio UI refinement.

## What is the current behavior?

The Explorer result settings popover uses a spacious vertical layout
with mixed control heights and local active-state overrides.

## What is the new behavior?

- Condenses the result settings into the horizontal form layout used by
compact settings surfaces.
- Uses base ToggleGroup, Select, MultiSelector, and Switch component
variants.
- Adds shared tiny Toggle and MultiSelector sizes so the compact
controls render at 26px.
- Uses the accent token for shared toggle active states.
- Keeps the chart configuration behavior and disabled states intact.

## Verification

- UI and UI Patterns focused tests
- UI, UI Patterns, and Studio typechecks
- Studio ESLint
- Local visual verification against the supplied prototype



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Improvements**
* Chart-specific configuration options now appear only when chart view
is selected, keeping display settings focused and relevant.
* Updated chart controls provide clearer options for scale, cumulative
values, and labels.
* Added compact sizing for multi-select fields and toggles to improve
alignment with other form controls.
* Refined toggle styling and adjusted small-size dimensions for a more
consistent interface.

* **Tests**
  * Added coverage for compact multi-select and toggle sizes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Saxon Fletcher <SaxonF@users.noreply.github.com>
2026-08-25 18:16:40 +10:00
Saxon Fletcher ee6961beb0 fix(studio): clarify assistant tool terminal states (#49364)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Small Assistant terminal-state fixes.

## Stack context

This stack is based on #49352 (`chore/assistant-tool-outcomes`) and
assumes #49350–#49352 merge first.

Review bottom to top:

1. #49361 — assistant notebook run tool
2. #49362 — assistant notebook run UI
3. #49364 — terminal-state polish

## What is the current behavior?

Completed notebook updates can be re-diffed against newer live content,
and log-query failures can use SQL-specific or empty fallback UI.

## What is the new behavior?

- Replaces completed notebook update previews with a stable
success/error/skipped summary.
- Keeps the Open notebook action on successful updates.
- Uses logs-specific failure copy for Assistant log queries.
- Shows an explicit fallback when a failed log tool input or output
cannot be parsed.

## How to test manually

### Notebook update terminal states

1. Ask the AI Assistant to update an existing notebook, then approve the
proposal.
2. Confirm the proposal becomes a compact **Notebook updated: [name]**
summary instead of re-diffing against the newly saved notebook.
3. Click **Open notebook** and confirm it opens the updated notebook.
4. Request another notebook update and click **Skip**. Confirm the
terminal summary says **Skipped notebook update**.
5. Refresh or reopen the conversation and confirm both summaries remain
stable.

### Logs failure copy

1. Ask the Assistant to query Logs with an intentionally invalid table
or column and approve the query.
2. Confirm the failed result says **Failed to query logs**, not **Failed
to execute SQL**.
3. Confirm the failed tool remains visible rather than disappearing when
its result cannot be rendered.

## Automated test

The focused top-of-stack suite passes 9 test files and 85 tests.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Added clearer failure messaging when query logs contain invalid input,
missing results, or errors.
- Added compact summaries for completed, failed, and skipped notebook
updates.
- Notebook update summaries include an “Open notebook” link when
applicable.

- **Bug Fixes**
- Improved handling and display of query-log failures instead of showing
blank content.
- Preserved detailed previews for notebook updates that are still in
progress.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 18:16:34 +10:00
Saxon Fletcher 1a013ea2c8 feat(studio): render assistant notebook runs (#49362)
<img width="1944" height="1053" alt="image"
src="https://github.com/user-attachments/assets/74c6968b-5ad4-46f7-adcc-a144221877b2"
/>


## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Assistant notebook-run UI, reusable result previews, and approval flow.

## Stack context

This stack is based on #49352 (`chore/assistant-tool-outcomes`) and
assumes #49350–#49352 merge first.

Review bottom to top:

1. #49361 — assistant notebook run tool
2. #49362 — assistant notebook run UI
3. #49364 — terminal-state polish

## What is the current behavior?

The `run_notebook` tool has no dedicated Assistant renderer, and the
shared notebook preview cannot display saved query results.

## What is the new behavior?

- Adds a run mode to the shared minified notebook preview.
- Adds a dedicated renderer for notebook-run tool parts and wires it
into `Message.Parts.tsx`.
- Loads the current notebook and presents all cells behind one **Run
notebook** approval.
- Renders database and Logs results inside their matching notebook cells
using the existing Explorer table/chart renderer and row-limit metadata.
- Gives cells with results separate bordered surfaces while preserving
the existing create/update layouts.
- Warns when the notebook changed before approval or since a historical
run.
- Preserves raw run results for the user while the model receives
separately sanitized output.
- Handles malformed input and notebook-loading failures without hiding
the approval state.

## How to test manually

This PR now contains both the reusable result preview and the
`tool-run_notebook` Assistant wiring, so it can be tested directly from
this branch. #49364 is not required for the notebook-run UI path.

1. Create and save a notebook with at least six cells. Include:
   - a markdown cell
   - a database query that returns rows
   - a query that returns no rows
   - a query that fails
   - a Logs query
   - a database query with a row limit
2. Ask the AI Assistant: **Read this notebook and analyze it using its
current results.**
3. Confirm the approval card displays the notebook name and current
cells, with one **Run notebook** button and one **Skip** action.
4. Click **Skip** and confirm the card remains visible with **Skipped
notebook run**.
5. Ask again and click **Run notebook**. Confirm the card enters a
running state, then shows **Notebook executed** with each result under
the cell that produced it.
6. Confirm the successful empty query says **Success. No rows returned**
and shows **0 rows**.
7. Confirm the failed query shows its error without hiding the other
cell results.
8. Confirm row counts and database row-limit copy appear below the
corresponding results.
9. Confirm only the first five cells are initially visible, then click
**Show more cells** and verify the remaining cells appear.
10. Refresh or reopen the conversation and confirm the completed
notebook preview and results remain visible.
11. Start another run but leave it awaiting approval. Edit and save the
notebook in another tab, then return and confirm the card warns
**Notebook changed since the Assistant read it**.
12. Complete a run, then edit and save the notebook. Reopen the
conversation and confirm the historical card warns **Notebook changed
since this run**.
13. Ask the Assistant to create or update a notebook and confirm those
proposal previews retain their grouped layout.

## Automated test

`mise exec node@22 -- pnpm --dir apps/studio exec vitest --run
components/ui/AIAssistantPanel/AssistantNotebookPreview.test.tsx
components/ui/AIAssistantPanel/NotebookRunRenderer.test.tsx`

12 tests pass at this stack boundary.
2026-08-25 18:16:34 +10:00
dcac820571 feat(studio): add assistant notebook run tool (#49361)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Assistant feature and data-handling plumbing.

## Stack context

This stack is based on #49352 (`chore/assistant-tool-outcomes`) and
assumes #49350–#49352 merge first.

Review bottom to top:

1. #49361 — assistant notebook run tool
2. #49362 — assistant notebook run UI
3. #49364 — terminal-state polish

## What is the current behavior?

The Assistant can read and edit notebooks, but it cannot execute all
saved query cells as one approved operation.

## What is the new behavior?

- Adds a `run_notebook` tool with one approval gate for the complete
notebook.
- Executes database and log cells sequentially in notebook order.
- Rejects stale runs when the notebook changed after the Assistant read
it.
- Resolves primary and read-replica connections and forwards
authorization to log and replica requests.
- Shares rows with the model only when the organization's AI
data-sharing level permits it.
- Strictly validates and sanitizes persisted notebook-run output before
replaying message history.
- Registers the tool in prompts, filtering, mocks, and tool
construction.

## How to test manually

This is the tool/data layer; use the top-of-stack preview from #49364
for the complete UI while checking these behaviors.

1. In Explorer, create and save a notebook named **Assistant run smoke
test** with:
   - a markdown cell
   - a working database query
   - a working Logs query
- a database query that returns no rows, such as `select 1 where false`
2. Open the AI Assistant and ask: **Read the “Assistant run smoke test”
notebook and analyze it using its current results.**
3. Confirm the Assistant reads the notebook and requests one
`run_notebook` approval for all query cells, rather than requesting one
approval per cell.
4. Approve the run. Confirm database and Logs queries execute in
notebook order, the markdown cell is not executed, and the Assistant
responds only after the complete run finishes.
5. Start another run but do not approve it yet. In another tab, edit and
save the notebook. Return to the pending approval and approve it.
6. Confirm the stale run is rejected, the Assistant reads the latest
notebook version, and a new approval is required.
7. Optional privacy check: set the organization AI data-sharing level to
schema-only, run a query containing a recognizable value, and confirm
the value remains visible in the notebook result UI but is not repeated
in the Assistant's answer.

## Automated test

`mise exec node@22 -- pnpm --dir apps/studio exec vitest --run
lib/ai/tool-filter.test.ts lib/ai/tools/index.test.ts
lib/ai/tools/mock-tools.test.ts lib/ai/tools/notebook-tools.test.ts
lib/ai/tools/tool-sanitizer.test.ts`

80 tests pass at this stack boundary.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added AI-assisted notebook execution for database and log cells, with
approval, freshness checks, replica support, and per-cell error
handling.
- Added notebook deletion and database discovery and validation for
notebook management.
  - Added configurable privacy controls for notebook results.
  - Added request header support for analytics SQL execution.

- **Bug Fixes**
- Improved replica lookup handling so other notebook cells can continue
when one lookup fails.
- Prevented invalid, unauthorized, or overly detailed notebook execution
results from being exposed.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Saxon Fletcher <SaxonF@users.noreply.github.com>
2026-08-25 18:16:33 +10:00
claude[bot]andClaude 580af6e336 fix(www): stop blog tag and author breadcrumbs from becoming the page h1 (#49507)
<!-- ccr-slack-attribution -->
_Requested by **Pam Chia** · [Slack
thread](https://supabase.slack.com/archives/C07P3AU3J2D/p1787616624076769)_

**Before:** searching "supabase blog" on Google surfaces blog tag
sitelinks titled `Blog/Tags/Supabase` and `Blog/Tags/Community`, each
with the same snippet scraped from the footer newsletter form ("Get
product updates and news from Supabase").

**After:** those results use the route's real title, `Blog | Supabase`,
with a description specific to the tag, for example "Blog posts tagged
Supabase."

This change stops the visible breadcrumb on blog tag and author pages
from being the page's only `<h1>`, and gives tag and category pages
distinct meta descriptions.

## How this changes the Google result

The bad sitelinks come from two independent mechanisms, and each half of
this PR targets one of them:

**Titles.** Google prefers a page's `<h1>` over its `<title>` when the
two disagree, and on tag pages the only `<h1>` is the breadcrumb, whose
textContent is exactly `Blog/Tags/Supabase` (JSX strips the whitespace
between the children). Demoting the breadcrumb to a `<nav>` removes the
conflicting heading, so Google should fall back to the route's real
`<title>`:

- `Blog/Tags/Supabase` becomes `Blog | Supabase`
- `Blog/Tags/Community` becomes `Blog | Community`

**Snippets.** The "Get product updates and news from Supabase. Subscribe
..." text is not a meta description; it is Google's own synthesized
snippet, scraped from the footer newsletter form. Every tag and category
page shipped the byte-identical description "Latest news from the
Supabase team.", and Google discards a description duplicated across
many URLs. With a unique per-page description, Google has a usable
candidate again:

- tag rows should show `Blog posts tagged Supabase.` / `Blog posts
tagged Community.`
- category rows (`Blog | Engineering`, `Blog | Product`) already had
correct titles but the same scraped snippet; they should now show `Blog
posts in Engineering.` / `Blog posts in Product.`

Two caveats. Meta descriptions are suggestions, not directives, so
Google can still synthesize its own snippet; removing the
duplicate-description cause makes the supplied one much more likely to
win, but does not force it. And the replacement `<h1>` is the constant
sr-only `Supabase Blog` on every listing page: if Google again prefers
the h1 over the title, all sitelinks would read `Supabase Blog`. A
page-specific heading ("Posts tagged Supabase", "Posts by <author>")
would eliminate that residual risk and is a candidate follow-up.

Neither change appears in search results until Google recrawls and
reprocesses these URLs (see Additional context; the tag routes are
absent from the sitemap, which slows this). Requesting reindexing of a
few of these URLs in Search Console would speed it up.

## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Bug fix (SEO / accessibility), `apps/www` only.

## What is the current behavior?

Two separate defects feed the same bad search result.

Google prefers a page's `<h1>` over its `<title>` when the two disagree,
and on tag pages the only `<h1>` is the breadcrumb.
`apps/www/app/blog/tags/[tag]/TagClient.tsx:21-27` wraps `Blog` / `/` /
`Tags` / `/` / `<tag>` in an `<h1>`; JSX strips the whitespace between
those children, so the element's textContent is exactly
`Blog/Tags/Supabase`. The route's own `<title>` is already fine
(`apps/www/app/blog/tags/[tag]/page.tsx:26`).
`apps/www/app/blog/authors/[author]/AuthorClient.tsx:55-60` has the
identical defect. Category pages escape it because
`apps/www/app/blog/BlogLayoutShell.tsx:19` counts `/blog/categories/` as
a listing route and renders the sr-only `<h1>Supabase Blog</h1>` at line
23, while `CategoryClient.tsx` renders no `<h1>` of its own.

Separately, every tag and category page shipped the byte-identical
description `Latest news from the Supabase team.`
(`apps/www/app/blog/tags/[tag]/page.tsx:27`,
`apps/www/app/blog/categories/[category]/page.tsx:23`). Google discards
a description reused verbatim across many pages and generates its own
snippet, in this case from the footer newsletter copy at
`apps/www/components/Footer/index.tsx:179`.

## What is the new behavior?

- `BlogLayoutShell.tsx` — `isListingRoute` now covers `/blog/tags/` and
`/blog/authors/` alongside `/blog/categories/`, via a
`LISTING_ROUTE_PREFIXES` constant. Those routes now render the same
sr-only `<h1>Supabase Blog</h1>` category pages already had.
- `TagClient.tsx` and `AuthorClient.tsx` — the breadcrumb is now a `<nav
aria-label="Breadcrumb">` instead of an `<h1>`. Every existing
className, the `/` separator spans and their `px-2` padding are
unchanged. The `h1` element selector in
`apps/www/styles/globals.css:176-179` applies `font-heading font-medium
tracking-normal`, so those three utilities move onto the `nav` to keep
the rendering byte-identical. No visual change is intended; only the
element and its accessible role change.
- `tags/[tag]/page.tsx` and `categories/[category]/page.tsx` —
`generateMetadata` now returns `Blog posts tagged ${label}.` and `Blog
posts in ${label}.`, matching the shape the author route already uses
(`apps/www/app/blog/authors/[author]/page.tsx:37`). Both use `startCase`
from `apps/www/lib/helpers.tsx:75-81` rather than `capitalize`, so
`launch-week` reads "Launch Week" and matches the filter chip label at
`apps/www/components/Blog/BlogFilters.tsx:56-57`. Title and description
use the same label.

## Additional context

`apps/www` is owned by `@supabase/marketing` per
`.github/CODEOWNERS:13`, so marketing should review this.

Recovery is not immediate: Google has to recrawl these routes before the
corrected titles and descriptions show up in search results.

Noted follow-ups, deliberately out of scope here:

- `/blog/tags/*` and `/blog/authors/*` are absent from the generated
sitemap (`apps/www/internals/generate-sitemap.mjs`), which slows
discovery and recrawl.
- The page bodies still pass a `capitalize`-derived label to `TagClient`
and `CategoryClient`, so the visible tag breadcrumb reads "Launch week"
while the title now reads "Launch Week". Aligning the visible label
would be a rendered-text change, so it is left for a separate PR.
- `openGraph` metadata on these routes is untouched and still carries
the generic copy.

### How it was tested

Prettier passes on the five changed files with the repo config, in both
the default and the `SORT_IMPORTS=false` mode CI uses. Full typecheck
and lint could not be run in this environment (no `node_modules`); the
changes are type-trivial — a `string[]`.`some()` predicate, a JSX tag
swap, and two template literals over an existing exported
`startCase(string): string` helper — and the diff parses clean under
`tsc` with module resolution disabled. Worth a reviewer eyeballing the
tag and author pages side by side against production to confirm the
breadcrumb renders identically.


---
_Generated by [Claude
Code](https://claude.ai/code/session_0164goAzGTkGnoxzCKagJ3Hw)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-25 14:44:58 +08:00
CharisandJoshen Lim 40d9a2e929 fix(studio): invalidate notebook cache after assistant delete (#49496)
Stacked on supabase/supabase#49415.

## Summary

- collect completed assistant delete_notebook tool calls as deleted
cache effects
- evict deleted notebooks from the React Query cache and notebook state
- cover collector, cache eviction, and the open-tab Notebook not found
state

## Verification

- pnpm test:studio -- notebook-cache-invalidation
ExplorerNotebookTab.assistant-cache-invalidation
- pnpm --filter studio typecheck
- touched-file ESLint and Prettier checks

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Improved notebook deletion handling so removed notebooks no longer
remain visible after deletion.
* Navigation and cached notebook data now update promptly when a
notebook is deleted.
* Attempting to access a deleted notebook now displays a clear “Notebook
not found” message.

* **Tests**
* Added coverage for notebook deletion, cache invalidation, navigation
updates, and the resulting not-found state.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-08-25 14:41:56 +08:00
Danny White 5f50338a2f fix(studio): keep region flags visible on light surfaces (#49517)
## What kind of change does this PR introduce?

Studio interface fix.

## What is the current behavior?

Region flags with light backgrounds, such as Japan, can disappear
against light Studio surfaces. Flag rendering is also repeated across
region selectors and infrastructure views.

## What is the new behavior?

Region flags use a shared `RegionFlag` component with the existing small
radius and a subtle 1px border. The treatment is applied consistently
across project creation, replication, read replicas, infrastructure, and
Edge Function observability.

| Before | After |
| --- | --- |
| <img width="746" height="246" alt="CleanShot 2026-08-25 at 14 01
07@2x"
src="https://github.com/user-attachments/assets/5ccffccd-f253-47ca-a587-e97d1e8306a8"
/> | <img width="746" height="234" alt="CleanShot 2026-08-25 at 14 09
20@2x"
src="https://github.com/user-attachments/assets/9d59f7f6-4364-4c2c-8b97-a9673616736a"
/> |

## To test

- Open the new project flow and inspect the selected region and region
menu. Confirm light flags remain visible without changing size or aspect
ratio.
- Open Database Replication and inspect region flags in the diagram and
destination form.
- Open `/project/<ref>/settings/infrastructure` and inspect flags in the
topology, map, and read replica details.
- Open Edge Function observability and inspect the region filter
options.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **UI Improvements**
* Standardized region flag displays across project creation,
replication, infrastructure, read replica, and observability views.
* Region flags now use consistent styling, rounded borders, and
rendering throughout the Studio interface.
* Improved visual consistency for selected regions, database nodes,
tooltips, and region options.
* Decorative flags in observability views are handled appropriately for
assistive technologies.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 16:25:12 +10:00
Charis de3a8799d6 fix(studio): invalidate notebook caches after assistant create/update (#49415)
## Summary
- The assistant's `create_notebook`/`update_notebook` tools run entirely
server-side, so an open notebook tab's React Query cache and Valtio
store never learn a write happened — the tab keeps showing stale content
until a manual reload.
- Adds `collectNotebookCacheEffects`/`applyNotebookCacheEffects`
(`apps/studio/lib/ai/notebook-cache-invalidation.ts`), which scan
finished assistant messages for completed
`create_notebook`/`update_notebook` tool calls and evict the affected
notebook via `evictNotebookFromCaches`
(`apps/studio/data/content/notebooks/notebook-cache.ts`), plus
invalidate the nav list.
- Wired into `createChatInstance`'s `onFinish` in
`state/ai-assistant-state.tsx`, with per-chat dedupe so replayed history
isn't reprocessed.
- Removes the cache entry outright rather than invalidating it, since a
remounting `useNotebookQuery` would otherwise read the stale cached
value synchronously before its refetch lands.
- Explicitly skips eviction when the open tab has unsaved local edits,
so an assistant write can't silently discard them.

Related: [FE-4235](https://linear.app/supabase/issue/FE-4235)

**Out of scope:** this only protects the client-side cache/store from
being clobbered after the fact. Preventing the assistant's
`update_notebook` tool call itself from overwriting a user's unsaved
edits (a data-layer conflict, not a cache-freshness one) is tracked
separately in [FE-4255](https://linear.app/supabase/issue/FE-4255).

## Test plan
- [x] `pnpm test:studio -- notebook-cache notebook-cache-invalidation
ai-assistant-state.notebook-cache-invalidation
ExplorerNotebookTab.assistant-cache-invalidation
ExplorerNotebookTabCoordinator` — all passing
- [x] Reproduction-first component test
(`ExplorerNotebookTab.assistant-cache-invalidation.test.tsx`) — verified
it fails without the fix (stale content persists) and passes with it
- [x] Regression test for the dirty-notebook guard (an edited, unsaved
notebook is left untouched by an assistant write)
- [x] `pnpm typecheck --filter=studio` / `pnpm lint --filter=studio`
clean


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Notebook changes made through the AI assistant now appear correctly in
open notebook tabs and after reopening them.
* Saved notebook caches are refreshed after completed create or update
actions, preventing stale content from being displayed.
  * Unsaved notebook changes are preserved during cache cleanup.
  * Closing a notebook tab now consistently removes its cached content.

* **Tests**
* Added coverage for assistant-driven updates, remounts, duplicate
actions, project context changes, and cache behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 14:15:27 +08:00
Joshen Lim 3490a63a7c Hook up analyze button in notebook (#49463)
## Context

Hooks up the "Analyze" CTA on a notebook which runs a prompt in the
Assistant to run the notebook and summarize findings
<img width="230" height="63" alt="image"
src="https://github.com/user-attachments/assets/fd30f301-1c52-4e9b-810c-74820cf52720"
/>

Note: running notebooks have not been hooked up yet on the Assistant
side of things

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Added an Analyze action to notebook tabs.
* Notebook changes must be saved before analysis can begin, with a
confirmation prompt to save.
  * Analysis starts automatically after a successful save.
* The Analyze action now shows a loading state while analysis is being
created.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 13:44:20 +08:00
Alaister YoungandAlaister Young 002be81efb [FE-4184] fix(studio): hide view logs link for disabled services (#49487)
On Multigres/HA projects, Realtime is intentionally shown as
**Disabled** in the project home status hover card, but the row still
linked to logs with a "View logs" hover affordance and used the same
warning triangle as an unhealthy service. Disabled services now render
as a non-interactive row with a neutral "off" icon.

**Changed:**
- `ServiceStatus.tsx` – services with status `DISABLED` render a plain
`div` instead of a `Link` (no hover background, no "View logs" +
chevron). All other services keep the existing click-to-logs behavior.
- `DISABLED` services now show a muted `MinusCircle` icon instead of the
`AlertTriangle` used for unhealthy services, so "off" no longer reads as
"broken".
- "View logs" affordance is also revealed on keyboard focus
(`group-focus-visible`), not just hover.
- Applies to any `DISABLED` service, not just Realtime – PostgREST also
resolves to `DISABLED` when its `db_schema` is empty.

## To test

- Open the home page of a Multigres/HA project and hover the **Status**
stat to open the service hover card
- Realtime row shows a muted circle-minus icon with "Disabled", no hover
highlight and no "View logs" link
- Other rows (Database, Auth, Storage, etc.) still highlight on hover,
show "View logs" on hover or keyboard focus, and navigate to their logs
page on click
- Unhealthy services still show the warning triangle
- On a non-HA project, all rows (including Realtime) behave as before

Addresses FE-4184

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-08-25 05:20:06 +00:00
Joshen Lim f1526d2d1b Fix running queyr cell marks notebook tab with unsaved change indicator (#49464)
## Context

Fixes a small bug whereby running any query cell within a notebook will
mark the notebook tab with the unsaved changes status indicator

`handleSqlCommit` gets called when we run the query, and it flips the
notebook's status to "unsaved" hence why its happening. Hence opting to
skip committing the changes in `handleSqlCommit` if there's no change to
the SQL content

<img width="224" height="69" alt="image"
src="https://github.com/user-attachments/assets/7015b527-b249-4f2e-bcf1-948b5fe3f5a9"
/>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Bug Fixes**
- Prevented unnecessary notebook updates when committed SQL is
unchanged.
  - Continued saving SQL changes as expected.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 11:57:04 +08:00
Joshen Lim 63a6e27142 Trigger native browser confirmation when exiting session if there's unsaved changes (#49465)
## Context

As per PR title - triggers the native browser discard confirmation
dialog while in the explorer UI if exiting the session (e.g by
refreshing or closing the tab) and there's any tabs with unsaved changes

<img width="593" height="431" alt="image"
src="https://github.com/user-attachments/assets/85b50c3e-ee69-4d27-8819-12151e6fc9f7"
/>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Added a warning when attempting to leave or close the page while a
notebook has unsaved changes.
* Prevented unnecessary warnings when no discardable changes are
present.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 11:40:33 +08:00
Ali Waseem 310b29c37b fix(ui): anchor radio group bubble inputs to their group (#49494) 2026-08-24 17:38:18 -06:00
shaziya e616c6d267 Add blog post: Enterprise-managed auth for the Supabase MCP server (#49493)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

New blog post announcing enterprise-managed auth for the Supabase MCP
server, built with Anthropic and Okta.

## What is the current behavior?

No blog post exists for this launch.

## What is the new behavior?

Adds `/blog/enterprise-managed-auth-for-the-supabase-mcp-server` dated
2026-08-24, authored by Cemal Kılıç and Greg Richardson, with the OG and
thumbnail images.

Supersedes #49492 (closed by a branch rename).

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Announced general availability of enterprise-managed authentication
for the Supabase MCP server.
* Added details on Okta-based administration through Claude,
user-specific roles and permissions, and centralized onboarding,
offboarding, and access reviews.
  * Included plan availability requirements and setup guidance.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 19:33:07 +00:00
Monica KhouryandClaude Sonnet 5 d5ee11bea0 fix: hand off AI assistant to the project page in org view (#49477)
Fixes FE-4200, FE-4206.

## What is the current behavior?

Submitting a support ticket from an org-level page (with no project in
the URL) shows a "While you wait" AI assistant card. However, the
assistant is built around project-scoped context from the URL, so making
it work here required adding project-context fallbacks across several
features.

Two previous PRs addressed individual issues, but testing continued to
surface the same underlying problem in other areas, including chat
persistence, message rating, table browsing, and SQL editor actions.

- **#49244**  
- **#49430**  

Rather than keep adding fallbacks, this PR removes the underlying
context mismatch.

## What is the new behavior?

When a support ticket is submitted from an org-level page, the "While
you wait" card now links to the relevant project instead of trying to
run the AI Assistant without real project context.

The link opens the project with the AI Assistant sidebar and hands off
the support ticket. The chat is created there, so project-scoped
features like schema browsing, SQL actions, message rating, and chat
persistence work natively without special-casing.

If there’s no relevant project, the card isn’t shown.

The ticket form also restores the "No specific project" option for cases
where the auto-selected project isn't relevant.

## Additional context

Also fixes ?sidebar= deep links not opening the sidebar after
client-side navigation. LayoutSidebarProvider now reacts to URL param
changes instead of only checking on initial load.

## How to test

1. Submit a project-related support ticket from an org-level page.
2. Confirm the "While you wait" card shows "Open Assistant in project".
3. Click it and confirm the correct project opens with the AI Assistant
sidebar and support chat active.
4. Verify project-scoped features work, such as schema questions and
Edit query / Run.
5. Refresh and confirm the chat persists.
6. Select "No specific project" and confirm no assistant card is shown.
7. Submit a ticket from a project support page and confirm the existing
inline assistant behavior is unchanged.
8. Verify a project ?sidebar=ai-assistant deep link still opens the
sidebar normally.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added support handoff links when a submitted ticket belongs to another
project.
* Handoff links securely preserve support request details without
exposing them in the URL.
* Opening a valid handoff link creates and selects a support chat with
the submitted request context.

* **Bug Fixes**
  * Improved sidebar behavior when URL state changes.
  * Project selector validation messages now remain visible.
* Invalid, expired, or mismatched handoffs now fall back to a new chat
and display an error message.
* Handoff details are securely handled only once and cleared after use.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 21:37:25 +03:00
CharisandJoshen Lim 89b4f1aca4 feat(studio): add delete_notebook tool to AI assistant (#49413)
## Summary

* Adds a `delete_notebook` AI assistant tool (`needsApproval: true`)
that lets the assistant delete a notebook with explicit user approval,
mirroring the existing `create_notebook`/`update_notebook` tools.
* Wires up a destructive-styled approval card in the AI Assistant Panel
(fetches the notebook to show its name, warns the deletion is permanent)
using the same `Confirm`/tool-approval plumbing as the other notebook
tools.
* Updates `tool-filter.ts` opt-in gating, the assistant system prompt,
the eval-harness mock tools, and the eval dataset with `delete_notebook`
coverage.
* Adds test coverage in `notebook-tools.test.ts`, `mock-tools.test.ts`,
and `NotebookProposalRenderer.test.tsx`.

Closes
[FE-4242](https://linear.app/supabase/issue/FE-4242/assistant-delete-notebook-tool).

## Test plan

- [X] `pnpm typecheck --filter=studio` passes
- [X] `pnpm --filter studio exec vitest run` for the touched files
(notebook-tools, mock-tools, NotebookProposalRenderer,
[Message.Parts](<http://Message.Parts>), and existing consumers of
`content-delete-mutation`) — all passing
- [X] `eslint` and `prettier --check` clean on all touched files
- [X] Manual verification of the approval UI in a running Studio
instance (not done in this session)

## Summary by CodeRabbit

* **New Features**
* Added AI-assisted notebook deletion with explicit confirmation and
irreversible-action warnings.
* Added safeguards to distinguish deleting an entire notebook from
removing individual panels.
* Completed deletions now display the deleted notebook’s name without an
option to reopen it.
* **Bug Fixes**
* Improved handling of missing notebooks and invalid deletion requests.
* **Tests**
* Added coverage for deletion approval, denial, errors, and successful
completion.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added AI-assisted notebook deletion with explicit approval and
irreversible-action warnings.
* Added confirmation, loading, error, and completion states for notebook
deletion.
* Prevented accidental full-notebook deletion when only a panel or
section should be removed.
* Improved notebook update results by showing applied changes when
available.

* **Bug Fixes**
  * Notebook deletion now uses the required API version.
* Improved handling and validation of missing notebooks during deletion.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-08-24 13:18:12 -04:00
Miranda LimonczenkoandClaude Opus 5 60f7903b52 fix(www): group the filter controls and announce the result count (#49410)
Closes FE-4251

## Problem

The filter sidebars are unstructured `div` nesting. Measured on a
preview:

* 9 checkboxes on `/features` and 13 on `/partners/catalog`, none inside
a `fieldset`, a `role="group"`, or any region.
* The `/features` "Filter by tags:" `h2` has no `id`, so nothing can
reference it as a group name.
* The only landmarks on `/features` are two `nav` elements, so the
filter panel is unreachable by landmark navigation.

A screen reader user meets a checkbox announced as "authentication,
checkbox" with nothing conveying that it filters features by tag.

Separately, both result counts update on every filter change with no
live region, so the outcome of toggling a filter is never announced.

## Solution

* Wrap each checkbox set in a labelled `role="group"`.
* Wrap each filter panel in an `aside` labelled "Filters".
* Add `aria-live="polite"` to both result counts.

The two pages name their group differently on purpose. `/features` uses
`aria-labelledby` pointing at the existing `h2`, so the visible heading
is the accessible name. `/partners/catalog` uses `aria-label`, because
`filtersPanel` renders into both the desktop sidebar and the mobile
sheet, so an `id` would appear twice in the DOM. That file already calls
out the duplicate-id hazard at line 152 as its reason for using wrapping
labels.

Chose `role="group"` over `fieldset` and `legend` to avoid resetting UA
styling in a styled sidebar.

The single self-hosted checkbox keeps its own label and needs no group.

## Manual testing

**/features**

1. Open
[/features](https://zone-www-dot-com-git-www-filter-groups-and-live-count-supabase.vercel.app/features)
with Screenreader.
2. Confirm the tag checkboxes report as a group named "Filter by tags:".
3. Confirm a "Filters" landmark appears in landmark navigation.
4. Tick a tag filter. The result count changes and is announced.

**/partners/catalog**

5. Open
[/partners/catalog](https://zone-www-dot-com-git-www-filter-groups-and-live-count-supabase.vercel.app/partners/catalog)
at a desktop width. The filter panel is `hidden md:block`, so the
landmark only exists at md and above.
6. Confirm the category checkboxes report as a group named "Categories".
7. Open the mobile filter sheet at a narrow width and confirm the group
is still named, with no duplicate ids.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Accessibility Improvements**
* Improved screen reader navigation for partner catalog and feature
filters.
  * Added accessible labels and landmarks for filter sections.
  * Updated result counts to be announced when selections change.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 09:46:03 -07:00
Miranda LimonczenkoandClaude Opus 5 78d6d57faa fix(www): stop rendering the invisible Clear all filters button (#49409)
Closes FE-4250

<img width="661" height="294" alt="Screenshot 2026-08-21 at 10 44 38 AM"
src="https://github.com/user-attachments/assets/db7e09db-845c-43a8-a6ca-5d0c67436355"
/>



## Problem

With no filters active, `/features` still rendered the "Clear all
filters" button and hid it with `opacity-0`. Found with VoiceOver, which
announced "You are currently on a button" on an apparently empty
control.

Measured on a preview with no filters active:

| Property | Value |
| -- | -- |
| `opacity` | `0` |
| `visibility` | `visible` |
| `display` | `block` |
| `tabIndex` | `-1` |
| `aria-hidden`, `inert`, `disabled` | none |
| `pointer-events` | `auto` |
| Layout | 256 x 26px |

Two assumptions were wrong. `opacity: 0` does not remove an element from
the accessibility tree, and `tabIndex="-1"` only removes it from tab
order, not the tree. Screen readers walk the tree. It was also a live
256 x 26 mouse target, so a sighted user could click an invisible
button.

## Solution

Render it conditionally, matching `IntegrationsContent.tsx` which
already does this and was unaffected.

No layout shift. The button is the last child of the sidebar column, so
nothing above it moves when it appears.

## Manual testing

1. Open
[/features](https://zone-www-dot-com-git-www-features-clear-filters-button-supabase.vercel.app/features)
with no filters applied. Confirm no "Clear all filters" button exists
anywhere in the DOM.
2. Tick a tag filter in the left sidebar. The button appears.
3. Click it. Every filter clears, the count returns to 79 features, and
the button disappears again.

For the before state, open [/features on
production](https://supabase.com/features) with no filters, then run
this in the console. It reveals the button that is present but
invisible:

```js
const b = [...document.querySelectorAll('button')].find(x => /Clear all filters/.test(x.textContent))
Object.assign(b.style, { opacity: '1', outline: '3px solid red' })
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* The “Clear all filters” button now appears only when filters are
active.
* Improved keyboard navigation by removing inactive filter controls from
the tab order.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 09:38:38 -07:00
Miranda LimonczenkoandClaude Opus 5 21265b2e59 docs(database): make writing and running the tests part of the procedure (#49276)
Ref DOCS-1274

Follow-up to #49017, now merged.

This is the go-to-green piece: everything aimed at the three failing
eval checks, and nothing else. Technical corrections follow in the PR
stacked on this one.

## Problem

`build-docs-002-rls-guide` points an agent at this guide with a
vibe-coder prompt that never says RLS, policy, role, or test. Grants,
policies, access probes, indexes, and security-definer placement all
pass. Three checks fail, and have failed on every recorded run:

| Check | What it measures | Why it failed |
| --- | --- | --- |
| `pgTAP test file(s) written under supabase/tests/` | Any `.sql` file
exists | The agent never wrote one. |
| `supabase test db runs at least 8 assertions and all pass` | Suite
runs, ≥8 assertions, none failing | Nothing to run. The only example was
`plan(4)`, under the floor even if copied perfectly. |
| `tests assert allow and deny per operation … for anon and
authenticated` | LLM judge on coverage | Never reached the judge: "no
test files to review". |

The guide already had a `Test your policies` section, so this isn't a
strength problem. Agents don't read the page. They fetch it through an
LLM extraction guided by their own query, and that query asked for
enabling RLS, policy syntax, `auth.uid()`, indexes, and security definer
functions. It never mentioned tests. A section about testing never
enters the extract, so more testing prose cannot reach the agent.

There was also a plain documentation bug underneath it: `Secure a table
with RLS` said a table isn't secured until the suite passes, but the
procedure beneath it ran 1–3 and ended on `grant`. A reader following
the numbered steps finished without ever being told to write a test.

## Solution

Put the tests where the procedure and the examples already are.

- **`Secure a table with RLS`** opens with the four steps that finish a
table, ending on `supabase test db`. Until the suite passes, you don't
know whether the policies do what you intended.
- **`Enable RLS and set the grants` gains step 4** — `supabase test new
<table>_rls.test`, then `supabase test db`. The procedure ends on a
passing suite instead of a grant.
- **The public-read example** gains its policy and
`announcements_rls.test.sql`, so a test file rides along in the
enable-RLS extract.
- **The four policy examples** are followed immediately by
`profiles_rls.test.sql`, so one rides along in the `create policy`
extract too.
- **`Run the test suite` shrinks** to creating and running the files. It
no longer carries content that has to survive extraction.
- Each file leads with its own path as a comment, so it survives if the
fence metadata is dropped.

### How that maps to the three checks

| Check | Addressed by |
| --- | --- |
| Test files written | A complete test file now sits inside both
extracts an agent's own query pulls, and step 4 of the procedure names
the command that creates one. |
| ≥8 assertions, all passing | `announcements_rls.test.sql` is
`plan(10)`, `profiles_rls.test.sql` is `plan(14)`. Either alone clears
the floor; together, 24. |
| Coverage judge | `profiles` asserts allow **and** deny for all four
operations. Allowed writes use `returning` + `results_eq`, proving state
changed rather than that nothing raised. `using`-filtered denials use
`is_empty`, asserting the row is unchanged rather than that an error was
raised — the case the rubric explicitly fails suites for getting wrong.
Both files switch role with `set local role` and identity with `set
local request.jwt.claim.sub`, and cover `anon` as well as
`authenticated`. |



## Manual testing

1. Open the [Row Level Security
guide](https://docs-git-docs-rls-tests-in-procedure-supabase.vercel.app/docs/guides/database/postgres/row-level-security)
on the preview. `Secure a table with RLS` opens with a four-step
definition of done ending on `supabase test db`.
2. Read `Enable RLS and set the grants`. The procedure runs 1–4 and ends
on writing and running the test, not on the grant.
3. Scroll to `DELETE policies`. The four policies are followed
immediately by `profiles_rls.test.sql`, not a pointer to a later
section.
4. Open the [markdown
version](https://docs-git-docs-rls-tests-in-procedure-supabase.vercel.app/docs/guides/database/postgres/row-level-security.md),
which is what agents fetch. Both test files are present, each leading
with its path.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Documentation

- Updated database security guidance for enabling row-level security and
configuring grants.
- Added per-table pgTAP testing requirements and revised `supabase test
db` examples.
- Expanded examples for permitted and denied access across public and
authenticated roles.
- Added dedicated guidance for profile testing and security-definer
member/non-member cases.
- Documented recursive-policy `42P17` failures and the security-definer
workaround.
- Clarified indexing, denial diagnosis, returned-row verification, and
table-hardening links.
- Streamlined the general policy-testing guidance.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 09:23:33 -07:00
Miranda LimonczenkoandClaude Opus 5 0243ad7cf1 fix(www): make the view toggles a radio group and fix the filter rows (#49346)
Closes FE-4227

> [!NOTE]
> Bottom of a stack. #49409 and #49410 sit on top of this one, so merge
this first.

## Problem

Five defects in the view toggles on `/features` and `/partners/catalog`,
plus one in the `/features` filter rows. All measured on a preview.

**Toggles**

| Defect | Evidence |
| -- | -- |
| No pointer cursor | Tailwind 4 Preflight no longer sets `cursor:
pointer` on buttons. 14 of 19 buttons on `/features` computed to
`default`. Anchors were unaffected, which is why it looked inconsistent
rather than total. |
| The selected toggle offered a pointer | It is a no-op, so the cursor
promised an action that does nothing. |
| The selected state was invisible in light mode | `bg-surface-300` and
`bg-surface-75` both resolve to pure white. Contrast ratio exactly
1.000. The light theme base lightness is `.995` and each surface step
adds `.024`, so every lighter step clamps at white. The only cue left
was icon colour. |
| Hover inverted the selection | Unselected hover is `bg-surface-200`, a
2.7% black overlay, while the selected state was white. Hovering the
wrong button made it look selected. |
| No grouping | Two unrelated buttons. Nothing conveyed one choice with
two options, and the selected view was not programmatically determinable
at all. |

**Filter rows on /features**

A pointer appeared only on the narrow gap between each checkbox and its
label:

| Element | Computed cursor |
| -- | -- |
| wrapper `div` | `pointer` |
| `label` | `default` |
| checkbox | `default` |

`cursor-pointer!` sat on the wrapper. A declaration targeting an element
always beats an inherited value, so `!important` on the parent changed
nothing and both children overrode it.

## Solution

**Toggles become a `ToggleGroup`** on both pages, replacing the raw
button pairs.

* `type="single"` renders `role="group"` with `role="radio"` and
`aria-checked` per item. That describes one choice with two options
rather than two independent toggles, so a screen reader announces the
selection and its position in the set.
* Each group gets an `aria-label`, which the existing `ToggleGroup`
usage on `/pricing` lacks.
* Selected item gets `cursor-default`, unselected gets `cursor-pointer`.
* Selected background becomes `bg-surface-400`, a 5.4% overlay that
clears the 2.7% unselected hover and removes the inversion.

**Filter rows** become wrapping `label` elements with `cursor-pointer`
directly on the label, matching `IntegrationsContent.tsx`. The whole row
becomes a click target, and `id` values derived from raw product names
go away.

`toggleVariants` sets the selected background to `bg-surface-300` under
both `data-[state=on]:` and `aria-checked:`, and twMerge only dedupes
matching prefixes. Both are overridden here so adopting the primitive
does not reintroduce the invisible state this PR fixes. The primitive
defect is FE-4245.

### Behaviour change

The toggle pair is now a single tab stop navigated with arrow keys,
rather than two separate tab stops. That is correct for a mutually
exclusive group, but it is a change from current behaviour.

### Related, deliberately not here

| Work | Where |
| -- | -- |
| Checkbox primitive pointer cursor | #49408, so the shared-package
change is reviewed separately. The checkbox itself still shows an arrow
on this branch. |
| Naming these toggles, which rely on `title` | FE-4229 |
| Base-layer cursor fix across www, Docs and Studio | FE-4228 |
| Sharing one component between the two pages | FE-4244 |

## Manual testing

1. Open
[/features](https://zone-www-dot-com-git-www-view-toggle-pointer-cursor-supabase.vercel.app/features)
in light mode. The selected toggle is visibly darker than the unselected
one.
2. Hover the selected toggle. The cursor is an arrow. Hover the
unselected one. It is a pointer, and it does not become darker than the
selected one.
3. Tab to the toggle pair. It takes one tab stop. Move between options
with the arrow keys.
4. Inspect either toggle. It has `role="radio"` with `aria-checked`
tracking the selection, and the wrapping group has an `aria-label`.
5. Hover a tag filter row over the label text and over the gap between
the checkbox and the text. Both show a pointer. The checkbox itself
still shows an arrow here; that is #49408.
6. Click a filter row well away from the checkbox. The filter toggles.
7. Repeat steps 1 to 4 on
[/partners/catalog](https://zone-www-dot-com-git-www-view-toggle-pointer-cursor-supabase.vercel.app/partners/catalog).

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 09:19:59 -07:00
Miranda LimonczenkoandClaude Opus 5 c79d7be7d9 fix(www): give the feature and partner card grids list semantics (#49411)
Closes FE-4252

## Problem

`/features` renders 79 feature cards as bare `Link` elements in a grid
`div`. Measured on a preview, `main` contains zero `ul`, `ol`, `li`, and
zero `role="list"`. `/partners/catalog` is the same.

A screen reader user gets a run of loose links with no "list, 79 items",
no set size, and no way to navigate by list. Sighted users see an
obvious grid of cards, and the structure conveying that is purely
visual.

Same defect class as FE-4101 and DOCS-1279, both already in this
milestone.

## Solution

Make each card container a `ul` with one `li` per card. Four containers:

| File | Container |
| -- | -- |
| `apps/www/pages/features.tsx` | feature card grid |
| `apps/www/app/partners/catalog/IntegrationsContent.tsx` | featured
partners grid |
| same | grid view |
| same | list view |

This change makes a Screenreader announce the number of items and track
them.

Most of this diff is re-indentation from the added wrapper.

## Manual testing

**/features**

1. Open
[/features](https://zone-www-dot-com-git-www-card-grid-list-semantics-supabase.vercel.app/features)
with Screenreader. Confirm the cards report as a list of 79 items, and
that the count tracks the filters.
2. Check the grid at mobile, tablet and desktop widths. Cards stay equal
height within a row and the column counts are unchanged.

**/partners/catalog**

3. Open
[/partners/catalog](https://zone-www-dot-com-git-www-card-grid-list-semantics-supabase.vercel.app/partners/catalog)
in grid view with Screenreader. Confirm both the featured section and
the main grid are lists.
4. Switch to [list
view](https://zone-www-dot-com-git-www-card-grid-list-semantics-supabase.vercel.app/partners/catalog?view=list).
Confirm it is a list and the dividing lines between rows are unchanged.

Compare any of these against
[production](https://supabase.com/features). The rendering should be
identical; only the markup changes.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Accessibility**
* Improved semantic structure for partner catalog and feature cards
using properly organized lists.
* Expanded card links to make larger portions of featured and grid cards
clickable.
  * Preserved existing layouts, content, and filtering behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 09:19:40 -07:00
Miranda LimonczenkoandClaude Opus 5 3178da7f4d fix(ui): give enabled checkboxes a pointer cursor (#49408)
Closes FE-4249

## Problem

The `Checkbox` primitive sets `disabled:cursor-not-allowed` but never
sets a base cursor. It renders a Radix `button`, and a UA `button {
cursor: default }` rule beats an inherited value from any parent, so an
enabled checkbox shows an arrow while being clickable. The `disabled:`
variant only makes sense if a base cursor exists.

A parent cannot fix this. `/features` tried `cursor-pointer!` on a
wrapper `div` with a sibling checkbox and label. Measured:

| Element | Computed cursor |
| -- | -- |
| wrapper `div` | `pointer` |
| `label` | `default` |
| checkbox `button` | `default` |

A declaration targeting an element always beats an inherited value, so
`!important` on the parent changed nothing. Only the bare gap between
the two children showed a pointer.

## Solution

Add the base `cursor-pointer` that the existing `disabled:` variant
already implied.

Split out of #49346 so this shared-package change gets reviewed on its
own. It affects www, Docs and Studio.

## Manual testing

**www**

1. Open
[/features](https://zone-www-dot-com-git-ui-checkbox-pointer-cursor-supabase.vercel.app/features).
2. Hover any filter checkbox in the left sidebar. The cursor is a
pointer.

**Studio**, since this is a shared primitive. Needs Vercel SSO and a
logged-in account.

3. Open the [Studio
preview](https://studio-staging-git-ui-checkbox-pointer-cursor-supabase.vercel.app)
and pick any project.
4. Go to Table Editor and click the funnel icon in the left sidebar.
5. Hover the checkboxes in the "Filter entity types" popover. Each shows
a pointer.

**Disabled state**, which this PR must not change.

6. In devtools, add `disabled` to any checkbox. The cursor becomes
`not-allowed`.

**Docs has nothing to check.** `apps/docs` contains no `Checkbox` usage.
A runtime sweep found zero checkboxes on the troubleshooting page with
its Products filter open, and on `/docs`,
`/docs/guides/database/overview` and `/docs/guides/auth`. Its
[preview](https://docs-git-ui-checkbox-pointer-cursor-supabase.vercel.app/docs)
builds only because `packages/ui` is a dependency.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Style**
* Updated checkbox controls to display a pointer cursor, making them
feel clickable.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 09:17:26 -07:00
Miranda LimonczenkoandClaude Opus 5 932180541e fix(ui-patterns): give the shared InfoTooltip trigger an accessible name (#49345)
Closes FE-4093

## Problem

The shared `InfoTooltip` trigger's only child is an SVG and it has no
accessible name, so a screen reader announces an unnamed button and the
information the tooltip carries is unreachable. `button-name`, critical.

`/pricing` renders 34 of them.

## Solution

* Add an optional `label` prop rendered as `sr-only` text, with a
generic fallback so the 22 call sites that pass nothing still get a
name. The prop is optional because 26 files import this component across
www, Studio, design-system and ui-patterns.
* Drop the redundant `role="button"` from a native button.
* Label the four www call sites. A shared fallback alone would leave
`/pricing` announcing 34 identical names, which passes axe and stays
unusable. The labels come from the feature title and plan already in
scope, so no pricing data changes.

Docs is unaffected. It has its own `InfoTooltip` at
`apps/docs/features/ui/InfoTooltip.tsx` and never imports the shared
one.

## Manual testing

1. Open
[/pricing](https://zone-www-dot-com-git-ui-patterns-infotooltip-ac-07e2ab-supabase.vercel.app/pricing)
using a Screenreader.
2. Tab through the comparison table. Each info tooltip announces its own
feature, for example "About Database size".
3. Tab to a plan-specific tooltip. It announces the feature and the
plan, for example "About Automatic backups on the pro plan".
4. Confirm the icons render unchanged and the tooltips still open on
hover and on focus.
5. Run axe on the page. `button-name` reports zero elements.
6. Open the [design system InfoTooltip
page](https://design-system-git-ui-patterns-infotooltip-acces-66ec02-supabase.vercel.app/design-system/docs/fragments/info-tooltip)
and confirm the demo still renders.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Accessibility Improvements**
  * Added descriptive labels to pricing information tooltips.
* Improved screen reader context for compute estimates, features, and
plan-specific pricing.
  * Added a default “More information” label for unlabeled tooltips.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 09:14:12 -07:00
claude[bot]andClaude 235488e66b fix(studio): guard two undefined dereferences crashing the table editor and SQL editor (#49412)
<!-- ccr-slack-attribution -->
_Requested by **Ali Waseem** · [Slack
thread](https://supabase.slack.com/archives/C063LNYJJKS/p1787336596649619)_

**Before:** editing a cell in the table editor could throw, and the edit
was silently lost — the typed value vanished and nothing was saved.
Separately, opening the SQL editor could throw before the editor
rendered, and the global error boundary replaced the entire page, so
there was no editor at all until a reload.

**After:** a row change with no matching previous row is a no-op instead
of a throw, and the SQL editor shows its normal loading state instead of
taking down the page.

Two independent undefined guards for two confirmed Sentry crashes, one
per commit so either can be dropped on its own.

**How:** the first commit moves the existing previousRow guard in
`useOnRowsChange` above the `changedColumn` computation that
dereferences it, and drops the non-null assertion that hid the problem
from TypeScript. The second reads the snippet content in
`deriveSnippetIdentity` through optional chaining, so a missing
`snippets` map, or an entry without a `snippet`, resolves to
still-loading — the same answer the old code gave for an id that is not
in the map. Behaviour is unchanged in every case that did not crash.

## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Bug fix.

## What is the current behavior?

**[K7M, Cannot read properties of undefined (reading
'idx')](https://supabase.sentry.io/issues/7681899596/)** — 4 events / 1
user — in `apps/studio/components/grid/components/grid/Grid.utils.tsx`.
Inside `useOnRowsChange`, the callback passed to
`Object.keys(rowData).find(...)` reads the candidate column off
`previousRow` through a non-null assertion, three lines above the `if
(!previousRow || !changedColumn) return` that was meant to protect it.
`rows.find(...)` returns undefined whenever no row matches, and the
assertion is why TypeScript never flagged the dereference. The four
events came from one user inside about two minutes, so it is
deterministic rather than a one-off, and every throw is an edit the user
loses.

**[K7J, Cannot use 'in' operator to search for a snippet uuid in
undefined](https://supabase.sentry.io/issues/7680905437/)** — 1 event /
1 user, full-page crash — in
`apps/studio/components/interfaces/SQLEditor/SQLEditor.utils.ts`, line
331. `deriveSnippetIdentity` applies the `in` operator to its `snippets`
argument and then reads `snippets[id].snippet.content`. The parameter is
declared required and non-optional, but `snippets` arrived undefined at
runtime, so `in` threw and the error reached the global error boundary,
which unmounted the whole SQL editor page. The `snippets[id].snippet`
read on the same line is a second unguarded dereference: an entry
without a `snippet` crashes identically.

## What is the new behavior?

Both crashes become no-ops.

- Grid: return early when `previousRow` is missing, then compute
`changedColumn`, with the assertion removed. When a previous row is
found, the code takes exactly the path it took before.
- SQL editor: `snippets?.[id]?.snippet?.content === undefined` replaces
the `in` check. A missing map, a missing entry, and an entry with no
`snippet` all read as still loading, which is what the surrounding code
already does while a snippet is being fetched. The parameter type is
left required, since the only caller (`useSnippetIdentity.ts`) passes
the store's `snippets` record, which is typed as always present — the
type is not the thing that was wrong.

Two test cases are added to the existing `deriveSnippetIdentity` block,
which previously only passed fully populated maps: one for an undefined
`snippets` map, and one for an entry missing its `snippet`.

## Additional context

**Why `snippets` was undefined is unexplained.** The store initialises
it to an empty object
(`apps/studio/state/sql-editor/sql-editor-state.ts:34`) and its only
reassignment writes an object, so there is no code path in studio that
sets it to undefined. This commit is a defensive guard against a crash,
not a root-cause fix, and nothing here should be read as an explanation.

**Verification:** no local checks were possible in the authoring
environment — the checkout has no `node_modules` and `pnpm install`
cannot complete there, so typecheck, lint and the studio unit tests
could not be run. CI on this PR is the only verification.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-24 10:11:44 -06:00
1cffe632e3 fix: webhook apikey (#47317)
## TL;DR
Database webhooks/Cron jobs now add `apikey: <secret-key>` for edge
function auth..

## ref:
- related to: https://github.com/supabase/supabase/pull/46890
- towards COM-269

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## New Features
* Improved edge function webhook authentication by automatically
selecting the appropriate API key or authorization header format.
* Authorization headers are now added or normalized when required, while
preserving existing custom headers and supported credentials.

## Improvements
* Simplified “Add header” and “Add parameter” controls with clearer
labels.
* Updated authentication actions to clearly describe the selected header
type.

## Tests
* Expanded coverage for key formats, authorization behavior, header
preservation, and revised control labels.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Tomás Pozo <tomaspozo@users.noreply.github.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-08-24 10:06:36 -06:00
ChloeGarciaMillerand 8dcebc08ca fix: ESLint errors relating to accessibility in account preferences (#49301)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Improve toggle accessibility and `aria-label` for screen readers.

## What is the current behavior?

Toggles have no accessible name or description because FormItemLayout is
not properly linked to the Switch.
An `aria-label` was missing.

## What is the new behavior?

An `aria-label` and IDs have been added to associate the label with the
switch and make the toggles accessible to screen readers.

## Additional context

No visual changes have been made.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Accessibility**
  * Improved screen reader labels for password visibility controls.
  * Linked preference labels with their corresponding toggle controls.
* Added descriptive identifiers to telemetry, dashboard, and hotkey
settings for easier navigation.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 18:05:45 +02:00
claude[bot]andClaude 66bfb8a22d chore(docs): add Tomás Torgal to humans.txt (#49483)
<!-- ccr-slack-attribution -->
_Requested by **Ivan Vasilov** · [Slack
thread](https://supabase.slack.com/archives/C0161K73J1J/p1787582317369359?thread_ts=1787582317.369359&cid=C0161K73J1J)_

## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Docs update — adds a new joiner to `apps/docs/public/humans.txt`.

## What is the current behavior?

Tomás Torgal is not listed in humans.txt.

## What is the new behavior?

Tomás Torgal joined as Account Executive EMEA and asked to be added to
humans.txt. Added in alphabetical order, between `Tomás Pozo` and `Tyler
Hillery`.

## Additional context

Part of the onboarding process. Name-only entry, matching the file's
existing convention.

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-24 16:52:26 +02:00
Cemal Kılıç dbeb67e4b7 feat: add learn more link for enterprise mcp auth (#49475)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

add "Learn more" link for enterprise mcp auth


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Added a link to enterprise MCP authentication guidance in the advanced
SSO settings.
* Clarified the field label and description by updating “IDJAG” to
“ID-JAG” terminology.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 16:29:14 +02:00
Esteban SuárezandAli Waseem adffb26613 docs: add fx as a supported MCP client (#49446)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Docs update: adds [fx](https://fx.sh) to the MCP client list, following
the same pattern as the recently added Warp (#48838), GitHub Copilot CLI
(#46150) and OpenCode (#41825) clients.

fx is a native coding agent and an MCP client. It supports Streamable
HTTP and the full OAuth flow (metadata discovery, PKCE, Dynamic Client
Registration fallback, refresh), so it connects to the hosted Supabase
MCP server without a proxy.

## What is the current behavior?

fx is not in the client list, so users have to hand-write the config. fx
keys servers under `mcp` rather than `mcpServers` and names the
transport `http`, which is easy to get wrong by adapting another
client's snippet.

## What is the new behavior?

fx appears in the **AI Agent CLI** group, in both the docs page and the
dashboard's Connect panel. It renders as:

> **fx**
>
> Add this configuration to `~/.fx/mcp.json`:
>
> ```json
> {
>   "mcp": {
>     "supabase": {
>       "type": "http",
>       "url": "https://mcp.supabase.com/mcp"
>     }
>   }
> }
> ```
>
> fx reads MCP servers only from this profile, so a file inside a
repository cannot add one. If a session is already open, apply the
change with `/mcp reload`.
>
> Then authenticate from the fx shell. This opens your browser to
complete the OAuth flow:
>
> ```bash
> /mcp auth supabase --open
> ```
>
> Confirm the server is connected with `/mcp list`.
>
> For more details, see [MCP
configuration](https://fx.sh/docs/capabilities/mcp) in fx.

fx is configured by file only, so it gets an `alternate` instruction
block and no `install` command, matching Cursor, VS Code, Warp and
Antigravity.

## Additional context

The config above was verified end to end against the hosted server: the
OAuth flow completes and `/mcp list` reports the server connected.

Two notes on the diff:

- **`types.ts`** gains an `FxMcpConfig` interface, a type guard and a
branch in `getMcpUrl`. fx's shape is not covered by any existing
interface (`OpenCodeMcpConfig` is the other `mcp`-rooted one, but
carries `$schema` and `type: 'remote'`). Since `getMcpUrl` throws on an
unrecognized shape and runs for every client with instructions, the
guard is required rather than cosmetic. Antigravity (#43597) and
OpenCode (#41825) added their shapes the same way.
- **Tests.** `utils/getMcpIconSrc.test.ts` gains a case for the new dark
icon variant, alongside the existing cursor and perplexity cases.
`types.test.ts` is new and checks that every client's `transformConfig`
output round-trips back through `getMcpUrl`, which is what guards the
throw above. Happy to drop either if you'd rather keep the diff to the
usual shape for a client addition.

Prettier passes with the repo config, `tsc --noEmit` is clean, and both
test files pass.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
  * Added fx as a supported MCP client in the MCP URL builder.
* Added profile-based setup guidance, OAuth authentication instructions,
connection verification, and documentation links.
  * Added light and dark fx icons for improved visual support.
* **Bug Fixes**
  * Improved MCP URL detection for fx configurations.
* **Tests**
  * Added coverage for MCP URL extraction and dark-mode icon selection.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-08-24 08:22:12 -06:00