mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
bot/decrease-eslint-ratchet-baselines
100
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
995f6f65c7 |
[FE-4483] fix(studio): disable network bans for v3 projects (#50997)
Disables network bans for v3 (`AWS_K8S`) projects and shows a specific unsupported notice. The shared banned-IP query waits for project details and skips unsupported projects, covering both Database Settings and Advisor for v3 and High Availability projects. The hook returns the standard query result and uses `skipToken` to prevent unsupported requests, including manual refetches. Database Settings handles project-detail errors at the call site. Open unban confirmations are cleared when the section becomes disabled, and submission checks eligibility. Addresses [FE-4483](https://linear.app/supabase/issue/FE-4483/disable-network-bans-for-v3-aws-k8s-projects). ## To test - Open Database Settings on a v3 project. Check that Network bans shows the v3 notice, hides the IP list and unban controls, and makes no network-bans retrieval request on initial load or reload, including while Advisor is mounted. - Check that an HA project still shows its existing notice and makes no network-bans retrieval request on initial load or reload. - Navigate from a supported project to a v3 or HA project and check that no banned-IP request is sent for the unsupported project and no banned-IP signals from the previous project appear in Advisor. - If project details fail without cached data, check that Network bans shows an error after retries finish and does not retrieve bans. A successful retry should restore normal behavior. - Open an unban confirmation on a supported project, then navigate to a v3 or HA project. Check that the dialog closes without sending an unban request and stays closed when returning. A newly opened confirmation should still work. - On a supported project, check the empty state and banned IP list. Confirm that users with permission can unban an IP and users without permission see a disabled button with the permissions tooltip. Validation: 17 focused tests passed, covering automatic and manual request suppression, project-detail error display and recovery, and navigation between supported and unsupported projects. Changed-file ESLint, Prettier, and full Studio typecheck (without the incremental cache) passed. Earlier local browser checks on `9912c6c` confirmed no retrieval requests for an HA project on AWS_K8S across reloads and Advisor, and a successful empty state on a supported project. The local failed-project case redirected to the organization after retries, so the inline error remains verified by the component test only. The latest preview, standalone v3 notice, populated bans/unban, and no-permission tooltip still need browser verification. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Banned IP settings now show an unsupported-project notice for AWS Kubernetes projects and hide ban lists and unban actions for AWS Kubernetes and High Availability projects. * Banned IP data loads only after project details are available and only for supported projects; unsupported projects do not display cached ban data. * Project-detail errors are shown separately from ban-list errors. * Unban confirmations close when a project becomes unsupported or an unban succeeds. Unbanning is unavailable when you lack update permission or the project is unsupported. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
27af9ca162 |
chore(www): run production builds through Turbo (#50713)
www builds currently bypass Turbo. This caches Next.js compilation and sitemap generation while keeping content refreshes and asset uploads on every build, including cache hits. **Changed:** - Refresh content before Turbo hashes its inputs, and upload assets after Turbo saves or restores the build output. - Include generated content, shared code, environment settings, sitemaps, and the customer RSS feed in the cache configuration. - Remove the redundant `vercel.json` build override and consolidate public environment settings into `NEXT_PUBLIC_*`. Cache reuse requires the same commit and build inputs because production CDN URLs include the commit SHA. **Added:** - Build lifecycle tests covering cache restoration, input invalidation, root/app commands, and upload ordering and failure handling. ## To test - From `apps/www`, run `pnpm exec vitest run turbo-build.test.ts generate-sitemap.test.ts scripts/lib/githubStars.test.ts`. - Check the Vercel preview build runs content preparation before `build:next`, and verify the homepage, `/sitemap.xml`, and `/customers-rss.xml` load. - Rebuild with identical prepared content and environment settings to check compilation is cached. Asset uploads should still run when enabled. Validation: 63 tests passed, along with typecheck, ESLint for the new test, formatting, and a full local build. The local build used public example settings and placeholder survey configuration, with asset uploads disabled; Vercel deployment validation is still pending. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Build & Deployment** - Production builds now reuse cached outputs and restore generated assets when a cache is available. - Static assets upload after a successful build, and changes to content, documentation, configuration, or shared components trigger a fresh build. - **Documentation** - Added production build guidance covering caching, CDN uploads, overrides, and direct-build limitations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
89ae80073d |
[FE-4400] feat(studio): shift-click range selection in Unified Logs (#50462)
Shift-clicking a row checkbox in Unified Logs now selects every row between the last clicked row and the clicked one, following up on #50381. Per review, the legacy logs table now uses react-data-grid's native shift-click selection (the same mechanism as the table editor) instead of the custom anchor logic from #50381, and Unified Logs matches the grid's semantics. **Semantics (all three tables):** a shift-click applies the clicked checkbox's new state to every row between the last clicked row and the clicked one. The last clicked row itself is untouched. In Unified Logs a shift-click after the selection has been cleared is a plain toggle. **Changed:** - `LogTable` passes `selectedRows`, `onSelectedRowsChange`, and `rowKeyGetter` to the grid and renders the checkbox through a small `LogSelectCell` component using `useRowSelection`. The custom anchor ref, its resets, and the inline toggle are gone. Checking a row still closes the single-row side panel. - `getShiftClickSelection` moved from the Logs utils to `apps/studio/lib/shift-click-selection.ts` and rewritten to the grid's rule. Only Unified Logs uses it now, via a `getShiftClickRowSelection` adapter for TanStack Table's `RowSelectionState`. Tests cover both. - Unified Logs owns a selection anchor ref and passes it into the column generator. The checkbox cell handles `onClick` with the shift key, computes the range over the table's displayed row model (so it spans sort order and infinite-scrolled pages), and writes back through the table's own selection setter. Shift mousedown is prevented so no text selection spans rows. - The `LogTable` test mock of react-data-grid now implements the grid's row selection so the component tests exercise the native path. ## To test - Postgres logs: click one checkbox, then shift-click a checkbox further down. Every row in between should be checked and the action bar shows the count. Repeat upward. - Shift-click an already-checked row: it and the rows back to the last clicked row uncheck, the last clicked row stays as it was. - Checking a box closes the single-row side panel. Clicking a row body clears the selection and opens the panel. - Tab to a checkbox and press Space: it still toggles. Arrow keys plus Shift+Space still toggle the focused row. - Unified Logs: same shift-click behavior. Clear the selection or change a filter, then shift-click: only that one row toggles. Scroll to load more rows and shift-click across the boundary. - Copy as JSON/Markdown and Explain with AI still use the selected rows in both tables. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Improved row selection in Settings Logs and Unified Logs. - Shift-click now selects or deselects the range between the anchor row and clicked row. - Clicking an already selected row clears the relevant selection while preserving the anchor row. - Added more consistent checkbox, keyboard, and range-selection behavior across log tables. - Selecting a checkbox no longer opens the corresponding log, while clicking the row continues to open it. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
a47397d5fe |
fix(common): restore narrow Feature type (#50850)
The platform API now types `ProfileResponse.disabled_features` as `string[]` (since #48981), which collapsed the `Feature` union to plain `string`, so `isFeatureEnabled` accepted any string and typos went uncaught. **Changed:** - `Feature` is now a local `RuntimeFeature` union (the profile-driven flags) plus the keys of `enabled-features.json`, instead of deriving from the API type - `useIsFeatureEnabled` casts the merged runtime disabled list to `Feature[]`, since the profile field is now `string[]` The runtime feature list duplicates what the backend knows. Once the enum is restored in the API spec, `Feature` can go back to deriving from the generated type. ## To test - `pnpm typecheck` passes - Passing a bogus string to `useIsFeatureEnabled` / `isFeatureEnabled` is now a type error - Nothing behavioral changes, so a quick sanity check that the sidebar / billing / org settings still render is enough <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **No user-facing changes** * This update does not change the app’s visible features or behavior. It includes internal typing adjustments only. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
2f1ad03640 |
fix(www): prevent GitHub stars from falling back to zero (#50704)
The www build saves failed GitHub star requests as zero, which the navigation displays as `0K`. This passes `GITHUB_TOKEN` through Turbo's build environment and preserves a valid previously generated count when a request fails. If there is no valid previous count, the navigation displays “GitHub” and the homepage contribution graphic omits the number. Cached fallback is available only when the previous generated content exists; rate limiting is a possible cause of the original failure, but has not been confirmed from deployment logs. ## To test - Run `pnpm --filter www exec vitest run scripts/lib/githubStars.test.ts` — all 16 tests pass, covering authenticated and anonymous requests, rate limiting, malformed responses, and missing or invalid cached content. - Build with a valid `GITHUB_TOKEN` and check that the navigation and homepage graphic show the star count. - Simulate a failed GitHub request with and without existing generated content. Confirm that a valid previous count is retained, or that no zero count appears when none is available. Verified locally: live GitHub fetch through the new loader, Turbo dry run with strict environment filtering and `GITHUB_TOKEN` allowed, Prettier, and ESLint (one existing default-export warning). Full build and browser checks have not been run. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - GitHub star counts are now displayed only when valid; otherwise, the interface shows a clear fallback label. - Star counts can fall back to cached data when GitHub is unavailable or returns invalid results. - Builds without GitHub data now complete gracefully instead of failing. - **Tests** - Added coverage for authenticated and unauthenticated requests, cached fallbacks, invalid responses, and clean builds. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
240bfce7f6 |
[FE-4198] feat(studio): select a range of logs with shift-click (#50381)
Shift-clicking a log row checkbox now selects every row between the last clicked row and the clicked one, so you can grab a consecutive block of logs to copy without checking each one. Applies everywhere the shared `LogTable` renders: Postgres/API/Auth/Edge Functions logs and the Logs Explorer. **Added:** - `getShiftClickSelection` in `Logs.utils.ts`: pure helper that computes the next selection from the ordered row keys, the current selection, the anchor row, and the clicked row. Adds the inclusive range in either direction. If the whole range is already selected it deselects the range instead. Falls back to a plain toggle when there's no usable anchor. Covered by unit tests, plus `LogTable` component tests for range select, the no-anchor fallback, anchor clearing, and range deselect. **Changed:** - `LogTable` tracks the last toggled row as the range anchor (a ref, since it's only read in handlers). The anchor is set by plain clicks, shift-clicks, and the Shift+Space row toggle, and cleared whenever the selection becomes empty (toggling off the last row, plain row click, Escape, action bar clear, select-all then deselect-all, or a new query loading). - The checkbox cell handles `onClick` instead of `onCheckedChange` so the shift key is available. Keyboard Space on a focused checkbox still toggles it, since Radix dispatches a click for it. - A shift mousedown on the checkbox cell is prevented so the browser doesn't start a text selection across rows. Unified Logs has its own row selection (TanStack Table) and is not changed here. ## To test - Open any log page with a decent number of rows, e.g. Postgres logs. Click one checkbox, then shift-click a checkbox several rows below. Every row in between should be checked and the action bar should show the count. Repeat upward. - Shift-click a range that's already fully selected: the range should clear, and rows outside it stay as they were. - Plain-click a row's message text (not the checkbox): side panel opens and the selection clears. A following shift-click should just toggle that one row. - Press Escape or the action bar's clear button, then shift-click: also just a single toggle. - Focus a row with the arrow keys, press Shift+Space, then shift-click a lower checkbox: the range should extend from the keyboard-toggled row. - Tab to a checkbox and press Space: it should still toggle. - After a shift-click, confirm no text is highlighted across the rows. - Copy as JSON/Markdown/CSV still copies the selected rows in display order. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added shift-click range selection to the logs table for selecting or deselecting consecutive rows. - Preserved single-row selection when range selection is unavailable. - Improved selection behavior when clearing selections or changing log queries, preventing stale range anchors. - **Tests** - Added coverage for forward and reverse range selection, deselection, partial selections, fallback behavior, and input immutability. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
3bac7165bd |
chore(studio): move the TanStack Start deploy onto Nitro (#50030)
Moves the Studio TanStack Start build off the hand-rolled Vercel setup (an `api/server.js` function shim, rewrites in `vercel.ts`, a custom `?dpl=` skew-protection Vite plugin, and `scripts/serve.js` for self-hosted) and onto Nitro, which TanStack Start documents as its deployment path. Documents are served from the static SPA shell on the CDN; only `/api/*` and `/_serverFn/*` invoke the function. **Removed:** - `api/server.js`, `scripts/serve.js`, `scripts/smoke-server.mjs` - The `skewProtectionDpl` Vite plugin, `renderBuiltUrl`, and the `vite:preloadError` reload backstop in `router.tsx` (TanStack Router already reloads once on a failed lazy import) - Rewrites, `functions`, `outputDirectory`, and `cleanUrls` from `vercel.ts` (redirects and headers stay) - `magic-string` and `@jridgewell/remapping` devDependencies, the `preview` script **Added:** - `nitro` plugin in `vite.config.ts`. Preset is auto-detected: `.vercel/output` on Vercel, a self-contained node server in `.output` everywhere else. `vercel.immutableStaticFiles` puts hashed chunks under `/_vercel/immutable/` so tabs opened before a redeploy keep loading their chunks; `functions.maxDuration: 300` carries over the old function timeout - `scripts/vercel-spa-routes.ts`: Nitro module that rewrites the generated Build Output routes (documents -> `_shell.html`, allow-list -> `__server`, missing chunk -> 404, base-path prefixes), with a unit test - `server.ts`: TanStack Start server entry that initializes Sentry before the route tree loads and wraps the handler with `wrapFetchWithSentry` **Changed:** - `start:tanstack` runs `.output/server/index.mjs` directly with Node's `--env-file-if-exists` for the `.env` cascade. Node doesn't expand `$VAR` references, so `scripts/generateLocalEnv.js` now writes literal values into `.env.test` - Dockerfile's TanStack stage copies `.output` instead of running `pnpm deploy`; the `server.js` shim loads `.env` and imports the Nitro server - `NEXT_PUBLIC_BASE_PATH` (the platform's `/dashboard`) only sets the router basepath; Vite's `base` stays at the root so chunks can use the immutable store. The routes module emits prefixed rules for `/dashboard/api/*` and `/dashboard/_serverFn/*` and rewrites `public/` files requested under the prefix back to the root - Self-hosted security headers come from a Nitro `routeRules` entry; on Vercel they stay in `vercel.ts` - `tslib` is inlined for the build only: Nitro's dev runner has no interop for its CJS wrapper - Monaco's worker chunks follow the client assets dir so they land in the immutable store too Verified on the `studio-staging` preview (`STUDIO_FRAMEWORK=tanstack` is scoped to this branch there): documents come back as the static shell, `/dashboard/api/*` hits the function, `public/` files resolve under the prefix, a missing immutable chunk 404s. Across two deployments of this branch, the older deployment's chunks still load from the immutable store and requests carrying its `__vdpl` cookie are answered by that deployment. Self-hosted path covered by the TanStack E2E job and the Docker build job. ## To test - On the `studio-staging` preview: `/dashboard/project/<ref>` should show `content-disposition: inline; filename="_shell.html"` and a single-region `x-vercel-id`; `/dashboard/api/get-utc-time` a two-region id - Sign in and click through a few pages, including one that opens Monaco (SQL editor) so the worker chunks load - After the next deploy, a tab left open on the previous one should still navigate (lazy chunks) and call the API without errors - Self-hosted: `STUDIO_FRAMEWORK=tanstack pnpm --filter studio build && pnpm --filter studio start`, then check `/api/platform/profile` and that responses carry the security headers <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Production TanStack deployments now run on Nitro’s self-contained server output. * Vercel routing serves static pages first while directing API and server-function requests appropriately. * Server-function requests can include deployment identification for consistent handling. * Local environment generation now writes resolved configuration values. * **Bug Fixes** * Improved handling of missing static assets and SPA fallback routing. * Server-side error monitoring now captures request errors in the new runtime. * **Refactor** * Replaced the legacy production server and smoke-test workflow with Nitro-based startup. * Removed automatic reload handling for stale client assets. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
1966209483 |
chore(deps): upgrade vitest to v5 (#49994)
Upgrades Vitest from 4.1.4 to 5.0.0 across the monorepo, fixes the handful of things v5 turned into hard errors, and drops the `vi.clearAllMocks()` boilerplate that v5's `clearMocks` default makes redundant. **Changed:** - `vitest`, `@vitest/ui`, `@vitest/coverage-v8` 4.1.4 → 5.0.0 (catalog) - `vi.mock` calls that lived inside `beforeAll`/`beforeEach`/test bodies moved to module scope (v5 throws on nested calls). Affects the Studio and docs setup files and four Studio tests. - `detectBrowser` test restores `navigator` via `vi.unstubAllGlobals()` instead of assigning `global.navigator`, which now reaches jsdom's getter-only property. - `RowEditor.utils.test.ts` restores its `JSON.stringify` spy. It used to leak a throwing mock for the rest of the file, which v5's coverage provider now trips over. A later test in the same file had been asserting the leak's side effect (valid JSON reported as invalid) and now asserts the correct behavior. - `@testing-library/jest-dom` 6.6 → 7.0.1. Its vitest type augmentation resolves through a peer now, so it lands on each package's own `vitest` instead of whichever copy pnpm hoisted. Fixes `toBeInTheDocument` type errors in dev-tools after the reshuffle. - `@testing-library/react` 16.0.0 → 16.3.3 for the React 19 peer range. - `vite: catalog:` added to dev-tools, www, and common. Without it they resolved a newer vite than the catalog pin, which forked a second vitest instance in the lockfile. There's now one. - ai-commands custom matcher types use v5's `Matchers<R, T>` form. - 110 test files: `vi.clearAllMocks()` removed from `beforeEach`/`afterEach` hooks, along with hooks that only did that and the imports they left unused. Calls that also reset/restore mocks are untouched. Second commit, mechanical. **Added:** - `.vitest/` to the root gitignore (v5 writes JSON/JUnit/HTML reporter output there) **Removed:** - `vite-tsconfig-paths` catalog entry and deps. Vitest 5 resolves tsconfig paths itself. Release-age note: this sat in draft with a temporary `minimumReleaseAgeExclude` entry for `vitest` and `@vitest/*` while 5.0.0 was inside the workspace's 3-day `minimumReleaseAge` window. That window has closed, so the exclusion is gone and nothing bypasses the release-age gate. **Perf** (local, medians of 3 runs, same machine): | Suite | v4.1.4 | v5.0.0 | |---|---|---| | studio | 144.1s | 141.7s (-2%) | | studio `--coverage` | 156.9s | 146.4s (-7%) | | ui-patterns | 6.27s | 5.07s (-19%) | | ui `--coverage` | 3.35s | 2.14s (-36%) | | www | 0.89s | 0.47s (-47%) | Studio is dominated by jsdom environment setup per file, which v5 doesn't change. `vitest doctor` recommends keeping the current pool config: the vm pools and `isolate: false` all break tests. ## To test - `pnpm install --frozen-lockfile` succeeds with no `minimumReleaseAgeExclude` entry for vitest. - CI: Studio unit tests, ui, ui-patterns, www, docs, and typecheck/lint should all be green. The lint ratchet was checked locally: warning counts on touched Studio files are identical to master. - `pnpm test:studio` locally passes with coverage (588 files, 6240 tests). - Open a Studio test that uses `toBeInTheDocument` in your editor and confirm no type errors on jest-dom matchers, in Studio and in `packages/dev-tools`. - Known pre-existing failures unrelated to this PR: one dev-tools test (`getEventCountBadge` capped pill) fails on master too. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Tests - Improved test coverage for JSON validation and mobile navigation behavior. - Updated test setup, cleanup, environment configuration, and matcher support across application and shared package suites. - Removed obsolete coverage for alternate MCP transport selection. ## Chores - Streamlined TypeScript path resolution and Vitest reporter output handling. - Updated testing libraries and Vitest tooling across documentation, Studio, website, and shared packages. - Added Vitest reporter output to ignored files. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
ec1029dff0 |
chore: migrate from clsx + tailwind-merge to shadcn-ui/cn (#49938)
Migrates the repo off `clsx` + `tailwind-merge` to [shadcn-ui/cn](https://github.com/shadcn-ui/cn). Every app and package already gets `cn` from `packages/ui`, so the swap happens in that one helper and flows through to Studio, docs, www, and the rest. **Changed:** - `packages/ui` `cn` helper now uses `createCn` from `cn/config`, keeping the custom `card`/`content` spacing scale so `p-card` still overrides `p-4`. It has an explicit signature and re-exports `ClassValue`. - The four www Launch Week files that imported the `ClassValue` type from `clsx` now import it from `ui`. - `blocks/vue` local `lib/utils.ts` re-exports `cn` from the package. - Comments/README that referenced tailwind-merge. **Removed:** - Direct `clsx` and `tailwind-merge` deps from `ui`, `ui-patterns`, `www`, and `blocks/vue`. `ui-patterns` and `www` declared them without importing. **Added:** - `packages/ui/src/lib/utils/cn.test.ts` covering clsx-style joining, conflict resolution, the custom spacing scale, and variant handling. Not migrated: the standalone apps under `examples/`. They're outside the workspace and mostly on Tailwind v3, which `cn` doesn't support. Lockfile note: after merging master, the lockfile diff is only the intended swap (`clsx` and `tailwind-merge` out, `cn@0.2.5` in). `tailwind-merge` stays in the lockfile as a transitive dep of a third-party package. Release-age note: this sat in draft with a temporary `minimumReleaseAgeExclude` entry for `cn` while `cn` was inside the workspace's 3-day `minimumReleaseAge` window. That window has closed, so the exclusion is gone and nothing bypasses the release-age gate. ## To test - `pnpm install --frozen-lockfile` succeeds with no `minimumReleaseAgeExclude` entry for `cn`. - `pnpm --filter ui test` – new `cn.test.ts` passes, including `cn('p-4', 'p-card')` → `p-card`. - Typecheck passes for studio, ui, ui-patterns, vue-blocks. www typecheck panics under tsgo on master already (pre-existing, unrelated); it passes with the JS `tsc` binary. - Spot-check Studio locally: class overrides still win in the usual places (e.g. `CodeEditor` height, `Button` variants with a custom `className`). https://claude.ai/code/session_01MkAt16tsPRDTm9oB5Jr8Ub <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Standardized Tailwind class merging across shared UI utilities while preserving conditional classes, custom spacing classes, and variant behavior. * Updated related components and examples to use the standardized class-merging utility. * **Tests** * Added coverage for conditional class handling, conflicting utility resolution, custom spacing classes, and variant separation. * **Documentation** * Updated usage guidance to reflect the standardized Tailwind class-merging approach. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
0ddf2006d3 |
[FE-4337] feat(studio): block pause, restore, and add-ons on High Availability projects (#49990)
Studio-side guard for Multigres (`high_availability`) projects, mirroring the platform API guard from supabase/platform#37527. Pause, restore/PITR, and add-on affordances now show a clear "unavailable on High Availability projects" state instead of failing with a 400 after the click. <img width="1195" height="632" alt="Screenshot 2026-09-04 at 2 03 11 PM" src="https://github.com/user-attachments/assets/718c09f2-d92b-49dc-90ed-5d9ff810b03d" /> **Added:** - Pause project button is disabled on HA projects with a tooltip - Scheduled backups tab short-circuits to an HA empty state (matches the existing PITR tab). Per-row Restore buttons are also disabled with a tooltip as defense in depth, since BackupItem is reusable - Restore to new project shows an HA admonition ahead of the permission / PG15 / physical-backup checks - Add-ons page shows a page-level HA notice, all three rows are locked with a tooltip, and the side panels are not mounted on HA so `?panel=pitr|ipv4|customDomain` deep links are inert - Component tests for `PauseProjectButton` and `BackupItem`, plus unit tests for the new `isHighAvailability` branch in `Addons.utils.ts` **Changed:** - Add-ons rows are now consistent: the IPv4 row uses the same padlock tooltip as PITR and custom domain instead of a tooltip on the badge. Same disabled-reason strings as before, just surfaced via the padlock on non-HA projects too - `BackupItem` tooltip text extracted into a `getTooltipText()` function (mirrors `PauseProjectButton`) - `HighAvailabilityDisabledSectionNotice` accepts a `className` Detection reuses the existing `useIsHighAvailability()` hook, which the rest of Studio already treats as the Multigres signal. ## To test Use an HA project (`project.high_availability === true`) and a normal project. HA project: - Settings > General: "Pause project" is disabled, tooltip reads "Pausing is unavailable on High Availability projects" - Database > Backups > Scheduled backups: HA empty state, no "No backups yet" / daily backup copy - Database > Backups > Restore to new project: HA admonition, no restore controls - Settings > Add-ons: notice at the top, padlock on all three rows with per-row tooltip, clicking rows does nothing, and `?panel=pitr` / `?panel=ipv4` / `?panel=customDomain` open nothing Normal project (regression): - No "High Availability" strings on any of the above pages - Pause button enabled (or disabled only for its usual reasons, e.g. paid plan) - Add-on rows open their side panels on click and via `?panel=pitr` - Scheduled backups tab shows its normal list / empty state <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Features** - High Availability projects now clearly indicate when scheduled backups, backup restoration, project pausing, IPv4, PITR, and custom domains are unavailable. - Added explanatory notices, disabled controls, and tooltips throughout affected settings and backup screens. - Restore-to-new-project workflows now provide guidance to contact support when unavailable. - **Bug Fixes** - Improved consistency of availability messaging across High Availability project settings and database backup actions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
f125126aec |
chore: make agent instructions agent-agnostic (#49941)
Makes the repo's AI-agent setup tool-agnostic: instructions live in
`AGENTS.md` files, skills live in `.agents/skills/`, and Claude Code,
Codex, Cursor, and Copilot all read the same sources. Also sweeps the
skills for stale and duplicated content while everything was being
moved.
**Changed:**
- Every `CLAUDE.md` (root, `apps/studio`, `apps/docs`, `apps/kb`) is now
a one-line `@AGENTS.md` import; the content moved verbatim into an
`AGENTS.md` beside it. The root one moved from `.claude/CLAUDE.md` to
the repo root for consistency.
- All skills now live in `.agents/skills/`; `.claude/skills` is a single
symlink to it (replacing the old mix of real dirs and per-skill
symlinks). Path references in `.coderabbit.yaml`, code comments, and
docs updated to match.
- `.github/copilot-instructions.md` keeps only the review policy and
points at `AGENTS.md` + `.agents/skills/`. Copilot code review reads
those natively now, so the per-topic
`.github/instructions/*.instructions.md` files were duplicates of the
skills.
- Stale skill content fixed: `studio-queries` imported a toast library
Studio doesn't use, `telemetry-standards` and `studio-testing` used
import paths that don't resolve, `safe-sql-execution` cited a boundary
test that doesn't exist, the ask-the-docs references described an
`AiPrompt` mechanism that was replaced by the ID-keyed registry, plus a
handful of wrong paths, a self-contradicting `waitForTimeout` rule, an
invalid Playwright signature, and a ConfigCat flag described as PostHog.
- `studio-error-handling` now explains when to use `AlertError` (the
default) vs `ErrorMatcher`.
**Added:**
- `apps/docs/AGENTS.md` (docs test requirements, from the old Cursor
rule)
- `studio-shortcuts` skill (from the old Copilot instruction file,
verified against the current registry)
- `ask-the-docs/reference/graphql-endpoint.md` and
`search-embeddings.md` (from the old Cursor rules, with the missing
resolver/registration/codegen steps filled in)
- Feature-flag measurement section in `telemetry-standards`
**Removed:**
- `.cursor/` (rules folded in as above; skill symlinks no longer needed)
and `.cursorignore`
- `.github/instructions/` (8 files)
- `vercel-composition-patterns/AGENTS.md` – a 946-line verbatim
concatenation of its own `rules/` directory, and a nested `AGENTS.md`
that agents could auto-load as repo instructions
- `edit-the-docs/reference/structure-and-flow.md` – word-for-word copy
of the skill's own Phase 2 text
## To test
- `readlink .claude/skills` → `../.agents/skills`, and `ls
.claude/skills/copywriting/SKILL.md` resolves
- Open a Claude Code session at the repo root and in `apps/studio` – the
imported `AGENTS.md` content should load as before
- `git diff master --stat -M` shows the skill moves as 100% renames
(content unchanged except the listed fixes)
- Spot-check a fixed claim, e.g. `import { toast } from 'sonner'` in
`studio-queries`, or the `logs.all` ESLint rule cited in
`clickhouse-logs-queries/references/codebase-integration.md`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **Documentation**
- Expanded guidance for documentation workflows, GraphQL resources,
search, ClickHouse logs, React forms, Studio testing, shortcuts,
telemetry, accessibility, copywriting, and composition patterns.
- Clarified local testing, linting, build workflows, error handling, and
AI coding agent usage.
- Added contributor guidance for the knowledge base, documentation, and
Studio areas.
- **Chores**
- Consolidated agent instructions and skill references.
- Removed obsolete editor-specific guidance, duplicate links, and
superseded documentation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
|
||
|
|
c6435f1cbe |
fix(studio): hide shared pooler chart for high availability projects (#49904)
High Availability projects run Multigres and don't have Supavisor, so the Shared Pooler (Supavisor) client connections chart in the database report only ever rendered an "Unable to load data" error for them. This hides the chart for HA projects, following the same pattern as the Disk IO Burst Balance chart. **Changed:** - `supavisor-connections-active` chart is now hidden when `project.high_availability` is true **Added:** - Unit tests covering the shared pooler chart's visibility for standard, HA, and unentitled projects ## To test - Open Reports → Database on a High Availability project – the Shared Pooler (Supavisor) client connections chart should no longer appear - Open the same report on a standard Pro project – the chart should still render as before <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * The active connection chart is now hidden for High Availability projects and projects without the database entitlement, preventing empty or unavailable data from being displayed. * **Tests** * Added coverage to verify the chart appears only for eligible standard projects. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
5d5b3b2aa8 |
[FE-4278] fix(studio): allow broadcast before any realtime message arrives (#49792)
In the Realtime Inspector, the messages view — which holds every
"Broadcast a message" entry point — only rendered once at least one
message had been received. With only Broadcast enabled and no inbound
traffic, the page stayed on the "Create realtime experiences" onboarding
forever, so there was no way to send a broadcast at all.
The render gate now keys off a channel being set rather than
`logData.length`: once you join a channel, `MessagesTable` renders and
its existing empty states provide the send entry points ("Listening • No
message found yet…" toolbar + the "No Realtime messages found" panel).
The onboarding remains the pre-channel state.
Addresses
[FE-4278](https://linear.app/supabase/issue/FE-4278/realtime-inspector-cant-send-broadcast-without-incoming-messages).
## To test
- Realtime → Inspector, before joining a channel: the "Create realtime
experiences" onboarding still shows
- Join a channel (with Presence off / Broadcast only so nothing
arrives): the listening view renders immediately with "No message found
yet…" and "Broadcast a message" in both the toolbar and the empty-state
panel — previously this was stuck on the onboarding
- Click "Broadcast a message" and send with defaults: the broadcast
appears in the grid
- Stop listening: no crash, messages retained
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* The Realtime Inspector now displays the messages view as soon as a
channel is selected.
* Empty-state guidance, including the option to broadcast a message, is
now available before any messages arrive.
* Pre-channel onboarding remains visible until a channel is configured.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
|
||
|
|
c5cffb6afb |
[FE-3716] fix(studio): restrict HA project creation to us-east-1 in prod (#49787)
`getHighAvailabilityRegionCode` had `staging` and `local` cases but no `prod` case, so it returned `undefined` in production and the High Availability region filtering never applied — the creation flow offered every AWS region while HA Alpha is only live in `us-east-1`. Adds the `prod` case returning `us-east-1`, matching staging. The region filter and the "High Availability projects are currently limited to…" banner both key off this value, so no other changes are needed. This keeps the accepted hardcoded-per-environment pattern for Alpha; the API/entitlement-driven enabled-regions design stays open on the ticket for when the rollout expands. **Changed:** - `ProjectCreation.utils.ts` — `prod` → `us-east-1` - `ProjectCreation.utils.test.ts` — the two env tables previously pinned prod as unrestricted; now expect `us-east-1` Addresses [FE-3716](https://linear.app/supabase/issue/FE-3716/show-enabled-regions) (and the folded-in MUL-1337). ## To test - `pnpm --filter studio exec vitest run components/interfaces/ProjectCreation/ProjectCreation.utils.test.ts` - In prod after deploy: new project → toggle High Availability → region select offers only East US (North Virginia) and shows the "limited to" notice; staging/local behavior unchanged (only the `prod` env branch changed) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - High-availability project creation now correctly uses the `us-east-1` region for production environments. - Region selection is now properly restricted to `us-east-1` when creating production projects. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
a14fc04937 |
[MUL-1475] fix(studio): show setup state on HA topology diagram during boot (#49786)
While an HA (Multigres) project is provisioning, the `/ha-admin` topology endpoints fail or return an empty topology as a matter of course — the cluster topology diagram rendered that as a hard "Failed to retrieve cluster topology" error (or the "Cluster topology unavailable" contact-support state). The diagram now checks the project status and, while the project is building (`COMING_UP`/`UNKNOWN`, same pair `ProjectLayout` treats as booting), shows a "Setting up project" empty state instead. Both the project-detail query (self-polls while booting) and the ha-admin queries (30s interval) keep refetching, so the diagram appears on its own once boot completes. Once the project is past provisioning, genuine errors and the empty-topology state surface exactly as before. <img width="1491" height="769" alt="mul1475-setting-up-state-wide" src="https://github.com/user-attachments/assets/3f095634-9939-41cd-88c3-0849cbad7374" /> **Added:** - Component tests for the four states: booting + error, booting + empty (→ setup state), running + error (→ error alert), running + empty (→ unavailable state) Addresses [MUL-1475](https://linear.app/supabase/issue/MUL-1475/polish-infra-diagram). ## To test - On an HA project mid-provisioning (or simulate: dev toolbar project-status override → `COMING_UP`, with `/ha-admin` requests failing), open Settings → Infrastructure — the topology panel shows "Setting up project" with a spinner, not the error alert - On a healthy HA project, the topology diagram renders as before; if `/ha-admin` genuinely fails there, the error alert still shows - `pnpm --filter studio exec vitest run components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/HaInstanceConfiguration.test.tsx` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a “Setting up project” state while projects are provisioning or their status is unavailable. * Prevents premature topology errors or unavailable messages during project setup. * Added accessible status announcements for loading and setup-state transitions. * **Bug Fixes** * Active projects now correctly display topology errors when cluster health data cannot be retrieved. * Healthy responses with no topology data display an appropriate unavailable state. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
8e9d6d81f2 |
[FE-4273] feat(studio): add Multigres to support form services (#49784)
Adds "Multigres" to the "Which services are affected?" multi-select on the Contact Support form, so Alpha customers can tag tickets for the Multigres Front inbox. Placed alphabetically between Edge Functions and Realtime; the later option ids are renumbered, which is safe — they're only used as React list keys, and the submit payload sends the lowercase value tokens (`affectedServices: "multigres;..."`, verified with a live submission). Addresses [FE-4273](https://linear.app/supabase/issue/FE-4273/add-multigres-to-support-form-services). Front-inbox routing itself is Platform-side (SUPPORT-421) and should match on the token `multigres`. ## To test - Open /support/new → "Which services are affected?" → Multigres appears between Edge Functions and Realtime, selectable alongside other services, and the combobox search finds it - Submit a ticket with it selected → the POST to `/platform/feedback/send` carries `affectedServices` containing `multigres` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Multigres as a selectable service option in the support interface. * Updated service ordering to accommodate the new option. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
47b33ebb22 |
[MUL-1346] chore(studio): hide metrics export banner for HA projects (#49781)
Hides the "Export Metrics to your dashboards. Get started for free!" banner (`ObservabilityLink`) for High Availability (Multigres) projects — the Metrics API it links to is not available for them. The check lives inside the shared component, so it applies to every observability sub-page that renders the banner; non-HA projects are unchanged. Addresses [MUL-1346](https://linear.app/supabase/issue/MUL-1346/database-observability-dashboard-remove-text-for-unsupported-feature). ## To test - On an HA project: open Observability → Database (and any other observability sub-page, e.g. Auth) — the "Export Metrics to your dashboards" banner at the bottom of the page should be gone - On a non-HA project: same pages — the banner still shows, with "Get started for free!" linking to the metrics docs <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Metrics export links are now hidden for High Availability projects, where the Metrics API isn’t available. * Existing metrics export functionality remains unchanged for supported projects. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
7a399d7879 |
ci(studio): fetch enough history for paths-filter on push events (#49766)
Fixes the master-push failures in the Selfhosted Studio E2E workflow (e.g. [this run](https://github.com/supabase/supabase/actions/runs/33383940726)) where all shards die in ~30s at the `dorny/paths-filter` step with: ``` fatal: Not a valid object name <github.event.before>^{commit} fatal: could not read Username for 'https://github.com': No such device or address ``` On push events, paths-filter diffs against `github.event.before` using local git. With the default depth-1 checkout that commit usually isn't present, so the action falls back to a `git fetch` — which runs unauthenticated because we set `persist-credentials: false`, and GitHub rejects unauthenticated git fetches from the runner IPs. Whether a job passed depended on whether the runner's shared git cache happened to contain the previous master tip, which is why shards fail nondeterministically and re-runs partially recover. **Changed:** - `fetch-depth: 50` on the checkout preceding paths-filter in the three workflows that run it on push (`studio-e2e-test`, `studio-unit-tests`, `studio-docker-build`), so the comparison base is always fetched with the checkout action's own credentials and no fallback fetch happens. `persist-credentials: false` stays. PR events are unaffected either way — paths-filter uses the GitHub API there, not git. ## To test - CI on this PR passes (PR path exercises the API code path) - After merge, the next few master pushes run Selfhosted Studio E2E without the paths-filter step failing <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Improved automated build, end-to-end test, and unit test workflows by ensuring sufficient Git history is available for change detection. * Increased reliability of workflow runs triggered by code pushes. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
e73811f1c8 |
fix(studio): restore useTrackExperimentExposure hook (#49763)
Restores `hooks/misc/useTrackExperimentExposure.ts`, fixing the typecheck failure on master that broke the latest Studio production deploy. The hook was deleted as dead code in #49719 (it was genuinely unused on master at the time), but #49534 was in flight and reintroduced a usage in `plan-presentation.ts`. The two PRs merged cleanly with no textual conflict, so nothing typechecked the combination until the deploy off master failed with: ``` plan-presentation.ts(5,44): error TS2307: Cannot find module '@/hooks/misc/useTrackExperimentExposure' ``` **Added:** - `apps/studio/hooks/misc/useTrackExperimentExposure.ts` — restored verbatim from before #49719; no longer dead code since `plan-presentation.ts` imports it ## To test - `pnpm --filter studio typecheck` passes (verified locally) - `pnpm knip --workspace apps/studio` no longer flags the hook (verified locally) - Studio production deploy succeeds once merged https://claude.ai/code/session_01XZGr2n1dBzJ7m3DYsGu852 Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
2c76bb371b |
chore(studio): gate dead code with knip in CI (#49721)
Makes knip a CI gate for Studio so dead files and unused dependencies fail the PR instead of piling up. Third PR in the stack, on top of #49719 (dead code) and #49720 (unused deps), which get Studio to a clean run. **Changed:** - knip `pnpx knip@~5.50.0` → root devDependency `knip@6.32.3`, `pnpm knip` now runs it. The old `pnpx` form was actually broken: it resolved knip's `typescript` peer to TS 7 and crashed with `ts.getDefaultLibFilePath is not a function`. (6.33.0 is newer but blocked by `minimumReleaseAge`.) - `knip.jsonc` rewritten for v6 with a `workspaces["apps/studio"]` block. Framework-convention files (`router.tsx`, `start.ts`, `routes/**`, `compat/**`, `api/server.js`) are `entry` rather than `ignore` — an ignored file's imports aren't traced, which is how `ShellFallback.tsx` (only imported from `routes/__root.tsx`) was being reported as dead. knip 6's Next.js plugin already covers `instrumentation*.ts`, `proxy.ts`, `pages/**`; its tanstack-router plugin only looks under `src/`, hence the manual entries. Narrow `ignoreIssues` for graphql-codegen output and the `CONSTRAINT_TYPE` enum; `ignoreDependencies` for the five implicit deps from #49720, each with a comment; `ignoreBinaries: ["vercel"]`. - `apps/studio/CLAUDE.md`: one bullet on the gate and where framework files go. **Added:** - `.github/workflows/studio-knip.yml` — path-filtered to `apps/studio/**` + knip/pnpm config, mirrors `studio-lint-ratchet.yml`'s setup (no sparse checkout: knip needs every workspace's `package.json` to resolve the graph). Runs `pnpm knip --workspace apps/studio --reporter symbols --reporter github-actions` so findings show up as inline PR annotations. ~5s locally. Scope notes: the gate is Studio-only — the full-monorepo run still has ~400 dead files in `www`/`docs`/`blocks`, which is a separate effort. `exclude: ["types", "exports"]` is kept, so unused exports aren't gated yet, but `enumMembers`/`duplicates` are (they caught real things in #49719). ## To test - `pnpm knip --workspace apps/studio` exits 0 on this branch - The `Studio Dead Code (knip)` workflow runs on this PR and is green - Sanity-check the gate bites: add a throwaway `apps/studio/lib/unused.ts`, run `pnpm knip --workspace apps/studio` → reports it and exits 1 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **CI** * Added automated dead-code and unused-dependency checks for the Studio workspace on relevant pushes and pull requests. * Results appear in workflow summaries and as inline pull request annotations. * **Maintenance** * Improved analysis of framework-convention files and Studio code. * Standardized the local code-quality check and updated its configuration support. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
3260053e52 |
chore(studio): remove unused dependencies found by knip (#49720)
Removes the Studio dependencies knip reports as unused, and declares one it reports as unlisted. Second PR in the stack (on top of #49719, followed by #49721 which adds the CI gate). **Removed:** - `@ai-sdk/provider`, `@ai-sdk/provider-utils` — zero references - `eslint-plugin-jsx-a11y` — the `jsx-a11y/*` rules resolve through the plugin registered by `eslint-config-next` (via `eslint-config-supabase/next`); verified 259 a11y warnings still fire after removal - `common`, `config` from `devDependencies` — duplicates of the `dependencies` entries **Added:** - `@tailwindcss/postcss` as a Studio devDependency — `apps/studio/postcss.config.cjs` loads it (through `config/postcss.config`), but only `packages/config` declared it, so under pnpm's strict isolation it was never resolvable from Studio's own `node_modules` **Kept deliberately** (nothing imports them by a specifier knip can follow, but removing them breaks things — they get `ignoreDependencies` entries in #49721): `lodash-es` (string-resolved in `vite.config.ts`), `raw-loader` (loader string in `next.config.ts`), `import-in-the-middle` / `require-in-the-middle` (Sentry/OTel runtime hooks, #35030), `@babel/core` (resolution pin, #45876). Heads-up on the lockfile: ~500 of the lines are pnpm re-resolving `apps/www`'s stale auto-installed vitest peer from `vite@6.4.3` → `8.2.1` (www doesn't depend on vite directly; Studio already runs vitest on vite 8). Any dependency change triggers it — not specific to this PR. ## To test - `pnpm install --frozen-lockfile` succeeds - `pnpm dev:studio` — Tailwind styles still apply (the postcss plugin now resolves from Studio) - `pnpm lint --filter=studio` still reports `jsx-a11y/*` warnings, no "Definition for rule not found" - `pnpm --filter www test` (www's vitest now runs on vite 8) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated Studio’s development tooling configuration. * Removed unused package dependencies and development tools. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
b0e31be89a |
chore(studio): remove dead code found by knip (#49719)
Removes Studio code that nothing imports, as reported by knip. First PR in a stack of three: this one is pure deletions, #49720 removes the unused dependencies, #49721 upgrades knip and adds the CI gate so this doesn't accumulate again. Every file was verified with a repo-wide grep for its basename, exported symbols, and string/dynamic imports before deletion — none are reachable via `next/dynamic`, a barrel file, or a config. **Removed:** - `Billing/Usage/UsageWarningAlerts/{CPU,RAM,DiskIOBandwidth}Warnings.tsx` (whole directory) - `DataWarehouse/FormFooterChangeBadge.tsx` (whole directory) - `Database/Replication/ReplicationDiagram/EmptyReplicationDiagram.tsx` - `Integrations/Vercel/OrganizationPicker.tsx` - `QueryInsights/QueryInsightsTable/QueryInsightsTableRow.tsx` - `hooks/misc/useTrackExperimentExposure.ts` - `data/ai/{parse-client-code,sql-policy}-mutation.ts`, `data/misc/parse-query-mutation.ts`, `data/database/table-check-rls-mutation.ts` - `data/notifications/notifications-v2-{archive-all-mutation,summary-query}.ts` + their two now-unused keys in `notifications/keys.ts` (`listV2` kept) - `data/platform-apps/platform-app-{update,signing-key-delete}-mutation.ts` - `DateTimeFormats.DATE_ONLY` and the unused `Notebooks.{MarkdownCell,LogCell,ChartConfig}` types **Changed:** - `ReportPadding` no longer has a duplicate default export; its 9 default importers (observability pages) now use the named export Not removed: `CONSTRAINT_TYPE`'s unused members mirror the closed set of `pg_constraint.contype` values, so they're documentation rather than dead code — suppressed narrowly in #49721's knip config instead. ## To test - `pnpm --filter studio run typecheck` and `lint:ratchet` pass - Observability pages (`/project/[ref]/observability/*`) still render with padding — they're the only code touched, via the `ReportPadding` import change - Notifications popover still loads and marks-as-read (the removed keys weren't used for invalidation) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Removed Features** - Removed CPU, memory, and disk usage warning alerts. - Removed the Vercel organization picker and empty replication diagram. - Removed query insights row actions and several SQL assistance tools. - Removed notification summary and archive-all capabilities. - Removed platform app update and signing-key deletion actions. - Removed the form change-count badge and experiment exposure tracking. - **Refactor** - Updated observability reports to use the revised report layout export. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
29493e02d0 |
[FE-4010] feat(studio): add read-only replica connection option for HA projects (#49485)
For Multigres (HA) projects you can't connect to read replicas directly — reads go through a read-only load balancer on the primary's host at port 5433. Since #44695 stripped the pooler UI, HA projects showed no source option at all in the Connect dialog and still prompted for the IPv4 add-on. This surfaces it as a first-class, clearly-labeled read-only source. In the UI it's labeled `Replica (read-only)` rather than "load balancer" — the primary goes through the same gateway, so "load balancer" would be confusing from a product perspective (internally the `load-balancer` source identifier and `HIGH_AVAILABILITY_LOAD_BALANCER_PORT` constant keep their names). <img width="883" height="342" alt="Screenshot 2026-08-24 at 11 32 26 PM" src="https://github.com/user-attachments/assets/3716f6dd-0325-4b9d-adbc-9ece9244de62" /> **Added:** - Source select for HA projects in the Direct tab: `Primary database` + `Replica (read-only)` (individual replica rows are filtered out — they're only reachable via the load balancer) - Replica (load balancer) connection strings on all 9 connection types: primary host, port `5433`, with the Multigres-required `sslmode=require&sslnegotiation=direct` params (JDBC gets the `sslNegotiation` spelling, .NET gets `SSL Negotiation=Direct`) - `Read-only` badge on the connection code block + note pointing writes at the primary - Programmatic labels for the ConnectSheet select/switch/multi-select fields (the Source combobox previously had no accessible name) **Changed:** - The generated-file step (Node.js/Golang/.NET/Python/SQLAlchemy) is now source-aware — it previously ignored the Source selection entirely (also affected read replicas on normal projects) and silently rendered the primary's connection info - .NET template now emits `Port=` (Npgsql defaults to 5432 when omitted) and the install step actually installs Npgsql (pinned 9.0.5 — `SSL Negotiation` requires 9+) - SQLAlchemy `DATABASE_URL` merges `sslmode=require` into the string's existing query params instead of a hardcoded suffix that could drop TLS - Source option labels normalized to sentence case (`Primary database`, `Read replica (…)`) - `MultipleCodeBlock` (ui-patterns) accepts an optional `className` - HA coercion in `useConnectState` extended: a stale replica `connectionSource` restored from URL/localStorage falls back to the primary **Removed:** - IPv4 add-on admonition for HA projects (the forced-direct method was tripping it; the add-on doesn't apply to Multigres) Out of scope (needs platform work): SQL editor / Data API / other `DatabaseSelector` surfaces — executing against the load balancer requires a platform-issued connection string, and the load-balancers API only returns a REST endpoint today. The `5433` port is a client-side constant (`HIGH_AVAILABILITY_LOAD_BALANCER_PORT`) until the API exposes it. ## To test On an HA (Multigres) project: - Open Connect → Direct: Source shows exactly `Primary database` and `Replica (read-only)`; selecting the replica shows `…@<primary-host>:5433/postgres?sslmode=require&sslnegotiation=direct`, a `Read-only` badge, and the read-only note - Cycle all 9 connection types with the replica selected — every snippet carries port 5433 (`.NET` includes `Port=5433;…;SSL Negotiation=Direct`), badge/note persist - No "Enable IPv4 add-on" admonition anywhere in the Direct tab - Switch tabs / hard-reload: source resets to primary with no stale badge/string combos On a normal project: - Direct tab unchanged: no `Replica (read-only)` option, pooler badges and IPv4 admonitions behave as before, `.NET` now shows `Port=5432` and no `SSL Negotiation` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added read-only load-balancer connection options for high-availability projects. - Added .NET and SQLAlchemy connection examples with required SSL settings. - Added clear read-only labels and notices explaining write restrictions. - **Bug Fixes** - Suppressed IPv4 add-on notices for high-availability connections. - Improved connection-source selection and restored-setting handling. - Improved connection form identification and accessibility. - **Style** - Added customizable styling support for multi-code-block displays. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
928049ce2c |
[FE-3717] feat(studio): Multigres cluster topology diagram (#49298)
Adds an infrastructure/topology diagram for High Availability (Multigres) projects showing the real cluster topology — gateway tier, shard group, and the primary + read replicas inside it — on both the project homepage and the database/replication page, replacing the primary-only view and the "Replication unavailable" empty state. <img width="790" height="541" alt="Screenshot 2026-08-20 at 8 23 42 PM" src="https://github.com/user-attachments/assets/0bce21e3-2091-4285-84ca-60fdecb10d39" /> Addresses [FE-3717](https://linear.app/supabase/issue/FE-3717/show-replicas-in-replication-diagram). **Added:** - `data/ha-admin/` — read-only queries for the mgmt-api `/ha-admin/v1/{gateways,poolers,cells,databases}` multiadmin passthrough (ported from `bobbie/ha-stub`, re-authored to `queryOptions`). Responses are validated with zod at the fetch boundary (all fields optional per proto3 zero-value omission; enum-shaped fields stay plain strings so new proto values degrade gracefully); malformed payloads surface through the diagram's error fallback. - `HaTopology.utils.ts` — pure topology mapper (+ 26 unit tests): shard grouping, primary identified via `routingState.role` (deprecated `type` as fallback) with **failover-safe election** — when the outgoing and incoming primary briefly both claim `ROUTING_ROLE_PRIMARY`, the highest routing rule (coordinator term, leader subterm) wins, matching the multigateway's own election — plus status mapping onto the existing Healthy / Coming up / Going down / Unhealthy vocabulary, and an AZ formatter for `id.cell` that degrades to the raw cell name. - HA diagram nodes/edges: `Multigateway` card, shard group box with header pill (`Shard 1`, `Automatic failover` + tooltip), `Primary Database` card styled like the standard diagram's — neutral border, green icon chip (with the standard CPU / Disk / RAM footer — connections omitted until their meaning through the multigateway is confirmed), `Read Replica` cards, and the standard animated replication edges (status lives on the card badges). Poolers and gateways poll every 30s without re-running layout (topology projection + structural sharing). Drag-to-pan works through the shard group box, and the metrics footer's skeleton matches the loaded row height so the card doesn't shift. - Accessibility: the failover tooltip trigger is a keyboard-focusable button, status badges sit in stable `role="status"` live regions, the region flag is decorative (`alt=""`), and the edge dash/spinner animations respect `prefers-reduced-motion` (applied to the pipelines diagram's edges too). - Fallbacks: `AlertError` ("Failed to retrieve cluster topology") when either ha-admin query errors, and a "Cluster topology unavailable" empty state when the topology comes back empty — never a half-rendered diagram. **Changed:** - `InstanceConfiguration` is now topology-source-aware: it branches internally on `useHighAvailability()`, so both surfaces (homepage `TopSection` and the replication page) get the right diagram with no new wiring. The two-pass measured dagre layout moved into a shared `DiagramFlow`; `nodeTypes`/`edgeTypes` are module-level consts. - `getEdgeVisual` + the mid-edge icon chip lifted out of `ReplicationDiagram/Edges.tsx` into `components/ui/ReactFlow/EdgeVisual.tsx` so both diagrams derive edge icon + line style from one state object (no behavior change for the pipelines diagram). The primary card's CPU/Disk/RAM footer is likewise extracted into a shared `ComputeMetricsFooter`. - Fixes a latent relayout loop inherited from the region-box pattern: handing React Flow a freshly created (unmeasured) group node on every layout pass reset `nodesInitialized`, re-triggering the measured pass and `fitView` forever — which made the diagram snap back to center and effectively unpannable. The shared `DiagramFlow` now re-attaches known measurements to group nodes, which also covers the standard diagram's region boxes. - Standard diagram: the API Load Balancer → primary edge is now static — no data flows over it, the line only indicates a relation. - `database/replication` page: the HA early-return empty state is replaced by the diagram under a "High Availability cluster topology" header. Non-HA projects are untouched. **Intentional deviations from the mock** (for design review): 1. **No per-replica regions** — alpha replicas are one-per-cell inside a single region, so the mock's `eu-west-1` / `ap-southeast-1` on sibling replicas would be false. Availability zone per node, region shown once on the primary. 2. **"Primary Database", not "Main Database"** — matches the string both existing diagrams already ship, and the same component now renders both project types. 3. **No collapse chevron on the shard header** — alpha has exactly one shard; collapsing it would hide the whole diagram. The group box still ships; add collapse when `shards.length > 1`. 4. **Failover shown on the shard group, not replica cards** — failover is a cohort property; per-card badging would assert readiness we can't verify without a per-pooler `/status` fanout. 5. **Standard node/edge styling reused** (per review) — neutral primary border + green chip and the default animated edges instead of the mock's green ring and dashed green arrowed edges, keeping the HA and non-HA diagrams visually consistent. **Confirmed against a real local Multigres cluster:** cells are named `cell-1`/`cell-2`/… (not AZ-shaped — the AZ formatter falls back to the raw cell name as designed); `GET /platform/projects/{ref}/databases` returns only the primary row for HA projects; and the `/ha-admin` passthrough returns **each gateway/pooler record once per cell it fans out to** — the topology mapper dedupes by id, but worth confirming with @sbc-bobbie whether the backend should dedupe. **Known alpha limitation:** node health and the "replicating" edge state derive from the pooler's *topology record* (`lifecycleStatus`/`servingStatus`), not a live probe — a pooler that crashes without publishing a terminal state can read as healthy until the topology evicts its record, and a serving replica with paused replay still shows a green edge. This matches the existing replication diagram's semantics (`ACTIVE_HEALTHY` ⇒ animated edge). Live per-pooler signals (WAL receiver state, replay position) exist on `GET /poolers/{cell}/{name}/status` but need a per-pooler fanout — deliberately deferred, noted on `getPoolerStatus`. **Still to confirm** (doesn't block review): whether the `/ha-admin` passthrough is deployed to production or staging-only (if staging-only, this should get a flag before GA). ## To test Tested end-to-end locally against a real Multigres project (standard-project regression pass, HA creation flow, error fallback against real 500s, and full topology + polling + console checks against live multiadmin data): - **HA project homepage**: diagram card shows Multigateway → shard box (`Shard 1`, count badge, `Automatic failover` tooltip) → green-bordered Primary Database (region, AZ, size) + Read Replica cards (AZ), dashed green animated edges to healthy replicas. No flow/map toggle for HA. - **HA project → Database → Replication**: same diagram under a "High Availability cluster topology" header; no Destinations section; the old "Replication unavailable…" state is gone. - **Error path**: if `/ha-admin/v1/*` fails, both surfaces show "Failed to retrieve cluster topology" with Contact support — no partial diagram. - **Standard project regression**: homepage diagram (primary card, flow ⇄ map toggle round-trips), replication page (pipelines diagram + Destinations) all unchanged; zero requests to `/ha-admin/*`. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added High Availability topology diagrams to the Replication page. - Display gateways, primary databases, replicas, shards, statuses, regions, infrastructure details, and compute metrics. - Added observability links and live topology updates with loading, error, and unavailable states. - **Bug Fixes** - Improved handling of incomplete infrastructure identities and unexpected data. - Corrected topology layout, node spacing, and visual edge behavior. - **Accessibility** - Reduced-motion preferences now disable diagram animations and loading effects. - Improved status announcements for assistive technologies. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
23949ae633 |
[MUL-1364] fix(studio): use multipooler copy for dedicated pooler chart on HA (#49525)
The "Dedicated Pooler Client Connections" chart on the Database observability page labels its series `pgbouncer` and links to PgBouncer limits docs. High Availability projects run Multigres, whose dedicated pooler is multipooler, so that copy was misleading. This swaps the copy for HA projects and drops the docs link until multipooler docs exist (per the ticket, disabling the link for now is fine). **Changed:** - HA projects: legend label `pgbouncer` → `multipooler`, series tooltip → "Multipooler connections" - HA projects: the info icon shows a "docs coming soon" tooltip instead of linking to the compute-and-disk limits docs - Non-HA projects are unchanged **Added:** - Unit test for `getReportAttributesV2` covering both the PgBouncer and multipooler branches Out of scope (flagging for follow-up): the "Max pooler connections" reference line still uses the PgBouncer value on HA projects, and the Supavisor chart still renders for HA projects. Addresses https://linear.app/supabase/issue/MUL-1364/database-dashboard-update-dedicated-poolers-copy ## To test - On a High Availability project, open Observability → Database and find "Dedicated Pooler Client Connections" - Legend and hover tooltip should say `multipooler`; the info icon should show a tooltip ending in "(docs coming soon)" with no link - On a non-HA project, the chart should be unchanged: `pgbouncer` legend and the info icon links to the compute-and-disk docs <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - High Availability projects now display dedicated connection pooler charts with multipooler-specific labels and guidance. - Standard projects continue to show PgBouncer information and documentation links. - High Availability charts include a tooltip indicating that documentation is coming soon. - **Tests** - Added coverage to verify the correct chart labels, tooltips, and documentation behavior for both project types. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
3811e75140 |
[MUL-1417] feat(studio): show SSL enforcement as always on for HA projects (#49524)
High Availability (Multigres) projects always enforce SSL, and the management API now rejects any attempt to read or change the setting (supabase/platform#37484). This makes the Database Settings toggle reflect that instead of surfacing an error. **Changed:** - `SSLConfiguration`: skip the `ssl-enforcement` query for HA projects (via `useHighAvailability`) and render the "Enforce SSL on incoming connections" switch checked + disabled with the tooltip "SSL is always enforced on High Availability projects". Non-HA projects are unchanged. - `SSLEnforcementConfirmDialog`: add a controlled `open`/`onOpenChange` mode. The switch now opens the dialog from its own `onCheckedChange` rather than a wrapping `AlertDialogTrigger`, so a disabled switch can no longer open the dialog by clicking the row wrapper beside it (this was reachable for every disabled state, and for HA would have PUT into the new 400 guardrail). The JIT section's existing trigger-with-children usage is untouched. **Added:** - `SSLConfiguration.test.tsx` (MSW): HA → checked/disabled, tooltip, no `ssl-enforcement` request, no dialog from switch/wrapper clicks; non-HA → reflects fetched config, switch opens the dialog and Cancel leaves it unchanged. ## To test On an HA project → Project Settings → Database → SSL configuration: - Switch is on and disabled, hovering shows "SSL is always enforced on High Availability projects" - No request to `/v1/projects/{ref}/ssl-enforcement` fires, no spinner sticks, no error toast - Clicking the disabled switch or the empty area beside it does **not** open the "brief downtime" dialog On a non-HA project: - Switch reflects the current config and the GET fires once - Clicking the switch opens the confirm dialog with Enable/Disable SSL; Cancel and Escape close it without changing the switch or sending a PUT - Clicking beside the switch (not on it) does not open the dialog Linear: https://linear.app/supabase/issue/MUL-1417/database-settings-disable-ssl-enforcement-toggle <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - High Availability projects now show SSL as always enabled, with an explanatory tooltip. - SSL settings are protected from changes on High Availability projects. - SSL confirmation dialogs now open and close reliably when changing settings. - Added accessible announcements for SSL configuration loading and updates. - **Bug Fixes** - Improved SSL state handling for standard and High Availability projects. - Prevented unnecessary SSL enforcement checks for High Availability projects. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
0b37f0edc1 |
[MUL-1347] fix(studio): hide Disk IO Burst Balance chart for HA projects (#49527)
Hides the Disk IO Burst Balance chart on the Database observability page for High Availability projects. Their volumes have no burst credit pool, so the panel had nothing to load and rendered "Unable to load data for Disk IO Burst Balance". **Changed:** - `getReportAttributesV2` now also requires `!resolveHighAvailability(project)` before showing the `disk-io-burst-balance` chart – the existing feature flag and `hasBurstableIO` gating are unchanged for non-HA projects **Added:** - Unit tests covering the chart's visibility across HA / flag / compute size combinations ## To test - On a High Availability project with the `showDiskIOBurstBalanceChart` flag on, open `/project/[ref]/observability/database` – the Disk IO Burst Balance panel should no longer render - On a non-HA project with a burstable compute size (e.g. micro) and the flag on, the panel should still render as before Addresses https://linear.app/supabase/issue/MUL-1347/remove-panel-from-database-dashboard <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Hid the Disk I/O Burst Balance chart for High Availability projects, where no burst-credit data is available. * Continued hiding the chart when burst balancing is unsupported or disabled. * **Tests** * Added coverage for eligible projects and scenarios where the chart should remain hidden. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
002be81efb |
[FE-4184] fix(studio): hide view logs link for disabled services (#49487)
On Multigres/HA projects, Realtime is intentionally shown as **Disabled** in the project home status hover card, but the row still linked to logs with a "View logs" hover affordance and used the same warning triangle as an unhealthy service. Disabled services now render as a non-interactive row with a neutral "off" icon. **Changed:** - `ServiceStatus.tsx` – services with status `DISABLED` render a plain `div` instead of a `Link` (no hover background, no "View logs" + chevron). All other services keep the existing click-to-logs behavior. - `DISABLED` services now show a muted `MinusCircle` icon instead of the `AlertTriangle` used for unhealthy services, so "off" no longer reads as "broken". - "View logs" affordance is also revealed on keyboard focus (`group-focus-visible`), not just hover. - Applies to any `DISABLED` service, not just Realtime – PostgREST also resolves to `DISABLED` when its `db_schema` is empty. ## To test - Open the home page of a Multigres/HA project and hover the **Status** stat to open the service hover card - Realtime row shows a muted circle-minus icon with "Disabled", no hover highlight and no "View logs" link - Other rows (Database, Auth, Storage, etc.) still highlight on hover, show "View logs" on hover or keyboard focus, and navigate to their logs page on click - Unhealthy services still show the warning triangle - On a non-HA project, all rows (including Realtime) behave as before Addresses FE-4184 --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
caceeb429f |
[MUL-1336] fix(studio): show HA project costs as free during Alpha (#49383)
HA (Multigres) projects are free during Alpha, but the project creation form still presented the forced large compute as a real charge. The footer now shows **$0/m** for HA projects, with the usual compute price struck through + a "Free during Alpha" note in the cost-breakdown tooltip and the compute size dropdown. Follows the pattern from #49249. Addresses [MUL-1336](https://linear.app/supabase/issue/MUL-1336/bug-when-creating-new-projects). <img width="688" height="167" alt="Screenshot 2026-08-21 at 5 27 39 PM" src="https://github.com/user-attachments/assets/804b9243-77ae-4961-9083-5e1290734d3a" /> <img width="503" height="202" alt="Screenshot 2026-08-21 at 5 27 32 PM" src="https://github.com/user-attachments/assets/f217edd4-2204-4e5e-87f8-f54974e3c6fa" /> **Changed:** - `ProjectCreationFooter`: "Additional costs" shows `$0/m` when HA is on; the tooltip gains a "High availability projects are free during Alpha for up to 2 projects." sentence; the New-project row's price renders struck through with a "Free during Alpha" sub-line; the HA project's compute is excluded from "Total Monthly Compute Costs" (clamped at 0 so credits can't produce a negative total — a no-op for non-HA since spend already floors above zero) - `ComputeSizeSelector`: the per-option `$X/hour (~$Y/month)` line renders struck through with "Free during Alpha" beneath it when HA is on (both tagged `data-field="instance-details"` so the collapsed trigger keeps hiding them) - `ProjectCreationForm`: threads the watched `highAvailability` value into the footer The "Confirm compute costs" modal was already suppressed for HA by the existing `!values.highAvailability` guard — no change needed there. ## To test - On a paid org, open New Project and toggle High Availability on: the footer should read `$0/m` (brand green, no strikethrough), its ⓘ tooltip should show the HA sentence and the New row's `$110` struck through with "Free during Alpha", and the Total should exclude the $110; the compute dropdown's Large option should show its price struck through with "Free during Alpha" - Toggle HA off (and on/off a few times): all cost displays should revert exactly to normal — green real price, no strikethrough, no "Free during Alpha" anywhere outside the HA toggle's own description - With HA off and compute size Medium, submit: the "Confirm compute costs" modal should still appear as before (Cancel works) - Collapsed compute-size trigger should never show a price line or "Free during Alpha" in either state <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## New Features - High-availability project options now show compute pricing as free during Alpha. - Standard compute prices are displayed with a strikethrough alongside the Alpha-free notice. - Project cost summaries accurately show no additional compute charge for high-availability selections. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
b9df7aaf9e |
[FE-3711] feat(studio): make compute config read-only for HA projects (#49359)
Makes the compute-size configuration on Settings → Infrastructure read-only for High Availability (Multigres) projects during Alpha — HA projects run on a single fixed compute size and resizing isn't supported yet (previously attempting one could leave a project stuck Resizing). Gated on `project.high_availability` via the existing `useHighAvailability()` hook — the same signal every other HA gate in Studio uses. **Changed:** - Compute size options other than the project's current size render with the existing locked treatment (greyed out, lock icon, tooltip) for HA projects, and the whole radio group is disabled - A `HighAvailabilityDisabledSectionNotice` in the Compute section explains that HA projects run on a fixed compute size during Alpha - The compute branch of `onSubmit` and the read-replica compute-recommendation handoff are skipped for HA projects, so a compute change can never reach `POST /billing/addons` - The "Contact Us" larger-sizes card is hidden for HA projects - Form initialization now also fires once the project loads for HA projects (disk-attribute queries never run on their cloud provider, so the existing reset effect never fired and the picker showed the `ci_micro` fallback as selected) **Added:** - Two MSW page tests in the Infrastructure suite covering the HA read-only state and the unchanged editable state for non-HA projects ## To test - On an HA (Multigres) project: Settings → Infrastructure should show a notice under Compute size, the project's current size selected, every other size locked with a tooltip, no "Contact Us" card, and clicking any option should never surface the "Review changes" bar - On a regular project: compute selection, "Review changes" → "Confirm changes", and the Contact Us card all behave as before - `pnpm vitest run "tests/pages/project/[ref]/settings/infrastructure.test.tsx"` Addresses [FE-3711](https://linear.app/supabase/issue/FE-3711/make-compute-configuration-read-only-for-mvp) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added High Availability notices and guidance to the Compute settings. * High Availability projects now show compute sizes as read-only, with explanations for unavailable options. * Hid the larger-instance contact option for High Availability projects. * **Bug Fixes** * Prevented unsupported compute resizing and add-on changes for High Availability projects. * Preserved compute resizing and review actions for standard projects. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
aa3643f39d |
fix(studio): restrict geolocated default region to provider regions (#49141)
Follow-up to #49131. For `AWS_NIMBUS` orgs, the new-project form's Region trigger could show a region that wasn't in the dropdown at all (e.g. "Southeast Asia (Singapore)" while the list only offered "East US (North Virginia)"). The geolocation-based default region (`useDefaultRegionQuery`) picked the nearest region from **all** AWS regions and seeded it into `dbRegion` unvalidated, ignoring the provider's restricted region list. **Changed:** - `getDefaultRegionOption` now computes the nearest region only over the provider's available regions (new `getDefaultRegionCandidateKeys` helper). The flag-based restricted pool (`defaultRegionRestrictedPool`) narrows within that set and is ignored if the intersection would be empty. - The form's default-region selection is extracted into `resolveDefaultDbRegion` (`ProjectCreation.utils.ts`): High Availability region first, then the recommended smart region, then the geolocated default — used only when the provider actually offers that region — falling back to the provider's static default. - `getAvailableRegions` takes an injectable `environment` param (same pattern as `getHighAvailabilityRegionCode`) so the prod-only Nimbus region list is unit-testable. **Added:** - Unit tests for `getDefaultRegionCandidateKeys` (provider clamping incl. Nimbus on prod, restricted-pool intersection, empty-intersection fallback), `getAvailableRegions` across environments, and `resolveDefaultDbRegion` (branch priority plus the fallback when the geolocated region isn't offered). ## To test - Emulate a Nimbus org locally by setting `"infra:cloud_providers": ["AWS_NIMBUS"]` in `apps/studio/hooks/custom-content/custom-content.json`, then open the new-project form: the Region trigger must show the same region the dropdown offers (locally that's only Southeast Asia (Singapore)). To reproduce the original mismatch path, stub `https://www.cloudflare.com/cdn-cgi/trace` to return `loc=US` — the trigger should still be clamped to the provider's region rather than showing a US region - Block or fail the Cloudflare trace request: the trigger should fall back to the provider's static default region, not sit blank or loading - Restore the normal provider list: the smart-region flow ("General regions" + "Specific regions" with Recommended badges) is unaffected — the geolocation request doesn't even fire on that path — and toggling High Availability still transitions the region list cleanly <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit - **Bug Fixes** - Region suggestions now respect the selected cloud provider and deployment environment. - Project creation avoids unavailable geolocated regions and falls back to a supported provider default. - Restricted region pools now fall back reliably to available provider regions. - AWS Nimbus selection reflects the active environment while preserving high-availability and smart-region behavior. - **Tests** - Added coverage for provider-specific, environment-specific, restricted, and fallback region selection scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
de4bec77d6 |
[MUL-1338] fix(studio): lock compute size to large for HA projects (#49249)
When the High availability (Multigres) toggle is enabled in the New
Project form, the Compute size dropdown now offers only **Large** and
the form value is forced to `large`. Previously HA projects showed the
same micro/small/medium options as regular projects.
**Added:**
- `HIGH_AVAILABILITY_INSTANCE_SIZE` constant (`'large'`) alongside the
other `HIGH_AVAILABILITY_*` constants
**Changed:**
- `ComputeSizeSelector` watches `highAvailability` and renders only
Large when it's on (hiding the "Larger instance sizes available after
creation" row); the `cloudProvider` read is now a reactive `useWatch`
instead of a render-time `getValues()`, so the list re-filters when HA
forces the provider to `AWS_K8S`
- `HighAvailabilityInput` forces `instanceSize` to `large` when HA
toggles on and restores the previously selected size when it toggles
off, alongside the existing `dbRegion`/`cloudProvider` handling
- The compute size and region selects ignore Radix's spurious
`onValueChange('')` — Radix emits it when a select's value and option
list change in the same tick, which wiped the forced value (details in
the inline comments)
- HA projects skip the "Confirm compute costs" modal on submit — HA is
free during Alpha, so the forced large size shouldn't trigger the
$110/mo confirmation
## To test
- On a paid org, open the New Project form: with HA off, the Compute
size dropdown shows micro/small/medium plus the disabled "Larger
instance sizes available after creation" row
- Toggle High availability on: the dropdown shows only Large, the
trigger reads "large / 8 GB RAM / 2-core CPU" (not the placeholder), the
region locks as before, and the footer shows $110/m
- Check the network tab: the `available-regions` request goes out with
`desired_instance_size=large` and returns 200 (no request with an empty
`desired_instance_size`)
- Select medium first, toggle HA on then off: medium is restored (same
for other sizes); rapid toggling shouldn't leave the field blank
- With HA on, submitting goes straight through without the "Confirm
compute costs" modal; a non-HA medium project still shows it
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* High-availability projects now automatically use the required
dedicated instance size.
* Disabling high availability restores the previously selected instance
size.
* Compute size options are filtered based on cloud provider and
high-availability settings.
* **Bug Fixes**
* Prevented accidental clearing of compute size or region selections
during option updates.
* Compute-cost confirmation is no longer required for high-availability
projects.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
|
||
|
|
6073c7a7e7 |
[FE-4193] fix(studio): show proper names for custom identity providers (#49182)
Unregistered `custom:*` identity providers (e.g. white-label deployments' own OAuth providers) rendered their raw id — the account preferences "Sign-in methods" list showed something like `Custom:Acme` instead of `Acme`. `getProviderDisplay()` now derives a proper title-cased name from any `custom:*` id, so this works generically for every custom provider. **Changed:** - `getProviderDisplay()` derives a title-cased display name for unregistered `custom:*` providers (`custom:acme` → "Acme", `custom:my_provider` → "My Provider"), case-insensitively. Registered ones (e.g. `custom:openai` → ChatGPT) are unaffected. - `SignInWithCustom` reuses `getProviderDisplay()` instead of its own `formatProviderName`, which only stripped a lowercase `custom:` prefix — the display name also now flows into its error toast. - Added unit tests for the new fallback branch. ## To test - On a deployment with a custom provider (or by temporarily hardcoding an identity with `provider: 'custom:acme'` in `AccountIdentities`), check `/account/me` → Sign-in methods shows "Acme", not "Custom:Acme" - Unlink dialog/toast for that identity should also say "Acme" - Sign-in page with a custom provider configured should show "Continue with Acme" - `pnpm vitest run lib/external-identity-providers.test.ts` in `apps/studio` passes Addresses [FE-4193](https://linear.app/supabase/issue/FE-4193) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for unregistered custom identity providers. * Custom provider names are now displayed in a clearer, title-cased format with underscores converted to spaces. * Matching providers use the SAML icon while preserving their configured display names. * **Bug Fixes** * Improved sign-in error messages and button labels for custom providers. * Provider identifiers are now handled case-insensitively. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
397965cfae |
[FE-4186] fix(studio): endless region selector loading for AWS_NIMBUS orgs (#49131)
On the new-project form, the Region select's trigger label and inline
spinner were driven by `isLoadingAvailableRegions` — the `isPending`
state of `useOrganizationAvailableRegionsQuery`. For `AWS_NIMBUS` orgs
that query is permanently disabled (`smartRegionEnabled` is false), and
a disabled query stays `isPending` forever, so the trigger showed
"Loading available regions..." with a spinner indefinitely even though
the default region was actually selected underneath and the form still
worked.
**Changed:**
- The trigger label and spinner now use the provider-aware `isLoading`
(`smartRegionEnabled ? isLoadingAvailableRegions :
isLoadingDefaultRegion`), which the component already used for the
select's `disabled` state and placeholder. For non-Nimbus providers the
two values are identical, so the normal path is unaffected.
## To test
- Emulate a Nimbus deployment locally by setting
`"infra:cloud_providers": ["AWS_NIMBUS"]` in
`apps/studio/hooks/custom-content/custom-content.json`, then open the
new-project form: the Region field should show the default region (name
+ flag) within a moment — not an endless "Loading available regions..."
spinner — and the dropdown should open with the specific-regions list
- Restore the normal provider list and reload: the field should briefly
load, then show smart regions ("General regions") plus specific regions
with Recommended badges, as before
- Toggle High Availability on/off in either config: the selector should
transition between region lists without getting stuck loading
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved loading indicators in the region selector.
* The selector now consistently shows the correct loading state while
regions are being loaded.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
|
||
|
|
b044408e79 |
[FE-4185] feat(studio): custom content key for auth page logo link (#49130)
Adds a `dashboard_auth:logo_link_url` custom content key so white-labeled deployments can point the logged-out logo link at their own marketing site instead of the hardcoded `https://supabase.com`. **Added:** - `dashboard_auth:logo_link_url` custom content key (schema, types, default `null`, sample value) **Changed:** - `SignInLayout` and `ForgotPasswordLayout` now resolve the marketing-site logo href from custom content, falling back to `https://supabase.com` — these two shared layouts cover all auth pages (sign-in, sign-in-sso, sign-in-mfa, sign-in-partner, forgot/reset password) in both the Next and TanStack runtimes ## To test - On a normal deployment (key `null`): visit `/sign-in` and `/forgot-password` logged out — the logo should still link to `https://supabase.com` - Set `"dashboard_auth:logo_link_url": "https://example.com"` in `apps/studio/hooks/custom-content/custom-content.json` locally — the logo on those pages should link to `https://example.com` - Signed-in contexts (`logoLinkToMarketingSite` unset) still link to `/organizations` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for configuring the URL linked from authentication-page logos. * Authentication logos now use the configured destination when available. * Added a default destination to ensure logo links remain functional when no custom URL is set. * **Documentation** * Added sample configuration for the customizable authentication logo link. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
9952d6f10f |
[FE-4067] fix(studio): re-allow all regions in local project creation (#48704)
Local dev stacks can run in any of the three supported regions (e.g. Bobbie's is in `ap-southeast-1`), but enabling High Availability on the project creation form pinned local to Frankfurt only. This unrestricts local so all three regions are selectable again. **Changed:** - `getHighAvailabilityRegionCode()` returns `undefined` for `local` (same as prod), so `filterHighAvailabilityRegions()` no longer collapses the list — staging stays pinned to `us-east-1` - The three-region warning in `RegionSelector` now adds a local-only recommendation: "Use Central EU (Frankfurt) unless you're on a personal dev stack." - Updated unit tests, including an `ap-southeast-1` fixture region to prove pass-through ## To test - On a local stack, open the new project form and enable High Availability — the region selector should offer all three regions (East US, Frankfurt, Southeast Asia) instead of locking to Frankfurt, and the warning should recommend Frankfurt unless you're on a personal dev stack - Confirm staging behavior is unchanged (HA still pins to East US) - `pnpm --filter studio exec vitest run components/interfaces/ProjectCreation` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Local development projects can now use high-availability regions beyond Central EU. * Region filtering and availability messaging now correctly reflect the active environment, including staging restrictions. * **User Experience** * Added guidance recommending Central EU for local projects, unless using a personal development stack. * Region selection now provides clearer environment-specific information when options are limited. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
0e71933ce3 |
[FE-4070] fix(studio): allow adding expressions to RLS policies (#48700)
A table RLS policy created via SQL without a `USING`/`WITH CHECK` clause
stores `null` for that field, and the policy editor's payload diff
skipped `null` fields entirely — so adding an expression later through
the dashboard closed the panel as if saved but persisted nothing. This
fixes the diff so those policies are editable, and cleans up adjacent
issues in the same code path.
**Changed:**
- Extracted the update-payload diff from `PolicyEditorPanel`'s submit
handler into a pure `generateUpdatePolicyPayload()` in
`PolicyEditorPanel.utils.ts`. A stored `null` definition/check now
counts as empty, so typing an expression into a previously empty editor
produces a payload field. The diff is branched by command so INSERT
policies only ever emit `WITH CHECK`, never an invalid `USING` clause.
- The required-expression validation ("Please provide a SQL
expression…") now applies only when creating a policy. When updating, a
`null` clause is valid, so rename-only and role-only saves on such
policies work; the update path instead rejects attempts to clear an
existing `USING`/`WITH CHECK` expression with an inline error (`ALTER
POLICY` can only replace an expression, not remove it).
- Saving with no changes now closes the panel without a round trip —
previously a null-vs-undefined comparison injected a
present-but-`undefined` payload key, which sent a literal `BEGIN;
COMMIT;` to the user's database.
- Fixed the unsaved-changes check comparing the form's lowercase command
against `'INSERT'` (never matched), which made closing an untouched
INSERT policy editor prompt about unsaved changes. It now compares
`selectedPolicy.command`.
**Added:**
- `PolicyEditorPanel.utils.test.ts` — 11 unit tests covering null→value
transitions for definition and check, INSERT command mapping,
value→value updates, no-op saves, and empty-value handling.
## To test
- Run in the SQL editor: `create policy "p1" on <table> for delete to
authenticated;` (no `USING` clause), then edit `p1` in Database →
Policies, add a `USING` expression, and save. Confirm via `select
pg_get_expr(polqual, polrelid) from pg_policy where polname = 'p1'` that
the expression persisted.
- Same for INSERT: `create policy "p2" on <table> for insert to
authenticated;`, then add a `WITH CHECK` expression via the editor and
confirm `polwithcheck` is set (and `polqual` stays null).
- On `p1` (still without a `USING` expression? recreate it if you added
one), rename the policy without touching the expression editors — the
rename should save successfully.
- Edit a policy that already has a `USING` expression, change it, and
confirm the new expression persists (regression).
- Open a policy and save without changing anything — the panel should
close with no `policy-update` network request.
- On a policy with an existing `USING` (or `WITH CHECK`) expression,
clear that editor and save — an inline error should appear and no
request should fire.
- Open an INSERT policy that has a `WITH CHECK` expression, change
nothing, and close the panel — it should close without an "Unsaved
changes" prompt.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Policy updates now submit only changed fields.
* Improved handling of policy expressions, including INSERT-specific
mappings.
* Prevented removal of existing `USING` or `WITH CHECK` expressions
where unsupported.
* Empty expressions are omitted from update requests.
* Updates are canceled when no changes are detected.
* **Tests**
* Added coverage for unchanged policies, expression updates, name and
role changes, and INSERT policy behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
|
||
|
|
f877413e05 |
fix(docs ci): report Docs E2E check on every PR (#48681)
\"Docs E2E\" is a required status check on master, but the workflow only triggered on docs-related paths. A required check whose workflow never starts creates no check run at all, so every non-docs PR sat blocked on \"Expected — waiting for status to be reported\" (e.g. #48677). The fix relies on the asymmetry in how branch protection treats the two kinds of skipping: a job skipped via an `if:` condition still reports a check run (counted as passing), while a workflow filtered out by `paths:` reports nothing. **Changed:** - Dropped the `paths:` filter from the `pull_request` trigger — the workflow now runs on every PR to master - Added a `dorny/paths-filter` step (same pattern as `studio-e2e-test.yml`) carrying the exact path list the trigger used to have; it runs before checkout using the API, so non-docs PRs skip the expensive full-history checkout entirely and report green in seconds - Folded the later \"Detect docs app changes\" step into the same filter (`docs_app` output) - Flipped downstream step guards from `skip != 'true'` to `skip == 'false'` so they stay off when the scope step itself was skipped (its output is empty then, and empty `!= 'true'` would have run them) This also fixes draft PRs: the job-level draft condition now produces a skipped-but-reported check instead of nothing, and `ready_for_review` triggers a real run. No behavior change for docs PRs or `workflow_dispatch` runs. The required-check context (`Docs E2E`) keeps its name. ## To test - On this PR (docs-related since it edits the workflow): the full suite should run as before - On a non-docs PR after merge: \"Docs E2E\" reports green in seconds instead of hanging as \"Expected\" - On a draft PR: check reports as skipped, run happens on ready-for-review <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Documentation end-to-end checks now report a status for every qualifying pull request. * Documentation changes automatically run the relevant browser tests and upload test reports. * Pull requests without documentation changes receive a successful skipped check. * Preview environment validation now runs only when documentation changes are detected. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
270925b680 |
feat(studio): add dashboard_auth:sign_in_with_chatgpt enabled feature (#48677)
Adds a `dashboard_auth:sign_in_with_chatgpt` enabled-features flag so deployments can disable the sign in with ChatGPT button via `disabled_features`, the same way `dashboard_auth:sign_in_with_github` works. Previously the button was only gated by the ConfigCat rollout flag / localStorage opt-in, so white-labeled deployments with custom auth providers had no way to turn it off. **Added:** - `dashboard_auth:sign_in_with_chatgpt` (default `true`) in `enabled-features.json` + schema - Tests covering the feature-disabled state **Changed:** - `useEnabledIdentityProviders` now gates ChatGPT as `featureEnabled && (localStorageOptIn || configCatFlag)` — the feature flag is the static kill switch, the existing OR'd pair remains the rollout mechanism ## To test - Sign-in and sign-up pages behave exactly as before by default (flag defaults to `true`, ConfigCat/localStorage rollout gate unchanged) - With `dashboard_auth:sign_in_with_chatgpt` in a profile's `disabled_features`, the ChatGPT button no longer renders even with `?siwc-enabled=1` or the ConfigCat flag on - GitHub button gating unaffected <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added a feature flag to control ChatGPT sign-in availability. - ChatGPT sign-in is now available only when the feature is enabled and an applicable rollout or opt-in condition is met. - **Tests** - Expanded coverage for ChatGPT and GitHub sign-in provider availability under different feature-flag and rollout conditions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
3f5ac679e0 |
fix(studio): redirect to feature preview route after enabling (#48637)
Enabling a feature preview that has a route (e.g. Column-level
privileges) closed the modal but never navigated to the feature's page
on the TanStack runtime (local + staging). The modal closed itself via a
nuqs query-param update *and* called `router.push` — the queued nuqs
flush navigates to the pathname it captured before the push, landing
after the redirect and reverting it. The Next runtime was unaffected
because the stock nuqs pages adapter patches the URL shallowly via the
history API instead of navigating.
**Changed:**
- When the enabled preview has a `getRoute`, skip the explicit
`toggleFeaturePreviewModal(false)` — `router.push(route)` navigates
without the `featurePreviewModal` param, which is what closes the modal.
One URL update instead of two racing ones; works on both runtimes.
- Previews without a route keep the explicit close (unchanged behavior).
## To test
- On a project page, open Feature Previews (avatar menu), select
**Column-level privileges**, click **Enable feature** → modal closes and
you land on `/project/{ref}/database/column-privileges` with the "We've
taken you to where you can try it out." toast (no bounce back to the
previous page)
- Repeat with **Disable Advisor rules** → lands on
`/project/{ref}/advisors/rules/security`
- Enable a preview without a route (e.g. **PG Delta Diff**) → modal
closes, stays on the current page, "It's now active across the
dashboard." toast
- Disable a preview → modal stays open, "disabled" toast, no navigation
- Verified locally on the TanStack runtime; worth a quick click-through
on the Vercel preview (Next runtime) too
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved feature activation navigation to prevent conflicting URL
updates.
* Non-route features continue to close the preview modal and display the
activation confirmation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
|
||
|
|
fc5e03f9e3 |
[FE-4019] fix(studio): direct-only connection strings with SSL params for Multigres (#48433)
Multigres (high-availability) projects only accept TLS connections with direct SSL negotiation, and they don't support connection pooling at all — neither Supavisor nor the dedicated PgBouncer pooler exists for them. Studio previously showed pooler connection strings that would fail with "server closed the connection unexpectedly". This PR makes every connection-string surface direct-only for HA projects and appends `?sslmode=require&sslnegotiation=direct` to the examples. Non-HA projects are unchanged. Addresses [FE-4019](https://linear.app/supabase/issue/FE-4019/append-ssl-params-to-multigres-connection-string-examples-in-ui) **Changed:** - `buildConnectionStringPooler` gets an HA branch that collapses every slot in the bag to the direct connection string with the SSL params appended (mirroring the existing CLI branch, which also has no pooler) — dedicated slots come back `undefined` and `ipv4SupportedForDedicatedPooler` is forced off. Since HA never reaches the pooler layout anymore, the earlier per-URI SSL-append logic on pooler strings is removed - `useConnectState` coerces `connectionMethod` to `direct` and `useSharedPooler` to `false` for HA projects. The Connect sheet restores the last-used method from localStorage shared across projects, so a "Transaction pooler" selection made on a regular project could otherwise leak pooler-flavored notices, badges, and telemetry into an HA project - Prisma and Drizzle ORM tabs get an HA branch: `DATABASE_URL`/`DIRECT_URL` both use the direct connection, no `?pgbouncer=true` appended, with a comment explaining Multigres doesn't support pooling. The 5-arm nested ternaries in both files are flattened into `getEnvCode` helpers that switch on a shared `resolveOrmConnectionScenario` helper (`OrmConnection.utils.ts`), so the deployment-mode/HA branching lives in one tested place and each file keeps only its own formatting - The PgBouncer and Supavisor config queries are disabled (`enabled: !isHighAvailability`) in the Connect sheet — those endpoints serve pooler config that doesn't exist on Multigres - `parseConnectionParams` keeps the URI's query string in a new `search` field so formats rebuilt from parsed parts can carry it - psql switches from the `-h/-p/-d/-U` flag form to the quoted-URI form when query params are present (flags can't express them; psql still prompts for the password) - JDBC appends the params using pgJDBC's casing (`sslNegotiation`, supported since 42.7.4) - Prisma's `?pgbouncer=true` appends are query-aware (join with `&` when the URI already has a query string) via a new `appendConnectionStringParams` helper - The project home "Direct connection string" copy item also appends the params for HA projects **Added:** - Unit tests for the HA collapse behavior (all slots direct, dedicated config and IPv4 add-on ignored, no SSL params on non-HA output), the `useConnectState` coercion, the psql/JDBC builders (moved from `content.tsx` into `ConnectionString.utils.ts` so they're testable), and `resolveOrmConnectionScenario` (every deployment-mode/HA/pooler branch) **Known gaps (left out deliberately):** - The grid ExportDialog psql/pg_dump commands, the .NET `appsettings.json` (Npgsql only supports direct negotiation from v9 via `SSL Negotiation=Direct`), and the SQLAlchemy keyword-style `.env` are flag/keyword forms that can't carry the URI params — these would still fail against Multigres and need a follow-up - Settings > Database's Connection Pooling section and the pooler logs page have no HA gating yet — they'd still render pooler config UI for a Multigres project and should be hidden in a follow-up ## To test On a **Multigres (HA) project** (staging only supports `us-east-1` for Multigres): - Open the Connect sheet → Direct tab: there's no connection-method picker, and the connection string is the direct one ending with `?sslmode=require&sslnegotiation=direct` for the URI, PHP, and psql (quoted-URI form) types; JDBC includes `&sslmode=require&sslNegotiation=direct` - ORM tab → Prisma: both `DATABASE_URL` and `DIRECT_URL` are the direct connection string with the SSL params, no `pgbouncer=true`, with a "Multigres does not support connection pooling" comment. Drizzle likewise shows the direct string only - Framework tabs (e.g. Next.js): every `DATABASE_URL` carries the direct string with the params exactly once - Open the network tab: no requests to `/config/pgbouncer` or `/config/supavisor` while using the Connect sheet - To check the localStorage coercion: on a **regular** project pick "Transaction pooler" in the Connect sheet, then open the sheet on the Multigres project — no pooler badge/notices, string is still direct - Copy the URI, substitute your password, and `psql "<string>"` — it should connect - Project home → Copy dropdown → "Direct connection string" includes the params On a **regular (non-Multigres) project** — confirm nothing changed: - Connect sheet: direct/session/transaction strings for all connection types (URI, psql flag form, JDBC, PHP) look the same as before, no SSL params appended - Prisma/Drizzle tabs render identically (`?pgbouncer=true` still appended with `?`, dedicated-pooler alternatives still shown per IPv4 add-on state) - Project home copy dropdown is unchanged <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Enhanced connection-string generation for high-availability projects, including required SSL settings for direct connections. * Preserved URI query parameters in PostgreSQL, `psql`, JDBC, and generated environment configurations. * Improved ORM environment templates with clearer handling for pooler and high-availability connection scenarios. * **Bug Fixes** * High-availability projects now consistently use direct connections instead of pooler options. * Connection strings and generated templates update correctly when availability settings change. * **Tests** * Expanded coverage for query parameters, high-availability behavior, and connection scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
0833c586ac |
fix(studio): use redirect({ to }) for internal TanStack redirects (#48469)
Hover-preloading any link that points at a redirecting path (e.g. the
org invite "Decline" link to `/projects`) hung the tab under the
TanStack runtime: `redirect({ href })` is treated as an opaque external
target, and the router's preload retry ignores `href` when rebuilding
the location, so it re-runs the same `beforeLoad`, throws the same
redirect, and recurses forever (TanStack/router#7141 — internal targets
must use `to`).
**Changed:**
- `routes/__root.tsx` — the redirect-table `beforeLoad` splits the
destination with `splitInternalUrl()` and throws `redirect({ to, search,
hash, statusCode })` instead of `redirect({ href })`. `to` is
basepath-relative, so the manual `BASE_PATH` prefix goes away too.
- `routes/index.tsx` — same `href` → `to`/`search`/`hash` switch for the
`/` redirects; the "targets aren't in the routeTree yet" comment was
stale (all three destinations resolve to real routes now).
- `OrganizationInvite.tsx` — "Decline" links straight to
`/organizations`, skipping the `/projects` redirect hop entirely.
## To test
- On the TanStack runtime, hover (don't click) a link to a redirecting
path — e.g. the auth overview's "Go to observability" link
(`/project/:ref/reports/auth`) or the 404 page's `/projects` link. The
page must stay responsive (this hung before).
- `/projects` → `/organizations` (307), `/project/:ref/database` →
`/database/tables` (308), `/` → `/org`.
- Query/hash semantics still hold: `/?next=new-project&projectName=x` →
`/new/new-project?projectName=x`;
`/project/:ref/database/wrappers?foo=bar` →
`/integrations?category=wrapper&foo=bar`; `/org/:slug/invoices#other` →
`/org/:slug/billing#invoices`.
- Chained redirects stay bounded: `/project/:ref/database/linter` →
`/advisors/security` in two hops.
All of the above verified locally via Playwright against the TanStack
dev server; `redirects.shared` / `internal-url` / compat-router unit
tests pass.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **Bug Fixes**
- Fixed the invitation “Decline” action to route users to the
Organizations page instead of the Projects page.
- Improved Studio redirect/navigation handling by correctly preserving
URL search parameters and hash fragments and routing to the intended
destination.
- **Tests**
- Updated Organization Invite test expectations to reflect the corrected
“Decline” link destination.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
|
||
|
|
0d2d47c26f |
docs: point dashboard links at the Infrastructure settings page (#48437)
Follow-up to #48370, which merged the Compute and Disk settings page into Infrastructure and made `/settings/compute-and-disk` a permanent redirect. **Changed:** - Retargeted all 17 dashboard links from `/dashboard/project/_/settings/compute-and-disk` to `/dashboard/project/_/settings/infrastructure` (15 files across guides, troubleshooting entries, and the `migration_warnings` partial) - Updated link text that named the old page ("Compute and Disk settings" → "Infrastructure settings", plus one stale "Database Settings" label in the compute-and-disk guide) Links to the `/docs/guides/platform/compute-and-disk` docs guide are untouched — that page still exists; only dashboard deep links changed. > [!NOTE] > Best merged after #48370 — until then the Infrastructure page doesn't host the compute and disk config (the old URL keeps working either way via the redirect). ## To test - Spot-check a few changed pages on the preview (e.g. `/guides/platform/database-size`, `/guides/troubleshooting/high-cpu-usage`) and confirm the dashboard links land on the Infrastructure settings page - Confirm the compute-and-disk guide page itself still renders and its docs-internal links are unchanged <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Documentation** - Updated migration and troubleshooting guidance to direct users to the **Infrastructure** settings page, replacing outdated **Compute and Disk** links. - Refreshed platform/database/performance links for resizing, disk throughput/IOPS, upgrade steps, and related troubleshooting to use the updated **Infrastructure** routes and anchors. - Adjusted “Using the CLI” to point to the current local development getting-started page, and refined wording in the “Hit rate” section. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
0009b4bcdf |
chore(claude): hoist static form references in RHF skill example (#48434)
Quick follow-up to #48431 addressing Ivan's post-merge feedback: the canonical form example now defines `FORM_ID`, the zod schema, and static `defaultValues` at module level so they're stable references rather than being recreated on every render, with a note to use `useMemo` (runtime-dependent schemas) or the `values:` option (server-driven defaults) when hoisting isn't possible. ## To test - Skim the diff — docs-only change to `.claude/skills/react-hook-form/SKILL.md` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated the React Hook Form guidance with a canonical example using stable, module-level form configuration. * Clarified that schemas, inferred types, default values, and form identifiers should be defined outside the component. * Documented how submit buttons outside the form should reference the shared form identifier (and cautioned to use per-instance IDs when the component may mount multiple times). <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
d845768fcf |
chore(claude): add react-hook-form skill (#48431)
Adds a Claude skill encoding correct React Hook Form usage, so
AI-written form code follows best practices instead of copying the
anti-patterns common in older Studio code (prop-form
`form.watch()`/`formState` subscriptions, subscription-only watches,
unguarded `valueAsNumber`, `?? undefined` controlled values, defaults
computed from unloaded queries).
**Added:**
- `.claude/skills/react-hook-form/SKILL.md` — subscription model
(`useWatch`/`useFormState` with `control`), canonical zod + `FormField`
composition (layout deferred to `studio-ui-patterns`), `values:` option
for async data, null normalization for controlled inputs, number-input
handling, dirty-state and gating rules, plus a fix-what-you-touch policy
aligned with the `no-use-watch` lint ratchet
**Changed:**
- `.claude/CLAUDE.md` and `apps/studio/CLAUDE.md` — register the skill
in the skill lists/table
- `.coderabbit.yaml` — add the skill to the existing Studio
code-guidelines entry so CodeRabbit applies it when reviewing Studio
code
Benchmarked on three real form tasks (adding a live-updating field to
`ThroughputField`, a new sheet form with async + nullable data, a
review-changes step in `EditBucketModal`), each run with and without the
skill: 13/13 assertions with the skill vs 8/13 baseline. The baseline
shipped a genuine bug in one task — a `null` server default flowed into
a `''` its own schema rejected, making Save unreachable — which the
skill run avoided.
## To test
- Ask Claude Code to add a field to any Studio form and check it loads
the skill (it's in the studio CLAUDE.md skill table) and uses
`useWatch({ control, name })` rather than `form.watch`
- Skim `SKILL.md` for anything that contradicts current form conventions
— `apps/design-system` demos remain the layout source of truth
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Documentation**
* Added a new monorepo “react-hook-form” skill guide with recommended
patterns for safe form subscriptions, wiring, default values,
reset/submission flows, and common anti-patterns.
* Updated Studio skills/load guidance to expand and reorder the skills
matrix, including form logic and copywriting guidance.
* Updated required skill coverage so `react-hook-form` is included for
any form-related work.
* **Chores**
* Expanded automated review enforcement so Studio form code is checked
against the new “react-hook-form” skill guidance.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
|
||
|
|
ca2b50a0a7 |
chore(ui-patterns): collapse the admonition shim into ui-patterns/Admonition (#48377)
Follow-up to #48344: collapses the two resolution paths for the Admonition module into one. `src/admonition.tsx` was a back-compat shim re-exporting `src/Admonition/`. Two ways to resolve one module is exactly what produced the macOS self-import bug fixed in #48344, and the local typecheck errors that #48374 worked around. This removes the shim and standardizes on the PascalCase subpath, matching every other export in the package. **Changed:** - Codemodded all 246 `ui-patterns/admonition` imports to `ui-patterns/Admonition` (240 `.tsx`, 5 `.mdx`, 1 `.ts` across studio, docs, www, design-system, and lite-studio) - Pointed the 5 internal `'../admonition'` imports back at the `'../Admonition'` directory **Removed:** - `packages/ui-patterns/src/admonition.tsx`, and its `./admonition` entry in the exports map (regenerated with `pnpm gen:exports`) ## To test - `grep -r "ui-patterns/admonition" --include='*.ts*'` → no hits - `pnpm test:case-hazards` → passes - `pnpm typecheck` → all 15 tasks green - `pnpm --filter studio run lint:ratchet` → passes - `pnpm --filter ui-patterns vitest run src/Admonition` → 11 tests pass <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Standardized Admonition component imports across the application and documentation. * Improved compatibility with case-sensitive environments by using the canonical component path. * Removed the legacy Admonition import entry point. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
b9ab634cd0 |
fix(studio): stop 403'd integration queries from looping on remount (#48350)
Resolves FE-4014
A user with a project-scoped role opening any project integration
overview (e.g. Cron) hits an unbounded request loop — the page sits on a
skeleton forever while hammering the platform API until it gets rate
limited.
**Changed:**
- `useProjectOAuthIntegrationData` now passes `retryOnMount: false` to
its five queries, so a 403 settles as a terminal error instead of
refetching on every consumer mount
## Why
Project-scoped roles have no org-level permissions, so `GET
/platform/organizations/{slug}/oauth/apps` 403s. We don't retry 4xx, so
the query settles into `error` with no data — and an errored query with
no data is never fresh, so it refetches on *every* new observer mount.
That feeds a loop: refetch → `isLoading` true → `IntegrationPage` swaps
its whole subtree to a skeleton → `<Component />` unmounts → 403 lands →
`isLoading` false → remounts → mounts fresh observers → refetch.
Measured ~20 req/s (480 observer add/removes and 120 requests in a 6s
window) until the API 429s it, then it continues at the retry cadence
indefinitely.
The other four queries in that hook can 403 the same way for restricted
roles, and any one of them alone sustains the loop — hence the option on
all five.
Not fixed here: `IntegrationPage` tearing down its subtree whenever
`isLoading` flips
(`pages/project/[ref]/integrations/[id]/[pageId]/[childId]/index.tsx:58-94`)
is the amplifier that turns a wasted request into a loop, and will still
reset UI state on any background refetch. Worth a follow-up.
## To test
Needs an account with a project-scoped role in a shared org (not an org
owner/admin).
- Open `/project/{ref}/integrations` for that project, click into Cron
(or any integration) → overview should render, not sit on a skeleton
- Network tab: `organizations/{slug}/oauth/apps?type=authorized` should
fire once and 403, not repeat
- Console should show 1 error, not hundreds ending in a 429
- As an org owner, integration overviews should behave exactly as before
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Prevented repeated refetching of integration data after handled
authorization/403 errors, avoiding refetch loops on remount.
* Improved consistency on integration landing screens by standardizing
how related integration queries are enabled and retried.
* **Enhancements**
* Added permission-aware loading/error handling for OAuth integration
data, showing OAuth results only when the selected organization grants
read access.
* **Chores**
* Updated permission-check typings to treat an explicitly empty project
reference as absent.
* **Tests**
* Extended integration settings tests with permission fixtures to cover
OAuth read access.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
|
||
|
|
d25e10b9c2 |
fix(ui-patterns): fix admonition self-import + add case-sensitivity guard (#48344)
Fixes the TanStack Studio app failing to load locally, and adds a CI guard so the same class of bug can't come back. `packages/ui-patterns/src/admonition.tsx` is a back-compat shim containing `export * from './Admonition'`. On a case-insensitive filesystem (macOS, Windows) the resolver tries `./Admonition.tsx` before the directory index — and that's the same file. The shim re-exported itself and exported nothing, so every consumer of `ui-patterns/admonition` blew up with `does not provide an export named 'Admonition'`, plus knock-on Vite dep-optimizer errors about missing chunks. It works on Linux, so typecheck, lint, build and tests all pass on CI. This only reproduces on dev machines. **Changed:** - `admonition.tsx` now points at `./Admonition/index` explicitly, so the specifier can't resolve back to itself **Added:** - `scripts/check-case-hazards.mjs` — dependency-free, two textual checks so they fire on Linux CI: - **Self-resolving imports**: for `dir/X.tsx`, flags any extension-less relative specifier resolving to `dir/X` case-insensitively - **Case-colliding paths**: tracked paths (files and directory prefixes) equal when lowercased, which can't coexist in a case-insensitive checkout - `pnpm test:case-hazards`, plus a step in `typecheck.yml` after `setup-node` but before `pnpm install` — no deps needed, fails fast Scoped check 1 to genuine self-imports rather than all case-insensitive file/directory ambiguity. The broader rule lights up ~45 legitimate routing pairs (`_app.tsx` + `_app/`, `changelog.tsx` + `changelog/`) and would get switched off within a week. This version has zero false positives on master today. ## Follow-up (not in this PR) The underlying duplication is still there: `src/admonition.tsx` and `src/Admonition/` both exist, and the ~14 internal `'../Admonition'` imports inside the package resolve through the shim on macOS but through the directory on Linux. Two resolution paths for one module is exactly what produced this. Real fix is to collapse it. Current counts: **246** files import `ui-patterns/admonition`, **0** import `ui-patterns/Admonition`. So either rename the directory to lowercase and delete the shim (zero import churn, but one lowercase dir among ~50 PascalCase siblings), or codemod the 246 imports to PascalCase to match the package convention. I'd lean to the codemod, on a day it won't conflict with in-flight branches. ## To test - `pnpm test:case-hazards` on master → passes, ~16.5k files checked - Revert `admonition.tsx` to `export * from './Admonition'` and re-run → fails with the offending file and the suggested fix - Confirm the fixed form `'./Admonition/index'` is *not* flagged - With the fix in place: `rm -rf apps/studio/node_modules/.vite`, then `STUDIO_FRAMEWORK=tanstack pnpm dev:studio` → app loads, no `Pre-transform error` and no missing-export error in the console <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved detection of file-path casing issues that could cause failures on case-insensitive systems. * Corrected a module re-export to ensure the intended UI component is exposed consistently. * **Tests** * Added a dedicated case-sensitivity hazard check. * Integrated the check into the type-check workflow for earlier issue detection. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
8d4d3b57e0 |
feat(studio): add tanstack variant to the studio docker image (#48091)
Makes the self-hosted Docker image buildable with the TanStack/Vite
build alongside the existing Next one. The Dockerfile's new
`STUDIO_FRAMEWORK` build arg (default: `next`) selects which framework
lands in the image — the same variable `scripts/dispatch.js` keys on
everywhere else, so `--build-arg STUDIO_FRAMEWORK=tanstack` is the
docker spelling of the existing switch. Both flavors assemble a
normalized `/srv` tree, so a single production stage serves either with
the same CMD (`node apps/studio/server.js`), port 3000, and healthcheck.
Unlike Next's self-contained standalone output, the Vite SSR bundle
externalizes studio's dependencies and resolves them from `node_modules`
at request time, so the tanstack runtime tree is a prod-only `pnpm
deploy` plus the built `dist/`. The boot smoke test runs a second time
against that pruned tree, so a runtime import that's missing from
`dependencies` fails the image build instead of 500ing the deployed
container — which is exactly how this PR caught four packages
misclassified as devDependencies (`braintrust` +
`@smithy/property-provider` via the AI routes, `libpg-query` via the
parse-query API route, `@radix-ui/react-use-escape-keydown` via the
Queues panel; split into its own commit).
**Changed:**
- `apps/studio/Dockerfile`: `ARG STUDIO_FRAMEWORK` selects `build-next`
/ `build-tanstack` stages via `FROM build-${STUDIO_FRAMEWORK}`; both
normalize into one production layout
- `apps/studio/package.json`: moved the four runtime-imported packages
from devDependencies to dependencies (versions unchanged)
- `apps/studio/vite.config.ts`: pinned `preview.host` to `127.0.0.1` —
the prerender step boots `vite preview` and crawls its resolved URL, and
the default `localhost` host lets the server bind the IPv6 loopback
while the crawler fetches `127.0.0.1`, which ECONNREFUSEDs the whole
build inside BuildKit containers
- `.github/workflows/studio-docker-build.yml`: builds the tanstack image
as a second step (reuses the first build's layer cache; job name
unchanged)
**Added:**
- `build:studio:docker:tanstack` root script
Note: the tanstack image is ~2.0GB vs ~1.2GB for Next (externalized
`node_modules`); shrinking it via file tracing is a follow-up. Nothing
self-hosters pull changes until a tanstack-built image is published —
this makes it buildable and CI-checked.
## To test
- `pnpm build:studio:docker` then run the image against a stack —
behavior unchanged (healthcheck `/api/platform/profile` 200, `/` 307s to
`/project/default`)
- `pnpm build:studio:docker:tanstack` then run that image with the same
env — same healthcheck, redirect, and data endpoints (projects, pg-meta)
respond 200; browser loads Project Overview / Table Editor with no
requests leaving the container
- Both verified locally against the CLI stack (`host.docker.internal`
env, container reports `healthy`)
- Vercel + e2e checks on this PR exercise the `preview.host` change on
their runners
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Added TanStack-based Studio build support with a framework-selectable
Docker image.
- Added a local build command for the TanStack Studio Docker image.
- **Build & Deployment**
- Updated the Studio Docker build workflow to also publish a
TanStack-tagged Studio image when relevant.
- **Bug Fixes**
- Improved `vite preview` behavior in containers by binding to IPv4
loopback.
- Standardized the Studio container runtime port to `3000`.
- **Chores**
- Updated Studio runtime packages to support the TanStack build.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
|
||
|
|
a06eb5f26f |
[FE-3724] feat(studio): add enable cleanup button to cron jobs page (#48200)
Adds a standalone **Enable cleanup** button to the Cron Jobs page header so users can schedule the daily `delete-job-run-details` cleanup job proactively — previously this was only reachable inside the conditional "table too big" overflow dialog. Addresses [FE-3724](https://linear.app/supabase/issue/FE-3724/enable-pg-cron-cleanup-job-from-ui-and-api) (the UI half; the Management API half needs platform-side work). **Added:** - `Enable cleanup` button in the cron jobs header (left of Refresh), hidden while the existence check loads and whenever a `delete-job-run-details` job already exists - Confirmation dialog with a retention-period select (defaults to 7 days), live SQL preview, and telemetry (`cron_job_cleanup_enable_button_clicked` with `origin` + `retentionInterval`) - Component tests (MSW) for visibility gating and the schedule/cancel flows - E2E regression test for the full schedule → delete → button-reappears cycle **Fixed:** - Name-based `useCronJobQuery` lookup: the `queryFn` dropped the `name` param, and a not-found job returned `undefined` (rejected by react-query v5) — now passes `name` through and returns `CronJob | null` - Cache invalidation gaps: create/delete now invalidate the whole cron-jobs prefix (list, count, job details), so the footer count updates after create/delete and the button reappears after the cleanup job is deleted. The schedule mutation deliberately invalidates only the existence check + count (see inline comment) - Pre-existing e2e leak: the cleanup-workflow test left `delete-job-run-details` scheduled; it now cleans up after itself ## Screenshots | Header button | Dialog | | --- | --- | | <img width="890" height="325" alt="Screenshot 2026-07-22 at 9 44 40 PM" src="https://github.com/user-attachments/assets/966cd640-d8a6-4c8f-92e7-73151bf4de9c" /> | <img width="512" height="461" alt="fe3724-dialog" src="https://github.com/user-attachments/assets/6be1785f-cc7e-4048-a648-9ef260b0949f" /> | ## To test - Go to a project's Integrations → Cron → Jobs with pg_cron enabled and no `delete-job-run-details` job → the `Enable cleanup` button shows next to Refresh - Open the dialog, switch retention intervals → the SQL preview updates; confirm → success toast, the job appears in the grid (`0 12 * * *`), and the button disappears without a reload - Delete the `delete-job-run-details` job from the grid → the button reappears without a reload - Create then delete any other job → the footer `Total: N jobs` count updates both ways without a reload - Regression: with the high-query-cost banner forced (or via the e2e), the overflow dialog's "Schedule cleanup job" step still shows its success state — the dialog must not close mid-flow <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit * **New Features** * Added an **Enable cleanup** action to the Cron Jobs tab header, including a retention selector and SQL preview. * Enabling schedules the daily cleanup, shows a success toast, updates the grid, and hides the enable button; **Cancel** closes the dialog without scheduling. * **Bug Fixes** * Improved cron job lookup to work by name when needed. * Refreshed related cron job data more reliably after scheduling and deletion. * **Telemetry** * Added an event for cleanup enable button clicks. * **Tests** * Added component and Playwright coverage for enable/cancel/schedule/delete and cleanup banner flows. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
4b24cf028a |
chore(claude): improve CLAUDE.md files and skill triggering (#48261)
Improves the repo's agent guidance: distills the always-required `studio-best-practices` skill into `apps/studio/CLAUDE.md`, tunes every skill description for reliable triggering, and mechanically enforces the generated-files rule. Grounded in Anthropic's official CLAUDE.md guidance (see justifications below). ## The main change: Studio CLAUDE.md gets a Code style section **Why:** `studio-best-practices` was a skill that instructed agents to *always* load it before any Studio code work. Anthropic's guidance draws the line as: sometimes-relevant guidance → skill (loaded on demand); always-relevant guidance → CLAUDE.md. A skill that must always load has failed the test for being a skill — it costs a tool-call round trip and, worse, silently does nothing in sessions that forget to load it. Since `apps/studio/CLAUDE.md` is lazy-loaded only when an agent touches Studio files, inlining is properly scoped: non-Studio sessions never pay for it. **Why not verbatim:** the skill was 175 lines, mostly ❌/✅ worked examples teaching practices models already know. Inlining it whole would push the file past the ~200-line point where Anthropic warns rules start getting lost. Instead each section was distilled to the rule it exists to enforce — e.g. the loading/error/success section kept its code block because the *shape* (early returns at top level, flat `&&` chains inline) is the prescription, and prose loses it. **The framing that makes the generic rules earn their place:** models default to matching surrounding code, and not all existing Studio code follows these practices. The section opens with "older Studio code predates some of these conventions — follow them rather than mirroring nearby legacy patterns," which converts otherwise-redundant React advice into an explicit instruction to break from local precedent. One rule was added that the old skill lacked: `useEffect` is for external-system sync only (~364 Studio files contain effects, many in patterns we don't want copied). **Changed:** - `apps/studio/CLAUDE.md` — new Code style section (84 lines total, within budget); skills table no longer mandates a pre-load - `.claude/CLAUDE.md` — dropped `pnpm install` from commands (guessable; Anthropic's test: "would removing this cause mistakes?") **Removed:** - `.claude/skills/studio-best-practices/` — fully absorbed; its cross-references to other skills were already covered by the skills routing table ## Skill description tuning Descriptions are the only signal an agent sees before deciding to load a skill, and the observed failure mode is under-triggering on tasks that don't name the skill. Nine descriptions reworded: front-loaded matchable keywords, added incidental-trigger cases (e.g. a new feature that adds copy is a `copywriting` moment), and disambiguated overlaps (`vitest` is now the API reference deferring to `studio-testing` for strategy). The `safe-sql-execution` rewrite was additionally validated with skill-creator's trigger-eval loop against 20 realistic queries: held-out test accuracy 54% → 71%, with zero false triggers across all iterations. (`vitest` shows under `.agents/` because `.claude/skills/vitest` symlinks there.) ## Generated-files enforcement **Added:** `permissions.deny` rules in `.claude/settings.json` for the six generated-file globs the root CLAUDE.md already lists. CLAUDE.md prose is advisory; permission rules are mechanical and also gate sandboxed Bash writes. (Verified live: the rule blocked an unintended regeneration of `database-types.ts` during testing.) ## To test - CI: prettier + typos checks pass (docs-only + settings change, no app code) - In a fresh Claude Code session in the repo: ask it to edit `apps/studio/routeTree.gen.ts` — should be denied by the new permission rule - Ask it to do any Studio UI task — it should pick up the Code style rules from `apps/studio/CLAUDE.md` without loading a best-practices skill <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated development guidance for testing, copywriting, SQL safety, telemetry, queries, error handling, and toolbar reviews. * Restructured Vitest references into clearer tables and improved formatting across several guides. * Added Studio code-style conventions and clarified when task-specific guidance should be applied. * Removed outdated Studio best-practices guidance. * **Chores** * Added safeguards preventing edits to generated and protected files. * Simplified the documented development command sequence. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
fbf7ce44ef |
[FE-3544] fix(studio): role impersonation for truncated cell loads (#48215)
Loading a truncated cell's full value from the inline grid editors or the row side-panel editors called `getCellValue` without `roleImpersonationState`, so the fetch ran with full DB privileges instead of the role selected in **View as role** — leaking values RLS would deny. Same class of bug #46442 fixed for row copy/export; the mutation already accepted the state, these call sites just weren't passing it. **Changed:** - Pass `roleImpersonationState` into `getCellValue` in all 4 truncated-cell loaders (inline grid Text/Json editors + row side-panel Text/Json editors), mirroring the existing `Header.tsx` pattern **Added:** - MSW component test on the row side-panel `TextEditor` asserting the cell-value SQL is wrapped with `set local role` when impersonation is active, and not wrapped when it isn't ## To test Note: if the impersonated role can't select the row at all (e.g. force RLS with no policy), the main grid correctly shows 0 rows under **View as role**, so the "Load full value" button is never reachable — you can't exercise this path that way. Use a row the role *can* see and verify the request is role-wrapped: - Create a table with a text value long enough to be truncated in the grid (>16KB), with RLS enabled and an anon-visible row: ```sql create table public.secrets (id int primary key, secret text); alter table public.secrets enable row level security; alter table public.secrets force row level security; create policy "anon can read" on public.secrets for select to anon using (true); insert into public.secrets values (1, repeat('a', 20000)); ``` - In the Table Editor, set **View as role → anon** — the row should be visible with the `secret` cell truncated - With the network tab open, load the full value via each path: double-click the cell (inline editor) and the row side panel's expand editor → "Load full text data" (a `jsonb` column exercises the two JSON editor paths the same way) - The `pg-meta` query request body should start with `set_config('role', 'anon', true)` + anon JWT claims before the `select secret …`. Before this fix it was a bare unwrapped `select secret from public.secrets where id = 1;` - Drop the policy and confirm the grid shows 0 records under anon (denial still applies at the grid level); switch back to the default role and confirm the full value still loads normally with no wrapper Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
3121841863 |
[FE-2271] fix: correct stale email confirmation dashboard paths (#48228)
Users were getting AI-generated troubleshooting steps pointing at **Authentication → Settings → Sign up → "Enable email confirmations"** — a dashboard path that no longer exists (FE-2271). The guidance comes from external LLMs trained on stale supabase.com content: two 2022 blog tutorials contain that exact phrasing. The real toggle is **Authentication → Sign In / Providers → User Signups → "Confirm email"**. **Changed:** - Updated the Flutter chat and Angular Trello blog tutorials to point at the current toggle location (and removed screenshots of the old UI) - Repointed the legacy `/project/:ref/auth/settings` redirect from `/auth/users` to `/auth/providers`, so anyone following stale instructions lands on the page that actually has the auth config ## To test - Visit `/project/<ref>/auth/settings` in Studio — it should redirect to `/project/<ref>/auth/providers` (verified locally on both the redirect and the existing `redirects.shared.test.ts` suite) - Check the two blog posts render correctly and the dashboard deep link opens Sign In / Providers <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Updated authentication settings redirects so project settings pages now open the correct sign-in and provider configuration page. - **Documentation** - Updated Flutter and Angular tutorial instructions for disabling email confirmation. - Added current navigation guidance and clarified where to turn off the **Confirm email** option. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
25658ab733 |
chore(lint): ignore dist build output in shared ESLint config (#48216)
Follow-up to #48202. The shared ESLint flat config only globally ignored `.next`, `public`, and `.contentlayer`, so with the TanStack Start migration, Studio's Vite build output in `dist/` was getting linted too — making `pnpm --filter studio run lint:ratchet` (and regular lint) far slower than it should be. ESLint flat config doesn't respect `.gitignore`, so being gitignored didn't help. **Changed:** - Added `dist` to the global `ignores` in `eslint-config-supabase/next` (applies to all apps extending the shared config) ## To test - In `apps/studio` (with a `dist/` folder present from a TanStack build), run `npx eslint dist/server/server.js` — it should report "File ignored because of a matching ignore pattern" - `pnpm --filter studio run lint:ratchet` no longer spends time linting `dist/**` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated linting exclusions to ignore generated build output and static asset directories. * Generalized related configuration documentation for clarity. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
2d5ec97df8 |
chore: split CLAUDE.md into root and studio-specific files (#48202)
Splits agent guidance into a lean monorepo-wide root file and a studio-specific file that Claude Code lazy-loads when working under `apps/studio/`. This keeps every session's baseline context small while giving studio work much richer, enforceable guidance. **Changed:** - `.claude/CLAUDE.md` — now monorepo-wide only: corrected pnpm version (10 → 11), expanded workspace table (design-system, ui-library, lite-studio, ui-patterns, api-types, pg-meta, shared-data), commands (`format`, `generate:types`, `api:codegen`), CI gates + never-hand-edit generated files, monorepo-wide conventions (incl. the named-exports rule, which lives in the shared eslint preset and applies to all six apps), and monorepo-wide skill triggers. Studio detail is replaced by a pointer to the nested file. Also corrects a long-standing error inherited from the old file: the `_Shadcn_` convention was inverted — `Button_Shadcn_` is the only suffixed export left and is rarely the right choice; primitives are unsuffixed. - `.claude/skills/studio-ui-patterns/SKILL.md` — removed the same stale `_Shadcn_` claim from the forms section (this skill also feeds CodeRabbit reviews). - `apps/studio/components/README.md` — component template now uses a named export, matching the lint-enforced convention (was the one doc still showing `export default`). - `apps/studio/TANSTACK_MIGRATION.md` — cleanup checklist gains an item to remove the migration section from `apps/studio/CLAUDE.md` when the migration finishes. - `.gitignore` — removed the blanket `CLAUDE.md` ignore rule (added in #40231 for personal local files, no longer used that way). Nested `CLAUDE.md` files are now tracked by default, so shared guidance can't silently fail to land. For *personal* notes, use `CLAUDE.local.md` (Claude Code loads it automatically alongside `CLAUDE.md`, and it's now gitignored here) — or `.git/info/exclude` if you prefer a different filename. **Added:** - `apps/studio/CLAUDE.md` — studio guidance, loaded on demand: mandatory skill routing (always load `studio-best-practices`, plus a task → skill table), TanStack Start migration rules (pages/routes mirroring, when a manual mirror is needed, never delete `pages/**` files), data-layer/state orientation, a default-to-shipping-tests-with-changes policy, and a "defaults that differ here" list (ESLint warning ratchet + local `lint:ratchet` command, `copyToClipboard` await rule, `useParams` from `common`, dayjs/sonner, `ui` vs `ui-patterns` import split, `@tanstack/react-table` over `react-data-grid`, etc.). ## Accuracy Every factual claim in both files (62 total) was verified against the code by parallel review agents instructed to refute each one. Results: 54 correct as written, 2 wrong (the inherited `_Shadcn_` inversion, and a fabricated `useExecuteSqlQuery` hook name — the real export is `useExecuteSqlMutation`), 6 imprecise (e.g. dayjs plugins load in both runtime entries, the ratchet counts occurrences regardless of severity). All fixed in this PR. ## Context cost | File | Size | When it loads | % of a 200k window | |---|---|---|---| | `.claude/CLAUDE.md` | 70 lines, ~1.2k est. tokens | every session | ~0.6% | | `apps/studio/CLAUDE.md` | 53 lines, ~1.6k est. tokens | only when touching studio files | ~0.8% | The always-loaded footprint grew only ~0.2k est. tokens vs the old 45-line file — everything studio-heavy sits behind the lazy load, so docs/www sessions pay nothing for it. Both files are well under Claude Code's large-file warning threshold (~40k chars) and the <200-line adherence guidance, with room to roughly double before it's worth worrying about. ## To test - Open a fresh Claude Code session from the repo root and read any file under `apps/studio/` — `apps/studio/CLAUDE.md` should get pulled into context automatically. - `git check-ignore apps/studio/CLAUDE.md` exits 1 (not ignored); `git check-ignore CLAUDE.local.md` exits 0 (ignored). - Skim both files — every claim has been code-verified (see Accuracy above), but a human sanity pass on the *judgment* calls (what's included/omitted) is welcome. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Refreshed monorepo onboarding conventions with updated tooling requirements, expanded inventory, standardized common scripts, and clearer CI gating and checks. * Added/updated Studio contributor guidance, including the TanStack Start migration rules and Studio development/testing/UI conventions. * Updated Studio component documentation to use named exports. * Refreshed the “Forms” UI pattern guidance and adjusted the referenced UI primitives. * **Chores** * Updated ignore rules so the primary top-level onboarding document is tracked. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
0fe2366659 |
[FE-3790] fix(studio): hide Multigres from user-facing surfaces (#48191)
Hides the "Multigres" term from user-facing surfaces — it's the tech powering High Availability projects, but "High Availability" is the only term users should see for now (per Slack discussion with Saxon/Ivan). **Changed:** - High Availability badge hover card (project overview) no longer says "Driven by Multigres" - Project creation HA toggle description drops the Multigres name + multigres.com link, keeps the informational copy - All schema dropdowns now hide the `multigres` schema on HA projects, by wiring in the previously-unused `filterSchemasForHighAvailability` helper: - `SchemaSelector` (shared — Table Editor, Functions, Indexes, Triggers, Schema Visualizer, etc.) - `ExposedSchemaSelector` (API settings → exposed schemas) - `EnableExtensionModal`, `CreateIndexSidePanel`, `ForeignKeySelector`, `WrapperTableEditor`, Integrations install sheet `AdvancedSettings` - SQL editor schema autocomplete (`useAddDefinitions`) - Schema list computations in the touched components are now memoized (incl. stabilizing `SchemaSelector`'s `excludedSchemas` default so the memo actually holds) **Added:** - Unit tests for `filterSchemasForHighAvailability` / `resolveHighAvailability` - MSW component test for `SchemaSelector` asserting `multigres` is hidden on HA projects and still shown on non-HA projects The filter is HA-gated on purpose: a self-hosted/non-HA user with their own schema named `multigres` still sees it. The flag-gated Multigres option in Logs is intentionally untouched — that exposure is kept for the Multigres team's debugging (separate track). ## To test - On an HA project (`high_availability: true`): hover the High Availability badge on project overview — no "Multigres" mention; open schema dropdowns in Table Editor / Database pages / SQL editor autocomplete — no `multigres` schema - Project creation with HA entitlement: toggle description has no Multigres wording/link - On a non-HA project: schema dropdowns behave as before <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Made schema dropdowns and related selectors high-availability aware across extensions, indexes, integrations, SQL editing, API exposed schemas, and relationship editors. * Updated project high-availability UI text and badge hover description to remove outdated branding and clarify horizontally scalable Postgres architecture. * **Tests** * Added coverage to ensure the schema “multigres” option is hidden/shown correctly based on high availability, and validated high-availability value handling. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
badf16be07 |
[FE-3909] fix(studio): exclude generated columns from row insert form (#48195)
Inserting a row through the table editor failed on any table with a `GENERATED ALWAYS AS (...) STORED` column — the row editor sent an explicit value for the generated column (e.g. `false` for booleans, since the bool `Select` never hits the empty-string default heuristic from #46826), which Postgres rejects with `428C9: cannot insert a non-DEFAULT value into column`. **Changed:** - `RowField` now carries `isGenerated` (from pg-meta's `is_generated`, previously unused by Studio) - Generated columns are hidden from the row editor form (they're always computed by the database, so there's nothing to input) but stay in `rowFields` state so primary-key identifier logic is unaffected - `generateRowObjectFromFields` skips generated fields, so they're omitted from both insert and update payloads - `validateFields` skips generated fields — an error on a hidden field would be unfixable **Added:** - e2e test covering inserting a row into a table with a generated boolean column - unit tests for generated-column omission in insert/update payloads and validation ## To test 1. Create a table with a generated column: ```sql create table t ( id bigint generated by default as identity primary key, base_price int, discounted_price int, is_discounted boolean generated always as ( base_price is distinct from discounted_price ) stored ); ``` 2. Table Editor → `t` → Insert row — `is_discounted` should not appear in the form 3. Fill the other fields and save — the insert should succeed and the grid should show the computed value 4. Edit an existing row and save — should still work (generated column untouched) 5. Sanity-check a normal table with identity/default columns — clearing a default field on insert should still fall back to the default (#46826 behavior) Addresses [FE-3909](https://linear.app/supabase/issue/FE-3909/studio-insert-form-fails-on-generated-boolean-columns) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for generated columns in the table editor. * Generated columns are automatically computed and excluded from insert and update forms. * Generated values now appear correctly in the table after saving a row. * **Bug Fixes** * Prevented validation errors for non-editable generated fields. * Ensured generated columns are excluded from submitted row data. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
1144b83885 |
feat(studio): add loading and fallback states to SPA shell (#48185)
The prerendered TanStack SPA shell (`_shell.html`) had a visually empty body, so every cold load showed a blank page until the JS bundle downloaded and hydrated. This bakes proper fallback states into the shell as static HTML — none of them rely on JS executing. **Added:** - `ShellFallback` component, rendered as the `ClientOnly` fallback around the root `<Outlet />` — during the shell prerender it serializes into `_shell.html`, and on the client it unmounts the moment the app mounts (no hydration mismatch: `ClientOnly` renders the fallback on the server and first client render) - Animated `LogoLoader` (Supabase logo outline) centered on screen — the stroke-dash animation is pure CSS so it runs before any JS executes - Stuck-load help text that fades in after 7s via CSS `animation-delay` (clear cookies / reload, contact support@supabase.com — the support email is gated behind `IS_PLATFORM` so self-hosted builds don't get it) - `noscript` message for JS-disabled browsers, which also hides the loader so users don't see an infinite spinner (uses `dangerouslySetInnerHTML` so React hydration never diffs noscript children) - `data-nosnippet` on both text blocks so Google doesn't surface the boilerplate as the search snippet for dashboard URLs (the one shell serves every route) ## To test All on the Vercel preview: - Open the preview — on a cold load you should catch the animated logo loader before the app mounts (throttle to "Slow 4G" in devtools if it flashes by too fast), and it never reappears on client-side navigation - In devtools, block the JS bundle (Network tab → right-click the `/assets/index-*.js` request → Block request URL) and reload — the loader animates on its own, and the help text (clear cookies / contact support) fades in after ~7s - Disable JavaScript (devtools command palette → "Disable JavaScript") and reload — no spinner, just the "requires JavaScript" message - View page source (or `curl` any preview URL) — the body contains the logo SVG, the help text, and the noscript block, all with `data-nosnippet` on the text <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a client-aware loading shell for Studio during initialization. * Shows a branded loader with a help message that appears after a short delay. * Includes platform-specific support contact details when available. * **Bug Fixes** * Prevents partial or incomplete content from rendering before the app is ready. * Improves consistency for no-JavaScript fallback rendering to avoid hydration mismatches. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
bf0e84d55a |
fix(studio): make dev:studio-local work with the tanstack dev server (#48090)
With `STUDIO_FRAMEWORK=tanstack`, `pnpm dev:studio-local` ran Studio in platform mode against the management API instead of the local CLI stack (`/` redirected to `/org` instead of `/project/default`). Vite selects env files by *mode* while the Next dev server selects them via `NODE_ENV=test`, so the tanstack dev server never loaded `.env.test` and the developer's `.env.local` (`NEXT_PUBLIC_IS_PLATFORM="true"`) won. The shell `NODE_ENV=test` also gets inlined into the dev client bundle by Vite, flipping `API_URL` to the vitest-only MSW host. `vite dev --mode test` isn't a viable fix: TanStack Start's dev-server plugin treats mode `test` as "running under vitest" and skips installing its SSR middleware, so every route 404s. Instead, dev keeps mode `development` and overlays the env cascade named by `MODE` on top. **Changed:** - `dev:studio-local` now also sets `MODE=test` (the same knob `build:tanstack` / `e2e:setup:selfhosted` already use) - `vite.config.ts` dev server: loads the `MODE`-named env cascade for the `NEXT_PUBLIC_*` client defines and seeds it into `process.env` for SSR, without clobbering shell-provided values (matching `serve.js` semantics, and safe against TanStack's own load-env plugin since `loadEnv` gives existing `process.env` priority) - `vite.config.ts` dev server: remaps a shell `NODE_ENV=test` to `development` so it can't be baked into the client bundle (mirrors `next dev` behavior) Platform-mode `pnpm dev:studio` sets no `MODE`, so the overlay is a no-op there. Build (`--mode test`), `serve.js`, and vitest (separate `vitest.config`) paths are unchanged. ## To test - `supabase` CLI installed, then: `STUDIO_FRAMEWORK=tanstack pnpm dev:studio-local` - Visit http://localhost:8082 — it should redirect to `/project/default` (not `/org`) and the Default Project page should load with data from the local stack (network requests go to `localhost:8082/api/platform/...`, no `api.supabase.(com|green)` calls) - `pnpm dev:studio` (platform mode, tanstack) still behaves as before — redirects to `/org` - Next path regression check: plain `pnpm dev:studio-local` (no `STUDIO_FRAMEWORK`) still works <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved local Studio development and test-mode environment handling. * Prevented test settings from being incorrectly embedded in the client application. * Ensured environment values are loaded consistently across development and test scenarios. * **Chores** * Updated the local Studio development command to explicitly use test mode. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
b9c8857394 |
fix(studio): TanStack route parity fixes from Next comparison audit (#48028)
Audited every TanStack route (~300 files) against its Next.js pages-router counterpart — layout wrapping, root providers, API routes, and deploy config — and fixed the divergences found. Same bug class as #48024, plus a few setup-level gaps. **Fixed (user-visible):** - `routes/__root.tsx` was missing `TimezoneProvider` + the `TimestampInfoProvider` bridge, so the stored timezone preference was silently ignored app-wide (timestamps always rendered in browser-local time) - `routes/_auth.tsx` wrapped all 10 auth pages in `AuthenticationLayout` (status banners + extra full-screen scroll container); in Next only `/sign-in` has it via getLayout. The parent is now a passthrough and sign-in wraps at the leaf - `routes/project/$ref/integrations.tsx` hardcoded `ProjectIntegrationsLayout`; the Next pages use `ProjectIntegrationsLayoutDispatch`, which switches to the Marketplace layout when that flag is enabled - `GlobalShortcuts` wasn't mounted, so the shortcuts-reference sheet (`?`) and its command-menu entry were unreachable - `routes/join.tsx` added a full-screen wrapper the Next page doesn't have (double `min-h-screen` around `InterstitialLayout`) **Fixed (behavior/config):** - ConfigCat flags lost the `plan` custom attribute, so plan-targeted flags could evaluate differently - `vercel.ts`: `api/server.js` had no `maxDuration` (Next sets up to 300s per route — stripe-sync, AI streaming); added the `/.well-known/vercel/flags` rewrite + JSON content-type (Flags Explorer endpoint previously fell through to the HTML shell); added `img`/`favicon` cache-control headers - `routes/api/v1/.../functions/$slug/body.ts` (bespoke reimplementation) dropped `apiWrapper`'s global catch — errors now get Sentry capture + the same 500 `{ error }` body - Reverted migration drift in `__root.tsx`: tooltip `delayDuration` 0 → Radix default (matching Next), `og:image` back to `supabase-og.png` - lodash → lodash-es for the whole SSR module graph (#48029, merged into this branch): the lodash CJS build's named-export interop yields non-functions under the Vite SSR module runner, which 500'd every page once `GlobalShortcuts` (or anything calling lodash during SSR render) mounted. An `options.ssr`-gated `resolveId` plugin in `vite.config.ts` serves `lodash-es` (same version, real ESM) to app source, workspace packages, and deps alike; client bundles untouched. Note: dev servers need a restart after pulling this (config change) Also corrected two stale route comments claiming the CLI/Stripe login pages inline `APIAuthorizationLayout` (they inline `InterstitialLayout`). **Not changed (audited, intentionally left):** - Redirect-only pages briefly flash `DefaultLayout` chrome under TanStack (normally unreachable — router-level redirects fire first) - Org pages inherit an inert `AppLayout` div via `routes/_app.tsx` (visually a no-op; Next org pages don't have it) - Adapter-level differences: framework 405s instead of Next's `Allow`-header JSON, `bodyParser.sizeLimit` not enforced on two routes, narrower favicon non-prod detection (commented as known) - Known pre-existing dev console error (also on Next master): closing the shortcuts sheet logs a setState-in-render warning — `@tanstack/react-hotkeys@0.10.0` calls `setOptions` in the `useHotkeySequence` render body, notifying `useHotkeyRegistrations` subscribers mid-render. Worth an upstream report/dep bump as a follow-up ## To test Verified on the local TanStack dev server via Playwright (all pass): - Set a timezone in the account dropdown → log timestamps show that timezone's row in the hover tooltip - `?` opens the shortcuts sheet; `⌘K` → "Show all keyboard shortcuts" does too - `/sign-in` still shows banners/window chrome; `/sign-up`, `/sign-in-sso`, `/forgot-password`, `/cli/login` render without the extra wrapper - `/project/<ref>/integrations` renders (legacy sidebar when marketplace flag off) - `/join` renders a single centered interstitial - `og:image` meta is `supabase-og.png` - Vercel deploy-button new-project page renders the consolidated #47995 form inside the window chrome - `vercel.ts` changes are deploy-config only — verify Flags Explorer + function timeout on a preview deploy <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added timezone-aware timestamp handling across Studio. - Added support for global keyboard shortcuts. - Updated authentication page layouts for a more consistent sign-in experience. - Refreshed social sharing imagery. - **Bug Fixes** - Improved error reporting and responses when loading function source files fails. - Improved handling of integration page layouts. - Fixed Vercel routing for feature configuration requests. - **Performance** - Added caching for static images and favicons. - Increased server execution time for longer-running requests. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
58621818d0 |
feat(studio): switch TanStack skew protection to ?dpl= query params (#48008)
Switches the TanStack build's Vercel skew protection from the `__vdpl` session cookie to `?dpl=<deployment-id>` query params baked into asset URLs at build time. Assets stay pinned to the deployment that built them, while document navigations and API fetches always reach the latest deployment (with the cookie, a session stayed fully pinned — including reloads — until the tab closed). **Removed:** - `pinDeploymentForSession` (the `__vdpl` cookie) from `router.tsx`, plus the cookie clearing in the refresh toast and the `vite:preloadError` backstop - `credentials: 'omit'` on the deployment-commit check — its only purpose was escaping the cookie pin, and API fetches are now inherently unpinned **Added:** - `skewProtectionDpl` plugin + `experimental.renderBuiltUrl` in `vite.config.ts`, active only when `VERCEL_SKEW_PROTECTION_ENABLED=1`. Full coverage needs three mechanisms (Vite has no single hook for this — see [vitejs/vite#13834](https://github.com/vitejs/vite/discussions/13834#discussioncomment-7469745)): 1. `renderBuiltUrl` — CSS `url()`s, images, workers, and `__vite__mapDeps` preload lists 2. a `generateBundle` (`order: 'post'`) rewrite of chunk-to-chunk `import`/`from` specifiers, which Rolldown emits as bare relative paths that `renderBuiltUrl` never sees — with sourcemaps recombined per chunk (`magic-string` + `@jridgewell/remapping` devDeps) so Sentry columns stay exact 3. a post-`buildApp` patch of the prerendered `_shell.html` (script/preload tags + embedded router manifest come from TanStack, not Vite's asset pipeline); without it the entry graph double-downloads because preload and import URLs differ ## To test - Built with fake `VERCEL_SKEW_PROTECTION_ENABLED=1 VERCEL_DEPLOYMENT_ID=dpl_TESTPIN123abc`: every chunk import specifier (static + dynamic), `__vite__mapDeps` entry, CSS font URL, and `_shell.html` asset URL carries `?dpl=`; zero unpinned `/assets/` references remain - Sourcemap accuracy verified by tracing a minified position through the recombined map: resolves to the exact original file/line/column (`use-check-latest-deploy.tsx:62:8`) - Built without the env vars: output contains no `dpl=` anywhere (self-hosted/e2e builds unaffected) - `smoke:tanstack` passes on both builds; `tsc --noEmit` and eslint clean - On the preview: load the dashboard, check Network tab — chunk/CSS requests should carry `?dpl=` matching the deployment; hard reload should hit the latest deployment (no pin on document requests) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Improved deployment consistency by pinning generated asset and module URLs to the current deployment (using `?dpl=`). * Simplified refresh and preload-error recovery to reduce reload-loop risk. * Kept API request behavior aligned with the updated deployment routing/pinning approach. * Preserved correct routing across deployment configurations. * **Developer Experience** * Added build-time tooling to rewrite pinned URLs for client assets while maintaining source map integrity. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
8b82d5c472 |
[FE-3895] fix(studio): fit unified logs table to mobile viewport (#47930)
The unified logs table has a fixed content width of ~1400px, so on mobile it overflowed the viewport — columns were clipped and the header appeared misaligned with the rows (the underlying columns were actually aligned; the table just didn't fit). **Changed:** - Progressively hide the three widest columns on narrow viewports via responsive display classes: `method` from `sm`, `pathname` from `md`, `event message` from `lg`. - On phones only the essential columns remain (checkbox, level, date, log type, status), so the table fits with no horizontal scroll. - Desktop (≥`lg`) is unchanged — all columns render exactly as before. Full row data (method/pathname/event message) is still accessible by clicking a row to open the detail panel. ## To test - Open a project's **Logs** (Unified Logs preview) at a mobile width (~390px), with some API log rows in range. - Confirm the table fits the screen — no horizontal scroll/clipping — and the `DATE` header sits cleanly above the dates. - Widen the browser: `method` appears ~640px, `pathname` ~768px, `event message` ~1024px. - At desktop width, confirm all columns show and header/rows line up as before. - Tap a row on mobile → detail panel opens with the full log (method, pathname, event message). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Style** * Improved responsive table layouts for unified logs. * Columns now adapt visibility based on screen size, keeping key information accessible on narrow displays. * Event messages flex more naturally when visible. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
67b17c885c |
fix(studio): allow github.com and vercel.com avatars in img-src CSP (#47885)
The TanStack build renders remote images as plain `<img>` tags — there's no Next.js image optimizer rewriting them to same-origin `/_next/image` URLs — so remote avatar origins now hit the CSP directly and were being blocked (e.g. `Loading the image 'https://github.com/alaister.png?size=96' violates the following Content Security Policy directive: "img-src 'self' ..."`). **Changed:** - Added `https://github.com` to `img-src` — GitHub profile avatars (`https://github.com/<username>.png`, used by the user dropdown, AI assistant messages, org invites, and audit logs). The URL 302s to `avatars.githubusercontent.com`, which is already allowed (CSP validates both hops of a redirect). - Moved `https://vercel.com` from the dev/staging-only `img-src` list to the unconditional list — Vercel integration account avatars (`https://vercel.com/api/www/avatar/...`) load in prod too. Audited all other `next/image` usages in studio: everything else is either a local `${BASE_PATH}/img/...` asset (`'self'`) or a marketplace image served from `NEXT_PUBLIC_MARKETPLACE_API_URL`, which is already in `img-src`. The old `remotePatterns` entry for `api-frameworks.vercel.sh` has no remaining references, so it was deliberately not ported. ## To test - On the TanStack build, sign in with a GitHub-linked account and check the user avatar renders in the top-right user dropdown (no CSP violation in the console) - Check org audit logs (`/org/_/audit`) render member avatars - With a Vercel integration installed, check the account avatar renders in org integration settings - Sanity-check the Next.js build still renders the same avatars (both builds share `getCSP()`) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * GitHub profile avatar images now display correctly. * Image loading rules for staging and development environments were refined to improve content security. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
55f5676d66 |
ci(studio): run E2E against both Next + TanStack (stack 6/6, from #46424) (#47119)
**Stack 6/6 (final)** of the TanStack Start migration (#46424). The middle slices (#47107 → #47118) have all merged, so this now sits directly on master. ## What's in this PR One file: `.github/workflows/studio-e2e-test.yml` — adds `framework: [next, tanstack]` to the test/report matrices and sets `STUDIO_FRAMEWORK` (consumed by `scripts/dispatch.js`). Until now CI only built/tested Next. This flips on the dual-framework E2E matrix so the TanStack build gets exercised end-to-end on every run. ## ⚠️ Depends on #47657 (merge that first) The `tanstack` shard needs the Monaco loader fix in **#47657** to be on master. Quick version: master's #47182 re-nested the Monaco assets under `public/monaco-editor/vs/` and the TanStack root was still pointing at the old flat path, so Monaco didn't mount anywhere in the TanStack build and every editor-backed test timed out (RLS, cron SQL, realtime JSON, db functions, GraphiQL). Kept that fix on its own branch rather than piling it onto this one. Merge order: 1. #47657 → master 2. re-merge master into here (I'll cascade it) 3. `tanstack` shard goes green → merge this ## ⚠️ Branch-protection note This renames the E2E jobs (`E2E tests` → `E2E tests (next|tanstack, shard)`), so master's current required status checks (`E2E tests (1, 2)` / `(2, 2)`) stop being reported. The required-check list in branch protection needs updating to the new names when this merges. ## Verification Config-only, no app code. The real validation is this matrix running both shards green once #47657 lands — the `next` shards already pass here; the `tanstack` shards pass once the Monaco fix is on master. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Integration overview markdown can now be loaded more reliably from a synchronized on-disk registry (raw markdown support). * **Bug Fixes** * Navigation, redirects, and prefetch now preserve query strings and hash fragments more consistently using Next-like semantics (including repeated keys, empty clearing, and lossless encoding like newlines). * Improved internal-link/router compatibility for Next-style `?`/`#` targets and base-path handling. * Edge Functions diff tab matching works correctly in the browser without Node-specific path utilities. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
ad181489b1 |
feat(studio): adopt @sentry/tanstackstart-react server instrumentation on the TanStack build (#47724)
Stacked on #47666 (base `alaister/tanstack-sentry-init`; retarget to `master` when that merges). **Supersedes #47721** (the manual `@sentry/node` wrapper). Client stays on #47666's `@sentry/react` setup. Adopts the official `@sentry/tanstackstart-react` SDK **on the server only**, after a spike (#47723) evaluating the full unified client+server SDK. The spike found the SDK's **browser** `tanstackRouterBrowserTracingIntegration` is a broken no-op stub at 10.59.0/10.64.0 — so the client stays on `@sentry/react` (whose equivalent integration is a real, working implementation, already shipped in #47666). The **server** exports, however, are a clear upgrade and slot in cleanly. ### What this adds (server-side, TanStack build only) - **`instrument.server.mjs`** — `Sentry.init` from `@sentry/tanstackstart-react`, mirroring `sentry.server.config.ts` + `release: VERCEL_GIT_COMMIT_SHA`. - **`start.ts`** — `sentryGlobalRequestMiddleware` + `sentryGlobalFunctionMiddleware` at the front of the existing `createStart(...)` middleware. **This is the win**: it captures request- and server-function errors *including the ones swallowed into 500s* — the exact class the manual wrapper (and the Next server SDK) miss. - **`api/server.js` / `scripts/serve.js`** — gated (`STUDIO_FRAMEWORK==='tanstack'`) instrument init + `wrapFetchWithSentry` on the handler. - **`vite.config.ts`** — `sentryTanstackStart({ …, autoInstrumentMiddleware: false })` as the last plugin: source-map upload + release injection (skips gracefully without an auth token). Middleware is wired explicitly rather than via the plugin's string-rewrite. ### Guarantees - **Client untouched** — the `@sentry/nextjs`→`@sentry/react` alias and #47666's client init are unchanged. - **Next untouched** — `instrumentation.ts` / `sentry.server.config.ts` etc. stay as-is; all new code is TanStack-gated. - **No server SDK in the client bundle** — verified after build: no `@sentry/node` / server middleware / `wrapFetchWithSentry` in `dist/client/assets` (`start.ts`'s server import is tree-shaken out). ### Verified TanStack build exit 0 (past `assertNoChunkCycles`), post-build server boot served `/api/get-utc-time → 200`, `tsc --noEmit` clean, prettier/eslint clean. Node smoke: no-DSN init is a clean no-op; wrapped handler returns 200. ### To test (deploy with a server DSN) Throw a server error from an `/api/*` route (or a `/_serverFn/*`) — including one that gets turned into a 500 without rethrowing — and confirm a server event in Sentry with `release` = the deploy SHA. Compared to #47721, the swallowed-500 case should now be captured via the middleware. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Sentry integration for the Studio app’s TanStack Start runtime, including request and server-function instrumentation. * Wrapped server request handling to capture errors reliably, with tracing enabled. * Updated build tooling to conditionally upload source maps when credentials are present. * **Bug Fixes** * Improved resilience by safely falling back to a no-op Sentry setup if instrumentation cannot be loaded. * Ensured existing request protection remains enabled while adding observability middleware. * **Chores / Config** * Added `SKIP_ASSET_UPLOAD` to the build environment list to control cache/build behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
a3f2c4ffc1 |
chore(deps): upgrade to TypeScript 7 (native compiler) (#47757)
Upgrades the monorepo to TypeScript 7.0.2, released 2026-07-08. `tsc` is now the native Go compiler ([announcement](https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/)) — full turbo typecheck drops from ~56s to ~19s locally. TS 7.0 ships **without a programmatic API** (it lands in 7.1), so this uses Microsoft's recommended side-by-side setup: the `typescript` name resolves to `@typescript/typescript6` (the 6.0 API republished) for API consumers — typescript-eslint and Next.js build typechecking — while `@typescript/native` (the real `typescript@7.0.2`) owns the `tsc` bin that typecheck scripts run. Exactly one version of each is in the lockfile; nothing imports the native package as a library. When 7.1 + tool support lands we can collapse back to a single `typescript` dep in the catalog. **Changed:** - `pnpm-workspace.yaml`: catalog aliases for `typescript` / `@typescript/native` - 17 package.json files: `@typescript/native` added beside each `typescript` dep so every package's `tsc` is the native binary - `apps/studio/tsconfig.json`: exclude `dist/` (gitignored build output) from typechecking **Fixed** (real type errors TS 6 under-reported): - `packages/ui-patterns` CodeBlock: `borderLeft: null` → `undefined` (`CSSProperties` doesn't accept null) - `apps/www` CodeBlock: removed a JSX `@ts-ignore` comment that tsgo doesn't honor and fixed what it masked (untyped `.js` theme objects, possibly-undefined highlighter children) ⚠️ **Merge timing:** the new packages are inside pnpm's 3-day `minimumReleaseAge` window until ~July 11. Installs from the committed lockfile are unaffected (resolution is skipped), but anything that forces a re-resolution before then will fail — hold off merging until the window passes. Note for editors: the compat package has no `lib/tsserver.js`, so VS Code's "Use Workspace Version" won't work — use the bundled TS or the TypeScript Native Preview extension. ## To test - `pnpm install && pnpm typecheck` — all 15 tasks green, and `./node_modules/.bin/tsc --version` prints 7.0.2 - `pnpm lint --filter=studio` — typescript-eslint still parses (resolves the 6.0 API) - `pnpm build --filter=design-system` (or any Next app) — Next's tsconfig validation and build typecheck still work - CodeBlock rendering on www (syntax highlighting, line highlights with/without border) — the two fixes are behavior-neutral but worth an eyeball <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements / New Features** * Enhanced TypeScript tooling support across the workspace for smoother development builds and checks. * **Bug Fixes** * Code blocks render more reliably when content is empty or missing. * Highlighted code line styling applies more consistently. * **Maintenance** * Studio TypeScript builds now avoid including generated output (such as `dist`) during compilation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
74bc0a8e27 |
fix(studio): initialize Sentry on the TanStack build (captures were silent no-ops) (#47666)
Stacked on #47657 (base is `alaister/tanstack-migration-fixes`; retarget to `master` once that merges). The TanStack runtime never ran `Sentry.init` — `instrumentation-client.ts` is a Next-convention file nothing imports under TanStack Start, so every `Sentry.captureException` on that build (including the `routes/__root.tsx` error-boundary / `routerErrorComponent` reports) was a silent no-op. - **Shared config source**: the entire client config moves verbatim from `instrumentation-client.ts` into `lib/sentry-client-options.ts` (`buildSentryClientOptions`). Both runtimes build from it, so Next and TanStack can't drift — the builds differ only in two explicit knobs. - **TanStack init**: `sentry.tanstack.ts` initializes `@sentry/react` from `getRouter()` (TanStack Start's real client bootstrap — the earliest point with the router instance), wiring `tanstackRouterBrowserTracingIntegration(router)`. Window-guarded + idempotent; `router.tsx` is TanStack-only so the Next build is untouched. (Named without `.client.` — Start's import-protection fails the build for `*.client.*` in the server graph.) - **Third-party error filter is intentionally Next-only**: without the bundler-injected `applicationKey` metadata (only `withSentryConfig` provides it), the SDK tags *every* event `third_party_code: true` and `beforeSend` would drop them all — recreating the silent no-op with a DSN set. Follow-up: add `@sentry/vite-plugin` moduleMetadata, then enable. - **DSN-less builds stay crash-free**: `vite.config.ts` inlines `undefined` for unset `NEXT_PUBLIC_SENTRY_DSN`/`NEXT_PUBLIC_SENTRY_ENVIRONMENT` (a literal `process.env.*` in the bundle is the exact `process is not defined` class #47657 fixed). No-DSN → disabled client, plus the existing `IS_PLATFORM`/consent gates. - Tests: `instrumentation-client.test.ts` moved to `lib/sentry-client-options.test.ts` with all 36 assertions kept, plus integration-gating and Next/TanStack parity tests. `tsc` clean; full `vite build --mode test` passes. Follow-up (separate): server-side Sentry for the Start handler (`server.ts` entry + `@sentry/node`-style init). ## To test - **Locally (no DSN set)**: load the TanStack build — no Sentry network requests, no console errors, and crucially no `ReferenceError: process is not defined` (the define fallback). Forcing an error must not POST to any `/envelope` endpoint. - **On a preview/deploy (DSN set, telemetry consent accepted)**: throw a test error (e.g. crash a route component) → a POST to `o…ingest.sentry.io/api/…/envelope/` fires, and the event lands in Sentry with a `codeSampleRate` tag and **no** `third_party_code` tag. Navigation spans named after TanStack routes appear when the 2% pageload trace samples in. - **Next build regression check**: the Next dev/preview still reports errors exactly as before (`instrumentation-client.ts` now builds its options from the same shared source). --- ### Review feedback: Sentry `/envelope` never fires on TanStack (Joshen) Root-caused: `@sentry/core`'s `Client.sendSession` silently drops the session when the client has no `release`. The Next build gets a release injected by `withSentryConfig` (the Vercel commit SHA); the Vite build runs no Sentry bundler plugin, so it had no release → session envelopes were discarded before transport → zero `/envelope` traffic (errors/transactions are separate). Fix: inject `release: NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA` on the TanStack build (vite.config re-exposes `VERCEL_GIT_COMMIT_SHA` under the `NEXT_PUBLIC_` name, same SHA the Next release resolves to). Also switched `integrations` to the function form so defaults are preserved by contract (not just by current SDK behavior). 45 unit tests green. **To test (deploys only — the SHA is unset locally, so this can't be reproduced on a local dev build):** on this PR's Vercel preview with a DSN + telemetry consent, load any page and watch the Network tab for a POST to `…ingest.sentry.io/…/envelope/` — a session envelope should now fire on load, matching the Next build. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Improved client-side error and performance monitoring for the Studio app across both router setups. * Added support for passing release/version information into monitoring data. * **Bug Fixes** * Reduced noisy error reporting by better filtering common browser, extension, cancellation, and load-related issues. * Prevented browser bundles from referencing missing environment values at runtime. * Made monitoring initialization safer in server-rendered and client-only environments. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
18431efb25 |
fix(studio): TanStack post-merge fixes — Monaco loader, fonts, CSP (from #46424) (#47657)
Post-merge fixes for the TanStack Start migration (#46424) — things that broke on the TanStack build as master evolved under the migration branches. Kept on their own branch off master rather than piling onto the E2E-matrix PR (#47119); all land on master and cascade up to S6 + the big PR. Common theme: a master PR changed something the Next pipeline handles via `next/font` / `pages/_app.tsx` / `next.config.ts`, but the hand-rolled TanStack equivalent (`routes/__root.tsx`, `styles/fonts.css`, `vercel.ts`) wasn't updated to match — invisible on the Next deploy, broken only on TanStack. --- ## 1. Monaco loader path (#47182) #47182 re-nested the served Monaco assets from a flat `public/monaco-editor/` layout into `public/monaco-editor/vs/` and updated `pages/_app.tsx`, but `routes/__root.tsx` still pointed `loader.config` at the old path, so `loader.js` 404'd and **no Monaco editor mounted anywhere in the TanStack build**. Now mirrors the Next config (`${origin}${BASE_PATH}/monaco-editor/vs`, window-guarded for SSR). Was failing the whole `tanstack` E2E shard on #47119. ## 2. Inter + Manrope fonts (#47306) #47306 renamed Tailwind's sans var `--font-custom` → `--font-sans` and added `--font-heading` (Manrope), set via `next/font` on Next. `fonts.css` still only set the now-ignored `--font-custom`, so the body fell back to the theme's system chain (`Circular, custom-font, Helvetica…`) at weight 450 — that's the "Inter weights look wrong". Manrope was missing entirely. - Wire `--font-sans` (Inter) + `--font-heading` (Manrope) to match `next/font`. - **Vendor all three families** (Inter, Manrope, Source Code Pro) via `@font-face` so nothing depends on the Google Fonts CDN — matches `next/font` self-hosting, and (see below) `font-src` doesn't allow `fonts.gstatic.com` anyway. Verified in-browser: computed `body` → `Inter`, headings → `Manrope`, all loading from local `/assets/*.woff2`. ## 3. Security headers / CSP (next.config.ts `headers()`) The Next build sets X-Frame-Options / X-Content-Type-Options / HSTS / **Content-Security-Policy** / Referrer-Policy via `next.config.ts`. The TanStack build never carried these over — `vercel.ts` only set cache-control, so **the deployed TanStack dashboard shipped with no CSP at all**. The TanStack deploy serves a static shell (no server to attach headers), so they go in the Vercel config: - `security-headers.ts` — shared source of truth, reuses `getCSP()`, env-gated exactly like next.config. - `vercel.ts` — apply to every response (all base-path prefixes): full `getCSP()` + HSTS on platform. - `scripts/serve.js` — the non-platform set (`frame-ancestors 'none'`) for the self-hosted server. **Tested the policy in a real browser** (temporarily enforced it on the TanStack build via /test-supabase-local): everything passed except one real gap — `font-src` was missing `data:`, so GraphiQL's bundled Monaco codicon font and Stripe's payment-element fonts (both data: URIs) were blocked (37 violations on a cold load). Added `data:` to `font-src` in `csp.ts` → violations drop to zero, SQL editor Monaco renders clean. That gap affects the Next build too. --- ## 4. `node:path` import crashing `/project/[ref]/merge` Found by a full-site click-through of the TanStack build (all product areas, ongoing — see below). `useEdgeFunctionsDiff.ts` + `EdgeFunctionsDiffPanel.tsx` did `import { basename } from 'path'` in client code. Webpack (Next) polyfills `path` in the browser; Vite externalizes it, so the whole `/merge` route crashed with "Module \"path\" has been externalized for browser compatibility". Replaced the two `basename` call sites with a string helper. Verified in-browser: `/merge` renders. ## 5. URL shape — Next-style search-param semantics + shim fixes The dashboard produced malformed URLs vs the Next build (strange query params, trailing slashes, `##` hashes). Root cause + audit verified empirically against `@tanstack/react-router@1.170.10`; all fixed with unit tests and browser-verified: - **`createRouter` used TanStack's default JSON search codec** — `?flag=true` became `?flag=%22true%22` via links, repeated `?filter=…&filter=…` collapsed into a JSON array (breaking multi-filter/sort table-editor URLs and the account-page round-trip, which double-encoded), and search values arrived as numbers/booleans where the app expects strings. New `lib/router-search-params.ts` (Next-style: strings in, strings out, repeated keys → string[]) wired into the router. - **Link shim** (`compat/next/link.tsx`): `URL.hash` includes the leading `#` while TanStack's `hash` prop adds its own → every `href="…#section"` navigated to `##section` (hash-scroll broke); `Object.fromEntries(searchParams)` dropped repeated query params. Both fixed. - **Trailing slash injected before the query** on every `?`-only relative navigation (`/auth/providers/?provider=…`): fixed in the compat router (prefix current pathname) and via a custom nuqs adapter (`lib/nuqs-tanstack-adapter.tsx`) replacing the stock tanstack-router adapter, whose `navigate({ to: '?…' })` writes hit the same TanStack behavior (123 files use nuqs). - **Pathname-less `router.push({ query })` leaked path params** — Next re-consumes `ref`/`id` from `query` into the path pattern; the shim didn't, yielding `/editor/17597?schema=public&ref=<ref>&id=17597&filter=…` from table-editor filter/sort, linter panels, and advisor shortcuts. The shim now defaults the pathname to the current route pattern and backfills omitted params. - **Redirects dropped query + hash** (Next's `redirects()` preserves them): `__root.tsx` `matchRedirect` and `routes/index.tsx` now carry incoming params/hash through (consumed rule params excluded, destination's own params win). `/?next=new-project&projectName=zzz` → `/new/new-project?projectName=zzz`; `/sql/quickstarts?template=x#frag` → `/sql/examples?template=x#frag`. Browser-verified post-fix: advisors `?preset=WARN`, providers `?provider=Google`, `?schema=auth` — all clean (no `/?`, no leaks); repeated `filter` params survive hydration; `=true` unquoted; single `#`. ## 6. TanStack `navigate` corrupting query values (Logs Explorer SQL newline loss) TanStack router-core treats a query string embedded in `navigate({ to })` as part of the *path*: `decodePath` percent-decodes it and `sanitizePathSegment` strips control characters, silently deleting every `%0A`. Logs Explorer's SQL (`s` param) lost its newlines on Run/reload — `order by timestamp desc` / `limit 5` glued into `desclimit 5`, which then failed the LIMIT lint. Pre-existing on the TanStack build (the stock nuqs adapter had the same shape); Next unaffected. Fixed by never embedding query strings in `to`: the nuqs adapter and the compat `router.push`/`replace`/`prefetch` (plus the `next/navigation` shim) now pass search as an object through the app codec (`splitInternalUrl` hoisted to `lib/internal-url.ts`). Guard test drives a real `createRouter` with multi-line SQL through both producers. Browser-verified: newlines survive the full Run → reload → re-Run cycle. ## 7. Integration overview markdown never loaded (all integrations) `MarkdownContent` used a template-literal dynamic import (``import(`@/static-data/integrations/${id}/overview.md`)``) — webpack builds a context module for that, Vite can't analyze it, so every integration detail page threw `Failed to resolve module specifier` and rendered no overview text. Fixed with an explicit lazy registry of literal imports (`static-data/integrations/overviews.ts`, drift-guarded by a test) plus an `mdRawLoader()` Vite plugin mirroring next.config's turbopack raw-loader rule. Both runtimes keep working; md stays out of the main bundle. ## 8. GraphiQL editor never mounted (`exports is not defined`) Our `umdAmdShortCircuit()` Vite plugin (which disarms Monaco's global AMD loader for deps like papaparse) rewrote `typeof define === 'function' && define.amd` to `false` inside `monaco-editor`'s bundled copy of marked — whose UMD relies on its own *local* `define` shim — so the whole optimized monaco chunk failed to evaluate and GraphiQL's editor pane stayed blank. The check now only short-circuits when `define` is the global AMD loader. Browser-verified: all four GraphiQL Monaco panes mount, queries execute. (Known follow-up: GraphiQL's Monaco workers fall back to the main thread under Vite — functional, worker wiring is Next-specific `setup-workers/webpack`.) ## 9. `@sentry/nextjs` bundling Next internals — built TanStack bundle crashed (caught by E2E) The E2E suite against the **built** TanStack bundle (not the dev server) found lazy chunks like `table-editor-*.js` dead on arrival: `@sentry/nextjs` (imported by ~25 client files) drags in `next/dist/shared/lib/constants`, whose module scope evaluates `process?.features?.typescript` — optional chaining doesn't guard an undeclared `process` in the browser, so the whole chunk failed at load with `ReferenceError: process is not defined`. Dev shims `process`, which is why weeks of dev-server testing never saw it. Fixed by aliasing `@sentry/nextjs` → `compat/sentry-nextjs.ts` (re-exports `@sentry/react`, same deduped 10.59.0, plus explicit stand-ins for the three Next-only APIs) in the Vite build only. Verified: fresh build has zero Next-internals markers in any chunk; table editor loads clean; full E2E suite run against the built bundle. Note for the stack: `alaister/tanstack-start` / the E2E-matrix branch already carried a different fix for the same crash (a `next/constants` shim) that never made it to master — the cherry-pick onto those branches keeps **both** (the shim covers any other transitive importer; the alias keeps Next internals out of the client bundle entirely). **Follow-up found while fixing:** Sentry is never *initialized* in the TanStack runtime — `instrumentation-client.ts` / `sentry.server.config.ts` are Next-convention files nothing imports under TanStack, so `captureException` calls are silent no-ops. Needs an `@sentry/react` init (+ `tanstackRouterBrowserTracingIntegration`) wired into the TanStack client entry as its own PR. ## 10. GraphiQL Monaco workers + edge-function Deno typings (Vite-only gaps) - **GraphiQL's Monaco workers ran on the main thread** under Vite ("Could not create web worker(s)…" — `setup-workers/webpack`'s `new URL(...)` form isn't rewritten by Vite). A `graphiqlViteWorkers()` plugin resolves the import to graphiql's own `setup-workers/vite` variant for client builds (SSR untouched, Next untouched); the setup-workers chain is `optimizeDeps.exclude`d because the Rolldown optimizer can't load `?worker` ids. - **Edge-function editors silently lost their Deno typings** — `AIEditor` loaded `public/deno/*.d.ts` via `/* @vite-ignore */` imports that always failed at runtime under Vite. The `.md` raw loader is generalized into `rawTextLoader` (exact-path allowlist for the two typings files, served as virtual string modules so the dep scanner never parses `.d.ts` syntax), and the imports are now static-analyzable literals that both bundlers handle (turbopack's raw-loader rules match them on the Next side). ## Split out for reviewability App-level fixes that reproduce on the Next build too (DOM-nesting hydration errors, the ghost deleted-snippet nav, the recurring pg-meta `migrations` 400) moved to their own PR: #47667. Sentry initialization for the TanStack runtime (captures were silent no-ops) is #47666, stacked on this PR. ## Full-site test campaign Drove every dashboard product area on the local TanStack build (Playwright, human-style) hunting migration regressions: redirects/404/catch-alls, org, account, project home/branches/merge, table editor CRUD, SQL editor (Monaco/run/save/templates/AI), all database pages, all auth pages, storage CRUD, edge functions + realtime, logs/observability, advisors, settings, integrations hub incl. nested routes, global UI (palette/connect/switchers/theme/fonts), and a cross-cutting sweep (document titles, back/forward chain, hard-refresh hydration on deep URLs, trailing-slash active state). Every failure found is fixed above and re-verified in-browser; remaining console quirks were cross-checked against the deployed Next build and are pre-existing (tracked separately). ## To test Most fixes are already browser-verified + covered by unit tests and the self-hosted E2E suite; the last two landed after the final browser pass and still need an in-browser check: 1. **GraphiQL Monaco workers** — restart the dev server (clear `apps/studio/node_modules/.vite` once first — the optimizer cache may hold a stale prebundle of the worker chain). Open `/project/<ref>/integrations/graphiql/graphiql` with the console open: the `Could not create web worker(s). Falling back to loading web worker code in main thread` warning must be gone, and DevTools → Sources → Threads shows the three workers (json, editor, graphql). Autocomplete in the query editor stays responsive. 2. **Edge-function Deno typings** — `/project/<ref>/functions/new`: no "Failed to load … typings" console error, and typing `Deno.` in the editor offers typed completions (e.g. `Deno.env`). Spot-checks for the rest (all previously verified): - `/project/<ref>/merge` renders (no "Module path" crash). - Multi-line SQL in Logs Explorer survives Run → reload (no `desclimit` gluing, no LIMIT-lint false failure); `s` param keeps `%0A`. - `/auth/providers` → open a provider → `?provider=…` with no trailing slash before `?`; table-editor filter/sort URLs carry no leaked `ref`/`id` params; `/?next=new-project&projectName=x` lands on `/new/new-project?projectName=x`. - Integration detail pages (cron/queues/vault/data_api) show their overview prose; GraphiQL query editor mounts. - Built bundle (`MODE=test vite build` + `start:tanstack`): table editor loads with no `process is not defined`. - `curl -sI` any page on a platform deploy: `X-Content-Type-Options: nosniff` (was the invalid `no-sniff`). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Centralized integration overview markdown loading with registry-based lookup. * Improved Monaco loading/asset path handling for smoother editor startup. * **Bug Fixes** * Next-style navigation/search handling now preserves pathname, hash, repeated query keys, and special characters (including newlines). * Redirects now reliably carry over query and hash with correct precedence. * **Security/Configuration** * Updated CSP font sourcing and unified security headers delivery across environments; conditional HSTS behavior. * Refreshed font CSS variables and font-face definitions to match the theme. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- ### Review feedback: non-prod favicon (Joshen) The TanStack `__root.tsx` hardcoded the prod favicon; local + hosted staging now use the white staging favicon (`/favicon/staging`), matching what `pages/_app.tsx` passes to `MetaFaviconsPagesRouter` for non-prod. Rather than pull the pages-router component into the TanStack head, it reuses the same synchronous `NEXT_PUBLIC_ENVIRONMENT` signal the file already uses for `IS_DEV_TOOLBAR_ENABLED` (the `head()` route option isn't a React component, so it can't run `_app`'s async CLI check — but the env signal covers the reported local/staging case). --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
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> |
||
|
|
32798c3162 |
[FE-3423] chore(studio): flag pages/** edits to mirror into TanStack routes (#47650)
Adds a PR-time reminder to mirror any edit to `apps/studio/pages/**` into the corresponding `apps/studio/routes/**` file, since the Next.js pages router and the TanStack Start route tree ship side-by-side during the migration and can silently drift. **Added:** - A CodeRabbit `path_instructions` rule (`.coderabbit.yaml`) scoped to `apps/studio/pages/**` that prompts authors to check whether a page change needs mirroring into `routes/**`. It encodes the migration's nuance so it isn't noise — pure body edits on re-export (Path A) pages propagate automatically, but layout/`getLayout`, `staticData` props, `withAuth`, redirect-path, or new-page changes must be mirrored by hand. Framed as verify-not-block, and explicitly tells authors *not* to delete the `pages/**` file. **Changed:** - `apps/studio/TANSTACK_MIGRATION.md` — documents the guardrail under the Runtime model section, and adds a cleanup-checklist line to remove it once `pages/**` is deleted (FE-3106). This is temporary scaffolding — it comes out with the final `pages/**` cleanup pass. ## To test - This needs to land on `master` first, then open a throwaway PR that touches a file under `apps/studio/pages/**` and confirm CodeRabbit leaves the reminder comment. - `path_instructions` can be flaky — if CodeRabbit doesn't fire reliably, the fallback is a GitHub Action + sticky PR comment scoped to `paths: ['apps/studio/pages/**']`. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added migration guidance for Studio page changes to help keep mirrored routes in sync during the transition period. * Clarified when page updates need to be reflected in the matching route files, including new pages and changes to layout, access control, titles, static data, or paths. * Added a cleanup reminder for removing the temporary review guidance once the migration is complete. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
4a18670367 |
[FE-2417] fix(studio): update disk EBS UI copy to match new limits (#47646)
Updates the dashboard disk-management copy to match the new AWS EBS modification limits (already reflected in the docs): from the old fixed "4-hour cooldown / once every 4 hours" framing to "up to 4 modifications within a rolling 24-hour window". This is a copy-only change plus one small logic-constant alignment. Timer/countdown behavior is unchanged — this only updates wording to bring the dashboard in line with the docs. **Changed:** - `DiskSpaceBar` autoscaling tooltip, `DiskCountdownRadial` card, `DiskSizeConfiguration` "Importing a lot of data?" alert, `DiskSizeConfigurationModal` alert title + both countdown branches, `DiskManagementReviewAndSubmitDialog` IOPS + disk-size row descriptions, and two code comments — all reworded to the new "4 per rolling 24-hour window" framing - `DiskSizeConfigurationModal` countdown now derives from the shared `COOLDOWN_DURATION` constant (4h) instead of a stale hardcoded `6 * 60` (6h), so the legacy resize path matches the newer disk-attributes path ## To test - Open a Pro AWS project → **Settings → Compute and Disk** → hover the **Autoscaling** pill on the disk bar: tooltip should read "…limited to 4 within a rolling 24-hour window" (no "once every 4 hours") - Change IOPS only → **Review changes** → IOPS row description shows the new "rolling 24-hour window… as soon as the previous one completes" copy - Change disk size → **Review changes** → Disk size row shows "You can modify disk attributes up to 4 times within a rolling 24-hour window" (not "For 4 hours after changes…") - On a non-AWS Pro project → **Database → Settings → Increase disk size**: modal title reads "Disk modifications are limited to 4 per rolling 24-hour window"; any "resize again in ~X" countdown is bounded by 4 hours, not 6 - Sanity: none of the old "4-hour cooldown" / "once every 4 hours" strings appear anywhere in the disk UI <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Updated disk resizing messages across the app to reflect a rolling 24-hour limit instead of a fixed 4-hour cooldown. * Clarified when disk size, IOPS, and throughput changes are available again, including more accurate next-available timing. * Improved warning copy in disk configuration and review dialogs so limit messages are consistent and easier to understand. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
4129c8954d |
feat(studio): TanStack project routes — auth/logs/settings/functions (stack 5.2/6, from #46424) (#47118)
**Stack 5.2/6** of the TanStack Start migration (#46424) — second half of the project routes (S5 was split for CodeRabbit's 150-file cap). Stacked on **#47117** (5.1). > [!NOTE] > Same shape as 5.1 — thin route wrappers over the existing pages-router components. With this PR every route is present, so `routeTree.gen.ts` is now **byte-identical to the migration branch**. ## What's in this PR - **Remaining project routes:** auth, logs, settings, observability, functions, advisors, project-level integrations. - **Supporting edits:** hoist `EdgeFunctionsIndexPageWrapper` out of `getLayout`, `functions/secrets`, and move `DefaultLayout` to the root for the logs page. - `routeTree.gen.ts` regenerated for the full set. ## Verification On top of S1–5.1: `studio` typecheck ✓, lint (0 errors) ✓, **Next build ✓ (181/181 pages)**. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Reorganized internal routing and page structure to improve navigation and maintainability across project settings, logs, functions, authentication, integrations, and observability sections. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
46b31eb53a |
[FE-3379] feat(studio): warn when db passwords need percent-encoding (#47564)
Users who set a database password with special characters (\`@\`, \`#\`, \`%\`, \`+\`, etc.) get no warning that it must be percent-encoded when used in a connection URL, which leads to confusing connection failures ([FE-3379](https://linear.app/supabase/issue/FE-3379)). <img width="700" height="200" alt="Screenshot 2026-07-03 at 6 26 43 PM" src="https://github.com/user-attachments/assets/48608d65-8057-4abe-96fc-c0ede3550951" /> <img width="1002" height="395" alt="Screenshot 2026-07-03 at 6 27 14 PM" src="https://github.com/user-attachments/assets/1366b985-7d80-4e7d-97f0-c79d5c84cefd" /> <img width="548" height="303" alt="Screenshot 2026-07-03 at 6 27 26 PM" src="https://github.com/user-attachments/assets/b042101a-0e88-4730-adb8-1b490018f208" /> **Changed:** - `PasswordStrengthBar` now shows a warning-colored callout (with a docs link) whenever the entered password contains characters that need percent-encoding — this covers project creation, reset database password, restore-to-new-project, and the Vercel deploy-button flow - Replaced `DATABASE_PASSWORD_REGEX` (only caught `@`, `:`, `/`) with a `passwordNeedsPercentEncoding()` helper based on `encodeURIComponent`, so `#`, `%`, `+`, `?`, `&`, spaces etc. are caught too - Moved `SpecialSymbolsCallout` from `ProjectCreation/` to `components/ui/` since it's now shared **Added:** - Info admonition in the Connect sheet next to connection strings that still contain `[YOUR-PASSWORD]` (direct connection + `.env`-based file setups; hidden for psql and .NET where percent-encoding doesn't apply, and after a password reset since the substituted password is already encoded) ## To test - Project creation → type a password containing \`#\` or \`@\` → warning callout appears above the strength bar; disappears for alphanumeric passwords - Database Settings → Reset database password → same behaviour - Connect sheet → Direct connection → note shows under the connection string for URI/JDBC types, not for psql; after resetting the password from the sheet, the note disappears (password is substituted already encoded) - Connect sheet → Node.js/Python/Go/SQLAlchemy file setups show the note; .NET does not - \`pnpm vitest run lib/password-strength.test.ts\` passes <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit * **New Features** * Added a dedicated password encoding note (with documentation link) on direct connection screens when the password is embedded in a URL. * Added an encoding hint to the password strength area when percent-encoding is required. * **Bug Fixes** * Removed regex-based “invalid password” callout and replaced it with safer percent-encoding detection logic. * **Tests** * Added test coverage for `passwordNeedsPercentEncoding`. * Removed obsolete Project Creation password regex tests. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
7d3f72ec7d |
feat(studio): TanStack project routes — data surfaces (stack 5.1/6, from #46424) (#47117)
**Stack 5.1/6** of the TanStack Start migration (#46424). The original S5 (174 files) was over CodeRabbit's 150-file review cap, so it's split into 5.1 + 5.2 by product. Stacked on **#47113** (S4). > [!NOTE] > Thin route wrappers rendering the existing pages-router components via compat shims. Next-safe (full Next build run). The TanStack app isn't functional end-to-end until 5.2 + the matrix flip. ## What's in this PR - **Data-cluster project routes:** database, editor, sql, storage, realtime, branches. - **Top-level / onboarding routes:** `authorize`, `join`, `logout`, `redeem`, `verify-email`, `claim-project`, aws-marketplace, Vercel/GitHub integration entrypoints; `_app`/`_auth` layout shells; `/org/_` + `/project/_` catch-alls. - **Supporting edits:** hoist `BranchesPageWrapper` out of `getLayout`, `ConnectStepsSection` `import.meta.glob`, `api/server.js`. - `routeTree.gen.ts` regenerated for the routes present so far. ## Verification On top of S1–S4: `studio` typecheck ✓, lint (0 errors) ✓, **Next build ✓ (181/181 pages)**. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Restructured application routing infrastructure for improved code organization and maintainability. * Extracted and refactored layout wrapper components for enhanced reusability across different sections of the application. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
a4820de066 |
chore(studio): remove unused ExternalLinkIcon from DatabaseMenu.utils (#47486)
Removes a dead `ExternalLinkIcon` constant and its now-orphaned `ArrowUpRight` import that were breaking the build with a TS6133 (declared but never read) error. **Removed:** - `ExternalLinkIcon` constant and the `ArrowUpRight` lucide import (unused) ## To test - `pnpm typecheck --filter=studio` passes - Database menu still renders normally <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Removed an unused icon import and a redundant internal constant. * No user-facing behavior or menu options changed. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
2f90228f04 |
feat(studio): port API handlers to TanStack server routes (stack 4/6, from #46424) (#47113)
**Stack 4/6** of the TanStack Start migration (#46424). Stacked on **#47112** (S3). > [!NOTE] > Mechanical and homogeneous — every file is the same shape: a `createFileRoute(...)` whose `server.handlers` delegate to the existing `pages/api` handler via `toWebHandler` (the compat shim from S2). The pages-router handlers are unchanged; Next still serves them directly and ignores `routes/`. ## What's in this PR - `routes/api/**` (~104 files): platform (`pg-meta`, auth, storage, integrations, profile, telemetry, organizations, projects…), `ai/*`, `v1/*`, `connect`, `content`/`mcp`, and standalone endpoints (`deployment-mode`, `get-ip-address`, etc.). - `routeTree.gen.ts` — **regenerated** for the routes present so far (root + auth/app + api). ## Review tip The route files are near-identical wrappers, so this is fast to skim. The generated `routeTree.gen.ts` isn't meaningful review surface. ## Verification On top of S1–S3: `studio` typecheck ✓, lint (0 errors) ✓. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Model Context Protocol (MCP) API endpoint with configurable feature support and read-only mode * Added function artifact streaming capability for self-hosted functions * **Chores** * Migrated API route infrastructure for improved system architecture <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
3d931aceb7 |
feat(studio): TanStack app shell — root + auth/org routes (stack 3/6, from #46424) (#47112)
**Stack 3/6** of the TanStack Start migration (#46424). Stacked on **#47110** (S2) → review that first; this PR's diff is the app shell. > [!NOTE] > Thin route wrappers that render the existing pages-router page components through the compat shims (S2). Next is untouched — it builds `pages/` and ignores `routes/`. The app doesn't function end-to-end on TanStack until the API + project routes land (S4/S5) and the flag is flipped. ## What's in this PR - `routes/__root.tsx` — root layout + a `beforeLoad` that runs the shared redirect rules; `router.tsx`. - `routes/_auth/*` — sign-in/up, forgot/reset password, SSO/MFA/partner sign-in, CLI login, Stripe-projects login. - `routes/_app/*` — account (me/security/audit/tokens), `org/$slug/*` (general/billing/team/usage/…), support. - `routeTree.gen.ts` — **regenerated** by the tanstackStart vite plugin for exactly the routes in this PR (the migration branch's tree references all ~300 routes, so it can't be copied verbatim here). It's a generated artifact; the meaningful review surface is the route files. ## Verification On top of S1+S2: `studio` typecheck ✓, lint (0 errors) ✓. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Enhanced internal routing infrastructure to improve application performance and code organization. These behind-the-scenes updates ensure a more stable and maintainable foundation for the platform without affecting existing functionality or user experience. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
4fa106e53c |
fix(studio): stop GraphiQL from corrupting other Monaco editors (#47363)
GraphiQL (`@graphiql/react`) runs a second Monaco instance that injects
two global, page-wide styles which corrupt Studio's other editors once a
GraphiQL chunk has loaded (it persists across client-side navigation, so
a full reload hides it). After visiting GraphiQL and returning to e.g.
the SQL editor, the editor collapses to a ~5px sliver and its syntax
colors swap to GraphiQL's theme.
**Changed:**
- `monaco.css` — a higher-specificity counter-rule
(`.monaco-editor.monaco-editor { position: relative !important }`) beats
GraphiQL's runtime-injected `.monaco-editor { position: absolute
!important }`, which otherwise pulls Studio's `@monaco-editor/react`
wrapper out of flow and collapses it to ~5px.
- GraphiQL now uses the primary `supabase` Monaco theme instead of a
separate `supabase-graphql-*` theme, so the global `.mtk*` token palette
stays identical and syntax colors no longer bleed into other editors.
**Added:**
- E2E test (`monaco-graphiql-coexistence.spec.ts`) reproducing both bugs
via client-side SQL editor → GraphiQL → SQL editor navigation (a full
reload unloads the chunk and hides the bug).
- Component test (`CodeEditor.test.tsx`) guarding the height-class
precedence regression from #47339/#47350 — a caller height (e.g. the
email template editor's `h-96`) must win over the default `h-full`.
Covered as a component test since the email source editor isn't
reachable on self-hosted.
## To test
- Open the SQL editor → **Integrations → GraphiQL** → back to the SQL
editor (in-app navigation, not a reload). It should stay full height and
keep its own syntax colors.
- Confirm autocomplete still works in the SQL editor.
- `pnpm --prefix e2e/studio run e2e --
features/monaco-graphiql-coexistence.spec.ts`
- `pnpm --prefix apps/studio test -- CodeEditor.test`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved Monaco editor styling so GraphiQL no longer affects the SQL
editor’s theme or layout when navigating between them.
* Fixed editor sizing so a custom height now takes precedence over the
default full-height setting.
* Polished GraphiQL panel styling for more consistent spacing and
appearance across themes.
* **New Features**
* GraphiQL now uses the shared editor theme for better visual
consistency with Studio.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
|
||
|
|
4f80bb70cd |
fix(studio): prevent Monaco editor collapse after visiting GraphiQL (#47339)
Fixes a pre-existing bug where visiting **GraphiQL** leaves the **SQL editor** (and other Monaco editors) collapsed to a ~5px slit with the background spilling over it, until a full navigation away. ## Root cause GraphiQL (`@graphiql/react`) and the rest of Studio's editors (`@monaco-editor/react`) share one global Monaco instance. Visiting GraphiQL does `import 'graphiql/style.css'`, which injects a **second copy of Monaco's CSS** globally and persists for the session. `CodeEditor` hard-codes a `monaco-editor` class onto the `@monaco-editor/react` **wrapper** div (it's not a real Monaco editor — Monaco creates its own `.monaco-editor` inside it). That makes the wrapper subject to global `.monaco-editor` rules. After GraphiQL's CSS loads, the wrapper flips from `position: relative` to `position: absolute`, drops out of the flex flow, and collapses to `height: 0`. Monaco then lays out against a 0-height container → ~5px editor, and the full-size gutter/background layers spill over the area. Confirmed by inspecting the same wrapper before vs after a GraphiQL visit — identical inline styles, but `position` flips `relative` → `absolute` and height `266px` → `0`. ## Fix Add `h-full` to the wrapper so it fills its (full-height) section even when it's `position: absolute`, instead of collapsing to 0. Monaco then measures the correct height. In the normal `relative` state this is identical to the existing flex-stretch behavior. This is the contained fix. The deeper fix is isolating GraphiQL's Monaco from the shared instance (so it can't inject CSS / mutate global state affecting other editors) — larger, worth a follow-up. ## To test - Open the SQL editor (renders fine). - Go to Integrations → GraphiQL, then back to the SQL editor. - Editor should be full height and fully visible (previously a ~5px slit covered by the background). - Sanity-check other editors that use `CodeEditor` (e.g. RLS policy editor, function editor) still render at the right height. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved the code editor’s sizing so it keeps its full height during navigation and no longer collapses to a near-zero display in some cases. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
5c0b627904 |
fix(studio): fix GraphiQL editor layout, gutter bleed and spacing (#47334)
Fixes three GraphiQL/integrations layout issues introduced by the Marketplace layout change (#45856), which dropped the height passthrough on the integration page content wrapper. **Changed:** - **Full-height integration pages** — the content wrapper had no height, so GraphiQL's `h-full` editor collapsed instead of filling the page. Added `flex-1 min-h-0` to the wrapper in both the legacy (`LegacyIntegrationPage`) and marketplace (`MarketplaceDetail`) render paths. - **GraphiQL gutter bleed** — Monaco's `.overflow-guard` was ending up `overflow: visible` (an inline style Monaco sets at runtime), so the oversized opaque line-number gutter escaped the editor and painted over the page above it. Re-asserted the clip, scoped to GraphiQL so the SQL editor is untouched. - **GraphiQL editor spacing** — removed GraphiQL's default 16px query-editor padding so the scroll shadow sits flush, and restored the content's breathing room via Monaco's own `padding` (top/bottom) and `glyphMargin` (line-number left inset) options, which leave the scroll shadow pinned to the top edge. Before: <img width="2056" height="814" alt="Screenshot 2026-06-26 at 5 27 24 PM" src="https://github.com/user-attachments/assets/573856bf-2bfb-4bf2-9dd7-59c29b423ec9" /> ## To test - Open a project → **Integrations → GraphiQL** (the `graphiql` tab). The editor should fill the full page height. - Scroll the query editor — the scroll shadow should sit flush at the top edge, not float inset, and the white gutter should not bleed over the page header above. - Confirm line numbers have left padding and content has top/bottom padding. - Trigger autocomplete in the editor — the suggestion popup should still appear (not clipped by the gutter `overflow: hidden`). - Toggle the **Marketplace** feature preview (Account dropdown → Feature Previews) and re-check the GraphiQL page in both states, since it renders through two different page components. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved the GraphQL in-browser editor layout to prevent the editor gutter from overlapping surrounding content. * Removed unnecessary query-editor padding so scrolling and shadow effects display correctly in the available space. * Ensured Monaco editor spacing/settings are applied consistently to both existing and newly created editors. * Fixed full-height sizing for integration pages so content stays correctly constrained and doesn’t collapse or overflow. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
7b5e976c9f |
chore: manage CodeRabbit config in .coderabbit.yaml (#47328)
Sets up `.coderabbit.yaml` so our CodeRabbit configuration lives in the repo — version-controlled, visible to contributors, and reviewable — instead of split between the dashboard and nowhere. Three parts: 1. **Skills as code guidelines** — wires our `.claude/skills/` into reviews. 2. **Path instructions** — migrates the telemetry rules out of the CodeRabbit dashboard UI. 3. **Path filters** — skips machine-generated files so reviews focus on hand-written code. Supersedes #47327 (closed). ## 1. Skills as review guidelines CodeRabbit's code-guidelines feature reads guideline files and, by default, **directory-scopes** them — a file applies only to its own folder and below. Our skills live in `.claude/skills/` (no code), so they'd never reach `apps/studio`. The `applyTo` field on `filePatterns` decouples *where the guideline lives* from *which code it governs*, so we point CodeRabbit straight at the skills: | Skills | Apply to | | --- | --- | | `studio-best-practices`, `studio-ui-patterns`, `vercel-composition-patterns`, `studio-queries`, `studio-error-handling` | `apps/studio/**/*.{ts,tsx}` | | `studio-testing`, `studio-mock-api-tests` | `apps/studio/**/*.test.{ts,tsx}` | | `studio-e2e-tests` | `e2e/studio/**/*.spec.ts` | Skills stay the **single source of truth** — consumed directly, no duplicated/generated copy. ## 2. Path instructions (migrated from the dashboard) Moved the two existing telemetry path instructions into the file so they're version-controlled: - `packages/common/telemetry-constants.ts` — event-naming enforcement (`[object]_[verb]` snake_case, approved verb list, camelCase props, `useSendEventMutation` flag, JSDoc + union-type checks). - `apps/studio/components/**/*.tsx` — only suggest PostHog tracking for growth-relevant interactions, not passive/UI-only ones. ## 3. Path filters (skip generated files) Excludes machine-generated / vendored paths from review (mirrors `.prettierignore`): API types, generated DB types, route trees, design-system / icons / ui-library registries, generated icon components, and the lockfile. Keeps reviews focused on hand-written code and preserves OSS rate-limit budget on large codegen diffs. ## Notes - Cost is \$0 — CodeRabbit Pro (incl. code guidelines) is free for public repos. - `vitest` skill left out (generic framework reference, not our conventions). - The `telemetry-standards` skill is intentionally **not** also wired as a guideline — the migrated path instruction above is the curated version; wiring both would double up. ## To test - PR touching `apps/studio/**/*.tsx` → CodeRabbit cites Studio conventions - PR touching `e2e/studio/**/*.spec.ts` → cites E2E conventions - PR editing `telemetry-constants.ts` with a bad verb / non-camelCase prop → flagged - PR that regenerates e.g. `packages/api-types/types/**` → those files not reviewed - Confirm Studio guidelines don't bleed into unrelated areas (docs, www) ## Follow-ups (not here) - Extend `filePatterns` to other scopes: `dev-toolbar-review` → `packages/dev-tools/**` - Optionally skip bot PRs via `auto_review.ignore_title_keywords` - Move any remaining dashboard settings into this file as we find them <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Added/updated automated review configuration to disable org-level inheritance and enable automatic issue enrichment. * Excluded generated/vendor artifacts (e.g., lockfiles, API/type outputs, generated docs/www, UI registry/icon sources) from review. * Added path-scoped review guidance for telemetry event naming/verification and tighter review focus for production UI event-tracking suggestions. * Extended internal coding guidelines to apply local skill docs across Studio source, unit/component tests, and Studio Playwright E2E specs. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
072add9945 |
[FE-3682] feat(studio): warn on Vercel preview/dev env var sync (#47298)
Clarifies what the Vercel environment-variable sync toggles actually do and guards the risky path. Enabling Preview/Development sync pushes this project's **production** credentials into those Vercel environments — previously this wasn't clear, so users expected isolated preview deployments and were surprised when previews hit production. Addresses **FE-3682** (support case SU-385292). **Changed:** - Reworded the sync section: a single heading + intro that makes clear the toggles sync this project's production credentials to the selected Vercel environments, and that most projects only need `production`. - Recommend Branching for preview isolation, linking to the in-dashboard branches page (`/project/<ref>/branches`) instead of docs. - Switched the toggle rows to `FormItemLayout` (`flex-row-reverse`) for consistent layout/spacing; descriptions now clarify these are the **Vercel** environments. **Added:** - Inline `Admonition` warning when Preview/Development sync is enabled, with branching-aware copy (a "Not recommended with Branching" variant when Branching is on, explaining production creds are used until a branch finishes provisioning). - Confirmation dialog before saving whenever Preview/Development sync is on, naming exactly which credentials get exposed (project ref, API URL, anon + service role keys, DB connection strings). Production-only saves skip the dialog. ## Screenshots <img width="707" height="630" alt="Screenshot 2026-06-25 at 6 43 23 PM" src="https://github.com/user-attachments/assets/30d45527-5a48-44c2-bdb7-2e576f5e4c7d" /> **Default state (production only)** <img width="704" height="786" alt="Screenshot 2026-06-25 at 6 43 46 PM" src="https://github.com/user-attachments/assets/75a12f65-99d0-4aad-9360-a7a6e6c91ca1" /> **Preview + Development enabled — inline warning (no Branching)** <img width="535" height="373" alt="Screenshot 2026-06-25 at 6 44 18 PM" src="https://github.com/user-attachments/assets/29d75804-fa93-402b-8cee-1faedd0ac9c7" /> **Confirmation dialog (no Branching)** <img width="705" height="824" alt="Screenshot 2026-06-25 at 6 48 09 PM" src="https://github.com/user-attachments/assets/c3f7bf97-7c6e-4be4-9a5b-90d422b03f81" /> **Inline warning — Branching enabled** <img width="530" height="415" alt="Screenshot 2026-06-25 at 6 48 20 PM" src="https://github.com/user-attachments/assets/a5ede69e-6186-488e-bf1e-49007b231201" /> **Confirmation dialog — Branching enabled** ## To test - Open a project's **Integrations → Vercel** settings with a connected Vercel project (the project-scoped connection form). - Toggle **Preview** and/or **Development** on → inline warning appears; toggle both off → it disappears. - On a project with **Branching enabled**, confirm the warning shows the "Not recommended with Branching" variant. - Click **Save** with Preview/Dev on → confirmation dialog appears naming the credentials. **Cancel** aborts (no save), **Sync credentials** saves. - Save with **only Production** on → no dialog, saves directly. - Confirm the **Branching** links navigate to `/project/<ref>/branches`. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a confirmation step before syncing Preview or Development environment variables. * Improved the sync settings UI with clearer descriptions and a warning message when these environments are enabled. * Made the sync flow aware of project branching status, with guidance that adapts to the project setup. * **Bug Fixes** * Improved the save flow so successful updates now reset the form, close the dialog, and show a success message consistently. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
6946ec2b2d |
build(studio): Next-compat shims (stack 2/6, from #46424) (#47110)
**Stack 2/6** of the TanStack Start migration (#46424). Stacked on **#47107** (S1) — review that first; this PR's diff is just the compat shims. > [!NOTE] > Purely additive. Next never imports these files — under TanStack they're wired in via Vite aliases (`next/*` → `@/compat/next/*`). No routes consume them yet (that begins in stack 3). ## What's in this PR `apps/studio/compat/next/*` — drop-in shims so the existing pages-router code runs unchanged under TanStack Start: - `link`, `router`, `navigation`, `head`, `image`, `legacy/image`, `script`, `dynamic`, `server`, `_router-events` — React/runtime shims over `@tanstack/react-router`. - `api.ts` — `toWebHandler`, which adapts a pages-router API handler `(req, res)` into a TanStack server-route Web `fetch` handler. ## Verification On top of S1: `studio` typecheck ✓, lint (0 errors) ✓. Next build is unaffected (nothing imports these under tsc). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added broad Next.js compatibility support for routing, links, dynamic imports, images, scripts, head metadata, navigation hooks, server responses, and API handlers. * Improved handling of redirects, pathname/search params, base paths, and event callbacks for smoother app behavior. * **Tests** * Added coverage for URL resolution and dynamic route interpolation to verify Next-style routing behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
9eab4f8fbf |
build(studio): Vite/TanStack-Start build pipeline behind flag (stack 1/6, from #46424) (#47107)
**Stack 1/6** of the TanStack Start migration (#46424), split into reviewable, independently-mergeable PRs. > [!IMPORTANT] > **Next stays the default and only active framework after this PR.** This wires up the Vite/TanStack-Start build pipeline behind the `STUDIO_FRAMEWORK` flag, but there are no TanStack routes yet — so the TanStack build isn't functional or tested until later PRs in the stack. Nothing about the Next build, dev, or deploy changes behaviourally here. ## What's in this PR - **Dispatch:** `dev`/`build`/`start` now go through `scripts/dispatch.js`, which runs the Next variant unless `STUDIO_FRAMEWORK=tanstack`. The original commands are preserved as `dev:next`/`build:next`/`start:next`. - **Build pipeline:** `vite.config.ts`, `serve.js`, `smoke-server.mjs`, vite/tanstack deps, `turbo.jsonc`. - **`tsconfig.json`:** `jsx: react-jsx`, `moduleResolution: Bundler`, `target: ES2022`. Because `include` is `**/*.ts(x)`, this re-typechecks the whole app, so the companion adaptations below land with it. - **Shared adaptations (companions to the tsconfig change):** `BufferSource` casts, `packages/ui` unused-`React` import removals, etc. - **Routing/middleware plumbing:** `next.config.ts` + `redirects.shared.ts` (redirect rules now shared with `vercel.ts`), `proxy.ts`/`start.ts` middleware + `hosted-api-allowlist.ts`. ## Verification Run locally off `master`: frozen install ✓, `studio` typecheck ✓, **Next build ✓** (compiles + generates all routes), lint ratchet ✓ ("some rules improved"), prettier ✓. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a hosted API endpoint allowlist to return 404 for non-supported `/api/*` routes. * Introduced a TanStack route-migration checklist and expanded TanStack Start routing support. * **Improvements** * Enhanced deployment refresh/detection by tightening cookie handling for “latest deployment” updates. * Centralized redirect/maintenance-mode rules for consistent platform vs self-hosted behavior. * Improved production serving with a dedicated static + proxy server and a post-build smoke test. * **Dependencies** * Updated TanStack-related packages and React Table/query tooling versions. * **Documentation / Chores** * Updated formatting and tooling config; added shared build environment parsing utilities. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
e81c714aae |
refactor(studio): lazy self-hosted admin client + enforce in API routes (from #46424) (#47104)
Extracted from the TanStack Start migration (#46424) to shrink that PR. The self-hosted storage/auth API routes each constructed a module-scope admin client (`createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_SERVICE_KEY!)`). Those env vars only exist on self-hosted, so eager module-scope construction is wasteful on platform and fragile on any runtime that evaluates an API module before its route is hit (constructing with `undefined` credentials throws on import). **Changed:** - Add `lib/api/self-hosted-admin.ts` — `selfHostedSupabaseAdmin`, a `Proxy` that defers `createClient(...)` until first property access (inside a handler, i.e. on self-hosted where the vars are set). - Swap **all 17** storage/auth/vector-bucket handlers from module-scope `createClient(...)` to `import { selfHostedSupabaseAdmin as supabase }`. - **Enforce it:** add an eslint `no-restricted-syntax` rule banning module-scope `createClient` in `pages/api/**` + `routes/**` (now that every flagged handler is lazy). The same eslint config block also carries an analytics-SQL boundary rule — 0 violations on master. Behaviour is unchanged (the client is still built lazily inside the handler). This is also the change that makes those routes safe under TanStack's single-handler module evaluation. ## To test - Self-hosted Studio: storage buckets/objects, vector buckets, and auth users operations work as before. ## Verification studio lint (0 errors, both rules active) ✓ · studio typecheck ✓. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Standardized self-hosted Supabase admin client usage across platform authentication and storage endpoints, removing per-route client setup. * Improved reliability by lazily creating the admin client only when first used. * **Chores / Tooling** * Updated ESLint rules to prevent module-scope Supabase client creation in API routes and to enforce safe analytics SQL access patterns. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Ali Waseem <waseema393@gmail.com> |
||
|
|
2fdb59a905 |
test(e2e/studio): drop racy post-action waits in database specs (from #46424) (#47106)
Follow-up to #47077, extracted from the TanStack Start migration (#46424). Three `waitForResponse` waits in `database.spec.ts` were registered *after* their triggering action, so the response could resolve before the listener attached and the wait would time out (this surfaced under TanStack, where the data is SSR-streamed, but the waits are redundant on Next too). **Removed:** - Schema Visualizer *actions*: `waitForSchemaVisualizerToLoad(...'auth')` registered after the schema-selector click — the `focusTableInVisualizer` loop immediately below already auto-waits for the auth schema's tables. - table update / duplicate: `waitForDatabaseToLoad(...)` after the save mutation — the `toBeVisible` assertion right after each already waits for the list to refetch. - the now-unused `waitForDatabaseToLoad` / `waitForSchemaVisualizerToLoad` imports. The UI assertions are the real synchronization points, so behaviour is unchanged on Next. ## To test - Studio E2E `database.spec.ts` passes (the Schema Visualizer + Tables groups). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Improved database e2e test reliability by optimizing synchronization logic and eliminating timing-sensitive helpers that could introduce flakiness during schema and table operations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
ba00a311db |
test(studio): harden flaky E2E specs (extracted from #46424) (#47077)
Pulls the framework-agnostic E2E test fixes out of the TanStack Start migration PR (#46424) so they can land on `master` independently and scope that PR down. Test files only — no app/source changes. > [!NOTE] > **These changes originate from #46424** (the Next.js → TanStack Start migration). They were made while getting the E2E suite green on both builds, but they're pure test-file changes that are framework-agnostic and already pass on the current Next.js build. A few are *also* written to tolerate TanStack behaviour (called out in code comments) — harmless and correct on Next today. **Changed:** - `realtime-inspector.spec.ts` — drop the racy `waitForResponse(/settings/)` (the "Join a channel" UI assertion already gates on settings loading); click the message row's timestamp instead of its center, which the wide untruncated-JSON cell pushes under the always-present detail panel. - `database.spec.ts` — gate the three Schema Visualizer / Tables tests on the visualizer UI (`focusTableInVisualizer` already auto-waits for the schema, including the freshly-created table) instead of the `pg-meta … public-infinite_tables` XHR. - `database-webhooks.spec.ts` — wait on the `Database Webhooks` heading instead of marketing copy that was removed when the page moved to the new integrations UI. - `queue-integration.spec.ts` — wait on the unconditional "Create queue" button instead of the grid (which only renders once a queue exists); assert creation by polling for either valid end-state. ## To test - Run the affected specs against a local self-hosted studio and confirm they pass: `pnpm --prefix e2e/studio run e2e -- features/realtime-inspector.spec.ts features/database.spec.ts features/database-webhooks.spec.ts features/queue-integration.spec.ts` - Or just let the studio E2E suite run on this PR (Next.js build). Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
446398bd28 |
fix(studio): remove default DataGrid borders in table editor (#46633)
Follow-up to #46448, which removed the doubled DataGrid borders across Studio. The table editor grid had the same doubled border at the bottom, but unlike the other grids it still needs a top border — and that top border was rendering in react-data-grid's own `--rdg-border-color` rather than the studio default. **Changed:** - Removed the doubled bottom border on the table editor `<DataGrid>` (`border-b-0!`) - Forced the top border to the default border color via the `border-t-default!` token (≈ rgb(46,46,46) / `--border-default`) instead of leaning on react-data-grid's `--rdg-border-color` ## To test - Open the table editor for any table (`/project/[ref]/editor/[id]`) - Confirm there's a single top border between the filter/sort toolbar and the grid header, in the standard border color - Confirm there's no extra line at the bottom of the grid <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Style** * Refined grid visuals and spacing to improve alignment and visual consistency across the app. Adjustments to border and growth behavior reduce border inconsistencies and layout jitter during resizing. Context menu display behavior remains intact, ensuring expected right-click interactions continue to work smoothly for users. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
ea695fdfa9 |
[FE-3496] feat(studio): hide unexposed tables from Data API docs (#46508)
The autogenerated Data API docs listed every table and database function from the PostgREST OpenAPI spec, even ones that aren't actually accessible via the Data API (i.e. with grants revoked). This filters the docs down to only the entities that are exposed, and surfaces a count of the excluded ones with a link to enable them. This applies to **both** autogenerated docs surfaces: - the **API Docs side panel** (the slide-over opened from the API docs button), and - the **full-page Data API docs** at `/integrations/data_api/docs`. <img width="259" height="272" alt="Screenshot 2026-06-01 at 5 48 21 PM" src="https://github.com/user-attachments/assets/d2af86f2-5436-4e94-8295-83ecc74a77d9" /> **Changed:** - Both docs UIs now only list tables and functions that have Data API access (any `anon`/`authenticated`/`service_role` grant). Fully-revoked entities are hidden. - Side panel: both the sidebar list and the drilled-in resource picker are filtered. - Full page: the menu's Tables/Functions groups are filtered, with a footer note under each. **Added:** - A footer under each list — "N table(s)/function(s) not exposed via **Data API**" — linking to Data API settings (`/integrations/data_api/settings`) so the entity can be granted access. - One-shot `useExposedTablesQuery` / `useExposedFunctionsQuery` hooks reusing the same granted/custom/revoked SQL as the Data API settings page (no new SQL). - Pure, unit-tested `partitionExposedDocsEntities()` helper (fails open if grant status hasn't loaded / errors, so docs are never blanked). - Optional `footer` slot on `ProductMenuGroup` (rendered by `DocsMenu`) so the full-page menu can show the not-exposed note under a group. **Note on the "all" queries:** the new `useExposedTablesQuery` / `useExposedFunctionsQuery` fetch the full grant-status list in a single request (rather than paginating like the Data API settings page does). This is deliberate — the docs sections aren't paginated and render every entity from the OpenAPI spec at once, so we need the complete status set to cross-reference against. Ideally we'd refactor the docs to be paginated in future, at which point these queries should move to a paginated approach too; until then, the one-shot "all" fetch is what matches the current (unpaginated) docs behavior. ## To test - On a project, revoke a `public` table's Data API access (Data API settings → uncheck it) - Open the **full-page** docs at `/integrations/data_api/docs`: the table should no longer appear under Tables and Views, and you should see "1 table not exposed via Data API" under that menu group - Open the **API Docs side panel** and expand Tables and Views: same behavior - Click the "Data API" link → goes to Data API settings (closes the side panel if open) - Same for a database function under Functions - Tables/functions that are still granted (or have custom/partial grants) should remain visible <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Data API docs now reflect actual exposure: tables/functions not exposed by permissions are hidden and counted. * Sections display footer indicators with counts of hidden entities and links to Data API settings. * Navigation lists and docs menu updated to show only exposed entities and the new "not exposed" cues. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
7e9badc6b8 |
chore(studio): migrate useStaticEffectEvent to React 19 useEffectEvent (#46415)
Studio is on `react@^19.2.6`, and `useEffectEvent` shipped stable in React 19.2 with the same signature as the userland polyfill. This drops the local hook in `apps/studio` and `apps/www` in favor of the built-in. **Removed:** - `apps/studio/hooks/useStaticEffectEvent.ts` - `apps/www/hooks/useStaticEffectEvent.ts` - `.claude/skills/use-static-effect-event/` — skill is obsolete **Changed:** - 26 call sites: dropped the `useStaticEffectEvent` import, added `useEffectEvent` to the existing `react` import, renamed call sites - `.claude/CLAUDE.md`: `apps/studio` row updated React 18 → React 19 - `.claude/skills/vercel-composition-patterns/SKILL.md`: removed stale "Studio uses React 18, skip these patterns" warning ## To test - `pnpm typecheck --filter=studio` — passes locally - `pnpm typecheck --filter=www` — passes locally - `grep -rn "useStaticEffectEvent"` returns nothing outside `node_modules` - Smoke-test areas that use the hook: schema visualizer edges (intersection check), spreadsheet import, sign-in/CLI login flows, side panels with unsaved-changes prompts **Out of scope:** pre-existing Tailwind lint warning on `DefaultEdge.tsx:141` (`outline` + `outline-1` conflict) — unrelated to this migration <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Internal event handling migrated to React’s built-in event hooks across the Studio app; no user-facing changes. * **Documentation** * Clarified React 19 compatibility and noted Studio now targets React 19. * Removed obsolete documentation for a deprecated internal hook. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46415?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 --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
b0d023bd04 |
fix(studio): remove default DataGrid borders across studio surfaces (#46448)
Follow-up to #46413, which fixed an unwanted top border on the Auth Users grid by upgrading `border-t-0` → `border-t-0!` so the Tailwind rule actually wins over react-data-grid's `.rdg { border: 1px solid var(--rdg-border-color); }` shorthand. The same issue exists on every other DataGrid in Studio — this applies the fix consistently. **Changed:** - `border-t-0! border-b-0!` applied to all `<DataGrid>` call sites in Studio (11 in total) Fixes this issue everywhere: <img width="609" height="223" alt="Screenshot 2026-05-28 at 3 40 02 PM" src="https://github.com/user-attachments/assets/f49d8849-dd58-4675-ade4-a2656aadb8f9" /> ## To test Spot-check that the top/bottom borders look right (no doubled border under the page chrome, no extra line at the bottom of the table) on each route below. Use any project ref for `[ref]`: - `/project/[ref]/observability/query-performance` — main grid + the WithStatements grid inside - `/project/[ref]/observability/query-insights` — both modes (explorer + triage) - `/project/[ref]/advisors/security` - `/project/[ref]/advisors/performance` - `/project/[ref]/integrations/cron/jobs` — jobs list - `/project/[ref]/integrations/cron/jobs/<jobName>` — previous runs tab - `/project/[ref]/integrations/queues/queues` — queues list - `/project/[ref]/integrations/queues/queues/<queueName>` — single queue messages - `/project/[ref]/integrations/vault/secrets` - `/project/[ref]/sql/new` — results pane at the bottom - `/project/[ref]/realtime/inspector` - `/project/[ref]/logs/explorer` — and the preview pages: `auth-logs`, `edge-logs`, `postgres-logs`, `cron-logs`, `pg-upgrade-logs`, `postgrest-logs`, `realtime-logs`, `replication-logs`, `pgcron-logs`, `storage-logs`, `edge-functions-logs`, `pooler-logs`, `dedicated-pooler-logs` - `/project/[ref]/functions/[functionSlug]/logs` and `/invocations` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Style** * Refined border styling on data grids across multiple features including integrations, query tools, and logs for improved visual consistency. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46448?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 --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
29af5308f3 |
[FE-3493] fix(studio): respect role impersonation when copying truncated rows (#46442)
Copy/export of selected rows in the Table Editor refetches full values for cells truncated in the grid (via `getCellValue`), but that refetch was bypassing role impersonation. The main grid query respects the impersonated role; the truncated-cell hydration didn't, so the copy could fetch as the service role even when "View as <role>" was active – an inconsistency, since the UI still indicates the impersonated role is in effect. Threads `roleImpersonationState` through `hydrateTruncatedRows` → `getCellValue`, and wraps the SQL in `wrapWithRoleImpersonation` (matching how `getTableRows` does it). Addresses FE-3493. **Changed:** - `getCellValue` accepts an optional `roleImpersonationState` and wraps its SQL with `wrapWithRoleImpersonation` + flags `isRoleImpersonationEnabled` on `executeSql` - `hydrateTruncatedRows` threads `roleImpersonationState` through to `getCellValue` - `Header.tsx`'s `onCopyRows` passes the in-scope `roleImpersonationState` into `hydrateTruncatedRows` ## To test 1. Open the Table Editor on a table with a row containing a large/truncated string value and a primary key 2. Enable role impersonation → "View as role" → pick any role with read access to the table 3. Select the row, then `Copy → Copy as JSON` (also try CSV / SQL) 4. The copy should succeed and contain the full (non-truncated) value 5. Inspect the SQL request – it should now be wrapped with the impersonation context, matching how the main grid query is wrapped Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
d6835c4b42 |
[FE-3483] fix(studio): redirect OAuth callback errors to /sign-in (#46414)
OAuth/SSO callback failures (e.g. GitHub returning an email that collides with gotrue's `users_email_partial_key` constraint) were stranding users on `/sign-in-mfa` with the raw error rendered under the "Two-factor authentication" heading. They now redirect to `/sign-in`, where the error surfaces above the email form under "Welcome back" and the form stays interactive so users can fall back to email/password without refreshing. Addresses FE-3483. **Changed:** - `pages/sign-in-mfa.tsx`: redirect to `/sign-in` when `auth.initialize()` returns an error, instead of stopping the loader and rendering the error on the MFA page. The error is already captured in the shared `AuthProvider` state by `gotrueClient.initialize()` before the redirect, so it survives the navigation via `useAuthError()`. - `components/interfaces/SignIn/SignInForm.tsx`: render `useAuthError()` as an inline `AlertError` above the email/password fields. Form stays interactive so users hitting the duplicate-email case can use email sign-in inline. This is the "surgical" option from the ticket — option 3 (point the OAuth callbacks at `/sign-in` directly) is still the right long-term cleanup. ## To test 1. Visit `/sign-in-mfa#error=server_error&error_description=Database+error+saving+new+user` — should redirect to `/sign-in` with the error rendered above the email form under "Welcome back". 2. Type into the email/password fields — form should be interactive (this is the part the "replace the form" alternative would have broken). 3. Hard-reload `/sign-in` — no `AlertError`, normal form. 4. Sign in with a real email/password account that has MFA enabled — `/sign-in-mfa` should load normally with the "Two-factor authentication" heading and verification form. No redirect, no `AlertError`. 5. Try `/sign-in-mfa?returnTo=%2Forganizations#error=server_error&error_description=test` — after redirect the URL should be `/sign-in?returnTo=%2Forganizations` (query preserved, hash consumed by gotrue). Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
7959948005 |
fix(studio): make useTrack stable across renders (#46412)
Follow-up to #46140 — the returned `track` function was re-created on every router change or selected project/org refetch, which made it unstable for consumers that depend on referential equality (e.g. effect deps, memoized children). **Changed:** - Read `project?.ref`, `org?.slug`, and `router.pathname` through `useLatest` so the values inside `track` stay current without being deps of the `useCallback` - Drop the deps from the `useCallback` — `track` is now stable for the lifetime of the component ## To test - Verify telemetry events still send with correct `project` / `organization` groups and `pathname` - Confirm any consumers that put `track` in `useEffect` deps no longer re-run unnecessarily on route or project changes <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Improved telemetry event tracking to capture more accurate context information at the time events are sent, ensuring data reflects current application state. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46412?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 --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
293eef83e6 |
[FE-3408] fix(studio): allow project overview stat values to grow vertically (#46370)
The Compute card's "High Availability" badge was overflowing the cell horizontally in 2-column layouts and bleeding vertically into adjacent cards when the badges wrapped onto a second line in narrow/vertical layouts. Root cause was in `SingleStat`: the value row used `h-[34px]` + `truncate` (overflow: hidden), so the inner `flex-wrap` couldn't grow the row, and the flex column lacked `min-w-0` so it couldn't shrink to its grid track. **Changed:** - `SingleStat` outer flex gets `min-w-0` so the grid item is constrained by its track - Right column swapped from `truncate` to `min-w-0 flex-1` (takes remaining space, can shrink) - Value row swapped from `h-[34px]` to `min-h-[34px]` with `py-0.5` — keeps the 34px baseline for single-line text values, but lets the row grow when badges wrap Closes [FE-3408](https://linear.app/supabase/issue/FE-3408) ## To test - Open the project overview on a project with `high_availability` enabled - At 2-column widths: the "HIGH AVAILABILITY" badge should sit fully inside the Compute card alongside the compute size badge — no clipping at the right edge - At narrow / 1-column widths: when the two badges need to wrap, the Compute card should grow vertically rather than letting the second-line badge overlap the cards above/below - Spot check the other stat cards (GitHub, Recent branch, Last migration, Last backup) — long text values should still truncate with an ellipsis as before <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Style** * Updated stat card layout and inner spacing to improve responsiveness and prevent overflow. * Improved text truncation and minimum-width behavior for stat values and labels. * Standardized spacing, truncation and color handling across activity stats for more consistent display. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46370?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 --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
3da6116b78 |
[FE-3442] fix(studio): include /rest/v1 in Data API access table URL (#46367)
The Data API Access section on the new-table panel was showing `https://<ref>.supabase.co/<table>` instead of the correct `https://<ref>.supabase.co/rest/v1/<table>`. The bug was duplicated endpoint-resolution logic in `ApiAccessToggle.tsx` that omitted `/rest/v1`. Replaced it with the existing `getApiEndpoint` utility from `DataApi.utils.ts`, which already handles this correctly (and is unit-tested). Addresses [FE-3442](https://linear.app/supabase/issue/FE-3442/data-api-access-shows-incorrect-table-url). **Changed:** - `ApiAccessToggle.tsx` now uses `getApiEndpoint` for URL construction, ensuring `/rest/v1/` is always included. ## To test 1. Open the dashboard, go to Table Editor, click "New table". 2. Scroll to the "Data API Access" section, enter a table name (e.g. `test_table`). 3. Confirm the URL shown is `https://<ref>.supabase.co/rest/v1/test_table` (not `https://<ref>.supabase.co/test_table`). 4. Try the same with a non-public schema — URL should be `.../rest/v1/<schema>.<table>`. 5. With read replicas / load balancer selected via the database selector, confirm the URL still resolves to `<replica-or-lb-host>/rest/v1/<table>`. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Optimized Data API endpoint computation in the table editor interface to improve performance and code maintainability. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46367?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 --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
b28323be98 |
fix(studio): prevent infinite render loop in new-project form (#46131)
Fixes a "Maximum update depth exceeded" infinite render loop on `/new/[slug]` introduced by #46085. The symptom showed up on the internal-only configuration dropdown, but the entire form was looping. ## Root cause The new `useEffect` that syncs `dataApiDefaultPrivileges` to the experiment-driven default had `form.formState` in its deps. `form.formState` is a react-hook-form Proxy that returns a new reference on every render, so the effect refired after every render → `setValue` → render → effect → loop. ## Fix Pull the dirty check out of the effect into a stable boolean computed during render, and drop `form.formState` from the deps. Semantics unchanged — still syncs on flag resolve, still skips when the user has touched the field. ## To test - Hard-reload `/new/[slug]` and confirm there's no "Maximum update depth exceeded" error in the console - Open the configuration dropdown (internal-only) and confirm it interacts normally - With the `data-api-revoke-on-create-default` flag off, confirm `dataApiDefaultPrivileges` defaults to `true`; with it on, defaults to `false` - Manually toggle the dataApiDefaultPrivileges field, then confirm the effect no longer overwrites your choice when the flag resolves <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed data API default privileges synchronization to prevent unnecessary updates and improve application stability during configuration changes. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46131?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 --> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
5950b6ca04 |
test(e2e/studio): stabilize flaky and TZ/OS-sensitive specs (#46039)
Backports a batch of e2e test stabilization fixes — each commit is
scoped to a single failure class and only touches `e2e/studio/` files.
**Changed:**
- **`_global.setup` — playwright-locks cleanup was dead code**: the
lock-cleanup block was at the bottom of `Global Setup`, but every branch
above it returns early — so it never ran. Tests that use
`withFileOnceSetup` (cron-jobs) would see a stale `setup.done.json`
marker from the previous run and silently skip their setup, leaving e.g.
`pg_cron` uninstalled and all 11 cron-jobs specs failing. Moved the
cleanup to before any early return.
- **filter-bar — Home key**: macOS Chromium doesn't honor a standalone
`Home` keypress inside text inputs (macOS routes "go to line start" via
`Cmd+ArrowLeft` / `Fn+ArrowLeft`). Tests that expected the cursor to
jump to position 0 silently kept the previous selection. Replaced with
`el.setSelectionRange(0, 0)` so the assertion runs against a known
cursor position on every OS.
- **filter-bar — date filters**: tests inserted rows with `CURRENT_DATE`
/ `NOW()` (postgres session TZ = UTC) and asserted with JS-local dates
from `getDateValue()`. Near midnight the two diverged and the filter
returned 0 rows. Switched the inserts to explicit `getDateValue()`
strings so insert and assert use the same calendar day.
- **queue-table-operations — `networkidle`**: Studio holds long-poll /
SSE connections (PostHog, realtime), so `page.reload({ waitUntil:
'networkidle' })` never resolves and timed out. Replaced with a targeted
`waitForTableToLoad` API waiter.
- **sql-editor — RLS smoke test**: a hard-coded table name
(`pw_rls_smoke_test`) collided across 3 parallel workers running against
the same db. Suffixed with `test.info().parallelIndex`.
- **table-editor — FK spec timeout**: `waitForApiResponseWithTimeout`
for `query?key=table-update` returns `null` on timeout (silent), then
the panel-close assertion fails. Bumped 15s → 30s to absorb
parallel-load latency.
- **table-editor / storage-helpers — URL encoding & redirect race**:
post-action URL assertions were over-specific (`%20` vs `+` encoding)
and the bucket-delete redirect could race other history updates. Relaxed
the regex to accept both encodings; asserting the row removal directly
is a more stable signal than the redirect URL.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Tests**
* Improved end-to-end determinism with explicit dates/timestamps and
stable cursor positioning
* Prevented parallel-test collisions by using unique identifiers for
resources
* Made page reloads and API waits more robust for long-lived connections
and increased timeouts
* Strengthened assertions to rely on stable UI signals instead of
transient navigation/network state
* Ensured test setup reliably cleans up temporary locks before any setup
steps run
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46039?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 -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
|
||
|
|
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>
|
||
|
|
409a38a4ea |
[FE-3145] feat(studio): use data_api_revoke_default_privileges flag (#45683)
Swap the project-creation revoke from custom `db_sql` over to the new `data_api_revoke_default_privileges` API field. Same behaviour, just delegated to the platform so non-studio flows (branches, CLI, terraform) can apply the same revoke logic — addresses [FE-3145](https://linear.app/supabase/issue/FE-3145/swap-frontend-to-use-revoke-default-privileges-flag). Backend support landed in supabase/platform#32158 and supabase/platform#32493 (FUP that decoupled the flag from `data_api_use_api_schema`). **Changed:** - `apps/studio/data/projects/project-create-mutation.ts` — accepts `dataApiRevokeDefaultPrivileges` and forwards it as `data_api_revoke_default_privileges` - `apps/studio/pages/new/[slug].tsx` — drops the inline `buildDefaultPrivilegesSql('revoke')` injection in `dbSql`, passes the flag instead - `apps/studio/pages/integrations/vercel/[slug]/deploy-button/new-project.tsx` — same swap on the Vercel deploy-button flow - `packages/api-types/types/platform.d.ts` — adds the new field to `CreateProjectBody` **Preserved:** - The `dataApiRevokeOnCreateDefault` PostHog flag still gates the default checkbox state and telemetry — only the SQL application changes - `data_api_use_api_schema: false` stays as-is — projects keep `public` + `graphql_public` exposed, no project-shape change ## To test - Project creation form (`/new/<org>`): - With PostHog flag off: "Automatically expose new tables" defaults to checked → request body has `data_api_revoke_default_privileges: false` - Manually uncheck the box → request body has `data_api_revoke_default_privileges: true`, project ends up with revoked default grants on `public` - With "Enable Data API" off → `data_api_revoke_default_privileges: false` (no point revoking when nothing's exposed) - Vercel deploy-button flow (`/integrations/vercel/<slug>/deploy-button`): - Same checkbox behaviour as above - Migration SQL from the GitHub repo still runs as `db_sql` separately <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for a dedicated `dataApiRevokeDefaultPrivileges` option during project creation. * **Refactor** * Simplified Data API privilege configuration by using a dedicated parameter instead of SQL-based management across project creation flows. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |