mirror of
https://github.com/supabase/supabase.git
synced 2026-07-19 13:56:47 -04:00
create-pull-request/patch
243 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
dc23320e43 |
Add sentry capture exception to apiWrapper (#47804)
## Context As per PR title - also adjusts the imports for files consuming `apiWrapper` to remove the default export for `apiWrapper` Have tested locally by throwing an error in one of the API routes - verified that the event shows up on Sentry <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * API errors are now captured in Sentry before returning server error responses, improving production visibility while keeping endpoint behavior the same. * **Tests** * Added coverage to confirm rejected handler executions are reported to Sentry and return the expected HTTP 500 JSON payload. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0acc0eb8b3 |
feat: Support Form - Sync AI assistant conversation to Front (#46778)
# Sync AI assistant conversation to Front ## What & why When a user submits a support ticket, an AI assistant chat opens so they get help immediately while waiting for a human agent. This PR mirrors every turn of that chat into the Front conversation the support form already created, so the support team sees the full context and Front automations (routing, emails, CSAT) can act on it. Studio holds no Front credentials — it calls the platform endpoints (see the platform PR) to do the syncing. The assistant card is gated behind the `supportAssistantFollowUp` ConfigCat flag. ## How it works 1. **Submit** — `SupportFormV3` generates a stable `threadRef` (via the `uuid` package — `crypto.randomUUID()` is `undefined` in insecure contexts like non-localhost HTTP and would throw, silently aborting the submit) and sends it on `/platform/feedback/send`. The response returns the Front `conversationId`. Both are stored on `SubmittedSupportRequest`. 2. **Open chat** — `SupportAssistantSuccessCardContent` opens a chat seeded with `supportMetadata` (`threadRef`, `frontConversationId`, subject, category, severity, …). The first message is a `<support>…</support>` XML block. 3. **First user message** — the chat is tagged `isSupportChat = true`; the `onFinish` hook fires `syncSupportChatToFront`. 4. **Subsequent turns** — each `onFinish` slices the unsynced delta, strips the XML metadata block from the seed message, and posts to the platform messages endpoint. 5. **Escalation / resolve** — the `escalate_to_human` / `resolve_support_conversation` tools (and manual **Escalate**/**Resolve** buttons in the assistant input) flip lifecycle status via `setSupportLifecycleStatus` → `syncSupportLifecycleToFront`, which calls the escalation/resolve endpoints. Front rules act on `ai_support_status`. The assistant only resolves after the user explicitly confirms the issue is fixed. ## Key design decisions - **`threadRef` as the shared key** — one UUID travels as `threadRef` on submit and as `chatId` on every sync, so all messages thread into a single Front conversation. - **`conversationId` from the form response** — passed to all sync/lifecycle calls so the platform skips lazy derivation and PATCHes custom fields directly. - **Delta-only sync** — `lastSyncedMessageCount` tracks what's been sent; the boundary is snapshotted before the async call to avoid skipping messages that arrive mid-flight. - **Server-side de-dup** — stable `external_id` (`chatId:msg.id`) means retries don't duplicate in Front. - **Fire-and-forget** — sync failures log to Sentry, never break the chat; `isSyncing` resets on rehydration so the next `onFinish` retries the same delta. Message and lifecycle syncs use separate guards (`isSyncing` / `isLifecycleSyncing`) so an in-flight message sync can't drop an escalate/resolve. - **Lifecycle queued until the conversation exists** — if a lifecycle transition is requested before the initial message sync has returned a `frontConversationId`, it's stored as `pendingLifecycleStatus` and flushed once the id is assigned, rather than dropped. - **Tools return immediately** — the lifecycle tools return a stub to the AI SDK; the real Front call happens in `onFinish`, keeping async I/O out of the tool execute path. - **XML seed stripped before sync** — only the user's actual `<message>` is sent to Front (or dropped entirely if the form already created the conversation). ## Changes | Area | File(s) | | --- | --- | | Support form state | `SupportForm.state.ts` — `threadRef` / `frontConversationId` on `SubmittedSupportRequest` | | Support form submit | `support-ticket-send.ts` — sends `threadRef`, reads `conversationId` | | Support form UI | `SupportFormV3.tsx` — generates `threadRef`, stores `conversationId` | | AI assistant state | `ai-assistant-state.tsx` — `SupportChatMetadata`, `setSupportLifecycleStatus`, `onFinish` wiring, tool handling | | Message sync | `state/ai-chat-front-sync.ts` — delta tracking, message filtering, initial vs. incremental | | API data layer | `data/feedback/ai-chat-front-sync.ts` — typed platform-client wrappers for the three conversation endpoints | | Support tools | `lib/ai/tools/support-tools.ts` — `escalate_to_human`, `resolve_support_conversation` | | Tool integration | `lib/ai/tool-filter.ts`, `tools/index.ts`, `generate-assistant-response.ts` | | Success card | `SupportAssistantSuccessCardContent.tsx` — tags chat on first engagement | | Assistant panel UI | `AIAssistant.tsx` — Escalate/Resolve buttons, disabled input on closed chats, support placeholders | <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit - **New Features** - Support chats now include “Escalate to human” and “Resolve” actions. - Support submissions can be associated with a stable Front thread via a generated `threadRef`, preserving linkage across follow-ups. - AI assistant responses and input hints adapt when support mode is active. - **Bug Fixes** - Improved support chat state management and lifecycle handling to keep conversation metadata and message history synchronized more reliably with Front. - **Chores** - Added/updated coverage to reflect the new support-chat state and syncing behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
c4c213ce3d |
feat(studio): switch dashboard assistant to remote MCP server (#47479)
## I have read the [CONTRIBUTING.md](<https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md>) file. YES ## What kind of change does this PR introduce? Feature / refactor. ## What is the current behavior? The dashboard assistant runs `@supabase/mcp-server-supabase` in-process over an in-memory transport (`lib/ai/supabase-mcp.ts`). ## What is the new behavior? The assistant connects to the **remote MCP server** over HTTP (`@ai-sdk/mcp`), forwarding the dashboard session token as a bearer. URL comes from `NEXT_PUBLIC_MCP_URL` with a local-dev fallback; platform-only, and Nimbus works via the same env var. * **Tool model unchanged:** UI-controlled `execute_sql` (with `needsApproval`) and `deploy_edge_function` still come from Studio; the allowlist (`TOOL_CATEGORY_MAP`) remains the gate keeping the remote's write tools away from the assistant (`read_only` is defense-in-depth). * **Attribution:** sends `x-source-name: supabase-studio` (+ `x-source-version`) → logged as `source_name`/`client_name`. * **Connection lifecycle:** the HTTP client is closed via the request's `AbortSignal` (tools execute later during streaming); `signal` is required on `getTools`/`getMcpTools`. * **Resilience:** a remote-MCP failure degrades to the remaining tools instead of failing the assistant. * **Drift protection:** relied-upon tools are typed against `keyof typeof supabaseMcpToolSchemas`, so a package bump that renames/removes one fails `pnpm typecheck`; a runtime check also warns if the deployed server returns fewer tools. * Adds unit tests for the above. ## Additional context * Verified end-to-end against a local remote MCP server with a dashboard token: `initialize` 200, tools listed, a tool executed, client closed cleanly. * The remote MCP (mgmt-api) already accepts dashboard session tokens (GoTrue-JWT auth path) — no backend change needed. `NEXT_PUBLIC_MCP_URL` must point at each env's `/mcp`. * `@supabase/mcp-server-supabase` is kept — still used by the self-hosted `/api/mcp` routes. Closes [AI-137](https://linear.app/supabase/issue/AI-137/switch-dashboard-assistant-to-remote-mcp) ## Rollout * **Rollout:** merges with `USE_REMOTE_MCP` off (in-process); flip it to `true` per environment (staging → prod → Nimbus) once each one's prerequisites land. * **Rollback:** unset `USE_REMOTE_MCP` and redeploy to fall back to the in-process client — no revert needed. ## Summary by CodeRabbit * **Bug Fixes** * Improved AI request handling so tool loading and generation clean up properly when a request is cancelled or the browser connection closes. * Added safer fallback behavior when remote tool loading fails, so AI features can continue with available tools instead of stopping entirely. * Updated remote tool access to use the current project reference and preserve the correct access headers. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * AI tools now connect more reliably to remote services and stop cleanly when requests end or are canceled. * Tool loading is more resilient, continuing with available tools if remote access is unavailable. * **Bug Fixes** * Improved cleanup to prevent lingering connections during SQL generation and policy workflows. * Added safer handling for remote tool changes and invalid responses. * **Tests** * Expanded automated coverage for remote tool setup, cancellation, and fallback behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
514c3aa0d0 | fix(self-hosted): type generation should respect exposed schemas (#47577) | ||
|
|
3521ff06e1 |
Joshen/fe 3778 rls tester to support insert queries (#47554)
## Context Back to working on the [RLS Tester](https://github.com/orgs/supabase/discussions/45233), slowly adding support for mutation queries. First part here will be to add support for testing `INSERT` based queries (Note that there's no changes to the sandbox stuff in this PR) ## Changes involved - If testing an `INSERT` query, we show a big warning first that the query will be ran on the actual DB - Note that we skip the warning if the sandbox is used <img width="534" height="231" alt="image" src="https://github.com/user-attachments/assets/ef75a0c9-61e4-49b0-9d78-458e8e5f7f4f" /> - If the testing as an anon user + RLS enabled <img width="601" height="386" alt="image" src="https://github.com/user-attachments/assets/b21f048d-bac1-4ddd-b84b-c231ae9f9e3e" /> - If testing as an auth-ed user + RLS enabled, but the INSERT violates RLS (conditions don't meet) <img width="604" height="489" alt="image" src="https://github.com/user-attachments/assets/41c40486-48d5-4eee-b7cd-8f993edc47be" /> - Else if testing as an auth-ed user + RLS enabled and INSERT matches RLS <img width="612" height="402" alt="image" src="https://github.com/user-attachments/assets/41854b40-b351-408b-8d23-cc5e0fa40813" /> - Minor cosmetic layout change here - Use layout horizontal - Also added the user ID below the dropdown with click to copy action for convenience <img width="615" height="528" alt="image" src="https://github.com/user-attachments/assets/b9c04395-5435-474a-b3c5-640143faa782" /> - Added inline guard againsts some conditions - Should not be able to run UPDATE or DELETE queries <img width="622" height="319" alt="image" src="https://github.com/user-attachments/assets/351af7c6-8f1e-47ae-8651-3b9b0b512490" /> - Should not be able to run multiple queries <img width="612" height="317" alt="image" src="https://github.com/user-attachments/assets/603d9a1f-1d1f-40f2-806d-93aea6b6cf8e" /> ## To test - [ ] Verify that the RLS Tester works as expected for an insert query - Against actual DB - Against sandbox (only available on staging) - [ ] Verify that inline guards are all working as expected - Let me know if there's any edge cases I might have missed! <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * RLS Tester results are now operation-aware (SELECT vs mutations), with clearer “no rows/all rows” and policy evaluation explanations. * Added copy-to-clipboard for the impersonated user ID. * Query parsing now surfaces richer context, including WHERE clause details and statement count, and SELECT-only previews. * **Bug Fixes** * Improved handling of blocked mutation queries and RLS-related error messaging. * Updated RLS Tester navigation to the correct policies page. * Refined sandbox-assisted execution flow and empty/error states. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
8a9a9948a8 | fix(studio): self-hosted folder listings return metadata only (#47403) | ||
|
|
2aa1b52234 |
feat(studio): add feature to rewrite queries DEBUG-145 (#47266)
## Problem Moving the Logs Explorer to ClickHouse means users' saved BigQuery queries no longer run. <img width="2430" height="1010" alt="CleanShot 2026-06-29 at 11 36 04@2x" src="https://github.com/user-attachments/assets/ae0ab155-7d3d-4ae9-81c3-22bf3a88cf8c" /> ## Fix Rewrite the query with AI instead of a SQL transpiler. AI handles the long tail of nested fields and dialect differences far better than a rule-based rewriter, and it needs no extra runtime dependency. - `rewriteLogsSqlWithAI` posts the current query to `/api/ai/code/complete` with `dialect: 'clickhouse'`. The endpoint skips the Postgres schema and best-practices for that dialect and uses logs-specific instructions and model so the output is ClickHouse logs SQL (FROM `logs` + `source` filter, no `unnest` joins, nested fields read from `log_attributes['...']`). - The query's `source` is detected and its real `log_attributes` keys are fetched and passed to the model, so it maps to exact paths instead of guessing. - The rewrite runs in the background and is proposed as a side-by-side accept/discard diff in the editor. The AI Assistant panel is not opened. - Entry points: a banner shown only for legacy-looking queries (dismissal persisted), and a "Fix Query" button next to Field Reference. - The Field Reference drawers discover `log_attributes` keys from real data so the listed fields match what the source actually emits. ## Dependencies Built on top of #47265 (Logs Explorer -> OTEL endpoint) — that is the base branch of this PR. Merge #47265 first. Behind `otelLegacyLogs` (off by default). Part of DEBUG-145 (split from #47087). ## How to test - Open the Logs Explorer with a BigQuery logs query (the templates have some), click "Fix Query", and confirm the diff shows valid ClickHouse SQL. Accept it and confirm the applied query runs. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added an OTEL legacy logs workflow (behind a feature flag) with an interactive banner and a “Fix Query” ClickHouse rewrite action, including an accept/discard diff review overlay. * Introduced OTEL-aware field reference rendering with dynamic discovery of `log_attributes` keys and updated OTEL source insertion behavior. * Enabled dialect-aware SQL completion for ClickHouse logs, using logs-specific instructions and output constraints. * **Bug Fixes** * Improved rewrite flow validation and handling, including log source detection and cleanup of AI-generated SQL formatting. * **Tests** * Added Vitest coverage for rewrite prompt generation, detection/classification utilities, SQL fence stripping, OTEL field mapping, and OTEL log attribute key discovery. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
7007a8e5e8 |
fix(studio): raise body size limit for saving SQL snippets (#47032)
## What kind of change does this PR introduce? Bug fix — closes #45060. ## What is the current behavior? Saving a large SQL snippet from the SQL Editor fails when the content exceeds ~1 MB. The content API route (`PUT /platform/projects/{ref}/content`) relies on Next.js's default API body-parser limit of `1mb`, so large snippets — for example a multi-thousand-line RPC — are rejected with a `413 Payload Too Large` before the handler runs, and the snippet can't be saved. ## What is the new behavior? The route now sets an explicit body size limit of `5mb`, matching the limit already used by the AI SQL endpoint (`pages/api/ai/sql/generate-v4.ts`). Large SQL snippets save successfully, and the value is consistent with existing SQL-handling routes in the app. ```ts export const config = { api: { bodyParser: { sizeLimit: '5mb', }, }, } ``` ## Additional context - Only the content route's `PUT` handler accepts the snippet body; the sibling `item/[id].ts` route doesn't take a content body, so no change is needed there. - Supersedes the stale #45101 (no activity in ~8 weeks); this version documents the rationale and aligns the limit with the existing precedent in the codebase. --- - [x] I have read the [CONTRIBUTING](https://github.com/supabase/supabase/blob/master/apps/studio/CONTRIBUTING.md) guidelines. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed an issue preventing users from uploading or processing large content, such as SQL snippets, which would previously result in rejection errors. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
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> |
||
|
|
96dfc746b7 |
fix: bump stripe sync engine package (#47105)
Bumps the Stripe Sync Engine package to version 1.0.32. Note that the package name has also changed from `stripe-experiment-sync` to `@stripe/sync-engine`. Manual tests run on preview: - [x] Install a fresh version of 1.0.32. - [x] Uninstall freshly installed version 1.0.32 - [x] Upgrade from a lower version (1.0.31 tested) - [x] Upgrade to 1.0.32 and uninstall - [x] Confirm that data is being synced |
||
|
|
1baaded0bb |
Consolidate execute-sql-query into execute-sql-mutation (#46944)
## Context Just some clean up as I was going through stuff - `useExecuteSqlQuery` is deprecated and not used at all - As such `execute-sql-query` is technically irrelevant, the more relevant file is `execute-sql-mutation` - Hence opting to consolidate `execute-sql-query` into `execute-sql-mutation` - Also removing `ExecuteSqlError` since its just re-exporting the `ResponseError` type There's a lot of file changes but its essentially just updating the importing statements across the files |
||
|
|
b28f91741f | fix(self-hosted): reveal and copy secret api key in project settings (#46592) | ||
|
|
ca9b02b5ac | feat(self-hosted): add minimal project settings (#46554) | ||
|
|
1d203f6c93 |
feat: Support CLI for Vector buckets (#46381)
## Context > [!IMPORTANT] > Will open up for review once CLI PR is merged and deployed so that it's easier to test Related PR: https://github.com/supabase/cli/pull/5230 Adding support for vector buckets for local CLI - will need to be tested locally via `pnpm run dev:studio-local` ## To test There's a bit of testing instructions in the linear ticket [here](https://linear.app/supabase/issue/FE-3474/show-vector-buckets-in-local-admin-studio) as it involves using a branch of CLI - otherwise do reach out to Fabrizio if any help might be needed, but generally: ### Local CLI You might need to manually set `isCli` to `true` in `StorageMenuV2` if the "Vectors" nav item isn't showing up on the storage UI given we're testing via `pnpm run dev:studio-local` - [x] Can create bucket - [x] Can delete bucket - [x] Can create indexes - [x] Can insert data into indexes (via FDW) - [x] Can delete indexes Known issues (that aren't directly solvable from FE end) Reach out to Fabrizio for context as we were both investigating this - PG database needs to be on 17.6 (otherwise there's no S3 vectors FDW) - Storage version needs to be on 1.59.0 ### Self-hosted (This might be tricky to actually test, but just ensure that the code satisfies this) - [x] Cannot see vector buckets ### Hosted - [x] Everything works status quo <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Vector bucket management UI and platform APIs (create/list/delete buckets & indexes) * Local S3 credentials endpoint and client-side hook for self‑hosted/CLI use * **Bug Fixes** * Improved S3 vector setup notifications and clearer error guidance for manual installation * **Refactor** * Deployment-mode gating: platform vs CLI/self‑hosted now controls feature visibility and page behavior * **Tests** * Added suites covering deployment-mode gates and vector bucket error/usage scenarios * **Chores** * Build env updated to expose local S3 credential vars <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46381?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: Ali Waseem <waseema393@gmail.com> |
||
|
|
c1b473e472 | fix: adjust connect sheet for cli and self-hosted (#46217) | ||
|
|
c1276c8e9a | feat(self-hosted): add new API keys to self-hosted Studio and MCP server (#46173) | ||
|
|
d143571586 |
feat(assistant): trace-level scorers + server-side tool execution with needsApproval (#45654)
## Motivation When Assistant runs a potentially destructive tool like `execute_sql`, it stops the LLM request and prompts for client-side approval and execution of the tool. After approval, a second request kicks off under a separate trace. This has made scoring and [Topics](https://www.braintrust.dev/blog/topics) classification challenging, as the generated `output` is split across stateless requests. The [span-level scoring](https://www.braintrust.dev/docs/evaluate/custom-code#score-spans) approach we've used thusfar (after the LLM call, we massage the result into an `output` payload that's stuck onto the root span) has been cumbersome and led to invalid scores / topics where only part of the assistant response is considered. It's also inefficient, as we're duplicating potentially large info (like the `search_docs` output) that already exists within the trace. An alternative to scoring spans is to [score traces](https://www.braintrust.dev/docs/evaluate/custom-code#score-traces). Braintrust [best practices](https://www.braintrust.dev/docs/evaluate/score-online#best-practices) advise: > Use span scope for evaluating individual operations or outputs. Use trace scope for evaluating multi-turn conversations, overall workflow completion, or when your scorer needs access to the full execution context. We've also received [direct guidance](https://supabase.slack.com/archives/C05QYJBLX89/p1777925770927149?thread_ts=1777905716.911979&cid=C05QYJBLX89) from their team to use this approach. ## Changes Migrates eval scorers from custom `AssistantEvalOutput` shape to trace-level scoring via `trace.getThread()` / `trace.getSpans()`, with thread parsing that scores the full latest Assistant turn and passes prior conversation separately where relevant. Moves `execute_sql` and `deploy_edge_function` from client-side execution after approval to AI SDK `needsApproval` + server-side `execute()`. SQL results returned to the model are gated by AI opt-in level, so row data is only included with `schema_and_log_and_data`; otherwise the tool returns the no-data-permissions sentinel. Adds `metadata.isFinalStep` to disambiguate multiple LLM requests within an "assistant" turn due to tool call requests/responses. For online evals, this means we should configure automations to only score traces with `metadata.isFinalStep = true` to ensure we're judging the complete generated response. Other minor kaizen changes: - Renamed `promptProviderOptions` to `systemProviderOptions` to clarify that this is associated with the "system" message and disambiguate from the root `providerOptions` - Adds `evals/trace-utils.ts` to handle Zod validation of the `unknown` span shapes from Braintrust, to more easily access typed inputs/output on tool spans. - Bumps AI SDK floor version `^6.0.116` → `^6.0.174` - Tweaked the "Conciseness" scorer to not unfairly dock points for the new `[called tool_name]` labels in serialized assistant response ## Verification In the studio staging build, I asked Assistant to create a todos table with 3 sample todos. I manually approved the `execute_sql` call and saw Assistant generate text before & after the call. In Braintrust I verified two traces were produced (see [filtered logs](https://www.braintrust.dev/app/supabase.io/p/Assistant/logs?v=Staging&tvt=trace&search={%22filter%22:[{%22text%22:%22metadata.environment%2520%253D%2520%27staging%27%22,%22label%22:%22metadata.environment%2520%253D%2520%27staging%27%22,%22originType%22:%22btql%22},{%22text%22:%22%2560Chat%2520ID%2560%2520%253D%2520%25221cb2ac45-e5e7-458c-9da4-3bf6863b8842%2522%22,%22label%22:%22Chat%2520ID%2520equals%25201cb2ac45-e5e7-458c-9da4-3bf6863b8842%22,%22originType%22:%22form%22}]})), the first with `metadata.isFinalStep = false` and the second with `metadata.isFinalStep = true`. In the Braintrust staging scorers, I ran the preview Completeness scorer on the second trace and verified it sees the complete Assistant response including markers for tool calls ([link to trace](https://www.braintrust.dev/app/supabase.io/p/Assistant%20(Staging%20Scorers)/trace?object_type=project_logs&object_id=b5214b62-ad1e-4929-9d5b-40b1daebe948&r=0ed0a4f8-8aff-4a34-bb1d-1df1d88a5070&s=ff9015f8-6bf7-4ab3-83a9-ca4e69e27e82)) <img width="1193" height="960" alt="CleanShot 2026-05-07 at 11 27 10@2x" src="https://github.com/user-attachments/assets/509d4858-c3a1-4068-986d-3aa4d5617d1a" /> I also tested the `deploy_edge_function` workflow and verified it still prompts for permission and warns on deployment of existing functions. **References** - https://www.braintrust.dev/docs/evaluate/custom-code#score-traces - https://ai-sdk.dev/docs/ai-sdk-core/tools-and-tool-calling#tool-execution-approval Supercedes https://github.com/supabase/supabase/pull/45556 and https://github.com/supabase/supabase/pull/45339 Closes AI-473 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Tool actions (SQL execution, edge-function deploy) now require explicit user Approve/Deny before proceeding. * **Improvements** * Assistant pauses for approval responses before sending follow-ups, giving clearer control over risky actions. * Deploy/replace flows show confirmation and clearer replace warnings. * Evaluation/scoring updated to use richer trace data for more accurate assistant performance signals. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0433eeb5f5 |
feat(studio): mark sql provenance for safety (#45336)
Mark provenance of SQL via the branded types SafeSqlFragment and UntrustedSqlFragment. Only SafeSqlFragment should be executed; UntrustedSqlFragments require some kind of implicit user approval (show on screen + user has to click something) before they are promoted to SafeSqlFragment. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Editor and RLS tester show loading states for inferred/generated SQL and include a dedicated user SQL editor for safer edits. * **Refactor** * Platform-wide SQL handling tightened: snippets and AI-generated SQL are treated as untrusted/display-only until promoted, improving safety and consistency. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5f867e5f6c |
Feature Preview: RLS Tester (#45121)
## Context Resolves FE-3077 Related discussion: https://github.com/orgs/supabase/discussions/45233 Verifying the correctness of your RLS policies set up has always been a gap, as highlighted by a number of GitHub discussions like [here](https://github.com/orgs/supabase/discussions/12269) and [here](https://github.com/orgs/supabase/discussions/14401). As such, we're piloting a dedicated UI for RLS testing (using role impersonation as the base), in which you'll be able to - Run a SQL query as a user (not logged in / logged in - this is the role impersonation part) - See which RLS policies are being evaluated as part of the query - And hopefully be able to debug which policies are not set up correctly Changes are currently set as a feature preview - and we'll iterate as we get feedback from everyone 🙂 🙏 <img width="613" height="957" alt="image" src="https://github.com/user-attachments/assets/83c37f8a-28fc-43b3-b0ff-e28571d8710c" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * RLS Tester: run queries as anon or authenticated users, view inferred SQL, per-table policy summaries, and data previews of accessible rows. * UI preview: new RLS Tester preview card and modal with opt-in toggle; RLS Tester sheet with role/user selector and query editor. * SQLEditor: “Explain” tab is always visible. * **Chores** * Added supporting API endpoints, background checks for table RLS status, and a local-storage flag to persist the preview opt-in. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
36ae9beb0c |
chore(ai): remove DPA signer killswitch for assistant tracing (#45134)
Removes the temporary killswitch added when Braintrust was onboarded as
a subprocessor, to satisfy the 30-day DPA notice obligation. The window
has elapsed and legal has cleared removal.
Drops the `orgIsDpaSigned` check from `isTracingAllowed`, removes the
extra `/platform/organizations/{slug}/documents/dpa-signed` network hop
from `getOrgAIDetails`, and cleans up all call sites and tests.
Closes AI-596
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Simplified AI tracing eligibility logic by removing DPA signing status
checks. Tracing authorization decisions now depend solely on region,
HIPAA addon status, and project sensitivity settings.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
7f5865872a |
Enforce noUnusedLocals and noUnusedParameters in tsconfig.json + fix all related issues (#45264)
## Context Enforce `noUnusedLocals` and `noUnusedParameters` in tsconfig.json + fix all related issues |
||
|
|
8f69a10cc9 |
fix(studio): reliable schema-aware SQL editor AI completions (#44730)
A variety of fixes and improvements to the Cmd+K AI completions endpoint in the [SQL Editor](https://supabase.com/dashboard/project/_/sql/new): - Pre-load table definitions for the public schema and any other schemas referenced in the editor, so the model has real column names without needing to fetch them dynamically - Replace the generic tool suite with a single streamlined `getSchemaDefinitions` tool the model can still call to look up additional schemas on demand without behavior differences across platform & self-hosted - Swap generic chat system prompt for a purpose-built `COMPLETION_PROMPT`; fix role (`assistant` → `user`) for consistency with other endpoints - Validate and type the request body with `zod`, which was previously untyped (`any`) - Improve Cmd+K behavior when nothing is selected — use the full editor content as context, return the complete query rather than just the changed fragment, and switch to a generation mode when the editor is blank - Escape single quotes in schema names when fetching entity definitions in `pg-meta` to prevent schema names from breaking out of the SQL string and injecting arbitrary content into the prompt ## Before Before, the SQL Editor would often hallucinate tables / columns that don't exist in the user's database making it less helpful if you don't know the exact table/column names. Even with maximum Assistant opt-in level on the org, it would often fail to call the necessary tools to gather database context. <img width="5062" height="1522" alt="image" src="https://github.com/user-attachments/assets/fbe1130f-6b5a-41a8-99d7-7268880af188" /> <img width="2540" height="658" alt="image" src="https://github.com/user-attachments/assets/a31c2967-7751-4fce-a9b7-60bd77660b1a" /> Sometimes it also silently fails and generates empty queries: <img width="1352" height="398" alt="CleanShot 2026-04-09 at 17 46 06@2x" src="https://github.com/user-attachments/assets/e17c103a-d47d-47e6-8c2e-101f0fae5651" /> Or echos back the user's prompt: <img width="1368" height="282" alt="CleanShot 2026-04-09 at 23 04 56@2x" src="https://github.com/user-attachments/assets/7dff6e64-f54e-45b5-8e86-5399e5a2fe41" /> ## After In this example, the completion correctly interpreted my request for "completed" todos as a query on the `completed_foo` column in my `public` schema, instead of assuming existence of a `completed` column. <img width="1452" height="838" alt="CleanShot 2026-04-09 at 17 43 13@2x" src="https://github.com/user-attachments/assets/7a575589-78b4-448d-810a-0330ff08ef8b" /> In this example, the completion was correctly aware of an `other` schema because it was detected in my existing query. I didn't have to select the text, it included the full query in context when unselected. Notice how it correctly used the `is_done` column when I asked for "completed" cakes: <img width="1372" height="534" alt="CleanShot 2026-04-09 at 17 39 07@2x" src="https://github.com/user-attachments/assets/e6b7eb6f-f3e8-4fa1-90a3-b5e34ddc14e4" /> Supersedes #44151 Closes AI-544 |
||
|
|
19027e73f8 |
[FE-3036] feat(studio): runtime env var overrides for enabled features (#45049)
Lets self-hosted Studio toggle flags in `enabled-features.json` at container start time via `ENABLED_FEATURES_*` env vars, without rebuilding the prebuilt image. Addresses [FE-3036](https://linear.app/supabase/issue/FE-3036/allow-enabled-featuresjson-flags-to-be-overridden-via-env-vars) and is a prerequisite for [COM-205](https://linear.app/supabase/issue/COM-205/add-feature-flag-to-disable-all-logs-in-studio). **Added:** - `packages/common/enabled-features/overrides.ts` — pure parser that maps `ENABLED_FEATURES_*` env vars to a disabled-features list (forward-only key mapping, boolean validation, typo warnings) + 10 vitest tests - `apps/studio/pages/api/enabled-features-overrides.ts` — Next.js API route reading `process.env` at request time; no-op (`{ disabled_features: [] }`) when `IS_PLATFORM` - `apps/studio/data/misc/enabled-features-override-query.ts` — React Query hook with `staleTime: Infinity`, `enabled: !IS_PLATFORM` - `packages/common/enabled-features/README.md` — docs the env var convention, resolution order, `IS_PLATFORM` gating, and the `Support.constants.ts` build-time caveat **Changed:** - `apps/studio/hooks/misc/useIsFeatureEnabled.ts` — merges the override's `disabled_features` with `profile.disabled_features` ### Env var shape One var per flag, prefixed `ENABLED_FEATURES_`. Feature key → env name: uppercase with every non-alphanumeric char replaced by `_`. ```bash ENABLED_FEATURES_LOGS_ALL=false ENABLED_FEATURES_BRANDING_LARGE_LOGO=true ``` Values are `true`/`false` case-insensitively. Other values and prefixed vars that don't match a known feature are logged and ignored. ### Resolution order (runtime, Studio only) 1. `ENABLED_FEATURES_*` (self-hosted, via API route → React Query → hook) 2. `profile.disabled_features` (hosted, from `/platform/profile`) 3. `enabled-features.json` static value 4. Default (enabled) `ENABLED_FEATURES_OVERRIDE_DISABLE_ALL` still short-circuits everything. ### Known limitation `apps/studio/components/interfaces/Support/Support.constants.ts:4` calls `isFeatureEnabled('billing:all')` at module load to build `CATEGORY_OPTIONS`, which is spread into Zod form schemas. That call site stays resolved from the JSON — documented in the package README. `billing:all` isn't on the radar for self-hosted runtime toggling. ## To test - `cd packages/common && pnpm exec vitest run enabled-features` — 10 new tests pass - `pnpm --filter studio run typecheck` clean - Spin Studio locally with `NEXT_PUBLIC_IS_PLATFORM=false` and `ENABLED_FEATURES_LOGS_TEMPLATES=false`; `/project/[ref]/logs/explorer/templates` should reflect the flag after the override fetch resolves - Confirm the API route returns `{ disabled_features: [] }` when `NEXT_PUBLIC_IS_PLATFORM=true` - Set a typo like `ENABLED_FEATURES_LOGS_TMEPLATES=false` and check the warning in container logs; flag stays enabled <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Runtime feature-flag overrides for self-hosted deployments (env var driven), new API endpoint and client-side hook to fetch overrides, and client logic now merges profile and runtime overrides. * **Documentation** * Added comprehensive README describing the feature-flag system and override configuration. * **Tests** * Added unit tests for override parsing and E2E tests covering runtime override behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
205cbe7d26 | chore(studio}: enforce import order, remove bare import specifiers (#44585) | ||
|
|
8aeacc6152 |
feat(assistant): disable Braintrust tracing for EU regions and DPA signers (#44504)
**Changes** - Extracted tracing conditional to an `isTracingAllowed` helper with unit tests (the function is simple but sensitive hence the extra testing precaution) - Disables Braintrust tracing for projects in EU database regions (region prefix `eu-`) to address GDPR data residency concerns - Disables Braintrust tracing for orgs whose owners have signed the previous DPA, as a stopgap during the 30-day notice period for the updated DPA that adds Braintrust as a subprocessor - Refactored `org-ai-details.ts` → `ai-details.ts`, splitting `getOrgAIDetails` into separate org and project helpers to cleanly scope the EU-region check at the project level DPA check uses the newly added `/documents/dpa-signed` endpoint from https://github.com/supabase/platform/pull/31060. This PR includes regenerated `api.d.ts` and `platform.d.ts` from running `pnpm codegen` in `packages/api-types` to get type safety on this new endpoint. Note tracing is still yet to be activated in production, this is a preparatory step. **To verify** Send a chat message and check for the `x-braintrust-span-id` response header on `POST /api/ai/sql/generate-v4` — it should be absent for DPA-signed orgs or EU-region projects, and present otherwise. <img width="3594" height="1992" alt="CleanShot 2026-04-03 at 14 28 58@2x" src="https://github.com/user-attachments/assets/4c91d7ad-2604-4531-a78e-dedf41632fa5" /> If you have access to the Braintrust dashboard, you can also verify whether logs are produced or not in the Assistant project there. Closes AI-570 Closes AI-569 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Tracks organization DPA signing and detects EU-region projects * Assistant tracing now follows a combined compliance policy (HIPAA addon, DPA, project sensitivity, region) * Added helpers to fetch org and project AI details * **Documentation** * Expanded API docs with additional examples and clarified parameter descriptions * Added response schemas for subscription preview and document status * **Tests** * Added/updated tests covering DPA/region behavior and tracing policy enforcement <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
adf8b0c67c |
feat(assistant): per-endpoint reasoningEffort + model config cleanup (#43981)
We're exploring support for newer models like [gpt-5.4-nano](https://openai.com/index/introducing-gpt-5-4-mini-and-nano/) in Assistant. This model doesn't support the `'minimal'` reasoning effort level we use for gpt-5-mini which leads to vague errors. <img width="595" height="263" alt="CleanShot 2026-03-18 at 17 13 05@2x" src="https://github.com/user-attachments/assets/cf7c2370-322d-4a8a-be55-23e680db0aa0" /> Also, we've [previously discussed](https://supabase.slack.com/archives/C0161K73J1J/p1771544464850199?thread_ts=1771493920.775699&cid=C0161K73J1J) that reasoning adds unnecessary latency to otherwise simple AI completion endpoints like `title-v2`. We want more control of reasoning level independent of model/endpoint. This PR aims to solve both problems by: - making reasoning effort configurable on a per-request basis - adding compile-time guardrails to prevent selecting an incompatible reasoning level for models - adding a `DEFAULT_COMPLETION_MODEL` with minimal reasoning that we can update with newer models that support disabling reasoning (independent of Assistant chat model reasoning) Other improvements to our model config logic: - Fixes bug in `onboarding/design.ts` and `assistant.eval.ts` where `providerOptions` was being dropped - `getModel()` now returns a bundled `modelParams` object (spread into AI SDK calls) so `providerOptions` can't be accidentally omitted (this [has happened before](https://supabase.slack.com/archives/C0161K73J1J/p1771518443534309?thread_ts=1771493920.775699&cid=C0161K73J1J)) - Introduces an `ASSISTANT_MODELS` registry as a single source of truth for assistant model config, eliminating hardcoded model IDs across the codebase - Aligns free/pro model conditional logic with `assistant.advance_model` entitlement naming conventions instead of the `isLimited` pattern - Adds `console.error` logging of Assistant stream errors so we can interpret reasoning effort compatibility errors in the future (instead of just opaque "Sorry, I'm having trouble responding right now" card) - Removes unnecessary type casts and generally making the model config logic stricter - Removes pre-existing dead code: `anthropic` provider variant in `GetModelParams` / `PROVIDERS` registry that was never implemented in `getModel()` Now if you try to select an unsupported reasoning level you get a type error: <img width="1306" height="320" alt="CleanShot 2026-03-20 at 14 37 24@2x" src="https://github.com/user-attachments/assets/a6ac234b-5ea5-4d81-8e01-ac4be34a0800" /> And if for some reason an invalid reasoning level slips through, you now get a server-side error surfacing the issue: <img width="1268" height="204" alt="CleanShot 2026-03-20 at 14 58 14@2x" src="https://github.com/user-attachments/assets/aadc1b7a-9495-475f-9741-39979bd27cd7" /> I've tested gpt-5 and gpt-5-mini are still working on the staging preview and verified the models were selected properly in Braintrust logs. Both models are available on my Pro test account, and my Free test account shows the Pro upgrade CTA. Closes AI-446 Closes AI-551 |
||
|
|
aa12ae790a |
fix: flatten AI generation schema for filters (#44092)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? OpenAI claims to support recursive schemas with $defs/$ref, but in practice it's unreliable. When Zod's z.lazy() is converted to JSON Schema, it produces recursive $ref entries that OpenAI's structured output frequently rejects with errors like "Recursive reference detected" or "Invalid schema for response_format". Simplify the AI generation schema since we only support AND and don't need the recursion because we don't support nesting of groups. |
||
|
|
d29fbf6eb7 |
feat(assistant): upgrade AI SDK v5 → v6 (#43931)
Upgrades `ai` from v5 to v6 and all related packages.
**Package bumps:**
- `ai`: `5.0.52` → `^6.0.116`
- `@ai-sdk/openai`: `2.0.32` → `^3.0.41`
- `@ai-sdk/react`: `2.0.52` → `^3.0.118`
- `@ai-sdk/provider`: `^2.0.0` → `^3.0.8`
- `@ai-sdk/provider-utils`: `^3.0.0` → `^4.0.19`
- `@ai-sdk/amazon-bedrock`: `^3.0.0` → `^4.0.81`
- `@ai-sdk/mcp`: N/A → `^1.0.25`
- `openai`: bumped to `^4.104.0`
- `braintrust`: `3.0.x` → `^3.4.0`
**Breaking change migrations:**
- `generateObject` removed in v6 — migrated 5 API routes to
`generateText` with `Output.object({ schema })`, returning
`result.output`
- `convertToModelMessages` is now async — added `await`
- MCP import path changed: `experimental_createMCPClient` from `ai` →
`createMCPClient` from `@ai-sdk/mcp`
- `openai()` defaults to Responses API — added `store: false` to
provider options for ZDR org compatibility
**Streaming fix:**
Added `Content-Encoding: none` header to `pipeUIMessageStreamToResponse`
calls. Without it, proxy middleware buffers the entire SSE response
before flushing, causing the full reply to appear at once.
**Zero Data Retention fix:**
In recent AI SDK versions, `openai()` default to Responses API instead
of the legacy chat completions API. This produces a 404 from OpenAI with
message `"Items are not persisted for Zero Data Retention organizations.
Remove this item from your input and try again."` The Responses API is
OpenAI's [recommended
endpoint](https://developers.openai.com/api/docs/guides/migrate-to-responses).
This PR adds `store: false` as mentioned in
https://github.com/vercel/ai/issues/10060 to avoid incompatible
persistence attempts.
**References:**
- https://ai-sdk.dev/docs/migration-guides/migration-guide-6-0
-
https://ai-sdk.dev/docs/troubleshooting/streaming-not-working-when-proxied
- https://github.com/vercel/ai/issues/10060
Closes AI-514
Related AI-509
|
||
|
|
fe0da16820 |
refactor: move /incident-banner to app router (#43930)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Refactor ## What is the current behavior? The `/incident-banner` endpoint is implemented using the Pages Router. ## What is the new behavior? The `/incident-banner` endpoint is moved to the App Router, enabling caching of the upstream fetch. This does not turn on the querying from the frontend yet, making that a separate PR so we can revert easily if needed. ## Additional context |
||
|
|
46a793a32d |
fix: increase timeout of stripe sync engine install (#43932)
Sets the timeout of the function performing the Stripe Sync Engine install to 5 minutes so it won't timeout when running in the background. |
||
|
|
a4641d0b9f |
refactor: move /incident-status to app router (#43881)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Refactor ## What is the current behavior? `/incident-status` is handled via Pages Router. ## What is the new behavior? `/incident-status` is handled via App Router, enabling use of Vercel Data Cache to cache the upstream fetch. ## Additional context Adding the first App Router route handler triggered `next typegen` (run as `pretypecheck`) to generate `.next/dev/types/validator.ts`, which imports all route files and expanded the type-checked graph. This surfaced pre-existing `null`-safety errors in: - `components/grid/SupabaseGrid.utils.ts` — `useSearchParams()` result - `components/layouts/ProjectLayout/UpgradingState/index.tsx` — `useSearchParams()` result - `pages/project/[ref]/sql/quickstarts.tsx` — `useParams()` result - `pages/project/[ref]/sql/templates.tsx` — `useParams()` result These are fixed with optional chaining. The `tsconfig.json` change (adding `.next/dev/types/**/*.ts` to `include`) is auto-generated by Next.js and committed as correct behavior. |
||
|
|
65237597e4 |
feat: upgrade flow and other improvements (#43289)
This PR: * Adds an upgrade flow to the stripe sync engine, allowing users to upgrade to the latest version when it becomes available. * When a new version of sync engine becomes available, users will see an upgrade button instead of install button. * Bumps `supabase-management-js` to version 2.0.2 and `stripe-experiment-sync` to version 1.0.27. * Uses `parseSchemaComment` and related logic from the `stripe-experiment-sync` package in order to avoid writing duplicate code in supabase ui. * Allows installation/uninstallation to timeout after 5 minutes to avoid these operations from getting stuck in case an error occurs in their processing. This allows users to retry the operation, as opposed to the older behaviour where the users always see a spinner on the install/uninstall button and couldn't do anything. * Remove the SSL enforcement admonition as it is no longer required. Sync engine can now be installed with or without SSL enforcement enabled. --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
62426253c3 |
fix: pass exposedSchemas to getLints in MCP advisor operations (#43790)
## Summary - MCP `getSecurityAdvisors` and `getPerformanceAdvisors` now pass `exposedSchemas` to `getLints`, fixing empty advisor results in local/self-hosted environments - Extracts `DEFAULT_EXPOSED_SCHEMAS` constant shared between the MCP handler and the `run-lints` API route (cc @joshenlim related https://github.com/supabase/supabase/pull/40043) - Adds unit tests for `enrichLintsQuery` and the MCP advisor operations ## The bug The MCP advisor tools (`get_advisors`) return empty arrays (`[]`) for **all** scenarios when running locally via `supabase start`. No security or performance advisors are surfaced, even when the database has clear issues (e.g., tables with no RLS). ### Root cause In `lib/api/self-hosted/mcp.ts`, both `getSecurityAdvisors` and `getPerformanceAdvisors` call `getLints({ headers })` **without passing `exposedSchemas`**: ```typescript // Before (mcp.ts:131) const { data, error } = await getLints({ headers }) ``` When `exposedSchemas` is `undefined`, `enrichLintsQuery` in `lints.ts` skips the `SET LOCAL pgrst.db_schemas = '...'` SQL statement: ```typescript // lints.ts:23 ${!!exposedSchemas ? `set local pgrst.db_schemas = '${exposedSchemas}';` : ''} ``` Without this GUC being set, the splinter SQL queries filter results using `current_setting('pgrst.db_schemas', 't')` — which returns an empty string in local environments. Every schema-filtered lint matches no schemas and returns zero rows. ### Why this only affects local/self-hosted environments In **hosted Supabase**, PostgREST sets the `pgrst.db_schemas` GUC on its own database connections based on the project's API configuration. The Studio MCP server in production reads the same project configuration, so the GUC is already available. **Locally**, PostgREST runs in a separate Docker container and only sets this GUC on _its own_ connections. Studio connects directly to PostgreSQL (bypassing PostgREST), so `current_setting('pgrst.db_schemas', 't')` returns `''`. The HTTP API endpoint (`/api/platform/.../run-lints`) already worked because `run-lints.ts` passes `exposedSchemas: 'public, storage'` — this parameter was simply never added to the MCP code path. ## How we verified the fix ### 1. Tests written to fail against the previous code We wrote two test files that target the exact bug: **`tests/unit/lints/enrichLintsQuery.test.ts`** — validates the SQL generation: - Confirms `SET LOCAL pgrst.db_schemas` is included when `exposedSchemas` is provided - Confirms it's omitted when `undefined` or empty (documenting current behavior) **`tests/unit/lints/mcp-advisors.test.ts`** — validates the MCP operations: - Asserts `getSecurityAdvisors` passes `exposedSchemas` to `getLints` - Asserts `getPerformanceAdvisors` passes `exposedSchemas` to `getLints` - Asserts the value matches `DEFAULT_EXPOSED_SCHEMAS` - Verifies SECURITY/PERFORMANCE category filtering still works Before the fix, the two `exposedSchemas` assertions failed: ``` FAIL getSecurityAdvisors should pass exposedSchemas to getLints → expected { Object (headers) } to have property "exposedSchemas" FAIL getPerformanceAdvisors should pass exposedSchemas to getLints → expected { Object (headers) } to have property "exposedSchemas" ``` ### 2. Fix applied, all tests pass After adding `exposedSchemas: DEFAULT_EXPOSED_SCHEMAS` to both MCP operations, all 14 tests pass (9 new + 5 existing MCP tests). ## Test plan run `supabase start`, create a table without RLS, call `get_advisors` via MCP — should return `rls_disabled_in_public` lint --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
7d1b38f804 |
Float up error code from status page into incident-status endpoint (#43737)
## Context Just a nit change to float the status code from status page API into incident-status endpoint so its clearer what the error is from the network tab --------- Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com> |
||
|
|
c5b6695380 |
fix: Remove auth from /incident-status and /incident-banner endpoints (#43751)
|
||
|
|
befc817f94 |
feat: version who-knows-what of incident banner (#43726)
Feature ## What is the current behavior? Incident banner logic depends on StatusPage and Supabase project for metadata. ## What is the new behavior? New incident banner logic that depends only on incident.io. Displays in non-production environments for now because I haven't wired up the rest of the workflow. This is just to allow a total end-to-end testing/playground for test incidents <-> Slack <-> preview dashboard for people to try out the UX. ## Additional context You can test using my [test incident](https://app.incident.io/supabase/incidents/405). This has severity minor, so the preview site should have a banner. Toggle to informative, hard refresh dashboard with cache off, and banner should disappear. Toggle back to minor, hard refresh without cache again, and banner should reappear. Same thing if you edit the "Banner shown" field from 1 to -1 and back. |
||
|
|
b7cbc11d21 | add data api page to integrations for self-hosted | ||
|
|
2541d58fb1 |
feat(studio): add /api/status-override endpoint for status page banner override (#43641)
New feature — adds a platform-only API endpoint to Studio.
## What is the current behavior?
`NEXT_PUBLIC_ONGOING_INCIDENT` is not exposed outside of the dashboard.
## What is the new behavior?
`GET /api/status-override` returns `{ enabled: boolean }` indicating
whether `NEXT_PUBLIC_ONGOING_INCIDENT` is set to `"true"`. The endpoint
returns 404 on self-hosted and is added to the proxy allowlist for
hosted platform access.
This is so that the incident banner bot can detect whether an override
is in place.
|
||
|
|
8732fc3bd9 |
fix: add multi-object download signing for storage (#43576)
Bug fix ## What is the current behavior? Read-only users cannot download files because the download feature requires minting a temporary API key, which is properly blocked for read-only users. ## What is the new behavior? Instead of using temporary API keys, we now create signed URLs for the files to be downloaded. We batch-create signed URLs for an entire folder's worth of files, requiring only a single management API call, then use those signed URLs to download the files. This allows read-only users to download files without needing elevated permissions. ## Additional context Resolves FE-2737 |
||
|
|
9b028f6fd5 |
feat(studio): map error codes to docs (#43140)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? This introduces a small snippet preview of the error code coming via our content API for the docs. This appears in a couple of places right now. - **Auth Overview** - This page isn't fully released yet, but it appears on the error codes table (as depicted below). - **Logs** - When you delve into the logs panel, if there's an error code available, they're also wrapped in this popover. We are also working on a shared-data package (#43458) to potentially replace this endpoint internally. Also introduces a multifaceted button to debug/fix with either Assistant or LLM of choice. | Auth Overview | Logs Panel | |--------|--------| | <img width="407" height="287" alt="Screenshot 2026-03-09 at 14 14 09" src="https://github.com/user-attachments/assets/7450dddb-6828-4cd3-802d-37d47ba1b440" /> | <img width="394" height="216" alt="Screenshot 2026-03-09 at 14 13 56" src="https://github.com/user-attachments/assets/80c2a46e-dbe4-4e88-a0a7-68b977a71d6b" /> | --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
6cd3857d70 |
fix: added support for is and is not null (#43404)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? - For the new filters experience, we are missing null changes for dates and also no support for isNull - Updated E2E tests to account for new null cases |
||
|
|
564f4f66ee |
Joshen/fe 2660 clean up stale feature flags enabled for 2 months part 1 (#43329)
## Context Just cleaning up feature flags that have been toggled on for all users and unchanged for the past 2 months - advisorRules - newJwtSecrets - isWorkOSTPAEnabled - EnableOAuth21 - gitlessBranching - showRefreshToast - awsPrivateLinkIntegration - useBedrockAssistant (Already not used) - enableStripeSyncEngineIntegration - ShowExplainWithAiInQueryPerformance Doing it in 2 parts so its easier for review |
||
|
|
5a01291c23 |
feat(studio): smart incident banner targeting (#43112)
Feature enhancement — smarter incident banner targeting logic ## What is the current behavior? Displaying the incident banner requires toggling a flag or environment variable. Banners are shown to all users regardless of whether their projects are in affected regions or whether the incident affects project creation. ## What is the new behavior? Banner visibility is now driven by `show_banner` metadata from the StatusPage API — no manual flag or env var toggle needed. Per-user targeting is then applied: - Users with projects only see the banner when they have a database in an affected region - Users without projects only see the banner when the incident affects project creation Incident responses are enriched with cache data (`affected_regions`, `affects_project_creation`) fetched from a Supabase table. Visibility logic is extracted into a dedicated hook and pure utility function, backed by unit tests. ## Additional context Resolves FE-2562 |
||
|
|
3fcb6cbe2c |
fix(studio): pass providerOptions to all AI SDK calls (#43031)
`reasoningEffort: 'minimal'` was [configured](https://github.com/supabase/supabase/blob/d5cc70560d/apps/studio/lib/ai/model.utils.ts#L55-L59) in the provider registry but `getModel()` returns it as a separate value that callers must destructure and forward — and 7 of 8 endpoints weren't doing so. This meant `gpt-5-mini` (a reasoning model) was running at default reasoning effort for every call. This PR destructures `providerOptions` from `getModel()` and passes it to `generateObject`/`generateText` in all affected endpoints. ## Benchmark (local, median of 5 runs) | Endpoint | Before (s) | After (s) | Speedup | |----------|-----------|----------|---------| | title-v2 | 7.0 | 1.9 | 3.7x | | cron-v2 | 2.3 | 0.9 | 2.6x | | filter-v1 | 5.8 | 2.2 | 2.6x | | feedback/classify | 3.5 | 0.9 | 3.9x | | feedback/rate | 2.9 | 0.9 | 3.2x | `code/complete` and `policy` also received the fix but aren't benchmarked here as they require a live DB connection and use multi-step tool calls (separate latency concern tracked in AI-419). To test the SQL naming, visit the SQL Editor in sidebar, add some SQL like: ```sql create table todos ( id serial primary key, task text not null, completed boolean default false ); ``` Right click on the snippet, "Rename" and "Rename with Supabase AI" Closes AI-443 |
||
|
|
3d14b5e7bf |
fix: show uninstall progress (#42860)
This PR makes the following changes: * Refactors the Stripe sync engine integration so that impossible states are unrepresentable in the code. * Factors out common code and functions into a single location to avoid duplication. * Factors out code to fetch installation/uninstallation and sync status into a separate hook to make the code more readable. * Shows uninstall progress when the user uninstalls the integration. * Moves the **Uninstall integration** button from the **Settings** page to the **Overview** page. This is done to avoid us having to track the uninstallation progress via the url query params when the user is redirected to the **Overview** page during uninstallation. Also it makes sense for installation/uninstallation to be available on the same location. Note that even with the above changes there are some limitations to how the uninstallation progress is shown. In particular, if the user refreshes the page, the uninstallation status is lost because the background uninstallation procedure currently doesn't update the comment on the stripe schema during uninstallation. We are making a change in the stripe sync engine code for that here: https://github.com/stripe-experiments/sync-engine/pull/113 --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
20d1ac0f83 |
feat(assistant): send user feedback to Braintrust traces (#43021)
- Expose Braintrust span ID to client via `x-braintrust-span-id` response header, captured in chat transport - On feedback submission, call `logFeedback()` with `scores["User Rating"]` (1/0), `comment`, and on the root span assign `metadata.feedbackCategory` - Silently skipped when tracing is disabled (HIPAA, missing env vars) - Log `requestedModel` in trace metadata so we can see what model the user selected vs what was actually used after throttling Example traces: - [Thumbs up](https://www.braintrust.dev/app/supabase.io/p/Assistant/trace?object_type=project_logs&object_id=5a8d02e5-b3b6-40cc-ba76-ecee286478f4&r=0bb71680-784c-45c1-a234-cba0242562d6&s=0bb71680-784c-45c1-a234-cba0242562d6) - [Thumbs down + negative feedback](https://www.braintrust.dev/app/supabase.io/p/Assistant/trace?object_type=project_logs&object_id=5a8d02e5-b3b6-40cc-ba76-ecee286478f4&r=d5a78084-6c9a-4230-8615-1e864bb9bac7&s=d5a78084-6c9a-4230-8615-1e864bb9bac7) <img width="645" height="173" alt="CleanShot 2026-02-19 at 13 30 25@2x" src="https://github.com/user-attachments/assets/6c463e83-27c6-4afb-a8d0-a329ed61270a" /> Closes AI-442 |
||
|
|
e8ab92408f |
feat(assistant): enable Braintrust tracing for non-sensitive chats (#42963)
Enables Braintrust tracing for AI Assistant chats to support debugging and future online evals. **Code Changes** - Wraps `generateAssistantResponse` in a Braintrust `traced()` span, logging the user's latest message as input along with metadata (`chatId`, `chatName`, `projectRef`, `userId`, `orgId`, `planId`, etc.) - Threads JWT claims from `apiWrapper` → handler to log `userId` in Braintrust without an extra API call (+ expanded `apiWrapper` tests) - Threads `orgId` and `planId` from `getOrgAIDetails` to log in Braintrust **Infrastructure Changes** - Created a "Vercel" service account in Braintrust - Added `BRAINTRUST_API_KEY` and `BRAINTRUST_PROJECT_ID` env vars to the studio-staging project in Vercel using a service token for the above service account - Added an "Overview" view to the Logs tab in the Braintrust Assistant project to surface the new metadata **Precautions** - HIPAA sensitive projects are excluded from logging (see https://github.com/supabase/supabase/pull/42787 for the detection logic) - Production is temporarily excluded from logging until we're confident in the setup **Testing steps** - Chat with the AI Assistant in the [studio-staging preview build](https://github.com/supabase/supabase/pull/42963#issuecomment-3917178023) below - Visit the [Logs tab in the Braintrust Assistant project](https://www.braintrust.dev/app/supabase.io/p/Assistant/logs) and inspect the trace <img width="4680" height="962" alt="CleanShot 2026-02-18 at 17 43 55@2x" src="https://github.com/user-attachments/assets/c3a11b21-4e7f-4e90-bdab-a25ab8ee0d1f" /> <img width="2632" height="1288" alt="CleanShot 2026-02-18 at 17 45 04@2x" src="https://github.com/user-attachments/assets/6c7b6ebc-5090-4ede-8f71-859ff7e386aa" /> **References** - https://www.braintrust.dev/docs/integrations/sdk-integrations/vercel - https://www.braintrust.dev/docs/instrument/custom-tracing Closes AI-438 |
||
|
|
2fc062a725 |
feat(assistant): detect HIPAA customers in assistant logic (#42787)
Detects HIPAA customers server-side in the assistant code path. Threads `isHipaaEnabled` boolean through `getOrgAIDetails` → `generate-v4` → `generateAssistantResponse`. The motivation is to support online evals down the road, where we'll want to exclude HIPAA projects from Assistant tracing. This PR follows existing patterns for checking if HIPAA is enabled for a project (org has HIPAA addon + project is sensitive). Example [[1]](https://github.com/supabase/supabase/blob/a5dd0a96716561443778f38a518b61d6cac95c19/apps/studio/components/interfaces/Settings/Addons/Addons.tsx#L75), [[2]](https://github.com/supabase/supabase/blob/6858d4e18d9359d573fe3dff73bc4e5fa1cfe219/apps/studio/hooks/misc/useOrgOptedIntoAi.ts#L69). ```ts const hasHipaaAddon = subscriptionHasHipaaAddon(subscription) && settings?.is_sensitive ``` (I call it `isHipaaEnabled` in this PR to avoid it being misunderstood as just the org-level addon, rather it's a combo of that addon being present AND high compliance being enabled on the project). ### Verification steps <details><summary>Click to view the steps I followed to sanity check it works with the local stack</summary> Tested locally with `mise fullstack`: 1. Found my org's subscription ID: ```sh docker exec platform-db-1 psql -U postgres -c "SELECT id, customer_id, status FROM orb.subscriptions;" ``` 2. Added HIPAA addon to it: ```sh docker exec platform-db-1 psql -U postgres -c " UPDATE orb.subscriptions SET price_intervals = price_intervals || '[{\"price\": {\"unit_config\": {\"unit_amount\": \"350.00\"}, \"external_price_id\": \"addon_security_hipaa\", \"item\": {\"name\": \"HIPAA\"}}}]'::jsonb WHERE id = '<subscription_id>';" ``` 2. Toggled on High Compliance (Project Settings → General) 3. Added a temporary log after `getOrgAIDetails` in `generate-v4.ts`: ```ts console.log('[HIPAA]', { isHipaaEnabled }) ``` 4. Sent a message in the AI Assistant → `isHipaaEnabled: true` 5. Toggled off High Compliance → resent → `isHipaaEnabled: false` 6. Removed addon from subscription, left project toggle on → `isHipaaEnabled: false` ```sql -- Find addon index: SELECT ordinality - 1 as idx FROM orb.subscriptions, jsonb_array_elements(price_intervals) WITH ORDINALITY AS elem(val, ordinality) WHERE id = '<subscription_id>' AND val->'price'->>'external_price_id' = 'addon_security_hipaa'; -- Remove by index: UPDATE orb.subscriptions SET price_intervals = price_intervals - <idx> WHERE id = '<subscription_id>'; ``` All three cases confirm `isHipaaEnabled` requires both the org addon and the project-level toggle. </details> Closes AI-434 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added HIPAA mode detection and exposed it in AI workflows. * API request functions now accept optional custom authorization headers for downstream calls. * **Tests** * Added tests covering HIPAA scenarios and verifying authorization header propagation in related flows. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
70510acf5b |
feat(studio-local): functions management api - test functions (#42350)
Feature ## What is the current behavior? Functions page on self-hosted differs from Platform ## What is the new behavior? Adds the possibility to try/test functions in Self-Host version. ## Summary by CodeRabbit * **Bug Fixes** * Improved edge function URL validation so testing works reliably both on-platform and off-platform, including proper URL handling for local setups. * **UI Improvements** * Moved the Test button in the edge functions interface for more consistent layout while preserving its behavior. * **Tests** * Expanded tests to cover platform-aware URL validation scenarios. --------- Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com> |
||
|
|
997203cd64 |
feat(studio-local): functions management api - function blob artifacts (#42349)
## What kind of change does this PR introduce? Feature ## What is the current behavior? Functions page on self-hosted differs from Platform ## What is the new behavior? > [!NOTE] > This PR only add readonly operations. Function edit and deploy should be implemented in a future one. Adds the possibility to download and see function code in Self-Host version. <details> <img width="1465" height="944" alt="image" src="https://github.com/user-attachments/assets/4bbf8f5c-3390-4de6-9e8b-8ec9cd59ebad" /> </details> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * API endpoint to stream function files/artifacts as multipart/form-data. * New function file entry type and server-side file listing for functions. * **Improvements** * Edge Functions "Code" navigation item always visible. * Download popover reworked: ZIP download always available; CLI section shown only on supported platforms. * Editor set to read-only and file actions disabled on unsupported environments. * **Editor** * Added JavaScript, TypeScript, and Markdown language modules for the embedded editor. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com> |