Commit Graph
38106 Commits
Author SHA1 Message Date
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
Arshdeep Singh 166cab8dee docs: fix api link path in pg_net.mdx (#49478)
## 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?

fix: Updates the Data API link in current permission section

## What is the current behavior?

The link currently points to the wrong path, resulting in a 404 error.

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

## Summary by CodeRabbit

* **Documentation**
* Updated the Data API permissions documentation link to point to the
current API guide.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 18:21:14 +05:30
Steven Eubank 665f043ecb fix(docs)link-ch-sql-syntax (#49473)
semi related to this PR: https://github.com/supabase/changelog/pull/234

Trying to ensure the information architecture links someone reading the
debugging docs to the correct info on SQL syntax required by CH. This is
a simple QOL change vs doing a larger IA fix

## 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

## What is the current behavior?

Does not direct users to CH sql syntax doc

## What is the new behavior?

Directs users to CH sql syntax doc

## Additional context


https://supabase.com/changelog/48235-migration-of-supabase-management-api-logs-all-analytics-endpoint-to-logs-endpoint


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

## Summary by CodeRabbit

* **Documentation**
* Updated the MCP server description to link to Logs Explorer
documentation for the supported ClickHouse SQL syntax used when querying
logs.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 14:37:15 +02:00
Arshdeep SinghandJeremias Menichelli e478aabb80 Clarify pg_net net schema grants (#49472)
## 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?

Documentation update — adds a new "Permissions" section to the pg_net
guide.

## What is the current behavior?

The pg_net docs don't explain the default permission model for the net
schema. Customers running security reviews flag that net schema objects
(net.http_request_queue, net._http_response) are readable by
anon/authenticated via inherited PUBLIC grants, and some have run their
own REVOKE scripts to lock this down. This breaks the pg_net background
worker, since postgres (the role the worker runs as) inherits its own
access through that same PUBLIC grant.

## What is the new behavior?

Adds a "Permissions" section clarifying that the default grants are safe
as-is, net isn't exposed through the Data API, and anon/authenticated
are NOLOGIN roles with no direct database connection.

## Additional context

For background and reviewer discussion on the accuracy of this, see the
https://supabase.slack.com/archives/C02FHG9QQAF/p1787299415288589.

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

## Summary by CodeRabbit

* **Documentation**
  * Added permissions guidance for the `net` schema.
  * Clarified access available to `anon` and `authenticated` roles.
* Explained why these permissions do not expose request data through the
Data API or direct database connections.

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

---------

Co-authored-by: Jeremias Menichelli <jmenichelli@gmail.com>
2026-08-24 17:29:48 +05:30
Victor Farazdagi 3bc52101ee (docs/pipelines): early access destinations (#49304)
## What kind of change does this PR introduce?

Docs update


## Summary

- Add Early Access setup and reference guides for ClickHouse, DuckLake,
and Snowflake.
- Update Pipelines navigation and shared documentation with
destination-specific data models, source requirements, schema-change
support, and recovery behavior.
- Keep all three destinations organization-gated. DuckLake is documented
only as a Pipelines replication destination i.e. query compute remains
external and this is not a Warehouse launch.

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

* **New Features**
* Added ClickHouse, DuckLake, and Snowflake as Early Access Pipelines
destinations.
  * Added BigQuery as a managed destination.
* Added destination navigation and setup guides covering configuration,
replication behavior, schema changes, type mappings, troubleshooting,
and monitoring.

* **Documentation**
* Clarified destination availability, regional guidance, requirements,
limitations, and processing behavior.
* Documented destination-specific schema-change support, table identity
requirements, reset behavior, and CDC replication modes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 14:44:54 +03:00
Katerina Skroumpelou 30835c6f5a docs: remove deprecated processLock from react-native auth quickstart (#49471)
Removes `lock: processLock` from the React Native auth quickstart. Since
supabase-js 2.107.0 the client coordinates session refreshes without a
lock (single-flight dedupe within the client, with concurrent refresh
races resolved server-side), so the option is no longer needed; it is
deprecated and will be removed in v3, and upcoming 2.x releases log a
one-time deprecation warning when it is passed. The quickstart installs
`@supabase/supabase-js@^2`, so anyone following it gets the lockless
behavior out of the box.

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

## Summary by CodeRabbit

* **Bug Fixes**
* Updated the React Native authentication quickstart to initialize the
client without the removed locking configuration, improving
compatibility with current authentication setup.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 13:36:05 +03:00
claude[bot] c32db2b80b fix(studio): track resourceAccess='account' for legacy access tokens (#49448) 2026-08-24 16:44:23 +08:00
Ayaan Gazali 18896e33de fix(studio): give two DropdownMenuTriggers asChild so they stop nesting buttons (#49264)
## 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. Two `DropdownMenuTrigger`s wrap a `Button` without `asChild`,
so each renders a `<button>` inside a `<button>`. One of them also loses
its `aria-label`, leaving an icon-only menu trigger with no accessible
name.

## What is the current behavior?

`DropdownMenuTrigger` forwards to `DropdownMenuPrimitive.Trigger`, which
renders its own `<button>` unless `asChild` is set. So this:

```tsx
<DropdownMenuTrigger>
  <Button variant="default" className="px-1" icon={<MoreVertical />}
          aria-label={`Open actions for ${hook.title}`} />
</DropdownMenuTrigger>
```

produces `<button><button/></button>`, which is invalid HTML, and puts
the props on the inner element rather than on the thing that actually
opens the menu.

Measured by rendering `HookCard` before and after, rather than reasoning
about it:

| | before | after |
| --- | --- | --- |
| `container.querySelectorAll('button button').length` | 1 | 0 |
| `aria-label` on `[aria-haspopup="menu"]` | `null` | `Open actions for
Send Email` |

That second row is the part worth caring about. The `aria-label` was
written deliberately for a button whose only content is a `MoreVertical`
icon, and it lands on the nested inner button instead of the trigger, so
a screen reader gets no name for the control it actually operates.

Two sites:

- `components/interfaces/Auth/Hooks/HookCard.tsx`, the per-hook actions
menu. This is the one with the orphaned `aria-label`.
- `components/layouts/ProjectLayout/PauseFailedState.tsx`, the overflow
menu next to "Download backup".

## What is the new behavior?

Both get `asChild`, so the `Button` becomes the trigger. No nesting, and
the props land where they were meant to.

## Additional context

#48948 fixed exactly this in `RestoreFailedState.tsx`, which sits in the
same directory as `PauseFailedState.tsx` and has the same overflow-menu
shape. This is that fix applied to the two places it was not.

I swept all 4398 `.tsx` files across studio, www, docs, design-system,
ui-library, `packages/ui` and `packages/ui-patterns` for any Radix-style
trigger (`DropdownMenu`, `Tooltip`, `Popover`, `Dialog`, `Sheet`,
`AlertDialog`, `HoverCard`, `Collapsible`, `ContextMenu`, `Menubar`,
`Select`, `Tabs`, `Accordion`) that wraps a button-like element without
`asChild`. After discarding one false positive in
`EdgeFunctionDetails.tsx`, where the `Button` is a sibling of
`TabsTrigger` inside `TabsList` rather than its child, these two are the
only ones left. So this should be the end of the pattern rather than the
start of a series.

No test added, matching what #48948 did for the same change. The
`asChild` behaviour belongs to Radix, and a test asserting DOM nesting
around two JSX attributes would be testing the library. I did verify it
the other way round while developing: a throwaway render assertion
failed on unmodified master with a nested-button count of 1 and a null
trigger `aria-label`, and passed after the change. Happy to commit that
assertion if you would rather have it in the suite.

Gates: `test:prettier` passes repo wide, `typecheck --filter=studio
--force` passes 9/9, `--filter studio run lint:ratchet` reports rules
improved, and the tests covering both touched directories pass (18
files, 143 tests, including the `RestoringState` suite that came in with
#48948).

Freshman contributor. Found this with Claude Code's help by checking
whether the `asChild` fix in #48948 had siblings, and I confirmed the
nesting and the missing accessible name myself before touching anything.


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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved dropdown menu trigger behavior in the authentication hooks
and project layout interfaces.
* Existing buttons now correctly serve as menu triggers without changing
available actions or menu behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 10:43:56 +02:00
Cemal Kılıç f857be2063 feat: enable idjag for all (#49462)
## 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?

remove feature flag gate for enterprise mcp auth



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

## Summary by CodeRabbit

* **New Features**
  * Advanced SSO settings are now available for all SSO configurations.
* **Changes**
* Removed organization-specific eligibility restrictions for advanced
SSO settings.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 10:35:39 +02:00
Saxon FletcherandJoshen Lim de2a7d8d9e Add view options to Query (#49447)
Currently Query tabs in explorer do not support view options e.g. table
vs chart. This adds display state to query tabs to match the behaviour
of Notebooks

## To test
- create a query in explorer
- Run a query
- Set the display options via toolbar

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

* **New Features**
  * Query results can now be displayed as either a table or chart.
* Chart settings are saved with each query draft and restored when
reopened.
* Display preferences are maintained independently across query drafts.
  * Editing a preview query now converts it into a permanent tab.
* **Bug Fixes**
* Invalid or legacy display settings safely fall back to the table view
without removing saved drafts.
* Charts and empty states now use the available editor space more
effectively.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-08-24 16:19:17 +08:00
Alaister YoungandAlaister Young caceeb429f [MUL-1336] fix(studio): show HA project costs as free during Alpha (#49383)
HA (Multigres) projects are free during Alpha, but the project creation
form still presented the forced large compute as a real charge. The
footer now shows **$0/m** for HA projects, with the usual compute price
struck through + a "Free during Alpha" note in the cost-breakdown
tooltip and the compute size dropdown. Follows the pattern from #49249.

Addresses
[MUL-1336](https://linear.app/supabase/issue/MUL-1336/bug-when-creating-new-projects).

<img width="688" height="167" alt="Screenshot 2026-08-21 at 5 27 39 PM"
src="https://github.com/user-attachments/assets/804b9243-77ae-4961-9083-5e1290734d3a"
/>
<img width="503" height="202" alt="Screenshot 2026-08-21 at 5 27 32 PM"
src="https://github.com/user-attachments/assets/f217edd4-2204-4e5e-87f8-f54974e3c6fa"
/>

**Changed:**
- `ProjectCreationFooter`: "Additional costs" shows `$0/m` when HA is
on; the tooltip gains a "High availability projects are free during
Alpha for up to 2 projects." sentence; the New-project row's price
renders struck through with a "Free during Alpha" sub-line; the HA
project's compute is excluded from "Total Monthly Compute Costs"
(clamped at 0 so credits can't produce a negative total — a no-op for
non-HA since spend already floors above zero)
- `ComputeSizeSelector`: the per-option `$X/hour (~$Y/month)` line
renders struck through with "Free during Alpha" beneath it when HA is on
(both tagged `data-field="instance-details"` so the collapsed trigger
keeps hiding them)
- `ProjectCreationForm`: threads the watched `highAvailability` value
into the footer

The "Confirm compute costs" modal was already suppressed for HA by the
existing `!values.highAvailability` guard — no change needed there.

## To test

- On a paid org, open New Project and toggle High Availability on: the
footer should read `$0/m` (brand green, no strikethrough), its ⓘ tooltip
should show the HA sentence and the New row's `$110` struck through with
"Free during Alpha", and the Total should exclude the $110; the compute
dropdown's Large option should show its price struck through with "Free
during Alpha"
- Toggle HA off (and on/off a few times): all cost displays should
revert exactly to normal — green real price, no strikethrough, no "Free
during Alpha" anywhere outside the HA toggle's own description
- With HA off and compute size Medium, submit: the "Confirm compute
costs" modal should still appear as before (Cancel works)
- Collapsed compute-size trigger should never show a price line or "Free
during Alpha" in either state

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

## New Features

- High-availability project options now show compute pricing as free
during Alpha.
- Standard compute prices are displayed with a strikethrough alongside
the Alpha-free notice.
- Project cost summaries accurately show no additional compute charge
for high-availability selections.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-08-24 16:10:14 +08:00
Alaister YoungandAlaister Young b9df7aaf9e [FE-3711] feat(studio): make compute config read-only for HA projects (#49359)
Makes the compute-size configuration on Settings → Infrastructure
read-only for High Availability (Multigres) projects during Alpha — HA
projects run on a single fixed compute size and resizing isn't supported
yet (previously attempting one could leave a project stuck Resizing).

Gated on `project.high_availability` via the existing
`useHighAvailability()` hook — the same signal every other HA gate in
Studio uses.

**Changed:**
- Compute size options other than the project's current size render with
the existing locked treatment (greyed out, lock icon, tooltip) for HA
projects, and the whole radio group is disabled
- A `HighAvailabilityDisabledSectionNotice` in the Compute section
explains that HA projects run on a fixed compute size during Alpha
- The compute branch of `onSubmit` and the read-replica
compute-recommendation handoff are skipped for HA projects, so a compute
change can never reach `POST /billing/addons`
- The "Contact Us" larger-sizes card is hidden for HA projects
- Form initialization now also fires once the project loads for HA
projects (disk-attribute queries never run on their cloud provider, so
the existing reset effect never fired and the picker showed the
`ci_micro` fallback as selected)

**Added:**
- Two MSW page tests in the Infrastructure suite covering the HA
read-only state and the unchanged editable state for non-HA projects

## To test

- On an HA (Multigres) project: Settings → Infrastructure should show a
notice under Compute size, the project's current size selected, every
other size locked with a tooltip, no "Contact Us" card, and clicking any
option should never surface the "Review changes" bar
- On a regular project: compute selection, "Review changes" → "Confirm
changes", and the Contact Us card all behave as before
- `pnpm vitest run
"tests/pages/project/[ref]/settings/infrastructure.test.tsx"`

Addresses
[FE-3711](https://linear.app/supabase/issue/FE-3711/make-compute-configuration-read-only-for-mvp)

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

## Summary by CodeRabbit

* **New Features**
* Added High Availability notices and guidance to the Compute settings.
* High Availability projects now show compute sizes as read-only, with
explanations for unavailable options.
* Hid the larger-instance contact option for High Availability projects.

* **Bug Fixes**
* Prevented unsupported compute resizing and add-on changes for High
Availability projects.
  * Preserved compute resizing and review actions for standard projects.

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

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-08-24 16:09:43 +08:00
CharisandJoshen Lim 48cc37f0d2 refactor(studio): extract notebook cache eviction helper (#49414)
## Summary

Part 1 of the FE-4247 stack
([FE-4247](https://linear.app/supabase/issue/FE-4247/assistant-invalidate-cache-after-notebook-editdeletion)).
Pure refactor, no behavior change — extracts the notebook cache eviction
logic that `ExplorerNotebookTabCoordinator` had open-coded into a shared
helper, so the upcoming assistant create/update/delete cache
invalidation (PR 2/3 in the stack) can reuse it instead of duplicating
the two-cache-layer eviction dance.

- New `evictNotebookFromCaches({ queryClient, projectRef, id, mode })`
in `apps/studio/data/content/notebooks/notebook-cache.ts`. `mode:
'refresh' | 'remove'` selects `invalidateQueries` vs `removeQueries` on
`contentKeys.resource`. Drops the notebook from `notebooksState` only
when its status is `'saved'`, matching the original open-coded guard
exactly. Returns whether it evicted, so callers can branch.
- `ExplorerNotebookTabCoordinator` now calls the helper with `mode:
'remove'` instead of inlining the logic.

## Test plan

- [x] `pnpm test:studio -- notebook-cache
ExplorerNotebookTabCoordinator` — new helper tests
(refresh/remove/dirty-guard/unknown-id) and existing coordinator tests
all pass
- [x] `pnpm typecheck --filter=studio`
- [x] `pnpm lint --filter=studio` — 0 errors, no new warnings

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

- **Bug Fixes**
- Improved detection of unsaved notebook changes for tab indicators and
close confirmations.
- Empty, never-saved notebooks are no longer included in discard
prompts.
- Improved cache cleanup when closing saved notebooks while preserving
unsaved work.
  - Added safeguards for missing notebook records.
- **Tests**
- Added coverage for notebook cache refresh, removal, preservation, and
no-op scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-08-24 15:59:41 +08:00
Danny White fdf33e72c4 fix(studio): clean up onboarding returnTo paths (#49283)
## What kind of change does this PR introduce?

Bug fix. Follow-up to #41041 and DEPR-318.

## What is the current behavior?

Marketing "Start your project" links go to `/dashboard`, which redirects
unauthenticated users to `/org` and sets `returnTo=/org`. That value
survives when they switch from sign-in to sign-up, so email verification
still lands on the org list instead of org creation.

## What is the new behavior?

- Sign-in's **Sign up** link rewrites `returnTo=/org` (and
`/organizations`) to `/new`
- Docs mobile menu, www homepage/product CTAs, and solution page CTAs
link to `/dashboard/sign-up` for guests
- Signed-in visitors get the dashboard URL instead, so they never hit
the sign-up form
- Shared `DASHBOARD_SIGN_UP_URL` / `getDashboardCtaHref` helpers for www

Stacked on #41041.

## To test

Stacked on #41041. The studio preview below includes both PRs. www and
docs have their own previews.

### Studio: sign-in → sign-up rewrite

Using the [studio-staging
preview](https://studio-staging-git-dnywh-fixonboarding-return-to-supabase.vercel.app/)
from Vercel checks:

1. Open the preview while logged out. It should land on
`/dashboard/sign-in?returnTo=%2Forg`
2. Click **Sign up**. Expect the URL to include `returnTo=%2Fnew`

### Optional: www CTAs

Using the [www
preview](https://zone-www-dot-com-git-dnywh-fixonboarding-return-to-supabase.vercel.app/):

3. Logged out: homepage, product, or solutions **Start your project**
should go to `/dashboard/sign-up`
4. Logged in: the same CTAs should go to `/dashboard` (not sign-up)
(thought this will be hard if not impossible to test on staging)

### Optional: docs CTAs

Using the [docs
preview](https://docs-git-dnywh-fixonboarding-return-to-supabase.vercel.app/):

5. On mobile nav while logged out, click **Start your project**. Expect
`/dashboard/sign-up`

### Compare on supabase.green

Optional. Just to show what happens currently on `master`:

6. Open **supabase.green** while logged out, then click **Sign up** from
`/dashboard/sign-in?returnTo=%2Forg`. `returnTo` should stay as `/org`

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

## Summary by CodeRabbit

* **New Features**
* Start-project and sign-up links now direct visitors to registration
while signed-in users continue to reach the dashboard.
* Homepage, product, solution, and mobile navigation CTAs now provide
consistent authentication-aware destinations.
* Sign-up links preserve return destinations and existing navigation
parameters.

* **Bug Fixes**
* Corrected mobile navigation and marketing CTA links that previously
sent visitors to the dashboard root instead of the appropriate sign-up
flow.


<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 17:32:56 +10:00
Danny White ee931e49a1 fix(studio): send new signups to org creation directly (#41041)
## What kind of change does this PR introduce?

Bug fix. Resolves DEPR-318.

## What is the current behavior?

New users who confirm their email land on `/sign-in`, then
`/organizations`, then get bounced to `/new` via a `useEffect`.
Cancelling org creation with zero orgs sends them back to
`/organizations`, which immediately redirects into `/new` again.

## What is the new behavior?

- Signup email verification redirects to `/new` directly
- `/organizations` with zero orgs shows the existing empty state instead
of force-redirecting

## To test

### One-time setup

Assuming you don’t already have a staging account with **zero** orgs:

1. On **supabase.green**, sign up with a fresh email and confirm it
2. Stop at org creation. Do **not** create an org

### On this PR

Using the [studio-staging
preview](https://studio-staging-git-dnywh-fixremove-org-redirect-supabase.vercel.app/)
from Vercel checks:

4. Sign in on the preview with that account
5. Open `/dashboard/organizations`. Expect the **Create an
organization** empty state, with no redirect to `/new`
6. Open `/dashboard/new`, click **Cancel**. Expect to land on
`/organizations` and stay there

### Compare on supabase.green

Optional. Just to show what happens currently on `master`:

7. Repeat steps 3–5 on **supabase.green**. `/organizations` should
bounce to `/new`, and **Cancel** should send you back into org creation

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

* **Bug Fixes**
* Improved signup redirects by preserving valid destinations and
relevant query parameters.
* Added safer fallback behavior for missing, invalid, or unsupported
destinations.
  * Improved handling of signup redirects provided in multiple formats.
* Prevented automatic redirection from the organizations page when no
organizations exist.

* **Style**
  * Updated the organizations page title capitalization for consistency.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 17:23:25 +10:00
Pamela Chia 21a27eeb4f feat(www): canonicalize homepage markdown at /index.md (#49384)
The www root markdown lived at an accidental URL: `/.md` served the
homepage markdown only because middleware strips the `.md` suffix and
the empty slug fell through to the homepage allowlist entry, while the
canonical-looking `/index.md` 404'd. The served markdown also opened
with stale legacy positioning copy that no longer matches the site. I
renamed the homepage content slug to `index` end-to-end so `/index.md`
is the one canonical markdown URL.

**Changed:**
- **`/index.md` serves the homepage markdown (200 `text/markdown`)**:
`content/md/homepage.md` renamed to `index.md`; the middleware bare-root
slug mapping, the generator's sort special-case, and the homepage
alternate tag follow, so the tag now advertises `/index.md`.
- **Legacy aliases 308 to the canonical URL**: `/.md`, `/homepage.md`,
and bare `/index` redirect via `lib/redirects.js`; `/llms/homepage.txt`
retargeted straight to `/index.md` to avoid a redirect chain. New
`next.config.test.ts` assertions pin all four.
- **Positioning refreshed**: the markdown now opens with "Supabase is
the Postgres development platform" (matching the site title), replacing
the outdated tagline.
- **Generator safety**: the redirect-exclusion filter in
`generateMdContent.mjs` now exempts the `index` slug (its HTML page is
`/`, not `/index`, so a `/index` redirect never refers to it), and the
build fails if `content/md/index.md` ever goes missing while middleware
still maps `/` to the `index` slug.
- **CI actually runs the new assertions**: I widened the `www-tests.yml`
paths filter to include `apps/www/lib/**/*.js`,
`apps/www/content/md/**`, and `apps/www/scripts/**/*.mjs`. It previously
only matched `.ts*` and the next.config files, so a PR touching only
`lib/redirects.js`, the markdown content, or the generator would skip
the tests that pin these redirects.

**Note:** the existing homepage alternate tag still exists, re-pointed
to the canonical URL. Whether the homepage should advertise a markdown
sibling at all is a separate decision; leaving it aimed at a 308 would
break tag consumers. Positioning wording is editorial, happy to tweak.

## To test
Tested on Vercel preview:
- [x] `curl -si <preview>/index.md`: expect 200 `content-type:
text/markdown`, body opens with the Postgres development platform
positioning and no longer contains the old tagline
- [x] `curl -sI <preview>/.md`: expect 308 with `location: /index.md`
- [x] `curl -sI <preview>/homepage.md` and `curl -sI
<preview>/llms/homepage.txt`: expect 308 with `location: /index.md`
- [x] `curl -sI <preview>/index`: expect 308 with `location: /`
- [x] `curl -s -H "Accept: text/markdown" -o /dev/null -w "%{http_code}
%{content_type}" <preview>/`: expect `200 text/markdown` (bare-URL
negotiation unchanged)
- [x] `curl -s <preview>/ | grep -o 'type="text/markdown"
href="[^"]*"'`: expect href ending `/index.md`

## Linear
- fixes GROWTH-1117



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

## Summary by CodeRabbit

- **New Features**
- Added support for `/index.md` as the canonical Markdown representation
of the homepage.
- Added permanent redirects for legacy homepage Markdown and text URLs.
  - Added `/index` to `/` redirect handling.

- **Bug Fixes**
- Updated homepage metadata, alternate links, Markdown negotiation, and
content generation to consistently use the new canonical path.
  - Improved homepage content description.

- **Tests**
- Expanded coverage for homepage Markdown routes, redirects, and URL
matching.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 15:19:56 +08:00
Joshen Lim 5c6ef8ae3d Joshenlim/fe 4221 explorer tab behaviours to mimic sql editor (#49386)
## Context

Improves the tab behaviour for explorer to follow the SQL Editor
- Tabs now start as preview tabs and become permanent once you start
interacting with them
 - Query Tabs become permanent as soon as you start typing in the editor
- Chat tabs become permanent as soon as you start typing in the chat
input
- Notebook tabs become permanenet as soon as you make any changes to the
notebook
- Notebooks with unsaved changes will show the orange dot indicator
<img width="197" height="67" alt="image"
src="https://github.com/user-attachments/assets/3005c379-a49a-4cd8-8d90-65406b186141"
/>
- Closing a notebook tab with unsaved changes will show a confirmation
dialog
  - Except if the new notebook has no content (no changes)
<img width="375" height="218" alt="image"
src="https://github.com/user-attachments/assets/6ad10779-6415-4c55-bb4f-61d938e744c9"
/>


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

* **New Features**
* Explorer chat, query, and notebook tabs now begin as previews and
become permanent when edited or saved.
* Added unsaved-change indicators and close confirmation for edited
notebook tabs.
  * Confirmed closure of edited notebooks now discards unsaved changes.
* **Bug Fixes**
  * Improved restoration and persistence of Explorer drafts.
  * Notebook saves now reflect the latest edits and tab state.
* Prevented stale save responses from incorrectly marking newer edits as
saved.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 14:35:22 +08:00
Joshen Lim 4dc973048d Add confirmation modal when running notebook if notebook contains query cells that aren't read only (#49376)
## Context

Adds a confirmation modal when hitting "run notebook" if the notebook
contains any query cells that involve any sort of mutation (insert,
update, alter, etc, etc). Also gives users the option to run the
notebook's read only cells as an alternative.

<img width="432" height="355" alt="image"
src="https://github.com/user-attachments/assets/0413a3ad-5419-4c83-8bf3-976bfa683b9a"
/>


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

* **New Features**
* Added confirmation prompts before running queries that may modify data
or database structure.
* Prompts identify potentially mutating notebook queries and allow
running read-only cells instead.
* Query execution now includes checks for destructive operations and
missing row-level security, with optional automatic setup.
* Notebook runs use the latest saved and unsaved SQL and reliably reset
execution status.

* **Bug Fixes**
* Improved notebook layout behavior so content shrinks correctly within
flexible sections.

* **Tests**
* Expanded coverage for mutation detection, comments, multiple
statements, live SQL, and cell filtering.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 14:15:56 +08:00
claude[bot] 8ec45b23dc chore(studio): remove dead unified logs banner telemetry and storage key (#49454) 2026-08-24 03:57:42 +00:00
Danny White 34454037d3 clean up docs admonition structure (#48669)
## What kind of change does this PR introduce?

Docs update. Resolves DEPR-634.

Stacked on #48664. The linter package and CI revision pins will be
updated after
[supa-mdx-lint#121](https://github.com/supabase-community/supa-mdx-lint/pull/121)
merges and is released.

## What is the current behavior?

Admonition body content can contain structural headings, which inherit
prose spacing and produce awkward callout layouts. Standalone Docs
actions are also rendered as ordinary body content in two places.

| Before |
| --- |
| <img width="1264" height="840" alt="70168"
src="https://github.com/user-attachments/assets/00aa7620-a6b4-452c-971f-b3ce2eda0e8c"
/> |
| _Recent violation with Markdown header in `children`. Notice the big
gap up top._ |

## What is the new behavior?

- Documents that admonition titles belong in the `title` prop,
standalone calls to action belong in `actions`, and document sections
belong outside admonitions.
- Configures heading-inside-admonition violations as errors for the
forthcoming linter release.
- Moves the UI-library and wrapper dashboard buttons into the existing
`actions` slot without changing the shared component.

Validated with the forthcoming linter across all 810 Docs sources, Docs
type-checking, targeted ESLint and Prettier checks, and desktop/mobile
rendering.


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

* **Documentation**
* Clarified admonition guidelines for optional titles, headings, rich
content, and standalone calls to action.
* Improved guidance on when contextual links and interactive examples
belong in admonition content.

* **Style**
* Updated documentation call-to-action buttons to use the designated
actions area.

* **Quality Improvements**
* Added validation to prevent headings inside admonitions and maintain
consistent formatting.
  * Updated documentation linting to apply the latest validation rules.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 00:26:03 +00:00
Joshen Lim a18253f7c7 QueryEditor to have the same validations as per SQL editor (#49380)
## Context

Adds the same validations such as UPDATE without where clause, or
destructive query into the QueryEditor of explorer / notebooks. Kicks in
for both notebook cells and query tab

<img width="887" height="718" alt="image"
src="https://github.com/user-attachments/assets/27757d41-e5df-4473-9278-ec30ff2306ca"
/>


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

- **New Features**
  - Added safety checks for potentially destructive database queries.
  - Queries may pause for confirmation before execution.
  - Added optional RLS statement handling during query execution.
  - Added warnings and cancellation support for pending query runs.
  - Added read-only mode to prevent SQL edits and proposal acceptance.

- **Bug Fixes**
  - SQL commits now use the current editor content.
  - Discarding a proposed query is handled directly and reliably.

- **Tests**
- Added coverage for query approval, cancellation, and RLS-enabled table
creation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-22 15:49:12 +08:00
Charis 233cbdc8e5 Restore notebook diff preview for completed updates (#49402)
## Summary

This is **PR 3 of 3** in the FE-4243 stack fixing "Notebook update
proposal shows 'unapplyable' error for already-completed updates."

- Consumes the `previous_content` field added by PR 2 (#49401) to
reconstruct diffs for already-applied notebook updates
- Restores the diff preview that PR 1 initially dropped — completed
updates now show the full before/after instead of a generic "Notebook
updated" message
- Uses the same diff derivation function called pre-approval,
guaranteeing the rendered diff matches what was shown during
confirmation
- Includes defensive fallback handling for older persisted chats (before
`previous_content` existed) and edge cases

**Depends on**: PR 2 (#49401) merging first — this PR consumes the
`previous_content` field from that server change.

Resolves FE-4243 

## Test plan

- ✅ 19/19 tests pass in NotebookProposalRenderer.test.tsx (2 confirmed
as real regressions)
- ✅ 118/118 tests pass in full AIAssistantPanel suite
- ✅ Typecheck: clean on modified files
- ✅ ESLint: zero errors/warnings on changed files  
- ✅ Lint ratchet: passes (some rules improved)
- ✅ New regression tests cover: delete_cell, insert_cell, missing
previous_content, and operations that no longer reconcile
- ✅ No notebook fetch in completed update tests (proves no redundant
re-fetching)

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

* **New Features**
* Added visual previews showing notebook changes, including inserted and
deleted cells, when prior content is available.
  * Prevented duplicate cells from appearing in update previews.
* Retained a compact completion message when change details are
unavailable or inconsistent.
  * Ensured previews are shown only for the relevant notebook.

* **Tests**
* Added coverage for notebook update previews, deletion and insertion
diffs, duplicate prevention, notebook matching, and fallback behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-21 15:09:44 -04:00
Charis 8920439569 Expose previous notebook content in update_notebook (#49401)
## Summary
- Plumb pre-update notebook snapshot through `update_notebook` tool
response as `previous_content`
- Add sanitizers in `tool-sanitizer.ts` to strip snapshot before model
sees it
- Add client-side stripping in `prepareMessagesForAPI` to avoid
re-uploading snapshot on subsequent turns
- This is PR 2 of 3 fixing Linear issue FE-4243 (notebook update
proposal shows 'unapplyable' error for already-completed updates)
- Ships no visible behavior change on its own; enables PR 3 to restore
diff preview for completed updates

## Test plan
- [x] Unit tests: 80/80 passing across notebook-tools.test.ts,
tool-sanitizer.test.ts, generate-assistant-response.utils.test.ts,
message-utils.test.ts, and mock-tools.test.ts
- [x] Typecheck: clean for all changed files
- [x] ESLint: zero errors, lint:ratchet passes (exit 0)
- [x] Integration: previous_content is correctly populated with
pre-update notebook, stripped before model context, and stripped on
client-side re-upload

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

- **Bug Fixes**
- Notebook updates now retain previous content for recovery and history.
- AI responses expose only the notebook’s ID and name, keeping previous
content out of model-visible data.

- **Tests**
- Added coverage for notebook update results, content sanitization, and
message preparation, including cases where previous content is absent or
preserved.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-21 14:58:32 -04:00
Daniel Guerra b2a216b617 feat(billing): Use the customer data endpoint to update billing emails (#49160)
## What kind of change does this PR introduce?

Change the update billing email component so it uses the update customer
endpoint instead of the update org endpoint. This allows users that have
the BILLING_WRITE permission to use the endpoint to update relevant
organization data, while keeping the restrictions of the update
organization endpoint that allow updating other values (e.g. the org
name).

This change requires an update in the Update Customer endpoint to
support billing email updates. Do not merge until that is deployed.

## What is the current behavior?

- Admins are not allowed to update the billing emails of an
organization.
- The update organization endpoint (`PATCH
/platform/organizations/{slug}/`) is used to update the billing email
details.

## What is the new behavior?

- Both admin and owners are allowed to update the billing email details.
- The update customer endpoint (`PUT
/platform/organizations/{slug}/customer`) is used to update the billing
email details.

### Additional Context

[Platform PR](https://github.com/supabase/platform/pull/37145), needs to
be deployed first.


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

* **New Features**
  * Billing email settings now use customer profile information.
* Added support for updating primary and additional billing email
addresses.
* Billing customer details now display address and billing name
information.

* **Bug Fixes**
* Prevented unrelated billing profile fields from being overwritten
during updates.
* Billing forms now synchronize correctly when customer profile data
changes.
* Removed unnecessary organization name requirements from billing
profile updates.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-21 10:56:20 -06:00
kemal.earth 0218de559b fix(studio): validation scroll area bug in scoped pat (#49395)
## 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?

When trying to submit the scoped pat creation form a second time, after
expanding accordion in the `<ScrollArea />` the `scrollTo` was breaking
the height of the container. This PR fixes that.


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

- **Bug Fixes**
- Improved the missing-permissions warning when creating scoped access
tokens.
- The warning now scrolls into view after each invalid submission
attempt, using smooth scrolling when supported.
- Prevented repeated scrolling during unrelated form updates or
motion-preference changes.
- Selecting a permission or applying a non-empty preset clears the
warning state.
  - Improved accessibility by respecting reduced-motion preferences.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-21 17:32:59 +01:00
Charis c172195269 test(studio): add eval cases for list_databases-driven notebook creation (#49398)
## Summary
- Adds three eval cases exercising the behavior this stack wires up: a
happy path where the model calls `list_databases` before targeting a
named read replica, a guard against fabricating an identifier when the
user names a region/replica `list_databases` doesn't actually return,
and a guard against targeting a non-primary database when the user never
asked for one.

Part 6/6 (final) of the stack for FE-4225 (expose valid database
identifiers to the notebook AI agent). Stacked on #49334.

## Test plan
- [x] Ran all three cases against the real model; inspected transcripts
directly
- [x] Re-verified reworded `correctAnswer` text against real outputs via
the correctness evaluator
- [x] `pnpm --filter studio exec tsc --noEmit` passes
- [x] `prettier --check` passes

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

## Summary by CodeRabbit

* **Tests**
* Added evaluation coverage for selecting the correct database replica
when creating notebooks.
  * Verified primary-database defaults when no database is specified.
* Added checks to prevent fabricated database identifiers when a
requested replica is unavailable.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-21 12:12:55 -04:00
Charis 27ff49c145 Stop re-deriving notebook update diffs after completion (#49399)
## Summary

- Fixes false-negative "This update can't be applied" warning for
completed notebook updates (FE-4243)
- When `state='output-available'` (tool completed), skips notebook fetch
and diff derivation
- Renders compact "Notebook updated: {name}" instead of a phantom/failed
diff
- `UnapplyableNotebookUpdateNotice` now accepts and forwards
`footerAction` prop, preserving "Open notebook" link
- Different warning copy for terminal confirm states
(success/error/denied): "Preview unavailable / notebook has changed"
instead of "can't be applied"
- Preserves diff derivation for non-completed states
(output-denied/error)

This is PR 1 of a 3-PR stack; PRs 2-3 restore the full diff preview for
completed updates (requires server snapshot).

Towards FE-4243

## Test plan

- [x] All 15 tests in NotebookProposalRenderer.test.tsx pass
- [x] Typecheck clean
- [x] ESLint clean
- [x] Regression tests added: completed updates with missing target
cells (auto & manual approval)
- [x] Confirms denied/error states still derive against live content

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

## Summary by CodeRabbit

- **New Features**
  - Added clearer status handling for AI-generated notebook updates.
- Completed updates now show a confirmation with the notebook name when
available.
- Update actions and footer controls now adapt to the proposal’s current
state.

- **Bug Fixes**
- Improved messaging when notebook changes prevent an update preview
from being reconstructed.
- Preserved accurate previews for denied or failed updates using the
notebook’s latest content.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-21 12:05:52 -04:00
Gildas Garcia c7e8373bce Scoped PAT: Fix projects handling when user has more than 100 projects (#49393)
## Problem

Some users have more than 100 projects and our current UI has the
following issues:

1. The project selector only loads the first 100 making it impossible to
see more
2. The review step and the token permissions view only loads the first
100 so we may display invalid warnings about missing projects

However, we currently don't have an API route to fetch many projects by
their refs in a single call.

## Solution

1. Make sure we load more projects when scrolling down in the project
selector
2. When below 100 project, show the admonition for missing resources.
Anyone above for the time being won't see these message and we display
the project refs instead of their names

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

- **New Features**
- Improved scoped access-token setup with paginated project loading and
an easier scrolling project selector.
- Organization and project access are now displayed as separate, clearer
access indicators.
- Access details show project information when available, with a
fallback reference when details cannot be loaded.

- **Bug Fixes**
- Updated resource warnings to better reflect deleted resources and
large project lists.
  - Improved multi-select list handling for more reliable interactions.
- Preserved the name of inaccessible organizations when displaying lost
access.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-21 18:01:28 +02:00
Charis dd534d229b docs(studio): instruct the notebook agent to use list_databases (#49334)
## Summary
- Adds a bullet to `NOTEBOOKS_PROMPT` instructing the assistant to call
`list_databases` before setting a `database_cell`'s
`database_identifier`, mirroring the existing `list_tables`
schema-validation instruction immediately above it.

Part 5/6 of the stack for FE-4225 (expose valid database identifiers to
the notebook AI agent). Stacked on #49333. This is the last piece that
makes the assistant actually *use* the tool and schema field wired up
earlier in the stack, rather than just having them available.

## Test plan
- [x] `pnpm --filter studio exec tsc --noEmit` passes
- [x] `prettier --check` passes

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved notebook database configuration by ensuring database
identifiers are selected from available databases.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-21 11:57:13 -04:00
Miranda LimonczenkoandClaude Opus 5 21fccb0ecd fix(www): name the /features page button controls (#49343)
Closes FE-4097


https://github.com/user-attachments/assets/bc7cad1a-763e-469f-8a3b-e4d23bed94d9

_See bottom left of screen for screen reader captions._

## Problem

Two controls in the shared `/features/[slug]` template have no
accessible name. Both live in the template, so both fire on all 79
feature pages.

* The feature list dropdown trigger contains only a `List` icon.
`button-name`, critical.
* The breadcrumb back chevron wraps only a `ChevronLeft`. `link-name`,
serious.

## Solution

* Name both with `sr-only` text, matching the sibling prev and next
controls in the same component and the theme switcher in the site
header.
* Label the product pill with its destination. It announced only
"vector", with no indication it filters the catalog. Not an axe finding,
since the product name already supplies a name. The label keeps the
visible word so it satisfies WCAG 2.5.3 Label in Name.
* Fix a stray `className="` inside the `iconClassName` string literal,
which dropped the icons' width class.
* Add `cursor-pointer` to `buttonClassName`. Tailwind 4 no longer sets a
pointer cursor on buttons, so the middle control behaved differently
from its two anchor siblings. This line belongs to FE-4227 and sits here
only to keep two open PRs off adjacent lines of the same file.

## Manual testing

1. Open
[/features/ai-integrations](https://zone-www-dot-com-git-www-features-chrome-access-1aef01-supabase.vercel.app/features/ai-integrations)
using a Screenreader.
2. Tab through the three round controls at top right. They announce
"Previous feature", "Browse all features", "Next feature". **Note:** The
order of the elements is strange; captured in a separate ticket.
3. Tab to the round back control at top left. It announces "Back to all
features".
4. Tab to the product pill beside it. It announces "All vector
features", and the visible word "vector" is unchanged.
5. Hover each of the three round controls. All show a pointer cursor.
6. Run axe on the page. `button-name` and `link-name` report zero
elements.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 08:48:04 -07:00
Miranda LimonczenkoandClaude Opus 5 61b2a18724 fix(docs): stop rendering empty troubleshooting error-code pills (#49344)
Closes DOCS-1281

## Problem

Two defects in the "Related error codes" list, both from the page
diverging from what `Troubleshooting.utils.ts` already does.

* **Empty pills.** `formatError` returns an empty string when an error
has neither an HTTP status code nor a code. The page renders the pill
anyway, giving a link with no text whose `href` ends in `errorCodes=`
with no value. So it is both an unnamed link and a pill filtering on
nothing.
* **Duplicate pills.** The same formatted code renders once per
underlying error object, so one entry shows seven identical "500
unexpected_failure" pills.

Measured on production, across the 59 entries that render the section:

| | Count |
| -- | -- |
| Entries with an empty pill | 23 |
| Empty pills | 33 |
| Entries with duplicate pills | 4 |
| Redundant pills | 9 |

The guard also evaluated to `0` rather than `false` for an empty array,
which React renders as a literal "0".

## Solution

* Derive the formatted codes once, drop the empties, and dedupe. An
entry whose every code formats empty no longer renders a heading and
rule with nothing under them.
* Call `formatError` once per code instead of twice per pill, and key on
the code now that codes are unique.
* Fix the same `0`-rendering guard on the keywords section.

`Troubleshooting.utils.ts` already filters on `error?.http_status_code
|| error?.code` at lines 69 and 150, and already dedupes by formatted
code at lines 72 to 79. This brings the page in line with the sidebar
and filter list rather than introducing a new pattern.

`formatError` itself is unchanged. It also produces grouping and sort
keys in `Troubleshooting.utils.ts` and `Troubleshooting.ui.tsx`, so
changing its return contract would reach well beyond this fix.

## Manual testing

Compare each page against production, which still shows both defects.

1. Open [dashboard-errors-when-managing-users on
production](https://supabase.com/docs/guides/troubleshooting/dashboard-errors-when-managing-users-N1ls4A).
It shows 8 pills: seven identical "500 unexpected_failure" and one
empty.
2. Open [the same page on the
preview](https://docs-git-docs-troubleshooting-empty-error-pills-supabase.vercel.app/docs/guides/troubleshooting/dashboard-errors-when-managing-users-N1ls4A).
One "500 unexpected_failure" pill remains.
3. Open [prisma-error-management on
production](https://supabase.com/docs/guides/troubleshooting/prisma-error-management-Cm5P_o).
It shows 6 empty pills.
4. Open [the same page on the
preview](https://docs-git-docs-troubleshooting-empty-error-pills-supabase.vercel.app/docs/guides/troubleshooting/prisma-error-management-Cm5P_o).
The section is gone, because every code on that entry formats empty.
5. Run axe on either preview page. `link-name` reports zero elements.


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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved troubleshooting displays by formatting and deduplicating
error values.
  * Removed empty or invalid error entries from the rendered results.
* Related error-code links now appear only when valid error codes are
available.

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

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 08:44:28 -07:00