616 Commits
Author SHA1 Message Date
Joshen Lim 94b8b06eb2 Clean up auto region selection experiment (#51121)
## Context

Just cleans up the experiment that was introduced
[here](https://github.com/supabase/supabase/issues/50851) - can clean up
feature flag in ConfigCat thereafter too

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

## Summary by CodeRabbit

* **Project Creation**
* Removed the “Best available” region option. Choose a specific region
or smart group when creating a project; the selected region name appears
in the selector.
  * Recommended badges remain visible on recommended regions.
* **Telemetry**
* Project creation events no longer include details about the removed
region option or the initial region recommendation.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-10-05 12:13:11 +08:00
Jeremias Menichelli 99103b3571 feat: Add edge function and hooks for search V2 (#51103) 2026-09-30 18:12:07 -03:00
Artur Zakirov bd9a0ff4e6 feat(orioledb): rename orioledb from Public Alpha to Public Beta in dashboard (#50975)
## Problem

We need to rename orioledb in Dashboard.

## Solution

- Update Studio copy/badges referencing OrioleDB from "Public Alpha" to
"Public Beta" (project creation advanced config, restore-to-new-project,
PITR empty state)
- Remove the scheduled-backups block that hid backups for OrioleDB
projects — OrioleDB now has WAL-G scheduled backups in beta, so that
page should behave normally. PITR keeps its existing guard since PITR is
not yet supported for OrioleDB.
- Update the `useOrioleDb` telemetry property doc-comment to reflect the
beta status
- Update project-creation wizard test expectations/fixtures accordingly
(`release_channel: 'beta'`)

Marketing (`apps/www`) and docs (`apps/docs`) references to OrioleDB
alpha status are being updated separately.

<!--
## Preview links

If relevant, include links to changed pages for easy review access.

Copy the preview base URL from the Vercel bot comment on this PR. Use
the following table as an example template.

| Site | Live | Preview | Search for |
| -------------- |
-------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------
| ----------------------------- |
| WWW | [/blog/your-post](https://supabase.com/blog/your-post) |
[/blog/your-post](https://zone-www-dot-com-git-branch-name-supabase.vercel.app/blog/your-post)
| unique phrase from the change |
| Docs |
[/docs/guides/your-page](https://supabase.com/docs/guides/your-page) |
[/docs/guides/your-page](https://docs-git-branch-name-supabase.vercel.app/docs/guides/your-page)
| unique phrase from the change |
| Studio | [/dashboard](https://supabase.com/dashboard) |
[/dashboard](https://studio-git-branch-name-supabase.vercel.app/dashboard)
| unique phrase from the change |
| Design system | [/design-system](https://supabase.com/design-system) |
[/design-system](https://design-system-git-branch-name-supabase.vercel.app/design-system)
| unique phrase from the change |
| UI library | [/library](https://supabase.com/library) |
[/library](https://ui-library-git-branch-name-supabase.vercel.app/library)
| unique phrase from the change |
| Knowledge base |
[/kb/guides/your-page](https://supabase.com/kb/guides/your-page) |
[/kb/guides/your-page](https://kb-git-branch-name-supabase.vercel.app/kb/guides/your-page)
| unique phrase from the change |
-->

<!-- ## Additional context

Optionally add any other context or screenshots.

-->

## Review instructions

## Checklist

Check all before review:

- [x] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
- [x] If I wrote a new docs topic or edited an existing topic, I used
the `/write-the-docs` or `/edit-the-docs` skill, which applies the docs
[style
guide](https://github.com/supabase/supabase/tree/master/apps/docs/style-guide)


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

* **Updates**
* OrioleDB is now labeled as being in public beta rather than public
alpha, and project creation selects the beta release channel.
* Restore-to-new-project and Point-in-Time Recovery notices clarify that
these features are unavailable for OrioleDB projects.
* OrioleDB projects now follow the standard eligibility checks and page
flow for scheduled backups.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-30 17:39:41 +02:00
Charis 0daafca2ca feat(studio): status page banner (incident / maintenance / upcoming) (#51044)
## Summary

* Adds a new global status banner (`StatusBanner`) driven by the
[incident.io](<http://incident.io>) status page data, showing at most
one of: an active incident, in-progress maintenance, or upcoming
maintenance, in that priority order.
* All three types are independently dismissible (persisted to a new
localStorage key, `status-banner-dismissed-keys`); dismissal hides the
banner for items still active, and a new incident reappears even if a
related item was previously dismissed.
* Only shows to users who are actually affected (based on their
projects' regions) or when region data is incomplete (fails open), and
is bypassed entirely by the existing emergency incident override.
* Behind the existing `incidentIoStatusPage` ConfigCat flag —
`AppBannerWrapper` renders this new banner instead of the legacy
`StatusPageBanner` only when the flag is on; default behavior is
unchanged.
* This is PR 5b in a stacked series for Linear
[FE-4057](https://linear.app/supabase/issue/FE-4057) — see that issue
for full design context.

## Test plan

* New unit tests (`StatusBanner.utils.test.ts`) covering
banner-selection priority, dismissal-key handling, and copy generation
* New MSW component test (`StatusBanner.test.tsx`) covering loading
state, dismiss-and-persist, and the emergency-override path
* `pnpm --filter studio run typecheck`, `lint:ratchet`, `pnpm knip
--workspace apps/studio`, `pnpm test:prettier`, and relevant vitest
suites all pass

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

Co-Authored-By: Claude
[noreply@anthropic.com](<mailto:noreply@anthropic.com>)

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

* **New Features**
* Added status banners for relevant incidents and scheduled maintenance,
including incident details, maintenance timing, and links to the status
page.
* Banners can be dismissed, and dismissed items stay hidden while new
incidents or maintenance updates can still appear.
* Upcoming maintenance banners appear within the relevant lead time, and
maintenance timing is shown when available.
* Emergency overrides display a warning banner without a dismiss option.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-29 18:09:47 -04:00
Pamela ChiaandJoshen Lim 4a941518e3 feat(studio): track Explorer runs and saves (#51004)
I added outcome events for Explorer query runs and successful manual
notebook saves. Existing page visits and preview toggles do not show
whether users complete queries or persist notebooks.

**Changed:**
- **Query usage:** Accepted runs from query tabs and notebook cells emit
submitted and terminal outcome events with a shared run ID. Canceled
confirmations emit no run events.
- **Notebook adoption:** Successful manual saves emit created or updated
events. Recreated notebooks count as creations. Unsaved drafts and
failed saves emit neither.
- **Event metadata:** Explorer action events use `Explorer` as their
page title.

**Note:** Assistant-generated saves are outside this PR. Custom
properties omit SQL and notebook content. Page visits still carry the
browser title, which can include a notebook name.

## To test

Tested on the staging preview:
- [x] Run valid and invalid SQL from an Explorer query tab. Each run
emits one submitted event and one matching completed or failed event
with the same run ID.
- [x] Run database and Logs notebook query cells, then add a markdown
cell. The query cells emit matching event pairs; the markdown cell emits
no query event.
- [x] Save a new notebook, then edit and save it again. The successful
saves emit created and updated events.
- [x] Cancel a guarded query. It emits no query run event.
- [ ] Recreate a notebook deleted on the server after local edits. A
successful save emits created, not updated.
- [x] Inspect an Explorer action event request. Its page title is
`Explorer`; page visits still use the browser title.
- [ ] Force a notebook save failure. It should emit no save event. This
case was not tested manually.

## Linear
- fixes GROWTH-1298


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

* **Analytics**
* Explorer query runs are tracked for database and log queries,
including whether they complete or fail.
* Query activity is associated with its location in Explorer, such as a
query tab or notebook cell.
  * Successful notebook saves are tracked as creations or updates.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-09-29 13:54:13 -07:00
Joshen Lim 93a262d185 Check region selection for project creation (#51012)
## Context

Previously added telemetry for `selectedRegionOption` and
`selectedRegionOptionType`
[here](https://github.com/supabase/supabase/issues/50851) if the best
available region option is available for users

Opting to extend this telemetry (still just for Free plan orgs)
irregardless if best available region was selected and include
`initialRecommendedRegion`

Main thing to understand is what regions users are spinning projects up
in outside of the recommended option

## To test
- [ ] Verify the telemetry network request after creating projects
- [ ] Non-free plan: Telemetry request doesn't have
`initialRecommendedRegion` in the payload
- [ ] Free plan: Telemetry request has `initialRecommendedRegion` in the
payload
- Sends correctly if best available region option is available (default
behaviour for staging)
- Sends correctly if best available region option is NOT available
(override with dev tools the configcat flag)
2026-09-29 16:34:03 +08:00
3f205627e0 feat(library): redesign the site around the block catalog (#50372)
## 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?

Feature — the visual redesign itself.

Part 5 of 6 in a stack that splits the library redesign into reviewable
pieces. The four PRs beneath it carry the build, content and Markdown
work; what's left here is layout, navigation and styling.

## What is the current behavior?

The library is laid out like a documentation site: a sidebar tree of
framework folders, a homepage that lists links, and a guide page that
opens with prose. That shape suits reference material, but the library's
job is to help someone find a block and install it — and the sidebar is
the only way to discover one.

## What is the new behavior?

The homepage is the catalog itself — blocks grouped by what they do
(authentication, database, storage, realtime, messaging, AI,
foundations) rather than by framework, each with a preview of what it
renders, filterable by category.

Navigation moves into a site header whose Explore menu opens the same
categories, so the catalog is reachable from any page and the per-page
sidebar tree is gone.

A guide opens with what the reader came for: the block's name, the
install command, and a preview pane with tabs — the running component
and its files — before any prose. The file tree that used to sit
mid-page under "Folder structure" is one of those tabs. Every guide also
offers a copy of the agent prompt that points at its Markdown.

Getting-started pages get the same treatment: the quickstart is now a
framework-tabbed walkthrough rather than a wall of setup links.

## Additional context

`BlockOverviewTabs` renders Preview and Files here. #50369, stacked on
top of this one, adds the third "What's added" tab — it is the only part
of the redesign that depends on the new resource analyzer, which is why
it sits above this PR rather than below it.

Also removes what the redesign orphaned: the table-of-contents component
and its `remark` / `mdast-util-toc` dependencies, and the sidebar nav
and command-item configuration the new header replaced.

The block source changes are typography only — auth card titles move
from `text-2xl` to `font-medium text-lg tracking-normal` — which is what
regenerates the auth registry artifacts.


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

* **New Features**
* Added a redesigned Supabase Library catalog with categorized blocks,
framework-aware navigation, previews, file views, and installation
actions.
* Added framework-specific quickstart guides for Next.js, React, Vue,
Nuxt, React Router, and TanStack Start.
* Added copy-to-clipboard prompts, “Open in v0” actions, starter
templates, and richer visual previews.

* **Improvements**
* Updated documentation layouts, FAQ content, typography, navigation,
accessibility, and responsive behavior.
* Improved mobile navigation, framework selection, and standardized
block installation guidance.
* Refined authentication and social-login block presentation with more
consistent heading styles.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
2026-09-29 10:45:23 +10:00
Alaister YoungandAlaister Young a47397d5fe fix(common): restore narrow Feature type (#50850)
The platform API now types `ProfileResponse.disabled_features` as
`string[]` (since #48981), which collapsed the `Feature` union to plain
`string`, so `isFeatureEnabled` accepted any string and typos went
uncaught.

**Changed:**
- `Feature` is now a local `RuntimeFeature` union (the profile-driven
flags) plus the keys of `enabled-features.json`, instead of deriving
from the API type
- `useIsFeatureEnabled` casts the merged runtime disabled list to
`Feature[]`, since the profile field is now `string[]`

The runtime feature list duplicates what the backend knows. Once the
enum is restored in the API spec, `Feature` can go back to deriving from
the generated type.

## To test

- `pnpm typecheck` passes
- Passing a bogus string to `useIsFeatureEnabled` / `isFeatureEnabled`
is now a type error
- Nothing behavioral changes, so a quick sanity check that the sidebar /
billing / org settings still render is enough


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

## Summary by CodeRabbit

* **No user-facing changes**
* This update does not change the app’s visible features or behavior. It
includes internal typing adjustments only.

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

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-09-25 17:21:38 +10:00
+8 e273d2b818 chore(studio): move Explorer SQL Editor link to sidebar footer (#50829)
## What

- Moves the temporary "Switch to SQL Editor" button out of the Explorer
sidebar header into a footer section ("Looking for snippets?") with a
short explanation and an **Open SQL Editor** button.
- Replaces the header slot with a menu for the Explorer startup
preference (**Start page** / **SQL query**), instead of linking out to
account preferences.

## How to test

1. Enable the Explorer feature preview and open
`/project/<ref>/explorer`.
2. **Header menu:** click the ⋮ button next to the Explorer title. Pick
**SQL query**, then check that **Explorer startup** on `/account/me`
shows the same value (and vice versa).
3. **Footer:** click **Open SQL Editor**. You should land in the SQL
Editor with the **Back to Explorer** button in its title bar.
4. Open **Notebooks** or **Chats** in the sidebar and check that the
menu and footer are hidden there, like the old button was.

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

* **New Features**
* Choose whether the Explorer opens to the Start page or SQL query from
the Explorer preferences menu. Your selection is saved and retained when
you reopen the menu.
  * Access the SQL Editor from the Explorer’s sidebar footer.
* Explorer preferences are available from the Explorer navigation
header.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Tyler <dshukertjr@gmail.com>
Co-authored-by: Nik Richers <nrichers@gmail.com>
Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
Co-authored-by: Jordi Enric <37541088+jordienr@users.noreply.github.com>
Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com>
Co-authored-by: Katerina Skroumpelou <mandarini@users.noreply.github.com>
Co-authored-by: Franek <franek@ferly.co.uk>
Co-authored-by: Franek Richardson <franek@supabase.io>
Co-authored-by: Michał Olszewski <35968924+charconstpointer@users.noreply.github.com>
Co-authored-by: Steven Eubank <47563310+smeubank@users.noreply.github.com>
Co-authored-by: Anthony Lio <lionnet.ant@gmail.com>
Co-authored-by: Joey Lei <6957385+leizerbeam@users.noreply.github.com>
Co-authored-by: Ali Waseem <waseema393@gmail.com>
Co-authored-by: Samir Ketema <6003000+samirketema@users.noreply.github.com>
Co-authored-by: K-Dog (Kevin) <k.grueneberg1994@gmail.com>
2026-09-25 14:31:46 +08:00
K-Dog (Kevin) a5ad2ce745 feat: log query/ingest insights (#50570)
We are doing a soft rollout for log pricing including log ingest and log
querying. We currently only want to display usage/soft warnings, which
is why the metrics are filtered out in some components.
2026-09-25 11:45:46 +08:00
Joshen Lim 0d3b73794b Joshenlim/fe 4465 experiment with best available region selection (#50851)
## Context

Adds a "Best available region" option in the region selector for the
project creation form
- Should only show up for free plan organizations (will be selected as
the default option instead of the recommended option from GET
`/available-regions`)
- "Recommended" badges will also be hidden in this scenario
- Behaviour should be status quo for non free plan organizations
<img width="500" alt="image"
src="https://github.com/user-attachments/assets/de0a183d-37c0-445d-98ca-c5aaf6353e73"
/>

## To test
Important to ensure that project creation still behaves as per usual
- [ ] Free plan: Creating a project with "best available region" select
creates the project if the recommended region from GET
`/available-regions`
- A quick way to check this is to swap to a paid org and see the
"recommended" general region
- [ ] Free plan: Can also create a project with other regions selected
as per usual
- [ ] Non free plan: Can create project as per usual
- [ ] Verify that everything is status quo if configcat feature flag is
off
2026-09-24 17:38:58 +08:00
Danny WhiteandJoshen Lim 05a45dd1ed feat(studio): rename Replication to Pipelines (#50637)
## What kind of change does this PR introduce?

Feature and docs update.

## What is the current behavior?

The Dashboard lists Pipelines destinations under Database > Replication.
Read replicas have moved to Infrastructure, but the temporary notices
remain on the destinations page and new destination sheet.

Closes PIPE-1021.

## What is the new behavior?

The canonical Dashboard routes are Database > Pipelines, while legacy
Replication list and detail URLs permanently redirect to the equivalent
Pipelines routes. Navigation, command palette, shortcuts, pipeline
links, docs, and current marketing copy use Pipelines. Read-replica
notices and their obsolete dismissal state are removed.

| Before | After |
| --- | --- |
| <img width="1024" height="759" alt="Replication Database Agua Basket
Supabase"
src="https://github.com/user-attachments/assets/53f9f565-1ed1-43e9-a7d9-b66b2a47e948"
/> | <img width="1024" height="759" alt="2540"
src="https://github.com/user-attachments/assets/14ab2d61-d01c-483f-9d4f-0ac286dae159"
/> |

The Management API, pipeline behaviour, replication logs, and Postgres
replication terminology remain unchanged.

## To test

- Open `/project/<ref>/database/pipelines` and confirm the Database
navigation, page header, and pipeline breadcrumb say Pipelines.
- Open
`/project/<ref>/database/replication?source=bookmark#destinations` and a
legacy pipeline detail URL. Confirm each redirects to the matching
Pipelines URL while preserving parameters and fragments.
- From the Pipelines page, open Add destination. Confirm no read-replica
migration notice appears.
- Open the Pipelines guide and confirm its Dashboard steps lead to
Database > Pipelines.

## Before merge

- [ ] Get changelog entry reviewed
https://github.com/supabase/changelog/pull/262 and prepare to merge
simultaneously

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

- **New Features**
- Added dedicated **Database > Pipelines** pages for pipeline lists and
details.
- Added permanent redirects from legacy Replication URLs to their
corresponding Pipelines pages.
- Read replica management links now open **Settings > Infrastructure**.

- **Documentation**
- Updated Pipelines setup, monitoring, troubleshooting, and usage
guidance to reference the current dashboard locations.
  - Updated Realtime guidance to use **Database > Publications**.

- **Updates**
- Renamed dashboard navigation, breadcrumbs, commands, and keyboard
shortcuts from **Replication** to **Pipelines**.
  - Removed the “Read replicas have moved” notification.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-09-23 08:52:07 +10:00
5bdfb8743c fix(telemetry): give warehouse_disabled the same schema and table counts as warehouse_enabled (#50643)
<!-- ccr-slack-attribution -->
_Requested by **Pam Chia** · [Slack
thread](https://supabase.slack.com/archives/C076KTY11DF/p1789979663384919?thread_ts=1789953229.116889&cid=C076KTY11DF)_

## 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 (telemetry).

## What is the current behavior?

**Before:** Disabling Warehouse fires `warehouse_disabled` with no
properties at all, while enabling it fires `warehouse_enabled` with
`schemaTargetCount` and `tableTargetCount`. Disables can be counted, but
nothing says how much was being replicated when the user turned it off,
so churn cannot be segmented by the size or shape of the setup being
torn down.

## What is the new behavior?

**After:** `warehouse_disabled` carries `schemaTargetCount` and
`tableTargetCount` with exactly the same meaning they have on
`warehouse_enabled`: schemas replicated in full, and tables replicated
individually on top of those. A disable of a project replicating one
whole schema plus two loose tables now reports one schema target and two
table targets, so enable and disable volume line up on the same two
properties.

## Additional context

**How:** The counts are read once, when the user confirms the dialog,
and held in a ref until the mutation succeeds. The setup mutation's own
`onSuccess` invalidates the setup-status and replication-sources queries
and awaits those refetches before the caller's callback runs, so
anything read inside `onSuccess` already reflects the post-disable state
and would report nothing replicated. The event is tracked from that
hook-level `onSuccess` rather than a `mutateAsync` callback: the status
refetch swaps the Disable card out of the panel, and mutate-level
callbacks are skipped once the component has unmounted.

The shape is reproduced from the `supabase_warehouse` publication
through the same helpers the table picker uses — the publication's
tables become a selection, and that selection is mapped back to targets
against the project's selectable schemas. Counting distinct schemas and
tables off the replicated-table list instead would put a different
meaning behind the same property names: a fully covered schema would be
counted as its individual tables rather than as one schema target, and
the two events would no longer be comparable.

Both properties are optional. The replicated-table list is assembled
from four queries, and when they have not resolved the properties are
omitted rather than sent as `0`, so "unknown" is never recorded as
"nothing was replicated".

Tests: unit tests for the extracted `buildSchemasWithTables` helper, and
a component test that drives the disable dialog against a publication
covering one schema in full plus one table from another.

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

https://claude.ai/code/session_0197pGnhiAkhiiYiRxY3qVFY

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Pamela Chia <pamelachiamayyee@gmail.com>
2026-09-21 20:58:13 +08:00
Danny White 512201dcd0 chore(ui): remove the Classic Dark theme (#50387)
## What kind of change does this PR introduce?

Chore.

## What is the current behaviour?

Classic Dark remains available across the shared theme library and
several apps. Studio now supports System, Dark, and Light as its theme
modes, but still carries compatibility paths for Classic Dark.

## What is the new behaviour?

- Removes Classic Dark from shared theme options, application commands,
stylesheets, previews, examples, and replay handling.
- Deletes the Classic Dark and faux Classic Dark stylesheets.
- Removes the now-unused Classic Dark branches from Studio theme colour
controls.
- Migrates `classic-dark` to `dark` so first rendered frame renders Dark
(not Light)

| After |
| --- |
| <img width="1458" height="1778" alt="CleanShot 2026-09-18 at 11 07
40@2x"
src="https://github.com/user-attachments/assets/679bf87f-a3c1-4599-ad2f-292d98d0b856"
/> |

## To test

1. In Studio, open Account Preferences → Appearance. Confirm the
available themes are System, Dark, and Light, and that theme colour
controls still work in each resolved mode.
2. Set the `theme` local storage value to `classic-dark`, then reload
Studio. Confirm it renders as Dark immediately and the stored value
becomes `dark`.
3. Open the theme switcher in Design System, Learn, and UI Library.
Confirm Classic Dark is no longer available and Light, Dark, and System
still apply correctly.


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

## Summary by CodeRabbit

* **Changes**
* Removed the Classic Dark theme option from theme menus and settings
across the application.
* Classic Dark selections are automatically migrated to the standard
Dark theme.
* Updated theme documentation and demonstrations to list only System,
Light, and Dark.
* Removed Classic Dark styling and preview support; existing Dark,
Light, and System themes remain available.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-21 10:53:14 +10:00
Nik RichersandNik Richers e3c677fc5a feat(docs): track prompt panel copies in PostHog (#50482)
## 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 telemetry for `PromptPanel` to help us understand how people
interact with our AI prompts better.

 Relates to DOCS-1393

Dashboard(restricted access): [Docs: AI prompt
affordances](https://eu.posthog.com/project/34344/dashboard/957235)

## What is the current behavior?

The docs homepage cover renders a setup panel with "AI Prompt" and "CLI"
tabs, and guides render `AiPrompt` blocks. Both are built on the shared
`PromptPanel`, whose copy button called `copyToClipboard` and nothing
else. Copying was therefore unmeasured, while the neighbouring
affordances (`ask_ai_clicked`, `agent_setup_clicked`,
`copy_as_markdown_clicked`) are already instrumented.

## What is the new behavior?

`PromptPanel` takes an optional `telemetry` prop. When it is set, the
panel sends a new docs-owned event after a **successful** clipboard
write, so instrumentation lives in the shared component instead of a
forked homepage copy button.

New event in `packages/common/telemetry-constants.ts`:

| | |
| --- | --- |
| `action` | `docs_ai_prompt_copied` |
| `source` | `homepage` \| `guide` \| `agent_setup` |
| `tab` | `prompt` \| `cli` (omitted for panes outside that set) |
| `promptId` | prompt id, when the panel comes from an `AiPrompt` block
|

Wired consumers: `HomePageCover` (`homepage`), `AiPrompt` (`guide` by
default, plus `promptId`), and `AgentSetup` (`agent_setup`). No prompt
body text and no PII is sent.

Studio's existing `ai_prompt_copied` event is deliberately left alone:
it has a different owner and surface, and merging the two would blend
unrelated funnels.

### Proof it works

```
$ pnpm run test:local:unwatch features/ui/PromptPanel.telemetry.test.ts

 RUN  v5.0.0 /apps/docs

 Test Files  1 passed (1)
      Tests  4 passed (4)
   Duration  775ms
```

## Additional context

Test plan, run against a local docs server with a stub telemetry
endpoint so the request bodies could be read directly:

| Case | Observed payload |
| --- | --- |
| Homepage, AI Prompt tab | `{"source":"homepage","tab":"prompt"}` |
| Homepage, CLI tab | `{"source":"homepage","tab":"cli"}` |
| Next.js quickstart `AiPrompt` |
`{"source":"guide","tab":"prompt","promptId":"nextjs"}` |
| `automate-with-agents/health` `AgentSetup` |
`{"source":"agent_setup","tab":"prompt","promptId":"monitoring-agent-health"}`
|
| Clipboard write rejected | no request sent, error toast shown, button
does not flip to "copied" |

The failure case was re-checked with a control click on the same page
after restoring a working clipboard, which did send the event, so the
negative result is not just a missed handler.

Also run: `turbo typecheck --filter=docs --filter=common` (passes),
Prettier check on the touched files (passes), and ESLint on the touched
docs files (no new findings; the one warning on `HomePageCover` is the
pre-existing default export).

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

* **New Features**
* Successful prompt copies are now tracked across the homepage,
documentation guides, and agent setup experiences.
* Copy activity records the prompt’s source, selected format, and
associated prompt when available, providing more complete usage
insights.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Nik Richers <nik@validmind.ai>
2026-09-20 17:08:03 +00:00
Pamela Chia 64ab76262e feat(studio): exhaustion banner links to metrics (#50276) 2026-09-17 22:23:10 +02:00
Pamela Chia 66d4b4c19b chore(studio): remove expired tos update banner (#50533) 2026-09-18 00:52:40 +08:00
Saxon Fletcher 0043e6f53b feat(studio): add Explorer onboarding and startup preference (#50493)
<img width="1454" height="920" alt="image"
src="https://github.com/user-attachments/assets/a289b618-2bd2-4957-ac49-71d4e372d2cc"
/>


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

Feature.

## What is the current behavior?

Explorer always opens on its start page, without onboarding or a startup
preference.

## What is the new behavior?

Adds one-time onboarding with wireframe option cards and a collapsed
Learn more section. Users can start on the Explorer start page or in a
new SQL query tab, and change that choice in Account preferences →
Dashboard. Preferences persist per account in the browser.

## Additional context

How to test:
1. With Explorer enabled and fresh browser storage, open Explorer and
select either startup option. Confirm Open Explorer follows the
selection and onboarding stays dismissed after reload.
2. Change Explorer startup in Account preferences → Dashboard, then
reopen Explorer. SQL query should create one normal query tab; Start
page should restore the pinned home tab.
3. Use the keyboard to select an option and toggle Learn more. Expand it
in a short viewport and check that the page scrolls normally.

Validation: 235 tests pass, including 20 new cases; Studio typecheck and
formatting pass.

The local production build was stopped during compilation and was not
verified locally.



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

- **New Features**
- Added an Explorer onboarding experience with startup-view selection,
guidance, and a Learn more section.
- Added Explorer settings to choose between the Start page and SQL query
views.
  - Explorer preferences now persist across sessions and accounts.
  - Explorer can open directly to a new SQL query when selected.
- The Explorer Home tab is shown based on the selected startup
preference.
- **Accessibility**
  - Reduced-motion settings now disable the Explorer loading animation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-17 15:53:18 +10:00
Danny White 3e2d54eccb feat(studio): add Warehouse table management and disable (#50195)
## What kind of change does this PR introduce?

Feature and UI polish.

## What is the current behavior?

Warehouse setup uses a schema accordion for table selection. Once
Warehouse is enabled, users cannot remove replicated tables or disable
Warehouse from Studio.

## What is the new behavior?

- Replaces the schema accordion with one grouped, searchable table
selector.
- Still allows for **Select all** and **Clear** actions for each schema.
- Starts first-time setup with no tables selected and preselects current
replicated tables when editing.
	- Adds support for removing previously replicated tables.
- Adds a confirmed **Disable Warehouse** action.
- Tracks successful Warehouse enable and disable actions.

Disabling Warehouse removes its replication pipeline, publication,
catalogue access, and foreign tables. Copied data remains in DuckLake
storage until the user deletes it. Re-enabling a table rebuilds its data
rather than reusing the retained copy.

| Before | After |
| --- | --- |
| <img width="1024" height="759" alt="Integrations Test US East 1 testdw
Supabase"
src="https://github.com/user-attachments/assets/bded025b-1d45-41dc-8a35-9159baf8f9b7"
/> | <img width="1024" height="759" alt="Integrations test Teamer
Supabase"
src="https://github.com/user-attachments/assets/69026d94-98a0-4878-ab58-2e9697296d93"
/> |
| <img width="1280" height="1323" alt="Integrations Test testdw
Supabase"
src="https://github.com/user-attachments/assets/3f71e754-1a87-4d58-a7b9-dd39d3e0ac5a"
/> | <img width="1280" height="1323" alt="Integrations Regular AWS
Teamer Supabase"
src="https://github.com/user-attachments/assets/758ed48e-9ed6-45d3-ae94-e171147a21d5"
/> |
| _Feature did not exist_ | <img width="1024" height="759"
alt="Integrations Regular AWS Teamer Supabase"
src="https://github.com/user-attachments/assets/c977ac57-8b0c-4482-882b-69ad7602b5df"
/> |

## Additional context

Platform support for updating and disabling Warehouse was added in
[supabase/platform#38190](https://github.com/supabase/platform/pull/38190).

### To test

1. Open `/project/{ref}/integrations/warehouse/overview` before setup.
2. Confirm **Tables to replicate** starts at zero and **Enable
Warehouse** is disabled until a table is selected.
3. Confirm each schema's **Select all** and **Clear** actions update
every table in that schema.
4. Enable Warehouse with a partial selection and wait for setup to
complete.
5. Edit the selection, add and remove replicated tables, then confirm
the saved selection is reflected in the publication.
6. Disable Warehouse, confirm the retention warning, and verify the
integration returns to its initial state.
7. Re-enable Warehouse and confirm selected tables are rebuilt.
8. Trigger a replication pipeline limit error and confirm the inline
guidance links to Database Replication.

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

- **New Features**
  - Added the ability to disable Warehouse from the setup panel.
  - Warehouse setup now starts with no table selections.
- Editing a setup preselects replicated tables and supports updating
selections, including removing tables.
- Added searchable schema and table selection with screen-reader count
announcements.
  - Added telemetry tracking for initial Warehouse enablement.

- **Bug Fixes**
- Warehouse disable failures now show an error while keeping the
confirmation dialog open for retry.
  - Configuration updates now refresh related data automatically.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-17 14:17:00 +10:00
cc540ff302 feat(studio): add safe theme colour controls (#49804)
## What kind of change does this PR introduce?

Feature.

## What is the current behaviour?

Studio Appearance preferences only select a theme mode. The underlying
theme colours cannot be adjusted, and the existing proof of concept
allowed unsafe combinations and introduced a bespoke Slider variant.

## What is the new behaviour?

- Preserves the existing System, Dark, Light, and Classic Dark theme
options. Classic Dark remains a fixed preset.
- Adds four theme colour controls using the existing Supabase Slider
unchanged. Each control presents a consistent 0 to 100 scale mapped to
bounded light and dark ranges.
- Previews colour changes while dragging and persists them once the
interaction finishes, including rapid pointer gestures.
- Stores light and dark overrides separately, validates stored values,
clamps legacy values, and removes overrides that return to their shipped
defaults.
- Adds concise descriptions for Chroma, Contrast, Surface, and Elevation
step, with a scoped Reset action shown only when the active theme
differs from its defaults.
- Keeps Slider in a stable shared chunk so production builds do not
create a circular dependency between generated UI chunks.

| Before | After |
| --- | --- |
| <img width="1448" height="1284" alt="CleanShot 2026-09-15 at 14 33
53@2x"
src="https://github.com/user-attachments/assets/d55151c7-b2a9-40c6-9468-e77ae685ac38"
/> | <img width="1454" height="1958" alt="CleanShot 2026-09-15 at 17 48
47@2x"
src="https://github.com/user-attachments/assets/9d302e67-76cc-4341-948c-81713dea2e93"
/> |

## To test

1. Open `/account/me` and scroll to Appearance.
2. Switch between System, Dark, Light, and Classic Dark. Confirm the
same four modes remain available in the account theme menu.
3. Confirm Classic Dark retains its existing appearance and does not
show theme colour controls.
4. In System, Dark, or Light, move each Theme colors slider to both
ends. Confirm the dashboard previews the change, remains readable, and
the theme cards do not shift or remount.
5. Reload the page and confirm colour changes persist separately for
Light and Dark.
6. Return all sliders to their defaults, or select Reset, and confirm
the Reset action disappears.
7. In System mode, change the operating system theme and confirm each
resolved mode restores its own colour settings.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
2026-09-17 10:33:59 +10:00
99be7f92ce feat(studio): add Privacy Policy update notice (#50397)
## Summary

Adds a compact Privacy Policy update notice for signed-in Studio users
on organization landing pages.

- Shows on `/org`, `/organizations`, and `/org/:slug`
- Opens the approved policy explanation in a dialog
- Links to the Privacy Policy and `privacy@supabase.com`
- Persists acknowledgement in a dated local storage key
- Stays off project and organization settings routes so it cannot cover
product controls

## Why

The Privacy Policy changes the data controller from Supabase, Inc. to
Supabase Pte. Ltd. User rights and protections are unchanged.

This restores the established authenticated Studio notification pattern:

- [#35923](https://github.com/supabase/supabase/pull/35923): May 2025
Privacy Policy notice
- [#43681](https://github.com/supabase/supabase/pull/43681) and
[#43889](https://github.com/supabase/supabase/pull/43889): March 2026
Privacy Policy notice and design pass
- [#45632](https://github.com/supabase/supabase/pull/45632): May 2026
Terms of Service notice
- [#48524](https://github.com/supabase/supabase/pull/48524): current
reusable Studio banner stack

## Release order

The policy content and Studio notice deploy independently. Keep this PR
in draft until [#50392](https://github.com/supabase/supabase/pull/50392)
is approved, merged, and live. The notice appears immediately when this
Studio change deploys.

## To test

1. Open Studio on `/organizations` or an organization project-list page.
2. Confirm the compact Privacy Policy notice appears.
3. Open **Learn more** and confirm the dialog copy and both links.
4. Select **Understood** or close the notice.
5. Reload and confirm the notice remains dismissed.
6. Remove `privacy-policy-update-2026-09-16-dismissed` from local
storage and confirm the notice returns.
7. Open a project route and confirm the notice is absent.

## Verification

- Prettier passes on changed files.
- ESLint passes on changed Studio files.
- Focused Vitest suites pass: 25 tests.
- Studio Unit Tests & Build Check passes.
- TypeScript & Lint, UI Tests, Studio Docker Build, dead-code, ratchet,
and validation workflows pass.
- All four self-hosted Studio E2E shards pass for both router
implementations.
- All deploy previews pass.
- The Studio preview rendered the compact notice on the organization
landing page without console errors. The dialog and dismissal flow still
need an authenticated browser pass after the session redirected to
sign-in.

A direct local Studio TypeScript check reaches one existing unrelated
error in
`packages/ui-patterns/src/McpUrlBuilder/components/InstructionBlocks.tsx`;
no changed file reports an error and the required TypeScript CI workflow
passes.

## Measurement

Success means signed-in users can find the updated policy from the
organization landing experience without interrupting project work. The
dated dismissal key confirms acknowledgement locally. CI protects the
non-blocking route scope, and Privacy can monitor questions sent to
`privacy@supabase.com` after release.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Pamela Chia <pamelachiamayyee@gmail.com>
2026-09-16 17:51:25 +08:00
Ali Waseem 5b099ee03f chore: share Sentry browser-noise filters between studio and docs FE-4392 (#50407)
Studio and docs each kept their own Sentry `ignoreErrors` list, so
browser-extension and DOM-mutation noise that Studio already filtered
still reached Sentry from docs. Moved the app-agnostic filters (network,
extension DOM mutation, non-Error throws, cross-origin script errors)
into `packages/common/sentry.ts` and spread them into both client
configs, leaving app-specific entries local. Docs will stop reporting
extension-driven `insertBefore`/`removeChild` crashes, matching Studio's
existing behavior — `ignoreErrors` drops events before `beforeSend`
runs, so the error-boundary exemption no longer applies to them.

Fixes FE-4392

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

## Summary by CodeRabbit

- **Bug Fixes**
- Reduced non-actionable browser noise in error monitoring by filtering
known network, browser extension, DOM-manipulation, cross-origin, and
non-error failures.
- Applied consistent filtering across the documentation site and studio
error tracking.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 09:38:36 -06:00
Jordi Enric fa7c223209 fix(studio): use Compute management endpoints FUNC-896 (#50393)
## Problem

Studio still called the legacy `/workers` Management API routes and used
the old `project_worker` response contract, so Compute instances could
not be listed or retrieved after the API rename. The production API type
check also detected drift in the v1 and platform declarations.

## Fix

- Regenerate the v1, v2, and platform API declarations from the deployed
schemas.
- Update Studio list and detail queries to `/compute`.
- Align typed fixtures with the Compute response schemas and
`project_compute_instance` resource type.
- Update platform response type references to the generated `_Output`
schema names.

## How to test

- Run `pnpm api:verify-types`.
- Run `pnpm --filter api-types test`.
- Run `pnpm --filter studio test data/compute/compute.utils.test.ts
"tests/pages/project/[ref]/compute/index.test.tsx"`.
- Run `pnpm --filter studio typecheck`.
- Run `pnpm --filter common typecheck`.
- Run `pnpm --filter studio lint:ratchet`.

Expected result: production API declarations are synchronized, and
Studio requests the `/compute` list and detail endpoints and renders
`project_compute_instance` responses successfully.

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

## Summary by CodeRabbit

* **Improvements**
* Updated API response handling across profiles, backups, notifications,
integrations, warehouses, access tokens, payments, and other Studio
workflows for more accurate serialized data.
* Compute instance pages and queries now use the compute-specific API
endpoints and response data.
* Improved feature-flag type handling when disabled feature data is
unavailable.

* **Tests**
* Updated automated coverage and fixtures to reflect current compute and
API response formats.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 12:50:56 +02:00
Jordi Enric 8984305b1e feat: sample non-crash sentry errors at one percent (#50339)
## Problem

Browser Sentry reporting sends ordinary application errors at full
volume even though full-page crashes are the highest-priority signal.

## Fix

Sample eligible browser errors without `globalErrorBoundary` at 1%
across Studio, www, and docs. Keep 100% of eligible errors tagged with
`globalErrorBoundary`, preserve consent and existing noise filters, and
record the applied rate in `codeSampleRate`.

## How to test

- Run `node node_modules/vitest/vitest.mjs run
../../packages/common/sentry.test.ts lib/sentry-capture.test.tsx` from
`apps/www`.
- Run `node node_modules/vitest/vitest.mjs run
lib/sentry-client-options.test.ts` from `apps/studio`.
- Expected result: tagged page crashes bypass sampling, ordinary errors
use the 1% cutoff, and Studio applies sampling once while preserving its
existing filters.


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

- **Bug Fixes**
- Improved error reporting reliability by ensuring page-crash errors are
captured without sampling.
- Non-crash application errors are now sampled at a low rate, with
sampling metadata retained for monitoring.
- Updated filtering behavior so relevant Studio errors continue to be
reported consistently, including errors previously affected by
client-side filtering.
- Preserved filtering for third-party-only errors that do not represent
application failures.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 11:43:24 +02:00
Gildas Garcia 63bedef77f MFA Recovery codes: allow users to download their recovery codes (#50267)
## What kind of change does this PR introduce?

After users have set up a new MFA (first or not), we must:

- check whether recovery codes have already been generated
- if there are none, generate recovery codes and display them, "forcing"
users to copy them
- if already generated, show them how many are still available

> [!NOTE]
> The _Delete my recovery codes_ button in last screenshot only appear
on local and staging environments

## How to test

- On an account that doesn't have recovery codes generated yet and has
an MFA added
- You should see an admonition suggesting to generate the codes

## Screenshots

<img width="729" height="306" alt="image"
src="https://github.com/user-attachments/assets/79ba3870-4ef8-4571-9fd6-36eed20c9c24"
/>

<img width="550" height="356" alt="image"
src="https://github.com/user-attachments/assets/1632611a-996a-470d-b6cd-a4693b0f4602"
/>

<img width="719" height="205" alt="image"
src="https://github.com/user-attachments/assets/73cef611-05cf-4fac-bbd2-243f9b28e48d"
/>


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

- **New Features**
- Added support for generating, copying, and confirming MFA recovery
codes.
- Added recovery-code status visibility, including remaining and
exhausted codes.
  - Added the ability to delete recovery codes with confirmation.
- Added clear loading, success, and error states for recovery-code
actions.
  - Recovery-code status refreshes after codes are generated or deleted.

- **Bug Fixes**
- Recovery-code notices now remain visible when all codes have been
used.
  - Recovery-code dialogs can now be closed after generation errors.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 11:16:47 +02:00
Sean Oliver d439ba57f4 feat(studio): mask HTML attributes in session replay (#48818)
## 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?

Hardening ahead of any decision to enable session replay, plus a
dependency bump. Follow-up to #48515.

### What's inside

- ~50 lines of logic: the callback, the `url()` pattern, and the theme
and SVG-reference gates
([session-replay.ts](https://github.com/supabase/supabase/pull/48818/changes#diff-b7e4f10387ee7a116dd1673f70a55c0ba066687ff2d228bc2320eba75a349fac))
- ~170 lines of allowlist, one attribute name per line, skimmable ([same
file](https://github.com/supabase/supabase/pull/48818/changes#diff-b7e4f10387ee7a116dd1673f70a55c0ba066687ff2d228bc2320eba75a349fac))
- ~150 lines of comments saying why each group is allowlisted, since a
wrong entry is a privacy or a fidelity bug ([same
file](https://github.com/supabase/supabase/pull/48818/changes#diff-b7e4f10387ee7a116dd1673f70a55c0ba066687ff2d228bc2320eba75a349fac))
- ~430 lines of tests, one case per policy decision
([session-replay.test.ts](https://github.com/supabase/supabase/pull/48818/changes#diff-f9feb872ad0136cf87c7e9fb2af72eb3f4019464c06f0b7dd050ffb85373ccb8))
- 1 line of dependency bump, plus its lockfile
([package.json](https://github.com/supabase/supabase/pull/48818/changes#diff-50d7c39a9430d37971aa76858165ab4f7921c4cc4340b28e9b673ce6982e63cf))

## What is the current behavior?

Session replay is disabled in every environment, and no recordings
exist. This is about what a recording *would* contain if it were ever
switched on.

Attributes are the one channel replay masking cannot reach. `maskTextFn`
only sees DOM text nodes, so a component interpolating customer data
into a `placeholder`, `title` or `aria-label` would be captured
verbatim. Before `posthog-js` 1.413.0 there was no hook for it at all,
and the only mitigation was blocking the element, which drops it from
the capture entirely.

Two places in Studio where that would apply:

- `CreateOrUpdateCustomProviderSheet.tsx:506-507` interpolates the
project's API host into both `value` and `placeholder`. The `value` is
masked. The `placeholder` is not.
- `FileExplorerHeader.tsx:185` renders `Search in
${currentFolderName}...`, a customer storage folder name.

The list is not complete. Any component echoing context into a tooltip
reproduces it, and the author has no reason to be thinking about replay.

Linear [GROWTH-1094](https://linear.app/supabase/issue/GROWTH-1094).
Blocks [GROWTH-1073](https://linear.app/supabase/issue/GROWTH-1073).

## What is the new behavior?

`maskAttributeFn` with a default-deny policy: an allowlist of the
attributes replay needs to render, everything else masked.

### Policy edge cases

- **rrweb's `rr_*` layout attributes have to be allowlisted
explicitly.** posthog-js only applies its own exemption for those when
`maskAllElementAttributes` does the masking. A callback does not get the
exemption.
- **HTML `id` is masked. SVG `id` passes.** `AreaChart.tsx:119` emits
`<linearGradient id="colorUv">` and references it as
`fill="url(#colorUv)"`, so masking it breaks the gradient. But Studio
also binds customer-named values to `id` (`bucket.id` is a storage
bucket name). Split on `element.namespaceURI`.
- **SVG reference attributes pass only fragment-only targets.** recharts
clips every series with `clip-path="url(#clipPath-<id>)"`, so
`clip-path`, `mask`, `filter`, `marker-*`, `fill` and `stroke` have to
survive. They accept external URLs too, so the policy checks the target
rather than allowlisting the attribute name.
- **The `url()` pattern consumes escaped delimiters and ignores case.**
A target containing a quote serializes as `\"` and one containing a
bracket as `\)`, so a naive `[^")]*` stops at the backslash and leaves
the tail of the URL recorded. `URL(...)` is the same function as
`url(...)`. A token the pattern cannot parse falls through to a masking
fallback rather than passing.
- **`url()` targets inside `style` are masked, keeping the
declarations.** The feedback widget puts `toPng(document.body)`, a
base64 PNG of the whole dashboard, into a `background-image`, and the
storage preview panes put signed object URLs there. No other masking
path covers those, because they are not text nodes, a canvas, a network
request or an `img src`.

The config also pins `maskAllElementAttributes: false`. Left unset it
resolves from the PostHog UI, and `true` discards `maskAttributeFn`
entirely.

The `posthog-js` floor rises to `^1.416.1`, the first version carrying
both attribute masking and the "coarse option wins" precedence.

This does not enable recording anywhere.

## Additional context

### Verification

Ran on the studio-staging preview against a live session: 817 seconds,
190 clicks, 82 keypresses. Staging has no server-side masking config, so
everything masked came from this code.

| Check | Result |
|---|---|
| Storage folder search placeholder | Asterisked. Pre-fix it read
`Search in <folder>...` |
| Custom auth provider sheet | Fully masked, including the callback URL
field |
| Canary folder name in event properties | 0 hits, with 51 events in the
session as the control |
| Console capture | `console_log_count: 0` despite the project having
`capture_console_log_opt_in: true` |
| Telemetry regression | None: `$pageview` x34, `$pageleave` x5,
`$groupidentify` x4, `$identify` x1 |

Recording was scoped to that one preview by an origin restriction plus a
URL trigger. Both were reverted afterwards along with the project
toggle.

The policy has 175 unit tests. Separately, the config was bundled with
esbuild and applied to a DOM reproducing Studio's serialized output (the
AreaChart gradient, a recharts `clip-path`, a lucide icon, an inline
`background-image`), and the chart, gradient fill and icon come out
pixel-identical.

### Known fidelity costs

- `img src` is masked, so images don't render in replay. Storage object
URLs are signed customer content.
- `ProviderIcon` renders its mark as `maskImage: url(<src>)` and
`normalizeIconPath` accepts absolute URLs, so provider icons don't
render either.

### Out of scope

rrweb records `<style>` element text without calling either masking
function, because its text-node serializer skips masking when the parent
is `STYLE`. This PR does not reach that channel. Fixed separately in
#50270 / [GROWTH-1229](https://linear.app/supabase/issue/GROWTH-1229).

`captureJsonLd` also defaults on as of PostHog's 2026-08-30 defaults,
which is a capture channel masking doesn't reach. Studio renders no
`ld+json`, so it's inert there, and pinning it off was left out to keep
this PR to its scope.

### The allowlist is the weak part

The policy is default-deny over attribute *names*, so its surface is
every attribute any shipped library emits, and that set grows with each
dependency. A miss is also invisible to these tests, which assert what
the function returns rather than whether some selector elsewhere still
matches. Both failure directions are reachable that way: an attribute
carrying customer data, and an attribute a stylesheet needs.

[GROWTH-1232](https://linear.app/supabase/issue/GROWTH-1232) tracks the
mechanism change: scope by namespace instead of by name, since 50 of the
159 entries exist only to serve SVG rendering, plus a conformance test
that derives the expected set from the codebase so a new dependency
fails CI rather than degrading a replay. Deliberately not done here,
since rewriting the mechanism of a privacy control buys maintainability
rather than correctness.
2026-09-14 09:48:58 -07:00
Joshen Lim c9e035910d Add HA toggle to enabled features (#50344)
## Context

As per PR title - flags the HA toggle in project creation form behind a
flag in enabled-features
Behaviour should be status quo for both staging and prod

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

## Summary by CodeRabbit

* **New Features**
* Added a high-availability option to the project creation flow for
eligible accounts when the feature is enabled.
  * The option is available through controlled feature configuration.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 23:14:10 +08:00
claude[bot]andClaude 25f411657d fix(telemetry): widen plan-presentation exposure event variant type to 5 variants (#50318)
&lt;!-- ccr-slack-attribution --&gt;
_Requested by **Pam Chia** · [Slack
thread](https://supabase.slack.com/archives/C076KTY11DF/p1789349119093319?thread_ts=1789349119.093319&cid=C076KTY11DF)_

## 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 (telemetry type).

## What is the current behavior?

The `pricing_panel_plan_presentation_experiment_exposed` event's
`variant` property in `packages/common/telemetry-constants.ts` only
types 3 of the experiment's 5 live variants (`'control' | 'parity' |
'gaps'`), even though the experiment source in `plan-presentation.ts`
defines and actively uses 5: `control`, `parity`, `gaps`, `fullscreen`,
`fullscreen-gaps`. The two full-screen variants are silently untyped in
the telemetry catalog.

## What is the new behavior?

The `variant` property is widened to `'control' | 'parity' | 'gaps' |
'fullscreen' | 'fullscreen-gaps'`, matching the exact casing of
`PLAN_PRESENTATION_VARIANTS` in the experiment source, and consistent
with how other experiment-variant unions in the same file (e.g.
`rlsOptionVariant`) are kept in sync with their source enum.

## Additional context

Linear: GROWTH-1234

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

https://claude.ai/code/session_01Gxb4n5ujMPeio1VmkowHc5

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

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-14 18:24:36 +08:00
Jordi Enric fb22534439 fix: share sentry crash policy and enable www reporting (#50232)
## Problem

The website initializes Sentry only on the server and edge runtimes,
leaving browser crashes unreported. Its crash-reporting setup also needs
the same consent and third-party filtering policy that docs and Studio
otherwise maintain separately.

## Fix

Add www browser initialization and tagged crash capture for both Next.js
routers, with accessible fallback focus. Move the shared
consent/platform and third-party filtering into common/sentry, reuse it
from all three apps, and remove the duplicated docs/www helpers and
tests. Preserve each app's initialization and Studio's additional noise
filtering, sampling, and sanitization.

Include the source-map upload token in www's build cache inputs, and
trigger the shared/www and Studio test workflows when the shared policy
changes.

## How to test

- Run `pnpm --filter www test ../../packages/common/sentry.test.ts
lib/sentry-capture.test.tsx`: all 22 shared-policy and real-SDK capture
tests passed locally.
- Run `pnpm --filter studio exec vitest run
lib/sentry-client-options.test.ts`: all 42 Studio options and
policy-parity tests passed locally.
- The www capture tests exercise the actual initializer and both router
handlers with an in-memory transport, verify crash tags and fallback
focus, and enforce consent. Removing initialization, capture calls,
boundary tags, or consent gating was verified to fail these tests.
- On a www preview with its DSN configured, accept telemetry consent and
trigger temporary render errors in both routers. Verify they reach the
www Sentry project with the boundary tag and readable stack traces.

Formatting passes. Full local app typechecks encounter existing
dependency/generated-file drift, with no diagnostics in changed files.
Three unchanged TanStack mock call-count tests fail locally and
reproduce against the pre-refactor implementation. Live Sentry ingestion
and source-map uploads remain deployment checks.


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

- **Accessibility**
- Error pages now automatically move focus to a clearly labeled error
message, helping screen-reader and keyboard users understand when a page
fails.

- **Reliability**
- Browser error reporting now captures application crashes more
consistently across supported page types and navigation transitions.
- Reporting respects consent and platform availability while filtering
unrelated third-party failures.

- **Testing**
- Expanded automated coverage for error capture, reporting rules,
consent handling, and accessible error-page behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 09:28:08 +02:00
Aleksi ImmonenandSean Oliver 66e6cd1639 feat: capture Freebuff ad click ids (#50181)
## 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?

Feature: ad attribution capture.

## What is the current behavior?

Freebuff ad clicks arrive on supabase.com with a signed click id in
`?bfcid=`. Nothing captures it, so those signups are unattributed.

## What is the new behavior?

This PR captures `bfcid` and writes it to a cookie that, in production,
is scoped so the management API receives it. The conversion is reported
server-side on profile creation, in a separate change tracked in
GROWTH-1217.

Start with `enforceConsentDecision` in
`packages/common/consented-url-cookie.ts`. It is the rule everything
else hangs off, and `consented-url-cookie.test.ts` covers the state
matrix.

Capture:

- `bfcid` is read on landing and held in `sessionStorage` until the
consent decision resolves. Memory alone loses it when someone navigates
before answering the banner.
- Once consent is granted it goes into a cookie. In production on
`*.supabase.com` that cookie is scoped to `domain=supabase.com`, and it
is host-only elsewhere. It is written only after consent, which is the
signal GROWTH-1217 relies on.
- Values are validated with `/^bfc_[A-Za-z0-9._-]{1,508}$/`, the
validator Freebuff publishes in their tag, so we never store a value
their tag would reject.
- `bfcid` is added to the first-touch attribution props, which feed
pageview telemetry and are already consent-gated.

Consent:

- `enforceConsentDecision` reduces the decision to two states. Undecided
and declined both clear the cookie, since neither has consent to point
at. They differ in the retained value: an undecided visitor may still
accept, so it waits for them.
- `clearConsentedUrlCookie` drops the cookie. `discardConsentedUrlValue`
also drops the retained value.
- A module-level valtio subscription registers on import, guarded on
`window` so it is inert during SSR.

`packages/common/consent-state.ts` gains a generic `isResolved` flag and
no vendor knowledge. A consumer acting on a decision needs to tell "not
decided yet" from "decided against", which `hasConsented` cannot express
alone. `applyPriorDecisionToSDK` now returns its promise chains, so its
signature becomes `void | Promise<void>` and initialization awaits
settlement before marking the decision resolved. Worth checking the call
sites.

## Additional context

160 tests pass in `packages/common`. Typecheck and Prettier are clean
locally on the changed files. CI is still running on the latest commit.

Unverified: the clearing paths are covered by unit tests only. The
consent SDK is short-circuited in local and preview builds, so they
cannot be exercised outside production. An end-to-end conversion
recorded by Freebuff is also unverified, since it needs the server-side
change deployed.

GROWTH-1216


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

## Summary by CodeRabbit

- **New Features**
- Added consent-aware handling for Freebuff Ads click identifiers,
retaining valid URL values until consent is resolved and storing them in
a cookie after approval.
- Added automatic cleanup when consent is denied or withdrawn, while
preserving unrelated cookies.
- Added support for capturing the click identifier in first-touch
attribution data.
- **Bug Fixes**
- Improved consent initialization tracking so completion is reported
after successful or failed resolution.
- Added safeguards for restricted browser storage, cookies, and
server-rendered environments.

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

Co-authored-by: Sean Oliver <882952+seanoliver@users.noreply.github.com>
2026-09-11 12:14:08 -07:00
Gildas GarciaandAlaister Young 737b8595f2 Update API types (#50234)
## Problem

platform, v1 and v2 have been already completely migrated and introduced
some changes.

Some types have been renamed, some outputs and inputs updated.

## Solution

- Update the API types
- Fix the TS errors

## Update

Taking this over to unblock #50134, which needs the new scoped token
permission ids from the regenerated types.

- Merged `master`.
- Regenerated `api-v2.d.ts` from the production spec. The previous files
came from a local API that exposed a webhook events endpoint production
doesn't have yet. Production has since added standardized 400 error
responses on the v2 organization endpoints. `api-v1.d.ts` and
`platform.d.ts` already matched production.
- Fixed `verify-production-types`. It formatted the regenerated files in
a temp directory outside the repository, so Prettier fell back to its
defaults and the comparison could never match the committed files. It
now passes the repository config explicitly. `pnpm api:verify-types`
passes on this branch.
- Verified locally: `pnpm typecheck`, `pnpm api:verify-types`, Studio
unit tests.

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

* **Bug Fixes**
* Preserved descriptions when saving, sharing, moving, or unsharing
notebooks, reports, SQL snippets, and saved queries.
* Improved handling of empty or null values across notebook
descriptions, billing usage, pooler settings, and infrastructure fields.
* Improved read-replica connection handling, including read-only
connection strings.
* Updated storage configuration and capability handling to match current
settings.

* **API and Compatibility**
* Updated organization, project, storage, OAuth, billing, and
infrastructure data handling to match current API responses.
  * OAuth app creation and updates now require scopes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-09-11 12:17:49 +08:00
Francesco Sansalvadore 0bf22ee6fc chore(studio): update product naming (#50208)
workers -> compute

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

- **New Features**
- Added the Compute experience for deploying, viewing, managing, and
monitoring compute instances.
- Added Compute navigation, instance detail pages, secrets, logs,
deployment dialogs, generated snippets, and CLI commands.
- Added filtering, status, availability, and data-loading support for
compute instances.

- **Updates**
- Updated labels, icons, links, feature controls, unified logs, and
secret-deletion messaging to use Compute terminology.
  - Compute routes now replace the previous Workers routes and pages.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-10 16:26:48 +02:00
1966209483 chore(deps): upgrade vitest to v5 (#49994)
Upgrades Vitest from 4.1.4 to 5.0.0 across the monorepo, fixes the
handful of things v5 turned into hard errors, and drops the
`vi.clearAllMocks()` boilerplate that v5's `clearMocks` default makes
redundant.

**Changed:**
- `vitest`, `@vitest/ui`, `@vitest/coverage-v8` 4.1.4 → 5.0.0 (catalog)
- `vi.mock` calls that lived inside `beforeAll`/`beforeEach`/test bodies
moved to module scope (v5 throws on nested calls). Affects the Studio
and docs setup files and four Studio tests.
- `detectBrowser` test restores `navigator` via `vi.unstubAllGlobals()`
instead of assigning `global.navigator`, which now reaches jsdom's
getter-only property.
- `RowEditor.utils.test.ts` restores its `JSON.stringify` spy. It used
to leak a throwing mock for the rest of the file, which v5's coverage
provider now trips over. A later test in the same file had been
asserting the leak's side effect (valid JSON reported as invalid) and
now asserts the correct behavior.
- `@testing-library/jest-dom` 6.6 → 7.0.1. Its vitest type augmentation
resolves through a peer now, so it lands on each package's own `vitest`
instead of whichever copy pnpm hoisted. Fixes `toBeInTheDocument` type
errors in dev-tools after the reshuffle.
- `@testing-library/react` 16.0.0 → 16.3.3 for the React 19 peer range.
- `vite: catalog:` added to dev-tools, www, and common. Without it they
resolved a newer vite than the catalog pin, which forked a second vitest
instance in the lockfile. There's now one.
- ai-commands custom matcher types use v5's `Matchers<R, T>` form.
- 110 test files: `vi.clearAllMocks()` removed from
`beforeEach`/`afterEach` hooks, along with hooks that only did that and
the imports they left unused. Calls that also reset/restore mocks are
untouched. Second commit, mechanical.

**Added:**
- `.vitest/` to the root gitignore (v5 writes JSON/JUnit/HTML reporter
output there)

**Removed:**
- `vite-tsconfig-paths` catalog entry and deps. Vitest 5 resolves
tsconfig paths itself.

Release-age note: this sat in draft with a temporary
`minimumReleaseAgeExclude` entry for `vitest` and `@vitest/*` while
5.0.0 was inside the workspace's 3-day `minimumReleaseAge` window. That
window has closed, so the exclusion is gone and nothing bypasses the
release-age gate.

**Perf** (local, medians of 3 runs, same machine):

| Suite | v4.1.4 | v5.0.0 |
|---|---|---|
| studio | 144.1s | 141.7s (-2%) |
| studio `--coverage` | 156.9s | 146.4s (-7%) |
| ui-patterns | 6.27s | 5.07s (-19%) |
| ui `--coverage` | 3.35s | 2.14s (-36%) |
| www | 0.89s | 0.47s (-47%) |

Studio is dominated by jsdom environment setup per file, which v5
doesn't change. `vitest doctor` recommends keeping the current pool
config: the vm pools and `isolate: false` all break tests.

## To test

- `pnpm install --frozen-lockfile` succeeds with no
`minimumReleaseAgeExclude` entry for vitest.
- CI: Studio unit tests, ui, ui-patterns, www, docs, and typecheck/lint
should all be green. The lint ratchet was checked locally: warning
counts on touched Studio files are identical to master.
- `pnpm test:studio` locally passes with coverage (588 files, 6240
tests).
- Open a Studio test that uses `toBeInTheDocument` in your editor and
confirm no type errors on jest-dom matchers, in Studio and in
`packages/dev-tools`.
- Known pre-existing failures unrelated to this PR: one dev-tools test
(`getEventCountBadge` capped pill) fails on master too.


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

## Tests
- Improved test coverage for JSON validation and mobile navigation
behavior.
- Updated test setup, cleanup, environment configuration, and matcher
support across application and shared package suites.
- Removed obsolete coverage for alternate MCP transport selection.

## Chores
- Streamlined TypeScript path resolution and Vitest reporter output
handling.
- Updated testing libraries and Vitest tooling across documentation,
Studio, website, and shared packages.
- Added Vitest reporter output to ignored files.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
2026-09-10 16:45:54 +08:00
Joshen Lim a1686025b6 Joshenlim/fe 4291 keep unsaved notebooks accessible after page refresh (#49673)
## Context

Changes here adds a "Draft" state for notebooks with a new
`notebook-drafts` store - similar to how we handle query tabs in the
explorer.
This implies that if a user refreshes the tab while there's unsaved
changes to notebooks, the changes can be persisted locally and the user
will be able to continue from where they left off.

This also implies that If you create a new notebook (OR open an existing
notebook and make some changes) and refresh the browser, we no longer
show the native browser confirmation dialog about discarding changes.

We also reuse the existing confirmation dialog when saving a notebook if
its draft has diverged from the server side content - just updated the
language to be more generic rather than saying that the Assistant made
changes
<img width="429" height="238" alt="image"
src="https://github.com/user-attachments/assets/5c392aed-1633-4428-8060-28f495a01f04"
/>

Also fixes an unrelated issue - renaming a notebook should mark the
notebook as having unsaved changes (with the orange indicator)

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

## Summary by CodeRabbit

* **New Features**
* Unsaved notebook edits are saved locally and restored when reopening
Studio.
* Drafts are scoped by project and protected from server changes through
conflict detection.
* Notebook tabs indicate unsaved changes, including drafts from unsaved
notebooks.
* **Bug Fixes**
* Closing a tab with local edits prompts for confirmation and removes
its saved draft.
  * Notebook save state reflects the server-confirmed update time.
  * Conflict messages clearly describe changes made on the server.
* **Style**
  * Improved keyboard focus behavior for tab controls.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-09 17:17:25 +08:00
Joshen Lim db0e6b761b Joshenlim/fe 4304 bring database connections out of feature preview (#50107)
## Context

As per PR title - we're bringing Database Connections out of feature
preview and it'll live on the dashboard by default 🙂
Also deprecating the existing Ongoing queries panel which Database
Connections now supercedes.

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

* **New Features**
* Database Connections is now available without feature-preview
activation.
* The SQL editor’s “View running queries” option now links directly to
Database Connections.

* **Bug Fixes**
* Query cancellation and session termination now refresh database
activity data.

* **Removed**
* Removed the in-editor ongoing queries panel and its termination
controls.
* Removed the Database Connections promotional banner, preview
messaging, settings, and related telemetry.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-08 17:26:24 +08:00
Jordi Enric be030229bf feat(studio): add workers to unified logs FE-4281 (#49682)
## Problem

Unified Logs does not expose Workers logs, so users cannot search
Workers ingress, runtime, or build events alongside other services.

## Fix

Add a Workers log type that classifies all three Workers OTEL streams.
Gate the option and any persisted Workers filters with the existing
Workers feature flag.

## How to test

- Enable the Workers feature flag and open Unified Logs.
- Select Workers from the Log Type filter.
- Expected result: Unified Logs shows ingress, runtime, and build events
with the Workers icon.
- Disable the Workers feature flag and load a URL containing
`log_type:eq:workers`.
- Expected result: the Workers option and filter are removed, and
Workers logs are not queried.
- Run `./node_modules/.bin/vitest --run
components/interfaces/UnifiedLogs/UnifiedLogs.queries.test.ts
components/interfaces/UnifiedLogs/UnifiedLogs.utils.test.ts
data/workers/worker-logs-query.test.ts` from `apps/studio`.

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

* **New Features**
  * Added Workers as a selectable log type in Unified Logs.
* Unified Logs now combines worker ingress, guest, and API streams under
the Workers category.
  * Added a dedicated Workers icon and worker log filtering.

* **Improvements**
  * Worker filters and URL parameters respect feature availability.
* Worker details show relevant metadata while omitting unavailable HTTP
fields.
  * Improved handling of worker log levels, statuses, and raw data.
  * Added stronger validation for unified log data.

* **Tests**
* Added coverage for worker routing, filtering, feature visibility,
parsing, and metadata redaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-07 15:53:36 +02:00
Francesco SansalvadoreandClaude Sonnet 5 b0601f9ab7 feat(storage): add object versioning feature flag and feature preview (#49202)
| # | Branch | Base |
| - | ------ | ---- |
| 1 | `feat/storage-versioning-private-alpha` ◀ | `master` |
| 2 | `feat/storage-versioning/002-bucket-form-fields` | 1 |
| 3 | `feat/storage-versioning/003-bucket-modals` | 2 |
| 4 | `feat/storage-versioning/004-object-versions-data` | 3 |
| 5 | `feat/storage-versioning/005-file-preview-versions` | 4 |
| 6 | `feat/storage-versioning/006-billing-storage-retention` | 5 |

### PR 01

Adding feature flag for versioning.

- `UI_PREVIEW_STORAGE_VERSIONING` local storage key, allowlisted
- Feature preview entry gated on
`useFlag('storageVersioningPrivateAlpha')`
- `useIsStorageVersioningEnabled()`, following the existing
`useIsSqlEditorManualSaveEnabled` shape

<img width="910" height="604" alt="Screenshot 2026-08-19 at 11 33 45"
src="https://github.com/user-attachments/assets/5c51c3fa-6100-48e5-914d-63a9948a5024"
/>

Note: will improve the feature preview with an image once we approach
release.

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

## Summary by CodeRabbit

- **New Features**
  - Added a Storage Versioning feature preview in the dashboard.
- Preview access is controlled by feature flags and is disabled by
default.
- Added descriptive information about Storage Versioning and its Private
Alpha availability.
- Added support for remembering the Storage Versioning preview setting.

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

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 12:53:01 +02:00
Coenen BenjaminandCharis Lam 11289328e5 add support for warehouse connection string (#49914)
Add support for connection string for warehouse. 
This PR gives the ability to enable warehouse on a project and also get
the connection string to connect to.

> This project is only available in staging for now and gated behind a
feature flag

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

- **New Features**
  - Added a Warehouse connection option to the Connect dialog.
- Select schemas and tables to replicate, with setup progress, error
recovery, and retry support.
- View copyable Warehouse connection details, credentials guidance,
command-line instructions, and DuckLake setup scripts.
  - Warehouse availability is controlled by feature configuration.

- **Tests**
- Added coverage for Warehouse table selection, setup script generation,
URL parsing, and connection configuration utilities.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Benjamin <5719034+bnjjj@users.noreply.github.com>
Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com>
2026-09-07 11:24:42 +02:00
c086fe0d3f fix(studio): stop duplicating access_token_creation_sheet_dismissed on Done (#50077)
<!-- ccr-slack-attribution -->
_Requested by **Pam Chia** · [Slack
thread](https://supabase.slack.com/archives/C076KTY11DF/p1788743741768969?thread_ts=1788743741.768969&cid=C076KTY11DF)_

## 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 (telemetry).

## What is the current behavior?

`access_token_creation_sheet_dismissed` (added in #49965) fires on every
close of the "Generate token" sheet in `/account/tokens`, including a
successful completion. The "Token created" step closes the sheet through
a "safe" path (clicking **Done**), but `handleOpenChange` tracked the
dismissed event on that path too: a 1:1 duplicate of the already-tracked
`access_token_done_button_clicked` event, with `step: 'success'`.

The event's `tokenType` property was also never meaningful: it is
derived from a variable that is only set after a token is actually
created and never reset, so on a first-attempt abandonment it is always
`'none'` by construction, and on a later abandonment in the same session
it carries the *previous* token's type.

The sheet also force-closes when the permissions map fails to load. That
close was indistinguishable from a user abandonment.

Linear:
[GROWTH-1196](https://linear.app/supabase/issue/GROWTH-1196/fix-access-token-creation-sheet-dismissed-duplicate-on-done)

## What is the new behavior?

- The event no longer fires on **Done**. The token-created step already
blocks Escape, outside click, and Cancel, so the event now only reflects
the sheet closing before a token exists.
- Dropped `tokenType` (never described the abandoned attempt, see above)
and `step` (a constant `'form'` once Done stops firing it; it was also
typed Numeric project-wide in PostHog, so its string values read as NULL
in HogQL).
- New properties, read from the live form at close time through a small
`useImperativeHandle` ref on `NewScopedTokenForm` (`useForm` ownership
stays inside the form component):
- `resourceAccess` (`project` | `organization` | `account`): the
in-flight scope selection. `account` is the classic-token path, so this
carries what `tokenType` was meant to. It is the default `project` when
the form is untouched, so filter on `isFormTouched` before reading it as
intent.
- `formStep` (`form` | `review`): which screen the user was on. The
sheet-level `step` never captured this.
  - `isFormTouched`: whether any field was changed from its default.
- `trigger` (`user` | `permissions_load_error`): the forced close on a
failed permissions load now fires with its own trigger, so an endpoint
regression shows up in the funnel instead of silently lowering
`access_token_created`.
- Fixed a double-fire on the load-error path: the form's error effect
depended on the `onCancel` callback identity and re-ran on the sheet's
close re-render (double toast, and a double event). It now reads the
callback through a ref and depends only on `isError`, matching the
existing `isReducedMotionPreferredRef` pattern in the same file.

## Additional context

`NewScopedTokenSheet.test.tsx` asserts: Done does not emit the dismissed
event; Cancel and Escape emit it with `trigger: 'user'` and the
in-progress `resourceAccess` and `isFormTouched`; dismissing from the
review screen reports `formStep: 'review'`; a 500 from the permissions
endpoint emits exactly one event with `trigger:
'permissions_load_error'` and closes the sheet.

`step` being typed Numeric in PostHog affects every event that sends a
string `step`. That is a PostHog data-management fix handled separately,
not in this PR.

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

https://claude.ai/code/session_01XW73umv73LrrKxFwwymSaH

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Pamela Chia <pamelachiamayyee@gmail.com>
2026-09-07 16:53:56 +08:00
kemal.earthandGildas Garcia 8654991847 feat(studio): additional events for scoped pat telemetry (#49965)
## 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?

Adds PostHog tracking to the final step of the scoped PAT creation flow,
after `access_token_created` fires. The token value is only ever shown
once, so this measures whether users actually leave with a usable token.

Three new events on the "Token created" step:

| Event | Properties |
| --- | --- |
| `access_token_copied` | `tokenType` |
| `access_token_stored_checkbox_clicked` | `tokenType`, `isChecked` |
| `access_token_done_button_clicked` | `tokenType`, `hasCopiedToken` |

- `isChecked` is the resulting state, so unticking the acknowledgement
is captured too.
- `hasCopiedToken` records whether the Copy button was used before
finishing. Done is gated on the checkbox, not on copying, so this
separates "copied it" from "ticked the box and left."
- `tokenType` is threaded through from the sheet, which creates a
classic token when resource access is `account` and a scoped one
otherwise. It matches the existing `access_token_created` /
`access_token_removed` property.

## Changes

- `packages/common/telemetry-constants.ts` — three event interfaces,
added to the
`TelemetryEvent` union
- `NewScopedTokenSuccess.tsx` — `useTrack()` plus a new `tokenType`
prop;
copy/acknowledge/done routed
- `NewScopedTokenSheet.tsx` — `createdToken` state now holds `{ token,
tokenType }` so
the success step knows which
- `NewScopedTokenSheet.test.tsx` — extended the two tests that already
walk the full
success flow with assertions  and classic paths)

## Testing

`pnpm test:studio` on `NewSco16 passing. Typecheck clean.


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

* **Analytics**
* Added tracking for key access-token creation interactions, including
copying tokens, selecting storage options, and completing the flow.
* Tracking distinguishes between classic and scoped access tokens and
records whether a token was copied before completion.
* Added tracking when the access-token creation sheet is dismissed,
including the current step.

* **Behavior**
* Existing copy, storage-selection, notification, and completion actions
continue to work as expected.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com>
2026-09-04 11:15:18 +02:00
Charis 9aaa753306 feat(studio): add telemetry for explorer/sql editor temporary switch buttons (#49898)
## Summary

Add PostHog event tracking for the two new buttons introduced in PR
supabase/supabase#49698 that allow users to temporarily switch between
the Explorer and SQL Editor:

* **Explorer button**: "Back to SQL Editor" button in the Explorer
sidebar title bar now fires `explorer_temp_access_sql_editor_clicked`
event
* **SQL Editor button**: "Back to Explorer" button in the SQL Editor
title bar (shown during temporary visits) now fires
`sql_editor_back_explorer_clicked` event

Both event interfaces follow the repo's telemetry-standards conventions,
carrying only `groups: TelemetryGroups` property with no additional
custom properties.

## Test plan

- [X] Verify `explorer_temp_access_sql_editor_clicked` event fires in
PostHog when clicking "Back to SQL Editor" button in Explorer
- [X] Verify `sql_editor_back_explorer_clicked` event fires in PostHog
when clicking "Back to Explorer" button in SQL Editor
- [X] Run typecheck: `pnpm typecheck` passes without errors
- [X] Run lint: `pnpm lint --filter=studio` passes

## Issue

Resolves
[FE-4213](https://linear.app/supabase/issue/FE-4213/explorer-set-up-telemetry-for-metrics-where-appropriate)

## Summary by CodeRabbit

* **Analytics**
  * Added tracking for navigation from the Explorer to the SQL Editor.
  * Added tracking for returning from the SQL Editor to the Explorer.
2026-09-02 09:07:06 -04:00
Pamela Chia 5db8a0e960 feat(studio): instrument sign-in attempts and failures (#49853)
The /sign-in page emitted only a pageview on entry and the success-side
`sign_in` event on exit: failed or abandoned attempts were invisible, so
"never interacted" and "tried and failed silently" could not be told
apart in the sign-in funnel. I added an unsampled `sign_in_submitted`
event at every initiation point and classified failure capture via
`dashboard_error_created` with a new `signin` origin.

**Changed:**
- **Submit attempts observable**: `sign_in_submitted` (method: `email`,
provider id, `sso`, or partner) fires from the DOM submit handler on the
password and SSO forms (so submits that fail client-side validation
still count), and from the OAuth, custom-provider, and partner
initiation handlers.
- **Failures classified**: each sign-in error path feeds the existing
funnel-error pipe with origin `signin` and a controlled reason slug
(`invalid_credentials`, `email_not_confirmed`, `captcha_failed`,
`sso_provider_not_found`, ...). GoTrue auth errors now classify via
their numeric `status`, guarded so transport failures (`status: 0`) stay
`network_error`.
- **Attempt events survive the OAuth redirect**: the telemetry event
POST sends with `keepalive` (scoped to `sign_in_submitted`, since
keepalive requests share a per-page in-flight body quota), so a
dispatched request is no longer aborted by the provider navigation; send
rejections are caught centrally instead of surfacing as unhandled
rejections. The fetch still dispatches after an async token lookup, so
preview testing verifies the GitHub-path event actually lands on the
wire.
- **Captcha rejection is no longer silent**: a rejected hCaptcha
challenge resolves the stuck loading toast with an error message, emits
`captcha_challenge_failed` (distinct from `captcha_failed`, which stays
reserved for the auth server rejecting a submitted token), reports to
error monitoring, and resets the captcha widget (previously: unhandled
promise rejection and a spinner that never resolved).
- **Partner method validated**: the partner sign-in page resolves the
URL-hash value against the provider registry and forwards the canonical
provider id into `method` on both `sign_in_submitted` and `sign_in`;
anything unregistered records as `unregistered_partner`, so a crafted
link can't poison the breakdown on either event.

**Note:** failure events stay on the shared 10%
`dashboard_error_created` sampling rate (a per-origin carve-out would
break cross-source volume comparability); the unsampled attempt event
carries the tried-vs-never-interacted signal at full volume.

## To test

Tested on Vercel preview (studio-staging, wire-level network capture +
staging ingestion check):
- [x] On `/sign-in`, submit a bogus email + password: expect a `POST
*/platform/telemetry/event` request with `action: sign_in_submitted`,
`method: email` in the network tab, plus an error toast. Observed: 201,
auth returned 400 as expected.
- [x] Submit with an empty password: expect `sign_in_submitted` to still
fire (validation failures count as attempts). Observed: event fired with
201 and no auth call followed.
- [x] Click "Continue with GitHub": expect `sign_in_submitted` with
`method: github` on the wire before the provider redirect. Observed: the
POST completed (201) before the browser landed on github.com, so the
keepalive path holds.
- [x] Negative case: fresh page load with no interaction fires no
`sign_in_submitted`.
- [x] Ingestion: all fired events (methods `email`, `github`, plus
organic `sso` submits from a real login on the same preview) arrived in
the staging project with the expected properties.
- [x] Re-ran the email and GitHub paths on the scoped-keepalive build
(`129bf8d`): both `sign_in_submitted` POSTs returned 201 (the GitHub one
completed despite the provider redirect), and both events ingested into
the staging project with the expected `method`/`category` properties.

## Linear
- GROWTH-1165 (no `fixes` keyword on purpose: the evidence checks run on
prod data post-deploy, and the issue closes manually after they pass)


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

## Summary by CodeRabbit

* **New Features**
* Improved sign-in protection with more reliable invisible CAPTCHA
handling.
* Added sign-in submission tracking across password, SSO, partner,
custom OAuth, and external-provider flows.
* Added detailed classification for authentication, validation, CAPTCHA,
provider, and network errors.

* **Bug Fixes**
  * Sign-in now stops safely and resets CAPTCHA when verification fails.
* Improved error reporting for failed sign-in attempts, including
redirects and OAuth flows.
* Ensured sign-in telemetry is delivered reliably during OAuth
redirects.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-02 19:02:37 +08:00
Pamela Chia 3338be76f0 fix(studio): emit sign_in on totp challenge (#49755)
The dashboard's `sign_in` event never fires when a user completes a TOTP
challenge: `SignInForm` only tracks when no MFA challenge is needed, and
the /sign-in-mfa page only tracks on mount when the assurance level is
already satisfied (OAuth/SSO returns). Sign-ins that go through the
actual MFA form were invisible to analytics, and the login audit event
was missing on the same path.

**Changed:**
- **MFA-challenged sign-ins now tracked**: `SignInMfaForm` fires
`sign_in` (reading the same `method` query param the page mount site
reads) plus the login audit event on successful TOTP verification, in
the sign-in context only. The forgot-password flow stays untracked: it
is a reset, not a sign-in.
- **Password+MFA sign-ins report `method: email`**: `SignInForm` now
passes `?method=email` when routing to /sign-in-mfa instead of falling
through to `unknown`.
- **Partner TOTP sign-ins carry their provider**: `SignInPartner` now
passes `?method=<partner>` when routing to /sign-in-mfa, matching the
raw-provider-name convention the other entry points use.
- **Join caveat documented**: the `SignInEvent` doc comment now notes
the event is captured server-side and races the identify call, so it is
not a valid funnel join key across the auth boundary.

## Linear
- fixes GROWTH-1156


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

* **New Features**
* Added sign-in method details to MFA redirects for email and partner
authentication, improving sign-in flow tracking.
* Added telemetry and login auditing for successful MFA sign-ins while
keeping forgot-password flows untracked.
* **Documentation**
* Clarified sign-in event tracking coverage, including OAuth providers,
server-side capture, anonymous identifiers, and the sign-in page.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-01 13:26:08 +00:00
Charis 4b1f93bb99 feat(explorer): add path back to SQL Editor for snippet access (#49698)
## 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?

Feature

## What is the current behavior?

Users who have opted into the Explorer feature preview have no way back
to the SQL Editor from within Explorer, so they can't easily check their
old snippets.

## What is the new behavior?

- The Explorer sidebar title bar now has a button (using the same icon
as the SQL Editor/Explorer nav entry) that links to the SQL Editor, with
a tooltip explaining it's a temporary switch to access snippets.
- Clicking it marks the visit as temporary in localStorage, which
surfaces a matching "Back to Explorer" button in the SQL Editor title
bar. Clicking that button clears the temporary flag and returns to
Explorer.
- Fixed the product menu title bar badge slot to sit flush right instead
of directly next to the title text.

## Additional context

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

* **New Features**
  * Added a quick switch from the Explorer to the project’s SQL Editor.
* Added a “Back to Explorer” option in the SQL Editor when opened from
Explorer.
  * Added tooltips to clarify these navigation actions.
* Navigation state is preserved per project for a smoother return
experience.

* **UI Improvements**
* Improved product menu spacing and title truncation for better layout
handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-01 09:07:54 -04:00
Mert YEREKAPANandkemal d11705ded0 feat(studio): add plan-change panel presentation experiment (#49534)
## What

A/B test for the plan-change side panel
(`/org/_/billing?panel=subscriptionPlan`) — gated behind PostHog flag
`pricingPanelPlanPresentation` (multivariate, 3 arms).

The current panel drops `description`, `preface`, and `footer` from
`shared-data/plans.ts` and uses a much smaller type scale than the www
pricing page, so the two surfaces look unrelated and plan differences
are hard to reason about. This experiment tests whether matching the www
style and surfacing plan gaps improves upgrade conversion.

| Variant | Surface |
| --- | --- |
| `control` | Current panel — no change (baseline cohort, still tracked)
|
| `parity` | www pricing page style: mono uppercase heading,
description, CTA above price, large mono price, preface ("Everything in
the Free Plan, plus:"), 13px features |
| `gaps` | `parity` + gap rows at the bottom showing what the plan is
missing (✗ Daily backups, ✗ Email support, dimmed ✓ 1-day log retention)
|

## Variants

Control
<img width="3520" height="2394" alt="Arc 2026-08-26 16 14 09"
src="https://github.com/user-attachments/assets/95464e83-b377-4754-85ee-c65dce0206c7"
/>

Parity
<img width="3520" height="2394" alt="Arc 2026-08-26 16 14 01"
src="https://github.com/user-attachments/assets/f50e66e2-7cbe-4e65-b1fb-083efd79ff00"
/>

Gaps
<img width="3520" height="2394" alt="Arc 2026-08-26 16 29 48"
src="https://github.com/user-attachments/assets/fbb08a12-1b76-4ce5-9247-20a6e8399be3"
/>


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

* **New Features**
* Added a refreshed subscription plan selector with pricing,
descriptions, features, exclusions, and plan-specific messaging.
* Added upgrade and downgrade actions with loading states and
eligibility-based controls.
* Added plan comparison views highlighting missing and lower-tier
features.
* Added tailored handling for enterprise plans and supported billing
arrangements.
* Improved accessibility by respecting reduced-motion preferences during
plan highlights.

* **Tests**
* Expanded coverage for plan eligibility, feature comparisons, and
presentation variants.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: kemal <hello@kemal.earth>
2026-08-31 11:53:16 +02:00
5b01b5a9c7 fix(studio): report advisorCategory consistently across advisor telemetry surfaces (#49746)
<!-- ccr-slack-attribution -->
_Requested by **Pam Chia** · [Slack
thread](https://supabase.slack.com/archives/C076KTY11DF/p1788139328573799?thread_ts=1788139328.573799&cid=C076KTY11DF)_

## 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 (telemetry correctness). No user-visible change.

## What is the current behavior?

Linear:
[GROWTH-1153](https://linear.app/supabase/issue/GROWTH-1153/telemetry-advisorcategory-omitted-for-health-lints-on-two-of-five)

**Before:** five surfaces emit the optional `advisorCategory` property
on `advisor_detail_opened` and `advisor_assistant_button_clicked`, and
they disagree about how to derive it. Three pass the lint's category
straight through as `categories[0]`. Two compute it with a hardcoded
ladder — `categories.includes('SECURITY') ? 'SECURITY' :
categories.includes('PERFORMANCE') ? 'PERFORMANCE' : undefined` — which
predates the `HEALTH` category and falls through to `undefined` for
anything it does not name. Because the property is optional, those two
surfaces ship the event with `advisorCategory` silently absent: no type
error, no runtime error, just a hole in the data. A reader querying a
category breakdown of either event gets numbers that depend on which
surface the user happened to click, and `HEALTH` is under-counted. The
split is clearest in `AdvisorSection.tsx`, where a single advisor card
emits both events — the card click through the ladder (L83) and the
Assistant button through the pass-through (L206) — so one card can
report two different categories for the same lint.

The cause is that `AdvisorCategory` in
`packages/common/telemetry-constants.ts` is schema-derived:

```ts
type AdvisorCategory =
  components['schemas']['GetProjectLintsResponse'][number]['categories'][number]
```

The API-types regeneration in supabase/supabase #49646 (merged
2026-08-27, `26e89b36c349893540f8efbd45613921be0a4d18`) widened
`categories` from `('PERFORMANCE' | 'SECURITY')[]` to `('PERFORMANCE' |
'SECURITY' | 'HEALTH')[]`. `AdvisorCategory` picked up the third value
incidentally and the two ladders were never updated — a union widening
is invisible to a hardcoded ladder, so nothing broke loudly.

| Event | Surface | HEALTH behavior before |
| --- | --- | --- |
| `advisor_detail_opened` |
`apps/studio/components/ui/AdvisorPanel/AdvisorPanel.tsx` (L203) |
ladder → property absent |
| `advisor_detail_opened` |
`apps/studio/components/interfaces/ProjectHome/AdvisorSection.tsx` (L83)
| ladder → property absent |
| `advisor_detail_opened` |
`apps/studio/components/interfaces/Linter/LinterDataGrid.tsx` (L163) |
pass-through → `'HEALTH'` |
| `advisor_assistant_button_clicked` |
`apps/studio/components/interfaces/Linter/LintDetail.tsx` (L38) |
pass-through → `'HEALTH'` |
| `advisor_assistant_button_clicked` |
`apps/studio/components/interfaces/ProjectHome/AdvisorSection.tsx`
(L206) | pass-through → `'HEALTH'` |

The two `advisorCategory` property doc comments in
`telemetry-constants.ts` (L2949, L2980) also still read "Category of the
advisor (SECURITY or PERFORMANCE)", which the widening made false.

## What is the new behavior?

**After:** all five surfaces derive `advisorCategory` the same way, so a
category breakdown of these two events is consistent regardless of which
surface produced the event, and `HEALTH` is reported wherever it can
occur. The two ladder sites now read `item.original.categories[0]`,
matching the three sites that already did. The `signal` branch (which
reports `'SECURITY'`) and the `notification` branch (`undefined`) of
those two expressions are unchanged, so nothing about non-lint advisor
items moves. The stale parenthetical is cut from both doc comments.

Net diff is 3 files, -12/+4 lines. No behavior change outside the value
of one optional telemetry property.

## Additional context

**How.** The fix is the pass-through, not an extended ladder. Per the
two options considered:

1. **No lint carries more than one category in practice.** Every lint
fixture in `apps/studio` uses a single-element array (`['SECURITY']`,
`['PERFORMANCE']`). The API type permits a multi-element array, but
nothing in the repo produces one, so the ladder's
SECURITY-over-PERFORMANCE priority is not load-bearing.
2. **The advisors UI already treats the first element as canonical** —
`LinterDataGrid.tsx` L196 renders `<LintCategoryBadge
category={selectedLint.categories[0]} />`.
3. **Extending the ladder would not actually produce agreement.** In the
one reachable multi-category case, a ladder with a `HEALTH` branch
appended still reports the higher-priority category while the three
pass-through sites report `categories[0]`. Only `categories[0]` makes
all five agree, which is the point of the change.

**Reviewers should look at this first — how much data is actually
affected.** Narrower than the headline suggests, and worth stating
precisely. Every surface feeding these events filters lints upstream by
category, and all three filters still admit only `SECURITY` or
`PERFORMANCE`:

- `AdvisorPanel.utils.ts` `createAdvisorLintItems` drops any lint that
resolves to no tab (`if (!tab) return null`), and it is the item source
for **both** ladder surfaces
- `pages/project/[ref]/advisors/security.tsx` filters
`categories.includes('SECURITY')`
- `pages/project/[ref]/advisors/performance.tsx` filters
`categories.includes('PERFORMANCE')`

So a HEALTH-**only** lint is not surfaced anywhere in Studio today and
cannot currently reach any of the five emit sites. The divergence
reachable today is a lint carrying `HEALTH` alongside another category:
it passes the filters, and then the ladder sites and the pass-through
sites disagree. The HEALTH-only omission is latent, and becomes live
data loss the moment HEALTH lints are surfaced — presumably the point of
the API adding the category. Practical consequence: **no backfill or
historical-data caveat is needed**, because no HEALTH-only event was
ever emitted. This is a correctness fix that gets the emit surfaces
right ahead of the category being shown, not a response to an active
data incident.

**How it was tested.** Honest caveat up front: `pnpm install` cannot
complete in this sandbox, so the Studio-scoped checks could not be run
here. `apps/studio` depends on `@std/path` → `npm:@jsr/std__path`, and
the JSR registry is network-blocked in this environment (`GET
https://npm.jsr.io/~/11/@jsr/std__path/1.0.8.tgz` → `403`, both direct
and proxied; `registry.npmjs.org` returns `200`, so it is JSR
specifically). CI on this PR is the real signal for Studio lint,
typecheck, and tests. What did run clean:

- `prettier --config prettier.config.mjs --check` on all three changed
files — clean
- `tsc --noEmit` in `packages/common` (installed via `pnpm install
--filter=common...`) — clean, and `--listFiles` confirms it genuinely
covers both `telemetry-constants.ts` and the widened
`packages/api-types/types/platform.d.ts`
- the changed expression typechecked in a standalone harness against the
real generated `components['schemas']['GetProjectLintsResponse']`,
confirming `categories[0]` is assignable to `AdvisorCategory |
undefined` — with a negative control that correctly errored (`Type
'"HEALTH"' is not assignable to type '"PERFORMANCE" | "SECURITY" |
undefined'`) to prove the harness had teeth

No tests are added. There is no existing test coverage of
`handleItemClick` / `handleCardClick` in either ladder component, and
the change is a narrowing of one expression to match three existing call
sites rather than new logic. Asserting an emitted property value would
require standing up component tests for two components that have none,
which is a larger piece of work than this fix and better done as its own
change.

**Suggested follow-up, deliberately not in this PR.**
`createAdvisorLintItems` and the two advisors pages filter HEALTH lints
out entirely, so the category the API now returns is invisible in
Studio. Whether to surface it is a product decision about a new advisor
category, not a telemetry fix. Also out of scope by request:
`Linter.utils.tsx` badge styling (HEALTH falling back to PERFORMANCE's
badge is harmless).

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

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Pamela Chia <pamelachiamayyee@gmail.com>
2026-08-31 15:48:01 +08:00
5e8a83e11a feat(studio): add explorer_banner_exposed impression event (#49747)
<!-- ccr-slack-attribution -->
_Requested by **Pam Chia** · [Slack
thread](https://supabase.slack.com/archives/C076KTY11DF/p1788139328573799?thread_ts=1788139328.573799&cid=C076KTY11DF)_

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

Feature (telemetry). Adds one PostHog event.

Linear issue:
[GROWTH-1154](https://linear.app/supabase/issue/GROWTH-1154/telemetry-explorer-feature-preview-banner-has-no-exposure-event-so)

## What is the current behavior?

The Explorer feature preview banner emits
`explorer_banner_dismiss_button_clicked` and
`explorer_banner_cta_button_clicked` (both from
`apps/studio/components/ui/BannerStack/Banners/BannerExplorer.tsx`,
shipped in #49606), and nothing else. With no impression event there is
no denominator, so no click-through or dismiss rate can be reported.

## What is the new behavior?

`explorer_banner_exposed` fires when the banner content is rendered, at
most once per page load.

The event is declared in `packages/common/telemetry-constants.ts` next
to the two existing Explorer banner events and added to the
`TelemetryEvent` union, following the existing `*_exposed` family. It
carries no custom properties; `project` and `organization` groups are
attached by `apps/studio/lib/telemetry/track.ts`.

**Verification:**

- `prettier --check` on both changed files: passing
- `tsc --noEmit` in `packages/common`, which covers the new event
interface and the `TelemetryEvent` union: passing
- Studio-scoped lint, typecheck, and tests: green on CI
- Browser-tested on the studio-staging preview (Playwright): the
exposure event fires exactly once per page load (201 on the wire), does
not re-fire on client-side navigation or banner hover within the same
page load, fires again after a full reload, and does not fire after
dismissal; the CTA and dismiss click events are unchanged and carry the
`project`/`organization` groups

**Out of scope:**

- Pre-consent drops: every telemetry event waits for consent, so this
event degrades the same way the rest of the `*_exposed` family does
(transient, recovers on the next page load). A family-wide fix is a
separate issue.
- Mirroring the `explorer` flag state into event properties: redundant
once exposure exists.
- The CTA handler not dismissing the banner: raised separately, both
click handlers untouched.
-
[GROWTH-1153](https://linear.app/supabase/issue/GROWTH-1153/telemetry-advisorcategory-omitted-for-health-lints-on-two-of-five)
and its draft PR #49746: separate issue, no overlap.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Xwj2SotnaHByjbTfqF4Kdm); reworked
per Pam's review._

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Pamela Chia <pamelachiamayyee@gmail.com>
2026-08-31 15:47:43 +08:00
Ivan Vasilov 26e89b36c3 chore: Regenerate API types and fix all issues (#49646)
A bunch of small issues have showed up where the API types are breaking
the FE repo:
- Regenerate the API types.
- For the removed Response types, use the return types from the
operations instead.
- Fix some types which now have a suffix `_Output`.
- Add `requires_indirect_tax_declaration` property to Organization
instances in mocks.

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

## Summary by CodeRabbit

* **Refactor**
* Updated Studio and shared type references to use generated API
definitions consistently.
  * Improved typing for SSO configuration creation and updates.
  * Aligned telemetry lint categories with API-provided values.
  * Marked the legacy API type re-export as deprecated.

* **Tests**
* Updated test fixtures and response types to reflect current API
contracts.
  * Added indirect tax declaration data to organization test scenarios.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-27 17:07:58 +02:00
Joshen Lim 961fc749d4 Add feature preview banner toast for explorerd (#49606)
## Context

Adds a feature preview banner toast for the explorer - flagged behind
the configcat flag
<img width="315" height="342" alt="image"
src="https://github.com/user-attachments/assets/9dbd7ffd-02c6-4083-9ca0-266b862e1b5d"
/>


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

## Summary by CodeRabbit

- **New Features**
- Added an Explorer preview banner to project layouts when the feature
is enabled.
- Added an “Enable Explorer” call-to-action that opens the feature
preview.
  - Banner dismissal is remembered and persists across sessions.
  - Added telemetry tracking for banner dismissal and CTA interactions.

- **Bug Fixes**
- Improved banner behavior and stability when displaying database
connection notifications.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-27 14:12:04 +08:00
Joshen Lim 2d1a2ff9a2 Set up feature preview for explorer (#49602)
## Context

Sets up the Explorer behind the feature preview modal + removes the
temporary entry point from the SQL Editor
Changes are still not live on production, so will only affect local +
staging.

Enabling the feature preview will replace the sidebar nav for SQL Editor
to new Explorer (Icon remains unchanged, just the label)

<img width="918" height="647" alt="image"
src="https://github.com/user-attachments/assets/b088eb47-1176-4618-b345-d1ec0521b092"
/>


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

- **New Features**
- Added an “Explorer & Notebooks” feature preview with an overview image
and direct access to Explorer or SQL Editor.
  - Added Explorer navigation when the preview is enabled.

- **Improvements**
- Updated desktop and mobile navigation to consistently display the
available editor destination.
- Improved the Explorer shortcut tooltip to clearly say “Go to
Explorer.”
  - Organized SQL Editor previews under the Editors category.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-26 22:45:11 +08:00