diff --git a/apps/framework/harness/run-eval.ts b/apps/framework/harness/run-eval.ts
index 0f758e53..3f85d9fe 100644
--- a/apps/framework/harness/run-eval.ts
+++ b/apps/framework/harness/run-eval.ts
@@ -34,6 +34,7 @@ import {
getExperimentDisplayMetadata,
} from '@supabase-evals/core';
import type {
+ AgentUsage,
ExperimentConfig,
EvalInterface,
EvalManifest,
@@ -360,6 +361,8 @@ async function runOne(
transcript: TranscriptPart[];
agentReport: string;
stoppedReason: string;
+ usage?: AgentUsage;
+ durationMs?: number;
}
> {
const prompt = parseEvalMarkdown(
@@ -388,6 +391,11 @@ async function runOne(
let lastTranscript: TranscriptPart[] = [];
let lastAgentReport = '';
let lastStoppedReason = 'not_started';
+ // Performance metrics for the attempt that produced the reported score:
+ // the agent's own token/cost accounting and its wall-clock time (agent run
+ // only — sandbox boot and scoring excluded, so harnesses compare fairly).
+ let lastUsage: AgentUsage | undefined;
+ let lastDurationMs: number | undefined;
for (let attempt = 1; attempt <= RUNS; attempt += 1) {
if (ev.mode === 'local-stack') {
@@ -442,6 +450,7 @@ async function runOne(
})
);
+ const agentStart = Date.now();
const run = await exp.agent.run({
systemPrompt: buildSystemPrompt('local-stack', session.promptAddendum),
userPrompt: prompt,
@@ -457,6 +466,8 @@ async function runOne(
lastTranscript = run.transcript;
lastAgentReport = run.agentReport;
lastStoppedReason = run.stoppedReason;
+ lastUsage = run.usage;
+ lastDurationMs = Date.now() - agentStart;
// Export the agent's workspace to the host so scorers can run host
// tooling (vite/vitest from the repo root) against the produced files
@@ -495,6 +506,8 @@ async function runOne(
transcript: run.transcript,
agentReport: run.agentReport,
stoppedReason: run.stoppedReason,
+ usage: lastUsage,
+ durationMs: lastDurationMs,
};
}
logRetryAttempt(expName, ev, attempt, last);
@@ -528,6 +541,7 @@ async function runOne(
session.promptAddendum,
skillsPrompt
);
+ const agentStart = Date.now();
const run = await exp.agent.run({
systemPrompt,
userPrompt: prompt,
@@ -544,6 +558,8 @@ async function runOne(
lastTranscript = run.transcript;
lastAgentReport = run.agentReport;
lastStoppedReason = run.stoppedReason;
+ lastUsage = run.usage;
+ lastDurationMs = Date.now() - agentStart;
last = await (scorer as ToolScorer)({
...session.scoringContext,
toolCalls: run.toolCalls,
@@ -561,6 +577,8 @@ async function runOne(
transcript: run.transcript,
agentReport: run.agentReport,
stoppedReason: run.stoppedReason,
+ usage: lastUsage,
+ durationMs: lastDurationMs,
};
}
logRetryAttempt(expName, ev, attempt, last);
@@ -575,6 +593,8 @@ async function runOne(
transcript: lastTranscript,
agentReport: lastAgentReport,
stoppedReason: lastStoppedReason,
+ usage: lastUsage,
+ durationMs: lastDurationMs,
};
}
diff --git a/apps/framework/harness/types.ts b/apps/framework/harness/types.ts
index d4cfc677..0930acf0 100644
--- a/apps/framework/harness/types.ts
+++ b/apps/framework/harness/types.ts
@@ -6,6 +6,7 @@ import type {
} from '@supabase-evals/core/eval-metadata';
export type {
+ AgentUsage,
ScoreResult,
CheckResult,
ToolCallRecord,
diff --git a/apps/framework/scripts/export-results.ts b/apps/framework/scripts/export-results.ts
index 3b32923f..1288bc3a 100644
--- a/apps/framework/scripts/export-results.ts
+++ b/apps/framework/scripts/export-results.ts
@@ -129,6 +129,8 @@ async function readResultFile(
checks: parsedResult.checks,
skills: parsedResult.skills,
docs: parsedResult.docs,
+ usage: parsedResult.usage,
+ durationMs: parsedResult.durationMs,
prompt: promptData?.prompt,
promptSourcePath: promptData?.promptSourcePath,
attempts: parsedResult.attempts,
diff --git a/apps/web/src/components/results/eval-details.tsx b/apps/web/src/components/results/eval-details.tsx
index c83e256b..a0172cea 100644
--- a/apps/web/src/components/results/eval-details.tsx
+++ b/apps/web/src/components/results/eval-details.tsx
@@ -7,8 +7,18 @@ import {
XIcon,
} from "lucide-react"
-import { passFailClassName } from "@/components/results/table-shared"
-import type { CheckResult, DocsCall, ParsedResult } from "@/lib/eval-results"
+import {
+ formatCost,
+ formatDuration,
+ formatTokens,
+ passFailClassName,
+} from "@/components/results/table-shared"
+import {
+ runTokens,
+ type CheckResult,
+ type DocsCall,
+ type ParsedResult,
+} from "@/lib/eval-results"
import { formatProductLabel, formatTagLabel } from "@/lib/format"
import { cn } from "@/lib/utils"
@@ -193,8 +203,22 @@ function ResultDocsCalls({ calls }: { calls: DocsCall[] }) {
)
}
+/** "1.2M tokens (982k in / 218k out)" — total with the in/out split when known. */
+function tokensLabel(result: ParsedResult): string | undefined {
+ const total = runTokens(result)
+ if (total === undefined) return undefined
+ const { inputTokens, outputTokens } = result.usage ?? {}
+ const split =
+ inputTokens !== undefined && outputTokens !== undefined
+ ? ` (${formatTokens(inputTokens)} in / ${formatTokens(outputTokens)} out)`
+ : ""
+ return `${formatTokens(total)}${split}`
+}
+
/** Everything recorded about one run, shown when its row in the sheet is expanded. */
export function EvalDetails({ result }: { result: ParsedResult }) {
+ const tokens = tokensLabel(result)
+
return (
{result.prompt ? (
@@ -210,6 +234,19 @@ export function EvalDetails({ result }: { result: ParsedResult }) {
/>
) : null}
+ {result.durationMs !== undefined ? (
+
+ ) : null}
+ {tokens ? : null}
+ {result.usage?.costUsd !== undefined ? (
+
+ ) : null}
{result.sourcePath}}
diff --git a/apps/web/src/components/results/table-shared.test.ts b/apps/web/src/components/results/table-shared.test.ts
index 234b0eec..ccf9fb8a 100644
--- a/apps/web/src/components/results/table-shared.test.ts
+++ b/apps/web/src/components/results/table-shared.test.ts
@@ -1,6 +1,9 @@
import { describe, expect, it } from "vitest"
import {
+ formatCost,
+ formatDuration,
+ formatTokens,
hasMoreContentToRight,
scoreLabel,
} from "@/components/results/table-shared"
@@ -13,6 +16,24 @@ describe("scoreLabel", () => {
})
})
+describe("metric formatters", () => {
+ it("formats durations as seconds under a minute, minutes above", () => {
+ expect(formatDuration(38_000)).toBe("38s")
+ expect(formatDuration(245_000)).toBe("4m 05s")
+ })
+
+ it("formats token counts compactly", () => {
+ expect(formatTokens(845)).toBe("845")
+ expect(formatTokens(12_400)).toBe("12k")
+ expect(formatTokens(1_230_000)).toBe("1.2M")
+ })
+
+ it("keeps cents-level costs from rounding away", () => {
+ expect(formatCost(0.042)).toBe("$0.042")
+ expect(formatCost(1.5)).toBe("$1.50")
+ })
+})
+
describe("hasMoreContentToRight", () => {
it("only reports overflow before the right edge", () => {
expect(
diff --git a/apps/web/src/components/results/table-shared.ts b/apps/web/src/components/results/table-shared.ts
index e05afc34..d32a5b67 100644
--- a/apps/web/src/components/results/table-shared.ts
+++ b/apps/web/src/components/results/table-shared.ts
@@ -43,6 +43,27 @@ export function scoreLabel(
return `${Math.round((passed / total) * 100)}%`
}
+/** Formats a run duration: "38s" under a minute, "4m 05s" above. */
+export function formatDuration(ms: number) {
+ const totalSec = Math.round(ms / 1000)
+ const min = Math.floor(totalSec / 60)
+ const sec = totalSec % 60
+ if (!min) return `${sec}s`
+ return `${min}m ${String(sec).padStart(2, "0")}s`
+}
+
+/** Formats a token count compactly: "845", "12k", "1.2M". */
+export function formatTokens(count: number) {
+ if (count >= 1_000_000) return `${(count / 1_000_000).toFixed(1)}M`
+ if (count >= 1_000) return `${Math.round(count / 1_000)}k`
+ return `${Math.round(count)}`
+}
+
+/** Formats a USD cost, keeping cents-level runs from rounding to $0.00. */
+export function formatCost(usd: number) {
+ return usd < 0.1 ? `$${usd.toFixed(3)}` : `$${usd.toFixed(2)}`
+}
+
/** Checks whether a horizontal scroller has content beyond its right edge. */
export function hasMoreContentToRight({
scrollLeft,
diff --git a/apps/web/src/data/eval-results.json b/apps/web/src/data/eval-results.json
index 5b28a57e..98441a60 100644
--- a/apps/web/src/data/eval-results.json
+++ b/apps/web/src/data/eval-results.json
@@ -60,38 +60,24 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
- "calls": [
- {
- "source": "web_fetch",
- "query": "List any entries tagged breaking-change, and anything relevant to: local development with the CLI, database migrations, RLS policies, the anon/authenticated roles, API keys (publishable/secret vs anon/service_role), seed files, or config.toml. Include dates and links.",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/changelog.md"
- }
- ],
- "resultChars": 8255
- },
- {
- "source": "web_fetch",
- "query": "Show the full recommended workflow and exact SQL for exposing a table in the public schema to the Data API, including GRANT statements for anon and authenticated roles, enabling RLS, and read-only access patterns. Quote the SQL verbatim.",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/api/securing-your-api.md"
- }
- ],
- "resultChars": 1245
- }
- ]
+ "calls": []
},
+ "usage": {
+ "inputTokens": 1105758,
+ "outputTokens": 15696,
+ "cachedInputTokens": 1055589,
+ "cacheCreationInputTokens": 46130,
+ "costUsd": 1.229437
+ },
+ "durationMs": 286852,
"prompt": "We're kicking off a todos app and I want the Supabase side ready for the team\nto build on. Set it up the way we'd run it in development, with schema changes\ntracked as migrations so they can be reviewed and replayed.\n\nFor the first slice we just need a `todos` table. Todos aren't public: anyone\nsigned in can read all of them, but nothing should be writable through the API\nfor now. Add a couple of sample todos so there's something to look at.\n\nBefore you hand it back, make sure the running API actually behaves that way —\nsigned-in users get the todos, signed-out requests get nothing.",
"promptSourcePath": "evals/build-cli-001-bootstrap-app/PROMPT.md",
- "attempts": 1,
+ "attempts": 2,
"sourcePath": "claude-code-opus-5/build-cli-001-bootstrap-app.json"
},
{
@@ -139,37 +125,21 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"declarative database schemas add column generate migration\", limit: 4) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas",
- "title": "Declarative database schemas"
- },
- {
- "url": "https://supabase.com/docs/guides/local-development/cli-workflows",
- "title": "Local development workflow"
- },
- {
- "url": "https://supabase.com/docs/guides/deployment/database-migrations",
- "title": "Database Migrations"
- },
- {
- "url": "https://supabase.com/docs/guides/deployment/managing-environments",
- "title": "Managing Environments"
- }
- ],
- "resultChars": 66910
- }
- ]
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 434468,
+ "outputTokens": 5421,
+ "cachedInputTokens": 409308,
+ "cacheCreationInputTokens": 21397,
+ "costUsd": 0.49331424999999995
},
+ "durationMs": 179864,
"prompt": "Add a description text column to the `products` table in my local Supabase stack",
"promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md",
"attempts": 1,
@@ -208,12 +178,12 @@
{
"name": "cron command enqueues to the 'tasks' queue",
"passed": true,
- "notes": "queue depth 0 -> 1"
+ "notes": "queue depth 1 -> 2"
},
{
"name": "process-tasks function drains the queue",
"passed": true,
- "notes": "function removed the seeded message (id 10) from the queue"
+ "notes": "function removed the seeded message (id 42) from the queue"
}
],
"skills": {
@@ -222,74 +192,54 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"pgmq queues send read pop archive pgmq_public API\", limit: 6) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"pg_cron schedule job queue pgmq send message\", limit: 6) { nodes { title href content } } }",
"hasContent": true,
"pages": [
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart",
- "title": "Quickstart"
- },
{
"url": "https://supabase.com/docs/guides/queues/pgmq",
"title": "PGMQ Extension"
},
{
- "url": "https://supabase.com/docs/guides/queues",
- "title": "Supabase Queues"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net",
+ "title": "pg_net: Async Networking"
},
{
- "url": "https://supabase.com/docs/guides/queues/api",
- "title": "API"
+ "url": "https://supabase.com/docs/guides/troubleshooting/pgcron-debugging-guide-n1KTaz",
+ "title": "pg_cron debugging guide"
},
{
- "url": "https://supabase.com/docs/guides/queues/expose-self-hosted-queues",
- "title": "Expose Queues for local and self-hosted Supabase"
- }
- ],
- "resultChars": 39340
- },
- {
- "source": "web_fetch",
- "query": "How to create/schedule a cron job named X running every minute, and how to schedule a job that calls a Supabase Queue send / edge function. Show exact SQL syntax for cron.schedule and cron.unschedule, and any notes about naming or the pg_cron version. Include the full code examples verbatim.",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/cron/quickstart.md"
- }
- ],
- "resultChars": 1475
- },
- {
- "source": "web_fetch",
- "query": "List any entries tagged breaking-change, and any entries related to Queues/pgmq, pg_cron/Cron, or Edge Functions runtime/deployment. Include dates and links.",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/cron",
+ "title": "Cron"
+ },
{
- "url": "https://supabase.com/changelog.md"
- }
- ],
- "resultChars": 8295
- },
- {
- "source": "web_fetch",
- "query": "What exactly changed about the delay parameter behavior in pgmq 1.5.1 versus 1.4.4? Quote the details precisely, including any impact on send()/send_batch() and what values of delay are affected.",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/cron/install",
+ "title": "Install"
+ },
{
- "url": "https://supabase.com/changelog/39378-potential-breaking-change-in-pgmq-from-1-4-4-to-1-5-1-and-temporary-halt-on-upgrade-for-existing-projects"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
+ "title": "Automatic embeddings"
}
],
- "resultChars": 659
+ "resultChars": 74253
}
]
},
+ "usage": {
+ "inputTokens": 3947465,
+ "outputTokens": 35662,
+ "cachedInputTokens": 3833530,
+ "cacheCreationInputTokens": 108881,
+ "costUsd": 3.5147612500000003
+ },
+ "durationMs": 668725,
"prompt": "I want to set up a recurring background workflow on my local Supabase stack.\n\nCan you set up a cron job called `enqueue-tasks` to run every minute and push a task into a queue called `tasks`? Then add a `process-tasks` edge function that reads messages off the `tasks` queue and removes them, so a scheduled worker can keep the backlog drained.",
"promptSourcePath": "evals/build-cli-003-pg-cron-queue-workflow/PROMPT.md",
"attempts": 1,
@@ -343,70 +293,24 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"restore pg_dump custom format dump into Supabase migrate existing postgres database\", limit: 6) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres",
- "title": "Migrate from Postgres to Supabase"
- },
- {
- "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/vercel-postgres",
- "title": "Migrate from Vercel Postgres to Supabase"
- },
- {
- "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/neon",
- "title": "Migrate from Neon to Supabase"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
- "title": "Restore a Platform Project to Self-Hosted"
- },
- {
- "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/heroku",
- "title": "Migrate from Heroku to Supabase"
- },
- {
- "url": "https://supabase.com/docs/guides/platform/migrating-within-supabase/backup-restore",
- "title": "Backup and Restore using the CLI"
- }
- ],
- "resultChars": 78095
- },
- {
- "source": "web_fetch",
- "query": "What are the exact recommended commands and flags for restoring a pg_dump dump into a Supabase Postgres database? Include any notes about roles, ownership, privileges, extensions, schemas to exclude, and disabling triggers.",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres.md"
- }
- ],
- "resultChars": 1424
- },
- {
- "source": "web_fetch",
- "query": "List any recent entries tagged breaking-change, especially anything related to the CLI, local development, `supabase start`, `supabase db` commands, database restores/migrations, or Postgres major versions.",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/changelog.md"
- }
- ],
- "resultChars": 1248
- }
- ]
+ "calls": []
},
+ "usage": {
+ "inputTokens": 807597,
+ "outputTokens": 13063,
+ "cachedInputTokens": 749979,
+ "cacheCreationInputTokens": 53304,
+ "costUsd": 1.0569264999999999
+ },
+ "durationMs": 227553,
"prompt": "I have an existing Postgres database I want to migrate to Supabase. There's a binary dump at `source.dump` in the current directory.\n\nCan you set up a local Supabase project and restore the dump into it?",
"promptSourcePath": "evals/build-database-001-migrate-postgres-to-supabase/PROMPT.md",
- "attempts": 1,
+ "attempts": 2,
"sourcePath": "claude-code-opus-5/build-database-001-migrate-postgres-to-supabase.json"
},
{
@@ -452,12 +356,12 @@
{
"name": "user A cannot force-read user B note",
"passed": true,
- "notes": "status=403"
+ "notes": "status=200"
},
{
"name": "user B cannot force-read user A note",
"passed": true,
- "notes": "status=403"
+ "notes": "status=200"
}
],
"skills": {
@@ -473,7 +377,7 @@
"calls": [
{
"source": "search_docs",
- "query": "{searchDocs(query:\"Edge Function auth user JWT createClient Authorization header RLS\", limit:5){nodes{title href content}}}",
+ "query": "{ searchDocs(query: \"Edge Function auth user JWT Authorization header RLS createClient\", limit: 4) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
@@ -489,21 +393,25 @@
"title": "Build a User Management App with Next.js"
},
{
- "url": "https://supabase.com/docs/guides/auth/choosing-a-server-package",
- "title": "Which package to use"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/error-codes",
- "title": "Error codes"
+ "url": "https://supabase.com/docs/guides/functions/auth-headers",
+ "title": "Authorization headers"
}
],
- "resultChars": 65767
+ "resultChars": 54154
}
]
},
+ "usage": {
+ "inputTokens": 1186785,
+ "outputTokens": 11822,
+ "cachedInputTokens": 1126604,
+ "cacheCreationInputTokens": 55595,
+ "costUsd": 1.2298787500000001
+ },
+ "durationMs": 192838,
"prompt": "I built an Edge Function called `private-notes` for showing a user's saved\nprivate notes.\n\nCan you check whether there's any way one user could see another user's notes?\n\nPlease fix and deploy it if needed.",
"promptSourcePath": "evals/build-functions-004-service-role-bypass/PROMPT.md",
- "attempts": 2,
+ "attempts": 1,
"sourcePath": "claude-code-opus-5/build-functions-004-service-role-bypass.json"
},
{
@@ -545,17 +453,17 @@
{
"name": "user with JWT reads only their own rows",
"passed": true,
- "notes": "status 200: [{\"user_id\":\"cff75a07-aaa5-4010-95bb-ed51fa7d82a8\",\"metric\":\"steps_a_ms6x4xfn\",\"value\":111}]"
+ "notes": "status 200: [{\"user_id\":\"a468b6fd-79eb-4ecb-be19-de117397fcaa\",\"metric\":\"steps_a_ms7qzro3\",\"value\":111}]"
},
{
"name": "user cannot read another user's rows by passing user_id",
"passed": true,
- "notes": "status 200: [{\"user_id\":\"cff75a07-aaa5-4010-95bb-ed51fa7d82a8\",\"metric\":\"steps_a_ms6x4xfn\",\"value\":111}]"
+ "notes": "status 200: [{\"user_id\":\"a468b6fd-79eb-4ecb-be19-de117397fcaa\",\"metric\":\"steps_a_ms7qzro3\",\"value\":111}]"
},
{
"name": "service key bypasses RLS to read the target user's rows",
"passed": true,
- "notes": "status 200: [{\"user_id\":\"e73e078a-fec3-4f26-9532-a1e6e6f32e83\",\"metric\":\"steps_b_ms6x4xfn\",\"value\":222}]"
+ "notes": "status 200: [{\"user_id\":\"f2ff5d1b-eb44-44c1-b8dd-62edc94d9099\",\"metric\":\"steps_b_ms7qzro3\",\"value\":222}]"
},
{
"name": "non-service key is not granted service access",
@@ -591,73 +499,97 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"edge function verify_jwt config functions auth service role key\", limit: 6) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"@supabase/server SDK edge functions\", limit: 8) { nodes { title href content } } }",
"hasContent": true,
"pages": [
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions",
+ "title": "Edge Functions"
+ },
{
"url": "https://supabase.com/docs/guides/functions/auth",
"title": "Securing Edge Functions"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-headers",
- "title": "Authorization headers"
+ "url": "https://supabase.com/docs/guides/functions/recursive-functions",
+ "title": "Recursive / Nested Function Calls"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
+ "url": "https://supabase.com/docs/reference/cli/supabase-functions",
+ "title": "Manage Supabase Edge functions"
},
{
- "url": "https://supabase.com/docs/guides/functions/function-configuration",
- "title": "Function Configuration"
+ "url": "https://supabase.com/docs/guides/getting-started/features",
+ "title": "Features"
},
{
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
+ "url": "https://supabase.com/docs/guides/database/secure-data",
+ "title": "Securing your data"
},
{
"url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
"title": "Integrating With Supabase Auth"
}
],
- "resultChars": 62524
+ "resultChars": 67090
},
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"@supabase/server package secret key publishable key API keys\", limit: 6) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"Edge Function verify JWT service role key apikey header authorization\", limit: 8) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
+ "title": "Envoy API Gateway"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
},
{
- "url": "https://supabase.com/docs/guides/auth/choosing-a-server-package",
- "title": "Which package to use"
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys",
+ "title": "Understanding API keys"
},
{
"url": "https://supabase.com/docs/guides/auth/signing-keys",
"title": "JWT Signing Keys"
},
{
- "url": "https://supabase.com/docs/guides/integrations/supabase-for-platforms",
- "title": "Supabase for Platforms"
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
},
{
- "url": "https://supabase.com/docs/guides/api/creating-routes",
- "title": "Creating API Routes"
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/error-codes",
+ "title": "Error codes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth-headers",
+ "title": "Authorization headers"
}
],
- "resultChars": 85604
+ "resultChars": 118701
}
]
},
+ "usage": {
+ "inputTokens": 3071259,
+ "outputTokens": 34956,
+ "cachedInputTokens": 2946881,
+ "cacheCreationInputTokens": 119900,
+ "costUsd": 3.1199204999999997
+ },
+ "durationMs": 575574,
"prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nOur product stores per-user metrics in the existing `user_stats` table.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.",
"promptSourcePath": "evals/build-functions-005-dual-auth-user-secret/PROMPT.md",
- "attempts": 1,
+ "attempts": 2,
"sourcePath": "claude-code-opus-5/build-functions-005-dual-auth-user-secret.json"
},
{
@@ -698,7 +630,7 @@
{
"name": "user A lists only own files",
"passed": true,
- "notes": "saw: 019fb0eb-a03d-7688-b099-e5a490624b08/receipt-alpha.pdf, 019fb0eb-a03d-7688-b099-e5a490624b08/receipt-beta.pdf"
+ "notes": "saw: 019fb3db-36f2-7251-ae52-6b7799110271/receipt-alpha.pdf, 019fb3db-36f2-7251-ae52-6b7799110271/receipt-beta.pdf"
},
{
"name": "user B cannot read user A files",
@@ -719,7 +651,7 @@
{
"name": "configured private per-user storage access",
"passed": true,
- "judgeNotes": "Meets all criteria: private user-files bucket, authenticated owner-scoped SELECT and INSERT policies with WITH CHECK on storage.objects, RLS kept enabled, and supabase-js createSignedUrl with expiry for temporary sharing. No disallowed public bucket, permissive policies, anon/public access policies, getPublicUrl sharing, or client service-role usage."
+ "judgeNotes": "Meets rubric: private bucket, owner-scoped SELECT and INSERT policies on storage.objects for authenticated users using foldername/auth.uid, RLS kept enabled, and supabase-js createSignedUrl with expiry for sharing. No disqualifying public bucket/public URL/service-role-client guidance."
}
],
"skills": {
@@ -734,18 +666,21 @@
"docs": {
"calls": [
{
- "source": "search_docs",
- "query": "{ searchDocs(query: \"storage RLS policies private bucket user folder auth.uid\", limit: 6) { nodes { title href content } } }",
+ "source": "web_fetch",
+ "query": "List any recent breaking changes or notable changes related to Storage buckets, storage RLS policies, signed URLs, bucket types (analytics/vector), or storage.objects owner columns. Include dates.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/storage/schema/helper-functions",
- "title": "Storage Helper Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
- "title": "Storage Buckets"
- },
+ "url": "https://supabase.com/changelog.md"
+ }
+ ],
+ "resultChars": 1334
+ },
+ {
+ "source": "search_docs",
+ "query": "{\n searchDocs(query: \"storage RLS policy user can only access own folder foldername auth.uid\", limit: 5) {\n nodes {\n title\n href\n content\n }\n }\n}",
+ "hasContent": true,
+ "pages": [
{
"url": "https://supabase.com/docs/guides/storage/security/access-control",
"title": "Storage Access Control"
@@ -755,38 +690,54 @@
"title": "Configure S3 Storage"
},
{
- "url": "https://supabase.com/docs/guides/local-development/database-migrations",
- "title": "Database migrations"
+ "url": "https://supabase.com/docs/guides/storage/debugging/error-codes",
+ "title": "Error Codes"
},
{
- "url": "https://supabase.com/docs/guides/security/product-security",
- "title": "Secure configuration of Supabase products"
- }
+ "url": "https://supabase.com/docs/guides/storage/security/ownership",
+ "title": "Ownership"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/third-party/clerk",
+ "title": "Clerk"
+ }
],
- "resultChars": 36724
+ "resultChars": 39031
},
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"createSignedUrl expiresIn temporary link download private bucket\", limit: 4) { nodes { title href content } } }",
+ "query": "{\n searchDocs(query: \"createSignedUrl signed URL expires storage javascript\", limit: 5) {\n nodes {\n title\n href\n content\n ... on ClientLibraryFunctionReference { methodName language }\n }\n }\n}",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsigneduploadurl"
+ "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsignedurl"
},
{
- "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsignedurl"
+ "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsignedurls"
},
{
- "url": "https://supabase.com/docs/reference/dart/file-buckets-createsignedurl"
+ "url": "https://supabase.com/docs/guides/storage/serving/downloads",
+ "title": "Serving assets from Storage"
},
{
- "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsignedurls"
+ "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsigneduploadurl"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/dart/file-buckets-createsignedurl"
}
],
- "resultChars": 3116
+ "resultChars": 7891
}
]
},
+ "usage": {
+ "inputTokens": 1734258,
+ "outputTokens": 16905,
+ "cachedInputTokens": 1656742,
+ "cacheCreationInputTokens": 73055,
+ "costUsd": 1.7612897499999995
+ },
+ "durationMs": 251192,
"prompt": "Our app lets signed-in users keep personal files like receipts and bank\nstatements. These files are private — a user must only ever be able to upload\nand download their own. The app uploads each file under a path that starts\nwith the owner's user id, e.g. `/receipt-march.pdf`.\n\nSet up a `user-files` bucket on our project and lock it down that way.\n\nUsers also sometimes share one of their files with someone else through a\ntemporary link that expires. Include the supabase-js code the app should use\nfor that.",
"promptSourcePath": "evals/build-storage-001-private-bucket-access/PROMPT.md",
"attempts": 1,
@@ -817,7 +768,7 @@
{
"name": "pgTAP test file(s) written under supabase/tests/",
"passed": true,
- "notes": "2 file(s): supabase/tests/002_memberships_isolation.test.sql, supabase/tests/001_tenant_isolation.test.sql"
+ "notes": "2 file(s): supabase/tests/002_membership_integrity_test.sql, supabase/tests/001_tenant_isolation_test.sql"
},
{
"name": "pgTAP isolation tests ran and pass",
@@ -827,7 +778,7 @@
{
"name": "agent correctly identifies the posts isolation bug from test results",
"passed": true,
- "judgeNotes": "The agent correctly identifies `posts` as having the tenant isolation flaw: authenticated members of any org can read posts from other orgs due to a missing `m.org_id = posts.org_id` predicate. It grounds this in the pgTAP failures and direct psql reproduction, and does not blame `notes` or dismiss the tests."
+ "judgeNotes": "Correctly identifies `posts` as the tenant isolation flaw, explains authenticated members can read posts from other orgs, grounds it in pgTAP failure output, and distinguishes `notes` as correctly isolated."
}
],
"skills": {
@@ -836,12 +787,21 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 652705,
+ "outputTokens": 15946,
+ "cachedInputTokens": 608713,
+ "cacheCreationInputTokens": 39947,
+ "costUsd": 0.97351225
+ },
+ "durationMs": 236473,
"prompt": "Can you audit the tenant isolation on our tables? Write some database tests covering both the happy path and the negative case, run them, and share the results.",
"promptSourcePath": "evals/build-tests-001-rls-tenant-isolation/PROMPT.md",
"attempts": 1,
@@ -878,12 +838,12 @@
{
"name": "HNSW index on the embedding column",
"passed": true,
- "notes": "CREATE INDEX document_sections_embedding_idx ON public.document_sections USING hnsw (embedding vector_ip_ops)"
+ "notes": "CREATE INDEX document_sections_embedding_hnsw_idx ON public.document_sections USING hnsw (embedding vector_ip_ops)"
},
{
"name": "index operator class matches the search operator",
"passed": true,
- "notes": "function operators: <#>\nindexes: CREATE INDEX document_sections_embedding_idx ON public.document_sections USING hnsw (embedding vector_ip_ops)"
+ "notes": "function operators: <#>\nindexes: CREATE INDEX document_sections_embedding_hnsw_idx ON public.document_sections USING hnsw (embedding vector_ip_ops)"
},
{
"name": "user A search returns only own sections, best match first",
@@ -908,51 +868,70 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"semantic search pgvector match_document_sections RLS embedding gte-small\", limit: 6) { nodes { title href content } } }",
- "hasContent": true,
- "pages": []
- },
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"semantic search pgvector match_document_sections RLS embedding gte-small edge function\", limit: 6) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"Supabase.ai gte-small embeddings edge function vector 384 dimensions\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/ai/hybrid-search",
- "title": "Hybrid search"
- },
- {
- "url": "https://supabase.com/docs/guides/ai/rag-with-permissions",
- "title": "RAG with Permissions"
+ "url": "https://supabase.com/docs/guides/ai/choosing-compute-addon",
+ "title": "Choosing your Compute Add-on"
},
{
- "url": "https://supabase.com/docs/guides/ai/semantic-search",
- "title": "Semantic search"
+ "url": "https://supabase.com/docs/guides/ai/concepts",
+ "title": "Concepts"
},
{
"url": "https://supabase.com/docs/guides/functions/examples/semantic-search",
"title": "Semantic Search"
},
{
- "url": "https://supabase.com/docs/guides/ai/vector-columns",
- "title": "Vector columns"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search",
+ "title": "Semantic search"
},
{
"url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
"title": "Automatic embeddings"
}
],
- "resultChars": 84107
+ "resultChars": 74041
+ },
+ {
+ "source": "search_docs",
+ "query": "{ searchDocs(query: \"RAG with permissions row level security vector match function security invoker\", limit: 3) { nodes { title href } } }",
+ "hasContent": false,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/ai/rag-with-permissions",
+ "title": "RAG with Permissions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/tables",
+ "title": "Tables and Data"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security"
+ }
+ ],
+ "resultChars": 389
}
]
},
+ "usage": {
+ "inputTokens": 1318761,
+ "outputTokens": 18268,
+ "cachedInputTokens": 1241201,
+ "cacheCreationInputTokens": 72177,
+ "costUsd": 1.5559567499999996
+ },
+ "durationMs": 273412,
"prompt": "We're adding semantic search to our internal knowledge base app. I already wrote the edge functions, but search doesn't work yet. Can you set up whatever the database needs to make search work end to end?\n\nSome documents are confidential, so users should only have access to documents they own.",
"promptSourcePath": "evals/build-vectors-001-rag-with-permissions/PROMPT.md",
"attempts": 1,
@@ -985,12 +964,12 @@
{
"name": "configured the Supabase Metrics API scrape correctly",
"passed": true,
- "judgeNotes": "Supabase scrape uses HTTPS, the required metrics path, basic_auth with password_file, targets the project ref on supabase.co, preserves the app job, and docker-compose mounts the secrets directory containing the password file."
+ "judgeNotes": "Meets all required criteria: HTTPS Supabase Metrics API scrape at /customer/v1/privileged/metrics for a supabase.co project target, uses basic_auth with password_file, preserves the app scrape, and docker-compose mounts the secrets directory containing that password file."
},
{
"name": "documented live deployment and verification steps",
"passed": true,
- "judgeNotes": "README includes Secret API key creation, matching secret file path, Compose Prometheus restart/reload guidance, and concrete verification via curl to the endpoint, Prometheus targets API, and Grafana dashboard."
+ "judgeNotes": "README includes steps to create a Supabase Secret API key, write it to the matching password_file path, start/reload/recreate the Compose stack as needed, and verify via Prometheus targets and PromQL. Auth endpoint and secret handling match the provided config."
}
],
"skills": {
@@ -1006,34 +985,38 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"Prometheus metrics endpoint project observability scrape\", limit: 8) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"Prometheus metrics endpoint project metrics scrape\", limit: 6) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-self-hosted",
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted",
"title": "Metrics API with Prometheus & Grafana (self-hosted)"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics",
- "title": "Metrics API"
- },
- {
- "url": "https://supabase.com/docs/guides/telemetry/metrics/vendor-agnostic",
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic",
"title": "Vendor-agnostic Metrics API setup"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-cloud",
- "title": "Metrics API with Grafana Cloud"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics",
+ "title": "Metrics API"
},
{
- "url": "https://supabase.com/docs/guides/platform/read-replicas",
- "title": "Read Replicas"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud",
+ "title": "Metrics API with Grafana Cloud"
}
],
- "resultChars": 32656
+ "resultChars": 19943
}
]
},
+ "usage": {
+ "inputTokens": 2594286,
+ "outputTokens": 29508,
+ "cachedInputTokens": 2500099,
+ "cacheCreationInputTokens": 89723,
+ "costUsd": 2.5714682499999992
+ },
+ "durationMs": 504745,
"prompt": "Can you wire my Supabase project metrics into our existing observability stack and document\nin the observability README what we need to do to make the config live?",
"promptSourcePath": "evals/deploy-database-001-prometheus-metrics/PROMPT.md",
"attempts": 1,
@@ -1091,59 +1074,37 @@
"docs": {
"calls": [
{
- "source": "search_docs",
- "query": "{ searchDocs(query: \"Edge Function secrets environment variables manage\", limit: 6) { nodes { title href content } } }",
+ "source": "web_fetch",
+ "query": "How do you set secrets/environment variables for deployed edge functions? What are the CLI commands, the default env file conventions, and any reserved/restricted secret names or gotchas?",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/database/secure-data",
- "title": "Securing your data"
- },
- {
- "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
- "title": "Automatic embeddings"
- },
- {
- "url": "https://supabase.com/docs/guides/troubleshooting/inspecting-edge-function-environment-variables-wg5qOQ",
- "title": "Inspecting edge function environment variables"
+ "url": "https://supabase.com/docs/guides/functions/secrets.md"
}
],
- "resultChars": 65698
+ "resultChars": 1113
},
{
- "source": "search_docs",
- "query": "{ searchDocs(query: \"config.toml edge_runtime.secrets env() local development\", limit: 3) { nodes { title href content } } }",
+ "source": "web_fetch",
+ "query": "List any breaking-change entries related to Edge Functions, function deployment, secrets, or the CLI.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
- },
- {
- "url": "https://supabase.com/docs/guides/deployment/branching/configuration",
- "title": "Configuration"
- },
- {
- "url": "https://supabase.com/docs/guides/local-development/managing-config",
- "title": "Managing config and secrets"
+ "url": "https://supabase.com/changelog.md"
}
],
- "resultChars": 18379
+ "resultChars": 1311
}
]
},
+ "usage": {
+ "inputTokens": 2076302,
+ "outputTokens": 19865,
+ "cachedInputTokens": 2007622,
+ "cacheCreationInputTokens": 64603,
+ "costUsd": 1.9593067500000005
+ },
+ "durationMs": 597487,
"prompt": "Our weather widget currently calls WeatherAPI straight from the browser, which\nleaks our API key. I want to move that behind a Supabase Edge Function called\n`weather` that holds the key server-side and proxies the request.\n\nThe function should read the key from an environment variable named\n`WEATHER_API_KEY`. Our key already lives in a local `.env` file at the project\nroot.\n\nDeploy the function to our project so it's live, and make sure the deployed\nfunction can actually read the key at runtime.",
"promptSourcePath": "evals/deploy-functions-001-edge-function-secrets/PROMPT.md",
"attempts": 1,
@@ -1199,20 +1160,16 @@
]
},
"docs": {
- "calls": [
- {
- "source": "web_fetch",
- "query": "Extract the full step-by-step instructions for self-hosting Supabase with Docker: how to obtain the docker directory, the .env file, which secrets must be generated/changed (JWT secret, anon/service keys, postgres password, dashboard credentials, secret_key_base, vault enc key, etc.), how to generate them, and any securing-your-services guidance. Include exact commands and env var names verbatim.",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/self-hosting/docker.md"
- }
- ],
- "resultChars": 4806
- }
- ]
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 2252749,
+ "outputTokens": 18436,
+ "cachedInputTokens": 2180480,
+ "cacheCreationInputTokens": 68202,
+ "costUsd": 1.9984425
},
+ "durationMs": 281135,
"prompt": "I'm moving off the hosted Supabase and running the whole thing myself on a VPS I\njust spun up. Can you get a Docker setup ready for me to copy onto the box?\n\nI don't need it running here, I'll do the actual bring-up once I'm on the\nserver. I just want everything in place and the secrets set up. Put it in a `supabase-docker/`\nfolder at the repo root so I can scp the whole thing across in one go.",
"promptSourcePath": "evals/deploy-self-hosting-001-docker-compose/PROMPT.md",
"attempts": 1,
@@ -1238,7 +1195,7 @@
],
"suite": "benchmark",
"interface": "mcp",
- "passed": false,
+ "passed": true,
"checks": [
{
"name": "victim session active before delete-account",
@@ -1259,8 +1216,7 @@
},
{
"name": "deleted user cannot sign back in",
- "passed": false,
- "notes": "deleted account can still sign in"
+ "passed": true
},
{
"name": "other users keep their sessions and access",
@@ -1269,7 +1225,7 @@
{
"name": "diagnosed and explained session revocation",
"passed": true,
- "judgeNotes": "Meets the rubric: identifies soft-delete-only root cause with no auth user/session revocation; implements real revocation by banning and deleting sessions/refresh tokens, plus RLS flag checks; consistently explains that stale JWTs remain valid for purely local validation until exp while its RLS fix closes the Data API path for covered tables; and correctly distinguishes publishable frontend keys with RLS from server-only secret/service_role-style keys that bypass RLS."
+ "judgeNotes": "The answer identifies the root cause: the old delete_account only tombstoned public.profiles and did not remove auth.users or revoke sessions/refresh tokens. It implements a real fix by deleting auth.sessions, relying on refresh token cascade, deleting auth.users, and adding cascade cleanup. It also adds RLS liveness checks against auth.users/profiles and auth.sessions, so its claim that the Data API path is closed to replayed unexpired JWTs is consistent with the implemented fix. It still correctly notes in the migration comments that already issued JWTs remain valid until expiry unless the data path checks session existence. It also correctly treats publishable keys as frontend-safe under user JWT/RLS and secret/service-role style keys as server-only and RLS-bypassing. No disqualifying claims are present."
}
],
"skills": {
@@ -1285,39 +1241,39 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"delete user account revoke sessions invalidate access token\", limit: 6) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"delete user account revoke sessions access token still valid after delete\", limit: 6) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
"url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows",
"title": "OAuth 2.1 Flows"
},
- {
- "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers",
- "title": "Multiple SSO Providers"
- },
{
"url": "https://supabase.com/docs/guides/auth/sessions",
"title": "User sessions"
},
- {
- "url": "https://supabase.com/docs/guides/platform/temporary-access",
- "title": "Temporary access"
- },
{
"url": "https://supabase.com/docs/guides/auth/managing-user-data",
"title": "User Management"
},
+ {
+ "url": "https://supabase.com/docs/guides/platform/temporary-access",
+ "title": "Temporary access"
+ },
{
"url": "https://supabase.com/docs/guides/resources/glossary",
"title": "Glossary"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers",
+ "title": "Multiple SSO Providers"
}
],
"resultChars": 86320
},
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"publishable key secret key API keys migration anon service_role\", limit: 6) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"publishable key secret key API keys migration anon service_role\", limit: 8) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
@@ -1343,455 +1299,606 @@
{
"url": "https://supabase.com/docs/guides/auth/quickstarts/with-expo-react-native-social-auth",
"title": "Build a Social Auth App with Expo React Native"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-sveltekit",
+ "title": "Build a User Management App with SvelteKit"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-solidjs",
+ "title": "Build a User Management App with SolidJS"
}
],
- "resultChars": 166856
+ "resultChars": 230030
},
{
"source": "web_fetch",
- "query": "Extract the FULL text/content of this page verbatim as much as possible. I need details on: publishable key vs secret key, which Postgres role each maps to (anon, service_role, authenticated), RLS enforcement vs bypass, whether keys are JWTs or opaque, rotation/revocation, multiple keys, disabling keys, legacy anon/service_role key deprecation timeline, apikey vs Authorization Bearer header behavior, auth.uid()/auth.jwt() implications, and any links to migration guides.",
+ "query": "Extract the FULL text of this page verbatim (or as close as possible), especially anything about: publishable keys sb_publishable_, secret keys sb_secret_, which key is safe in browsers, Postgres roles (anon, authenticated, service_role), RLS bypass, whether these keys are JWTs, asymmetric/local verification vs auth server call, revocation, rotation, legacy anon/service_role JWT keys, coexistence and deprecation dates, auth.role(), auth.uid(), policies TO anon.",
"hasContent": true,
"pages": [
{
"url": "https://supabase.com/docs/guides/api/api-keys.md"
}
],
- "resultChars": 3025
+ "resultChars": 1685
},
{
"source": "web_fetch",
- "query": "Extract the full content verbatim as much as possible. I need: step-by-step migration, deprecation timeline/dates for legacy anon and service_role keys, gotchas, clients that verify JWT locally, apikey vs Authorization Bearer header behavior, RLS behavior changes, role mapping (anon/authenticated/service_role), whether publishable keys resolve to anon and what happens after sign-in, rotation/revocation, multiple keys, disabling keys independently.",
+ "query": "Extract the full text verbatim, especially anything about publishable keys, secret keys, anon, service_role, RLS bypass, roles that requests map to, and which keys are safe to expose.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys.md"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api.md"
}
],
- "resultChars": 4100
+ "resultChars": 1302
},
{
"source": "web_fetch",
- "query": "Extract everything about deleting users, soft delete vs hard delete, banning users (banned_until), what happens to existing JWTs/sessions after deletion, and the \"Deleting users\" section verbatim. Also any mention of auth.admin.deleteUser shouldSoftDelete.",
+ "query": "Quote verbatim every sentence that mentions: JWT, verification, verified, asymmetric, symmetric, cached, cache, latency, revoke, revocation, rotate, rotation, disable, deprecat, 2026, auth server, GoTrue, RLS, bypassrls, anon role, authenticated role, service_role, auth.uid(), auth.role(), user access token, Authorization header. Include headings and bullet structure. Do not summarize - quote.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/auth/users.md"
+ "url": "https://supabase.com/docs/guides/api/api-keys.md"
}
],
- "resultChars": 593
+ "resultChars": 1572
},
{
"source": "web_fetch",
- "query": "Extract the full reference docs for auth.admin.deleteUser: signature, parameters (including shouldSoftDelete), notes/caveats verbatim.",
+ "query": "Find and quote verbatim all entries related to API keys, publishable keys, secret keys, JWT signing keys, legacy anon/service_role key deprecation. Include dates, titles, breaking-change tags, and any URLs.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/reference/javascript/auth-admin-deleteuser.md"
+ "url": "https://supabase.com/changelog.md"
}
],
- "resultChars": 215
+ "resultChars": 1735
},
{
"source": "web_fetch",
- "query": "Extract the full reference docs for auth.admin.deleteUser: signature, parameters (including shouldSoftDelete), notes/caveats verbatim.",
+ "query": "Extract everything about: access token JWT lifetime/expiry defaults, refresh tokens, auth.sessions table, session termination/revocation, what happens when a user is deleted or banned, how sessions are validated on API requests, session_id claim, signOut scopes, and any statement about JWTs being stateless/valid until expiry. Quote key sentences verbatim.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/reference/javascript/auth-admin-deleteuser"
+ "url": "https://supabase.com/docs/guides/auth/sessions.md"
}
],
- "resultChars": 706
+ "resultChars": 1868
},
{
"source": "web_fetch",
- "query": "Extract full reference docs for auth.admin.signOut: signature, parameters, the scope options (global, local, others), and all notes verbatim.",
+ "query": "Extract everything about: JWT claims (especially session_id, sub, aud, exp), default JWT expiry/TTL, where configured, how the Data API/PostgREST validates JWTs, whether any database/session lookup happens, revocation, and auth.jwt() helper. Quote key sentences verbatim.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/reference/javascript/auth-admin-signout"
+ "url": "https://supabase.com/docs/guides/auth/jwts.md"
}
],
- "resultChars": 928
+ "resultChars": 1359
},
{
"source": "web_fetch",
- "query": "Extract the full content verbatim as much as possible. Focus on: publishable key vs secret key definitions, which Postgres role each maps to (anon, authenticated, service_role), RLS enforced vs bypassed, BYPASSRLS, whether keys are JWTs or opaque, what happens to the role when a user signs in, apikey vs Authorization Bearer header, rotation/revocation, creating multiple named keys, disabling/deleting keys, legacy key deprecation timeline, and auth.uid()/auth.jwt() notes.",
+ "query": "Extract everything verbatim about signOut scopes (global, local, others), what signOut does to refresh tokens vs access tokens, and any note that access tokens remain valid until they expire.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/getting-started/api-keys.md"
+ "url": "https://supabase.com/docs/guides/auth/signout.md"
}
],
- "resultChars": 2479
+ "resultChars": 960
},
{
"source": "web_fetch",
- "query": "List every changelog entry that mentions API keys, publishable keys, secret keys, sb_publishable, sb_secret, JWT signing keys, or legacy anon/service_role key deprecation. Include dates and any deprecation timeline dates verbatim.",
+ "query": "Extract everything about: deleting users (hard vs soft delete), auth.users columns including deleted_at and banned_until, banning users, cascading deletes to sessions/identities, and the auth.users schema. Quote key sentences verbatim.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/changelog.md"
+ "url": "https://supabase.com/docs/guides/auth/users.md"
}
],
- "resultChars": 1334
+ "resultChars": 668
},
{
"source": "web_fetch",
- "query": "Find and quote verbatim the auth config keys related to JWT expiry (jwt_expiry), refresh token rotation, refresh_token_reuse_interval, and any session timebox / inactivity timeout keys, including their default values.",
+ "query": "Extract verbatim everything about auth.admin.deleteUser: signature, parameters (id, shouldSoftDelete), what soft delete means, permissions required (service_role), and any notes about sessions or tokens.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/local-development/cli/config.md"
+ "url": "https://supabase.com/docs/reference/javascript/auth-admin-deleteuser"
}
],
- "resultChars": 215
+ "resultChars": 992
},
{
"source": "web_fetch",
- "query": "Quote verbatim the auth config keys for JWT expiry (auth.jwt_expiry), refresh token rotation (auth.enable_refresh_token_rotation), refresh_token_reuse_interval, and any session timebox/inactivity keys, with defaults.",
+ "query": "Extract verbatim: signature of auth.admin.signOut, parameters (jwt, scope), what it does, and any notes.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/cli/config.md"
+ "url": "https://supabase.com/docs/reference/javascript/auth-admin-signout"
}
],
- "resultChars": 215
+ "resultChars": 498
},
{
"source": "web_fetch",
- "query": "Quote VERBATIM, with no paraphrasing, these sections if present: (1) any table or list mapping keys to Postgres roles and RLS; (2) the section about the `anon` role and `authenticated` role; (3) the section titled \"Legacy API keys\" or similar including any deprecation dates; (4) any \"Limitations\" or \"Known limitations\" section; (5) anything about `auth.uid()`, `auth.jwt()`, claims, or JWTs; (6) anything about the apikey header and Authorization header. Output the raw markdown of those sections.",
+ "query": "Extract verbatim the attributes accepted, especially ban_duration / banned_until, and any notes about what banning does.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/getting-started/api-keys.md"
+ "url": "https://supabase.com/docs/reference/javascript/auth-admin-updateuserbyid"
}
],
- "resultChars": 1599
+ "resultChars": 866
},
{
"source": "web_fetch",
- "query": "Quote verbatim the config.toml auth keys: auth.jwt_expiry (with description and default), auth.enable_refresh_token_rotation, auth.refresh_token_reuse_interval. Also any session timebox/inactivity timeout keys.",
+ "query": "Output the complete raw markdown of this page from the first heading to the end, verbatim, including all tables, code blocks, admonitions/callouts, and links. Do not summarize or omit anything.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/local-development/cli/config"
+ "url": "https://supabase.com/docs/guides/api/api-keys.md"
}
],
- "resultChars": 899
+ "resultChars": 13491
},
{
"source": "web_fetch",
- "query": "Quote verbatim the \"Deleting users\" section and anything about JWT remaining valid after deletion, and any mention of soft delete or signing users out.",
+ "query": "Extract verbatim anything about deleting users, cascading foreign keys to auth.users, ON DELETE CASCADE, and the recommended way to delete a user's data.",
"hasContent": true,
"pages": [
{
"url": "https://supabase.com/docs/guides/auth/managing-user-data.md"
}
],
- "resultChars": 534
+ "resultChars": 1330
},
{
"source": "web_search",
- "query": "Supabase changelog publishable secret API keys general availability legacy anon service_role deprecation 2026",
+ "query": "Supabase GoTrue banned_until existing access token still valid until expiry ban user",
"hasContent": false,
"pages": [
{
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys | Supabase Docs"
+ "url": "https://supabase.com/docs/guides/auth/managing-user-data",
+ "title": "User Management | Supabase Docs"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys | Supabase Docs"
+ "url": "https://supabase.com/docs/guides/platform/temporary-access",
+ "title": "Temporary access | Supabase Docs"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/rotating-anon-service-and-jwt-secrets-1Jq6yd",
- "title": "Supabase Docs | Troubleshooting | Rotating Anon, Service, and JWT Secrets"
+ "url": "https://supabase.com/docs/guides/auth/sessions",
+ "title": "User sessions | Supabase Docs"
},
{
- "url": "https://supabase.com/changelog/29260-upcoming-changes-to-supabase-api-keys",
- "title": "Upcoming changes to Supabase API Keys · Changelog"
+ "url": "https://supabase.com/docs/reference/self-hosting-auth/introduction",
+ "title": "Self-Hosting | Supabase Docs"
},
{
- "url": "https://supabase.com/changelog?next=Y3Vyc29yOnYyOpK0MjAyNC0wOS0xM1QxNTowMDoyOVrOAG2JYw%3D%3D&restPage=2",
- "title": "Changelog"
- },
+ "url": "https://supabase.com/docs/guides/auth/troubleshooting",
+ "title": "Supabase Docs | Auth Troubleshooting"
+ }
+ ],
+ "resultChars": 2842
+ },
+ {
+ "source": "web_fetch",
+ "query": "Reproduce VERBATIM the full sections about: (1) how long sessions/access tokens live and where the JWT expiry setting is configured in the dashboard/CLI, (2) the exact paragraph(s) discussing \"Why is the user still logged in after signing out\" / how to check session_id against auth.sessions, including any SQL/RLS example, (3) any statement about whether Supabase automatically checks the session still exists. Output the raw text, do not summarize.",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/auth/sessions.md"
+ }
+ ],
+ "resultChars": 1278
+ },
+ {
+ "source": "web_search",
+ "query": "Supabase delete account flow Edge Function service_role auth.admin.deleteUser recommended pattern SECURITY DEFINER cannot delete auth.users",
+ "hasContent": false,
+ "pages": [
{
- "url": "https://supabase.com/changelog/42949-breaking-change-removing-access-to-openapi-spec-via-the-anon-key",
- "title": "Breaking Change: Removing access to OpenAPI spec via the anon key · Changelog"
+ "url": "https://supabase.com/docs/reference/javascript/auth-admin-deleteuser",
+ "title": "JavaScript: deleteUser | Supabase Docs"
},
{
- "url": "https://supabase.com/docs/guides/database/secure-data",
- "title": "Securing your data | Supabase Docs"
+ "url": "https://supabase.com/docs/guides/auth/managing-user-data",
+ "title": "User Management | Supabase Docs"
},
{
- "url": "https://supabase.com/docs/guides/api/creating-routes",
- "title": "Creating API Routes | Supabase Docs"
+ "url": "https://supabase.com/docs/reference/swift/auth-admin-deleteuser",
+ "title": "Swift API Reference | Supabase Docs"
}
],
- "resultChars": 2967
+ "resultChars": 2775
},
{
"source": "web_fetch",
- "query": "List any entries (with dates) about session revocation, sign out, user deletion, JWT expiry, asymmetric JWT signing keys, or auth.sessions. Quote the entry titles and dates.",
+ "query": "Output the complete raw markdown of this page verbatim, including all tables, code blocks, callouts, and links. Do not summarize. Pay special attention to anything about RLS policy changes, `TO anon`, `auth.role()`, roles, rotation, disabling legacy keys, and caching/verification.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/changelog.md"
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys.md"
}
],
- "resultChars": 1335
+ "resultChars": 13041
},
{
"source": "web_fetch",
- "query": "Quote verbatim the entire changelog entry, especially: publication date, the timeline with all dates, description of publishable and secret keys, role mapping, RLS, revocation/rotation, multiple keys, and any statement about legacy key deprecation.",
+ "query": "List every entry mentioning auth, sessions, JWT, refresh tokens, signing keys, or asymmetric JWTs — especially anything tagged breaking-change. Include dates and titles verbatim.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/changelog/29260-upcoming-changes-to-supabase-api-keys"
+ "url": "https://supabase.com/changelog.md"
}
],
- "resultChars": 215
+ "resultChars": 1393
},
{
- "source": "web_fetch",
- "query": "Quote verbatim the list of claims in a Supabase access token (especially session_id), and anything about JWT expiry defaults, revocation, and that JWTs cannot be revoked before expiry.",
- "hasContent": true,
+ "source": "web_search",
+ "query": "Supabase auth.users deleted_at soft delete gotrue what happens obfuscates email anonymized",
+ "hasContent": false,
"pages": [
{
- "url": "https://supabase.com/docs/guides/auth/jwts.md"
+ "url": "https://supabase.com/docs/guides/auth/managing-user-data",
+ "title": "User Management | Supabase Docs"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/self-hosting-auth/deletes-a-user",
+ "title": "Supabase API reference - Deletes a user"
}
],
- "resultChars": 911
+ "resultChars": 2631
},
{
"source": "web_fetch",
- "query": "Quote verbatim anything about: the anon and authenticated roles, service_role bypassing RLS / BYPASSRLS, `TO authenticated` / `TO anon` policy role targeting, auth.uid(), auth.jwt(), and how API keys map to roles. Also any warnings about policies without a TO clause or about service_role.",
+ "query": "Extract verbatim the admin DELETE /admin/users/{user_id} endpoint docs: body params (should_soft_delete), auth requirements, description.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security.md"
+ "url": "https://supabase.com/docs/reference/self-hosting-auth/deletes-a-user"
}
],
- "resultChars": 1591
+ "resultChars": 656
},
{
"source": "web_fetch",
- "query": "Quote verbatim the entry for session_id and the exp claim, plus any note on which claims are guaranteed/required in Supabase access tokens.",
+ "query": "Extract verbatim the documentation for auth.jwt() and auth.uid() helper functions, including what auth.jwt() returns, examples with ->> claim extraction, and any notes about which claims are available (session_id, app_metadata, user_metadata).",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/auth/jwt-fields.md"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security.md"
}
],
- "resultChars": 530
+ "resultChars": 1243
},
{
"source": "web_search",
- "query": "site:supabase.com/changelog sb_publishable secret API keys",
+ "query": "Supabase auth.sessions foreign key user_id ON DELETE CASCADE refresh_tokens schema",
"hasContent": false,
"pages": [
{
- "url": "https://supabase.com/changelog/29260-upcoming-changes-to-supabase-api-keys",
- "title": "Upcoming changes to Supabase API Keys · Changelog"
- },
- {
- "url": "https://supabase.com/changelog?next=Y3Vyc29yOnYyOpK0MjAyNC0wOS0yM1QwNzowMzozNVrOAG46dg%3D%3D&restPage=2",
- "title": "Changelog"
- },
- {
- "url": "https://supabase.com/changelog/42949-breaking-change-removing-access-to-openapi-spec-via-the-anon-key",
- "title": "Breaking Change: Removing access to OpenAPI spec via the anon key · Changelog"
+ "url": "https://supabase.com/docs/guides/auth/managing-user-data",
+ "title": "User Management | Supabase Docs"
},
{
- "url": "https://supabase.com/changelog/29289-supabase-auth-asymmetric-keys-support-in-2025",
- "title": "Supabase Auth: Asymmetric Keys support in 2025 · Changelog"
+ "url": "https://supabase.com/docs/guides/auth/sessions",
+ "title": "User sessions | Supabase Docs"
},
{
- "url": "https://supabase.com/changelog/46458-passkeys-for-supabase-auth-beta",
- "title": "Passkeys for Supabase Auth (Beta) · Changelog"
+ "url": "https://supabase.com/docs/guides/troubleshooting/dashboard-errors-when-managing-users-N1ls4A",
+ "title": "Supabase Docs | Troubleshooting | Errors when creating / updating / deleting users"
},
{
- "url": "https://supabase.com/changelog/43465-developer-update-march-2026",
- "title": "Developer Update - March 2026 · Changelog"
- },
+ "url": "https://supabase.com/docs/guides/auth",
+ "title": "Auth | Supabase Docs"
+ }
+ ],
+ "resultChars": 2838
+ },
+ {
+ "source": "web_search",
+ "query": "Supabase publishable key auth.role() returns null RLS policy \"TO anon\" breaks new API keys",
+ "hasContent": false,
+ "pages": [
{
- "url": "https://supabase.com/changelog/18972-edge-functions-secrets-should-now-get-updated-upon-resetting-db-password-or-jwt",
- "title": "Edge Functions secrets should now get updated upon resetting DB password or JWT secret · Changelog"
+ "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
+ "title": "Supabase Docs | Troubleshooting | Why is my service role key client getting RLS errors or not returning data?"
},
{
- "url": "https://supabase.com/changelog/45702-developer-update-may-2026",
- "title": "Developer Update - May 2026 · Changelog"
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys",
+ "title": "Understanding API keys | Supabase Docs"
},
{
- "url": "https://supabase.com/changelog/29494-supabase-platform-access-control-project-permissions-breaking-changes-on-october",
- "title": "Supabase Platform Access Control: Project Permissions Breaking Changes on October 15, 2024 · Changelog"
+ "url": "https://supabase.com/docs/guides/database/secure-data",
+ "title": "Securing your data | Supabase Docs"
},
{
- "url": "https://supabase.com/changelog/46346-feature-preview-temporary-token-based-database-access",
- "title": "Feature Preview: Temporary token-based database access · Changelog"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security | Supabase Docs"
}
],
- "resultChars": 2996
+ "resultChars": 2914
},
{
- "source": "search_docs",
- "query": "{ searchDocs(query: \"delete user account revoke sessions sign out all devices\", limit: 8) { nodes { title href content } } }",
- "hasContent": true,
+ "source": "web_search",
+ "query": "Supabase secret key sb_secret_ \"not a JWT\" verification opaque key lookup cached revocation propagation",
+ "hasContent": false,
"pages": [
{
- "url": "https://supabase.com/docs/guides/auth/passkeys",
- "title": "Passkey authentication"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication | Supabase Docs"
},
{
- "url": "https://supabase.com/docs/reference/javascript/auth-signout"
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys",
+ "title": "Understanding API keys | Supabase Docs"
},
{
- "url": "https://supabase.com/docs/reference/javascript/auth-admin-signout"
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables | Supabase Docs"
},
{
- "url": "https://supabase.com/docs/guides/auth/managing-user-data",
- "title": "User Management"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/signout",
- "title": "Signing out"
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys | Supabase Docs"
},
{
- "url": "https://supabase.com/docs/guides/auth/auth-email-passwordless",
- "title": "Passwordless email logins"
+ "url": "https://supabase.com/docs/guides/troubleshooting/performing-administration-tasks-on-the-server-side-with-the-servicerole-secret-BYM4Fa",
+ "title": "Supabase Docs | Troubleshooting | Performing administration tasks on the server side with a secret key"
},
{
- "url": "https://supabase.com/docs/reference/swift/auth-signout",
- "title": "signOut()"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys",
+ "title": "JWT Signing Keys | Supabase Docs"
},
{
- "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers",
- "title": "Multiple SSO Providers"
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions | Supabase Docs"
}
],
- "resultChars": 55523
+ "resultChars": 2984
},
{
- "source": "search_docs",
- "query": "{ searchDocs(query: \"ban user banned_until block user access token\", limit: 8) { nodes { title href } } }",
+ "source": "web_search",
+ "query": "supabase auth \"banned_until\" refresh token grant \"user_banned\" error 403 IsBanned refresh",
"hasContent": false,
"pages": [
{
- "url": "https://supabase.com/docs/guides/platform/temporary-access",
- "title": "Temporary access"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/jwt-fields",
- "title": "JWT Claims Reference"
- },
- {
- "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers",
- "title": "Multiple SSO Providers"
+ "url": "https://supabase.com/docs/guides/auth/debugging/error-codes",
+ "title": "Error Codes | Supabase Docs"
},
{
- "url": "https://supabase.com/docs/guides/auth/auth-anonymous",
- "title": "Anonymous Sign-Ins"
+ "url": "https://supabase.com/docs/guides/auth/troubleshooting",
+ "title": "Supabase Docs | Auth Troubleshooting"
},
{
- "url": "https://supabase.com/docs/guides/auth/sessions",
- "title": "User sessions"
+ "url": "https://supabase.com/docs/guides/auth/managing-user-data",
+ "title": "User Management | Supabase Docs"
}
],
- "resultChars": 582
+ "resultChars": 2582
},
{
"source": "web_fetch",
- "query": "Quote the entire entry verbatim including publication date, timeline dates, key descriptions, role mapping, RLS notes, rotation/revocation, and legacy key deprecation statements.",
+ "query": "Extract verbatim the entries for user_banned, session_not_found, refresh_token_not_found, refresh_token_already_used, user_not_found, and bad_jwt — including HTTP status codes and descriptions.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/changelog/29260-upcoming-changes-to-supabase-api-keys"
+ "url": "https://supabase.com/docs/guides/auth/debugging/error-codes.md"
}
],
- "resultChars": 215
+ "resultChars": 958
},
{
"source": "web_fetch",
- "query": "Quote verbatim the table rows / descriptions for these error codes: session_not_found, user_banned, refresh_token_not_found, refresh_token_already_used, session_expired, user_not_found, bad_jwt.",
+ "query": "Output verbatim the parts explaining how publishable and secret keys are verified/validated by the API gateway (opaque string matching? mapping to a pre-signed JWT? role mapping?), how they map to Postgres roles anon/authenticated/service_role, what happens when a publishable key is combined with a user access token, and anything about asymmetric ES256/JWKS verification, caching, and revocation.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/auth/debugging/error-codes.md"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys.md"
}
],
- "resultChars": 1077
+ "resultChars": 1772
},
{
"source": "web_fetch",
- "query": "Quote the attributes list for updateUserById, especially ban_duration - its type, description, and accepted values (e.g. 'none', '24h').",
+ "query": "Quote verbatim the explanation of why a service_role/secret key client hits RLS: which header determines the Postgres role (apikey vs Authorization), what happens when a user JWT is also present, and any mention of publishable/secret keys.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/reference/javascript/auth-admin-updateuserbyid"
+ "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z"
}
],
- "resultChars": 843
+ "resultChars": 1016
},
{
"source": "web_fetch",
- "query": "Quote verbatim any warnings about getSession vs getUser vs getClaims on the server, and why getUser must be used (revalidating the token with the Auth server).",
+ "query": "Output the complete raw markdown of this page verbatim, including all tables, code blocks and callouts. Do not summarize.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/auth/server-side/nextjs.md"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api.md"
+ }
+ ],
+ "resultChars": 18178
+ },
+ {
+ "source": "web_search",
+ "query": "Supabase RLS policy check auth.jwt() ->> 'session_id' exists in auth.sessions security definer permission denied for table sessions",
+ "hasContent": false,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security | Supabase Docs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/rls-performance-and-best-practices-Z5Jjwv",
+ "title": "Supabase Docs | Troubleshooting | RLS Performance and Best Practices"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
+ "title": "Token Security and Row Level Security | Supabase Docs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
+ "title": "Supabase Docs | Troubleshooting | Why is my service role key client getting RLS errors or not returning data?"
+ },
+ {
+ "url": "https://supabase.com/features/row-level-security",
+ "title": "Authorization via Row Level Security | Supabase Features"
}
],
- "resultChars": 1190
+ "resultChars": 2927
},
{
"source": "web_fetch",
- "query": "Quote verbatim the description of getClaims: when it verifies locally (asymmetric JWT) vs calls the Auth server, and any caveats about revocation / trusting claims.",
+ "query": "Extract verbatim the causes and fixes for errors when deleting users, especially foreign key constraint violations (e.g. storage objects_owner_fkey, public tables without on delete cascade).",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/reference/javascript/auth-getclaims"
+ "url": "https://supabase.com/docs/guides/troubleshooting/dashboard-errors-when-managing-users-N1ls4A"
+ }
+ ],
+ "resultChars": 1187
+ },
+ {
+ "source": "web_search",
+ "query": "Supabase \"publishable key\" revoke rotate multiple publishable keys dashboard \"API Keys\" disable legacy keys date",
+ "hasContent": false,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/rotating-anon-service-and-jwt-secrets-1Jq6yd",
+ "title": "Supabase Docs | Troubleshooting | Rotating Anon, Service, and JWT Secrets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys",
+ "title": "Understanding API keys | Supabase Docs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/signing-keys",
+ "title": "JWT Signing Keys | Supabase Docs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys | Supabase Docs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication | Supabase Docs"
+ },
+ {
+ "url": "https://supabase.com/changelog/29260-upcoming-changes-to-supabase-api-keys",
+ "title": "Upcoming changes to Supabase API Keys · Changelog"
+ },
+ {
+ "url": "https://supabase.com/blog/supabase-security-2025-retro",
+ "title": "Supabase Security Retro: 2025"
}
],
- "resultChars": 907
+ "resultChars": 2958
},
{
"source": "web_fetch",
- "query": "Quote verbatim everything about the apikey header vs the Authorization header, publishable and secret keys, which Postgres role results, what happens when both a secret key in apikey and a user JWT in Authorization are sent, RLS enforcement, and verify_jwt.",
+ "query": "Quote verbatim the full announcement, especially: the timeline/date table, statements about publishable keys (how many, revocation), secret keys (multiple, custom role, instant revocation), whether keys are JWTs, Postgres roles, RLS, and any 'breaking change' labels or notes about what breaks.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/functions/auth-headers.md"
+ "url": "https://supabase.com/changelog/29260-upcoming-changes-to-supabase-api-keys"
+ }
+ ],
+ "resultChars": 215
+ },
+ {
+ "source": "web_search",
+ "query": "supabase github discussion publishable key \"request.jwt.claims\" OR \"auth.role()\" returns anon RLS policy still works new API keys",
+ "hasContent": false,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security | Supabase Docs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/rls-performance-and-best-practices-Z5Jjwv",
+ "title": "Supabase Docs | Troubleshooting | RLS Performance and Best Practices"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys",
+ "title": "Understanding API keys | Supabase Docs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
+ "title": "Token Security and Row Level Security | Supabase Docs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
+ "title": "Supabase Docs | Troubleshooting | Why is my service role key client getting RLS errors or not returning data?"
}
],
- "resultChars": 1519
+ "resultChars": 3144
},
{
"source": "web_fetch",
- "query": "Quote verbatim everything about anon/publishable/secret/service_role keys, which Postgres role each results in, RLS enforcement vs bypass, and the apikey vs Authorization header.",
+ "query": "Quote verbatim anything about: the anon and authenticated roles, `TO anon`, `TO authenticated`, auth.role(), auth.jwt(), whether auth.role() is deprecated, bypassing RLS with service_role / secret keys, and any mention of publishable or secret keys.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/api/securing-your-api.md"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security.md"
+ }
+ ],
+ "resultChars": 1309
+ },
+ {
+ "source": "web_search",
+ "query": "Supabase secret key assign custom Postgres role instead of service_role dashboard \"API Keys\" 2026",
+ "hasContent": false,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys",
+ "title": "Understanding API keys | Supabase Docs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys | Supabase Docs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/secure-data",
+ "title": "Securing your data | Supabase Docs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables | Supabase Docs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/rotating-anon-service-and-jwt-secrets-1Jq6yd",
+ "title": "Supabase Docs | Troubleshooting | Rotating Anon, Service, and JWT Secrets"
+ },
+ {
+ "url": "https://supabase.com/changelog/29260-upcoming-changes-to-supabase-api-keys",
+ "title": "Upcoming changes to Supabase API Keys · Changelog"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication | Supabase Docs"
}
],
- "resultChars": 1341
+ "resultChars": 3075
},
{
"source": "web_fetch",
- "query": "Quote verbatim: any mention of (a) \"last used\" indicators for API keys; (b) what Postgres role applies when a SECRET key is sent together with a signed-in user's JWT; (c) whether a secret key can be configured to assume a role other than service_role; (d) the full \"Secret keys\" section; (e) the full \"Publishable key\" section; (f) anything about how many publishable keys can exist vs secret keys.",
+ "query": "Quote verbatim anything about the new API keys (publishable/secret), legacy anon and service_role key deprecation dates, disabling legacy keys, and RLS.",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/getting-started/api-keys.md"
+ "url": "https://supabase.com/blog/supabase-security-2025-retro"
}
],
- "resultChars": 1243
+ "resultChars": 979
}
]
},
+ "durationMs": 724302,
"prompt": "Last week support removed a user through our app's delete-account flow — the\napp calls the `delete_account` function over RPC as the signed-in user. This\nmorning that same person was back: still signed in, reading and saving their\ndata like nothing happened.\n\nFigure out why the account still works, fix the flow so a deleted account\nloses access, and tell me whether there is any window where they could still\nget in after the fix.\n\nOne more thing while you're at it: we're migrating off the legacy\nanon/service_role API keys to the new publishable and secret keys, and the\nteam isn't sure which one belongs in the frontend and what each means for\nRLS. Give us a quick rundown.",
"promptSourcePath": "evals/investigate-auth-001-deleted-user-access/PROMPT.md",
- "attempts": 2,
+ "attempts": 1,
"sourcePath": "claude-code-opus-5/investigate-auth-001-deleted-user-access.json"
},
{
@@ -1840,7 +1947,7 @@
{
"name": "diagnosed missing publication membership",
"passed": true,
- "judgeNotes": "Diagnosed the issue as orders missing from the supabase_realtime publication despite SUBSCRIBED status, applied ALTER PUBLICATION supabase_realtime ADD TABLE public.orders, and preserved RLS/policies and courier_locations. Did not blame or fix via client code/RLS/networking."
+ "judgeNotes": "Diagnosed missing orders table in supabase_realtime publication, applied ALTER PUBLICATION supabase_realtime ADD TABLE public.orders, preserved RLS/policies and existing courier_locations publication. Did not blame client/RLS as root cause or weaken security."
}
],
"skills": {
@@ -1856,7 +1963,7 @@
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"enable postgres changes realtime publication table\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"enable realtime postgres changes publication alter publication supabase_realtime\", limit: 4) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
@@ -1872,18 +1979,44 @@
"title": "Benchmarks"
},
{
- "url": "https://supabase.com/docs/guides/realtime/authorization",
- "title": "Realtime Authorization"
- },
+ "url": "https://supabase.com/docs/guides/platform/migrating-within-supabase/backup-restore",
+ "title": "Backup and Restore using the CLI"
+ }
+ ],
+ "resultChars": 98243
+ },
+ {
+ "source": "web_fetch",
+ "query": "What exact SQL is required to enable a table for postgres_changes realtime? Show the ALTER PUBLICATION statement and any REPLICA IDENTITY requirements. Also: what are the RLS requirements for the subscribing role, and does the channel still report SUBSCRIBED if the table is not in the publication?",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/realtime/postgres-changes.md"
+ }
+ ],
+ "resultChars": 1394
+ },
+ {
+ "source": "web_fetch",
+ "query": "List any breaking changes or recent changes related to Realtime, postgres_changes, or the supabase_realtime publication.",
+ "hasContent": true,
+ "pages": [
{
- "url": "https://supabase.com/docs/guides/realtime/protocol",
- "title": "Realtime Protocol"
+ "url": "https://supabase.com/changelog.md"
}
],
- "resultChars": 112153
+ "resultChars": 1285
}
]
},
+ "usage": {
+ "inputTokens": 993185,
+ "outputTokens": 7994,
+ "cachedInputTokens": 936167,
+ "cacheCreationInputTokens": 51958,
+ "costUsd": 1.0682690000000001
+ },
+ "durationMs": 350794,
"prompt": "Our dispatch dashboard shows incoming orders as they happen. The courier\nlocation feed on the same page updates live without problems, but new orders\nonly show up after a page refresh.\n\nThe dashboard uses supabase-js to subscribe to INSERT events on the `orders`\ntable through postgres_changes, the same way it subscribes to courier\nlocations. The channel's status callback logs SUBSCRIBED and there are no\nerrors in the browser console.\n\nFigure out why no order events ever arrive and fix it.",
"promptSourcePath": "evals/investigate-realtime-001-subscribed-no-events/PROMPT.md",
"attempts": 1,
@@ -1913,17 +2046,17 @@
{
"name": "identified image-transform and the recurring 503 pattern",
"passed": true,
- "judgeNotes": "Identified image-transform as the affected function and described the recurring HTTP 503 pattern across the morning of 2026-04-28, covering the 8 gateway failures from 07:00Z through 12:00Z. Also correctly avoided treating the older billing-webhook 503s as the main issue."
+ "judgeNotes": "Identified image-transform as affected and described eight recurring 503s across 07:00–12:00Z on 2026-04-28, while distinguishing unrelated billing-webhook 503s."
},
{
"name": "attributed recurring 503s to gateway/platform layer, not function code",
"passed": true,
- "judgeNotes": "Attributes the recurring image-transform 503s to the gateway/platform layer, explicitly stating they appear only in gateway/API logs and that failed requests never reached the function runtime. Grounds this in valid observations: no corresponding edge-function log rows for 503s, nearby successful invocations with 200s and normal runtimes, and distinguishes gateway 503s from avatar-upload's function-level 500."
+ "judgeNotes": "Attributes the recurring image-transform 503s to the gateway/platform layer before the function code ran, and grounds this in valid observations: gateway/API 503s have no corresponding edge-function invocation records, same deployment had interleaved successes, and avatar-upload's logged 500 is distinguished as a separate function-level error."
},
{
"name": "recommended a concrete next step",
"passed": true,
- "judgeNotes": "The assistant recommended several concrete next steps: find half-hourly triggers, obtain volume data for :00/:30 windows from Logs Explorer, flatten spikes with jitter/queueing, add retry with backoff, and triage correlated avatar-upload errors."
+ "judgeNotes": "The assistant recommended several concrete next steps, including querying current error rate, obtaining unsampled gateway logs for a specific time window, pulling Storage logs, checking platform-side worker/boot-time limits, and triaging correlated function errors separately."
}
],
"skills": {
@@ -1938,9 +2071,17 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 341090,
+ "outputTokens": 8233,
+ "cachedInputTokens": 300351,
+ "cacheCreationInputTokens": 36705,
+ "costUsd": 0.60620575
+ },
+ "durationMs": 132052,
"prompt": "Users have been reporting that image uploads are intermittently failing with server errors throughout the morning of `2026-04-28`.\n\nCan you investigate the project logs and tell me what is going on and what we\nshould do next?",
"promptSourcePath": "evals/investigate-reliability-003-edge-function-5xx-correlation/PROMPT.md",
- "attempts": 2,
+ "attempts": 1,
"sourcePath": "claude-code-opus-5/investigate-reliability-003-edge-function-5xx-correlation.json"
},
{
@@ -1994,7 +2135,7 @@
{
"name": "diagnosed RLS and added owner-scoped policies",
"passed": true,
- "judgeNotes": "Diagnosed RLS enabled with zero policies as deny-all for Data API/authenticated, kept RLS enabled, and created authenticated SELECT and INSERT policies scoped to user_id = auth.uid() with WITH CHECK for inserts. Did not use permissive/anon policies or disable RLS."
+ "judgeNotes": "Diagnosed RLS enabled with no policies as deny-all, created authenticated owner-scoped SELECT and INSERT policies using auth.uid() with WITH CHECK for inserts, and kept RLS enabled."
}
],
"skills": {
@@ -2003,41 +2144,53 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"row level security policy select insert auth.uid user_id private table\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"auth.uid() function definition request.jwt.claims sub returns null RLS\", limit: 6) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/api/securing-your-api",
- "title": "Securing your API"
+ "url": "https://supabase.com/docs/guides/ai/rag-with-permissions",
+ "title": "RAG with Permissions"
},
{
- "url": "https://supabase.com/docs/guides/realtime/getting_started",
- "title": "Getting Started with Realtime"
+ "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
+ "title": "Token Security and Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended",
- "title": "Advanced pgTAP Testing"
+ "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-select-returning-an-empty-data-array-and-i-have-data-in-the-table-xvOPgx",
+ "title": "Why is my select returning an empty data array and I have data in the table?"
},
{
- "url": "https://supabase.com/docs/guides/realtime/authorization",
- "title": "Realtime Authorization"
+ "url": "https://supabase.com/docs/reference/javascript/setauth"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/column-level-security",
- "title": "Column Level Security"
+ "url": "https://supabase.com/docs/reference/swift/auth-getclaims",
+ "title": "getClaims()"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/third-party/clerk",
+ "title": "Clerk"
}
],
- "resultChars": 81499
+ "resultChars": 37466
}
]
},
+ "usage": {
+ "inputTokens": 1714177,
+ "outputTokens": 15026,
+ "cachedInputTokens": 1641682,
+ "cacheCreationInputTokens": 67903,
+ "costUsd": 1.6445207499999996
+ },
+ "durationMs": 237203,
"prompt": "Our app lets signed-in users save bookmarks and view them on their dashboard. Bookmarks are stored in the `bookmarks` table and are private — a user must only ever see their own. \nUsers also need to be able to save new bookmarks from the app.\n\nI can see the rows when I query the table directly, but the dashboard shows an empty list for every user.\n\nFind out why the Data API returns nothing and fix it.",
"promptSourcePath": "evals/resolve-dataapi-001-empty-results/PROMPT.md",
"attempts": 1,
@@ -2087,7 +2240,7 @@
{
"name": "the avatar migration and history reconciliation were done via the Supabase CLI",
"passed": true,
- "judgeNotes": "Avatar migration was applied through `supabase db push` in #22, with output `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` History was reconciled by adding the missing local migration file `supabase/migrations/20240115000000_add_profile_bio.sql` in #20, after which `supabase migration list` (#21/#24) showed local and remote aligned. Only read-only `psql` inspections were used; no disallowed direct SQL mutation or prepared-statement workaround was seen."
+ "judgeNotes": "Applied pending avatar_url migration with `supabase db push` in action #16, which showed `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` Reconciled the orphan bio migration by adding local file `supabase/migrations/20240115000000_add_profile_bio.sql` (#14), then using the Supabase CLI workflow (`supabase db reset` locally in #15 and successful `supabase db push` in #16), so the remote history no longer blocked the push. Only read-only psql inspection was used; no disallowed direct SQL mutation or prepared-statement workaround seen."
}
],
"skills": {
@@ -2102,6 +2255,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 889490,
+ "outputTokens": 10680,
+ "cachedInputTokens": 829130,
+ "cacheCreationInputTokens": 56456,
+ "costUsd": 1.0545339999999999
+ },
+ "durationMs": 223487,
"prompt": "I'm trying to ship a migration to our hosted project and it's not working. Can you figure out what's wrong and get it deployed?",
"promptSourcePath": "evals/resolve-database-001-migration-history-mismatch/PROMPT.md",
"attempts": 1,
@@ -2157,12 +2318,20 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 638410,
+ "outputTokens": 5858,
+ "cachedInputTokens": 594654,
+ "cacheCreationInputTokens": 39581,
+ "costUsd": 0.7126622499999999
+ },
+ "durationMs": 98530,
"prompt": "My database CPU keeps spiking and the app gets slow when loading recent events for a user. Can you figure out what query is causing it and make the database change needed to fix it?\n\nEnd your turn with a short summary of what you changed and why.",
"promptSourcePath": "evals/resolve-performance-001-slow-query-cpu-spike/PROMPT.md",
"attempts": 1,
@@ -2234,13 +2403,20 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase",
- "supabase-postgres-best-practices"
+ "supabase"
]
},
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 1023077,
+ "outputTokens": 10753,
+ "cachedInputTokens": 961841,
+ "cacheCreationInputTokens": 56787,
+ "costUsd": 1.1275032500000002
+ },
+ "durationMs": 164757,
"prompt": "A customer reported that notes showed up in the wrong workspace.\n\nCan you investigate what is going on and fix it?",
"promptSourcePath": "evals/resolve-security-002-rls-cross-tenant-leak/PROMPT.md",
"attempts": 1,
@@ -2293,7 +2469,7 @@
{
"name": "REST API returns no todos to anonymous requests",
"passed": true,
- "notes": "0 rows"
+ "notes": "error 42501: permission denied for table todos"
},
{
"name": "REST API returns the todos to authenticated requests",
@@ -2306,8 +2482,41 @@
"loaded": []
},
"docs": {
- "calls": []
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "{ searchDocs(query: \"row level security policy authenticated role read only table\", limit: 4) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/api/securing-your-api",
+ "title": "Securing your API"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/column-level-security",
+ "title": "Column Level Security"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
+ "title": "Token Security and Row Level Security"
+ }
+ ],
+ "resultChars": 66384
+ }
+ ]
},
+ "usage": {
+ "inputTokens": 528869,
+ "outputTokens": 10084,
+ "cachedInputTokens": 498799,
+ "cacheCreationInputTokens": 26679,
+ "costUsd": 0.68593325
+ },
+ "durationMs": 399112,
"prompt": "We're kicking off a todos app and I want the Supabase side ready for the team\nto build on. Set it up the way we'd run it in development, with schema changes\ntracked as migrations so they can be reviewed and replayed.\n\nFor the first slice we just need a `todos` table. Todos aren't public: anyone\nsigned in can read all of them, but nothing should be writable through the API\nfor now. Add a couple of sample todos so there's something to look at.\n\nBefore you hand it back, make sure the running API actually behaves that way —\nsigned-in users get the todos, signed-out requests get nothing.",
"promptSourcePath": "evals/build-cli-001-bootstrap-app/PROMPT.md",
"attempts": 1,
@@ -2360,30 +2569,38 @@
"calls": [
{
"source": "search_docs",
- "query": "{searchDocs(query:\"declarative database schemas db diff generate migration\", limit:4){nodes{title href content}}}",
+ "query": "{ searchDocs(query: \"declarative database schema migrations db diff workflow\", limit: 4) { nodes { title href content } } }",
"hasContent": true,
"pages": [
- {
- "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas",
- "title": "Declarative database schemas"
- },
{
"url": "https://supabase.com/docs/guides/local-development/cli-workflows",
"title": "Local development workflow"
},
{
- "url": "https://supabase.com/docs/guides/deployment/database-migrations",
- "title": "Database Migrations"
+ "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers",
+ "title": "Multiple SSO Providers"
},
{
- "url": "https://supabase.com/docs/guides/deployment/managing-environments",
- "title": "Managing Environments"
+ "url": "https://supabase.com/docs/reference/cli/supabase-db-pull",
+ "title": "Pull schema from the remote database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations",
+ "title": "Database Migrations"
}
],
- "resultChars": 66910
+ "resultChars": 62949
}
]
},
+ "usage": {
+ "inputTokens": 364551,
+ "outputTokens": 5182,
+ "cachedInputTokens": 342720,
+ "cacheCreationInputTokens": 18581,
+ "costUsd": 0.43388025
+ },
+ "durationMs": 138818,
"prompt": "Add a description text column to the `products` table in my local Supabase stack",
"promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md",
"attempts": 1,
@@ -2427,7 +2644,7 @@
{
"name": "process-tasks function drains the queue",
"passed": true,
- "notes": "function removed the seeded message (id 36) from the queue"
+ "notes": "function removed the seeded message (id 65) from the queue"
}
],
"skills": {
@@ -2438,34 +2655,46 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"queues cron schedule pgmq edge function drain queue\", limit: 8) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"pg_cron schedule job queue pgmq send\", limit: 6) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
- "title": "Automatic embeddings"
+ "url": "https://supabase.com/docs/guides/queues/pgmq",
+ "title": "PGMQ Extension"
},
{
"url": "https://supabase.com/docs/guides/database/extensions/pg_net",
"title": "pg_net: Async Networking"
},
{
- "url": "https://supabase.com/docs/guides/functions/schedule-functions",
- "title": "Scheduling Edge Functions"
+ "url": "https://supabase.com/docs/guides/troubleshooting/pgcron-debugging-guide-n1KTaz",
+ "title": "pg_cron debugging guide"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart",
- "title": "Quickstart"
+ "url": "https://supabase.com/docs/guides/cron",
+ "title": "Cron"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/pgcron-debugging-guide-n1KTaz",
- "title": "pg_cron debugging guide"
- }
+ "url": "https://supabase.com/docs/guides/cron/install",
+ "title": "Install"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/schedule-functions",
+ "title": "Scheduling Edge Functions"
+ }
],
- "resultChars": 63907
+ "resultChars": 47601
}
]
},
+ "usage": {
+ "inputTokens": 1198095,
+ "outputTokens": 16421,
+ "cachedInputTokens": 1145665,
+ "cacheCreationInputTokens": 48757,
+ "costUsd": 1.30712875
+ },
+ "durationMs": 333147,
"prompt": "I want to set up a recurring background workflow on my local Supabase stack.\n\nCan you set up a cron job called `enqueue-tasks` to run every minute and push a task into a queue called `tasks`? Then add a `process-tasks` edge function that reads messages off the `tasks` queue and removes them, so a scheduled worker can keep the backlog drained.",
"promptSourcePath": "evals/build-cli-003-pg-cron-queue-workflow/PROMPT.md",
"attempts": 1,
@@ -2520,6 +2749,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 329296,
+ "outputTokens": 5806,
+ "cachedInputTokens": 310874,
+ "cacheCreationInputTokens": 15172,
+ "costUsd": 0.412304
+ },
+ "durationMs": 295974,
"prompt": "I have an existing Postgres database I want to migrate to Supabase. There's a binary dump at `source.dump` in the current directory.\n\nCan you set up a local Supabase project and restore the dump into it?",
"promptSourcePath": "evals/build-database-001-migrate-postgres-to-supabase/PROMPT.md",
"attempts": 1,
@@ -2568,12 +2805,12 @@
{
"name": "user A cannot force-read user B note",
"passed": true,
- "notes": "status=200"
+ "notes": "status=403"
},
{
"name": "user B cannot force-read user A note",
"passed": true,
- "notes": "status=200"
+ "notes": "status=403"
}
],
"skills": {
@@ -2581,8 +2818,45 @@
"loaded": []
},
"docs": {
- "calls": []
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "{\n searchDocs(query: \"Edge Function auth getUser Authorization header RLS user client\", limit: 5) {\n nodes {\n title\n href\n content\n }\n }\n}",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
+ "title": "Integrating With Supabase Auth"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
+ "title": "Why is my service role key client getting RLS errors or not returning data?"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs",
+ "title": "Build a User Management App with Next.js"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth-headers",
+ "title": "Authorization headers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
+ }
+ ],
+ "resultChars": 61921
+ }
+ ]
},
+ "usage": {
+ "inputTokens": 798375,
+ "outputTokens": 9141,
+ "cachedInputTokens": 755688,
+ "cacheCreationInputTokens": 38888,
+ "costUsd": 0.869042
+ },
+ "durationMs": 151332,
"prompt": "I built an Edge Function called `private-notes` for showing a user's saved\nprivate notes.\n\nCan you check whether there's any way one user could see another user's notes?\n\nPlease fix and deploy it if needed.",
"promptSourcePath": "evals/build-functions-004-service-role-bypass/PROMPT.md",
"attempts": 1,
@@ -2612,7 +2886,7 @@
"suite": "benchmark",
"interface": "cli",
"cliVersion": "2.109.1",
- "passed": true,
+ "passed": false,
"checks": [
{
"name": "seed rows present",
@@ -2622,42 +2896,42 @@
{
"name": "rejects request with no credentials",
"passed": true,
- "notes": "status 401: {\"error\":\"Unauthorized\"}"
+ "notes": "status 401: {\"error\":\"Missing credentials: send a user access token or the secret key\"}"
},
{
"name": "user with JWT reads only their own rows",
"passed": true,
- "notes": "status 200: [{\"user_id\":\"370cd0f2-cda6-44ce-afad-754f7b5fd3fb\",\"metric\":\"steps_a_ms6xp2i0\",\"value\":111}]"
+ "notes": "status 200: [{\"user_id\":\"b6fe2304-29ff-470e-9e3e-4ce6eb0b740a\",\"metric\":\"steps_a_ms7qze0p\",\"value\":111}]"
},
{
"name": "user cannot read another user's rows by passing user_id",
- "passed": true,
- "notes": "status 200: [{\"user_id\":\"370cd0f2-cda6-44ce-afad-754f7b5fd3fb\",\"metric\":\"steps_a_ms6xp2i0\",\"value\":111}]"
+ "passed": false,
+ "notes": "status 403: {\"error\":\"Not allowed to read another user's stats\"}"
},
{
"name": "service key bypasses RLS to read the target user's rows",
"passed": true,
- "notes": "status 200: [{\"user_id\":\"2b64c372-40da-4ea6-90cd-c4ac620fa7e7\",\"metric\":\"steps_b_ms6xp2i0\",\"value\":222}]"
+ "notes": "status 200: [{\"user_id\":\"dfc90d04-50ac-4076-b165-012785f8d9bf\",\"metric\":\"steps_b_ms7qze0p\",\"value\":222}]"
},
{
"name": "non-service key is not granted service access",
"passed": true,
- "notes": "status 401: {\"error\":\"Unauthorized\"}"
+ "notes": "status 401: {\"error\":\"Missing credentials: send a user access token or the secret key\"}"
},
{
"name": "rejects an unverified (forged) user token",
"passed": true,
- "notes": "status 401: {\"error\":\"Unauthorized\"}"
+ "notes": "status 401: {\"error\":\"Invalid or expired access token\"}"
},
{
"name": "a user token in the apikey slot is not treated as the service key",
"passed": true,
- "notes": "status 401: {\"error\":\"Unauthorized\"}"
+ "notes": "status 401: {\"error\":\"Missing credentials: send a user access token or the secret key\"}"
},
{
"name": "implementation uses @supabase/server",
- "passed": true,
- "notes": "imports @supabase/server / withSupabase"
+ "passed": false,
+ "notes": "hand-rolled (raw supabase-js or other) — this eval requires @supabase/server"
}
],
"skills": {
@@ -2665,41 +2939,16 @@
"loaded": []
},
"docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"@supabase/server package edge function api keys secret key publishable key\", limit: 6) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/choosing-a-server-package",
- "title": "Which package to use"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
- }
- ],
- "resultChars": 76864
- }
- ]
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 2471477,
+ "outputTokens": 34592,
+ "cachedInputTokens": 2402058,
+ "cacheCreationInputTokens": 65722,
+ "costUsd": 2.4958915000000004
},
+ "durationMs": 665714,
"prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nOur product stores per-user metrics in the existing `user_stats` table.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.",
"promptSourcePath": "evals/build-functions-005-dual-auth-user-secret/PROMPT.md",
"attempts": 2,
@@ -2743,7 +2992,7 @@
{
"name": "user A lists only own files",
"passed": true,
- "notes": "saw: 019fb0e9-cc49-7119-a6b5-8129b1bef946/receipt-alpha.pdf, 019fb0e9-cc49-7119-a6b5-8129b1bef946/receipt-beta.pdf"
+ "notes": "saw: 019fb3da-82d7-72ef-8298-b411fbe1c2f6/receipt-alpha.pdf, 019fb3da-82d7-72ef-8298-b411fbe1c2f6/receipt-beta.pdf"
},
{
"name": "user B cannot read user A files",
@@ -2764,7 +3013,7 @@
{
"name": "configured private per-user storage access",
"passed": true,
- "judgeNotes": "Meets requirements: private user-files bucket, authenticated owner-scoped SELECT and INSERT storage.objects policies with WITH CHECK, no RLS disabling or public access, and supabase-js createSignedUrl/createSignedUrls examples with expiries."
+ "judgeNotes": "Meets the rubric: creates a private user-files bucket, keeps RLS, defines authenticated owner-scoped SELECT and INSERT policies with matching WITH CHECK, and provides supabase-js createSignedUrl code with an expiry for temporary sharing. No public bucket, permissive policies, anon policies, getPublicUrl, or client-side service role usage."
}
],
"skills": {
@@ -2775,46 +3024,65 @@
"calls": [
{
"source": "search_docs",
- "query": "{\n searchDocs(query: \"storage RLS policy user id folder path createSignedUrl private bucket\", limit: 8) {\n nodes {\n title\n href\n content\n }\n }\n}",
+ "query": "query {\n searchDocs(query: \"storage RLS policy user folder owner private bucket\", limit: 6) {\n nodes {\n title\n href\n content\n }\n }\n}",
"hasContent": true,
"pages": [
- {
- "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
- "title": "Storage Buckets"
- },
{
"url": "https://supabase.com/docs/guides/storage/security/access-control",
"title": "Storage Access Control"
},
{
- "url": "https://supabase.com/docs/guides/security/product-security",
- "title": "Secure configuration of Supabase products"
+ "url": "https://supabase.com/docs/guides/storage/schema/helper-functions",
+ "title": "Storage Helper Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
+ "title": "Storage Buckets"
},
{
"url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
"title": "Configure S3 Storage"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/why-cant-i-uploadlistetc-my-public-bucket-Z6CmGt",
- "title": "Why can't I upload/list/etc my public bucket?"
+ "url": "https://supabase.com/docs/guides/security/product-security",
+ "title": "Secure configuration of Supabase products"
},
{
- "url": "https://supabase.com/docs/guides/storage/schema/helper-functions",
- "title": "Storage Helper Functions"
+ "url": "https://supabase.com/docs/guides/storage/schema/design",
+ "title": "The Storage Schema"
+ }
+ ],
+ "resultChars": 25024
+ },
+ {
+ "source": "search_docs",
+ "query": "query {\n createSigned: searchDocs(query: \"createSignedUrl signed URL expiresIn download\", limit: 3) {\n nodes { title href content }\n }\n}",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/storage/serving/image-transformations",
+ "title": "Storage Image Transformations"
},
{
- "url": "https://supabase.com/docs/guides/storage/serving/downloads",
- "title": "Serving assets from Storage"
+ "url": "https://supabase.com/docs/reference/dart/file-buckets-createsignedurl"
},
{
- "url": "https://supabase.com/docs/guides/auth/third-party/clerk",
- "title": "Clerk"
+ "url": "https://supabase.com/docs/reference/swift/storage-from-createsignedurl",
+ "title": "from.createSignedUrl()"
}
],
- "resultChars": 35640
+ "resultChars": 21648
}
]
},
+ "usage": {
+ "inputTokens": 862924,
+ "outputTokens": 15635,
+ "cachedInputTokens": 798422,
+ "cacheCreationInputTokens": 60707,
+ "costUsd": 1.18919275
+ },
+ "durationMs": 213888,
"prompt": "Our app lets signed-in users keep personal files like receipts and bank\nstatements. These files are private — a user must only ever be able to upload\nand download their own. The app uploads each file under a path that starts\nwith the owner's user id, e.g. `/receipt-march.pdf`.\n\nSet up a `user-files` bucket on our project and lock it down that way.\n\nUsers also sometimes share one of their files with someone else through a\ntemporary link that expires. Include the supabase-js code the app should use\nfor that.",
"promptSourcePath": "evals/build-storage-001-private-bucket-access/PROMPT.md",
"attempts": 1,
@@ -2845,17 +3113,17 @@
{
"name": "pgTAP test file(s) written under supabase/tests/",
"passed": true,
- "notes": "1 file(s): supabase/tests/tenant_isolation_test.sql"
+ "notes": "1 file(s): supabase/tests/tenant_isolation.test.sql"
},
{
"name": "pgTAP isolation tests ran and pass",
"passed": true,
- "notes": "10 passed, 3 failed"
+ "notes": "12 passed, 4 failed"
},
{
"name": "agent correctly identifies the posts isolation bug from test results",
"passed": true,
- "judgeNotes": "The agent correctly identifies `posts` as the table with the broken tenant isolation policy, grounds it in pgTAP failures showing cross-tenant reads, and distinguishes that `notes` passes. It treats the test results as authoritative and identifies the missing `m.org_id = posts.org_id` correlation as the root cause."
+ "judgeNotes": "The agent correctly identifies `posts` as having the broken tenant isolation policy, explains that authenticated users with any membership can read posts from other orgs, and grounds this in pgTAP failures and direct confirmation. It also correctly states `notes` isolation holds."
}
],
"skills": {
@@ -2865,6 +3133,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 363455,
+ "outputTokens": 13491,
+ "cachedInputTokens": 334948,
+ "cacheCreationInputTokens": 25259,
+ "costUsd": 0.6794697500000001
+ },
+ "durationMs": 184059,
"prompt": "Can you audit the tenant isolation on our tables? Write some database tests covering both the happy path and the negative case, run them, and share the results.",
"promptSourcePath": "evals/build-tests-001-rls-tenant-isolation/PROMPT.md",
"attempts": 1,
@@ -2933,30 +3209,38 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"gte-small embedding dimensions Supabase.ai Session edge function\", limit: 4) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"Supabase.ai Session gte-small embedding dimensions edge function\", limit: 4) { nodes { title href content } } }",
"hasContent": true,
"pages": [
- {
- "url": "https://supabase.com/docs/guides/functions/examples/semantic-search",
- "title": "Semantic Search"
- },
{
"url": "https://supabase.com/docs/guides/ai/semantic-search",
"title": "Semantic search"
},
{
- "url": "https://supabase.com/docs/guides/functions/ai-models",
- "title": "Running AI Models"
+ "url": "https://supabase.com/docs/guides/functions/examples/semantic-search",
+ "title": "Semantic Search"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/ai/concepts",
+ "title": "Concepts"
},
{
- "url": "https://supabase.com/docs/guides/ai/quickstarts/generate-text-embeddings",
- "title": "Generate Embeddings"
+ "url": "https://supabase.com/docs/guides/ai/choosing-compute-addon",
+ "title": "Choosing your Compute Add-on"
}
],
- "resultChars": 42731
+ "resultChars": 44417
}
]
},
+ "usage": {
+ "inputTokens": 1088280,
+ "outputTokens": 17271,
+ "cachedInputTokens": 1029626,
+ "cacheCreationInputTokens": 54720,
+ "costUsd": 1.3089029999999997
+ },
+ "durationMs": 249685,
"prompt": "We're adding semantic search to our internal knowledge base app. I already wrote the edge functions, but search doesn't work yet. Can you set up whatever the database needs to make search work end to end?\n\nSome documents are confidential, so users should only have access to documents they own.",
"promptSourcePath": "evals/build-vectors-001-rag-with-permissions/PROMPT.md",
"attempts": 1,
@@ -2989,12 +3273,12 @@
{
"name": "configured the Supabase Metrics API scrape correctly",
"passed": true,
- "judgeNotes": "Meets requirements: preserves app scrape, adds HTTPS Supabase Metrics API target with correct path and project host, uses basic_auth password_file, and docker-compose mounts the secrets directory containing that password file."
+ "judgeNotes": "Meets rubric: preserves app scrape, adds HTTPS Supabase Metrics API scrape at the correct path for a project supabase.co target, uses Basic Auth with password_file, and docker-compose mounts the secrets directory containing that file."
},
{
"name": "documented live deployment and verification steps",
"passed": true,
- "judgeNotes": "README includes creating a Supabase Secret API key, writing it to the mounted secret file, reloading Prometheus/Compose stack, and verifying via Prometheus targets and Grafana."
+ "judgeNotes": "README includes required live setup: create Supabase Secret API key, write it to the matching mounted password_file path, reload Prometheus, and verify via Prometheus targets/Grafana. Endpoint and auth match the config and no real secret is hardcoded."
}
],
"skills": {
@@ -3005,37 +3289,41 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"Prometheus metrics endpoint project observability\", limit: 6) { nodes { title href content } } }",
+ "query": "{searchDocs(query:\"Prometheus metrics endpoint scrape project metrics observability\",limit:6){nodes{title href content}}}",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-self-hosted",
- "title": "Metrics API with Prometheus & Grafana (self-hosted)"
- },
- {
- "url": "https://supabase.com/docs/guides/telemetry/metrics",
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics",
"title": "Metrics API"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/vendor-agnostic",
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic",
"title": "Vendor-agnostic Metrics API setup"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-cloud",
- "title": "Metrics API with Grafana Cloud"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted",
+ "title": "Metrics API with Prometheus & Grafana (self-hosted)"
},
{
- "url": "https://supabase.com/docs/guides/platform/read-replicas",
- "title": "Read Replicas"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud",
+ "title": "Metrics API with Grafana Cloud"
}
],
- "resultChars": 32656
+ "resultChars": 19943
}
]
},
+ "usage": {
+ "inputTokens": 1581072,
+ "outputTokens": 19202,
+ "cachedInputTokens": 1526601,
+ "cacheCreationInputTokens": 50797,
+ "costUsd": 1.5798267500000005
+ },
+ "durationMs": 369397,
"prompt": "Can you wire my Supabase project metrics into our existing observability stack and document\nin the observability README what we need to do to make the config live?",
"promptSourcePath": "evals/deploy-database-001-prometheus-metrics/PROMPT.md",
- "attempts": 1,
+ "attempts": 2,
"sourcePath": "claude-code-opus-5-no-skills/deploy-database-001-prometheus-metrics.json"
},
{
@@ -3086,7 +3374,7 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"edge function secrets environment variables set env-file deploy\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"Edge Functions manage secrets environment variables secrets set env-file\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
@@ -3094,26 +3382,34 @@
"title": "Environment Variables"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/inspecting-edge-function-environment-variables-wg5qOQ",
- "title": "Inspecting edge function environment variables"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-transcribe-speech",
- "title": "Transcription Telegram Bot"
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
},
{
"url": "https://supabase.com/docs/guides/deployment/branching/configuration",
"title": "Configuration"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-generate-speech-stream",
- "title": "Streaming Speech with ElevenLabs"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
+ "title": "Automatic embeddings"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/ephemeral-storage",
+ "title": "File Storage"
}
],
- "resultChars": 38347
+ "resultChars": 65222
}
]
},
+ "usage": {
+ "inputTokens": 1489415,
+ "outputTokens": 17191,
+ "cachedInputTokens": 1433508,
+ "cacheCreationInputTokens": 51759,
+ "costUsd": 1.4914697500000003
+ },
+ "durationMs": 426778,
"prompt": "Our weather widget currently calls WeatherAPI straight from the browser, which\nleaks our API key. I want to move that behind a Supabase Edge Function called\n`weather` that holds the key server-side and proxies the request.\n\nThe function should read the key from an environment variable named\n`WEATHER_API_KEY`. Our key already lives in a local `.env` file at the project\nroot.\n\nDeploy the function to our project so it's live, and make sure the deployed\nfunction can actually read the key at runtime.",
"promptSourcePath": "evals/deploy-functions-001-edge-function-secrets/PROMPT.md",
"attempts": 1,
@@ -3166,6 +3462,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 1392819,
+ "outputTokens": 22740,
+ "cachedInputTokens": 1325198,
+ "cacheCreationInputTokens": 63960,
+ "costUsd": 1.649864
+ },
+ "durationMs": 334435,
"prompt": "I'm moving off the hosted Supabase and running the whole thing myself on a VPS I\njust spun up. Can you get a Docker setup ready for me to copy onto the box?\n\nI don't need it running here, I'll do the actual bring-up once I'm on the\nserver. I just want everything in place and the secrets set up. Put it in a `supabase-docker/`\nfolder at the repo root so I can scp the whole thing across in one go.",
"promptSourcePath": "evals/deploy-self-hosting-001-docker-compose/PROMPT.md",
"attempts": 1,
@@ -3222,7 +3526,7 @@
{
"name": "diagnosed and explained session revocation",
"passed": true,
- "judgeNotes": "Meets the rubric: diagnoses soft-delete-only flow, implements real auth/session/refresh-token revocation plus RLS gating, explains Data API has no post-deletion window under its implemented RLS fix while unexpired JWTs can still matter for non-policy/local-ish surfaces, and correctly distinguishes publishable frontend/RLS-enforced keys from server-only secret keys that bypass RLS."
+ "judgeNotes": "Meets the rubric: correctly diagnoses soft-delete-only flow, implements auth/session/refresh-token revocation plus RLS enforcement, gives a consistent JWT expiry caveat, and accurately distinguishes publishable frontend keys from secret server-only RLS-bypassing keys."
}
],
"skills": {
@@ -3262,47 +3566,17 @@
}
],
"resultChars": 136765
- },
- {
- "source": "web_fetch",
- "query": "Report verbatim any statements about: (a) how many secret keys or publishable keys a project can have (limits/maximums), (b) whether secret keys can be viewed again after creation or are shown only once, (c) whether publishable/secret keys expire or have an expiry, (d) whether keys are JWTs, (e) key format prefixes. Quote exact sentences.",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/getting-started/api-keys"
- }
- ],
- "resultChars": 964
- },
- {
- "source": "web_fetch",
- "query": "Report verbatim any statements about deprecation timeline for legacy anon/service_role keys, limits on number of keys, and whether legacy and new keys can coexist. Also note the page's stated last-updated date if visible.",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys"
- }
- ],
- "resultChars": 1009
- },
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"how many secret keys can I create limit reveal secret key dashboard\", limit: 2) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/limits",
- "title": "Limits"
- }
- ],
- "resultChars": 15838
}
]
},
+ "usage": {
+ "inputTokens": 1142035,
+ "outputTokens": 23675,
+ "cachedInputTokens": 1077464,
+ "cacheCreationInputTokens": 60766,
+ "costUsd": 2.29108025
+ },
+ "durationMs": 438025,
"prompt": "Last week support removed a user through our app's delete-account flow — the\napp calls the `delete_account` function over RPC as the signed-in user. This\nmorning that same person was back: still signed in, reading and saving their\ndata like nothing happened.\n\nFigure out why the account still works, fix the flow so a deleted account\nloses access, and tell me whether there is any window where they could still\nget in after the fix.\n\nOne more thing while you're at it: we're migrating off the legacy\nanon/service_role API keys to the new publishable and secret keys, and the\nteam isn't sure which one belongs in the frontend and what each means for\nRLS. Give us a quick rundown.",
"promptSourcePath": "evals/investigate-auth-001-deleted-user-access/PROMPT.md",
"attempts": 2,
@@ -3354,7 +3628,7 @@
{
"name": "diagnosed missing publication membership",
"passed": true,
- "judgeNotes": "The assistant correctly identified the root cause as public.orders missing from the supabase_realtime publication despite the channel reaching SUBSCRIBED, applied an idempotent ALTER PUBLICATION supabase_realtime ADD TABLE public.orders migration, preserved courier_locations and existing RLS/policies, and did not blame or alter RLS, grants, client code, networking, or recreate the publication."
+ "judgeNotes": "The assistant correctly identified that orders was missing from the supabase_realtime publication despite SUBSCRIBED working, applied exactly ALTER PUBLICATION supabase_realtime ADD TABLE public.orders, verified courier_locations remained, and did not weaken RLS/policies or blame client code/RLS as root cause."
}
],
"skills": {
@@ -3364,6 +3638,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 376060,
+ "outputTokens": 3481,
+ "cachedInputTokens": 345290,
+ "cacheCreationInputTokens": 27245,
+ "costUsd": 0.44827225
+ },
+ "durationMs": 70508,
"prompt": "Our dispatch dashboard shows incoming orders as they happen. The courier\nlocation feed on the same page updates live without problems, but new orders\nonly show up after a page refresh.\n\nThe dashboard uses supabase-js to subscribe to INSERT events on the `orders`\ntable through postgres_changes, the same way it subscribes to courier\nlocations. The channel's status callback logs SUBSCRIBED and there are no\nerrors in the browser console.\n\nFigure out why no order events ever arrive and fix it.",
"promptSourcePath": "evals/investigate-realtime-001-subscribed-no-events/PROMPT.md",
"attempts": 1,
@@ -3393,17 +3675,17 @@
{
"name": "identified image-transform and the recurring 503 pattern",
"passed": true,
- "judgeNotes": "The assistant explicitly identified `image-transform` as returning 503 eight times on 2026-04-28 between 07:00 and 12:00 UTC, and described the recurring pattern across the morning with the specific gateway failures. It did not incorrectly center the old billing-webhook issue."
+ "judgeNotes": "Identified image-transform as affected and described the recurring HTTP 503 pattern across the morning of 2026-04-28, covering all 8 gateway failures from 07:00Z–12:00Z."
},
{
"name": "attributed recurring 503s to gateway/platform layer, not function code",
"passed": true,
- "judgeNotes": "The assistant clearly attributes the recurring 503s to the gateway/platform layer, not image-transform code, and grounds this in valid observations: 503s appear only in API/gateway logs, lack function execution metadata, have no corresponding edge-function log entries, while actual function executions returned 200. It also distinguishes the avatar-upload 500 as a function-level error and recommends escalation to Supabase/platform support rather than redeploying or fixing image-transform code."
+ "judgeNotes": "Attributes image-transform 503s to the gateway/platform layer, explicitly says they never reached the function and not to debug transform code. Grounds this in valid observations: 503s appear only in API/gateway logs with zero edge-function 503s while function-side records are 200s, unchanged deployment ID, and contrasts with avatar-upload's function-side 500."
},
{
"name": "recommended a concrete next step",
"passed": true,
- "judgeNotes": "The assistant recommended concrete next steps, including escalating gateway 503s to Supabase support with request IDs, identifying the scheduled caller, obtaining a real failing user request with timestamp/request ID, and pulling scoped logs from Logs Explorer/log drain."
+ "judgeNotes": "The assistant recommended concrete next steps, including pulling unsampled logs for a specific window and escalating to Supabase support with gateway request IDs and timestamps."
}
],
"skills": {
@@ -3413,6 +3695,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 297245,
+ "outputTokens": 6301,
+ "cachedInputTokens": 259968,
+ "cacheCreationInputTokens": 33758,
+ "costUsd": 0.5167205
+ },
+ "durationMs": 98800,
"prompt": "Users have been reporting that image uploads are intermittently failing with server errors throughout the morning of `2026-04-28`.\n\nCan you investigate the project logs and tell me what is going on and what we\nshould do next?",
"promptSourcePath": "evals/investigate-reliability-003-edge-function-5xx-correlation/PROMPT.md",
"attempts": 1,
@@ -3469,7 +3759,7 @@
{
"name": "diagnosed RLS and added owner-scoped policies",
"passed": true,
- "judgeNotes": "Diagnosed deny-all RLS due to no policies, kept RLS enabled, and added authenticated SELECT and INSERT policies scoped to user_id = auth.uid() with WITH CHECK for inserts."
+ "judgeNotes": "Diagnosed RLS enabled with zero policies/default-deny causing empty Data API results; kept RLS enabled; added authenticated SELECT policy using user_id = auth.uid() and authenticated INSERT policy with WITH CHECK enforcing user_id = auth.uid()."
}
],
"skills": {
@@ -3479,6 +3769,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 1212439,
+ "outputTokens": 12625,
+ "cachedInputTokens": 1166382,
+ "cacheCreationInputTokens": 41982,
+ "costUsd": 1.1822545
+ },
+ "durationMs": 199892,
"prompt": "Our app lets signed-in users save bookmarks and view them on their dashboard. Bookmarks are stored in the `bookmarks` table and are private — a user must only ever see their own. \nUsers also need to be able to save new bookmarks from the app.\n\nI can see the rows when I query the table directly, but the dashboard shows an empty list for every user.\n\nFind out why the Data API returns nothing and fix it.",
"promptSourcePath": "evals/resolve-dataapi-001-empty-results/PROMPT.md",
"attempts": 1,
@@ -3528,7 +3826,7 @@
{
"name": "the avatar migration and history reconciliation were done via the Supabase CLI",
"passed": true,
- "judgeNotes": "Applied pending avatar_url via `supabase db push` in #25, with output `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` Reconciled orphan bio migration by adding the missing local file `20240115000000_add_profile_bio.sql` in #22, after which `supabase migration list` aligned and `db push` proceeded. No disallowed workaround or direct remote mutation observed."
+ "judgeNotes": "Avatar migration was applied through the Supabase CLI with `supabase db push` in #19, showing `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` The orphan bio migration was reconciled by adding the missing local migration file `20240115000000_add_profile_bio.sql` in #17, after which CLI migration list/dry-run no longer showed the remote-only blocker and the successful `supabase db push` proceeded. Read-only `psql` inspection was used, but no direct SQL mutation or prepared-statement reset workaround was seen."
}
],
"skills": {
@@ -3538,6 +3836,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 543077,
+ "outputTokens": 5814,
+ "cachedInputTokens": 506486,
+ "cacheCreationInputTokens": 33341,
+ "costUsd": 0.6238232499999999
+ },
+ "durationMs": 107162,
"prompt": "I'm trying to ship a migration to our hosted project and it's not working. Can you figure out what's wrong and get it deployed?",
"promptSourcePath": "evals/resolve-database-001-migration-history-mismatch/PROMPT.md",
"attempts": 1,
@@ -3594,6 +3900,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 389916,
+ "outputTokens": 4415,
+ "cachedInputTokens": 358269,
+ "cacheCreationInputTokens": 28120,
+ "costUsd": 0.48352849999999997
+ },
+ "durationMs": 76388,
"prompt": "My database CPU keeps spiking and the app gets slow when loading recent events for a user. Can you figure out what query is causing it and make the database change needed to fix it?\n\nEnd your turn with a short summary of what you changed and why.",
"promptSourcePath": "evals/resolve-performance-001-slow-query-cpu-spike/PROMPT.md",
"attempts": 1,
@@ -3666,6 +3980,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 1065038,
+ "outputTokens": 10596,
+ "cachedInputTokens": 1021040,
+ "cacheCreationInputTokens": 40058,
+ "costUsd": 1.0460764999999999
+ },
+ "durationMs": 167729,
"prompt": "A customer reported that notes showed up in the wrong workspace.\n\nCan you investigate what is going on and fix it?",
"promptSourcePath": "evals/resolve-security-002-rls-cross-tenant-leak/PROMPT.md",
"attempts": 1,
@@ -3732,12 +4054,21 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 1759409,
+ "outputTokens": 9665,
+ "cachedInputTokens": 1679469,
+ "cacheCreationInputTokens": 75515,
+ "costUsd": 1.5761882499999997
+ },
+ "durationMs": 295125,
"prompt": "We're kicking off a todos app and I want the Supabase side ready for the team\nto build on. Set it up the way we'd run it in development, with schema changes\ntracked as migrations so they can be reviewed and replayed.\n\nFor the first slice we just need a `todos` table. Todos aren't public: anyone\nsigned in can read all of them, but nothing should be writable through the API\nfor now. Add a couple of sample todos so there's something to look at.\n\nBefore you hand it back, make sure the running API actually behaves that way —\nsigned-in users get the todos, signed-out requests get nothing.",
"promptSourcePath": "evals/build-cli-001-bootstrap-app/PROMPT.md",
"attempts": 1,
@@ -3794,6 +4125,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 517186,
+ "outputTokens": 2333,
+ "cachedInputTokens": 491534,
+ "cacheCreationInputTokens": 21814,
+ "costUsd": 0.46020849999999996
+ },
+ "durationMs": 99316,
"prompt": "Add a description text column to the `products` table in my local Supabase stack",
"promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md",
"attempts": 1,
@@ -3846,81 +4185,118 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"pg_cron schedule pgmq queue send message example\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"pg_cron schedule queue send message example\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
- {
- "url": "https://supabase.com/docs/guides/queues/pgmq",
- "title": "PGMQ Extension"
- },
{
"url": "https://supabase.com/docs/guides/database/extensions/pg_net",
"title": "pg_net: Async Networking"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/pgcron-debugging-guide-n1KTaz",
- "title": "pg_cron debugging guide"
+ "url": "https://supabase.com/docs/guides/auth/auth-hooks/send-sms-hook",
+ "title": "Send SMS Hook"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart",
- "title": "Quickstart"
+ "url": "https://supabase.com/docs/guides/queues/pgmq",
+ "title": "PGMQ Extension"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/auth-hooks/send-email-hook",
+ "title": "Send Email Hook"
},
{
"url": "https://supabase.com/docs/guides/functions/schedule-functions",
"title": "Scheduling Edge Functions"
}
],
- "resultChars": 55834
+ "resultChars": 102399
},
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"edge function supabase-js service role client import example Deno.serve\", limit: 3) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"Edge Functions cron queues process messages example\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/functions",
- "title": "Edge Functions"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
+ "title": "Automatic embeddings"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/background-tasks",
+ "title": "Background Tasks"
},
{
- "url": "https://supabase.com/docs/guides/database/connecting-to-postgres/serverless-drivers",
- "title": "Serverless Drivers"
+ "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions",
+ "title": "Consuming Supabase Queue Messages with Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/auth-hooks/send-email-hook",
+ "title": "Send Email Hook"
},
{
- "url": "https://supabase.com/docs/guides/functions/unit-test",
- "title": "Testing your Edge Functions"
+ "url": "https://supabase.com/docs/guides/functions/recursive-functions",
+ "title": "Recursive / Nested Function Calls"
}
],
- "resultChars": 26350
+ "resultChars": 90930
},
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"Edge Functions default secrets SUPABASE_URL SUPABASE_SERVICE_ROLE_KEY automatically populated local\", limit: 3) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"cron.schedule invoke pgmq.send message queue local development vault\", limit: 3) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
+ "title": "Automatic embeddings"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net",
+ "title": "pg_net: Async Networking"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
+ "url": "https://supabase.com/docs/guides/cron/quickstart",
+ "title": "Quickstart"
}
],
- "resultChars": 28165
- }
- ]
- },
+ "resultChars": 54697
+ },
+ {
+ "source": "search_docs",
+ "query": "{ searchDocs(query: \"Edge Function environment variables SUPABASE_SERVICE_ROLE_KEY SUPABASE_URL createClient example\", limit: 3) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
+ "title": "Self-Hosted Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-refine",
+ "title": "Build a User Management App with Refine"
+ }
+ ],
+ "resultChars": 49300
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 1710335,
+ "outputTokens": 11299,
+ "cachedInputTokens": 1622482,
+ "cacheCreationInputTokens": 83733,
+ "costUsd": 1.6383322500000002
+ },
+ "durationMs": 198788,
"prompt": "I want to set up a recurring background workflow on my local Supabase stack.\n\nCan you set up a cron job called `enqueue-tasks` to run every minute and push a task into a queue called `tasks`? Then add a `process-tasks` edge function that reads messages off the `tasks` queue and removes them, so a scheduled worker can keep the backlog drained.",
"promptSourcePath": "evals/build-cli-003-pg-cron-queue-workflow/PROMPT.md",
"attempts": 1,
@@ -3974,12 +4350,21 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 1952693,
+ "outputTokens": 10382,
+ "cachedInputTokens": 1869997,
+ "cacheCreationInputTokens": 76799,
+ "costUsd": 1.7046692500000002
+ },
+ "durationMs": 441132,
"prompt": "I have an existing Postgres database I want to migrate to Supabase. There's a binary dump at `source.dump` in the current directory.\n\nCan you set up a local Supabase project and restore the dump into it?",
"promptSourcePath": "evals/build-database-001-migrate-postgres-to-supabase/PROMPT.md",
"attempts": 1,
@@ -4048,6 +4433,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 504698,
+ "outputTokens": 4123,
+ "cachedInputTokens": 448366,
+ "cacheCreationInputTokens": 52218,
+ "costUsd": 0.6748084999999999
+ },
+ "durationMs": 58251,
"prompt": "I built an Edge Function called `private-notes` for showing a user's saved\nprivate notes.\n\nCan you check whether there's any way one user could see another user's notes?\n\nPlease fix and deploy it if needed.",
"promptSourcePath": "evals/build-functions-004-service-role-bypass/PROMPT.md",
"attempts": 1,
@@ -4092,17 +4485,17 @@
{
"name": "user with JWT reads only their own rows",
"passed": true,
- "notes": "status 200: {\"data\":[{\"user_id\":\"b0cee6b2-6005-4375-acfc-e42243e7b9fe\",\"metric\":\"steps_a_ms6x1j4o\",\"value\":111}]}"
+ "notes": "status 200: [{\"user_id\":\"7546c6b3-f167-4f6f-a316-97126cfaa61f\",\"metric\":\"steps_a_ms7qea3n\",\"value\":111}]"
},
{
"name": "user cannot read another user's rows by passing user_id",
"passed": true,
- "notes": "status 200: {\"data\":[{\"user_id\":\"b0cee6b2-6005-4375-acfc-e42243e7b9fe\",\"metric\":\"steps_a_ms6x1j4o\",\"value\":111}]}"
+ "notes": "status 200: [{\"user_id\":\"7546c6b3-f167-4f6f-a316-97126cfaa61f\",\"metric\":\"steps_a_ms7qea3n\",\"value\":111}]"
},
{
"name": "service key bypasses RLS to read the target user's rows",
"passed": true,
- "notes": "status 200: {\"data\":[{\"user_id\":\"ab402c7a-0f99-490c-87f2-8214ddbef994\",\"metric\":\"steps_b_ms6x1j4o\",\"value\":222}]}"
+ "notes": "status 200: [{\"user_id\":\"420a9b72-5052-4691-873a-ce33fc49915d\",\"metric\":\"steps_b_ms7qea3n\",\"value\":222}]"
},
{
"name": "non-service key is not granted service access",
@@ -4136,691 +4529,369 @@
},
"docs": {
"calls": [
- {
- "source": "web_fetch",
- "query": "List any entries about: new API key system (sb_publishable_/sb_secret_), Edge Functions env vars, edge runtime, JWT signing keys, getClaims, or breaking changes to auth/apikey handling. Include dates and links.",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/changelog.md"
- }
- ],
- "resultChars": 1355
- },
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"edge functions environment variables SUPABASE_URL SUPABASE_ANON_KEY SUPABASE_SERVICE_ROLE_KEY default secrets\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"verify_jwt config.toml edge functions\", limit: 6) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
+ "url": "https://supabase.com/docs/guides/functions/deploy",
+ "title": "Deploy to Production"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
+ "url": "https://supabase.com/docs/guides/functions/function-configuration",
+ "title": "Function Configuration"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
+ "url": "https://supabase.com/docs/guides/functions/development-tips",
+ "title": "Development tips"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
+ "url": "https://supabase.com/docs/guides/functions/examples/mcp-server-mcp-lite",
+ "title": "Building an MCP Server with mcp-lite"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
- "title": "Integrating With Supabase Auth"
+ "url": "https://supabase.com/docs/guides/ai-tools/byo-mcp",
+ "title": "Deploy MCP servers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth-headers",
+ "title": "Authorization headers"
}
],
- "resultChars": 41771
+ "resultChars": 35159
},
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"new API keys publishable secret key sb_secret sb_publishable service_role apikey header\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"Edge Functions auth service_role apikey header bypass JWT verification\", limit: 6) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
+ "title": "Envoy API Gateway"
},
{
"url": "https://supabase.com/docs/guides/getting-started/api-keys",
"title": "Understanding API keys"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
- "title": "Envoy API Gateway"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
- }
- ],
- "resultChars": 98570
- },
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"edge function call with service role bypass RLS forward Authorization header user JWT getUser\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
- "title": "Why is my service role key client getting RLS errors or not returning data?"
+ "url": "https://supabase.com/docs/guides/functions/error-codes",
+ "title": "Error codes"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
+ "url": "https://supabase.com/docs/guides/functions/function-configuration",
+ "title": "Function Configuration"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-headers",
- "title": "Authorization headers"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
},
{
"url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
"title": "Integrating With Supabase Auth"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/error-codes",
- "title": "Error codes"
}
],
- "resultChars": 28724
+ "resultChars": 71369
},
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"@supabase/server withSupabase edge function auth\") { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"new API keys sb_secret sb_publishable JWT signing keys\", limit: 6) { nodes { title href content } } }",
"hasContent": true,
"pages": [
- {
- "url": "https://supabase.com/docs/guides/auth/choosing-a-server-package",
- "title": "Which package to use"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
- },
{
"url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
"title": "Migrating to publishable and secret API keys"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
- "title": "Integrating With Supabase Auth"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets",
- "title": "Resumable WebSockets with Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/functions",
- "title": "Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/ai-tools/byo-mcp",
- "title": "Deploy MCP servers"
- },
- {
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net",
- "title": "pg_net: Async Networking"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
},
{
- "url": "https://supabase.com/docs/guides/auth",
- "title": "Auth"
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-angular",
+ "title": "Build a User Management App with Angular"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/roles",
- "title": "Postgres Roles"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys",
+ "title": "JWT Signing Keys"
},
{
- "url": "https://supabase.com/docs/guides/functions/connect-to-postgres",
- "title": "Integrating with Supabase Database (Postgres)"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
+ "title": "Envoy API Gateway"
},
{
- "url": "https://supabase.com/docs/guides/functions/cors",
- "title": "CORS (Cross-Origin Resource Sharing) support for Invoking from the browser"
- },
+ "url": "https://supabase.com/docs/guides/auth/server-side/creating-a-client",
+ "title": "Creating a Supabase client for SSR"
+ }
+ ],
+ "resultChars": 163706
+ },
+ {
+ "source": "search_docs",
+ "query": "{ searchDocs(query: \"Edge Functions environment variables SUPABASE_SERVICE_ROLE_KEY SUPABASE_URL Deno.env\", limit: 6) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
{
- "url": "https://supabase.com/docs/guides/functions/quickstart-dashboard",
- "title": "Getting Started with Edge Functions (Dashboard)"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
+ "title": "Self-Hosted Functions"
},
{
- "url": "https://supabase.com/docs/guides/auth/architecture",
- "title": "Auth architecture"
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables"
},
{
- "url": "https://supabase.com/docs/guides/database/secure-data",
- "title": "Securing your data"
+ "url": "https://supabase.com/docs/guides/troubleshooting/inspecting-edge-function-environment-variables-wg5qOQ",
+ "title": "Inspecting edge function environment variables"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs",
- "title": "Build a User Management App with Next.js"
+ "url": "https://supabase.com/docs/guides/functions",
+ "title": "Edge Functions"
},
{
- "url": "https://supabase.com/docs/guides/functions/websockets",
- "title": "Handling WebSockets"
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/edge-function-401-error-response",
- "title": "Edge Function 401 error response"
- },
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
+ }
+ ],
+ "resultChars": 51941
+ },
+ {
+ "source": "web_fetch",
+ "query": "List entries related to: new JWT signing keys, new API key formats (sb_secret_/sb_publishable_), Edge Functions changes, verify_jwt, service role key handling. Include dates and short descriptions.",
+ "hasContent": true,
+ "pages": [
{
- "url": "https://supabase.com/docs/guides/database/connecting-to-postgres/serverless-drivers",
- "title": "Serverless Drivers"
- },
+ "url": "https://supabase.com/changelog.md"
+ }
+ ],
+ "resultChars": 1557
+ },
+ {
+ "source": "search_docs",
+ "query": "{ searchDocs(query: \"Securing Edge Functions user JWT service role pattern auth.uid RLS\", limit: 3) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
{
"url": "https://supabase.com/docs/guides/functions/auth-headers",
"title": "Authorization headers"
},
{
- "url": "https://supabase.com/docs/guides/functions/architecture",
- "title": "Edge Functions Architecture"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/quickstart",
- "title": "Getting Started with Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/examples/auth-send-email-hook-react-email-resend",
- "title": "Custom Auth Emails with React Email and Resend"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/social-login/auth-apple",
- "title": "Login with Apple"
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs",
+ "title": "Build a User Management App with Next.js"
},
{
- "url": "https://supabase.com/docs/guides/auth/enterprise-sso",
- "title": "Enterprise Single Sign-On"
- },
+ "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
+ "title": "Token Security and Row Level Security"
+ }
+ ],
+ "resultChars": 59824
+ },
+ {
+ "source": "search_docs",
+ "query": "{ searchDocs(query: \"Publishable and secret API keys migrating from anon and service_role\", limit: 3) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
{
- "url": "https://supabase.com/docs/guides/functions/recursive-functions",
- "title": "Recursive / Nested Function Calls"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys",
+ "title": "JWT Signing Keys"
},
{
- "url": "https://supabase.com/docs/guides/integrations/build-a-supabase-oauth-integration",
- "title": "Build a Supabase Integration"
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
},
{
- "url": "https://supabase.com/docs/guides/auth/sessions",
- "title": "User sessions"
- },
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
+ }
+ ],
+ "resultChars": 61983
+ },
+ {
+ "source": "search_docs",
+ "query": "{ searchDocs(query: \"Edge Functions secrets default environment variables SUPABASE_URL SUPABASE_ANON_KEY SUPABASE_SERVICE_ROLE_KEY local development\", limit: 3) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
{
- "url": "https://supabase.com/docs/guides/auth/quickstarts/astrojs",
- "title": "Use Supabase Auth with Astro"
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables"
},
{
"url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
"title": "Self-Hosted Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
}
],
- "resultChars": 12
+ "resultChars": 28165
},
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"edge function verify_jwt secret key apikey header\") { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"Securing Edge Functions auth modes user secret publishable withSupabase distinguish caller\", limit: 3) { nodes { title href content } } }",
"hasContent": true,
"pages": [
- {
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
- },
{
"url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
"title": "Migrating to publishable and secret API keys"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/auth-headers",
- "title": "Authorization headers"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/error-codes",
- "title": "Error codes"
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys",
+ "title": "Understanding API keys"
},
{
- "url": "https://supabase.com/docs/guides/ai/examples/openai",
- "title": "Generating OpenAI GPT3 completions"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/auth-hooks/send-email-hook",
- "title": "Send Email Hook"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
- "title": "Envoy API Gateway"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-kotlin",
- "title": "Build a Product Management Android App with Jetpack Compose"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/jwts",
- "title": "JSON Web Token (JWT)"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/function-configuration",
- "title": "Function Configuration"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/status-codes",
- "title": "Status codes"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows",
- "title": "OAuth 2.1 Flows"
- },
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
+ }
+ ],
+ "resultChars": 34411
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 2951950,
+ "outputTokens": 18202,
+ "cachedInputTokens": 2855026,
+ "cacheCreationInputTokens": 92645,
+ "costUsd": 3.1017552499999983
+ },
+ "durationMs": 353478,
+ "prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nOur product stores per-user metrics in the existing `user_stats` table.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.",
+ "promptSourcePath": "evals/build-functions-005-dual-auth-user-secret/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "claude-code-sonnet-5/build-functions-005-dual-auth-user-secret.json"
+ },
+ {
+ "experiment": "claude-code-sonnet-5",
+ "experimentSuite": "benchmark",
+ "experimentDisplay": {
+ "agent": "claude-code",
+ "modelProvider": "anthropic",
+ "modelId": "claude-sonnet-5",
+ "reasoningEffort": "high"
+ },
+ "eval": "build-storage-001-private-bucket-access",
+ "stage": "build",
+ "product": [
+ "storage",
+ "database"
+ ],
+ "topic": [
+ "rls",
+ "sdk"
+ ],
+ "suite": "benchmark",
+ "interface": "mcp",
+ "passed": true,
+ "checks": [
+ {
+ "name": "bucket user-files exists",
+ "passed": true
+ },
+ {
+ "name": "bucket user-files is private",
+ "passed": true
+ },
+ {
+ "name": "RLS still enabled on storage.objects",
+ "passed": true
+ },
+ {
+ "name": "user A lists only own files",
+ "passed": true,
+ "notes": "saw: 019fb3d8-71f9-7792-af20-c7e581864416/receipt-alpha.pdf, 019fb3d8-71f9-7792-af20-c7e581864416/receipt-beta.pdf"
+ },
+ {
+ "name": "user B cannot read user A files",
+ "passed": true
+ },
+ {
+ "name": "anon reads no files",
+ "passed": true
+ },
+ {
+ "name": "user A can upload into own folder",
+ "passed": true
+ },
+ {
+ "name": "user B cannot upload into user A folder",
+ "passed": true
+ },
+ {
+ "name": "configured private per-user storage access",
+ "passed": true,
+ "judgeNotes": "Meets the rubric: creates a private user-files bucket, adds authenticated owner-scoped SELECT and INSERT policies with WITH CHECK for uploads, does not disable RLS or use public access, and uses createSignedUrl with an expiry for temporary sharing."
+ }
+ ],
+ "skills": {
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase"
+ ]
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "{ searchDocs(query: \"storage RLS policy user folder ownership\", limit: 5) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
{
- "url": "https://supabase.com/docs/guides/auth/auth-mfa",
- "title": "Multi-Factor Authentication"
+ "url": "https://supabase.com/docs/guides/storage/schema/helper-functions",
+ "title": "Storage Helper Functions"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
- "title": "Integrating With Supabase Auth"
+ "url": "https://supabase.com/docs/guides/auth/third-party/clerk",
+ "title": "Clerk"
},
{
- "url": "https://supabase.com/docs/guides/functions/websockets",
- "title": "Handling WebSockets"
+ "url": "https://supabase.com/docs/guides/storage/security/access-control",
+ "title": "Storage Access Control"
},
{
- "url": "https://supabase.com/docs/guides/integrations/partner-integration-guide",
- "title": "Supabase Partner Integration Guide"
+ "url": "https://supabase.com/docs/guides/storage/debugging/error-codes",
+ "title": "Error Codes"
},
{
"url": "https://supabase.com/docs/guides/resources/glossary",
"title": "Glossary"
- },
- {
- "url": "https://supabase.com/docs/guides/database/secure-data",
- "title": "Securing your data"
}
],
- "resultChars": 335959
+ "resultChars": 39120
},
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"SUPABASE_SECRET_KEYS SUPABASE_PUBLISHABLE_KEYS environment variables edge functions\") { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"createSignedUrl storage share temporary link expires\", limit: 3) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/docker",
- "title": "Self-Hosting with Docker"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
- "title": "Envoy API Gateway"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/quickstarts/with-expo-react-native-social-auth",
- "title": "Build a Social Auth App with Expo React Native"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/quickstart-dashboard",
- "title": "Getting Started with Edge Functions (Dashboard)"
- },
- {
- "url": "https://supabase.com/docs/guides/ai/examples/nextjs-vector-search",
- "title": "Vector search with Next.js and OpenAI"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/troubleshooting/inspecting-edge-function-environment-variables-wg5qOQ",
- "title": "Inspecting edge function environment variables"
- },
- {
- "url": "https://supabase.com/docs/guides/database/secure-data",
- "title": "Securing your data"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-generate-speech-stream",
- "title": "Streaming Speech with ElevenLabs"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/architecture",
- "title": "Edge Functions Architecture"
- },
- {
- "url": "https://supabase.com/docs/guides/integrations/vercel-marketplace",
- "title": "Vercel Marketplace"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/unit-test",
- "title": "Testing your Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/functions",
- "title": "Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-transcribe-speech",
- "title": "Transcription Telegram Bot"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/server-side/creating-a-client",
- "title": "Creating a Supabase client for SSR"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/connect-to-postgres",
- "title": "Integrating with Supabase Database (Postgres)"
- },
- {
- "url": "https://supabase.com/docs/guides/integrations/build-a-supabase-oauth-integration",
- "title": "Build a Supabase Integration"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
- "title": "Integrating With Supabase Auth"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/examples/cloudflare-turnstile",
- "title": "CAPTCHA support with Cloudflare Turnstile"
- },
- {
- "url": "https://supabase.com/docs/guides/integrations/supabase-for-platforms",
- "title": "Supabase for Platforms"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/deploy",
- "title": "Deploy to Production"
- },
- {
- "url": "https://supabase.com/docs/guides/telemetry/reports",
- "title": "Reports"
+ "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsignedurl"
},
{
- "url": "https://supabase.com/docs/guides/functions/schedule-functions",
- "title": "Scheduling Edge Functions"
+ "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsignedurls"
},
{
- "url": "https://supabase.com/docs/guides/functions/recursive-functions",
- "title": "Recursive / Nested Function Calls"
+ "url": "https://supabase.com/docs/guides/storage/serving/downloads",
+ "title": "Serving assets from Storage"
}
],
- "resultChars": 436561
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"new API keys publishable secret migration edge functions\") { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
- },
- {
- "url": "https://supabase.com/docs/guides/integrations/supabase-for-platforms",
- "title": "Supabase for Platforms"
- },
- {
- "url": "https://supabase.com/docs/guides/ai-tools/mcp",
- "title": "Supabase MCP Server"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs",
- "title": "Build a User Management App with Next.js"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/development-tips",
- "title": "Development tips"
- },
- {
- "url": "https://supabase.com/docs/guides/platform/migrating-within-supabase/backup-restore",
- "title": "Backup and Restore using the CLI"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/docker",
- "title": "Self-Hosting with Docker"
- },
- {
- "url": "https://supabase.com/docs/guides/database/secure-data",
- "title": "Securing your data"
- },
- {
- "url": "https://supabase.com/docs/guides/ai/examples/nextjs-vector-search",
- "title": "Vector search with Next.js and OpenAI"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/local-development/cli/getting-started",
- "title": "Supabase CLI"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/features",
- "title": "Features"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/quickstart-dashboard",
- "title": "Getting Started with Edge Functions (Dashboard)"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
- "title": "Envoy API Gateway"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-kotlin",
- "title": "Build a Product Management Android App with Jetpack Compose"
- },
- {
- "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers",
- "title": "Multiple SSO Providers"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/quickstarts/with-expo-react-native-social-auth",
- "title": "Build a Social Auth App with Expo React Native"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
- "title": "Integrating With Supabase Auth"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-expo-react-native",
- "title": "Build a User Management App with Expo React Native"
- },
- {
- "url": "https://supabase.com/docs/guides/platform/delete-project",
- "title": "Deleting Your Project"
- },
- {
- "url": "https://supabase.com/docs/guides/functions",
- "title": "Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/recursive-functions",
- "title": "Recursive / Nested Function Calls"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-ionic-react",
- "title": "Build a User Management App with Ionic React"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-ionic-angular",
- "title": "Build a User Management App with Ionic Angular"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-angular",
- "title": "Build a User Management App with Angular"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
- }
- ],
- "resultChars": 611775
+ "resultChars": 5976
}
]
},
- "prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nOur product stores per-user metrics in the existing `user_stats` table.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.",
- "promptSourcePath": "evals/build-functions-005-dual-auth-user-secret/PROMPT.md",
- "attempts": 1,
- "sourcePath": "claude-code-sonnet-5/build-functions-005-dual-auth-user-secret.json"
- },
- {
- "experiment": "claude-code-sonnet-5",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "claude-code",
- "modelProvider": "anthropic",
- "modelId": "claude-sonnet-5",
- "reasoningEffort": "high"
- },
- "eval": "build-storage-001-private-bucket-access",
- "stage": "build",
- "product": [
- "storage",
- "database"
- ],
- "topic": [
- "rls",
- "sdk"
- ],
- "suite": "benchmark",
- "interface": "mcp",
- "passed": true,
- "checks": [
- {
- "name": "bucket user-files exists",
- "passed": true
- },
- {
- "name": "bucket user-files is private",
- "passed": true
- },
- {
- "name": "RLS still enabled on storage.objects",
- "passed": true
- },
- {
- "name": "user A lists only own files",
- "passed": true,
- "notes": "saw: 019fb0e6-fae1-72ae-a0ef-528df766bb3f/receipt-alpha.pdf, 019fb0e6-fae1-72ae-a0ef-528df766bb3f/receipt-beta.pdf"
- },
- {
- "name": "user B cannot read user A files",
- "passed": true
- },
- {
- "name": "anon reads no files",
- "passed": true
- },
- {
- "name": "user A can upload into own folder",
- "passed": true
- },
- {
- "name": "user B cannot upload into user A folder",
- "passed": true
- },
- {
- "name": "configured private per-user storage access",
- "passed": true,
- "judgeNotes": "Meets all criteria: private user-files bucket, authenticated owner-scoped SELECT and INSERT policies with WITH CHECK, no public/anon access or permissive policies, RLS not disabled, and supabase-js createSignedUrl with expiry for temporary sharing."
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"storage RLS policy private user folder signed URL\", limit: 5) { nodes { title href ... on Guide { content } } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
- "title": "Storage Buckets"
- },
- {
- "url": "https://supabase.com/docs/guides/storage/schema/helper-functions",
- "title": "Storage Helper Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/third-party/clerk",
- "title": "Clerk"
- },
- {
- "url": "https://supabase.com/docs/guides/storage/security/access-control",
- "title": "Storage Access Control"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
- "title": "Configure S3 Storage"
- }
- ],
- "resultChars": 28558
- }
- ]
+ "usage": {
+ "inputTokens": 500518,
+ "outputTokens": 4719,
+ "cachedInputTokens": 437314,
+ "cacheCreationInputTokens": 59091,
+ "costUsd": 0.72722875
},
+ "durationMs": 74133,
"prompt": "Our app lets signed-in users keep personal files like receipts and bank\nstatements. These files are private — a user must only ever be able to upload\nand download their own. The app uploads each file under a path that starts\nwith the owner's user id, e.g. `/receipt-march.pdf`.\n\nSet up a `user-files` bucket on our project and lock it down that way.\n\nUsers also sometimes share one of their files with someone else through a\ntemporary link that expires. Include the supabase-js code the app should use\nfor that.",
"promptSourcePath": "evals/build-storage-001-private-bucket-access/PROMPT.md",
"attempts": 1,
@@ -4856,12 +4927,12 @@
{
"name": "pgTAP isolation tests ran and pass",
"passed": true,
- "notes": "4 passed, 4 failed"
+ "notes": "4 passed, 2 failed"
},
{
"name": "agent correctly identifies the posts isolation bug from test results",
"passed": true,
- "judgeNotes": "The agent correctly identifies posts as having the tenant isolation flaw, specifically that authenticated members can read posts from orgs they do not belong to, and grounds this in pgTAP failures. It also notes notes is correctly isolated. Extra discussion of memberships does not undermine the required conclusion."
+ "judgeNotes": "The agent correctly identifies `posts` as having the tenant isolation flaw: its SELECT policy checks membership by user but does not match `posts.org_id`, allowing authenticated members to read other organizations' posts. It grounds this in the pgTAP failure for the posts negative case and does not blame `notes` or dismiss the tests."
}
],
"skills": {
@@ -4870,12 +4941,21 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 959378,
+ "outputTokens": 9934,
+ "cachedInputTokens": 886691,
+ "cacheCreationInputTokens": 68835,
+ "costUsd": 1.14178125
+ },
+ "durationMs": 141333,
"prompt": "Can you audit the tenant isolation on our tables? Write some database tests covering both the happy path and the negative case, run them, and share the results.",
"promptSourcePath": "evals/build-tests-001-rls-tenant-isolation/PROMPT.md",
"attempts": 1,
@@ -4946,37 +5026,16 @@
]
},
"docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"gte-small embedding dimensions Supabase.ai Session\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/ai/choosing-compute-addon",
- "title": "Choosing your Compute Add-on"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/ai-models",
- "title": "Running AI Models"
- },
- {
- "url": "https://supabase.com/docs/guides/ai/semantic-search",
- "title": "Semantic search"
- },
- {
- "url": "https://supabase.com/docs/guides/ai/concepts",
- "title": "Concepts"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/examples/semantic-search",
- "title": "Semantic Search"
- }
- ],
- "resultChars": 62210
- }
- ]
+ "calls": []
},
+ "usage": {
+ "inputTokens": 3677255,
+ "outputTokens": 27954,
+ "cachedInputTokens": 3576367,
+ "cacheCreationInputTokens": 95793,
+ "costUsd": 3.11184975
+ },
+ "durationMs": 384207,
"prompt": "We're adding semantic search to our internal knowledge base app. I already wrote the edge functions, but search doesn't work yet. Can you set up whatever the database needs to make search work end to end?\n\nSome documents are confidential, so users should only have access to documents they own.",
"promptSourcePath": "evals/build-vectors-001-rag-with-permissions/PROMPT.md",
"attempts": 1,
@@ -5009,12 +5068,12 @@
{
"name": "configured the Supabase Metrics API scrape correctly",
"passed": true,
- "judgeNotes": "Supabase scrape is deployable: HTTPS, correct metrics path, Basic Auth with password_file, project target on supabase.co, app job preserved, and docker-compose mounts the password file at the referenced path."
+ "judgeNotes": "Meets requirements: preserves app scrape, adds Supabase HTTPS scrape at /customer/v1/privileged/metrics targeting .supabase.co:443, uses HTTP Basic Auth with password_file, and docker-compose wires the password via a Compose secret mounted at /run/secrets/supabase_metrics_password."
},
{
"name": "documented live deployment and verification steps",
"passed": true,
- "judgeNotes": "README includes Secret API key creation, matching secret file placement, Compose start/reload instructions, and concrete verification via Prometheus targets."
+ "judgeNotes": "README includes Secret API key creation, matching Compose secret file path, project-ref replacement, Prometheus reload, and concrete verification via Prometheus targets."
}
],
"skills": {
@@ -5030,34 +5089,42 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"project metrics endpoint prometheus\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"Prometheus metrics endpoint project\", limit: 5) { nodes { title href ... on Guide { content } } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-self-hosted",
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted",
"title": "Metrics API with Prometheus & Grafana (self-hosted)"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics",
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics",
"title": "Metrics API"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/vendor-agnostic",
- "title": "Vendor-agnostic Metrics API setup"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud",
+ "title": "Metrics API with Grafana Cloud"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-cloud",
- "title": "Metrics API with Grafana Cloud"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic",
+ "title": "Vendor-agnostic Metrics API setup"
},
{
"url": "https://supabase.com/docs/guides/database/replication/manual-replication-monitoring",
"title": "Manual replication monitoring"
}
],
- "resultChars": 27147
+ "resultChars": 23548
}
]
},
+ "usage": {
+ "inputTokens": 1493886,
+ "outputTokens": 15407,
+ "cachedInputTokens": 1420017,
+ "cacheCreationInputTokens": 69876,
+ "costUsd": 1.5525035
+ },
+ "durationMs": 218649,
"prompt": "Can you wire my Supabase project metrics into our existing observability stack and document\nin the observability README what we need to do to make the config live?",
"promptSourcePath": "evals/deploy-database-001-prometheus-metrics/PROMPT.md",
"attempts": 1,
@@ -5096,7 +5163,7 @@
{
"name": "the weather function reads WEATHER_API_KEY from the environment",
"passed": true,
- "judgeNotes": "Reads WEATHER_API_KEY from the runtime environment using Deno.env.get(\"WEATHER_API_KEY\")."
+ "judgeNotes": "The function reads WEATHER_API_KEY from the runtime environment using Deno.env.get('WEATHER_API_KEY')."
},
{
"name": "WEATHER_API_KEY value is not committed to the repo",
@@ -5116,34 +5183,42 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"edge functions environment variables secrets set\", limit: 5) { nodes { title href ... on Guide { content } } } }",
+ "query": "{ searchDocs(query: \"edge function environment variables secrets deploy\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
"url": "https://supabase.com/docs/guides/troubleshooting/inspecting-edge-function-environment-variables-wg5qOQ",
"title": "Inspecting edge function environment variables"
},
- {
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
- },
{
"url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
"title": "Migrating to publishable and secret API keys"
},
+ {
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables"
+ },
{
"url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-transcribe-speech",
"title": "Transcription Telegram Bot"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
+ "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-generate-speech-stream",
+ "title": "Streaming Speech with ElevenLabs"
}
],
- "resultChars": 39587
+ "resultChars": 41423
}
]
},
+ "usage": {
+ "inputTokens": 4153341,
+ "outputTokens": 23352,
+ "cachedInputTokens": 4033965,
+ "cacheCreationInputTokens": 114654,
+ "costUsd": 3.629748
+ },
+ "durationMs": 716774,
"prompt": "Our weather widget currently calls WeatherAPI straight from the browser, which\nleaks our API key. I want to move that behind a Supabase Edge Function called\n`weather` that holds the key server-side and proxies the request.\n\nThe function should read the key from an environment variable named\n`WEATHER_API_KEY`. Our key already lives in a local `.env` file at the project\nroot.\n\nDeploy the function to our project so it's live, and make sure the deployed\nfunction can actually read the key at runtime.",
"promptSourcePath": "evals/deploy-functions-001-edge-function-secrets/PROMPT.md",
"attempts": 1,
@@ -5201,6 +5276,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 2385071,
+ "outputTokens": 9461,
+ "cachedInputTokens": 2300598,
+ "cacheCreationInputTokens": 80204,
+ "costUsd": 1.910154
+ },
+ "durationMs": 181227,
"prompt": "I'm moving off the hosted Supabase and running the whole thing myself on a VPS I\njust spun up. Can you get a Docker setup ready for me to copy onto the box?\n\nI don't need it running here, I'll do the actual bring-up once I'm on the\nserver. I just want everything in place and the secrets set up. Put it in a `supabase-docker/`\nfolder at the repo root so I can scp the whole thing across in one go.",
"promptSourcePath": "evals/deploy-self-hosting-001-docker-compose/PROMPT.md",
"attempts": 1,
@@ -5257,7 +5340,7 @@
{
"name": "diagnosed and explained session revocation",
"passed": true,
- "judgeNotes": "The answer correctly identifies the soft-delete-only bug, implements real revocation via session deletion/refresh-token cascade plus sign-in blocking, adds RLS checks to close stale-token data access for the covered tables, and explains the remaining stateless JWT caveat consistently. It also correctly distinguishes publishable frontend keys from server-only secret keys that bypass RLS."
+ "judgeNotes": "Diagnoses the soft-delete-only flow, implements real auth/session revocation via session deletion and banning, adds RLS to block stale JWTs on the data path, explains the remaining stateless JWT/local-validation window consistently, and correctly distinguishes publishable vs secret keys."
}
],
"skills": {
@@ -5273,36 +5356,21 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"publishable key secret key vs anon service_role migration\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": []
- },
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"publishable key secret key vs anon service_role migration\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"delete user account RPC security definer revoke sessions\", limit: 5) { nodes { ... on Guide { title href content } } } }",
"hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
- },
- {
- "url": "https://supabase.com/docs/guides/troubleshooting/rotating-anon-service-and-jwt-secrets-1Jq6yd",
- "title": "Rotating Anon, Service, and JWT Secrets"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
- }
- ],
- "resultChars": 61183
+ "pages": [],
+ "resultChars": 71
}
]
},
+ "usage": {
+ "inputTokens": 1888484,
+ "outputTokens": 24861,
+ "cachedInputTokens": 1796259,
+ "cacheCreationInputTokens": 87690,
+ "costUsd": 2.091134
+ },
+ "durationMs": 298878,
"prompt": "Last week support removed a user through our app's delete-account flow — the\napp calls the `delete_account` function over RPC as the signed-in user. This\nmorning that same person was back: still signed in, reading and saving their\ndata like nothing happened.\n\nFigure out why the account still works, fix the flow so a deleted account\nloses access, and tell me whether there is any window where they could still\nget in after the fix.\n\nOne more thing while you're at it: we're migrating off the legacy\nanon/service_role API keys to the new publishable and secret keys, and the\nteam isn't sure which one belongs in the frontend and what each means for\nRLS. Give us a quick rundown.",
"promptSourcePath": "evals/investigate-auth-001-deleted-user-access/PROMPT.md",
"attempts": 2,
@@ -5354,7 +5422,7 @@
{
"name": "diagnosed missing publication membership",
"passed": true,
- "judgeNotes": "Diagnosed missing orders table from supabase_realtime publication, applied ALTER PUBLICATION ... ADD TABLE public.orders, preserved courier_locations and RLS/policies."
+ "judgeNotes": "The assistant correctly identified that orders was missing from the supabase_realtime publication despite the channel reaching SUBSCRIBED, added only public.orders to the existing publication, preserved courier_locations and did not alter RLS/policies or blame client code/networking."
}
],
"skills": {
@@ -5362,13 +5430,19 @@
"supabase",
"supabase-postgres-best-practices"
],
- "loaded": [
- "supabase"
- ]
+ "loaded": []
},
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 452571,
+ "outputTokens": 2267,
+ "cachedInputTokens": 411078,
+ "cacheCreationInputTokens": 37378,
+ "costUsd": 0.5170825
+ },
+ "durationMs": 44170,
"prompt": "Our dispatch dashboard shows incoming orders as they happen. The courier\nlocation feed on the same page updates live without problems, but new orders\nonly show up after a page refresh.\n\nThe dashboard uses supabase-js to subscribe to INSERT events on the `orders`\ntable through postgres_changes, the same way it subscribes to courier\nlocations. The channel's status callback logs SUBSCRIBED and there are no\nerrors in the browser console.\n\nFigure out why no order events ever arrive and fix it.",
"promptSourcePath": "evals/investigate-realtime-001-subscribed-no-events/PROMPT.md",
"attempts": 1,
@@ -5398,17 +5472,17 @@
{
"name": "identified image-transform and the recurring 503 pattern",
"passed": true,
- "judgeNotes": "Identified image-transform as the affected function and described recurring 503s throughout the morning of 2026-04-28, covering the gateway failure pattern and distinguishing it from unrelated billing-webhook errors."
+ "judgeNotes": "Identified image-transform as affected and described the recurring HTTP 503 pattern across the morning of 2026-04-28, including most/all 8 gateway failures from 07:00Z to 12:00Z."
},
{
"name": "attributed recurring 503s to gateway/platform layer, not function code",
"passed": true,
- "judgeNotes": "Attributes recurring 503s to gateway/infrastructure before function execution, not function code, and grounds it in valid observations: gateway-only 503s with zero corresponding invocation 503s, nearby successful invocations on unchanged deployment/version, and distinction from avatar-upload's function-level 500."
+ "judgeNotes": "Attributes the recurring 503s to the gateway/platform layer rather than function code, explicitly saying the requests never reached runtime and died at the gateway. Grounds this in valid observations: 503s only appear in API/gateway logs with no corresponding edge-function runtime rows, nearby 200 invocations succeeded, and deployment_id/version stayed stable. It also distinguishes avatar-upload's 500 as separate. Although it speculates about cold starts and suggests code-level optimizations, the primary layer attribution satisfies the rubric."
},
{
"name": "recommended a concrete next step",
"passed": true,
- "judgeNotes": "The assistant provided concrete actionable next steps, including checking Edge Function concurrency/instance limits and cold-start behavior for the specific time window, investigating periodic traffic spikes, adding retry-with-backoff, and digging into specific function logs."
+ "judgeNotes": "The assistant provided multiple concrete, actionable next steps, including measuring import/init latency, reducing cold-start weight, keeping the function warm, adding retries, and pulling current logs if recurrence continues."
}
],
"skills": {
@@ -5416,14 +5490,24 @@
"supabase",
"supabase-postgres-best-practices"
],
- "loaded": []
+ "loaded": [
+ "supabase"
+ ]
},
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 523797,
+ "outputTokens": 7044,
+ "cachedInputTokens": 477388,
+ "cacheCreationInputTokens": 42294,
+ "costUsd": 0.89742525
+ },
+ "durationMs": 108415,
"prompt": "Users have been reporting that image uploads are intermittently failing with server errors throughout the morning of `2026-04-28`.\n\nCan you investigate the project logs and tell me what is going on and what we\nshould do next?",
"promptSourcePath": "evals/investigate-reliability-003-edge-function-5xx-correlation/PROMPT.md",
- "attempts": 2,
+ "attempts": 1,
"sourcePath": "claude-code-sonnet-5/investigate-reliability-003-edge-function-5xx-correlation.json"
},
{
@@ -5477,7 +5561,7 @@
{
"name": "diagnosed RLS and added owner-scoped policies",
"passed": true,
- "judgeNotes": "Diagnosed RLS enabled with no policies causing deny-all Data API results, kept RLS enabled, and created authenticated SELECT and INSERT policies scoped to user_id = auth.uid() with USING and WITH CHECK respectively."
+ "judgeNotes": "The answer correctly diagnoses RLS enabled with no policies causing deny-all Data API results, keeps RLS enabled, and creates authenticated SELECT and INSERT policies scoped to user_id = auth.uid() with WITH CHECK for inserts."
}
],
"skills": {
@@ -5486,12 +5570,21 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 829552,
+ "outputTokens": 5547,
+ "cachedInputTokens": 787785,
+ "cacheCreationInputTokens": 37509,
+ "costUsd": 0.7889647500000002
+ },
+ "durationMs": 92927,
"prompt": "Our app lets signed-in users save bookmarks and view them on their dashboard. Bookmarks are stored in the `bookmarks` table and are private — a user must only ever see their own. \nUsers also need to be able to save new bookmarks from the app.\n\nI can see the rows when I query the table directly, but the dashboard shows an empty list for every user.\n\nFind out why the Data API returns nothing and fix it.",
"promptSourcePath": "evals/resolve-dataapi-001-empty-results/PROMPT.md",
"attempts": 1,
@@ -5541,7 +5634,7 @@
{
"name": "the avatar migration and history reconciliation were done via the Supabase CLI",
"passed": true,
- "judgeNotes": "Applied pending avatar_url migration with `supabase db push` (#17), which output `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` Reconciled the orphan bio migration by adding the missing local migration file `20240115000000_add_bio.sql` (#15), after which `supabase migration list` showed local and remote aligned (#16). Read-only psql inspection was used; no disallowed workaround or direct mutation was seen."
+ "judgeNotes": "Avatar migration was applied through `supabase db push` in action #19, with output `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` The orphan bio migration history was reconciled by adding the missing local migration file `20240115000000_add_profile_bio.sql` in action #17, after which `supabase migration list` showed local and remote aligned. Only read-only psql inspection was used; no disallowed workaround or direct remote mutation was observed."
}
],
"skills": {
@@ -5556,6 +5649,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 845819,
+ "outputTokens": 4218,
+ "cachedInputTokens": 791115,
+ "cacheCreationInputTokens": 50857,
+ "costUsd": 0.83869775
+ },
+ "durationMs": 94472,
"prompt": "I'm trying to ship a migration to our hosted project and it's not working. Can you figure out what's wrong and get it deployed?",
"promptSourcePath": "evals/resolve-database-001-migration-history-mismatch/PROMPT.md",
"attempts": 1,
@@ -5598,7 +5699,7 @@
{
"name": "query plan uses an index and avoids sequential scan",
"passed": true,
- "notes": "Limit (cost=55.55..55.61 rows=25 width=88)\n -> Sort (cost=55.55..55.61 rows=25 width=88)\n Sort Key: created_at DESC\n -> Bitmap Heap Scan on events (cost=4.48..54.97 rows=25 width=88)\n Recheck Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)\n -> Bitmap Index Scan on events_user_id_created_at_idx (cost=0.00..4.47 rows=25 width=0)\n Index Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)"
+ "notes": "Limit (cost=79.74..79.86 rows=50 width=58)\n -> Sort (cost=79.74..79.99 rows=100 width=58)\n Sort Key: created_at DESC\n -> Bitmap Heap Scan on events (cost=5.06..76.42 rows=100 width=58)\n Recheck Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)\n -> Bitmap Index Scan on events_user_id_created_at_idx (cost=0.00..5.03 rows=100 width=0)\n Index Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)"
},
{
"name": "inserts still work",
@@ -5617,6 +5718,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 566317,
+ "outputTokens": 3967,
+ "cachedInputTokens": 519610,
+ "cacheCreationInputTokens": 42589,
+ "costUsd": 0.64638025
+ },
+ "durationMs": 80615,
"prompt": "My database CPU keeps spiking and the app gets slow when loading recent events for a user. Can you figure out what query is causing it and make the database change needed to fix it?\n\nEnd your turn with a short summary of what you changed and why.",
"promptSourcePath": "evals/resolve-performance-001-slow-query-cpu-spike/PROMPT.md",
"attempts": 1,
@@ -5694,6 +5803,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 626188,
+ "outputTokens": 3393,
+ "cachedInputTokens": 569176,
+ "cacheCreationInputTokens": 52895,
+ "costUsd": 0.7211857500000001
+ },
+ "durationMs": 65782,
"prompt": "A customer reported that notes showed up in the wrong workspace.\n\nCan you investigate what is going on and fix it?",
"promptSourcePath": "evals/resolve-security-002-rls-cross-tenant-leak/PROMPT.md",
"attempts": 1,
@@ -5733,7 +5850,7 @@
{
"name": "todos table exists with at least 2 seeded rows",
"passed": true,
- "notes": "found 2 rows"
+ "notes": "found 3 rows"
},
{
"name": "row level security is enabled on todos",
@@ -5751,7 +5868,7 @@
{
"name": "REST API returns the todos to authenticated requests",
"passed": true,
- "notes": "2 rows"
+ "notes": "3 rows"
}
],
"skills": {
@@ -5761,6 +5878,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 811294,
+ "outputTokens": 6474,
+ "cachedInputTokens": 786152,
+ "cacheCreationInputTokens": 21670,
+ "costUsd": 0.7084585000000001
+ },
+ "durationMs": 255759,
"prompt": "We're kicking off a todos app and I want the Supabase side ready for the team\nto build on. Set it up the way we'd run it in development, with schema changes\ntracked as migrations so they can be reviewed and replayed.\n\nFor the first slice we just need a `todos` table. Todos aren't public: anyone\nsigned in can read all of them, but nothing should be writable through the API\nfor now. Add a couple of sample todos so there's something to look at.\n\nBefore you hand it back, make sure the running API actually behaves that way —\nsigned-in users get the todos, signed-out requests get nothing.",
"promptSourcePath": "evals/build-cli-001-bootstrap-app/PROMPT.md",
"attempts": 1,
@@ -5812,6 +5937,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 325585,
+ "outputTokens": 1325,
+ "cachedInputTokens": 310282,
+ "cacheCreationInputTokens": 12113,
+ "costUsd": 0.28051125
+ },
+ "durationMs": 79130,
"prompt": "Add a description text column to the `products` table in my local Supabase stack",
"promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md",
"attempts": 1,
@@ -5850,12 +5983,12 @@
{
"name": "cron command enqueues to the 'tasks' queue",
"passed": true,
- "notes": "queue depth 0 -> 1"
+ "notes": "queue depth 1 -> 2"
},
{
"name": "process-tasks function drains the queue",
"passed": true,
- "notes": "function removed the seeded message (id 3) from the queue"
+ "notes": "function removed the seeded message (id 4) from the queue"
}
],
"skills": {
@@ -5865,6 +5998,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 1098895,
+ "outputTokens": 9045,
+ "cachedInputTokens": 1068094,
+ "cacheCreationInputTokens": 26792,
+ "costUsd": 0.9483520000000003
+ },
+ "durationMs": 237438,
"prompt": "I want to set up a recurring background workflow on my local Supabase stack.\n\nCan you set up a cron job called `enqueue-tasks` to run every minute and push a task into a queue called `tasks`? Then add a `process-tasks` edge function that reads messages off the `tasks` queue and removes them, so a scheduled worker can keep the backlog drained.",
"promptSourcePath": "evals/build-cli-003-pg-cron-queue-workflow/PROMPT.md",
"attempts": 1,
@@ -5919,6 +6060,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 1116730,
+ "outputTokens": 8621,
+ "cachedInputTokens": 1065952,
+ "cacheCreationInputTokens": 47005,
+ "costUsd": 1.0617942500000002
+ },
+ "durationMs": 366622,
"prompt": "I have an existing Postgres database I want to migrate to Supabase. There's a binary dump at `source.dump` in the current directory.\n\nCan you set up a local Supabase project and restore the dump into it?",
"promptSourcePath": "evals/build-database-001-migrate-postgres-to-supabase/PROMPT.md",
"attempts": 1,
@@ -5947,7 +6096,7 @@
],
"suite": "benchmark",
"interface": "mcp",
- "passed": false,
+ "passed": true,
"checks": [
{
"name": "rejects missing auth",
@@ -5961,8 +6110,8 @@
},
{
"name": "reads only with the caller's JWT",
- "passed": false,
- "notes": "bearer_tokens=2, all_match=false"
+ "passed": true,
+ "notes": "bearer_tokens=2, all_match=true"
},
{
"name": "user A cannot force-read user B note",
@@ -5982,9 +6131,17 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 476234,
+ "outputTokens": 4189,
+ "cachedInputTokens": 439609,
+ "cacheCreationInputTokens": 33021,
+ "costUsd": 0.54955375
+ },
+ "durationMs": 67284,
"prompt": "I built an Edge Function called `private-notes` for showing a user's saved\nprivate notes.\n\nCan you check whether there's any way one user could see another user's notes?\n\nPlease fix and deploy it if needed.",
"promptSourcePath": "evals/build-functions-004-service-role-bypass/PROMPT.md",
- "attempts": 2,
+ "attempts": 1,
"sourcePath": "claude-code-sonnet-5-no-skills/build-functions-004-service-role-bypass.json"
},
{
@@ -6011,7 +6168,7 @@
"suite": "benchmark",
"interface": "cli",
"cliVersion": "2.109.1",
- "passed": false,
+ "passed": true,
"checks": [
{
"name": "seed rows present",
@@ -6021,42 +6178,42 @@
{
"name": "rejects request with no credentials",
"passed": true,
- "notes": "status 401: {\"error\":\"Missing bearer token\"}"
+ "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
},
{
"name": "user with JWT reads only their own rows",
"passed": true,
- "notes": "status 200: {\"data\":[{\"user_id\":\"53dfc849-cc40-4ef2-80d0-bf282c98b6c7\",\"metric\":\"steps_a_ms6xiocg\",\"value\":111}]}"
+ "notes": "status 200: {\"data\":[{\"user_id\":\"38a60245-dca4-4fe1-a662-40b4bc95fcf9\",\"metric\":\"steps_a_ms7qeorz\",\"value\":111}]}"
},
{
"name": "user cannot read another user's rows by passing user_id",
"passed": true,
- "notes": "status 200: {\"data\":[{\"user_id\":\"53dfc849-cc40-4ef2-80d0-bf282c98b6c7\",\"metric\":\"steps_a_ms6xiocg\",\"value\":111}]}"
+ "notes": "status 200: {\"data\":[{\"user_id\":\"38a60245-dca4-4fe1-a662-40b4bc95fcf9\",\"metric\":\"steps_a_ms7qeorz\",\"value\":111}]}"
},
{
"name": "service key bypasses RLS to read the target user's rows",
"passed": true,
- "notes": "status 200: {\"data\":[{\"user_id\":\"e51e9bc6-ff44-46b5-83e3-08763a07bd87\",\"metric\":\"steps_b_ms6xiocg\",\"value\":222}]}"
+ "notes": "status 200: {\"data\":[{\"user_id\":\"91fc317a-e47f-4784-a93a-51115e14a44e\",\"metric\":\"steps_b_ms7qeorz\",\"value\":222}]}"
},
{
"name": "non-service key is not granted service access",
"passed": true,
- "notes": "status 401: {\"error\":\"Missing bearer token\"}"
+ "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
},
{
"name": "rejects an unverified (forged) user token",
"passed": true,
- "notes": "status 401: {\"error\":\"Invalid or expired access token\"}"
+ "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
},
{
"name": "a user token in the apikey slot is not treated as the service key",
"passed": true,
- "notes": "status 401: {\"error\":\"Missing bearer token\"}"
+ "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
},
{
"name": "implementation uses @supabase/server",
- "passed": false,
- "notes": "hand-rolled (raw supabase-js or other) — this eval requires @supabase/server"
+ "passed": true,
+ "notes": "imports @supabase/server / withSupabase"
}
],
"skills": {
@@ -6064,11 +6221,48 @@
"loaded": []
},
"docs": {
- "calls": []
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "{ searchDocs(query: \"edge function environment variables SUPABASE_URL SUPABASE_SERVICE_ROLE_KEY SUPABASE_ANON_KEY default secrets\", limit: 5) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
+ "title": "Self-Hosted Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-generate-speech-stream",
+ "title": "Streaming Speech with ElevenLabs"
+ }
+ ],
+ "resultChars": 45031
+ }
+ ]
},
+ "usage": {
+ "inputTokens": 2574462,
+ "outputTokens": 24876,
+ "cachedInputTokens": 2496224,
+ "cacheCreationInputTokens": 74304,
+ "costUsd": 2.35914
+ },
+ "durationMs": 369001,
"prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nOur product stores per-user metrics in the existing `user_stats` table.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.",
"promptSourcePath": "evals/build-functions-005-dual-auth-user-secret/PROMPT.md",
- "attempts": 2,
+ "attempts": 1,
"sourcePath": "claude-code-sonnet-5-no-skills/build-functions-005-dual-auth-user-secret.json"
},
{
@@ -6109,7 +6303,7 @@
{
"name": "user A lists only own files",
"passed": true,
- "notes": "saw: 019fb0e7-0613-730a-ae13-0efd0c195137/receipt-alpha.pdf, 019fb0e7-0613-730a-ae13-0efd0c195137/receipt-beta.pdf"
+ "notes": "saw: 019fb3d8-7893-76a8-946d-ad148e9f33f6/receipt-alpha.pdf, 019fb3d8-7893-76a8-946d-ad148e9f33f6/receipt-beta.pdf"
},
{
"name": "user B cannot read user A files",
@@ -6130,7 +6324,7 @@
{
"name": "configured private per-user storage access",
"passed": true,
- "judgeNotes": "Meets requirements: private user-files bucket, authenticated owner-scoped SELECT and INSERT policies with WITH CHECK on storage.objects, no RLS disabling or public access, and supabase-js createSignedUrl with expiry for sharing."
+ "judgeNotes": "Meets all criteria: private bucket, authenticated owner-scoped SELECT and INSERT policies with WITH CHECK, no RLS disabling or public access, and uses createSignedUrl with expiry for sharing."
}
],
"skills": {
@@ -6140,6 +6334,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 370641,
+ "outputTokens": 2676,
+ "cachedInputTokens": 333042,
+ "cacheCreationInputTokens": 34003,
+ "costUsd": 0.46462775
+ },
+ "durationMs": 51836,
"prompt": "Our app lets signed-in users keep personal files like receipts and bank\nstatements. These files are private — a user must only ever be able to upload\nand download their own. The app uploads each file under a path that starts\nwith the owner's user id, e.g. `/receipt-march.pdf`.\n\nSet up a `user-files` bucket on our project and lock it down that way.\n\nUsers also sometimes share one of their files with someone else through a\ntemporary link that expires. Include the supabase-js code the app should use\nfor that.",
"promptSourcePath": "evals/build-storage-001-private-bucket-access/PROMPT.md",
"attempts": 1,
@@ -6170,17 +6372,17 @@
{
"name": "pgTAP test file(s) written under supabase/tests/",
"passed": true,
- "notes": "1 file(s): supabase/tests/database/tenant_isolation_test.sql"
+ "notes": "1 file(s): supabase/tests/database/rls_tenant_isolation.test.sql"
},
{
"name": "pgTAP isolation tests ran and pass",
"passed": true,
- "notes": "6 passed, 2 failed"
+ "notes": "5 passed, 4 failed"
},
{
"name": "agent correctly identifies the posts isolation bug from test results",
"passed": true,
- "judgeNotes": "The agent correctly identifies `posts` as the table with the broken tenant isolation policy, explains that authenticated members of any org can read other organizations’ posts, and grounds the conclusion in pgTAP failures. It distinguishes `notes` as correctly isolated for reads and treats the test results as authoritative."
+ "judgeNotes": "The agent correctly identifies `posts` as the table with the broken tenant isolation policy, explains that authenticated members can read posts from organizations they are not members of, and grounds the conclusion in the pgTAP failures while treating `notes` as correctly isolated."
}
],
"skills": {
@@ -6190,6 +6392,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 851503,
+ "outputTokens": 11547,
+ "cachedInputTokens": 822076,
+ "cacheCreationInputTokens": 26086,
+ "costUsd": 0.8800675000000001
+ },
+ "durationMs": 150953,
"prompt": "Can you audit the tenant isolation on our tables? Write some database tests covering both the happy path and the negative case, run them, and share the results.",
"promptSourcePath": "evals/build-tests-001-rls-tenant-isolation/PROMPT.md",
"attempts": 1,
@@ -6255,37 +6465,16 @@
"loaded": []
},
"docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"match_document_sections pgvector edge function embeddings\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/functions/examples/semantic-search",
- "title": "Semantic Search"
- },
- {
- "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
- "title": "Automatic embeddings"
- },
- {
- "url": "https://supabase.com/docs/guides/ai/semantic-search",
- "title": "Semantic search"
- },
- {
- "url": "https://supabase.com/docs/guides/database/extensions/pgvector",
- "title": "pgvector: Embeddings and vector similarity"
- },
- {
- "url": "https://supabase.com/docs/guides/ai/hybrid-search",
- "title": "Hybrid search"
- }
- ],
- "resultChars": 68270
- }
- ]
+ "calls": []
},
+ "usage": {
+ "inputTokens": 1570337,
+ "outputTokens": 15314,
+ "cachedInputTokens": 1519810,
+ "cacheCreationInputTokens": 46369,
+ "costUsd": 1.4539962499999999
+ },
+ "durationMs": 199755,
"prompt": "We're adding semantic search to our internal knowledge base app. I already wrote the edge functions, but search doesn't work yet. Can you set up whatever the database needs to make search work end to end?\n\nSome documents are confidential, so users should only have access to documents they own.",
"promptSourcePath": "evals/build-vectors-001-rag-with-permissions/PROMPT.md",
"attempts": 1,
@@ -6318,12 +6507,12 @@
{
"name": "configured the Supabase Metrics API scrape correctly",
"passed": false,
- "judgeNotes": "Fails: Supabase scrape is not deployable against .supabase.co/red, uses http and host.docker.internal, uses inline basic_auth password instead of password_file, and docker-compose.yml does not mount a password_file via volume or secret."
+ "judgeNotes": "Fails: Supabase scrape uses scheme: http and target host.docker.internal:40813 instead of a deployable .supabase.co or .supabase.red HTTPS target. App job and password_file mount are preserved, but endpoint wiring is not deployable as required."
},
{
"name": "documented live deployment and verification steps",
- "passed": false,
- "judgeNotes": "README includes Secret API key creation, reload/restart, and Prometheus target verification, but it does not provide required steps to place a matching secret file; the config uses an inline placeholder instead of a concrete password_file/secret-file setup."
+ "passed": true,
+ "judgeNotes": "README includes Secret API key creation, secret file placement, Compose restart/reload, and concrete verification via Prometheus targets/Grafana. Endpoint/auth and secret handling are consistent."
}
],
"skills": {
@@ -6334,30 +6523,38 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"self-hosted metrics endpoint prometheus\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"metrics endpoint prometheus self-hosted\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-self-hosted",
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted",
"title": "Metrics API with Prometheus & Grafana (self-hosted)"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics",
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics",
"title": "Metrics API"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/vendor-agnostic",
- "title": "Vendor-agnostic Metrics API setup"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud",
+ "title": "Metrics API with Grafana Cloud"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-cloud",
- "title": "Metrics API with Grafana Cloud"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic",
+ "title": "Vendor-agnostic Metrics API setup"
}
],
- "resultChars": 23542
+ "resultChars": 19943
}
]
},
+ "usage": {
+ "inputTokens": 1600312,
+ "outputTokens": 9689,
+ "cachedInputTokens": 1520364,
+ "cacheCreationInputTokens": 76472,
+ "costUsd": 1.4983670000000002
+ },
+ "durationMs": 154569,
"prompt": "Can you wire my Supabase project metrics into our existing observability stack and document\nin the observability README what we need to do to make the config live?",
"promptSourcePath": "evals/deploy-database-001-prometheus-metrics/PROMPT.md",
"attempts": 2,
@@ -6410,6 +6607,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 2452992,
+ "outputTokens": 13959,
+ "cachedInputTokens": 2380353,
+ "cacheCreationInputTokens": 68276,
+ "costUsd": 1.9884085000000011
+ },
+ "durationMs": 374923,
"prompt": "Our weather widget currently calls WeatherAPI straight from the browser, which\nleaks our API key. I want to move that behind a Supabase Edge Function called\n`weather` that holds the key server-side and proxies the request.\n\nThe function should read the key from an environment variable named\n`WEATHER_API_KEY`. Our key already lives in a local `.env` file at the project\nroot.\n\nDeploy the function to our project so it's live, and make sure the deployed\nfunction can actually read the key at runtime.",
"promptSourcePath": "evals/deploy-functions-001-edge-function-secrets/PROMPT.md",
"attempts": 1,
@@ -6462,6 +6667,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 1331551,
+ "outputTokens": 8441,
+ "cachedInputTokens": 1286724,
+ "cacheCreationInputTokens": 41345,
+ "costUsd": 1.13091325
+ },
+ "durationMs": 131027,
"prompt": "I'm moving off the hosted Supabase and running the whole thing myself on a VPS I\njust spun up. Can you get a Docker setup ready for me to copy onto the box?\n\nI don't need it running here, I'll do the actual bring-up once I'm on the\nserver. I just want everything in place and the secrets set up. Put it in a `supabase-docker/`\nfolder at the repo root so I can scp the whole thing across in one go.",
"promptSourcePath": "evals/deploy-self-hosting-001-docker-compose/PROMPT.md",
"attempts": 1,
@@ -6518,7 +6731,7 @@
{
"name": "diagnosed and explained session revocation",
"passed": true,
- "judgeNotes": "Meets rubric: identifies soft-delete-only cause, implements auth/session revocation plus RLS checks, accurately explains JWT expiry/local validation caveat consistent with its RLS fix, and correctly distinguishes publishable vs secret keys and RLS behavior."
+ "judgeNotes": "Diagnoses soft-delete-only flow and lack of session/refresh-token revocation. Implements real auth-side revocation by banning/deleted_at plus deleting sessions/refresh tokens, and strengthens RLS to check deleted=false. JWT window explanation is consistent: token remains cryptographically valid until expiry for local validation, but the implemented RLS data path blocks access immediately. Correctly explains publishable key is frontend/RLS-enforced and secret/service_role is server-only and bypasses RLS."
}
],
"skills": {
@@ -6526,22 +6739,16 @@
"loaded": []
},
"docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"publishable key secret key anon service_role migration RLS\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": []
- },
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"publishable key secret key anon service_role migration RLS\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [],
- "resultChars": 149036
- }
- ]
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 2046837,
+ "outputTokens": 23724,
+ "cachedInputTokens": 1983515,
+ "cacheCreationInputTokens": 59156,
+ "costUsd": 1.9761544999999996
},
+ "durationMs": 322841,
"prompt": "Last week support removed a user through our app's delete-account flow — the\napp calls the `delete_account` function over RPC as the signed-in user. This\nmorning that same person was back: still signed in, reading and saving their\ndata like nothing happened.\n\nFigure out why the account still works, fix the flow so a deleted account\nloses access, and tell me whether there is any window where they could still\nget in after the fix.\n\nOne more thing while you're at it: we're migrating off the legacy\nanon/service_role API keys to the new publishable and secret keys, and the\nteam isn't sure which one belongs in the frontend and what each means for\nRLS. Give us a quick rundown.",
"promptSourcePath": "evals/investigate-auth-001-deleted-user-access/PROMPT.md",
"attempts": 2,
@@ -6593,7 +6800,7 @@
{
"name": "diagnosed missing publication membership",
"passed": true,
- "judgeNotes": "The assistant correctly identified the root cause as orders missing from the supabase_realtime publication, explained why SUBSCRIBED can occur without INSERT events, added public.orders to the existing publication with ALTER PUBLICATION, and preserved RLS/policies and the courier_locations feed. It did not blame client code, networking, grants, or weaken security."
+ "judgeNotes": "Diagnosed the missing orders table in supabase_realtime publication, applied ALTER PUBLICATION ADD TABLE public.orders, and did not weaken RLS/policies or disrupt courier_locations."
}
],
"skills": {
@@ -6603,6 +6810,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 396923,
+ "outputTokens": 2337,
+ "cachedInputTokens": 367077,
+ "cacheCreationInputTokens": 26244,
+ "costUsd": 0.42467950000000004
+ },
+ "durationMs": 46962,
"prompt": "Our dispatch dashboard shows incoming orders as they happen. The courier\nlocation feed on the same page updates live without problems, but new orders\nonly show up after a page refresh.\n\nThe dashboard uses supabase-js to subscribe to INSERT events on the `orders`\ntable through postgres_changes, the same way it subscribes to courier\nlocations. The channel's status callback logs SUBSCRIBED and there are no\nerrors in the browser console.\n\nFigure out why no order events ever arrive and fix it.",
"promptSourcePath": "evals/investigate-realtime-001-subscribed-no-events/PROMPT.md",
"attempts": 1,
@@ -6632,17 +6847,17 @@
{
"name": "identified image-transform and the recurring 503 pattern",
"passed": true,
- "judgeNotes": "Identified `image-transform` as the affected function and described the recurring HTTP 503 gateway pattern across the morning of 2026-04-28, covering most of the failures in the 07:00Z–12:00Z window. Also correctly treated old billing-webhook 503s as unrelated."
+ "judgeNotes": "The assistant correctly identified `image-transform` as the affected function and described the recurring HTTP 503 pattern across the morning of 2026-04-28, listing most/all gateway failures from 07:00Z through 12:00Z. It also correctly distinguished the older billing-webhook 503s as unrelated."
},
{
"name": "attributed recurring 503s to gateway/platform layer, not function code",
"passed": true,
- "judgeNotes": "Attributes the recurring image-transform 503s to the gateway/platform layer before function execution, grounded in gateway-only 503s with no matching invocation/runtime rows, unchanged version/deployment, and contrast with avatar-upload's true in-function 500."
+ "judgeNotes": "Attributes the recurring image-transform 503s to the gateway/platform layer before function invocation, grounded in the observation that 503s appear in gateway logs but not edge-function execution logs while successful invocations do appear. It also distinguishes the avatar-upload 500 as a function-level error."
},
{
"name": "recommended a concrete next step",
"passed": true,
- "judgeNotes": "The assistant recommended concrete actionable next steps, including checking resource/concurrency limits, investigating a memory-heavy dependency, adding retry/backoff, and separately improving error logging for avatar-upload."
+ "judgeNotes": "The assistant gave specific actionable next steps, including pulling deployment/boot logs for exact 503 timestamps, checking concurrency/CPU/memory limits and traffic spikes, and investigating shared native dependencies."
}
],
"skills": {
@@ -6652,6 +6867,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 418001,
+ "outputTokens": 5682,
+ "cachedInputTokens": 373008,
+ "cacheCreationInputTokens": 41395,
+ "costUsd": 0.6058917500000001
+ },
+ "durationMs": 83258,
"prompt": "Users have been reporting that image uploads are intermittently failing with server errors throughout the morning of `2026-04-28`.\n\nCan you investigate the project logs and tell me what is going on and what we\nshould do next?",
"promptSourcePath": "evals/investigate-reliability-003-edge-function-5xx-correlation/PROMPT.md",
"attempts": 1,
@@ -6708,7 +6931,7 @@
{
"name": "diagnosed RLS and added owner-scoped policies",
"passed": true,
- "judgeNotes": "Diagnoses RLS enabled with no policies causing deny-all/empty Data API results; keeps RLS enabled; creates authenticated SELECT policy with auth.uid() = user_id and INSERT policy with WITH CHECK enforcing auth.uid() = user_id."
+ "judgeNotes": "Diagnosed RLS enabled with no policies causing deny-all Data API results, kept RLS enabled, and created authenticated SELECT and INSERT policies scoped to auth.uid() = user_id with WITH CHECK for inserts."
}
],
"skills": {
@@ -6718,6 +6941,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 349706,
+ "outputTokens": 2281,
+ "cachedInputTokens": 314351,
+ "cacheCreationInputTokens": 31759,
+ "costUsd": 0.43135025
+ },
+ "durationMs": 38845,
"prompt": "Our app lets signed-in users save bookmarks and view them on their dashboard. Bookmarks are stored in the `bookmarks` table and are private — a user must only ever see their own. \nUsers also need to be able to save new bookmarks from the app.\n\nI can see the rows when I query the table directly, but the dashboard shows an empty list for every user.\n\nFind out why the Data API returns nothing and fix it.",
"promptSourcePath": "evals/resolve-dataapi-001-empty-results/PROMPT.md",
"attempts": 1,
@@ -6767,7 +6998,7 @@
{
"name": "the avatar migration and history reconciliation were done via the Supabase CLI",
"passed": true,
- "judgeNotes": "Applied via `supabase db push` (#12), which shows `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` Reconciled the orphan bio migration by adding the missing local migration file `supabase/migrations/20240115000000_add_profile_bio.sql` (#10), after which `supabase migration list` (#11) showed local and remote aligned. Only read-only psql inspection was used; no disallowed workaround seen."
+ "judgeNotes": "Applied avatar_url via `supabase db push` (#16), which showed `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` Reconciled the orphan bio migration by adding the missing local migration file `20240115000000_add_profile_bio.sql` (#14), after which `supabase migration list` and the successful push showed histories aligned. No disallowed workaround observed; psql use was read-only inspection."
}
],
"skills": {
@@ -6777,6 +7008,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 531970,
+ "outputTokens": 3923,
+ "cachedInputTokens": 490224,
+ "cacheCreationInputTokens": 38423,
+ "costUsd": 0.6005447499999998
+ },
+ "durationMs": 77960,
"prompt": "I'm trying to ship a migration to our hosted project and it's not working. Can you figure out what's wrong and get it deployed?",
"promptSourcePath": "evals/resolve-database-001-migration-history-mismatch/PROMPT.md",
"attempts": 1,
@@ -6833,6 +7072,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 489220,
+ "outputTokens": 3023,
+ "cachedInputTokens": 450816,
+ "cacheCreationInputTokens": 34802,
+ "costUsd": 0.5371345000000001
+ },
+ "durationMs": 52849,
"prompt": "My database CPU keeps spiking and the app gets slow when loading recent events for a user. Can you figure out what query is causing it and make the database change needed to fix it?\n\nEnd your turn with a short summary of what you changed and why.",
"promptSourcePath": "evals/resolve-performance-001-slow-query-cpu-spike/PROMPT.md",
"attempts": 1,
@@ -6905,6 +7152,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 409200,
+ "outputTokens": 2478,
+ "cachedInputTokens": 378417,
+ "cacheCreationInputTokens": 27181,
+ "costUsd": 0.43964374999999994
+ },
+ "durationMs": 49837,
"prompt": "A customer reported that notes showed up in the wrong workspace.\n\nCan you investigate what is going on and fix it?",
"promptSourcePath": "evals/resolve-security-002-rls-cross-tenant-leak/PROMPT.md",
"attempts": 1,
@@ -6971,1612 +7226,672 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"RLS expose table anon authenticated policies select insert update supabase local development migrations\", limit: 5) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"Row Level Security policies authenticated select all rows no writes\", limit: 5) { nodes { title href content ... on Guide { subsections { nodes { title href content } } } } } }",
"hasContent": true,
"pages": [
- {
- "url": "https://supabase.com/docs/guides/local-development/cli-workflows",
- "title": "Local development workflow"
- },
{
"url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
"title": "Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/api/securing-your-api",
- "title": "Securing your API"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-1",
+ "title": "Benchmarks"
},
{
- "url": "https://supabase.com/docs/guides/auth/quickstarts/with-expo-react-native-social-auth",
- "title": "Build a Social Auth App with Expo React Native"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#call-functions-with-select",
+ "title": "Call functions with select"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs",
- "title": "Build a User Management App with RedwoodJS"
- }
- ],
- "resultChars": 163038
- }
- ]
- },
- "prompt": "We're kicking off a todos app and I want the Supabase side ready for the team\nto build on. Set it up the way we'd run it in development, with schema changes\ntracked as migrations so they can be reviewed and replayed.\n\nFor the first slice we just need a `todos` table. Todos aren't public: anyone\nsigned in can read all of them, but nothing should be writable through the API\nfor now. Add a couple of sample todos so there's something to look at.\n\nBefore you hand it back, make sure the running API actually behaves that way —\nsigned-in users get the todos, signed-out requests get nothing.",
- "promptSourcePath": "evals/build-cli-001-bootstrap-app/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini/build-cli-001-bootstrap-app.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "build-cli-002-declarative-schema",
- "stage": "build",
- "product": [
- "database"
- ],
- "topic": [
- "declarative-schema",
- "migrations"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "passed": true,
- "checks": [
- {
- "name": "supabase db diff used to generate the migration",
- "passed": true
- },
- {
- "name": "schema file updated to include description column",
- "passed": true
- },
- {
- "name": "a new migration was generated for the change",
- "passed": true
- },
- {
- "name": "description column exists in the live database",
- "passed": true
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": []
- },
- "prompt": "Add a description text column to the `products` table in my local Supabase stack",
- "promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini/build-cli-002-declarative-schema.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "build-cli-003-pg-cron-queue-workflow",
- "stage": "build",
- "product": [
- "database",
- "edge-functions",
- "cron",
- "queues"
- ],
- "topic": [
- "sql",
- "sdk"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "passed": true,
- "checks": [
- {
- "name": "pg_cron job 'enqueue-tasks' scheduled to run every minute",
- "passed": true,
- "notes": "schedule='* * * * *', active=true"
- },
- {
- "name": "cron command enqueues to the 'tasks' queue",
- "passed": true,
- "notes": "queue depth 1 -> 2"
- },
- {
- "name": "process-tasks function drains the queue",
- "passed": true,
- "notes": "function removed the seeded message (id 4) from the queue"
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"pg_cron schedule cron jobs Supabase local development\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks",
+ "title": "Benchmarks"
+ },
{
- "url": "https://supabase.com/docs/guides/cron",
- "title": "Cron"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#add-indexes",
+ "title": "Add indexes"
},
{
- "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
- "title": "Automatic embeddings"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#rls-performance-recommendations",
+ "title": "RLS performance recommendations"
},
{
- "url": "https://supabase.com/docs/guides/auth/auth-hooks/send-email-hook",
- "title": "Send Email Hook"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#bypassing-row-level-security",
+ "title": "Bypassing Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/cron/install",
- "title": "Install"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#mfa",
+ "title": "MFA"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net",
- "title": "pg_net: Async Networking"
- }
- ],
- "resultChars": 94119
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase Queues pgmq pop send delete read edge functions local development\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#authjwt",
+ "title": "auth.jwt()"
+ },
{
- "url": "https://supabase.com/docs/guides/queues",
- "title": "Supabase Queues"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#authuid",
+ "title": "auth.uid()"
},
{
- "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions",
- "title": "Consuming Supabase Queue Messages with Edge Functions"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#helper-functions",
+ "title": "Helper functions"
},
{
- "url": "https://supabase.com/docs/guides/queues/api",
- "title": "API"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-3",
+ "title": "Benchmarks"
},
{
- "url": "https://supabase.com/docs/guides/local-development/cli/testing-and-linting",
- "title": "Testing and linting"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#views",
+ "title": "Views"
},
{
- "url": "https://supabase.com/docs/guides/functions/architecture",
- "title": "Edge Functions Architecture"
- }
- ],
- "resultChars": 18872
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase edge functions local development deploy serve deno\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#delete-policies",
+ "title": "DELETE policies"
+ },
{
- "url": "https://supabase.com/docs/guides/functions/quickstart",
- "title": "Getting Started with Edge Functions"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#update-policies",
+ "title": "UPDATE policies"
},
{
- "url": "https://supabase.com/docs/guides/functions/quickstart-dashboard",
- "title": "Getting Started with Edge Functions (Dashboard)"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#insert-policies",
+ "title": "INSERT policies"
},
{
- "url": "https://supabase.com/docs/guides/functions",
- "title": "Edge Functions"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#more-resources",
+ "title": "More resources"
},
{
- "url": "https://supabase.com/docs/guides/functions/development-environment",
- "title": "Development Environment"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-4",
+ "title": "Benchmarks"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/mcp-server-mcp-lite",
- "title": "Building an MCP Server with mcp-lite"
- }
- ],
- "resultChars": 47492
- }
- ]
- },
- "prompt": "I want to set up a recurring background workflow on my local Supabase stack.\n\nCan you set up a cron job called `enqueue-tasks` to run every minute and push a task into a queue called `tasks`? Then add a `process-tasks` edge function that reads messages off the `tasks` queue and removes them, so a scheduled worker can keep the backlog drained.",
- "promptSourcePath": "evals/build-cli-003-pg-cron-queue-workflow/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini/build-cli-003-pg-cron-queue-workflow.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "build-database-001-migrate-postgres-to-supabase",
- "stage": "build",
- "product": [
- "database"
- ],
- "topic": [
- "migrations"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "passed": true,
- "checks": [
- {
- "name": "all 3 tables exist (teams, members, tasks)",
- "passed": true
- },
- {
- "name": "row counts match (teams=5, members=10, tasks=13)",
- "passed": true
- },
- {
- "name": "foreign key constraints survived the restore",
- "passed": true
- },
- {
- "name": "tasks_team_status_idx index survived the restore",
- "passed": true
- },
- {
- "name": "sequences synced (next insert won't conflict with existing IDs)",
- "passed": true
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": []
- },
- "prompt": "I have an existing Postgres database I want to migrate to Supabase. There's a binary dump at `source.dump` in the current directory.\n\nCan you set up a local Supabase project and restore the dump into it?",
- "promptSourcePath": "evals/build-database-001-migrate-postgres-to-supabase/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini/build-database-001-migrate-postgres-to-supabase.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "build-functions-004-service-role-bypass",
- "stage": "build",
- "product": [
- "edge-functions",
- "auth",
- "database"
- ],
- "topic": [
- "rls",
- "security",
- "sdk"
- ],
- "suite": "benchmark",
- "interface": "mcp",
- "passed": true,
- "checks": [
- {
- "name": "rejects missing auth",
- "passed": true,
- "notes": "status=401"
- },
- {
- "name": "user A reads own note",
- "passed": true,
- "notes": "status=200"
- },
- {
- "name": "reads only with the caller's JWT",
- "passed": true,
- "notes": "bearer_tokens=2, all_match=true"
- },
- {
- "name": "user A cannot force-read user B note",
- "passed": true,
- "notes": "status=200"
- },
- {
- "name": "user B cannot force-read user A note",
- "passed": true,
- "notes": "status=200"
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query {\n searchDocs(query: \"Supabase Edge Functions verify JWT Authorization header createClient service role key anon key auth.getUser\", limit: 5) {\n nodes {\n title\n href\n content\n }\n }\n}",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#specify-roles-in-your-policies",
+ "title": "Specify roles in your policies"
+ },
{
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#minimize-joins",
+ "title": "Minimize joins"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#use-security-definer-functions",
+ "title": "Use security definer functions"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-2",
+ "title": "Benchmarks"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
- "title": "Integrating With Supabase Auth"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#add-filters-to-every-query",
+ "title": "Add filters to every query"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
- "title": "Why is my service role key client getting RLS errors or not returning data?"
- }
- ],
- "resultChars": 45333
- },
- {
- "source": "web_search",
- "query": "https://supabase.com/changelog.md",
- "pages": [
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#select-policies",
+ "title": "SELECT policies"
+ },
{
- "url": "https://supabase.com/changelog.md"
- }
- ]
- },
- {
- "source": "search_docs",
- "query": "query {\n searchDocs(query: \"Supabase Edge Functions environment variables SUPABASE_ANON_KEY SUPABASE_PUBLISHABLE_KEY\", limit: 10) {\n nodes {\n title\n href\n content\n }\n }\n}",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#creating-policies",
+ "title": "Creating policies"
+ },
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#authenticated-and-unauthenticated-roles",
+ "title": "Authenticated and unauthenticated roles"
},
{
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#auto-enable-rls-for-new-tables",
+ "title": "Auto-enable RLS for new tables"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#enabling-row-level-security",
+ "title": "Enabling Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#policies",
+ "title": "Policies"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#row-level-security-in-supabase",
+ "title": "Row Level Security in Supabase"
},
{
- "url": "https://supabase.com/docs/guides/auth/quickstarts/with-expo-react-native-social-auth",
- "title": "Build a Social Auth App with Expo React Native"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api",
+ "title": "Securing your API"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-generate-speech-stream",
- "title": "Streaming Speech with ElevenLabs"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#add-rls-policies",
+ "title": "Add RLS policies"
},
{
- "url": "https://supabase.com/docs/guides/integrations/vercel-marketplace",
- "title": "Vercel Marketplace"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#disable-the-data-api",
+ "title": "Disable the Data API"
},
{
- "url": "https://supabase.com/docs/guides/auth/server-side/creating-a-client",
- "title": "Creating a Supabase client for SSR"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#use-a-dedicated-api-schema",
+ "title": "Use a dedicated API schema"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
- }
- ],
- "resultChars": 189134
- }
- ]
- },
- "prompt": "I built an Edge Function called `private-notes` for showing a user's saved\nprivate notes.\n\nCan you check whether there's any way one user could see another user's notes?\n\nPlease fix and deploy it if needed.",
- "promptSourcePath": "evals/build-functions-004-service-role-bypass/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini/build-functions-004-service-role-bypass.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "build-functions-005-dual-auth-user-secret",
- "stage": "build",
- "product": [
- "edge-functions",
- "auth",
- "database"
- ],
- "topic": [
- "sdk",
- "rls",
- "security"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "cliVersion": "2.109.1",
- "passed": false,
- "checks": [
- {
- "name": "read stack config from `supabase status`",
- "passed": false,
- "notes": "missing API_URL/SECRET_KEY/PUBLISHABLE_KEY — new API keys are required for @supabase/server; is the stack running on a new-enough CLI? got keys: ANON_KEY, DB_URL, JWT_SECRET, PUBLISHABLE_KEY, SECRET_KEY, SERVICE_ROLE_KEY"
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase",
- "supabase-postgres-best-practices"
- ]
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"Edge Functions verify JWT service role apikey header auth.getUser Deno.serve Supabase\", limit: 5) { nodes { __typename title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#default-privileges-for-new-tables-and-functions",
+ "title": "Default privileges for new tables and functions"
+ },
{
- "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
- "title": "Integrating With Supabase Auth"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#grant-access-explicitly",
+ "title": "Grant access explicitly"
},
{
- "url": "https://supabase.com/docs/guides/functions/websockets",
- "title": "Handling WebSockets"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#examples",
+ "title": "Examples"
},
{
- "url": "https://supabase.com/docs/guides/functions",
- "title": "Edge Functions"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#accessing-request-information",
+ "title": "Accessing request information"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#enforce-additional-rules-on-each-request",
+ "title": "Enforce additional rules on each request"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets",
- "title": "Resumable WebSockets with Edge Functions"
- }
- ],
- "resultChars": 49160
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"functions verify_jwt false config.toml edge function\", limit: 5) { nodes { __typename title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/getting-started/features",
+ "title": "Features"
+ },
{
- "url": "https://supabase.com/docs/guides/functions/function-configuration",
- "title": "Function Configuration"
+ "url": "https://supabase.com/docs/guides/getting-started/features#phone-logins",
+ "title": "Phone logins"
},
{
- "url": "https://supabase.com/docs/guides/functions/deploy",
- "title": "Deploy to Production"
+ "url": "https://supabase.com/docs/guides/getting-started/features#database",
+ "title": "Database"
},
{
- "url": "https://supabase.com/docs/guides/functions/development-tips",
- "title": "Development tips"
+ "url": "https://supabase.com/docs/guides/getting-started/features#postgres-database",
+ "title": "Postgres database"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/github-actions",
- "title": "GitHub Actions"
+ "url": "https://supabase.com/docs/guides/getting-started/features#vector-database",
+ "title": "Vector database"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-headers",
- "title": "Authorization headers"
- }
- ],
- "resultChars": 20522
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"supabase functions serve entrypoint config.toml no-verify-jwt import_map deno.json\", limit: 5) { nodes { __typename title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/getting-started/features#auto-generated-rest-api-via-postgrest",
+ "title": "Auto-generated REST API via PostgREST"
+ },
{
- "url": "https://supabase.com/docs/guides/functions/development-tips",
- "title": "Development tips"
+ "url": "https://supabase.com/docs/guides/getting-started/features#auto-generated-graphql-api-via-pg_graphql",
+ "title": "Auto-generated GraphQL API via pg_graphql"
},
{
- "url": "https://supabase.com/docs/guides/functions/dependencies",
- "title": "Managing dependencies"
+ "url": "https://supabase.com/docs/guides/getting-started/features#database-webhooks",
+ "title": "Database webhooks"
},
{
- "url": "https://supabase.com/docs/guides/functions/function-configuration",
- "title": "Function Configuration"
+ "url": "https://supabase.com/docs/guides/getting-started/features#secrets-and-encryption",
+ "title": "Secrets and encryption"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/mcp-server-mcp-lite",
- "title": "Building an MCP Server with mcp-lite"
+ "url": "https://supabase.com/docs/guides/getting-started/features#replication",
+ "title": "Replication"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
- }
- ],
- "resultChars": 32932
- },
- {
- "source": "web_search",
- "query": "\"failed to determine entrypoint\" \"No .npmrc file found\" Supabase functions serve",
- "pages": []
- }
- ]
- },
- "prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nOur product stores per-user metrics in the existing `user_stats` table.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.",
- "promptSourcePath": "evals/build-functions-005-dual-auth-user-secret/PROMPT.md",
- "attempts": 2,
- "sourcePath": "codex-gpt-5.4-mini/build-functions-005-dual-auth-user-secret.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "build-storage-001-private-bucket-access",
- "stage": "build",
- "product": [
- "storage",
- "database"
- ],
- "topic": [
- "rls",
- "sdk"
- ],
- "suite": "benchmark",
- "interface": "mcp",
- "passed": true,
- "checks": [
- {
- "name": "bucket user-files exists",
- "passed": true
- },
- {
- "name": "bucket user-files is private",
- "passed": true
- },
- {
- "name": "RLS still enabled on storage.objects",
- "passed": true
- },
- {
- "name": "user A lists only own files",
- "passed": true,
- "notes": "saw: 019fb0e7-3951-71a0-8d70-ee9bba881248/receipt-alpha.pdf, 019fb0e7-3951-71a0-8d70-ee9bba881248/receipt-beta.pdf"
- },
- {
- "name": "user B cannot read user A files",
- "passed": true
- },
- {
- "name": "anon reads no files",
- "passed": true
- },
- {
- "name": "user A can upload into own folder",
- "passed": true
- },
- {
- "name": "user B cannot upload into user A folder",
- "passed": true
- },
- {
- "name": "configured private per-user storage access",
- "passed": true,
- "judgeNotes": "Creates private user-files bucket, authenticated owner-scoped SELECT and INSERT policies with WITH CHECK using first path segment = auth.uid(), keeps RLS enabled, and provides createSignedUrl code with expiry. No disallowed public bucket/getPublicUrl/service-role usage."
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"storage policies signed urls user owns files bucket create policies\", limit: 5) { nodes { __typename ... on Guide { title href content } ... on ClientLibraryFunctionReference { title href content language methodName } } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/getting-started/features#platform",
+ "title": "Platform"
+ },
{
- "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
- "title": "Storage Buckets"
+ "url": "https://supabase.com/docs/guides/getting-started/features#database-backups",
+ "title": "Database backups"
},
{
- "url": "https://supabase.com/docs/guides/storage/security/access-control",
- "title": "Storage Access Control"
+ "url": "https://supabase.com/docs/guides/getting-started/features#custom-domains",
+ "title": "Custom domains"
},
{
- "url": "https://supabase.com/docs/guides/storage/schema/custom-roles",
- "title": "Custom Roles"
+ "url": "https://supabase.com/docs/guides/getting-started/features#network-restrictions",
+ "title": "Network restrictions"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
- "title": "Configure S3 Storage"
- }
- ],
- "resultChars": 20163
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"createSignedUrl storage objects select policy signed url private bucket\", limit: 5) { nodes { __typename ... on Guide { title href content } ... on ClientLibraryFunctionReference { title href content language methodName } } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/getting-started/features#ssl-enforcement",
+ "title": "SSL enforcement"
+ },
{
- "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
- "title": "Storage Buckets"
+ "url": "https://supabase.com/docs/guides/getting-started/features#branching",
+ "title": "Branching"
},
{
- "url": "https://supabase.com/docs/guides/storage/serving/downloads",
- "title": "Serving assets from Storage"
+ "url": "https://supabase.com/docs/guides/getting-started/features#terraform-provider",
+ "title": "Terraform provider"
},
{
- "url": "https://supabase.com/docs/guides/storage/cdn/smart-cdn",
- "title": "Smart CDN"
+ "url": "https://supabase.com/docs/guides/getting-started/features#read-replicas",
+ "title": "Read replicas"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
- "title": "Configure S3 Storage"
- }
- ],
- "resultChars": 21896
- }
- ]
- },
- "prompt": "Our app lets signed-in users keep personal files like receipts and bank\nstatements. These files are private — a user must only ever be able to upload\nand download their own. The app uploads each file under a path that starts\nwith the owner's user id, e.g. `/receipt-march.pdf`.\n\nSet up a `user-files` bucket on our project and lock it down that way.\n\nUsers also sometimes share one of their files with someone else through a\ntemporary link that expires. Include the supabase-js code the app should use\nfor that.",
- "promptSourcePath": "evals/build-storage-001-private-bucket-access/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini/build-storage-001-private-bucket-access.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "build-tests-001-rls-tenant-isolation",
- "stage": "build",
- "product": [
- "database"
- ],
- "topic": [
- "tests",
- "rls"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "passed": true,
- "checks": [
- {
- "name": "pgTAP test file(s) written under supabase/tests/",
- "passed": true,
- "notes": "1 file(s): supabase/tests/database/tenant_isolation.test.sql"
- },
- {
- "name": "pgTAP isolation tests ran and pass",
- "passed": true,
- "notes": "4 passed, 0 failed"
- },
- {
- "name": "agent correctly identifies the posts isolation bug from test results",
- "passed": true,
- "judgeNotes": "The agent correctly identifies `posts` as the table with the tenant isolation flaw, states that `notes` was already scoped correctly, explains that authenticated members could read posts from other orgs, and cites the pgTAP verification results after fixing the policy."
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": [
- {
- "source": "web_search",
- "query": "site:supabase.com/changelog.md Supabase changelog breaking-change row level security testing",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs \"RLS policies testing\" Supabase pgTAP",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs \"RLS policies testing\" pgTAP auth.uid() set_config request.jwt.claim.sub",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs \"RLS policies testing\" \"set_config\" Supabase",
- "pages": []
- }
- ]
- },
- "prompt": "Can you audit the tenant isolation on our tables? Write some database tests covering both the happy path and the negative case, run them, and share the results.",
- "promptSourcePath": "evals/build-tests-001-rls-tenant-isolation/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini/build-tests-001-rls-tenant-isolation.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "build-vectors-001-rag-with-permissions",
- "stage": "build",
- "product": [
- "database",
- "vectors"
- ],
- "topic": [
- "sql",
- "rls"
- ],
- "suite": "benchmark",
- "interface": "mcp",
- "passed": true,
- "checks": [
- {
- "name": "document_sections.embedding is vector(384)",
- "passed": true,
- "notes": "vector(384)"
- },
- {
- "name": "HNSW index on the embedding column",
- "passed": true,
- "notes": "CREATE INDEX document_sections_embedding_idx ON public.document_sections USING hnsw (embedding vector_cosine_ops)"
- },
- {
- "name": "index operator class matches the search operator",
- "passed": true,
- "notes": "function operators: <=>\nindexes: CREATE INDEX document_sections_embedding_idx ON public.document_sections USING hnsw (embedding vector_cosine_ops)"
- },
- {
- "name": "user A search returns only own sections, best match first",
- "passed": true
- },
- {
- "name": "user B search returns only own sections, best match first",
- "passed": true
- },
- {
- "name": "user A reads only own sections through the API",
- "passed": true
- },
- {
- "name": "user A reads only own documents through the API",
- "passed": true
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"pgvector semantic search embeddings RLS Supabase\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/getting-started/features#log-drains",
+ "title": "Log drains"
+ },
{
- "url": "https://supabase.com/docs/guides/ai/rag-with-permissions",
- "title": "RAG with Permissions"
+ "url": "https://supabase.com/docs/guides/getting-started/features#studio",
+ "title": "Studio"
},
{
- "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
- "title": "Automatic embeddings"
+ "url": "https://supabase.com/docs/guides/getting-started/features#studio-single-sign-on",
+ "title": "Studio Single Sign-On"
},
{
- "url": "https://supabase.com/docs/guides/ai/hybrid-search",
- "title": "Hybrid search"
+ "url": "https://supabase.com/docs/guides/getting-started/features#realtime",
+ "title": "Realtime"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pgvector",
- "title": "pgvector: Embeddings and vector similarity"
+ "url": "https://supabase.com/docs/guides/getting-started/features#postgres-changes",
+ "title": "Postgres changes"
},
{
- "url": "https://supabase.com/docs/guides/ai/semantic-search",
- "title": "Semantic search"
- }
- ],
- "resultChars": 76895
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"pgvector vector type without dimension Supabase\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/getting-started/features#broadcast",
+ "title": "Broadcast"
+ },
{
- "url": "https://supabase.com/docs/guides/ai/vector-columns",
- "title": "Vector columns"
+ "url": "https://supabase.com/docs/guides/getting-started/features#presence",
+ "title": "Presence"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pgvector",
- "title": "pgvector: Embeddings and vector similarity"
+ "url": "https://supabase.com/docs/guides/getting-started/features#auth",
+ "title": "Auth"
},
{
- "url": "https://supabase.com/docs/guides/ai/vector-indexes/hnsw-indexes",
- "title": "HNSW indexes"
+ "url": "https://supabase.com/docs/guides/getting-started/features#email-login",
+ "title": "Email login"
},
{
- "url": "https://supabase.com/docs/guides/ai/semantic-search",
- "title": "Semantic search"
+ "url": "https://supabase.com/docs/guides/getting-started/features#social-login",
+ "title": "Social login"
},
{
- "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
- "title": "Automatic embeddings"
- }
- ],
- "resultChars": 65961
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase RLS documents owner_id authenticated policy\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/getting-started/features#passwordless-login",
+ "title": "Passwordless login"
+ },
{
- "url": "https://supabase.com/docs/guides/ai/rag-with-permissions",
- "title": "RAG with Permissions"
+ "url": "https://supabase.com/docs/guides/getting-started/features#authorization-via-row-level-security",
+ "title": "Authorization via Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/storage/schema/helper-functions",
- "title": "Storage Helper Functions"
+ "url": "https://supabase.com/docs/guides/getting-started/features#captcha-protection",
+ "title": "CAPTCHA protection"
},
{
- "url": "https://supabase.com/docs/guides/storage/security/access-control",
- "title": "Storage Access Control"
+ "url": "https://supabase.com/docs/guides/getting-started/features#server-side-auth",
+ "title": "Server-Side Auth"
},
{
- "url": "https://supabase.com/docs/guides/auth/users",
- "title": "Users"
+ "url": "https://supabase.com/docs/guides/getting-started/features#storage",
+ "title": "Storage"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
- "title": "Token Security and Row Level Security"
- }
- ],
- "resultChars": 46468
- }
- ]
- },
- "prompt": "We're adding semantic search to our internal knowledge base app. I already wrote the edge functions, but search doesn't work yet. Can you set up whatever the database needs to make search work end to end?\n\nSome documents are confidential, so users should only have access to documents they own.",
- "promptSourcePath": "evals/build-vectors-001-rag-with-permissions/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini/build-vectors-001-rag-with-permissions.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "deploy-database-001-prometheus-metrics",
- "stage": "deploy",
- "product": [
- "database"
- ],
- "topic": [
- "observability"
- ],
- "suite": "benchmark",
- "passed": false,
- "checks": [
- {
- "name": "preserved existing app scrape job",
- "passed": true
- },
- {
- "name": "configured the Supabase Metrics API scrape correctly",
- "passed": false,
- "judgeNotes": "Fails because Prometheus uses basic_auth.password with an environment variable instead of basic_auth.password_file, and docker-compose.yml does not mount that password_file via a volume or Compose secret. The app scrape is preserved and the endpoint/path/scheme are otherwise correct."
- },
- {
- "name": "documented live deployment and verification steps",
- "passed": false,
- "judgeNotes": "README explains creating a Supabase Secret API key, placing it in observability/.env, and restarting the Compose stack, but it lacks concrete verification steps such as checking Prometheus targets or running a PromQL/Grafana query to confirm the Supabase scrape is live."
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query {\n searchDocs(query: \"project metrics observability prometheus metrics endpoint\", limit: 5) {\n nodes {\n title\n href\n content\n }\n }\n}",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/getting-started/features#file-storage",
+ "title": "File storage"
+ },
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics",
- "title": "Metrics API"
+ "url": "https://supabase.com/docs/guides/getting-started/features#content-delivery-network",
+ "title": "Content Delivery Network"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-self-hosted",
- "title": "Metrics API with Prometheus & Grafana (self-hosted)"
+ "url": "https://supabase.com/docs/guides/getting-started/features#smart-content-delivery-network",
+ "title": "Smart Content Delivery Network"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/vendor-agnostic",
- "title": "Vendor-agnostic Metrics API setup"
+ "url": "https://supabase.com/docs/guides/getting-started/features#image-transformations",
+ "title": "Image transformations"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-cloud",
- "title": "Metrics API with Grafana Cloud"
+ "url": "https://supabase.com/docs/guides/getting-started/features#resumable-uploads",
+ "title": "Resumable uploads"
},
{
- "url": "https://supabase.com/docs/guides/platform/read-replicas",
- "title": "Read Replicas"
- }
- ],
- "resultChars": 32694
- }
- ]
- },
- "prompt": "Can you wire my Supabase project metrics into our existing observability stack and document\nin the observability README what we need to do to make the config live?",
- "promptSourcePath": "evals/deploy-database-001-prometheus-metrics/PROMPT.md",
- "attempts": 2,
- "sourcePath": "codex-gpt-5.4-mini/deploy-database-001-prometheus-metrics.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "deploy-functions-001-edge-function-secrets",
- "stage": "deploy",
- "product": [
- "edge-functions"
- ],
- "topic": [
- "security"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "passed": true,
- "checks": [
- {
- "name": "WEATHER_API_KEY is set as a Function secret on the project",
- "passed": true
- },
- {
- "name": "the weather function is deployed to the project",
- "passed": true,
- "notes": "status ACTIVE"
- },
- {
- "name": "the weather function reads WEATHER_API_KEY from the environment",
- "passed": true,
- "judgeNotes": "Reads WEATHER_API_KEY from the runtime environment via Deno.env.get(\"WEATHER_API_KEY\")."
- },
- {
- "name": "WEATHER_API_KEY value is not committed to the repo",
- "passed": true
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query { searchDocs(query:\"create edge function deno serve request supabase edge functions weather proxy fetch headers\", limit: 5) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } ... on TroubleshootingGuide { title href content } } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/getting-started/features#s3-compatibility",
+ "title": "S3 compatibility"
+ },
{
- "url": "https://supabase.com/docs/guides/functions",
+ "url": "https://supabase.com/docs/guides/getting-started/features#edge-functions",
"title": "Edge Functions"
},
{
- "url": "https://supabase.com/docs/guides/database/connecting-to-postgres/serverless-drivers",
- "title": "Serverless Drivers"
+ "url": "https://supabase.com/docs/guides/getting-started/features#deno-edge-functions",
+ "title": "Deno Edge Functions"
},
{
- "url": "https://supabase.com/docs/guides/functions/http-methods",
- "title": "Routing"
+ "url": "https://supabase.com/docs/guides/getting-started/features#regional-invocations",
+ "title": "Regional invocations"
},
{
- "url": "https://supabase.com/docs/guides/local-development/cli/testing-and-linting",
- "title": "Testing and linting"
+ "url": "https://supabase.com/docs/guides/getting-started/features#npm-compatibility",
+ "title": "NPM compatibility"
},
{
- "url": "https://supabase.com/docs/guides/functions/cors",
- "title": "CORS (Cross-Origin Resource Sharing) support for Invoking from the browser"
- }
- ],
- "resultChars": 32587
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query:\"Edge Functions secrets environment variables deploy functions supabase secrets set edge function runtime environment variable\", limit: 5) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } ... on ManagementApiReference { title href content } ... on TroubleshootingGuide { title href content } } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/getting-started/features#project-management",
+ "title": "Project management"
+ },
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
+ "url": "https://supabase.com/docs/guides/getting-started/features#cli",
+ "title": "CLI"
},
{
- "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
- "title": "Automatic embeddings"
+ "url": "https://supabase.com/docs/guides/getting-started/features#management-api",
+ "title": "Management API"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-generate-speech-stream",
- "title": "Streaming Speech with ElevenLabs"
+ "url": "https://supabase.com/docs/guides/getting-started/features#client-libraries",
+ "title": "Client libraries"
},
{
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
+ "url": "https://supabase.com/docs/guides/getting-started/features#feature-status",
+ "title": "Feature status"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-transcribe-speech",
- "title": "Transcription Telegram Bot"
- }
- ],
- "resultChars": 70876
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query:\"Edge Functions invoke curl apikey Authorization header no verify jwt public function invoke\", limit: 5) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } ... on TroubleshootingGuide { title href content } } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/getting-started/features#private-alpha",
+ "title": "Private alpha"
+ },
{
- "url": "https://supabase.com/docs/guides/functions/error-codes",
- "title": "Error codes"
+ "url": "https://supabase.com/docs/guides/getting-started/features#public-alpha",
+ "title": "Public alpha"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-headers",
- "title": "Authorization headers"
+ "url": "https://supabase.com/docs/guides/getting-started/features#beta",
+ "title": "Beta"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
- "title": "Integrating With Supabase Auth"
+ "url": "https://supabase.com/docs/guides/getting-started/features#generally-available",
+ "title": "Generally available"
},
{
- "url": "https://supabase.com/docs/guides/functions/status-codes",
- "title": "Status codes"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended",
+ "title": "Advanced pgTAP Testing"
},
{
- "url": "https://supabase.com/docs/guides/functions/function-configuration",
- "title": "Function Configuration"
- }
- ],
- "resultChars": 26210
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query:\"Authorization headers Edge Functions apikey anon key invoke browser\", limit: 5) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#additional-resources",
+ "title": "Additional resources"
+ },
{
- "url": "https://supabase.com/docs/guides/functions/cors",
- "title": "CORS (Cross-Origin Resource Sharing) support for Invoking from the browser"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#4-test-cases",
+ "title": "4. Test cases:"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/features",
- "title": "Features"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#3-rls-policies-declaration",
+ "title": "3. RLS policies declaration"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-headers",
- "title": "Authorization headers"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#2-grant-role-privileges",
+ "title": "2. Grant role privileges"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#1-app-schema-definitions",
+ "title": "1. App schema definitions"
},
{
- "url": "https://supabase.com/docs/guides/functions/error-codes",
- "title": "Error codes"
- }
- ],
- "resultChars": 42697
- }
- ]
- },
- "prompt": "Our weather widget currently calls WeatherAPI straight from the browser, which\nleaks our API key. I want to move that behind a Supabase Edge Function called\n`weather` that holds the key server-side and proxies the request.\n\nThe function should read the key from an environment variable named\n`WEATHER_API_KEY`. Our key already lives in a local `.env` file at the project\nroot.\n\nDeploy the function to our project so it's live, and make sure the deployed\nfunction can actually read the key at runtime.",
- "promptSourcePath": "evals/deploy-functions-001-edge-function-secrets/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini/deploy-functions-001-edge-function-secrets.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "deploy-self-hosting-001-docker-compose",
- "stage": "deploy",
- "product": [
- "database",
- "auth",
- "storage"
- ],
- "topic": [
- "self-hosting"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "passed": true,
- "checks": [
- {
- "name": "cloned the self-host stack (docker-compose.yml + volumes/db)",
- "passed": true
- },
- {
- "name": "didn't conflate with the CLI (no supabase/config.toml in the stack)",
- "passed": true
- },
- {
- "name": "secrets rotated off the shipped defaults",
- "passed": true
- },
- {
- "name": "ANON_KEY and SERVICE_ROLE_KEY are HS256 JWTs signed by JWT_SECRET",
- "passed": true
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query {\n searchDocs(query: \"self-hosted Supabase docker compose API_EXTERNAL_URL auth/v1 envoy kong\", limit: 5) {\n nodes {\n ... on Guide {\n title\n href\n content\n }\n ... on TroubleshootingGuide {\n title\n href\n content\n }\n ... on CLICommandReference {\n title\n href\n content\n }\n }\n totalCount\n }\n}",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#testing-focus-areas",
+ "title": "Testing focus areas"
+ },
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
- "title": "Envoy API Gateway"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#what-makes-this-complex",
+ "title": "What makes this complex?"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https",
- "title": "Configure Reverse Proxy and HTTPS"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#system-overview",
+ "title": "System overview"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#not-another-todo-app-testing-complex-organizations",
+ "title": "Not another todo app: Testing complex organizations"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth",
- "title": "Configure Social Login (OAuth) Providers"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#example-advanced-rls-testing",
+ "title": "Example: Advanced RLS testing"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-saml-sso",
- "title": "Configure SAML SSO"
- }
- ],
- "resultChars": 97845
- },
- {
- "source": "search_docs",
- "query": "query {\n searchDocs(query: \"Self-Hosting with Docker docker-compose.yml self-hosted Supabase\", limit: 5) {\n nodes {\n ... on Guide {\n title\n href\n content\n }\n }\n totalCount\n }\n}",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/self-hosting/docker",
- "title": "Self-Hosting with Docker"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#benefits",
+ "title": "Benefits"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
- "title": "Restore a Platform Project to Self-Hosted"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#creating-a-pre-test-hook",
+ "title": "Creating a pre-test hook"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https",
- "title": "Configure Reverse Proxy and HTTPS"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#test-file-organization",
+ "title": "Test file organization"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17",
- "title": "Upgrade to Postgres 17"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#schema-wide-row-level-security-testing",
+ "title": "Schema-wide Row Level Security testing"
},
{
- "url": "https://supabase.com/docs/guides/queues/expose-self-hosted-queues",
- "title": "Expose Queues for local and self-hosted Supabase"
- }
- ],
- "resultChars": 69788
- }
- ]
- },
- "prompt": "I'm moving off the hosted Supabase and running the whole thing myself on a VPS I\njust spun up. Can you get a Docker setup ready for me to copy onto the box?\n\nI don't need it running here, I'll do the actual bring-up once I'm on the\nserver. I just want everything in place and the secrets set up. Put it in a `supabase-docker/`\nfolder at the repo root so I can scp the whole thing across in one go.",
- "promptSourcePath": "evals/deploy-self-hosting-001-docker-compose/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini/deploy-self-hosting-001-docker-compose.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "investigate-auth-001-deleted-user-access",
- "stage": "investigate",
- "product": [
- "auth"
- ],
- "topic": [
- "security",
- "sdk"
- ],
- "suite": "benchmark",
- "interface": "mcp",
- "passed": true,
- "checks": [
- {
- "name": "victim session active before delete-account",
- "passed": true
- },
- {
- "name": "delete_account flow ran for the victim",
- "passed": true
- },
- {
- "name": "delete-account revokes the user's sessions",
- "passed": true,
- "notes": "sessions left: 0"
- },
- {
- "name": "deleted user's refresh token is rejected",
- "passed": true
- },
- {
- "name": "deleted user cannot sign back in",
- "passed": true
- },
- {
- "name": "other users keep their sessions and access",
- "passed": true
- },
- {
- "name": "diagnosed and explained session revocation",
- "passed": true,
- "judgeNotes": "Diagnosed soft-delete-only flow, implemented auth user deletion plus RLS that closes the Data API stale-JWT path, explained JWT expiry caveat sufficiently, and correctly distinguished publishable/anon from secret/service_role keys."
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"publishable secret keys anon service_role frontend RLS\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/database/secure-data",
- "title": "Securing your data"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#test-helper-benefits",
+ "title": "Test helper benefits"
},
{
- "url": "https://supabase.com/docs/guides/auth/jwt-fields",
- "title": "JWT Claims Reference"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#installing-test-helpers",
+ "title": "Installing test helpers"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs",
- "title": "Build a User Management App with RedwoodJS"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#setting-up-dbdev",
+ "title": "Setting up dbdev"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#using-databasedev",
+ "title": "Using database.dev"
},
{
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
- }
- ],
- "resultChars": 91173
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"delete user revoke sessions auth.admin.deleteUser delete_account sessions invalidation\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/database/postgres/column-level-security",
+ "title": "Column Level Security"
+ },
{
- "url": "https://supabase.com/docs/guides/auth/managing-user-data",
- "title": "User Management"
+ "url": "https://supabase.com/docs/guides/database/postgres/column-level-security#considerations-when-using-column-level-privileges",
+ "title": "Considerations when using column-level privileges"
},
{
- "url": "https://supabase.com/docs/reference/javascript/auth-admin-deleteuser"
+ "url": "https://supabase.com/docs/guides/database/postgres/column-level-security#manage-column-privileges-in-migrations",
+ "title": "Manage column privileges in migrations"
},
{
- "url": "https://supabase.com/docs/reference/dart/auth-admin-deleteuser"
+ "url": "https://supabase.com/docs/guides/database/postgres/column-level-security#manage-column-privileges-in-the-dashboard",
+ "title": "Manage column privileges in the Dashboard"
},
{
- "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers",
- "title": "Multiple SSO Providers"
+ "url": "https://supabase.com/docs/guides/database/postgres/column-level-security#privileges-at-the-column-level",
+ "title": "Privileges at the column level"
},
{
- "url": "https://supabase.com/docs/reference/swift/auth-admin-deleteuser",
- "title": "deleteUser()"
+ "url": "https://supabase.com/docs/guides/database/postgres/column-level-security#policies-at-the-row-level",
+ "title": "Policies at the row level"
}
],
- "resultChars": 27499
+ "resultChars": 271624
},
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"row level security auth.uid deleted flag policy\", limit: 5) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"Exposing a Table to the Data API RLS authenticated anon\", limit: 5) { nodes { title href content ... on Guide { subsections { nodes { title href content } } } } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/local-development/cli-workflows",
- "title": "Local development workflow"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api",
+ "title": "Securing your API"
},
{
- "url": "https://supabase.com/docs/guides/storage/management/delete-objects",
- "title": "Delete Objects"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#examples",
+ "title": "Examples"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
- "title": "Row Level Security"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#accessing-request-information",
+ "title": "Accessing request information"
},
{
- "url": "https://supabase.com/docs/guides/auth/auth-mfa",
- "title": "Multi-Factor Authentication"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#enforce-additional-rules-on-each-request",
+ "title": "Enforce additional rules on each request"
},
{
- "url": "https://supabase.com/docs/guides/database/database-advisors?queryGroups=lint&lint=0003_auth_rls_initplan",
- "title": "Database Advisor: Lint 0003_auth_rls_initplan"
- }
- ],
- "resultChars": 74757
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"auth.admin signOut deleteUser revoke refresh token\", limit: 10) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#use-a-dedicated-api-schema",
+ "title": "Use a dedicated API schema"
+ },
{
- "url": "https://supabase.com/docs/reference/javascript/auth-signout"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#add-rls-policies",
+ "title": "Add RLS policies"
},
{
- "url": "https://supabase.com/docs/reference/javascript/auth-admin-deleteuser"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#grant-access-explicitly",
+ "title": "Grant access explicitly"
},
{
- "url": "https://supabase.com/docs/guides/auth/managing-user-data",
- "title": "User Management"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#default-privileges-for-new-tables-and-functions",
+ "title": "Default privileges for new tables and functions"
},
{
- "url": "https://supabase.com/docs/reference/dart/auth-admin-deleteuser"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api#disable-the-data-api",
+ "title": "Disable the Data API"
},
{
- "url": "https://supabase.com/docs/guides/integrations/build-a-supabase-oauth-integration",
- "title": "Build a Supabase Integration"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security"
},
{
- "url": "https://supabase.com/docs/reference/api/v1-revoke-token",
- "title": "[Beta] Revoke oauth app authorization and it's corresponding tokens"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#minimize-joins",
+ "title": "Minimize joins"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows",
- "title": "OAuth 2.1 Flows"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#row-level-security-in-supabase",
+ "title": "Row Level Security in Supabase"
},
{
- "url": "https://supabase.com/docs/reference/javascript/oauth-admin",
- "title": "OAuth Admin"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#policies",
+ "title": "Policies"
},
{
- "url": "https://supabase.com/docs/reference/swift/auth-admin-deleteuser",
- "title": "deleteUser()"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#enabling-row-level-security",
+ "title": "Enabling Row Level Security"
},
{
- "url": "https://supabase.com/docs/reference/javascript/auth-admin-signout"
- }
- ],
- "resultChars": 56854
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"revoke sessions delete user auth.sessions revoke refresh tokens\", limit: 10) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#auto-enable-rls-for-new-tables",
+ "title": "Auto-enable RLS for new tables"
+ },
{
- "url": "https://supabase.com/docs/guides/auth/sessions",
- "title": "User sessions"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#authenticated-and-unauthenticated-roles",
+ "title": "Authenticated and unauthenticated roles"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows",
- "title": "OAuth 2.1 Flows"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#creating-policies",
+ "title": "Creating policies"
},
{
- "url": "https://supabase.com/docs/guides/resources/glossary",
- "title": "Glossary"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#select-policies",
+ "title": "SELECT policies"
},
{
- "url": "https://supabase.com/docs/reference/javascript/oauth-server-revokegrant"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#insert-policies",
+ "title": "INSERT policies"
},
{
- "url": "https://supabase.com/docs/guides/auth/managing-user-data",
- "title": "User Management"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#update-policies",
+ "title": "UPDATE policies"
},
{
- "url": "https://supabase.com/docs/reference/api/v1-revoke-token",
- "title": "[Beta] Revoke oauth app authorization and it's corresponding tokens"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#delete-policies",
+ "title": "DELETE policies"
},
{
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#views",
+ "title": "Views"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/should-i-set-a-shorter-max-age-parameter-on-the-cookies-8sbF4V",
- "title": "Should I set a shorter Max-Age parameter on the cookies?"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#helper-functions",
+ "title": "Helper functions"
},
{
- "url": "https://supabase.com/docs/guides/auth/server-side/creating-a-client",
- "title": "Creating a Supabase client for SSR"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#authuid",
+ "title": "auth.uid()"
},
{
- "url": "https://supabase.com/docs/guides/auth/auth-anonymous",
- "title": "Anonymous Sign-Ins"
- }
- ],
- "resultChars": 160501
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"sign out all sessions delete user auth admin revoke\", limit: 10) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#authjwt",
+ "title": "auth.jwt()"
+ },
{
- "url": "https://supabase.com/docs/reference/javascript/auth-signout"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#mfa",
+ "title": "MFA"
},
{
- "url": "https://supabase.com/docs/guides/auth/passkeys",
- "title": "Passkey authentication"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#bypassing-row-level-security",
+ "title": "Bypassing Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
- "title": "Row Level Security"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#rls-performance-recommendations",
+ "title": "RLS performance recommendations"
},
{
- "url": "https://supabase.com/docs/guides/auth/signout",
- "title": "Signing out"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#add-indexes",
+ "title": "Add indexes"
},
{
- "url": "https://supabase.com/docs/guides/auth/managing-user-data",
- "title": "User Management"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks",
+ "title": "Benchmarks"
},
{
- "url": "https://supabase.com/docs/reference/javascript/auth-admin-signout"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#call-functions-with-select",
+ "title": "Call functions with select"
},
{
- "url": "https://supabase.com/docs/guides/auth/sessions",
- "title": "User sessions"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-1",
+ "title": "Benchmarks"
},
{
- "url": "https://supabase.com/docs/guides/resources/glossary",
- "title": "Glossary"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#add-filters-to-every-query",
+ "title": "Add filters to every query"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows",
- "title": "OAuth 2.1 Flows"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-2",
+ "title": "Benchmarks"
},
{
- "url": "https://supabase.com/docs/reference/javascript/auth-admin-deletefactor"
- }
- ],
- "resultChars": 108752
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#use-security-definer-functions",
+ "title": "Use security definer functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-3",
+ "title": "Benchmarks"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#specify-roles-in-your-policies",
+ "title": "Specify roles in your policies"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-4",
+ "title": "Benchmarks"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#more-resources",
+ "title": "More resources"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/database-advisors?queryGroups=lint&lint=0026_pg_graphql_anon_table_exposed",
+ "title": "Database Advisor: Lint 0026_pg_graphql_anon_table_exposed"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/database-advisors?queryGroups=lint&lint=0023_sensitive_columns_exposed",
+ "title": "Database Advisor: Lint 0023_sensitive_columns_exposed"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/database-advisors?queryGroups=lint&lint=0017_foreign_table_in_api",
+ "title": "Database Advisor: Lint 0017_foreign_table_in_api"
+ }
+ ],
+ "resultChars": 180978
}
]
},
- "prompt": "Last week support removed a user through our app's delete-account flow — the\napp calls the `delete_account` function over RPC as the signed-in user. This\nmorning that same person was back: still signed in, reading and saving their\ndata like nothing happened.\n\nFigure out why the account still works, fix the flow so a deleted account\nloses access, and tell me whether there is any window where they could still\nget in after the fix.\n\nOne more thing while you're at it: we're migrating off the legacy\nanon/service_role API keys to the new publishable and secret keys, and the\nteam isn't sure which one belongs in the frontend and what each means for\nRLS. Give us a quick rundown.",
- "promptSourcePath": "evals/investigate-auth-001-deleted-user-access/PROMPT.md",
+ "usage": {
+ "inputTokens": 9670792,
+ "outputTokens": 24068,
+ "cachedInputTokens": 9143552
+ },
+ "durationMs": 539539,
+ "prompt": "We're kicking off a todos app and I want the Supabase side ready for the team\nto build on. Set it up the way we'd run it in development, with schema changes\ntracked as migrations so they can be reviewed and replayed.\n\nFor the first slice we just need a `todos` table. Todos aren't public: anyone\nsigned in can read all of them, but nothing should be writable through the API\nfor now. Add a couple of sample todos so there's something to look at.\n\nBefore you hand it back, make sure the running API actually behaves that way —\nsigned-in users get the todos, signed-out requests get nothing.",
+ "promptSourcePath": "evals/build-cli-001-bootstrap-app/PROMPT.md",
"attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini/investigate-auth-001-deleted-user-access.json"
+ "sourcePath": "codex-gpt-5.4-mini/build-cli-001-bootstrap-app.json"
},
{
"experiment": "codex-gpt-5.4-mini",
@@ -8587,44 +7902,34 @@
"modelId": "gpt-5.4-mini",
"reasoningEffort": "medium"
},
- "eval": "investigate-realtime-001-subscribed-no-events",
- "stage": "investigate",
+ "eval": "build-cli-002-declarative-schema",
+ "stage": "build",
"product": [
- "realtime",
"database"
],
"topic": [
- "sdk"
+ "declarative-schema",
+ "migrations"
],
"suite": "benchmark",
- "interface": "mcp",
+ "interface": "cli",
"passed": true,
"checks": [
{
- "name": "orders table added to supabase_realtime publication",
+ "name": "supabase db diff used to generate the migration",
"passed": true
},
{
- "name": "courier_locations still in supabase_realtime publication",
+ "name": "schema file updated to include description column",
"passed": true
},
{
- "name": "publication still publishes INSERT events",
+ "name": "a new migration was generated for the change",
"passed": true
},
{
- "name": "RLS still enabled on orders",
+ "name": "description column exists in the live database",
"passed": true
- },
- {
- "name": "staff can still read orders through RLS",
- "passed": true,
- "notes": "authenticated sees 2 of 2 orders"
- },
- {
- "name": "diagnosed missing publication membership",
- "passed": true,
- "judgeNotes": "Identified missing orders table in supabase_realtime as root cause, added only public.orders to existing publication, verified courier_locations remained, and did not weaken RLS/policies."
}
],
"skills": {
@@ -8633,45 +7938,344 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"postgres_changes realtime publication insert table not receiving events\", limit: 5) { nodes { __typename title href content } } }",
+ "query": "query { searchDocs(query: \"declarative database schemas local development generate migration\", limit: 5) { nodes { title href content ... on Guide { subsections { nodes { title href content } } } } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/realtime/subscribing-to-database-changes",
- "title": "Subscribing to Database Changes"
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas",
+ "title": "Declarative database schemas"
},
{
- "url": "https://supabase.com/docs/guides/realtime/postgres-changes",
- "title": "Postgres Changes"
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas#other-entities",
+ "title": "Other entities"
},
{
- "url": "https://supabase.com/docs/guides/realtime/protocol",
- "title": "Realtime Protocol"
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas#overview",
+ "title": "Overview"
},
{
- "url": "https://supabase.com/docs/guides/realtime/benchmarks",
- "title": "Benchmarks"
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas#schema-migrations",
+ "title": "Schema migrations"
},
{
- "url": "https://supabase.com/docs/guides/database/replication/pipelines-faq",
- "title": "Pipelines FAQ"
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas#declaring-your-schema",
+ "title": "Declaring your schema"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas#updating-your-schema",
+ "title": "Updating your schema"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas#deploying-your-schema-changes",
+ "title": "Deploying your schema changes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas#managing-dependencies",
+ "title": "Managing dependencies"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas#pulling-in-your-production-schema",
+ "title": "Pulling in your production schema"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas#rolling-back-a-schema-change",
+ "title": "Rolling back a schema change"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas#known-caveats",
+ "title": "Known caveats"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas#data-manipulation-language",
+ "title": "Data manipulation language"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas#view-ownership",
+ "title": "View ownership"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas#rls-policies",
+ "title": "RLS policies"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows",
+ "title": "Local development workflow"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#before-you-begin",
+ "title": "Before you begin"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#the-supabase-directory",
+ "title": "The ./supabase directory"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#move-an-existing-project-to-local-development",
+ "title": "Move an existing project to local development"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#step-1-initialize",
+ "title": "Step 1: Initialize"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#step-2-authenticate",
+ "title": "Step 2: Authenticate"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#step-3-link-to-your-remote-project",
+ "title": "Step 3: Link to your remote project"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#step-4-pull-the-remote-schema",
+ "title": "Step 4: Pull the remote schema"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#step-5-create-seed-data",
+ "title": "Step 5: Create seed data"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#step-6-verify",
+ "title": "Step 6: Verify"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#step-7-commit",
+ "title": "Step 7: Commit"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#start-a-new-project-from-scratch",
+ "title": "Start a new project from scratch"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#step-1-initialize-1",
+ "title": "Step 1: Initialize"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#step-2-start-the-local-stack",
+ "title": "Step 2: Start the local stack"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#step-3-create-your-schema",
+ "title": "Step 3: Create your schema"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#step-4-add-seed-data",
+ "title": "Step 4: Add seed data"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#step-5-verify",
+ "title": "Step 5: Verify"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#step-6-commit",
+ "title": "Step 6: Commit"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#the-daily-workflow",
+ "title": "The daily workflow"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#making-schema-changes",
+ "title": "Making schema changes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#generating-types",
+ "title": "Generating types"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#staying-in-sync-with-your-team",
+ "title": "Staying in sync with your team"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#pushing-to-a-remote-project",
+ "title": "Pushing to a remote project"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#resetting-a-remote-dev-or-staging-project",
+ "title": "Resetting a remote dev or staging project"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#key-commands-at-a-glance",
+ "title": "Key commands at a glance"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#cleaning-up-generated-migrations",
+ "title": "Cleaning up generated migrations"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#grants",
+ "title": "Grants"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#revokere-grant-patterns",
+ "title": "Revoke/re-grant patterns"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#extension-statements",
+ "title": "Extension statements"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#known-limitations-of-db-diff",
+ "title": "Known limitations of db diff"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows#troubleshooting",
+ "title": "Troubleshooting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/seeding-your-database",
+ "title": "Seeding your database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/seeding-your-database#what-is-seed-data",
+ "title": "What is seed data?"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/seeding-your-database#generating-seed-data",
+ "title": "Generating seed data"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/seeding-your-database#splitting-up-your-seed-file",
+ "title": "Splitting up your seed file"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/seeding-your-database#using-seed-files",
+ "title": "Using seed files"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations",
+ "title": "Database Migrations"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations#how-migration-tracking-works",
+ "title": "How migration tracking works"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations#diagnosing-and-fixing-sync-errors",
+ "title": "Diagnosing and fixing sync errors"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations#working-with-a-team",
+ "title": "Working with a team"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations#deploy-your-project",
+ "title": "Deploy your project"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations#seeding-data",
+ "title": "Seeding data"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations#schema-migrations",
+ "title": "Schema migrations"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations#diffing-changes",
+ "title": "Diffing changes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations#step-3-if-the-migration-history-table-is-wrong",
+ "title": "Step 3: If the migration history table is wrong"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations#step-2-if-you-made-changes-on-the-remote-database-directly",
+ "title": "Step 2: If you made changes on the remote database directly"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations#step-1-check-whats-out-of-sync",
+ "title": "Step 1: Check what's out of sync"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs",
+ "title": "Build a User Management App with RedwoodJS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#set-up-an-account-component",
+ "title": "Set up an account component"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#profile-photos",
+ "title": "Profile photos"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#create-an-upload-widget",
+ "title": "Create an upload widget"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#launch",
+ "title": "Launch!"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#see-also",
+ "title": "See also"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#about-redwoodjs",
+ "title": "About RedwoodJS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#project-setup",
+ "title": "Project setup"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#create-a-project",
+ "title": "Create a project"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#set-up-the-database-schema",
+ "title": "Set up the database schema"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#get-api-details",
+ "title": "Get API details"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#building-the-app",
+ "title": "Building the app"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#initialize-a-redwoodjs-app",
+ "title": "Initialize a RedwoodJS app"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#app-styling-optional",
+ "title": "App styling (optional)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#start-redwoodjs-and-your-first-page",
+ "title": "Start RedwoodJS and your first page"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#set-up-a-login-component",
+ "title": "Set up a login component"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#update-home-page",
+ "title": "Update home page"
}
],
- "resultChars": 124600
+ "resultChars": 259370
}
]
},
- "prompt": "Our dispatch dashboard shows incoming orders as they happen. The courier\nlocation feed on the same page updates live without problems, but new orders\nonly show up after a page refresh.\n\nThe dashboard uses supabase-js to subscribe to INSERT events on the `orders`\ntable through postgres_changes, the same way it subscribes to courier\nlocations. The channel's status callback logs SUBSCRIBED and there are no\nerrors in the browser console.\n\nFigure out why no order events ever arrive and fix it.",
- "promptSourcePath": "evals/investigate-realtime-001-subscribed-no-events/PROMPT.md",
+ "usage": {
+ "inputTokens": 433846,
+ "outputTokens": 2716,
+ "cachedInputTokens": 407680
+ },
+ "durationMs": 81309,
+ "prompt": "Add a description text column to the `products` table in my local Supabase stack",
+ "promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md",
"attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini/investigate-realtime-001-subscribed-no-events.json"
+ "sourcePath": "codex-gpt-5.4-mini/build-cli-002-declarative-schema.json"
},
{
"experiment": "codex-gpt-5.4-mini",
@@ -8682,32 +8286,36 @@
"modelId": "gpt-5.4-mini",
"reasoningEffort": "medium"
},
- "eval": "investigate-reliability-003-edge-function-5xx-correlation",
- "stage": "investigate",
+ "eval": "build-cli-003-pg-cron-queue-workflow",
+ "stage": "build",
"product": [
- "edge-functions"
+ "database",
+ "edge-functions",
+ "cron",
+ "queues"
],
"topic": [
- "observability"
+ "sql",
+ "sdk"
],
"suite": "benchmark",
- "interface": "mcp",
- "passed": false,
+ "interface": "cli",
+ "passed": true,
"checks": [
{
- "name": "identified image-transform and the recurring 503 pattern",
+ "name": "pg_cron job 'enqueue-tasks' scheduled to run every minute",
"passed": true,
- "judgeNotes": "The assistant explicitly identified `image-transform` as the affected function and described the recurring HTTP 503 pattern across the morning of 2026-04-28, covering all 8 failures from 07:00Z through 12:00Z."
+ "notes": "schedule='* * * * *', active=true"
},
{
- "name": "attributed recurring 503s to gateway/platform layer, not function code",
- "passed": false,
- "judgeNotes": "The assistant does not attribute the recurring image-transform 503s to the gateway/platform layer. It instead frames them as function-specific failures likely inside external @acme packages or an upstream service and recommends inspecting function implementations/logging, despite noting unchanged deployment and intermittent successes."
- },
+ "name": "cron command enqueues to the 'tasks' queue",
+ "passed": true,
+ "notes": "queue depth 0 -> 1"
+ },
{
- "name": "recommended a concrete next step",
+ "name": "process-tasks function drains the queue",
"passed": true,
- "judgeNotes": "The assistant provided concrete actionable next steps, including inspecting specific external package implementations/release history, adding structured error logging, creating/verifying Storage buckets and policies, and re-testing uploads with correlation factors."
+ "notes": "function removed the seeded message (id 4) from the queue"
}
],
"skills": {
@@ -8716,16 +8324,135 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
- "calls": []
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"pgmq pop delete edge function queue supabase local development cron\", limit: 5) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/cron/quickstart",
+ "title": "Quickstart"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net",
+ "title": "pg_net: Async Networking"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions",
+ "title": "Consuming Supabase Queue Messages with Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/schedule-functions",
+ "title": "Scheduling Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/background-tasks",
+ "title": "Background Tasks"
+ }
+ ],
+ "resultChars": 32405
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Supabase Queues create queue pgmq create queue docs\", limit: 5) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
+ "title": "Automatic embeddings"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/extensions/pgmq",
+ "title": "pgmq: Queues"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/queues",
+ "title": "Supabase Queues"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/queues/quickstart",
+ "title": "Quickstart"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/queues/pgmq",
+ "title": "PGMQ Extension"
+ }
+ ],
+ "resultChars": 66485
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"pgmq send pop delete read queue create\", limit: 10) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/queues/pgmq",
+ "title": "PGMQ Extension"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/queues/quickstart",
+ "title": "Quickstart"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/queues",
+ "title": "Supabase Queues"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/queues/api",
+ "title": "API"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/queues/expose-self-hosted-queues",
+ "title": "Expose Queues for local and self-hosted Supabase"
+ }
+ ],
+ "resultChars": 39378
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Edge Function SUPABASE_SERVICE_ROLE_KEY local environment variable createClient\", limit: 5) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
+ "title": "Self-Hosted Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/javascript/oauth-admin-createclient"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/deploy",
+ "title": "Deploy to Production"
+ }
+ ],
+ "resultChars": 36083
+ }
+ ]
},
- "prompt": "Users have been reporting that image uploads are intermittently failing with server errors throughout the morning of `2026-04-28`.\n\nCan you investigate the project logs and tell me what is going on and what we\nshould do next?",
- "promptSourcePath": "evals/investigate-reliability-003-edge-function-5xx-correlation/PROMPT.md",
- "attempts": 2,
- "sourcePath": "codex-gpt-5.4-mini/investigate-reliability-003-edge-function-5xx-correlation.json"
+ "usage": {
+ "inputTokens": 1741838,
+ "outputTokens": 15624,
+ "cachedInputTokens": 1584000
+ },
+ "durationMs": 164228,
+ "prompt": "I want to set up a recurring background workflow on my local Supabase stack.\n\nCan you set up a cron job called `enqueue-tasks` to run every minute and push a task into a queue called `tasks`? Then add a `process-tasks` edge function that reads messages off the `tasks` queue and removes them, so a scheduled worker can keep the backlog drained.",
+ "promptSourcePath": "evals/build-cli-003-pg-cron-queue-workflow/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini/build-cli-003-pg-cron-queue-workflow.json"
},
{
"experiment": "codex-gpt-5.4-mini",
@@ -8736,49 +8463,37 @@
"modelId": "gpt-5.4-mini",
"reasoningEffort": "medium"
},
- "eval": "resolve-dataapi-001-empty-results",
- "stage": "resolve",
+ "eval": "build-database-001-migrate-postgres-to-supabase",
+ "stage": "build",
"product": [
- "data-api",
- "database",
- "auth"
+ "database"
],
"topic": [
- "rls",
- "sdk"
+ "migrations"
],
"suite": "benchmark",
- "interface": "mcp",
+ "interface": "cli",
"passed": true,
"checks": [
{
- "name": "RLS still enabled on bookmarks",
- "passed": true
- },
- {
- "name": "user A reads own bookmarks",
+ "name": "all 3 tables exist (teams, members, tasks)",
"passed": true
},
{
- "name": "user B cannot read user A bookmarks",
+ "name": "row counts match (teams=5, members=10, tasks=13)",
"passed": true
},
{
- "name": "anon reads no bookmarks",
+ "name": "foreign key constraints survived the restore",
"passed": true
},
{
- "name": "user A can save a new bookmark",
+ "name": "tasks_team_status_idx index survived the restore",
"passed": true
},
{
- "name": "user B cannot insert a bookmark as user A",
+ "name": "sequences synced (next insert won't conflict with existing IDs)",
"passed": true
- },
- {
- "name": "diagnosed RLS and added owner-scoped policies",
- "passed": true,
- "judgeNotes": "The assistant correctly diagnosed RLS enabled with no policies causing deny-all Data API results, kept RLS enabled, and created authenticated SELECT and INSERT owner-scoped policies using auth.uid() = user_id with WITH CHECK for insert."
}
],
"skills": {
@@ -8787,7 +8502,8 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
@@ -8803,43 +8519,26 @@
},
{
"source": "web_search",
- "query": "site:supabase.com changelog.md supabase",
+ "query": "site:supabase.com/changelog.md Supabase changelog.md",
"pages": []
},
{
- "source": "search_docs",
- "query": "query {\n searchDocs(query: \"row level security auth.uid select insert policy authenticated user_id bookmarks\", limit: 5) {\n nodes {\n title\n href\n ... on Guide { content }\n }\n }\n}",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
- "title": "Row Level Security"
- },
- {
- "url": "https://supabase.com/docs/guides/storage/management/copy-move-objects",
- "title": "Copy Objects"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/features",
- "title": "Features"
- },
- {
- "url": "https://supabase.com/docs/guides/realtime/getting_started",
- "title": "Getting Started with Realtime"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/auth-mfa",
- "title": "Multi-Factor Authentication"
- }
- ],
- "resultChars": 81216
+ "source": "web_search",
+ "query": "Supabase changelog markdown breaking-change site:supabase.com",
+ "pages": []
}
]
},
- "prompt": "Our app lets signed-in users save bookmarks and view them on their dashboard. Bookmarks are stored in the `bookmarks` table and are private — a user must only ever see their own. \nUsers also need to be able to save new bookmarks from the app.\n\nI can see the rows when I query the table directly, but the dashboard shows an empty list for every user.\n\nFind out why the Data API returns nothing and fix it.",
- "promptSourcePath": "evals/resolve-dataapi-001-empty-results/PROMPT.md",
+ "usage": {
+ "inputTokens": 1385480,
+ "outputTokens": 6132,
+ "cachedInputTokens": 1164032
+ },
+ "durationMs": 264463,
+ "prompt": "I have an existing Postgres database I want to migrate to Supabase. There's a binary dump at `source.dump` in the current directory.\n\nCan you set up a local Supabase project and restore the dump into it?",
+ "promptSourcePath": "evals/build-database-001-migrate-postgres-to-supabase/PROMPT.md",
"attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini/resolve-dataapi-001-empty-results.json"
+ "sourcePath": "codex-gpt-5.4-mini/build-database-001-migrate-postgres-to-supabase.json"
},
{
"experiment": "codex-gpt-5.4-mini",
@@ -8850,45 +8549,46 @@
"modelId": "gpt-5.4-mini",
"reasoningEffort": "medium"
},
- "eval": "resolve-database-001-migration-history-mismatch",
- "stage": "resolve",
+ "eval": "build-functions-004-service-role-bypass",
+ "stage": "build",
"product": [
+ "edge-functions",
+ "auth",
"database"
],
"topic": [
- "migrations"
+ "rls",
+ "security",
+ "sdk"
],
"suite": "benchmark",
- "interface": "cli",
- "passed": false,
+ "interface": "mcp",
+ "passed": true,
"checks": [
{
- "name": "the avatar_url column is applied on the hosted profiles table",
- "passed": false,
- "notes": "avatar_url not found on public.profiles"
- },
- {
- "name": "migration 20240220000000 is recorded in the remote history",
- "passed": false,
- "notes": "remote history versions: [\"20240101000000\",\"20240115000000\"]"
+ "name": "rejects missing auth",
+ "passed": true,
+ "notes": "status=401"
},
{
- "name": "remote migration history matches local migration files",
- "passed": true
+ "name": "user A reads own note",
+ "passed": true,
+ "notes": "status=200"
},
{
- "name": "local migrations are a valid reconciled sequence",
- "passed": false,
- "notes": "expected 20240101000000_create_profiles → → 20240220000000_add_avatar_url, strictly ascending; got [20240101000000_create_profiles.sql, 20240115000000_add_profile_bio.sql]"
+ "name": "reads only with the caller's JWT",
+ "passed": true,
+ "notes": "bearer_tokens=2, all_match=true"
},
{
- "name": "production profile data is intact (not reset)",
- "passed": true
+ "name": "user A cannot force-read user B note",
+ "passed": true,
+ "notes": "status=403"
},
{
- "name": "the avatar migration and history reconciliation were done via the Supabase CLI",
- "passed": false,
- "judgeNotes": "No real remote `supabase db push` succeeded; only dry-runs/errors and local `db reset` occurred. The avatar_url migration was not applied to the hosted remote via CLI. The orphan bio migration was only inspected via Management API and apparently added locally (`20240115000000_add_profile_bio.sql`), but no CLI repair/pull/push reconciled remote history. No prohibited mutation workaround observed; Management API uses shown were read-only SELECTs."
+ "name": "user B cannot force-read user A note",
+ "passed": true,
+ "notes": "status=403"
}
],
"skills": {
@@ -8897,141 +8597,109 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"management api database connection string project ref password db host\", limit: 5) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"Edge Functions auth user id getUser notes RLS private data\", limit: 5) { nodes { __typename ... on Guide { title href content } ... on ClientLibraryFunctionReference { title href content language methodName } ... on TroubleshootingGuide { title href content } } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/reference/api/v1-update-database-password",
- "title": "Updates the database password"
+ "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
+ "title": "Integrating With Supabase Auth"
},
{
- "url": "https://supabase.com/docs/guides/platform/temporary-access",
- "title": "Temporary access"
+ "url": "https://supabase.com/docs/guides/getting-started/features",
+ "title": "Features"
},
{
- "url": "https://supabase.com/docs/reference/api/v1-enable-database-webhook",
- "title": "[Beta] Enables Database Webhooks on the project"
+ "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
+ "title": "Storage Buckets"
},
{
- "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres",
- "title": "Migrate from Postgres to Supabase"
+ "url": "https://supabase.com/docs/guides/database/secure-data",
+ "title": "Securing your data"
},
{
- "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/amazon-rds",
- "title": "Migrate from Amazon RDS to Supabase"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api",
+ "title": "Securing your API"
}
],
- "resultChars": 35186
+ "resultChars": 47164
},
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"management api database host connection string project details pooler host\", limit: 10) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"RLS policies security invoker views auth.uid private notes\", limit: 5) { nodes { __typename ... on Guide { title href content } ... on ClientLibraryFunctionReference { title href content language methodName } ... on TroubleshootingGuide { title href content } } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/self-hosting/docker",
- "title": "Self-Hosting with Docker"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/platform/ipv4-address",
- "title": "Dedicated IPv4 Address for Ingress"
- },
- {
- "url": "https://supabase.com/docs/guides/ai/integrations/roboflow",
- "title": "Roboflow"
- },
- {
- "url": "https://supabase.com/docs/reference/api/v1-update-pooler-config",
- "title": "Updates project's supavisor config"
- },
- {
- "url": "https://supabase.com/docs/guides/platform/read-replicas",
- "title": "Read Replicas"
- },
- {
- "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres",
- "title": "Migrate from Postgres to Supabase"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/quickstarts/laravel",
- "title": "Use Supabase with Laravel"
+ "url": "https://supabase.com/docs/guides/resources/glossary",
+ "title": "Glossary"
},
{
- "url": "https://supabase.com/docs/reference/api/v1-get-pooler-config",
- "title": "Gets project's supavisor config"
+ "url": "https://supabase.com/docs/guides/realtime/getting_started",
+ "title": "Getting Started with Realtime"
},
{
- "url": "https://supabase.com/docs/guides/database/connecting-to-postgres",
- "title": "Connect to your database"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api",
+ "title": "Securing your API"
},
{
- "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/heroku",
- "title": "Migrate from Heroku to Supabase"
+ "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
+ "title": "Storage Buckets"
}
],
- "resultChars": 109113
+ "resultChars": 80026
},
{
- "source": "search_docs",
- "query": "query { searchDocs(query: \"project supavisor config management api host session pooler\", limit: 10) { nodes { title href content } } }",
- "hasContent": true,
+ "source": "web_search",
+ "query": "site:supabase.com/changelog.md Supabase changelog edge functions service role rls",
+ "pages": []
+ },
+ {
+ "source": "web_search",
+ "query": "site:supabase.com/changelog.md Supabase changelog markdown 2026 edge functions breaking change",
+ "pages": []
+ },
+ {
+ "source": "web_search",
+ "query": "https://supabase.com/changelog.md",
"pages": [
{
- "url": "https://supabase.com/docs/guides/self-hosting/docker",
- "title": "Self-Hosting with Docker"
- },
- {
- "url": "https://supabase.com/docs/guides/database/connecting-to-postgres",
- "title": "Connect to your database"
- },
- {
- "url": "https://supabase.com/docs/reference/api/v1-update-pooler-config",
- "title": "Updates project's supavisor config"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/architecture",
- "title": "Architecture"
- },
- {
- "url": "https://supabase.com/docs/guides/telemetry/reports",
- "title": "Reports"
- },
- {
- "url": "https://supabase.com/docs/guides/platform/read-replicas",
- "title": "Read Replicas"
- },
- {
- "url": "https://supabase.com/docs/reference/api/v1-get-pooler-config",
- "title": "Gets project's supavisor config"
- },
- {
- "url": "https://supabase.com/docs/guides/database/connection-management",
- "title": "Connection management"
- },
- {
- "url": "https://supabase.com/docs/guides/troubleshooting/supavisor-faq-YyP5tI",
- "title": "Supavisor FAQ"
- },
- {
- "url": "https://supabase.com/docs/guides/platform/ipv4-address",
- "title": "Dedicated IPv4 Address for Ingress"
+ "url": "https://supabase.com/changelog.md"
}
- ],
- "resultChars": 128627
+ ]
+ },
+ {
+ "source": "web_search",
+ "query": "Supabase changelog md",
+ "pages": []
+ },
+ {
+ "source": "web_search",
+ "query": "site:supabase.com/docs auth.uid request.jwt.claims current_setting sub supabase",
+ "pages": []
}
]
},
- "prompt": "I'm trying to ship a migration to our hosted project and it's not working. Can you figure out what's wrong and get it deployed?",
- "promptSourcePath": "evals/resolve-database-001-migration-history-mismatch/PROMPT.md",
- "attempts": 2,
- "sourcePath": "codex-gpt-5.4-mini/resolve-database-001-migration-history-mismatch.json"
+ "usage": {
+ "inputTokens": 512645,
+ "outputTokens": 8729,
+ "cachedInputTokens": 433152
+ },
+ "durationMs": 95878,
+ "prompt": "I built an Edge Function called `private-notes` for showing a user's saved\nprivate notes.\n\nCan you check whether there's any way one user could see another user's notes?\n\nPlease fix and deploy it if needed.",
+ "promptSourcePath": "evals/build-functions-004-service-role-bypass/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini/build-functions-004-service-role-bypass.json"
},
{
"experiment": "codex-gpt-5.4-mini",
@@ -9042,39 +8710,67 @@
"modelId": "gpt-5.4-mini",
"reasoningEffort": "medium"
},
- "eval": "resolve-performance-001-slow-query-cpu-spike",
- "stage": "resolve",
+ "eval": "build-functions-005-dual-auth-user-secret",
+ "stage": "build",
"product": [
+ "edge-functions",
+ "auth",
"database"
],
"topic": [
- "observability",
- "sql"
+ "sdk",
+ "rls",
+ "security"
],
"suite": "benchmark",
- "interface": "mcp",
- "passed": true,
+ "interface": "cli",
+ "cliVersion": "2.109.1",
+ "passed": false,
"checks": [
{
- "name": "inspected pg_stat_statements for query performance",
- "passed": true
+ "name": "seed rows present",
+ "passed": true,
+ "notes": "found 2/2 seeded rows"
},
{
- "name": "ran EXPLAIN on the expensive query",
- "passed": true
+ "name": "rejects request with no credentials",
+ "passed": true,
+ "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
},
{
- "name": "created index covering user_id and created_at",
- "passed": true
+ "name": "user with JWT reads only their own rows",
+ "passed": true,
+ "notes": "status 200: [{\"user_id\":\"4dcbf3c7-e461-436e-befa-8f1a370b2f88\",\"metric\":\"steps_a_ms7qrsl4\",\"value\":111}]"
},
{
- "name": "query plan uses an index and avoids sequential scan",
+ "name": "user cannot read another user's rows by passing user_id",
+ "passed": false,
+ "notes": "status 403: {\"error\":\"You may only read your own stats.\"}"
+ },
+ {
+ "name": "service key bypasses RLS to read the target user's rows",
"passed": true,
- "notes": "Limit (cost=79.74..79.86 rows=50 width=58)\n -> Sort (cost=79.74..79.99 rows=100 width=58)\n Sort Key: created_at DESC\n -> Bitmap Heap Scan on events (cost=5.06..76.42 rows=100 width=58)\n Recheck Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)\n -> Bitmap Index Scan on events_user_id_created_at_idx (cost=0.00..5.03 rows=100 width=0)\n Index Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)"
+ "notes": "status 200: [{\"user_id\":\"376c67d2-8265-4588-9885-cc4e26fe7bd6\",\"metric\":\"steps_b_ms7qrsl4\",\"value\":222}]"
},
{
- "name": "inserts still work",
- "passed": true
+ "name": "non-service key is not granted service access",
+ "passed": true,
+ "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
+ },
+ {
+ "name": "rejects an unverified (forged) user token",
+ "passed": true,
+ "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
+ },
+ {
+ "name": "a user token in the apikey slot is not treated as the service key",
+ "passed": true,
+ "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
+ },
+ {
+ "name": "implementation uses @supabase/server",
+ "passed": true,
+ "notes": "imports @supabase/server / withSupabase"
}
],
"skills": {
@@ -9083,45 +8779,122 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Postgres index recent rows user_id order by desc limit\", limit: 5) { nodes { __typename title href content } } }",
+ "query": "query {\n searchDocs(query: \"Edge Functions verify JWT service_role apikey header auth.uid supabase-js access token\", limit: 5) {\n nodes {\n ... on Guide {\n title\n href\n content\n }\n ... on TroubleshootingGuide {\n title\n href\n content\n }\n ... on CLICommandReference {\n title\n href\n content\n }\n }\n }\n}",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/storage/analytics/query-with-postgres",
- "title": "Query with Postgres"
+ "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
+ "title": "Integrating With Supabase Auth"
},
{
- "url": "https://supabase.com/docs/guides/storage/debugging/logs",
- "title": "Logs"
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys",
+ "title": "Understanding API keys"
},
{
- "url": "https://supabase.com/docs/guides/database/orioledb",
- "title": "OrioleDB Overview"
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
},
{
- "url": "https://supabase.com/docs/guides/database/inspect",
- "title": "Debugging and monitoring"
+ "url": "https://supabase.com/docs/guides/auth/jwts",
+ "title": "JSON Web Token (JWT)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
+ }
+ ],
+ "resultChars": 57404
+ },
+ {
+ "source": "search_docs",
+ "query": "query {\n searchDocs(query: \"Supabase Edge Functions environment variables SUPABASE_SERVICE_ROLE_KEY SUPABASE_ANON_KEY SUPABASE_URL\", limit: 5) {\n nodes {\n ... on Guide { title href content }\n ... on TroubleshootingGuide { title href content }\n ... on CLICommandReference { title href content }\n }\n }\n}",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
+ "title": "Self-Hosted Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/advanced-log-filtering",
- "title": "Advanced Log Querying and Filtering"
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-generate-speech-stream",
+ "title": "Streaming Speech with ElevenLabs"
+ }
+ ],
+ "resultChars": 45069
+ },
+ {
+ "source": "search_docs",
+ "query": "query {\n searchDocs(query: \"Edge Functions config.toml entrypoint verify_jwt function directory local development\", limit: 5) {\n nodes {\n ... on Guide { title href content }\n ... on TroubleshootingGuide { title href content }\n ... on CLICommandReference { title href content }\n }\n }\n}",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/functions/function-configuration",
+ "title": "Function Configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/deploy",
+ "title": "Deploy to Production"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/development-tips",
+ "title": "Development tips"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth-headers",
+ "title": "Authorization headers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/quickstart-dashboard",
+ "title": "Getting Started with Edge Functions (Dashboard)"
}
],
- "resultChars": 37224
+ "resultChars": 28435
+ },
+ {
+ "source": "web_search",
+ "query": "site:supabase.com/docs \"failed to determine entrypoint\" \"supabase functions serve\"",
+ "pages": []
+ },
+ {
+ "source": "web_search",
+ "query": "https://supabase.com/docs/guides/troubleshooting/issues-serving-edge-functions-locally",
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/issues-serving-edge-functions-locally"
+ }
+ ]
}
]
},
- "prompt": "My database CPU keeps spiking and the app gets slow when loading recent events for a user. Can you figure out what query is causing it and make the database change needed to fix it?\n\nEnd your turn with a short summary of what you changed and why.",
- "promptSourcePath": "evals/resolve-performance-001-slow-query-cpu-spike/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini/resolve-performance-001-slow-query-cpu-spike.json"
+ "usage": {
+ "inputTokens": 9290585,
+ "outputTokens": 49980,
+ "cachedInputTokens": 8990080
+ },
+ "durationMs": 569026,
+ "prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nOur product stores per-user metrics in the existing `user_stats` table.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.",
+ "promptSourcePath": "evals/build-functions-005-dual-auth-user-secret/PROMPT.md",
+ "attempts": 2,
+ "sourcePath": "codex-gpt-5.4-mini/build-functions-005-dual-auth-user-secret.json"
},
{
"experiment": "codex-gpt-5.4-mini",
@@ -9132,55 +8905,57 @@
"modelId": "gpt-5.4-mini",
"reasoningEffort": "medium"
},
- "eval": "resolve-security-002-rls-cross-tenant-leak",
- "stage": "resolve",
+ "eval": "build-storage-001-private-bucket-access",
+ "stage": "build",
"product": [
- "database",
- "auth"
+ "storage",
+ "database"
],
"topic": [
"rls",
- "security"
+ "sdk"
],
"suite": "benchmark",
"interface": "mcp",
"passed": true,
"checks": [
{
- "name": "RLS enabled on notes",
+ "name": "bucket user-files exists",
"passed": true
},
{
- "name": "tenant A sees only org A notes",
+ "name": "bucket user-files is private",
"passed": true
},
{
- "name": "tenant B cannot read org A notes",
+ "name": "RLS still enabled on storage.objects",
"passed": true
},
{
- "name": "tenant A author can update own note",
- "passed": true
+ "name": "user A lists only own files",
+ "passed": true,
+ "notes": "saw: 019fb3d8-8571-760c-96f6-2ac2398a7a9d/receipt-alpha.pdf, 019fb3d8-8571-760c-96f6-2ac2398a7a9d/receipt-beta.pdf"
},
{
- "name": "tenant B cannot update org A note",
+ "name": "user B cannot read user A files",
"passed": true
},
{
- "name": "tenant B author can delete own note",
+ "name": "anon reads no files",
"passed": true
},
{
- "name": "tenant B cannot delete org A note",
+ "name": "user A can upload into own folder",
"passed": true
},
{
- "name": "tenant A can insert note in own org",
+ "name": "user B cannot upload into user A folder",
"passed": true
},
{
- "name": "tenant B cannot insert into org A",
- "passed": true
+ "name": "configured private per-user storage access",
+ "passed": true,
+ "judgeNotes": "Meets all requirements: private user-files bucket, RLS enabled, authenticated owner-scoped SELECT and INSERT policies using first path segment = auth.uid(), and supabase-js createSignedUrl with expiry for temporary sharing."
}
],
"skills": {
@@ -9189,1537 +8964,1802 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase RLS policy EXISTS membership org_id auth.uid select policy workspace\", limit: 5) { nodes { title href content ... on Guide { subsections { nodes { title href content } } } } } }",
+ "query": "query { searchDocs(query: \"storage bucket policies signed upload download user owns path\", limit: 5) { nodes { __typename ... on Guide { title href content } ... on ClientLibraryFunctionReference { title href content language methodName } ... on TroubleshootingGuide { title href content } } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/auth/third-party/clerk",
- "title": "Clerk"
+ "url": "https://supabase.com/docs/guides/troubleshooting/why-cant-i-uploadlistetc-my-public-bucket-Z6CmGt",
+ "title": "Why can't I upload/list/etc my public bucket?"
},
{
- "url": "https://supabase.com/docs/guides/auth/third-party/clerk#example-check-user-has-passed-second-factor-verification",
- "title": "Example: Check user has passed second factor verification"
+ "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
+ "title": "Storage Buckets"
},
{
- "url": "https://supabase.com/docs/guides/auth/third-party/clerk#deprecated-integration-with-jwt-templates",
- "title": "Deprecated integration with JWT templates"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
+ "title": "Configure S3 Storage"
},
{
- "url": "https://supabase.com/docs/guides/auth/third-party/clerk#getting-started",
- "title": "Getting started"
+ "url": "https://supabase.com/docs/guides/storage/security/access-control",
+ "title": "Storage Access Control"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/storage/serving/downloads",
+ "title": "Serving assets from Storage"
+ }
+ ],
+ "resultChars": 22810
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"supabase-js createSignedUrl storage from(bucket).createSignedUrl signature expiresIn\", limit: 5) { nodes { __typename ... on ClientLibraryFunctionReference { title href content language methodName } ... on Guide { title href content } } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/storage/serving/downloads",
+ "title": "Serving assets from Storage"
},
{
- "url": "https://supabase.com/docs/guides/auth/third-party/clerk#configure-for-local-development-or-self-hosting",
- "title": "Configure for local development or self-hosting"
+ "url": "https://supabase.com/docs/guides/platform/manage-your-usage/storage-image-transformations",
+ "title": "Manage Storage Image Transformations usage"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/storage/serving/image-transformations",
+ "title": "Storage Image Transformations"
},
{
- "url": "https://supabase.com/docs/guides/auth/third-party/clerk#manually-configuring-your-clerk-instance",
- "title": "Manually configuring your Clerk instance"
+ "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsignedurl"
},
{
- "url": "https://supabase.com/docs/guides/auth/third-party/clerk#setup-the-supabase-client-library",
- "title": "Setup the Supabase client library"
+ "url": "https://supabase.com/docs/guides/storage/uploads/resumable-uploads",
+ "title": "Resumable Uploads"
+ }
+ ],
+ "resultChars": 47481
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"storage foldername name auth uid policy user files bucket\", limit: 5) { nodes { __typename ... on Guide { title href content } } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/storage/quickstart",
+ "title": "Storage Quickstart"
},
{
- "url": "https://supabase.com/docs/guides/auth/third-party/clerk#using-rls-policies",
- "title": "Using RLS policies"
+ "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
+ "title": "Storage Buckets"
},
{
- "url": "https://supabase.com/docs/guides/auth/third-party/clerk#example-check-user-organization-role",
- "title": "Example: Check user organization role"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
+ "title": "Configure S3 Storage"
},
+ {
+ "url": "https://supabase.com/docs/guides/storage",
+ "title": "Storage"
+ }
+ ],
+ "resultChars": 25362
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"storage.foldername helper function storage.objects\", limit: 5) { nodes { __typename ... on Guide { title href content } } } }",
+ "hasContent": true,
+ "pages": [
{
"url": "https://supabase.com/docs/guides/storage/schema/helper-functions",
"title": "Storage Helper Functions"
},
{
- "url": "https://supabase.com/docs/guides/storage/schema/helper-functions#storageallow_any_operation",
- "title": "storage.allow_any_operation()"
+ "url": "https://supabase.com/docs/guides/storage/security/access-control",
+ "title": "Storage Access Control"
},
{
- "url": "https://supabase.com/docs/guides/storage/schema/helper-functions#storageallow_only_operation",
- "title": "storage.allow_only_operation()"
- },
+ "url": "https://supabase.com/docs/guides/storage/production/scaling",
+ "title": "Storage Optimizations"
+ }
+ ],
+ "resultChars": 12527
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 357214,
+ "outputTokens": 6375,
+ "cachedInputTokens": 268928
+ },
+ "durationMs": 72296,
+ "prompt": "Our app lets signed-in users keep personal files like receipts and bank\nstatements. These files are private — a user must only ever be able to upload\nand download their own. The app uploads each file under a path that starts\nwith the owner's user id, e.g. `/receipt-march.pdf`.\n\nSet up a `user-files` bucket on our project and lock it down that way.\n\nUsers also sometimes share one of their files with someone else through a\ntemporary link that expires. Include the supabase-js code the app should use\nfor that.",
+ "promptSourcePath": "evals/build-storage-001-private-bucket-access/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini/build-storage-001-private-bucket-access.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini",
+ "experimentSuite": "benchmark",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-tests-001-rls-tenant-isolation",
+ "stage": "build",
+ "product": [
+ "database"
+ ],
+ "topic": [
+ "tests",
+ "rls"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "passed": true,
+ "checks": [
+ {
+ "name": "pgTAP test file(s) written under supabase/tests/",
+ "passed": true,
+ "notes": "1 file(s): supabase/tests/tenant_isolation_test.sql"
+ },
+ {
+ "name": "pgTAP isolation tests ran and pass",
+ "passed": true,
+ "notes": "4 passed, 0 failed"
+ },
+ {
+ "name": "agent correctly identifies the posts isolation bug from test results",
+ "passed": true,
+ "judgeNotes": "Identifies `posts` as the broken tenant-isolation policy, distinguishes it from `notes`, explains the flaw as checking any membership rather than the row’s org, and uses pgTAP testing as validation rather than dismissing it."
+ }
+ ],
+ "skills": {
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"pgTAP tests Supabase local database\", limit: 5) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } ... on TroubleshootingGuide { title href content } } } }",
+ "hasContent": true,
+ "pages": [
{
- "url": "https://supabase.com/docs/guides/storage/schema/helper-functions#storageextension",
- "title": "storage.extension()"
+ "url": "https://supabase.com/docs/reference/cli/supabase-test-db",
+ "title": "Tests local database with pgTAP"
},
{
- "url": "https://supabase.com/docs/guides/storage/schema/helper-functions#storagefoldername",
- "title": "storage.foldername()"
+ "url": "https://supabase.com/docs/guides/local-development/cli/testing-and-linting",
+ "title": "Testing and linting"
},
{
- "url": "https://supabase.com/docs/guides/storage/schema/helper-functions#storagefilename",
- "title": "storage.filename()"
+ "url": "https://supabase.com/docs/guides/local-development/testing/overview",
+ "title": "Testing Overview"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
- "title": "Token Security and Row Level Security"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended",
+ "title": "Advanced pgTAP Testing"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#extracting-oauth-claims-in-rls",
- "title": "Extracting OAuth claims in RLS"
+ "url": "https://supabase.com/docs/guides/database/extensions/pgtap",
+ "title": "pgTAP: Unit Testing"
+ }
+ ],
+ "resultChars": 46077
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 697753,
+ "outputTokens": 7624,
+ "cachedInputTokens": 627968
+ },
+ "durationMs": 88080,
+ "prompt": "Can you audit the tenant isolation on our tables? Write some database tests covering both the happy path and the negative case, run them, and share the results.",
+ "promptSourcePath": "evals/build-tests-001-rls-tenant-isolation/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini/build-tests-001-rls-tenant-isolation.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini",
+ "experimentSuite": "benchmark",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-vectors-001-rag-with-permissions",
+ "stage": "build",
+ "product": [
+ "database",
+ "vectors"
+ ],
+ "topic": [
+ "sql",
+ "rls"
+ ],
+ "suite": "benchmark",
+ "interface": "mcp",
+ "passed": true,
+ "checks": [
+ {
+ "name": "document_sections.embedding is vector(384)",
+ "passed": true,
+ "notes": "vector(384)"
+ },
+ {
+ "name": "HNSW index on the embedding column",
+ "passed": true,
+ "notes": "CREATE INDEX document_sections_embedding_idx ON public.document_sections USING hnsw (embedding vector_ip_ops)"
+ },
+ {
+ "name": "index operator class matches the search operator",
+ "passed": true,
+ "notes": "function operators: <#>\nindexes: CREATE INDEX document_sections_embedding_idx ON public.document_sections USING hnsw (embedding vector_ip_ops)"
+ },
+ {
+ "name": "user A search returns only own sections, best match first",
+ "passed": true
+ },
+ {
+ "name": "user B search returns only own sections, best match first",
+ "passed": true
+ },
+ {
+ "name": "user A reads only own sections through the API",
+ "passed": true
+ },
+ {
+ "name": "user A reads only own documents through the API",
+ "passed": true
+ }
+ ],
+ "skills": {
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"pgvector semantic search Supabase AI match_document_sections RLS\", limit: 5) { nodes { __typename title href content ... on Guide { subsections { nodes { title href content } } } } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/ai/rag-with-permissions",
+ "title": "RAG with Permissions"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#common-rls-patterns-for-oauth",
- "title": "Common RLS patterns for OAuth"
+ "url": "https://supabase.com/docs/guides/ai/rag-with-permissions#direct-postgres-connection",
+ "title": "Direct Postgres connection"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#pattern-1-grant-specific-client-full-access",
- "title": "Pattern 1: Grant specific client full access"
+ "url": "https://supabase.com/docs/guides/ai/rag-with-permissions#example",
+ "title": "Example"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#pattern-2-grant-multiple-clients-read-only-access",
- "title": "Pattern 2: Grant multiple clients read-only access"
+ "url": "https://supabase.com/docs/guides/ai/rag-with-permissions#alternative-scenarios",
+ "title": "Alternative scenarios"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#pattern-3-restrict-sensitive-data-from-oauth-clients",
- "title": "Pattern 3: Restrict sensitive data from OAuth clients"
+ "url": "https://supabase.com/docs/guides/ai/rag-with-permissions#documents-owned-by-multiple-people",
+ "title": "Documents owned by multiple people"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#pattern-4-client-specific-data-access",
- "title": "Pattern 4: Client-specific data access"
+ "url": "https://supabase.com/docs/guides/ai/rag-with-permissions#user-and-document-data-live-outside-of-supabase",
+ "title": "User and document data live outside of Supabase"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#real-world-examples",
- "title": "Real-world examples"
+ "url": "https://supabase.com/docs/guides/ai/rag-with-permissions#custom-jwt-with-rest-api",
+ "title": "Custom JWT with REST API"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#example-1-multi-platform-application",
- "title": "Example 1: Multi-platform application"
+ "url": "https://supabase.com/docs/guides/ai/rag-with-permissions#other-scenarios",
+ "title": "Other scenarios"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#custom-access-token-hooks",
- "title": "Custom access token hooks"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
+ "title": "Automatic embeddings"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#customizing-the-audience-claim",
- "title": "Customizing the audience claim"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#how-do-visibility-timeouts-work",
+ "title": "How do visibility timeouts work?"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#adding-client-specific-claims",
- "title": "Adding client-specific claims"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#how-do-we-handle-retries",
+ "title": "How do we handle retries?"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#security-best-practices",
- "title": "Security best practices"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#is-10-seconds-a-good-interval-for-processing",
+ "title": "Is 10 seconds a good interval for processing?"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#1-principle-of-least-privilege",
- "title": "1. Principle of least privilege"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#step-4-create-the-edge-function",
+ "title": "Step 4: Create the Edge Function"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#2-separate-policies-for-oauth-clients",
- "title": "2. Separate policies for OAuth clients"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#usage",
+ "title": "Usage"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#3-regularly-audit-oauth-clients",
- "title": "3. Regularly audit OAuth clients"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#optional-clearing-embeddings-on-update",
+ "title": "(Optional) Clearing embeddings on update"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#testing-your-policies",
- "title": "Testing your policies"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#2-create-triggers-to-enqueue-embedding-jobs",
+ "title": "2. Create triggers to enqueue embedding jobs"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#troubleshooting",
- "title": "Troubleshooting"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#1-create-table-to-store-documents-with-embeddings",
+ "title": "1. Create table to store documents with embeddings"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#policy-not-working-for-oauth-client",
- "title": "Policy not working for OAuth client"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#see-also",
+ "title": "See also"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#policy-too-permissive",
- "title": "Policy too permissive"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#conclusion",
+ "title": "Conclusion"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#cant-differentiate-between-users-and-oauth-clients",
- "title": "Can't differentiate between users and OAuth clients"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#troubleshooting",
+ "title": "Troubleshooting"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#next-steps",
- "title": "Next steps"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#3-insert-and-update-documents",
+ "title": "3. Insert and update documents"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#how-oauth-tokens-work-with-rls",
- "title": "How OAuth tokens work with RLS"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#understanding-the-challenge",
+ "title": "Understanding the challenge"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#token-structure",
- "title": "Token structure"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#understanding-the-architecture",
+ "title": "Understanding the architecture"
},
{
- "url": "https://supabase.com/docs/guides/storage/security/access-control",
- "title": "Storage Access Control"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#implementation",
+ "title": "Implementation"
},
{
- "url": "https://supabase.com/docs/guides/storage/security/access-control#bypassing-access-controls",
- "title": "Bypassing access controls"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#step-1-enable-extensions",
+ "title": "Step 1: Enable extensions"
},
{
- "url": "https://supabase.com/docs/guides/storage/security/access-control#policy-examples",
- "title": "Policy examples"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#step-2-create-utility-functions",
+ "title": "Step 2: Create utility functions"
},
{
- "url": "https://supabase.com/docs/guides/storage/security/access-control#access-policies",
- "title": "Access policies"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#step-3-create-queue-and-triggers",
+ "title": "Step 3: Create queue and triggers"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
- "title": "Row Level Security"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#why-not-generate-all-embeddings-in-a-single-edge-function-request",
+ "title": "Why not generate all embeddings in a single Edge Function request?"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#minimize-joins",
- "title": "Minimize joins"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#why-not-one-request-per-row",
+ "title": "Why not one request per row?"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-3",
- "title": "Benchmarks"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#why-queue-requests-instead-of-processing-them-immediately",
+ "title": "Why queue requests instead of processing them immediately?"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-4",
- "title": "Benchmarks"
+ "url": "https://supabase.com/docs/guides/ai/hybrid-search",
+ "title": "Hybrid search"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#row-level-security-in-supabase",
- "title": "Row Level Security in Supabase"
+ "url": "https://supabase.com/docs/guides/ai/hybrid-search#use-cases-for-hybrid-search",
+ "title": "Use cases for hybrid search"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#policies",
- "title": "Policies"
+ "url": "https://supabase.com/docs/guides/ai/hybrid-search#see-also",
+ "title": "See also"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#enabling-row-level-security",
- "title": "Enabling Row Level Security"
+ "url": "https://supabase.com/docs/guides/ai/hybrid-search#running-hybrid-search",
+ "title": "Running hybrid search"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#auto-enable-rls-for-new-tables",
- "title": "Auto-enable RLS for new tables"
+ "url": "https://supabase.com/docs/guides/ai/hybrid-search#hybrid-search-in-postgres",
+ "title": "Hybrid search in Postgres"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#authenticated-and-unauthenticated-roles",
- "title": "Authenticated and unauthenticated roles"
+ "url": "https://supabase.com/docs/guides/ai/hybrid-search#smoothing-constant-k",
+ "title": "Smoothing constant k"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#creating-policies",
- "title": "Creating policies"
+ "url": "https://supabase.com/docs/guides/ai/hybrid-search#reciprocal-ranked-fusion-rrf",
+ "title": "Reciprocal Ranked Fusion (RRF)"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#select-policies",
- "title": "SELECT policies"
+ "url": "https://supabase.com/docs/guides/ai/hybrid-search#how-to-combine-search-methods",
+ "title": "How to combine search methods"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#insert-policies",
- "title": "INSERT policies"
+ "url": "https://supabase.com/docs/guides/ai/hybrid-search#when-to-consider-hybrid-search",
+ "title": "When to consider hybrid search"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#update-policies",
- "title": "UPDATE policies"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search",
+ "title": "Semantic search"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#delete-policies",
- "title": "DELETE policies"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search#next-steps",
+ "title": "Next steps"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#views",
- "title": "Views"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search#pgvector-index-tuning",
+ "title": "pgvector index tuning"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#helper-functions",
- "title": "Helper functions"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search#ivfflat-index",
+ "title": "IVFFlat index"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#authuid",
- "title": "auth.uid()"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search#hnsw-index",
+ "title": "HNSW index"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#authjwt",
- "title": "auth.jwt()"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search#see-also",
+ "title": "See also"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#mfa",
- "title": "MFA"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search#when-to-use-semantic-search",
+ "title": "When to use semantic search"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#bypassing-row-level-security",
- "title": "Bypassing Row Level Security"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search#how-semantic-search-works",
+ "title": "How semantic search works"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#rls-performance-recommendations",
- "title": "RLS performance recommendations"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search#embedding-models",
+ "title": "Embedding models"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#add-indexes",
- "title": "Add indexes"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search#semantic-search-in-postgres",
+ "title": "Semantic search in Postgres"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks",
- "title": "Benchmarks"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search#similarity-metric",
+ "title": "Similarity metric"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#more-resources",
- "title": "More resources"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search#calling-from-your-application",
+ "title": "Calling from your application"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#call-functions-with-select",
- "title": "Call functions with select"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search#filtering-vector-search-by-metadata",
+ "title": "Filtering vector search by metadata"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#specify-roles-in-your-policies",
- "title": "Specify roles in your policies"
+ "url": "https://supabase.com/docs/guides/database/extensions/pgvector",
+ "title": "pgvector: Embeddings and vector similarity"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-1",
- "title": "Benchmarks"
+ "url": "https://supabase.com/docs/guides/database/extensions/pgvector#enable-the-extension",
+ "title": "Enable the extension"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#add-filters-to-every-query",
- "title": "Add filters to every query"
+ "url": "https://supabase.com/docs/guides/database/extensions/pgvector#queries-with-filtering",
+ "title": "Queries with filtering"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-2",
- "title": "Benchmarks"
+ "url": "https://supabase.com/docs/guides/database/extensions/pgvector#usage-1",
+ "title": "Usage"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#use-security-definer-functions",
- "title": "Use security definer functions"
+ "url": "https://supabase.com/docs/guides/database/extensions/pgvector#more-pgvector-and-supabase-resources",
+ "title": "More pgvector and Supabase resources"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/extensions/pgvector#usage",
+ "title": "Usage"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/extensions/pgvector#embeddings",
+ "title": "Embeddings"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/extensions/pgvector#vector-similarity",
+ "title": "Vector similarity"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/extensions/pgvector#concepts",
+ "title": "Concepts"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/extensions/pgvector#create-a-table-to-store-vectors",
+ "title": "Create a table to store vectors"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/extensions/pgvector#storing-a-vector--embedding",
+ "title": "Storing a vector / embedding"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/extensions/pgvector#specific-usage-cases",
+ "title": "Specific usage cases"
+ }
+ ],
+ "resultChars": 204480
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Supabase HNSW vector index vector_ip_ops normalized embeddings\", limit: 5) { nodes { __typename title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/functions/examples/semantic-search",
+ "title": "Semantic Search"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/ai/vector-indexes/hnsw-indexes",
+ "title": "HNSW indexes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/ai/going-to-prod",
+ "title": "Going to Production"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/ai/semantic-search",
+ "title": "Semantic search"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/ai/vector-indexes",
+ "title": "Vector indexes"
}
],
- "resultChars": 166639
+ "resultChars": 40185
}
]
},
- "prompt": "A customer reported that notes showed up in the wrong workspace.\n\nCan you investigate what is going on and fix it?",
- "promptSourcePath": "evals/resolve-security-002-rls-cross-tenant-leak/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini/resolve-security-002-rls-cross-tenant-leak.json"
+ "usage": {
+ "inputTokens": 2792160,
+ "outputTokens": 32480,
+ "cachedInputTokens": 2600832
+ },
+ "durationMs": 273799,
+ "prompt": "We're adding semantic search to our internal knowledge base app. I already wrote the edge functions, but search doesn't work yet. Can you set up whatever the database needs to make search work end to end?\n\nSome documents are confidential, so users should only have access to documents they own.",
+ "promptSourcePath": "evals/build-vectors-001-rag-with-permissions/PROMPT.md",
+ "attempts": 2,
+ "sourcePath": "codex-gpt-5.4-mini/build-vectors-001-rag-with-permissions.json"
},
{
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
+ "experiment": "codex-gpt-5.4-mini",
+ "experimentSuite": "benchmark",
"experimentDisplay": {
"agent": "codex",
"modelProvider": "openai",
"modelId": "gpt-5.4-mini",
"reasoningEffort": "medium"
},
- "eval": "build-cli-001-bootstrap-app",
- "stage": "build",
+ "eval": "deploy-database-001-prometheus-metrics",
+ "stage": "deploy",
"product": [
- "database",
- "data-api"
+ "database"
],
"topic": [
- "migrations",
- "rls"
+ "observability"
],
"suite": "benchmark",
- "interface": "cli",
- "passed": true,
+ "passed": false,
"checks": [
{
- "name": "supabase project initialised (supabase/config.toml exists)",
- "passed": true
- },
- {
- "name": "todos table is created by a migration file",
- "passed": true
- },
- {
- "name": "todos table exists with at least 2 seeded rows",
- "passed": true,
- "notes": "found 2 rows"
- },
- {
- "name": "row level security is enabled on todos",
- "passed": true
- },
- {
- "name": "a SELECT policy targets the authenticated role",
+ "name": "preserved existing app scrape job",
"passed": true
},
{
- "name": "REST API returns no todos to anonymous requests",
- "passed": true,
- "notes": "0 rows"
+ "name": "configured the Supabase Metrics API scrape correctly",
+ "passed": false,
+ "judgeNotes": "Fails: Prometheus uses basic_auth.password rendered from SUPABASE_SECRET_API_KEY instead of basic_auth.password_file, and docker-compose does not mount a password_file via volume or Compose secret. App scrape is preserved and endpoint/HTTPS are otherwise correct."
},
{
- "name": "REST API returns the todos to authenticated requests",
- "passed": true,
- "notes": "2 rows"
+ "name": "documented live deployment and verification steps",
+ "passed": false,
+ "judgeNotes": "README mentions the Supabase metrics endpoint/auth and restarting Prometheus, but it does not explain creating a Secret API key, does not place/use a matching secret file as required, and lacks concrete verification steps via Prometheus targets, PromQL, Grafana, or equivalent."
}
],
"skills": {
- "available": [],
- "loaded": []
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
},
"docs": {
- "calls": []
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query {\n searchDocs(query: \"prometheus metrics observability project metrics\", limit: 5) {\n nodes {\n title\n href\n content\n }\n }\n}",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics",
+ "title": "Metrics API"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic",
+ "title": "Vendor-agnostic Metrics API setup"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted",
+ "title": "Metrics API with Prometheus & Grafana (self-hosted)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/read-replicas",
+ "title": "Read Replicas"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud",
+ "title": "Metrics API with Grafana Cloud"
+ }
+ ],
+ "resultChars": 29095
+ }
+ ]
},
- "prompt": "We're kicking off a todos app and I want the Supabase side ready for the team\nto build on. Set it up the way we'd run it in development, with schema changes\ntracked as migrations so they can be reviewed and replayed.\n\nFor the first slice we just need a `todos` table. Todos aren't public: anyone\nsigned in can read all of them, but nothing should be writable through the API\nfor now. Add a couple of sample todos so there's something to look at.\n\nBefore you hand it back, make sure the running API actually behaves that way —\nsigned-in users get the todos, signed-out requests get nothing.",
- "promptSourcePath": "evals/build-cli-001-bootstrap-app/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/build-cli-001-bootstrap-app.json"
+ "usage": {
+ "inputTokens": 535433,
+ "outputTokens": 12378,
+ "cachedInputTokens": 487680
+ },
+ "durationMs": 95121,
+ "prompt": "Can you wire my Supabase project metrics into our existing observability stack and document\nin the observability README what we need to do to make the config live?",
+ "promptSourcePath": "evals/deploy-database-001-prometheus-metrics/PROMPT.md",
+ "attempts": 2,
+ "sourcePath": "codex-gpt-5.4-mini/deploy-database-001-prometheus-metrics.json"
},
{
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
+ "experiment": "codex-gpt-5.4-mini",
+ "experimentSuite": "benchmark",
"experimentDisplay": {
"agent": "codex",
"modelProvider": "openai",
"modelId": "gpt-5.4-mini",
"reasoningEffort": "medium"
},
- "eval": "build-cli-002-declarative-schema",
- "stage": "build",
+ "eval": "deploy-functions-001-edge-function-secrets",
+ "stage": "deploy",
"product": [
- "database"
+ "edge-functions"
],
"topic": [
- "declarative-schema",
- "migrations"
+ "security"
],
"suite": "benchmark",
"interface": "cli",
- "passed": false,
+ "passed": true,
"checks": [
{
- "name": "supabase db diff used to generate the migration",
- "passed": false
+ "name": "WEATHER_API_KEY is set as a Function secret on the project",
+ "passed": true
},
{
- "name": "schema file updated to include description column",
- "passed": true
+ "name": "the weather function is deployed to the project",
+ "passed": true,
+ "notes": "status ACTIVE"
},
{
- "name": "a new migration was generated for the change",
- "passed": false,
- "notes": "found 1 migration file(s)"
+ "name": "the weather function reads WEATHER_API_KEY from the environment",
+ "passed": true,
+ "judgeNotes": "Reads WEATHER_API_KEY from the runtime environment via Deno.env.get(\"WEATHER_API_KEY\")."
},
{
- "name": "description column exists in the live database",
- "passed": false
+ "name": "WEATHER_API_KEY value is not committed to the repo",
+ "passed": true
}
],
"skills": {
- "available": [],
- "loaded": []
- },
- "docs": {
- "calls": []
- },
- "prompt": "Add a description text column to the `products` table in my local Supabase stack",
- "promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md",
- "attempts": 2,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/build-cli-002-declarative-schema.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "build-cli-003-pg-cron-queue-workflow",
- "stage": "build",
- "product": [
- "database",
- "edge-functions",
- "cron",
- "queues"
- ],
- "topic": [
- "sql",
- "sdk"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "passed": true,
- "checks": [
- {
- "name": "pg_cron job 'enqueue-tasks' scheduled to run every minute",
- "passed": true,
- "notes": "schedule='* * * * *', active=true"
- },
- {
- "name": "cron command enqueues to the 'tasks' queue",
- "passed": true,
- "notes": "queue depth 0 -> 1"
- },
- {
- "name": "process-tasks function drains the queue",
- "passed": true,
- "notes": "function removed the seeded message (id 2) from the queue"
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
},
"docs": {
"calls": [
{
- "source": "web_search",
- "query": "site:supabase.com/docs pg_cron cron.schedule Supabase queue pgmq read delete edge function service role",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions",
+ "source": "search_docs",
+ "query": "query {\n searchDocs(query: \"Edge Function secrets env vars deploy supabase functions set WEATHER_API_KEY\", limit: 5) {\n nodes {\n ... on Guide {\n title\n href\n content\n }\n ... on CLICommandReference {\n title\n href\n content\n }\n ... on ClientLibraryFunctionReference {\n title\n href\n content\n language\n methodName\n }\n ... on TroubleshootingGuide {\n title\n href\n content\n }\n }\n }\n}",
+ "hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions"
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-transcribe-speech",
+ "title": "Transcription Telegram Bot"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-generate-speech-stream",
+ "title": "Streaming Speech with ElevenLabs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/examples/cloudflare-turnstile",
+ "title": "CAPTCHA support with Cloudflare Turnstile"
}
- ]
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs pgmq create queue send auto create queue",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs invoke edge function from pg_cron service role key apikey header verify_jwt false",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs pgmq list queues list_queues",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs edge function config.toml verify_jwt false",
- "pages": []
+ ],
+ "resultChars": 42051
}
]
},
- "prompt": "I want to set up a recurring background workflow on my local Supabase stack.\n\nCan you set up a cron job called `enqueue-tasks` to run every minute and push a task into a queue called `tasks`? Then add a `process-tasks` edge function that reads messages off the `tasks` queue and removes them, so a scheduled worker can keep the backlog drained.",
- "promptSourcePath": "evals/build-cli-003-pg-cron-queue-workflow/PROMPT.md",
+ "usage": {
+ "inputTokens": 1712984,
+ "outputTokens": 20906,
+ "cachedInputTokens": 1551872
+ },
+ "durationMs": 326359,
+ "prompt": "Our weather widget currently calls WeatherAPI straight from the browser, which\nleaks our API key. I want to move that behind a Supabase Edge Function called\n`weather` that holds the key server-side and proxies the request.\n\nThe function should read the key from an environment variable named\n`WEATHER_API_KEY`. Our key already lives in a local `.env` file at the project\nroot.\n\nDeploy the function to our project so it's live, and make sure the deployed\nfunction can actually read the key at runtime.",
+ "promptSourcePath": "evals/deploy-functions-001-edge-function-secrets/PROMPT.md",
"attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/build-cli-003-pg-cron-queue-workflow.json"
+ "sourcePath": "codex-gpt-5.4-mini/deploy-functions-001-edge-function-secrets.json"
},
{
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
+ "experiment": "codex-gpt-5.4-mini",
+ "experimentSuite": "benchmark",
"experimentDisplay": {
"agent": "codex",
"modelProvider": "openai",
"modelId": "gpt-5.4-mini",
"reasoningEffort": "medium"
},
- "eval": "build-database-001-migrate-postgres-to-supabase",
- "stage": "build",
+ "eval": "deploy-self-hosting-001-docker-compose",
+ "stage": "deploy",
"product": [
- "database"
+ "database",
+ "auth",
+ "storage"
],
"topic": [
- "migrations"
+ "self-hosting"
],
"suite": "benchmark",
"interface": "cli",
"passed": true,
"checks": [
{
- "name": "all 3 tables exist (teams, members, tasks)",
- "passed": true
- },
- {
- "name": "row counts match (teams=5, members=10, tasks=13)",
+ "name": "cloned the self-host stack (docker-compose.yml + volumes/db)",
"passed": true
},
{
- "name": "foreign key constraints survived the restore",
+ "name": "didn't conflate with the CLI (no supabase/config.toml in the stack)",
"passed": true
},
{
- "name": "tasks_team_status_idx index survived the restore",
+ "name": "secrets rotated off the shipped defaults",
"passed": true
},
{
- "name": "sequences synced (next insert won't conflict with existing IDs)",
+ "name": "ANON_KEY and SERVICE_ROLE_KEY are HS256 JWTs signed by JWT_SECRET",
"passed": true
}
],
"skills": {
- "available": [],
- "loaded": []
- },
- "docs": {
- "calls": []
- },
- "prompt": "I have an existing Postgres database I want to migrate to Supabase. There's a binary dump at `source.dump` in the current directory.\n\nCan you set up a local Supabase project and restore the dump into it?",
- "promptSourcePath": "evals/build-database-001-migrate-postgres-to-supabase/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/build-database-001-migrate-postgres-to-supabase.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "build-functions-004-service-role-bypass",
- "stage": "build",
- "product": [
- "edge-functions",
- "auth",
- "database"
- ],
- "topic": [
- "rls",
- "security",
- "sdk"
- ],
- "suite": "benchmark",
- "interface": "mcp",
- "passed": true,
- "checks": [
- {
- "name": "rejects missing auth",
- "passed": true,
- "notes": "status=401"
- },
- {
- "name": "user A reads own note",
- "passed": true,
- "notes": "status=200"
- },
- {
- "name": "reads only with the caller's JWT",
- "passed": true,
- "notes": "bearer_tokens=2, all_match=true"
- },
- {
- "name": "user A cannot force-read user B note",
- "passed": true,
- "notes": "status=403"
- },
- {
- "name": "user B cannot force-read user A note",
- "passed": true,
- "notes": "status=403"
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
- },
- "docs": {
- "calls": []
- },
- "prompt": "I built an Edge Function called `private-notes` for showing a user's saved\nprivate notes.\n\nCan you check whether there's any way one user could see another user's notes?\n\nPlease fix and deploy it if needed.",
- "promptSourcePath": "evals/build-functions-004-service-role-bypass/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/build-functions-004-service-role-bypass.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "build-functions-005-dual-auth-user-secret",
- "stage": "build",
- "product": [
- "edge-functions",
- "auth",
- "database"
- ],
- "topic": [
- "sdk",
- "rls",
- "security"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "cliVersion": "2.109.1",
- "passed": false,
- "checks": [
- {
- "name": "seed rows present",
- "passed": true,
- "notes": "found 2/2 seeded rows"
- },
- {
- "name": "rejects request with no credentials",
- "passed": true,
- "notes": "status 401: {\"error\":\"Missing or invalid apikey\"}"
- },
- {
- "name": "user with JWT reads only their own rows",
- "passed": false,
- "notes": "status 401: {\"error\":\"Missing or invalid apikey\"}"
- },
- {
- "name": "user cannot read another user's rows by passing user_id",
- "passed": false,
- "notes": "status 401: {\"error\":\"Missing or invalid apikey\"}"
- },
- {
- "name": "service key bypasses RLS to read the target user's rows",
- "passed": false,
- "notes": "status 401: {\"error\":\"Missing or invalid apikey\"}"
- },
- {
- "name": "non-service key is not granted service access",
- "passed": true,
- "notes": "status 401: {\"error\":\"Missing or invalid apikey\"}"
- },
- {
- "name": "rejects an unverified (forged) user token",
- "passed": true,
- "notes": "status 401: {\"error\":\"Missing or invalid apikey\"}"
- },
- {
- "name": "a user token in the apikey slot is not treated as the service key",
- "passed": true,
- "notes": "status 401: {\"error\":\"Missing or invalid apikey\"}"
- },
- {
- "name": "implementation uses @supabase/server",
- "passed": false,
- "notes": "hand-rolled (raw supabase-js or other) — this eval requires @supabase/server"
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
- },
- "docs": {
- "calls": [
- {
- "source": "web_search",
- "query": "site:supabase.com docs supabase functions serve entrypoint failed to determine entrypoint verify_jwt config.toml user-stats",
- "pages": []
- }
- ]
- },
- "prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nOur product stores per-user metrics in the existing `user_stats` table.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.",
- "promptSourcePath": "evals/build-functions-005-dual-auth-user-secret/PROMPT.md",
- "attempts": 2,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/build-functions-005-dual-auth-user-secret.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "build-storage-001-private-bucket-access",
- "stage": "build",
- "product": [
- "storage",
- "database"
- ],
- "topic": [
- "rls",
- "sdk"
- ],
- "suite": "benchmark",
- "interface": "mcp",
- "passed": true,
- "checks": [
- {
- "name": "bucket user-files exists",
- "passed": true
- },
- {
- "name": "bucket user-files is private",
- "passed": true
- },
- {
- "name": "RLS still enabled on storage.objects",
- "passed": true
- },
- {
- "name": "user A lists only own files",
- "passed": true,
- "notes": "saw: 019fb0e7-4308-75bd-a52e-bb64802d730c/receipt-alpha.pdf, 019fb0e7-4308-75bd-a52e-bb64802d730c/receipt-beta.pdf"
- },
- {
- "name": "user B cannot read user A files",
- "passed": true
- },
- {
- "name": "anon reads no files",
- "passed": true
- },
- {
- "name": "user A can upload into own folder",
- "passed": true
- },
- {
- "name": "user B cannot upload into user A folder",
- "passed": true
- },
- {
- "name": "configured private per-user storage access",
- "passed": true,
- "judgeNotes": "Configured a private user-files bucket (public=false), kept storage.objects RLS enabled, added authenticated SELECT and INSERT policies scoped to bucket and owner via first folder segment = auth.uid(), and provided supabase-js createSignedUrl with a 15-minute expiry. No public bucket/getPublicUrl/service-role client misuse."
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"storage bucket RLS policy auth.uid prefix storage.objects signed url\", limit: 5) { nodes { __typename title href content } } }",
+ "query": "query { searchDocs(query: \"Supabase Docker self-hosting compose env example official docs\", limit: 5) { nodes { title href content ... on Guide { subsections { nodes { title href content } } } } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/storage/security/access-control",
- "title": "Storage Access Control"
+ "url": "https://supabase.com/docs/guides/self-hosting",
+ "title": "Self-Hosting"
},
{
- "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
- "title": "Storage Buckets"
+ "url": "https://supabase.com/docs/guides/self-hosting#telemetry",
+ "title": "Telemetry"
},
{
- "url": "https://supabase.com/docs/guides/security/product-security",
- "title": "Secure configuration of Supabase products"
+ "url": "https://supabase.com/docs/guides/self-hosting#support-and-community",
+ "title": "Support and community"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
- "title": "Configure S3 Storage"
+ "url": "https://supabase.com/docs/guides/self-hosting#get-started",
+ "title": "Get started"
},
{
- "url": "https://supabase.com/docs/guides/storage/schema/design",
- "title": "The Storage Schema"
- }
- ],
- "resultChars": 21438
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"supabase-js createSignedUrl storage download temporary link\", limit: 5) { nodes { __typename title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/self-hosting#enterprise-self-hosting",
+ "title": "Enterprise self-hosting"
+ },
{
- "url": "https://supabase.com/docs/guides/storage/serving/downloads",
- "title": "Serving assets from Storage"
+ "url": "https://supabase.com/docs/guides/self-hosting#community-driven-projects",
+ "title": "Community-driven projects"
},
{
- "url": "https://supabase.com/docs/guides/storage/uploads/resumable-uploads",
- "title": "Resumable Uploads"
+ "url": "https://supabase.com/docs/guides/self-hosting#about-self-hosting",
+ "title": "About self-hosting"
},
{
- "url": "https://supabase.com/docs/reference/dart/file-buckets-createsignedurl"
+ "url": "https://supabase.com/docs/guides/self-hosting#how-self-hosted-supabase-differs",
+ "title": "How self-hosted Supabase differs"
},
{
- "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsignedurl"
+ "url": "https://supabase.com/docs/guides/self-hosting#your-responsibilities-when-self-hosting",
+ "title": "Your responsibilities when self-hosting"
},
{
- "url": "https://supabase.com/docs/guides/storage/management/download-objects",
- "title": "Download Objects"
- }
- ],
- "resultChars": 25058
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"storage.buckets policy create bucket RLS\", limit: 5) { nodes { __typename title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
+ },
{
- "url": "https://supabase.com/docs/guides/storage/security/access-control",
- "title": "Storage Access Control"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#backward-compatibility",
+ "title": "Backward compatibility"
},
{
- "url": "https://supabase.com/docs/guides/platform/migrating-within-supabase/backup-restore",
- "title": "Backup and Restore using the CLI"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#differences-from-the-supabase-platform",
+ "title": "Differences from the Supabase platform"
},
{
- "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
- "title": "Storage Buckets"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#environment-variables-configuration",
+ "title": "Environment variables configuration"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-ionic-vue",
- "title": "Build a User Management App with Ionic Vue"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#verifying-the-setup",
+ "title": "Verifying the setup"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-svelte",
- "title": "Build a User Management App with Svelte"
- }
- ],
- "resultChars": 96990
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"storage.createBucket RLS policy required bucket table\", limit: 5) { nodes { __typename title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#new-api-keys-format",
+ "title": "New API keys format"
+ },
{
- "url": "https://supabase.com/docs/guides/storage/security/access-control",
- "title": "Storage Access Control"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#adding-the-new-keys",
+ "title": "Adding the new keys"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
- "title": "Configure S3 Storage"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#before-you-begin",
+ "title": "Before you begin"
},
{
- "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
- "title": "Storage Buckets"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#what-client-sdk-sends",
+ "title": "What client SDK sends"
},
{
- "url": "https://supabase.com/docs/guides/local-development/database-migrations",
- "title": "Database migrations"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#kong-api-gateway-routing",
+ "title": "Kong API gateway routing"
},
{
- "url": "https://supabase.com/docs/guides/storage/schema/design",
- "title": "The Storage Schema"
- }
- ],
- "resultChars": 32878
- }
- ]
- },
- "prompt": "Our app lets signed-in users keep personal files like receipts and bank\nstatements. These files are private — a user must only ever be able to upload\nand download their own. The app uploads each file under a path that starts\nwith the owner's user id, e.g. `/receipt-march.pdf`.\n\nSet up a `user-files` bucket on our project and lock it down that way.\n\nUsers also sometimes share one of their files with someone else through a\ntemporary link that expires. Include the supabase-js code the app should use\nfor that.",
- "promptSourcePath": "evals/build-storage-001-private-bucket-access/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/build-storage-001-private-bucket-access.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "build-tests-001-rls-tenant-isolation",
- "stage": "build",
- "product": [
- "database"
- ],
- "topic": [
- "tests",
- "rls"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "passed": true,
- "checks": [
- {
- "name": "pgTAP test file(s) written under supabase/tests/",
- "passed": true,
- "notes": "1 file(s): supabase/tests/tenant_isolation.sql"
- },
- {
- "name": "pgTAP isolation tests ran and pass",
- "passed": true,
- "notes": "6 passed, 0 failed"
- },
- {
- "name": "agent correctly identifies the posts isolation bug from test results",
- "passed": true,
- "judgeNotes": "The agent correctly identifies `posts` as having the tenant isolation flaw: the policy checks membership but not the row's `org_id`, allowing authenticated members to read posts from other orgs. It does not blame `notes` or dismiss pgTAP; it adds/runs tests and reports passing after fixing the policy."
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
- },
- "docs": {
- "calls": []
- },
- "prompt": "Can you audit the tenant isolation on our tables? Write some database tests covering both the happy path and the negative case, run them, and share the results.",
- "promptSourcePath": "evals/build-tests-001-rls-tenant-isolation/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/build-tests-001-rls-tenant-isolation.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "build-vectors-001-rag-with-permissions",
- "stage": "build",
- "product": [
- "database",
- "vectors"
- ],
- "topic": [
- "sql",
- "rls"
- ],
- "suite": "benchmark",
- "interface": "mcp",
- "passed": true,
- "checks": [
- {
- "name": "document_sections.embedding is vector(384)",
- "passed": true,
- "notes": "vector(384)"
- },
- {
- "name": "HNSW index on the embedding column",
- "passed": true,
- "notes": "CREATE INDEX document_sections_embedding_hnsw_idx ON public.document_sections USING hnsw (embedding vector_cosine_ops) WHERE (embedding IS NOT NULL)"
- },
- {
- "name": "index operator class matches the search operator",
- "passed": true,
- "notes": "function operators: <=>\nindexes: CREATE INDEX document_sections_embedding_hnsw_idx ON public.document_sections USING hnsw (embedding vector_cosine_ops) WHERE (embedding IS NOT NULL)"
- },
- {
- "name": "user A search returns only own sections, best match first",
- "passed": true
- },
- {
- "name": "user B search returns only own sections, best match first",
- "passed": true
- },
- {
- "name": "user A reads only own sections through the API",
- "passed": true
- },
- {
- "name": "user A reads only own documents through the API",
- "passed": true
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
- },
- "docs": {
- "calls": []
- },
- "prompt": "We're adding semantic search to our internal knowledge base app. I already wrote the edge functions, but search doesn't work yet. Can you set up whatever the database needs to make search work end to end?\n\nSome documents are confidential, so users should only have access to documents they own.",
- "promptSourcePath": "evals/build-vectors-001-rag-with-permissions/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/build-vectors-001-rag-with-permissions.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "deploy-database-001-prometheus-metrics",
- "stage": "deploy",
- "product": [
- "database"
- ],
- "topic": [
- "observability"
- ],
- "suite": "benchmark",
- "passed": false,
- "checks": [
- {
- "name": "preserved existing app scrape job",
- "passed": true
- },
- {
- "name": "configured the Supabase Metrics API scrape correctly",
- "passed": false,
- "judgeNotes": "Fails: Supabase scrape uses basic_auth.password instead of password_file, and docker-compose.yml does not mount the password file via a volume or Compose secret. README also instructs hardcoding the Secret API key in prometheus.yml."
- },
- {
- "name": "documented live deployment and verification steps",
- "passed": false,
- "judgeNotes": "README instructs replacing a placeholder directly in prometheus.yml rather than placing a matching secret file, and the Compose setup does not mount/use a secret file. It also only says restart Prometheus or reload, not restart/reload the Compose stack. Verification is present but secret setup does not meet the rubric."
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
- },
- "docs": {
- "calls": [
- {
- "source": "web_search",
- "query": "site:supabase.com/docs Supabase Prometheus metrics endpoint observability",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs/guides/telemetry/metrics/grafana-self-hosted Supabase Metrics API self-hosted Prometheus Grafana official",
- "pages": []
- }
- ]
- },
- "prompt": "Can you wire my Supabase project metrics into our existing observability stack and document\nin the observability README what we need to do to make the config live?",
- "promptSourcePath": "evals/deploy-database-001-prometheus-metrics/PROMPT.md",
- "attempts": 2,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/deploy-database-001-prometheus-metrics.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "deploy-functions-001-edge-function-secrets",
- "stage": "deploy",
- "product": [
- "edge-functions"
- ],
- "topic": [
- "security"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "passed": true,
- "checks": [
- {
- "name": "WEATHER_API_KEY is set as a Function secret on the project",
- "passed": true
- },
- {
- "name": "the weather function is deployed to the project",
- "passed": true,
- "notes": "status ACTIVE"
- },
- {
- "name": "the weather function reads WEATHER_API_KEY from the environment",
- "passed": true,
- "judgeNotes": "The function reads WEATHER_API_KEY from the runtime environment using Deno.env.get(\"WEATHER_API_KEY\")."
- },
- {
- "name": "WEATHER_API_KEY value is not committed to the repo",
- "passed": true
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
- },
- "docs": {
- "calls": [
- {
- "source": "web_search",
- "query": "site:supabase.com/docs Supabase Edge Functions Project not specified functions.supabase.co",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "https://supabase.com/docs/guides/functions/deploy",
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/functions/deploy"
- }
- ]
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs management api invoke edge function supabase",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "\"Project not specified\" supabase function",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs \"Edge Function\" invoke management API",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs \"functions/v1\" \"project not specified\"",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs \"functions.supabase.co\" \"apikey\" \"project\"",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "'functions.supabase.co'",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs/reference/api/v1 functions invoke edge function",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs/reference/api v1 projects functions logs supabase",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs/reference/api publishable keys project api keys supabase management api",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "https://supabase.com/docs/reference/api/introduction",
- "pages": [
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#request-flows",
+ "title": "Request flows"
+ },
{
- "url": "https://supabase.com/docs/reference/api/introduction"
- }
- ]
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs \"publishable key\" \"Management API\" Supabase project",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs/reference/api \"publishable key\" \"projects/{ref}\" supabase",
- "pages": []
- }
- ]
- },
- "prompt": "Our weather widget currently calls WeatherAPI straight from the browser, which\nleaks our API key. I want to move that behind a Supabase Edge Function called\n`weather` that holds the key server-side and proxies the request.\n\nThe function should read the key from an environment variable named\n`WEATHER_API_KEY`. Our key already lives in a local `.env` file at the project\nroot.\n\nDeploy the function to our project so it's live, and make sure the deployed\nfunction can actually read the key at runtime.",
- "promptSourcePath": "evals/deploy-functions-001-edge-function-secrets/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/deploy-functions-001-edge-function-secrets.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "deploy-self-hosting-001-docker-compose",
- "stage": "deploy",
- "product": [
- "database",
- "auth",
- "storage"
- ],
- "topic": [
- "self-hosting"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "passed": true,
- "checks": [
- {
- "name": "cloned the self-host stack (docker-compose.yml + volumes/db)",
- "passed": true
- },
- {
- "name": "didn't conflate with the CLI (no supabase/config.toml in the stack)",
- "passed": true
- },
- {
- "name": "secrets rotated off the shipped defaults",
- "passed": true
- },
- {
- "name": "ANON_KEY and SERVICE_ROLE_KEY are HS256 JWTs signed by JWT_SECRET",
- "passed": true
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase self-host Docker compose environment variables anon key service_role JWT secrets\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#unauthenticated-requests-api-key-only-no-user-session-jwt",
+ "title": "Unauthenticated requests (API key only, no user session JWT)"
+ },
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#authenticated-requests-user-session-jwt",
+ "title": "Authenticated requests (user session JWT)"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#additional-resources",
+ "title": "Additional resources"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
- "title": "Envoy API Gateway"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#how-it-works",
+ "title": "How it works"
},
{
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#regenerating-asymmetric-key-pair",
+ "title": "Regenerating asymmetric key pair"
},
{
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
- }
- ],
- "resultChars": 88894
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"Self-hosting with Docker quick start Linux generate-keys.sh docker-compose.yml .env.example\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
- },
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#rotating-the-new-api-keys",
+ "title": "Rotating the new API keys"
+ },
{
"url": "https://supabase.com/docs/guides/self-hosting/docker",
"title": "Self-Hosting with Docker"
},
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#exposing-your-postgres-database",
+ "title": "Exposing your Postgres database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#changing-database-password",
+ "title": "Changing database password"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-secrets",
+ "title": "Configuring secrets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-supabase-services",
+ "title": "Configuring Supabase services"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-social-login-oauth-providers",
+ "title": "Configuring social login (OAuth) providers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-phone-login-sms-and-mfa",
+ "title": "Configuring phone login, SMS, and MFA"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-an-email-server",
+ "title": "Configuring an email server"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-s3-storage",
+ "title": "Configuring S3 Storage"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#using-file-backend-in-storage-on-macos",
+ "title": "Using file backend in Storage on macOS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-supabase-ai-assistant",
+ "title": "Configuring Supabase AI Assistant"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-postgres-through-supavisor",
+ "title": "Accessing Postgres through Supavisor"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#setting-log_min_messages-in-postgres",
+ "title": "Setting log_min_messages in Postgres"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#managing-your-secrets",
+ "title": "Managing your secrets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#demo",
+ "title": "Demo"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#contents",
+ "title": "Contents"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#before-you-begin",
+ "title": "Before you begin"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#system-requirements",
+ "title": "System requirements"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#installing-supabase",
+ "title": "Installing Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#quick-start-linux",
+ "title": "Quick start (Linux)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#manual-installation",
+ "title": "Manual installation"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-and-securing-supabase",
+ "title": "Configuring and securing Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#generate-keys-and-secrets",
+ "title": "Generate keys and secrets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configure-supabase-urls",
+ "title": "Configure Supabase URLs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#where-to-find-your-credentials",
+ "title": "Where to find your credentials"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#studio-authentication",
+ "title": "Studio authentication"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#starting-and-stopping",
+ "title": "Starting and stopping"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-supabase-studio-dashboard",
+ "title": "Accessing Supabase Studio (Dashboard)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-postgres",
+ "title": "Accessing Postgres"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-edge-functions",
+ "title": "Accessing Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-apis",
+ "title": "Accessing APIs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#enabling-analytics",
+ "title": "Enabling analytics"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-https",
+ "title": "Configuring HTTPS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#managing-the-stack",
+ "title": "Managing the stack"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#updating",
+ "title": "Updating"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#uninstalling",
+ "title": "Uninstalling"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#advanced-topics",
+ "title": "Advanced topics"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#architecture",
+ "title": "Architecture"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#setting-database-password",
+ "title": "Setting database password"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
+ "title": "Restore a Platform Project to Self-Hosted"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#auth-considerations",
+ "title": "Auth considerations"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#postgres-version-compatibility",
+ "title": "Postgres version compatibility"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#extension-not-available",
+ "title": "Extension not available"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#troubleshooting",
+ "title": "Troubleshooting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#before-you-begin",
+ "title": "Before you begin"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#step-1-get-your-platform-connection-string",
+ "title": "Step 1: Get your platform connection string"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#step-2-back-up-your-platform-database",
+ "title": "Step 2: Back up your platform database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#step-3-prepare-your-self-hosted-instance",
+ "title": "Step 3: Prepare your self-hosted instance"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#step-4-restore-to-your-self-hosted-database",
+ "title": "Step 4: Restore to your self-hosted database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#step-5-verify-the-restore",
+ "title": "Step 5: Verify the restore"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#whats-included-in-the-restore-and-whats-not",
+ "title": "What's included in the restore and what's not"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#version-mismatches-between-platform-and-self-hosted",
+ "title": "Version mismatches between platform and self-hosted"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#connection-refused",
+ "title": "Connection refused"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#legacy-studio-configuration",
+ "title": "Legacy Studio configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#custom-roles-missing-passwords",
+ "title": "Custom roles missing passwords"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#additional-resources",
+ "title": "Additional resources"
+ },
{
"url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth",
"title": "Configure Social Login (OAuth) Providers"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates",
- "title": "Custom Email Templates"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-2-configure-environment-variables",
+ "title": "Step 2: Configure environment variables"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
- "title": "Envoy API Gateway"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#before-you-begin",
+ "title": "Before you begin"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#oauth-request-flow",
+ "title": "OAuth request flow"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#auth-environment-variables",
+ "title": "Auth environment variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-by-step-configuration",
+ "title": "Step-by-step configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-1-register-your-app-with-the-provider",
+ "title": "Step 1: Register your app with the provider"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-3-enable-the-matching-lines-in-docker-compose-configuration",
+ "title": "Step 3: Enable the matching lines in Docker Compose configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-4-restart-the-auth-service",
+ "title": "Step 4: Restart the auth service"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-5-verify-the-configuration",
+ "title": "Step 5: Verify the configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#provider-specific-setup",
+ "title": "Provider-specific setup"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#other-supported-providers",
+ "title": "Other supported providers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#variables-added-to-the-environment-but-provider-still-not-working",
+ "title": "Variables added to the environment but provider still not working"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#site-url-or-redirect-url-errors-after-login",
+ "title": "Site URL or redirect URL errors after login"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#nonce-check-failure-on-mobile-google-sign-in",
+ "title": "Nonce check failure on mobile (Google Sign In)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#test-the-login-flow",
+ "title": "Test the login flow"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#troubleshooting",
+ "title": "Troubleshooting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#auth-service-fails-to-start",
+ "title": "Auth service fails to start"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#environment-variable-reference",
+ "title": "Environment variable reference"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#additional-resources",
+ "title": "Additional resources"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#provider-not-enabled-or-provider-seen-as-false-in-settings"
}
],
- "resultChars": 103382
- }
- ]
- },
- "prompt": "I'm moving off the hosted Supabase and running the whole thing myself on a VPS I\njust spun up. Can you get a Docker setup ready for me to copy onto the box?\n\nI don't need it running here, I'll do the actual bring-up once I'm on the\nserver. I just want everything in place and the secrets set up. Put it in a `supabase-docker/`\nfolder at the repo root so I can scp the whole thing across in one go.",
- "promptSourcePath": "evals/deploy-self-hosting-001-docker-compose/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/deploy-self-hosting-001-docker-compose.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "investigate-auth-001-deleted-user-access",
- "stage": "investigate",
- "product": [
- "auth"
- ],
- "topic": [
- "security",
- "sdk"
- ],
- "suite": "benchmark",
- "interface": "mcp",
- "passed": false,
- "checks": [
- {
- "name": "victim session active before delete-account",
- "passed": true
- },
- {
- "name": "delete_account flow ran for the victim",
- "passed": true
- },
- {
- "name": "delete-account revokes the user's sessions",
- "passed": true,
- "notes": "sessions left: 0"
- },
- {
- "name": "deleted user's refresh token is rejected",
- "passed": true
- },
- {
- "name": "deleted user cannot sign back in",
- "passed": false,
- "notes": "deleted account can still sign in"
- },
- {
- "name": "other users keep their sessions and access",
- "passed": true
- },
- {
- "name": "diagnosed and explained session revocation",
- "passed": false,
- "judgeNotes": "The answer correctly diagnoses the soft-delete-only bug, revokes auth sessions by deleting auth.sessions (cascading refresh tokens), adds RLS checks against deleted profiles, and correctly distinguishes publishable vs secret keys. However, it says 'deleting a user does not automatically sign them out' even though its implemented fix does not delete the auth user, only sessions, and the rubric requires fixing the flow so the auth user is deleted or equivalently identity and sessions are removed. The implemented fix leaves identities/auth user intact, so future sign-in may still be possible; it does not fully satisfy real account deletion/removal of identity. It also overstates 'no database-access window' based on a deleted profile RLS check, which is acceptable for the shown data path, but the missing identity/user deletion is a failing issue."
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
- },
- "docs": {
- "calls": [
- {
- "source": "web_search",
- "query": "site:supabase.com/docs publishable key secret key anon service_role RLS Supabase",
- "pages": []
+ "resultChars": 307956
},
{
- "source": "web_search",
- "query": "site:supabase.com/docs migrating to new API keys publishable secret keys Supabase docs",
- "pages": []
- }
- ]
- },
- "prompt": "Last week support removed a user through our app's delete-account flow — the\napp calls the `delete_account` function over RPC as the signed-in user. This\nmorning that same person was back: still signed in, reading and saving their\ndata like nothing happened.\n\nFigure out why the account still works, fix the flow so a deleted account\nloses access, and tell me whether there is any window where they could still\nget in after the fix.\n\nOne more thing while you're at it: we're migrating off the legacy\nanon/service_role API keys to the new publishable and secret keys, and the\nteam isn't sure which one belongs in the frontend and what each means for\nRLS. Give us a quick rundown.",
- "promptSourcePath": "evals/investigate-auth-001-deleted-user-access/PROMPT.md",
- "attempts": 2,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/investigate-auth-001-deleted-user-access.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "investigate-realtime-001-subscribed-no-events",
- "stage": "investigate",
- "product": [
- "realtime",
- "database"
- ],
- "topic": [
- "sdk"
- ],
- "suite": "benchmark",
- "interface": "mcp",
- "passed": true,
- "checks": [
- {
- "name": "orders table added to supabase_realtime publication",
- "passed": true
- },
- {
- "name": "courier_locations still in supabase_realtime publication",
- "passed": true
- },
- {
- "name": "publication still publishes INSERT events",
- "passed": true
- },
- {
- "name": "RLS still enabled on orders",
- "passed": true
- },
- {
- "name": "staff can still read orders through RLS",
- "passed": true,
- "notes": "authenticated sees 2 of 2 orders"
- },
- {
- "name": "diagnosed missing publication membership",
- "passed": true,
- "judgeNotes": "Identified orders missing from supabase_realtime publication, added only public.orders with ALTER PUBLICATION, verified courier_locations remained, and did not weaken RLS/policies or blame client/RLS as root cause."
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"self-hosting docker compose Supabase official\", limit: 5) { nodes { title href content ... on Guide { subsections { nodes { title href content } } } } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting",
+ "title": "Self-Hosting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting#telemetry",
+ "title": "Telemetry"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting#support-and-community",
+ "title": "Support and community"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting#get-started",
+ "title": "Get started"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting#enterprise-self-hosting",
+ "title": "Enterprise self-hosting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting#community-driven-projects",
+ "title": "Community-driven projects"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting#about-self-hosting",
+ "title": "About self-hosting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting#how-self-hosted-supabase-differs",
+ "title": "How self-hosted Supabase differs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting#your-responsibilities-when-self-hosting",
+ "title": "Your responsibilities when self-hosting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker",
+ "title": "Self-Hosting with Docker"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#exposing-your-postgres-database",
+ "title": "Exposing your Postgres database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#advanced-topics",
+ "title": "Advanced topics"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#architecture",
+ "title": "Architecture"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#setting-database-password",
+ "title": "Setting database password"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#changing-database-password",
+ "title": "Changing database password"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-secrets",
+ "title": "Configuring secrets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-supabase-services",
+ "title": "Configuring Supabase services"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-social-login-oauth-providers",
+ "title": "Configuring social login (OAuth) providers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-phone-login-sms-and-mfa",
+ "title": "Configuring phone login, SMS, and MFA"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-an-email-server",
+ "title": "Configuring an email server"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-s3-storage",
+ "title": "Configuring S3 Storage"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#using-file-backend-in-storage-on-macos",
+ "title": "Using file backend in Storage on macOS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-supabase-ai-assistant",
+ "title": "Configuring Supabase AI Assistant"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-postgres-through-supavisor",
+ "title": "Accessing Postgres through Supavisor"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#setting-log_min_messages-in-postgres",
+ "title": "Setting log_min_messages in Postgres"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#managing-your-secrets",
+ "title": "Managing your secrets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#demo",
+ "title": "Demo"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#contents",
+ "title": "Contents"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#before-you-begin",
+ "title": "Before you begin"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#system-requirements",
+ "title": "System requirements"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#installing-supabase",
+ "title": "Installing Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#quick-start-linux",
+ "title": "Quick start (Linux)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#manual-installation",
+ "title": "Manual installation"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-and-securing-supabase",
+ "title": "Configuring and securing Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#generate-keys-and-secrets",
+ "title": "Generate keys and secrets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configure-supabase-urls",
+ "title": "Configure Supabase URLs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#where-to-find-your-credentials",
+ "title": "Where to find your credentials"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#studio-authentication",
+ "title": "Studio authentication"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#starting-and-stopping",
+ "title": "Starting and stopping"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-supabase-studio-dashboard",
+ "title": "Accessing Supabase Studio (Dashboard)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-postgres",
+ "title": "Accessing Postgres"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-edge-functions",
+ "title": "Accessing Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-apis",
+ "title": "Accessing APIs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#enabling-analytics",
+ "title": "Enabling analytics"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-https",
+ "title": "Configuring HTTPS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#managing-the-stack",
+ "title": "Managing the stack"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#updating",
+ "title": "Updating"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#uninstalling",
+ "title": "Uninstalling"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/remove-superuser-access",
+ "title": "Remove superuser access from Studio"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/remove-superuser-access#verify-roles",
+ "title": "Verify roles"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/remove-superuser-access#step-3-restart-supabase",
+ "title": "Step 3: Restart Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/remove-superuser-access#step-2-update-environment-variables-in-docker-composeyml",
+ "title": "Step 2: Update environment variables in docker-compose.yml"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/remove-superuser-access#step-1-update-database-object-ownership",
+ "title": "Step 1: Update database object ownership"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/remove-superuser-access#changing-the-configuration",
+ "title": "Changing the configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/remove-superuser-access#overview",
+ "title": "Overview"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
+ "title": "Restore a Platform Project to Self-Hosted"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#step-5-verify-the-restore",
+ "title": "Step 5: Verify the restore"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#whats-included-in-the-restore-and-whats-not",
+ "title": "What's included in the restore and what's not"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#auth-considerations",
+ "title": "Auth considerations"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#postgres-version-compatibility",
+ "title": "Postgres version compatibility"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#troubleshooting",
+ "title": "Troubleshooting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#version-mismatches-between-platform-and-self-hosted",
+ "title": "Version mismatches between platform and self-hosted"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#extension-not-available",
+ "title": "Extension not available"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#connection-refused",
+ "title": "Connection refused"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#legacy-studio-configuration",
+ "title": "Legacy Studio configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#custom-roles-missing-passwords",
+ "title": "Custom roles missing passwords"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#additional-resources",
+ "title": "Additional resources"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#before-you-begin",
+ "title": "Before you begin"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#step-1-get-your-platform-connection-string",
+ "title": "Step 1: Get your platform connection string"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#step-2-back-up-your-platform-database",
+ "title": "Step 2: Back up your platform database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#step-4-restore-to-your-self-hosted-database",
+ "title": "Step 4: Restore to your self-hosted database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#step-3-prepare-your-self-hosted-instance",
+ "title": "Step 3: Prepare your self-hosted instance"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli/getting-started",
+ "title": "Supabase CLI"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli/getting-started#learn-more",
+ "title": "Learn more"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli/getting-started#how-to-opt-out",
+ "title": "How to opt out"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli/getting-started#telemetry",
+ "title": "Telemetry"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli/getting-started#stopping-local-services",
+ "title": "Stopping local services"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli/getting-started#access-your-projects-services",
+ "title": "Access your project's services"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli/getting-started#running-supabase-locally",
+ "title": "Running Supabase locally"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli/getting-started#updating-the-supabase-cli",
+ "title": "Updating the Supabase CLI"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli/getting-started#beta-channel",
+ "title": "Beta channel"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli/getting-started#installing-the-supabase-cli",
+ "title": "Installing the Supabase CLI"
+ }
+ ],
+ "resultChars": 264252
+ }
+ ]
},
- "docs": {
- "calls": []
+ "usage": {
+ "inputTokens": 1407185,
+ "outputTokens": 13866,
+ "cachedInputTokens": 1342208
},
- "prompt": "Our dispatch dashboard shows incoming orders as they happen. The courier\nlocation feed on the same page updates live without problems, but new orders\nonly show up after a page refresh.\n\nThe dashboard uses supabase-js to subscribe to INSERT events on the `orders`\ntable through postgres_changes, the same way it subscribes to courier\nlocations. The channel's status callback logs SUBSCRIBED and there are no\nerrors in the browser console.\n\nFigure out why no order events ever arrive and fix it.",
- "promptSourcePath": "evals/investigate-realtime-001-subscribed-no-events/PROMPT.md",
+ "durationMs": 343107,
+ "prompt": "I'm moving off the hosted Supabase and running the whole thing myself on a VPS I\njust spun up. Can you get a Docker setup ready for me to copy onto the box?\n\nI don't need it running here, I'll do the actual bring-up once I'm on the\nserver. I just want everything in place and the secrets set up. Put it in a `supabase-docker/`\nfolder at the repo root so I can scp the whole thing across in one go.",
+ "promptSourcePath": "evals/deploy-self-hosting-001-docker-compose/PROMPT.md",
"attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/investigate-realtime-001-subscribed-no-events.json"
+ "sourcePath": "codex-gpt-5.4-mini/deploy-self-hosting-001-docker-compose.json"
},
{
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
+ "experiment": "codex-gpt-5.4-mini",
+ "experimentSuite": "benchmark",
"experimentDisplay": {
"agent": "codex",
"modelProvider": "openai",
"modelId": "gpt-5.4-mini",
"reasoningEffort": "medium"
},
- "eval": "investigate-reliability-003-edge-function-5xx-correlation",
+ "eval": "investigate-auth-001-deleted-user-access",
"stage": "investigate",
"product": [
- "edge-functions"
+ "auth"
],
"topic": [
- "observability"
+ "security",
+ "sdk"
],
"suite": "benchmark",
"interface": "mcp",
- "passed": true,
+ "passed": false,
"checks": [
{
- "name": "identified image-transform and the recurring 503 pattern",
- "passed": true,
- "judgeNotes": "Identified image-transform as the affected function and described recurring HTTP 503 gateway failures throughout the morning of 2026-04-28, covering the relevant 07:00Z-12:00Z window and most/all failures."
+ "name": "victim session active before delete-account",
+ "passed": true
},
{
- "name": "attributed recurring 503s to gateway/platform layer, not function code",
- "passed": true,
- "judgeNotes": "Attributes image-transform 503s to gateway/platform layer, supported by unchanged deployment/version with intermittent successes and distinction from avatar-upload's function-level 500."
+ "name": "delete_account flow ran for the victim",
+ "passed": true
},
{
- "name": "recommended a concrete next step",
+ "name": "delete-account revokes the user's sessions",
"passed": true,
- "judgeNotes": "The assistant recommended concrete next steps: checking Supabase platform/edge runtime incident health, correlating failing requests with payloads/request IDs, adding retries for 503s, and opening a Supabase support case with timestamps, function slugs, deployment IDs, and failing request IDs."
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
- },
- "docs": {
- "calls": []
- },
- "prompt": "Users have been reporting that image uploads are intermittently failing with server errors throughout the morning of `2026-04-28`.\n\nCan you investigate the project logs and tell me what is going on and what we\nshould do next?",
- "promptSourcePath": "evals/investigate-reliability-003-edge-function-5xx-correlation/PROMPT.md",
+ "notes": "sessions left: 0"
+ },
+ {
+ "name": "deleted user's refresh token is rejected",
+ "passed": true
+ },
+ {
+ "name": "deleted user cannot sign back in",
+ "passed": true
+ },
+ {
+ "name": "other users keep their sessions and access",
+ "passed": true
+ },
+ {
+ "name": "diagnosed and explained session revocation",
+ "passed": false,
+ "judgeNotes": "Mostly correct diagnosis, real revocation/data-path fix, and key clarification. However it does not clearly state that the JWT itself remains valid until expiry for purely local validation (e.g. getClaims/custom signature+expiry middleware), and its wording could imply session revocation makes the access token itself invalid. Rubric requires that caveat even when RLS closes the Data API path."
+ }
+ ],
+ "skills": {
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query {\n searchDocs(query: \"delete user revoke sessions auth admin supabase delete account\", limit: 5) {\n nodes { title href content }\n }\n}",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/auth/passkeys",
+ "title": "Passkey authentication"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/managing-user-data",
+ "title": "User Management"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/sso",
+ "title": "Enable SSO for Your Organization"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/sessions",
+ "title": "User sessions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/custom-oauth-providers",
+ "title": "Custom OAuth/OIDC Providers"
+ }
+ ],
+ "resultChars": 53447
+ },
+ {
+ "source": "search_docs",
+ "query": "query {\n searchDocs(query: \"publishable secret key anon service_role frontend RLS\", limit: 10) {\n nodes { title href content }\n }\n}",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/database/secure-data",
+ "title": "Securing your data"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/jwt-fields",
+ "title": "JWT Claims Reference"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs",
+ "title": "Build a User Management App with RedwoodJS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/signing-keys",
+ "title": "JWT Signing Keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys",
+ "title": "Understanding API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
+ "title": "Storage Buckets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/storage/security/access-control",
+ "title": "Storage Access Control"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/auth-anonymous",
+ "title": "Anonymous Sign-Ins"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
+ }
+ ],
+ "resultChars": 152691
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"delete user revoke sessions admin api delete account auth.admin.listUsers deleteUser signOut revoke refresh tokens\", limit: 10) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/auth/managing-user-data",
+ "title": "User Management"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/javascript/auth-admin-deleteuser"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/javascript/auth-signout"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers",
+ "title": "Multiple SSO Providers"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/swift/auth-admin-deleteuser",
+ "title": "deleteUser()"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/passkeys",
+ "title": "Passkey authentication"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows",
+ "title": "OAuth 2.1 Flows"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/dart/auth-admin-deleteuser"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/api/v1-revoke-token",
+ "title": "[Beta] Revoke oauth app authorization and it's corresponding tokens"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/javascript/auth-admin-signout"
+ }
+ ],
+ "resultChars": 77440
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 712339,
+ "outputTokens": 12941,
+ "cachedInputTokens": 641920
+ },
+ "durationMs": 122131,
+ "prompt": "Last week support removed a user through our app's delete-account flow — the\napp calls the `delete_account` function over RPC as the signed-in user. This\nmorning that same person was back: still signed in, reading and saving their\ndata like nothing happened.\n\nFigure out why the account still works, fix the flow so a deleted account\nloses access, and tell me whether there is any window where they could still\nget in after the fix.\n\nOne more thing while you're at it: we're migrating off the legacy\nanon/service_role API keys to the new publishable and secret keys, and the\nteam isn't sure which one belongs in the frontend and what each means for\nRLS. Give us a quick rundown.",
+ "promptSourcePath": "evals/investigate-auth-001-deleted-user-access/PROMPT.md",
"attempts": 2,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/investigate-reliability-003-edge-function-5xx-correlation.json"
+ "sourcePath": "codex-gpt-5.4-mini/investigate-auth-001-deleted-user-access.json"
},
{
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
+ "experiment": "codex-gpt-5.4-mini",
+ "experimentSuite": "benchmark",
"experimentDisplay": {
"agent": "codex",
"modelProvider": "openai",
"modelId": "gpt-5.4-mini",
"reasoningEffort": "medium"
},
- "eval": "resolve-dataapi-001-empty-results",
- "stage": "resolve",
+ "eval": "investigate-realtime-001-subscribed-no-events",
+ "stage": "investigate",
"product": [
- "data-api",
- "database",
- "auth"
+ "realtime",
+ "database"
],
"topic": [
- "rls",
"sdk"
],
"suite": "benchmark",
@@ -10727,290 +10767,297 @@
"passed": true,
"checks": [
{
- "name": "RLS still enabled on bookmarks",
- "passed": true
- },
- {
- "name": "user A reads own bookmarks",
+ "name": "orders table added to supabase_realtime publication",
"passed": true
},
{
- "name": "user B cannot read user A bookmarks",
+ "name": "courier_locations still in supabase_realtime publication",
"passed": true
},
{
- "name": "anon reads no bookmarks",
+ "name": "publication still publishes INSERT events",
"passed": true
},
{
- "name": "user A can save a new bookmark",
+ "name": "RLS still enabled on orders",
"passed": true
},
{
- "name": "user B cannot insert a bookmark as user A",
- "passed": true
+ "name": "staff can still read orders through RLS",
+ "passed": true,
+ "notes": "authenticated sees 2 of 2 orders"
},
{
- "name": "diagnosed RLS and added owner-scoped policies",
+ "name": "diagnosed missing publication membership",
"passed": true,
- "judgeNotes": "Diagnosed RLS enabled with no policies as deny-all, kept RLS enabled, and created authenticated owner-scoped SELECT and INSERT policies using user_id = auth.uid() with WITH CHECK for INSERT. Extra UPDATE/DELETE owner policies do not violate the rubric."
+ "judgeNotes": "The assistant correctly diagnosed that orders INSERT events were silent because public.orders was missing from the supabase_realtime publication despite the channel subscribing. It fixed exactly that with ALTER PUBLICATION supabase_realtime ADD TABLE public.orders, verified courier_locations remained in the publication, and did not alter RLS/policies or blame client code/networking."
}
],
"skills": {
- "available": [],
- "loaded": []
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
},
"docs": {
- "calls": []
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Supabase Realtime postgres_changes INSERT table not receiving events replica identity publication\", limit: 5) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/realtime/postgres-changes",
+ "title": "Postgres Changes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/realtime/subscribing-to-database-changes",
+ "title": "Subscribing to Database Changes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/replication/pipelines-faq",
+ "title": "Pipelines FAQ"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/realtime/benchmarks",
+ "title": "Benchmarks"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/replication/pipelines",
+ "title": "Set up Pipelines"
+ }
+ ],
+ "resultChars": 102930
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"postgres_changes realtime insert events table publication replica identity orders\", limit: 5) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/realtime/postgres-changes",
+ "title": "Postgres Changes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/replication/bigquery",
+ "title": "BigQuery destination"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/replication/pipelines-faq",
+ "title": "Pipelines FAQ"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres",
+ "title": "Migrate from Postgres to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/replication/pipelines",
+ "title": "Set up Pipelines"
+ }
+ ],
+ "resultChars": 116451
+ }
+ ]
},
- "prompt": "Our app lets signed-in users save bookmarks and view them on their dashboard. Bookmarks are stored in the `bookmarks` table and are private — a user must only ever see their own. \nUsers also need to be able to save new bookmarks from the app.\n\nI can see the rows when I query the table directly, but the dashboard shows an empty list for every user.\n\nFind out why the Data API returns nothing and fix it.",
- "promptSourcePath": "evals/resolve-dataapi-001-empty-results/PROMPT.md",
+ "usage": {
+ "inputTokens": 356526,
+ "outputTokens": 4252,
+ "cachedInputTokens": 313984
+ },
+ "durationMs": 62898,
+ "prompt": "Our dispatch dashboard shows incoming orders as they happen. The courier\nlocation feed on the same page updates live without problems, but new orders\nonly show up after a page refresh.\n\nThe dashboard uses supabase-js to subscribe to INSERT events on the `orders`\ntable through postgres_changes, the same way it subscribes to courier\nlocations. The channel's status callback logs SUBSCRIBED and there are no\nerrors in the browser console.\n\nFigure out why no order events ever arrive and fix it.",
+ "promptSourcePath": "evals/investigate-realtime-001-subscribed-no-events/PROMPT.md",
"attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/resolve-dataapi-001-empty-results.json"
+ "sourcePath": "codex-gpt-5.4-mini/investigate-realtime-001-subscribed-no-events.json"
},
{
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
+ "experiment": "codex-gpt-5.4-mini",
+ "experimentSuite": "benchmark",
"experimentDisplay": {
"agent": "codex",
"modelProvider": "openai",
"modelId": "gpt-5.4-mini",
"reasoningEffort": "medium"
},
- "eval": "resolve-database-001-migration-history-mismatch",
- "stage": "resolve",
+ "eval": "investigate-reliability-003-edge-function-5xx-correlation",
+ "stage": "investigate",
"product": [
- "database"
+ "edge-functions"
],
"topic": [
- "migrations"
+ "observability"
],
"suite": "benchmark",
- "interface": "cli",
+ "interface": "mcp",
"passed": false,
"checks": [
{
- "name": "the avatar_url column is applied on the hosted profiles table",
- "passed": true
- },
- {
- "name": "migration 20240220000000 is recorded in the remote history",
- "passed": false,
- "notes": "remote history versions: [\"20240101000000\",\"20240115000000\"]"
- },
- {
- "name": "remote migration history matches local migration files",
- "passed": false,
- "notes": "remote-only versions still unreconciled: [\"20240115000000\"] (remote: [\"20240101000000\",\"20240115000000\"], local: [\"20240101000000\",\"20240220000000\"])"
- },
- {
- "name": "local migrations are a valid reconciled sequence",
- "passed": false,
- "notes": "expected 20240101000000_create_profiles → → 20240220000000_add_avatar_url, strictly ascending; got [20240101000000_create_profiles.sql, 20240220000000_add_avatar_url.sql]"
- },
- {
- "name": "production profile data is intact (not reset)",
- "passed": true
+ "name": "identified image-transform and the recurring 503 pattern",
+ "passed": true,
+ "judgeNotes": "The assistant correctly identified image-transform as the affected function and described repeated/intermittent 503 gateway responses throughout the morning of 2026-04-28, with successful 200s in between. It did not incorrectly center the issue on billing-webhook."
},
{
- "name": "the avatar migration and history reconciliation were done via the Supabase CLI",
+ "name": "attributed recurring 503s to gateway/platform layer, not function code",
"passed": false,
- "judgeNotes": "No successful `supabase db push` occurred; all push/list attempts failed with IPv6/DNS errors. The avatar_url change was applied via a non-CLI Management API call to `/v1/projects/{ref}/database/migrations` in command #58, not via `supabase db push`. No CLI reconciliation command such as `supabase migration repair` or `supabase db pull` succeeded."
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
- },
- "docs": {
- "calls": []
- },
- "prompt": "I'm trying to ship a migration to our hosted project and it's not working. Can you figure out what's wrong and get it deployed?",
- "promptSourcePath": "evals/resolve-database-001-migration-history-mismatch/PROMPT.md",
- "attempts": 2,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/resolve-database-001-migration-history-mismatch.json"
- },
- {
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.4-mini",
- "reasoningEffort": "medium"
- },
- "eval": "resolve-performance-001-slow-query-cpu-spike",
- "stage": "resolve",
- "product": [
- "database"
- ],
- "topic": [
- "observability",
- "sql"
- ],
- "suite": "benchmark",
- "interface": "mcp",
- "passed": true,
- "checks": [
- {
- "name": "inspected pg_stat_statements for query performance",
- "passed": true
- },
- {
- "name": "ran EXPLAIN on the expensive query",
- "passed": true
- },
- {
- "name": "created index covering user_id and created_at",
- "passed": true
+ "judgeNotes": "The response notes gateway 503s and unchanged deployment/version, but it explicitly says it cannot prove whether the fault is inside the packages or the Supabase runtime/gateway and recommends rollback/redeploy/checking function package behavior. It does not clearly attribute the recurring 503s to the gateway/platform layer as required."
},
{
- "name": "query plan uses an index and avoids sequential scan",
+ "name": "recommended a concrete next step",
"passed": true,
- "notes": "Limit (cost=55.55..55.61 rows=25 width=88)\n -> Sort (cost=55.55..55.61 rows=25 width=88)\n Sort Key: created_at DESC\n -> Bitmap Heap Scan on events (cost=4.48..54.97 rows=25 width=88)\n Recheck Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)\n -> Bitmap Index Scan on events_user_id_created_at_desc_idx (cost=0.00..4.47 rows=25 width=0)\n Index Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)"
- },
- {
- "name": "inserts still work",
- "passed": true
+ "judgeNotes": "The assistant recommended concrete next steps, including checking dependencies, rolling back/redeploying, adding explicit logging, and opening a Supabase support case with timestamps and the 503/200 pattern."
}
],
"skills": {
- "available": [],
- "loaded": []
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
},
"docs": {
"calls": []
},
- "prompt": "My database CPU keeps spiking and the app gets slow when loading recent events for a user. Can you figure out what query is causing it and make the database change needed to fix it?\n\nEnd your turn with a short summary of what you changed and why.",
- "promptSourcePath": "evals/resolve-performance-001-slow-query-cpu-spike/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/resolve-performance-001-slow-query-cpu-spike.json"
+ "usage": {
+ "inputTokens": 199892,
+ "outputTokens": 5606,
+ "cachedInputTokens": 182144
+ },
+ "durationMs": 60945,
+ "prompt": "Users have been reporting that image uploads are intermittently failing with server errors throughout the morning of `2026-04-28`.\n\nCan you investigate the project logs and tell me what is going on and what we\nshould do next?",
+ "promptSourcePath": "evals/investigate-reliability-003-edge-function-5xx-correlation/PROMPT.md",
+ "attempts": 2,
+ "sourcePath": "codex-gpt-5.4-mini/investigate-reliability-003-edge-function-5xx-correlation.json"
},
{
- "experiment": "codex-gpt-5.4-mini-no-skills",
- "experimentSuite": "no-skills",
+ "experiment": "codex-gpt-5.4-mini",
+ "experimentSuite": "benchmark",
"experimentDisplay": {
"agent": "codex",
"modelProvider": "openai",
"modelId": "gpt-5.4-mini",
"reasoningEffort": "medium"
},
- "eval": "resolve-security-002-rls-cross-tenant-leak",
+ "eval": "resolve-dataapi-001-empty-results",
"stage": "resolve",
"product": [
+ "data-api",
"database",
"auth"
],
"topic": [
"rls",
- "security"
+ "sdk"
],
"suite": "benchmark",
"interface": "mcp",
"passed": true,
"checks": [
{
- "name": "RLS enabled on notes",
- "passed": true
- },
- {
- "name": "tenant A sees only org A notes",
- "passed": true
- },
- {
- "name": "tenant B cannot read org A notes",
+ "name": "RLS still enabled on bookmarks",
"passed": true
},
{
- "name": "tenant A author can update own note",
+ "name": "user A reads own bookmarks",
"passed": true
},
{
- "name": "tenant B cannot update org A note",
+ "name": "user B cannot read user A bookmarks",
"passed": true
},
{
- "name": "tenant B author can delete own note",
+ "name": "anon reads no bookmarks",
"passed": true
},
{
- "name": "tenant B cannot delete org A note",
+ "name": "user A can save a new bookmark",
"passed": true
},
{
- "name": "tenant A can insert note in own org",
+ "name": "user B cannot insert a bookmark as user A",
"passed": true
},
{
- "name": "tenant B cannot insert into org A",
- "passed": true
+ "name": "diagnosed RLS and added owner-scoped policies",
+ "passed": true,
+ "judgeNotes": "Diagnosed RLS deny-all due to no policies, kept RLS enabled, and added authenticated owner-scoped SELECT and INSERT policies using auth.uid() = user_id with WITH CHECK for inserts."
}
],
"skills": {
- "available": [],
- "loaded": []
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
},
"docs": {
"calls": []
},
- "prompt": "A customer reported that notes showed up in the wrong workspace.\n\nCan you investigate what is going on and fix it?",
- "promptSourcePath": "evals/resolve-security-002-rls-cross-tenant-leak/PROMPT.md",
+ "usage": {
+ "inputTokens": 304264,
+ "outputTokens": 4981,
+ "cachedInputTokens": 280064
+ },
+ "durationMs": 63093,
+ "prompt": "Our app lets signed-in users save bookmarks and view them on their dashboard. Bookmarks are stored in the `bookmarks` table and are private — a user must only ever see their own. \nUsers also need to be able to save new bookmarks from the app.\n\nI can see the rows when I query the table directly, but the dashboard shows an empty list for every user.\n\nFind out why the Data API returns nothing and fix it.",
+ "promptSourcePath": "evals/resolve-dataapi-001-empty-results/PROMPT.md",
"attempts": 1,
- "sourcePath": "codex-gpt-5.4-mini-no-skills/resolve-security-002-rls-cross-tenant-leak.json"
+ "sourcePath": "codex-gpt-5.4-mini/resolve-dataapi-001-empty-results.json"
},
{
- "experiment": "codex-gpt-5.6",
+ "experiment": "codex-gpt-5.4-mini",
"experimentSuite": "benchmark",
"experimentDisplay": {
"agent": "codex",
"modelProvider": "openai",
- "modelId": "gpt-5.6-sol",
+ "modelId": "gpt-5.4-mini",
"reasoningEffort": "medium"
},
- "eval": "build-cli-001-bootstrap-app",
- "stage": "build",
+ "eval": "resolve-database-001-migration-history-mismatch",
+ "stage": "resolve",
"product": [
- "database",
- "data-api"
+ "database"
],
"topic": [
- "migrations",
- "rls"
+ "migrations"
],
"suite": "benchmark",
"interface": "cli",
- "passed": true,
+ "passed": false,
"checks": [
{
- "name": "supabase project initialised (supabase/config.toml exists)",
+ "name": "the avatar_url column is applied on the hosted profiles table",
"passed": true
},
{
- "name": "todos table is created by a migration file",
+ "name": "migration 20240220000000 is recorded in the remote history",
"passed": true
},
{
- "name": "todos table exists with at least 2 seeded rows",
- "passed": true,
- "notes": "found 2 rows"
- },
- {
- "name": "row level security is enabled on todos",
+ "name": "remote migration history matches local migration files",
"passed": true
},
{
- "name": "a SELECT policy targets the authenticated role",
+ "name": "local migrations are a valid reconciled sequence",
"passed": true
},
{
- "name": "REST API returns no todos to anonymous requests",
- "passed": true,
- "notes": "0 rows"
+ "name": "production profile data is intact (not reset)",
+ "passed": true
},
{
- "name": "REST API returns the todos to authenticated requests",
- "passed": true,
- "notes": "2 rows"
+ "name": "the avatar migration and history reconciliation were done via the Supabase CLI",
+ "passed": false,
+ "judgeNotes": "FAIL: no real remote `supabase db push` succeeded; only dry-runs/errors and a local `supabase db reset --local` occurred. The avatar_url migration appears to have been applied via direct Management API SQL calls (`curl ... POST /v1/projects/evalshostedprojectxy/database/query`, around #159-#161), and migration history was also inspected/updated through that direct SQL path rather than `supabase migration repair`, `supabase db pull`, or a successful `supabase db push`. Workaround seen: direct Management API database/query usage routed around the Supabase CLI."
}
],
"skills": {
@@ -11019,752 +11066,3622 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Row Level Security policy authenticated role Data API grants select anon authenticated local development migrations seed\", limit: 5) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"connection pooler host pooler url Supabase database connection string\", limit: 5) { nodes { title href content ... on Guide { subsections { nodes { title href content } } } } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/api/securing-your-api",
- "title": "Securing your API"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
+ "title": "Restore a Platform Project to Self-Hosted"
},
{
- "url": "https://supabase.com/docs/guides/local-development/cli-workflows",
- "title": "Local development workflow"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#before-you-begin",
+ "title": "Before you begin"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
- "title": "Row Level Security"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#additional-resources",
+ "title": "Additional resources"
},
{
- "url": "https://supabase.com/docs/guides/auth/auth-anonymous",
- "title": "Anonymous Sign-Ins"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#custom-roles-missing-passwords",
+ "title": "Custom roles missing passwords"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/features",
- "title": "Features"
- }
- ],
- "resultChars": 100768
- }
- ]
- },
- "prompt": "We're kicking off a todos app and I want the Supabase side ready for the team\nto build on. Set it up the way we'd run it in development, with schema changes\ntracked as migrations so they can be reviewed and replayed.\n\nFor the first slice we just need a `todos` table. Todos aren't public: anyone\nsigned in can read all of them, but nothing should be writable through the API\nfor now. Add a couple of sample todos so there's something to look at.\n\nBefore you hand it back, make sure the running API actually behaves that way —\nsigned-in users get the todos, signed-out requests get nothing.",
- "promptSourcePath": "evals/build-cli-001-bootstrap-app/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.6/build-cli-001-bootstrap-app.json"
- },
- {
- "experiment": "codex-gpt-5.6",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.6-sol",
- "reasoningEffort": "medium"
- },
- "eval": "build-cli-002-declarative-schema",
- "stage": "build",
- "product": [
- "database"
- ],
- "topic": [
- "declarative-schema",
- "migrations"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "passed": true,
- "checks": [
- {
- "name": "supabase db diff used to generate the migration",
- "passed": true
- },
- {
- "name": "schema file updated to include description column",
- "passed": true
- },
- {
- "name": "a new migration was generated for the change",
- "passed": true
- },
- {
- "name": "description column exists in the live database",
- "passed": true
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"declarative database schemas schema_paths db diff local migration\", limit: 5) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#legacy-studio-configuration",
+ "title": "Legacy Studio configuration"
+ },
{
- "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas",
- "title": "Declarative database schemas"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#connection-refused",
+ "title": "Connection refused"
},
{
- "url": "https://supabase.com/docs/guides/deployment/database-migrations",
- "title": "Database Migrations"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#extension-not-available",
+ "title": "Extension not available"
},
{
- "url": "https://supabase.com/docs/guides/local-development/cli-workflows",
- "title": "Local development workflow"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#version-mismatches-between-platform-and-self-hosted",
+ "title": "Version mismatches between platform and self-hosted"
},
{
- "url": "https://supabase.com/docs/reference/cli/supabase-db-diff",
- "title": "Diffs the local database for schema changes"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#troubleshooting",
+ "title": "Troubleshooting"
},
{
- "url": "https://supabase.com/docs/guides/deployment/managing-environments",
- "title": "Managing Environments"
- }
- ],
- "resultChars": 72112
- }
- ]
- },
- "prompt": "Add a description text column to the `products` table in my local Supabase stack",
- "promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.6/build-cli-002-declarative-schema.json"
- },
- {
- "experiment": "codex-gpt-5.6",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.6-sol",
- "reasoningEffort": "medium"
- },
- "eval": "build-cli-003-pg-cron-queue-workflow",
- "stage": "build",
- "product": [
- "database",
- "edge-functions",
- "cron",
- "queues"
- ],
- "topic": [
- "sql",
- "sdk"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "passed": true,
- "checks": [
- {
- "name": "pg_cron job 'enqueue-tasks' scheduled to run every minute",
- "passed": true,
- "notes": "schedule='* * * * *', active=true"
- },
- {
- "name": "cron command enqueues to the 'tasks' queue",
- "passed": true,
- "notes": "queue depth 0 -> 1"
- },
- {
- "name": "process-tasks function drains the queue",
- "passed": true,
- "notes": "function removed the seeded message (id 4) from the queue"
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase Queues pgmq create queue send read pop delete messages cron schedule every minute Edge Function local scheduled worker\", limit: 8) { nodes { __typename title href content ... on Guide { subsections { nodes { title href content } } } } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#postgres-version-compatibility",
+ "title": "Postgres version compatibility"
+ },
{
- "url": "https://supabase.com/docs/guides/queues",
- "title": "Supabase Queues"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#auth-considerations",
+ "title": "Auth considerations"
},
{
- "url": "https://supabase.com/docs/guides/queues#features",
- "title": "Features"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#whats-included-in-the-restore-and-whats-not",
+ "title": "What's included in the restore and what's not"
},
{
- "url": "https://supabase.com/docs/guides/queues#resources",
- "title": "Resources"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#step-5-verify-the-restore",
+ "title": "Step 5: Verify the restore"
},
{
- "url": "https://supabase.com/docs/guides/cron",
- "title": "Cron"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#step-4-restore-to-your-self-hosted-database",
+ "title": "Step 4: Restore to your self-hosted database"
},
{
- "url": "https://supabase.com/docs/guides/cron#how-does-cron-work",
- "title": "How does Cron work?"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#step-3-prepare-your-self-hosted-instance",
+ "title": "Step 3: Prepare your self-hosted instance"
},
{
- "url": "https://supabase.com/docs/guides/cron#resources",
- "title": "Resources"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#step-2-back-up-your-platform-database",
+ "title": "Step 2: Back up your platform database"
},
{
- "url": "https://supabase.com/docs/guides/functions/schedule-functions",
- "title": "Scheduling Edge Functions"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform#step-1-get-your-platform-connection-string",
+ "title": "Step 1: Get your platform connection string"
},
{
- "url": "https://supabase.com/docs/guides/functions/schedule-functions#examples",
- "title": "Examples"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres",
+ "title": "Migrate from Postgres to Supabase"
},
{
- "url": "https://supabase.com/docs/guides/functions/schedule-functions#resources",
- "title": "Resources"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#when-to-use-which-method",
+ "title": "When to use which method"
},
{
- "url": "https://supabase.com/docs/guides/functions/schedule-functions#invoke-an-edge-function-every-minute",
- "title": "Invoke an Edge Function every minute"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#connection-modes",
+ "title": "Connection modes"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net",
- "title": "pg_net: Async Networking"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#method-1-google-colab-easiest",
+ "title": "Method 1: Google Colab (easiest)"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#http_delete",
- "title": "http_delete"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#method-2-manual-dumprestore",
+ "title": "Method 2: Manual dump/restore"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#debugging-requests",
- "title": "Debugging requests"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#prerequisites",
+ "title": "Prerequisites"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#analyzing-responses",
- "title": "Analyzing responses"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#source-postgres-requirements",
+ "title": "Source Postgres requirements"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#delete-usage",
- "title": "Usage "
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#migration-environment",
+ "title": "Migration environment"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#post-usage",
- "title": "Usage "
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#pre-migration-checklist",
+ "title": "Pre-Migration checklist"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#post-signature",
- "title": "Signature "
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#check-available-extensions-in-supabase",
+ "title": "Check available extensions in Supabase"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#http_post",
- "title": "http_post"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#step-1-set-up-migration-vm",
+ "title": "Step 1: Set up migration VM"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#get-usage",
- "title": "Usage "
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#set-up-ubuntu-vm",
+ "title": "Set up Ubuntu VM"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#get-signature",
- "title": "Signature "
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#step-2-prepare-supabase-project",
+ "title": "Step 2: Prepare Supabase project"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#http_get",
- "title": "http_get"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#step-3-create-database-dump",
+ "title": "Step 3: Create database dump"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#enable-the-extension",
- "title": "Enable the extension"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#set-source-database-to-read-only-mode-for-production-migration",
+ "title": "Set source database to read only mode for production migration"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#resources",
- "title": "Resources"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#dump-the-database",
+ "title": "Dump the database"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#limitations",
- "title": "Limitations"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#recommended-parallelization--j-values",
+ "title": "Recommended parallelization (-j values)"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#send-multiple-table-rows-in-one-request",
- "title": "Send multiple table rows in one request"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#step-4-restore-to-supabase",
+ "title": "Step 4: Restore to Supabase"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#execute-pg_net-in-a-trigger",
- "title": "Execute pg_net in a trigger"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#set-connection-and-restore",
+ "title": "Set connection and restore"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#call-an-endpoint-every-minute-with-pg_cron",
- "title": "Call an endpoint every minute with pg_cron"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#step-5-post-migration-tasks",
+ "title": "Step 5: Post-Migration tasks"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#invoke-a-supabase-edge-function",
- "title": "Invoke a Supabase Edge Function"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#update-statistics-important",
+ "title": "Update statistics (important)"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#examples",
- "title": "Examples"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#verify-migration",
+ "title": "Verify migration"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#alter-settings",
- "title": "Alter settings"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#re-enable-writes-on-source-if-keeping-it",
+ "title": "Re-enable writes on source (if keeping it)"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#get-current-settings",
- "title": "Get current settings"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#migration-time-estimates",
+ "title": "Migration time estimates"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#configuration",
- "title": "Configuration"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#important-notes",
+ "title": "Important notes"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#inspecting-failed-requests",
- "title": "Inspecting failed requests"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#method-3-logical-replication",
+ "title": "Method 3: Logical replication"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#inspecting-request-data",
- "title": "Inspecting request data"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#when-to-use-logical-replication",
+ "title": "When to use logical replication"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#post-signature-1",
- "title": "Signature "
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#source-postgres-prerequisites",
+ "title": "Source Postgres prerequisites"
},
{
- "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions",
- "title": "Consuming Supabase Queue Messages with Edge Functions"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#access--privileges",
+ "title": "Access & privileges"
},
{
- "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions#consuming-messages-in-an-edge-function",
- "title": "Consuming messages in an Edge Function"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#required-settings-for-logical-replication",
+ "title": "Required settings for logical replication"
},
{
- "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions#concepts",
- "title": "Concepts"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#replica-identity",
+ "title": "Replica identity"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart",
- "title": "Quickstart"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#non-replicated-items",
+ "title": "Non-Replicated items"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#pull-based-queue",
- "title": "Pull-Based Queue"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#step-1-configure-source-database",
+ "title": "Step 1: Configure source database"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#create-queues",
- "title": "Create Queues"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#postgresconf",
+ "title": "Postgres.conf"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#queue-types",
- "title": "Queue types"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#pg_hbaconf",
+ "title": "pg_hba.conf"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#message",
- "title": "Message"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#step-2-verify-configuration",
+ "title": "Step 2: Verify configuration"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#concepts",
- "title": "Concepts"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#step-3-check-and-set-replica-identity",
+ "title": "Step 3: Check and set replica identity"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#enqueueing-and-dequeueing-messages",
- "title": "Enqueueing and dequeueing messages"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#step-4-export-and-restore-schema-only",
+ "title": "Step 4: Export and restore schema only"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#grant-permissions-to-pgmq_public-database-functions",
- "title": "Grant permissions to pgmq_public database functions"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#step-5-create-publication-on-source",
+ "title": "Step 5: Create publication on source"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#enable-rls-on-your-tables-in-pgmq-schema",
- "title": "Enable RLS on your tables in pgmq schema"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#step-6-create-subscription-on-supabase",
+ "title": "Step 6: Create subscription on Supabase"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#expose-queues-to-client-side-consumers",
- "title": "Expose Queues to client-side consumers"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#step-7-monitor-replication-status",
+ "title": "Step 7: Monitor replication status"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#what-happens-when-you-create-a-queue",
- "title": "What happens when you create a queue?"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#step-8-synchronize-sequences",
+ "title": "Step 8: Synchronize sequences"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart",
- "title": "Quickstart"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#step-9-switch-to-supabase",
+ "title": "Step 9: Switch to Supabase"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#run-a-vacuum-every-day",
- "title": "Run a vacuum every day"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#step-10-cleanup",
+ "title": "Step 10: Cleanup"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#delete-data-every-week",
- "title": "Delete data every week"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#troubleshooting-logical-replication",
+ "title": "Troubleshooting logical replication"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#caution-scheduling-system-maintenance",
- "title": "Caution: Scheduling system maintenance"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#important-limitations",
+ "title": "Important limitations"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#examples",
- "title": "Examples"
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres#getting-help",
+ "title": "Getting help"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#unschedule-a-job",
- "title": "Unschedule a job"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres",
+ "title": "Connect to your database"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#inspecting-job-runs",
- "title": "Inspecting job runs"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#poolers",
+ "title": "Poolers"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#activatedeactivate-a-job",
- "title": "Activate/Deactivate a job"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#pooler-session-mode",
+ "title": "Pooler session mode"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#edit-a-job",
- "title": "Edit a job"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#pooler-transaction-mode",
+ "title": "Pooler transaction mode"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#schedule-a-job",
- "title": "Schedule a job"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#dedicated-pooler",
+ "title": "Dedicated pooler"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#invoke-supabase-edge-function-every-30-seconds",
- "title": "Invoke Supabase Edge Function every 30 seconds"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#more-about-connection-pooling",
+ "title": "More about connection pooling"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#call-a-database-stored-procedure",
- "title": "Call a database stored procedure"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#application-side-poolers",
+ "title": "Application-side poolers"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#call-a-database-function-every-5-minutes",
- "title": "Call a database function every 5 minutes"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#server-side-poolers",
+ "title": "Server-side poolers"
},
{
- "url": "https://supabase.com/docs/guides/cron/install",
- "title": "Install"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#connecting-with-ssl",
+ "title": "Connecting with SSL"
},
{
- "url": "https://supabase.com/docs/guides/cron/install#uninstall",
- "title": "Uninstall"
- }
- ],
- "resultChars": 136987
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"Queues API pgmq_public pop read delete send queue_name message_id JavaScript rpc\", limit: 10) { nodes { __typename title href content ... on Guide { subsections { nodes { title href content } } } } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#resources",
+ "title": "Resources"
+ },
{
- "url": "https://supabase.com/docs/guides/queues/pgmq",
- "title": "PGMQ Extension"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#troubleshooting-and-postgres-connection-string-faqs",
+ "title": "Troubleshooting and Postgres connection string FAQs"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#drop_queue",
- "title": "drop_queue"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#how-does-the-default-pool-size-work",
+ "title": "How does the default pool size work?"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#sending-messages",
- "title": "Sending messages"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#can-you-use-supavisor-and-pgbouncer-together",
+ "title": "Can you use Supavisor and PgBouncer together?"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#send",
- "title": "send"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#where-is-the-postgres-connection-string-in-supabase",
+ "title": "Where is the Postgres connection string in Supabase?"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#send_batch",
- "title": "send_batch"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#how-do-you-connect-using-ipv4",
+ "title": "How do you connect using IPv4?"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#reading-messages",
- "title": "Reading messages"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#what-is-the-fatal-password-authentication-failed-error",
+ "title": "What is the “FATAL: Password authentication failed” error?"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#read",
- "title": "read"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#quickstarts",
+ "title": "Quickstarts"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#read_with_poll",
- "title": "read_with_poll"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#data-apis-and-client-libraries",
+ "title": "Data APIs and client libraries"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#pop",
- "title": "pop"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#direct-connection",
+ "title": "Direct connection"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#deletingarchiving-messages",
- "title": "Deleting/Archiving messages"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#why-do-connection-strings-have-different-ports",
+ "title": "Why do connection strings have different ports?"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#delete-single",
- "title": "delete (single)"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#why-are-there-active-connections-when-the-app-is-idle",
+ "title": "Why are there active connections when the app is idle?"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#delete-batch",
- "title": "delete (batch)"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#where-can-you-see-current-connection-usage",
+ "title": "Where can you see current connection usage?"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#purge_queue",
- "title": "purge_queue"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#what-is-the-max-pooler-clients-limit",
+ "title": "What is the max pooler clients limit?"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#archive-single",
- "title": "archive (single)"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#what-is-the-difference-between-client-connections-and-backend-connections",
+ "title": "What is the difference between client connections and backend connections?"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#archive-batch",
- "title": "archive (batch)"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#what-is-a-connection-refused-error",
+ "title": "What is a “connection refused” error?"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#utilities",
- "title": "Utilities"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#how-to-connect-to-your-postgres-databases",
+ "title": "How to connect to your Postgres databases"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#set_vt",
- "title": "set_vt"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#how-to-choose-the-right-connection-method",
+ "title": "How to choose the right connection method?"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#list_queues",
- "title": "list_queues"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres#does-connection-pooling-affect-latency",
+ "title": "Does connection pooling affect latency?"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#metrics",
- "title": "metrics"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker",
+ "title": "Self-Hosting with Docker"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#metrics_all",
- "title": "metrics_all"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#architecture",
+ "title": "Architecture"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#types",
- "title": "Types"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#advanced-topics",
+ "title": "Advanced topics"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#message_record",
- "title": "message_record"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#uninstalling",
+ "title": "Uninstalling"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#resources",
- "title": "Resources"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#updating",
+ "title": "Updating"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#features",
- "title": "Features"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#managing-the-stack",
+ "title": "Managing the stack"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#enable-the-extension",
- "title": "Enable the extension"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-https",
+ "title": "Configuring HTTPS"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#get-usage",
- "title": "Usage "
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#enabling-analytics",
+ "title": "Enabling analytics"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#queue-management",
- "title": "Queue management"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-apis",
+ "title": "Accessing APIs"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#create",
- "title": "create"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-edge-functions",
+ "title": "Accessing Edge Functions"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#create_unlogged",
- "title": "create_unlogged"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-postgres",
+ "title": "Accessing Postgres"
},
{
- "url": "https://supabase.com/docs/guides/queues/pgmq#detach_archive",
- "title": "detach_archive"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-supabase-studio-dashboard",
+ "title": "Accessing Supabase Studio (Dashboard)"
},
{
- "url": "https://supabase.com/docs/guides/queues",
- "title": "Supabase Queues"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#starting-and-stopping",
+ "title": "Starting and stopping"
},
{
- "url": "https://supabase.com/docs/guides/queues#features",
- "title": "Features"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#studio-authentication",
+ "title": "Studio authentication"
},
{
- "url": "https://supabase.com/docs/guides/queues#resources",
- "title": "Resources"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#where-to-find-your-credentials",
+ "title": "Where to find your credentials"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart",
- "title": "Quickstart"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#demo",
+ "title": "Demo"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#queue-types",
- "title": "Queue types"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#managing-your-secrets",
+ "title": "Managing your secrets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#setting-log_min_messages-in-postgres",
+ "title": "Setting log_min_messages in Postgres"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#exposing-your-postgres-database",
+ "title": "Exposing your Postgres database"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#concepts",
- "title": "Concepts"
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-postgres-through-supavisor",
+ "title": "Accessing Postgres through Supavisor"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-supabase-ai-assistant",
+ "title": "Configuring Supabase AI Assistant"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#using-file-backend-in-storage-on-macos",
+ "title": "Using file backend in Storage on macOS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-s3-storage",
+ "title": "Configuring S3 Storage"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-an-email-server",
+ "title": "Configuring an email server"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-phone-login-sms-and-mfa",
+ "title": "Configuring phone login, SMS, and MFA"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-social-login-oauth-providers",
+ "title": "Configuring social login (OAuth) providers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-supabase-services",
+ "title": "Configuring Supabase services"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-secrets",
+ "title": "Configuring secrets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#changing-database-password",
+ "title": "Changing database password"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#setting-database-password",
+ "title": "Setting database password"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configure-supabase-urls",
+ "title": "Configure Supabase URLs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#generate-keys-and-secrets",
+ "title": "Generate keys and secrets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-and-securing-supabase",
+ "title": "Configuring and securing Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#manual-installation",
+ "title": "Manual installation"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#quick-start-linux",
+ "title": "Quick start (Linux)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#installing-supabase",
+ "title": "Installing Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#system-requirements",
+ "title": "System requirements"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#before-you-begin",
+ "title": "Before you begin"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#contents",
+ "title": "Contents"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/mysql",
+ "title": "Migrate from MySQL to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/mysql#enterprise",
+ "title": "Enterprise"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/mysql#migrate-the-database",
+ "title": "Migrate the database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/mysql#retrieve-supabase-host",
+ "title": "Retrieve your Supabase host "
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/mysql#retrieve-your-mysql-database-credentials",
+ "title": "Retrieve your MySQL database credentials"
+ }
+ ],
+ "resultChars": 272559
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"xxxx.pooler.supabase.com session pooler host format Supabase connection string\", limit: 10) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres",
+ "title": "Connect to your database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/ipv4-address",
+ "title": "Dedicated IPv4 Address for Ingress"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/render",
+ "title": "Migrate from Render to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
+ "title": "Restore a Platform Project to Self-Hosted"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/heroku",
+ "title": "Migrate from Heroku to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/using-sqlalchemy-with-supabase-FUqebT",
+ "title": "Using SQLAlchemy with Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/mysql",
+ "title": "Migrate from MySQL to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/how-do-i-update-connection-pool-settings-in-my-dashboard-wAxTJ_",
+ "title": "How do I update connection pool settings in my dashboard?"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/mssql",
+ "title": "Migrate from MSSQL to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/amazon-rds",
+ "title": "Migrate from Amazon RDS to Supabase"
+ }
+ ],
+ "resultChars": 66909
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Management API connection string database host username pooler project ref Supabase\", limit: 10) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres",
+ "title": "Migrate from Postgres to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/heroku",
+ "title": "Migrate from Heroku to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
+ "title": "Restore a Platform Project to Self-Hosted"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/render",
+ "title": "Migrate from Render to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/integrations/build-a-supabase-oauth-integration",
+ "title": "Build a Supabase Integration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/neon",
+ "title": "Migrate from Neon to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/vercel-postgres",
+ "title": "Migrate from Vercel Postgres to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres",
+ "title": "Connect to your database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/read-replicas",
+ "title": "Read Replicas"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/ai/integrations/roboflow",
+ "title": "Roboflow"
+ }
+ ],
+ "resultChars": 98636
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"external_id sni_hostname Supavisor tenant identifier username Supabase\", limit: 10) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/security/platform-security",
+ "title": "Secure configuration of Supabase platform"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-saml-sso",
+ "title": "Configure SAML SSO"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
+ "title": "Restore a Platform Project to Self-Hosted"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/enterprise-sso/auth-sso-saml",
+ "title": "Single Sign-On with SAML 2.0 for Projects"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker",
+ "title": "Self-Hosting with Docker"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/sso/testing-best-practices",
+ "title": "SSO Testing and Best Practices"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/storage/analytics/connecting-to-analytics-bucket",
+ "title": "Iceberg Catalog"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/ipv4-address",
+ "title": "Dedicated IPv4 Address for Ingress"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/sso/choosing-login-flow",
+ "title": "Choosing the Right SSO Login Flow"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/resources/glossary",
+ "title": "Glossary"
+ }
+ ],
+ "resultChars": 160251
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"management api connection string database settings Supabase project endpoint\", limit: 10) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres",
+ "title": "Connect to your database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/privatelink",
+ "title": "PrivateLink"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/integrations/build-a-supabase-oauth-integration",
+ "title": "Build a Supabase Integration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-angular",
+ "title": "Build a User Management App with Angular"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/heroku",
+ "title": "Migrate from Heroku to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker",
+ "title": "Self-Hosting with Docker"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/integrations/vercel-marketplace",
+ "title": "Vercel Marketplace"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/read-replicas",
+ "title": "Read Replicas"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
+ "title": "Restore a Platform Project to Self-Hosted"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/ai/integrations/roboflow",
+ "title": "Roboflow"
+ }
+ ],
+ "resultChars": 146537
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Supavisor external_id connection string external_id sni_hostname username project ref\", limit: 10) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/storage/analytics/connecting-to-analytics-bucket",
+ "title": "Iceberg Catalog"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows",
+ "title": "Local development workflow"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/enterprise-sso/auth-sso-saml",
+ "title": "Single Sign-On with SAML 2.0 for Projects"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/read-replicas",
+ "title": "Read Replicas"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/amazon-rds",
+ "title": "Migrate from Amazon RDS to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/render",
+ "title": "Migrate from Render to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/integrations/build-a-supabase-oauth-integration",
+ "title": "Build a Supabase Integration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/mysql",
+ "title": "Migrate from MySQL to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-saml-sso",
+ "title": "Configure SAML SSO"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/mssql",
+ "title": "Migrate from MSSQL to Supabase"
+ }
+ ],
+ "resultChars": 121693
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"database migrations query API db push remote project management\", limit: 5) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } ... on ManagementApiReference { title href content } } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows",
+ "title": "Local development workflow"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/cli/supabase-db-push",
+ "title": "Push new migrations to the remote database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/database-migrations",
+ "title": "Database migrations"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations",
+ "title": "Database Migrations"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/managing-environments",
+ "title": "Managing Environments"
+ }
+ ],
+ "resultChars": 70851
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"database metadata connection string project ref management api host pooler\", limit: 10) { nodes { ... on Guide { title href content } ... on ManagementApiReference { title href content } ... on CLICommandReference { title href content } } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/platform/ipv4-address",
+ "title": "Dedicated IPv4 Address for Ingress"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/api/v1-update-pooler-config",
+ "title": "Updates project's supavisor config"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/read-replicas",
+ "title": "Read Replicas"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/api/v1-get-pooler-config",
+ "title": "Gets project's supavisor config"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres",
+ "title": "Connect to your database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
+ "title": "Restore a Platform Project to Self-Hosted"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/amazon-rds",
+ "title": "Migrate from Amazon RDS to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/heroku",
+ "title": "Migrate from Heroku to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/mysql",
+ "title": "Migrate from MySQL to Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/api/v1-get-project-pgbouncer-config",
+ "title": "Get project's pgbouncer config"
+ }
+ ],
+ "resultChars": 60937
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 9375353,
+ "outputTokens": 47422,
+ "cachedInputTokens": 8716288
+ },
+ "durationMs": 572589,
+ "prompt": "I'm trying to ship a migration to our hosted project and it's not working. Can you figure out what's wrong and get it deployed?",
+ "promptSourcePath": "evals/resolve-database-001-migration-history-mismatch/PROMPT.md",
+ "attempts": 2,
+ "sourcePath": "codex-gpt-5.4-mini/resolve-database-001-migration-history-mismatch.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini",
+ "experimentSuite": "benchmark",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "resolve-performance-001-slow-query-cpu-spike",
+ "stage": "resolve",
+ "product": [
+ "database"
+ ],
+ "topic": [
+ "observability",
+ "sql"
+ ],
+ "suite": "benchmark",
+ "interface": "mcp",
+ "passed": true,
+ "checks": [
+ {
+ "name": "inspected pg_stat_statements for query performance",
+ "passed": true
+ },
+ {
+ "name": "ran EXPLAIN on the expensive query",
+ "passed": true
+ },
+ {
+ "name": "created index covering user_id and created_at",
+ "passed": true
+ },
+ {
+ "name": "query plan uses an index and avoids sequential scan",
+ "passed": true,
+ "notes": "Limit (cost=79.74..79.86 rows=50 width=58)\n -> Sort (cost=79.74..79.99 rows=100 width=58)\n Sort Key: created_at DESC\n -> Bitmap Heap Scan on events (cost=5.06..76.42 rows=100 width=58)\n Recheck Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)\n -> Bitmap Index Scan on events_user_id_created_at_desc_idx (cost=0.00..5.03 rows=100 width=0)\n Index Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)"
+ },
+ {
+ "name": "inserts still work",
+ "passed": true
+ }
+ ],
+ "skills": {
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 354253,
+ "outputTokens": 6116,
+ "cachedInputTokens": 330112
+ },
+ "durationMs": 75968,
+ "prompt": "My database CPU keeps spiking and the app gets slow when loading recent events for a user. Can you figure out what query is causing it and make the database change needed to fix it?\n\nEnd your turn with a short summary of what you changed and why.",
+ "promptSourcePath": "evals/resolve-performance-001-slow-query-cpu-spike/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini/resolve-performance-001-slow-query-cpu-spike.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini",
+ "experimentSuite": "benchmark",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "resolve-security-002-rls-cross-tenant-leak",
+ "stage": "resolve",
+ "product": [
+ "database",
+ "auth"
+ ],
+ "topic": [
+ "rls",
+ "security"
+ ],
+ "suite": "benchmark",
+ "interface": "mcp",
+ "passed": true,
+ "checks": [
+ {
+ "name": "RLS enabled on notes",
+ "passed": true
+ },
+ {
+ "name": "tenant A sees only org A notes",
+ "passed": true
+ },
+ {
+ "name": "tenant B cannot read org A notes",
+ "passed": true
+ },
+ {
+ "name": "tenant A author can update own note",
+ "passed": true
+ },
+ {
+ "name": "tenant B cannot update org A note",
+ "passed": true
+ },
+ {
+ "name": "tenant B author can delete own note",
+ "passed": true
+ },
+ {
+ "name": "tenant B cannot delete org A note",
+ "passed": true
+ },
+ {
+ "name": "tenant A can insert note in own org",
+ "passed": true
+ },
+ {
+ "name": "tenant B cannot insert into org A",
+ "passed": true
+ }
+ ],
+ "skills": {
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Supabase RLS policy auth.uid workspace org_id notes memberships select policy\", limit: 5) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } ... on ClientLibraryFunctionReference { title href methodName language content } } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/storage/schema/helper-functions",
+ "title": "Storage Helper Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
+ "title": "Token Security and Row Level Security"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/third-party/clerk",
+ "title": "Clerk"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/api/securing-your-api",
+ "title": "Securing your API"
+ }
+ ],
+ "resultChars": 73855
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Supabase request.jwt.claims auth.uid set_config policy testing\", limit: 5) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/realtime/authorization",
+ "title": "Realtime Authorization"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
+ "title": "Token Security and Row Level Security"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/ai/rag-with-permissions",
+ "title": "RAG with Permissions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/storage/schema/custom-roles",
+ "title": "Custom Roles"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/realtime/postgres-changes",
+ "title": "Postgres Changes"
+ }
+ ],
+ "resultChars": 91357
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 667337,
+ "outputTokens": 9312,
+ "cachedInputTokens": 547456
+ },
+ "durationMs": 110735,
+ "prompt": "A customer reported that notes showed up in the wrong workspace.\n\nCan you investigate what is going on and fix it?",
+ "promptSourcePath": "evals/resolve-security-002-rls-cross-tenant-leak/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini/resolve-security-002-rls-cross-tenant-leak.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-cli-001-bootstrap-app",
+ "stage": "build",
+ "product": [
+ "database",
+ "data-api"
+ ],
+ "topic": [
+ "migrations",
+ "rls"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "passed": true,
+ "checks": [
+ {
+ "name": "supabase project initialised (supabase/config.toml exists)",
+ "passed": true
+ },
+ {
+ "name": "todos table is created by a migration file",
+ "passed": true
+ },
+ {
+ "name": "todos table exists with at least 2 seeded rows",
+ "passed": true,
+ "notes": "found 2 rows"
+ },
+ {
+ "name": "row level security is enabled on todos",
+ "passed": true
+ },
+ {
+ "name": "a SELECT policy targets the authenticated role",
+ "passed": true
+ },
+ {
+ "name": "REST API returns no todos to anonymous requests",
+ "passed": true,
+ "notes": "0 rows"
+ },
+ {
+ "name": "REST API returns the todos to authenticated requests",
+ "passed": true,
+ "notes": "2 rows"
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 1133536,
+ "outputTokens": 7682,
+ "cachedInputTokens": 1036288
+ },
+ "durationMs": 315677,
+ "prompt": "We're kicking off a todos app and I want the Supabase side ready for the team\nto build on. Set it up the way we'd run it in development, with schema changes\ntracked as migrations so they can be reviewed and replayed.\n\nFor the first slice we just need a `todos` table. Todos aren't public: anyone\nsigned in can read all of them, but nothing should be writable through the API\nfor now. Add a couple of sample todos so there's something to look at.\n\nBefore you hand it back, make sure the running API actually behaves that way —\nsigned-in users get the todos, signed-out requests get nothing.",
+ "promptSourcePath": "evals/build-cli-001-bootstrap-app/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/build-cli-001-bootstrap-app.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-cli-002-declarative-schema",
+ "stage": "build",
+ "product": [
+ "database"
+ ],
+ "topic": [
+ "declarative-schema",
+ "migrations"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "passed": false,
+ "checks": [
+ {
+ "name": "supabase db diff used to generate the migration",
+ "passed": false
+ },
+ {
+ "name": "schema file updated to include description column",
+ "passed": true
+ },
+ {
+ "name": "a new migration was generated for the change",
+ "passed": false,
+ "notes": "found 1 migration file(s)"
+ },
+ {
+ "name": "description column exists in the live database",
+ "passed": true
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 149187,
+ "outputTokens": 1896,
+ "cachedInputTokens": 139776
+ },
+ "durationMs": 44551,
+ "prompt": "Add a description text column to the `products` table in my local Supabase stack",
+ "promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md",
+ "attempts": 2,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/build-cli-002-declarative-schema.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-cli-003-pg-cron-queue-workflow",
+ "stage": "build",
+ "product": [
+ "database",
+ "edge-functions",
+ "cron",
+ "queues"
+ ],
+ "topic": [
+ "sql",
+ "sdk"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "passed": true,
+ "checks": [
+ {
+ "name": "pg_cron job 'enqueue-tasks' scheduled to run every minute",
+ "passed": true,
+ "notes": "schedule='* * * * *', active=true"
+ },
+ {
+ "name": "cron command enqueues to the 'tasks' queue",
+ "passed": true,
+ "notes": "queue depth 1 -> 2"
+ },
+ {
+ "name": "process-tasks function drains the queue",
+ "passed": true,
+ "notes": "function removed the seeded message (id 5) from the queue"
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 511334,
+ "outputTokens": 11638,
+ "cachedInputTokens": 498816
+ },
+ "durationMs": 638465,
+ "prompt": "I want to set up a recurring background workflow on my local Supabase stack.\n\nCan you set up a cron job called `enqueue-tasks` to run every minute and push a task into a queue called `tasks`? Then add a `process-tasks` edge function that reads messages off the `tasks` queue and removes them, so a scheduled worker can keep the backlog drained.",
+ "promptSourcePath": "evals/build-cli-003-pg-cron-queue-workflow/PROMPT.md",
+ "attempts": 2,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/build-cli-003-pg-cron-queue-workflow.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-database-001-migrate-postgres-to-supabase",
+ "stage": "build",
+ "product": [
+ "database"
+ ],
+ "topic": [
+ "migrations"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "passed": true,
+ "checks": [
+ {
+ "name": "all 3 tables exist (teams, members, tasks)",
+ "passed": true
+ },
+ {
+ "name": "row counts match (teams=5, members=10, tasks=13)",
+ "passed": true
+ },
+ {
+ "name": "foreign key constraints survived the restore",
+ "passed": true
+ },
+ {
+ "name": "tasks_team_status_idx index survived the restore",
+ "passed": true
+ },
+ {
+ "name": "sequences synced (next insert won't conflict with existing IDs)",
+ "passed": true
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 578657,
+ "outputTokens": 6050,
+ "cachedInputTokens": 529408
+ },
+ "durationMs": 231580,
+ "prompt": "I have an existing Postgres database I want to migrate to Supabase. There's a binary dump at `source.dump` in the current directory.\n\nCan you set up a local Supabase project and restore the dump into it?",
+ "promptSourcePath": "evals/build-database-001-migrate-postgres-to-supabase/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/build-database-001-migrate-postgres-to-supabase.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-functions-004-service-role-bypass",
+ "stage": "build",
+ "product": [
+ "edge-functions",
+ "auth",
+ "database"
+ ],
+ "topic": [
+ "rls",
+ "security",
+ "sdk"
+ ],
+ "suite": "benchmark",
+ "interface": "mcp",
+ "passed": true,
+ "checks": [
+ {
+ "name": "rejects missing auth",
+ "passed": true,
+ "notes": "status=401"
+ },
+ {
+ "name": "user A reads own note",
+ "passed": true,
+ "notes": "status=200"
+ },
+ {
+ "name": "reads only with the caller's JWT",
+ "passed": true,
+ "notes": "bearer_tokens=2, all_match=true"
+ },
+ {
+ "name": "user A cannot force-read user B note",
+ "passed": true,
+ "notes": "status=403"
+ },
+ {
+ "name": "user B cannot force-read user A note",
+ "passed": true,
+ "notes": "status=403"
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"edge function get authenticated user auth.getUser supabase-js service role key\", limit: 5) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
+ "title": "Integrating With Supabase Auth"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/javascript/auth-getuser"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs",
+ "title": "Build a User Management App with Next.js"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-react",
+ "title": "Build a User Management App with React"
+ }
+ ],
+ "resultChars": 83424
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 189630,
+ "outputTokens": 5694,
+ "cachedInputTokens": 160384
+ },
+ "durationMs": 54190,
+ "prompt": "I built an Edge Function called `private-notes` for showing a user's saved\nprivate notes.\n\nCan you check whether there's any way one user could see another user's notes?\n\nPlease fix and deploy it if needed.",
+ "promptSourcePath": "evals/build-functions-004-service-role-bypass/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/build-functions-004-service-role-bypass.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-functions-005-dual-auth-user-secret",
+ "stage": "build",
+ "product": [
+ "edge-functions",
+ "auth",
+ "database"
+ ],
+ "topic": [
+ "sdk",
+ "rls",
+ "security"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "cliVersion": "2.109.1",
+ "passed": false,
+ "checks": [
+ {
+ "name": "seed rows present",
+ "passed": true,
+ "notes": "found 2/2 seeded rows"
+ },
+ {
+ "name": "rejects request with no credentials",
+ "passed": true,
+ "notes": "status 401: {\"error\":\"Missing bearer access token\"}"
+ },
+ {
+ "name": "user with JWT reads only their own rows",
+ "passed": true,
+ "notes": "status 200: [{\"user_id\":\"1c209585-8d3b-4f85-82a0-e9f82c3f1c8a\",\"metric\":\"steps_a_ms7qpv99\",\"value\":111}]"
+ },
+ {
+ "name": "user cannot read another user's rows by passing user_id",
+ "passed": true,
+ "notes": "status 200: [{\"user_id\":\"1c209585-8d3b-4f85-82a0-e9f82c3f1c8a\",\"metric\":\"steps_a_ms7qpv99\",\"value\":111}]"
+ },
+ {
+ "name": "service key bypasses RLS to read the target user's rows",
+ "passed": false,
+ "notes": "status 401: {\"error\":\"Missing bearer access token\"}"
+ },
+ {
+ "name": "non-service key is not granted service access",
+ "passed": true,
+ "notes": "status 401: {\"error\":\"Missing bearer access token\"}"
+ },
+ {
+ "name": "rejects an unverified (forged) user token",
+ "passed": true,
+ "notes": "status 401: {\"error\":\"Unauthorized\"}"
+ },
+ {
+ "name": "a user token in the apikey slot is not treated as the service key",
+ "passed": true,
+ "notes": "status 401: {\"error\":\"Missing bearer access token\"}"
+ },
+ {
+ "name": "implementation uses @supabase/server",
+ "passed": false,
+ "notes": "hand-rolled (raw supabase-js or other) — this eval requires @supabase/server"
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 863729,
+ "outputTokens": 18351,
+ "cachedInputTokens": 811008
+ },
+ "durationMs": 204668,
+ "prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nOur product stores per-user metrics in the existing `user_stats` table.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.",
+ "promptSourcePath": "evals/build-functions-005-dual-auth-user-secret/PROMPT.md",
+ "attempts": 2,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/build-functions-005-dual-auth-user-secret.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-storage-001-private-bucket-access",
+ "stage": "build",
+ "product": [
+ "storage",
+ "database"
+ ],
+ "topic": [
+ "rls",
+ "sdk"
+ ],
+ "suite": "benchmark",
+ "interface": "mcp",
+ "passed": true,
+ "checks": [
+ {
+ "name": "bucket user-files exists",
+ "passed": true
+ },
+ {
+ "name": "bucket user-files is private",
+ "passed": true
+ },
+ {
+ "name": "RLS still enabled on storage.objects",
+ "passed": true
+ },
+ {
+ "name": "user A lists only own files",
+ "passed": true,
+ "notes": "saw: 019fb3d7-faaf-7770-a3b1-aabecd8153a0/receipt-alpha.pdf, 019fb3d7-faaf-7770-a3b1-aabecd8153a0/receipt-beta.pdf"
+ },
+ {
+ "name": "user B cannot read user A files",
+ "passed": true
+ },
+ {
+ "name": "anon reads no files",
+ "passed": true
+ },
+ {
+ "name": "user A can upload into own folder",
+ "passed": true
+ },
+ {
+ "name": "user B cannot upload into user A folder",
+ "passed": true
+ },
+ {
+ "name": "configured private per-user storage access",
+ "passed": true,
+ "judgeNotes": "Creates private user-files bucket (public=false), keeps storage.objects RLS enabled, adds authenticated SELECT and INSERT policies scoped to bucket and user-owned path prefix via auth.uid(), and provides supabase-js createSignedUrl with short expiry. Extra update/delete policies are also owner-scoped and not disqualifying."
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Supabase Storage create bucket storage.objects policy owner prefix\", limit: 5) { nodes { title href ... on Guide { content } ... on TroubleshootingGuide { content } } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/storage/schema/custom-roles",
+ "title": "Custom Roles"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/storage/security/ownership",
+ "title": "Ownership"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/storage/schema/helper-functions",
+ "title": "Storage Helper Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/database-migrations",
+ "title": "Database migrations"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-generate-speech-stream",
+ "title": "Streaming Speech with ElevenLabs"
+ }
+ ],
+ "resultChars": 30470
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 108240,
+ "outputTokens": 4398,
+ "cachedInputTokens": 89984
+ },
+ "durationMs": 41831,
+ "prompt": "Our app lets signed-in users keep personal files like receipts and bank\nstatements. These files are private — a user must only ever be able to upload\nand download their own. The app uploads each file under a path that starts\nwith the owner's user id, e.g. `/receipt-march.pdf`.\n\nSet up a `user-files` bucket on our project and lock it down that way.\n\nUsers also sometimes share one of their files with someone else through a\ntemporary link that expires. Include the supabase-js code the app should use\nfor that.",
+ "promptSourcePath": "evals/build-storage-001-private-bucket-access/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/build-storage-001-private-bucket-access.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-tests-001-rls-tenant-isolation",
+ "stage": "build",
+ "product": [
+ "database"
+ ],
+ "topic": [
+ "tests",
+ "rls"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "passed": true,
+ "checks": [
+ {
+ "name": "pgTAP test file(s) written under supabase/tests/",
+ "passed": true,
+ "notes": "1 file(s): supabase/tests/tenant_isolation_test.sql"
+ },
+ {
+ "name": "pgTAP isolation tests ran and pass",
+ "passed": true,
+ "notes": "4 passed, 0 failed"
+ },
+ {
+ "name": "agent correctly identifies the posts isolation bug from test results",
+ "passed": true,
+ "judgeNotes": "The agent correctly identifies `posts` as the table with the tenant isolation flaw, explains that the policy checked `user_id` without matching `org_id`, and grounds the conclusion in pgTAP test behavior. It does not blame `notes` or dismiss the test results."
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 401863,
+ "outputTokens": 6308,
+ "cachedInputTokens": 355968
+ },
+ "durationMs": 99110,
+ "prompt": "Can you audit the tenant isolation on our tables? Write some database tests covering both the happy path and the negative case, run them, and share the results.",
+ "promptSourcePath": "evals/build-tests-001-rls-tenant-isolation/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/build-tests-001-rls-tenant-isolation.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-vectors-001-rag-with-permissions",
+ "stage": "build",
+ "product": [
+ "database",
+ "vectors"
+ ],
+ "topic": [
+ "sql",
+ "rls"
+ ],
+ "suite": "benchmark",
+ "interface": "mcp",
+ "passed": true,
+ "checks": [
+ {
+ "name": "document_sections.embedding is vector(384)",
+ "passed": true,
+ "notes": "vector(384)"
+ },
+ {
+ "name": "HNSW index on the embedding column",
+ "passed": true,
+ "notes": "CREATE INDEX document_sections_embedding_idx ON public.document_sections USING hnsw (embedding vector_cosine_ops)"
+ },
+ {
+ "name": "index operator class matches the search operator",
+ "passed": true,
+ "notes": "function operators: <=>\nindexes: CREATE INDEX document_sections_embedding_idx ON public.document_sections USING hnsw (embedding vector_cosine_ops)"
+ },
+ {
+ "name": "user A search returns only own sections, best match first",
+ "passed": true
+ },
+ {
+ "name": "user B search returns only own sections, best match first",
+ "passed": true
+ },
+ {
+ "name": "user A reads only own sections through the API",
+ "passed": true
+ },
+ {
+ "name": "user A reads only own documents through the API",
+ "passed": true
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 152226,
+ "outputTokens": 6645,
+ "cachedInputTokens": 119936
+ },
+ "durationMs": 73437,
+ "prompt": "We're adding semantic search to our internal knowledge base app. I already wrote the edge functions, but search doesn't work yet. Can you set up whatever the database needs to make search work end to end?\n\nSome documents are confidential, so users should only have access to documents they own.",
+ "promptSourcePath": "evals/build-vectors-001-rag-with-permissions/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/build-vectors-001-rag-with-permissions.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "deploy-database-001-prometheus-metrics",
+ "stage": "deploy",
+ "product": [
+ "database"
+ ],
+ "topic": [
+ "observability"
+ ],
+ "suite": "benchmark",
+ "passed": false,
+ "checks": [
+ {
+ "name": "preserved existing app scrape job",
+ "passed": true
+ },
+ {
+ "name": "configured the Supabase Metrics API scrape correctly",
+ "passed": false,
+ "judgeNotes": "Uses hardcoded basic_auth password instead of password_file, and docker-compose.yml does not mount or provide the password_file via volume or Compose secret. README also instructs using a Secret API key directly. Existing app scrape is preserved and endpoint/scheme/target path are otherwise correct."
+ },
+ {
+ "name": "documented live deployment and verification steps",
+ "passed": false,
+ "judgeNotes": "README includes reload and Prometheus Targets verification, but it instructs replacing a password placeholder directly in prometheus.yml instead of creating/placing a matching secret file. The Compose stack also does not mount/use a secret file, so the required secret setup is missing and would encourage hardcoding the Secret API key."
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"project metrics prometheus observability endpoint\", limit: 10) { nodes { __typename ... on Guide { title href content } ... on TroubleshootingGuide { title href content } ... on ManagementApiReference { title href content } } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics",
+ "title": "Metrics API"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic",
+ "title": "Vendor-agnostic Metrics API setup"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud",
+ "title": "Metrics API with Grafana Cloud"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted",
+ "title": "Metrics API with Prometheus & Grafana (self-hosted)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/read-replicas",
+ "title": "Read Replicas"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/how-to-view-database-metrics-uqf2z_",
+ "title": "How to View Database Metrics"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports",
+ "title": "Reports"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/connection-management",
+ "title": "Connection management"
+ }
+ ],
+ "resultChars": 72463
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 425258,
+ "outputTokens": 7606,
+ "cachedInputTokens": 370688
+ },
+ "durationMs": 77272,
+ "prompt": "Can you wire my Supabase project metrics into our existing observability stack and document\nin the observability README what we need to do to make the config live?",
+ "promptSourcePath": "evals/deploy-database-001-prometheus-metrics/PROMPT.md",
+ "attempts": 2,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/deploy-database-001-prometheus-metrics.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "deploy-functions-001-edge-function-secrets",
+ "stage": "deploy",
+ "product": [
+ "edge-functions"
+ ],
+ "topic": [
+ "security"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "passed": true,
+ "checks": [
+ {
+ "name": "WEATHER_API_KEY is set as a Function secret on the project",
+ "passed": true
+ },
+ {
+ "name": "the weather function is deployed to the project",
+ "passed": true,
+ "notes": "status ACTIVE"
+ },
+ {
+ "name": "the weather function reads WEATHER_API_KEY from the environment",
+ "passed": true,
+ "judgeNotes": "Reads WEATHER_API_KEY from the runtime environment via Deno.env.get(\"WEATHER_API_KEY\")."
+ },
+ {
+ "name": "WEATHER_API_KEY value is not committed to the repo",
+ "passed": true
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query {\n searchDocs(query: \"supabase secrets set env file functions deploy project ref\", limit: 5) {\n nodes {\n ... on CLICommandReference {\n title\n href\n content\n methodName\n language\n }\n ... on Guide {\n title\n href\n content\n }\n }\n totalCount\n }\n}",
+ "hasContent": true,
+ "pages": []
+ },
+ {
+ "source": "search_docs",
+ "query": "query {\n searchDocs(query: \"supabase secrets set env file functions deploy project ref\", limit: 5) {\n nodes {\n title\n href\n content\n }\n totalCount\n }\n}",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/branching/configuration",
+ "title": "Configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-transcribe-speech",
+ "title": "Transcription Telegram Bot"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/examples/push-notifications",
+ "title": "Sending Push Notifications"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-generate-speech-stream",
+ "title": "Streaming Speech with ElevenLabs"
+ }
+ ],
+ "resultChars": 48809
+ },
+ {
+ "source": "search_docs",
+ "query": "query {\n searchDocs(query: \"Edge Functions hosted URL project ref functions supabase.co invocation\", limit: 10) {\n nodes {\n title\n href\n content\n }\n totalCount\n }\n}",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/functions/storage-caching",
+ "title": "Integrating with Supabase Storage"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
+ "title": "Self-Hosted Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
+ "title": "Integrating With Supabase Auth"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/recursive-functions",
+ "title": "Recursive / Nested Function Calls"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions",
+ "title": "Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/architecture",
+ "title": "Edge Functions Architecture"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/quickstart-dashboard",
+ "title": "Getting Started with Edge Functions (Dashboard)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/integrations/supabase-for-platforms",
+ "title": "Supabase for Platforms"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/database-migrations",
+ "title": "Database migrations"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/storage/analytics/connecting-to-analytics-bucket",
+ "title": "Iceberg Catalog"
+ }
+ ],
+ "resultChars": 95305
+ },
+ {
+ "source": "search_docs",
+ "query": "query {\n searchDocs(query: \"management api invoke edge function project ref\", limit: 10) {\n nodes {\n title\n href\n content\n }\n totalCount\n }\n}",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/reference/api/v1-delete-a-project",
+ "title": "Deletes the given project"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/quickstart-dashboard",
+ "title": "Getting Started with Edge Functions (Dashboard)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
+ "title": "Self-Hosted Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/api/v1-create-a-function",
+ "title": "Create a function"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/api/v1-update-a-project",
+ "title": "Updates the given project"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/api/v1-deploy-a-function",
+ "title": "Deploy a function"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/api/v1-list-all-functions",
+ "title": "List all functions"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/api/v1-get-project",
+ "title": "Gets a specific project that belongs to the authenticated user"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/api/v1-get-project-function-combined-stats",
+ "title": "Gets a project's function combined statistics"
+ }
+ ],
+ "resultChars": 29028
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 2455866,
+ "outputTokens": 18062,
+ "cachedInputTokens": 2280576
+ },
+ "durationMs": 211800,
+ "prompt": "Our weather widget currently calls WeatherAPI straight from the browser, which\nleaks our API key. I want to move that behind a Supabase Edge Function called\n`weather` that holds the key server-side and proxies the request.\n\nThe function should read the key from an environment variable named\n`WEATHER_API_KEY`. Our key already lives in a local `.env` file at the project\nroot.\n\nDeploy the function to our project so it's live, and make sure the deployed\nfunction can actually read the key at runtime.",
+ "promptSourcePath": "evals/deploy-functions-001-edge-function-secrets/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/deploy-functions-001-edge-function-secrets.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "deploy-self-hosting-001-docker-compose",
+ "stage": "deploy",
+ "product": [
+ "database",
+ "auth",
+ "storage"
+ ],
+ "topic": [
+ "self-hosting"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "passed": true,
+ "checks": [
+ {
+ "name": "cloned the self-host stack (docker-compose.yml + volumes/db)",
+ "passed": true
+ },
+ {
+ "name": "didn't conflate with the CLI (no supabase/config.toml in the stack)",
+ "passed": true
+ },
+ {
+ "name": "secrets rotated off the shipped defaults",
+ "passed": true
+ },
+ {
+ "name": "ANON_KEY and SERVICE_ROLE_KEY are HS256 JWTs signed by JWT_SECRET",
+ "passed": true
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"self-hosting Docker compose secrets kong jwt anon service_role postgres pgbouncer gotrue storage studio meta vector config\", limit: 5) { nodes { title href content ... on Guide { subsections { nodes { title href content } } } } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#request-flows",
+ "title": "Request flows"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#unauthenticated-requests-api-key-only-no-user-session-jwt",
+ "title": "Unauthenticated requests (API key only, no user session JWT)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#backward-compatibility",
+ "title": "Backward compatibility"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#authenticated-requests-user-session-jwt",
+ "title": "Authenticated requests (user session JWT)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#additional-resources",
+ "title": "Additional resources"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#rotating-the-new-api-keys",
+ "title": "Rotating the new API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#regenerating-asymmetric-key-pair",
+ "title": "Regenerating asymmetric key pair"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#how-it-works",
+ "title": "How it works"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#what-client-sdk-sends",
+ "title": "What client SDK sends"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#kong-api-gateway-routing",
+ "title": "Kong API gateway routing"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#before-you-begin",
+ "title": "Before you begin"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#adding-the-new-keys",
+ "title": "Adding the new keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#new-api-keys-format",
+ "title": "New API keys format"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#verifying-the-setup",
+ "title": "Verifying the setup"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#environment-variables-configuration",
+ "title": "Environment variables configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#differences-from-the-supabase-platform",
+ "title": "Differences from the Supabase platform"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/remove-superuser-access",
+ "title": "Remove superuser access from Studio"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/remove-superuser-access#step-2-update-environment-variables-in-docker-composeyml",
+ "title": "Step 2: Update environment variables in docker-compose.yml"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/remove-superuser-access#step-1-update-database-object-ownership",
+ "title": "Step 1: Update database object ownership"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/remove-superuser-access#changing-the-configuration",
+ "title": "Changing the configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/remove-superuser-access#overview",
+ "title": "Overview"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/remove-superuser-access#verify-roles",
+ "title": "Verify roles"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/remove-superuser-access#step-3-restart-supabase",
+ "title": "Step 3: Restart Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17",
+ "title": "Upgrade to Postgres 17"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#custom-postgres-configuration",
+ "title": "Custom Postgres configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#troubleshooting",
+ "title": "Troubleshooting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#pg_upgrade-fails-with-replication-slot-errors",
+ "title": "pg_upgrade fails with replication slot errors"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#pgsodium--supabase-vault-errors",
+ "title": "pgsodium / Supabase Vault errors"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#services-fail-to-connect-after-upgrade",
+ "title": "Services fail to connect after upgrade"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#disk-space-issues-during-upgrade",
+ "title": "Disk space issues during upgrade"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#restoring-from-a-manual-backup",
+ "title": "Restoring from a manual backup"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#postgres-17-fails-to-start-with-a-leftover-db-config-volume",
+ "title": "Postgres 17 fails to start with a leftover db-config volume"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#upgrade-an-existing-postgres-15-deployment",
+ "title": "Upgrade an existing Postgres 15 deployment"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#new-deployment-with-postgres-17",
+ "title": "New deployment with Postgres 17"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#what-the-upgrade-does",
+ "title": "What the upgrade does"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#create-a-backup",
+ "title": "Create a backup"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#requirements",
+ "title": "Requirements"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#extensions-removed-in-postgres-17",
+ "title": "Extensions removed in Postgres 17"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#run-the-upgrade",
+ "title": "Run the upgrade"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#after-the-upgrade",
+ "title": "After the upgrade"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#before-you-begin",
+ "title": "Before you begin"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#rollback",
+ "title": "Rollback"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#upgrade-process-details",
+ "title": "Upgrade process details"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https",
+ "title": "Configure Reverse Proxy and HTTPS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#set-up-https",
+ "title": "Set up HTTPS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#before-you-begin",
+ "title": "Before you begin"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#step-4-restart-and-verify",
+ "title": "Step 4: Restart and verify"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#troubleshooting",
+ "title": "Troubleshooting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#certificate-not-issued",
+ "title": "Certificate not issued"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#websocket-connection-failed",
+ "title": "WebSocket connection failed"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#oauth-callback-url-mismatch",
+ "title": "OAuth callback URL mismatch"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#mixed-content-warnings",
+ "title": "Mixed content warnings"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#err_cert_authority_invalid",
+ "title": "ERR_CERT_AUTHORITY_INVALID"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#additional-resources",
+ "title": "Additional resources"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#step-2-configure-kong-for-ssl",
+ "title": "Step 2: Configure Kong for SSL"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#step-1-generate-a-self-signed-certificate",
+ "title": "Step 1: Generate a self-signed certificate"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#self-signed-certificates-development-only",
+ "title": "Self-signed certificates (development only)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#step-3-verify-https-connection",
+ "title": "Step 3: Verify HTTPS connection"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#step-2-start-the-reverse-proxy",
+ "title": "Step 2: Start the reverse proxy"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#step-3-update-configuration-variables",
+ "title": "Step 3: Update configuration variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#step-1-update-environment-variables",
+ "title": "Step 1: Update environment variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth",
+ "title": "Configure Social Login (OAuth) Providers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-1-register-your-app-with-the-provider",
+ "title": "Step 1: Register your app with the provider"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#before-you-begin",
+ "title": "Before you begin"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#oauth-request-flow",
+ "title": "OAuth request flow"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#auth-environment-variables",
+ "title": "Auth environment variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-by-step-configuration",
+ "title": "Step-by-step configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-2-configure-environment-variables",
+ "title": "Step 2: Configure environment variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-3-enable-the-matching-lines-in-docker-compose-configuration",
+ "title": "Step 3: Enable the matching lines in Docker Compose configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-4-restart-the-auth-service",
+ "title": "Step 4: Restart the auth service"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-5-verify-the-configuration",
+ "title": "Step 5: Verify the configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#provider-specific-setup",
+ "title": "Provider-specific setup"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#other-supported-providers",
+ "title": "Other supported providers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#test-the-login-flow",
+ "title": "Test the login flow"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#troubleshooting",
+ "title": "Troubleshooting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#variables-added-to-the-environment-but-provider-still-not-working",
+ "title": "Variables added to the environment but provider still not working"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#site-url-or-redirect-url-errors-after-login",
+ "title": "Site URL or redirect URL errors after login"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#nonce-check-failure-on-mobile-google-sign-in",
+ "title": "Nonce check failure on mobile (Google Sign In)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#auth-service-fails-to-start",
+ "title": "Auth service fails to start"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#environment-variable-reference",
+ "title": "Environment variable reference"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#additional-resources",
+ "title": "Additional resources"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17#permission-denied-on-the-data-directory"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#provider-not-enabled-or-provider-seen-as-false-in-settings"
+ }
+ ],
+ "resultChars": 203726
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Self-hosting with Docker quick start Linux generate-keys.sh docker-compose.yml .env.example utils/add-new-auth-keys.sh kong-entrypoint.sh\", limit: 10) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker",
+ "title": "Self-Hosting with Docker"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth",
+ "title": "Configure Social Login (OAuth) Providers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
+ "title": "Envoy API Gateway"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https",
+ "title": "Configure Reverse Proxy and HTTPS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
+ "title": "Self-Hosted Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates",
+ "title": "Custom Email Templates"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/enable-mcp",
+ "title": "Enabling MCP Server Access"
+ }
+ ],
+ "resultChars": 132033
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 632648,
+ "outputTokens": 9559,
+ "cachedInputTokens": 581248
+ },
+ "durationMs": 150786,
+ "prompt": "I'm moving off the hosted Supabase and running the whole thing myself on a VPS I\njust spun up. Can you get a Docker setup ready for me to copy onto the box?\n\nI don't need it running here, I'll do the actual bring-up once I'm on the\nserver. I just want everything in place and the secrets set up. Put it in a `supabase-docker/`\nfolder at the repo root so I can scp the whole thing across in one go.",
+ "promptSourcePath": "evals/deploy-self-hosting-001-docker-compose/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/deploy-self-hosting-001-docker-compose.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "investigate-auth-001-deleted-user-access",
+ "stage": "investigate",
+ "product": [
+ "auth"
+ ],
+ "topic": [
+ "security",
+ "sdk"
+ ],
+ "suite": "benchmark",
+ "interface": "mcp",
+ "passed": false,
+ "checks": [
+ {
+ "name": "victim session active before delete-account",
+ "passed": true
+ },
+ {
+ "name": "delete_account flow ran for the victim",
+ "passed": true
+ },
+ {
+ "name": "delete-account revokes the user's sessions",
+ "passed": true,
+ "notes": "sessions left: 0"
+ },
+ {
+ "name": "deleted user's refresh token is rejected",
+ "passed": true
+ },
+ {
+ "name": "deleted user cannot sign back in",
+ "passed": false,
+ "notes": "deleted account can still sign in"
+ },
+ {
+ "name": "other users keep their sessions and access",
+ "passed": true
+ },
+ {
+ "name": "diagnosed and explained session revocation",
+ "passed": false,
+ "judgeNotes": "Fails because the implemented delete flow still does not delete the Supabase auth user or remove identities; it only soft-deletes the profile and deletes sessions. That revokes current sessions/refresh tokens but does not prevent the same auth user/identity from signing in again. The answer also under-identifies the original auth-layer bug, focusing on RLS rather than the missing auth user/identity deletion. Key explanation and RLS-based data-access window are mostly consistent, but the core revocation/sign-in fix is incomplete."
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Supabase publishable secret anon service_role keys frontend RLS\", limit: 5) { nodes { title href content ... on Guide { subsections { nodes { title href content } } } } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/database/secure-data",
+ "title": "Securing your data"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/secure-data#more-information",
+ "title": "More information"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/secure-data#edge-functions",
+ "title": "Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/secure-data#direct-database-connections",
+ "title": "Direct database connections"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/secure-data#frontend-access",
+ "title": "Frontend access"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/secure-data#data-api",
+ "title": "Data API"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/secure-data#connecting-your-app-securely",
+ "title": "Connecting your app securely"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs",
+ "title": "Build a User Management App with RedwoodJS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#create-an-upload-widget",
+ "title": "Create an upload widget"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#launch",
+ "title": "Launch!"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#see-also",
+ "title": "See also"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#initialize-a-redwoodjs-app",
+ "title": "Initialize a RedwoodJS app"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#about-redwoodjs",
+ "title": "About RedwoodJS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#project-setup",
+ "title": "Project setup"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#create-a-project",
+ "title": "Create a project"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#set-up-the-database-schema",
+ "title": "Set up the database schema"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#get-api-details",
+ "title": "Get API details"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#building-the-app",
+ "title": "Building the app"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#app-styling-optional",
+ "title": "App styling (optional)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#start-redwoodjs-and-your-first-page",
+ "title": "Start RedwoodJS and your first page"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#set-up-a-login-component",
+ "title": "Set up a login component"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#set-up-an-account-component",
+ "title": "Set up an account component"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#update-home-page",
+ "title": "Update home page"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs#profile-photos",
+ "title": "Profile photos"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys#step-1-create-the-new-api-keys",
+ "title": "Step 1: Create the new API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys#step-2-swap-the-publishable-key-in-client-code",
+ "title": "Step 2: Swap the publishable key in client code"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys#step-3-swap-the-secret-key-in-backend-code",
+ "title": "Step 3: Swap the secret key in backend code"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys#database-webhooks-and-pg_net",
+ "title": "Database Webhooks and pg_net"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys#step-4-update-edge-functions",
+ "title": "Step 4: Update Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys#option-1-read-the-new-keys-from-the-environment",
+ "title": "Option 1: Read the new keys from the environment"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys#option-2-adopt-the-supabaseserver-sdk",
+ "title": "Option 2: Adopt the @supabase/server SDK"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys#step-5-verify-nothing-uses-the-legacy-keys",
+ "title": "Step 5: Verify nothing uses the legacy keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys#step-6-deactivate-the-legacy-keys",
+ "title": "Step 6: Deactivate the legacy keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys#known-limitations",
+ "title": "Known limitations"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys#next-steps",
+ "title": "Next steps"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys#before-you-start",
+ "title": "Before you start"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys",
+ "title": "Understanding API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys#security-considerations",
+ "title": "Security considerations"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys#interaction-with-supabase-auth",
+ "title": "Interaction with Supabase Auth"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys#known-limitations-and-compatibility-differences",
+ "title": "Known limitations and compatibility differences"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys#publishable-keys",
+ "title": "Publishable keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys#overview",
+ "title": "Overview"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys#what-to-do-if-a-secret-key-or-service_role-has-been-leaked-or-compromised",
+ "title": "What to do if a secret key or service_role has been leaked or compromised?"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys#best-practices-for-handling-secret-keys",
+ "title": "Best practices for handling secret keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys#what-secret-keys-allow-access-to",
+ "title": "What secret keys allow access to"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#specify-roles-in-your-policies",
+ "title": "Specify roles in your policies"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#add-indexes",
+ "title": "Add indexes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks",
+ "title": "Benchmarks"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#call-functions-with-select",
+ "title": "Call functions with select"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-1",
+ "title": "Benchmarks"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#add-filters-to-every-query",
+ "title": "Add filters to every query"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-2",
+ "title": "Benchmarks"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#use-security-definer-functions",
+ "title": "Use security definer functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#minimize-joins",
+ "title": "Minimize joins"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#row-level-security-in-supabase",
+ "title": "Row Level Security in Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#policies",
+ "title": "Policies"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#enabling-row-level-security",
+ "title": "Enabling Row Level Security"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#auto-enable-rls-for-new-tables",
+ "title": "Auto-enable RLS for new tables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#authenticated-and-unauthenticated-roles",
+ "title": "Authenticated and unauthenticated roles"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#creating-policies",
+ "title": "Creating policies"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#select-policies",
+ "title": "SELECT policies"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#insert-policies",
+ "title": "INSERT policies"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#update-policies",
+ "title": "UPDATE policies"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#delete-policies",
+ "title": "DELETE policies"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#views",
+ "title": "Views"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#helper-functions",
+ "title": "Helper functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#authuid",
+ "title": "auth.uid()"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#authjwt",
+ "title": "auth.jwt()"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#mfa",
+ "title": "MFA"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#bypassing-row-level-security",
+ "title": "Bypassing Row Level Security"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#rls-performance-recommendations",
+ "title": "RLS performance recommendations"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#more-resources",
+ "title": "More resources"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-4",
+ "title": "Benchmarks"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-3",
+ "title": "Benchmarks"
+ }
+ ],
+ "resultChars": 247461
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 321226,
+ "outputTokens": 9972,
+ "cachedInputTokens": 265728
+ },
+ "durationMs": 92519,
+ "prompt": "Last week support removed a user through our app's delete-account flow — the\napp calls the `delete_account` function over RPC as the signed-in user. This\nmorning that same person was back: still signed in, reading and saving their\ndata like nothing happened.\n\nFigure out why the account still works, fix the flow so a deleted account\nloses access, and tell me whether there is any window where they could still\nget in after the fix.\n\nOne more thing while you're at it: we're migrating off the legacy\nanon/service_role API keys to the new publishable and secret keys, and the\nteam isn't sure which one belongs in the frontend and what each means for\nRLS. Give us a quick rundown.",
+ "promptSourcePath": "evals/investigate-auth-001-deleted-user-access/PROMPT.md",
+ "attempts": 2,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/investigate-auth-001-deleted-user-access.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "investigate-realtime-001-subscribed-no-events",
+ "stage": "investigate",
+ "product": [
+ "realtime",
+ "database"
+ ],
+ "topic": [
+ "sdk"
+ ],
+ "suite": "benchmark",
+ "interface": "mcp",
+ "passed": true,
+ "checks": [
+ {
+ "name": "orders table added to supabase_realtime publication",
+ "passed": true
+ },
+ {
+ "name": "courier_locations still in supabase_realtime publication",
+ "passed": true
+ },
+ {
+ "name": "publication still publishes INSERT events",
+ "passed": true
+ },
+ {
+ "name": "RLS still enabled on orders",
+ "passed": true
+ },
+ {
+ "name": "staff can still read orders through RLS",
+ "passed": true,
+ "notes": "authenticated sees 2 of 2 orders"
+ },
+ {
+ "name": "diagnosed missing publication membership",
+ "passed": true,
+ "judgeNotes": "Identified orders missing from supabase_realtime publication despite subscription working, added public.orders with ALTER PUBLICATION, preserved courier_locations and did not alter RLS/policies."
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 216110,
+ "outputTokens": 2955,
+ "cachedInputTokens": 196224
+ },
+ "durationMs": 49598,
+ "prompt": "Our dispatch dashboard shows incoming orders as they happen. The courier\nlocation feed on the same page updates live without problems, but new orders\nonly show up after a page refresh.\n\nThe dashboard uses supabase-js to subscribe to INSERT events on the `orders`\ntable through postgres_changes, the same way it subscribes to courier\nlocations. The channel's status callback logs SUBSCRIBED and there are no\nerrors in the browser console.\n\nFigure out why no order events ever arrive and fix it.",
+ "promptSourcePath": "evals/investigate-realtime-001-subscribed-no-events/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/investigate-realtime-001-subscribed-no-events.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "investigate-reliability-003-edge-function-5xx-correlation",
+ "stage": "investigate",
+ "product": [
+ "edge-functions"
+ ],
+ "topic": [
+ "observability"
+ ],
+ "suite": "benchmark",
+ "interface": "mcp",
+ "passed": true,
+ "checks": [
+ {
+ "name": "identified image-transform and the recurring 503 pattern",
+ "passed": true,
+ "judgeNotes": "Identified image-transform as the affected function and described the recurring HTTP 503 pattern across the morning of 2026-04-28, including all 8 gateway failures from 07:00Z through 12:00Z."
+ },
+ {
+ "name": "attributed recurring 503s to gateway/platform layer, not function code",
+ "passed": true,
+ "judgeNotes": "The assistant clearly attributes the recurring image-transform 503s to the Supabase gateway/routing/platform layer rather than function code. It grounds this in valid observations: API/gateway logs show repeated 503s, while Edge-function logs show nearby successful 200 invocations on the same deployment/version with low latency, and it distinguishes these gateway 503s from the separate avatar-upload function-level 500."
+ },
+ {
+ "name": "recommended a concrete next step",
+ "passed": true,
+ "judgeNotes": "Recommended concrete next steps, including treating the 503s as a platform incident and opening/attaching a Supabase support case with exact timestamps and deployment IDs, plus retries and improved error logging."
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 137605,
+ "outputTokens": 4646,
+ "cachedInputTokens": 106368
+ },
+ "durationMs": 47004,
+ "prompt": "Users have been reporting that image uploads are intermittently failing with server errors throughout the morning of `2026-04-28`.\n\nCan you investigate the project logs and tell me what is going on and what we\nshould do next?",
+ "promptSourcePath": "evals/investigate-reliability-003-edge-function-5xx-correlation/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/investigate-reliability-003-edge-function-5xx-correlation.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "resolve-dataapi-001-empty-results",
+ "stage": "resolve",
+ "product": [
+ "data-api",
+ "database",
+ "auth"
+ ],
+ "topic": [
+ "rls",
+ "sdk"
+ ],
+ "suite": "benchmark",
+ "interface": "mcp",
+ "passed": true,
+ "checks": [
+ {
+ "name": "RLS still enabled on bookmarks",
+ "passed": true
+ },
+ {
+ "name": "user A reads own bookmarks",
+ "passed": true
+ },
+ {
+ "name": "user B cannot read user A bookmarks",
+ "passed": true
+ },
+ {
+ "name": "anon reads no bookmarks",
+ "passed": true
+ },
+ {
+ "name": "user A can save a new bookmark",
+ "passed": true
+ },
+ {
+ "name": "user B cannot insert a bookmark as user A",
+ "passed": true
+ },
+ {
+ "name": "diagnosed RLS and added owner-scoped policies",
+ "passed": true,
+ "judgeNotes": "Diagnosed RLS deny-all due to no policies, created authenticated SELECT and INSERT policies scoped to user_id = auth.uid(), and kept RLS enabled."
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 127261,
+ "outputTokens": 2198,
+ "cachedInputTokens": 111104
+ },
+ "durationMs": 42020,
+ "prompt": "Our app lets signed-in users save bookmarks and view them on their dashboard. Bookmarks are stored in the `bookmarks` table and are private — a user must only ever see their own. \nUsers also need to be able to save new bookmarks from the app.\n\nI can see the rows when I query the table directly, but the dashboard shows an empty list for every user.\n\nFind out why the Data API returns nothing and fix it.",
+ "promptSourcePath": "evals/resolve-dataapi-001-empty-results/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/resolve-dataapi-001-empty-results.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "resolve-database-001-migration-history-mismatch",
+ "stage": "resolve",
+ "product": [
+ "database"
+ ],
+ "topic": [
+ "migrations"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "passed": false,
+ "checks": [
+ {
+ "name": "the avatar_url column is applied on the hosted profiles table",
+ "passed": true
+ },
+ {
+ "name": "migration 20240220000000 is recorded in the remote history",
+ "passed": true
+ },
+ {
+ "name": "remote migration history matches local migration files",
+ "passed": true
+ },
+ {
+ "name": "local migrations are a valid reconciled sequence",
+ "passed": true
+ },
+ {
+ "name": "production profile data is intact (not reset)",
+ "passed": true
+ },
+ {
+ "name": "the avatar migration and history reconciliation were done via the Supabase CLI",
+ "passed": false,
+ "judgeNotes": "FAIL: avatar_url was applied via direct psql SQL (#29: ALTER TABLE ... ADD COLUMN avatar_url), not via a successful supabase db push. Migration history was also edited directly (#30: INSERT into supabase_migrations.schema_migrations), not reconciled via Supabase CLI repair/pull/push. No supabase db push succeeded; all push attempts errored."
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 297514,
+ "outputTokens": 9872,
+ "cachedInputTokens": 260096
+ },
+ "durationMs": 103823,
+ "prompt": "I'm trying to ship a migration to our hosted project and it's not working. Can you figure out what's wrong and get it deployed?",
+ "promptSourcePath": "evals/resolve-database-001-migration-history-mismatch/PROMPT.md",
+ "attempts": 2,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/resolve-database-001-migration-history-mismatch.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "resolve-performance-001-slow-query-cpu-spike",
+ "stage": "resolve",
+ "product": [
+ "database"
+ ],
+ "topic": [
+ "observability",
+ "sql"
+ ],
+ "suite": "benchmark",
+ "interface": "mcp",
+ "passed": true,
+ "checks": [
+ {
+ "name": "inspected pg_stat_statements for query performance",
+ "passed": true
+ },
+ {
+ "name": "ran EXPLAIN on the expensive query",
+ "passed": true
+ },
+ {
+ "name": "created index covering user_id and created_at",
+ "passed": true
+ },
+ {
+ "name": "query plan uses an index and avoids sequential scan",
+ "passed": true,
+ "notes": "Limit (cost=0.28..119.10 rows=50 width=58)\n -> Index Scan using events_user_id_created_at_idx on events (cost=0.28..237.92 rows=100 width=58)\n Index Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)"
+ },
+ {
+ "name": "inserts still work",
+ "passed": true
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 221537,
+ "outputTokens": 5659,
+ "cachedInputTokens": 205696
+ },
+ "durationMs": 56035,
+ "prompt": "My database CPU keeps spiking and the app gets slow when loading recent events for a user. Can you figure out what query is causing it and make the database change needed to fix it?\n\nEnd your turn with a short summary of what you changed and why.",
+ "promptSourcePath": "evals/resolve-performance-001-slow-query-cpu-spike/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/resolve-performance-001-slow-query-cpu-spike.json"
+ },
+ {
+ "experiment": "codex-gpt-5.4-mini-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.4-mini",
+ "reasoningEffort": "medium"
+ },
+ "eval": "resolve-security-002-rls-cross-tenant-leak",
+ "stage": "resolve",
+ "product": [
+ "database",
+ "auth"
+ ],
+ "topic": [
+ "rls",
+ "security"
+ ],
+ "suite": "benchmark",
+ "interface": "mcp",
+ "passed": true,
+ "checks": [
+ {
+ "name": "RLS enabled on notes",
+ "passed": true
+ },
+ {
+ "name": "tenant A sees only org A notes",
+ "passed": true
+ },
+ {
+ "name": "tenant B cannot read org A notes",
+ "passed": true
+ },
+ {
+ "name": "tenant A author can update own note",
+ "passed": true
+ },
+ {
+ "name": "tenant B cannot update org A note",
+ "passed": true
+ },
+ {
+ "name": "tenant B author can delete own note",
+ "passed": true
+ },
+ {
+ "name": "tenant B cannot delete org A note",
+ "passed": true
+ },
+ {
+ "name": "tenant A can insert note in own org",
+ "passed": true
+ },
+ {
+ "name": "tenant B cannot insert into org A",
+ "passed": true
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 111051,
+ "outputTokens": 2147,
+ "cachedInputTokens": 94336
+ },
+ "durationMs": 32894,
+ "prompt": "A customer reported that notes showed up in the wrong workspace.\n\nCan you investigate what is going on and fix it?",
+ "promptSourcePath": "evals/resolve-security-002-rls-cross-tenant-leak/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.4-mini-no-skills/resolve-security-002-rls-cross-tenant-leak.json"
+ },
+ {
+ "experiment": "codex-gpt-5.6",
+ "experimentSuite": "benchmark",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.6-sol",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-cli-001-bootstrap-app",
+ "stage": "build",
+ "product": [
+ "database",
+ "data-api"
+ ],
+ "topic": [
+ "migrations",
+ "rls"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "passed": true,
+ "checks": [
+ {
+ "name": "supabase project initialised (supabase/config.toml exists)",
+ "passed": true
+ },
+ {
+ "name": "todos table is created by a migration file",
+ "passed": true
+ },
+ {
+ "name": "todos table exists with at least 2 seeded rows",
+ "passed": true,
+ "notes": "found 2 rows"
+ },
+ {
+ "name": "row level security is enabled on todos",
+ "passed": true
+ },
+ {
+ "name": "a SELECT policy targets the authenticated role",
+ "passed": true
+ },
+ {
+ "name": "REST API returns no todos to anonymous requests",
+ "passed": true,
+ "notes": "0 rows"
+ },
+ {
+ "name": "REST API returns the todos to authenticated requests",
+ "passed": true,
+ "notes": "2 rows"
+ }
+ ],
+ "skills": {
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"local development migrations seed.sql RLS authenticated role Data API grants select policy\", limit: 6) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/api/securing-your-api",
+ "title": "Securing your API"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#pull-based-queue",
- "title": "Pull-Based Queue"
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows",
+ "title": "Local development workflow"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#message",
- "title": "Message"
+ "url": "https://supabase.com/docs/guides/resources/glossary",
+ "title": "Glossary"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#create-queues",
- "title": "Create Queues"
+ "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
+ "title": "Token Security and Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#what-happens-when-you-create-a-queue",
- "title": "What happens when you create a queue?"
+ "url": "https://supabase.com/docs/guides/storage/schema/helper-functions",
+ "title": "Storage Helper Functions"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#expose-queues-to-client-side-consumers",
- "title": "Expose Queues to client-side consumers"
- },
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended",
+ "title": "Advanced pgTAP Testing"
+ }
+ ],
+ "resultChars": 96104
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 1337061,
+ "outputTokens": 6071,
+ "cachedInputTokens": 1238453
+ },
+ "durationMs": 402057,
+ "prompt": "We're kicking off a todos app and I want the Supabase side ready for the team\nto build on. Set it up the way we'd run it in development, with schema changes\ntracked as migrations so they can be reviewed and replayed.\n\nFor the first slice we just need a `todos` table. Todos aren't public: anyone\nsigned in can read all of them, but nothing should be writable through the API\nfor now. Add a couple of sample todos so there's something to look at.\n\nBefore you hand it back, make sure the running API actually behaves that way —\nsigned-in users get the todos, signed-out requests get nothing.",
+ "promptSourcePath": "evals/build-cli-001-bootstrap-app/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.6/build-cli-001-bootstrap-app.json"
+ },
+ {
+ "experiment": "codex-gpt-5.6",
+ "experimentSuite": "benchmark",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.6-sol",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-cli-002-declarative-schema",
+ "stage": "build",
+ "product": [
+ "database"
+ ],
+ "topic": [
+ "declarative-schema",
+ "migrations"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "passed": true,
+ "checks": [
+ {
+ "name": "supabase db diff used to generate the migration",
+ "passed": true
+ },
+ {
+ "name": "schema file updated to include description column",
+ "passed": true
+ },
+ {
+ "name": "a new migration was generated for the change",
+ "passed": true
+ },
+ {
+ "name": "description column exists in the live database",
+ "passed": true
+ }
+ ],
+ "skills": {
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"local development declarative schemas schema_paths generate migration db diff\", limit: 5) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#enable-rls-on-your-tables-in-pgmq-schema",
- "title": "Enable RLS on your tables in pgmq schema"
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas",
+ "title": "Declarative database schemas"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#grant-permissions-to-pgmq_public-database-functions",
- "title": "Grant permissions to pgmq_public database functions"
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations",
+ "title": "Database Migrations"
},
{
- "url": "https://supabase.com/docs/guides/queues/quickstart#enqueueing-and-dequeueing-messages",
- "title": "Enqueueing and dequeueing messages"
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows",
+ "title": "Local development workflow"
},
{
- "url": "https://supabase.com/docs/guides/queues/api",
- "title": "API"
+ "url": "https://supabase.com/docs/guides/deployment/managing-environments",
+ "title": "Managing Environments"
},
{
- "url": "https://supabase.com/docs/guides/queues/api#pgmq_publicpopqueue_name",
- "title": "pgmq_public.pop(queue_name)"
- },
+ "url": "https://supabase.com/docs/reference/cli/supabase-db-diff",
+ "title": "Diffs the local database for schema changes"
+ }
+ ],
+ "resultChars": 72112
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 201981,
+ "outputTokens": 1832,
+ "cachedInputTokens": 174044
+ },
+ "durationMs": 104249,
+ "prompt": "Add a description text column to the `products` table in my local Supabase stack",
+ "promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.6/build-cli-002-declarative-schema.json"
+ },
+ {
+ "experiment": "codex-gpt-5.6",
+ "experimentSuite": "benchmark",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.6-sol",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-cli-003-pg-cron-queue-workflow",
+ "stage": "build",
+ "product": [
+ "database",
+ "edge-functions",
+ "cron",
+ "queues"
+ ],
+ "topic": [
+ "sql",
+ "sdk"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "passed": true,
+ "checks": [
+ {
+ "name": "pg_cron job 'enqueue-tasks' scheduled to run every minute",
+ "passed": true,
+ "notes": "schedule='* * * * *', active=true"
+ },
+ {
+ "name": "cron command enqueues to the 'tasks' queue",
+ "passed": true,
+ "notes": "queue depth 0 -> 1"
+ },
+ {
+ "name": "process-tasks function drains the queue",
+ "passed": true,
+ "notes": "function removed the seeded message (id 36) from the queue"
+ }
+ ],
+ "skills": {
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Supabase Queues pgmq create queue send read delete archive SQL cron schedule every minute Edge Function\", limit: 8) { nodes { __typename title href content } } }",
+ "hasContent": true,
+ "pages": [
{
- "url": "https://supabase.com/docs/guides/queues/api#pgmq_publicsendqueue_name-message-sleep_seconds",
- "title": "pgmq_public.send(queue_name, message, sleep_seconds)"
+ "url": "https://supabase.com/docs/guides/cron",
+ "title": "Cron"
},
{
- "url": "https://supabase.com/docs/guides/queues/api#pgmq_publicsend_batchqueue_name-messages-sleep_seconds",
- "title": "pgmq_public.send_batch(queue_name, messages, sleep_seconds)"
+ "url": "https://supabase.com/docs/guides/functions/schedule-functions",
+ "title": "Scheduling Edge Functions"
},
{
- "url": "https://supabase.com/docs/guides/queues/api#pgmq_publicreadqueue_name-sleep_seconds-n",
- "title": "pgmq_public.read(queue_name, sleep_seconds, n)"
+ "url": "https://supabase.com/docs/guides/queues",
+ "title": "Supabase Queues"
},
{
- "url": "https://supabase.com/docs/guides/queues/api#pgmq_publicarchivequeue_name-message_id",
- "title": "pgmq_public.archive(queue_name, message_id)"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net",
+ "title": "pg_net: Async Networking"
},
{
- "url": "https://supabase.com/docs/guides/queues/api#pgmq_publicdeletequeue_name-message_id",
- "title": "pgmq_public.delete(queue_name, message_id)"
+ "url": "https://supabase.com/docs/guides/cron/quickstart",
+ "title": "Quickstart"
},
{
"url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions",
"title": "Consuming Supabase Queue Messages with Edge Functions"
},
{
- "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions#consuming-messages-in-an-edge-function",
- "title": "Consuming messages in an Edge Function"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions#concepts",
- "title": "Concepts"
- },
- {
- "url": "https://supabase.com/docs/guides/database/functions",
- "title": "Database Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/database/functions#error-handling",
- "title": "Error handling"
- },
- {
- "url": "https://supabase.com/docs/guides/database/functions#general-logging",
- "title": "General logging"
- },
- {
- "url": "https://supabase.com/docs/guides/database/functions#create-database-functions",
- "title": "Create Database Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/database/functions#deep-dive",
- "title": "Deep dive"
- },
- {
- "url": "https://supabase.com/docs/guides/database/functions#resources",
- "title": "Resources"
- },
- {
- "url": "https://supabase.com/docs/guides/database/functions#advanced-logging",
- "title": "Advanced logging"
- },
- {
- "url": "https://supabase.com/docs/guides/database/functions#function-privileges",
- "title": "Function privileges"
- },
- {
- "url": "https://supabase.com/docs/guides/database/functions#security-definer-vs-invoker",
- "title": "Security definer vs invoker"
- },
- {
- "url": "https://supabase.com/docs/guides/database/functions#database-functions-vs-edge-functions",
- "title": "Database Functions vs Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/database/functions#suggestions",
- "title": "Suggestions"
- },
- {
- "url": "https://supabase.com/docs/guides/database/functions#passing-parameters",
- "title": "Passing parameters"
- },
- {
- "url": "https://supabase.com/docs/guides/database/functions#returning-data-sets",
- "title": "Returning data sets"
+ "url": "https://supabase.com/docs/guides/cron/install",
+ "title": "Install"
},
{
- "url": "https://supabase.com/docs/guides/database/functions#simple-functions",
- "title": "Simple functions"
- },
+ "url": "https://supabase.com/docs/guides/queues/api",
+ "title": "API"
+ }
+ ],
+ "resultChars": 36594
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Supabase Queues quickstart create queue pgmq.create Edge Function read delete SUPABASE_SERVICE_ROLE_KEY\", limit: 6) { nodes { __typename title href content } } }",
+ "hasContent": true,
+ "pages": [
{
- "url": "https://supabase.com/docs/guides/database/functions#getting-started",
- "title": "Getting started"
+ "url": "https://supabase.com/docs/guides/queues/quickstart",
+ "title": "Quickstart"
},
{
- "url": "https://supabase.com/docs/guides/database/functions#quick-demo",
- "title": "Quick demo"
+ "url": "https://supabase.com/docs/guides/queues/api",
+ "title": "API"
},
{
- "url": "https://supabase.com/docs/guides/database/functions#debugging-functions",
- "title": "Debugging functions"
+ "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions",
+ "title": "Consuming Supabase Queue Messages with Edge Functions"
},
{
- "url": "https://supabase.com/docs/guides/database/functions#using-database-functions-to-call-an-external-api",
- "title": "Using Database Functions to call an external API"
+ "url": "https://supabase.com/docs/guides/queues",
+ "title": "Supabase Queues"
},
{
- "url": "https://supabase.com/docs/guides/database/functions#call-database-functions-using-javascript",
- "title": "Call Database Functions using JavaScript"
+ "url": "https://supabase.com/docs/guides/database/extensions/pgmq",
+ "title": "pgmq: Queues"
},
{
- "url": "https://supabase.com/docs/reference/javascript/rpc"
+ "url": "https://supabase.com/docs/guides/queues/expose-self-hosted-queues",
+ "title": "Expose Queues for local and self-hosted Supabase"
}
],
- "resultChars": 288356
+ "resultChars": 22338
}
]
},
+ "usage": {
+ "inputTokens": 1331536,
+ "outputTokens": 5876,
+ "cachedInputTokens": 1277245
+ },
+ "durationMs": 229741,
"prompt": "I want to set up a recurring background workflow on my local Supabase stack.\n\nCan you set up a cron job called `enqueue-tasks` to run every minute and push a task into a queue called `tasks`? Then add a `process-tasks` edge function that reads messages off the `tasks` queue and removes them, so a scheduled worker can keep the backlog drained.",
"promptSourcePath": "evals/build-cli-003-pg-cron-queue-workflow/PROMPT.md",
"attempts": 1,
@@ -11818,41 +14735,48 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"restore existing PostgreSQL pg_dump custom binary dump local Supabase pg_restore roles schema migration\", limit: 5) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } ... on TroubleshootingGuide { title href content } } } }",
+ "query": "query { searchDocs(query: \"restore pg_restore custom format dump local Supabase CLI existing database migration\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
- {
- "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
- "title": "Restore a Platform Project to Self-Hosted"
- },
{
"url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres",
"title": "Migrate from Postgres to Supabase"
},
{
- "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/vercel-postgres",
- "title": "Migrate from Vercel Postgres to Supabase"
- },
- {
- "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/neon",
- "title": "Migrate from Neon to Supabase"
+ "url": "https://supabase.com/docs/guides/platform/migrating-within-supabase/backup-restore",
+ "title": "Backup and Restore using the CLI"
},
{
"url": "https://supabase.com/docs/guides/local-development/restoring-downloaded-backup",
"title": "Restoring a downloaded backup locally"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
+ "title": "Restore a Platform Project to Self-Hosted"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/vercel-postgres",
+ "title": "Migrate from Vercel Postgres to Supabase"
}
],
- "resultChars": 42818
+ "resultChars": 75030
}
]
},
+ "usage": {
+ "inputTokens": 1062256,
+ "outputTokens": 3920,
+ "cachedInputTokens": 992167
+ },
+ "durationMs": 313340,
"prompt": "I have an existing Postgres database I want to migrate to Supabase. There's a binary dump at `source.dump` in the current directory.\n\nCan you set up a local Supabase project and restore the dump into it?",
"promptSourcePath": "evals/build-database-001-migrate-postgres-to-supabase/PROMPT.md",
"attempts": 1,
@@ -11915,16 +14839,21 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Edge Functions authorization JWT getUser Authorization header service role row level security\", limit: 5) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } ... on ClientLibraryFunctionReference { title href content language methodName } } } }",
+ "query": "query { searchDocs(query: \"Edge Functions authentication Authorization header getUser createClient service role RLS\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
+ "title": "Why is my service role key client getting RLS errors or not returning data?"
+ },
{
"url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs",
"title": "Build a User Management App with Next.js"
@@ -11934,66 +14863,295 @@
"title": "Integrating With Supabase Auth"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-headers",
- "title": "Authorization headers"
+ "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
+ "title": "Storage Buckets"
},
{
- "url": "https://supabase.com/docs/guides/auth/auth-mfa",
- "title": "Multi-Factor Authentication"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api",
+ "title": "Securing your API"
+ }
+ ],
+ "resultChars": 75066
+ },
+ {
+ "source": "web_search",
+ "query": "https://supabase.com/changelog.md",
+ "pages": [
+ {
+ "url": "https://supabase.com/changelog.md"
+ }
+ ]
+ },
+ {
+ "source": "web_search",
+ "query": "site:supabase.com/changelog.md Supabase changelog Edge Functions breaking change",
+ "pages": []
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 841466,
+ "outputTokens": 5351,
+ "cachedInputTokens": 799565
+ },
+ "durationMs": 142816,
+ "prompt": "I built an Edge Function called `private-notes` for showing a user's saved\nprivate notes.\n\nCan you check whether there's any way one user could see another user's notes?\n\nPlease fix and deploy it if needed.",
+ "promptSourcePath": "evals/build-functions-004-service-role-bypass/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.6/build-functions-004-service-role-bypass.json"
+ },
+ {
+ "experiment": "codex-gpt-5.6",
+ "experimentSuite": "benchmark",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.6-sol",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-functions-005-dual-auth-user-secret",
+ "stage": "build",
+ "product": [
+ "edge-functions",
+ "auth",
+ "database"
+ ],
+ "topic": [
+ "sdk",
+ "rls",
+ "security"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "cliVersion": "2.109.1",
+ "passed": true,
+ "checks": [
+ {
+ "name": "seed rows present",
+ "passed": true,
+ "notes": "found 2/2 seeded rows"
+ },
+ {
+ "name": "rejects request with no credentials",
+ "passed": true,
+ "notes": "status 401: {\"error\":\"Unauthorized\"}"
+ },
+ {
+ "name": "user with JWT reads only their own rows",
+ "passed": true,
+ "notes": "status 200: [{\"user_id\":\"b5eee0f6-2b39-4753-a8cc-3d9a18444d77\",\"metric\":\"steps_a_ms7qfmor\",\"value\":111}]"
+ },
+ {
+ "name": "user cannot read another user's rows by passing user_id",
+ "passed": true,
+ "notes": "status 200: [{\"user_id\":\"b5eee0f6-2b39-4753-a8cc-3d9a18444d77\",\"metric\":\"steps_a_ms7qfmor\",\"value\":111}]"
+ },
+ {
+ "name": "service key bypasses RLS to read the target user's rows",
+ "passed": true,
+ "notes": "status 200: [{\"user_id\":\"7c5d7d63-4508-4e45-bc54-37920e1fb44c\",\"metric\":\"steps_b_ms7qfmor\",\"value\":222}]"
+ },
+ {
+ "name": "non-service key is not granted service access",
+ "passed": true,
+ "notes": "status 401: {\"error\":\"Unauthorized\"}"
+ },
+ {
+ "name": "rejects an unverified (forged) user token",
+ "passed": true,
+ "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
+ },
+ {
+ "name": "a user token in the apikey slot is not treated as the service key",
+ "passed": true,
+ "notes": "status 401: {\"error\":\"Unauthorized\"}"
+ },
+ {
+ "name": "implementation uses @supabase/server",
+ "passed": true,
+ "notes": "imports @supabase/server / withSupabase"
+ }
+ ],
+ "skills": {
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Edge Functions authentication verify_jwt service role apikey header getUser authorization supabase-js\", limit: 8) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
+ "title": "Integrating With Supabase Auth"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys",
+ "title": "Understanding API keys"
},
{
"url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
"title": "New API Keys and Asymmetric Authentication"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/jwts",
+ "title": "JSON Web Token (JWT)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth-headers",
+ "title": "Authorization headers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/websockets",
+ "title": "Handling WebSockets"
+ }
+ ],
+ "resultChars": 82810
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"supabase config.toml functions verify_jwt false Edge Functions per function configuration\", limit: 5) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/functions/function-configuration",
+ "title": "Function Configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/development-tips",
+ "title": "Development tips"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/deploy",
+ "title": "Deploy to Production"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/examples/mcp-server-mcp-lite",
+ "title": "Building an MCP Server with mcp-lite"
}
],
- "resultChars": 85366
+ "resultChars": 32331
},
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase Edge Functions authenticate user Authorization header createClient getUser RLS\", limit: 8) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } ... on ClientLibraryFunctionReference { title href content language methodName } } } }",
+ "query": "query { searchDocs(query: \"@supabase/server withSupabase auth publishable secret ctx.authMode Edge Functions access token\", limit: 10) { nodes { title href content } } }",
"hasContent": true,
"pages": [
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys",
+ "title": "Understanding API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/choosing-a-server-package",
+ "title": "Which package to use"
+ },
{
"url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
"title": "Integrating With Supabase Auth"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
- "title": "Why is my service role key client getting RLS errors or not returning data?"
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs",
- "title": "Build a User Management App with Next.js"
+ "url": "https://supabase.com/docs/guides/ai-tools/byo-mcp",
+ "title": "Deploy MCP servers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets",
+ "title": "Resumable WebSockets with Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/ai/hugging-face",
+ "title": "Hugging Face Inference API"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/secure-data",
+ "title": "Securing your data"
+ }
+ ],
+ "resultChars": 76740
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"@supabase/server withSupabase legacy service_role key auth mode service role apikey\", limit: 8) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
},
{
"url": "https://supabase.com/docs/guides/functions/auth",
"title": "Securing Edge Functions"
},
{
- "url": "https://supabase.com/docs/guides/database/secure-data",
- "title": "Securing your data"
+ "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
+ "title": "Why is my service role key client getting RLS errors or not returning data?"
},
{
- "url": "https://supabase.com/docs/guides/auth/users",
- "title": "Users"
+ "url": "https://supabase.com/docs/guides/api/creating-routes",
+ "title": "Creating API Routes"
},
{
- "url": "https://supabase.com/docs/guides/auth",
- "title": "Auth"
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-svelte",
+ "title": "Build a User Management App with Svelte"
},
{
- "url": "https://supabase.com/docs/guides/api/securing-your-api",
- "title": "Securing your API"
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-sveltekit",
+ "title": "Build a User Management App with SvelteKit"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs",
+ "title": "Build a User Management App with Next.js"
}
],
- "resultChars": 98711
+ "resultChars": 150930
}
]
},
- "prompt": "I built an Edge Function called `private-notes` for showing a user's saved\nprivate notes.\n\nCan you check whether there's any way one user could see another user's notes?\n\nPlease fix and deploy it if needed.",
- "promptSourcePath": "evals/build-functions-004-service-role-bypass/PROMPT.md",
+ "usage": {
+ "inputTokens": 2385885,
+ "outputTokens": 16768,
+ "cachedInputTokens": 2310886
+ },
+ "durationMs": 423179,
+ "prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nOur product stores per-user metrics in the existing `user_stats` table.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.",
+ "promptSourcePath": "evals/build-functions-005-dual-auth-user-secret/PROMPT.md",
"attempts": 1,
- "sourcePath": "codex-gpt-5.6/build-functions-004-service-role-bypass.json"
+ "sourcePath": "codex-gpt-5.6/build-functions-005-dual-auth-user-secret.json"
},
{
"experiment": "codex-gpt-5.6",
@@ -12004,67 +15162,57 @@
"modelId": "gpt-5.6-sol",
"reasoningEffort": "medium"
},
- "eval": "build-functions-005-dual-auth-user-secret",
+ "eval": "build-storage-001-private-bucket-access",
"stage": "build",
"product": [
- "edge-functions",
- "auth",
+ "storage",
"database"
],
"topic": [
- "sdk",
"rls",
- "security"
+ "sdk"
],
"suite": "benchmark",
- "interface": "cli",
- "cliVersion": "2.109.1",
+ "interface": "mcp",
"passed": true,
"checks": [
{
- "name": "seed rows present",
- "passed": true,
- "notes": "found 2/2 seeded rows"
+ "name": "bucket user-files exists",
+ "passed": true
},
{
- "name": "rejects request with no credentials",
- "passed": true,
- "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
+ "name": "bucket user-files is private",
+ "passed": true
},
{
- "name": "user with JWT reads only their own rows",
- "passed": true,
- "notes": "status 200: [{\"user_id\":\"34e9425b-8b58-4aa6-9deb-31c762170653\",\"metric\":\"steps_a_ms6z3nra\",\"value\":111}]"
+ "name": "RLS still enabled on storage.objects",
+ "passed": true
},
{
- "name": "user cannot read another user's rows by passing user_id",
+ "name": "user A lists only own files",
"passed": true,
- "notes": "status 200: [{\"user_id\":\"34e9425b-8b58-4aa6-9deb-31c762170653\",\"metric\":\"steps_a_ms6z3nra\",\"value\":111}]"
+ "notes": "saw: 019fb3d8-c503-76c5-90fb-18aa2ec789dc/receipt-alpha.pdf, 019fb3d8-c503-76c5-90fb-18aa2ec789dc/receipt-beta.pdf"
},
{
- "name": "service key bypasses RLS to read the target user's rows",
- "passed": true,
- "notes": "status 200: [{\"user_id\":\"942dd963-0318-4a34-9185-2acf0f1025e8\",\"metric\":\"steps_b_ms6z3nra\",\"value\":222}]"
+ "name": "user B cannot read user A files",
+ "passed": true
},
{
- "name": "non-service key is not granted service access",
- "passed": true,
- "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
+ "name": "anon reads no files",
+ "passed": true
},
{
- "name": "rejects an unverified (forged) user token",
- "passed": true,
- "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
+ "name": "user A can upload into own folder",
+ "passed": true
},
{
- "name": "a user token in the apikey slot is not treated as the service key",
- "passed": true,
- "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
+ "name": "user B cannot upload into user A folder",
+ "passed": true
},
{
- "name": "implementation uses @supabase/server",
+ "name": "configured private per-user storage access",
"passed": true,
- "notes": "imports @supabase/server / withSupabase"
+ "judgeNotes": "Meets rubric: private user-files bucket, authenticated owner-scoped SELECT and INSERT policies using first path segment = auth.uid(), no RLS disabling/public bucket/permissive anon policies, and supabase-js createSignedUrl with expiry for sharing."
}
],
"skills": {
@@ -12073,153 +15221,249 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Edge Functions authenticate JWT Authorization header service_role apikey verify_jwt Deno serve createClient\", limit: 8) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"Supabase Storage access control private bucket RLS foldername auth.uid signed URL createSignedUrl supabase-js\", limit: 8) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/functions/websockets",
- "title": "Handling WebSockets"
+ "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
+ "title": "Storage Buckets"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets",
- "title": "Resumable WebSockets with Edge Functions"
+ "url": "https://supabase.com/docs/guides/storage/serving/downloads",
+ "title": "Serving assets from Storage"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
+ "url": "https://supabase.com/docs/guides/storage/s3/authentication",
+ "title": "S3 Authentication"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-headers",
- "title": "Authorization headers"
+ "url": "https://supabase.com/docs/guides/storage/schema/custom-roles",
+ "title": "Custom Roles"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
- "title": "Why is my service role key client getting RLS errors or not returning data?"
+ "url": "https://supabase.com/docs/guides/functions/examples/amazon-bedrock-image-generator",
+ "title": "Generate Images with Amazon Bedrock"
},
{
- "url": "https://supabase.com/docs/guides/functions",
- "title": "Edge Functions"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
+ "title": "Configure S3 Storage"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
- "title": "Integrating With Supabase Auth"
+ "url": "https://supabase.com/docs/guides/storage",
+ "title": "Storage"
},
{
- "url": "https://supabase.com/docs/guides/functions/http-methods",
- "title": "Routing"
+ "url": "https://supabase.com/docs/guides/troubleshooting/supabase-storage-inefficient-folder-operations-and-hierarchical-rls-challenges-b05a4d",
+ "title": "Supabase Storage: Inefficient folder operations and hierarchical RLS challenges"
}
],
- "resultChars": 60939
+ "resultChars": 38858
},
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Edge Functions SUPABASE_SECRET_KEY environment variable secret key apikey header manual JWT verification getUser verify_jwt false\", limit: 10) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"storage.objects RLS policy storage.foldername(name) auth.uid bucket_id INSERT SELECT private bucket SQL\", limit: 6) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
+ "url": "https://supabase.com/docs/guides/storage/schema/helper-functions",
+ "title": "Storage Helper Functions"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
- "title": "Integrating With Supabase Auth"
+ "url": "https://supabase.com/docs/guides/storage/security/access-control",
+ "title": "Storage Access Control"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
+ "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
+ "title": "Storage Buckets"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
+ "url": "https://supabase.com/docs/guides/storage/schema/design",
+ "title": "The Storage Schema"
},
{
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
+ "title": "Configure S3 Storage"
},
{
- "url": "https://supabase.com/docs/guides/functions/function-configuration",
- "title": "Function Configuration"
- },
+ "url": "https://supabase.com/docs/guides/security/product-security",
+ "title": "Secure configuration of Supabase products"
+ }
+ ],
+ "resultChars": 25062
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"JavaScript createSignedUrl(path expiresIn options download) Supabase Storage reference\", limit: 4) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
{
- "url": "https://supabase.com/docs/guides/auth/jwts",
- "title": "JSON Web Token (JWT)"
+ "url": "https://supabase.com/docs/guides/storage/serving/image-transformations",
+ "title": "Storage Image Transformations"
},
{
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
+ "url": "https://supabase.com/docs/guides/storage/serving/downloads",
+ "title": "Serving assets from Storage"
},
{
- "url": "https://supabase.com/docs/guides/auth/auth-mfa",
- "title": "Multi-Factor Authentication"
+ "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsignedurl"
},
{
- "url": "https://supabase.com/docs/guides/functions/websockets",
- "title": "Handling WebSockets"
+ "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsignedurls"
}
],
- "resultChars": 122455
- },
+ "resultChars": 25414
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 565700,
+ "outputTokens": 3770,
+ "cachedInputTokens": 527484
+ },
+ "durationMs": 89830,
+ "prompt": "Our app lets signed-in users keep personal files like receipts and bank\nstatements. These files are private — a user must only ever be able to upload\nand download their own. The app uploads each file under a path that starts\nwith the owner's user id, e.g. `/receipt-march.pdf`.\n\nSet up a `user-files` bucket on our project and lock it down that way.\n\nUsers also sometimes share one of their files with someone else through a\ntemporary link that expires. Include the supabase-js code the app should use\nfor that.",
+ "promptSourcePath": "evals/build-storage-001-private-bucket-access/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.6/build-storage-001-private-bucket-access.json"
+ },
+ {
+ "experiment": "codex-gpt-5.6",
+ "experimentSuite": "benchmark",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.6-sol",
+ "reasoningEffort": "medium"
+ },
+ "eval": "build-tests-001-rls-tenant-isolation",
+ "stage": "build",
+ "product": [
+ "database"
+ ],
+ "topic": [
+ "tests",
+ "rls"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "passed": true,
+ "checks": [
+ {
+ "name": "pgTAP test file(s) written under supabase/tests/",
+ "passed": true,
+ "notes": "1 file(s): supabase/tests/database/tenant_isolation.sql"
+ },
+ {
+ "name": "pgTAP isolation tests ran and pass",
+ "passed": true,
+ "notes": "5 passed, 4 failed"
+ },
+ {
+ "name": "agent correctly identifies the posts isolation bug from test results",
+ "passed": true,
+ "judgeNotes": "The agent correctly identifies `posts` as having a tenant isolation flaw, specifically that posts from other tenants are exposed, and grounds it in pgTAP/test results (`posts expose other tenants`, 5/9 passed). It does not blame `notes`; it says cross-tenant notes are blocked. Additional membership issues do not undermine the required conclusion."
+ }
+ ],
+ "skills": {
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
+ },
+ "docs": {
+ "calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"@supabase/server auth legacy service_role key apikey Edge Functions service_role JWT\", limit: 10) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"row level security tenant isolation policy testing pgTAP auth.uid set local request.jwt.claims\", limit: 6) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
+ "url": "https://supabase.com/docs/guides/auth/auth-mfa",
+ "title": "Multi-Factor Authentication"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
+ "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
+ "title": "Token Security and Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
+ "url": "https://supabase.com/docs/guides/local-development/testing/overview",
+ "title": "Testing Overview"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
+ "url": "https://supabase.com/docs/guides/ai/rag-with-permissions",
+ "title": "RAG with Permissions"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
- "title": "Integrating With Supabase Auth"
+ "url": "https://supabase.com/docs/guides/resources/glossary",
+ "title": "Glossary"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
- "title": "Why is my service role key client getting RLS errors or not returning data?"
+ "url": "https://supabase.com/docs/guides/realtime/authorization",
+ "title": "Realtime Authorization"
+ }
+ ],
+ "resultChars": 75568
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Supabase CLI database testing pgTAP supabase test db tests database\", limit: 8) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli/testing-and-linting",
+ "title": "Testing and linting"
},
{
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
+ "url": "https://supabase.com/docs/reference/cli/supabase-test-db",
+ "title": "Tests local database with pgTAP"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets",
- "title": "Resumable WebSockets with Edge Functions"
+ "url": "https://supabase.com/docs/guides/local-development/testing/overview",
+ "title": "Testing Overview"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/testing",
+ "title": "Testing Your Database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended",
+ "title": "Advanced pgTAP Testing"
},
{
- "url": "https://supabase.com/docs/guides/auth/jwt-fields",
- "title": "JWT Claims Reference"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/functions/function-configuration",
- "title": "Function Configuration"
+ "url": "https://supabase.com/docs/guides/database/extensions/pgtap",
+ "title": "pgTAP: Unit Testing"
}
],
- "resultChars": 114347
+ "resultChars": 75496
}
]
},
- "prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nOur product stores per-user metrics in the existing `user_stats` table.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.",
- "promptSourcePath": "evals/build-functions-005-dual-auth-user-secret/PROMPT.md",
- "attempts": 2,
- "sourcePath": "codex-gpt-5.6/build-functions-005-dual-auth-user-secret.json"
+ "usage": {
+ "inputTokens": 774817,
+ "outputTokens": 8761,
+ "cachedInputTokens": 730737
+ },
+ "durationMs": 193428,
+ "prompt": "Can you audit the tenant isolation on our tables? Write some database tests covering both the happy path and the negative case, run them, and share the results.",
+ "promptSourcePath": "evals/build-tests-001-rls-tenant-isolation/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.6/build-tests-001-rls-tenant-isolation.json"
},
{
"experiment": "codex-gpt-5.6",
@@ -12230,57 +15474,50 @@
"modelId": "gpt-5.6-sol",
"reasoningEffort": "medium"
},
- "eval": "build-storage-001-private-bucket-access",
+ "eval": "build-vectors-001-rag-with-permissions",
"stage": "build",
"product": [
- "storage",
- "database"
+ "database",
+ "vectors"
],
"topic": [
- "rls",
- "sdk"
+ "sql",
+ "rls"
],
"suite": "benchmark",
"interface": "mcp",
"passed": true,
"checks": [
{
- "name": "bucket user-files exists",
- "passed": true
- },
- {
- "name": "bucket user-files is private",
- "passed": true
+ "name": "document_sections.embedding is vector(384)",
+ "passed": true,
+ "notes": "vector(384)"
},
{
- "name": "RLS still enabled on storage.objects",
- "passed": true
+ "name": "HNSW index on the embedding column",
+ "passed": true,
+ "notes": "CREATE INDEX document_sections_embedding_hnsw_idx ON public.document_sections USING hnsw (embedding vector_ip_ops)"
},
{
- "name": "user A lists only own files",
+ "name": "index operator class matches the search operator",
"passed": true,
- "notes": "saw: 019fb117-0187-77b3-8842-0d324488c642/receipt-alpha.pdf, 019fb117-0187-77b3-8842-0d324488c642/receipt-beta.pdf"
+ "notes": "function operators: <#>\nindexes: CREATE INDEX document_sections_embedding_hnsw_idx ON public.document_sections USING hnsw (embedding vector_ip_ops)"
},
{
- "name": "user B cannot read user A files",
+ "name": "user A search returns only own sections, best match first",
"passed": true
},
{
- "name": "anon reads no files",
+ "name": "user B search returns only own sections, best match first",
"passed": true
},
{
- "name": "user A can upload into own folder",
+ "name": "user A reads only own sections through the API",
"passed": true
},
{
- "name": "user B cannot upload into user A folder",
+ "name": "user A reads only own documents through the API",
"passed": true
- },
- {
- "name": "configured private per-user storage access",
- "passed": true,
- "judgeNotes": "Meets requirements: private user-files bucket, authenticated owner-scoped SELECT and INSERT policies on storage.objects with WITH CHECK for uploads, no RLS disabling or public access, and supabase-js createSignedUrl with short expiry."
}
],
"skills": {
@@ -12289,72 +15526,92 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Storage access control policy foldername auth.uid createSignedUrl private bucket upload download\", limit: 6) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"pgvector semantic search match_documents RPC vector cosine HNSW RLS auth.uid\", limit: 8) { nodes { ... on Guide { title href content } ... on ClientLibraryFunctionReference { title href content language methodName } ... on TroubleshootingGuide { title href content } } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
- "title": "Storage Buckets"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search",
+ "title": "Semantic search"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/why-cant-i-uploadlistetc-my-public-bucket-Z6CmGt",
- "title": "Why can't I upload/list/etc my public bucket?"
+ "url": "https://supabase.com/docs/guides/ai/hybrid-search",
+ "title": "Hybrid search"
},
{
- "url": "https://supabase.com/docs/guides/security/product-security",
- "title": "Secure configuration of Supabase products"
+ "url": "https://supabase.com/docs/guides/ai/rag-with-permissions",
+ "title": "RAG with Permissions"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
- "title": "Configure S3 Storage"
+ "url": "https://supabase.com/docs/guides/ai/vector-columns",
+ "title": "Vector columns"
},
{
- "url": "https://supabase.com/docs/guides/storage/quickstart",
- "title": "Storage Quickstart"
+ "url": "https://supabase.com/docs/guides/storage/vector/querying-vectors",
+ "title": "Querying Vectors"
},
{
- "url": "https://supabase.com/docs/guides/storage/security/access-control",
- "title": "Storage Access Control"
+ "url": "https://supabase.com/docs/guides/ai/vector-indexes/hnsw-indexes",
+ "title": "HNSW indexes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/ai/vector-indexes",
+ "title": "Vector indexes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/ai/langchain",
+ "title": "LangChain"
}
],
- "resultChars": 28532
+ "resultChars": 91451
},
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"JavaScript createSignedUrl storage from expiresIn example supabase-js\", limit: 4) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"Supabase Edge Functions gte-small embedding dimensions 384 pgvector HNSW\", limit: 5) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/storage/serving/downloads",
- "title": "Serving assets from Storage"
+ "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
+ "title": "Automatic embeddings"
},
{
- "url": "https://supabase.com/docs/guides/storage/serving/image-transformations",
- "title": "Storage Image Transformations"
+ "url": "https://supabase.com/docs/guides/ai/semantic-search",
+ "title": "Semantic search"
},
{
- "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsignedurl"
+ "url": "https://supabase.com/docs/guides/functions/examples/semantic-search",
+ "title": "Semantic Search"
},
{
- "url": "https://supabase.com/docs/guides/platform/manage-your-usage/storage-image-transformations",
- "title": "Manage Storage Image Transformations usage"
+ "url": "https://supabase.com/docs/guides/ai/choosing-compute-addon",
+ "title": "Choosing your Compute Add-on"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/ai/concepts",
+ "title": "Concepts"
}
],
- "resultChars": 31603
+ "resultChars": 76193
}
]
},
- "prompt": "Our app lets signed-in users keep personal files like receipts and bank\nstatements. These files are private — a user must only ever be able to upload\nand download their own. The app uploads each file under a path that starts\nwith the owner's user id, e.g. `/receipt-march.pdf`.\n\nSet up a `user-files` bucket on our project and lock it down that way.\n\nUsers also sometimes share one of their files with someone else through a\ntemporary link that expires. Include the supabase-js code the app should use\nfor that.",
- "promptSourcePath": "evals/build-storage-001-private-bucket-access/PROMPT.md",
+ "usage": {
+ "inputTokens": 1439204,
+ "outputTokens": 11483,
+ "cachedInputTokens": 1389438
+ },
+ "durationMs": 239299,
+ "prompt": "We're adding semantic search to our internal knowledge base app. I already wrote the edge functions, but search doesn't work yet. Can you set up whatever the database needs to make search work end to end?\n\nSome documents are confidential, so users should only have access to documents they own.",
+ "promptSourcePath": "evals/build-vectors-001-rag-with-permissions/PROMPT.md",
"attempts": 1,
- "sourcePath": "codex-gpt-5.6/build-storage-001-private-bucket-access.json"
+ "sourcePath": "codex-gpt-5.6/build-vectors-001-rag-with-permissions.json"
},
{
"experiment": "codex-gpt-5.6",
@@ -12365,33 +15622,30 @@
"modelId": "gpt-5.6-sol",
"reasoningEffort": "medium"
},
- "eval": "build-tests-001-rls-tenant-isolation",
- "stage": "build",
+ "eval": "deploy-database-001-prometheus-metrics",
+ "stage": "deploy",
"product": [
"database"
],
"topic": [
- "tests",
- "rls"
+ "observability"
],
"suite": "benchmark",
- "interface": "cli",
"passed": true,
"checks": [
{
- "name": "pgTAP test file(s) written under supabase/tests/",
- "passed": true,
- "notes": "1 file(s): supabase/tests/database/tenant_isolation.test.sql"
+ "name": "preserved existing app scrape job",
+ "passed": true
},
{
- "name": "pgTAP isolation tests ran and pass",
+ "name": "configured the Supabase Metrics API scrape correctly",
"passed": true,
- "notes": "9 passed, 0 failed"
+ "judgeNotes": "Meets requirements: HTTPS Supabase Metrics API scrape, correct metrics path, Basic Auth with password_file, app job preserved, and Compose secret wired to the matching /run/secrets path."
},
{
- "name": "agent correctly identifies the posts isolation bug from test results",
+ "name": "documented live deployment and verification steps",
"passed": true,
- "judgeNotes": "The agent correctly identifies `posts` as having a tenant isolation flaw allowing cross-organization reads, and grounds the conclusion in pgTAP failures/results. It does not blame `notes` or dismiss the tests."
+ "judgeNotes": "README includes Secret API key creation, matching Docker secret file setup, Compose restart/reload guidance, and concrete verification via Prometheus targets, PromQL, and Grafana."
}
],
"skills": {
@@ -12400,45 +15654,56 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"row level security testing pgTAP auth.uid tenant isolation policies\", limit: 5) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"Prometheus metrics endpoint project metrics authentication service role username password /customer/v1/privileged/metrics\", limit: 8) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } ... on ManagementApiReference { title href content } } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended",
- "title": "Advanced pgTAP Testing"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic",
+ "title": "Vendor-agnostic Metrics API setup"
},
{
- "url": "https://supabase.com/docs/guides/local-development/testing/overview",
- "title": "Testing Overview"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics",
+ "title": "Metrics API"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pgtap",
- "title": "pgTAP: Unit Testing"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted",
+ "title": "Metrics API with Prometheus & Grafana (self-hosted)"
},
{
- "url": "https://supabase.com/docs/guides/database/testing",
- "title": "Testing Your Database"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
+ "title": "Envoy API Gateway"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
- "title": "Row Level Security"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud",
+ "title": "Metrics API with Grafana Cloud"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/security/security-testing",
+ "title": "Security testing of your Supabase projects"
}
],
- "resultChars": 70562
+ "resultChars": 47488
}
]
},
- "prompt": "Can you audit the tenant isolation on our tables? Write some database tests covering both the happy path and the negative case, run them, and share the results.",
- "promptSourcePath": "evals/build-tests-001-rls-tenant-isolation/PROMPT.md",
+ "usage": {
+ "inputTokens": 425988,
+ "outputTokens": 7415,
+ "cachedInputTokens": 391776
+ },
+ "durationMs": 155156,
+ "prompt": "Can you wire my Supabase project metrics into our existing observability stack and document\nin the observability README what we need to do to make the config live?",
+ "promptSourcePath": "evals/deploy-database-001-prometheus-metrics/PROMPT.md",
"attempts": 1,
- "sourcePath": "codex-gpt-5.6/build-tests-001-rls-tenant-isolation.json"
+ "sourcePath": "codex-gpt-5.6/deploy-database-001-prometheus-metrics.json"
},
{
"experiment": "codex-gpt-5.6",
@@ -12449,49 +15714,127 @@
"modelId": "gpt-5.6-sol",
"reasoningEffort": "medium"
},
- "eval": "build-vectors-001-rag-with-permissions",
- "stage": "build",
+ "eval": "deploy-functions-001-edge-function-secrets",
+ "stage": "deploy",
"product": [
- "database",
- "vectors"
+ "edge-functions"
],
"topic": [
- "sql",
- "rls"
+ "security"
],
"suite": "benchmark",
- "interface": "mcp",
+ "interface": "cli",
"passed": true,
"checks": [
{
- "name": "document_sections.embedding is vector(384)",
- "passed": true,
- "notes": "vector(384)"
+ "name": "WEATHER_API_KEY is set as a Function secret on the project",
+ "passed": true
},
{
- "name": "HNSW index on the embedding column",
+ "name": "the weather function is deployed to the project",
"passed": true,
- "notes": "CREATE INDEX document_sections_embedding_hnsw_idx ON public.document_sections USING hnsw (embedding vector_cosine_ops)"
+ "notes": "status ACTIVE"
},
{
- "name": "index operator class matches the search operator",
+ "name": "the weather function reads WEATHER_API_KEY from the environment",
"passed": true,
- "notes": "function operators: <=>\nindexes: CREATE INDEX document_sections_embedding_hnsw_idx ON public.document_sections USING hnsw (embedding vector_cosine_ops)"
+ "judgeNotes": "The function reads WEATHER_API_KEY from the runtime environment using Deno.env.get(\"WEATHER_API_KEY\")."
},
{
- "name": "user A search returns only own sections, best match first",
+ "name": "WEATHER_API_KEY value is not committed to the repo",
+ "passed": true
+ }
+ ],
+ "skills": {
+ "available": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ],
+ "loaded": [
+ "supabase",
+ "supabase-postgres-best-practices"
+ ]
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Edge Functions secrets environment variables Deno.env deploy function verify_jwt CORS invoke\", limit: 6) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/functions",
+ "title": "Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/features",
+ "title": "Features"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli/testing-and-linting",
+ "title": "Testing and linting"
+ }
+ ],
+ "resultChars": 49477
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 1394625,
+ "outputTokens": 10206,
+ "cachedInputTokens": 1318568
+ },
+ "durationMs": 252495,
+ "prompt": "Our weather widget currently calls WeatherAPI straight from the browser, which\nleaks our API key. I want to move that behind a Supabase Edge Function called\n`weather` that holds the key server-side and proxies the request.\n\nThe function should read the key from an environment variable named\n`WEATHER_API_KEY`. Our key already lives in a local `.env` file at the project\nroot.\n\nDeploy the function to our project so it's live, and make sure the deployed\nfunction can actually read the key at runtime.",
+ "promptSourcePath": "evals/deploy-functions-001-edge-function-secrets/PROMPT.md",
+ "attempts": 1,
+ "sourcePath": "codex-gpt-5.6/deploy-functions-001-edge-function-secrets.json"
+ },
+ {
+ "experiment": "codex-gpt-5.6",
+ "experimentSuite": "benchmark",
+ "experimentDisplay": {
+ "agent": "codex",
+ "modelProvider": "openai",
+ "modelId": "gpt-5.6-sol",
+ "reasoningEffort": "medium"
+ },
+ "eval": "deploy-self-hosting-001-docker-compose",
+ "stage": "deploy",
+ "product": [
+ "database",
+ "auth",
+ "storage"
+ ],
+ "topic": [
+ "self-hosting"
+ ],
+ "suite": "benchmark",
+ "interface": "cli",
+ "passed": true,
+ "checks": [
+ {
+ "name": "cloned the self-host stack (docker-compose.yml + volumes/db)",
"passed": true
},
{
- "name": "user B search returns only own sections, best match first",
+ "name": "didn't conflate with the CLI (no supabase/config.toml in the stack)",
"passed": true
},
{
- "name": "user A reads only own sections through the API",
+ "name": "secrets rotated off the shipped defaults",
"passed": true
},
{
- "name": "user A reads only own documents through the API",
+ "name": "ANON_KEY and SERVICE_ROLE_KEY are HS256 JWTs signed by JWT_SECRET",
"passed": true
}
],
@@ -12501,316 +15844,708 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"pgvector semantic search embeddings match_documents RLS auth.uid vector index HNSW RPC security invoker\", limit: 8) { nodes { ... on Guide { title href content } ... on ClientLibraryFunctionReference { title href content language methodName } } } }",
+ "query": "query { searchDocs(query: \"self-hosting Docker docker-compose .env secrets JWT_SECRET ANON_KEY SERVICE_ROLE_KEY production VPS\", limit: 8) { nodes { ... on Guide { title href content subsections { nodes { title href content } } } ... on TroubleshootingGuide { title href content } } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/ai/semantic-search",
- "title": "Semantic search"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#backward-compatibility",
+ "title": "Backward compatibility"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#differences-from-the-supabase-platform",
+ "title": "Differences from the Supabase platform"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#environment-variables-configuration",
+ "title": "Environment variables configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#verifying-the-setup",
+ "title": "Verifying the setup"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#new-api-keys-format",
+ "title": "New API keys format"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#kong-api-gateway-routing",
+ "title": "Kong API gateway routing"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#what-client-sdk-sends",
+ "title": "What client SDK sends"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#how-it-works",
+ "title": "How it works"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#regenerating-asymmetric-key-pair",
+ "title": "Regenerating asymmetric key pair"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#rotating-the-new-api-keys",
+ "title": "Rotating the new API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#before-you-begin",
+ "title": "Before you begin"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#request-flows",
+ "title": "Request flows"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#unauthenticated-requests-api-key-only-no-user-session-jwt",
+ "title": "Unauthenticated requests (API key only, no user session JWT)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#authenticated-requests-user-session-jwt",
+ "title": "Authenticated requests (user session JWT)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#additional-resources",
+ "title": "Additional resources"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#adding-the-new-keys",
+ "title": "Adding the new keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker",
+ "title": "Self-Hosting with Docker"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#exposing-your-postgres-database",
+ "title": "Exposing your Postgres database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#setting-log_min_messages-in-postgres",
+ "title": "Setting log_min_messages in Postgres"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#managing-your-secrets",
+ "title": "Managing your secrets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#demo",
+ "title": "Demo"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#before-you-begin",
+ "title": "Before you begin"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#system-requirements",
+ "title": "System requirements"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#installing-supabase",
+ "title": "Installing Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#quick-start-linux",
+ "title": "Quick start (Linux)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#manual-installation",
+ "title": "Manual installation"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-and-securing-supabase",
+ "title": "Configuring and securing Supabase"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#generate-keys-and-secrets",
+ "title": "Generate keys and secrets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configure-supabase-urls",
+ "title": "Configure Supabase URLs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#where-to-find-your-credentials",
+ "title": "Where to find your credentials"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#studio-authentication",
+ "title": "Studio authentication"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#starting-and-stopping",
+ "title": "Starting and stopping"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-supabase-studio-dashboard",
+ "title": "Accessing Supabase Studio (Dashboard)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-postgres",
+ "title": "Accessing Postgres"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-edge-functions",
+ "title": "Accessing Edge Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-apis",
+ "title": "Accessing APIs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#enabling-analytics",
+ "title": "Enabling analytics"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-https",
+ "title": "Configuring HTTPS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#managing-the-stack",
+ "title": "Managing the stack"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#updating",
+ "title": "Updating"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#uninstalling",
+ "title": "Uninstalling"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#advanced-topics",
+ "title": "Advanced topics"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#architecture",
+ "title": "Architecture"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#setting-database-password",
+ "title": "Setting database password"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#changing-database-password",
+ "title": "Changing database password"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-secrets",
+ "title": "Configuring secrets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-supabase-services",
+ "title": "Configuring Supabase services"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-social-login-oauth-providers",
+ "title": "Configuring social login (OAuth) providers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-phone-login-sms-and-mfa",
+ "title": "Configuring phone login, SMS, and MFA"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-an-email-server",
+ "title": "Configuring an email server"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-s3-storage",
+ "title": "Configuring S3 Storage"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#using-file-backend-in-storage-on-macos",
+ "title": "Using file backend in Storage on macOS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#configuring-supabase-ai-assistant",
+ "title": "Configuring Supabase AI Assistant"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#accessing-postgres-through-supavisor",
+ "title": "Accessing Postgres through Supavisor"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/docker#contents",
+ "title": "Contents"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth",
+ "title": "Configure Social Login (OAuth) Providers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#troubleshooting",
+ "title": "Troubleshooting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#test-the-login-flow",
+ "title": "Test the login flow"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#oauth-request-flow",
+ "title": "OAuth request flow"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#before-you-begin",
+ "title": "Before you begin"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#additional-resources",
+ "title": "Additional resources"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#environment-variable-reference",
+ "title": "Environment variable reference"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#auth-service-fails-to-start",
+ "title": "Auth service fails to start"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#nonce-check-failure-on-mobile-google-sign-in",
+ "title": "Nonce check failure on mobile (Google Sign In)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#site-url-or-redirect-url-errors-after-login",
+ "title": "Site URL or redirect URL errors after login"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-5-verify-the-configuration",
+ "title": "Step 5: Verify the configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#provider-specific-setup",
+ "title": "Provider-specific setup"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-4-restart-the-auth-service",
+ "title": "Step 4: Restart the auth service"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-3-enable-the-matching-lines-in-docker-compose-configuration",
+ "title": "Step 3: Enable the matching lines in Docker Compose configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-2-configure-environment-variables",
+ "title": "Step 2: Configure environment variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#other-supported-providers",
+ "title": "Other supported providers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-1-register-your-app-with-the-provider",
+ "title": "Step 1: Register your app with the provider"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#step-by-step-configuration",
+ "title": "Step-by-step configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#auth-environment-variables",
+ "title": "Auth environment variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#variables-added-to-the-environment-but-provider-still-not-working",
+ "title": "Variables added to the environment but provider still not working"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
+ "title": "Self-Hosted Functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#invoke-the-default-function",
+ "title": "Invoke the default function"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#using-inline-environment-variables",
+ "title": "Using inline environment variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#using-an-env-file-recommended",
+ "title": "Using an env file (recommended)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#custom-environment-variables",
+ "title": "Custom environment variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#step-3-invoke-your-function",
+ "title": "Step 3: Invoke your function"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#step-2-restart-the-functions-service-to-pick-up-the-new-function",
+ "title": "Step 2: Restart the functions service to pick up the new function"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#step-1-add-a-new-function-directory-and-the-function-code",
+ "title": "Step 1: Add a new function directory and the function code"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#create-a-new-function",
+ "title": "Create a new function"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#memory-or-timeout-errors",
+ "title": "Memory or timeout errors"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#custom-env-vars-not-available-in-functions",
+ "title": "Custom env vars not available in functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#changes-to-function-code-not-reflected-after-editing",
+ "title": "Changes to function code not reflected after editing"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#500-error-on-invocation",
+ "title": "500 error on invocation"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#troubleshooting",
+ "title": "Troubleshooting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#copying-functions-from-supabase-platform",
+ "title": "Copying functions from Supabase platform"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#deploying-functions-to-a-remote-server",
+ "title": "Deploying functions to a remote server"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#managing-functions-via-dashboard",
+ "title": "Managing functions via dashboard"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#internal-vs-external-urls",
+ "title": "Internal vs external URLs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#calling-supabase-services-from-functions",
+ "title": "Calling Supabase services from functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#accessing-variables-in-functions",
+ "title": "Accessing variables in functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
+ "title": "Envoy API Gateway"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#see-also",
+ "title": "See also"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#common-issues",
+ "title": "Common issues"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#logs",
+ "title": "Logs"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#troubleshooting",
+ "title": "Troubleshooting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#admin-interface",
+ "title": "Admin interface"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#customizing-the-configuration",
+ "title": "Customizing the configuration"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#security-hardening",
+ "title": "Security hardening"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#cors",
+ "title": "CORS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#x-forwarded-headers",
+ "title": "X-Forwarded headers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#forwarded-headers-and-cors",
+ "title": "Forwarded headers and CORS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#opaque-key-translation",
+ "title": "Opaque key translation"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#api-key-enforcement-on-protected-routes",
+ "title": "API key enforcement on protected routes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#dashboard-basic-auth",
+ "title": "Dashboard basic auth"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#authentication",
+ "title": "Authentication"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#routes",
+ "title": "Routes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#how-the-configuration-is-rendered-at-startup",
+ "title": "How the configuration is rendered at startup"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#configuration-file-structure",
+ "title": "Configuration file structure"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#architecture",
+ "title": "Architecture"
},
{
- "url": "https://supabase.com/docs/guides/ai/rag-with-permissions",
- "title": "RAG with Permissions"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#verify",
+ "title": "Verify"
},
{
- "url": "https://supabase.com/docs/guides/ai/hybrid-search",
- "title": "Hybrid search"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#enabling-the-envoy-gateway",
+ "title": "Enabling the Envoy gateway"
},
{
- "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
- "title": "Automatic embeddings"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#before-you-begin",
+ "title": "Before you begin"
},
{
- "url": "https://supabase.com/docs/guides/ai/vector-columns",
- "title": "Vector columns"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys",
+ "title": "JWT Signing Keys"
},
{
- "url": "https://supabase.com/docs/guides/ai/going-to-prod",
- "title": "Going to Production"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#how-to-deactivate-the-anon-and-service_role-jwt-based-api-keys-after-moving-to-publishable-and-secret-keys",
+ "title": "How to deactivate the anon and service_role JWT-based API keys after moving to publishable and secret keys?"
},
{
- "url": "https://supabase.com/docs/guides/ai/vector-indexes",
- "title": "Vector indexes"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#can-you-still-use-an-old-anon-and-service-role-api-keys-after-enabling-the-publishable-and-secret-keys",
+ "title": "Can you still use an old anon and service-role API keys after enabling the publishable and secret keys?"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pgvector",
- "title": "pgvector: Embeddings and vector similarity"
- }
- ],
- "resultChars": 97234
- }
- ]
- },
- "prompt": "We're adding semantic search to our internal knowledge base app. I already wrote the edge functions, but search doesn't work yet. Can you set up whatever the database needs to make search work end to end?\n\nSome documents are confidential, so users should only have access to documents they own.",
- "promptSourcePath": "evals/build-vectors-001-rag-with-permissions/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.6/build-vectors-001-rag-with-permissions.json"
- },
- {
- "experiment": "codex-gpt-5.6",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.6-sol",
- "reasoningEffort": "low"
- },
- "eval": "deploy-database-001-prometheus-metrics",
- "stage": "deploy",
- "product": [
- "database"
- ],
- "topic": [
- "observability"
- ],
- "suite": "benchmark",
- "passed": true,
- "checks": [
- {
- "name": "preserved existing app scrape job",
- "passed": true
- },
- {
- "name": "configured the Supabase Metrics API scrape correctly",
- "passed": true,
- "judgeNotes": "Prometheus preserves the app scrape and adds a deployable Supabase scrape over HTTPS to the correct metrics path using HTTP Basic Auth with password_file. The target is a project ref on supabase.co, and docker-compose wires the matching password file via a Compose secret mounted at /run/secrets/supabase_secret_key."
- },
- {
- "name": "documented live deployment and verification steps",
- "passed": true,
- "judgeNotes": "README includes Secret API key creation, matching secret file placement, Compose stack deploy/restart guidance, and concrete verification via Prometheus targets, Grafana/Prometheus labels, and curl."
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"Prometheus metrics project endpoint customer v1 privileged metrics service_role authentication hosted Supabase\", limit: 5) { nodes { __typename title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#why-are-anon-and-service_role-jwt-based-keys-no-longer-recommended",
+ "title": "Why are anon and service_role JWT-based keys no longer recommended?"
+ },
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-self-hosted",
- "title": "Metrics API with Prometheus & Grafana (self-hosted)"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#why-is-it-not-possible-to-extract-the-private-key-or-shared-secret-from-supabase",
+ "title": "Why is it not possible to extract the private key or shared secret from Supabase?"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics",
- "title": "Metrics API"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#frequently-asked-questions",
+ "title": "Frequently asked questions"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/vendor-agnostic",
- "title": "Vendor-agnostic Metrics API setup"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#choosing-the-right-signing-algorithm",
+ "title": "Choosing the right signing algorithm"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-cloud",
- "title": "Metrics API with Grafana Cloud"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#public-key-discovery-and-caching",
+ "title": "Public key discovery and caching"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
- }
- ],
- "resultChars": 39702
- }
- ]
- },
- "prompt": "Can you wire my Supabase project metrics into our existing observability stack and document\nin the observability README what we need to do to make the config live?",
- "promptSourcePath": "evals/deploy-database-001-prometheus-metrics/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.6/deploy-database-001-prometheus-metrics.json"
- },
- {
- "experiment": "codex-gpt-5.6",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.6-sol",
- "reasoningEffort": "medium"
- },
- "eval": "deploy-functions-001-edge-function-secrets",
- "stage": "deploy",
- "product": [
- "edge-functions"
- ],
- "topic": [
- "security"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "passed": true,
- "checks": [
- {
- "name": "WEATHER_API_KEY is set as a Function secret on the project",
- "passed": true
- },
- {
- "name": "the weather function is deployed to the project",
- "passed": true,
- "notes": "status ACTIVE"
- },
- {
- "name": "the weather function reads WEATHER_API_KEY from the environment",
- "passed": true,
- "judgeNotes": "The function reads WEATHER_API_KEY from the runtime environment using Deno.env.get(\"WEATHER_API_KEY\")."
- },
- {
- "name": "WEATHER_API_KEY value is not committed to the repo",
- "passed": true
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": [
- "supabase"
- ]
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"Edge Functions environment variables secrets supabase secrets set deploy functions invoke CORS\", limit: 6) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#lifetime-of-a-signing-key",
+ "title": "Lifetime of a signing key"
+ },
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#rotating-and-revoking-keys",
+ "title": "Rotating and revoking keys"
},
{
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#getting-started",
+ "title": "Getting started"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#benefits-of-the-signing-keys-system",
+ "title": "Benefits of the signing keys system"
},
{
- "url": "https://supabase.com/docs/guides/functions/storage-caching",
- "title": "Integrating with Supabase Storage"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#overview",
+ "title": "Overview"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
- "title": "Integrating With Supabase Auth"
- }
- ],
- "resultChars": 36973
- }
- ]
- },
- "prompt": "Our weather widget currently calls WeatherAPI straight from the browser, which\nleaks our API key. I want to move that behind a Supabase Edge Function called\n`weather` that holds the key server-side and proxies the request.\n\nThe function should read the key from an environment variable named\n`WEATHER_API_KEY`. Our key already lives in a local `.env` file at the project\nroot.\n\nDeploy the function to our project so it's live, and make sure the deployed\nfunction can actually read the key at runtime.",
- "promptSourcePath": "evals/deploy-functions-001-edge-function-secrets/PROMPT.md",
- "attempts": 1,
- "sourcePath": "codex-gpt-5.6/deploy-functions-001-edge-function-secrets.json"
- },
- {
- "experiment": "codex-gpt-5.6",
- "experimentSuite": "benchmark",
- "experimentDisplay": {
- "agent": "codex",
- "modelProvider": "openai",
- "modelId": "gpt-5.6-sol",
- "reasoningEffort": "medium"
- },
- "eval": "deploy-self-hosting-001-docker-compose",
- "stage": "deploy",
- "product": [
- "database",
- "auth",
- "storage"
- ],
- "topic": [
- "self-hosting"
- ],
- "suite": "benchmark",
- "interface": "cli",
- "passed": true,
- "checks": [
- {
- "name": "cloned the self-host stack (docker-compose.yml + volumes/db)",
- "passed": true
- },
- {
- "name": "didn't conflate with the CLI (no supabase/config.toml in the stack)",
- "passed": true
- },
- {
- "name": "secrets rotated off the shipped defaults",
- "passed": true
- },
- {
- "name": "ANON_KEY and SERVICE_ROLE_KEY are HS256 JWTs signed by JWT_SECRET",
- "passed": true
- }
- ],
- "skills": {
- "available": [
- "supabase",
- "supabase-postgres-best-practices"
- ],
- "loaded": []
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"self-hosting Docker compose production secrets JWT_SECRET ANON_KEY SERVICE_ROLE_KEY DASHBOARD_PASSWORD POOLER_TENANT_ID\", limit: 8) { nodes { __typename title href content } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#how-to-create-mint-jwts-if-access-to-the-private-key-or-shared-secret-is-not-possible",
+ "title": "How to create (mint) JWTs if access to the private key or shared secret is not possible?"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#why-is-a-5-minute-wait-imposed-when-changing-signing-key-states",
+ "title": "Why is a 5 minute wait imposed when changing signing key states?"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#why-is-deleting-the-legacy-jwt-secret-disallowed",
+ "title": "Why is deleting the legacy JWT secret disallowed?"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#why-does-revoking-the-legacy-jwt-secret-require-disabling-of-anon-and-service_role-api-keys",
+ "title": "Why does revoking the legacy JWT secret require disabling of anon and service_role API keys?"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#using-jwt-based-anon-key-in-a-mobile-desktop-or-cli-application-and-need-to-rotate-a-service_role-jwt-secret",
+ "title": "Using JWT-based anon key in a mobile, desktop, or CLI application and need to rotate a service_role JWT secret?"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/signing-keys#how-are-publishable-and-secret-keys-implemented-on-the-hosted-platform",
+ "title": "How are publishable and secret keys implemented on the hosted platform?"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates",
+ "title": "Custom Email Templates"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates#authentication-email-templates",
+ "title": "Authentication email templates"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates#step-2-update-docker-composeyml-1",
+ "title": "Step 2: Update docker-compose.yml"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates#step-1-create-the-templates-directory",
+ "title": "Step 1: Create the templates directory"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates#example-1",
+ "title": "Example"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates#notification-email-templates",
+ "title": "Notification email templates"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates#step-3-restart-containers",
+ "title": "Step 3: Restart containers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates#what-this-configuration-does",
+ "title": "What this configuration does"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates#step-2-update-docker-composeyml",
+ "title": "Step 2: Update docker-compose.yml"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates#step-1-create-a-templates-directory",
+ "title": "Step 1: Create a templates directory"
+ },
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
+ "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates#example",
+ "title": "Example"
},
{
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
+ "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates#step-3-restart-containers-1",
+ "title": "Step 3: Restart containers"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
- "title": "Envoy API Gateway"
+ "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates#overview",
+ "title": "Overview"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth",
- "title": "Configure Social Login (OAuth) Providers"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https",
+ "title": "Configure Reverse Proxy and HTTPS"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/docker",
- "title": "Self-Hosting with Docker"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#before-you-begin",
+ "title": "Before you begin"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#step-3-update-configuration-variables",
+ "title": "Step 3: Update configuration variables"
},
{
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#step-4-restart-and-verify",
+ "title": "Step 4: Restart and verify"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
- "title": "Configure S3 Storage"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#troubleshooting",
+ "title": "Troubleshooting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#certificate-not-issued",
+ "title": "Certificate not issued"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#websocket-connection-failed",
+ "title": "WebSocket connection failed"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#oauth-callback-url-mismatch",
+ "title": "OAuth callback URL mismatch"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#mixed-content-warnings",
+ "title": "Mixed content warnings"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#err_cert_authority_invalid",
+ "title": "ERR_CERT_AUTHORITY_INVALID"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#additional-resources",
+ "title": "Additional resources"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#set-up-https",
+ "title": "Set up HTTPS"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#step-1-update-environment-variables",
+ "title": "Step 1: Update environment variables"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#step-2-start-the-reverse-proxy",
+ "title": "Step 2: Start the reverse proxy"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#step-3-verify-https-connection",
+ "title": "Step 3: Verify HTTPS connection"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#self-signed-certificates-development-only",
+ "title": "Self-signed certificates (development only)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#step-1-generate-a-self-signed-certificate",
+ "title": "Step 1: Generate a self-signed certificate"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https#step-2-configure-kong-for-ssl",
+ "title": "Step 2: Configure Kong for SSL"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth#provider-not-enabled-or-provider-seen-as-false-in-settings"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#401-invalid-jwt"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#400-missing-function-name-in-request"
}
],
- "resultChars": 154701
+ "resultChars": 488024
}
]
},
+ "usage": {
+ "inputTokens": 542716,
+ "outputTokens": 9044,
+ "cachedInputTokens": 496423
+ },
+ "durationMs": 169511,
"prompt": "I'm moving off the hosted Supabase and running the whole thing myself on a VPS I\njust spun up. Can you get a Docker setup ready for me to copy onto the box?\n\nI don't need it running here, I'll do the actual bring-up once I'm on the\nserver. I just want everything in place and the secrets set up. Put it in a `supabase-docker/`\nfolder at the repo root so I can scp the whole thing across in one go.",
"promptSourcePath": "evals/deploy-self-hosting-001-docker-compose/PROMPT.md",
"attempts": 1,
@@ -12866,7 +16601,7 @@
{
"name": "diagnosed and explained session revocation",
"passed": true,
- "judgeNotes": "Diagnoses soft-delete-only RPC, implements auth user deletion with cascading session/refresh token/identity removal, adds RLS active-session mitigation and explains JWT stateless expiry caveat consistently. Correctly distinguishes publishable frontend key/RLS from secret server-only RLS-bypassing key."
+ "judgeNotes": "Diagnoses soft-delete-only profile flag as root cause; fixes by deleting auth.users with cascaded sessions/refresh tokens and adds RLS active-session gate; explains JWTs remain valid until exp but data path is closed by its implemented RLS while local validation/custom paths can still accept stale tokens; correctly distinguishes publishable frontend/RLS key from secret server-only RLS-bypassing key."
}
],
"skills": {
@@ -12875,50 +16610,59 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"delete user existing access token session revoke refresh token admin deleteUser publishable secret API keys RLS\", limit: 8) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"delete user existing access token session revoke sign out auth.sessions session_id RLS publishable secret keys legacy anon service_role\", limit: 10) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/auth/third-party/clerk",
- "title": "Clerk"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys",
+ "title": "JWT Signing Keys"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
- "title": "Token Security and Row Level Security"
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
- "title": "Why is my service role key client getting RLS errors or not returning data?"
+ "url": "https://supabase.com/docs/guides/auth/auth-anonymous",
+ "title": "Anonymous Sign-Ins"
},
{
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
+ "url": "https://supabase.com/docs/guides/auth/sessions",
+ "title": "User sessions"
},
{
- "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
- "title": "Storage Buckets"
+ "url": "https://supabase.com/docs/guides/troubleshooting/rotating-anon-service-and-jwt-secrets-1Jq6yd",
+ "title": "Rotating Anon, Service, and JWT Secrets"
},
{
- "url": "https://supabase.com/docs/guides/storage/security/access-control",
- "title": "Storage Access Control"
+ "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers",
+ "title": "Multiple SSO Providers"
},
{
- "url": "https://supabase.com/docs/guides/storage/security/ownership",
- "title": "Ownership"
+ "url": "https://supabase.com/docs/guides/auth/jwt-fields",
+ "title": "JWT Claims Reference"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/api/securing-your-api",
+ "title": "Securing your API"
},
{
- "url": "https://supabase.com/docs/guides/auth/oauth-server/getting-started",
- "title": "Getting Started with OAuth 2.1 Server"
+ "url": "https://supabase.com/docs/guides/database/database-advisors?queryGroups=lint&lint=0012_auth_allow_anonymous_sign_ins",
+ "title": "Database Advisor: Lint 0012_auth_allow_anonymous_sign_ins"
}
],
- "resultChars": 95765
+ "resultChars": 147064
},
{
"source": "web_search",
@@ -12931,59 +16675,45 @@
},
{
"source": "web_search",
- "query": "site:supabase.com/changelog Supabase auth delete user session API keys publishable secret",
+ "query": "site:supabase.com/changelog Supabase breaking change auth sessions API keys publishable secret",
"pages": []
},
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"auth.sessions session_id JWT claim RLS revoke session access token cannot revoke delete user\", limit: 10) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"How to ensure access token cannot be used after sign out session_id auth.sessions RLS\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
- {
- "url": "https://supabase.com/docs/guides/storage/security/ownership",
- "title": "Ownership"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
- "title": "Token Security and Row Level Security"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/third-party/clerk",
- "title": "Clerk"
- },
{
"url": "https://supabase.com/docs/guides/auth/sessions",
"title": "User sessions"
},
{
- "url": "https://supabase.com/docs/guides/auth/auth-anonymous",
- "title": "Anonymous Sign-Ins"
- },
- {
- "url": "https://supabase.com/docs/guides/ai/rag-with-permissions",
- "title": "RAG with Permissions"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/oauth-server/getting-started",
- "title": "Getting Started with OAuth 2.1 Server"
+ "url": "https://supabase.com/docs/guides/auth/third-party/clerk",
+ "title": "Clerk"
},
{
- "url": "https://supabase.com/docs/guides/resources/glossary",
- "title": "Glossary"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api",
+ "title": "Securing your API"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
- "title": "Why is my service role key client getting RLS errors or not returning data?"
+ "url": "https://supabase.com/docs/guides/auth/server-side/creating-a-client",
+ "title": "Creating a Supabase client for SSR"
},
{
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
+ "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
+ "title": "Token Security and Row Level Security"
}
],
- "resultChars": 137238
+ "resultChars": 102740
}
]
},
+ "usage": {
+ "inputTokens": 1323421,
+ "outputTokens": 9795,
+ "cachedInputTokens": 1259729
+ },
+ "durationMs": 216538,
"prompt": "Last week support removed a user through our app's delete-account flow — the\napp calls the `delete_account` function over RPC as the signed-in user. This\nmorning that same person was back: still signed in, reading and saving their\ndata like nothing happened.\n\nFigure out why the account still works, fix the flow so a deleted account\nloses access, and tell me whether there is any window where they could still\nget in after the fix.\n\nOne more thing while you're at it: we're migrating off the legacy\nanon/service_role API keys to the new publishable and secret keys, and the\nteam isn't sure which one belongs in the frontend and what each means for\nRLS. Give us a quick rundown.",
"promptSourcePath": "evals/investigate-auth-001-deleted-user-access/PROMPT.md",
"attempts": 1,
@@ -13035,7 +16765,7 @@
{
"name": "diagnosed missing publication membership",
"passed": true,
- "judgeNotes": "The assistant correctly diagnosed orders missing from supabase_realtime, applied ALTER PUBLICATION supabase_realtime ADD TABLE public.orders via migration, verified courier_locations remained, and did not weaken RLS or policies."
+ "judgeNotes": "The assistant identified the root cause as public.orders missing from the supabase_realtime publication despite SUBSCRIBED, applied exactly ALTER PUBLICATION supabase_realtime ADD TABLE public.orders, and preserved courier_locations, RLS, and policies without blaming or weakening them."
}
],
"skills": {
@@ -13044,14 +16774,15 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Postgres Changes enable table supabase_realtime publication add table postgres_changes SUBSCRIBED no events\", limit: 5) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } } } }",
+ "query": "query { searchDocs(query: \"postgres_changes table must be added to supabase_realtime publication Realtime replication publication\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
@@ -13059,26 +16790,32 @@
"title": "Subscribing to Database Changes"
},
{
- "url": "https://supabase.com/docs/guides/realtime/postgres-changes",
- "title": "Postgres Changes"
+ "url": "https://supabase.com/docs/guides/database/replication/pipelines-faq",
+ "title": "Pipelines FAQ"
},
{
- "url": "https://supabase.com/docs/guides/realtime/benchmarks",
- "title": "Benchmarks"
+ "url": "https://supabase.com/docs/guides/database/replication/pipelines",
+ "title": "Set up Pipelines"
},
{
- "url": "https://supabase.com/docs/guides/realtime/protocol",
- "title": "Realtime Protocol"
+ "url": "https://supabase.com/docs/guides/database/postgres/setup-replication-external",
+ "title": "Replicate to another Postgres database using Logical Replication"
},
{
- "url": "https://supabase.com/docs/guides/realtime/authorization",
- "title": "Realtime Authorization"
+ "url": "https://supabase.com/docs/guides/realtime/concepts",
+ "title": "Realtime Concepts"
}
],
- "resultChars": 119071
+ "resultChars": 52444
}
]
},
+ "usage": {
+ "inputTokens": 461051,
+ "outputTokens": 2643,
+ "cachedInputTokens": 433135
+ },
+ "durationMs": 75854,
"prompt": "Our dispatch dashboard shows incoming orders as they happen. The courier\nlocation feed on the same page updates live without problems, but new orders\nonly show up after a page refresh.\n\nThe dashboard uses supabase-js to subscribe to INSERT events on the `orders`\ntable through postgres_changes, the same way it subscribes to courier\nlocations. The channel's status callback logs SUBSCRIBED and there are no\nerrors in the browser console.\n\nFigure out why no order events ever arrive and fix it.",
"promptSourcePath": "evals/investigate-realtime-001-subscribed-no-events/PROMPT.md",
"attempts": 1,
@@ -13103,22 +16840,22 @@
],
"suite": "benchmark",
"interface": "mcp",
- "passed": true,
+ "passed": false,
"checks": [
{
"name": "identified image-transform and the recurring 503 pattern",
"passed": true,
- "judgeNotes": "Identified image-transform as the affected function and described the recurring pattern of 8 HTTP 503 responses across 07:00–12:00 UTC on 2026-04-28."
+ "judgeNotes": "Assistant identified image-transform as affected and described eight intermittent HTTP 503s across 07:00–12:00 UTC on 2026-04-28, matching the required recurring gateway failure pattern."
},
{
"name": "attributed recurring 503s to gateway/platform layer, not function code",
- "passed": true,
- "judgeNotes": "Attributes the recurring image-transform 503s to the Supabase edge gateway/platform layer rather than function code. Grounds this in valid observations: failures only in gateway/API logs with no function runtime invocations, successful nearby invocations on the same deployment, and distinction from avatar-upload's function-level 500."
+ "passed": false,
+ "judgeNotes": "Although it notes the 503s appear only in gateway logs with no Edge Function invocations, it also frames the issue as gateway/runtime startup instability and recommends redeploying/pinning the image-transform function, which the rubric lists as a fail condition."
},
{
"name": "recommended a concrete next step",
"passed": true,
- "judgeNotes": "The assistant recommended concrete next steps, including opening a Supabase support case with project ref, region, time window, and gateway log IDs, plus investigating specific correlated issues."
+ "judgeNotes": "The assistant recommended concrete actionable next steps, including redeploying/pinning dependencies, adding retries, changing upload architecture, adding structured logging, and opening a Supabase support ticket with specific timestamps and gateway log IDs."
}
],
"skills": {
@@ -13127,12 +16864,48 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
- "calls": []
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Edge Functions 503 gateway error request did not reach function logs troubleshooting\", limit: 5) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/debugging",
+ "title": "Debugging guide"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/edge-function-503-response",
+ "title": "Edge Function 503 error response"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/status-codes",
+ "title": "Status codes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/edge-function-504-error-response",
+ "title": "Edge Function 504 error response"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/edge-function-404-error-response",
+ "title": "Edge Function 404 error response"
+ }
+ ],
+ "resultChars": 45511
+ }
+ ]
},
+ "usage": {
+ "inputTokens": 415691,
+ "outputTokens": 2681,
+ "cachedInputTokens": 385761
+ },
+ "durationMs": 78186,
"prompt": "Users have been reporting that image uploads are intermittently failing with server errors throughout the morning of `2026-04-28`.\n\nCan you investigate the project logs and tell me what is going on and what we\nshould do next?",
"promptSourcePath": "evals/investigate-reliability-003-edge-function-5xx-correlation/PROMPT.md",
"attempts": 2,
@@ -13189,7 +16962,7 @@
{
"name": "diagnosed RLS and added owner-scoped policies",
"passed": true,
- "judgeNotes": "The assistant correctly diagnosed RLS enabled with no policies as the cause of empty Data API results, kept RLS enabled, created authenticated SELECT and INSERT owner-scoped policies using auth.uid() = user_id with WITH CHECK for insert, and verified isolation. It did not disable RLS or create permissive/public policies."
+ "judgeNotes": "Diagnosed RLS enabled with no policies causing deny-all/empty Data API results, kept RLS enabled, and created authenticated SELECT and INSERT policies scoped to user_id = auth.uid() with WITH CHECK for insert. Did not disable RLS or use permissive anon/public policies."
}
],
"skills": {
@@ -13198,38 +16971,39 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Data API expose table grant authenticated RLS auth.uid select insert policy\", limit: 5) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"Row Level Security auth.uid select insert policy authenticated Data API grants\", limit: 5) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } } } }",
"hasContent": true,
"pages": [
{
"url": "https://supabase.com/docs/guides/api/securing-your-api",
"title": "Securing your API"
},
- {
- "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended",
- "title": "Advanced pgTAP Testing"
- },
{
"url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
"title": "Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/storage/schema/helper-functions",
- "title": "Storage Helper Functions"
+ "url": "https://supabase.com/docs/guides/getting-started/features",
+ "title": "Features"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended",
+ "title": "Advanced pgTAP Testing"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-flutter",
- "title": "Build a User Management App with Flutter"
+ "url": "https://supabase.com/docs/guides/ai/rag-with-permissions",
+ "title": "RAG with Permissions"
}
],
- "resultChars": 114795
+ "resultChars": 100048
},
{
"source": "web_search",
@@ -13242,11 +17016,17 @@
},
{
"source": "web_search",
- "query": "site:supabase.com/changelog Supabase changelog Data API grants RLS",
+ "query": "site:supabase.com/changelog.md breaking-change Data API grants RLS",
"pages": []
}
]
},
+ "usage": {
+ "inputTokens": 563022,
+ "outputTokens": 4360,
+ "cachedInputTokens": 524463
+ },
+ "durationMs": 130200,
"prompt": "Our app lets signed-in users save bookmarks and view them on their dashboard. Bookmarks are stored in the `bookmarks` table and are private — a user must only ever see their own. \nUsers also need to be able to save new bookmarks from the app.\n\nI can see the rows when I query the table directly, but the dashboard shows an empty list for every user.\n\nFind out why the Data API returns nothing and fix it.",
"promptSourcePath": "evals/resolve-dataapi-001-empty-results/PROMPT.md",
"attempts": 1,
@@ -13296,7 +17076,7 @@
{
"name": "the avatar migration and history reconciliation were done via the Supabase CLI",
"passed": true,
- "judgeNotes": "Applied the pending avatar_url migration through `supabase db push --db-url \"$DB_URL\" --yes` in action #12, whose output indicates it finished. Reconciled the orphan bio migration by adding `supabase/migrations/20240115000000_add_profile_bio.sql` in action #10 so local and remote migration history matched before the push. No disallowed workaround observed."
+ "judgeNotes": "Avatar migration was applied through `supabase db push --db-url \"$DB_URL\"`, with output `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` History was reconciled by adding the missing local migration file `supabase/migrations/20240115000000_add_profile_bio.sql`, after which `supabase db push` proceeded without the orphan migration blocking it. Only read-only `psql` inspection was used; no prohibited workaround seen."
}
],
"skills": {
@@ -13305,41 +17085,48 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase CLI database migrations db push migration list repair remote migration history\", limit: 5) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } } } }",
+ "query": "query { searchDocs(query: \"Supabase CLI database migrations db push migration history repair linked project\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
"url": "https://supabase.com/docs/reference/cli/supabase-db-push",
"title": "Push new migrations to the remote database"
},
- {
- "url": "https://supabase.com/docs/guides/local-development/cli-workflows",
- "title": "Local development workflow"
- },
{
"url": "https://supabase.com/docs/guides/deployment/database-migrations",
"title": "Database Migrations"
},
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows",
+ "title": "Local development workflow"
+ },
{
"url": "https://supabase.com/docs/reference/cli/supabase-migration-repair",
"title": "Repair the migration history table"
},
{
- "url": "https://supabase.com/docs/reference/cli/supabase-migration-list",
- "title": "List local and remote migrations"
+ "url": "https://supabase.com/docs/guides/local-development/database-migrations",
+ "title": "Database migrations"
}
],
- "resultChars": 50099
+ "resultChars": 61657
}
]
},
+ "usage": {
+ "inputTokens": 400296,
+ "outputTokens": 3328,
+ "cachedInputTokens": 369380
+ },
+ "durationMs": 72218,
"prompt": "I'm trying to ship a migration to our hosted project and it's not working. Can you figure out what's wrong and get it deployed?",
"promptSourcePath": "evals/resolve-database-001-migration-history-mismatch/PROMPT.md",
"attempts": 1,
@@ -13395,14 +17182,15 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"database query optimization EXPLAIN ANALYZE indexes pg_stat_statements\", limit: 5) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } } } }",
+ "query": "query { searchDocs(query: \"database query optimization indexes explain analyze pg_stat_statements\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
@@ -13413,20 +17201,20 @@
"url": "https://supabase.com/docs/guides/database/query-optimization",
"title": "Query Optimization"
},
- {
- "url": "https://supabase.com/docs/guides/troubleshooting/running-explain-analyze-on-functions",
- "title": "Running EXPLAIN ANALYZE on functions"
- },
{
"url": "https://supabase.com/docs/guides/database/postgres/configuration",
"title": "Database configuration"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/understanding-postgresql-explain-output-Un9dqX",
- "title": "Understanding Postgres EXPLAIN Output"
+ "url": "https://supabase.com/docs/guides/troubleshooting/running-explain-analyze-on-functions",
+ "title": "Running EXPLAIN ANALYZE on functions"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_stat_statements",
+ "title": "pg_stat_statements: Query Performance Monitoring"
}
],
- "resultChars": 39586
+ "resultChars": 30971
},
{
"source": "web_search",
@@ -13439,16 +17227,17 @@
},
{
"source": "web_search",
- "query": "site:supabase.com/changelog Supabase changelog breaking change database indexes query performance",
- "pages": []
- },
- {
- "source": "web_search",
- "query": "site:supabase.com/docs/guides/database/postgres/row-level-security Supabase RLS public schema",
+ "query": "site:supabase.com/changelog Supabase changelog database breaking change indexes July 2026",
"pages": []
}
]
},
+ "usage": {
+ "inputTokens": 711242,
+ "outputTokens": 3626,
+ "cachedInputTokens": 668280
+ },
+ "durationMs": 120459,
"prompt": "My database CPU keeps spiking and the app gets slow when loading recent events for a user. Can you figure out what query is causing it and make the database change needed to fix it?\n\nEnd your turn with a short summary of what you changed and why.",
"promptSourcePath": "evals/resolve-performance-001-slow-query-cpu-spike/PROMPT.md",
"attempts": 1,
@@ -13520,29 +17309,48 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"row level security multi tenant team workspace membership policies auth.uid() security definer\", limit: 5) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } } } }",
+ "query": "query { searchDocs(query: \"row level security auth uid tenant workspace policy exists membership\", limit: 5) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
- "title": "Row Level Security"
+ "url": "https://supabase.com/docs/guides/resources/glossary",
+ "title": "Glossary"
},
{
- "url": "https://supabase.com/docs/guides/auth/users",
- "title": "Users"
+ "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers",
+ "title": "Multiple SSO Providers"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/column-level-security",
+ "title": "Column Level Security"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/realtime/getting_started",
+ "title": "Getting Started with Realtime"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/features",
+ "title": "Features"
}
],
- "resultChars": 38609
+ "resultChars": 67361
}
]
},
+ "usage": {
+ "inputTokens": 582131,
+ "outputTokens": 5041,
+ "cachedInputTokens": 547985
+ },
+ "durationMs": 124793,
"prompt": "A customer reported that notes showed up in the wrong workspace.\n\nCan you investigate what is going on and fix it?",
"promptSourcePath": "evals/resolve-security-002-rls-cross-tenant-leak/PROMPT.md",
"attempts": 1,
@@ -13611,34 +17419,40 @@
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase row level security authenticated role select policy migrations seed local development CLI db reset\", limit: 5) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } } } }",
+ "query": "query { searchDocs(query: \"Postgres row level security authenticated role SELECT policy Supabase migrations seed.sql local development\", limit: 5) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/local-development/cli-workflows",
- "title": "Local development workflow"
+ "url": "https://supabase.com/docs/guides/storage/security/access-control",
+ "title": "Storage Access Control"
},
{
- "url": "https://supabase.com/docs/reference/cli/supabase-db-reset",
- "title": "Resets the local database to current migrations"
+ "url": "https://supabase.com/docs/guides/database/postgres/roles",
+ "title": "Postgres Roles"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/column-level-security",
- "title": "Column Level Security"
+ "url": "https://supabase.com/docs/guides/database/secure-data",
+ "title": "Securing your data"
},
{
- "url": "https://supabase.com/docs/guides/deployment/branching/troubleshooting",
- "title": "Troubleshooting"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/deployment/branching/working-with-branches",
- "title": "Working with branches"
+ "url": "https://supabase.com/docs/guides/database/postgres/roles-superuser",
+ "title": "Roles, superuser access and unsupported operations"
}
],
- "resultChars": 49117
+ "resultChars": 43003
}
]
},
+ "usage": {
+ "inputTokens": 800355,
+ "outputTokens": 5600,
+ "cachedInputTokens": 755429
+ },
+ "durationMs": 358319,
"prompt": "We're kicking off a todos app and I want the Supabase side ready for the team\nto build on. Set it up the way we'd run it in development, with schema changes\ntracked as migrations so they can be reviewed and replayed.\n\nFor the first slice we just need a `todos` table. Todos aren't public: anyone\nsigned in can read all of them, but nothing should be writable through the API\nfor now. Add a couple of sample todos so there's something to look at.\n\nBefore you hand it back, make sure the running API actually behaves that way —\nsigned-in users get the todos, signed-out requests get nothing.",
"promptSourcePath": "evals/build-cli-001-bootstrap-app/PROMPT.md",
"attempts": 1,
@@ -13664,11 +17478,11 @@
],
"suite": "benchmark",
"interface": "cli",
- "passed": false,
+ "passed": true,
"checks": [
{
"name": "supabase db diff used to generate the migration",
- "passed": false
+ "passed": true
},
{
"name": "schema file updated to include description column",
@@ -13691,7 +17505,7 @@
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase CLI create migration alter table add column local database migration\", limit: 3) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"Supabase CLI local database migrations alter table add column\", limit: 3) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
@@ -13708,9 +17522,35 @@
}
],
"resultChars": 54403
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"declarative database schemas schema_paths supabase db diff migration\", limit: 3) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas",
+ "title": "Declarative database schemas"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations",
+ "title": "Database Migrations"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows",
+ "title": "Local development workflow"
+ }
+ ],
+ "resultChars": 55139
}
]
},
+ "usage": {
+ "inputTokens": 223759,
+ "outputTokens": 1544,
+ "cachedInputTokens": 199848
+ },
+ "durationMs": 102338,
"prompt": "Add a description text column to the `products` table in my local Supabase stack",
"promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md",
"attempts": 2,
@@ -13765,554 +17605,304 @@
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase Queues create queue pgmq create send read delete Edge Functions JavaScript\", limit: 8) { nodes { ... on Guide { title href content subsections { nodes { title href content } } } ... on ClientLibraryFunctionReference { title href content language methodName } } } }",
+ "query": "query { searchDocs(query: \"Supabase Queues pgmq create queue send read delete Edge Function JavaScript cron schedule every minute\", limit: 8) { nodes { ... on Guide { title href content subsections { nodes { title href content } } } ... on ClientLibraryFunctionReference { title href content language methodName } ... on CLICommandReference { title href content } } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/queues",
- "title": "Supabase Queues"
- },
- {
- "url": "https://supabase.com/docs/guides/queues#features",
- "title": "Features"
- },
- {
- "url": "https://supabase.com/docs/guides/queues#resources",
- "title": "Resources"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions",
- "title": "Consuming Supabase Queue Messages with Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions#concepts",
- "title": "Concepts"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions#consuming-messages-in-an-edge-function",
- "title": "Consuming messages in an Edge Function"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart",
- "title": "Quickstart"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#enable-rls-on-your-tables-in-pgmq-schema",
- "title": "Enable RLS on your tables in pgmq schema"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#queue-types",
- "title": "Queue types"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#create-queues",
- "title": "Create Queues"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#what-happens-when-you-create-a-queue",
- "title": "What happens when you create a queue?"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#expose-queues-to-client-side-consumers",
- "title": "Expose Queues to client-side consumers"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#grant-permissions-to-pgmq_public-database-functions",
- "title": "Grant permissions to pgmq_public database functions"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#enqueueing-and-dequeueing-messages",
- "title": "Enqueueing and dequeueing messages"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#message",
- "title": "Message"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#pull-based-queue",
- "title": "Pull-Based Queue"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#concepts",
- "title": "Concepts"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/api",
- "title": "API"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/api#pgmq_publicpopqueue_name",
- "title": "pgmq_public.pop(queue_name)"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/api#pgmq_publicsendqueue_name-message-sleep_seconds",
- "title": "pgmq_public.send(queue_name, message, sleep_seconds)"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/api#pgmq_publicsend_batchqueue_name-messages-sleep_seconds",
- "title": "pgmq_public.send_batch(queue_name, messages, sleep_seconds)"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/api#pgmq_publicarchivequeue_name-message_id",
- "title": "pgmq_public.archive(queue_name, message_id)"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/api#pgmq_publicdeletequeue_name-message_id",
- "title": "pgmq_public.delete(queue_name, message_id)"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/api#pgmq_publicreadqueue_name-sleep_seconds-n",
- "title": "pgmq_public.read(queue_name, sleep_seconds, n)"
- },
- {
- "url": "https://supabase.com/docs/guides/database/connecting-to-postgres/serverless-drivers",
- "title": "Serverless Drivers"
- },
- {
- "url": "https://supabase.com/docs/guides/database/connecting-to-postgres/serverless-drivers#supabase-edge-functions",
- "title": "Supabase Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/database/connecting-to-postgres/serverless-drivers#quickstart",
- "title": "Quickstart"
- },
- {
- "url": "https://supabase.com/docs/guides/database/connecting-to-postgres/serverless-drivers#vercel-edge-functions",
- "title": "Vercel Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/database/connecting-to-postgres/serverless-drivers#cloudflare-workers",
- "title": "Cloudflare Workers"
- },
- {
- "url": "https://supabase.com/docs/guides/database/connecting-to-postgres/serverless-drivers#manual-configuration",
- "title": "Manual configuration"
- },
- {
- "url": "https://supabase.com/docs/guides/database/extensions/pgmq",
- "title": "pgmq: Queues"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/connect-to-postgres",
- "title": "Integrating with Supabase Database (Postgres)"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/connect-to-postgres#ssl-connections",
- "title": "SSL connections"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/connect-to-postgres#production",
- "title": "Production"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/connect-to-postgres#local-development",
- "title": "Local development"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/connect-to-postgres#using-supabase-js",
- "title": "Using supabase-js"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/connect-to-postgres#using-a-postgres-client",
- "title": "Using a Postgres client"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/connect-to-postgres#using-drizzle",
- "title": "Using Drizzle"
- },
- {
- "url": "https://supabase.com/docs/guides/functions",
- "title": "Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/functions#quick-technical-notes",
- "title": "Quick technical notes"
+ "url": "https://supabase.com/docs/guides/functions/schedule-functions",
+ "title": "Scheduling Edge Functions"
},
{
- "url": "https://supabase.com/docs/guides/functions#when-to-use-edge-functions",
- "title": "When to use Edge Functions"
+ "url": "https://supabase.com/docs/guides/functions/schedule-functions#invoke-an-edge-function-every-minute",
+ "title": "Invoke an Edge Function every minute"
},
{
- "url": "https://supabase.com/docs/guides/functions#examples",
+ "url": "https://supabase.com/docs/guides/functions/schedule-functions#examples",
"title": "Examples"
},
{
- "url": "https://supabase.com/docs/guides/functions#how-it-works",
- "title": "How it works"
- }
- ],
- "resultChars": 151897
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"Consuming Supabase Queue Messages with Edge Functions queue.read queue.delete\", limit: 5) { nodes { ... on Guide { title href content subsections { nodes { title href content } } } } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions",
- "title": "Consuming Supabase Queue Messages with Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions#consuming-messages-in-an-edge-function",
- "title": "Consuming messages in an Edge Function"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions#concepts",
- "title": "Concepts"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/architecture",
- "title": "Edge Functions Architecture"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/architecture#1-understanding-edge-functions-through-an-example-image-filtering",
- "title": "1. Understanding Edge Functions through an example: Image filtering"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/architecture#2-deployment-process",
- "title": "2. Deployment process"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/architecture#3-global-distribution-and-routing",
- "title": "3. Global distribution and routing"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/architecture#4-execution-mechanics-fast-and-isolated",
- "title": "4. Execution mechanics: Fast and isolated"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/architecture#benefits-and-use-cases",
- "title": "Benefits and use cases"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart",
- "title": "Quickstart"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#enqueueing-and-dequeueing-messages",
- "title": "Enqueueing and dequeueing messages"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#grant-permissions-to-pgmq_public-database-functions",
- "title": "Grant permissions to pgmq_public database functions"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#concepts",
- "title": "Concepts"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#pull-based-queue",
- "title": "Pull-Based Queue"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#message",
- "title": "Message"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#queue-types",
- "title": "Queue types"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#create-queues",
- "title": "Create Queues"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#what-happens-when-you-create-a-queue",
- "title": "What happens when you create a queue?"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#expose-queues-to-client-side-consumers",
- "title": "Expose Queues to client-side consumers"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart#enable-rls-on-your-tables-in-pgmq-schema",
- "title": "Enable RLS on your tables in pgmq schema"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/recursive-functions",
- "title": "Recursive / Nested Function Calls"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/recursive-functions#what-gets-rate-limited",
- "title": "What gets rate limited"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/recursive-functions#rate-limit-budget",
- "title": "Rate limit budget"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/recursive-functions#handling-rate-limit-errors",
- "title": "Handling rate limit errors"
+ "url": "https://supabase.com/docs/guides/functions/schedule-functions#resources",
+ "title": "Resources"
},
{
- "url": "https://supabase.com/docs/guides/functions/recursive-functions#tips-for-avoiding-rate-limits",
- "title": "Tips for avoiding rate limits"
+ "url": "https://supabase.com/docs/guides/cron",
+ "title": "Cron"
},
{
- "url": "https://supabase.com/docs/guides/functions/recursive-functions#1-batch-operations-instead-of-individual-calls",
- "title": "1. Batch operations instead of individual calls"
+ "url": "https://supabase.com/docs/guides/cron#resources",
+ "title": "Resources"
},
{
- "url": "https://supabase.com/docs/guides/functions/recursive-functions#2-limit-recursion-depth",
- "title": "2. Limit recursion depth"
+ "url": "https://supabase.com/docs/guides/cron#how-does-cron-work",
+ "title": "How does Cron work?"
},
{
- "url": "https://supabase.com/docs/guides/functions/recursive-functions#3-use-queues-for-large-workloads",
- "title": "3. Use queues for large workloads"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net",
+ "title": "pg_net: Async Networking"
},
{
- "url": "https://supabase.com/docs/guides/functions/recursive-functions#4-use-shared-libraries-instead-of-separate-functions",
- "title": "4. Use shared libraries instead of separate functions"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#http_get",
+ "title": "http_get"
},
{
- "url": "https://supabase.com/docs/guides/functions/recursive-functions#5-add-delays-for-non-urgent-processing",
- "title": "5. Add delays for non-urgent processing"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#get-signature",
+ "title": "Signature "
},
{
- "url": "https://supabase.com/docs/guides/functions/recursive-functions#common-patterns-and-their-impact",
- "title": "Common patterns and their impact"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#get-usage",
+ "title": "Usage "
},
{
- "url": "https://supabase.com/docs/guides/functions/recursive-functions#increasing-rate-limits",
- "title": "Increasing rate limits"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#http_post",
+ "title": "http_post"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets",
- "title": "Resumable WebSockets with Edge Functions"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#post-signature",
+ "title": "Signature "
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets#architecture",
- "title": "Architecture"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#post-usage",
+ "title": "Usage "
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets#database-schema",
- "title": "Database schema"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#http_delete",
+ "title": "http_delete"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets#edge-function-websocket-proxy",
- "title": "Edge Function (WebSocket proxy)"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#resources",
+ "title": "Resources"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets#browser-client",
- "title": "Browser client"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#limitations",
+ "title": "Limitations"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets#why-this-pattern-works",
- "title": "Why this pattern works"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#send-multiple-table-rows-in-one-request",
+ "title": "Send multiple table rows in one request"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets#next-steps",
- "title": "Next steps"
- }
- ],
- "resultChars": 105925
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase Cron schedule SQL cron.schedule job name every minute\", limit: 5) { nodes { ... on Guide { title href content subsections { nodes { title href content } } } } } }",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#execute-pg_net-in-a-trigger",
+ "title": "Execute pg_net in a trigger"
+ },
{
- "url": "https://supabase.com/docs/guides/cron/quickstart",
- "title": "Quickstart"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#call-an-endpoint-every-minute-with-pg_cron",
+ "title": "Call an endpoint every minute with pg_cron"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#call-a-database-function-every-5-minutes",
- "title": "Call a database function every 5 minutes"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#invoke-a-supabase-edge-function",
+ "title": "Invoke a Supabase Edge Function"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#schedule-a-job",
- "title": "Schedule a job"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#examples",
+ "title": "Examples"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#edit-a-job",
- "title": "Edit a job"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#alter-settings",
+ "title": "Alter settings"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#activatedeactivate-a-job",
- "title": "Activate/Deactivate a job"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#get-current-settings",
+ "title": "Get current settings"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#unschedule-a-job",
- "title": "Unschedule a job"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#configuration",
+ "title": "Configuration"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#inspecting-job-runs",
- "title": "Inspecting job runs"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#inspecting-failed-requests",
+ "title": "Inspecting failed requests"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#examples",
- "title": "Examples"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#inspecting-request-data",
+ "title": "Inspecting request data"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#delete-data-every-week",
- "title": "Delete data every week"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#post-signature-1",
+ "title": "Signature "
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#run-a-vacuum-every-day",
- "title": "Run a vacuum every day"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#delete-usage",
+ "title": "Usage "
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#call-a-database-stored-procedure",
- "title": "Call a database stored procedure"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#analyzing-responses",
+ "title": "Analyzing responses"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#invoke-supabase-edge-function-every-30-seconds",
- "title": "Invoke Supabase Edge Function every 30 seconds"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#debugging-requests",
+ "title": "Debugging requests"
},
{
- "url": "https://supabase.com/docs/guides/cron/quickstart#caution-scheduling-system-maintenance",
- "title": "Caution: Scheduling system maintenance"
+ "url": "https://supabase.com/docs/guides/database/extensions/pg_net#enable-the-extension",
+ "title": "Enable the extension"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net",
- "title": "pg_net: Async Networking"
+ "url": "https://supabase.com/docs/guides/queues",
+ "title": "Supabase Queues"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#delete-usage",
- "title": "Usage "
+ "url": "https://supabase.com/docs/guides/queues#resources",
+ "title": "Resources"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#enable-the-extension",
- "title": "Enable the extension"
+ "url": "https://supabase.com/docs/guides/queues#features",
+ "title": "Features"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#debugging-requests",
- "title": "Debugging requests"
+ "url": "https://supabase.com/docs/guides/cron/quickstart",
+ "title": "Quickstart"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#analyzing-responses",
- "title": "Analyzing responses"
+ "url": "https://supabase.com/docs/guides/cron/quickstart#delete-data-every-week",
+ "title": "Delete data every week"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#http_get",
- "title": "http_get"
+ "url": "https://supabase.com/docs/guides/cron/quickstart#examples",
+ "title": "Examples"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#get-signature",
- "title": "Signature "
+ "url": "https://supabase.com/docs/guides/cron/quickstart#inspecting-job-runs",
+ "title": "Inspecting job runs"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#get-usage",
- "title": "Usage "
+ "url": "https://supabase.com/docs/guides/cron/quickstart#unschedule-a-job",
+ "title": "Unschedule a job"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#http_post",
- "title": "http_post"
+ "url": "https://supabase.com/docs/guides/cron/quickstart#caution-scheduling-system-maintenance",
+ "title": "Caution: Scheduling system maintenance"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#post-signature",
- "title": "Signature "
+ "url": "https://supabase.com/docs/guides/cron/quickstart#activatedeactivate-a-job",
+ "title": "Activate/Deactivate a job"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#post-usage",
- "title": "Usage "
+ "url": "https://supabase.com/docs/guides/cron/quickstart#edit-a-job",
+ "title": "Edit a job"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#http_delete",
- "title": "http_delete"
+ "url": "https://supabase.com/docs/guides/cron/quickstart#schedule-a-job",
+ "title": "Schedule a job"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#post-signature-1",
- "title": "Signature "
+ "url": "https://supabase.com/docs/guides/cron/quickstart#invoke-supabase-edge-function-every-30-seconds",
+ "title": "Invoke Supabase Edge Function every 30 seconds"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#inspecting-request-data",
- "title": "Inspecting request data"
+ "url": "https://supabase.com/docs/guides/cron/quickstart#call-a-database-stored-procedure",
+ "title": "Call a database stored procedure"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#inspecting-failed-requests",
- "title": "Inspecting failed requests"
+ "url": "https://supabase.com/docs/guides/cron/quickstart#call-a-database-function-every-5-minutes",
+ "title": "Call a database function every 5 minutes"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#configuration",
- "title": "Configuration"
+ "url": "https://supabase.com/docs/guides/cron/quickstart#run-a-vacuum-every-day",
+ "title": "Run a vacuum every day"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#get-current-settings",
- "title": "Get current settings"
+ "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions",
+ "title": "Consuming Supabase Queue Messages with Edge Functions"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#alter-settings",
- "title": "Alter settings"
+ "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions#consuming-messages-in-an-edge-function",
+ "title": "Consuming messages in an Edge Function"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#examples",
- "title": "Examples"
+ "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions#concepts",
+ "title": "Concepts"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#invoke-a-supabase-edge-function",
- "title": "Invoke a Supabase Edge Function"
+ "url": "https://supabase.com/docs/guides/queues/quickstart",
+ "title": "Quickstart"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#call-an-endpoint-every-minute-with-pg_cron",
- "title": "Call an endpoint every minute with pg_cron"
+ "url": "https://supabase.com/docs/guides/queues/quickstart#enqueueing-and-dequeueing-messages",
+ "title": "Enqueueing and dequeueing messages"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#execute-pg_net-in-a-trigger",
- "title": "Execute pg_net in a trigger"
+ "url": "https://supabase.com/docs/guides/queues/quickstart#grant-permissions-to-pgmq_public-database-functions",
+ "title": "Grant permissions to pgmq_public database functions"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#send-multiple-table-rows-in-one-request",
- "title": "Send multiple table rows in one request"
+ "url": "https://supabase.com/docs/guides/queues/quickstart#enable-rls-on-your-tables-in-pgmq-schema",
+ "title": "Enable RLS on your tables in pgmq schema"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#resources",
- "title": "Resources"
+ "url": "https://supabase.com/docs/guides/queues/quickstart#expose-queues-to-client-side-consumers",
+ "title": "Expose Queues to client-side consumers"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pg_net#limitations",
- "title": "Limitations"
+ "url": "https://supabase.com/docs/guides/queues/quickstart#what-happens-when-you-create-a-queue",
+ "title": "What happens when you create a queue?"
},
{
- "url": "https://supabase.com/docs/guides/functions/schedule-functions",
- "title": "Scheduling Edge Functions"
+ "url": "https://supabase.com/docs/guides/queues/quickstart#create-queues",
+ "title": "Create Queues"
},
{
- "url": "https://supabase.com/docs/guides/functions/schedule-functions#resources",
- "title": "Resources"
+ "url": "https://supabase.com/docs/guides/queues/quickstart#queue-types",
+ "title": "Queue types"
},
{
- "url": "https://supabase.com/docs/guides/functions/schedule-functions#invoke-an-edge-function-every-minute",
- "title": "Invoke an Edge Function every minute"
+ "url": "https://supabase.com/docs/guides/queues/quickstart#message",
+ "title": "Message"
},
{
- "url": "https://supabase.com/docs/guides/functions/schedule-functions#examples",
- "title": "Examples"
+ "url": "https://supabase.com/docs/guides/queues/quickstart#pull-based-queue",
+ "title": "Pull-Based Queue"
},
{
- "url": "https://supabase.com/docs/guides/cron",
- "title": "Cron"
+ "url": "https://supabase.com/docs/guides/queues/quickstart#concepts",
+ "title": "Concepts"
},
{
- "url": "https://supabase.com/docs/guides/cron#resources",
- "title": "Resources"
+ "url": "https://supabase.com/docs/guides/cron/install",
+ "title": "Install"
},
{
- "url": "https://supabase.com/docs/guides/cron#how-does-cron-work",
- "title": "How does Cron work?"
+ "url": "https://supabase.com/docs/guides/cron/install#uninstall",
+ "title": "Uninstall"
+ }
+ ],
+ "resultChars": 130674
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Queues create_queue pgmq.create send message pop queue Supabase\", limit: 5) { nodes { ... on Guide { title href content } } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/queues",
+ "title": "Supabase Queues"
},
{
- "url": "https://supabase.com/docs/guides/auth/auth-hooks/send-email-hook",
- "title": "Send Email Hook"
+ "url": "https://supabase.com/docs/guides/queues/quickstart",
+ "title": "Quickstart"
},
{
- "url": "https://supabase.com/docs/guides/auth/auth-hooks/send-email-hook#email-change-behavior-and-token-hash-mapping",
- "title": "Email change behavior and token hash mapping"
+ "url": "https://supabase.com/docs/guides/queues/api",
+ "title": "API"
},
{
- "url": "https://supabase.com/docs/guides/auth/auth-hooks/send-email-hook#email-sending-behavior",
- "title": "Email sending behavior"
+ "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions",
+ "title": "Consuming Supabase Queue Messages with Edge Functions"
},
{
- "url": "https://supabase.com/docs/guides/auth/auth-hooks/send-email-hook#what-to-send",
- "title": "What to send"
+ "url": "https://supabase.com/docs/guides/queues/expose-self-hosted-queues",
+ "title": "Expose Queues for local and self-hosted Supabase"
}
],
- "resultChars": 176011
+ "resultChars": 21990
}
]
},
+ "usage": {
+ "inputTokens": 821904,
+ "outputTokens": 5933,
+ "cachedInputTokens": 770491
+ },
+ "durationMs": 226626,
"prompt": "I want to set up a recurring background workflow on my local Supabase stack.\n\nCan you set up a cron job called `enqueue-tasks` to run every minute and push a task into a queue called `tasks`? Then add a `process-tasks` edge function that reads messages off the `tasks` queue and removes them, so a scheduled worker can keep the backlog drained.",
"promptSourcePath": "evals/build-cli-003-pg-cron-queue-workflow/PROMPT.md",
"attempts": 1,
@@ -14368,34 +17958,40 @@
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase CLI local development restore pg_dump pg_restore database dump\", limit: 5) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"Supabase CLI local project restore pg_restore custom format dump local database\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
"url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres",
"title": "Migrate from Postgres to Supabase"
},
- {
- "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
- "title": "Restore a Platform Project to Self-Hosted"
- },
{
"url": "https://supabase.com/docs/guides/local-development/restoring-downloaded-backup",
"title": "Restoring a downloaded backup locally"
},
{
- "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/vercel-postgres",
- "title": "Migrate from Vercel Postgres to Supabase"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
+ "title": "Restore a Platform Project to Self-Hosted"
},
{
- "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/neon",
- "title": "Migrate from Neon to Supabase"
+ "url": "https://supabase.com/docs/reference/cli/supabase-db-dump",
+ "title": "Dumps data or schemas from the remote database"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/migrating-within-supabase/backup-restore",
+ "title": "Backup and Restore using the CLI"
}
],
- "resultChars": 42818
+ "resultChars": 72826
}
]
},
+ "usage": {
+ "inputTokens": 918567,
+ "outputTokens": 2988,
+ "cachedInputTokens": 864801
+ },
+ "durationMs": 265271,
"prompt": "I have an existing Postgres database I want to migrate to Supabase. There's a binary dump at `source.dump` in the current directory.\n\nCan you set up a local Supabase project and restore the dump into it?",
"promptSourcePath": "evals/build-database-001-migrate-postgres-to-supabase/PROMPT.md",
"attempts": 1,
@@ -14460,7 +18056,7 @@
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Edge Functions authenticate user Authorization header supabase-js getUser service role RLS\", limit: 5) { nodes { ... on Guide { title href content } ... on ClientLibraryFunctionReference { title href content language methodName } } } }",
+ "query": "query { searchDocs(query: \"Edge Functions authenticate user Authorization header createClient global headers auth getUser RLS\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
@@ -14468,22 +18064,32 @@
"title": "Integrating With Supabase Auth"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs",
- "title": "Build a User Management App with Next.js"
+ "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
+ "title": "Why is my service role key client getting RLS errors or not returning data?"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
+ "url": "https://supabase.com/docs/guides/functions/auth-headers",
+ "title": "Authorization headers"
},
{
- "url": "https://supabase.com/docs/guides/functions",
- "title": "Edge Functions"
+ "url": "https://supabase.com/docs/guides/getting-started/features",
+ "title": "Features"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
}
],
- "resultChars": 70238
+ "resultChars": 32476
}
]
},
+ "usage": {
+ "inputTokens": 356807,
+ "outputTokens": 2181,
+ "cachedInputTokens": 332670
+ },
+ "durationMs": 68936,
"prompt": "I built an Edge Function called `private-notes` for showing a user's saved\nprivate notes.\n\nCan you check whether there's any way one user could see another user's notes?\n\nPlease fix and deploy it if needed.",
"promptSourcePath": "evals/build-functions-004-service-role-bypass/PROMPT.md",
"attempts": 1,
@@ -14528,17 +18134,17 @@
{
"name": "user with JWT reads only their own rows",
"passed": true,
- "notes": "status 200: [{\"user_id\":\"66ade428-6967-435a-a7db-83fb2df16e59\",\"metric\":\"steps_a_ms6zjqfe\",\"value\":111}]"
+ "notes": "status 200: [{\"user_id\":\"7903f4d7-5350-4f63-9c7e-101722b3c748\",\"metric\":\"steps_a_ms7qexeu\",\"value\":111}]"
},
{
"name": "user cannot read another user's rows by passing user_id",
"passed": true,
- "notes": "status 200: [{\"user_id\":\"66ade428-6967-435a-a7db-83fb2df16e59\",\"metric\":\"steps_a_ms6zjqfe\",\"value\":111}]"
+ "notes": "status 200: [{\"user_id\":\"7903f4d7-5350-4f63-9c7e-101722b3c748\",\"metric\":\"steps_a_ms7qexeu\",\"value\":111}]"
},
{
"name": "service key bypasses RLS to read the target user's rows",
"passed": true,
- "notes": "status 200: [{\"user_id\":\"21a6e5f1-81f2-4735-b460-3461be1f3c1d\",\"metric\":\"steps_b_ms6zjqfe\",\"value\":222}]"
+ "notes": "status 200: [{\"user_id\":\"3aecca92-537a-4350-a5b6-183c777bf1f8\",\"metric\":\"steps_b_ms7qexeu\",\"value\":222}]"
},
{
"name": "non-service key is not granted service access",
@@ -14569,162 +18175,224 @@
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Edge Functions authenticate JWT getClaims service role apikey header SUPABASE_SERVICE_ROLE_KEY\", limit: 8) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"Edge Functions authenticate JWT Authorization header service role apikey header SUPABASE_SERVICE_ROLE_KEY createClient getUser\", limit: 8) { nodes { __typename title href content } } }",
"hasContent": true,
"pages": [
{
"url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
"title": "Integrating With Supabase Auth"
},
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
+ "title": "Why is my service role key client getting RLS errors or not returning data?"
+ },
{
"url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
"title": "New API Keys and Asymmetric Authentication"
},
- {
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
- },
{
"url": "https://supabase.com/docs/guides/getting-started/api-keys",
"title": "Understanding API keys"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
+ "url": "https://supabase.com/docs/guides/functions/auth-headers",
+ "title": "Authorization headers"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
- "title": "Why is my service role key client getting RLS errors or not returning data?"
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
},
{
- "url": "https://supabase.com/docs/guides/auth/third-party/firebase-auth",
- "title": "Firebase Auth"
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
},
{
- "url": "https://supabase.com/docs/guides/auth/jwt-fields",
- "title": "JWT Claims Reference"
+ "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets",
+ "title": "Resumable WebSockets with Edge Functions"
}
],
- "resultChars": 87163
+ "resultChars": 69243
},
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"New API Keys Edge Functions apikey secret key service role validate secret key @supabase/server\", limit: 10) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"@supabase/server verifyCredentials apikey service_role Edge Functions dual authentication\", limit: 10) { nodes { __typename title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
+ "url": "https://supabase.com/docs/guides/functions/auth-headers",
+ "title": "Authorization headers"
},
{
"url": "https://supabase.com/docs/guides/functions/auth",
"title": "Securing Edge Functions"
},
+ {
+ "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets",
+ "title": "Resumable WebSockets with Edge Functions"
+ },
{
"url": "https://supabase.com/docs/guides/getting-started/api-keys",
"title": "Understanding API keys"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/cloudflare-turnstile",
- "title": "CAPTCHA support with Cloudflare Turnstile"
+ "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
+ "title": "Integrating With Supabase Auth"
},
{
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
+ "url": "https://supabase.com/docs/guides/functions/function-configuration",
+ "title": "Function Configuration"
},
{
- "url": "https://supabase.com/docs/guides/auth/passkeys",
- "title": "Passkey authentication"
+ "url": "https://supabase.com/docs/reference/cli/supabase-functions",
+ "title": "Manage Supabase Edge functions"
},
{
- "url": "https://supabase.com/docs/guides/functions/quickstart-dashboard",
- "title": "Getting Started with Edge Functions (Dashboard)"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
+ "title": "Envoy API Gateway"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/secure-data",
+ "title": "Securing your data"
+ }
+ ],
+ "resultChars": 84025
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Securing Edge Functions multiple auth modes user secret withSupabase auth array\", limit: 5) { nodes { __typename title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
+ "title": "Integrating With Supabase Auth"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
},
{
"url": "https://supabase.com/docs/guides/database/secure-data",
"title": "Securing your data"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-ionic-angular",
- "title": "Build a User Management App with Ionic Angular"
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables"
}
],
- "resultChars": 114420
+ "resultChars": 35980
},
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"@supabase/server validateApiKey Edge Function SUPABASE_SECRET_KEYS\", limit: 5) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"withSupabase({ auth: ['user', 'secret'] })\", limit: 10) { nodes { __typename title href content } } }",
"hasContent": true,
"pages": [
{
"url": "https://supabase.com/docs/guides/functions/auth",
"title": "Securing Edge Functions"
},
+ {
+ "url": "https://supabase.com/docs/guides/auth/choosing-a-server-package",
+ "title": "Which package to use"
+ },
{
"url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
"title": "Migrating to publishable and secret API keys"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
+ "url": "https://supabase.com/docs/guides/auth",
+ "title": "Auth"
},
{
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
+ "url": "https://supabase.com/docs/guides/functions/connect-to-postgres",
+ "title": "Integrating with Supabase Database (Postgres)"
},
{
- "url": "https://supabase.com/docs/guides/auth/passkeys",
- "title": "Passkey authentication"
+ "url": "https://supabase.com/docs/guides/functions/error-codes",
+ "title": "Error codes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/enterprise-sso",
+ "title": "Enterprise Single Sign-On"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/performing-administration-tasks-on-the-server-side-with-the-servicerole-secret-BYM4Fa",
+ "title": "Performing administration tasks on the server side with a secret key"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/server-side",
+ "title": "Server-Side Rendering"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs",
+ "title": "Build a User Management App with Next.js"
}
],
- "resultChars": 51999
+ "resultChars": 92577
},
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"@supabase/server service_role apikey legacy service role Edge Functions withSupabase auth mode\", limit: 8) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"@supabase/server legacy SUPABASE_SERVICE_ROLE_KEY apikey verifyCredentials service_role auth mode\", limit: 10) { nodes { __typename title href content } } }",
"hasContent": true,
"pages": [
+ {
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
+ },
{
"url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
"title": "Migrating to publishable and secret API keys"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
- "title": "Integrating With Supabase Auth"
+ "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
+ "title": "Why is my service role key client getting RLS errors or not returning data?"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
},
{
"url": "https://supabase.com/docs/guides/getting-started/api-keys",
"title": "Understanding API keys"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
+ "url": "https://supabase.com/docs/guides/database/postgres/roles",
+ "title": "Postgres Roles"
},
{
- "url": "https://supabase.com/docs/guides/auth/choosing-a-server-package",
- "title": "Which package to use"
+ "url": "https://supabase.com/docs/guides/auth/third-party/auth0",
+ "title": "Auth0"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
- "title": "Why is my service role key client getting RLS errors or not returning data?"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys",
+ "title": "JWT Signing Keys"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
+ "url": "https://supabase.com/docs/guides/auth/third-party/firebase-auth",
+ "title": "Firebase Auth"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security"
}
],
- "resultChars": 73001
+ "resultChars": 141414
}
]
},
+ "usage": {
+ "inputTokens": 1884191,
+ "outputTokens": 15131,
+ "cachedInputTokens": 1797594
+ },
+ "durationMs": 378948,
"prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nOur product stores per-user metrics in the existing `user_stats` table.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.",
"promptSourcePath": "evals/build-functions-005-dual-auth-user-secret/PROMPT.md",
"attempts": 1,
@@ -14768,7 +18436,7 @@
{
"name": "user A lists only own files",
"passed": true,
- "notes": "saw: 019fb129-6dc4-779f-a3a1-a1c86804f6c6/receipt-alpha.pdf, 019fb129-6dc4-779f-a3a1-a1c86804f6c6/receipt-beta.pdf"
+ "notes": "saw: 019fb3d8-3473-708c-915e-3a7bb033e086/receipt-alpha.pdf, 019fb3d8-3473-708c-915e-3a7bb033e086/receipt-beta.pdf"
},
{
"name": "user B cannot read user A files",
@@ -14789,7 +18457,7 @@
{
"name": "configured private per-user storage access",
"passed": true,
- "judgeNotes": "The answer creates a private user-files bucket, keeps RLS enabled, adds authenticated SELECT and INSERT policies scoped to bucket and owner folder via auth.uid(), and provides supabase-js createSignedUrl with a short expiry. No public bucket, permissive policies, public URL, or client service role usage."
+ "judgeNotes": "Meets all requirements: private user-files bucket, RLS remains enabled, authenticated owner-scoped SELECT and INSERT policies with WITH CHECK, and supabase-js createSignedUrl with a short expiry."
}
],
"skills": {
@@ -14800,7 +18468,7 @@
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase Storage RLS policy foldername auth.uid private bucket createSignedUrl JavaScript\", limit: 5) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"Storage access control RLS policies storage.objects foldername auth.uid signed URL createSignedUrl private bucket supabase-js\", limit: 5) { nodes { ... on Guide { title href content } ... on ClientLibraryFunctionReference { title href content language methodName } } } }",
"hasContent": true,
"pages": [
{
@@ -14808,26 +18476,32 @@
"title": "Storage Buckets"
},
{
- "url": "https://supabase.com/docs/guides/storage/schema/helper-functions",
- "title": "Storage Helper Functions"
+ "url": "https://supabase.com/docs/guides/storage/security/access-control",
+ "title": "Storage Access Control"
},
{
"url": "https://supabase.com/docs/guides/security/product-security",
"title": "Secure configuration of Supabase products"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
- "title": "Configure S3 Storage"
+ "url": "https://supabase.com/docs/guides/storage/schema/custom-roles",
+ "title": "Custom Roles"
},
{
"url": "https://supabase.com/docs/guides/storage/serving/downloads",
"title": "Serving assets from Storage"
}
],
- "resultChars": 23009
+ "resultChars": 15993
}
]
},
+ "usage": {
+ "inputTokens": 230937,
+ "outputTokens": 2017,
+ "cachedInputTokens": 208353
+ },
+ "durationMs": 59435,
"prompt": "Our app lets signed-in users keep personal files like receipts and bank\nstatements. These files are private — a user must only ever be able to upload\nand download their own. The app uploads each file under a path that starts\nwith the owner's user id, e.g. `/receipt-march.pdf`.\n\nSet up a `user-files` bucket on our project and lock it down that way.\n\nUsers also sometimes share one of their files with someone else through a\ntemporary link that expires. Include the supabase-js code the app should use\nfor that.",
"promptSourcePath": "evals/build-storage-001-private-bucket-access/PROMPT.md",
"attempts": 1,
@@ -14858,17 +18532,17 @@
{
"name": "pgTAP test file(s) written under supabase/tests/",
"passed": true,
- "notes": "1 file(s): supabase/tests/tenant_isolation.test.sql"
+ "notes": "1 file(s): supabase/tests/database/tenant_isolation.test.sql"
},
{
"name": "pgTAP isolation tests ran and pass",
"passed": true,
- "notes": "8 passed, 3 failed"
+ "notes": "20 passed, 0 failed"
},
{
"name": "agent correctly identifies the posts isolation bug from test results",
"passed": true,
- "judgeNotes": "Correctly identifies `posts` as having broken tenant isolation, grounded in pgTAP failures showing cross-tenant post visibility, and distinguishes `notes` as correctly restricted."
+ "judgeNotes": "The agent correctly identified `posts` as having broken tenant isolation, specifically that a tenant A authenticated user could see 2/2 posts across organizations instead of only their own. It grounded this in reproduction/test results and did not misattribute the read-isolation flaw to `notes`."
}
],
"skills": {
@@ -14879,34 +18553,68 @@
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"database testing pgTAP row level security auth.uid set_config request.jwt.claims\", limit: 5) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"Supabase database testing pgTAP RLS auth.uid set role authenticated tests\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/realtime/authorization",
- "title": "Realtime Authorization"
+ "url": "https://supabase.com/docs/guides/local-development/testing/overview",
+ "title": "Testing Overview"
},
{
- "url": "https://supabase.com/docs/guides/auth/auth-mfa",
- "title": "Multi-Factor Authentication"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended",
+ "title": "Advanced pgTAP Testing"
},
{
- "url": "https://supabase.com/docs/guides/ai/rag-with-permissions",
- "title": "RAG with Permissions"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pgaudit",
- "title": "PGAudit: Postgres Auditing"
+ "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
+ "title": "Token Security and Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/features",
- "title": "Features"
+ "url": "https://supabase.com/docs/guides/database/testing",
+ "title": "Testing Your Database"
+ }
+ ],
+ "resultChars": 78740
+ },
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"pgTAP throws_ok row level security policy test Supabase\", limit: 5) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended",
+ "title": "Advanced pgTAP Testing"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/testing/overview",
+ "title": "Testing Overview"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/extensions/pgtap",
+ "title": "pgTAP: Unit Testing"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli/testing-and-linting",
+ "title": "Testing and linting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/testing",
+ "title": "Testing Your Database"
}
],
- "resultChars": 72236
+ "resultChars": 47133
}
]
},
+ "usage": {
+ "inputTokens": 561038,
+ "outputTokens": 8820,
+ "cachedInputTokens": 525955
+ },
+ "durationMs": 172885,
"prompt": "Can you audit the tenant isolation on our tables? Write some database tests covering both the happy path and the negative case, run them, and share the results.",
"promptSourcePath": "evals/build-tests-001-rls-tenant-isolation/PROMPT.md",
"attempts": 1,
@@ -14943,12 +18651,12 @@
{
"name": "HNSW index on the embedding column",
"passed": true,
- "notes": "CREATE INDEX document_sections_embedding_hnsw_idx ON public.document_sections USING hnsw (embedding vector_cosine_ops)"
+ "notes": "CREATE INDEX document_sections_embedding_hnsw_idx ON public.document_sections USING hnsw (embedding vector_ip_ops)"
},
{
"name": "index operator class matches the search operator",
"passed": true,
- "notes": "function operators: <=>\nindexes: CREATE INDEX document_sections_embedding_hnsw_idx ON public.document_sections USING hnsw (embedding vector_cosine_ops)"
+ "notes": "function operators: <#>\nindexes: CREATE INDEX document_sections_embedding_hnsw_idx ON public.document_sections USING hnsw (embedding vector_ip_ops)"
},
{
"name": "user A search returns only own sections, best match first",
@@ -14975,7 +18683,7 @@
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"pgvector semantic search match_documents RPC row level security auth.uid embeddings\", limit: 5) { nodes { ... on Guide { title href content } ... on ClientLibraryFunctionReference { title href content language methodName } } } }",
+ "query": "query { searchDocs(query: \"pgvector semantic search match_documents RPC row level security auth.uid security invoker\", limit: 5) { nodes { ... on Guide { title href content } ... on ClientLibraryFunctionReference { title href content methodName language } } } }",
"hasContent": true,
"pages": [
{
@@ -14991,18 +18699,24 @@
"title": "Hybrid search"
},
{
- "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
- "title": "Automatic embeddings"
+ "url": "https://supabase.com/docs/guides/database/full-text-search",
+ "title": "Full Text Search"
},
{
- "url": "https://supabase.com/docs/guides/ai/vector-columns",
- "title": "Vector columns"
+ "url": "https://supabase.com/docs/guides/getting-started/features",
+ "title": "Features"
}
],
- "resultChars": 80299
+ "resultChars": 95111
}
]
},
+ "usage": {
+ "inputTokens": 510341,
+ "outputTokens": 5838,
+ "cachedInputTokens": 481268
+ },
+ "durationMs": 164454,
"prompt": "We're adding semantic search to our internal knowledge base app. I already wrote the edge functions, but search doesn't work yet. Can you set up whatever the database needs to make search work end to end?\n\nSome documents are confidential, so users should only have access to documents they own.",
"promptSourcePath": "evals/build-vectors-001-rag-with-permissions/PROMPT.md",
"attempts": 1,
@@ -15015,7 +18729,7 @@
"agent": "codex",
"modelProvider": "openai",
"modelId": "gpt-5.6-sol",
- "reasoningEffort": "low"
+ "reasoningEffort": "medium"
},
"eval": "deploy-database-001-prometheus-metrics",
"stage": "deploy",
@@ -15035,12 +18749,12 @@
{
"name": "configured the Supabase Metrics API scrape correctly",
"passed": true,
- "judgeNotes": "Meets requirements: app scrape preserved, Supabase HTTPS metrics endpoint configured with Basic Auth password_file, project target present, and docker-compose wires the secret to Prometheus."
+ "judgeNotes": "Meets requirements: preserves app scrape, adds HTTPS Supabase Metrics API target with correct path and project host, uses basic_auth with password_file, and wires the file via a Compose secret mounted at /run/secrets/supabase_metrics_api_key."
},
{
"name": "documented live deployment and verification steps",
"passed": true,
- "judgeNotes": "README includes Secret API key creation, environment-backed Compose secret mounted to the expected password_file path, restart/recreate and reload commands, and concrete verification via Prometheus targets/Grafana/curl."
+ "judgeNotes": "README includes Secret API key creation, matching secret file placement, Compose recreate/reload instructions, and concrete verification via Prometheus targets/PromQL."
}
],
"skills": {
@@ -15051,46 +18765,48 @@
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Prometheus metrics hosted project customer v1 privileged metrics service_role Supabase observability\", limit: 8) { nodes { __typename title href content } } }",
+ "query": "query { searchDocs(query: \"Prometheus metrics endpoint hosted project customer v1 privileged metrics service role authentication\", limit: 8) { nodes { __typename title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-self-hosted",
- "title": "Metrics API with Prometheus & Grafana (self-hosted)"
- },
- {
- "url": "https://supabase.com/docs/guides/telemetry/metrics",
- "title": "Metrics API"
- },
- {
- "url": "https://supabase.com/docs/guides/telemetry/metrics/vendor-agnostic",
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic",
"title": "Vendor-agnostic Metrics API setup"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-cloud",
- "title": "Metrics API with Grafana Cloud"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted",
+ "title": "Metrics API with Prometheus & Grafana (self-hosted)"
},
{
- "url": "https://supabase.com/docs/guides/platform/read-replicas",
- "title": "Read Replicas"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud",
+ "title": "Metrics API with Grafana Cloud"
},
{
- "url": "https://supabase.com/docs/guides/database/connection-management",
- "title": "Connection management"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics",
+ "title": "Metrics API"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/roles",
- "title": "Postgres Roles"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
+ "title": "Envoy API Gateway"
},
{
"url": "https://supabase.com/docs/guides/security/security-testing",
"title": "Security testing of your Supabase projects"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/extensions/pgaudit",
+ "title": "PGAudit: Postgres Auditing"
}
],
- "resultChars": 48186
+ "resultChars": 64134
}
]
},
+ "usage": {
+ "inputTokens": 393161,
+ "outputTokens": 6847,
+ "cachedInputTokens": 363046
+ },
+ "durationMs": 128871,
"prompt": "Can you wire my Supabase project metrics into our existing observability stack and document\nin the observability README what we need to do to make the config live?",
"promptSourcePath": "evals/deploy-database-001-prometheus-metrics/PROMPT.md",
"attempts": 1,
@@ -15129,7 +18845,7 @@
{
"name": "the weather function reads WEATHER_API_KEY from the environment",
"passed": true,
- "judgeNotes": "Reads WEATHER_API_KEY from the runtime environment via Deno.env.get(\"WEATHER_API_KEY\")."
+ "judgeNotes": "The function reads WEATHER_API_KEY from the runtime environment using Deno.env.get(\"WEATHER_API_KEY\")."
},
{
"name": "WEATHER_API_KEY value is not committed to the repo",
@@ -15144,13 +18860,9 @@
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase Edge Functions environment variables secrets set env file deploy function no verify jwt invoke\", limit: 6) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } } } }",
+ "query": "query { searchDocs(query: \"Supabase Edge Functions secrets set env-file deploy function no verify jwt invoke\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
- },
{
"url": "https://supabase.com/docs/guides/ai/examples/openai",
"title": "Generating OpenAI GPT3 completions"
@@ -15159,19 +18871,29 @@
"url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
"title": "Migrating to publishable and secret API keys"
},
+ {
+ "url": "https://supabase.com/docs/guides/functions/examples/upstash-redis",
+ "title": "Upstash Redis"
+ },
{
"url": "https://supabase.com/docs/guides/functions/secrets",
"title": "Environment Variables"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/upstash-redis",
- "title": "Upstash Redis"
+ "url": "https://supabase.com/docs/guides/integrations/supabase-for-platforms",
+ "title": "Supabase for Platforms"
}
],
- "resultChars": 35184
+ "resultChars": 45765
}
]
},
+ "usage": {
+ "inputTokens": 2547058,
+ "outputTokens": 9615,
+ "cachedInputTokens": 2459277
+ },
+ "durationMs": 318287,
"prompt": "Our weather widget currently calls WeatherAPI straight from the browser, which\nleaks our API key. I want to move that behind a Supabase Edge Function called\n`weather` that holds the key server-side and proxies the request.\n\nThe function should read the key from an environment variable named\n`WEATHER_API_KEY`. Our key already lives in a local `.env` file at the project\nroot.\n\nDeploy the function to our project so it's live, and make sure the deployed\nfunction can actually read the key at runtime.",
"promptSourcePath": "evals/deploy-functions-001-edge-function-secrets/PROMPT.md",
"attempts": 1,
@@ -15224,71 +18946,53 @@
"docs": {
"calls": [
{
- "source": "search_docs",
- "query": "query { searchDocs(query: \"self-hosting Docker docker-compose .env secrets JWT_SECRET ANON_KEY SERVICE_ROLE_KEY POOLER_TENANT_ID\", limit: 8) { nodes { __typename title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
- "title": "Envoy API Gateway"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/docker",
- "title": "Self-Hosting with Docker"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth",
- "title": "Configure Social Login (OAuth) Providers"
- },
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"self-hosting Docker docker-compose .env secrets JWT_SECRET ANON_KEY SERVICE_ROLE_KEY dashboard username password\", limit: 8) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
},
{
"url": "https://supabase.com/docs/guides/auth/signing-keys",
"title": "JWT Signing Keys"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/custom-email-templates",
- "title": "Custom Email Templates"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
+ "title": "Envoy API Gateway"
},
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-saml-sso",
- "title": "Configure SAML SSO"
- }
- ],
- "resultChars": 171411
- },
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"Self-hosting with Docker Quick Start Linux download docker directory git sparse checkout generate-keys.sh\", limit: 5) { nodes { __typename title href content } } }",
- "hasContent": true,
- "pages": [
{
"url": "https://supabase.com/docs/guides/self-hosting/docker",
"title": "Self-Hosting with Docker"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth",
+ "title": "Configure Social Login (OAuth) Providers"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
- "title": "Envoy API Gateway"
+ "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
+ "title": "Restore a Platform Project to Self-Hosted"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting",
- "title": "Self-Hosting"
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-kotlin",
+ "title": "Build a Product Management Android App with Jetpack Compose"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
+ "title": "Configure S3 Storage"
}
],
- "resultChars": 79242
+ "resultChars": 201909
}
]
},
+ "usage": {
+ "inputTokens": 853529,
+ "outputTokens": 11658,
+ "cachedInputTokens": 807094
+ },
+ "durationMs": 187743,
"prompt": "I'm moving off the hosted Supabase and running the whole thing myself on a VPS I\njust spun up. Can you get a Docker setup ready for me to copy onto the box?\n\nI don't need it running here, I'll do the actual bring-up once I'm on the\nserver. I just want everything in place and the secrets set up. Put it in a `supabase-docker/`\nfolder at the repo root so I can scp the whole thing across in one go.",
"promptSourcePath": "evals/deploy-self-hosting-001-docker-compose/PROMPT.md",
"attempts": 1,
@@ -15344,7 +19048,7 @@
{
"name": "diagnosed and explained session revocation",
"passed": true,
- "judgeNotes": "Meets the rubric: identifies the soft-delete-only RPC as the cause, implements deletion of the auth user with session/refresh-token revocation via cascade plus RLS gates that close the data path for stale JWTs, explains JWTs remain cryptographically valid until expiry while data access is blocked by the shipped RLS fix, and correctly distinguishes publishable frontend keys from secret backend-only RLS-bypassing keys."
+ "judgeNotes": "Meets rubric: identifies soft-delete-only root cause, implements auth user deletion/session revocation plus RLS live-user gating, consistently explains JWT residual validity and why Data API access is blocked by the implemented RLS check, and correctly distinguishes publishable vs secret keys and RLS bypass behavior."
}
],
"skills": {
@@ -15355,7 +19059,7 @@
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"delete user access token remains valid until expiry revoke sessions JWT RLS\", limit: 5) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } } } }",
+ "query": "query { searchDocs(query: \"delete user JWT remains valid until expiry sign out sessions RLS auth.uid deleted user access token\", limit: 8) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
@@ -15363,40 +19067,47 @@
"title": "User sessions"
},
{
- "url": "https://supabase.com/docs/guides/realtime/authorization",
- "title": "Realtime Authorization"
+ "url": "https://supabase.com/docs/guides/auth/managing-user-data",
+ "title": "User Management"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/javascript/auth-signout"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/should-i-set-a-shorter-max-age-parameter-on-the-cookies-8sbF4V",
- "title": "Should I set a shorter Max-Age parameter on the cookies?"
+ "url": "https://supabase.com/docs/guides/storage/security/ownership",
+ "title": "Ownership"
},
{
"url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
"title": "Token Security and Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/storage/security/ownership",
- "title": "Ownership"
+ "url": "https://supabase.com/docs/guides/storage/management/delete-objects",
+ "title": "Delete Objects"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/signing-keys",
+ "title": "JWT Signing Keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/users",
+ "title": "Users"
}
],
- "resultChars": 40980
+ "resultChars": 83955
},
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"publishable key secret key frontend RLS bypass legacy anon service_role\", limit: 5) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } } } }",
+ "query": "query { searchDocs(query: \"publishable key secret key legacy anon service_role RLS frontend migration\", limit: 10) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/storage/security/access-control",
- "title": "Storage Access Control"
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs",
+ "title": "Build a User Management App with RedwoodJS"
},
{
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
- "title": "Row Level Security"
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
},
{
"url": "https://supabase.com/docs/guides/auth/signing-keys",
@@ -15405,32 +19116,70 @@
{
"url": "https://supabase.com/docs/guides/getting-started/api-keys",
"title": "Understanding API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/secure-data",
+ "title": "Securing your data"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/jwt-fields",
+ "title": "JWT Claims Reference"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/rotating-anon-service-and-jwt-secrets-1Jq6yd",
+ "title": "Rotating Anon, Service, and JWT Secrets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/storage/security/access-control",
+ "title": "Storage Access Control"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security"
}
],
- "resultChars": 91501
+ "resultChars": 153619
},
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"self delete user database function auth.users security definer delete account\", limit: 8) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } } } }",
+ "query": "query { searchDocs(query: \"Understanding API keys publishable secret keys sb_publishable sb_secret bypass RLS\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/auth/managing-user-data",
- "title": "User Management"
+ "url": "https://supabase.com/docs/guides/getting-started/api-keys",
+ "title": "Understanding API keys"
},
{
- "url": "https://supabase.com/docs/guides/database/extensions/pgaudit",
- "title": "PGAudit: Postgres Auditing"
+ "url": "https://supabase.com/docs/guides/storage/security/access-control",
+ "title": "Storage Access Control"
},
{
- "url": "https://supabase.com/docs/guides/auth/auth-anonymous",
- "title": "Anonymous Sign-Ins"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
}
],
- "resultChars": 38021
+ "resultChars": 74569
}
]
},
+ "usage": {
+ "inputTokens": 790652,
+ "outputTokens": 7400,
+ "cachedInputTokens": 751134
+ },
+ "durationMs": 185118,
"prompt": "Last week support removed a user through our app's delete-account flow — the\napp calls the `delete_account` function over RPC as the signed-in user. This\nmorning that same person was back: still signed in, reading and saving their\ndata like nothing happened.\n\nFigure out why the account still works, fix the flow so a deleted account\nloses access, and tell me whether there is any window where they could still\nget in after the fix.\n\nOne more thing while you're at it: we're migrating off the legacy\nanon/service_role API keys to the new publishable and secret keys, and the\nteam isn't sure which one belongs in the frontend and what each means for\nRLS. Give us a quick rundown.",
"promptSourcePath": "evals/investigate-auth-001-deleted-user-access/PROMPT.md",
"attempts": 1,
@@ -15482,7 +19231,7 @@
{
"name": "diagnosed missing publication membership",
"passed": true,
- "judgeNotes": "The assistant correctly diagnosed that the channel could subscribe while INSERT events were silent because public.orders was missing from the supabase_realtime publication, added only public.orders to the existing publication via ALTER PUBLICATION in an idempotent migration, preserved courier_locations and existing RLS/policies, and did not blame or weaken RLS/client/networking."
+ "judgeNotes": "Identified orders missing from supabase_realtime, added only public.orders to the existing publication, verified courier_locations remained, and did not weaken RLS/policies or blame unrelated causes."
}
],
"skills": {
@@ -15492,6 +19241,12 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 226372,
+ "outputTokens": 1272,
+ "cachedInputTokens": 206917
+ },
+ "durationMs": 39133,
"prompt": "Our dispatch dashboard shows incoming orders as they happen. The courier\nlocation feed on the same page updates live without problems, but new orders\nonly show up after a page refresh.\n\nThe dashboard uses supabase-js to subscribe to INSERT events on the `orders`\ntable through postgres_changes, the same way it subscribes to courier\nlocations. The channel's status callback logs SUBSCRIBED and there are no\nerrors in the browser console.\n\nFigure out why no order events ever arrive and fix it.",
"promptSourcePath": "evals/investigate-realtime-001-subscribed-no-events/PROMPT.md",
"attempts": 1,
@@ -15521,17 +19276,17 @@
{
"name": "identified image-transform and the recurring 503 pattern",
"passed": true,
- "judgeNotes": "The assistant correctly identified `image-transform` as the affected function and described eight intermittent HTTP 503 gateway responses spanning 2026-04-28 07:00–12:00 UTC, including the recurring pattern and isolation from runtime logs."
+ "judgeNotes": "Identified `image-transform` as affected and described eight recurring HTTP 503 gateway failures across 07:00–12:00Z on 2026-04-28, with appropriate distinction from unrelated issues."
},
{
"name": "attributed recurring 503s to gateway/platform layer, not function code",
"passed": true,
- "judgeNotes": "The assistant explicitly attributes the recurring image-transform 503s to the gateway/platform layer rather than function code. It grounds this in valid observations: 503s appear in API gateway logs but not Edge Function runtime logs, nearby successful requests occurred on the same deployment/version, and it distinguishes the separate avatar-upload 500 as a function-level issue to treat separately."
+ "judgeNotes": "Attributes the recurring 503s to the Edge Function gateway/platform layer, grounded in gateway/API records with no corresponding runtime executions, unchanged deployment/version with nearby successes, and distinguishes them from avatar-upload's runtime 500."
},
{
"name": "recommended a concrete next step",
"passed": true,
- "judgeNotes": "The assistant recommended concrete actionable next steps, including opening a Supabase support case with 503 timestamps, function name, and deployment ID, requesting gateway-level investigation, and capturing request/correlation IDs."
+ "judgeNotes": "Assistant recommended concrete next steps including opening a Supabase support case with project ref, timestamps, function name, and gateway event IDs; checking scheduled jobs/traffic spikes; classifying 503s via metadata; and investigating related logs."
}
],
"skills": {
@@ -15539,8 +19294,43 @@
"loaded": []
},
"docs": {
- "calls": []
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "query { searchDocs(query: \"Edge Functions 503 service unavailable request not reaching function logs causes\", limit: 5) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/edge-function-503-response",
+ "title": "Edge Function 503 error response"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/status-codes",
+ "title": "Status codes"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/edge-function-504-error-response",
+ "title": "Edge Function 504 error response"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/edge-function-404-error-response",
+ "title": "Edge Function 404 error response"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
+ "title": "Self-Hosted Functions"
+ }
+ ],
+ "resultChars": 36301
+ }
+ ]
},
+ "usage": {
+ "inputTokens": 317905,
+ "outputTokens": 2038,
+ "cachedInputTokens": 291499
+ },
+ "durationMs": 69581,
"prompt": "Users have been reporting that image uploads are intermittently failing with server errors throughout the morning of `2026-04-28`.\n\nCan you investigate the project logs and tell me what is going on and what we\nshould do next?",
"promptSourcePath": "evals/investigate-reliability-003-edge-function-5xx-correlation/PROMPT.md",
"attempts": 1,
@@ -15597,7 +19387,7 @@
{
"name": "diagnosed RLS and added owner-scoped policies",
"passed": true,
- "judgeNotes": "The assistant correctly diagnosed RLS enabled with no policies causing deny-all Data API behavior, kept RLS enabled, and created authenticated SELECT and INSERT policies scoped to user_id = auth.uid(), with INSERT enforced via WITH CHECK. It also avoided permissive/public policies and verified owner isolation."
+ "judgeNotes": "Diagnosed RLS deny-all due to no policies, kept RLS enabled, and added authenticated owner-scoped SELECT and INSERT policies using auth.uid() = user_id / WITH CHECK."
}
],
"skills": {
@@ -15605,29 +19395,14 @@
"loaded": []
},
"docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"Row Level Security auth.uid select insert policy authenticated users own rows\", limit: 3) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
- "title": "Row Level Security"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/features",
- "title": "Features"
- },
- {
- "url": "https://supabase.com/docs/guides/database/postgres/column-level-security",
- "title": "Column Level Security"
- }
- ],
- "resultChars": 46550
- }
- ]
+ "calls": []
},
+ "usage": {
+ "inputTokens": 225128,
+ "outputTokens": 1969,
+ "cachedInputTokens": 205564
+ },
+ "durationMs": 64168,
"prompt": "Our app lets signed-in users save bookmarks and view them on their dashboard. Bookmarks are stored in the `bookmarks` table and are private — a user must only ever see their own. \nUsers also need to be able to save new bookmarks from the app.\n\nI can see the rows when I query the table directly, but the dashboard shows an empty list for every user.\n\nFind out why the Data API returns nothing and fix it.",
"promptSourcePath": "evals/resolve-dataapi-001-empty-results/PROMPT.md",
"attempts": 1,
@@ -15677,7 +19452,7 @@
{
"name": "the avatar migration and history reconciliation were done via the Supabase CLI",
"passed": true,
- "judgeNotes": "Avatar migration was applied by `supabase db push --db-url \"$DB_URL\" --yes`, with output showing `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` History was reconciled by adding the missing local migration file `supabase/migrations/20240115000000_add_profile_bio.sql` and then running the Supabase CLI push workflow. No disallowed workaround or direct remote SQL mutation was used."
+ "judgeNotes": "#13 ran `supabase db push --db-url \"$DB_URL\" --yes`, after which `public.profiles` had `avatar_url`. History was reconciled by #11 adding the missing local migration `supabase/migrations/20240115000000_add_profile_bio.sql`, aligning local/remote migration history before the push. No disallowed workaround or direct SQL mutation of `avatar_url`/migration history was shown."
}
],
"skills": {
@@ -15688,20 +19463,20 @@
"calls": [
{
"source": "search_docs",
- "query": "query { searchDocs(query: \"Supabase CLI db push migration history repair duplicate table hosted project migration list\", limit: 5) { nodes { title href content } } }",
+ "query": "query { searchDocs(query: \"Supabase CLI migration deploy db push remote migration history repair\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/reference/cli/supabase-migration-repair",
- "title": "Repair the migration history table"
+ "url": "https://supabase.com/docs/guides/deployment/database-migrations",
+ "title": "Database Migrations"
},
{
- "url": "https://supabase.com/docs/guides/platform/migrating-within-supabase/backup-restore",
- "title": "Backup and Restore using the CLI"
+ "url": "https://supabase.com/docs/guides/local-development/cli-workflows",
+ "title": "Local development workflow"
},
{
- "url": "https://supabase.com/docs/guides/deployment/database-migrations",
- "title": "Database Migrations"
+ "url": "https://supabase.com/docs/reference/cli/supabase-migration-repair",
+ "title": "Repair the migration history table"
},
{
"url": "https://supabase.com/docs/guides/local-development/database-migrations",
@@ -15712,10 +19487,16 @@
"title": "Push new migrations to the remote database"
}
],
- "resultChars": 74715
+ "resultChars": 61657
}
]
},
+ "usage": {
+ "inputTokens": 497132,
+ "outputTokens": 3626,
+ "cachedInputTokens": 468597
+ },
+ "durationMs": 128360,
"prompt": "I'm trying to ship a migration to our hosted project and it's not working. Can you figure out what's wrong and get it deployed?",
"promptSourcePath": "evals/resolve-database-001-migration-history-mismatch/PROMPT.md",
"attempts": 1,
@@ -15770,29 +19551,14 @@
"loaded": []
},
"docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"Postgres multicolumn index WHERE equality ORDER BY DESC LIMIT query performance\", limit: 3) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/database/orioledb",
- "title": "OrioleDB Overview"
- },
- {
- "url": "https://supabase.com/docs/guides/database/query-optimization",
- "title": "Query Optimization"
- },
- {
- "url": "https://supabase.com/docs/guides/database/inspect",
- "title": "Debugging and monitoring"
- }
- ],
- "resultChars": 26398
- }
- ]
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 364516,
+ "outputTokens": 1933,
+ "cachedInputTokens": 338769
},
+ "durationMs": 65277,
"prompt": "My database CPU keeps spiking and the app gets slow when loading recent events for a user. Can you figure out what query is causing it and make the database change needed to fix it?\n\nEnd your turn with a short summary of what you changed and why.",
"promptSourcePath": "evals/resolve-performance-001-slow-query-cpu-spike/PROMPT.md",
"attempts": 1,
@@ -15865,6 +19631,12 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 296318,
+ "outputTokens": 2935,
+ "cachedInputTokens": 274355
+ },
+ "durationMs": 89708,
"prompt": "A customer reported that notes showed up in the wrong workspace.\n\nCan you investigate what is going on and fix it?",
"promptSourcePath": "evals/resolve-security-002-rls-cross-tenant-leak/PROMPT.md",
"attempts": 1,
@@ -15903,7 +19675,7 @@
{
"name": "todos table exists with at least 2 seeded rows",
"passed": true,
- "notes": "found 2 rows"
+ "notes": "found 3 rows"
},
{
"name": "row level security is enabled on todos",
@@ -15921,7 +19693,7 @@
{
"name": "REST API returns the todos to authenticated requests",
"passed": true,
- "notes": "2 rows"
+ "notes": "3 rows"
}
],
"skills": {
@@ -15946,9 +19718,28 @@
}
],
"resultChars": 93411
+ },
+ {
+ "source": "web_fetch",
+ "query": "https://supabase.com/changelog/45329-breaking-change-tables-not-exposed-to-data-and-graphql-api-automatically",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/changelog/45329-breaking-change-tables-not-exposed-to-data-and-graphql-api-automatically"
+ }
+ ],
+ "resultChars": 12703
}
]
},
+ "usage": {
+ "inputTokens": 126470,
+ "outputTokens": 6835,
+ "cachedInputTokens": 1259008,
+ "reasoningTokens": 4484,
+ "costUsd": 0.9268974000000001
+ },
+ "durationMs": 632705,
"prompt": "We're kicking off a todos app and I want the Supabase side ready for the team\nto build on. Set it up the way we'd run it in development, with schema changes\ntracked as migrations so they can be reviewed and replayed.\n\nFor the first slice we just need a `todos` table. Todos aren't public: anyone\nsigned in can read all of them, but nothing should be writable through the API\nfor now. Add a couple of sample todos so there's something to look at.\n\nBefore you hand it back, make sure the running API actually behaves that way —\nsigned-in users get the todos, signed-out requests get nothing.",
"promptSourcePath": "evals/build-cli-001-bootstrap-app/PROMPT.md",
"attempts": 1,
@@ -15998,24 +19789,21 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
- "calls": [
- {
- "source": "web_fetch",
- "query": "https://supabase.com/changelog.md",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/changelog.md"
- }
- ],
- "resultChars": 93411
- }
- ]
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 24072,
+ "outputTokens": 1373,
+ "cachedInputTokens": 151552,
+ "reasoningTokens": 1004,
+ "costUsd": 0.15333660000000002
},
+ "durationMs": 151963,
"prompt": "Add a description text column to the `products` table in my local Supabase stack",
"promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md",
"attempts": 1,
@@ -16053,12 +19841,12 @@
{
"name": "cron command enqueues to the 'tasks' queue",
"passed": true,
- "notes": "queue depth 0 -> 1"
+ "notes": "queue depth 1 -> 2"
},
{
"name": "process-tasks function drains the queue",
"passed": true,
- "notes": "function removed the seeded message (id 37) from the queue"
+ "notes": "function removed the seeded message (id 39) from the queue"
}
],
"skills": {
@@ -16067,14 +19855,15 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"pg_cron schedule job send message to pgmq queue every minute\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"pg_cron schedule job every minute pgmq send queue\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
@@ -16085,50 +19874,34 @@
"url": "https://supabase.com/docs/guides/queues/pgmq",
"title": "PGMQ Extension"
},
- {
- "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
- "title": "Automatic embeddings"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/schedule-functions",
- "title": "Scheduling Edge Functions"
- },
{
"url": "https://supabase.com/docs/guides/cron",
"title": "Cron"
- }
- ],
- "resultChars": 68390
- },
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"Supabase Queues pgmq consume messages edge function read delete\", limit: 4) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions",
- "title": "Consuming Supabase Queue Messages with Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/queues",
- "title": "Supabase Queues"
},
{
- "url": "https://supabase.com/docs/guides/queues/api",
- "title": "API"
+ "url": "https://supabase.com/docs/guides/functions/schedule-functions",
+ "title": "Scheduling Edge Functions"
},
{
"url": "https://supabase.com/docs/guides/queues/quickstart",
"title": "Quickstart"
}
],
- "resultChars": 18714
+ "resultChars": 48142
}
]
},
+ "usage": {
+ "inputTokens": 86507,
+ "outputTokens": 5153,
+ "cachedInputTokens": 1042176,
+ "reasoningTokens": 5036,
+ "costUsd": 0.7250088
+ },
+ "durationMs": 495031,
"prompt": "I want to set up a recurring background workflow on my local Supabase stack.\n\nCan you set up a cron job called `enqueue-tasks` to run every minute and push a task into a queue called `tasks`? Then add a `process-tasks` edge function that reads messages off the `tasks` queue and removes them, so a scheduled worker can keep the backlog drained.",
"promptSourcePath": "evals/build-cli-003-pg-cron-queue-workflow/PROMPT.md",
- "attempts": 1,
+ "attempts": 2,
"sourcePath": "opencode-kimi-k3/build-cli-003-pg-cron-queue-workflow.json"
},
{
@@ -16178,12 +19951,33 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
- "calls": []
+ "calls": [
+ {
+ "source": "web_fetch",
+ "query": "https://supabase.com/docs/guides/resources/migrating-to-supabase/postgres.md",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/resources/migrating-to-supabase/postgres.md"
+ }
+ ],
+ "resultChars": 19900
+ }
+ ]
},
+ "usage": {
+ "inputTokens": 95034,
+ "outputTokens": 3917,
+ "cachedInputTokens": 604928,
+ "reasoningTokens": 5397,
+ "costUsd": 0.6062903999999999
+ },
+ "durationMs": 584307,
"prompt": "I have an existing Postgres database I want to migrate to Supabase. There's a binary dump at `source.dump` in the current directory.\n\nCan you set up a local Supabase project and restore the dump into it?",
"promptSourcePath": "evals/build-database-001-migrate-postgres-to-supabase/PROMPT.md",
"attempts": 1,
@@ -16250,36 +20044,53 @@
},
"docs": {
"calls": [
+ {
+ "source": "web_fetch",
+ "query": "https://supabase.com/changelog.md",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/changelog.md"
+ }
+ ],
+ "resultChars": 93411
+ },
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"edge function get user from Authorization header JWT auth.getUser service role bypass RLS\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"edge function get user from Authorization header auth.getUser\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z",
- "title": "Why is my service role key client getting RLS errors or not returning data?"
+ "url": "https://supabase.com/docs/reference/javascript/auth-getuser"
},
{
"url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
"title": "Integrating With Supabase Auth"
},
{
- "url": "https://supabase.com/docs/guides/storage/security/access-control",
- "title": "Storage Access Control"
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs",
+ "title": "Build a User Management App with Next.js"
},
{
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
+ "url": "https://supabase.com/docs/reference/dart/auth-admin-getuserbyid"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/why-is-my-select-returning-an-empty-data-array-and-i-have-data-in-the-table-xvOPgx",
- "title": "Why is my select returning an empty data array and I have data in the table?"
+ "url": "https://supabase.com/docs/guides/functions/auth",
+ "title": "Securing Edge Functions"
}
],
- "resultChars": 21680
+ "resultChars": 55466
}
]
},
+ "usage": {
+ "inputTokens": 96598,
+ "outputTokens": 4806,
+ "cachedInputTokens": 709120,
+ "reasoningTokens": 7397,
+ "costUsd": 0.6855749999999999
+ },
+ "durationMs": 459949,
"prompt": "I built an Edge Function called `private-notes` for showing a user's saved\nprivate notes.\n\nCan you check whether there's any way one user could see another user's notes?\n\nPlease fix and deploy it if needed.",
"promptSourcePath": "evals/build-functions-004-service-role-bypass/PROMPT.md",
"attempts": 1,
@@ -16318,37 +20129,37 @@
{
"name": "rejects request with no credentials",
"passed": true,
- "notes": "status 401: {\"message\":\"Invalid credentials\"}"
+ "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
},
{
"name": "user with JWT reads only their own rows",
"passed": true,
- "notes": "status 200: [{\"user_id\":\"37806d0f-f274-4021-aea2-77e34259085f\",\"metric\":\"steps_a_ms6x7jy9\",\"value\":111}]"
+ "notes": "status 200: [{\"user_id\":\"1da31b8b-c945-4940-824b-8284d0588b47\",\"metric\":\"steps_a_ms7qmi4a\",\"value\":111}]"
},
{
"name": "user cannot read another user's rows by passing user_id",
"passed": true,
- "notes": "status 200: [{\"user_id\":\"37806d0f-f274-4021-aea2-77e34259085f\",\"metric\":\"steps_a_ms6x7jy9\",\"value\":111}]"
+ "notes": "status 200: [{\"user_id\":\"1da31b8b-c945-4940-824b-8284d0588b47\",\"metric\":\"steps_a_ms7qmi4a\",\"value\":111}]"
},
{
"name": "service key bypasses RLS to read the target user's rows",
"passed": true,
- "notes": "status 200: [{\"user_id\":\"ff362a6e-3573-4069-b30d-24e34c6a5e04\",\"metric\":\"steps_b_ms6x7jy9\",\"value\":222}]"
+ "notes": "status 200: [{\"user_id\":\"46f53d5c-4837-4a2b-8900-fd5f724ce718\",\"metric\":\"steps_b_ms7qmi4a\",\"value\":222}]"
},
{
"name": "non-service key is not granted service access",
"passed": true,
- "notes": "status 401: {\"message\":\"Invalid credentials\"}"
+ "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
},
{
"name": "rejects an unverified (forged) user token",
"passed": true,
- "notes": "status 401: {\"message\":\"Invalid credentials\"}"
+ "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
},
{
"name": "a user token in the apikey slot is not treated as the service key",
"passed": true,
- "notes": "status 401: {\"message\":\"Invalid credentials\"}"
+ "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
},
{
"name": "implementation uses @supabase/server",
@@ -16362,45 +20173,61 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
+ {
+ "source": "web_fetch",
+ "query": "https://supabase.com/changelog.md",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/changelog.md"
+ }
+ ],
+ "resultChars": 93411
+ },
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"edge functions environment variables SUPABASE_SERVICE_ROLE_KEY secret key sb_secret verify_jwt\", limit: 6) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"edge function environment variables SUPABASE_URL SUPABASE_ANON_KEY SUPABASE_SERVICE_ROLE_KEY SUPABASE_SECRET_KEY publishable\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
+ "url": "https://supabase.com/docs/guides/functions/secrets",
+ "title": "Environment Variables"
},
{
"url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
"title": "Self-Hosted Functions"
},
{
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
- "title": "Integrating With Supabase Auth"
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
},
{
"url": "https://supabase.com/docs/guides/functions/auth",
"title": "Securing Edge Functions"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/inspecting-edge-function-environment-variables-wg5qOQ",
- "title": "Inspecting edge function environment variables"
+ "url": "https://supabase.com/docs/guides/auth/quickstarts/with-expo-react-native-social-auth",
+ "title": "Build a Social Auth App with Expo React Native"
}
],
- "resultChars": 42813
+ "resultChars": 94601
}
]
},
+ "usage": {
+ "inputTokens": 131469,
+ "outputTokens": 4083,
+ "cachedInputTokens": 801792,
+ "reasoningTokens": 13999,
+ "costUsd": 0.9061746000000002
+ },
+ "durationMs": 732621,
"prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nOur product stores per-user metrics in the existing `user_stats` table.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.",
"promptSourcePath": "evals/build-functions-005-dual-auth-user-secret/PROMPT.md",
"attempts": 1,
@@ -16443,7 +20270,7 @@
{
"name": "user A lists only own files",
"passed": true,
- "notes": "saw: 019fb0ea-b2de-76fc-8fc8-c72ce1837e46/receipt-alpha.pdf, 019fb0ea-b2de-76fc-8fc8-c72ce1837e46/receipt-beta.pdf"
+ "notes": "saw: 019fb3de-d388-7259-9985-55471f65f9d7/receipt-alpha.pdf, 019fb3de-d388-7259-9985-55471f65f9d7/receipt-beta.pdf"
},
{
"name": "user B cannot read user A files",
@@ -16464,7 +20291,7 @@
{
"name": "configured private per-user storage access",
"passed": true,
- "judgeNotes": "Meets all criteria: private user-files bucket, RLS left enabled, authenticated owner-scoped SELECT and INSERT policies using foldername/auth.uid with WITH CHECK, and supabase-js createSignedUrl with expiry. Does not use public bucket/getPublicUrl/service role client-side."
+ "judgeNotes": "Meets all required criteria: private user-files bucket, authenticated owner-scoped SELECT and INSERT policies with WITH CHECK while keeping RLS, and supabase-js createSignedUrl with expiry for temporary sharing. No disqualifying public bucket, permissive policies, anon/public scope, getPublicUrl, or client service role usage."
}
],
"skills": {
@@ -16473,7 +20300,8 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
@@ -16491,145 +20319,42 @@
},
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"storage access control bucket RLS policies owner folder\") { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"storage access control RLS policies private bucket user folder auth.uid\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
- {
- "url": "https://supabase.com/docs/guides/storage/security/access-control",
- "title": "Storage Access Control"
- },
{
"url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
"title": "Storage Buckets"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs",
- "title": "Build a User Management App with Next.js"
- },
- {
- "url": "https://supabase.com/docs/guides/security/product-security",
- "title": "Secure configuration of Supabase products"
- },
- {
- "url": "https://supabase.com/docs/guides/platform/migrating-within-supabase/backup-restore",
- "title": "Backup and Restore using the CLI"
+ "url": "https://supabase.com/docs/guides/storage/security/access-control",
+ "title": "Storage Access Control"
},
{
"url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
"title": "Configure S3 Storage"
},
{
- "url": "https://supabase.com/docs/guides/auth/third-party/clerk",
- "title": "Clerk"
- },
- {
- "url": "https://supabase.com/docs/guides/resources/glossary",
- "title": "Glossary"
- },
- {
- "url": "https://supabase.com/docs/guides/storage/security/ownership",
- "title": "Ownership"
- },
- {
- "url": "https://supabase.com/docs/guides/storage/schema/design",
- "title": "The Storage Schema"
- },
- {
- "url": "https://supabase.com/docs/guides/storage/schema/helper-functions",
- "title": "Storage Helper Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/storage/schema/custom-roles",
- "title": "Custom Roles"
- },
- {
- "url": "https://supabase.com/docs/guides/local-development/database-migrations",
- "title": "Database migrations"
+ "url": "https://supabase.com/docs/guides/security/product-security",
+ "title": "Secure configuration of Supabase products"
},
{
"url": "https://supabase.com/docs/guides/storage/debugging/error-codes",
"title": "Error Codes"
- },
- {
- "url": "https://supabase.com/docs/guides/storage/quickstart",
- "title": "Storage Quickstart"
- },
- {
- "url": "https://supabase.com/docs/guides/troubleshooting/supabase-storage-inefficient-folder-operations-and-hierarchical-rls-challenges-b05a4d",
- "title": "Supabase Storage: Inefficient folder operations and hierarchical RLS challenges"
- },
- {
- "url": "https://supabase.com/docs/guides/database/postgres/column-level-security",
- "title": "Column Level Security"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security",
- "title": "Token Security and Row Level Security"
- },
- {
- "url": "https://supabase.com/docs/guides/storage/production/scaling",
- "title": "Storage Optimizations"
- },
- {
- "url": "https://supabase.com/docs/guides/api/securing-your-api",
- "title": "Securing your API"
- },
- {
- "url": "https://supabase.com/docs/guides/realtime/getting_started",
- "title": "Getting Started with Realtime"
- },
- {
- "url": "https://supabase.com/docs/guides/storage/cdn/fundamentals",
- "title": "Storage CDN"
- },
- {
- "url": "https://supabase.com/docs/guides/troubleshooting/why-cant-i-uploadlistetc-my-public-bucket-Z6CmGt",
- "title": "Why can't I upload/list/etc my public bucket?"
- },
- {
- "url": "https://supabase.com/docs/guides/storage/management/delete-objects",
- "title": "Delete Objects"
- },
- {
- "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas",
- "title": "Declarative database schemas"
- },
- {
- "url": "https://supabase.com/docs/guides/troubleshooting/storage-error-403-forbidden-new-row-violates-row-level-security-policy-on-upload-a94384",
- "title": "Storage error: 403 Forbidden: 'new row violates row-level security policy' on upload"
- },
- {
- "url": "https://supabase.com/docs/guides/storage/s3/authentication",
- "title": "S3 Authentication"
- },
- {
- "url": "https://supabase.com/docs/guides/ai-tools/mcp",
- "title": "Supabase MCP Server"
- },
- {
- "url": "https://supabase.com/docs/guides/realtime/authorization",
- "title": "Realtime Authorization"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/features",
- "title": "Features"
- }
- ],
- "resultChars": 284508
- },
- {
- "source": "web_fetch",
- "query": "https://supabase.com/docs/guides/storage/security/access-control.md",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/storage/security/access-control.md"
}
],
- "resultChars": 4169
+ "resultChars": 33308
}
]
},
+ "usage": {
+ "inputTokens": 51630,
+ "outputTokens": 1874,
+ "cachedInputTokens": 184064,
+ "reasoningTokens": 1915,
+ "costUsd": 0.2669442
+ },
+ "durationMs": 488355,
"prompt": "Our app lets signed-in users keep personal files like receipts and bank\nstatements. These files are private — a user must only ever be able to upload\nand download their own. The app uploads each file under a path that starts\nwith the owner's user id, e.g. `/receipt-march.pdf`.\n\nSet up a `user-files` bucket on our project and lock it down that way.\n\nUsers also sometimes share one of their files with someone else through a\ntemporary link that expires. Include the supabase-js code the app should use\nfor that.",
"promptSourcePath": "evals/build-storage-001-private-bucket-access/PROMPT.md",
"attempts": 1,
@@ -16659,17 +20384,17 @@
{
"name": "pgTAP test file(s) written under supabase/tests/",
"passed": true,
- "notes": "1 file(s): supabase/tests/rls_tenant_isolation_test.sql"
+ "notes": "1 file(s): supabase/tests/tenant_isolation_test.sql"
},
{
"name": "pgTAP isolation tests ran and pass",
"passed": true,
- "notes": "9 passed, 6 failed"
+ "notes": "12 passed, 8 failed"
},
{
"name": "agent correctly identifies the posts isolation bug from test results",
"passed": true,
- "judgeNotes": "The agent correctly identifies `posts` as having the broken tenant isolation policy, specifically that authenticated members can read posts from organizations they are not members of, and grounds this in pgTAP failures (#6, #12). It treats the test results as authoritative and distinguishes `notes` as correctly denying cross-org reads, while also noting other issues."
+ "judgeNotes": "The agent correctly identifies `posts` as having a broken tenant isolation policy, specifically that authenticated members of any org can read other organizations' posts, and grounds this in pgTAP failures (tests 7–8). It does not blame `notes` and treats the test results as authoritative."
}
],
"skills": {
@@ -16678,12 +20403,21 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 73656,
+ "outputTokens": 5206,
+ "cachedInputTokens": 354816,
+ "reasoningTokens": 13285,
+ "costUsd": 0.6047778
+ },
+ "durationMs": 500539,
"prompt": "Can you audit the tenant isolation on our tables? Write some database tests covering both the happy path and the negative case, run them, and share the results.",
"promptSourcePath": "evals/build-tests-001-rls-tenant-isolation/PROMPT.md",
"attempts": 1,
@@ -16749,55 +20483,64 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
- {
- "source": "web_fetch",
- "query": "https://supabase.com/changelog.md",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/changelog.md"
- }
- ],
- "resultChars": 93411
- },
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"semantic search pgvector match documents function embeddings\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"semantic search pgvector match_documents function gte-small 384 dimensions\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
"url": "https://supabase.com/docs/guides/ai/semantic-search",
"title": "Semantic search"
},
- {
- "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
- "title": "Automatic embeddings"
- },
{
"url": "https://supabase.com/docs/guides/ai/hybrid-search",
"title": "Hybrid search"
},
+ {
+ "url": "https://supabase.com/docs/guides/database/extensions/pgvector",
+ "title": "pgvector: Embeddings and vector similarity"
+ },
{
"url": "https://supabase.com/docs/guides/ai/vector-columns",
"title": "Vector columns"
},
{
- "url": "https://supabase.com/docs/guides/functions/examples/semantic-search",
- "title": "Semantic Search"
+ "url": "https://supabase.com/docs/guides/storage/vector/querying-vectors",
+ "title": "Querying Vectors"
+ }
+ ],
+ "resultChars": 61362
+ },
+ {
+ "source": "web_fetch",
+ "query": "https://supabase.com/docs/guides/ai/vector-columns.md",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/ai/vector-columns.md"
}
],
- "resultChars": 71630
+ "resultChars": 7335
}
]
},
+ "usage": {
+ "inputTokens": 109107,
+ "outputTokens": 8399,
+ "cachedInputTokens": 1260800,
+ "reasoningTokens": 14978,
+ "costUsd": 1.0562160000000003
+ },
+ "durationMs": 732029,
"prompt": "We're adding semantic search to our internal knowledge base app. I already wrote the edge functions, but search doesn't work yet. Can you set up whatever the database needs to make search work end to end?\n\nSome documents are confidential, so users should only have access to documents they own.",
"promptSourcePath": "evals/build-vectors-001-rag-with-permissions/PROMPT.md",
- "attempts": 2,
+ "attempts": 1,
"sourcePath": "opencode-kimi-k3/build-vectors-001-rag-with-permissions.json"
},
{
@@ -16826,12 +20569,12 @@
{
"name": "configured the Supabase Metrics API scrape correctly",
"passed": true,
- "judgeNotes": "Meets all requirements: HTTPS Supabase Metrics API scrape for the project target, correct metrics path, Basic Auth with password_file, app scrape preserved, and docker-compose mounts the secrets directory containing the password file."
+ "judgeNotes": "Adds a valid HTTPS Supabase Metrics API scrape for evalshostedprojectxy.supabase.co with /customer/v1/privileged/metrics, Basic Auth using password_file, preserves the app scrape, and docker-compose mounts the secret directory matching the password_file path."
},
{
"name": "documented live deployment and verification steps",
"passed": true,
- "judgeNotes": "README includes concrete steps to obtain a Secret API key, place it in the mounted secret file, reload/restart the Compose stack, and verify via Prometheus targets plus a Grafana/PromQL query."
+ "judgeNotes": "README includes Secret API key provisioning, matching secret file placement, Compose start/restart/reload steps, and concrete verification via Prometheus targets/API query plus Grafana dashboard guidance. Endpoint/auth and secret handling are consistent."
}
],
"skills": {
@@ -16847,54 +20590,164 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"metrics endpoint prometheus scrape project metrics\") { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"metrics endpoint Prometheus scrape Supabase project metrics\") { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-self-hosted",
- "title": "Metrics API with Prometheus & Grafana (self-hosted)"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics",
+ "title": "Metrics API"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted",
+ "title": "Metrics API with Prometheus & Grafana (self-hosted)"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic",
+ "title": "Vendor-agnostic Metrics API setup"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud",
+ "title": "Metrics API with Grafana Cloud"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/connection-management",
+ "title": "Connection management"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/how-to-view-database-metrics-uqf2z_",
+ "title": "How to View Database Metrics"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/read-replicas",
+ "title": "Read Replicas"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/realtime/benchmarks",
+ "title": "Benchmarks"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics",
- "title": "Metrics API"
+ "url": "https://supabase.com/docs/guides/troubleshooting/grafana-not-displaying-data-sXJrMj",
+ "title": "Grafana not displaying data"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/vendor-agnostic",
- "title": "Vendor-agnostic Metrics API setup"
+ "url": "https://supabase.com/docs/guides/database/postgres/timeouts",
+ "title": "Timeouts"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-cloud",
- "title": "Metrics API with Grafana Cloud"
+ "url": "https://supabase.com/docs/guides/local-development/cli/testing-and-linting",
+ "title": "Testing and linting"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/how-to-view-database-metrics-uqf2z_",
- "title": "How to View Database Metrics"
+ "url": "https://supabase.com/docs/guides/integrations/supabase-for-platforms",
+ "title": "Supabase for Platforms"
},
{
- "url": "https://supabase.com/docs/guides/platform/read-replicas",
- "title": "Read Replicas"
+ "url": "https://supabase.com/docs/guides/deployment/branching/troubleshooting",
+ "title": "Troubleshooting"
},
{
- "url": "https://supabase.com/docs/guides/database/connection-management",
- "title": "Connection management"
+ "url": "https://supabase.com/docs/guides/troubleshooting/why-do-i-see-auth--api-requests-in-the-dashboard-my-app-has-no-users-CyadiO",
+ "title": "Why do I see Auth & API requests in the dashboard? My app has no users"
},
{
- "url": "https://supabase.com/docs/guides/realtime/benchmarks",
- "title": "Benchmarks"
+ "url": "https://supabase.com/docs/guides/platform/manage-your-usage/logs-ingest",
+ "title": "Manage Logs Ingest usage"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/grafana-not-displaying-data-sXJrMj",
- "title": "Grafana not displaying data"
+ "url": "https://supabase.com/docs/guides/platform",
+ "title": "Supabase Platform"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/storage/analytics/query-with-postgres",
+ "title": "Query with Postgres"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/functions/architecture",
+ "title": "Edge Functions Architecture"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/reports",
+ "url": "https://supabase.com/docs/guides/troubleshooting/monitor-supavisor-postgres-connections",
+ "title": "How to monitor Postgres and Supavisor connections"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/manage-your-usage/egress",
+ "title": "Manage Egress usage"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/local-development/cli/getting-started",
+ "title": "Supabase CLI"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/api/rest/generating-types",
+ "title": "Generating TypeScript Types"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports",
"title": "Reports"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging",
+ "title": "Monitoring and Debugging"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/supabase-grafana-memory-charts",
+ "title": "Interpreting Supabase Grafana Memory Charts"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/platform/performance",
+ "title": "Performance Tuning"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/interpreting-supabase-grafana-cpu-charts-9JSlkC",
+ "title": "Interpreting Supabase Grafana CPU charts"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting",
+ "title": "Self-Hosting"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/api/quickstart",
+ "title": "Build an API route in less than 2 minutes."
+ },
+ {
+ "url": "https://supabase.com/docs/guides/deployment/maturity-model",
+ "title": "Maturity Model"
+ }
+ ],
+ "resultChars": 201209
+ },
+ {
+ "source": "web_fetch",
+ "query": "https://supabase.com/docs/guides/telemetry/metrics/grafana-self-hosted.md",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-self-hosted.md"
+ }
+ ],
+ "resultChars": 3753
+ },
+ {
+ "source": "web_fetch",
+ "query": "https://supabase.com/docs/guides/platform/metrics.md",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/platform/metrics.md"
}
],
- "resultChars": 81235
+ "resultChars": 4838
}
]
},
+ "usage": {
+ "inputTokens": 101393,
+ "outputTokens": 7591,
+ "cachedInputTokens": 894720,
+ "reasoningTokens": 12005,
+ "costUsd": 0.866535
+ },
+ "durationMs": 563873,
"prompt": "Can you wire my Supabase project metrics into our existing observability stack and document\nin the observability README what we need to do to make the config live?",
"promptSourcePath": "evals/deploy-database-001-prometheus-metrics/PROMPT.md",
"attempts": 1,
@@ -16951,27 +20804,26 @@
"docs": {
"calls": [
{
- "source": "search_docs",
- "query": "{ searchDocs(query: \"edge function secrets environment variables supabase secrets set env file\", limit: 3) { nodes { title href content } } }",
+ "source": "web_fetch",
+ "query": "https://supabase.com/changelog.md",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/troubleshooting/inspecting-edge-function-environment-variables-wg5qOQ",
- "title": "Inspecting edge function environment variables"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-transcribe-speech",
- "title": "Transcription Telegram Bot"
+ "url": "https://supabase.com/changelog.md"
}
],
- "resultChars": 18708
+ "resultChars": 93411
}
]
},
+ "usage": {
+ "inputTokens": 127976,
+ "outputTokens": 8541,
+ "cachedInputTokens": 1712896,
+ "reasoningTokens": 12794,
+ "costUsd": 1.2178217999999998
+ },
+ "durationMs": 730156,
"prompt": "Our weather widget currently calls WeatherAPI straight from the browser, which\nleaks our API key. I want to move that behind a Supabase Edge Function called\n`weather` that holds the key server-side and proxies the request.\n\nThe function should read the key from an environment variable named\n`WEATHER_API_KEY`. Our key already lives in a local `.env` file at the project\nroot.\n\nDeploy the function to our project so it's live, and make sure the deployed\nfunction can actually read the key at runtime.",
"promptSourcePath": "evals/deploy-functions-001-edge-function-secrets/PROMPT.md",
"attempts": 1,
@@ -17026,31 +20878,16 @@
]
},
"docs": {
- "calls": [
- {
- "source": "web_fetch",
- "query": "https://supabase.com/changelog.md",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/changelog.md"
- }
- ],
- "resultChars": 93411
- },
- {
- "source": "web_fetch",
- "query": "https://supabase.com/docs/guides/self-hosting/docker.md",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/self-hosting/docker.md"
- }
- ],
- "resultChars": 30212
- }
- ]
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 78364,
+ "outputTokens": 3611,
+ "cachedInputTokens": 409088,
+ "reasoningTokens": 4043,
+ "costUsd": 0.4726283999999999
},
+ "durationMs": 283317,
"prompt": "I'm moving off the hosted Supabase and running the whole thing myself on a VPS I\njust spun up. Can you get a Docker setup ready for me to copy onto the box?\n\nI don't need it running here, I'll do the actual bring-up once I'm on the\nserver. I just want everything in place and the secrets set up. Put it in a `supabase-docker/`\nfolder at the repo root so I can scp the whole thing across in one go.",
"promptSourcePath": "evals/deploy-self-hosting-001-docker-compose/PROMPT.md",
"attempts": 1,
@@ -17105,7 +20942,7 @@
{
"name": "diagnosed and explained session revocation",
"passed": true,
- "judgeNotes": "Meets rubric: identifies soft-delete root cause, implements real auth/session/user deletion with refresh token revocation, correctly explains stateless JWT residual window consistent with remaining RLS behavior and mitigation, and accurately distinguishes publishable frontend/RLS-enforced keys from secret server-only/RLS-bypassing keys."
+ "judgeNotes": "Diagnoses soft-delete only, implements auth user/session/refresh token revocation via auth.users/auth.sessions deletion, gives a consistent JWT residual-window caveat and mitigation, and correctly distinguishes publishable vs secret keys including RLS bypass for secret/server-only."
}
],
"skills": {
@@ -17121,34 +20958,53 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"publishable secret API keys anon service_role migration RLS\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"publishable secret API keys migration anon service_role\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs",
- "title": "Build a User Management App with RedwoodJS"
- },
{
"url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
"title": "Migrating to publishable and secret API keys"
},
{
- "url": "https://supabase.com/docs/guides/auth/quickstarts/with-expo-react-native-social-auth",
- "title": "Build a Social Auth App with Expo React Native"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys",
+ "title": "JWT Signing Keys"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-sveltekit",
- "title": "Build a User Management App with SvelteKit"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
+ "title": "New API Keys and Asymmetric Authentication"
},
{
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
+ "url": "https://supabase.com/docs/guides/integrations/supabase-for-platforms",
+ "title": "Supabase for Platforms"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs",
+ "title": "Build a User Management App with RedwoodJS"
+ }
+ ],
+ "resultChars": 107177
+ },
+ {
+ "source": "web_fetch",
+ "query": "https://supabase.com/docs/guides/api/api-keys.md",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/api/api-keys.md"
}
],
- "resultChars": 169611
+ "resultChars": 13494
}
]
},
+ "usage": {
+ "inputTokens": 69323,
+ "outputTokens": 4570,
+ "cachedInputTokens": 327424,
+ "reasoningTokens": 6770,
+ "costUsd": 0.4762962
+ },
+ "durationMs": 337973,
"prompt": "Last week support removed a user through our app's delete-account flow — the\napp calls the `delete_account` function over RPC as the signed-in user. This\nmorning that same person was back: still signed in, reading and saving their\ndata like nothing happened.\n\nFigure out why the account still works, fix the flow so a deleted account\nloses access, and tell me whether there is any window where they could still\nget in after the fix.\n\nOne more thing while you're at it: we're migrating off the legacy\nanon/service_role API keys to the new publishable and secret keys, and the\nteam isn't sure which one belongs in the frontend and what each means for\nRLS. Give us a quick rundown.",
"promptSourcePath": "evals/investigate-auth-001-deleted-user-access/PROMPT.md",
"attempts": 1,
@@ -17199,7 +21055,7 @@
{
"name": "diagnosed missing publication membership",
"passed": true,
- "judgeNotes": "Diagnosed the silent subscription as orders missing from supabase_realtime despite SUBSCRIBED status, applied exactly ALTER PUBLICATION supabase_realtime ADD TABLE public.orders, preserved courier_locations and did not weaken RLS/policies."
+ "judgeNotes": "The assistant correctly identified the root cause as public.orders missing from the supabase_realtime publication despite the channel reaching SUBSCRIBED, applied exactly ALTER PUBLICATION supabase_realtime ADD TABLE public.orders, and preserved courier_locations, RLS, and policies. No disallowed root-cause blame or weakening changes were made."
}
],
"skills": {
@@ -17214,6 +21070,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 26292,
+ "outputTokens": 1632,
+ "cachedInputTokens": 171008,
+ "reasoningTokens": 1421,
+ "costUsd": 0.17597340000000003
+ },
+ "durationMs": 135967,
"prompt": "Our dispatch dashboard shows incoming orders as they happen. The courier\nlocation feed on the same page updates live without problems, but new orders\nonly show up after a page refresh.\n\nThe dashboard uses supabase-js to subscribe to INSERT events on the `orders`\ntable through postgres_changes, the same way it subscribes to courier\nlocations. The channel's status callback logs SUBSCRIBED and there are no\nerrors in the browser console.\n\nFigure out why no order events ever arrive and fix it.",
"promptSourcePath": "evals/investigate-realtime-001-subscribed-no-events/PROMPT.md",
"attempts": 1,
@@ -17242,17 +21106,17 @@
{
"name": "identified image-transform and the recurring 503 pattern",
"passed": true,
- "judgeNotes": "Identified image-transform as the affected function and described the recurring HTTP 503 pattern across the morning of 2026-04-28, including most/all 8 gateway failures from 07:00Z to 12:00Z."
+ "judgeNotes": "Identified image-transform as the affected function and described the recurring HTTP 503 gateway pattern across the morning of 2026-04-28, including most/all failures from 07:00Z–12:00Z. Did not incorrectly center the old billing-webhook issue."
},
{
"name": "attributed recurring 503s to gateway/platform layer, not function code",
"passed": false,
- "judgeNotes": "The response notes that 503s have only gateway logs and no function execution logs, but it ultimately attributes the incident to the function's unpinned npm dependency/module-load behavior and recommends pinning/redeploying the function as the direct fix. That violates the rubric requirement to attribute the recurring 503s to the gateway/platform layer rather than function code/runtime."
+ "judgeNotes": "Although it attributes the observed 503s to the gateway surface and cites valid evidence, it ultimately posits an unpinned function dependency/cold-start boot failure as the root cause and recommends pinning/redeploying the function, which the rubric treats as a failure."
},
{
"name": "recommended a concrete next step",
"passed": true,
- "judgeNotes": "The assistant recommended concrete actionable next steps, including pinning a known-good dependency version and redeploying, checking package publish history, adding retries, and alerting on gateway-level 503s without executions."
+ "judgeNotes": "The assistant provided concrete actionable next steps, including pinning the dependency and redeploying, checking npm publish history for specific packages/timeframes, pinning all function dependencies, adding lockfiles, and setting up gateway-level 5xx alerting."
}
],
"skills": {
@@ -17267,6 +21131,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 37444,
+ "outputTokens": 1836,
+ "cachedInputTokens": 110592,
+ "reasoningTokens": 3786,
+ "costUsd": 0.22983960000000003
+ },
+ "durationMs": 190435,
"prompt": "Users have been reporting that image uploads are intermittently failing with server errors throughout the morning of `2026-04-28`.\n\nCan you investigate the project logs and tell me what is going on and what we\nshould do next?",
"promptSourcePath": "evals/investigate-reliability-003-edge-function-5xx-correlation/PROMPT.md",
"attempts": 2,
@@ -17322,7 +21194,7 @@
{
"name": "diagnosed RLS and added owner-scoped policies",
"passed": true,
- "judgeNotes": "Diagnosed RLS deny-all due to no policies, kept RLS enabled, and added authenticated SELECT and INSERT policies scoped to user_id = auth.uid() with WITH CHECK for inserts."
+ "judgeNotes": "The assistant correctly diagnosed RLS enabled with no policies as the cause of empty Data API results, kept RLS enabled, and created owner-scoped SELECT and INSERT policies for the authenticated role using auth.uid() with WITH CHECK for inserts."
}
],
"skills": {
@@ -17331,12 +21203,21 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 47737,
+ "outputTokens": 2670,
+ "cachedInputTokens": 216064,
+ "reasoningTokens": 3305,
+ "costUsd": 0.29765520000000006
+ },
+ "durationMs": 192701,
"prompt": "Our app lets signed-in users save bookmarks and view them on their dashboard. Bookmarks are stored in the `bookmarks` table and are private — a user must only ever see their own. \nUsers also need to be able to save new bookmarks from the app.\n\nI can see the rows when I query the table directly, but the dashboard shows an empty list for every user.\n\nFind out why the Data API returns nothing and fix it.",
"promptSourcePath": "evals/resolve-dataapi-001-empty-results/PROMPT.md",
"attempts": 1,
@@ -17385,7 +21266,7 @@
{
"name": "the avatar migration and history reconciliation were done via the Supabase CLI",
"passed": true,
- "judgeNotes": "Applied avatar_url with `supabase db push` (#19), which showed `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` Reconciled orphan bio migration by adding local file `20240115000000_add_profile_bio.sql` (#16), after which `supabase migration list` showed local/remote aligned (#17) and the push succeeded. No disallowed workaround or direct SQL mutation seen."
+ "judgeNotes": "Applied pending avatar_url via `supabase db push` (#22), which output `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` Reconciled orphan bio history by adding local migration file `supabase/migrations/20240115000000_add_profile_bio.sql` (#19), after which `supabase migration list` showed local and remote aligned for 20240115000000 (#21). No disallowed workaround or direct remote mutation observed; psql usage was read-only inspection."
}
],
"skills": {
@@ -17400,6 +21281,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 29610,
+ "outputTokens": 2557,
+ "cachedInputTokens": 262144,
+ "reasoningTokens": 3276,
+ "costUsd": 0.2549682
+ },
+ "durationMs": 184977,
"prompt": "I'm trying to ship a migration to our hosted project and it's not working. Can you figure out what's wrong and get it deployed?",
"promptSourcePath": "evals/resolve-database-001-migration-history-mismatch/PROMPT.md",
"attempts": 1,
@@ -17441,7 +21330,7 @@
{
"name": "query plan uses an index and avoids sequential scan",
"passed": true,
- "notes": "Limit (cost=55.55..55.61 rows=25 width=88)\n -> Sort (cost=55.55..55.61 rows=25 width=88)\n Sort Key: created_at DESC\n -> Bitmap Heap Scan on events (cost=4.48..54.97 rows=25 width=88)\n Recheck Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)\n -> Bitmap Index Scan on idx_events_user_created_at (cost=0.00..4.47 rows=25 width=0)\n Index Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)"
+ "notes": "Limit (cost=55.55..55.61 rows=25 width=88)\n -> Sort (cost=55.55..55.61 rows=25 width=88)\n Sort Key: created_at DESC\n -> Bitmap Heap Scan on events (cost=4.48..54.97 rows=25 width=88)\n Recheck Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)\n -> Bitmap Index Scan on events_user_id_created_at_idx (cost=0.00..4.47 rows=25 width=0)\n Index Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)"
},
{
"name": "inserts still work",
@@ -17461,6 +21350,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 26838,
+ "outputTokens": 1827,
+ "cachedInputTokens": 129024,
+ "reasoningTokens": 1611,
+ "costUsd": 0.1707912
+ },
+ "durationMs": 120112,
"prompt": "My database CPU keeps spiking and the app gets slow when loading recent events for a user. Can you figure out what query is causing it and make the database change needed to fix it?\n\nEnd your turn with a short summary of what you changed and why.",
"promptSourcePath": "evals/resolve-performance-001-slow-query-cpu-spike/PROMPT.md",
"attempts": 1,
@@ -17531,15 +21428,24 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 57456,
+ "outputTokens": 3130,
+ "cachedInputTokens": 248320,
+ "reasoningTokens": 3282,
+ "costUsd": 0.34304399999999996
+ },
+ "durationMs": 730662,
"prompt": "A customer reported that notes showed up in the wrong workspace.\n\nCan you investigate what is going on and fix it?",
"promptSourcePath": "evals/resolve-security-002-rls-cross-tenant-leak/PROMPT.md",
- "attempts": 1,
+ "attempts": 2,
"sourcePath": "opencode-kimi-k3/resolve-security-002-rls-cross-tenant-leak.json"
},
{
@@ -17575,7 +21481,7 @@
{
"name": "todos table exists with at least 2 seeded rows",
"passed": true,
- "notes": "found 2 rows"
+ "notes": "found 3 rows"
},
{
"name": "row level security is enabled on todos",
@@ -17593,7 +21499,7 @@
{
"name": "REST API returns the todos to authenticated requests",
"passed": true,
- "notes": "2 rows"
+ "notes": "3 rows"
}
],
"skills": {
@@ -17603,6 +21509,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 24032,
+ "outputTokens": 2433,
+ "cachedInputTokens": 124672,
+ "reasoningTokens": 969,
+ "costUsd": 0.16052760000000002
+ },
+ "durationMs": 318355,
"prompt": "We're kicking off a todos app and I want the Supabase side ready for the team\nto build on. Set it up the way we'd run it in development, with schema changes\ntracked as migrations so they can be reviewed and replayed.\n\nFor the first slice we just need a `todos` table. Todos aren't public: anyone\nsigned in can read all of them, but nothing should be writable through the API\nfor now. Add a couple of sample todos so there's something to look at.\n\nBefore you hand it back, make sure the running API actually behaves that way —\nsigned-in users get the todos, signed-out requests get nothing.",
"promptSourcePath": "evals/build-cli-001-bootstrap-app/PROMPT.md",
"attempts": 1,
@@ -17653,6 +21567,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 21714,
+ "outputTokens": 826,
+ "cachedInputTokens": 62976,
+ "reasoningTokens": 429,
+ "costUsd": 0.1028598
+ },
+ "durationMs": 142932,
"prompt": "Add a description text column to the `products` table in my local Supabase stack",
"promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md",
"attempts": 1,
@@ -17695,7 +21617,7 @@
{
"name": "process-tasks function drains the queue",
"passed": true,
- "notes": "function removed the seeded message (id 8) from the queue"
+ "notes": "function removed the seeded message (id 38) from the queue"
}
],
"skills": {
@@ -17703,37 +21625,16 @@
"loaded": []
},
"docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "{\n searchDocs(query: \"pgmq queues consume messages edge function pop\", limit: 5) {\n nodes {\n title\n href\n content\n }\n }\n}",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/queues/pgmq",
- "title": "PGMQ Extension"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions",
- "title": "Consuming Supabase Queue Messages with Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/quickstart",
- "title": "Quickstart"
- },
- {
- "url": "https://supabase.com/docs/guides/ai/automatic-embeddings",
- "title": "Automatic embeddings"
- },
- {
- "url": "https://supabase.com/docs/guides/queues/api",
- "title": "API"
- }
- ],
- "resultChars": 68440
- }
- ]
+ "calls": []
},
+ "usage": {
+ "inputTokens": 38790,
+ "outputTokens": 4807,
+ "cachedInputTokens": 413696,
+ "reasoningTokens": 5181,
+ "costUsd": 0.39029879999999995
+ },
+ "durationMs": 362119,
"prompt": "I want to set up a recurring background workflow on my local Supabase stack.\n\nCan you set up a cron job called `enqueue-tasks` to run every minute and push a task into a queue called `tasks`? Then add a `process-tasks` edge function that reads messages off the `tasks` queue and removes them, so a scheduled worker can keep the backlog drained.",
"promptSourcePath": "evals/build-cli-003-pg-cron-queue-workflow/PROMPT.md",
"attempts": 1,
@@ -17787,6 +21688,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 39488,
+ "outputTokens": 1640,
+ "cachedInputTokens": 217600,
+ "reasoningTokens": 1287,
+ "costUsd": 0.227649
+ },
+ "durationMs": 342744,
"prompt": "I have an existing Postgres database I want to migrate to Supabase. There's a binary dump at `source.dump` in the current directory.\n\nCan you set up a local Supabase project and restore the dump into it?",
"promptSourcePath": "evals/build-database-001-migrate-postgres-to-supabase/PROMPT.md",
"attempts": 1,
@@ -17849,6 +21758,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 26191,
+ "outputTokens": 1367,
+ "cachedInputTokens": 68352,
+ "reasoningTokens": 543,
+ "costUsd": 0.12772860000000003
+ },
+ "durationMs": 104728,
"prompt": "I built an Edge Function called `private-notes` for showing a user's saved\nprivate notes.\n\nCan you check whether there's any way one user could see another user's notes?\n\nPlease fix and deploy it if needed.",
"promptSourcePath": "evals/build-functions-004-service-role-bypass/PROMPT.md",
"attempts": 1,
@@ -17877,7 +21794,7 @@
"suite": "benchmark",
"interface": "cli",
"cliVersion": "2.109.1",
- "passed": true,
+ "passed": false,
"checks": [
{
"name": "seed rows present",
@@ -17887,91 +21804,62 @@
{
"name": "rejects request with no credentials",
"passed": true,
- "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
+ "notes": "status 404: Function not found"
},
{
"name": "user with JWT reads only their own rows",
- "passed": true,
- "notes": "status 200: [{\"user_id\":\"97383d24-8574-40e4-8bbf-893c839f4b1e\",\"metric\":\"steps_a_ms6x19hb\",\"value\":111}]"
+ "passed": false,
+ "notes": "status 404: Function not found"
},
{
"name": "user cannot read another user's rows by passing user_id",
- "passed": true,
- "notes": "status 200: [{\"user_id\":\"97383d24-8574-40e4-8bbf-893c839f4b1e\",\"metric\":\"steps_a_ms6x19hb\",\"value\":111}]"
+ "passed": false,
+ "notes": "status 404: Function not found"
},
{
"name": "service key bypasses RLS to read the target user's rows",
- "passed": true,
- "notes": "status 200: [{\"user_id\":\"76300586-725d-4552-ac8c-717466bca850\",\"metric\":\"steps_b_ms6x19hb\",\"value\":222}]"
+ "passed": false,
+ "notes": "status 404: Function not found"
},
{
"name": "non-service key is not granted service access",
"passed": true,
- "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
+ "notes": "status 404: Function not found"
},
{
"name": "rejects an unverified (forged) user token",
"passed": true,
- "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
+ "notes": "status 404: Function not found"
},
{
"name": "a user token in the apikey slot is not treated as the service key",
- "passed": true,
- "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}"
- },
- {
- "name": "implementation uses @supabase/server",
- "passed": true,
- "notes": "imports @supabase/server / withSupabase"
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"edge function verify service role key apikey header dual authentication\") { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
- "title": "Envoy API Gateway"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/auth-headers",
- "title": "Authorization headers"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/error-codes",
- "title": "Error codes"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt",
- "title": "Integrating With Supabase Auth"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
- }
- ],
- "resultChars": 79200
- }
- ]
+ "passed": true,
+ "notes": "status 404: Function not found"
+ },
+ {
+ "name": "implementation uses @supabase/server",
+ "passed": false,
+ "notes": "could not locate function source to inspect"
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 99525,
+ "outputTokens": 2630,
+ "cachedInputTokens": 487168,
+ "reasoningTokens": 13221,
+ "costUsd": 0.6824904
},
+ "durationMs": 733592,
"prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nOur product stores per-user metrics in the existing `user_stats` table.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.",
"promptSourcePath": "evals/build-functions-005-dual-auth-user-secret/PROMPT.md",
- "attempts": 1,
+ "attempts": 2,
"sourcePath": "opencode-kimi-k3-no-skills/build-functions-005-dual-auth-user-secret.json"
},
{
@@ -18011,7 +21899,7 @@
{
"name": "user A lists only own files",
"passed": true,
- "notes": "saw: 019fb0e7-791a-732c-b308-f2e318f79d38/receipt-alpha.pdf, 019fb0e7-791a-732c-b308-f2e318f79d38/receipt-beta.pdf"
+ "notes": "saw: 019fb3d9-a271-70ba-995e-4810cc757e60/receipt-alpha.pdf, 019fb3d9-a271-70ba-995e-4810cc757e60/receipt-beta.pdf"
},
{
"name": "user B cannot read user A files",
@@ -18032,7 +21920,7 @@
{
"name": "configured private per-user storage access",
"passed": true,
- "judgeNotes": "Meets all requirements: private user-files bucket, RLS kept enabled, authenticated owner-scoped SELECT and INSERT policies with WITH CHECK, and supabase-js createSignedUrl with expiry for temporary sharing."
+ "judgeNotes": "The answer creates a private user-files bucket, defines authenticated-only owner-scoped SELECT and INSERT policies on storage.objects using the first path folder matching auth.uid(), keeps RLS intact, and uses supabase-js createSignedUrl with an expiry for temporary sharing. No public bucket, public URL, permissive policy, anon scoping, or client service-role usage is present."
}
],
"skills": {
@@ -18040,8 +21928,45 @@
"loaded": []
},
"docs": {
- "calls": []
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "{\n searchDocs(query: \"storage bucket RLS policy owner folder auth.uid createSignedUrl expires\", limit: 5) {\n nodes {\n title\n href\n content\n }\n }\n}",
+ "hasContent": true,
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals",
+ "title": "Storage Buckets"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/storage/security/access-control",
+ "title": "Storage Access Control"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3",
+ "title": "Configure S3 Storage"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/security/product-security",
+ "title": "Secure configuration of Supabase products"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/storage/cdn/smart-cdn",
+ "title": "Smart CDN"
+ }
+ ],
+ "resultChars": 23308
+ }
+ ]
+ },
+ "usage": {
+ "inputTokens": 35753,
+ "outputTokens": 1714,
+ "cachedInputTokens": 67328,
+ "reasoningTokens": 1793,
+ "costUsd": 0.1800624
},
+ "durationMs": 142756,
"prompt": "Our app lets signed-in users keep personal files like receipts and bank\nstatements. These files are private — a user must only ever be able to upload\nand download their own. The app uploads each file under a path that starts\nwith the owner's user id, e.g. `/receipt-march.pdf`.\n\nSet up a `user-files` bucket on our project and lock it down that way.\n\nUsers also sometimes share one of their files with someone else through a\ntemporary link that expires. Include the supabase-js code the app should use\nfor that.",
"promptSourcePath": "evals/build-storage-001-private-bucket-access/PROMPT.md",
"attempts": 1,
@@ -18071,7 +21996,7 @@
{
"name": "pgTAP test file(s) written under supabase/tests/",
"passed": true,
- "notes": "1 file(s): supabase/tests/rls_tenant_isolation_test.sql"
+ "notes": "1 file(s): supabase/tests/tenant_isolation.test.sql"
},
{
"name": "pgTAP isolation tests ran and pass",
@@ -18081,7 +22006,7 @@
{
"name": "agent correctly identifies the posts isolation bug from test results",
"passed": true,
- "judgeNotes": "The agent correctly identifies `posts` as having a broken tenant isolation SELECT policy, explaining that authenticated users with any membership can read posts from other orgs because `m.org_id = posts.org_id` is missing. This conclusion is grounded in the pgTAP failures for cross-org post reads. The agent also notes a memberships exposure, but does not blame `notes` or dismiss the tests."
+ "judgeNotes": "The agent correctly identifies `posts` as having the broken tenant isolation policy, explains that authenticated members can read posts from other organizations due to the missing `m.org_id = posts.org_id` correlation, and grounds this in the pgTAP failures for cross-tenant post reads. It treats the test results as authoritative and does not blame `notes`."
}
],
"skills": {
@@ -18091,6 +22016,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 43500,
+ "outputTokens": 3438,
+ "cachedInputTokens": 177408,
+ "reasoningTokens": 8735,
+ "costUsd": 0.36631739999999996
+ },
+ "durationMs": 347535,
"prompt": "Can you audit the tenant isolation on our tables? Write some database tests covering both the happy path and the negative case, run them, and share the results.",
"promptSourcePath": "evals/build-tests-001-rls-tenant-isolation/PROMPT.md",
"attempts": 1,
@@ -18116,7 +22049,7 @@
],
"suite": "benchmark",
"interface": "mcp",
- "passed": true,
+ "passed": false,
"checks": [
{
"name": "document_sections.embedding is vector(384)",
@@ -18125,13 +22058,13 @@
},
{
"name": "HNSW index on the embedding column",
- "passed": true,
- "notes": "CREATE INDEX document_sections_embedding_idx ON public.document_sections USING hnsw (embedding vector_cosine_ops)"
+ "passed": false,
+ "notes": "no index on embedding column"
},
{
"name": "index operator class matches the search operator",
- "passed": true,
- "notes": "function operators: <=>\nindexes: CREATE INDEX document_sections_embedding_idx ON public.document_sections USING hnsw (embedding vector_cosine_ops)"
+ "passed": false,
+ "notes": "function operators: <=>\nindexes: none"
},
{
"name": "user A search returns only own sections, best match first",
@@ -18145,308 +22078,139 @@
"name": "user A reads only own sections through the API",
"passed": true
},
- {
- "name": "user A reads only own documents through the API",
- "passed": true
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"gte-small embedding dimensions vector 384 semantic search edge function\", limit: 3) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/functions/examples/semantic-search",
- "title": "Semantic Search"
- },
- {
- "url": "https://supabase.com/docs/guides/ai/choosing-compute-addon",
- "title": "Choosing your Compute Add-on"
- },
- {
- "url": "https://supabase.com/docs/guides/ai/semantic-search",
- "title": "Semantic search"
- }
- ],
- "resultChars": 39484
- }
- ]
- },
- "prompt": "We're adding semantic search to our internal knowledge base app. I already wrote the edge functions, but search doesn't work yet. Can you set up whatever the database needs to make search work end to end?\n\nSome documents are confidential, so users should only have access to documents they own.",
- "promptSourcePath": "evals/build-vectors-001-rag-with-permissions/PROMPT.md",
- "attempts": 2,
- "sourcePath": "opencode-kimi-k3-no-skills/build-vectors-001-rag-with-permissions.json"
- },
- {
- "experiment": "opencode-kimi-k3-no-skills",
- "experimentSuite": "no-skills",
- "experimentDisplay": {
- "agent": "opencode",
- "modelProvider": "moonshotai",
- "modelId": "moonshotai/kimi-k3"
- },
- "eval": "deploy-database-001-prometheus-metrics",
- "stage": "deploy",
- "product": [
- "database"
- ],
- "topic": [
- "observability"
- ],
- "suite": "benchmark",
- "passed": true,
- "checks": [
- {
- "name": "preserved existing app scrape job",
- "passed": true
- },
- {
- "name": "configured the Supabase Metrics API scrape correctly",
- "passed": true,
- "judgeNotes": "Supabase scrape is deployable with HTTPS, correct metrics path, Basic Auth using password_file, project target on supabase.co, app job preserved, and docker-compose mounts the password file."
- },
- {
- "name": "documented live deployment and verification steps",
- "passed": true,
- "judgeNotes": "README includes steps to create an sb_secret Secret API key, place it in the matching observability/secrets/supabase-metrics-key file, restart/reload the Compose/Prometheus stack, and verify via Prometheus targets/API query and Grafana. Endpoint/auth and secret setup match the config."
- }
- ],
- "skills": {
- "available": [],
- "loaded": []
- },
- "docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"metrics endpoint prometheus scrape project metrics\") { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-self-hosted",
- "title": "Metrics API with Prometheus & Grafana (self-hosted)"
- },
- {
- "url": "https://supabase.com/docs/guides/telemetry/metrics",
- "title": "Metrics API"
- },
- {
- "url": "https://supabase.com/docs/guides/telemetry/metrics/vendor-agnostic",
- "title": "Vendor-agnostic Metrics API setup"
- },
- {
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-cloud",
- "title": "Metrics API with Grafana Cloud"
- },
- {
- "url": "https://supabase.com/docs/guides/troubleshooting/how-to-view-database-metrics-uqf2z_",
- "title": "How to View Database Metrics"
- },
- {
- "url": "https://supabase.com/docs/guides/platform/read-replicas",
- "title": "Read Replicas"
- },
- {
- "url": "https://supabase.com/docs/guides/database/connection-management",
- "title": "Connection management"
- },
- {
- "url": "https://supabase.com/docs/guides/realtime/benchmarks",
- "title": "Benchmarks"
- },
- {
- "url": "https://supabase.com/docs/guides/troubleshooting/grafana-not-displaying-data-sXJrMj",
- "title": "Grafana not displaying data"
- },
- {
- "url": "https://supabase.com/docs/guides/telemetry/reports",
- "title": "Reports"
- }
- ],
- "resultChars": 81235
- },
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"management api create secret api key sb_secret\") { nodes { title href content methodName language } } }",
- "hasContent": true,
- "pages": []
- },
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"management api create secret api key sb_secret\") { nodes { title href content ... on ManagementApiReference { title href content } } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-kotlin",
- "title": "Build a Product Management Android App with Jetpack Compose"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-angular",
- "title": "Build a User Management App with Angular"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-ionic-angular",
- "title": "Build a User Management App with Ionic Angular"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-ionic-react",
- "title": "Build a User Management App with Ionic React"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-svelte",
- "title": "Build a User Management App with Svelte"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-redwoodjs",
- "title": "Build a User Management App with RedwoodJS"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-vue-3",
- "title": "Build a User Management App with Vue 3"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-ionic-vue",
- "title": "Build a User Management App with Ionic Vue"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs",
- "title": "Build a User Management App with Next.js"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-swift",
- "title": "Build a User Management App with Swift and SwiftUI"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-sveltekit",
- "title": "Build a User Management App with SvelteKit"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/quickstarts/with-expo-react-native-social-auth",
- "title": "Build a Social Auth App with Expo React Native"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-solidjs",
- "title": "Build a User Management App with SolidJS"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-react",
- "title": "Build a User Management App with React"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-expo-react-native",
- "title": "Build a User Management App with Expo React Native"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-refine",
- "title": "Build a User Management App with Refine"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nuxt-3",
- "title": "Build a User Management App with Nuxt 3"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-flutter",
- "title": "Build a User Management App with Flutter"
- },
- {
- "url": "https://supabase.com/docs/reference/api/v1-bulk-create-secrets",
- "title": "Bulk create secrets"
- },
+ {
+ "name": "user A reads only own documents through the API",
+ "passed": true
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 26763,
+ "outputTokens": 2810,
+ "cachedInputTokens": 153600,
+ "reasoningTokens": 4771,
+ "costUsd": 0.24008400000000002
+ },
+ "durationMs": 190375,
+ "prompt": "We're adding semantic search to our internal knowledge base app. I already wrote the edge functions, but search doesn't work yet. Can you set up whatever the database needs to make search work end to end?\n\nSome documents are confidential, so users should only have access to documents they own.",
+ "promptSourcePath": "evals/build-vectors-001-rag-with-permissions/PROMPT.md",
+ "attempts": 2,
+ "sourcePath": "opencode-kimi-k3-no-skills/build-vectors-001-rag-with-permissions.json"
+ },
+ {
+ "experiment": "opencode-kimi-k3-no-skills",
+ "experimentSuite": "no-skills",
+ "experimentDisplay": {
+ "agent": "opencode",
+ "modelProvider": "moonshotai",
+ "modelId": "moonshotai/kimi-k3"
+ },
+ "eval": "deploy-database-001-prometheus-metrics",
+ "stage": "deploy",
+ "product": [
+ "database"
+ ],
+ "topic": [
+ "observability"
+ ],
+ "suite": "benchmark",
+ "passed": true,
+ "checks": [
+ {
+ "name": "preserved existing app scrape job",
+ "passed": true
+ },
+ {
+ "name": "configured the Supabase Metrics API scrape correctly",
+ "passed": true,
+ "judgeNotes": "Meets all requirements: app scrape preserved, Supabase HTTPS metrics endpoint configured with correct path and project target, Basic Auth uses password_file, and docker-compose mounts the secrets directory containing that file."
+ },
+ {
+ "name": "documented live deployment and verification steps",
+ "passed": true,
+ "judgeNotes": "README includes steps to create/copy a Supabase Secret API key, write it to the mounted secret file, start or reload the Compose/Prometheus stack, and verify via Prometheus targets. Endpoint/auth and secret-file setup match the config; placeholder secret values are not committed credentials."
+ }
+ ],
+ "skills": {
+ "available": [],
+ "loaded": []
+ },
+ "docs": {
+ "calls": [
+ {
+ "source": "search_docs",
+ "query": "{ searchDocs(query: \"metrics endpoint prometheus scrape\", limit: 5) { nodes { title href content } } }",
+ "hasContent": true,
+ "pages": [
{
- "url": "https://supabase.com/docs/reference/api/v1-create-project-api-key",
- "title": "Creates a new API key for the project"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted",
+ "title": "Metrics API with Prometheus & Grafana (self-hosted)"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/vendor-agnostic",
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic",
"title": "Vendor-agnostic Metrics API setup"
},
{
- "url": "https://supabase.com/docs/guides/self-hosting/docker",
- "title": "Self-Hosting with Docker"
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics",
+ "title": "Metrics API"
},
{
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-cloud",
+ "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud",
"title": "Metrics API with Grafana Cloud"
- },
- {
- "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-self-hosted",
- "title": "Metrics API with Prometheus & Grafana (self-hosted)"
- },
- {
- "url": "https://supabase.com/docs/guides/integrations/supabase-for-platforms",
- "title": "Supabase for Platforms"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
}
],
- "resultChars": 729739
+ "resultChars": 19334
+ },
+ {
+ "source": "search_docs",
+ "query": "{ searchDocs(query: \"management api create project api key secret sb_secret\", limit: 4) { nodes { title href content methodName } } }",
+ "hasContent": true,
+ "pages": []
},
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"POST api-keys create new secret key management api endpoint\", limit: 8) { nodes { title href content ... on ManagementApiReference { title href content } } } }",
+ "query": "{ searchDocs(query: \"management api create secret api key endpoint\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-kotlin",
- "title": "Build a Product Management Android App with Jetpack Compose"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
- },
- {
- "url": "https://supabase.com/docs/reference/api/v1-create-project-api-key",
- "title": "Creates a new API key for the project"
- },
- {
- "url": "https://supabase.com/docs/guides/integrations/supabase-for-platforms",
- "title": "Supabase for Platforms"
- },
- {
- "url": "https://supabase.com/docs/reference/api/v1-get-project-api-keys",
- "title": "Get project api keys"
+ "url": "https://supabase.com/docs/guides/auth/signing-keys",
+ "title": "JWT Signing Keys"
},
{
- "url": "https://supabase.com/docs/reference/api/v1-get-project-api-key",
- "title": "Get API key"
+ "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-kotlin",
+ "title": "Build a Product Management Android App with Jetpack Compose"
},
{
"url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
"title": "New API Keys and Asymmetric Authentication"
},
{
- "url": "https://supabase.com/docs/reference/api/v1-create-project-signing-key",
- "title": "Create a new signing key for the project in standby status"
+ "url": "https://supabase.com/docs/reference/api/v1-bulk-create-secrets",
+ "title": "Bulk create secrets"
+ },
+ {
+ "url": "https://supabase.com/docs/reference/api/v1-create-project-api-key",
+ "title": "Creates a new API key for the project"
}
],
- "resultChars": 99738
+ "resultChars": 99533
}
]
},
+ "usage": {
+ "inputTokens": 60601,
+ "outputTokens": 7063,
+ "cachedInputTokens": 581120,
+ "reasoningTokens": 7209,
+ "costUsd": 0.5702189999999998
+ },
+ "durationMs": 631092,
"prompt": "Can you wire my Supabase project metrics into our existing observability stack and document\nin the observability README what we need to do to make the config live?",
"promptSourcePath": "evals/deploy-database-001-prometheus-metrics/PROMPT.md",
"attempts": 1,
@@ -18498,6 +22262,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 44583,
+ "outputTokens": 5108,
+ "cachedInputTokens": 368896,
+ "reasoningTokens": 3859,
+ "costUsd": 0.37892279999999995
+ },
+ "durationMs": 340282,
"prompt": "Our weather widget currently calls WeatherAPI straight from the browser, which\nleaks our API key. I want to move that behind a Supabase Edge Function called\n`weather` that holds the key server-side and proxies the request.\n\nThe function should read the key from an environment variable named\n`WEATHER_API_KEY`. Our key already lives in a local `.env` file at the project\nroot.\n\nDeploy the function to our project so it's live, and make sure the deployed\nfunction can actually read the key at runtime.",
"promptSourcePath": "evals/deploy-functions-001-edge-function-secrets/PROMPT.md",
"attempts": 1,
@@ -18547,137 +22319,16 @@
"loaded": []
},
"docs": {
- "calls": [
- {
- "source": "search_docs",
- "query": "query { searchDocs(query: \"self-hosting with docker generate API keys anon service_role JWT secret\") { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
- "title": "Envoy API Gateway"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/docker",
- "title": "Self-Hosting with Docker"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-kotlin",
- "title": "Build a Product Management Android App with Jetpack Compose"
- },
- {
- "url": "https://supabase.com/docs/guides/troubleshooting/rotating-anon-service-and-jwt-secrets-1Jq6yd",
- "title": "Rotating Anon, Service, and JWT Secrets"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-saml-sso",
- "title": "Configure SAML SSO"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https",
- "title": "Configure Reverse Proxy and HTTPS"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/restore-from-platform",
- "title": "Restore a Platform Project to Self-Hosted"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-ionic-react",
- "title": "Build a User Management App with Ionic React"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs",
- "title": "Build a User Management App with Next.js"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-solidjs",
- "title": "Build a User Management App with SolidJS"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-react",
- "title": "Build a User Management App with React"
- },
- {
- "url": "https://supabase.com/docs/guides/storage/serving/image-transformations",
- "title": "Storage Image Transformations"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-oauth",
- "title": "Configure Social Login (OAuth) Providers"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-angular",
- "title": "Build a User Management App with Angular"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-ionic-angular",
- "title": "Build a User Management App with Ionic Angular"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-phone-mfa",
- "title": "Configure Phone Login & MFA"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/server-side/creating-a-client",
- "title": "Creating a Supabase client for SSR"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-refine",
- "title": "Build a User Management App with Refine"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-sveltekit",
- "title": "Build a User Management App with SvelteKit"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-svelte",
- "title": "Build a User Management App with Svelte"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-swift",
- "title": "Build a User Management App with Swift and SwiftUI"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-flutter",
- "title": "Build a User Management App with Flutter"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-nuxt-3",
- "title": "Build a User Management App with Nuxt 3"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-ionic-vue",
- "title": "Build a User Management App with Ionic Vue"
- },
- {
- "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-vue-3",
- "title": "Build a User Management App with Vue 3"
- }
- ],
- "resultChars": 730694
- }
- ]
+ "calls": []
+ },
+ "usage": {
+ "inputTokens": 64372,
+ "outputTokens": 3082,
+ "cachedInputTokens": 247552,
+ "reasoningTokens": 5100,
+ "costUsd": 0.3901116
},
+ "durationMs": 258941,
"prompt": "I'm moving off the hosted Supabase and running the whole thing myself on a VPS I\njust spun up. Can you get a Docker setup ready for me to copy onto the box?\n\nI don't need it running here, I'll do the actual bring-up once I'm on the\nserver. I just want everything in place and the secrets set up. Put it in a `supabase-docker/`\nfolder at the repo root so I can scp the whole thing across in one go.",
"promptSourcePath": "evals/deploy-self-hosting-001-docker-compose/PROMPT.md",
"attempts": 1,
@@ -18732,7 +22383,7 @@
{
"name": "diagnosed and explained session revocation",
"passed": true,
- "judgeNotes": "The answer correctly identifies the soft-delete-only root cause, implements real auth user deletion with cascading session/refresh token/identity removal, and explains the remaining stateless JWT access-token window consistently with that implementation. It also accurately distinguishes publishable/frontend/RLS-enforced keys from secret/backend/RLS-bypassing keys and warns not to expose secret keys."
+ "judgeNotes": "Identifies soft-delete-only root cause, implements auth.users deletion with session/refresh-token revocation/cascade, hardens RLS for stale JWTs, and explains stateless JWT expiry caveat consistently. Correctly distinguishes publishable frontend/RLS-enforced use from secret server-only/RLS-bypassing use."
}
],
"skills": {
@@ -18743,20 +22394,38 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"publishable key secret key vs anon service_role API keys RLS\", limit: 5) { nodes { title content } } }",
+ "query": "{ searchDocs(query: \"publishable secret API keys vs anon service_role RLS\", limit: 4) { nodes { title href content } } }",
"hasContent": true,
- "pages": [],
- "resultChars": 64643
- },
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"Understanding API keys publishable anonymous RLS\", limit: 3) { nodes { title content } } }",
- "hasContent": true,
- "pages": [],
- "resultChars": 52294
+ "pages": [
+ {
+ "url": "https://supabase.com/docs/guides/auth/signing-keys",
+ "title": "JWT Signing Keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/quickstarts/refine",
+ "title": "Use Supabase with Refine"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
+ "title": "Migrating to publishable and secret API keys"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/auth/jwt-fields",
+ "title": "JWT Claims Reference"
+ }
+ ],
+ "resultChars": 70279
}
]
},
+ "usage": {
+ "inputTokens": 88039,
+ "outputTokens": 6265,
+ "cachedInputTokens": 432544,
+ "reasoningTokens": 10927,
+ "costUsd": 0.6517601999999999
+ },
+ "durationMs": 487724,
"prompt": "Last week support removed a user through our app's delete-account flow — the\napp calls the `delete_account` function over RPC as the signed-in user. This\nmorning that same person was back: still signed in, reading and saving their\ndata like nothing happened.\n\nFigure out why the account still works, fix the flow so a deleted account\nloses access, and tell me whether there is any window where they could still\nget in after the fix.\n\nOne more thing while you're at it: we're migrating off the legacy\nanon/service_role API keys to the new publishable and secret keys, and the\nteam isn't sure which one belongs in the frontend and what each means for\nRLS. Give us a quick rundown.",
"promptSourcePath": "evals/investigate-auth-001-deleted-user-access/PROMPT.md",
"attempts": 1,
@@ -18807,7 +22476,7 @@
{
"name": "diagnosed missing publication membership",
"passed": true,
- "judgeNotes": "Identifies missing orders table in supabase_realtime as root cause, applies ALTER PUBLICATION ADD TABLE public.orders, preserves existing publication/RLS/policies and courier_locations, and avoids disallowed fixes."
+ "judgeNotes": "Diagnosed orders missing from supabase_realtime publication and fixed with ALTER PUBLICATION ... ADD TABLE public.orders. Did not weaken RLS/policies or disrupt courier_locations. Mentions RLS only as a check, not root cause."
}
],
"skills": {
@@ -18817,6 +22486,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 38782,
+ "outputTokens": 3081,
+ "cachedInputTokens": 212480,
+ "reasoningTokens": 2803,
+ "costUsd": 0.26835
+ },
+ "durationMs": 256979,
"prompt": "Our dispatch dashboard shows incoming orders as they happen. The courier\nlocation feed on the same page updates live without problems, but new orders\nonly show up after a page refresh.\n\nThe dashboard uses supabase-js to subscribe to INSERT events on the `orders`\ntable through postgres_changes, the same way it subscribes to courier\nlocations. The channel's status callback logs SUBSCRIBED and there are no\nerrors in the browser console.\n\nFigure out why no order events ever arrive and fix it.",
"promptSourcePath": "evals/investigate-realtime-001-subscribed-no-events/PROMPT.md",
"attempts": 1,
@@ -18845,17 +22522,17 @@
{
"name": "identified image-transform and the recurring 503 pattern",
"passed": true,
- "judgeNotes": "The assistant identified image-transform as the affected function and described the recurring 8 HTTP 503 gateway failures across the morning of 2026-04-28 from 07:00Z–12:00Z, while distinguishing unrelated billing-webhook noise."
+ "judgeNotes": "Identified image-transform as affected and described the recurring 8 HTTP 503 gateway responses across 07:00Z-12:00Z on 2026-04-28, while distinguishing older billing-webhook errors."
},
{
"name": "attributed recurring 503s to gateway/platform layer, not function code",
"passed": true,
- "judgeNotes": "The assistant clearly attributes the recurring image-transform 503s to the gateway/platform layer, not function code, and grounds this in valid observations: gateway identifiers with no corresponding runtime execution records, nearby successful executions on unchanged deployment, and distinction from avatar-upload's function-level 500."
+ "judgeNotes": "Attributes 503s to API gateway/platform layer, not function code. Grounds this in valid observations: gateway/API logs show 503s while Edge Function invocation logs show successful 200s and no invocation for failed requests; stable deployment_id/version; distinguishes gateway 503s from avatar-upload function-level 500."
},
{
"name": "recommended a concrete next step",
"passed": true,
- "judgeNotes": "Recommended concrete next steps including opening a Supabase support ticket with gateway request IDs and timestamps, plus retry logic and alerting."
+ "judgeNotes": "Recommended concrete next steps including opening a Supabase support ticket with exact timestamps/project ref, correlating platform gateway/runtime metrics, adding retries, and setting up uptime alerts."
}
],
"skills": {
@@ -18865,9 +22542,17 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 18826,
+ "outputTokens": 1504,
+ "cachedInputTokens": 59392,
+ "reasoningTokens": 398,
+ "costUsd": 0.1028256
+ },
+ "durationMs": 70685,
"prompt": "Users have been reporting that image uploads are intermittently failing with server errors throughout the morning of `2026-04-28`.\n\nCan you investigate the project logs and tell me what is going on and what we\nshould do next?",
"promptSourcePath": "evals/investigate-reliability-003-edge-function-5xx-correlation/PROMPT.md",
- "attempts": 2,
+ "attempts": 1,
"sourcePath": "opencode-kimi-k3-no-skills/investigate-reliability-003-edge-function-5xx-correlation.json"
},
{
@@ -18920,7 +22605,7 @@
{
"name": "diagnosed RLS and added owner-scoped policies",
"passed": true,
- "judgeNotes": "Diagnosed RLS deny-all due to no policies, kept RLS enabled, and created authenticated SELECT and INSERT policies scoped to user_id = auth.uid() with WITH CHECK for inserts."
+ "judgeNotes": "Diagnosed RLS deny-all due to no policies and added authenticated-only owner-scoped SELECT and INSERT policies with auth.uid() = user_id, keeping RLS enabled."
}
],
"skills": {
@@ -18930,6 +22615,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 30827,
+ "outputTokens": 2622,
+ "cachedInputTokens": 183296,
+ "reasoningTokens": 2665,
+ "costUsd": 0.2267748
+ },
+ "durationMs": 175995,
"prompt": "Our app lets signed-in users save bookmarks and view them on their dashboard. Bookmarks are stored in the `bookmarks` table and are private — a user must only ever see their own. \nUsers also need to be able to save new bookmarks from the app.\n\nI can see the rows when I query the table directly, but the dashboard shows an empty list for every user.\n\nFind out why the Data API returns nothing and fix it.",
"promptSourcePath": "evals/resolve-dataapi-001-empty-results/PROMPT.md",
"attempts": 1,
@@ -18978,7 +22671,7 @@
{
"name": "the avatar migration and history reconciliation were done via the Supabase CLI",
"passed": true,
- "judgeNotes": "Avatar migration was applied through `supabase db push` in action #28, which shows `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` History was reconciled by adding/restoring the local orphan migration file `20240115000000_add_profile_bio.sql` (actions #20-#23), after which `supabase migration list` and the successful `supabase db push` showed local/remote histories aligned. Only read-only `psql` inspection was used; no banned direct SQL mutation or prepared-statement workaround was seen."
+ "judgeNotes": "Avatar migration was applied through `supabase db push` in action #16; the recorded output includes the tail of `Finished supabase db push`, and later inspection shows `avatar_url` present. History was reconciled by adding the missing local migration file `supabase/migrations/20240115000000_add_profile_bio.sql` in #15, then letting `supabase db push` proceed in #16. No prohibited direct SQL mutation or prepared-statement workaround was used."
}
],
"skills": {
@@ -18988,6 +22681,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 26746,
+ "outputTokens": 1715,
+ "cachedInputTokens": 101376,
+ "reasoningTokens": 942,
+ "costUsd": 0.1505058
+ },
+ "durationMs": 121871,
"prompt": "I'm trying to ship a migration to our hosted project and it's not working. Can you figure out what's wrong and get it deployed?",
"promptSourcePath": "evals/resolve-database-001-migration-history-mismatch/PROMPT.md",
"attempts": 1,
@@ -19029,7 +22730,7 @@
{
"name": "query plan uses an index and avoids sequential scan",
"passed": true,
- "notes": "Limit (cost=79.74..79.86 rows=50 width=58)\n -> Sort (cost=79.74..79.99 rows=100 width=58)\n Sort Key: created_at DESC\n -> Bitmap Heap Scan on events (cost=5.06..76.42 rows=100 width=58)\n Recheck Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)\n -> Bitmap Index Scan on idx_events_user_id_created_at (cost=0.00..5.03 rows=100 width=0)\n Index Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)"
+ "notes": "Limit (cost=79.74..79.86 rows=50 width=58)\n -> Sort (cost=79.74..79.99 rows=100 width=58)\n Sort Key: created_at DESC\n -> Bitmap Heap Scan on events (cost=5.06..76.42 rows=100 width=58)\n Recheck Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)\n -> Bitmap Index Scan on events_user_id_created_at_idx (cost=0.00..5.03 rows=100 width=0)\n Index Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)"
},
{
"name": "inserts still work",
@@ -19043,6 +22744,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 27666,
+ "outputTokens": 1410,
+ "cachedInputTokens": 86016,
+ "reasoningTokens": 845,
+ "costUsd": 0.1426278
+ },
+ "durationMs": 108148,
"prompt": "My database CPU keeps spiking and the app gets slow when loading recent events for a user. Can you figure out what query is causing it and make the database change needed to fix it?\n\nEnd your turn with a short summary of what you changed and why.",
"promptSourcePath": "evals/resolve-performance-001-slow-query-cpu-spike/PROMPT.md",
"attempts": 1,
@@ -19114,6 +22823,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 33286,
+ "outputTokens": 1882,
+ "cachedInputTokens": 96000,
+ "reasoningTokens": 1950,
+ "costUsd": 0.18613800000000003
+ },
+ "durationMs": 128908,
"prompt": "A customer reported that notes showed up in the wrong workspace.\n\nCan you investigate what is going on and fix it?",
"promptSourcePath": "evals/resolve-security-002-rls-cross-tenant-leak/PROMPT.md",
"attempts": 1,
diff --git a/apps/web/src/data/regression-eval-results.json b/apps/web/src/data/regression-eval-results.json
index 4f7e59cd..17a02e17 100644
--- a/apps/web/src/data/regression-eval-results.json
+++ b/apps/web/src/data/regression-eval-results.json
@@ -38,17 +38,17 @@
{
"name": "user with JWT reads only their own rows",
"passed": true,
- "notes": "status 200: {\"data\":[{\"user_id\":\"f214cdc1-b432-4379-94d2-f9ca3873ac65\",\"metric\":\"steps_a_ms76nxkn\",\"value\":111}]}"
+ "notes": "status 200: {\"data\":[{\"user_id\":\"da703ac9-0956-4e54-ad9e-99fe305eeb25\",\"metric\":\"steps_a_ms7qat4h\",\"value\":111}]}"
},
{
"name": "user cannot read another user's rows by passing user_id",
"passed": true,
- "notes": "status 200: {\"data\":[{\"user_id\":\"f214cdc1-b432-4379-94d2-f9ca3873ac65\",\"metric\":\"steps_a_ms76nxkn\",\"value\":111}]}"
+ "notes": "status 200: {\"data\":[{\"user_id\":\"da703ac9-0956-4e54-ad9e-99fe305eeb25\",\"metric\":\"steps_a_ms7qat4h\",\"value\":111}]}"
},
{
"name": "service key bypasses RLS to read the target user's rows",
"passed": true,
- "notes": "status 200: {\"data\":[{\"user_id\":\"5a03947a-138d-4984-adeb-096609e24f4c\",\"metric\":\"steps_b_ms76nxkn\",\"value\":222}]}"
+ "notes": "status 200: {\"data\":[{\"user_id\":\"a1710dc8-b752-4a0c-843f-7f83bba5a3e3\",\"metric\":\"steps_b_ms7qat4h\",\"value\":222}]}"
},
{
"name": "non-service key is not granted service access",
@@ -77,183 +77,70 @@
"supabase-postgres-best-practices"
],
"loaded": [
- "supabase"
+ "supabase",
+ "supabase-postgres-best-practices"
]
},
"docs": {
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"@supabase/server edge function withSupabase package\", limit: 8) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"@supabase/server npm edge function withSupabase\", limit: 10) { nodes { title href content } } }",
"hasContent": true,
"pages": [
- {
- "url": "https://supabase.com/docs/guides/auth/choosing-a-server-package",
- "title": "Which package to use"
- },
{
"url": "https://supabase.com/docs/guides/functions/auth",
"title": "Securing Edge Functions"
},
- {
- "url": "https://supabase.com/docs/guides/functions/connect-to-postgres",
- "title": "Integrating with Supabase Database (Postgres)"
- },
- {
- "url": "https://supabase.com/docs/guides/database/connecting-to-postgres/serverless-drivers",
- "title": "Serverless Drivers"
- },
- {
- "url": "https://supabase.com/docs/guides/functions",
- "title": "Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/server-side",
- "title": "Server-Side Rendering"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
- "title": "Self-Hosted Functions"
- },
{
"url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
"title": "Migrating to publishable and secret API keys"
- }
- ],
- "resultChars": 62021
- },
- {
- "source": "web_search",
- "query": "\"@supabase/server\" npm withSupabase edge function",
- "hasContent": false,
- "pages": [
- {
- "url": "https://supabase.com/blog/introducing-supabase-server",
- "title": "Introducing @supabase/server"
},
{
- "url": "https://supabase.com/docs/guides/functions/quickstart",
- "title": "Getting Started with Edge Functions | Supabase Docs"
- },
- {
- "url": "https://supabase.com/blog/edge-functions-node-npm",
- "title": "Edge Functions: Node and native npm compatibility"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/routing",
- "title": "Handling Routing in Functions | Supabase Docs"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions | Supabase Docs"
+ "url": "https://supabase.com/docs/guides/auth/choosing-a-server-package",
+ "title": "Which package to use"
},
{
"url": "https://supabase.com/docs/guides/functions/connect-to-postgres",
- "title": "Integrating with Supabase Database (Postgres) | Supabase Docs"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/examples/image-manipulation",
- "title": "Image Manipulation | Supabase Docs"
- },
- {
- "url": "https://supabase.com/docs/guides/ai-tools/ai-prompts/edge-functions",
- "title": "AI Prompt: Writing Supabase Edge Functions | Supabase Docs"
- }
- ],
- "resultChars": 3177
- },
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"new API keys publishable secret key edge functions environment variables SUPABASE_SECRET_KEY\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/auth",
- "title": "Securing Edge Functions"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys",
- "title": "New API Keys and Asymmetric Authentication"
- },
- {
- "url": "https://supabase.com/docs/guides/functions/secrets",
- "title": "Environment Variables"
- },
- {
- "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy",
- "title": "Envoy API Gateway"
- }
- ],
- "resultChars": 65829
- },
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"supabase config.toml edge functions import_map deno.json npm specifiers verify_jwt\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/functions/development-tips",
- "title": "Development tips"
+ "title": "Integrating with Supabase Database (Postgres)"
},
{
- "url": "https://supabase.com/docs/guides/functions/function-configuration",
- "title": "Function Configuration"
+ "url": "https://supabase.com/docs/guides/database/connecting-to-postgres/serverless-drivers",
+ "title": "Serverless Drivers"
},
{
- "url": "https://supabase.com/docs/guides/functions/dependencies",
- "title": "Managing dependencies"
+ "url": "https://supabase.com/docs/guides/functions",
+ "title": "Edge Functions"
},
{
"url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-generate-speech-stream",
"title": "Streaming Speech with ElevenLabs"
},
{
- "url": "https://supabase.com/docs/guides/security/npm-security",
- "title": "Securing npm installs"
- }
- ],
- "resultChars": 42096
- },
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"verify_jwt edge functions new secret key apikey header not a JWT authorization header required\", limit: 5) { nodes { title href content } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/getting-started/api-keys",
- "title": "Understanding API keys"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/signing-keys",
- "title": "JWT Signing Keys"
- },
- {
- "url": "https://supabase.com/docs/guides/auth/auth-hooks/send-email-hook",
- "title": "Send Email Hook"
+ "url": "https://supabase.com/docs/guides/functions/quickstart-dashboard",
+ "title": "Getting Started with Edge Functions (Dashboard)"
},
{
- "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys",
- "title": "Migrating to publishable and secret API keys"
+ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions",
+ "title": "Self-Hosted Functions"
},
{
- "url": "https://supabase.com/docs/guides/functions/error-codes",
- "title": "Error codes"
+ "url": "https://supabase.com/docs/guides/functions/unit-test",
+ "title": "Testing your Edge Functions"
}
],
- "resultChars": 110652
- },
- {
- "source": "web_search",
- "query": "\"failed to determine entrypoint\" supabase functions serve worker boot error",
- "pages": [],
- "resultChars": 2141
+ "resultChars": 84499
}
]
},
+ "usage": {
+ "inputTokens": 1718692,
+ "outputTokens": 10407,
+ "cachedInputTokens": 1635631,
+ "cacheCreationInputTokens": 78034,
+ "costUsd": 1.5917599999999996
+ },
+ "durationMs": 292714,
"prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nImplement it with the **`@supabase/server`** package, which is built for exactly\nthis kind of multi-auth Edge Function. Import it directly in your function:\n\n```ts\nimport { withSupabase } from \"npm:@supabase/server\";\n```\n\nOur product stores per-user metrics in a `user_stats` table that already exists\n(see `supabase/migrations/`), protected by row-level security so a user can read\nonly their own rows.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.\n\nGet the local stack running so the function is reachable at the path above.",
"promptSourcePath": "evals/build-functions-006-dual-auth-with-server/PROMPT.md",
"attempts": 1,
@@ -288,7 +175,7 @@
{
"name": "did not recommend read replicas for Realtime",
"passed": true,
- "judgeNotes": "The answer correctly treats the request as a Supabase Realtime/Postgres Changes setup, adds the table to the supabase_realtime publication, verifies it, and provides a client subscription snippet. It does not recommend or imply read replicas are needed or useful for live updates."
+ "judgeNotes": "The answer correctly treats the task as Supabase Realtime/Postgres Changes setup, adds the messages table to the supabase_realtime publication, verifies it, and provides postgres_changes client code. It does not recommend read replicas or confuse them with logical replication/publications."
}
],
"skills": {
@@ -304,65 +191,42 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"enable realtime postgres changes table subscribe\", limit: 5) { nodes { ... on Guide { title href content } } } }",
+ "query": "{ searchDocs(query: \"realtime postgres changes vs broadcast best practice\", limit: 5) { nodes { ... on Guide { title href content } } } }",
"hasContent": true,
"pages": [
{
"url": "https://supabase.com/docs/guides/realtime/postgres-changes",
"title": "Postgres Changes"
},
- {
- "url": "https://supabase.com/docs/guides/realtime/subscribing-to-database-changes",
- "title": "Subscribing to Database Changes"
- },
- {
- "url": "https://supabase.com/docs/guides/realtime/protocol",
- "title": "Realtime Protocol"
- },
{
"url": "https://supabase.com/docs/guides/realtime/benchmarks",
"title": "Benchmarks"
},
- {
- "url": "https://supabase.com/docs/guides/realtime/authorization",
- "title": "Realtime Authorization"
- }
- ],
- "resultChars": 112153
- },
- {
- "source": "search_docs",
- "query": "{ searchDocs(query: \"enable realtime for a table postgres changes\", limit: 3) { nodes { ... on Guide { title href content } } } }",
- "hasContent": true,
- "pages": [
- {
- "url": "https://supabase.com/docs/guides/realtime/postgres-changes",
- "title": "Postgres Changes"
- },
{
"url": "https://supabase.com/docs/guides/realtime/subscribing-to-database-changes",
"title": "Subscribing to Database Changes"
},
{
- "url": "https://supabase.com/docs/guides/realtime/benchmarks",
- "title": "Benchmarks"
- }
- ],
- "resultChars": 63078
- },
- {
- "source": "web_fetch",
- "query": "List any entries related to Realtime, Postgres Changes, or realtime publications, especially breaking changes.",
- "hasContent": true,
- "pages": [
+ "url": "https://supabase.com/docs/guides/realtime/architecture",
+ "title": "Realtime Architecture"
+ },
{
- "url": "https://supabase.com/changelog.md"
+ "url": "https://supabase.com/docs/guides/database/replication",
+ "title": "Database replication"
}
],
- "resultChars": 1395
+ "resultChars": 74914
}
]
},
+ "usage": {
+ "inputTokens": 833778,
+ "outputTokens": 6355,
+ "cachedInputTokens": 779346,
+ "cacheCreationInputTokens": 50047,
+ "costUsd": 0.8839257500000001
+ },
+ "durationMs": 89651,
"prompt": "I'm building a simple chat app on Supabase.\n\nUsers can send messages, and I want everyone in the same room to see new\nmessages appear automatically without refreshing the page.\n\nCan you inspect the project and set up whatever Supabase needs for live updates?",
"promptSourcePath": "evals/build-realtime-001-live-chat-updates/PROMPT.md",
"attempts": 1,
@@ -391,17 +255,17 @@
{
"name": "identified video-thumbnails and the 546 resource-limit pattern",
"passed": true,
- "judgeNotes": "Identified `video-thumbnails` as the affected function and correctly recognized failures as HTTP 546 / WORKER_RESOURCE_LIMIT due to CPUTime resource limits, not 500/503 server errors."
+ "judgeNotes": "The assistant correctly identified `video-thumbnails` as the affected function and explicitly recognized the failures as HTTP 546 responses due to resource/CPU limit (`CPUTime`, 2000ms), not 500s/503s."
},
{
"name": "attributed the 546s to CPU time exhaustion",
"passed": true,
- "judgeNotes": "The assistant specifically attributes the 546 failures to CPU time exhaustion, citing log evidence including `shutdown (reason: CPUTime, cpu_time_used: 2000ms, cpu_time_limit: 2000ms)` and distinguishing CPU time from wall-clock time."
+ "judgeNotes": "The assistant specifically attributed the 546 failures to CPU time exhaustion, citing log evidence: shutdown reason `CPUTime` and `cpu_time_used: 2000ms / limit: 2000ms`, and did not blame memory, wall-clock time, exceptions, or the unrelated email error."
},
{
"name": "recommended reducing/offloading CPU work as the fix",
"passed": true,
- "judgeNotes": "The assistant identified CPUTime resource limits and recommended the real fix as moving CPU-heavy thumbnail generation off the Edge Function to a background job/external service, and also suggested reducing decode work/using lighter libraries. It explicitly discouraged retries as a fix."
+ "judgeNotes": "Assistant clearly identified CPUTime limit from thumbnail generation and recommended reducing/offloading CPU-intensive work: moving heavy lifting to external service/background job and optimizing/reducing work per call. It also explicitly discouraged retries as the fix."
}
],
"skills": {
@@ -424,14 +288,14 @@
"url": "https://supabase.com/docs/guides/troubleshooting/edge-function-wall-clock-time-limit-reached-Nk38bW",
"title": "Edge Function 'wall clock time limit reached'"
},
- {
- "url": "https://supabase.com/docs/guides/troubleshooting/edge-function-shutdown-reasons-explained",
- "title": "Edge Function shutdown reasons explained"
- },
{
"url": "https://supabase.com/docs/guides/troubleshooting/edge-function-cpu-limits",
"title": "Understanding Edge Function CPU limits"
},
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/edge-function-shutdown-reasons-explained",
+ "title": "Edge Function shutdown reasons explained"
+ },
{
"url": "https://supabase.com/docs/guides/troubleshooting/edge-function-546-error-response",
"title": "546 - WORKER_RESOURCE_LIMIT Exceeded / WORKER_LIMIT Exceeded"
@@ -445,6 +309,14 @@
}
]
},
+ "usage": {
+ "inputTokens": 538323,
+ "outputTokens": 6679,
+ "cachedInputTokens": 474071,
+ "cacheCreationInputTokens": 59987,
+ "costUsd": 0.8009012499999999
+ },
+ "durationMs": 104715,
"prompt": "Our `video-thumbnails` edge function has been failing intermittently since this morning. It generates a thumbnail from a user-uploaded video, and about half the calls are erroring out.\n\nCan you investigate the project logs and tell me what's going on and what we should do about it?",
"promptSourcePath": "evals/investigate-functions-001-546-resource-limit/PROMPT.md",
"attempts": 1,
@@ -517,7 +389,7 @@
{
"name": "diagnosed secure default grants without weakening RLS",
"passed": true,
- "judgeNotes": "The answer correctly diagnoses missing Data API/base table grants under secure-by-default exposure behavior, distinguishes grants from RLS, preserves existing owner-scoped RLS, grants only SELECT and INSERT on public.journal_entries to authenticated, does not grant anon/public, and verifies RLS isolation remains intact."
+ "judgeNotes": "Diagnoses secure-by-default/raw SQL Data API grant issue, distinguishes grants from RLS, preserves existing owner-scoped RLS, grants only SELECT/INSERT on public.journal_entries to authenticated, keeps anon denied and RLS intact."
}
],
"skills": {
@@ -532,6 +404,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 764224,
+ "outputTokens": 5711,
+ "cachedInputTokens": 731138,
+ "cacheCreationInputTokens": 29240,
+ "costUsd": 0.7109979999999999
+ },
+ "durationMs": 116669,
"prompt": "Our app lets signed-in users keep a private journal. Entries are stored in the `journal_entries` table. A user should only ever see their own, and they need to be able to create new entries from the app.\n\nI can see the rows when I query the table directly, but the journal page shows an empty list for every signed-in user. New entries don't show up after saving either. Please figure out why and fix it.",
"promptSourcePath": "evals/resolve-dataapi-002-secure-default-grants/PROMPT.md",
"attempts": 1,
@@ -565,7 +445,7 @@
{
"name": "user A's update actually checks off their own task",
"passed": true,
- "notes": "saw: [{\"id\":\"548a06fc-35c7-4e10-a065-cf5e1c4431ef\",\"is_done\":true}]"
+ "notes": "saw: [{\"id\":\"cb03fd0c-c5a6-4563-b997-fe1a06ec41cf\",\"is_done\":true}]"
},
{
"name": "user B cannot update user A's task",
@@ -574,7 +454,7 @@
{
"name": "diagnosed the missing USING clause and added it",
"passed": true,
- "judgeNotes": "The assistant correctly identified the missing USING clause on the UPDATE RLS policy as the cause of silent zero-row updates, added a scoped USING ownership check for authenticated users, preserved the WITH CHECK ownership constraint, and kept RLS/ownership isolation intact."
+ "judgeNotes": "Diagnosed the missing UPDATE policy USING clause, explained WITH CHECK only validates new row values, fixed with owner-scoped USING plus retained WITH CHECK for authenticated users, kept RLS/security intact, and verified behavior."
}
],
"skills": {
@@ -590,34 +470,42 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"RLS UPDATE policy USING WITH CHECK required\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"RLS policy UPDATE USING WITH CHECK default row-level security\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
- {
- "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
- "title": "Row Level Security"
- },
{
"url": "https://supabase.com/docs/guides/troubleshooting/rls-simplified-BJTcS8",
"title": "RLS Simplified"
},
{
- "url": "https://supabase.com/docs/guides/storage/security/access-control",
- "title": "Storage Access Control"
+ "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended",
+ "title": "Advanced pgTAP Testing"
},
{
- "url": "https://supabase.com/docs/guides/realtime/reports",
- "title": "Realtime Reports"
+ "url": "https://supabase.com/docs/guides/auth/auth-anonymous",
+ "title": "Anonymous Sign-Ins"
},
{
- "url": "https://supabase.com/docs/guides/api/securing-your-api",
- "title": "Securing your API"
+ "url": "https://supabase.com/docs/guides/database/postgres/row-level-security",
+ "title": "Row Level Security"
+ },
+ {
+ "url": "https://supabase.com/docs/guides/database/postgres/column-level-security",
+ "title": "Column Level Security"
}
],
- "resultChars": 106091
+ "resultChars": 73029
}
]
},
+ "usage": {
+ "inputTokens": 1013748,
+ "outputTokens": 7470,
+ "cachedInputTokens": 959081,
+ "cacheCreationInputTokens": 50404,
+ "costUsd": 1.0033204999999998
+ },
+ "durationMs": 113129,
"prompt": "Our app lets signed-in users manage a personal `tasks` list. Users can create tasks and check them off (`is_done`).\n\nCreating a task works fine, and I can see the row in the table. But when a user checks off a task, the app's update call succeeds with no error, yet `is_done` never actually changes, and the API doesn't return the updated row either.\n\nFind out why the update has no effect and fix it.",
"promptSourcePath": "evals/resolve-dataapi-002-update-zero-rows-affected/PROMPT.md",
"attempts": 1,
@@ -646,7 +534,7 @@
{
"name": "answered unhealthy project recovery question safely",
"passed": true,
- "judgeNotes": "The answer clearly says restart is the right first step and pause/restore is not, distinguishes pause/restore from restart, and recommends concrete recovery steps like restarting, checking for resource issues, scaling/tuning, and reviewing logs/advisors. It does not mention contacting Supabase support, but overall satisfies the rubric."
+ "judgeNotes": "The answer safely says pause/restore is not the right first step, recommends restarting first, distinguishes it from pause/restore, and suggests scaling/tuning or contacting support if the project remains unhealthy."
}
],
"skills": {
@@ -662,25 +550,25 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"unhealthy project restart pause restore dashboard unusable\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"project unhealthy dashboard restart pause restore\", limit: 5) { nodes { title href content } } }",
"hasContent": true,
"pages": [
{
- "url": "https://supabase.com/docs/guides/troubleshooting/project-status-reports-unhealthy-services",
- "title": "Project Status reports unhealthy services"
+ "url": "https://supabase.com/docs/guides/platform/backups",
+ "title": "Database Backups"
},
{
"url": "https://supabase.com/docs/guides/platform/upgrading",
"title": "Upgrading"
},
- {
- "url": "https://supabase.com/docs/guides/platform/backups",
- "title": "Database Backups"
- },
{
"url": "https://supabase.com/docs/guides/platform/free-project-pausing",
"title": "Project Pausing"
},
+ {
+ "url": "https://supabase.com/docs/guides/troubleshooting/project-status-reports-unhealthy-services",
+ "title": "Project Status reports unhealthy services"
+ },
{
"url": "https://supabase.com/docs/guides/local-development/restoring-downloaded-backup",
"title": "Restoring a downloaded backup locally"
@@ -690,6 +578,14 @@
}
]
},
+ "usage": {
+ "inputTokens": 154258,
+ "outputTokens": 950,
+ "cachedInputTokens": 110906,
+ "cacheCreationInputTokens": 39381,
+ "costUsd": 0.34581525
+ },
+ "durationMs": 24123,
"prompt": "My Supabase dashboard says my project is unhealthy, and the dashboard is unusable.\n\nWould restart or pause/restore be better?",
"promptSourcePath": "evals/resolve-reliability-001-unhealthy-project-recovery/PROMPT.md",
"attempts": 1,
@@ -736,7 +632,7 @@
{
"name": "user A can replace their own avatar via upsert",
"passed": true,
- "notes": "saw: [{\"name\":\"019fb1dc-9359-7058-b603-dd8ab7fb156c/avatar.png\",\"metadata\":{\"version\":\"replacement\"}}]"
+ "notes": "saw: [{\"name\":\"019fb3d7-cf93-726e-beb4-51c20dc6f3fa/avatar.png\",\"metadata\":{\"version\":\"replacement\"}}]"
},
{
"name": "user B cannot overwrite user A's avatar",
@@ -745,7 +641,7 @@
{
"name": "added an owner-scoped UPDATE policy without weakening public reads",
"passed": true,
- "judgeNotes": "The assistant correctly diagnosed missing storage.objects UPDATE RLS for avatar upsert, explained public bucket only affects read/download behavior, kept public read/RLS intact, and added an authenticated owner-scoped UPDATE policy with both USING and WITH CHECK."
+ "judgeNotes": "Diagnosed missing storage.objects UPDATE policy for avatar upsert replacement, explained public bucket only affects read/download, kept public SELECT/RLS setup, and added authenticated owner-scoped UPDATE policy with USING and WITH CHECK."
}
],
"skills": {
@@ -760,6 +656,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 419922,
+ "outputTokens": 1987,
+ "cachedInputTokens": 372537,
+ "cacheCreationInputTokens": 43274,
+ "costUsd": 0.5276130000000001
+ },
+ "durationMs": 34084,
"prompt": "Our app has a public `avatars` bucket so profile photos have a public URL. Each user's avatar is stored at `/avatar.png`, and the app uploads it with `upsert: true` so a new photo replaces the old one at that same path.\n\nThe very first upload for a user always works, but replacing an existing avatar fails. Find out why and fix it.",
"promptSourcePath": "evals/resolve-storage-001-upsert-missing-update-policy/PROMPT.md",
"attempts": 1,
@@ -804,17 +708,17 @@
{
"name": "user with JWT reads only their own rows",
"passed": true,
- "notes": "status 200: [{\"user_id\":\"ab7cf30b-94e9-4d8a-88e5-3e1f534bd921\",\"metric\":\"steps_a_ms76gtwt\",\"value\":111}]"
+ "notes": "status 200: [{\"user_id\":\"5c263c4b-21a1-4fdd-bec2-67a93615cc3c\",\"metric\":\"steps_a_ms7q97hy\",\"value\":111}]"
},
{
"name": "user cannot read another user's rows by passing user_id",
"passed": true,
- "notes": "status 200: [{\"user_id\":\"ab7cf30b-94e9-4d8a-88e5-3e1f534bd921\",\"metric\":\"steps_a_ms76gtwt\",\"value\":111}]"
+ "notes": "status 200: [{\"user_id\":\"5c263c4b-21a1-4fdd-bec2-67a93615cc3c\",\"metric\":\"steps_a_ms7q97hy\",\"value\":111}]"
},
{
"name": "service key bypasses RLS to read the target user's rows",
"passed": true,
- "notes": "status 200: [{\"user_id\":\"b132b66f-5254-402f-95b1-145633801cdc\",\"metric\":\"steps_b_ms76gtwt\",\"value\":222}]"
+ "notes": "status 200: [{\"user_id\":\"aeb7f20a-56c2-4e2b-9ff0-d3635f80e315\",\"metric\":\"steps_b_ms7q97hy\",\"value\":222}]"
},
{
"name": "non-service key is not granted service access",
@@ -844,6 +748,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 1034992,
+ "outputTokens": 7725,
+ "cachedInputTokens": 985740,
+ "cacheCreationInputTokens": 45786,
+ "costUsd": 0.9904145
+ },
+ "durationMs": 219121,
"prompt": "Build and serve a Supabase Edge Function named `user-stats` for this project,\nreachable over HTTP at `/functions/v1/user-stats`.\n\nImplement it with the **`@supabase/server`** package, which is built for exactly\nthis kind of multi-auth Edge Function. Import it directly in your function:\n\n```ts\nimport { withSupabase } from \"npm:@supabase/server\";\n```\n\nOur product stores per-user metrics in a `user_stats` table that already exists\n(see `supabase/migrations/`), protected by row-level security so a user can read\nonly their own rows.\n\nTwo very different callers need to hit this one endpoint:\n\n1. **Our mobile app**, acting for a signed-in user. It sends that user's\n Supabase access token. The endpoint should return the user's own stats.\n\n2. **Our internal billing service**, a trusted backend with no signed-in user.\n It authenticates with the project's secret (service-role) key in the `apikey`\n header, and names the target user with a `user_id` in the JSON request body.\n It needs that user's stats.\n\nReturn the matching rows as JSON. The endpoint must be secure: only ever serve\nstats to a caller that is genuinely entitled to them, and turn away callers that\nare not.\n\nGet the local stack running so the function is reachable at the path above.",
"promptSourcePath": "evals/build-functions-006-dual-auth-with-server/PROMPT.md",
"attempts": 1,
@@ -878,7 +790,7 @@
{
"name": "did not recommend read replicas for Realtime",
"passed": true,
- "judgeNotes": "The answer correctly treats the task as Supabase Realtime/Postgres Changes setup, adds the table to the supabase_realtime publication, uses postgres_changes client subscription, and does not recommend or conflate read replicas."
+ "judgeNotes": "The answer correctly treats the issue as Supabase Realtime/Postgres Changes setup, adds the messages table to the supabase_realtime publication, verifies it, and provides a client subscription example. It does not recommend or imply read replicas are needed or useful."
}
],
"skills": {
@@ -888,6 +800,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 349167,
+ "outputTokens": 3179,
+ "cachedInputTokens": 323737,
+ "cacheCreationInputTokens": 21830,
+ "costUsd": 0.3964350000000001
+ },
+ "durationMs": 52846,
"prompt": "I'm building a simple chat app on Supabase.\n\nUsers can send messages, and I want everyone in the same room to see new\nmessages appear automatically without refreshing the page.\n\nCan you inspect the project and set up whatever Supabase needs for live updates?",
"promptSourcePath": "evals/build-realtime-001-live-chat-updates/PROMPT.md",
"attempts": 1,
@@ -916,17 +836,17 @@
{
"name": "identified video-thumbnails and the 546 resource-limit pattern",
"passed": true,
- "judgeNotes": "Identified `video-thumbnails` as affected and correctly described failures as HTTP 546 resource/CPU limit shutdowns, not 500/503 server errors."
+ "judgeNotes": "The assistant correctly identified `video-thumbnails` as the affected function and explicitly recognized failures as HTTP/status 546 due to Edge Runtime CPU/resource limit, not 500s or 503s."
},
{
"name": "attributed the 546s to CPU time exhaustion",
"passed": true,
- "judgeNotes": "The assistant explicitly attributes the 546 failures to CPU time exhaustion, citing the log shutdown reason CPUTime and cpu_time_used/cpu_time_limit at 2000ms. It distinguishes this from wall-clock time, memory, app exceptions, and unrelated errors."
+ "judgeNotes": "The assistant specifically attributes the 546 failures to CPU time exhaustion, citing log evidence including shutdown reason CPUTime and cpu_time_used/cpu_time_limit at 2000ms. It does not blame memory, wall-clock time, code exceptions, or unrelated errors."
},
{
"name": "recommended reducing/offloading CPU work as the fix",
"passed": true,
- "judgeNotes": "The assistant clearly identifies CPUTime limit as the cause and recommends moving CPU-heavy thumbnail generation out of the Edge Function to a worker/external service, or reducing work per call via downscaling/limiting input/leaner decode path. Although it also mentions retries, they are not the only proposed fix."
+ "judgeNotes": "The assistant explicitly recommends moving CPU-heavy video decoding/thumbnail generation off the Edge Function to a background/container worker, and also suggests reducing CPU work per call. It also correctly notes retries won't solve it."
}
],
"skills": {
@@ -936,6 +856,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 403359,
+ "outputTokens": 4797,
+ "cachedInputTokens": 354985,
+ "cacheCreationInputTokens": 44778,
+ "costUsd": 0.5959019999999999
+ },
+ "durationMs": 66485,
"prompt": "Our `video-thumbnails` edge function has been failing intermittently since this morning. It generates a thumbnail from a user-uploaded video, and about half the calls are erroring out.\n\nCan you investigate the project logs and tell me what's going on and what we should do about it?",
"promptSourcePath": "evals/investigate-functions-001-546-resource-limit/PROMPT.md",
"attempts": 1,
@@ -1008,7 +936,7 @@
{
"name": "diagnosed secure default grants without weakening RLS",
"passed": true,
- "judgeNotes": "Diagnoses missing Data API/table grants under secure-by-default/default privilege behavior, distinguishes grants from RLS, preserves owner-scoped RLS, grants only SELECT/INSERT on public.journal_entries to authenticated, and does not grant anon/public or weaken RLS."
+ "judgeNotes": "Diagnoses secure-by-default/missing explicit Data API grants, distinguishes grants from RLS, preserves owner-scoped RLS, grants only SELECT/INSERT on public.journal_entries to authenticated, and does not grant anon/public or disable/weaken RLS."
}
],
"skills": {
@@ -1018,6 +946,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 665066,
+ "outputTokens": 6508,
+ "cachedInputTokens": 640540,
+ "cacheCreationInputTokens": 21191,
+ "costUsd": 0.63276275
+ },
+ "durationMs": 102813,
"prompt": "Our app lets signed-in users keep a private journal. Entries are stored in the `journal_entries` table. A user should only ever see their own, and they need to be able to create new entries from the app.\n\nI can see the rows when I query the table directly, but the journal page shows an empty list for every signed-in user. New entries don't show up after saving either. Please figure out why and fix it.",
"promptSourcePath": "evals/resolve-dataapi-002-secure-default-grants/PROMPT.md",
"attempts": 1,
@@ -1051,7 +987,7 @@
{
"name": "user A's update actually checks off their own task",
"passed": true,
- "notes": "saw: [{\"id\":\"a953db77-ed22-45cf-9d05-6a11773c19f2\",\"is_done\":true}]"
+ "notes": "saw: [{\"id\":\"92e01d20-b79f-46b8-b304-06ba699f9070\",\"is_done\":true}]"
},
{
"name": "user B cannot update user A's task",
@@ -1060,7 +996,7 @@
{
"name": "diagnosed the missing USING clause and added it",
"passed": true,
- "judgeNotes": "The answer correctly identifies the missing USING clause on the UPDATE RLS policy as the cause of silent 0-row updates, explains the UPDATE USING vs WITH CHECK behavior, and fixes the policy with USING (user_id = auth.uid()) while retaining WITH CHECK (user_id = auth.uid()) scoped to authenticated ownership. It does not disable RLS or broaden access."
+ "judgeNotes": "Diagnoses the missing UPDATE policy USING clause as the cause of silent zero-row updates, explains WITH CHECK vs USING semantics, and fixes the authenticated owner-scoped policy with USING (user_id = auth.uid()) while retaining WITH CHECK (user_id = auth.uid()) and RLS."
}
],
"skills": {
@@ -1071,7 +1007,7 @@
"calls": [
{
"source": "search_docs",
- "query": "{ searchDocs(query: \"row level security policy UPDATE USING WITH CHECK default\", limit: 5) { nodes { title href content } } }",
+ "query": "{ searchDocs(query: \"RLS policy USING WITH CHECK update no rows returned\", limit: 5) { nodes { ... on Guide { title href content } } } }",
"hasContent": true,
"pages": [
{
@@ -1083,22 +1019,26 @@
"title": "Token Security and Row Level Security"
},
{
- "url": "https://supabase.com/docs/guides/troubleshooting/rls-simplified-BJTcS8",
- "title": "RLS Simplified"
+ "url": "https://supabase.com/docs/guides/api/securing-your-api",
+ "title": "Securing your API"
},
{
"url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended",
"title": "Advanced pgTAP Testing"
- },
- {
- "url": "https://supabase.com/docs/guides/api/securing-your-api",
- "title": "Securing your API"
}
],
- "resultChars": 87538
+ "resultChars": 84308
}
]
},
+ "usage": {
+ "inputTokens": 680941,
+ "outputTokens": 9062,
+ "cachedInputTokens": 644494,
+ "cacheCreationInputTokens": 32706,
+ "costUsd": 0.7725995000000002
+ },
+ "durationMs": 130701,
"prompt": "Our app lets signed-in users manage a personal `tasks` list. Users can create tasks and check them off (`is_done`).\n\nCreating a task works fine, and I can see the row in the table. But when a user checks off a task, the app's update call succeeds with no error, yet `is_done` never actually changes, and the API doesn't return the updated row either.\n\nFind out why the update has no effect and fix it.",
"promptSourcePath": "evals/resolve-dataapi-002-update-zero-rows-affected/PROMPT.md",
"attempts": 1,
@@ -1127,7 +1067,7 @@
{
"name": "answered unhealthy project recovery question safely",
"passed": true,
- "judgeNotes": "The answer clearly says pause/restore is not the right first step, distinguishes restart from restore, and recommends restarting first with log investigation if needed. It does not explicitly mention advisors/resource pressure/scaling or contacting Supabase support, but it provides concrete, safe initial recovery guidance and avoids presenting pause/restore as a reliable primary fix."
+ "judgeNotes": "Provides safe recovery guidance: says restart is the better first step, distinguishes restart/reboot from pause/restore, and warns pause/restore is heavier and not designed as a health fix. It could be stronger by mentioning logs/advisors/resource pressure/scaling and contacting support, but it includes a concrete safe first step and does not recommend pause/restore as the primary recovery path."
}
],
"skills": {
@@ -1137,9 +1077,17 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 291972,
+ "outputTokens": 3260,
+ "cachedInputTokens": 240465,
+ "cacheCreationInputTokens": 48044,
+ "costUsd": 0.5199385
+ },
+ "durationMs": 51402,
"prompt": "My Supabase dashboard says my project is unhealthy, and the dashboard is unusable.\n\nWould restart or pause/restore be better?",
"promptSourcePath": "evals/resolve-reliability-001-unhealthy-project-recovery/PROMPT.md",
- "attempts": 2,
+ "attempts": 1,
"sourcePath": "claude-code-sonnet-5-no-skills/resolve-reliability-001-unhealthy-project-recovery.json"
},
{
@@ -1183,7 +1131,7 @@
{
"name": "user A can replace their own avatar via upsert",
"passed": true,
- "notes": "saw: [{\"name\":\"019fb1dc-808e-709a-a52b-b98e3819d7fc/avatar.png\",\"metadata\":{\"version\":\"replacement\"}}]"
+ "notes": "saw: [{\"name\":\"019fb3d7-cae6-740f-8007-71776297231d/avatar.png\",\"metadata\":{\"version\":\"replacement\"}}]"
},
{
"name": "user B cannot overwrite user A's avatar",
@@ -1192,7 +1140,7 @@
{
"name": "added an owner-scoped UPDATE policy without weakening public reads",
"passed": true,
- "judgeNotes": "The answer correctly diagnoses missing UPDATE RLS policy for Supabase Storage upsert replacement, explains public bucket only covers read/download behavior, adds an authenticated owner-scoped UPDATE policy with USING and WITH CHECK, and does not weaken public-read setup or disable RLS."
+ "judgeNotes": "Diagnoses missing UPDATE RLS policy for upsert replacement, distinguishes public bucket/read from write operations, adds owner-scoped authenticated UPDATE policy with USING and WITH CHECK, and keeps public read/RLS intact."
}
],
"skills": {
@@ -1202,6 +1150,14 @@
"docs": {
"calls": []
},
+ "usage": {
+ "inputTokens": 300506,
+ "outputTokens": 1919,
+ "cachedInputTokens": 265902,
+ "cacheCreationInputTokens": 31010,
+ "costUsd": 0.3933605
+ },
+ "durationMs": 32846,
"prompt": "Our app has a public `avatars` bucket so profile photos have a public URL. Each user's avatar is stored at `/avatar.png`, and the app uploads it with `upsert: true` so a new photo replaces the old one at that same path.\n\nThe very first upload for a user always works, but replacing an existing avatar fails. Find out why and fix it.",
"promptSourcePath": "evals/resolve-storage-001-upsert-missing-update-policy/PROMPT.md",
"attempts": 1,
diff --git a/apps/web/src/lib/eval-results.test.ts b/apps/web/src/lib/eval-results.test.ts
index 67e05ed5..b01268f6 100644
--- a/apps/web/src/lib/eval-results.test.ts
+++ b/apps/web/src/lib/eval-results.test.ts
@@ -9,6 +9,7 @@ import {
getProductKeys,
getProductResults,
getVisibleExperiments,
+ runTokens,
scoreResults,
sortResults,
sortedResults,
@@ -164,6 +165,22 @@ describe("scoreResults", () => {
})
})
+describe("runTokens", () => {
+ it("prefers the harness's own total, else sums input and output", () => {
+ expect(
+ runTokens(makeResult({ usage: { totalTokens: 500, inputTokens: 400 } }))
+ ).toBe(500)
+ expect(
+ runTokens(makeResult({ usage: { inputTokens: 400, outputTokens: 50 } }))
+ ).toBe(450)
+ })
+
+ it("is undefined without token counts", () => {
+ expect(runTokens(makeResult())).toBeUndefined()
+ expect(runTokens(makeResult({ usage: { costUsd: 0.1 } }))).toBeUndefined()
+ })
+})
+
/**
* The site renders whatever `pnpm export-results` last wrote, so these guard the
* boundary between that export and the assumptions the UI makes about it.
diff --git a/apps/web/src/lib/eval-results.ts b/apps/web/src/lib/eval-results.ts
index d2b9884c..9db33546 100644
--- a/apps/web/src/lib/eval-results.ts
+++ b/apps/web/src/lib/eval-results.ts
@@ -175,3 +175,17 @@ export function scoreResults(sourceResults: ParsedResult[]) {
total: sourceResults.length,
}
}
+
+/**
+ * Total tokens a run consumed: the harness's own total when it reported one,
+ * else input + output (input already includes cache reads across harnesses).
+ */
+export function runTokens(result: ParsedResult): number | undefined {
+ const usage = result.usage
+ if (!usage) return undefined
+ if (usage.totalTokens !== undefined) return usage.totalTokens
+ if (usage.inputTokens === undefined && usage.outputTokens === undefined) {
+ return undefined
+ }
+ return (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0)
+}
diff --git a/packages/core/src/agents/claude-code/runner.test.ts b/packages/core/src/agents/claude-code/runner.test.ts
index 07450363..03f4888b 100644
--- a/packages/core/src/agents/claude-code/runner.test.ts
+++ b/packages/core/src/agents/claude-code/runner.test.ts
@@ -55,3 +55,41 @@ describe('claudeCodeRunner.deriveStopReason', () => {
expect(derive(undefined, ok)).toBe('stop');
});
});
+
+describe('claudeCodeRunner.extractUsage', () => {
+ const extract = claudeCodeRunner.extractUsage!;
+
+ it("reads the terminal result line's usage and cost", () => {
+ const raw = [
+ JSON.stringify({ type: 'system', subtype: 'init' }),
+ JSON.stringify({
+ type: 'result',
+ subtype: 'success',
+ total_cost_usd: 0.42,
+ usage: {
+ input_tokens: 10,
+ cache_creation_input_tokens: 200,
+ cache_read_input_tokens: 3000,
+ output_tokens: 40,
+ },
+ }),
+ ].join('\n');
+ expect(extract(raw)).toEqual({
+ // 10 raw + 3000 cache-read + 200 cache-creation: OpenAI-style totals
+ // so counts compare across agents.
+ inputTokens: 3210,
+ outputTokens: 40,
+ cachedInputTokens: 3000,
+ cacheCreationInputTokens: 200,
+ costUsd: 0.42,
+ });
+ });
+
+ it('returns undefined without a result line or usage fields', () => {
+ expect(extract(undefined)).toBeUndefined();
+ expect(extract('not json\n')).toBeUndefined();
+ expect(
+ extract(JSON.stringify({ type: 'result', subtype: 'success' }))
+ ).toBeUndefined();
+ });
+});
diff --git a/packages/core/src/agents/claude-code/runner.ts b/packages/core/src/agents/claude-code/runner.ts
index 37129ca1..05ba2a2a 100644
--- a/packages/core/src/agents/claude-code/runner.ts
+++ b/packages/core/src/agents/claude-code/runner.ts
@@ -7,6 +7,7 @@
import type { Model as AnthropicModel } from '@anthropic-ai/sdk/resources/messages';
import type { McpServerConfig } from '../../index.js';
import { parseJsonlRecords } from '../../json.js';
+import { anthropicUsage } from './usage.js';
import type { AgentRunner } from '../types.js';
import {
npmGlobalBin,
@@ -97,6 +98,15 @@ export const claudeCodeRunner: AgentRunner = {
if (subtype) return subtype; // e.g. error_max_turns — surface verbatim
return processStopReason(command);
},
+
+ extractUsage(raw) {
+ // The terminal `result` line carries the run's aggregate accounting:
+ // `usage: { input_tokens, cache_creation_input_tokens,
+ // cache_read_input_tokens, output_tokens }` plus `total_cost_usd`.
+ const result = lastResultEvent(raw);
+ if (!result) return undefined;
+ return anthropicUsage(result.usage, result.total_cost_usd);
+ },
};
/** Claude Code's `--mcp-config` schema: `{ mcpServers: { name: {type, command, args, env} } }`. */
diff --git a/packages/core/src/agents/claude-code/usage.ts b/packages/core/src/agents/claude-code/usage.ts
new file mode 100644
index 00000000..267ddd53
--- /dev/null
+++ b/packages/core/src/agents/claude-code/usage.ts
@@ -0,0 +1,45 @@
+/**
+ * Anthropic usage accounting for the Claude Code runner's whole-run totals
+ * (the terminal `result` line): Anthropic's `input_tokens` excludes cache
+ * reads/writes, so `inputTokens` is reported OpenAI-style (cached ⊆ input) to
+ * keep token counts comparable across agents. The cache splits stay reported
+ * separately.
+ */
+
+import type { AgentUsage } from '../../eval-metadata.js';
+import { finiteNumber, isRecord } from '../../json.js';
+
+export function anthropicUsage(
+ usage: unknown,
+ costUsd?: unknown
+): AgentUsage | undefined {
+ const fields = isRecord(usage) ? usage : undefined;
+ const rawInput = finiteNumber(fields?.input_tokens);
+ const cacheRead = finiteNumber(fields?.cache_read_input_tokens);
+ const cacheCreation = finiteNumber(fields?.cache_creation_input_tokens);
+ const outputTokens = finiteNumber(fields?.output_tokens);
+ const cost = finiteNumber(costUsd);
+
+ const hasInput =
+ rawInput !== undefined ||
+ cacheRead !== undefined ||
+ cacheCreation !== undefined;
+ if (!hasInput && outputTokens === undefined && cost === undefined) {
+ return undefined;
+ }
+
+ return {
+ ...(hasInput
+ ? {
+ inputTokens:
+ (rawInput ?? 0) + (cacheRead ?? 0) + (cacheCreation ?? 0),
+ }
+ : {}),
+ ...(outputTokens !== undefined ? { outputTokens } : {}),
+ ...(cacheRead !== undefined ? { cachedInputTokens: cacheRead } : {}),
+ ...(cacheCreation !== undefined
+ ? { cacheCreationInputTokens: cacheCreation }
+ : {}),
+ ...(cost !== undefined ? { costUsd: cost } : {}),
+ };
+}
diff --git a/packages/core/src/agents/codex/runner.test.ts b/packages/core/src/agents/codex/runner.test.ts
new file mode 100644
index 00000000..b4b49b4d
--- /dev/null
+++ b/packages/core/src/agents/codex/runner.test.ts
@@ -0,0 +1,49 @@
+import { describe, expect, it } from 'vitest';
+import { codexRunner } from './runner.js';
+
+describe('codexRunner.extractUsage', () => {
+ const extract = codexRunner.extractUsage!;
+
+ it('reads usage from turn.completed', () => {
+ const raw = [
+ JSON.stringify({ type: 'thread.started', thread_id: 't1' }),
+ JSON.stringify({
+ type: 'turn.completed',
+ usage: {
+ input_tokens: 100,
+ cached_input_tokens: 30,
+ output_tokens: 25,
+ },
+ }),
+ ].join('\n');
+ expect(extract(raw)).toEqual({
+ inputTokens: 100,
+ cachedInputTokens: 30,
+ outputTokens: 25,
+ });
+ });
+
+ it('sums usage across multiple turns', () => {
+ const raw = [
+ JSON.stringify({
+ type: 'turn.completed',
+ usage: { input_tokens: 100, cached_input_tokens: 0, output_tokens: 25 },
+ }),
+ JSON.stringify({
+ type: 'turn.completed',
+ usage: { input_tokens: 50, cached_input_tokens: 10, output_tokens: 5 },
+ }),
+ ].join('\n');
+ expect(extract(raw)).toEqual({
+ inputTokens: 150,
+ cachedInputTokens: 10,
+ outputTokens: 30,
+ });
+ });
+
+ it('returns undefined without a turn.completed usage payload', () => {
+ expect(extract(undefined)).toBeUndefined();
+ expect(extract('not json\n')).toBeUndefined();
+ expect(extract(JSON.stringify({ type: 'turn.completed' }))).toBeUndefined();
+ });
+});
diff --git a/packages/core/src/agents/codex/runner.ts b/packages/core/src/agents/codex/runner.ts
index f4e3837e..6a3fd581 100644
--- a/packages/core/src/agents/codex/runner.ts
+++ b/packages/core/src/agents/codex/runner.ts
@@ -9,7 +9,8 @@
import type { ChatModel } from 'openai/resources/shared';
import type { McpServerConfig } from '../../index.js';
-import { parseJsonlRecords } from '../../json.js';
+import type { AgentUsage } from '../../eval-metadata.js';
+import { finiteNumber, isRecord, parseJsonlRecords } from '../../json.js';
import type { AgentRunner } from '../types.js';
import {
npmGlobalBin,
@@ -115,6 +116,28 @@ export const codexRunner: AgentRunner = {
return processStopReason(command);
}
},
+
+ extractUsage(raw) {
+ // Each `turn.completed` carries `usage: { input_tokens,
+ // cached_input_tokens, output_tokens }`. `codex exec` runs a single turn,
+ // but sum across all of them to stay correct if that ever changes.
+ if (!raw) return undefined;
+ const { records } = parseJsonlRecords(raw);
+ let sawUsage = false;
+ let inputTokens = 0;
+ let cachedInputTokens = 0;
+ let outputTokens = 0;
+ for (const record of records) {
+ if (record.type !== 'turn.completed' || !isRecord(record.usage)) continue;
+ sawUsage = true;
+ inputTokens += finiteNumber(record.usage.input_tokens) ?? 0;
+ cachedInputTokens += finiteNumber(record.usage.cached_input_tokens) ?? 0;
+ outputTokens += finiteNumber(record.usage.output_tokens) ?? 0;
+ }
+ if (!sawUsage) return undefined;
+ const usage: AgentUsage = { inputTokens, cachedInputTokens, outputTokens };
+ return usage;
+ },
};
/** The last turn-level outcome in a `codex exec --json` stream, if any. */
diff --git a/packages/core/src/agents/engine.ts b/packages/core/src/agents/engine.ts
index de61c1fa..e10fda77 100644
--- a/packages/core/src/agents/engine.ts
+++ b/packages/core/src/agents/engine.ts
@@ -122,6 +122,8 @@ export function createCliAgent(
);
}
+ const usage = runner.extractUsage?.(raw);
+
return {
// The final report is the transcript's closing assistant message — the
// CLI's stdout is JSONL, not prose.
@@ -131,6 +133,7 @@ export function createCliAgent(
steps: adapted.steps,
stoppedReason:
runner.deriveStopReason?.(raw, command) ?? processStopReason(command),
+ ...(usage ? { usage } : {}),
};
},
};
diff --git a/packages/core/src/agents/opencode/runner.test.ts b/packages/core/src/agents/opencode/runner.test.ts
index 13a5b3af..45cd0877 100644
--- a/packages/core/src/agents/opencode/runner.test.ts
+++ b/packages/core/src/agents/opencode/runner.test.ts
@@ -83,6 +83,78 @@ describe('opencode runner', () => {
});
});
+describe('opencode runner extractUsage', () => {
+ const extract = createOpencodeRunner('anthropic/claude-sonnet-5')
+ .extractUsage!;
+
+ it('sums step_finish tokens and cost across steps', () => {
+ const raw = [
+ JSON.stringify({
+ type: 'step_finish',
+ part: {
+ type: 'step-finish',
+ reason: 'tool-calls',
+ cost: 0.01,
+ tokens: {
+ input: 100,
+ output: 20,
+ reasoning: 5,
+ cache: { read: 40, write: 10 },
+ },
+ },
+ }),
+ JSON.stringify({ type: 'text', part: { type: 'text', text: 'Done.' } }),
+ JSON.stringify({
+ type: 'step_finish',
+ part: {
+ type: 'step-finish',
+ reason: 'stop',
+ cost: 0.02,
+ tokens: { input: 200, output: 30, reasoning: 0, cache: { read: 90 } },
+ },
+ }),
+ ].join('\n');
+ expect(extract(raw)).toEqual({
+ inputTokens: 300,
+ outputTokens: 50,
+ reasoningTokens: 5,
+ cachedInputTokens: 130,
+ costUsd: 0.03,
+ });
+ });
+
+ it('omits a zero cost total (unknown pricing) but keeps token counts', () => {
+ const raw = JSON.stringify({
+ type: 'step_finish',
+ part: {
+ type: 'step-finish',
+ reason: 'stop',
+ cost: 0,
+ tokens: { input: 10, output: 2, reasoning: 0, cache: { read: 0 } },
+ },
+ });
+ expect(extract(raw)).toEqual({
+ inputTokens: 10,
+ outputTokens: 2,
+ reasoningTokens: 0,
+ cachedInputTokens: 0,
+ });
+ });
+
+ it('returns undefined without step_finish token payloads', () => {
+ expect(extract(undefined)).toBeUndefined();
+ expect(extract('not json\n')).toBeUndefined();
+ expect(
+ extract(
+ JSON.stringify({
+ type: 'step_finish',
+ part: { type: 'step-finish', reason: 'stop' },
+ })
+ )
+ ).toBeUndefined();
+ });
+});
+
/** Capture the `--model` flag, run env, and written config from one exec. */
async function captureExec(
model: string,
diff --git a/packages/core/src/agents/opencode/runner.ts b/packages/core/src/agents/opencode/runner.ts
index b7b437d9..dcc78cd7 100644
--- a/packages/core/src/agents/opencode/runner.ts
+++ b/packages/core/src/agents/opencode/runner.ts
@@ -26,8 +26,9 @@
import type { Config, McpLocalConfig } from '@opencode-ai/sdk';
import type { McpServerConfig } from '../../index.js';
import type { ModelProvider } from '../../eval-metadata.js';
+import type { AgentUsage } from '../../eval-metadata.js';
import { modelProviderSchema } from '../../eval-metadata.js';
-import { isRecord, parseJsonlRecords } from '../../json.js';
+import { finiteNumber, isRecord, parseJsonlRecords } from '../../json.js';
import type { AgentRunner } from '../types.js';
import {
SCRATCH,
@@ -181,6 +182,46 @@ export function createOpencodeRunner(
}
return processStopReason(command);
},
+
+ extractUsage(raw) {
+ // Each `step_finish` (one LLM call) carries `part.tokens: { input,
+ // output, reasoning, cache: { read, write } }` and a per-step `cost`.
+ // Sum across steps. opencode's `input` already includes cache reads
+ // (AI SDK convention), so it maps straight onto `inputTokens`.
+ if (!raw) return undefined;
+ const { records } = parseJsonlRecords(raw);
+ let sawUsage = false;
+ let inputTokens = 0;
+ let outputTokens = 0;
+ let reasoningTokens = 0;
+ let cachedInputTokens = 0;
+ let costUsd: number | undefined;
+ for (const record of records) {
+ if (record.type !== 'step_finish' || !isRecord(record.part)) continue;
+ const part = record.part;
+ const cost = finiteNumber(part.cost);
+ if (cost !== undefined) costUsd = (costUsd ?? 0) + cost;
+ if (!isRecord(part.tokens)) continue;
+ sawUsage = true;
+ inputTokens += finiteNumber(part.tokens.input) ?? 0;
+ outputTokens += finiteNumber(part.tokens.output) ?? 0;
+ reasoningTokens += finiteNumber(part.tokens.reasoning) ?? 0;
+ const cache = isRecord(part.tokens.cache)
+ ? part.tokens.cache
+ : undefined;
+ cachedInputTokens += finiteNumber(cache?.read) ?? 0;
+ }
+ if (!sawUsage && costUsd === undefined) return undefined;
+ const usage: AgentUsage = {
+ ...(sawUsage
+ ? { inputTokens, outputTokens, reasoningTokens, cachedInputTokens }
+ : {}),
+ // opencode prices runs from its models.dev catalog; 0 means "unknown"
+ // for gateway models, so only a positive total is trustworthy.
+ ...(costUsd ? { costUsd } : {}),
+ };
+ return usage;
+ },
};
}
diff --git a/packages/core/src/agents/types.ts b/packages/core/src/agents/types.ts
index baf91962..6a320f68 100644
--- a/packages/core/src/agents/types.ts
+++ b/packages/core/src/agents/types.ts
@@ -14,6 +14,7 @@
import type { CommandResult, McpServerConfig } from '../index.js';
import type {
AgentHarnessId,
+ AgentUsage,
ModelProvider,
ReasoningEffortLevel,
} from '../eval-metadata.js';
@@ -107,6 +108,11 @@ export interface AgentRunner {
* result. Falls back to a process-exit-based reason when omitted.
*/
deriveStopReason?(raw: string | undefined, command: CommandResult): string;
+ /**
+ * Optional: whole-run token/cost usage from the raw transcript's own
+ * accounting events. Undefined when the transcript doesn't carry any.
+ */
+ extractUsage?(raw: string | undefined): AgentUsage | undefined;
}
/**
diff --git a/packages/core/src/eval-metadata.ts b/packages/core/src/eval-metadata.ts
index 59a645cf..c92177b0 100644
--- a/packages/core/src/eval-metadata.ts
+++ b/packages/core/src/eval-metadata.ts
@@ -222,6 +222,26 @@ export const evalFrontmatterSchema = z.preprocess((raw) => {
};
}, evalMetadataSchema);
+/**
+ * Whole-run token/cost accounting, normalized across harnesses. Every field
+ * is optional — each harness reports what its transcript actually carries.
+ * `inputTokens` is reported OpenAI-style (cache reads/writes ⊆ input) so
+ * token counts stay comparable across agents.
+ */
+export const agentUsageSchema = z.object({
+ inputTokens: z.number().optional(),
+ outputTokens: z.number().optional(),
+ /** Prompt tokens served from cache (cache reads). */
+ cachedInputTokens: z.number().optional(),
+ /** Prompt tokens written to cache (Anthropic only). */
+ cacheCreationInputTokens: z.number().optional(),
+ reasoningTokens: z.number().optional(),
+ totalTokens: z.number().optional(),
+ /** Run cost in USD, when the harness reports one. */
+ costUsd: z.number().optional(),
+});
+export type AgentUsage = z.infer;
+
export const checkResultSchema = z.object({
name: z.string(),
passed: z.boolean(),
@@ -311,6 +331,10 @@ const evalResultShape = {
attempts: z.number().optional(),
skills: skillResultSchema.optional(),
docs: docsResultSchema.optional(),
+ // Performance metrics: the scoring attempt's agent token/cost accounting
+ // and wall-clock agent time, when the harness reports them.
+ usage: agentUsageSchema.optional(),
+ durationMs: z.number().optional(),
};
// Raw result files may carry extra fields we don't model; tolerate them.
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index af04d674..adeff72d 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -35,6 +35,7 @@ import {
} from '@supabase-evals/platform-lite';
import type {
AgentHarnessId,
+ AgentUsage,
CheckResult,
EvalSuite,
ExperimentDisplayMetadata,
@@ -44,7 +45,7 @@ import type {
} from './eval-metadata.js';
import { reasoningEffortSchema } from './eval-metadata.js';
import type { AgentMetadata, AgentSandbox } from './agents/types.js';
-import { isRecord } from './json.js';
+import { finiteNumber, isRecord } from './json.js';
// Resolved lazily on first use, not at module load: `import.meta.resolve` is a
// load-time side effect that throws under bundler SSR transforms (e.g. vitest),
@@ -124,6 +125,7 @@ export type {
} from './transcript/types.js';
export type {
AgentHarnessId,
+ AgentUsage,
CheckResult,
EvalInterface,
EvalMetadata,
@@ -379,6 +381,7 @@ export type AgentRunResult = {
transcript: TranscriptPart[];
steps: number;
stoppedReason: string;
+ usage?: AgentUsage;
};
export type AgentHarness = {
@@ -722,6 +725,27 @@ export function aiSdkAgent(options: {
const agentReport = result.text.trim();
+ // Whole-run accounting summed across steps by the AI SDK. Fields the
+ // provider didn't report come back undefined and stay omitted.
+ const totalUsage = result.totalUsage;
+ const usage: AgentUsage = {
+ ...(finiteNumber(totalUsage.inputTokens) !== undefined
+ ? { inputTokens: totalUsage.inputTokens }
+ : {}),
+ ...(finiteNumber(totalUsage.outputTokens) !== undefined
+ ? { outputTokens: totalUsage.outputTokens }
+ : {}),
+ ...(finiteNumber(totalUsage.cachedInputTokens) !== undefined
+ ? { cachedInputTokens: totalUsage.cachedInputTokens }
+ : {}),
+ ...(finiteNumber(totalUsage.reasoningTokens) !== undefined
+ ? { reasoningTokens: totalUsage.reasoningTokens }
+ : {}),
+ ...(finiteNumber(totalUsage.totalTokens) !== undefined
+ ? { totalTokens: totalUsage.totalTokens }
+ : {}),
+ };
+
return {
agentReport,
toolCalls,
@@ -731,6 +755,7 @@ export function aiSdkAgent(options: {
result.steps.length >= MAX_STEPS
? 'max_steps'
: result.finishReason,
+ ...(Object.keys(usage).length > 0 ? { usage } : {}),
};
} finally {
await closeMcpHandles(mcpHandles);
diff --git a/packages/core/src/json.ts b/packages/core/src/json.ts
index b8da5d0d..26c28023 100644
--- a/packages/core/src/json.ts
+++ b/packages/core/src/json.ts
@@ -4,6 +4,13 @@ export function isRecord(value: unknown): value is Record {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
+/** The value if it is a finite number, else undefined. */
+export function finiteNumber(value: unknown): number | undefined {
+ return typeof value === 'number' && Number.isFinite(value)
+ ? value
+ : undefined;
+}
+
export interface JsonlRecords {
records: Record[];
errors: string[];