mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 11:55:05 +03:00
restructure-migration-docs
271
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4c77ab5fef |
feat(telemetry): mirror org_count to PostHog person property (#45946)
## 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 + two follow-on fixes — small, scoped to telemetry / experiment plumbing. ## What is the current behavior? PostHog feature flags evaluated in Studio only have access to the `gotrue_id` person property (set in `useTelemetryIdentify`) and the `organization`/`project` group associations from pageviews. Flags can't target users by org membership without a behavioral cohort, which refreshes on a ~hourly schedule and lags behind real-time signup state. This is blocking the rollout of the `dataApiRevokeOnCreateDefault` experiment ahead of the May 30 default-privileges breaking change — we need to target brand-new dashboard signups with no prior org membership, and there's no person property to filter on. ## What is the new behavior? Three changes, scoped tightly to make experiment targeting reliable for brand-new signups: ### 1. Mirror `org_count` to a PostHog person property (`apps/studio/lib/telemetry.tsx`) The Studio `Telemetry` component now mirrors the user's current org-list length to a PostHog person property `org_count` via `posthog.identify(user.id, { org_count })`. The effect: - Subscribes to `useOrganizationsQuery` (shares the same React Query cache as `useSelectedOrganizationQuery`, so no extra network requests). - Dedupes via a ref keyed on `{ userId, orgCount }` so we only call identify when the value actually changes — handles user-switch (logout/login as different user with same count) correctly. - Generic enough to be useful beyond this experiment — analytics segmentation by org membership, future flags that depend on multi-org behavior, etc. ### 2. Merge pre-init identify properties (`packages/common/posthog-client.ts`) The previous `pendingIdentification` slot was a single-write buffer — calling `posthogClient.identify()` before the PostHog SDK initialized would overwrite any prior queued identify. Latent until this PR added a second identify caller (`org_count`), which exposed the last-write-wins behavior on first-visitor-before-consent flows. Now merges properties across pre-init calls for the same user so both `{ gotrue_id }` and `{ org_count }` land on the person record when the SDK flushes. Caught during Codex review. ### 3. Gate the exposure event on `org_count` being present (`apps/studio/hooks/misc/useDataApiRevokeOnCreateDefault.ts`) `useTrackDefaultPrivilegesExposure` previously fired on the first non-undefined value of the `dataApiRevokeOnCreateDefault` flag. For brand-new signups, this races the `org_count` identify: the initial `/flags/` response (before targeting can match) returns the untargeted variant, the exposure locks it in via `hasTracked`, then our identify fires and a subsequent `/flags/` refresh updates the flag — but the exposure has already recorded the wrong variant. Fix: gate the exposure on `org_count` being present on the SDK person, subscribing via `onFeatureFlags` so we pick up the post-identify `/flags/` response. Adds `posthogClient.getPersonProperty` as the local-state reader. Without this, the experiment would have a ~5-15% noise floor on cohort assignment for new signups. ## Verification End-to-end verified locally against the staging PostHog project (34343): - Local Studio's PostHog SDK has `$stored_person_properties: { gotrue_id: <uuid>, org_count: 1 }` after sign-in. - Both `$set` events landed server-side within ~300ms of each other, and the staging person record now shows `org_count = 1.0` with `gotrue_id` preserved. - Targeting query `person.properties.org_count == 1` works end-to-end against staging. ## Additional context Ref: [GROWTH-853](https://linear.app/supabase/issue/GROWTH-853) Targeting plan for the flag once shipped: `person.org_count == 1` plus a behavioral filter on recent `sign_up` event, at 5% rollout. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Telemetry now records and syncs the user's organization count as an analytics person property and avoids redundant identifications when unchanged. * Analytics client now merges queued identification properties made before initialization and exposes a method to read stored person properties. * **Bug Fixes** * Tracking now waits for organization-count readiness before firing certain exposure events to prevent missing data. * **Tests** * Added/updated tests to cover person-property behavior and gating logic. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45946) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
19e0b36650 | feat(logs): migrate unified logs queries to OTEL endpoint DEBUG-71 (#45642) | ||
|
|
e55411da5e |
feat(studio): Fly.io deprecation banner (#45778)
## Summary Adding an in-dashboard banner for the Fly.io May 31 suspension. Banner targets users on a Fly project (or with a Fly project in their currently-selected org) and surfaces a per-project breakdown of what's affected in a dialog. Detection is self-correcting: as soon as the user migrates off Fly, the banner disappears with no follow-up. <img width="557" height="502" alt="Screenshot 2026-05-11 at 5 08 22 PM" src="https://github.com/user-attachments/assets/7bafb712-3490-4555-9667-66e9909f1b1a" /> <img width="1675" height="536" alt="Screenshot 2026-05-11 at 3 55 06 PM" src="https://github.com/user-attachments/assets/6c1bf9d1-4dcc-4aac-a679-2ed477d2ed1c" /> ## Changes - **Detection hook** (`useFlyDeprecationProjects`): reads only from already-cached data — `useSelectedProjectQuery` for the current project, plus `useOrgProjectsInfiniteQuery` scoped to the selected org. Zero cross-org fan-out: worst case is one paginated query per session (the same one the project list page already makes). - **Banner component** (`FlyDeprecationBanner.tsx`): mounted in `AppBannerWrapper`. Dynamic title (primaries / branches / both), dialog lists affected projects with org name, numbered migration steps, links to backup/restore CLI + Dashboard backup + branching docs. List truncates to 5 entries with "…and N more." tail when more are affected. - **Telemetry**: `fly_deprecation_banner_exposed` and `fly_deprecation_banner_dismissed` events emitted via `useTrack` (auto-injects project + org groups). Properties: `primaryCount`, `branchCount`. CTA click tracking intentionally omitted — migration outcome is measured via warehouse `cloud_provider = 'FLY'` decay. - **LocalStorage**: dated dismissal key `FLY_DEPRECATION_2026_05_31`; orphan `FLY_POSTGRES_DEPRECATION_WARNING` from PR #33510 removed in the same change so users who dismissed the Feb 2025 banner still see this one. - **Support contact**: email `success@supabase.io` only (no support ticket link), per Brian's outreach copy in the Linear issues. ## Coverage trade-off Banner renders on project pages (selected-project check) and pages where the selected org's projects list is cached (org overview, project list). It does **not** render on `/dashboard` home or other pages without org context. Email outreach from GROWTH-817 / GROWTH-819 handles those users. This was a deliberate trade-off to avoid cross-org fan-out load. ## Lifecycle Banner expires `2026-06-01T00:00:00Z` (right after the May 31 deadline). Stale client bundles stop rendering it without a redeploy. Cleanup PR planned post-deadline to remove the component, hook, localStorage key, and telemetry events. ## Testing Tested on the Vercel preview with React Query cache overrides to mock a Fly project: - [x] Banner renders for a user with at least one project where `cloud_provider === 'FLY'` - [x] Banner does **not** render for a user with no Fly projects - [x] Banner does **not** render on `/sign-in` - [x] Title varies by primaries-only / branches-only / both - [x] Dialog lists affected projects with org name in parens - [x] Dialog list truncates to 5 with "…and N more." for larger sets - [x] Migration guide / Dashboard backup / branching links open in a new tab - [x] Dismiss (×) closes the banner and persists across hard reload (localStorage `fly-deprecation-2026-05-31-dismissed`) - [x] PostHog receives one `fly_deprecation_banner_exposed` per mount with `primaryCount` + `branchCount` and `$groups.organization` populated - [x] PostHog receives one `fly_deprecation_banner_dismissed` on close with the same property shape ## Linear - fixes GROWTH-817 - fixes GROWTH-819 |
||
|
|
d676c832f3 |
fix(studio): pre-empt React 19 regressions in tests + Support form (#45784)
Four React-19-sensitive patterns that pass on React 18 today but break
under React 19 (verified on the in-flight TanStack Start branch).
Landing on master now so the eventual React 19 upgrade is a no-op for
tests, instead of a separate cleanup pass under upgrade pressure.
Each fix is a strict superset / less-fragile equivalent of the existing
pattern, so master (React 18) stays green.
**Changed:**
- `hooks/misc/useStateTransition.ts` — fire on entry into `newTest` from
any state other than `newTest`, instead of requiring exactly `prevTest →
newTest`. React 18+ auto-batches dispatches across awaits (e.g.
`dispatch SUBMIT` in the handler, `dispatch ERROR` in `onError`),
collapsing `editing → submitting → error` into a single render where the
intermediate `submitting` tick is never observed. Strict superset of the
old check for our reducers — `success`/`error` are only reachable from
`submitting`.
- `Support/CategoryAndSeverityInfo.tsx` — guard `onValueChange` against
Radix Select's spurious `''` emission. When the controlled value
transitions from `undefined` to a defined value whose `SelectItem` isn't
mounted yet (dropdown closed → items haven't registered), Radix's hidden
`BubbleSelect` fires `onValueChange('')` and clobbers the field. No
`SelectItem` can have `value=""` (Radix throws), so any `''` is
guaranteed spurious — drop it before calling `field.onChange`.
([radix-ui/primitives#3381](https://github.com/radix-ui/primitives/issues/3381))
- `EditSecretModal.test.tsx` — `getByLabelText` → `findByLabelText`.
Under React 19's scheduling, the decrypted-value query resolves on a
separate render tick, so form fields appear one tick after the skeleton.
- `LogsPreviewer.test.tsx` — `addEventListener('click', spy)` instead of
`loadOlder.onclick = vi.fn()`. React 19 reassigns `.onclick` on managed
elements as part of its event wiring, clobbering the direct-property
spy.
## To test
### Unit tests
- `pnpm --filter studio test` — all unit tests pass on master (React 18)
### Support form URL prefill (Radix Select guard)
- `/support/new?category=Problem` → category dropdown reads "APIs and
client libraries" on first paint
- `/support/new?category=dashboard_bug` → "Dashboard bug"
(case-insensitive match)
- `/support/new?category=invalid_garbage` → falls back to "Select an
issue" placeholder, no crash
- `/support/new?subject=My%20issue&message=Details%20here` → subject and
message inputs are prefilled
- `/support/new?projectRef=<your-ref>&category=Problem` → both project
selector and category set, library selector appears
- With a prefilled URL, click the category dropdown and pick a different
option — the new value sticks (this is the path that surfaced the Radix
bug, want to confirm we didn't break user selection)
- DevTools console on first load should be clean — no React hydration
mismatch warning
### Support form submit (`useStateTransition` success + error branches)
- Submit a valid support form → green toast "Support request sent"
appears **once**, view swaps to the success screen, one `POST
/platform/feedback/send` in the network panel
- Block `POST /platform/feedback/send` in DevTools → submit → red error
toast appears **once** (not twice — if you see two toasts the relaxed
transition is firing more than it should), form stays editable with all
inputs preserved
- Unblock and submit again → success path runs cleanly
### Sidebar support form (same reducer + `useStateTransition`, separate
component)
- Open the support widget in the side nav (`SupportSidebarForm`)
- Repeat the success and error paths — should behave identically
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed category selector to prevent selected values from being
unexpectedly cleared during form interactions.
* **Tests**
* Improved test reliability for modal field rendering and event handling
assertions.
* **Chores**
* Clarified internal comments for form initialization logic.
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45784)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
|
||
|
|
4452e0ac2e |
Support form sidebar (#45203)
Refactors our help sidebar within Studio to include the actual support form itself when contact is selected. This PR also cleans up the initial state of the sidebar and the options within. ## To test: - Open an org and click the help icon top right - Click contact support - Submit a support ticket - Click done to return to support sidebar state <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Support form V3 and support sidebar with status button; direct-email helper and URL prefill * Success screen supports onFinish callback and customizable finish label * AI Assistant and Help options accept optional click callbacks; resource items gain keyboard/accessibility support * **Refactor** * Help panel split into home/support views with back navigation * Support components accept flexible align/className props and layout/styling tweaks * Initial URL params loader added for support form * **Tests** * New/updated tests for support flows, success screen, and help options interactions <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com> |
||
|
|
b14ecb5b1e |
fix: align grace-period banner copy on org usage page (#45652)
## 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 — copy + visibility logic on the org Usage page. ## What is the current behavior? On `/org/<slug>/usage` during a grace period, customers see two banners that read as contradictory: 1. *"Organization plan has exceeded its quota — grace period until {date}."* 2. *"You have not exceeded your Pro Plan quota in this billing cycle."* <img width="1680" height="372" alt="image" src="https://github.com/user-attachments/assets/13826260-55dd-4b55-a3dc-5afc51e6436e" /> Both are individually correct. The first is sticky from the previous cycle's overage (`org.restriction_status`); the second is a live scan over the current cycle. Neither anchors to which cycle it's talking about, so together they read like the dashboard contradicting itself. Surfaced by support off SU-368527 and SU-368395. ## What is the new behavior? - Top chrome banner copy: *"Organization exceeded its quota in the previous billing cycle / You have a grace period until {date} to bring usage back under quota."* - Inline `<Restriction />` grace-period alert switches from "is over its quota" to "went over its quota in the previous billing cycle." Same temporal anchor. - The "…in this billing cycle" summary line in `<TotalUsage>` is hidden whenever `restriction_status` is set. Mirrors the precedence rule `<Restriction />` already applies internally — backend status flag wins over the live cycle scan. <img width="1678" height="937" alt="CleanShot 2026-05-06 at 12 58 02" src="https://github.com/user-attachments/assets/df55eaed-1029-4f39-bea0-df77bcc5151e" /> ## Additional context Left the `gracePeriodOver` copy alone on purpose — it doesn't make a current-overage claim, so there's nothing to contradict, and adding "previous cycle" would muddy which cycle "previous" refers to. **Verified** - Lint and typecheck pass on `apps/studio`. **Before merge** - [ ] Load a grace-period org locally: confirm new copy on top banner and inline `<Restriction />`, and that the "not exceeded in this billing cycle" line is gone. - [ ] Copy review with support — happy to workshop wording. GROWTH-823 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Updates** * Updated grace period alert messaging to clarify organization quota status * Refined date formatting in billing restriction notifications * Modified usage display to conditionally hide certain information when account restrictions are active <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
e61853c59c |
fix(studio): clarify default privileges toggle covers tables (#45458)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated UI labels and descriptions across the Data API settings to clarify that default privileges apply to new tables only (removed references to functions). <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
dfd3eec8e9 |
feat(studio): compute metrics on project diagram Primary Database card (#45274)
## Problem The Primary Database card in the project homepage diagram showed region and instance size, but no live health data. Users had no quick way to spot a high-disk or high-CPU situation without navigating to the database report. ## Fix Added a clickable metrics row at the bottom of the Primary Database card showing CPU, Disk, and RAM as percentages, plus active/max connections when available. Each metric is color-coded (warning at 80%, destructive at 90%). Clicking the row navigates to the database observability report. The metrics are powered by a new \`useComputeMetrics\` hook that wraps the existing \`useInfraMonitoringAttributesQuery\` and \`useMaxConnectionsQuery\`, reusing the parse utilities already used by the database infrastructure section. The \`metricColor\` threshold logic is extracted into a separate util with unit tests. ## How to test - Open the project homepage for a running project - The Primary Database card should show a new bottom row: "CPU X% · Disk X% · RAM X% · Y/Z conns" - Values above 80% should appear in amber, above 90% in red - Click the metrics row and confirm it navigates to \`/project/<ref>/observability/database\` - While metrics are loading, a spinner should appear in the row - If the infra monitoring API is unavailable, the row should show "Metrics unavailable" instead of zeroes <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * Infrastructure configuration page now displays real-time compute metrics (CPU, disk, memory usage) with color-coded usage indicators based on thresholds. * Connection information is displayed when available. * Includes loading states and error handling for metric retrieval. * **Tests** * Added test coverage for metric color-coding logic. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
7f5865872a |
Enforce noUnusedLocals and noUnusedParameters in tsconfig.json + fix all related issues (#45264)
## Context Enforce `noUnusedLocals` and `noUnusedParameters` in tsconfig.json + fix all related issues |
||
|
|
75e08577c1 |
chore(studio): remove tableEditorApiAccessToggle flag (#45081)
Cleans up the `tableEditorApiAccessToggle` PostHog flag now that the gated UI is shipping to everyone. Follow-up to #45034 — the new project-creation checkbox makes the management UI a prerequisite, so no reason to keep it behind a flag. **Removed:** - `useDataApiGrantTogglesEnabled` hook - Old schemas-only multi-selector branch in the Data API settings page (the rich per-table / per-function toggles + default-privileges switch become the only UI) - Flag gate around the `<ApiAccessToggle>` section in the table editor side panel - Flag gates around `updateTableApiAccess` calls in the save pipeline (create / duplicate / update) - `tableEditorApiAccessToggleEnabled` telemetry property + stale JSDoc / docs references **Changed:** - `createTableApiAccessHandlerParams` no longer takes an `enabled` param — it was always `true` after removal ## To test - Integrations → Data API settings page: exposed tables, exposed functions, default-privileges toggle all render and save correctly - Table editor: creating, duplicating, and editing a table all run the expected Data API privilege updates - Project creation flow still works end-to-end (unchanged, but the submit telemetry no longer includes `tableEditorApiAccessToggleEnabled`) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * API access configuration is now always available in the table editor and PostgreSQL settings, removing previous conditional gating. * Simplified the "Automatically expose new tables and functions" interface by consolidating UI branches. * **Documentation** * Updated telemetry guidance and examples with current feature-flag references. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
40791f9846 |
chore(studio): migrate useHotKey to useShortcut (#45099)
## Summary - Migrates all 11 `useHotKey` call sites across 9 files to `useShortcut`, backed by `SHORTCUT_DEFINITIONS` in `state/shortcuts/registry.ts`. - Adds 10 new registry entries (all `showInSettings: false` to keep behavior identical to today — these were not previously user-configurable). - Deletes `apps/studio/hooks/ui/useHotKey.ts`. - Simplifies `ActionBar.handleSave` — the legacy hook passed a `KeyboardEvent` the callback used for `preventDefault`/`stopPropagation` and a textarea-plain-Enter guard; all of that is redundant under `useShortcut` (TanStack handles default/propagation; `Mod+Enter` never fires on plain Enter). - Removes a stale commented-out `useHotKey` reference in `DataTableFilterCommand.tsx`. Part of FE-3025 (legacy hotkey hook cleanup). `useKeyboardShortcuts` in `grid/components/common/Hooks.tsx` will be migrated in a follow-up. ## Test plan All shortcuts should still fire with **Cmd** (macOS) / **Ctrl** (Win/Linux). **Table Editor — operation queue** (requires pending unsaved edits on a row) - [x] `Cmd+S` saves pending edits - [x] `Cmd+.` toggles the operation queue side panel - [x] `Cmd+Z` undoes the latest edit and re-fetches the affected table rows - [x] With no pending edits, none of the above fire (gated by `isEnabled`) **Table Editor — side panel editor forms** (row, table, column, policy, etc.) - [x] `Cmd+Enter` submits the form when the panel is visible - [x] Does not submit if the form is disabled/loading or the panel is hidden **Unified Logs — data table** - [x] `Cmd+B` toggles the filter controls sidebar (desktop) - [x] `Cmd+B` opens the filter drawer (mobile, `<sm` breakpoint) - [x] `Cmd+Esc` resets active column filters (reset button visible) - [x] `Cmd+U` resets column order + visibility - [x] `Cmd+J` toggles live mode **Unified Logs — reset focus** - [x] `Cmd+.` blurs the currently focused element / resets focus to body **AI Assistant panel** - [x] While editing a message, `Cmd+Esc` cancels the edit **Regression checks** - [x] `pnpm --filter=studio typecheck` passes (verified locally) - [x] None of the new shortcut entries appear in Account → Preferences → Keyboard shortcuts (all `showInSettings: false`) - [x] Existing shortcuts (`Cmd+K`, `Cmd+I`, `Cmd+E`, results copy/download) still work unchanged <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Refactor * Implemented a centralized keyboard shortcut registry system for managing shortcuts consistently across the application * Updated multiple UI components throughout the interface to use the new shortcut management system * All existing keyboard shortcuts continue to function without any changes in behavior or user experience ## Chores * Removed legacy keyboard shortcut hook implementation <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d1a7d64e63 |
[FE-3023] feat(studio): default privileges toggle at project creation (#45034)
<img width="783" height="414" alt="Screenshot 2026-04-20 at 3 02 37 PM" src="https://github.com/user-attachments/assets/a353c35a-3de5-4bfa-ab31-829c79c43165" /> Adds a "Default privileges for new entities" checkbox under "Enable Data API" in both the main create flow and the Vercel deploy-button flow. Default checked (current behaviour). When unchecked, runs `buildDefaultPrivilegesSql('revoke')` after the base init script so new entities in `public` aren't auto-granted to `anon` / `authenticated` / `service_role`. This PR decouples the two surfaces: - **`tableEditorApiAccessToggle`** — unchanged; still gates only the integrations → Data API settings UI. - **`dataApiRevokeOnCreateDefault`** (new) — controls only the default state of the new checkbox at project creation. `true` → checkbox unchecked by default (revoke runs); `false`/absent → checkbox checked by default (no behaviour change). The new flag is already live in PostHog at **0% rollout, off for everyone**, so shipping this PR changes nothing until the flag is explicitly flipped. ## Added - `apps/studio/hooks/misc/useDataApiRevokeOnCreateDefault.ts` — reads the new PostHog flag. Returns `false` in `IS_TEST_ENV` so existing E2E flows don't silently change default behaviour. - Checkbox UI in `SecurityOptions.tsx` (main flow) and `pages/integrations/vercel/[slug]/deploy-button/new-project.tsx` (Vercel flow), with copy matching the integrations → Data API settings page. - Tooltip + dimmed state for the main-flow checkbox when "Enable Data API" is unchecked (can't configure default privileges if Data API is off). - Telemetry: `dataApiDefaultPrivilegesGranted` (raw checkbox value) and `dataApiRevokeOnCreateDefaultEnabled` (raw flag, conditionally included using the existing raw-flag pattern so undefined flag state → omitted property, not `false`). - Vitest unit tests for the new hook. ## Changed - `pages/new/[slug].tsx`: removed the `false &&` rollback guard. Revoke SQL now runs only when `dataApi && !dataApiDefaultPrivileges`. Dropped the now-unused `useDataApiGrantTogglesEnabled` import. - `pages/integrations/vercel/[slug]/deploy-button/new-project.tsx`: this flow was **never rolled back** — it still ran revoke whenever `tableEditorApiAccessToggle` was on for a user. Now correctly gated on the new flag + checkbox state. - `packages/common/telemetry-constants.ts`: added the two new properties and corrected the `tableEditorApiAccessToggleEnabled` docstring (it no longer claims to control project-creation revoke behaviour). ## Kill switch Flipping `dataApiRevokeOnCreateDefault` to off in PostHog fully disables the revoke SQL for new projects without needing a redeploy — the checkbox just defaults to checked again. ## Follow-ups (not blockers) - joshenlim's review comments on PR 43704: (1) Auth Policies table row incorrectly showing "exposed via Data API" based on schema-level check instead of table-level at `apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/index.tsx:64`; (2) Data API integrations page showing zero exposed tables even after exposing one. Both unrelated to this PR but will be more visible once the checkbox lands. - Once this flag fully rolls out, the old `tableEditorApiAccessToggle` docstring/comments elsewhere should stop claiming it controls project creation. ## To test - **Flag off (default state, simulates post-merge):** create a project with and without "Enable Data API" checked. The new "Default privileges for new entities" checkbox should default to **checked**. Submitting should produce an identical result to today — new tables in `public` are reachable via the Data API. - **Flag on (simulate rollout):** override the flag locally. The checkbox should default to **unchecked**. Creating a project with it unchecked should run the revoke SQL; create a new table in `public` afterwards and confirm it's not reachable via the Data API until grants are added. - **Enable Data API off:** the new checkbox should render disabled + dimmed with a tooltip reading "Enable the Data API to configure default privileges." The revoke SQL should not run in this case regardless of checkbox state. - **Vercel flow:** repeat at `/integrations/vercel/<slug>/deploy-button/new-project` — verify both checkbox states. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added an "Automatically expose new tables and functions" checkbox to project creation and Vercel deploy flow; enabled only when Data API is available (disabled with tooltip otherwise) and affects initial project provisioning. * **Telemetry** * Tracks exposure of the default-privileges control and includes checkbox state and feature-flag status on project-creation submissions. * **Tests** * Added tests for flag behavior, exposure tracking, deduplication, and submission telemetry. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Sean Oliver <882952+seanoliver@users.noreply.github.com> |
||
|
|
19027e73f8 |
[FE-3036] feat(studio): runtime env var overrides for enabled features (#45049)
Lets self-hosted Studio toggle flags in `enabled-features.json` at container start time via `ENABLED_FEATURES_*` env vars, without rebuilding the prebuilt image. Addresses [FE-3036](https://linear.app/supabase/issue/FE-3036/allow-enabled-featuresjson-flags-to-be-overridden-via-env-vars) and is a prerequisite for [COM-205](https://linear.app/supabase/issue/COM-205/add-feature-flag-to-disable-all-logs-in-studio). **Added:** - `packages/common/enabled-features/overrides.ts` — pure parser that maps `ENABLED_FEATURES_*` env vars to a disabled-features list (forward-only key mapping, boolean validation, typo warnings) + 10 vitest tests - `apps/studio/pages/api/enabled-features-overrides.ts` — Next.js API route reading `process.env` at request time; no-op (`{ disabled_features: [] }`) when `IS_PLATFORM` - `apps/studio/data/misc/enabled-features-override-query.ts` — React Query hook with `staleTime: Infinity`, `enabled: !IS_PLATFORM` - `packages/common/enabled-features/README.md` — docs the env var convention, resolution order, `IS_PLATFORM` gating, and the `Support.constants.ts` build-time caveat **Changed:** - `apps/studio/hooks/misc/useIsFeatureEnabled.ts` — merges the override's `disabled_features` with `profile.disabled_features` ### Env var shape One var per flag, prefixed `ENABLED_FEATURES_`. Feature key → env name: uppercase with every non-alphanumeric char replaced by `_`. ```bash ENABLED_FEATURES_LOGS_ALL=false ENABLED_FEATURES_BRANDING_LARGE_LOGO=true ``` Values are `true`/`false` case-insensitively. Other values and prefixed vars that don't match a known feature are logged and ignored. ### Resolution order (runtime, Studio only) 1. `ENABLED_FEATURES_*` (self-hosted, via API route → React Query → hook) 2. `profile.disabled_features` (hosted, from `/platform/profile`) 3. `enabled-features.json` static value 4. Default (enabled) `ENABLED_FEATURES_OVERRIDE_DISABLE_ALL` still short-circuits everything. ### Known limitation `apps/studio/components/interfaces/Support/Support.constants.ts:4` calls `isFeatureEnabled('billing:all')` at module load to build `CATEGORY_OPTIONS`, which is spread into Zod form schemas. That call site stays resolved from the JSON — documented in the package README. `billing:all` isn't on the radar for self-hosted runtime toggling. ## To test - `cd packages/common && pnpm exec vitest run enabled-features` — 10 new tests pass - `pnpm --filter studio run typecheck` clean - Spin Studio locally with `NEXT_PUBLIC_IS_PLATFORM=false` and `ENABLED_FEATURES_LOGS_TEMPLATES=false`; `/project/[ref]/logs/explorer/templates` should reflect the flag after the override fetch resolves - Confirm the API route returns `{ disabled_features: [] }` when `NEXT_PUBLIC_IS_PLATFORM=true` - Set a typo like `ENABLED_FEATURES_LOGS_TMEPLATES=false` and check the warning in container logs; flag stays enabled <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Runtime feature-flag overrides for self-hosted deployments (env var driven), new API endpoint and client-side hook to fetch overrides, and client logic now merges profile and runtime overrides. * **Documentation** * Added comprehensive README describing the feature-flag system and override configuration. * **Tests** * Added unit tests for override parsing and E2E tests covering runtime override behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
2349f76e18 |
fix(studio): guard no-op advisor dismissal localStorage updates (#45031)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Bug fix. ## What is the current behavior? Advisor dismissals use `useLocalStorageQuery`. When advisor signals pruning ran, it sometimes invoked `setDismissedKeys` even when nothing needed to change (no-op updater returning the same array reference). Separately, `useLocalStorageQuery` would still persist + `invalidateQueries` even when the computed next value was reference-equal to the current cached value. When `useAdvisorSignals` is mounted in two places at once (`AdvisorSection` + `AdvisorPanel`), those redundant invalidations / subscriber churn could occasionally cascade into React’s “Maximum update depth exceeded” error (often surfaced via Radix `composeRefs` in stack traces). CI saw this as an unhandled error during `AdvisorSignals.integration.test.tsx`. ## What is the new behavior? - `useLocalStorageQuery` now **early-returns** when `Object.is(next, current)` so no-op updates don’t write localStorage or invalidate the query. - `useAdvisorSignals` pruning effect now **short-circuits** unless there is actually a stale banned-IP dismissal to remove. ## Additional context Follow-up from #44372 (advisor signal items for banned IPs). Tests run locally: - `pnpm --filter studio exec vitest run components/ui/AdvisorPanel/useAdvisorSignals.test.tsx components/ui/AdvisorPanel/AdvisorSignals.integration.test.tsx hooks/misc/__tests__/useLocalStorageQuery.test.ts` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Enhanced handling of dismissed security alerts by preventing unnecessary state updates for stale dismissals, significantly reducing overhead and improving overall application performance. * Optimized local storage operations to skip redundant writes to storage and prevent triggering unnecessary cache updates and query invalidations when stored data values remain unchanged from the previous operation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b721a2d780 |
feat(studio): advisor signal items for banned IPs (#44372)
## What kind of change does this PR introduce? Feature. Resolves DEPR-430. ## What is the current behaviour? The homepage Advisor summary, shared Advisor panel, and top-nav Advisor indicator only surface lints and notifications. Banned IPs are not represented as dismissible Advisor items, so network bans are easy to miss unless a user visits Database Settings directly. The `public bucket allows listing` warning is no longer part of this PR. That warning will move to a follow-up Splinter `WARN` lint so it can flow through the standard lint surfaces instead of a bespoke Studio signal path. ## What is the new behaviour? - adds a new Advisor `signal` source for banned IPs on the platform homepage, in the shared Advisor panel, and in the top-nav Advisor indicator - keeps dismissals client-side only for now, scoped by project and exact IP fingerprint - keeps banned IP signals at `warning` severity because they still indicate suspicious traffic and remain actionable if a user wants to review or remove a ban - leaves `/project/[ref]/advisors/security` as follow-up work because that surface is still lint-native, and banned IPs are management-plane signals rather than Splinter lints | After | | --- | | <img width="1728" height="997" alt="Mallet Toolshed Supabase-65A60B4A-107E-4D79-B9A8-23F754BEAB08" src="https://github.com/user-attachments/assets/c08ecbbb-c302-43bd-81bb-6ba7eb18b7b3" /> | ## Reviewer testing notes 1. Use a throwaway project. 2. Get the database connection string for that project. 3. Attempt to connect with the wrong password 3-4 times until you hit an `ECONNREFUSED`-style error, which should mean your IP has been banned. 4. Refresh Studio and confirm the project overview shows the new `Banned IP address` signal. 5. Open the Advisor Center and confirm: - the top-nav Advisor dot turns warning yellow - the signal detail shows `Entity`, `Issue`, and `Resolve` - `Edit network bans`, `Dismiss`, and `Learn more` are present 6. Open Database Settings > Network bans and confirm your banned IP appears there and can be unbanned. 7. Note that `/project/[ref]/advisors/security` will not show this item. That page is still lint-only, and this banned IP work is a short-term client-side signal rather than a true lint. Longer term, we likely want a more durable event model here so banned IPs can power notifications, webhooks, emails, and other project-level alerts. --------- Co-authored-by: kemal <hello@kemal.earth> Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
3ed436de74 |
feat: new shortcuts hook with registrations (#44954)
## 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? - Brand new hook APIs for registering shortcuts using tanstack hotkeys - Support for command menu injection when shortcut is added <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Centralized keyboard shortcuts system with per‑shortcut registration and per‑user enable/disable preferences stored locally * Added a "Copy results as Markdown" shortcut (Mod+Shift+M) * Shortcuts can be surfaced in the Command Menu with a visual shortcut badge for discoverability * **Documentation** * Legacy keyboard shortcut hooks marked as deprecated and documentation updated to point to the new shortcut API <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
dd41a34706 |
[FE-2478] feat(studio): simplify Connect modal for HA projects (#44695)
Simplify the Connect modal for Multigres/High Availability projects. Pooling is always on for these projects, so the connection method distinction doesn't apply. **Removed:** - Connection Method selector (Direct/Transaction/Session) for HA projects - IPv4 add-on panel for HA projects - Pooler badge (Shared/Dedicated) for HA projects **Changed:** - "Type" label renamed to "Connection Type" for HA projects - Default connection method set to `transaction` (instead of `direct`) for HA projects Non-HA projects are completely unaffected. ## To test - Open Connect sheet → Direct tab on a **non-HA project** — verify everything looks the same as before - Open Connect sheet → Direct tab on an **HA project** — verify: - No Connection Method radio selector - Label reads "Connection Type" instead of "Type" - No IPv4 status panel - No pooler badge - Connection string displays correctly <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Connection UI now adapts for high-availability projects: hides pooler options and IPv4 status, and updates the connection type label for clarity. * **Tests** * Added tests covering connection configuration behavior when a project is high-availability. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
3cb440e844 |
fix(studio): fix multiple Sentry errors (#44715)
## Summary - [**SUPABASE-APP-E2R**](https://supabase.sentry.io/issues/SUPABASE-APP-E2R): Guard against undefined entries in notifications array in `AdvisorButton` (optional chaining on `.some()` callbacks) - [**SUPABASE-APP-EBA**](https://supabase.sentry.io/issues/SUPABASE-APP-EBA): Remove render-time `handleError()` throw in `useEdgeFunctionsDiff` — the hook already handles missing body data gracefully - [**SUPABASE-APP-BVN**](https://supabase.sentry.io/issues/SUPABASE-APP-BVN) / [**SUPABASE-APP-BTV**](https://supabase.sentry.io/issues/SUPABASE-APP-BTV): Guard `localStorage` access in `FeaturePreviewContext` with try-catch, matching the established pattern in `useLocalStorage.ts` (Safari private browsing) - [**SUPABASE-APP-AV3**](https://supabase.sentry.io/issues/SUPABASE-APP-AV3): Filter stale folder IDs before passing `expandedIds` to `react-accessible-treeview` in the SQL editor nav ## Test plan - [x] Verify AdvisorButton renders without errors when notifications data has sparse pages - [x] Verify branch merge page loads when edge function body fetch fails - [x] Verify feature previews initialize correctly in Safari private browsing - [x] Verify SQL editor folder expand/collapse works after deleting a folder <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Feature preview now falls back safely when browser storage is unavailable * Notifications display updated to tolerate missing entries without errors * Private snippets navigation no longer preserves expansion state for removed nodes * **Refactor** * Streamlined error aggregation in edge functions diff processing <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
73692b0a4d |
feat(studio): add stuck pausing and restoring escalations (#43368)
## What kind of change does this PR introduce? Bug fix / UX improvement for long-running project transitions. Resolves DEPR-362. ## What is the current behaviour? - `PausingState` does not preserve elapsed time across refreshes, so the stuck escalation can disappear for the same user. - `RestoringState` relies on weaker frontend heuristics and always showed a support CTA in the footer even before the restore was clearly long-running. ## What is the new behaviour? - `PausingState` - Persists a per-project pause start time in local storage so the stuck CTA survives refreshes in the same browser. - Escalates after 10 minutes. - Clears the stored timer when pausing succeeds or fails. - `RestoringState` - Persists a per-project restore start time in local storage so the stuck CTA survives refreshes in the same browser. - Removes the always-visible footer CTA and only escalates once restoration is genuinely long-running. - Computes the long-running threshold from volume size using a shared restore estimate: `max(10, ceil(estimateRestoreTime(sizeGb) * 1.5))`. - Clears the stored timer when restoration succeeds or fails. - Shared changes - Extracts reusable transition timing helpers and restore estimate helpers with unit tests. - Reuses the same restore estimate formula for branch restore timing and restore escalation, so the two do not drift. | `PausingState` | `RestoringState` | | --- | --- | | <img width="1570" height="906" alt="Krosno Toolshed Supabase-C6D7E29F-C38D-43E1-8AF9-C612B6A2FD8D" src="https://github.com/user-attachments/assets/e0bd9434-09b6-4cf6-bffa-07a0ddcdf5db" /> | <img width="1570" height="906" alt="Krosno Toolshed Supabase-51F4763D-B798-4B41-A92D-43B3CF8ECDAF" src="https://github.com/user-attachments/assets/d0e47356-dcc3-42aa-b602-802a35249a16" /> | ## Additional context - This PR intentionally stays frontend-only. - We are not exposing backend lifecycle timestamps here; local storage is the stopgap to improve the same-browser experience now. - If you need to test the frontend blocker states locally, use [`dnywh/chore/depr-362-blocker-preview-mocks`](https://github.com/supabase/supabase/tree/dnywh/chore/depr-362-blocker-preview-mocks) and append one of the following query params to a project URL: - `?mockProjectBlockingState=pausing` - `?mockProjectBlockingState=pausing-long-running` - `?mockProjectBlockingState=restoring` - `?mockProjectBlockingState=restoring-long-running` - I know these two views are quite differently stylistically, and will consolidate later - References DEPR-434 |
||
|
|
180ce515f6 |
style: require @ imports and sort imports for studio/hooks (#44444)
* **Chores** * Updated internal module import paths across hook files to use standardized path aliases for improved code consistency and maintainability. |
||
|
|
55e0b34a18 |
fix(studio): add option to treat empty CSV cells as NULL on import (#43281)
When importing a CSV file, empty cells were always imported as empty strings with no way to import NULL values instead. This adds a "Treat empty cells as NULL" checkbox to the import configuration panel. When enabled, PapaParse's transform option converts empty strings to null before the data is parsed and previewed, so the imported rows correctly contain NULL rather than empty strings. Fixes #43258. ## What kind of change does this PR introduce? Bug fix ## What is the current behavior? Empty cells in a CSV file are always imported as empty strings with no way to import NULL values instead. Fixes #43258. ## What is the new behavior? "Treat empty cells as NULL" checkbox is added to the import configuration panel. When enabled, empty cells are imported as NULL instead of empty strings. Toggling the checkbox instantly re-parses the preview. ## Additional context The fix uses PapaParse's transform option to convert empty strings to null before parsing. Applies to both file uploads and pasted text. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com> |
||
|
|
dcab88059b |
fix: minor sentry issues (#44148)
## 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? fixes: - [SUPABASE-APP-ER2](https://supabase.sentry.io/issues/7360649020/?project=5459134) - [SUPABASE-APP-ERM](https://supabase.sentry.io/issues/7361072759/?project=5459134) --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
2e1795dfa0 |
feat(studio): add pagination to query performance page FE-2774 (#43697)
## Problem The Query Performance page loaded all results in a single query with a fixed limit of 20 rows, giving users no way to browse beyond the first page. There was also no way to control how many rows were shown at once. ## Fix adds pagination ## How to test - Navigate to `/observability/query-performance` in Studio - scroll to bottom - should automatically load more results --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
d571c7404a |
chore: refactor <PreventNavigationOnUnsavedChanges> by extracting a usePreventNavigationOnUnsavedChanges hook (#43900)
## Problem We want `ui-patterns` to contain only visual components but https://github.com/supabase/supabase/pull/43577 introduced a component with logic about navigation ## Solution Extract the logic part into a hook and use it in the component. Next step will be to remove this component and use `<DiscardChangesConfirmationDialog>` directly along the hook where needed ## How to test Check that the fixes from #43577 still work: On staging, for each case: - Authentication email templates - Observability reports - Edge functions creation - Edge functions edition Test: - Modify the template/report/function - Navigate away using either the sidebar link, the browser back button or closing the tab - Cancel navigation in the confirmation dialog - Navigation should be prevented and you should not loose your changes Test: - Modify the template/report/function - Navigate away using either the sidebar link, the browser back button or closing the tab - Confirm navigation in the confirmation dialog - Navigation should not be prevented and you should have lost your changes |
||
|
|
4336c8cf5a |
fix(observability): use 30m step for 7-day dashboard to preserve spikes FE-2813 (#43998)
## Problem The database observability dashboard flattens critical spikes when viewing the 7-day window. A spike clearly visible at the 3-hour view (2-minute resolution) disappears completely at the 7-day view because the Prometheus query step was 1 hour, averaging each spike into a 60-minute bucket and reducing its apparent magnitude to near zero. ## Fix Increase the granularity in the 7 day window to prevent spikes from being flattened. Data point counts: 7-day view goes from ~168 to ~336 points per series, more consistent with the existing 12-hour view (~360 points). ## How to test - Open the observability database dashboard for a project that has had a recent CPU, RAM, or connection spike - Select the "Last 3 hours" time window and confirm the spike is visible - Switch to "Last 7 days" and confirm the same spike is now visible (previously it would disappear) - Confirm all other time windows (10m, 30m, 1h, 24h) still load and display correctly --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
b14ef270b2 |
feat: add shortcuts for copy markdown, json or download CSV (#43929)
## 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 copy markdown as a keyboard extension - Add copy json as keyboard extension - Add download CSV as keyboard extension All extensions can be toggled off ## Demo https://github.com/user-attachments/assets/c3390b0a-8350-4708-9aeb-7b73aa3b423c --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> |
||
|
|
be26feb9ba |
Chore/shift manual queries into pg meta 03 (#43951)
## Context Shifting more dashboard queries into pg-meta so that we centralize all manually written queries in one place Having them in packages/pg-meta also allows us to write tests for them ## To test Just needs a smoke test on - Table Editor - Fetching entities - Viewing definition - SQL Editor - View ongoing queries - Abort queries - Integrations - Queues - Database - Migrations -Triggers (Updating) |
||
|
|
9fa96977be |
chore: Minor prettier fixes (#43849)
This PR fixes some prettier issues: - Bump and unify all prettier versions to 3.7.3 across teh whole repo - Bump the SQL prettier plugin - When running `test:prettier`, check `mdx` files also - Run the new prettier format on all files --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
83592b1932 |
feat(billing): show billing address modal for paid orgs with missing address (#43480)
### Summary This PR adds a dismissable modal that prompts paid org users to fill in their billing address. We need billing addresses for tax compliance and the existing banner hasn't been as effective (~10k orgs still missing). The modal shows on page load when all of these are true: - ConfigCat flag `enableBillingAddressModal` is on - Org is on a paid plan (not free) - Org does not have billing address set - Org is not partner-managed - User has BILLING_WRITE permission on stripe.customer The modal can be dismissed via the close button, but re-opens on every page navigation. Once the user saves a valid address, the organizations query is invalidated and organization_missing_address flips to false - the modal stops appearing permanently. <img width="1256" height="703" alt="Screenshot 2026-03-05 at 4 22 11 PM" src="https://github.com/user-attachments/assets/57e7d1b8-b3b6-4366-ad23-60910a0defe8" /> ### Testing #### Automated Tests I've added unit tests in this PR #### Manual testing Manual test cases: - Free org - modal does not appear - Partner-managed org - modal does not appear - User with "developer role" modal does not appear - Configcat Flag disabled - modal does not appear - Dismiss modal, navigate to another page - modal re-opens - Fill form and save - modal closes and does not reappear - API failure loading billing data - shows error state with Retry button --------- Co-authored-by: Ignacio Dobronich <ignacio@dobronich.com> |
||
|
|
b2fdc7687f | feat: Implement telemetry on Search commands (#43563) | ||
|
|
0aa23980bb |
remove tableCreateGeneratePolicies experiment (failed variant) (#43498)
## Problem The `tableCreateGeneratePolicies` A/B experiment tested an AI-assisted policy generator (`RLSManagement`) as a variation in the table creation side panel. The variation didn't pass — control wins, so the standard RLS checkbox should be the permanent behavior. ## Changes - Deleted `useTableCreateGeneratePolicies` hook (PostHog flag + exposure tracking) - Deleted the entire `RLSManagement/` component directory (variation UI — `RLSManagement`, `PolicyList`, `PolicyListEmptyState`, `ToggleRLSButton`) - Removed experiment flag checks from `TableEditor.tsx` — RLS checkbox is now always rendered (was already the control) - Removed experiment conversion tracking from `SidePanelEditor.tsx` ## Testing Verified `pnpm typecheck` passes clean. Table creation side panel renders the RLS checkbox unconditionally as it did in the control. GROWTH-653 |
||
|
|
ebec20f542 |
chore: prevention of used leaked passwords entitlement (#43410)
### Changes - Replaces the isPaid plan-based check on the "Prevent use of leaked passwords" (PASSWORD_HIBP_ENABLED) setting with a proper entitlement check using the `password_hibp` entitlement key - Adds a new `useHasEntitlementAccess` hook that returns a reusable checker function for any entitlement key, backed by the same cached entitlements query ### Testing - Head to `/project/_/auth/providers?provider=Email` with an Org on the Free Plan - Assert that the "Prevent use of leaked passwords" toggle is disabled. - Head to `/project/_/auth/providers?provider=Email` with an Org on the Pro Plan - Assert that the "Prevent use of leaked passwords" toggle is enabled and can be toggled and saved. <img width="612" height="496" alt="image" src="https://github.com/user-attachments/assets/fc1ccc79-016c-4265-96ac-bdb458d2a8de" /> |
||
|
|
9f8536584c |
chore: remove maybeShowUpgradePrompt for entitlement-based gate (#43457)
### Changes - Remove maybeShowUpgradePrompt (plan-based) in favor of maybeShowUpgradePromptIfNotEntitled (entitlement-based) - Replaced the `maybeShowUpgradePrompt` with a `hasAccessToHelper` callback to default the date selection to a safe default so pages don't load with an out-of-range date. ### Testing - With an Org on the Free Plan, head to `/project/_/observability/api-overview?its=2026-03-04T15:06:50.704Z&ite=2026-03-20T15:06:50.704Z`. Notice that the end date in the URL is 16 days after the start date. - Assert that the actual range defaults to the entitled range of 1 day. <img width="467" height="483" alt="image" src="https://github.com/user-attachments/assets/e17c6957-3ece-4956-87aa-30cf62c84acd" /> |
||
|
|
aef1d70351 |
chore(studio): standardise discard changes behaviour (#43201)
## What kind of change does this PR introduce?
UX consistency improvement. Updates DEPR-355.
## What is the current behavior?
Discard-confirm close behavioir is implemented inconsistently across
Studio forms:
- some sheets/dialogs used `useConfirmOnClose`
- some duplicated local `CloseConfirmationModal` components
- some (e.g. `CreateHookSheet`) closed unconditionally and could lose
unsaved changes
## What is the new behavior?
Extracts and validates a reusable discard-close pattern for
dialogs/sheets
- enhances `useConfirmOnClose` with `handleOpenChange(open)` for
`Dialog`/`Sheet` `onOpenChange`
- adds shared `DiscardChangesConfirmationDialog` (`AlertDialog`-based,
override-able copy)
- migrates:
- `InviteMemberButton`
- `CreateHookSheet`
- `EditSecretSheet`
This standardizes close-guard behavior for
backdrop/escape/close-button/cancel-button flows without trying to block
route changes or arbitrary unmounts.
## Additional context
`CreateHookSheet` now also marks the generated secret action as dirty
(`setValue(..., { shouldDirty: true })`) so the discard guard behaves
correctly.
- Added tests for `useConfirmOnClose` covering:
- clean vs dirty close
- handleOpenChange(true|false)
- confirm/cancel behavior
- latest callback ref behavior
A follow-up PR is needed to migrate remaining duplicated
`CloseConfirmationModal` usages and older `useConfirmOnClose` call sites
to the shared `DiscardChangesConfirmationDialog` + `handleOpenChange`
pattern.
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
|
||
|
|
ddd94a9c24 |
Joshen/fe 2660 clean up stale feature flags enabled for 2 months part 2 (#43331)
## Context Follow up from https://github.com/supabase/supabase/pull/43329, but mutually exclusive Just cleaning up feature flags that have been toggled on for all users and unchanged for the past 2 months - edgefunctionreport - storagereport - realtimeReport - postgrestreport - authreportv2 - newEdgeFunctionOverviewCharts - apiReportCountries (Already not used) - SentryLogDrain - reportGranularityV2 - storageAnalyticsVector - ShowIndexAdvisorOnTableEditor |
||
|
|
564f4f66ee |
Joshen/fe 2660 clean up stale feature flags enabled for 2 months part 1 (#43329)
## Context Just cleaning up feature flags that have been toggled on for all users and unchanged for the past 2 months - advisorRules - newJwtSecrets - isWorkOSTPAEnabled - EnableOAuth21 - gitlessBranching - showRefreshToast - awsPrivateLinkIntegration - useBedrockAssistant (Already not used) - enableStripeSyncEngineIntegration - ShowExplainWithAiInQueryPerformance Doing it in 2 parts so its easier for review |
||
|
|
dcc5703674 |
feat(branching): add-pg-delta-diff-for-branching (#42952)
Allow to use the `pg-delta` capability for merge requests diffing. Feature flag it behind an auto opt-in flag. Must be merged after: https://github.com/supabase/platform/pull/29776 <img width="921" height="623" alt="Screenshot 2026-02-17 at 16 50 38" src="https://github.com/user-attachments/assets/bfe704e9-4137-45e1-b0b5-1cecce284d6e" /> Also updated the loading + final state of the diff view to: 1. Take all the height available - From: <img width="1894" height="893" alt="Screenshot 2026-02-16 at 20 46 15" src="https://github.com/user-attachments/assets/22ed8c72-2d9d-4b68-b315-6d40aefc0b3c" /> - To: <img width="1629" height="1396" alt="Screenshot 2026-02-16 at 20 57 26" src="https://github.com/user-attachments/assets/6e83c8e9-607d-4077-977e-046058ce3e44" /> 2. Show a proper loading state rather than just a plain grey skeleton - From: <img width="2232" height="1137" alt="Screenshot 2026-02-20 at 15 02 51" src="https://github.com/user-attachments/assets/0c924b04-d60f-49b5-a5a0-3bf1942bfdef" /> - To: <img width="2231" height="1129" alt="Screenshot 2026-02-20 at 15 05 46" src="https://github.com/user-attachments/assets/49751001-1818-4842-a0c8-b74683c2e9bc" /> |
||
|
|
22ff9b2d81 |
chore(studio): session expired dialog (#43122)
## What kind of change does this PR introduce? UI improvement ## What is the current behavior? The session expired dialog is quite hard to parse when, for most people, the ask is simple. ## What is the new behavior? Improved session expired dialog: - Refactored to use AlertDialog - Clarified copywriting - Uses the new AlertCollapsible to hide all the complicated debugging steps under a toggle - This component is documented in the design-system | Before | After | | --- | --- | | <img width="1024" height="563" alt="Supabase-B1728A05-DDD2-4A50-AED4-D62EAA2E7D7C" src="https://github.com/user-attachments/assets/771f85d8-21ea-42b5-99f5-b9b05f5617dd" /> | <img width="1024" height="563" alt="Storage Supabase" src="https://github.com/user-attachments/assets/b2fcab68-fb29-4cb9-bd42-aecc57b9fa32" /> | | <img width="1024" height="563" alt="Supabase-B1728A05-DDD2-4A50-AED4-D62EAA2E7D7C" src="https://github.com/user-attachments/assets/771f85d8-21ea-42b5-99f5-b9b05f5617dd" /> | <img width="1024" height="563" alt="Storage Supabase" src="https://github.com/user-attachments/assets/babd3711-5fdf-43b9-be06-d96268a191fd" /> | ## To test In apps/studio/hooks/misc/withAuth.tsx: ```diff - const [isSessionTimeoutModalOpen, setIsSessionTimeoutModalOpen] = useState(false) + const [isSessionTimeoutModalOpen, setIsSessionTimeoutModalOpen] = useState(true) // Mocked as true for UI testing ``` --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
31a85bcb97 |
Final clean up for useQueryStateWithSelect (#43008)
## Context Final clean up of `useQueryStateWithSelect` - removes the hook |
||
|
|
2f0197ac38 |
chore: realtime max message size entitlement (#41409)
Adds the Realtime max message size entitlement
### Testing
- Head to `project/_/realtime/settings` with an Org on the Pro with the
Spend Cap disabled
- Assert that the `Max payload size in KB` cannot exceed 3000
- Repeat the steps for max concurrent users and max presense events per
second
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Realtime settings now automatically reflect your subscription
entitlements with dynamic maximums for payload size, concurrent user
limits, and event rates.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
4651480f28 |
Joshen/fe 2540 fix safari csv drag drop typeerror in table editor (#42852)
## Context Addresses an error when drag and dropping a CSV in the Table Editor when the table is empty, specifically on Safari leading to a `undefined is not an object (evaluating 'n.type')` error For context, Safari obscures the item data from the drag event and only exposes it on the drop event ([ref](https://github.com/mdn/browser-compat-data/issues/24898)) hence why this issue ## Changes involved Am opting to change the UX instead of fixing this browser specific behaviour - Ignore file validity when dragging, let the on drop handle validate the type and reject unsupported files instead - This is better either way as currently our Table Editor shows "CSV files only", when we actually also support TSV files - Also made a slight adjustment to the drag over UI - border around the grid empty area, rather than the whole grid - Before: <img width="1151" height="911" alt="image" src="https://github.com/user-attachments/assets/049199aa-86bc-4e88-8444-5a7ee236c8d0" /> - After: <img width="1150" height="912" alt="image" src="https://github.com/user-attachments/assets/698ca8f3-a326-4a82-b1b4-4448aa8d777a" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Simplified the empty-table display and CSV import interface for a more consistent user experience. * Import button and drag-and-drop hints now remain visible when the table is empty, removing prior conditional hiding during drag. * Streamlined empty-state styling and messaging for a cleaner, more predictable appearance. * **Tests** * Updated end-to-end test expectations to reflect the persistent empty-state message during drag-over. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
c7dcda5644 |
feat(studio): move data api settings to integrations (#42711)
Feature ## What is the current behavior? Data API settings live under Project Settings. ## What is the new behavior? Data API settings are moved to the Integrations page, treating Data API as a platform integration. Includes security checks when toggling on the Data API to prevent unintended exposure of project data. ## Additional context Towards FE-2517 ## Summary by CodeRabbit * **New Features** * Added a Data API integration with Overview and Settings pages, endpoint display, and enable/disable toggle with safety checks and confirmation flow. * **Navigation Changes** * Data API moved from Project Settings into the Integrations area and routes now redirect to the new Overview page. * **Documentation** * Added an overview doc describing Data API endpoints and configuration. * **Tests** * Added unit tests for endpoint resolution and schema parsing utilities. |
||
|
|
749fbdd296 |
Add table filter for database triggers (#42679)
## Context Adds a filter for tables in database triggers, will only populate tables which there's triggers for (similar UX to database functions) <img width="737" height="427" alt="image" src="https://github.com/user-attachments/assets/f4ddfbae-282d-4f97-ac3e-d187f7d82229" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Streamlined the database triggers interface state management for better internal consistency. * Enhanced filtering logic to support combined search and table-based filtering. * **New Features** * Added a table filter control to the triggers interface for more granular filtering options. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0d761b0434 |
Connect sheet final content (#42374)
<img width="2892" height="2342" alt="image" src="https://github.com/user-attachments/assets/7e08929d-abc3-4397-b89d-99cc52d8190e" /> This is the third and final PR to complete the new connect sheet. First: https://github.com/supabase/supabase/pull/42367 Second: https://github.com/supabase/supabase/pull/42373 This re-adds the Direct, ORM, MCP tabs and their content, including via connect.schema. To test: - Flag will be enabled on all staging projects - Click connect and notice new Sheet - Click all tabs and ensure content is correct <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Multi-mode connection flow with mode selector and icons (framework, direct DB, ORM, MCP) * New framework/variant/library selector, richer connection guides and install steps (Prisma, Drizzle, direct) * MCP onboarding flows (Cursor, Codex, Claude Code) with server/auth commands and configuration UIs * **Refactor** * Connect schema and state rebuilt to be mode-driven with improved step resolution and cascading state updates * **Tests** * Expanded unit tests covering framework resolution, connect flows, and mode behaviors * **Chores** * ESLint ignores updated for content files <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
b9a09d8612 |
Connect sheet content structure (#42373)
This is part two of a [PR breakdown](https://github.com/supabase/supabase/pull/42276) that introduces our connect schema and how content is retrieved. This focuses on the Framework tab to start. Fields are generated and content is rendered using a connect.schema file. This schema file defines modes, fields and steps. Each mode has a set of fields. Each field can be dependent on another field. The steps generated are then based off the values of the modes and fields. Each step can also render varying content dynamically using a template {{framework}}/{{frameworkVariant}}/{{library}} which just replaces those values with what's in state (fields selected). [Part one needs to be merged first.](https://github.com/supabase/supabase/pull/42367) The next stage will add back all other tabs and content. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * New Connect Sheet UI to guide app-to-project connections with dynamic configuration and copyable connection parameters. * Multi-framework & mobile support with ready-to-use code examples, install commands, and step-by-step setup for 20+ frameworks. * Multiple PostgreSQL connection methods (direct, transaction, session) with safe/masked connection previews. * Copy-prompt that aggregates step content and code for easy sharing. * **UI** * Multi-file code viewer with tabbed code blocks and added syntax support (Swift, TOML, HTML). * **Tests** * Comprehensive unit tests for resolver and state logic. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
6b805289c7 |
chore(studio): remove feature flag for dataApiExposedBadge (#42563)
Cleanup / chore — removing a feature flag that has been at 100% rollout with no issues. ## What is the current behavior? The `dataApiExposedBadge` feature flag is checked at runtime via ConfigCat, even though it has been set to 100% for a while with no issues. ## What is the new behavior? The feature flag check is removed and the gated behavior is now unconditionally enabled. A reminder has been set to delete the flag from ConfigCat in a month. ## Summary by CodeRabbit **Refactor** * Simplified API access status indicators in the studio editor, ensuring security-related tooltips now display consistently based on actual access conditions. * Updated component interfaces and consolidated internal hook dependencies for improved code maintainability and organization. |
||
|
|
3f6843a6b1 |
bug: fix refetch loop (#42613)
Problem:
- new filters are creating an infinite fetch loop of ph.supabase.io
# Before:
snap.filters change → effect → setParams() → router.push()
→ URL updates → filters/sorts recalc → setParams recreated
→ effect re-runs → INFINITE LOOP 🔄
# After:
snap.filters change → effect → comparison shows change → timeout
scheduled
→ setParams() → router.push(shallow: true) → URL updates
→ filters/sorts recalc → setParams recreated → effect runs
→ comparison check: no content change → early return → LOOP BROKEN ✓
The deep comparison prevents the effect from re-executing when only the
dependency references change
(due to URL updates), not the actual filter content. Test it out and the
PostHog spam should stop!
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Bug Fixes
* **Prevented unnecessary URL updates** when filter state remains
unchanged, improving application responsiveness.
* **Optimized filter and sort parameter handling** with enhanced
callback efficiency and routing behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
a057c951ea |
Make edge functions page accessible on coming up (#42549)
## Context Related prior work was making edge functions page accessible while project is restoring - however the status of the project gets flipped to COMING_UP while it's restoring hence why the functions page was still inaccessible. ## Changes involved - Update `NavigationBar.utils` to have edge functions link to `/functions` irregardless of project status - (Unrelated) Disable (with tooltip) deploy new function CTA on edge functions page if project is not active <img width="403" height="108" alt="image" src="https://github.com/user-attachments/assets/88479247-999b-4d41-a444-6705f8c3993e" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Deploy Edge Function button now disables and shows a tooltip when the project is inactive to make deployment status clear. * **Bug Fixes** * Edge Functions link now points consistently to the functions view regardless of project build state. * **Refactor** * Consolidated project-active check and reorganized related UI wiring to standardize inactive-state handling across settings and controls. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a6541d725e |
Update cron job overview to opt to skip JOIN depending on query cost (#42492)
## Context
The Integrations -> Cron overview page renders a list of cron jobs by
doing a join on both `cron.jobs` and `cron.job_run_details` in order to
pull the data for "Latest run" and "Status" ("Next run" is just derived
from "Latest Run" and the job's schedule)
In the past, we've had users run into issues where this query would time
out, likely due to the join on `job_run_details` especially if that
table is really big (and the columns on that table aren't indexed), and
our solution was to inform users to clear out that table + schedule a
job to clean the `job_run_details` table on a certain cadence. This CTA
however blocks the UI from rendering the cron jobs overview entirely
<img width="1644" height="590" alt="image"
src="https://github.com/user-attachments/assets/1a0458e9-f686-452b-88bc-44459bc7c615"
/>
## Changes involved
Am opting to use the new preflight check introduced
[here](https://github.com/supabase/supabase/pulls?q=is%3Apr+author%3Ajoshenlim+is%3Aclosed)
- Attempt to fetch the data for the cron jobs overview normally
- If preflight check rejects (due to high cost), then opt to fetch the
data while omitting the join
- Show a banner instead to inform the user accordingly
- So that way users can still view their cron jobs (the latest run
column is a nice to have convenience really)
<img width="1151" height="379" alt="image"
src="https://github.com/user-attachments/assets/72cfaafb-e951-4601-b54e-c36a6f36332d"
/>
- Clicking learn more will then open a dialog to explain what this is
all about
- The steps to clear the `job_run_details` table + schedule a clean up
job still remains
<img width="450" height="484" alt="image"
src="https://github.com/user-attachments/assets/4491e766-64a1-40c9-9703-2e8b0da11c3f"
/>
<img width="450" height="610" alt="Screenshot 2026-02-05 at 12 56 39"
src="https://github.com/user-attachments/assets/644c9a7b-5afb-46bb-8c1e-9ece3986c2fb"
/>
<img width="450" height="507" alt="Screenshot 2026-02-05 at 13 01 37"
src="https://github.com/user-attachments/assets/9f0f40f2-7376-4c28-90f1-0b21a1a4560a"
/>
- Non-UI related changes include
- Automatically refresh cron jobs after scheduling a job, remove manual
CTA to refresh the jobs after scheduling the clean up job
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Previous Runs tab on cron job pages
* Interactive "Learn more" cleanup dialog with guided delete and
schedule steps
* Close-confirmation modal when editing cron jobs
* High-cost banner that enables a lightweight "minimal" list mode
* **Bug Fixes**
* Clearer placeholder (minus icon/message) when a job has no runs
* **Performance**
* Safer, more efficient fetching and pagination for large cron job
lists; reduced retries on high-cost queries
* **Tests**
* Expanded end-to-end tests covering high-cost flows and the cleanup
dialog
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
b6d8f2ae2d |
chore: remove tableQuickstart and realtimeButtonVariant experiments (#42388)
## Summary Removes two concluded A/B experiments that didn't produce positive results: - **tableQuickstart**: Tested AI-powered table generation, template selection, and assistant integration for new table creation - **realtimeButtonVariant**: Tested hiding the realtime button or replacing it with a triggers button ## Changes - Delete `TableQuickstart/` folder with AI widget, templates widget, and generation hooks - Delete `useRealtimeExperiment` hook and remove variant-conditional logic - Delete `/api/ai/table-quickstart/generate-schemas` endpoint - Remove telemetry event definitions for both experiments - Remove local storage exposure tracking key - Remove API endpoint from proxy whitelist - Clean up eslint baseline references ## Testing - [x] Tested locally - Table Editor renders correctly without experiment widgets - [x] TypeScript compiles without errors - [x] No remaining references to removed experiment code **Quick test:** 1. Navigate to Table Editor → New Tab shows only "Create a table" card (no AI/Templates/Assistant variants) 2. Open table create panel → Realtime checkbox shows unconditionally when realtime is enabled ## Linear fixes GROWTH-609 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Removed Features** * AI-powered table generation and quickstart assistance (templates, AI widget, generation hook, templates data, and related utilities) * Quickstart templates widget and predefined table templates * Database triggers management interface * Realtime experiment gating and related experiment variants * **API & Storage** * Hosted AI quickstart API endpoint removed * Local storage key for quickstart exposure tracking removed * **Telemetry** * Quickstart- and realtime-experiment telemetry events removed * **UI Changes** * Simplified realtime toggle control in the table editor <!-- end of auto-generated comment: release notes by coderabbit.ai --> |