Files
supabase/apps/studio/data/analytics/keys.ts
Jordi Enric 4096267623 feat(api-keys): migrate last-used indicator to ClickHouse endpoint (#47458)
## Problem

The "last used" indicator for the legacy `anon` / `service_role` API
keys (Project API keys settings) was disabled because it ran a BigQuery
`edge_logs` query. It is now re-enabled against the ClickHouse-backed
`api_keys.last_used.otel` analytics endpoint.

## Current behavior

- The `anon` / `service_role` "last used" indicator is off (the
BigQuery-backed query was disabled).

## New behavior

- New `useApiKeysLastUsedQuery` hook calls the `api_keys.last_used.otel`
endpoint (timestamp params only, no SQL sent), plus its query key and
the generated platform API type.
- `DisplayApiSettings` reads last-used from this hook instead of posting
BigQuery `edge_logs` SQL. The pure `getLastUsedAPIKeys` shaper is kept
and unit-tested. Still gated by the `showApiKeysLastUsed` flag.
- Removed the disabled secret-keys (`sb_secret_`) BigQuery last-used
path, which has no ClickHouse endpoint to migrate to: drops the dead
`useLastSeen` query, the `APIKeyRow` "Last Used" column, and the unused
`showLastSeen` prop.
- Reworded the delete-confirmation copy to be accurate for both secret
and publishable keys.

## Additional context

- Backed by the platform endpoint in supabase/platform#34892 (merged and
deployed).
- Scope: `anon` / `service_role` legacy keys. Secret/publishable and JWT
signing-key "last used" are follow-ups, pending the endpoint returning
those key types.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Improvements**
* Updated API key settings to show “last used” activity for the past 24
hours using a dedicated data source and time window.
  * Added clearer messaging when recent API key activity fails to load.
  * Removed the “Last Used” column from API key management tables.
* **Bug Fixes**
* Improved mapping so “last used” values correctly match the intended
key and role.
* Updated API key deletion confirmation to explain required backend
changes and resulting unauthorized behavior.
* **Tests**
* Added unit tests to validate “last used” computation and edge-case
filtering.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 14:35:32 +02:00

186 lines
3.7 KiB
TypeScript

export const analyticsKeys = {
// logs/reports endpoints
functionsCombinedStats: (
projectRef: string | undefined,
{
interval,
functionId,
}: {
functionId: string | undefined
interval: string | undefined
}
) =>
[
'projects',
projectRef,
'functions-combined-stats',
{
interval,
functionId,
},
] as const,
functionsInvStats: (
projectRef: string | undefined,
{
interval,
functionId,
}: {
functionId: string | undefined
interval: string | undefined
}
) =>
[
'projects',
projectRef,
'functions-inv-stats',
{
interval,
functionId,
},
] as const,
functionsReqStats: (
projectRef: string | undefined,
{
interval,
functionId,
}: {
functionId: string | undefined
interval: string | undefined
}
) =>
[
'projects',
projectRef,
'functions-req-stats',
{
interval,
functionId,
},
] as const,
functionsResourceUsage: (
projectRef: string | undefined,
{
interval,
functionId,
}: {
functionId: string | undefined
interval: string | undefined
}
) =>
[
'projects',
projectRef,
'functions-resource-usage',
{
interval,
functionId,
},
] as const,
orgDailyStats: (
orgSlug: string | undefined,
{
startDate,
endDate,
projectRef,
}: {
startDate?: string
endDate?: string
projectRef?: string
}
) =>
[
'organizations',
orgSlug,
'daily-stats',
{
startDate: isoDateStringToDate(startDate),
endDate: isoDateStringToDate(endDate),
projectRef,
},
] as const,
infraMonitoring: (
projectRef: string | undefined,
{
attribute,
startDate,
endDate,
interval,
databaseIdentifier,
}: {
attribute?: string
startDate?: string
endDate?: string
interval?: string
databaseIdentifier?: string
}
) =>
[
'projects',
projectRef,
'infra-monitoring',
{ attribute, startDate, endDate, interval, databaseIdentifier },
] as const,
infraMonitoringGroup: (
projectRef: string | undefined,
{
attributes,
startDate,
endDate,
interval,
databaseIdentifier,
}: {
attributes?: string[]
startDate?: string
endDate?: string
interval?: string
databaseIdentifier?: string
}
) =>
[
'projects',
projectRef,
'infra-monitoring',
'group',
{
attributes: attributes ? [...attributes].sort() : undefined,
startDate,
endDate,
interval,
databaseIdentifier,
},
] as const,
apiKeysLastUsed: (
projectRef: string | undefined,
{
isoTimestampStart,
isoTimestampEnd,
}: {
isoTimestampStart?: string
isoTimestampEnd?: string
}
) =>
['projects', projectRef, 'api-keys-last-used', { isoTimestampStart, isoTimestampEnd }] as const,
usageApiCounts: (projectRef: string | undefined, interval: string | undefined) =>
['projects', projectRef, 'usage.api-counts', interval] as const,
serviceHealth: (
projectRef: string | undefined,
{
startDate,
endDate,
granularity,
}: {
startDate?: string
endDate?: string
granularity?: string
}
) => ['projects', projectRef, 'service-health', { startDate, endDate, granularity }] as const,
}
function isoDateStringToDate(isoDateString: string | undefined): string | undefined {
if (!isoDateString) return isoDateString
return isoDateString.split('T')[0]
}