## 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>
## Problem
The legacy per-service log pages (postgres, auth, api, edge functions,
storage, realtime, cron, etc.) and the single-log detail panel query the
BigQuery-backed `logs.all` analytics endpoint. We are moving these reads
onto the OTEL ClickHouse endpoint (`logs.all.otel`).
## Fix
- Add `Logs.utils.otel.ts`: ClickHouse query builders
(rows/count/chart/single) + row mappers that target the single `logs`
table keyed by `source`, reading fields from the `log_attributes` map
and aliasing columns to the leaf names the renderers expect.
- Parameterize `buildWhereClauses` / `genWhereStatement` in
`Logs.utils.ts` so the OTEL builders reuse the shared nested AND/OR
filter grouping. Defaults keep the BigQuery behavior unchanged.
- Gate `useLogsPreview` (rows, count, chart) and `useSingleLog` (detail)
on the new `otelLegacyLogs` flag. BigQuery stays the default when the
flag is off.
- Extract the OTEL timestamp parser into `parseOtelTimestamp`
(`otel-inspection.utils.ts`) and reuse it in
`unified-logs-infinite-query.ts` (replaces an inline copy of the same
logic; no behavior change).
## Dependencies
None. Standalone, safe to merge on its own. Behind `otelLegacyLogs` (off
by default), so no user-facing change.
Part of DEBUG-145 (split from #47087).
## How to test
- In staging, go to Legacy Logs.
- All logs pages should work the same as before.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added OTEL-backed logs support for preview, count, chart, and
single-log details when enabled.
* **Bug Fixes**
* Improved timestamp parsing/normalization for OTEL data to ensure
correct display and pagination.
* Enhanced filtering behavior, including safer handling of unknown
filter keys and invalid values across OTEL queries.
* Improved single-log result shaping to preserve expected API/database
metadata in OTEL mode.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Problem
The facet counts in the unified logs sidebar were slow to load. The
query scanned the logs table about 14 times, once for each group of
counts (the total, each log type, each level, and method, status, and
pathname).
## Fix
Count the facets that have few distinct values (total, log type, level,
method, status) in a single scan instead of one scan each. Pathname
stays on its own scan because it has too many distinct values to count
that way.
A facet you are filtering on still gets its own scan, so it can keep
showing counts for its other values while the rest of the sidebar
reflects the filter.
This takes the common case from about 14 scans down to 3. The result
shape is unchanged, so nothing else needed updating.
Note: facet values with a count of zero are no longer returned. Only
values that actually appear show up.
## How to test
- Open Unified Logs for a project with the otelUnifiedLogs flag on.
- Check that the sidebar counts (log type, level, method, status,
pathname) and the total badge match what they showed before, and load
faster.
- Filter by a facet (e.g. log type) and confirm that facet still lists
counts for its other values, while the other facets update to match the
filter.
- Run the unit tests in apps/studio for UnifiedLogs.queries.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Updated unified log counting to a more efficient single-pass SQL
approach for facet and per-dimension counts.
* Standardized log-type filtering behavior across unified queries and
facet/count generation.
* **Bug Fixes**
* Improved “total/all” counts to correctly respect active filters,
including correct source handling and default log-type exclusion.
* **Refactor**
* Limited facet displays to the top 20 values per facet; facet totals
are now calculated from the retained rows.
* **Tests**
* Expanded SQL and filtering assertions to cover the new counting
structure and facet row behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Problem
The unified log dashboards' Postgres detail panel hid the `query` and
`detail` fields. They were present in the raw log message but never
surfaced in the structured view, making them harder to use when
debugging.
## Fix
- Select `pgl_parsed.query` and `pgl_parsed.detail` in the Postgres
service flow query.
- Add `Query` and `Details` field configs to the Postgres primary
fields, both with `wrap: true` so long values display in full instead of
truncating.
The parsed Postgres field is `detail` (singular); it is labeled
"Details" in the UI.
## How to test
- Open Studio and navigate to the unified logs dashboard for a project.
- Filter to Postgres logs and select a log row to open the detail panel.
- Confirm the Postgres section now shows `Query` and `Details` rows
below `User`.
- Expected result: rows render the parsed query and detail text,
wrapping for long values, and show an em dash when empty.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* PostgreSQL service flow logs now show additional always-visible
**Query** and **Details** fields, bringing parsed database query content
and expanded information directly into the log view.
* **Tests**
* Updated log inspection coverage to ensure the new parsed fields are
correctly surfaced in the flattened inspection output.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## 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
## 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 / chore — lints the analytics SQL wire boundary and tightens
internal API surface. Final PR in the safe-analytics-sql series (stacked
on #46476).
## What is the current behavior?
After PRs 1–10, every analytics SQL call site routes through
`executeAnalyticsSql`, but nothing prevents a future caller from
regressing by calling
`post('/platform/projects/{ref}/analytics/endpoints/logs.all', …)`
directly. `safe-analytics-sql.ts` also exports `rawSql` and
`LogSqlFragmentSeparator`, neither of which has external consumers —
`rawSql` in particular is a cast-to-brand escape hatch that should not
be reachable from outside the file. The safe-sql-execution skill
documents only the pg-meta (Postgres) side of the model.
## What is the new behavior?
- Adds an ESLint `no-restricted-syntax` rule in
`apps/studio/eslint.config.cjs` that fails on direct `post()` / `get()`
calls against
`/platform/projects/{ref}/analytics/endpoints/logs.all{,.otel}` outside
the `executeAnalyticsSql` wrapper.
- Un-exports `rawSql` and `LogSqlFragmentSeparator` from
`safe-analytics-sql.ts`; updates the `SafeLogSqlFragment` docstring
accordingly.
- Adds an "Analytics SQL" section to
`.claude/skills/safe-sql-execution/SKILL.md` covering the disjoint
`SafeLogSqlFragment` brand, the helpers, the wire boundary, and the new
lint.
## Additional context
Resolves FE-2949
## 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 / security hardening — continues the analytics SQL
provenance-tracking series (PR 8).
## What is the current behavior?
- `generateRegexpWhere` (unsafe: interpolates user-controlled filter
keys/values without escaping) still exists alongside
`generateRegexpWhereSafe` and its tests only cover the old function.
- `usePostgrestOverviewMetrics` builds a SQL query string with plain
string interpolation and calls the analytics endpoint directly via
`get()`.
- `edge-functions-last-hour-stats-query` builds a SQL query with
`functionIds` escaped via Postgres-only `quoteLiteral` and calls the
analytics endpoint directly via `post()`.
- `executeAnalyticsSql` has no way to pass a `key` query-string param
for network-tool identification.
- `rawSql('minute')` / `rawSql('hour')` / `rawSql('day')` and
`rawSql(value ? 'true' : 'false')` are used for static strings that
could be expressed with the `safeSql` template tag.
## What is the new behavior?
- `generateRegexpWhere` is deleted; its tests are replaced with
`generateRegexpWhereSafe` coverage including injection-attempt cases
(`level OR id IS NOT NULL`, `request.method); DROP TABLE edge_logs; --`)
that verify predicates are silently dropped rather than emitted.
- `usePostgrestOverviewMetrics` returns `SafeLogSqlFragment` from its
SQL builder and routes through `executeAnalyticsSql`.
- `edge-functions-last-hour-stats-query` uses `analyticsLiteral`
(BigQuery/ClickHouse-correct escaping) instead of `quoteLiteral`
(Postgres-only) and routes through `executeAnalyticsSql`.
- `executeAnalyticsSql` accepts an optional `key?: string` forwarded as
a query-string param on both GET and POST requests; `key:
'last-hour-stats'` is restored on the edge-functions query.
- Static `rawSql('...')` calls replaced with `safeSql\`...\`` template
literals throughout.
## Additional context
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Bug Fixes
- Removed legacy unsafe SQL-filter utility from Reports
## Chores
- Enhanced analytics SQL execution infrastructure with improved error
handling
- Added optional request identification parameter to analytics query
execution
- Refined SQL filtering mechanisms in reporting features
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46466?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 -->
## Context
Original task was to support searching `!=` on `event_message`, but this
PR addresses some things regarding searching on `event_message` in
unified logs that I found while working on this.
### `=` and `!=` are technically inaccurate
We're doing pattern matching when searching on event_message rather than
a strict equality check, so a more accurate operator would be `ilike
(~~*)` and `not ilike(!~~*)` - both of which would be case insensitive
for easier checking.
Am thus swapping to use these 2 operators when filtering on
`event_message`:
<img width="430" height="134" alt="image"
src="https://github.com/user-attachments/assets/c8a320b6-e016-44ae-aed0-1e7b6cefbda9"
/>
### Filtering on `event_message` was never server side
It seems like we have been only doing client side searching on
`event_message` which is inaccurate as we're only filtering against rows
that are on the current page. The `event_message` filtering was never
appended to the URL state as well so the changes in this PR ensures that
all search including `event_message` is server side.
### Rework on unified logs filtering via URL params
Because we're now supporting more than just `=` in unified logs, the
current filter system is insufficient (e.g can't just be
`status=x&method=y`). Am opting to use the same system as per how we do
filtering in the table editor where search params follow the syntax:
`{column}:{operator}:{value}`
<img width="521" height="46" alt="image"
src="https://github.com/user-attachments/assets/54e72eb2-1581-4c1a-910e-58d993da1766"
/>
## To test
- [ ] Verify that searching for logs in unified logs still works
- [ ] Verify that searching against event_message in unified logs works
as expected (both ilike and not ilike)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Repeatable URL-based column filters with operator support (e.g.,
equals, not-equals, pattern matching).
* Expanded pattern-style operators for message searches
(case-insensitive/contains, negation).
* **Improvements**
* Unified filter handling across logs list, charts, and counts for
consistent results.
* Range/slider filters and pagination remain supported and round-trip
via URL parameters.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46457?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 -->
## Context
Currently when opening an auth log, the log details panel is seemingly
very empty
Auth logs are pretty empty by their nature unlike the other logs so am
opting to adjust the detail panel for them slightly
### Changes involved
- Fixing passing `host` and `path` when rendering auth log details
- Opting to only show "Network" + "Authentication" segments for auth
(The other fields do not apply for auth logs)
<img width="434" height="476" alt="image"
src="https://github.com/user-attachments/assets/cf8bb128-2332-424a-a10e-a7e836acb7d5"
/>
- Make each section collapsible, allow users to adjust themselves how
they want to consume the information
<img width="421" height="474" alt="image"
src="https://github.com/user-attachments/assets/e842bc79-edff-4ec6-ae38-a9249966881d"
/>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Postgres connection and session info now appear in separate expandable
sections for easier browsing
* Auth-related fields (ID, status, path, referer) now extract and
present richer, more accurate values
* Request path and host resolution improved across service flow/network
views
* **Bug Fixes / Improvements**
* Safer parsing of auth event messages and more robust fallbacks for
missing fields
* Cleaner row styling and section rendering for consistent visuals
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46372?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 -->
## 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 / type safety improvement
## What is the current behavior?
The legacy log query stack (`genDefaultQuery`, `genCountQuery`,
`genChartQuery`, `genWhereStatement`, `useLogsPreview`, `useSingleLog`)
builds SQL from raw strings with no type-level guarantee that values are
safely interpolated. Identifier helpers (`bqIdent`, `bqDottedIdent`,
`clickhouseIdent`, `clickhouseDottedIdent`) are duplicated across
BigQuery and ClickHouse variants, and `bqDottedIdent` wraps the entire
dotted path in one backtick pair (`` `request.pathname` ``), which
BigQuery treats as a literal column name rather than a UNNEST alias
field — causing runtime query failures on dotted filter keys.
## What is the new behavior?
- All gen functions return `SafeLogSqlFragment` and all callers route
through `executeAnalyticsSql`, enforcing compile-time SQL provenance
tracking across the legacy stack.
- `bqIdent` / `bqDottedIdent` / `clickhouseIdent` /
`clickhouseDottedIdent` are replaced by a single `quotedIdent` function
that backtick-quotes each segment individually (e.g. ``
`request`.`pathname` ``). ClickHouse natively accepts backticks, so one
function serves both engines and the dotted-path quoting bug is fixed.
- `SQL_FILTER_TEMPLATES` entries are converted to `SafeLogSqlFragment`
(static via `safeSql`, dynamic via `safeSql` + `analyticsLiteral`).
- `buildWhereClauses` is extracted as a private helper returning
`SafeLogSqlFragment[]` so the pg_cron path can merge clauses without
unsafe slice-and-cast.
## Additional context
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Logs query generation migrated to safer, engine-agnostic SQL
fragments, typed filter templates, and unified identifier quoting for
stronger injection protection and more consistent queries.
* Logs preview and single-log retrieval now execute analytics SQL
end-to-end using the unified executor.
* **New Features**
* Analytics SQL executor can call the backend via GET or POST and
accepts method selection.
* **Tests**
* Updated tests to validate unified identifier quoting and safe-SQL
helper behavior.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46351?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 -->
## Context
Improved formatting for auth logs in unified logs - their metadata are
seemingly all hidden within "event_message" so the changes here bring
them up
- Fix detecting status, pathname, and method for auth logs from
`event_message`
- None were showing originally, status was mostly defaulting to `200`
- Improve formatting of `event_message` by prioritising errors +
floating up the auth action
- Currently only shows "request completed"
## Before
<img width="1449" height="955" alt="image"
src="https://github.com/user-attachments/assets/f0c7f166-06ab-4bfc-8653-6f5638bf1ae7"
/>
## After
<img width="1449" height="956" alt="image"
src="https://github.com/user-attachments/assets/cdf49bd8-c33a-4f40-a6b7-8783dc38d174"
/>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* More robust parsing of auth log messages to extract
error/status/method/path values and fall back to the original text when
parsing fails.
* Fixed cases where displayed status/method/pathname could be incorrect
for auth logs.
* **Improvements**
* Normalized auth error text (underscores → spaces) and optional
auth-action prefixes for clearer messages.
* Conditional sentence-capitalization for auth event messages.
* **New Features**
* Centralized log metadata extraction for unified log display.
* **Tests**
* Added tests covering auth and non-auth log parsing and metadata
extraction.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46365?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 -->
## 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 / security hardening (part 3 of stacked analytics safe-SQL
series; stacks on top of PR 2: "feat(logs): route unified-logs hooks
through executeAnalyticsSql")
## What is the current behavior?
`ServiceFlow.sql.ts` interpolates `logId` and `serviceType` as raw
template-literal strings directly into SQL (e.g. `` `WHERE el.id =
'${logId}'` ``). The legacy BigQuery branch of
`unified-log-inspection-query.ts` calls `post()` directly with a plain
`string`-typed SQL value, bypassing the `executeAnalyticsSql`
wire-boundary.
## What is the new behavior?
- Add `SAFE_SERVICE_LITERAL: Record<EdgeServiceType,
SafeLogSqlFragment>` — pre-branded SQL string literals for each service
type, built with `analyticsLiteral`.
- Rewrite `getBaseEdgeServiceFlowQuery`,
`getEdgeFunctionServiceFlowQuery`, and `getPostgresServiceFlowQuery` to
use `safeSql` template tag with `analyticsLiteral(logId)` and
`SAFE_SERVICE_LITERAL[serviceType]`. Return types changed to
`SafeLogSqlFragment`.
- Update the four thin wrappers (`getPostgrestServiceFlowQuery`,
`getAuthServiceFlowQuery`, `getStorageServiceFlowQuery`) to return
`SafeLogSqlFragment`.
- Replace `let sql = ''` + direct `post()` call in
`unified-log-inspection-query.ts`'s legacy BigQuery branch with `let
sql: SafeLogSqlFragment` + `executeAnalyticsSql`, eliminating the last
direct `post()` call to the analytics endpoint in this file.
`pnpm typecheck` passes cleanly.
## Additional context
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Secured analytics and log inspection queries through parameterized SQL
execution, preventing potential SQL injection vulnerabilities.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46336?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 -->
## 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?
Security / refactor — routes all unified-logs analytics queries through
the `executeAnalyticsSql` wire-boundary wrapper (PR 2 of the
safe-analytics-sql series).
## What is the current behavior?
All five unified-logs query hooks call `post()` directly with a raw SQL
string, bypassing the `SafeLogSqlFragment` type enforcement. The
`getUnifiedLogs` infinite-query also drops the brand by composing with a
plain template literal before sending to the wire.
## What is the new behavior?
- `unified-logs-infinite-query`: brand-dropping plain template literal
replaced with `safeSql` + `analyticsLiteral`; `post()` replaced with
`executeAnalyticsSql`
- `unified-logs-count-query`, `unified-logs-chart-query`,
`unified-logs-facet-count-query`: `post()` replaced with
`executeAnalyticsSql`
- `unified-log-inspection-query` (OTEL branch only): both `post()` calls
replaced with `executeAnalyticsSql`; legacy BigQuery branch is unchanged
pending PR 3
The wire boundary now rejects plain strings at compile time for all OTEL
unified-logs paths.
## Additional context
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46333?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 -->
## 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 - Security infrastructure
## What is the current behavior?
Analytics queries (BigQuery for legacy cloud, ClickHouse for self-hosted
OTEL) lack a compile-time safety model to prevent SQL injection from
untrusted input sources like URL parameters, UI inputs, or LLM output.
## What is the new behavior?
Implement a security model with a branded type `SafeLogSqlFragment` that
ensures all SQL fragments originate from either static code or
sanitization helpers. This includes:
- `analyticsLiteral()` for escaping string/number/boolean values
- `bqIdent()` and `clickhouseIdent()` for quoting identifiers with
engine-specific syntax
- `safeSql` template tag for composing fragments safely
- `executeAnalyticsSql()` wire boundary that rejects plain strings at
compile time
The pattern prevents cross-engine confusion by keeping
`SafeLogSqlFragment` (analytics) distinct from pg-meta's
`SafeSqlFragment` (Postgres).
## Additional context
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Introduced analytics SQL execution capabilities with built-in safety
validation for queries.
* Enhanced query robustness through keyword and identifier validation
mechanisms.
* Improved error handling and reporting for analytics operations.
* **Tests**
* Added comprehensive test suite for analytics SQL safety and validation
utilities.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46287?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 -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Introduced a safe SQL fragment system and helpers to build composable,
validated log queries and aggregations.
* **Refactor**
* Rewrote unified log query builders and inspection flows to use the new
safe fragments and identifier/literal validators.
* **Bug Fixes**
* Improved validation and error handling for filter keys and literal
escaping to prevent malformed or injectable queries.
* **Tests**
* Added tests covering identifier quoting, value escaping, and rejection
of invalid filter inputs.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45887)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
* Bump the deps, refactor deprecated code.
* Migrate keepPreviousData usage.
* Migrate all uses of InfiniteQuery.
* Fix refetchInterval in queries.
* Migrate all use of isLoading to isPending in mutations.
* Fix accessing location in claim-project.
* Fix a bug in duplicate query keys.
* Migrate all queries to use isPending.
* Revert "Fix accessing location in claim-project."
This reverts commit 2a07df64b5.
* Revert the rss.xml file to master.
* Add custom types for queries, mutations and infinite queries.
* Migrate all queries to use the new type.
* Migrate all infinite queries to useCustomInfiniteQueryOptions.
* Migrate all mutations to use useCustomMutationOptions.
* Add type to all imports in `types` folder.
* Migrate all uses of invalidateQueries to use object syntax.
* Migrate the remainder of useInfiniteQuery.
* Migrate all setQueriesData.
* Migrate all fetchQuery uses.
* Migrate some leftover functions from RQ.
* Fix issues found by Charis.
* Add loading opacity and keep previous data for logs
Wrapped TimelineChart and DataTableInfinite in divs with opacity transition during data fetching for improved UX. Added keepPreviousData: true to unified logs chart, count, and infinite queries to retain previous data while fetching new results.
* Remove keepPreviousData from logs count query
The keepPreviousData option was removed from the useUnifiedLogsCountQuery hook to rely on default query behavior or custom options. This may affect how data is retained between queries.
* Update UnifiedLogs.tsx
* Refactor TimelineChart opacity handling
Moved opacity and transition classes from a wrapping div directly to the TimelineChart component for cleaner structure and improved conditional styling.
* Improve function logs styling + add copy button
* Add tooltips for buttons in toolbar
* Remove 'info' from levels
* Add export logs to csv and json functionality
* Add duration selection for download logs if no time range specified in search
* Fix TS
* Fix TS
* Update DataTableColumnStatusCode.tsx
---------
Co-authored-by: Jonathan Summers-Muir <MildTomato@users.noreply.github.com>
* Update QueryOptions.ts
* Create UnifiedLogs_InspectionPanel_Architecture.md
* init new queries
* Create UnifiedLogs_ServiceFlow_Implementation_Plan.md
* Add service flow blocks to UnifiedLogs panel
Introduces ServiceFlowBlocks components to visually represent the service flow in UnifiedLogs, including Origin, Network, PostgREST, Postgres, and Response steps. Adds utility formatters and updates ServiceFlowPanel to render the new blocks with enriched data and loading/error states.
* Enable filterable fields in ServiceFlow blocks
Refactored ServiceFlow blocks to support filterable fields by passing filterFields and table props, updating BlockField to render filterable values as clickable actions, and aligning field configs with filterable IDs. Updated ServiceFlowPanel to use new block names and pass required props. This enhances interactivity and consistency in the UnifiedLogs service flow UI.
* Update ServiceFlowBlocks.tsx
* Enhance Service Flow with enriched fields and filtering
Expanded the Service Flow SQL query to extract 35+ flattened, meaningful fields including request, response, client location, network, headers, and JWT data. Updated the implementation plan to reflect new block architecture, filtering integration, and future enhancements. Added debug logging for enriched and raw log data in ServiceFlowPanel.
* Start adding inspection panel
* Moar logs
* Add Postgres service flow support to Unified Logs
Introduces Postgres as a first-class service flow type in Unified Logs, including SQL query, type definitions, UI blocks, and filtering. Updates ServiceFlow queries, types, and UI components to display enriched Postgres log details and event messages. Also refines filter fields, log type ordering, and minor UI adjustments for clarity and consistency.
* Lots of tidying up, moving blocks into their own files.
* Remove UnifiedLogs architecture and service flow docs
Deleted documentation files related to UnifiedLogs inspection panel architecture, service flow field mapping, implementation plan, and integration example. This cleans up outdated or redundant design and implementation reference materials.
* Refactor service flow blocks to use unified config system
Replaces individual service block components with a generic, config-driven system. Introduces a shared Block component and centralizes block configuration in blockConfigs.ts, reducing duplication and improving maintainability. Updates imports and removes now-unnecessary block files. Also refactors ServiceFlowPanel to use the new block structure and simplifies layer icon logic.
* Refactor ServiceFlow blocks and utilities structure
Consolidates edge service flow SQL queries to reduce duplication, removes ServiceFlowBlocks.tsx in favor of more modular block/component structure, and moves storage-specific utilities to a new utils/storageUtils.ts file. Updates imports in config files and ServiceFlowPanel to reflect the new structure. Type definitions are clarified and extended in types.ts.
* Update ServiceFlow.sql.ts
* Refactor ServiceFlow types for stronger type safety
Replaces generic 'any' types with specific types such as ColumnSchema, QuerySearchParamsType, and SearchParamsType in ServiceFlow components and ServiceFlowPanel. This improves type safety and code clarity, and removes unused metadata and workaround variables from ServiceFlowPanel.
* Remove debug flags and console logs from ServiceFlow components
Eliminated unused DEBUG_SERVICE_FLOW flags and related console logging from ServiceFlow.sql.ts and ServiceFlowPanel.tsx to clean up the codebase and reduce unnecessary output.
* Remove unused log query and filtering functions
Deleted unused functions related to log level filtering, base condition building, and the edge/supavisor logs queries. This cleanup simplifies the UnifiedLogs.queries.ts file by removing legacy or currently unused code.
* revert
* Remove ServiceFlow panel and types, update DataTableToolbar
Deleted the ServiceFlowPanel component and its associated types from the UnifiedLogs interface. Updated DataTableToolbar to toggle between PanelLeftClose and PanelLeftOpen icons based on the open state.
* Remove unused totalRows prop from DataTable
Eliminates the totalRows prop from UnifiedLogs and its context interface, as it is no longer used. This helps clean up the component API and related type definitions.
* Refactor log field configs and unify event message component
Replaces specialized PostgresEventMessage with a generic EventMessage component and updates references accordingly. Consolidates all log field configuration files into serviceFlowFields.ts, removing separate config files for each service. Cleans up unused types and utility imports, and deletes redundant formatters.
* Show empty state for Postgres block with no data
Added logic to display an empty state in the Postgres block when no Postgres data is available in non-Postgres logs. Also updated ServiceFlowPanel to render both PostgREST and Postgres blocks, ensuring the empty state is shown when appropriate.
* Remove Log Details tab from ServiceFlowPanel
The Log Details tab and its associated content have been removed from the ServiceFlowPanel component. This simplifies the UI by focusing on the Overview and Raw JSON tabs.
* Update UnifiedLogs.queries.ts
* Update UnifiedLogs.queries.ts
* Update apps/studio/components/interfaces/UnifiedLogs/ServiceFlow/components/shared/BlockField.tsx
* Refactor UnifiedLogs layout and improve service type formatting
Refactored UnifiedLogs.tsx to use a more flexible ResizablePanelGroup layout, replaced inline function logs panel with a new LogsListPanel component, and removed unused imports and code. Updated ServiceFlow.sql.ts to simplify JWT payload extraction and added a dedicated query for edge function service flow. Added a utility to format service type strings for display in UnifiedLogs.utils.ts.
* Refactor logs UI and improve service flow handling
Renamed FunctionLogsTab to LogsList and added a new LogsListPanel for displaying function logs in a side panel. Improved ServiceFlowPanel with better panel sizing, conditional query enabling, and UI adjustments. Enhanced EventMessage with badge styling and service type formatting. Updated CollapsibleSection for cleaner layout. Enabled debug mode in unified-log-inspection-query. Updated FilterSideBar to use ResizablePanel for improved layout flexibility.
* Refactor UnifiedLogs UI and ServiceFlow query fields
Removes unused skeletonClassName from BlockFieldConfig and related UI, simplifies ServiceFlow SQL query by returning null for unused JWT fields, and updates UnifiedLogs and LogsListPanel for improved layout and collapsible logs panel. Also adjusts table and log list row heights for better visual consistency.
* Update ServiceFlowHeader.tsx
* Update ServiceFlowHeader.tsx
* Refactor ServiceFlowPanel and header tooltip logic
Replaces custom tooltip implementation in ServiceFlowHeader with ButtonTooltip for navigation buttons. Simplifies serviceFlowType logic in ServiceFlowPanel by removing the getServiceFlowType helper and using direct mapping, reducing code complexity.
* Update UnifiedLogs.constants.tsx
* Remove commented code and add doc comment in UnifiedLogs
Removed an unused commented-out span in UnifiedLogs.fields.tsx and added a documentation comment for the Supabase storage logs query fragment in UnifiedLogs.queries.ts.
* Update UnifiedLogs.tsx
* Remove 'live' level from DataTable components
Eliminated the 'live' level from LEVELS constant and related color utility logic. Also removed commented code and references to 'live' in DataTableFilterControls and LiveRow, streamlining the DataTable component's status handling.
* Update UnifiedLogs.constants.tsx
* cleanup
---------
Co-authored-by: Alaister Young <a@alaisteryoung.com>
* Fix z-index position of row
* Fix column widths to make it fit a laptop viewport better
* Fix auto fetching when scrolling to the bottom
* Small style fixes + decouple count loading state from table loading state
* Refactor row uuid to just id, add de-duping logic to logs data, standardise unified logs query options
* Clean up logs
* Misc styling tweaks
* Reinstate prev cursor and direction for live mode
* Clean
* Revert text sizes
* Remove now resolved comments
* Split unified logs count into its own infinite query and refactor main UI to use that new query
* Split unified logs into its own infinite query and refactor main UI to use that new query
* Shift useChartData into unified-logs-chart-query, and refactor main UI to use that new query
* Rename unified-logs-query to unified-logs-infinite-query
* Remove uuid and live params from query string in react queries for unified logs