mirror of
https://github.com/supabase/supabase.git
synced 2026-07-09 06:06:12 -04:00
create-pull-request/patch
179 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9af6e65df4 |
fix(studio): DOM-nesting hydration errors, ghost deleted-snippet nav, and migrations query 400s (#47667)
App-level fixes that reproduce on BOTH the Next and TanStack builds — split out of #47657 (which stays TanStack-only) for reviewability. All were found by a full-site click-through of the dashboard. ## Invalid HTML nesting (React 19 "will cause a hydration error" console errors) - **FormLayout description rendered in a `<p>`** (`packages/ui-patterns`): consumers pass arbitrary JSX (the RowEditor's `created_at` timezone note passes a `<div>` with `<p>`s) → `<p>`-in-`<p>` / `<div>`-in-`<p>`. Container is now a `<div>` with identical classes (Tailwind preflight makes them render the same). - **Switch toggles nested inside Tooltip trigger buttons** (button-in-button) in ColumnEditor ("Allow Nullable" + "Is Unique"), ExtensionRow, and PublicationsTableItem → repo-standard `TooltipTrigger asChild` + `<div>` wrapper. - **Saved log queries rendered a `<div>` directly inside `<tbody>`** (`/logs/explorer/saved`) → rows are now proper `<tr><td colSpan>` wrappers; the component itself is untouched (it's valid in its sidebar usage). - **Nested anchors in observability metric cards**: a card-level `<Link>` wrapped MetricCard's "More information" `<Link>` (identical URLs) → the chevron affordance renders as a `<span>` when no `href` is passed; clicks bubble to the card link, tooltips preserved. Design-system standalone usage unaffected. - **`objectFit="cover"` passed to modern `next/image`** on the featured integration card (unknown-prop warning) — the className already had `object-cover`; prop dropped. ## Ghost dead-snippet after deletion Deleting the active SQL snippet left its id in `useDashboardHistory` (`history.sql`), so the "SQL Editor" nav item navigated to `/sql/<deleted-id>` — content fetch 404s, no editor pane renders, and a phantom tab reappears. Fixed both ends: delete flows now purge dashboard history (and the tabs store clears a stale `previewTabId`), and `/sql/[id]` treats a snippet 404 as "clean up + `router.replace` to `/sql/new` + toast" instead of rendering the dead state. Unit tests for the store/history cleanup. ## `pg-meta` migrations query 400s on every project load `ActivityStats` on project home runs the migrations list query, whose SQL was a bare `select * from supabase_migrations.schema_migrations` — that table only exists once a migration has run, so every other project logged a failed `?key=migrations` request on every load (visible in production consoles too). The SQL is now guarded with `to_regclass` + `query_to_xml` (same pattern as the advisor lints' `storage.buckets` guard), returning zero rows instead of erroring; legacy version-only tables still work. Tested against real dockerized Postgres (absent table, populated ordering, special chars, legacy schema) + MSW hook tests. Found and verified via /test-supabase-local (browser click-through + console audit on both builds). ## To test Console must stay free of React DOM-nesting errors ("cannot be a descendant of" / "cannot contain a nested") on each surface: 1. Table editor → Insert row panel (`created_at` field renders its timezone note) and Edit column panel ("Allow Nullable"/"Is Unique" tooltips still hover). 2. `/database/extensions` and `/database/publications` → toggle switches render, tooltips hover. 3. `/logs/explorer/saved` (with ≥1 saved query) → rows render full-width inside the table, hover shows Actions. 4. `/observability` → no nested-anchor error on load; card body click and the chevron both navigate; label help-icons still show tooltips. 5. `/integrations` → no `objectFit` unknown-prop warning; featured card images still cover. 6. **Ghost snippet**: open a SQL snippet → delete it via the sidebar → click the "SQL Editor" nav item → lands on `/sql/new` (no phantom tab, no 404 content fetch). Direct-load `/sql/<random-uuid>` → toast + redirect to `/sql/new`. 7. **Migrations 400**: load project home with a project that has never run a migration → the `pg-meta/<ref>/query?key=migrations` request returns **200** with `[]` (previously a 400 on every load). Database → Migrations still lists real migrations when they exist. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit * **Bug Fixes** * Deleted SQL snippets are fully removed from dashboard history and stale editor/tab state; users are redirected with a toast. * Closing preview tabs no longer leaves stale references. * Improved toggle/tooltip/dialog interactions to avoid broken UI, including metric headers showing tooltips even without direct links. * Migrations display safely when migration tables/relations are missing. * **UI Improvements** * Refreshed layout for saved queries, form descriptions, and integration imagery. * **Tests** * Added coverage for snippet history cleanup, tab removal, migrations SQL behavior, and query edge cases. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- ### Review feedback: `query_to_xml` breaks on Multigres (Ivan) The defensive migrations query (added here to stop the `?key=migrations` 400 when the table doesn't exist yet) originally guarded with `query_to_xml`, which is forbidden through Multigres's pooler (MUL-736 / PSQL-1318). Rewritten without `query_to_xml`/`xmltable` using the splinter#170 pattern: a PL/pgSQL `do` block guarded by `to_regclass` (PL/pgSQL defers planning, so a missing table never errors) stashes the rows into a transaction-local GUC via `set_config`, and a trailing `select` reads them back with `jsonb_array_elements`. Verified that postgres-meta sends the whole SQL as one simple-query string → single implicit transaction → the local GUC survives to the `select` and doesn't leak into the pooled connection. 6/6 dockerized-Postgres tests (absent table → `[]`, populated/ordered/special-chars, legacy version-only table, full pg-meta-shaped multi-statement string, GUC non-leakage). Note (out of scope, pre-existing): `packages/pg-meta/src/sql/studio/advisor/lints.ts` still uses `query_to_xml` — a separate pre-existing Multigres risk that should get its own splinter-pattern sync. --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> Co-authored-by: Saxon Fletcher <saxonafletcher@gmail.com> |
||
|
|
5dc054ae8f |
feat(studio): warn in Connect sheet when Data API is disabled (#47537)
## What kind of change does this PR introduce? Feature. Resolves DEPR-599. ## What is the current behavior? When the Data API is disabled (PostgREST has no exposed schemas), the Connect sheet still shows client-library setup steps for Framework and MCP modes without indicating that database queries will fail. ## What is the new behavior? When database access via the Connect instructions requires PostgREST, an inline warning appears above the steps (setup instructions remain visible): - **Framework**: warns when Data API is off; install, env vars, and auth/SSR setup still work - **MCP**: warns only when Database tools apply (selected explicitly, or by default when no feature filter is set) The warning fails open if PostgREST config cannot be loaded, and links to Data API settings via an "Enable Data API" CTA. | After | | --- | | <img width="1664" height="718" alt="CleanShot 2026-07-02 at 21 29 16@2x" src="https://github.com/user-attachments/assets/80d21927-c4dd-4158-8946-bf648b95e451" />| ## Additional context - Gating logic lives in `ConnectStepsSection.utils.ts` with unit tests - Out of scope: warning when Data API is on but zero tables/schemas are exposed - Coexists with the upcoming warehouse branch's catalog warning — that lives in a separate `WarehouseCatalogPanel` for `catalog` mode only <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Connection setup now checks Data API enablement and conditionally shows a “Data API disabled” warning, including an action to open Data API settings. * **Bug Fixes** * Warning logic now more accurately reflects the selected connection mode and chosen feature/tool selections. * **Tests** * Added a focused test suite covering the Data API configuration decision rules and when the warning should appear. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
3fcf980b0a |
fix(studio): batch of production Sentry crash fixes (array/null guards) (#47460)
Fixes a batch of production Studio crashes from Sentry (all caught by the global error boundary). Most are missing array/null guards where an endpoint typed as an array — or with a nested array field — returned a non-array body in production; a few are one-off render crashes. Resolves FE-3748. ## Issues fixed | Sentry | Error | Fix | | --- | --- | --- | | [J7R](https://supabase.sentry.io/issues/7492997940/) | Maximum update depth exceeded | Disable RadialBar animation in disk-cooldown countdown | | [JR5](https://supabase.sentry.io/issues/7548484681/) | resourceWarnings.find is not a function | Guard in ResourceExhaustionWarningBanner | | [JCJ](https://supabase.sentry.io/issues/7506024989/) | resourceWarnings.find is not a function | Guard in ProjectLayout + normalize query | | [K1Y](https://supabase.sentry.io/issues/7584792331/) | snippet.name on undefined | Optional-chain SQL editor download filename | | [B3K](https://supabase.sentry.io/issues/7141649636/) | pagination.count on undefined | Guard pagination in projects infinite query | | [JVP](https://supabase.sentry.io/issues/7560437621/) | schemas.some / extensions.find | Coerce pg-meta lists to arrays in useInstalledIntegrations | | [JR2](https://supabase.sentry.io/issues/7548339272/) | extensions.find is not a function | (same fix as JVP) | | [JQR](https://supabase.sentry.io/issues/7547163939/) | lints.filter is not a function | Normalize project lints query | | [JR3](https://supabase.sentry.io/issues/7548433501/) | entitlements.find is not a function | Guard call sites + normalize entitlements query | | [JQS](https://supabase.sentry.io/issues/7547557098/) | selected_addons.find is not a function | Normalize addons query arrays | <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved stability across several Studio screens by handling missing or unexpected data more safely. * Downloads now use a fallback name when a snippet name isn’t available. * Project, entitlement, schema, addon, warning, and extension views are less likely to break when data is missing or not in the expected format. * Pagination and countdown visuals now behave more consistently, with reduced chance of runtime errors or animation-related glitches. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
0abfbdd3d7 |
fix(studio): preserve session and redirect to MFA when AAL elevation is needed (#47145)
## 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? `withAuth` calls `signOut()` and redirects to `/sign-in` whenever the current AAL is below the required level. For IdP-initiated SSO logins — where the user lands directly on `/dashboard` rather than passing through `/sign-in-mfa` — this destroys the valid AAL1 session that was just established. Subsequent mgmt-api requests then return 401 Unauthorized, and the user is dumped on `/sign-in` with no way to recover except restarting the SSO flow (which loops them back to the same state). The platform already returns an actionable `403 Insufficient AAL: MFA required` on the first mgmt-api request, but the dashboard does not capture it. ## What is the new behavior? `withAuth` now distinguishes between "not logged in" and "needs AAL elevation": - **Logged in but AAL1** → `router.push('/sign-in-mfa?returnTo=…')`, session preserved. The existing `/sign-in-mfa` page picks up the session, renders the MFA form, and bounces the user to `returnTo` after a successful challenge. - **Not logged in** → unchanged: `signOut()` then redirect to `/sign-in?returnTo=…`. - `/sign-in-mfa` is also added to the "already there, do nothing" guard so the user isn't re-redirected mid-challenge. This relies on the gotrue client's local AAL state via `useAuthenticatorAssuranceLevelQuery`, which fires before any mgmt-api request, so no fetcher-level error parsing is needed. ## Additional context <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved multi-factor authentication (MFA) elevation flow to preserve user sessions instead of forcing sign-out and requiring users to restart sign-in. * Fixed unnecessary redirects when users are already on sign-in pages. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
c6fc456910 |
chore: cleanup duplicate exports studio (#47387)
## Problem Knip reports many duplicate exports (both named and default). Besides, we're moving away from default exports and even have an eslint rule to enforce it on new code. ## Solution - Cleanup those exports - Update imports when necessary No functional changes. If it builds, it's fine |
||
|
|
143769afac |
feat(studio): shared High Availability disabled hook and UI primitives (#47322)
Add generic building blocks for blocking features on High Availability projects: - useHighAvailability hook: HA state only (isHighAvailability, isPending) - HighAvailabilityDisabledEmptyState (full-page empty state) - HighAvailabilityDisabledSectionNotice (in-section admonition) The components carry a generic default title/description; consuming pages pass their own copy via props. HA state is read from the project's high_availability flag (same source as the High Availability badge on the project home page). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added clearer messaging for features that aren’t available in High Availability projects. * Introduced a standard High Availability status check to help the app adapt what it shows. * **Bug Fixes** * Hid non-applicable schema options when High Availability is enabled, reducing confusion in selection lists. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
f34aa108d5 |
chore: dead code cleanup (#47294)
## Problem There's still more unused code in the repository which slows down everything: - checkouts - tooling - probably builds (not sure how good turbopack is at handling this) ## Solution - remove old unused code - remove more recent code after checking git history to ensure it's not unfinished/ongoing work <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Removed several unused interface, onboarding, and helper components from the studio app. * Cleaned up outdated branching, integrations, query performance, support, and table/grid UI elements. * Removed a few unused utility hooks and key-mapping logic. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
fd0f2dd459 |
Scope last visited organization local storage to profile (#47071)
## Context If a user switches account without an explicit log out via the dashboard, landing back on `/org` will redirect users to the last visited organization as stored in local storage, in which it can result in the following state if the last visited organization does not exist in the current account <img width="2538" height="1060" alt="image" src="https://github.com/user-attachments/assets/270e482a-3515-48ef-898b-87e76fce80d6" /> ## Changes involved Am opting to scope the last visited organization to the user profile instead - this would be a bit more cleaner than trying to actively clear the last visited org slug from local storage with implicit account changes as there's no deterministic way to track that (afaik) from FE side of things ## To test Can reproduce the problem as such - Ensure that you have 2 accounts to log in with, and one account has an org that the other is not a part of - For the organization that has the "extra" org, ensure that you click into it so that the last visited org slug is saved in local storage - Mimic changing accounts by visiting `/auth/v1/authorize?provider=github` (using the domain for the env that you're testing on - e.g localhost:8000 for local, or green for staging preview) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Unified “last visited organization” handling across the Studio UI with a shared hook, improving consistency for home/dashboard return, cancel/back navigation, and account routing. * **Bug Fixes** * Updated redirects to only route to an organization when a valid last-visited value is available; otherwise users go to the general organizations page. * Kept MFA enrollment and factor delete/leave flows aligned to the unified last-visited organization value. * **Tests** * Updated onboarding and layout tests to match the new last-visited organization storage key format and hook/query success behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e491182054 |
Auth flow improvements (#46967)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES/NO ## What kind of change does this PR introduce? Bug fix, feature, docs update, ... ## What is the current behavior? Please link any relevant issues here. ## What is the new behavior? Feel free to include screenshots if it includes visual changes. ## Additional context Add any other context or screenshots. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * Added “Continue with {provider}” sign-in and sign-up flows using enabled external identity providers. * Enabled inbound branding to focus a specific provider for customized sign-in/sign-up experiences. * **Improvements** * Refined the sign-in options layout and “last used” tracking for clearer authentication choices. * Updated account identity/provider connection experiences (link/unlink and management UI). * **Bug Fixes** * Fixed hydration mismatches in sign-in and password-related layouts. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
2191669d08 |
feat(studio): add upgrade CTA placement experiment (#45858)
## Summary Replaces the header upgrade CTA (PR #44494, which design team wanted to iterate on) with a placement experiment that tests three non-chrome surfaces for the free-plan "Upgrade to Pro" CTA. PostHog flag `upgradeCtaPlacement` (free-plan users only) with four arms: | Variant | Surface | | --- | --- | | `control` | No CTA (baseline cohort, still tracked) | | `user_dropdown` | Full-width button pinned in the account dropdown | | `org_projects_list` | Project-card-shaped usage tile, first card in the org project grid | ## Details ### `user_dropdown` - Full-width `Upgrade to Pro` button in `UserDropdown`, gated to org-scoped routes only (`/project/*`, `/org/*`) so the org-billing CTA never shows on `/account`, `/organizations`, etc. — addresses the scope concern raised in review. - Dropdown uses controlled `open` state so it closes before navigation (it lives in the global layout, so a route change alone wouldn't dismiss the overlay). ### `org_projects_list` - `PlanUsageCard` renders as the first `<li>` in the project grid (via `ProjectList`'s `prependCard`), matching `ProjectCard` shape so it reads like another project tile. Also renders during the project-list loading state to avoid pop-in. <img width="3804" height="1494" alt="Arc 2026-06-08 20 02 54" src="https://github.com/user-attachments/assets/09c2218c-43d1-49ce-bae7-5075c9750d72" /> ### Shared card styling - Metric rows (Egress, Database size, Monthly active users, File storage) show `current / limit` with a progress ring; ring/value turn warning at ≥80% and over at ≥100%. - Rows are clickable deep-links to `/org/[slug]/usage#<anchor>` with a hover chevron and dashed separators; the same row component is used by both the embedded and project-card variants. - Skeleton placeholder renders from first paint so the card reserves layout while `useOrgUsageQuery` resolves. - Exposure is fired optimistically while the org query loads (skeleton shows immediately), but the experiment exposure event only fires once free-plan is confirmed. ### Telemetry - `upgrade_cta_clicked` with `placement: user_dropdown | home_usage_card | org_projects_list`. - `upgrade_cta_placement_experiment_exposed` with `variant` — the custom exposure event (snake_case experiment id `upgrade_cta_placement`; the flag key stays camelCase `upgradeCtaPlacement`). ### Header CTA sunset - `HeaderUpgradeButton` and its wiring in `LayoutHeader` / `MobileNavigationBar` removed (master's #46144 already removed the button; this branch drops the remaining `header_upgrade_cta_clicked` event). ## Before merging - [x] Create the `upgradeCtaPlacement` flag + experiment in PostHog (4 variants, free-plan targeting, custom exposure event `upgrade_cta_placement_experiment_exposed`). - [x] Archive the now-orphaned `headerUpgradeCta` flag. ## Test plan - [x] Override the flag per variant via the dev toolbar on staging; confirm each surface renders and `upgrade_cta_clicked` fires with the right `placement`. - [x] `control` shows no CTA but still emits the exposure event. - [x] Paid-plan org and self-hosted (`IS_PLATFORM=false`) show nothing. - [x] Clicking a metric row deep-links to the matching usage section; clicking Upgrade routes to billing. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Experimentally surface an “Upgrade to Pro” CTA in the user dropdown and on the projects page for eligible free-plan orgs. * Added a Plan Usage card showing free-plan metrics and upgrade prompts on the organization projects page; hides when irrelevant or errored. * Project list and its loading view support inserting a custom/prepend card in card mode. * **Telemetry** * Added tracking for CTA clicks and experiment exposure; placement is persisted per org. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: kemal <hello@kemal.earth> |
||
|
|
1c2d28d5b3 |
chore: wrap local storage into helper methods that are safer (#46628)
## 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? - Noticing our code we have many patterns of calling localstorage and handling those errors - We should add those in a single well tested file - Handle those errors in the singleton which makes it easier for us to debug customer issues. Logger is outputing local storage warnings for feature we expose - Side effect of this is random crashes on studio when local storage isn't available or handled correctly <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Improved browser storage handling across the app for more reliable persistence and graceful behavior in restricted or non-browser environments (settings, previews, charts, tabs, sign-in/session flows, integrations, and UI state). * **New Features** * Introduced a safe storage layer to standardize and harden local/session persistence. * **Tests** * Added comprehensive tests covering the new safe storage behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a7dda67549 |
feat(studio): add Multigres logs collection for HA projects (#46499)
## Problem High availability (Multigres) projects don't expose Multigres service logs in the Studio logs UI, so users on HA projects have no entry point to inspect them. ## Fix Add a `Multigres` logs collection, gated behind the `multigresLogs` ConfigCat flag **and** the project's `high_availability` flag (`useShowMultigresLogs`): - New `Multigres` entry in the logs sidebar `Collections`, linking to a new `multigres-logs` page that queries the `multigres_logs` table. - Wire `multigres_logs` through the logs constants, types, table SQL, query type, and service labels. - Row formatting: parse the JSON `event_message` and render `level` through `SeverityFormatter` and `msg` through `TextFormatter`, matching the other service collections (instead of dumping raw JSON). - `WARN` severity is now styled like `WARNING` (amber), since Multigres emits `level: WARN`. - Log detail drawer: parse the JSON `event_message` and spread its keys onto the log so each field (level, msg, query, error, connection_id, etc.) renders as its own collapsible row. - Single-log query omits the `metadata` column for `multigres_logs` (the table has no such column), fixing an `INVALID_ARGUMENT` error when opening the detail drawer. - Event chart: parse the level out of `event_message` via `JSON_VALUE` so error/warning bars are counted (the table has no top-level level column). - Add the `multigres_logs` source schema to the Field Reference drawer, same gating. ## Why a feature flag `high_availability` is an existing product feature that predates Multigres, so existing HA projects could otherwise see a broken collection querying a `multigres_logs` table they don't have. Requiring the `multigresLogs` flag ships the feature dark and decouples rollout from HA status. The flag must be created in ConfigCat before enabling; until then `useFlag` returns false and the feature stays hidden. ## How to test - Enable the `multigresLogs` flag (or override locally) and open a project where `high_availability` is `true`. - Navigate to `Logs`. Confirm a `Multigres` entry appears under `Collections` (after `Replication`). - Open it: the page loads at `/project/<ref>/logs/multigres-logs` and queries `multigres_logs`. - Confirm rows show a colored severity pill (including amber `WARN`) and a readable message rather than raw JSON. - Confirm the chart counts error/warning bars correctly. - Click a row: the detail drawer shows each parsed field as its own row, with no error. - Open the Field Reference drawer and confirm `Multigres` is listed as a source. - With the flag off, or on a non-HA project, confirm the collection and Field Reference source are both hidden. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Multigres added as a dedicated log source with its own Logs page, sidebar entry, and query type. * Log list and preview now parse Multigres payloads to surface timestamp, severity, and formatted message. * Multigres integrated into charting, prompt labels, and field-reference UI (hidden unless enabled). * New hook controls showing Multigres UI only when feature flag + HA project condition are met. * **Bug Fixes** * Severity rendering treats "WARN" the same as "WARNING". * **Tests** * Unit tests added for Multigres parsing and the show-Multigres hook. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
7f5e3cab93 | chore(studio): remove expired Fly.io deprecation banner (#46535) | ||
|
|
47c084e51d |
refactor(studio): migrate telemetry to useTrack (#46140)
## Summary
I migrated every `useSendEventMutation` call site in `apps/studio` to
`useTrack`, deleted the legacy hook, and added a lint guardrail so it
can't return. `useTrack` is the type-safe replacement: it auto-injects
`groups: { project, organization }` from the selected project/org and
types `action` + `properties` against `TelemetryEvent`. Existing call
sites built groups manually and were not type-checked at the action
level. The migration covers 81 files (60 trivial swaps, 9 org-only, 3
pre-auth, 5 bespoke, 4 test mocks).
## Changes
- Migrated trivial call sites across `pages/project/[ref]`,
`components/interfaces/*` (Reports, Storage, Realtime/Inspector,
SQLEditor, Functions, EdgeFunctions, Integrations, ProjectAPIDocs,
Branching/BranchManagement, TableGridEditor, Connect, Docs, Auth,
Support, Home, ProjectHome, App), `components/layouts/*`, and
`components/ui/*`.
- Migrated org-only sites (`Organization/Documents/*`,
`Organization/BillingSettings/Subscription/*`,
`Organization/SecuritySettings.tsx`,
`Account/Preferences/DashboardSettingsToggles.tsx`) by dropping the
manual `groups: { organization: ... }` and letting `useTrack`
auto-inject. Verified `useSelectedProjectQuery` is disabled on org
routes (gates on URL `[ref]`).
- Migrated pre-auth sites (`SignInForm.tsx`, `sign-in-mfa.tsx`,
`profile.tsx`) where neither project nor org is resolved.
- Bespoke handling:
- `execute-sql-mutation.ts` and `table-row-create-mutation.ts`: pass `{
project: projectRef }` via `groupOverrides` since the mutation can
target a non-selected project ref.
- `useStudioCommandMenuTelemetry.ts`: kept a direct `sendTelemetryEvent`
call because studio groups must override pre-built event groups
(opposite of `useTrack`'s override direction).
- `AIAssistantOption.tsx`: passes sentinel-aware `groupOverrides` so
`NO_PROJECT_MARKER`/`NO_ORG_MARKER` continue to suppress group emission.
- `SidePanelEditor.utils.tsx`: utility functions `createTable` and
`updateTable` now take a `track: Track` parameter (threaded from
`SidePanelEditor.tsx`); dropped the `organizationSlug` arg since groups
are no longer assembled manually.
- Branch-event attribution: preserved `parentProjectRef` overrides on
`branch_updated`, `branch_merge_completed`, `branch_merge_failed`,
`branch_merge_submitted`, `branch_delete_button_clicked`,
`branch_review_with_assistant_clicked`, and
`branch_*_merge_request_button_clicked`. Original code grouped these
under the parent (production) project, not the branch ref;
auto-injection would have shifted them onto the branch.
- Switched 4 test mocks from `@/data/telemetry/send-event-mutation` to
`@/lib/telemetry/track`. Removed obsolete tests around manual groups and
`try/catch` on telemetry rejection.
- Deleted `apps/studio/data/telemetry/send-event-mutation.ts`. The
deleted module is its own guardrail: any reintroduction of the import
fails at TypeScript module resolution before lint runs.
## Testing
Tested on preview deploy:
- [x] SQL editor `CREATE TABLE` fires `table_created` with method
`sql_editor` and `groups.project` set to the mutation's `projectRef`.
- [x] Table editor creates a table from the side panel; `table_created`
fires from `SidePanelEditor.utils` via threaded `track`.
- [x] Help button (`/project/[ref]/...`) fires `help_button_clicked`
with auto-injected project + org groups.
- [x] Sign-in form fires `sign_in` with empty groups (pre-auth,
expected).
- [x] Org documents page (`/org/[slug]/documents`) fires
`document_view_button_clicked` with org group only, no stale project
ref.
- [x] Command menu (`Cmd+K`) inside a project still fires
`command_menu_opened` with studio's project/org overriding any
event-supplied groups.
- [x] Support form "Ask the Assistant" without selected org fires
`ai_assistant_in_support_form_clicked` with no project/org groups
(sentinels suppress).
- [x] On a branch, "Update branch" / "Merge branch" / "Close merge
request" events fire with `groups.project` set to the parent project
ref, not the branch ref.
Local checks:
- [x] 22/22 tests pass across the 4 updated test files
(`SidePanelEditor.utils.createTable`, `EdgeFunctionRenderer`,
`LayoutSidebar`, `PlanUpdateSidePanel`).
- [x] `rg useSendEventMutation apps/studio` returns 0 hits.
## Linear
- fixes GROWTH-860
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Standardized telemetry across the Studio to a unified tracking system;
events now send simplified payloads with less contextual/grouping data.
* No user-facing flows changed; UI behavior, permissions, and
interactions remain the same.
* **Tests**
* Updated telemetry mocks and tests to align with the new tracking
approach.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46140?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
c1b473e472 | fix: adjust connect sheet for cli and self-hosted (#46217) | ||
|
|
2c651ddabc | fix(experiment): make dataApiRevokeOnCreateDefault flag reads shape-agnostic (#46289) | ||
|
|
fdceb29260 |
fix(telemetry): exposure event captures dataApiDefaultPrivileges + drop race-fix hook (#46085)
## 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? This PR addresses three issues with the implementation of the `dataApiRevokeOnCreateDefault` experiment ([GROWTH-858](https://linear.app/supabase/issue/GROWTH-858)) on the frontend side: 1. The `project_creation_default_privileges_exposed` event payload captures `dataApiEnabled`, which is the parent "Enable Data API" toggle. That value defaults to `true` for everyone in both arms, which doesn't help understand how people are interacting with the form. 2. The hook itself was gating on PostHog JS SDK values rather than our backend server values being sent from `/telemetry/feature-flags`. 3. The form on `/new/[slug]` captures `dataApiDefaultPrivileges` defaults once at mount via react-hook-form's `defaultValues`. If the flag is still loading when the page mounts, `useDataApiRevokeOnCreateDefaultEnabled()` returns `false` (coerced from undefined), and the form locks the field to the legacy default of `true`. The flag later resolving has no effect, and treatment users get the legacy default visually and in the exposure event. ## What is the new behavior? 1. Main-surface payload now sends `dataApiDefaultPrivileges` — the form field the experiment actually controls (`true` = legacy grants kept, `false` = revoked on create). Post-fix data will let us read out whether treatment users actually got the new default. 2. Hook is simplified: drop `orgCountReady`, drop the `onFeatureFlags` subscription, drop the `posthogClient` import. It now fires once when the flag resolves, period. Vercel surface is unchanged (still no `dataApiDefaultPrivileges` since there's no user-facing toggle there). Tests updated. 3. New useEffect in `/new/[slug]` watches the raw flag value and syncs `dataApiDefaultPrivileges` to the correct experiment-driven default when the flag resolves, gated on `getFieldState(...).isDirty` so we don't clobber intentional user input. ## Additional context Backend half of this fix is at supabase/platform#32933 (passes `org_count` and `signup_timestamp` in `personProperties` so the audience filter actually evaluates correctly). Both PRs are needed for the experiment to bucket at 5% and be measurable. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Changes** * Telemetry now records the selected default-privileges setting (dataApiDefaultPrivileges) in project-creation events; the previous dataApiEnabled field was removed. * Project-creation flows apply the experiment-driven default for that setting once the experiment resolves, but they do not overwrite user-edited choices. Vercel new-project flow syncs with the experiment until the user changes the checkbox. * **Tests** * Updated tests to validate tracking, deduplication, and sync/timing behaviors for dataApiDefaultPrivileges. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46085?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0bed80b340 |
chore(telemetry): clean up frontend event catalog (#45964)
## Summary Resolves 13 findings (2 HIGH, 5 MEDIUM, 6 LOW) from the frontend telemetry audit: 1 action-string collision, 1 camelCase experiment name, 9 dead events removed, 4 missing org groups attached, 1 ambiguous property renamed, 1 raw-string property narrowed, plus consolidations and a structural tightening on TABLE_EVENT_ACTIONS. ## Changes ### HIGH - Rename `EventPageCtaClickedEvent.action` to `www_event_page_cta_clicked` so it no longer collides with the pricing CTA event (which had a different schema sharing the same action string) - Snake_case the header-upgrade experiment exposure name (`headerUpgradeCta_experiment_exposed` → `header_upgrade_cta_experiment_exposed`); PostHog flag key and `?source=` URL param unchanged ### MEDIUM - Remove 4 dead `ProjectCreation*Step*` events (referenced a v2 route that doesn't exist; 0 emissions) - Remove 4 dead experiment exposure events: `ProjectCreationRlsOptionExperimentExposed`, `HomeNewExperimentExposed`, `TableCreateGeneratePoliciesExperimentExposed`, `TableCreateGeneratePoliciesExperimentConverted` (0 emissions) - Attach org group to `dpa_request_button_clicked` (0% had `$group_0` per Hex) - Delete `RegisterStateOfStartups2025NewsletterClicked` (interface naming outlier, 0 emissions, page renamed to 2026) - Rename `AssistantSuggestionRunQueryClickedEvent.category` to `mutationType` with tightened literal union (`'functions' | 'rls-policies' | 'unknown'`) - Attach org group to `project_creation_default_privileges_exposed` on Vercel surface via explicit `groupOverrides` (auto-injection misses because `useSelectedOrganizationQuery` is undefined on that page) ### LOW - Consolidate `IndexAdvisorBannerEnableButtonClickedEvent` + `IndexAdvisorDialogEnableButtonClickedEvent` into one event with `origin: 'banner' | 'dialog'` - Rename `ImportDataFileDroppedEvent` → `ImportDataFileAddedEvent` so the interface name matches the action and the verb is on the approved list - Rename `LogDrainConfirmButtonSubmittedEvent` → `LogDrainRemovedEvent` and action to `log_drain_removed` (fires on delete-confirm modal, matches `CronJobRemovedEvent` pattern) - Add `type` property to `CronJobRemovedEvent` (parsed from the job's command), matching the create/update event shape - Tighten `TABLE_EVENT_ACTIONS` values with `satisfies` against the event union so renames in the union fail typecheck here too - Attach org group to `www_pricing_plan_cta_clicked` at 5 emission sites when an org is available in the page context - Narrow `unified_logs_row_clicked.logType` from raw `string` to the 5-literal `LOG_TYPES` union (zod already validates server values) ### Bundled refactor Migrated 5 emission sites from deprecated `useSendEventMutation` to `useTrack` while their containing files were being edited: `DPA.tsx`, `DisplayBlockRenderer.tsx`, `Grid.tsx` (2 events), `DeleteCronJob.tsx`. Full sweep of the remaining ~79 files is a separate follow-up. ## Testing Mostly just renaming of events ## Linear - fixes GROWTH-798 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Standardized telemetry to a unified tracking system for more consistent analytics. * Simplified experiment exposure reporting for upgrade prompts. * **New Features** * More granular tracking for CSV import, cron job deletions, log drain removals, DPA downloads/requests, and pricing CTAs. * Assistant now classifies mutation queries more precisely. * **Bug Fixes** * Improved default-privileges exposure logic on Vercel deployments (skips when org missing). <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45964) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
86a3f8b03d |
chore: upgrade to react-19 (#45886)
- Most changes are related to either types or `useRef` usages (it now requires an initial value). - also updated `vaul` to its latest version and haven't noticed any change ([design-system demo](https://design-system-git-react-19-supabase.vercel.app/design-system/docs/components/drawer)) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Upgraded workspace to React 19. * **Bug Fixes** * Improved null-safety and ref handling across editors, UI components, shortcuts, and markdown/image rendering to reduce runtime errors. * Safer event/timeout/interval cleanup and more robust command/context handling. * **Chores** * Bumped vaul dependency versions. * **Documentation** * Type and TypeScript accuracy improvements for clearer developer feedback. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45886) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
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 --> |
||
|
|
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 --> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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. |
||
|
|
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> |
||
|
|
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> |
||
|
|
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" /> |
||
|
|
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 |
||
|
|
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 -->
|
||
|
|
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. |
||
|
|
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 -->
|