diff --git a/apps/web/src/data/eval-results.json b/apps/web/src/data/eval-results.json index 5b28a57e..e45abc5a 100644 --- a/apps/web/src/data/eval-results.json +++ b/apps/web/src/data/eval-results.json @@ -60,32 +60,21 @@ "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, + "source": "shell_fetch", + "query": "curl -s --max-time 25 https://supabase.com/changelog.md | head -60", "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 + "resultChars": 3161 } ] }, @@ -143,32 +132,7 @@ ] }, "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": [] }, "prompt": "Add a description text column to the `products` table in my local Supabase stack", "promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md", @@ -208,12 +172,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 11) from the queue" } ], "skills": { @@ -222,71 +186,94 @@ "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: \"cron job send message to queue pgmq schedule\", limit: 5) { 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/ai/automatic-embeddings", + "title": "Automatic embeddings" }, { - "url": "https://supabase.com/docs/guides/queues/expose-self-hosted-queues", - "title": "Expose Queues for local and self-hosted Supabase" + "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" } ], - "resultChars": 39340 + "resultChars": 72607 }, { - "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.", + "source": "search_docs", + "query": "{ searchDocs(query: \"Queues API read delete messages edge function supabase-js pgmq_public\", limit: 5) { nodes { title href content } } }", "hasContent": true, "pages": [ { - "url": "https://supabase.com/docs/guides/cron/quickstart.md" + "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/api", + "title": "API" + }, + { + "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/functions/connect-to-postgres", + "title": "Integrating with Supabase Database (Postgres)" } ], - "resultChars": 1475 + "resultChars": 26472 }, { - "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.", + "source": "search_docs", + "query": "{ searchDocs(query: \"Supabase Cron quickstart create job schedule syntax unschedule\", limit: 2) { nodes { title href content } } }", "hasContent": true, "pages": [ { - "url": "https://supabase.com/changelog.md" + "url": "https://supabase.com/docs/guides/cron/quickstart", + "title": "Quickstart" + }, + { + "url": "https://supabase.com/docs/guides/cron", + "title": "Cron" } ], - "resultChars": 8295 + "resultChars": 10735 }, { "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.", + "query": "List any entries tagged breaking-change or notable changes related to: Queues/pgmq, pg_cron/Supabase Cron, Edge Functions runtime env vars or API keys (publishable/secret vs anon/service_role). Include dates and links.", "hasContent": true, "pages": [ { - "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/changelog.md" } ], - "resultChars": 659 + "resultChars": 1273 } ] }, @@ -343,20 +330,17 @@ "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 } } }", + "query": "{ searchDocs(query: \"restore pg_dump custom format binary 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" @@ -369,38 +353,31 @@ "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-within-supabase/backup-restore", + "title": "Backup and Restore using the CLI" + }, { "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" + "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres", + "title": "Migrate from Postgres to Supabase" } ], "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.", + "query": "Extract the exact recommended commands and flags for restoring a Postgres dump into Supabase using pg_restore or psql. Include any notes about roles, ownership, --no-owner, --no-privileges, --clean, excluding schemas, disabling triggers, the auth/storage schemas, and any pre/post restore SQL steps.", "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 + "resultChars": 1484 } ] }, @@ -470,36 +447,7 @@ ] }, "docs": { - "calls": [ - { - "source": "search_docs", - "query": "{searchDocs(query:\"Edge Function auth user JWT createClient Authorization header RLS\", 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/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/auth/choosing-a-server-package", - "title": "Which package to use" - }, - { - "url": "https://supabase.com/docs/guides/functions/error-codes", - "title": "Error codes" - } - ], - "resultChars": 65767 - } - ] + "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", @@ -545,17 +493,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\":\"a0ff8c68-b892-4ea5-aa53-6f8bc45537d8\",\"metric\":\"steps_a_msgjccr3\",\"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\":\"a0ff8c68-b892-4ea5-aa53-6f8bc45537d8\",\"metric\":\"steps_a_msgjccr3\",\"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\":\"4b299a37-5f8a-42a5-b10f-6539753c3895\",\"metric\":\"steps_b_msgjccr3\",\"value\":222}]" }, { "name": "non-service key is not granted service access", @@ -589,75 +537,71 @@ }, "docs": { "calls": [ + { + "source": "shell_fetch", + "query": "curl -s https://supabase.com/changelog.md 2>&1 | head -80", + "pages": [ + { + "url": "https://supabase.com/changelog.md" + } + ], + "resultChars": 4557 + }, { "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: \"edge function authentication service role key user JWT verify_jwt\", limit: 8) { 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/functions/auth-headers", - "title": "Authorization headers" + "url": "https://supabase.com/docs/guides/getting-started/api-keys", + "title": "Understanding API keys" }, { - "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions", - "title": "Self-Hosted Functions" + "url": "https://supabase.com/docs/guides/auth/signing-keys", + "title": "JWT Signing Keys" }, { - "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/auth/signing-keys", - "title": "JWT Signing 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-legacy-jwt", "title": "Integrating With Supabase Auth" - } - ], - "resultChars": 62524 - }, - { - "source": "search_docs", - "query": "{ searchDocs(query: \"@supabase/server package secret key publishable key API keys\", limit: 6) { 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-functions", + "title": "Self-Hosted Functions" }, { "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/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/functions/error-codes", + "title": "Error codes" + } + ], + "resultChars": 93439 + }, + { + "source": "shell_fetch", + "query": "cd /tmp && curl -s https://supabase.com/docs/guides/functions/auth-headers.md | head -120", + "pages": [ { - "url": "https://supabase.com/docs/guides/api/creating-routes", - "title": "Creating API Routes" + "url": "https://supabase.com/docs/guides/functions/auth-headers.md" } ], - "resultChars": 85604 + "resultChars": 3375 } ] }, "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 +642,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: 019fd388-00cf-710e-b634-8da49723c499/receipt-alpha.pdf, 019fd388-00cf-710e-b634-8da49723c499/receipt-beta.pdf" }, { "name": "user B cannot read user A files", @@ -719,7 +663,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": "The answer creates a private user-files bucket, keeps storage.objects RLS, defines authenticated SELECT and INSERT policies scoped to bucket_id and the user's own top-level folder via storage.foldername(name)[1] = auth.uid()::text, and provides supabase-js createSignedUrl/createSignedUrls code with expiry for temporary sharing. It does not make the bucket public, use getPublicUrl, disable RLS, use permissive policies, or expose service role client-side." } ], "skills": { @@ -733,9 +677,20 @@ }, "docs": { "calls": [ + { + "source": "web_fetch", + "query": "List any entries tagged breaking-change, and any entries related to Storage (buckets, bucket types, RLS policies on storage.objects, signed URLs) or storage access control. Include dates and links.", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/changelog.md" + } + ], + "resultChars": 3847 + }, { "source": "search_docs", - "query": "{ searchDocs(query: \"storage RLS policies private bucket user folder auth.uid\", limit: 6) { nodes { title href content } } }", + "query": "{ searchDocs(query: \"storage RLS policies restrict users to own folder user id path\", limit: 6) { nodes { title href content } } }", "hasContent": true, "pages": [ { @@ -743,47 +698,48 @@ "title": "Storage Helper Functions" }, { - "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals", - "title": "Storage Buckets" + "url": "https://supabase.com/docs/guides/resources/glossary", + "title": "Glossary" }, { - "url": "https://supabase.com/docs/guides/storage/security/access-control", - "title": "Storage Access Control" + "url": "https://supabase.com/docs/guides/storage/security/ownership", + "title": "Ownership" }, { - "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3", - "title": "Configure S3 Storage" + "url": "https://supabase.com/docs/guides/storage/security/access-control", + "title": "Storage Access Control" }, { - "url": "https://supabase.com/docs/guides/local-development/database-migrations", - "title": "Database migrations" + "url": "https://supabase.com/docs/guides/database/postgres/column-level-security", + "title": "Column Level Security" }, { - "url": "https://supabase.com/docs/guides/security/product-security", - "title": "Secure configuration of Supabase products" + "url": "https://supabase.com/docs/guides/auth/third-party/clerk", + "title": "Clerk" } ], - "resultChars": 36724 + "resultChars": 32092 }, { "source": "search_docs", - "query": "{ searchDocs(query: \"createSignedUrl expiresIn temporary link download private bucket\", limit: 4) { nodes { title href content } } }", + "query": "{ searchDocs(query: \"createSignedUrl expiring temporary link share file\", limit: 4) { nodes { title href content } } }", "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/reference/javascript/file-buckets-createsignedurls" + "url": "https://supabase.com/docs/reference/csharp/storage-from-createsignedurl", + "title": "From().CreateSignedUrl()" } ], - "resultChars": 3116 + "resultChars": 3099 } ] }, @@ -817,17 +773,17 @@ { "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": "1 file(s): supabase/tests/tenant_isolation.test.sql" }, { "name": "pgTAP isolation tests ran and pass", "passed": true, - "notes": "7 passed, 5 failed" + "notes": "13 passed, 10 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: 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": "The agent correctly identifies `posts` as having the broken tenant isolation policy: authenticated members can read posts from orgs they do not belong to. It explicitly grounds this in pgTAP results (tests 6–8) and contrasts `posts` with `notes`, stating `notes` passed isolation tests and its policy is written correctly. It also treats the test failures as real defects rather than dismissing them." } ], "skills": { @@ -836,7 +792,8 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" ] }, "docs": { @@ -878,12 +835,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", @@ -913,12 +870,6 @@ }, "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 } } }", @@ -950,10 +901,86 @@ } ], "resultChars": 84107 - } - ] - }, - "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.", + }, + { + "source": "shell_fetch", + "query": "curl -s https://supabase.com/changelog.md | head -c 4000", + "pages": [ + { + "url": "https://supabase.com/changelog.md" + } + ], + "resultChars": 3973 + }, + { + "source": "web_fetch", + "query": "Extract VERBATIM all SQL code blocks and all statements about: gte-small embedding dimensions (384?), normalize:true option, create table with vector(N) column, HNSW index SQL and operator class choice (vector_ip_ops vs vector_cosine_ops vs vector_l2_ops), the match function (match_document_sections or similar) including whether it is security invoker or security definer, its set search_path, its language (sql/plpgsql), and how it orders and limits results. Also any note about inner product negation/sign. Quote SQL exactly.", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/ai/semantic-search.md" + } + ], + "resultChars": 1708 + }, + { + "source": "web_fetch", + "query": "Extract VERBATIM all SQL code blocks. Especially: create table statements with vector(N) columns, the recommended dimension for gte-small, any match/similarity search function SQL (security invoker/definer, set search_path, language, order by, limit), and any discussion of distance operators <->, <=>, <#> and normalized embeddings / inner product negation.", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/ai/vector-columns.md" + } + ], + "resultChars": 1343 + }, + { + "source": "web_fetch", + "query": "Extract VERBATIM all SQL code blocks for creating HNSW indexes, including all operator classes (vector_l2_ops, vector_ip_ops, vector_cosine_ops) and their matching distance operators. Quote any statement about which to use for normalized embeddings, inner product sign/negation, and index parameters m and ef_construction.", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/ai/vector-indexes/hnsw-indexes.md" + } + ], + "resultChars": 1164 + }, + { + "source": "web_fetch", + "query": "Extract VERBATIM all SQL code blocks and all statements about: RLS with pgvector semantic search, the match_document_sections function (full SQL verbatim, noting security invoker vs security definer, set search_path, language, order by, limit), RLS policies on documents and document_sections tables (especially the child-table policy referencing parent documents.owner_id), and any warnings about how RLS filtering interacts with vector index usage or match_count/limit.", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/ai/rag-with-permissions.md" + } + ], + "resultChars": 1699 + }, + { + "source": "web_fetch", + "query": "Quote verbatim the section \"Filtering with HNSW indexes\" (or any text about filtering, RLS, iterative index scans, hnsw.iterative_scan, ef_search, returning fewer rows than the limit / match_count). Also quote verbatim any text about the index parameters m and ef_construction and about which operator class to use for normalized embeddings or inner product.", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/ai/vector-indexes/hnsw-indexes.md" + } + ], + "resultChars": 1221 + }, + { + "source": "web_fetch", + "query": "Reproduce verbatim, exactly as written, every ```sql code block in the \"Filtering with HNSW indexes\" / iterative scan portion of the page, including any `set hnsw.iterative_scan`, `set hnsw.max_scan_tuples`, `set hnsw.scan_mem_multiplier`, `set hnsw.ef_search` statements. Also reproduce verbatim the sentences immediately around them. Do not summarize; copy exact text.", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/ai/vector-indexes/hnsw-indexes.md" + } + ], + "resultChars": 510 + } + ] + }, + "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": "claude-code-opus-5/build-vectors-001-rag-with-permissions.json" @@ -985,12 +1012,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 rubric requirements: Supabase HTTPS scrape uses the required metrics path, Basic Auth with password_file, a concrete supabase.co project target, preserves the app job, and docker-compose mounts the secrets directory containing the password file path." }, { "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 Secret API key creation, matching password_file path under observability/secrets, Compose up/reload steps, and concrete verification via Prometheus targets/API queries, PromQL, and direct endpoint curl. Auth and endpoint match the config and no real secret is hardcoded." } ], "skills": { @@ -1006,31 +1033,27 @@ "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 } ] }, @@ -1092,55 +1115,41 @@ "calls": [ { "source": "search_docs", - "query": "{ searchDocs(query: \"Edge Function secrets environment variables manage\", limit: 6) { nodes { title href content } } }", + "query": "{ searchDocs(query: \"edge function environment variables 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/troubleshooting/inspecting-edge-function-environment-variables-wg5qOQ", + "title": "Inspecting edge function 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/functions/secrets", + "title": "Environment Variables" }, { - "url": "https://supabase.com/docs/guides/database/secure-data", - "title": "Securing your data" + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions", + "title": "Self-Hosted Functions" }, { "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" } ], - "resultChars": 65698 + "resultChars": 62245 }, { - "source": "search_docs", - "query": "{ searchDocs(query: \"config.toml edge_runtime.secrets env() local development\", limit: 3) { nodes { title href content } } }", - "hasContent": true, + "source": "shell_fetch", + "query": "curl -s https://supabase.com/changelog.md 2>&1 | grep -i \"breaking\\|edge function\\|secret\" | head -30", "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": 5543 } ] }, @@ -1199,19 +1208,7 @@ ] }, "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": [] }, "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", @@ -1269,7 +1266,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": "Meets all rubric requirements: identifies soft-delete-only root cause, implements real session/refresh revocation and auth-user disablement/backfill, adds DB-state RLS to close the Data API stale-JWT window, explains remaining stateless JWT validity for local/server-side validation and mitigations, and correctly distinguishes publishable frontend keys from secret/service_role backend-only keys that bypass RLS." } ], "skills": { @@ -1284,508 +1281,86 @@ "docs": { "calls": [ { - "source": "search_docs", - "query": "{ searchDocs(query: \"delete user account revoke sessions invalidate access token\", limit: 6) { nodes { title href content } } }", - "hasContent": true, + "source": "shell_fetch", + "query": "curl -s https://supabase.com/changelog.md | head -60", "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/resources/glossary", - "title": "Glossary" + "url": "https://supabase.com/changelog.md" } ], - "resultChars": 86320 + "resultChars": 3161 }, { "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 legacy anon service_role API keys migration RLS\", 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/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/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/auth/quickstarts/with-expo-react-native-social-auth", + "title": "Build a Social Auth App with Expo React Native" }, { - "url": "https://supabase.com/docs/guides/integrations/supabase-for-platforms", - "title": "Supabase for Platforms" + "url": "https://supabase.com/docs/guides/auth/signing-keys", + "title": "JWT Signing Keys" }, { - "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-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" } ], - "resultChars": 166856 + "resultChars": 195336 }, { - "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.", - "hasContent": true, + "source": "shell_fetch", + "query": "cd /tmp && for p in guides/api/api-keys guides/api/securing-your-api; do echo \"=== $p ===\"; curl -s \"https://supabase.com/docs/$p.md\" | head -160; done", "pages": [ { - "url": "https://supabase.com/docs/guides/api/api-keys.md" + "url": "https://supabase.com/docs/$p.md" } ], - "resultChars": 3025 + "resultChars": 8730 }, { - "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.", - "hasContent": true, + "source": "shell_fetch", + "query": "cd /tmp && curl -s \"https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys.md\" | sed -n 1,90p", "pages": [ { "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys.md" } ], - "resultChars": 4100 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/auth/users.md" - } - ], - "resultChars": 593 - }, - { - "source": "web_fetch", - "query": "Extract the full reference docs for auth.admin.deleteUser: signature, parameters (including shouldSoftDelete), notes/caveats verbatim.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/reference/javascript/auth-admin-deleteuser.md" - } - ], - "resultChars": 215 - }, - { - "source": "web_fetch", - "query": "Extract the full reference docs for auth.admin.deleteUser: signature, parameters (including shouldSoftDelete), notes/caveats verbatim.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/reference/javascript/auth-admin-deleteuser" - } - ], - "resultChars": 706 - }, - { - "source": "web_fetch", - "query": "Extract full reference docs for auth.admin.signOut: signature, parameters, the scope options (global, local, others), and all notes verbatim.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/reference/javascript/auth-admin-signout" - } - ], - "resultChars": 928 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/getting-started/api-keys.md" - } - ], - "resultChars": 2479 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/changelog.md" - } - ], - "resultChars": 1334 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/local-development/cli/config.md" - } - ], - "resultChars": 215 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/cli/config.md" - } - ], - "resultChars": 215 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/getting-started/api-keys.md" - } - ], - "resultChars": 1599 + "resultChars": 5143 }, { - "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.", - "hasContent": true, + "source": "shell_fetch", + "query": "cd /tmp && curl -s \"https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys.md\" | sed -n 90,200p", "pages": [ { - "url": "https://supabase.com/docs/guides/local-development/cli/config" + "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys.md" } ], - "resultChars": 899 + "resultChars": 6532 }, { - "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.", - "hasContent": true, + "source": "shell_fetch", + "query": "cd /tmp && curl -s \"https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys.md\" | sed -n 200,280p", "pages": [ { - "url": "https://supabase.com/docs/guides/auth/managing-user-data.md" + "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys.md" } ], - "resultChars": 534 - }, - { - "source": "web_search", - "query": "Supabase changelog publishable secret API keys general availability legacy anon service_role deprecation 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/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/changelog?next=Y3Vyc29yOnYyOpK0MjAyNC0wOS0xM1QxNTowMDoyOVrOAG2JYw%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/database/secure-data", - "title": "Securing your data | Supabase Docs" - }, - { - "url": "https://supabase.com/docs/guides/api/creating-routes", - "title": "Creating API Routes | Supabase Docs" - } - ], - "resultChars": 2967 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/changelog.md" - } - ], - "resultChars": 1335 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/changelog/29260-upcoming-changes-to-supabase-api-keys" - } - ], - "resultChars": 215 - }, - { - "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, - "pages": [ - { - "url": "https://supabase.com/docs/guides/auth/jwts.md" - } - ], - "resultChars": 911 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/database/postgres/row-level-security.md" - } - ], - "resultChars": 1591 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/auth/jwt-fields.md" - } - ], - "resultChars": 530 - }, - { - "source": "web_search", - "query": "site:supabase.com/changelog sb_publishable secret API keys", - "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/changelog/29289-supabase-auth-asymmetric-keys-support-in-2025", - "title": "Supabase Auth: Asymmetric Keys support in 2025 · Changelog" - }, - { - "url": "https://supabase.com/changelog/46458-passkeys-for-supabase-auth-beta", - "title": "Passkeys for Supabase Auth (Beta) · Changelog" - }, - { - "url": "https://supabase.com/changelog/43465-developer-update-march-2026", - "title": "Developer Update - March 2026 · Changelog" - }, - { - "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/changelog/45702-developer-update-may-2026", - "title": "Developer Update - May 2026 · Changelog" - }, - { - "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/changelog/46346-feature-preview-temporary-token-based-database-access", - "title": "Feature Preview: Temporary token-based database access · Changelog" - } - ], - "resultChars": 2996 - }, - { - "source": "search_docs", - "query": "{ searchDocs(query: \"delete user account revoke sessions sign out all devices\", limit: 8) { nodes { title href content } } }", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/auth/passkeys", - "title": "Passkey authentication" - }, - { - "url": "https://supabase.com/docs/reference/javascript/auth-signout" - }, - { - "url": "https://supabase.com/docs/reference/javascript/auth-admin-signout" - }, - { - "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/auth/auth-email-passwordless", - "title": "Passwordless email logins" - }, - { - "url": "https://supabase.com/docs/reference/swift/auth-signout", - "title": "signOut()" - }, - { - "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers", - "title": "Multiple SSO Providers" - } - ], - "resultChars": 55523 - }, - { - "source": "search_docs", - "query": "{ searchDocs(query: \"ban user banned_until block user access token\", limit: 8) { nodes { title href } } }", - "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/auth-anonymous", - "title": "Anonymous Sign-Ins" - }, - { - "url": "https://supabase.com/docs/guides/auth/sessions", - "title": "User sessions" - } - ], - "resultChars": 582 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/changelog/29260-upcoming-changes-to-supabase-api-keys" - } - ], - "resultChars": 215 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/auth/debugging/error-codes.md" - } - ], - "resultChars": 1077 - }, - { - "source": "web_fetch", - "query": "Quote the attributes list for updateUserById, especially ban_duration - its type, description, and accepted values (e.g. 'none', '24h').", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/reference/javascript/auth-admin-updateuserbyid" - } - ], - "resultChars": 843 - }, - { - "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).", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/auth/server-side/nextjs.md" - } - ], - "resultChars": 1190 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/reference/javascript/auth-getclaims" - } - ], - "resultChars": 907 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/functions/auth-headers.md" - } - ], - "resultChars": 1519 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/api/securing-your-api.md" - } - ], - "resultChars": 1341 - }, - { - "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.", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/getting-started/api-keys.md" - } - ], - "resultChars": 1243 + "resultChars": 1634 } ] }, @@ -1840,7 +1415,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": "The assistant correctly identifies orders missing from the supabase_realtime publication as the root cause, adds only public.orders to the existing publication, and preserves courier_locations, RLS, policies, and grants. It does discuss RLS as a delivery gate but does not blame it or weaken it." } ], "skills": { @@ -1853,36 +1428,7 @@ ] }, "docs": { - "calls": [ - { - "source": "search_docs", - "query": "query { searchDocs(query: \"enable postgres changes realtime publication table\", limit: 5) { 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/realtime/postgres-changes", - "title": "Postgres Changes" - }, - { - "url": "https://supabase.com/docs/guides/realtime/benchmarks", - "title": "Benchmarks" - }, - { - "url": "https://supabase.com/docs/guides/realtime/authorization", - "title": "Realtime Authorization" - }, - { - "url": "https://supabase.com/docs/guides/realtime/protocol", - "title": "Realtime Protocol" - } - ], - "resultChars": 112153 - } - ] + "calls": [] }, "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", @@ -1913,17 +1459,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 the affected function and described the recurring HTTP 503 pattern across the morning of 2026-04-28, including all 8 gateway-only failures from 07:00Z through 12:00Z." }, { "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 503s to the gateway/platform layer, grounded in gateway-only logs with no edge-function invocations, nearby successes reaching the function, unchanged deployment/version, and distinction from avatar-upload's function-level 500." }, { "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 specific actionable next steps, including exporting detailed logs for a defined time window, identifying the scheduled caller, opening a Supabase support ticket/status-page check for platform-side gateway 503s, adding retry with jitter, and separately triaging the unrelated 500." } ], "skills": { @@ -1940,7 +1486,7 @@ }, "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 +1540,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 causing deny-all Data API behavior, kept RLS enabled, and created authenticated SELECT and INSERT policies scoped to user_id = auth.uid() with WITH CHECK for inserts." } ], "skills": { @@ -2003,38 +1549,39 @@ "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\", limit: 5) { 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/auth/oauth-server/oauth-flows", + "title": "OAuth 2.1 Flows" }, { - "url": "https://supabase.com/docs/guides/realtime/getting_started", - "title": "Getting Started with Realtime" + "url": "https://supabase.com/docs/guides/ai/rag-with-permissions", + "title": "RAG with Permissions" }, { - "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended", - "title": "Advanced pgTAP Testing" + "url": "https://supabase.com/docs/reference/swift/auth-getclaims", + "title": "getClaims()" }, { "url": "https://supabase.com/docs/guides/realtime/authorization", "title": "Realtime Authorization" }, { - "url": "https://supabase.com/docs/guides/database/postgres/column-level-security", - "title": "Column Level Security" + "url": "https://supabase.com/docs/guides/auth/jwt-fields", + "title": "JWT Claims Reference" } ], - "resultChars": 81499 + "resultChars": 71585 } ] }, @@ -2087,7 +1634,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": "Avatar migration was applied through `supabase db push` in #23, with output `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 `supabase/migrations/20240115000000_add_profile_bio.sql` in #21, after which `supabase migration list` showed local and remote matched and `supabase db push` proceeded. Read-only psql inspection was used; no disallowed workaround or direct SQL mutation was seen." } ], "skills": { @@ -2157,7 +1704,8 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" ] }, "docs": { @@ -2234,8 +1782,7 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase", - "supabase-postgres-best-practices" + "supabase" ] }, "docs": { @@ -2357,32 +1904,7 @@ "loaded": [] }, "docs": { - "calls": [ - { - "source": "search_docs", - "query": "{searchDocs(query:\"declarative database schemas db diff 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": [] }, "prompt": "Add a description text column to the `products` table in my local Supabase stack", "promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md", @@ -2422,12 +1944,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 36) from the queue" + "notes": "function removed the seeded message (id 11) from the queue" } ], "skills": { @@ -2438,31 +1960,51 @@ "calls": [ { "source": "search_docs", - "query": "{ searchDocs(query: \"queues cron schedule pgmq edge function drain queue\", limit: 8) { nodes { title href content } } }", + "query": "query { searchDocs(query: \"pg_cron schedule job every minute cron.schedule\", limit: 4) { 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/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/auth/auth-hooks/send-sms-hook", + "title": "Send SMS Hook" }, { - "url": "https://supabase.com/docs/guides/cron/quickstart", - "title": "Quickstart" + "url": "https://supabase.com/docs/guides/auth/auth-hooks/send-email-hook", + "title": "Send Email Hook" }, { - "url": "https://supabase.com/docs/guides/troubleshooting/pgcron-debugging-guide-n1KTaz", - "title": "pg_cron debugging guide" + "url": "https://supabase.com/docs/guides/cron", + "title": "Cron" + } + ], + "resultChars": 81247 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Queues pgmq read delete messages edge function\", 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/ai/automatic-embeddings", + "title": "Automatic embeddings" + }, + { + "url": "https://supabase.com/docs/guides/queues/pgmq", + "title": "PGMQ Extension" + }, + { + "url": "https://supabase.com/docs/guides/getting-started/features", + "title": "Features" } ], - "resultChars": 63907 + "resultChars": 68672 } ] }, @@ -2627,17 +2169,17 @@ { "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\":\"6d4a5797-3527-46d6-a6eb-b25cc69d591b\",\"metric\":\"steps_a_msgj0mbi\",\"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}]" + "notes": "status 200: [{\"user_id\":\"6d4a5797-3527-46d6-a6eb-b25cc69d591b\",\"metric\":\"steps_a_msgj0mbi\",\"value\":111}]" }, { "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\":\"d86dd439-6cc8-4813-a514-39ec3f9dcac3\",\"metric\":\"steps_b_msgj0mbi\",\"value\":222}]" }, { "name": "non-service key is not granted service access", @@ -2668,41 +2210,75 @@ "calls": [ { "source": "search_docs", - "query": "{ searchDocs(query: \"@supabase/server package edge function api keys secret key publishable key\", limit: 6) { nodes { title href content } } }", + "query": "{searchDocs(query:\"edge function service role key apikey header verify_jwt authorization dual auth\",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/functions/auth-headers", + "title": "Authorization headers" }, { - "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/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/auth/choosing-a-server-package", - "title": "Which package to use" + "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/auth/signing-keys", - "title": "JWT Signing Keys" + "url": "https://supabase.com/docs/guides/functions/error-codes", + "title": "Error codes" + } + ], + "resultChars": 71637 + }, + { + "source": "search_docs", + "query": "{searchDocs(query:\"@supabase/server package edge functions new API keys secret key\",limit:2){nodes{title href}}}", + "hasContent": false, + "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" + } + ], + "resultChars": 320 + }, + { + "source": "search_docs", + "query": "{searchDocs(query:\"Securing Edge Functions auth getUser service role JWT verification\",limit:1){nodes{title href content subsections{nodes{title content}}}}}", + "hasContent": true, + "pages": [] + }, + { + "source": "search_docs", + "query": "{searchDocs(query:\"Securing Edge Functions\",limit:1){nodes{title href content}}}", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/functions/auth", + "title": "Securing Edge Functions" } ], - "resultChars": 76864 + "resultChars": 7837 } ] }, "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-opus-5-no-skills/build-functions-005-dual-auth-user-secret.json" }, { @@ -2743,7 +2319,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: 019fd387-6fc4-714b-a2e1-ecf3fa15f0a5/receipt-alpha.pdf, 019fd387-6fc4-714b-a2e1-ecf3fa15f0a5/receipt-beta.pdf" }, { "name": "user B cannot read user A files", @@ -2764,7 +2340,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 all criteria: private user-files bucket, RLS policies for authenticated users scoped to bucket and owner folder with SELECT and INSERT WITH CHECK, RLS not disabled, and supabase-js createSignedUrl with expiry for temporary sharing. Also avoids public bucket/getPublicUrl/service-role client usage." } ], "skills": { @@ -2775,9 +2351,13 @@ "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": "{ searchDocs(query: \"storage RLS policy owner folder auth.uid private bucket\", limit: 5) { nodes { 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/buckets/fundamentals", "title": "Storage Buckets" @@ -2786,32 +2366,41 @@ "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" - }, + } + ], + "resultChars": 23289 + }, + { + "source": "search_docs", + "query": "{ searchDocs(query: \"createSignedUrl expiring temporary link storage\", limit: 5) { nodes { title href content } } }", + "hasContent": true, + "pages": [ { - "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3", - "title": "Configure S3 Storage" + "url": "https://supabase.com/docs/guides/storage/serving/downloads", + "title": "Serving assets from 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/reference/javascript/file-buckets-createsignedurl" }, { - "url": "https://supabase.com/docs/guides/storage/schema/helper-functions", - "title": "Storage Helper Functions" + "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsignedurls" }, { - "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/guides/storage/cdn/smart-cdn", + "title": "Smart CDN" } ], - "resultChars": 35640 + "resultChars": 11623 } ] }, @@ -2845,17 +2434,17 @@ { "name": "pgTAP test file(s) written under supabase/tests/", "passed": true, - "notes": "1 file(s): supabase/tests/tenant_isolation_test.sql" + "notes": "3 file(s): supabase/tests/001_tenant_isolation_read.sql, supabase/tests/003_membership_isolation.sql, supabase/tests/002_tenant_isolation_write.sql" }, { "name": "pgTAP isolation tests ran and pass", "passed": true, - "notes": "10 passed, 3 failed" + "notes": "10 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 the table with the tenant isolation flaw, explains that authenticated members can read posts from organizations they do not belong to, and grounds this in pgTAP/manual test results. It does not blame `notes` or dismiss the tests." } ], "skills": { @@ -2933,7 +2522,7 @@ "calls": [ { "source": "search_docs", - "query": "{ searchDocs(query: \"gte-small embedding dimensions Supabase.ai Session edge function\", limit: 4) { nodes { title href content } } }", + "query": "query { searchDocs(query: \"gte-small embedding dimensions Supabase.ai Session edge function\", limit: 5) { nodes { title href content } } }", "hasContent": true, "pages": [ { @@ -2951,9 +2540,41 @@ { "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": 61741 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"semantic search match_document_sections RLS vector hnsw\", limit: 5) { 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/ai/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/hybrid-search", + "title": "Hybrid search" + }, + { + "url": "https://supabase.com/docs/guides/ai/vector-indexes", + "title": "Vector indexes" } ], - "resultChars": 42731 + "resultChars": 51054 } ] }, @@ -2989,12 +2610,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 the rubric: preserves the app scrape, adds a Supabase Metrics API scrape for evalshostedprojectxy.supabase.co over HTTPS at /customer/v1/privileged/metrics, uses HTTP Basic Auth with password_file, and docker-compose mounts the matching secrets directory into Prometheus." }, { "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 steps to create a Supabase Secret API key, write it to the configured password_file path, restart/reload the Compose stack, and verify via direct endpoint curl, Prometheus targets/API query, and Grafana dashboard variables." } ], "skills": { @@ -3005,31 +2626,27 @@ "calls": [ { "source": "search_docs", - "query": "{ searchDocs(query: \"Prometheus metrics endpoint project observability\", limit: 6) { nodes { title href content } } }", + "query": "{ searchDocs(query: \"Prometheus metrics endpoint project metrics scraping\", 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 } ] }, @@ -3086,31 +2703,31 @@ "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 function secrets environment variables\", 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/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/secrets", + "title": "Environment Variables" }, { - "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-generate-speech-stream", - "title": "Streaming Speech with ElevenLabs" + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions", + "title": "Self-Hosted Functions" + }, + { + "url": "https://supabase.com/docs/guides/ai/automatic-embeddings", + "title": "Automatic embeddings" } ], - "resultChars": 38347 + "resultChars": 62245 } ] }, @@ -3222,7 +2839,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 all rubric requirements: diagnoses soft-delete-only flow, implements auth/session/refresh revocation plus RLS active-user enforcement, explains JWT stateless validity and remaining window consistently with the implemented RLS fix, and correctly distinguishes publishable frontend/RLS-enforced keys from secret server-only/RLS-bypassing keys." } ], "skills": { @@ -3233,73 +2850,299 @@ "calls": [ { "source": "search_docs", - "query": "{ searchDocs(query: \"publishable key secret key legacy anon service_role API keys RLS\", limit: 6) { nodes { title href content } } }", + "query": "{ searchDocs(query: \"delete user account revoke sessions access token remains valid JWT expiry\", limit: 6) { nodes { title href content } } }", "hasContent": true, "pages": [ { - "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/getting-started/api-keys", - "title": "Understanding API keys" + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows", + "title": "OAuth 2.1 Flows" }, { - "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/platform/sso/multiple-providers", + "title": "Multiple SSO Providers" }, { - "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/functions/secrets", - "title": "Environment Variables" + "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/getting-started/tutorials/with-redwoodjs", - "title": "Build a User Management App with RedwoodJS" + "url": "https://supabase.com/docs/guides/platform/temporary-access", + "title": "Temporary access" } ], - "resultChars": 136765 + "resultChars": 104786 }, { - "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.", + "source": "search_docs", + "query": "{ searchDocs(query: \"JWT expiry access token session revocation\", limit: 3) { nodes { title href content } } }", "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/auth/sessions", + "title": "User sessions" + }, { - "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys" + "url": "https://supabase.com/docs/guides/auth/jwts", + "title": "JSON Web Token (JWT)" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields", + "title": "JWT Claims Reference" + } + ], + "resultChars": 39278 + }, + { + "source": "web_search", + "query": "Supabase deleted or banned user access token JWT still valid until expiry stateless validation", + "hasContent": false, + "pages": [ + { + "url": "https://supabase.com/docs/guides/auth/managing-user-data", + "title": "User Management | Supabase Docs" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions", + "title": "User sessions | Supabase Docs" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwts", + "title": "JSON Web Token (JWT) | Supabase Docs" } ], - "resultChars": 1009 + "resultChars": 2768 }, { "source": "search_docs", - "query": "{ searchDocs(query: \"how many secret keys can I create limit reveal secret key dashboard\", limit: 2) { nodes { title href content } } }", + "query": "{ searchDocs(query: \"publishable key secret key API keys\", 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/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" + } + ], + "resultChars": 61983 + }, + { + "source": "web_search", + "query": "Supabase sb_publishable sb_secret new API keys replace anon service_role", + "hasContent": false, "pages": [ { "url": "https://supabase.com/docs/guides/getting-started/api-keys", - "title": "Understanding 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/troubleshooting/rotating-anon-service-and-jwt-secrets-1Jq6yd", + "title": "Supabase Docs | Troubleshooting | Rotating Anon, Service, and JWT Secrets" + }, + { + "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/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/docs/guides/api/creating-routes", + "title": "Creating API Routes | Supabase Docs" + }, + { + "url": "https://supabase.com/docs/guides/auth/signing-keys", + "title": "JWT Signing Keys | Supabase Docs" + }, + { + "url": "https://supabase.com/docs/guides/functions/secrets", + "title": "Environment Variables | Supabase Docs" + }, + { + "url": "https://supabase.com/blog/jwt-signing-keys", + "title": "Introducing JWT Signing Keys" + } + ], + "resultChars": 2877 + }, + { + "source": "search_docs", + "query": "{ searchDocs(query: \"ban user ban_duration banned_until admin updateUserById\", limit: 2) { nodes { title href content } } }", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/reference/javascript/auth-admin-updateuserbyid" + }, + { + "url": "https://supabase.com/docs/reference/dart/auth-admin-updateuserbyid" + } + ], + "resultChars": 2559 + }, + { + "source": "web_fetch", + "query": "What does auth.admin.signOut(jwt, scope) do? What are the scope options (global, local, others) and what exactly does it invalidate — access tokens, refresh tokens, or both? Quote the description verbatim.", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/reference/javascript/auth-admin-signout" + } + ], + "resultChars": 591 + }, + { + "source": "web_fetch", + "query": "Anything about deleting users, banning users, banned_until, and whether existing access tokens/sessions are invalidated? Quote relevant passages.", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/auth/managing-user-data" + } + ], + "resultChars": 1169 + }, + { + "source": "web_fetch", + "query": "Extract verbatim details on: (1) which key is for frontend/browser vs server-only; (2) what Postgres role each key maps to (does publishable map to anon role, secret to service_role?); (3) exactly how each key interacts with Row Level Security — does the publishable key respect RLS, does the secret key bypass RLS, and any caveats about how the bypass works; (4) what happens to the role when a user signs in with the publishable key (anon vs authenticated); (5) whether these keys are JWTs, expiry, rotation/revocation, whether multiple can exist. Quote the exact wording about RLS.", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/getting-started/api-keys" + } + ], + "resultChars": 1821 + }, + { + "source": "web_fetch", + "query": "Extract the full migration steps, how to disable/deactivate legacy anon and service_role keys, deprecation timeline dates, and any warnings, gotchas, or things that break during migration (e.g. Edge Functions, self-hosting, third-party integrations, JWT verification, custom claims).", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys" + } + ], + "resultChars": 1826 + }, + { + "source": "web_fetch", + "query": "Return verbatim any sentences about deleting a user, banning a user, and whether a JWT remains valid after deletion. Do not paraphrase.", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/auth/managing-user-data.md" + } + ], + "resultChars": 646 + }, + { + "source": "web_search", + "query": "Supabase dashboard JWT expiry maximum value 604800 seconds minimum access token expiry configurable", + "hasContent": false, + "pages": [ + { + "url": "https://supabase.com/docs/guides/auth/sessions", + "title": "User sessions | Supabase Docs" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwts", + "title": "JSON Web Token (JWT) | Supabase Docs" + }, + { + "url": "https://supabase.com/docs/guides/cli/config", + "title": "Supabase CLI config | Supabase Docs" + }, + { + "url": "https://supabase.com/docs/reference/python/auth-api", + "title": "Python API Reference | Supabase Docs" + }, + { + "url": "https://supabase.com/docs/guides/troubleshooting/jwt-expired-error-in-supabase-dashboard-F06k3x" + } + ], + "resultChars": 2896 + }, + { + "source": "web_fetch", + "query": "Focus narrowly on header mechanics and role resolution. Quote exactly: (a) what happens when you send a publishable key on the apikey header AND a user access token on the Authorization: Bearer header — which determines the Postgres role? (b) What happens if you send a SECRET key on apikey together with a user's Authorization Bearer JWT — does the user JWT override the secret key's service_role, or does service_role win? (c) Any statement about BYPASSRLS. (d) Any statement that secret keys should never be used with user tokens. (e) Any mention of whether publishable keys alone can read data if RLS is disabled.", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/getting-started/api-keys" + } + ], + "resultChars": 1477 + }, + { + "source": "web_fetch", + "query": "Summarize the announced changes and any concrete dates/timeline for legacy anon and service_role key deprecation, and the stated benefits (rotation, revocation, no JWT, multiple keys).", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/changelog/29260-upcoming-changes-to-supabase-api-keys" + } + ], + "resultChars": 215 + }, + { + "source": "web_fetch", + "query": "What does auth.jwt_expiry say? Quote the default and any stated maximum/minimum for JWT expiry in seconds.", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/cli/config" + } + ], + "resultChars": 372 + }, + { + "source": "web_search", + "query": "Supabase studio JWT expiry minimum value validation \"must be greater\" auth settings jwt_exp", + "hasContent": false, + "pages": [ + { + "url": "https://supabase.com/docs/guides/auth/jwts", + "title": "JSON Web Token (JWT) | Supabase Docs" + }, + { + "url": "https://supabase.com/docs/guides/auth/signing-keys", + "title": "JWT Signing Keys | Supabase Docs" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions", + "title": "User sessions | Supabase Docs" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields", + "title": "JWT Claims Reference | Supabase Docs" }, { - "url": "https://supabase.com/docs/guides/functions/limits", - "title": "Limits" + "url": "https://supabase.com/docs/guides/troubleshooting/jwt-expired-error-in-supabase-dashboard-F06k3x" } ], - "resultChars": 15838 + "resultChars": 2804 } ] }, @@ -3354,7 +3197,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 answer correctly identifies the root cause as `orders` missing from the `supabase_realtime` publication despite SUBSCRIBED status, fixes it with `alter publication supabase_realtime add table public.orders;`, preserves `courier_locations`, RLS, and policies, and does not blame client code/RLS/networking or weaken security." } ], "skills": { @@ -3393,17 +3236,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 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 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 recurring image-transform 503s to the gateway/platform layer before function execution, grounded in gateway-only 503s with no edge-function log rows while nearby invocations succeeded, and distinguishes them from avatar-upload's function-level 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 actionable next steps, including opening a Supabase support ticket with specific request IDs and timestamps, checking worker boot/deployment-fetch logs, mitigating cold-start imports, adding retry/backoff, fixing a separate function error, and querying full logs/setting alerts." } ], "skills": { @@ -3469,7 +3312,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 causing deny-all Data API behavior, kept RLS enabled, and created authenticated SELECT and INSERT policies scoped to user_id = auth.uid() with WITH CHECK for inserts. No disabling RLS or permissive public/anon policies." } ], "skills": { @@ -3528,7 +3371,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": "Applied avatar_url via `supabase db push` (#21), which showed `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` Reconciled orphan bio migration by adding local file `supabase/migrations/20240115000000_add_profile_bio.sql` (#19), after which `supabase migration list` showed local/remote alignment (#20). Read-only psql inspection was used; no disallowed workaround or direct SQL mutation seen." } ], "skills": { @@ -3732,7 +3575,8 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" ] }, "docs": { @@ -3832,12 +3676,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 5) from the queue" } ], "skills": { @@ -3846,14 +3690,15 @@ "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 cron.schedule pgmq\", limit: 5) { nodes { title href content } } }", "hasContent": true, "pages": [ { @@ -3869,55 +3714,55 @@ "title": "pg_cron debugging guide" }, { - "url": "https://supabase.com/docs/guides/queues/quickstart", - "title": "Quickstart" + "url": "https://supabase.com/docs/guides/cron/install", + "title": "Install" }, { - "url": "https://supabase.com/docs/guides/functions/schedule-functions", - "title": "Scheduling Edge Functions" + "url": "https://supabase.com/docs/guides/cron", + "title": "Cron" } ], - "resultChars": 55834 + "resultChars": 45463 }, { "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 Function read pgmq queue delete message worker\", 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/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/functions/unit-test", - "title": "Testing your Edge Functions" + "url": "https://supabase.com/docs/guides/queues/pgmq", + "title": "PGMQ Extension" } ], - "resultChars": 26350 + "resultChars": 57611 }, { "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: \"automatic embeddings edge function process queue pgmq_public read delete Deno.serve\", 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/functions", + "title": "Edge Functions" }, { - "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions", - "title": "Self-Hosted Functions" + "url": "https://supabase.com/docs/guides/database/connecting-to-postgres/serverless-drivers", + "title": "Serverless Drivers" } ], - "resultChars": 28165 + "resultChars": 51573 } ] }, @@ -3974,7 +3819,8 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" ] }, "docs": { @@ -4092,17 +3938,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: {\"data\":[{\"user_id\":\"dbbf5885-772a-4b83-9f7d-db882e9956f6\",\"metric\":\"steps_a_msgj5q82\",\"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: {\"data\":[{\"user_id\":\"dbbf5885-772a-4b83-9f7d-db882e9956f6\",\"metric\":\"steps_a_msgj5q82\",\"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: {\"data\":[{\"user_id\":\"bbcbab78-6116-45b6-9d54-7850ca2b4cde\",\"metric\":\"steps_b_msgj5q82\",\"value\":222}]}" }, { "name": "non-service key is not granted service access", @@ -4136,33 +3982,18 @@ }, "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: \"Edge Function auth service role user JWT apikey header\", 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-auth-keys", + "title": "New API Keys and Asymmetric Authentication" }, { - "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/getting-started/api-keys", + "title": "Understanding API keys" }, { "url": "https://supabase.com/docs/guides/functions/auth", @@ -4171,552 +4002,362 @@ { "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt", "title": "Integrating With Supabase Auth" - } - ], - "resultChars": 41771 - }, - { - "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 } } }", - "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/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/auth", - "title": "Securing Edge Functions" }, { "url": "https://supabase.com/docs/guides/functions/auth-headers", "title": "Authorization headers" - }, - { - "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": 46635 + } + ] + }, + "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": "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: 019fd385-885e-7338-a59f-26b101480bec/receipt-alpha.pdf, 019fd385-885e-7338-a59f-26b101480bec/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, adds authenticated owner-scoped SELECT and INSERT policies with WITH CHECK while keeping RLS intact, and provides supabase-js createSignedUrl code with expiry for temporary sharing. No public bucket, permissive policies, or client service-role usage." + } + ], + "skills": { + "available": [ + "supabase", + "supabase-postgres-best-practices" + ], + "loaded": [ + "supabase" + ] + }, + "docs": { + "calls": [] + }, + "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": "claude-code-sonnet-5/build-storage-001-private-bucket-access.json" + }, + { + "experiment": "claude-code-sonnet-5", + "experimentSuite": "benchmark", + "experimentDisplay": { + "agent": "claude-code", + "modelProvider": "anthropic", + "modelId": "claude-sonnet-5", + "reasoningEffort": "high" + }, + "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": "6 passed, 2 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 the conclusion in pgTAP failures for posts negative cases, notes that `notes` tests passed, and explains that authenticated members can read posts from other organizations due to missing org_id comparison." + } + ], + "skills": { + "available": [ + "supabase", + "supabase-postgres-best-practices" + ], + "loaded": [ + "supabase", + "supabase-postgres-best-practices" + ] + }, + "docs": { + "calls": [ { "source": "search_docs", - "query": "query { searchDocs(query: \"@supabase/server withSupabase edge function auth\") { nodes { title href content } } }", + "query": "{ searchDocs(query: \"pgTAP testing RLS policies local development\", limit: 5) { 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/auth", - "title": "Auth" - }, - { - "url": "https://supabase.com/docs/guides/database/postgres/roles", - "title": "Postgres Roles" - }, - { - "url": "https://supabase.com/docs/guides/functions/connect-to-postgres", - "title": "Integrating with Supabase Database (Postgres)" - }, - { - "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/functions/quickstart-dashboard", - "title": "Getting Started with Edge Functions (Dashboard)" - }, - { - "url": "https://supabase.com/docs/guides/auth/architecture", - "title": "Auth architecture" - }, - { - "url": "https://supabase.com/docs/guides/database/secure-data", - "title": "Securing your 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/websockets", - "title": "Handling WebSockets" + "url": "https://supabase.com/docs/guides/local-development/testing/overview", + "title": "Testing Overview" }, { - "url": "https://supabase.com/docs/guides/troubleshooting/edge-function-401-error-response", - "title": "Edge Function 401 error response" + "url": "https://supabase.com/docs/guides/database/testing", + "title": "Testing Your Database" }, { - "url": "https://supabase.com/docs/guides/database/connecting-to-postgres/serverless-drivers", - "title": "Serverless Drivers" + "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended", + "title": "Advanced pgTAP Testing" }, { - "url": "https://supabase.com/docs/guides/functions/auth-headers", - "title": "Authorization headers" + "url": "https://supabase.com/docs/guides/database/extensions/pgtap", + "title": "pgTAP: Unit Testing" }, { - "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/auth/enterprise-sso", - "title": "Enterprise Single Sign-On" - }, - { - "url": "https://supabase.com/docs/guides/functions/recursive-functions", - "title": "Recursive / Nested Function Calls" - }, - { - "url": "https://supabase.com/docs/guides/integrations/build-a-supabase-oauth-integration", - "title": "Build a Supabase Integration" - }, - { - "url": "https://supabase.com/docs/guides/auth/sessions", - "title": "User sessions" - }, - { - "url": "https://supabase.com/docs/guides/auth/quickstarts/astrojs", - "title": "Use Supabase Auth with Astro" - }, - { - "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", + "title": "Row Level Security" } ], - "resultChars": 12 - }, + "resultChars": 68117 + } + ] + }, + "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": "claude-code-sonnet-5/build-tests-001-rls-tenant-isolation.json" + }, + { + "experiment": "claude-code-sonnet-5", + "experimentSuite": "benchmark", + "experimentDisplay": { + "agent": "claude-code", + "modelProvider": "anthropic", + "modelId": "claude-sonnet-5", + "reasoningEffort": "high" + }, + "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", + "supabase-postgres-best-practices" + ] + }, + "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": "claude-code-sonnet-5/build-vectors-001-rag-with-permissions.json" + }, + { + "experiment": "claude-code-sonnet-5", + "experimentSuite": "benchmark", + "experimentDisplay": { + "agent": "claude-code", + "modelProvider": "anthropic", + "modelId": "claude-sonnet-5", + "reasoningEffort": "high" + }, + "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 job and adds a Supabase scrape using HTTPS, the required metrics path, HTTP Basic Auth with password_file, and a project target on supabase.co. docker-compose mounts the secrets directory so the password_file path is available." + }, + { + "name": "documented live deployment and verification steps", + "passed": true, + "judgeNotes": "README includes Secret API key creation, saving it to the configured password_file path, Prometheus reload, and concrete verification via Prometheus Targets/curl and Grafana dashboard." + } + ], + "skills": { + "available": [ + "supabase", + "supabase-postgres-best-practices" + ], + "loaded": [ + "supabase" + ] + }, + "docs": { + "calls": [ { "source": "search_docs", - "query": "query { searchDocs(query: \"edge function verify_jwt secret key apikey header\") { nodes { title href content } } }", + "query": "{ searchDocs(query: \"self-hosted metrics endpoint prometheus\", 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/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/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/auth/auth-mfa", - "title": "Multi-Factor Authentication" - }, - { - "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt", - "title": "Integrating With Supabase Auth" - }, - { - "url": "https://supabase.com/docs/guides/functions/websockets", - "title": "Handling WebSockets" + "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/integrations/partner-integration-guide", - "title": "Supabase Partner Integration Guide" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud", + "title": "Metrics API with Grafana Cloud" }, { - "url": "https://supabase.com/docs/guides/resources/glossary", - "title": "Glossary" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics", + "title": "Metrics API" }, { - "url": "https://supabase.com/docs/guides/database/secure-data", - "title": "Securing your data" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic", + "title": "Vendor-agnostic Metrics API setup" } ], - "resultChars": 335959 + "resultChars": 19943 }, { "source": "search_docs", - "query": "query { searchDocs(query: \"SUPABASE_SECRET_KEYS SUPABASE_PUBLISHABLE_KEYS environment variables edge functions\") { nodes { title href content } } }", + "query": "{ searchDocs(query: \"self-hosted postgres_exporter database metrics docker\", 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/monitoring-and-debugging/metrics/grafana-self-hosted", + "title": "Metrics API with Prometheus & Grafana (self-hosted)" }, { - "url": "https://supabase.com/docs/guides/functions/secrets", - "title": "Environment Variables" + "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17", + "title": "Upgrade to Postgres 17" }, { - "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions", - "title": "Self-Hosted Functions" + "url": "https://supabase.com/docs/guides/self-hosting/docker", + "title": "Self-Hosting with Docker" }, { - "url": "https://supabase.com/docs/guides/functions/auth", - "title": "Securing Edge Functions" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics", + "title": "Metrics API" }, { - "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/guides/functions/schedule-functions", - "title": "Scheduling Edge Functions" - }, - { - "url": "https://supabase.com/docs/guides/functions/recursive-functions", - "title": "Recursive / Nested Function Calls" - } - ], - "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" + "url": "https://supabase.com/docs/guides/troubleshooting/how-to-view-database-metrics-uqf2z_", + "title": "How to View Database Metrics" } ], - "resultChars": 611775 + "resultChars": 57396 } ] }, - "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", + "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": "claude-code-sonnet-5/build-functions-005-dual-auth-user-secret.json" + "sourcePath": "claude-code-sonnet-5/deploy-database-001-prometheus-metrics.json" }, { "experiment": "claude-code-sonnet-5", @@ -4727,57 +4368,35 @@ "modelId": "claude-sonnet-5", "reasoningEffort": "high" }, - "eval": "build-storage-001-private-bucket-access", - "stage": "build", + "eval": "deploy-functions-001-edge-function-secrets", + "stage": "deploy", "product": [ - "storage", - "database" + "edge-functions" ], "topic": [ - "rls", - "sdk" + "security" ], "suite": "benchmark", - "interface": "mcp", + "interface": "cli", "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", + "name": "WEATHER_API_KEY is set as a Function secret on the project", "passed": true }, { - "name": "user A lists only own files", + "name": "the weather function is deployed to the project", "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 + "notes": "status ACTIVE" }, { - "name": "user A can upload into own folder", - "passed": true + "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": "user B cannot upload into user A folder", + "name": "WEATHER_API_KEY value is not committed to the repo", "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": { @@ -4790,41 +4409,12 @@ ] }, "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 - } - ] + "calls": [] }, - "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", + "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": "claude-code-sonnet-5/build-storage-001-private-bucket-access.json" + "sourcePath": "claude-code-sonnet-5/deploy-functions-001-edge-function-secrets.json" }, { "experiment": "claude-code-sonnet-5", @@ -4835,33 +4425,35 @@ "modelId": "claude-sonnet-5", "reasoningEffort": "high" }, - "eval": "build-tests-001-rls-tenant-isolation", - "stage": "build", + "eval": "deploy-self-hosting-001-docker-compose", + "stage": "deploy", "product": [ - "database" + "database", + "auth", + "storage" ], "topic": [ - "tests", - "rls" + "self-hosting" ], "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": "cloned the self-host stack (docker-compose.yml + volumes/db)", + "passed": true }, { - "name": "pgTAP isolation tests ran and pass", - "passed": true, - "notes": "4 passed, 4 failed" + "name": "didn't conflate with the CLI (no supabase/config.toml in the stack)", + "passed": true }, { - "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." + "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": { @@ -4876,10 +4468,10 @@ "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", + "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": "claude-code-sonnet-5/build-tests-001-rls-tenant-isolation.json" + "sourcePath": "claude-code-sonnet-5/deploy-self-hosting-001-docker-compose.json" }, { "experiment": "claude-code-sonnet-5", @@ -4890,50 +4482,49 @@ "modelId": "claude-sonnet-5", "reasoningEffort": "high" }, - "eval": "build-vectors-001-rag-with-permissions", - "stage": "build", + "eval": "investigate-auth-001-deleted-user-access", + "stage": "investigate", "product": [ - "database", - "vectors" + "auth" ], "topic": [ - "sql", - "rls" + "security", + "sdk" ], "suite": "benchmark", "interface": "mcp", - "passed": true, + "passed": false, "checks": [ { - "name": "document_sections.embedding is vector(384)", - "passed": true, - "notes": "vector(384)" + "name": "victim session active before delete-account", + "passed": true }, { - "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": "delete_account flow ran for the victim", + "passed": true }, { - "name": "index operator class matches the search operator", + "name": "delete-account revokes the user's sessions", "passed": true, - "notes": "function operators: <=>\nindexes: CREATE INDEX document_sections_embedding_idx ON public.document_sections USING hnsw (embedding vector_cosine_ops)" + "notes": "sessions left: 0" }, { - "name": "user A search returns only own sections, best match first", + "name": "deleted user's refresh token is rejected", "passed": true }, { - "name": "user B search returns only own sections, best match first", - "passed": true + "name": "deleted user cannot sign back in", + "passed": false, + "notes": "deleted account can still sign in" }, { - "name": "user A reads only own sections through the API", + "name": "other users keep their sessions and access", "passed": true }, { - "name": "user A reads only own documents through the API", - "passed": true + "name": "diagnosed and explained session revocation", + "passed": true, + "judgeNotes": "Meets the rubric: identifies soft-delete-only root cause, implements real auth/session revocation via banning future sign-ins and deleting sessions/refresh tokens, adds RLS checks to close the Data API stale-JWT window, correctly caveats that stateless JWTs remain locally valid until expiry, and accurately distinguishes publishable vs secret keys including RLS bypass/server-only handling." } ], "skills": { @@ -4949,38 +4540,50 @@ "calls": [ { "source": "search_docs", - "query": "{ searchDocs(query: \"gte-small embedding dimensions Supabase.ai Session\", limit: 5) { nodes { title href content } } }", + "query": "{ searchDocs(query: \"delete user does not invalidate access token session revocation banned_until\", 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/auth/managing-user-data", + "title": "User Management" }, { - "url": "https://supabase.com/docs/guides/functions/ai-models", - "title": "Running AI Models" + "url": "https://supabase.com/docs/guides/auth/auth-anonymous", + "title": "Anonymous Sign-Ins" }, { - "url": "https://supabase.com/docs/guides/ai/semantic-search", - "title": "Semantic search" + "url": "https://supabase.com/docs/guides/auth/sessions", + "title": "User sessions" + } + ], + "resultChars": 34009 + }, + { + "source": "search_docs", + "query": "{ searchDocs(query: \"publishable key secret key migrating from anon service_role API keys RLS\", limit: 3) { 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/ai/concepts", - "title": "Concepts" + "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/semantic-search", - "title": "Semantic Search" + "url": "https://supabase.com/docs/guides/auth/signing-keys", + "title": "JWT Signing Keys" } ], - "resultChars": 62210 + "resultChars": 72483 } ] }, - "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": "claude-code-sonnet-5/build-vectors-001-rag-with-permissions.json" + "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": "claude-code-sonnet-5/investigate-auth-001-deleted-user-access.json" }, { "experiment": "claude-code-sonnet-5", @@ -4991,30 +4594,44 @@ "modelId": "claude-sonnet-5", "reasoningEffort": "high" }, - "eval": "deploy-database-001-prometheus-metrics", - "stage": "deploy", + "eval": "investigate-realtime-001-subscribed-no-events", + "stage": "investigate", "product": [ + "realtime", "database" ], "topic": [ - "observability" + "sdk" ], "suite": "benchmark", + "interface": "mcp", "passed": true, "checks": [ { - "name": "preserved existing app scrape job", + "name": "orders table added to supabase_realtime publication", "passed": true }, { - "name": "configured the Supabase Metrics API scrape correctly", + "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, - "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." + "notes": "authenticated sees 2 of 2 orders" }, { - "name": "documented live deployment and verification steps", + "name": "diagnosed missing publication membership", "passed": true, - "judgeNotes": "README includes Secret API key creation, matching secret file placement, Compose start/reload instructions, and concrete verification via Prometheus targets." + "judgeNotes": "Identified missing orders table in supabase_realtime publication as root cause, added public.orders with ALTER PUBLICATION, preserved courier_locations and RLS/policies, and did not blame or weaken RLS/client/networking." } ], "skills": { @@ -5027,41 +4644,12 @@ ] }, "docs": { - "calls": [ - { - "source": "search_docs", - "query": "{ searchDocs(query: \"project metrics endpoint prometheus\", limit: 5) { 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/database/replication/manual-replication-monitoring", - "title": "Manual replication monitoring" - } - ], - "resultChars": 27147 - } - ] + "calls": [] }, - "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", + "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": "claude-code-sonnet-5/deploy-database-001-prometheus-metrics.json" + "sourcePath": "claude-code-sonnet-5/investigate-realtime-001-subscribed-no-events.json" }, { "experiment": "claude-code-sonnet-5", @@ -5072,35 +4660,32 @@ "modelId": "claude-sonnet-5", "reasoningEffort": "high" }, - "eval": "deploy-functions-001-edge-function-secrets", - "stage": "deploy", + "eval": "investigate-reliability-003-edge-function-5xx-correlation", + "stage": "investigate", "product": [ "edge-functions" ], "topic": [ - "security" + "observability" ], "suite": "benchmark", - "interface": "cli", + "interface": "mcp", "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", + "name": "identified image-transform and the recurring 503 pattern", "passed": true, - "notes": "status ACTIVE" + "judgeNotes": "Identified image-transform as affected and described the recurring pattern of 8 HTTP 503 gateway failures across the morning of 2026-04-28, while distinguishing older billing-webhook 503s as unrelated." }, { - "name": "the weather function reads WEATHER_API_KEY from the environment", + "name": "attributed recurring 503s to gateway/platform layer, not function code", "passed": true, - "judgeNotes": "Reads WEATHER_API_KEY from the runtime environment using Deno.env.get(\"WEATHER_API_KEY\")." + "judgeNotes": "Attributes the image-transform 503s to gateway/platform-level rejection before function execution, not application code. Grounds this in the observation that the 503s appear in gateway/API logs but have no corresponding edge-function invocation/runtime rows, while nearby successful 200 invocations do appear. Also distinguishes them from function-level errors like avatar-upload's 500." }, { - "name": "WEATHER_API_KEY value is not committed to the repo", - "passed": true + "name": "recommended a concrete next step", + "passed": true, + "judgeNotes": "Recommended specific actionable next steps, including checking Supabase status/support for a regional platform incident during the affected time window, adding retries/alerting, and capturing payload/concurrency data if it recurs." } ], "skills": { @@ -5113,41 +4698,12 @@ ] }, "docs": { - "calls": [ - { - "source": "search_docs", - "query": "{ searchDocs(query: \"edge functions environment variables secrets set\", limit: 5) { nodes { title href ... on Guide { 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/examples/elevenlabs-transcribe-speech", - "title": "Transcription Telegram Bot" - }, - { - "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions", - "title": "Self-Hosted Functions" - } - ], - "resultChars": 39587 - } - ] + "calls": [] }, - "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", + "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": "claude-code-sonnet-5/deploy-functions-001-edge-function-secrets.json" + "sourcePath": "claude-code-sonnet-5/investigate-reliability-003-edge-function-5xx-correlation.json" }, { "experiment": "claude-code-sonnet-5", @@ -5158,35 +4714,49 @@ "modelId": "claude-sonnet-5", "reasoningEffort": "high" }, - "eval": "deploy-self-hosting-001-docker-compose", - "stage": "deploy", + "eval": "resolve-dataapi-001-empty-results", + "stage": "resolve", "product": [ + "data-api", "database", - "auth", - "storage" + "auth" ], "topic": [ - "self-hosting" + "rls", + "sdk" ], "suite": "benchmark", - "interface": "cli", + "interface": "mcp", "passed": true, "checks": [ { - "name": "cloned the self-host stack (docker-compose.yml + volumes/db)", + "name": "RLS still enabled on bookmarks", "passed": true }, { - "name": "didn't conflate with the CLI (no supabase/config.toml in the stack)", + "name": "user A reads own bookmarks", "passed": true }, { - "name": "secrets rotated off the shipped defaults", + "name": "user B cannot read user A bookmarks", "passed": true }, { - "name": "ANON_KEY and SERVICE_ROLE_KEY are HS256 JWTs signed by JWT_SECRET", + "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 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 WITH CHECK for inserts." } ], "skills": { @@ -5201,10 +4771,10 @@ "docs": { "calls": [] }, - "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", + "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": "claude-code-sonnet-5/deploy-self-hosting-001-docker-compose.json" + "sourcePath": "claude-code-sonnet-5/resolve-dataapi-001-empty-results.json" }, { "experiment": "claude-code-sonnet-5", @@ -5215,49 +4785,42 @@ "modelId": "claude-sonnet-5", "reasoningEffort": "high" }, - "eval": "investigate-auth-001-deleted-user-access", - "stage": "investigate", + "eval": "resolve-database-001-migration-history-mismatch", + "stage": "resolve", "product": [ - "auth" + "database" ], "topic": [ - "security", - "sdk" + "migrations" ], "suite": "benchmark", - "interface": "mcp", - "passed": false, + "interface": "cli", + "passed": true, "checks": [ { - "name": "victim session active before delete-account", + "name": "the avatar_url column is applied on the hosted profiles table", "passed": true }, { - "name": "delete_account flow ran for the victim", + "name": "migration 20240220000000 is recorded in the remote history", "passed": true }, { - "name": "delete-account revokes the user's sessions", - "passed": true, - "notes": "sessions left: 0" - }, - { - "name": "deleted user's refresh token is rejected", + "name": "remote migration history matches local migration files", "passed": true }, { - "name": "deleted user cannot sign back in", - "passed": false, - "notes": "deleted account can still sign in" + "name": "local migrations are a valid reconciled sequence", + "passed": true }, { - "name": "other users keep their sessions and access", + "name": "production profile data is intact (not reset)", "passed": true }, { - "name": "diagnosed and explained session revocation", + "name": "the avatar migration and history reconciliation were done via the Supabase CLI", "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": "Avatar migration was applied through `supabase db push` in #17, which shows `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` The orphan bio migration was reconciled by adding the missing local file `supabase/migrations/20240115000000_add_profile_bio.sql` in #15, after which `supabase migration list` showed local/remote alignment and the successful `db push` proceeded. No disallowed workaround or direct SQL mutation was used; psql commands were read-only inspections." } ], "skills": { @@ -5270,43 +4833,12 @@ ] }, "docs": { - "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 } } }", - "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 - } - ] + "calls": [] }, - "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": "claude-code-sonnet-5/investigate-auth-001-deleted-user-access.json" + "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, + "sourcePath": "claude-code-sonnet-5/resolve-database-001-migration-history-mismatch.json" }, { "experiment": "claude-code-sonnet-5", @@ -5317,44 +4849,39 @@ "modelId": "claude-sonnet-5", "reasoningEffort": "high" }, - "eval": "investigate-realtime-001-subscribed-no-events", - "stage": "investigate", + "eval": "resolve-performance-001-slow-query-cpu-spike", + "stage": "resolve", "product": [ - "realtime", "database" ], "topic": [ - "sdk" + "observability", + "sql" ], "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", + "name": "inspected pg_stat_statements for query performance", "passed": true }, { - "name": "publication still publishes INSERT events", + "name": "ran EXPLAIN on the expensive query", "passed": true }, { - "name": "RLS still enabled on orders", + "name": "created index covering user_id and created_at", "passed": true }, { - "name": "staff can still read orders through RLS", + "name": "query plan uses an index and avoids sequential scan", "passed": true, - "notes": "authenticated sees 2 of 2 orders" + "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_id_created_at (cost=0.00..4.47 rows=25 width=0)\n Index Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)" }, { - "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." + "name": "inserts still work", + "passed": true } ], "skills": { @@ -5369,62 +4896,10 @@ "docs": { "calls": [] }, - "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", + "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": "claude-code-sonnet-5/investigate-realtime-001-subscribed-no-events.json" - }, - { - "experiment": "claude-code-sonnet-5", - "experimentSuite": "benchmark", - "experimentDisplay": { - "agent": "claude-code", - "modelProvider": "anthropic", - "modelId": "claude-sonnet-5", - "reasoningEffort": "high" - }, - "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 recurring 503s throughout the morning of 2026-04-28, covering the gateway failure pattern and distinguishing it from unrelated billing-webhook errors." - }, - { - "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." - }, - { - "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." - } - ], - "skills": { - "available": [ - "supabase", - "supabase-postgres-best-practices" - ], - "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", - "attempts": 2, - "sourcePath": "claude-code-sonnet-5/investigate-reliability-003-edge-function-5xx-correlation.json" + "sourcePath": "claude-code-sonnet-5/resolve-performance-001-slow-query-cpu-spike.json" }, { "experiment": "claude-code-sonnet-5", @@ -5435,49 +4910,55 @@ "modelId": "claude-sonnet-5", "reasoningEffort": "high" }, - "eval": "resolve-dataapi-001-empty-results", + "eval": "resolve-security-002-rls-cross-tenant-leak", "stage": "resolve", "product": [ - "data-api", "database", "auth" ], "topic": [ "rls", - "sdk" + "security" ], "suite": "benchmark", "interface": "mcp", "passed": true, "checks": [ { - "name": "RLS still enabled on bookmarks", + "name": "RLS enabled on notes", "passed": true }, { - "name": "user A reads own bookmarks", + "name": "tenant A sees only org A notes", "passed": true }, { - "name": "user B cannot read user A bookmarks", + "name": "tenant B cannot read org A notes", "passed": true }, { - "name": "anon reads no bookmarks", + "name": "tenant A author can update own note", "passed": true }, { - "name": "user A can save a new bookmark", + "name": "tenant B cannot update org A note", "passed": true }, { - "name": "user B cannot insert a bookmark as user A", + "name": "tenant B author can delete own note", "passed": true }, { - "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." + "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": { @@ -5492,248 +4973,46 @@ "docs": { "calls": [] }, - "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", + "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": "claude-code-sonnet-5/resolve-dataapi-001-empty-results.json" + "sourcePath": "claude-code-sonnet-5/resolve-security-002-rls-cross-tenant-leak.json" }, { - "experiment": "claude-code-sonnet-5", - "experimentSuite": "benchmark", + "experiment": "claude-code-sonnet-5-no-skills", + "experimentSuite": "no-skills", "experimentDisplay": { "agent": "claude-code", "modelProvider": "anthropic", "modelId": "claude-sonnet-5", "reasoningEffort": "high" }, - "eval": "resolve-database-001-migration-history-mismatch", - "stage": "resolve", + "eval": "build-cli-001-bootstrap-app", + "stage": "build", "product": [ - "database" + "database", + "data-api" ], "topic": [ - "migrations" + "migrations", + "rls" ], "suite": "benchmark", "interface": "cli", "passed": true, "checks": [ { - "name": "the avatar_url column is applied on the hosted profiles table", + "name": "supabase project initialised (supabase/config.toml exists)", "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": 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." - } - ], - "skills": { - "available": [ - "supabase", - "supabase-postgres-best-practices" - ], - "loaded": [ - "supabase" - ] - }, - "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": 1, - "sourcePath": "claude-code-sonnet-5/resolve-database-001-migration-history-mismatch.json" - }, - { - "experiment": "claude-code-sonnet-5", - "experimentSuite": "benchmark", - "experimentDisplay": { - "agent": "claude-code", - "modelProvider": "anthropic", - "modelId": "claude-sonnet-5", - "reasoningEffort": "high" - }, - "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=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", - "passed": true - } - ], - "skills": { - "available": [ - "supabase", - "supabase-postgres-best-practices" - ], - "loaded": [ - "supabase" - ] - }, - "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": "claude-code-sonnet-5/resolve-performance-001-slow-query-cpu-spike.json" - }, - { - "experiment": "claude-code-sonnet-5", - "experimentSuite": "benchmark", - "experimentDisplay": { - "agent": "claude-code", - "modelProvider": "anthropic", - "modelId": "claude-sonnet-5", - "reasoningEffort": "high" - }, - "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" - ] - }, - "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", - "attempts": 1, - "sourcePath": "claude-code-sonnet-5/resolve-security-002-rls-cross-tenant-leak.json" - }, - { - "experiment": "claude-code-sonnet-5-no-skills", - "experimentSuite": "no-skills", - "experimentDisplay": { - "agent": "claude-code", - "modelProvider": "anthropic", - "modelId": "claude-sonnet-5", - "reasoningEffort": "high" - }, - "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", + "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" + "notes": "found 3 rows" }, { "name": "row level security is enabled on todos", @@ -5751,7 +5030,7 @@ { "name": "REST API returns the todos to authenticated requests", "passed": true, - "notes": "2 rows" + "notes": "3 rows" } ], "skills": { @@ -5855,7 +5134,7 @@ { "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": { @@ -6011,7 +5290,7 @@ "suite": "benchmark", "interface": "cli", "cliVersion": "2.109.1", - "passed": false, + "passed": true, "checks": [ { "name": "seed rows present", @@ -6021,42 +5300,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\":\"47f512a7-5c36-4b54-9afa-57decd8830d9\",\"metric\":\"steps_a_msgiwrbv\",\"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\":\"47f512a7-5c36-4b54-9afa-57decd8830d9\",\"metric\":\"steps_a_msgiwrbv\",\"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\":\"6097a397-7038-4a49-a80e-b31f0034d500\",\"metric\":\"steps_b_msgiwrbv\",\"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,52 +5343,149 @@ "loaded": [] }, "docs": { - "calls": [] - }, - "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": "claude-code-sonnet-5-no-skills/build-functions-005-dual-auth-user-secret.json" - }, - { - "experiment": "claude-code-sonnet-5-no-skills", - "experimentSuite": "no-skills", - "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 - }, - { + "calls": [ + { + "source": "search_docs", + "query": "{ searchDocs(query: \"withSupabase edge function auth publishable secret user ctx.user ctx.supabaseAdmin\", limit: 8) { 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/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/quickstart-dashboard", + "title": "Getting Started with Edge Functions (Dashboard)" + } + ], + "resultChars": 66458 + }, + { + "source": "search_docs", + "query": "{ searchDocs(query: \"verify_jwt Authorization headers combining auth modes secret key platform check\", limit: 5) { 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/functions/auth-headers", + "title": "Authorization headers" + }, + { + "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/auth/jwt-fields", + "title": "JWT Claims Reference" + } + ], + "resultChars": 47296 + }, + { + "source": "search_docs", + "query": "{ searchDocs(query: \"userClaims type id email role jwtClaims supabase/server package interface\", limit: 5) { 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/realtime/authorization", + "title": "Realtime Authorization" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields", + "title": "JWT Claims Reference" + }, + { + "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-nextjs", + "title": "Build a User Management App with Next.js" + } + ], + "resultChars": 103611 + } + ] + }, + "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-no-skills/build-functions-005-dual-auth-user-secret.json" + }, + { + "experiment": "claude-code-sonnet-5-no-skills", + "experimentSuite": "no-skills", + "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: 019fb0e7-0613-730a-ae13-0efd0c195137/receipt-alpha.pdf, 019fb0e7-0613-730a-ae13-0efd0c195137/receipt-beta.pdf" + "notes": "saw: 019fd385-2041-75ef-b1ba-4b4d12857be9/receipt-alpha.pdf, 019fd385-2041-75ef-b1ba-4b4d12857be9/receipt-beta.pdf" }, { "name": "user B cannot read user A files", @@ -6130,7 +5506,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 requirements: private bucket, authenticated owner-scoped SELECT and INSERT policies with WITH CHECK, no RLS disabling or permissive/public policies, and uses createSignedUrl with expiry for sharing." } ], "skills": { @@ -6170,17 +5546,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/tenant_isolation.test.sql" }, { "name": "pgTAP isolation tests ran and pass", "passed": true, - "notes": "6 passed, 2 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 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 do not belong to, and grounds the conclusion in pgTAP failures (#4 and #6). It treats the test results as authoritative and distinguishes notes as correctly isolated." } ], "skills": { @@ -6226,12 +5602,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_cosine_ops)" + "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_cosine_ops)" + "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", @@ -6258,31 +5634,23 @@ "calls": [ { "source": "search_docs", - "query": "{ searchDocs(query: \"match_document_sections pgvector edge function embeddings\", limit: 5) { nodes { title href content } } }", + "query": "{ searchDocs(query: \"gte-small embedding model dimensions 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/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/functions/examples/semantic-search", + "title": "Semantic Search" }, { - "url": "https://supabase.com/docs/guides/ai/hybrid-search", - "title": "Hybrid search" + "url": "https://supabase.com/docs/guides/ai/concepts", + "title": "Concepts" } ], - "resultChars": 68270 + "resultChars": 23525 } ] }, @@ -6309,7 +5677,7 @@ "observability" ], "suite": "benchmark", - "passed": false, + "passed": true, "checks": [ { "name": "preserved existing app scrape job", @@ -6317,13 +5685,13 @@ }, { "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." + "passed": true, + "judgeNotes": "Meets rubric: preserves app scrape, adds HTTPS Supabase Metrics API scrape to project .supabase.co target with correct path and Basic Auth password_file, and docker-compose mounts the password file read-only." }, { "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 steps to create/copy a Supabase Secret API key, place it in the mounted secrets/supabase_api_key file, reload Prometheus, and verify via Prometheus Targets or direct metrics curl. Endpoint and auth setup match the config and no real secret is hardcoded." } ], "skills": { @@ -6334,27 +5702,31 @@ "calls": [ { "source": "search_docs", - "query": "{ searchDocs(query: \"self-hosted metrics endpoint prometheus\", limit: 5) { nodes { title href content } } }", + "query": "{ searchDocs(query: \"project metrics endpoint prometheus\", limit: 5) { 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/telemetry/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/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", + "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/replication/manual-replication-monitoring", + "title": "Manual replication monitoring" } ], - "resultChars": 23542 + "resultChars": 23548 } ] }, @@ -6408,7 +5780,36 @@ "loaded": [] }, "docs": { - "calls": [] + "calls": [ + { + "source": "search_docs", + "query": "{ searchDocs(query: \"management api invoke edge function endpoint\", limit: 5) { nodes { title href content } } }", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/getting-started/features", + "title": "Features" + }, + { + "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/reference/cli/supabase-functions", + "title": "Manage Supabase Edge functions" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/docker", + "title": "Self-Hosting with Docker" + } + ], + "resultChars": 66572 + } + ] }, "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", @@ -6518,7 +5919,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": "The answer identifies soft-delete-only behavior, implements real auth-layer revocation by banning the auth user and deleting sessions/refresh tokens, adds RLS checks to close the data-access window for stale JWTs, and consistently explains that stateless JWTs remain locally valid until expiry. It also correctly distinguishes publishable frontend keys from secret server-only keys that bypass RLS." } ], "skills": { @@ -6526,21 +5927,7 @@ "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": [] }, "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", @@ -6593,7 +5980,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 missing orders table in supabase_realtime publication despite SUBSCRIBED status, fixed with ALTER PUBLICATION ADD TABLE public.orders, and did not weaken RLS/policies or disturb courier_locations." } ], "skills": { @@ -6632,17 +6019,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": "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": "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 recurring image-transform 503s to the gateway/infrastructure layer, grounded in the observation that 503s lack execution metadata/runtime invocation while 200s have deployment/version/execution data, and distinguishes them from the avatar-upload function-level 500." }, { "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 provided multiple concrete next steps: pulling runtime logs for specific timestamps, checking deployment version and possible rollback, checking memory/CPU limits, adding 5xx alerting, and investigating the correlated avatar-upload 500." } ], "skills": { @@ -6708,7 +6095,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 deny-all due to no policies, added authenticated SELECT and INSERT owner-scoped policies using auth.uid() = user_id / WITH CHECK, and kept RLS enabled." } ], "skills": { @@ -6767,7 +6154,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": "Avatar_url was applied through `supabase db push --yes`, which output `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` The orphan bio migration was reconciled by adding the missing local file `supabase/migrations/20240115000000_add_profile_bio.sql`, after which `supabase migration list` showed local and remote aligned; the subsequent push proceeded successfully. Only read-only `psql` inspection was used; no direct SQL mutation or prepared-statement workaround was seen." } ], "skills": { @@ -6971,38 +6358,70 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" ] }, "docs": { "calls": [ + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"curl -fsSL https://supabase.com/changelog.md | sed -n '1,120p'\"", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/changelog.md" + } + ], + "resultChars": 6745 + }, { "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 {\n searchDocs(query: \"local development migrations RLS expose table to data api authenticated anon grant select\", limit: 5) {\n nodes {\n title\n href\n content\n }\n }\n}", "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/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/getting-started/tutorials/with-flutter", + "title": "Build a User Management App with Flutter" }, { - "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-nextjs", + "title": "Build a User Management App with Next.js" + } + ], + "resultChars": 152845 + }, + { + "source": "search_docs", + "query": "query {\n searchDocs(query: \"Securing your API grants authenticated anon select public table RLS\", limit: 3) {\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", + "title": "Row Level Security" }, { - "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/api/securing-your-api", + "title": "Securing your API" + }, + { + "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" } ], - "resultChars": 163038 + "resultChars": 57503 } ] }, @@ -7056,13 +6475,54 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" ] }, "docs": { - "calls": [] - }, - "prompt": "Add a description text column to the `products` table in my local Supabase stack", + "calls": [ + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"curl -fsSL https://supabase.com/changelog.md | sed -n '1,120p'\"", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/changelog.md" + } + ], + "resultChars": 6745 + }, + { + "source": "search_docs", + "query": "query {\n searchDocs(query: \"declarative database schemas migrations generate migration local schema_paths\", limit: 5) {\n nodes {\n title\n href\n content\n }\n }\n}", + "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" + }, + { + "url": "https://supabase.com/docs/guides/database/prisma/prisma-troubleshooting", + "title": "Troubleshooting prisma errors" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers", + "title": "Multiple SSO Providers" + } + ], + "resultChars": 86950 + } + ] + }, + "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" @@ -7100,7 +6560,7 @@ { "name": "cron command enqueues to the 'tasks' queue", "passed": true, - "notes": "queue depth 1 -> 2" + "notes": "queue depth 0 -> 1" }, { "name": "process-tasks function drains the queue", @@ -7114,24 +6574,53 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" ] }, "docs": { "calls": [ { "source": "search_docs", - "query": "query { searchDocs(query: \"pg_cron schedule cron jobs Supabase local development\", limit: 5) { nodes { title href content } } }", + "query": "{ searchDocs(query:\"Supabase Edge Functions queue consumer messages pgmq\", limit: 5) { nodes { title href content } } }", "hasContent": true, "pages": [ { - "url": "https://supabase.com/docs/guides/cron", - "title": "Cron" + "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/examples/resumable-websockets", + "title": "Resumable WebSockets with Edge Functions" }, + { + "url": "https://supabase.com/docs/guides/queues/quickstart", + "title": "Quickstart" + } + ], + "resultChars": 26971 + }, + { + "source": "search_docs", + "query": "{ searchDocs(query:\"pg_cron schedule cron.schedule Supabase local database\", 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/cron", + "title": "Cron" + }, { "url": "https://supabase.com/docs/guides/auth/auth-hooks/send-email-hook", "title": "Send Email Hook" @@ -7149,59 +6638,42 @@ }, { "source": "search_docs", - "query": "query { searchDocs(query: \"Supabase Queues pgmq pop send delete read edge functions local development\", limit: 5) { nodes { title href content } } }", + "query": "{ searchDocs(query:\"pgmq pop delete read queue edge function Supabase\", limit: 5) { nodes { title href content } } }", "hasContent": true, "pages": [ - { - "url": "https://supabase.com/docs/guides/queues", - "title": "Supabase Queues" - }, { "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/recursive-functions", + "title": "Recursive / Nested Function Calls" + }, { "url": "https://supabase.com/docs/guides/queues/api", "title": "API" }, { - "url": "https://supabase.com/docs/guides/local-development/cli/testing-and-linting", - "title": "Testing and linting" + "url": "https://supabase.com/docs/guides/queues", + "title": "Supabase Queues" }, { "url": "https://supabase.com/docs/guides/functions/architecture", "title": "Edge Functions Architecture" } ], - "resultChars": 18872 + "resultChars": 25911 }, { - "source": "search_docs", - "query": "query { searchDocs(query: \"Supabase edge functions local development deploy serve deno\", limit: 5) { nodes { title href content } } }", + "source": "shell_fetch", + "query": "/bin/bash -lc \"curl -fsSL https://supabase.com/changelog.md | sed -n '1,220p'\"", "hasContent": true, "pages": [ { - "url": "https://supabase.com/docs/guides/functions/quickstart", - "title": "Getting Started with Edge Functions" - }, - { - "url": "https://supabase.com/docs/guides/functions/quickstart-dashboard", - "title": "Getting Started with Edge Functions (Dashboard)" - }, - { - "url": "https://supabase.com/docs/guides/functions", - "title": "Edge Functions" - }, - { - "url": "https://supabase.com/docs/guides/functions/development-environment", - "title": "Development Environment" - }, - { - "url": "https://supabase.com/docs/guides/functions/examples/mcp-server-mcp-lite", - "title": "Building an MCP Server with mcp-lite" + "url": "https://supabase.com/changelog.md" } ], - "resultChars": 47492 + "resultChars": 12701 } ] }, @@ -7258,11 +6730,100 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" ] }, "docs": { - "calls": [] + "calls": [ + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"curl -fsSL https://supabase.com/changelog.md | sed -n '1,220p'\"", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/changelog.md" + } + ], + "resultChars": 12701 + }, + { + "source": "search_docs", + "query": "query {\n searchDocs(query: \"restore dump local development supabase db restore pg_restore binary dump\", limit: 5) {\n nodes {\n title\n href\n content\n }\n }\n}", + "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/local-development/restoring-downloaded-backup", + "title": "Restoring a downloaded backup locally" + }, + { + "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres", + "title": "Migrate from Postgres to Supabase" + }, + { + "url": "https://supabase.com/docs/guides/troubleshooting/download-logical-backups", + "title": "How to download logical backups in Supabase with physical backups enabled?" + }, + { + "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/vercel-postgres", + "title": "Migrate from Vercel Postgres to Supabase" + } + ], + "resultChars": 39503 + }, + { + "source": "search_docs", + "query": "query {\n searchDocs(query: \"postgres-version local development supabase .temp/postgres-version pg17 start\", limit: 10) {\n nodes {\n title\n href\n content\n }\n }\n}", + "hasContent": true, + "pages": [ + { + "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/postgres-upgrade-17", + "title": "Upgrade to Postgres 17" + }, + { + "url": "https://supabase.com/docs/guides/ai/examples/building-chatgpt-plugins", + "title": "Building ChatGPT plugins" + }, + { + "url": "https://supabase.com/docs/guides/functions/development-environment", + "title": "Development Environment" + }, + { + "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" + }, + { + "url": "https://supabase.com/docs/guides/ai/vecs-python-client", + "title": "Python client" + }, + { + "url": "https://supabase.com/docs/guides/platform/upgrading", + "title": "Upgrading" + }, + { + "url": "https://supabase.com/docs/guides/local-development/cli-workflows", + "title": "Local development workflow" + }, + { + "url": "https://supabase.com/docs/guides/local-development/cli/getting-started", + "title": "Supabase CLI" + } + ], + "resultChars": 97512 + } + ] }, "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", @@ -7312,12 +6873,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": { @@ -7326,95 +6887,39 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" ] }, "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}", + "query": "query { searchDocs(query: \"Supabase Edge Functions forward Authorization header supabase-js createClient anon key auth.getUser verify_jwt\", limit: 5) { nodes { title href ... on Guide { content } ... on ClientLibraryFunctionReference { language methodName 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/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/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?" - } - ], - "resultChars": 45333 - }, - { - "source": "web_search", - "query": "https://supabase.com/changelog.md", - "pages": [ - { - "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/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/functions/secrets", - "title": "Environment Variables" + "url": "https://supabase.com/docs/guides/functions/websockets", + "title": "Handling WebSockets" }, { - "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions", - "title": "Self-Hosted Functions" + "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", - "title": "Securing Edge Functions" - }, - { - "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/examples/elevenlabs-generate-speech-stream", - "title": "Streaming Speech with ElevenLabs" - }, - { - "url": "https://supabase.com/docs/guides/integrations/vercel-marketplace", - "title": "Vercel Marketplace" - }, - { - "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/api-keys", - "title": "Understanding API keys" } ], - "resultChars": 189134 + "resultChars": 49916 } ] }, @@ -7450,11 +6955,51 @@ "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" - } - ], + "name": "seed rows present", + "passed": true, + "notes": "found 2/2 seeded rows" + }, + { + "name": "rejects request with no credentials", + "passed": true, + "notes": "status 503: {\"message\":\"name resolution failed\"}" + }, + { + "name": "user with JWT reads only their own rows", + "passed": false, + "notes": "status 503: {\"message\":\"name resolution failed\"}" + }, + { + "name": "user cannot read another user's rows by passing user_id", + "passed": false, + "notes": "status 503: {\"message\":\"name resolution failed\"}" + }, + { + "name": "service key bypasses RLS to read the target user's rows", + "passed": false, + "notes": "status 503: {\"message\":\"name resolution failed\"}" + }, + { + "name": "non-service key is not granted service access", + "passed": true, + "notes": "status 503: {\"message\":\"name resolution failed\"}" + }, + { + "name": "rejects an unverified (forged) user token", + "passed": true, + "notes": "status 503: {\"message\":\"name resolution failed\"}" + }, + { + "name": "a user token in the apikey slot is not treated as the service key", + "passed": true, + "notes": "status 503: {\"message\":\"name resolution failed\"}" + }, + { + "name": "implementation uses @supabase/server", + "passed": true, + "notes": "imports @supabase/server / withSupabase" + } + ], "skills": { "available": [ "supabase", @@ -7469,7 +7014,7 @@ "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 } } }", + "query": "query { searchDocs(query: \"Edge Functions authentication verify JWT service role supabase-js Deno user token\", limit: 5) { nodes { title href content ... on Guide { subsections { nodes { title href content } } } } } }", "hasContent": true, "pages": [ { @@ -7477,703 +7022,486 @@ "title": "Integrating With Supabase Auth" }, { - "url": "https://supabase.com/docs/guides/functions/websockets", - "title": "Handling WebSockets" + "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt#example", + "title": "Example" + }, + { + "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt#row-level-security", + "title": "Row Level Security" + }, + { + "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt#fetching-the-user", + "title": "Fetching the user" + }, + { + "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt#setting-up-auth-context", + "title": "Setting up auth context" }, { "url": "https://supabase.com/docs/guides/functions", "title": "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#how-it-works", + "title": "How it works" + }, + { + "url": "https://supabase.com/docs/guides/functions#quick-technical-notes", + "title": "Quick technical notes" + }, + { + "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#examples", + "title": "Examples" }, { "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/functions/function-configuration", - "title": "Function Configuration" + "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets#database-schema", + "title": "Database schema" }, { - "url": "https://supabase.com/docs/guides/functions/deploy", - "title": "Deploy to Production" + "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets#browser-client", + "title": "Browser client" }, { - "url": "https://supabase.com/docs/guides/functions/development-tips", - "title": "Development tips" + "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/functions/examples/github-actions", - "title": "GitHub Actions" + "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets#next-steps", + "title": "Next steps" }, { - "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/functions/examples/resumable-websockets#architecture", + "title": "Architecture" + }, { - "url": "https://supabase.com/docs/guides/functions/development-tips", - "title": "Development tips" + "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/functions/dependencies", - "title": "Managing dependencies" + "url": "https://supabase.com/docs/guides/functions/websockets", + "title": "Handling WebSockets" }, { - "url": "https://supabase.com/docs/guides/functions/function-configuration", - "title": "Function Configuration" + "url": "https://supabase.com/docs/guides/functions/websockets#testing-websockets-locally", + "title": "Testing WebSockets locally" }, { - "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/websockets#authentication", + "title": "Authentication" }, { - "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/functions/websockets#outbound-websockets", + "title": "Outbound WebSockets" + }, { - "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals", - "title": "Storage Buckets" + "url": "https://supabase.com/docs/guides/functions/websockets#creating-websocket-servers", + "title": "Creating WebSocket servers" }, { - "url": "https://supabase.com/docs/guides/storage/security/access-control", - "title": "Storage Access Control" + "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/custom-roles", - "title": "Custom Roles" + "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/self-hosting/self-hosted-s3", - "title": "Configure S3 Storage" + "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" } ], - "resultChars": 20163 + "resultChars": 108496 }, { "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 } } } }", + "query": "query { searchDocs(query: \"Supabase Edge Functions environment variables verify JWT apikey header\", limit: 5) { nodes { title href content ... on Guide { subsections { nodes { title href content } } } } } }", "hasContent": true, "pages": [ { - "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/serving/downloads", - "title": "Serving assets from Storage" + "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/storage/cdn/smart-cdn", - "title": "Smart CDN" + "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/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/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/ai/rag-with-permissions", - "title": "RAG with Permissions" + "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/ai/automatic-embeddings", - "title": "Automatic embeddings" + "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/ai/hybrid-search", - "title": "Hybrid search" + "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/database/extensions/pgvector", - "title": "pgvector: Embeddings and vector similarity" + "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/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/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/ai/vector-columns", - "title": "Vector columns" + "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/database/extensions/pgvector", - "title": "pgvector: Embeddings and vector similarity" + "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/ai/vector-indexes/hnsw-indexes", - "title": "HNSW indexes" + "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys#known-limitations", + "title": "Known limitations" }, { - "url": "https://supabase.com/docs/guides/ai/semantic-search", - "title": "Semantic search" + "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys#next-steps", + "title": "Next steps" }, { - "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/functions/auth", + "title": "Securing Edge Functions" + }, { - "url": "https://supabase.com/docs/guides/ai/rag-with-permissions", - "title": "RAG with Permissions" + "url": "https://supabase.com/docs/guides/functions/auth#custom-error-responses", + "title": "Custom error responses" }, { - "url": "https://supabase.com/docs/guides/storage/schema/helper-functions", - "title": "Storage Helper Functions" + "url": "https://supabase.com/docs/guides/functions/auth#environment-variables", + "title": "Environment variables" }, { - "url": "https://supabase.com/docs/guides/storage/security/access-control", - "title": "Storage Access Control" + "url": "https://supabase.com/docs/guides/functions/auth#authenticated-user-calls", + "title": "Authenticated user calls" }, { - "url": "https://supabase.com/docs/guides/auth/users", - "title": "Users" + "url": "https://supabase.com/docs/guides/functions/auth#service-to-service-calls", + "title": "Service-to-service calls" }, { - "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/functions/auth#public-functions", + "title": "Public functions" + }, { - "url": "https://supabase.com/docs/guides/telemetry/metrics", - "title": "Metrics API" + "url": "https://supabase.com/docs/guides/functions/auth#external-webhooks", + "title": "External webhooks" }, { - "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/functions/auth#combining-modes", + "title": "Combining modes" }, { - "url": "https://supabase.com/docs/guides/telemetry/metrics/vendor-agnostic", - "title": "Vendor-agnostic Metrics API setup" + "url": "https://supabase.com/docs/guides/getting-started/api-keys", + "title": "Understanding API keys" }, { - "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-cloud", - "title": "Metrics API with Grafana Cloud" + "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/platform/read-replicas", - "title": "Read Replicas" + "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/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#publishable-keys", + "title": "Publishable keys" + }, + { + "url": "https://supabase.com/docs/guides/getting-started/api-keys#overview", + "title": "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/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/self-hosted-auth-keys#backward-compatibility", + "title": "Backward compatibility" + }, + { + "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#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#additional-resources", + "title": "Additional resources" + }, + { + "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#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#request-flows", + "title": "Request flows" + }, + { + "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/auth/jwts", + "title": "JSON Web Token (JWT)" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwts#resources", + "title": "Resources" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwts#introduction", + "title": "Introduction" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwts#supabase-and-jwts", + "title": "Supabase and JWTs" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwts#using-custom-or-third-party-jwts", + "title": "Using custom or third-party JWTs" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwts#verifying-a-jwt-from-supabase", + "title": "Verifying a JWT from Supabase" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwts#verifying-with-a-shared-secret-signing-key", + "title": "Verifying with a shared secret signing key" } ], - "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": [ + "resultChars": 151372 + }, { "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 } } } }", + "query": "query { searchDocs(query: \"Supabase Edge Functions request headers apikey verify secret key auth user\", 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/functions/auth", + "title": "Securing 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/migrating-to-new-api-keys", + "title": "Migrating to publishable and secret API keys" }, { - "url": "https://supabase.com/docs/guides/functions/http-methods", - "title": "Routing" + "url": "https://supabase.com/docs/guides/getting-started/api-keys", + "title": "Understanding API keys" }, { - "url": "https://supabase.com/docs/guides/local-development/cli/testing-and-linting", - "title": "Testing and linting" + "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/cors", - "title": "CORS (Cross-Origin Resource Sharing) support for Invoking from the browser" + "url": "https://supabase.com/docs/guides/functions/auth-headers", + "title": "Authorization headers" } ], - "resultChars": 32587 + "resultChars": 53802 }, { "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 } } } }", + "query": "query { searchDocs(query: \"Edge Functions verify_jwt config.toml functions verify_jwt false\", 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/function-configuration", + "title": "Function Configuration" }, { - "url": "https://supabase.com/docs/guides/ai/automatic-embeddings", - "title": "Automatic embeddings" + "url": "https://supabase.com/docs/guides/functions/deploy", + "title": "Deploy to Production" }, { - "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-generate-speech-stream", - "title": "Streaming Speech with ElevenLabs" + "url": "https://supabase.com/docs/guides/functions/development-tips", + "title": "Development tips" }, { - "url": "https://supabase.com/docs/guides/functions/secrets", - "title": "Environment Variables" + "url": "https://supabase.com/docs/guides/functions/examples/github-actions", + "title": "GitHub Actions" }, { - "url": "https://supabase.com/docs/guides/functions/examples/elevenlabs-transcribe-speech", - "title": "Transcription Telegram Bot" + "url": "https://supabase.com/docs/guides/functions/auth-headers", + "title": "Authorization headers" } ], - "resultChars": 70876 + "resultChars": 20397 }, { "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 } } } }", + "query": "query { searchDocs(query: \"supabase functions new deno.json entrypoint config.toml function folder\", limit: 5) { nodes { title href content } } }", "hasContent": true, "pages": [ { - "url": "https://supabase.com/docs/guides/functions/error-codes", - "title": "Error codes" + "url": "https://supabase.com/docs/guides/functions/dependencies", + "title": "Managing dependencies" }, { - "url": "https://supabase.com/docs/guides/functions/auth-headers", - "title": "Authorization headers" + "url": "https://supabase.com/docs/guides/functions/development-tips", + "title": "Development tips" }, { - "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt", - "title": "Integrating With Supabase Auth" + "url": "https://supabase.com/docs/guides/functions/unit-test", + "title": "Testing your Edge Functions" }, { - "url": "https://supabase.com/docs/guides/functions/status-codes", - "title": "Status codes" + "url": "https://supabase.com/docs/guides/functions/development-environment", + "title": "Development Environment" }, { "url": "https://supabase.com/docs/guides/functions/function-configuration", "title": "Function Configuration" } ], - "resultChars": 26210 + "resultChars": 26445 }, { "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 } } } }", + "query": "query { searchDocs(query: \"supabase functions folder config.toml deno.json index.ts\", limit: 5) { nodes { title href content } } }", "hasContent": true, "pages": [ { - "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/functions/development-environment", + "title": "Development Environment" }, { - "url": "https://supabase.com/docs/guides/getting-started/features", - "title": "Features" + "url": "https://supabase.com/docs/guides/functions/dependencies", + "title": "Managing dependencies" }, { - "url": "https://supabase.com/docs/guides/functions/auth-headers", - "title": "Authorization headers" + "url": "https://supabase.com/docs/guides/local-development/managing-config", + "title": "Managing config and secrets" }, { - "url": "https://supabase.com/docs/guides/getting-started/api-keys", - "title": "Understanding API keys" + "url": "https://supabase.com/docs/guides/functions/unit-test", + "title": "Testing your Edge Functions" }, { - "url": "https://supabase.com/docs/guides/functions/error-codes", - "title": "Error codes" + "url": "https://supabase.com/docs/guides/functions/development-tips", + "title": "Development tips" } ], - "resultChars": 42697 + "resultChars": 26005 } ] }, - "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" + "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", @@ -8184,35 +7512,57 @@ "modelId": "gpt-5.4-mini", "reasoningEffort": "medium" }, - "eval": "deploy-self-hosting-001-docker-compose", - "stage": "deploy", + "eval": "build-storage-001-private-bucket-access", + "stage": "build", "product": [ - "database", - "auth", - "storage" + "storage", + "database" ], "topic": [ - "self-hosting" + "rls", + "sdk" ], "suite": "benchmark", - "interface": "cli", + "interface": "mcp", "passed": true, "checks": [ { - "name": "cloned the self-host stack (docker-compose.yml + volumes/db)", + "name": "bucket user-files exists", "passed": true }, { - "name": "didn't conflate with the CLI (no supabase/config.toml in the stack)", + "name": "bucket user-files is private", "passed": true }, { - "name": "secrets rotated off the shipped defaults", + "name": "RLS still enabled on storage.objects", "passed": true }, { - "name": "ANON_KEY and SERVICE_ROLE_KEY are HS256 JWTs signed by JWT_SECRET", + "name": "user A lists only own files", + "passed": true, + "notes": "saw: 019fd385-5d7f-73eb-bfec-77c78b45e381/receipt-alpha.pdf, 019fd385-5d7f-73eb-bfec-77c78b45e381/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": "The answer creates a private user-files bucket, keeps storage.objects RLS enabled, defines authenticated-role SELECT and INSERT policies scoped to the bucket and first path segment matching auth.uid(), and provides supabase-js createSignedUrl code with a 15-minute expiry. It does not make the bucket public, use public/anon policies, disable RLS, use getPublicUrl, or expose a service role key." } ], "skills": { @@ -8221,73 +7571,46 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" ] }, "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}", + "query": "query { searchDocs(query: \"Supabase Storage RLS policies bucket user folders signed URLs\", limit: 5) { nodes { __typename title href ... on Guide { content } ... on ClientLibraryFunctionReference { content language methodName } ... on TroubleshootingGuide { 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/storage/schema/helper-functions", + "title": "Storage Helper 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/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-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/self-hosting/restore-from-platform", - "title": "Restore a Platform Project to Self-Hosted" + "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/self-hosting/self-hosted-proxy-https", - "title": "Configure Reverse Proxy and HTTPS" + "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals", + "title": "Storage Buckets" }, { - "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17", - "title": "Upgrade to Postgres 17" + "url": "https://supabase.com/docs/guides/auth/third-party/clerk", + "title": "Clerk" }, { - "url": "https://supabase.com/docs/guides/queues/expose-self-hosted-queues", - "title": "Expose Queues for local and self-hosted Supabase" + "url": "https://supabase.com/docs/guides/storage/serving/downloads", + "title": "Serving assets from Storage" } ], - "resultChars": 69788 + "resultChars": 60712 } ] }, - "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", + "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/deploy-self-hosting-001-docker-compose.json" + "sourcePath": "codex-gpt-5.4-mini/build-storage-001-private-bucket-access.json" }, { "experiment": "codex-gpt-5.4-mini", @@ -8298,48 +7621,33 @@ "modelId": "gpt-5.4-mini", "reasoningEffort": "medium" }, - "eval": "investigate-auth-001-deleted-user-access", - "stage": "investigate", + "eval": "build-tests-001-rls-tenant-isolation", + "stage": "build", "product": [ - "auth" + "database" ], "topic": [ - "security", - "sdk" + "tests", + "rls" ], "suite": "benchmark", - "interface": "mcp", + "interface": "cli", "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", + "name": "pgTAP test file(s) written under supabase/tests/", "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 + "notes": "1 file(s): supabase/tests/tenant_isolation_test.sql" }, { - "name": "other users keep their sessions and access", - "passed": true + "name": "pgTAP isolation tests ran and pass", + "passed": true, + "notes": "4 passed, 0 failed" }, { - "name": "diagnosed and explained session revocation", + "name": "agent correctly identifies the posts isolation bug from test results", "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." + "judgeNotes": "Correctly identifies `posts` as the broken tenant isolation policy, states that any authenticated org member could read posts regardless of `org_id`, distinguishes `notes` as covered/correct, and uses the pgTAP run as validation after fixing." } ], "skills": { @@ -8348,690 +7656,437 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" ] }, "docs": { "calls": [ { "source": "search_docs", - "query": "query { searchDocs(query: \"publishable secret keys anon service_role frontend RLS\", limit: 5) { nodes { title href content } } }", + "query": "query { searchDocs(query: \"Supabase database tests RLS pgtap tenant isolation auth.uid()\", 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/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/local-development/testing/pgtap-extended#using-databasedev", + "title": "Using database.dev" }, { - "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#installing-test-helpers", + "title": "Installing test helpers" }, { - "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/local-development/testing/pgtap-extended#test-helper-benefits", + "title": "Test helper benefits" + }, { - "url": "https://supabase.com/docs/guides/auth/managing-user-data", - "title": "User Management" + "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/reference/javascript/auth-admin-deleteuser" + "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#test-file-organization", + "title": "Test file organization" }, { - "url": "https://supabase.com/docs/reference/dart/auth-admin-deleteuser" + "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/platform/sso/multiple-providers", - "title": "Multiple SSO Providers" + "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#benefits", + "title": "Benefits" }, { - "url": "https://supabase.com/docs/reference/swift/auth-admin-deleteuser", - "title": "deleteUser()" - } - ], - "resultChars": 27499 - }, - { - "source": "search_docs", - "query": "query { searchDocs(query: \"row level security auth.uid deleted flag policy\", limit: 5) { nodes { title href content } } }", - "hasContent": true, - "pages": [ + "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/local-development/cli-workflows", - "title": "Local development workflow" + "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/storage/management/delete-objects", - "title": "Delete Objects" + "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#system-overview", + "title": "System overview" }, { - "url": "https://supabase.com/docs/guides/database/postgres/row-level-security", - "title": "Row Level Security" + "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/auth/auth-mfa", - "title": "Multi-Factor Authentication" + "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#testing-focus-areas", + "title": "Testing focus areas" }, { - "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/local-development/testing/pgtap-extended#1-app-schema-definitions", + "title": "1. App schema definitions" + }, { - "url": "https://supabase.com/docs/reference/javascript/auth-signout" + "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/reference/javascript/auth-admin-deleteuser" + "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/auth/managing-user-data", - "title": "User Management" + "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#4-test-cases", + "title": "4. Test cases:" }, { - "url": "https://supabase.com/docs/reference/dart/auth-admin-deleteuser" + "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#additional-resources", + "title": "Additional resources" }, { - "url": "https://supabase.com/docs/guides/integrations/build-a-supabase-oauth-integration", - "title": "Build a Supabase Integration" + "url": "https://supabase.com/docs/guides/local-development/testing/overview", + "title": "Testing Overview" }, { - "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/local-development/testing/overview#troubleshooting", + "title": "Troubleshooting" }, { - "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows", - "title": "OAuth 2.1 Flows" + "url": "https://supabase.com/docs/guides/local-development/testing/overview#additional-resources", + "title": "Additional resources" }, { - "url": "https://supabase.com/docs/reference/javascript/oauth-admin", - "title": "OAuth Admin" + "url": "https://supabase.com/docs/guides/local-development/testing/overview#testing-approaches", + "title": "Testing approaches" }, { - "url": "https://supabase.com/docs/reference/swift/auth-admin-deleteuser", - "title": "deleteUser()" + "url": "https://supabase.com/docs/guides/local-development/testing/overview#database-unit-testing-with-pgtap", + "title": "Database unit testing with pgTAP" }, { - "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/local-development/testing/overview#application-level-testing", + "title": "Application-Level testing" + }, { - "url": "https://supabase.com/docs/guides/auth/sessions", - "title": "User sessions" + "url": "https://supabase.com/docs/guides/local-development/testing/overview#test-isolation-strategies", + "title": "Test isolation strategies" }, { - "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows", - "title": "OAuth 2.1 Flows" + "url": "https://supabase.com/docs/guides/local-development/testing/overview#continuous-integration-testing", + "title": "Continuous integration testing" }, { - "url": "https://supabase.com/docs/guides/resources/glossary", - "title": "Glossary" + "url": "https://supabase.com/docs/guides/local-development/testing/overview#best-practices", + "title": "Best practices" }, { - "url": "https://supabase.com/docs/reference/javascript/oauth-server-revokegrant" + "url": "https://supabase.com/docs/guides/local-development/testing/overview#real-world-examples", + "title": "Real-World examples" }, { - "url": "https://supabase.com/docs/guides/auth/managing-user-data", - "title": "User Management" + "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security", + "title": "Token Security and 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/auth/oauth-server/token-security#how-oauth-tokens-work-with-rls", + "title": "How OAuth tokens work with RLS" }, { - "url": "https://supabase.com/docs/guides/auth/signing-keys", - "title": "JWT Signing Keys" + "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#token-structure", + "title": "Token structure" }, { - "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/auth/oauth-server/token-security#extracting-oauth-claims-in-rls", + "title": "Extracting OAuth claims in RLS" }, { - "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/oauth-server/token-security#common-rls-patterns-for-oauth", + "title": "Common RLS patterns for OAuth" }, { - "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/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/reference/javascript/auth-signout" + "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/auth/passkeys", - "title": "Passkey authentication" + "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/database/postgres/row-level-security", - "title": "Row Level Security" + "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/auth/signout", - "title": "Signing out" + "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#real-world-examples", + "title": "Real-world examples" }, { - "url": "https://supabase.com/docs/guides/auth/managing-user-data", - "title": "User Management" + "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/reference/javascript/auth-admin-signout" + "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/auth/sessions", - "title": "User sessions" + "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/resources/glossary", - "title": "Glossary" + "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/auth/oauth-server/oauth-flows", - "title": "OAuth 2.1 Flows" + "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#security-best-practices", + "title": "Security best practices" }, { - "url": "https://supabase.com/docs/reference/javascript/auth-admin-deletefactor" - } - ], - "resultChars": 108752 - } - ] - }, - "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, - "sourcePath": "codex-gpt-5.4-mini/investigate-auth-001-deleted-user-access.json" - }, - { - "experiment": "codex-gpt-5.4-mini", - "experimentSuite": "benchmark", - "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 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": { - "available": [ - "supabase", - "supabase-postgres-best-practices" - ], - "loaded": [ - "supabase" - ] - }, - "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 } } }", - "hasContent": true, - "pages": [ + "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/realtime/subscribing-to-database-changes", - "title": "Subscribing to Database Changes" + "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/realtime/postgres-changes", - "title": "Postgres Changes" + "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/realtime/protocol", - "title": "Realtime Protocol" + "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#testing-your-policies", + "title": "Testing your policies" }, { - "url": "https://supabase.com/docs/guides/realtime/benchmarks", - "title": "Benchmarks" + "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#troubleshooting", + "title": "Troubleshooting" }, { - "url": "https://supabase.com/docs/guides/database/replication/pipelines-faq", - "title": "Pipelines FAQ" - } - ], - "resultChars": 124600 - } - ] - }, - "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/investigate-realtime-001-subscribed-no-events.json" - }, - { - "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", - "stage": "investigate", - "product": [ - "edge-functions" - ], - "topic": [ - "observability" - ], - "suite": "benchmark", - "interface": "mcp", - "passed": false, - "checks": [ - { - "name": "identified image-transform and the recurring 503 pattern", - "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." - }, - { - "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": "recommended a concrete next step", - "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." - } - ], - "skills": { - "available": [ - "supabase", - "supabase-postgres-best-practices" - ], - "loaded": [ - "supabase" - ] - }, - "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", - "attempts": 2, - "sourcePath": "codex-gpt-5.4-mini/investigate-reliability-003-edge-function-5xx-correlation.json" - }, - { - "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", - "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": "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": { - "available": [ - "supabase", - "supabase-postgres-best-practices" - ], - "loaded": [ - "supabase" - ] - }, - "docs": { - "calls": [ - { - "source": "web_search", - "query": "https://supabase.com/changelog.md", - "pages": [ + "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/changelog.md" - } - ] - }, - { - "source": "web_search", - "query": "site:supabase.com changelog.md supabase", - "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/auth/oauth-server/token-security#policy-too-permissive", + "title": "Policy too permissive" + }, + { + "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/auth/oauth-server/token-security#next-steps", + "title": "Next steps" + }, { "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/database/postgres/row-level-security#benchmarks-1", + "title": "Benchmarks" }, { - "url": "https://supabase.com/docs/guides/getting-started/features", - "title": "Features" + "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/realtime/getting_started", - "title": "Getting Started with Realtime" + "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-2", + "title": "Benchmarks" }, { - "url": "https://supabase.com/docs/guides/auth/auth-mfa", - "title": "Multi-Factor Authentication" - } - ], - "resultChars": 81216 - } - ] - }, - "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/resolve-dataapi-001-empty-results.json" - }, - { - "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", - "product": [ - "database" - ], - "topic": [ - "migrations" - ], - "suite": "benchmark", - "interface": "cli", - "passed": false, - "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": "remote migration history matches local migration files", - "passed": true - }, - { - "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": "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": "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." - } - ], - "skills": { - "available": [ - "supabase", - "supabase-postgres-best-practices" - ], - "loaded": [ - "supabase" - ] - }, - "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 } } }", - "hasContent": true, - "pages": [ + "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/reference/api/v1-update-database-password", - "title": "Updates the database password" + "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#minimize-joins", + "title": "Minimize joins" }, { - "url": "https://supabase.com/docs/guides/platform/temporary-access", - "title": "Temporary access" + "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-3", + "title": "Benchmarks" }, { - "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/database/postgres/row-level-security#specify-roles-in-your-policies", + "title": "Specify roles in your policies" }, { - "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres", - "title": "Migrate from Postgres to Supabase" + "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-4", + "title": "Benchmarks" }, { - "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/amazon-rds", - "title": "Migrate from Amazon RDS to Supabase" - } - ], - "resultChars": 35186 - }, - { - "source": "search_docs", - "query": "query { searchDocs(query: \"management api database host connection string project details pooler host\", limit: 10) { nodes { title href content } } }", - "hasContent": true, - "pages": [ + "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#more-resources", + "title": "More resources" + }, { - "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#row-level-security-in-supabase", + "title": "Row Level Security in Supabase" }, { - "url": "https://supabase.com/docs/guides/platform/ipv4-address", - "title": "Dedicated IPv4 Address for Ingress" + "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#policies", + "title": "Policies" }, { - "url": "https://supabase.com/docs/guides/ai/integrations/roboflow", - "title": "Roboflow" + "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/api/v1-update-pooler-config", - "title": "Updates project's supavisor config" + "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/platform/read-replicas", - "title": "Read Replicas" + "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/platform/migrating-to-supabase/postgres", - "title": "Migrate from Postgres to Supabase" + "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/getting-started/quickstarts/laravel", - "title": "Use Supabase with Laravel" + "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#insert-policies", + "title": "INSERT policies" }, { - "url": "https://supabase.com/docs/reference/api/v1-get-pooler-config", - "title": "Gets project's supavisor config" + "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#update-policies", + "title": "UPDATE policies" }, { - "url": "https://supabase.com/docs/guides/database/connecting-to-postgres", - "title": "Connect to your database" + "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#delete-policies", + "title": "DELETE policies" }, { - "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/heroku", - "title": "Migrate from Heroku to Supabase" + "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#authuid", + "title": "auth.uid()" + }, + { + "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#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#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/auth/third-party/firebase-auth", + "title": "Firebase Auth" + }, + { + "url": "https://supabase.com/docs/guides/auth/third-party/firebase-auth#use-the-admin-sdk-to-assign-the-role-custom-claim-to-all-users", + "title": "Use the admin SDK to assign the role custom claim to all users" + }, + { + "url": "https://supabase.com/docs/guides/auth/third-party/firebase-auth#use-firebase-authentication-functions-to-assign-the-authenticated-role", + "title": "Use Firebase Authentication functions to assign the authenticated role" + }, + { + "url": "https://supabase.com/docs/guides/auth/third-party/firebase-auth#setup-the-supabase-client-library", + "title": "Setup the Supabase client library" + }, + { + "url": "https://supabase.com/docs/guides/auth/third-party/firebase-auth#getting-started", + "title": "Getting started" + }, + { + "url": "https://supabase.com/docs/guides/auth/third-party/firebase-auth#adding-an-extra-layer-of-security-to-your-projects-rls-policies-self-hosting-only", + "title": "Adding an extra layer of security to your project's RLS policies (self-hosting only)" + }, + { + "url": "https://supabase.com/docs/guides/auth/third-party/firebase-auth#add-a-new-third-party-auth-integration-to-your-project", + "title": "Add a new Third-Party Auth integration to your project" + }, + { + "url": "https://supabase.com/docs/guides/auth/third-party/firebase-auth#assign-the-role-custom-claim" } ], - "resultChars": 109113 + "resultChars": 278584 }, { "source": "search_docs", - "query": "query { searchDocs(query: \"project supavisor config management api host session pooler\", limit: 10) { nodes { title href content } } }", + "query": "query { searchDocs(query: \"Supabase pgTAP test auth.uid set_config request.jwt.claim.sub local database\", limit: 10) { nodes { 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/ai/rag-with-permissions", + "title": "RAG with Permissions" }, { - "url": "https://supabase.com/docs/guides/database/connecting-to-postgres", - "title": "Connect to your database" + "url": "https://supabase.com/docs/guides/local-development/cli/testing-and-linting", + "title": "Testing and linting" }, { - "url": "https://supabase.com/docs/reference/api/v1-update-pooler-config", - "title": "Updates project's supavisor config" + "url": "https://supabase.com/docs/guides/local-development/database-migrations", + "title": "Database migrations" }, { - "url": "https://supabase.com/docs/guides/getting-started/architecture", - "title": "Architecture" + "url": "https://supabase.com/docs/guides/local-development/testing/overview", + "title": "Testing Overview" }, { - "url": "https://supabase.com/docs/guides/telemetry/reports", - "title": "Reports" + "url": "https://supabase.com/docs/guides/deployment/managing-environments", + "title": "Managing Environments" }, { - "url": "https://supabase.com/docs/guides/platform/read-replicas", - "title": "Read Replicas" + "url": "https://supabase.com/docs/guides/realtime/authorization", + "title": "Realtime Authorization" }, { - "url": "https://supabase.com/docs/reference/api/v1-get-pooler-config", - "title": "Gets project's supavisor config" + "url": "https://supabase.com/docs/reference/cli/supabase-test-db", + "title": "Tests local database with pgTAP" }, { - "url": "https://supabase.com/docs/guides/database/connection-management", - "title": "Connection management" + "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended", + "title": "Advanced pgTAP Testing" }, { - "url": "https://supabase.com/docs/guides/troubleshooting/supavisor-faq-YyP5tI", - "title": "Supavisor FAQ" + "url": "https://supabase.com/docs/guides/auth/third-party/firebase-auth", + "title": "Firebase Auth" }, { - "url": "https://supabase.com/docs/guides/platform/ipv4-address", - "title": "Dedicated IPv4 Address for Ingress" + "url": "https://supabase.com/docs/guides/platform/temporary-access", + "title": "Temporary access" } ], - "resultChars": 128627 + "resultChars": 115939 } ] }, - "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" + "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", @@ -9042,38 +8097,49 @@ "modelId": "gpt-5.4-mini", "reasoningEffort": "medium" }, - "eval": "resolve-performance-001-slow-query-cpu-spike", - "stage": "resolve", + "eval": "build-vectors-001-rag-with-permissions", + "stage": "build", "product": [ - "database" + "database", + "vectors" ], "topic": [ - "observability", - "sql" + "sql", + "rls" ], "suite": "benchmark", "interface": "mcp", "passed": true, "checks": [ { - "name": "inspected pg_stat_statements for query performance", - "passed": true + "name": "document_sections.embedding is vector(384)", + "passed": true, + "notes": "vector(384)" }, { - "name": "ran EXPLAIN on the expensive query", + "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": "created index covering user_id and created_at", + "name": "user B search returns only own sections, best match first", "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_idx (cost=0.00..5.03 rows=100 width=0)\n Index Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)" + "name": "user A reads only own sections through the API", + "passed": true }, { - "name": "inserts still work", + "name": "user A reads only own documents through the API", "passed": true } ], @@ -9083,1459 +8149,3896 @@ "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 { searchDocs(query: \"pgvector semantic search RLS Supabase\", limit: 5) { nodes { title href content ... on Guide { subsections { nodes { title href content } } } } } }", "hasContent": true, "pages": [ { - "url": "https://supabase.com/docs/guides/storage/analytics/query-with-postgres", - "title": "Query with Postgres" + "url": "https://supabase.com/docs/guides/ai/rag-with-permissions", + "title": "RAG with Permissions" }, { - "url": "https://supabase.com/docs/guides/storage/debugging/logs", - "title": "Logs" + "url": "https://supabase.com/docs/guides/ai/rag-with-permissions#example", + "title": "Example" }, { - "url": "https://supabase.com/docs/guides/database/orioledb", - "title": "OrioleDB Overview" + "url": "https://supabase.com/docs/guides/ai/rag-with-permissions#alternative-scenarios", + "title": "Alternative scenarios" }, { - "url": "https://supabase.com/docs/guides/database/inspect", - "title": "Debugging and monitoring" + "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/telemetry/advanced-log-filtering", - "title": "Advanced Log Querying and Filtering" - } - ], - "resultChars": 37224 - } - ] - }, - "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" - ] - }, - "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 } } } } } }", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/auth/third-party/clerk", - "title": "Clerk" - }, - { - "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/auth/third-party/clerk#deprecated-integration-with-jwt-templates", - "title": "Deprecated integration with JWT templates" - }, - { - "url": "https://supabase.com/docs/guides/auth/third-party/clerk#getting-started", - "title": "Getting started" - }, - { - "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/auth/third-party/clerk#manually-configuring-your-clerk-instance", - "title": "Manually configuring your Clerk instance" - }, - { - "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/auth/third-party/clerk#using-rls-policies", - "title": "Using RLS policies" - }, - { - "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/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/storage/schema/helper-functions", - "title": "Storage Helper Functions" + "url": "https://supabase.com/docs/guides/ai/rag-with-permissions#direct-postgres-connection", + "title": "Direct Postgres connection" }, { - "url": "https://supabase.com/docs/guides/storage/schema/helper-functions#storageallow_any_operation", - "title": "storage.allow_any_operation()" + "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/storage/schema/helper-functions#storageallow_only_operation", - "title": "storage.allow_only_operation()" + "url": "https://supabase.com/docs/guides/ai/rag-with-permissions#other-scenarios", + "title": "Other scenarios" }, { - "url": "https://supabase.com/docs/guides/storage/schema/helper-functions#storageextension", - "title": "storage.extension()" + "url": "https://supabase.com/docs/guides/ai/hybrid-search", + "title": "Hybrid search" }, { - "url": "https://supabase.com/docs/guides/storage/schema/helper-functions#storagefoldername", - "title": "storage.foldername()" + "url": "https://supabase.com/docs/guides/ai/hybrid-search#see-also", + "title": "See also" }, { - "url": "https://supabase.com/docs/guides/storage/schema/helper-functions#storagefilename", - "title": "storage.filename()" + "url": "https://supabase.com/docs/guides/ai/hybrid-search#running-hybrid-search", + "title": "Running hybrid search" }, { - "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/hybrid-search#hybrid-search-in-postgres", + "title": "Hybrid search in Postgres" }, { - "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/ai/hybrid-search#smoothing-constant-k", + "title": "Smoothing constant k" }, { - "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/hybrid-search#reciprocal-ranked-fusion-rrf", + "title": "Reciprocal Ranked Fusion (RRF)" }, { - "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/hybrid-search#how-to-combine-search-methods", + "title": "How to combine search methods" }, { - "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/hybrid-search#when-to-consider-hybrid-search", + "title": "When to consider hybrid search" }, { - "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/hybrid-search#use-cases-for-hybrid-search", + "title": "Use cases for hybrid search" }, { - "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/database/extensions/pgvector", + "title": "pgvector: Embeddings and vector similarity" }, { - "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#real-world-examples", - "title": "Real-world examples" + "url": "https://supabase.com/docs/guides/database/extensions/pgvector#usage-1", + "title": "Usage" }, { - "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/database/extensions/pgvector#create-a-table-to-store-vectors", + "title": "Create a table to store vectors" }, { - "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/database/extensions/pgvector#storing-a-vector--embedding", + "title": "Storing a vector / embedding" }, { - "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/database/extensions/pgvector#specific-usage-cases", + "title": "Specific usage cases" }, { - "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/database/extensions/pgvector#more-pgvector-and-supabase-resources", + "title": "More pgvector and Supabase resources" }, { - "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#security-best-practices", - "title": "Security best practices" + "url": "https://supabase.com/docs/guides/database/extensions/pgvector#queries-with-filtering", + "title": "Queries with filtering" }, { - "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/database/extensions/pgvector#concepts", + "title": "Concepts" }, { - "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/database/extensions/pgvector#vector-similarity", + "title": "Vector similarity" }, { - "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/database/extensions/pgvector#embeddings", + "title": "Embeddings" }, { - "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#testing-your-policies", - "title": "Testing your policies" + "url": "https://supabase.com/docs/guides/database/extensions/pgvector#usage", + "title": "Usage" }, { - "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#troubleshooting", - "title": "Troubleshooting" + "url": "https://supabase.com/docs/guides/database/extensions/pgvector#enable-the-extension", + "title": "Enable the extension" }, { - "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/semantic-search", + "title": "Semantic search" }, { - "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/semantic-search#similarity-metric", + "title": "Similarity metric" }, { - "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/semantic-search#pgvector-index-tuning", + "title": "pgvector index tuning" }, { - "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#next-steps", - "title": "Next steps" + "url": "https://supabase.com/docs/guides/ai/semantic-search#ivfflat-index", + "title": "IVFFlat index" }, { - "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/semantic-search#hnsw-index", + "title": "HNSW index" }, { - "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security#token-structure", - "title": "Token structure" + "url": "https://supabase.com/docs/guides/ai/semantic-search#see-also", + "title": "See also" }, { - "url": "https://supabase.com/docs/guides/storage/security/access-control", - "title": "Storage Access Control" + "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/storage/security/access-control#bypassing-access-controls", - "title": "Bypassing access controls" + "url": "https://supabase.com/docs/guides/ai/semantic-search#how-semantic-search-works", + "title": "How semantic search works" }, { - "url": "https://supabase.com/docs/guides/storage/security/access-control#policy-examples", - "title": "Policy examples" + "url": "https://supabase.com/docs/guides/ai/semantic-search#embedding-models", + "title": "Embedding models" }, { - "url": "https://supabase.com/docs/guides/storage/security/access-control#access-policies", - "title": "Access policies" + "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", - "title": "Row Level Security" + "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#minimize-joins", - "title": "Minimize joins" + "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#benchmarks-3", - "title": "Benchmarks" + "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#benchmarks-4", - "title": "Benchmarks" + "url": "https://supabase.com/docs/guides/ai/automatic-embeddings", + "title": "Automatic embeddings" }, { - "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/automatic-embeddings#usage", + "title": "Usage" }, { - "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#policies", - "title": "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#enabling-row-level-security", - "title": "Enabling 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#auto-enable-rls-for-new-tables", - "title": "Auto-enable RLS for new tables" + "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#authenticated-and-unauthenticated-roles", - "title": "Authenticated and unauthenticated roles" + "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#creating-policies", - "title": "Creating policies" + "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/database/postgres/row-level-security#select-policies", - "title": "SELECT policies" + "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/database/postgres/row-level-security#insert-policies", - "title": "INSERT policies" + "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/database/postgres/row-level-security#update-policies", - "title": "UPDATE policies" + "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/database/postgres/row-level-security#delete-policies", - "title": "DELETE policies" + "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/database/postgres/row-level-security#views", - "title": "Views" + "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#see-also", + "title": "See also" }, { - "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#helper-functions", - "title": "Helper functions" + "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#conclusion", + "title": "Conclusion" }, { - "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#authuid", - "title": "auth.uid()" + "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#troubleshooting", + "title": "Troubleshooting" }, { - "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#authjwt", - "title": "auth.jwt()" + "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/database/postgres/row-level-security#mfa", - "title": "MFA" + "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/database/postgres/row-level-security#bypassing-row-level-security", - "title": "Bypassing Row Level Security" + "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#understanding-the-challenge", + "title": "Understanding the challenge" }, { - "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/automatic-embeddings#2-create-triggers-to-enqueue-embedding-jobs", + "title": "2. Create triggers to enqueue embedding jobs" }, { - "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#understanding-the-architecture", + "title": "Understanding the architecture" }, { - "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks", - "title": "Benchmarks" + "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#implementation", + "title": "Implementation" }, { - "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#more-resources", - "title": "More resources" + "url": "https://supabase.com/docs/guides/ai/automatic-embeddings#step-1-enable-extensions", + "title": "Step 1: Enable extensions" }, { - "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/automatic-embeddings#step-2-create-utility-functions", + "title": "Step 2: Create utility functions" + } + ], + "resultChars": 176915 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"row level security auth.uid owner documents policy\", limit: 5) { nodes { title href content } } }", + "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/ai/rag-with-permissions", + "title": "RAG with Permissions" }, { - "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-1", - "title": "Benchmarks" + "url": "https://supabase.com/docs/guides/getting-started/features", + "title": "Features" }, { - "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/local-development/testing/pgtap-extended", + "title": "Advanced pgTAP Testing" }, { - "url": "https://supabase.com/docs/guides/database/postgres/row-level-security#benchmarks-2", - "title": "Benchmarks" + "url": "https://supabase.com/docs/guides/database/postgres/column-level-security", + "title": "Column Level Security" }, { - "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/getting-started/tutorials/with-nextjs", + "title": "Build a User Management App with Next.js" } ], - "resultChars": 166639 + "resultChars": 99695 } ] }, - "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": [] - }, - "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", + "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-cli-001-bootstrap-app.json" + "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-002-declarative-schema", - "stage": "build", + "eval": "deploy-database-001-prometheus-metrics", + "stage": "deploy", "product": [ "database" ], "topic": [ - "declarative-schema", - "migrations" + "observability" ], "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", + "name": "preserved existing app scrape job", "passed": true }, { - "name": "a new migration was generated for the change", + "name": "configured the Supabase Metrics API scrape correctly", "passed": false, - "notes": "found 1 migration file(s)" + "judgeNotes": "Fails: the Supabase scrape uses basic_auth.password with an environment variable instead of basic_auth.password_file, and docker-compose.yml does not mount or provide that password_file via a volume or Compose secret. The app scrape is preserved and the HTTPS metrics endpoint is otherwise correct." }, { - "name": "description column exists in the live database", - "passed": false + "name": "documented live deployment and verification steps", + "passed": false, + "judgeNotes": "README includes the Supabase Secret API key, Compose restart, and Prometheus Targets verification, but it does not require placing a matching secret file; it uses environment variables/.env instead. The rubric explicitly requires secret file setup." } ], "skills": { - "available": [], - "loaded": [] + "available": [ + "supabase", + "supabase-postgres-best-practices" + ], + "loaded": [ + "supabase" + ] }, "docs": { - "calls": [] + "calls": [ + { + "source": "search_docs", + "query": "query {\n searchDocs(query: \"Prometheus metrics Supabase project observability\", 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/monitoring-and-debugging/metrics/grafana-cloud", + "title": "Metrics API with Grafana Cloud" + }, + { + "url": "https://supabase.com/docs/guides/platform/read-replicas", + "title": "Read Replicas" + } + ], + "resultChars": 29095 + } + ] }, - "prompt": "Add a description text column to the `products` table in my local Supabase stack", - "promptSourcePath": "evals/build-cli-002-declarative-schema/PROMPT.md", + "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/build-cli-002-declarative-schema.json" + "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-003-pg-cron-queue-workflow", - "stage": "build", + "eval": "deploy-functions-001-edge-function-secrets", + "stage": "deploy", "product": [ - "database", - "edge-functions", - "cron", - "queues" + "edge-functions" ], "topic": [ - "sql", - "sdk" + "security" ], "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": "WEATHER_API_KEY is set as a Function secret on the project", + "passed": true }, { - "name": "cron command enqueues to the 'tasks' queue", + "name": "the weather function is deployed to the project", "passed": true, - "notes": "queue depth 0 -> 1" + "notes": "status ACTIVE" }, { - "name": "process-tasks function drains the queue", + "name": "the weather function reads WEATHER_API_KEY from the environment", "passed": true, - "notes": "function removed the seeded message (id 2) from the queue" + "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": [] + "available": [ + "supabase", + "supabase-postgres-best-practices" + ], + "loaded": [ + "supabase" + ] }, "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 { searchDocs(query: \"Edge Functions secrets environment variables deploy supabase secrets set env-file\", 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/queues/consuming-messages-with-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/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/secrets", + "title": "Environment Variables" + }, + { + "url": "https://supabase.com/docs/guides/deployment/branching/configuration", + "title": "Configuration" } - ] - }, - { - "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": [] + ], + "resultChars": 38385 }, { - "source": "web_search", - "query": "site:supabase.com/docs pgmq list queues list_queues", - "pages": [] + "source": "search_docs", + "query": "query { searchDocs(query: \"functions public URL project not specified functions.supabase.co project ref invocation URL\", 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/analytics/connecting-to-analytics-bucket", + "title": "Iceberg Catalog" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions", + "title": "Self-Hosted Functions" + }, + { + "url": "https://supabase.com/docs/guides/ai/automatic-embeddings", + "title": "Automatic embeddings" + }, + { + "url": "https://supabase.com/docs/reference/cli/supabase-projects-delete", + "title": "Delete a Supabase project" + } + ], + "resultChars": 44531 }, { - "source": "web_search", - "query": "site:supabase.com/docs edge function config.toml verify_jwt false", - "pages": [] - } - ] - }, - "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-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": [] - }, - "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": "search_docs", + "query": "query { searchDocs(query: \"Edge Functions invoke URL format project-ref functions.supabase.co functions/v1\", limit: 10) { 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/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/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", + "title": "Edge Functions" + }, + { + "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/functions/architecture", + "title": "Edge Functions Architecture" + }, + { + "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys", + "title": "Migrating to publishable and secret API keys" + } + ], + "resultChars": 105353 + }, { "source": "web_search", - "query": "site:supabase.com docs supabase functions serve entrypoint failed to determine entrypoint verify_jwt config.toml user-stats", + "query": "site:supabase.com/docs Edge Functions invoke URL project not specified functions supabase.co", "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" + "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-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-storage-001-private-bucket-access", - "stage": "build", + "eval": "deploy-self-hosting-001-docker-compose", + "stage": "deploy", "product": [ - "storage", - "database" + "database", + "auth", + "storage" ], "topic": [ - "rls", - "sdk" + "self-hosting" ], "suite": "benchmark", - "interface": "mcp", + "interface": "cli", "passed": true, "checks": [ { - "name": "bucket user-files exists", + "name": "cloned the self-host stack (docker-compose.yml + volumes/db)", "passed": true }, { - "name": "bucket user-files is private", + "name": "didn't conflate with the CLI (no supabase/config.toml in the stack)", "passed": true }, { - "name": "RLS still enabled on storage.objects", + "name": "secrets rotated off the shipped defaults", "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", + "name": "ANON_KEY and SERVICE_ROLE_KEY are HS256 JWTs signed by JWT_SECRET", "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": "shell_fetch", + "query": "/bin/bash -lc \"curl -fsSL https://supabase.com/changelog.md | sed -n '1,120p'\"", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/changelog.md" + } + ], + "resultChars": 6745 + }, { "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: \"self-host Docker Compose Supabase config.toml environment variables JWT secret ports\", 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/self-hosted-auth-keys", + "title": "New API Keys and Asymmetric Authentication" }, { - "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals", - "title": "Storage Buckets" + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#additional-resources", + "title": "Additional resources" }, { - "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-auth-keys#before-you-begin", + "title": "Before you begin" }, { - "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#adding-the-new-keys", + "title": "Adding the new keys" }, { - "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/self-hosted-auth-keys#new-api-keys-format", + "title": "New API keys format" + }, { - "url": "https://supabase.com/docs/guides/storage/serving/downloads", - "title": "Serving assets from Storage" + "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/storage/uploads/resumable-uploads", - "title": "Resumable Uploads" + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#environment-variables-configuration", + "title": "Environment variables configuration" }, { - "url": "https://supabase.com/docs/reference/dart/file-buckets-createsignedurl" + "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/reference/javascript/file-buckets-createsignedurl" + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys#backward-compatibility", + "title": "Backward compatibility" }, { - "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#rotating-the-new-api-keys", + "title": "Rotating the new API keys" + }, { - "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#regenerating-asymmetric-key-pair", + "title": "Regenerating asymmetric key pair" }, { - "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#how-it-works", + "title": "How it works" }, { - "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/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#kong-api-gateway-routing", + "title": "Kong API gateway routing" }, { - "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#request-flows", + "title": "Request flows" + }, { - "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#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-s3", "title": "Configure S3 Storage" }, { - "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals", - "title": "Storage Buckets" + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3#verify", + "title": "Verify" }, { - "url": "https://supabase.com/docs/guides/local-development/database-migrations", - "title": "Database migrations" + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3#session-token", + "title": "Session token" }, { - "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/self-hosting/self-hosted-s3#troubleshooting", + "title": "Troubleshooting" + }, { - "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-s3#signature-mismatch-errors", + "title": "Signature mismatch errors" + }, { - "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-s3#tus-upload-errors-on-cloudflare-r2", + "title": "TUS upload errors on Cloudflare R2" + }, { - "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-s3#permission-denied-on-uploads", + "title": "Permission denied on uploads" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3#upload-urls-point-to-localhost", + "title": "Upload URLs point to localhost" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3#additional-resources", + "title": "Additional resources" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3#enable-the-s3-protocol-endpoint", + "title": "Enable the S3 protocol endpoint" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3#test-with-the-aws-cli", + "title": "Test with the AWS CLI" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3#test-with-rclone", + "title": "Test with rclone" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3#how-to-configure-an-s3-backend", + "title": "How to configure an S3 backend" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3#using-rustfs", + "title": "Using RustFS" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3#using-minio", + "title": "Using MinIO" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3#using-aws-s3", + "title": "Using AWS S3" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3#s3-compatible-providers", + "title": "S3-compatible providers" }, { "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-envoy", - "title": "Envoy API Gateway" + "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/auth/signing-keys", - "title": "JWT Signing Keys" + "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/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-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-auth-keys", - "title": "New API Keys and Asymmetric Authentication" + "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/docker", - "title": "Self-Hosting with Docker" + "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-oauth", - "title": "Configure Social Login (OAuth) Providers" + "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/custom-email-templates", - "title": "Custom Email Templates" + "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-envoy", - "title": "Envoy API Gateway" - } - ], - "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": [ + "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-functions#calling-supabase-services-from-functions", + "title": "Calling Supabase services from functions" + }, + { + "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#managing-functions-via-dashboard", + "title": "Managing functions via dashboard" + }, + { + "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#copying-functions-from-supabase-platform", + "title": "Copying functions from Supabase platform" + }, + { + "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#500-error-on-invocation", + "title": "500 error on invocation" + }, + { + "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#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#memory-or-timeout-errors", + "title": "Memory or timeout errors" + }, + { + "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/docker", + "title": "Self-Hosting with Docker" + }, + { + "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#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-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#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#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/self-hosted-proxy-https", + "title": "Configure Reverse Proxy and HTTPS" + }, + { + "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#websocket-connection-failed", + "title": "WebSocket connection failed" + }, + { + "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#troubleshooting", + "title": "Troubleshooting" + }, + { + "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-update-configuration-variables", + "title": "Step 3: Update configuration variables" + }, + { + "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-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#before-you-begin", + "title": "Before you begin" + }, + { + "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#additional-resources", + "title": "Additional resources" + }, + { + "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#mixed-content-warnings", + "title": "Mixed content warnings" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#400-missing-function-name-in-request" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions#401-invalid-jwt" + } + ], + "resultChars": 308617 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"self-hosted Envoy default API gateway docker compose envoy kong custom kong.yml\", 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-envoy", + "title": "Envoy API Gateway" + }, + { + "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#see-also", + "title": "See also" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#before-you-begin", + "title": "Before you begin" + }, + { + "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/self-hosting/self-hosted-envoy#verify", + "title": "Verify" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#architecture", + "title": "Architecture" + }, + { + "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#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#routes", + "title": "Routes" + }, + { + "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#dashboard-basic-auth", + "title": "Dashboard basic auth" + }, + { + "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#opaque-key-translation", + "title": "Opaque key translation" + }, + { + "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#x-forwarded-headers", + "title": "X-Forwarded headers" + }, + { + "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#security-hardening", + "title": "Security hardening" + }, + { + "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#admin-interface", + "title": "Admin interface" + }, + { + "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#logs", + "title": "Logs" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/enable-mcp", + "title": "Enabling MCP Server Access" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/enable-mcp#step-4-create-the-ssh-tunnel", + "title": "Step 4: Create the SSH tunnel" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/enable-mcp#step-5-configure-your-mcp-client", + "title": "Step 5: Configure your MCP client" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/enable-mcp#step-6-start-using-the-self-hosted-mcp-server", + "title": "Step 6: Start using the self-hosted MCP server" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/enable-mcp#troubleshooting", + "title": "Troubleshooting" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/enable-mcp#security-considerations", + "title": "Security considerations" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/enable-mcp#accessing-via-ssh-tunnel", + "title": "Accessing via SSH tunnel" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/enable-mcp#step-1-determine-the-local-ip-address-that-will-be-used-to-access-the-mcp-server", + "title": "Step 1: Determine the local IP address that will be used to access the MCP server" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/enable-mcp#step-2-allow-connections-from-the-gateway-ip", + "title": "Step 2: Allow connections from the gateway IP" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/enable-mcp#step-3-restart-api-gateway", + "title": "Step 3: Restart 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-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#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-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-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#before-you-begin", + "title": "Before you begin" + }, + { + "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-auth-keys", + "title": "New API Keys and Asymmetric Authentication" + }, + { + "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/self-hosted-auth-keys#backward-compatibility", + "title": "Backward compatibility" + }, + { + "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#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" + } + ], + "resultChars": 246470 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Self-Hosting with Docker quick start Linux .env example docker-compose.yml generate-keys.sh\", limit: 5) { nodes { title href content ... on Guide { subsections { nodes { 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/docker#configuring-an-email-server", + "title": "Configuring an email server" + }, + { + "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-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#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#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/docker#changing-database-password", + "title": "Changing database password" + }, + { + "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#additional-resources", + "title": "Additional resources" + }, + { + "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#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#new-api-keys-format", + "title": "New API keys format" + }, + { + "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#adding-the-new-keys", + "title": "Adding the new 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#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#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-oauth", + "title": "Configure Social Login (OAuth) Providers" + }, + { + "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-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/self-hosted-functions", + "title": "Self-Hosted Functions" + }, + { + "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-functions#using-inline-environment-variables", + "title": "Using inline environment variables" + }, + { + "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#using-an-env-file-recommended", + "title": "Using an env file (recommended)" + }, + { + "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#invoke-the-default-function", + "title": "Invoke the default 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-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": 386963 + } + ] + }, + "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": "The answer identifies the original soft-delete-only bug, changes delete_account to delete auth.users with cascaded sessions/identities/profile removal, adds RLS gating on active profile, and explains the stale JWT caveat consistently: Data API path is closed by RLS, but purely local/custom JWT validation can accept until expiry and should check auth.sessions. It correctly distinguishes publishable/anon as frontend/public with RLS from secret/service_role as server-only RLS-bypassing credentials." + } + ], + "skills": { + "available": [ + "supabase", + "supabase-postgres-best-practices" + ], + "loaded": [ + "supabase", + "supabase-postgres-best-practices" + ] + }, + "docs": { + "calls": [ + { + "source": "search_docs", + "query": "query { searchDocs(query: \"delete user revoke sessions auth admin deleteUser delete_account\", 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/javascript/auth-admin-deleteuser" + }, + { + "url": "https://supabase.com/docs/guides/auth/managing-user-data", + "title": "User Management" + }, + { + "url": "https://supabase.com/docs/reference/dart/auth-admin-deleteuser" + }, + { + "url": "https://supabase.com/docs/reference/swift/auth-admin-deleteuser", + "title": "deleteUser()" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers", + "title": "Multiple SSO Providers" + } + ], + "resultChars": 27864 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"revoke sessions auth admin signOut user delete deleteUser session_id auth.sessions\", limit: 10) { 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/sessions", + "title": "User sessions" + }, + { + "url": "https://supabase.com/docs/guides/auth/managing-user-data", + "title": "User Management" + }, + { + "url": "https://supabase.com/docs/reference/javascript/auth-admin-signout" + }, + { + "url": "https://supabase.com/docs/guides/auth/signout", + "title": "Signing out" + }, + { + "url": "https://supabase.com/docs/reference/javascript/auth-signout" + }, + { + "url": "https://supabase.com/docs/guides/resources/glossary", + "title": "Glossary" + }, + { + "url": "https://supabase.com/docs/guides/auth/auth-anonymous", + "title": "Anonymous Sign-Ins" + }, + { + "url": "https://supabase.com/docs/reference/javascript/auth-admin-deleteuser" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers", + "title": "Multiple SSO Providers" + }, + { + "url": "https://supabase.com/docs/guides/auth/signing-keys", + "title": "JWT Signing Keys" + } + ], + "resultChars": 100963 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"auth.users delete cascade sessions refresh_tokens on delete cascade\", 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/auth/managing-user-data", + "title": "User Management" + }, + { + "url": "https://supabase.com/docs/guides/auth/auth-anonymous", + "title": "Anonymous Sign-Ins" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions", + "title": "User sessions" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows", + "title": "OAuth 2.1 Flows" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security", + "title": "Token Security and Row Level Security" + } + ], + "resultChars": 83816 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"publishable secret api keys anon service_role frontend rls\", limit: 10) { nodes { __typename ... on Guide { title href content } ... on ClientLibraryFunctionReference { title href content language methodName } } } }", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/database/secure-data", + "title": "Securing your data" + }, + { + "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/jwt-fields", + "title": "JWT Claims Reference" + }, + { + "url": "https://supabase.com/docs/guides/auth/signing-keys", + "title": "JWT Signing 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/getting-started/api-keys", + "title": "Understanding API keys" + }, + { + "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/api/securing-your-api", + "title": "Securing your API" + } + ], + "resultChars": 133497 + } + ] + }, + "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, + "sourcePath": "codex-gpt-5.4-mini/investigate-auth-001-deleted-user-access.json" + }, + { + "experiment": "codex-gpt-5.4-mini", + "experimentSuite": "benchmark", + "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 as root cause, added public.orders to existing publication, verified courier_locations remains included and RLS/policies were not weakened." + } + ], + "skills": { + "available": [ + "supabase", + "supabase-postgres-best-practices" + ], + "loaded": [ + "supabase", + "supabase-postgres-best-practices" + ] + }, + "docs": { + "calls": [ + { + "source": "search_docs", + "query": "query { searchDocs(query: \"postgres_changes publication Realtime INSERT table publication\", 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/realtime/subscribing-to-database-changes#create-a-trigger", + "title": "Create a trigger" + }, + { + "url": "https://supabase.com/docs/guides/realtime/subscribing-to-database-changes#listening-on-client-side", + "title": "Listening on client side" + }, + { + "url": "https://supabase.com/docs/guides/realtime/subscribing-to-database-changes#using-postgres-changes", + "title": "Using Postgres Changes" + }, + { + "url": "https://supabase.com/docs/guides/realtime/subscribing-to-database-changes#enable-postgres-changes", + "title": "Enable Postgres Changes" + }, + { + "url": "https://supabase.com/docs/guides/realtime/subscribing-to-database-changes#streaming-inserts", + "title": "Streaming inserts" + }, + { + "url": "https://supabase.com/docs/guides/realtime/subscribing-to-database-changes#streaming-updates", + "title": "Streaming updates" + }, + { + "url": "https://supabase.com/docs/guides/realtime/subscribing-to-database-changes#using-broadcast", + "title": "Using Broadcast" + }, + { + "url": "https://supabase.com/docs/guides/realtime/subscribing-to-database-changes#broadcast-authorization", + "title": "Broadcast authorization" + }, + { + "url": "https://supabase.com/docs/guides/realtime/subscribing-to-database-changes#create-a-trigger-function", + "title": "Create a trigger function" + }, + { + "url": "https://supabase.com/docs/guides/realtime/architecture", + "title": "Realtime Architecture" + }, + { + "url": "https://supabase.com/docs/guides/realtime/architecture#elixir--phoenix", + "title": "Elixir & Phoenix" + }, + { + "url": "https://supabase.com/docs/guides/realtime/architecture#channels", + "title": "Channels" + }, + { + "url": "https://supabase.com/docs/guides/realtime/architecture#global-cluster", + "title": "Global cluster" + }, + { + "url": "https://supabase.com/docs/guides/realtime/architecture#connecting-to-a-database", + "title": "Connecting to a database" + }, + { + "url": "https://supabase.com/docs/guides/realtime/architecture#broadcast-from-postgres", + "title": "Broadcast from Postgres" + }, + { + "url": "https://supabase.com/docs/guides/realtime/architecture#streaming-the-write-ahead-log", + "title": "Streaming the Write-Ahead Log" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes", + "title": "Postgres Changes" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#listening-to-delete-events", + "title": "Listening to DELETE events" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#listening-to-update-events", + "title": "Listening to UPDATE events" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#listening-to-insert-events", + "title": "Listening to INSERT events" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#listening-to-specific-schemas", + "title": "Listening to specific schemas" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#usage", + "title": "Usage" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#quick-start", + "title": "Quick start" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#database-instance-and-realtime-performance", + "title": "Database instance and realtime performance" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#spaces-in-table-names", + "title": "Spaces in table names" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#delete-events-are-not-filterable", + "title": "Delete events are not filterable" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#limitations", + "title": "Limitations" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#refreshed-tokens", + "title": "Refreshed tokens" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#custom-tokens", + "title": "Custom tokens" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#private-schemas", + "title": "Private schemas" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#receiving-old-records", + "title": "Receiving old records" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#contained-in-list-in", + "title": "Contained in list (in)" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#greater-than-or-equal-to-gte", + "title": "Greater than or equal to (gte)" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#greater-than-gt", + "title": "Greater than (gt)" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#less-than-lt", + "title": "Less than (lt)" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#less-than-or-equal-to-lte", + "title": "Less than or equal to (lte)" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#not-equal-to-neq", + "title": "Not equal to (neq)" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#equal-to-eq", + "title": "Equal to (eq)" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#available-filters", + "title": "Available filters" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#filtering-for-specific-changes", + "title": "Filtering for specific changes" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#listening-to-multiple-changes", + "title": "Listening to multiple changes" + }, + { + "url": "https://supabase.com/docs/guides/realtime/postgres-changes#listening-to-specific-tables", + "title": "Listening to specific tables" + }, + { + "url": "https://supabase.com/docs/guides/realtime/concepts", + "title": "Realtime Concepts" + }, + { + "url": "https://supabase.com/docs/guides/realtime/concepts#database-resources", + "title": "Database resources" + }, + { + "url": "https://supabase.com/docs/guides/realtime/concepts#database-connections", + "title": "Database connections" + }, + { + "url": "https://supabase.com/docs/guides/realtime/concepts#replication-slots", + "title": "Replication slots" + }, + { + "url": "https://supabase.com/docs/guides/realtime/concepts#schema-and-tables", + "title": "Schema and tables" + }, + { + "url": "https://supabase.com/docs/guides/realtime/concepts#functions", + "title": "Functions" + }, + { + "url": "https://supabase.com/docs/guides/realtime/concepts#concepts", + "title": "Concepts" + }, + { + "url": "https://supabase.com/docs/guides/realtime/concepts#channels", + "title": "Channels" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol", + "title": "Realtime Protocol" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#200", + "title": "2.0.0" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#binary-frames", + "title": "Binary frames" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#user-broadcast-push", + "title": "User Broadcast Push" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#user-broadcast", + "title": "User Broadcast" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#event-types", + "title": "Event types" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#client-sent-events", + "title": "Client sent events" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#phx_join", + "title": "phx_join" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#reconnection", + "title": "Reconnection" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#access-token-refresh", + "title": "Access token refresh" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#presence-errors", + "title": "Presence errors" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#broadcast-errors", + "title": "Broadcast errors" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#postgres-changes-subscription-errors", + "title": "Postgres Changes subscription errors" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#channel-level-system-errors", + "title": "Channel-level system errors" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#join-errors", + "title": "Join errors" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#error-handling", + "title": "Error handling" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#presence_diff", + "title": "presence_diff" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#presence_state", + "title": "presence_state" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#postgres_changes", + "title": "postgres_changes" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#broadcast-binary-frame-1", + "title": "broadcast (binary frame)" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#broadcast-text-frame-1", + "title": "broadcast (text frame)" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#system", + "title": "system" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#phx_reply", + "title": "phx_reply" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#phx_error", + "title": "phx_error" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#phx_close", + "title": "phx_close" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#server-sent-events", + "title": "Server sent events" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#presence", + "title": "presence" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#broadcast-binary-frame", + "title": "broadcast (binary frame)" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#broadcast-text-frame", + "title": "broadcast (text frame)" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#access_token", + "title": "access_token" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#heartbeat", + "title": "heartbeat" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#phx_leave", + "title": "phx_leave" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#websocket-connection-setup", + "title": "WebSocket connection setup" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#protocol-messages", + "title": "Protocol messages" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#100", + "title": "1.0.0" + }, + { + "url": "https://supabase.com/docs/guides/realtime/protocol#text-frames", + "title": "Text frames" + } + ], + "resultChars": 227332 + } + ] + }, + "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/investigate-realtime-001-subscribed-no-events.json" + }, + { + "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", + "stage": "investigate", + "product": [ + "edge-functions" + ], + "topic": [ + "observability" + ], + "suite": "benchmark", + "interface": "mcp", + "passed": false, + "checks": [ + { + "name": "identified image-transform and the recurring 503 pattern", + "passed": true, + "judgeNotes": "Identified image-transform as the affected function and described repeated 503s at the API gateway from 07:00 through 12:00 on 2026-04-28, covering the required recurring morning pattern." + }, + { + "name": "attributed recurring 503s to gateway/platform layer, not function code", + "passed": false, + "judgeNotes": "The response cites valid observations (gateway 503s, successful worker logs, unchanged deployment/version), but ultimately attributes the likely problem to `image-transform` or its dependencies and recommends inspecting/fixing function internals, rather than clearly attributing the recurring 503s to the gateway/platform layer." + }, + { + "name": "recommended a concrete next step", + "passed": true, + "judgeNotes": "The assistant provided several concrete next steps, including inspecting the image-transform dependency for outbound calls/timeouts/rate limits, adding structured logging with correlation IDs, checking external service availability/rate limits for the relevant date, and adding retry/fallback behavior." + } + ], + "skills": { + "available": [ + "supabase", + "supabase-postgres-best-practices" + ], + "loaded": [ + "supabase", + "supabase-postgres-best-practices" + ] + }, + "docs": { + "calls": [ + { + "source": "search_docs", + "query": "query { searchDocs(query: \"storage upload error logs server error signed URL upload intermittent 500\", limit: 5) { nodes { title href ... on Guide { content } ... on TroubleshootingGuide { content } } } }", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3", + "title": "Configure S3 Storage" + }, + { + "url": "https://supabase.com/docs/guides/storage/debugging/error-codes", + "title": "Error Codes" + }, + { + "url": "https://supabase.com/docs/guides/auth/debugging/error-codes", + "title": "Error Codes" + }, + { + "url": "https://supabase.com/docs/guides/storage/uploads/s3-uploads", + "title": "S3 Uploads" + }, + { + "url": "https://supabase.com/docs/guides/storage/uploads/resumable-uploads", + "title": "Resumable Uploads" + } + ], + "resultChars": 49905 + } + ] + }, + "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", + "experimentSuite": "benchmark", + "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 enabled with no policies causing deny-all Data API behavior, kept RLS enabled, and added authenticated-only SELECT and INSERT policies scoped to user_id = auth.uid() with WITH CHECK for inserts." + } + ], + "skills": { + "available": [ + "supabase", + "supabase-postgres-best-practices" + ], + "loaded": [ + "supabase", + "supabase-postgres-best-practices" + ] + }, + "docs": { + "calls": [ + { + "source": "search_docs", + "query": "query { searchDocs(query: \"exposing a table to the data api grants anon authenticated rls bookmarks\", limit: 5) { 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/database/database-advisors?queryGroups=lint&lint=0013_rls_disabled_in_public", + "title": "Database Advisor: Lint 0013_rls_disabled_in_public" + }, + { + "url": "https://supabase.com/docs/guides/database/secure-data", + "title": "Securing your data" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/row-level-security", + "title": "Row Level Security" + }, + { + "url": "https://supabase.com/docs/guides/database/database-advisors?queryGroups=lint&lint=0023_sensitive_columns_exposed", + "title": "Database Advisor: Lint 0023_sensitive_columns_exposed" + } + ], + "resultChars": 59418 + } + ] + }, + "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/resolve-dataapi-001-empty-results.json" + }, + { + "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", + "product": [ + "database" + ], + "topic": [ + "migrations" + ], + "suite": "benchmark", + "interface": "cli", + "passed": true, + "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": true, + "judgeNotes": "Applied avatar_url via `supabase db push --db-url \"$(cat supabase/.temp/pooler-url)\"` (#21), which output `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` (#18), after which CLI migration list/push no longer blocked. Read-only psql inspections were used; no forbidden direct SQL mutation or prepared-statement workaround observed." + } + ], + "skills": { + "available": [ + "supabase", + "supabase-postgres-best-practices" + ], + "loaded": [ + "supabase", + "supabase-postgres-best-practices" + ] + }, + "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": 1, + "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=83.74..83.86 rows=50 width=58)\n -> Sort (cost=83.74..83.99 rows=100 width=58)\n Sort Key: created_at DESC\n -> Bitmap Heap Scan on events (cost=9.06..80.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..9.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": [ + { + "source": "search_docs", + "query": "query { searchDocs(query: \"pg_stat_statements query optimization missing index composite index order by limit\", limit: 5) { nodes { title href content } } }", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/database/inspect", + "title": "Debugging and monitoring" + }, + { + "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/extensions/pg_stat_statements", + "title": "pg_stat_statements: Query Performance Monitoring" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/configuration", + "title": "Database configuration" + } + ], + "resultChars": 34191 + } + ] + }, + "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: \"RLS workspace scoping notes table Supabase\", limit: 5) { nodes { __typename ... on Guide { title href content } ... on TroubleshootingGuide { title href content } } } }", + "hasContent": true, + "pages": [ + { + "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/auth/oauth-server/token-security", + "title": "Token Security and Row Level Security" + }, + { + "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/database/secure-data", + "title": "Securing your data" + } + ], + "resultChars": 54248 + } + ] + }, + "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": [] + }, + "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": true + }, + { + "name": "description column exists in the live database", + "passed": false + } + ], + "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": [] + }, + "docs": { + "calls": [ + { + "source": "search_docs", + "query": "query {\n searchDocs(query: \"pgmq create_queue send pop delete supabase queues\", limit: 5) {\n edges {\n node {\n title\n href\n content\n }\n }\n }\n}", + "hasContent": true, + "pages": [ + { + "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/expose-self-hosted-queues", + "title": "Expose Queues for local and self-hosted Supabase" + }, + { + "url": "https://supabase.com/docs/guides/queues/pgmq", + "title": "PGMQ Extension" + }, + { + "url": "https://supabase.com/docs/guides/queues/api", + "title": "API" + } + ], + "resultChars": 39433 + }, + { + "source": "search_docs", + "query": "query {\n searchDocs(query: \"pg_cron schedule cron.schedule supabase\", limit: 10) {\n edges {\n node {\n title\n href\n content\n }\n }\n }\n}", + "hasContent": true, + "pages": [ + { + "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/functions/schedule-functions", + "title": "Scheduling Edge Functions" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/wrappers/overview", + "title": "Foreign Data Wrappers" + }, + { + "url": "https://supabase.com/docs/guides/cron", + "title": "Cron" + }, + { + "url": "https://supabase.com/docs/guides/ai/automatic-embeddings", + "title": "Automatic embeddings" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pg_cron", + "title": "pg_cron: Schedule Recurring Jobs with Cron Syntax in Postgres" + }, + { + "url": "https://supabase.com/docs/guides/database/migrating-to-pg-partman", + "title": "Migrate from TimescaleDB to pg_partman" + }, + { + "url": "https://supabase.com/docs/guides/cron/install", + "title": "Install" + }, + { + "url": "https://supabase.com/docs/guides/auth/auth-hooks/send-sms-hook", + "title": "Send SMS Hook" + } + ], + "resultChars": 97365 + } + ] + }, + "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-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": [] + }, + "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: {\"msg\":\"Error: Missing authorization header\"}" + }, + { + "name": "user with JWT reads only their own rows", + "passed": true, + "notes": "status 200: [{\"user_id\":\"d99e65f4-0b3c-49a0-9446-e33ca0a6a19e\",\"metric\":\"steps_a_msgixdyc\",\"value\":111}]" + }, + { + "name": "user cannot read another user's rows by passing user_id", + "passed": true, + "notes": "status 200: [{\"user_id\":\"d99e65f4-0b3c-49a0-9446-e33ca0a6a19e\",\"metric\":\"steps_a_msgixdyc\",\"value\":111}]" + }, + { + "name": "service key bypasses RLS to read the target user's rows", + "passed": false, + "notes": "status 401: {\"error\":\"Missing Authorization bearer token\"}" + }, + { + "name": "non-service key is not granted service access", + "passed": true, + "notes": "status 401: {\"error\":\"Missing Authorization bearer token\"}" + }, + { + "name": "rejects an unverified (forged) user token", + "passed": true, + "notes": "status 401: {\"msg\":\"Invalid JWT\"}" + }, + { + "name": "a user token in the apikey slot is not treated as the service key", + "passed": true, + "notes": "status 401: {\"error\":\"Missing Authorization bearer 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": [ + { + "source": "search_docs", + "query": "query {\n searchDocs(query: \"Edge Function getUser service_role apikey header auth.getUser Supabase JavaScript\", limit: 5) {\n nodes {\n title\n href\n ... on Guide { content }\n ... on ClientLibraryFunctionReference { methodName language content href }\n }\n totalCount\n }\n}", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/reference/javascript/auth-getuser" + }, + { + "url": "https://supabase.com/docs/reference/javascript/auth-admin-deleteuser" + }, + { + "url": "https://supabase.com/docs/reference/javascript/auth-admin-listusers" + }, + { + "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/javascript/oauth-admin-getclient" + } + ], + "resultChars": 18338 + }, + { + "source": "search_docs", + "query": "query {\n searchDocs(query: \"Supabase Edge Function SUPABASE_SERVICE_ROLE_KEY environment variable Deno.env.get\", limit: 10) {\n nodes {\n title\n href\n content\n }\n totalCount\n }\n}", + "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/guides/troubleshooting/inspecting-edge-function-environment-variables-wg5qOQ", + "title": "Inspecting edge function environment variables" + }, + { + "url": "https://supabase.com/docs/guides/database/connecting-to-postgres/serverless-drivers", + "title": "Serverless Drivers" + }, + { + "url": "https://supabase.com/docs/guides/functions/quickstart", + "title": "Getting Started with Edge Functions" + }, + { + "url": "https://supabase.com/docs/guides/functions/examples/sentry-monitoring", + "title": "Monitoring with Sentry" + }, + { + "url": "https://supabase.com/docs/guides/functions/development-environment", + "title": "Development Environment" + }, + { + "url": "https://supabase.com/docs/guides/functions/quickstart-dashboard", + "title": "Getting Started with Edge Functions (Dashboard)" + }, + { + "url": "https://supabase.com/docs/guides/local-development/cli/testing-and-linting", + "title": "Testing and linting" + } + ], + "resultChars": 68191 + } + ] + }, + "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: 019fd385-317f-7581-bf33-7fa76b6300d4/receipt-alpha.pdf, 019fd385-317f-7581-bf33-7fa76b6300d4/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": "The answer creates a private user-files bucket, keeps storage.objects RLS enabled, adds authenticated owner-scoped SELECT and INSERT policies using bucket_id plus auth.uid()-based path/owner constraints, and provides supabase-js createSignedUrl with a 1-hour expiry. No public bucket/getPublicUrl/service role misuse." + } + ], + "skills": { + "available": [], + "loaded": [] + }, + "docs": { + "calls": [ + { + "source": "search_docs", + "query": "query {\n searchDocs(query: \"Storage signed URLs createSignedUrl supabase-js\", limit: 5) {\n nodes {\n __typename\n ... on Guide { title href content }\n ... on ClientLibraryFunctionReference { title href language methodName content }\n ... on TroubleshootingGuide { title href content }\n }\n }\n}", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/storage/serving/downloads", + "title": "Serving assets from Storage" + }, + { + "url": "https://supabase.com/docs/guides/storage/serving/image-transformations", + "title": "Storage Image Transformations" + }, + { + "url": "https://supabase.com/docs/guides/storage/uploads/resumable-uploads", + "title": "Resumable Uploads" + }, + { + "url": "https://supabase.com/docs/guides/platform/manage-your-usage/storage-image-transformations", + "title": "Manage Storage Image Transformations usage" + }, + { + "url": "https://supabase.com/docs/reference/swift/storage-from-createsignedurls", + "title": "from.createSignedUrls()" + } + ], + "resultChars": 46993 + }, + { + "source": "search_docs", + "query": "query {\n searchDocs(query: \"storage objects RLS policy auth.uid name like uid prefix bucket private\", limit: 10) {\n nodes {\n __typename\n ... on Guide { title href content }\n ... on ClientLibraryFunctionReference { title href language methodName content }\n }\n }\n}", + "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/storage/schema/helper-functions", + "title": "Storage Helper Functions" + }, + { + "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/schema/design", + "title": "The Storage Schema" + }, + { + "url": "https://supabase.com/docs/guides/local-development/database-migrations", + "title": "Database migrations" + }, + { + "url": "https://supabase.com/docs/guides/resources/glossary", + "title": "Glossary" + }, + { + "url": "https://supabase.com/docs/guides/auth/third-party/clerk", + "title": "Clerk" + }, + { + "url": "https://supabase.com/docs/guides/storage/schema/custom-roles", + "title": "Custom Roles" + } + ], + "resultChars": 56975 + }, + { + "source": "search_docs", + "query": "query {\n searchDocs(query: \"Storage object ownership owner_id auth.uid\", limit: 5) {\n nodes {\n __typename\n ... on Guide { title href content }\n }\n }\n}", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/storage/security/ownership", + "title": "Ownership" + }, + { + "url": "https://supabase.com/docs/guides/storage/management/copy-move-objects", + "title": "Copy Objects" + }, + { + "url": "https://supabase.com/docs/guides/security/product-security", + "title": "Secure configuration of Supabase products" + }, + { + "url": "https://supabase.com/docs/guides/getting-started/features", + "title": "Features" + }, + { + "url": "https://supabase.com/docs/guides/storage/schema/design", + "title": "The Storage Schema" + } + ], + "resultChars": 22482 + } + ] + }, + "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 broken tenant isolation policy, specifically that it allowed members of any org to read posts from other orgs. It grounds the conclusion in the pgTAP result: the negative `posts` case failed before the fix, while notes passed, then the suite passed after updating the policy." + } + ], + "skills": { + "available": [], + "loaded": [] + }, + "docs": { + "calls": [ + { + "source": "search_docs", + "query": "query {\n searchDocs(query: \"pgTAP auth.uid set role supabase test authenticated request.jwt.claim.sub\", 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/local-development/testing/overview", + "title": "Testing Overview" + }, + { + "url": "https://supabase.com/docs/guides/auth/third-party/firebase-auth", + "title": "Firebase Auth" + }, + { + "url": "https://supabase.com/docs/guides/auth/third-party/workos", + "title": "WorkOS" + }, + { + "url": "https://supabase.com/docs/guides/auth/third-party/auth0", + "title": "Auth0" + }, + { + "url": "https://supabase.com/docs/guides/auth/third-party/aws-cognito", + "title": "Amazon Cognito (Amplify)" + } + ], + "resultChars": 42544 + } + ] + }, + "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": [] + }, + "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": true, + "judgeNotes": "Meets all requirements: existing app scrape preserved, Supabase target uses HTTPS with the required metrics path, Basic Auth with password_file, and docker-compose wires the password file via a Compose secret." + }, + { + "name": "documented live deployment and verification steps", + "passed": false, + "judgeNotes": "README places the secret file and restarts the Compose stack, but it does not explain how to create the Supabase Secret API key, and verification is too vague ('Confirm the supabase job is healthy') without concrete Prometheus Targets/PromQL/Grafana steps." + } + ], + "skills": { + "available": [], + "loaded": [] + }, + "docs": { + "calls": [ + { + "source": "web_search", + "query": "site:supabase.com/docs project metrics prometheus scrape endpoint supabase", + "pages": [] + }, + { + "source": "web_search", + "query": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic", + "pages": [ + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic" + } + ] + } + ] + }, + "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 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": [] + }, + "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": "web_search", + "query": "site:supabase.com/docs self-hosting docker compose env secrets supabase", + "pages": [] + }, + { + "source": "web_search", + "query": "https://supabase.com/docs/guides/self-hosting/docker", + "pages": [ + { + "url": "https://supabase.com/docs/guides/self-hosting/docker" + } + ] + } + ] + }, + "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, + "passed": true, "checks": [ { "name": "victim session active before delete-account", @@ -10556,8 +12059,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", @@ -10565,8 +12067,8 @@ }, { "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." + "passed": true, + "judgeNotes": "Identifies soft-delete-only bug, implements real auth user deletion with cascading session/refresh token removal, adds RLS live-profile checks so stale JWTs cannot access data path, explains JWT local-validity caveat and data-path window consistently, and correctly distinguishes publishable/frontend/RLS from secret/server-only/bypass-RLS keys." } ], "skills": { @@ -10576,20 +12078,949 @@ "docs": { "calls": [ { - "source": "web_search", - "query": "site:supabase.com/docs publishable key secret key anon service_role RLS Supabase", - "pages": [] + "source": "search_docs", + "query": "query { searchDocs(query:\"delete user revoke sessions Supabase auth admin deleteUser access token valid after deletion\", limit: 5) { nodes { title href content ... on Guide { subsections { 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/auth/managing-user-data#accessing-user-data-via-api", + "title": "Accessing user data via API" + }, + { + "url": "https://supabase.com/docs/guides/auth/managing-user-data#exporting-users", + "title": "Exporting users" + }, + { + "url": "https://supabase.com/docs/guides/auth/managing-user-data#deleting-users", + "title": "Deleting users" + }, + { + "url": "https://supabase.com/docs/guides/auth/managing-user-data#adding-and-retrieving-user-metadata", + "title": "Adding and retrieving user metadata" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions", + "title": "User sessions" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions#initiating-a-session", + "title": "Initiating a session" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions#what-is-a-session", + "title": "What is a session?" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions#access-token-jwt-claims", + "title": "Access token (JWT) claims" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions#limiting-session-lifetime-and-number-of-allowed-sessions-per-user", + "title": "Limiting session lifetime and number of allowed sessions per user" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions#frequently-asked-questions", + "title": "Frequently asked questions" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions#what-are-recommended-values-for-access-token-jwt-expiration", + "title": "What are recommended values for access token (JWT) expiration?" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions#what-is-refresh-token-reuse-detection-and-what-does-it-protect-from", + "title": "What is refresh token reuse detection and what does it protect from?" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions#what-are-the-benefits-of-using-access-and-refresh-tokens-instead-of-traditional-sessions", + "title": "What are the benefits of using access and refresh tokens instead of traditional sessions?" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions#how-to-ensure-an-access-token-jwt-cannot-be-used-after-a-user-signs-out", + "title": "How to ensure an access token (JWT) cannot be used after a user signs out" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions#using-http-only-cookies-to-store-access-and-refresh-tokens", + "title": "Using HTTP-only cookies to store access and refresh tokens" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows", + "title": "OAuth 2.1 Flows" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#confidential-clients-token_endpoint_auth_method-client_secret_post", + "title": "Confidential clients (token_endpoint_auth_method: client_secret_post)" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#example-in-javascript", + "title": "Example in JavaScript" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#step-6-token-response", + "title": "Step 6: Token response" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#access-token-structure", + "title": "Access token structure" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#oauth-specific-claims", + "title": "OAuth-specific claims" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#available-scopes", + "title": "Available scopes" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#refresh-token-flow", + "title": "Refresh token flow" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#when-to-refresh", + "title": "When to refresh" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#refresh-request", + "title": "Refresh request" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#confidential-clients-token_endpoint_auth_method-client_secret_basic-1", + "title": "Confidential clients (token_endpoint_auth_method: client_secret_basic)" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#public-clients-token_endpoint_auth_method-none-1", + "title": "Public clients (token_endpoint_auth_method: none)" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#confidential-clients-token_endpoint_auth_method-client_secret_post-1", + "title": "Confidential clients (token_endpoint_auth_method: client_secret_post)" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#example-in-javascript-1", + "title": "Example in JavaScript" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#refresh-response", + "title": "Refresh response" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#openid-connect-oidc", + "title": "OpenID Connect (OIDC)" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#id-tokens", + "title": "ID tokens" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#example-id-token", + "title": "Example ID token" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#standard-oidc-claims", + "title": "Standard OIDC claims" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#userinfo-endpoint", + "title": "UserInfo endpoint" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#oidc-discovery", + "title": "OIDC discovery" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#token-validation", + "title": "Token validation" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#jwks-endpoint", + "title": "JWKS endpoint" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#validating-tokens", + "title": "Validating tokens" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#what-to-validate", + "title": "What to validate" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#managing-user-grants", + "title": "Managing user grants" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#viewing-authorized-applications", + "title": "Viewing authorized applications" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#revoking-access", + "title": "Revoking access" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#next-steps", + "title": "Next steps" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#supported-grant-types", + "title": "Supported grant types" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#authorization-code-flow-with-pkce", + "title": "Authorization code flow with PKCE" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#how-it-works", + "title": "How it works" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#flow-diagram", + "title": "Flow diagram" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#step-1-generate-pkce-parameters", + "title": "Step 1: Generate PKCE parameters" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#step-2-authorization-request", + "title": "Step 2: Authorization request" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#required-parameters", + "title": "Required parameters" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#optional-parameters", + "title": "Optional parameters" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#step-3-user-authentication-and-consent", + "title": "Step 3: User authentication and consent" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#step-4-authorization-code-issued", + "title": "Step 4: Authorization code issued" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#step-5-token-exchange", + "title": "Step 5: Token exchange" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#public-clients-token_endpoint_auth_method-none", + "title": "Public clients (token_endpoint_auth_method: none)" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows#confidential-clients-token_endpoint_auth_method-client_secret_basic", + "title": "Confidential clients (token_endpoint_auth_method: client_secret_basic)" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso", + "title": "Enable SSO for Your Organization" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso#key-configuration-options", + "title": "Key configuration options" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso#need-help-choosing", + "title": "Need help choosing?" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso#sp-initiated-login", + "title": "SP-initiated login" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso#idp-initiated-login-recommended", + "title": "IdP-initiated login (recommended)" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso#choosing-your-login-flow", + "title": "Choosing your login flow" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso#supported-providers", + "title": "Supported providers" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso#advanced-scenarios", + "title": "Advanced scenarios" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso#testing-and-best-practices", + "title": "Testing and best practices" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso#removing-an-individual-sso-users-access", + "title": "Removing an individual SSO user's access" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso#disabling-sso-for-an-organization", + "title": "Disabling SSO for an organization" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso#enabling-sso-for-an-organization", + "title": "Enabling SSO for an organization" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso#how-sso-works-in-supabase", + "title": "How SSO works in Supabase" + }, + { + "url": "https://supabase.com/docs/guides/auth", + "title": "Auth" + }, + { + "url": "https://supabase.com/docs/guides/auth#about-authentication-and-authorization", + "title": "About authentication and authorization" + }, + { + "url": "https://supabase.com/docs/guides/auth#the-supabase-ecosystem", + "title": "The Supabase ecosystem" + }, + { + "url": "https://supabase.com/docs/guides/auth#providers", + "title": "Providers" + }, + { + "url": "https://supabase.com/docs/guides/auth#social-auth", + "title": "Social Auth" + }, + { + "url": "https://supabase.com/docs/guides/auth#phone-auth", + "title": "Phone Auth" + }, + { + "url": "https://supabase.com/docs/guides/auth#pricing", + "title": "Pricing" + } + ], + "resultChars": 191327 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query:\"RLS deleted user profile deleted policy auth.uid Supabase\", limit: 5) { nodes { title href content ... on Guide { subsections { 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/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#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#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/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#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#benchmarks-2", + "title": "Benchmarks" + }, + { + "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/storage/management/delete-objects", + "title": "Delete Objects" + }, + { + "url": "https://supabase.com/docs/guides/storage/management/delete-objects#rls", + "title": "RLS" + }, + { + "url": "https://supabase.com/docs/guides/storage/management/delete-objects#emptying-large-buckets", + "title": "Emptying large buckets" + }, + { + "url": "https://supabase.com/docs/guides/storage/management/delete-objects#delete-objects", + "title": "Delete objects" + }, + { + "url": "https://supabase.com/docs/guides/storage/schema/helper-functions", + "title": "Storage Helper Functions" + }, + { + "url": "https://supabase.com/docs/guides/storage/schema/helper-functions#storageextension", + "title": "storage.extension()" + }, + { + "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/schema/helper-functions#storageallow_any_operation", + "title": "storage.allow_any_operation()" + }, + { + "url": "https://supabase.com/docs/guides/storage/schema/helper-functions#storagefilename", + "title": "storage.filename()" + }, + { + "url": "https://supabase.com/docs/guides/storage/schema/helper-functions#storagefoldername", + "title": "storage.foldername()" + }, + { + "url": "https://supabase.com/docs/guides/auth/users", + "title": "Users" + }, + { + "url": "https://supabase.com/docs/guides/auth/users#permanent-and-anonymous-users", + "title": "Permanent and anonymous users" + }, + { + "url": "https://supabase.com/docs/guides/auth/users#resources", + "title": "Resources" + }, + { + "url": "https://supabase.com/docs/guides/auth/users#the-user-object", + "title": "The user object" + }, + { + "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended", + "title": "Advanced pgTAP Testing" + }, + { + "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/local-development/testing/pgtap-extended#using-databasedev", + "title": "Using database.dev" + }, + { + "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#setting-up-dbdev", + "title": "Setting up dbdev" + }, + { + "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#installing-test-helpers", + "title": "Installing test helpers" + }, + { + "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#test-helper-benefits", + "title": "Test helper benefits" + }, + { + "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#test-file-organization", + "title": "Test file organization" + }, + { + "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/local-development/testing/pgtap-extended#benefits", + "title": "Benefits" + }, + { + "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/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/local-development/testing/pgtap-extended#system-overview", + "title": "System overview" + }, + { + "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/local-development/testing/pgtap-extended#testing-focus-areas", + "title": "Testing focus areas" + }, + { + "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/local-development/testing/pgtap-extended#2-grant-role-privileges", + "title": "2. Grant role privileges" + }, + { + "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/local-development/testing/pgtap-extended#4-test-cases", + "title": "4. Test cases:" + }, + { + "url": "https://supabase.com/docs/guides/local-development/testing/pgtap-extended#additional-resources", + "title": "Additional resources" + } + ], + "resultChars": 149185 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query:\"Supabase revoke refresh tokens delete session admin delete user sign out immediate\", 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/guides/auth/oauth-server/oauth-flows", + "title": "OAuth 2.1 Flows" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions", + "title": "User sessions" + }, + { + "url": "https://supabase.com/docs/guides/auth/signout", + "title": "Signing out" + }, + { + "url": "https://supabase.com/docs/guides/auth/signing-keys", + "title": "JWT Signing Keys" + }, + { + "url": "https://supabase.com/docs/guides/auth", + "title": "Auth" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwts", + "title": "JSON Web Token (JWT)" + }, + { + "url": "https://supabase.com/docs/reference/javascript/oauth-server-revokegrant" + }, + { + "url": "https://supabase.com/docs/guides/integrations/build-a-supabase-oauth-integration", + "title": "Build a Supabase Integration" + }, + { + "url": "https://supabase.com/docs/guides/auth/server-side/advanced-guide", + "title": "Advanced guide" + } + ], + "resultChars": 129795 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query:\"Supabase sign out all sessions admin revoke user sessions\", limit: 10) { nodes { title href content } } }", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/auth/passkeys", + "title": "Passkey authentication" + }, + { + "url": "https://supabase.com/docs/guides/auth/signout", + "title": "Signing out" + }, + { + "url": "https://supabase.com/docs/guides/auth/auth-hooks/password-verification-hook", + "title": "Password Verification Hook" + }, + { + "url": "https://supabase.com/docs/guides/auth/auth-hooks/custom-access-token-hook", + "title": "Custom Access Token Hook" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions", + "title": "User sessions" + }, + { + "url": "https://supabase.com/docs/guides/auth/oauth-server/oauth-flows", + "title": "OAuth 2.1 Flows" + }, + { + "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", + "title": "Row Level Security" + }, + { + "url": "https://supabase.com/docs/guides/auth/managing-user-data", + "title": "User Management" + }, + { + "url": "https://supabase.com/docs/guides/auth/auth-hooks/mfa-verification-hook", + "title": "MFA Verification Hook" + } + ], + "resultChars": 149790 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query:\"Supabase banned_until deleted_at auth.users ban user sign in\", 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/guides/auth/sessions", + "title": "User sessions" + }, + { + "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/auth0", + "title": "Migrate from Auth0 to Supabase Auth" + }, + { + "url": "https://supabase.com/docs/guides/auth", + "title": "Auth" + }, + { + "url": "https://supabase.com/docs/guides/auth/auth-hooks/before-user-created-hook", + "title": "Before User Created Hook" + }, + { + "url": "https://supabase.com/docs/guides/deployment/going-into-prod", + "title": "Production Checklist" + }, + { + "url": "https://supabase.com/docs/guides/auth/auth-anonymous", + "title": "Anonymous Sign-Ins" + }, + { + "url": "https://supabase.com/docs/guides/auth/social-login/auth-apple", + "title": "Login with Apple" + }, + { + "url": "https://supabase.com/docs/guides/database/secure-data", + "title": "Securing your data" + }, + { + "url": "https://supabase.com/docs/guides/troubleshooting/dashboard-errors-when-managing-users-N1ls4A", + "title": "Errors when creating / updating / deleting users" + } + ], + "resultChars": 158620 }, { - "source": "web_search", - "query": "site:supabase.com/docs migrating to new API keys publishable secret keys Supabase docs", - "pages": [] + "source": "search_docs", + "query": "query { searchDocs(query:\"Supabase admin update user ban deleted_at\", 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/guides/auth/passkeys", + "title": "Passkey authentication" + }, + { + "url": "https://supabase.com/docs/guides/auth/auth-anonymous", + "title": "Anonymous Sign-Ins" + }, + { + "url": "https://supabase.com/docs/guides/platform/access-control", + "title": "Access Control" + } + ], + "resultChars": 102044 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query:\"Supabase delete user auth.users deleted_at banned_until\", 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/guides/auth/auth-anonymous", + "title": "Anonymous Sign-Ins" + }, + { + "url": "https://supabase.com/docs/guides/troubleshooting/dashboard-errors-when-managing-users-N1ls4A", + "title": "Errors when creating / updating / deleting users" + }, + { + "url": "https://supabase.com/docs/guides/auth/rate-limits", + "title": "Rate limits" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions", + "title": "User sessions" + }, + { + "url": "https://supabase.com/docs/guides/auth", + "title": "Auth" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso", + "title": "Enable SSO for Your Organization" + }, + { + "url": "https://supabase.com/docs/guides/troubleshooting/auth-error-500-database-error-querying-schema-eb6b44", + "title": "Auth error: '500: Database error querying schema'" + }, + { + "url": "https://supabase.com/docs/guides/troubleshooting/database-error-saving-new-user-RU_EwB", + "title": "Database error saving new user" + }, + { + "url": "https://supabase.com/docs/guides/api/custom-claims-and-role-based-access-control-rbac", + "title": "Custom Claims & Role-based Access Control (RBAC)" + } + ], + "resultChars": 77184 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query:\"Supabase user_banned banned_until auth.users update ban\", 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/guides/troubleshooting/dashboard-errors-when-managing-users-N1ls4A", + "title": "Errors when creating / updating / deleting users" + }, + { + "url": "https://supabase.com/docs/guides/auth/users", + "title": "Users" + }, + { + "url": "https://supabase.com/docs/guides/auth/rate-limits", + "title": "Rate limits" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions", + "title": "User sessions" + }, + { + "url": "https://supabase.com/docs/guides/auth", + "title": "Auth" + }, + { + "url": "https://supabase.com/docs/guides/database/secure-data", + "title": "Securing your data" + }, + { + "url": "https://supabase.com/docs/guides/platform/temporary-access", + "title": "Temporary access" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles", + "title": "Postgres Roles" + }, + { + "url": "https://supabase.com/docs/guides/api/custom-claims-and-role-based-access-control-rbac", + "title": "Custom Claims & Role-based Access Control (RBAC)" + } + ], + "resultChars": 75533 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query:\"Supabase publishable key secret key anon service role RLS\", limit: 10) { 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/database/secure-data", + "title": "Securing your 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/functions/secrets", + "title": "Environment Variables" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/row-level-security", + "title": "Row Level Security" + }, + { + "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-sveltekit", + "title": "Build a User Management App with SvelteKit" + }, + { + "url": "https://supabase.com/docs/guides/getting-started/quickstarts/sveltekit", + "title": "Use Supabase with SvelteKit" + }, + { + "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-nextjs", + "title": "Build a User Management App with Next.js" + } + ], + "resultChars": 233124 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query:\"Supabase API keys publishable secret key frontend backend\", limit: 10) { nodes { title href content } } }", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/auth/signing-keys", + "title": "JWT Signing Keys" + }, + { + "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/secure-data", + "title": "Securing your 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/self-hosting/docker", + "title": "Self-Hosting with Docker" + }, + { + "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/self-hosting/self-hosted-s3", + "title": "Configure S3 Storage" + }, + { + "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/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-angular", + "title": "Build a User Management App with Angular" + } + ], + "resultChars": 258792 } ] }, "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": "codex-gpt-5.4-mini-no-skills/investigate-auth-001-deleted-user-access.json" }, { @@ -10638,7 +13069,7 @@ { "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." + "judgeNotes": "The assistant correctly identified that the subscription could reach SUBSCRIBED but not receive INSERT events because public.orders was missing from the supabase_realtime publication. It fixed exactly that with ALTER PUBLICATION supabase_realtime ADD TABLE public.orders, verified courier_locations remained present, and did not alter RLS or policies." } ], "skills": { @@ -10672,22 +13103,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 recurring HTTP 503 gateway failures throughout the morning of 2026-04-28, covering the relevant 07:00Z-12:00Z window and most/all failures." + "judgeNotes": "Identified image-transform as the affected function and explicitly described the recurring HTTP 503 pattern across the morning of 2026-04-28, listing 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 image-transform 503s to gateway/platform layer, supported by unchanged deployment/version with intermittent successes and distinction from avatar-upload's function-level 500." + "passed": false, + "judgeNotes": "The assistant attributes the 503s primarily to the image-transform function/package/runtime path and recommends inspecting/rolling back/redeploying the function. It does not identify the gateway/Edge Functions platform layer in front of the function as the source, nor ground that attribution in missing invocation/runtime rows or unchanged deployment/version evidence." }, { "name": "recommended a concrete next step", "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." + "judgeNotes": "The assistant recommended concrete actionable next steps, including inspecting the specific deployment/package version, checking platform/dependency instability, rolling back or redeploying, and adding alerts/retry handling." } ], "skills": { @@ -10753,7 +13184,7 @@ { "name": "diagnosed RLS and added owner-scoped policies", "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": "Diagnosed RLS enabled with no policies causing deny-all Data API behavior; kept RLS enabled; added authenticated SELECT policy using auth.uid() = user_id and authenticated INSERT policy with check auth.uid() = user_id." } ], "skills": { @@ -10787,7 +13218,7 @@ ], "suite": "benchmark", "interface": "cli", - "passed": false, + "passed": true, "checks": [ { "name": "the avatar_url column is applied on the hosted profiles table", @@ -10795,18 +13226,15 @@ }, { "name": "migration 20240220000000 is recorded in the remote history", - "passed": false, - "notes": "remote history versions: [\"20240101000000\",\"20240115000000\"]" + "passed": true }, { "name": "remote migration history matches local migration files", - "passed": false, - "notes": "remote-only versions still unreconciled: [\"20240115000000\"] (remote: [\"20240101000000\",\"20240115000000\"], local: [\"20240101000000\",\"20240220000000\"])" + "passed": true }, { "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]" + "passed": true }, { "name": "production profile data is intact (not reset)", @@ -10814,8 +13242,8 @@ }, { "name": "the avatar migration and history reconciliation were done via the Supabase CLI", - "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." + "passed": true, + "judgeNotes": "Applied avatar_url via `supabase db push --db-url ... --yes` (#34), which showed `Applying migration 20240220000000_add_avatar_url.sql...` and `Finished supabase db push.` Reconciled orphan bio migration by adding local `supabase/migrations/20240115000000_add_profile_bio.sql` (#32), after which migration list matched and push proceeded. No disallowed direct SQL mutation or prepared-statement workaround seen." } ], "skills": { @@ -10827,7 +13255,7 @@ }, "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, + "attempts": 1, "sourcePath": "codex-gpt-5.4-mini-no-skills/resolve-database-001-migration-history-mismatch.json" }, { @@ -10945,823 +13373,351 @@ "name": "tenant B cannot insert into org A", "passed": true } - ], - "skills": { - "available": [], - "loaded": [] - }, - "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", - "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" - ] - }, - "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 } } }", - "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/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/auth/auth-anonymous", - "title": "Anonymous Sign-Ins" - }, - { - "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/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" - }, - { - "url": "https://supabase.com/docs/reference/cli/supabase-db-diff", - "title": "Diffs the local database for schema changes" - }, - { - "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" - ] + ], + "skills": { + "available": [], + "loaded": [] }, "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/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/cron", - "title": "Cron" - }, - { - "url": "https://supabase.com/docs/guides/cron#how-does-cron-work", - "title": "How does Cron work?" - }, - { - "url": "https://supabase.com/docs/guides/cron#resources", - "title": "Resources" - }, - { - "url": "https://supabase.com/docs/guides/functions/schedule-functions", - "title": "Scheduling Edge Functions" - }, - { - "url": "https://supabase.com/docs/guides/functions/schedule-functions#examples", - "title": "Examples" - }, - { - "url": "https://supabase.com/docs/guides/functions/schedule-functions#resources", - "title": "Resources" - }, - { - "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/database/extensions/pg_net", - "title": "pg_net: Async Networking" - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#http_delete", - "title": "http_delete" - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#debugging-requests", - "title": "Debugging requests" - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#analyzing-responses", - "title": "Analyzing responses" - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#delete-usage", - "title": "Usage " - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#post-usage", - "title": "Usage " - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#post-signature", - "title": "Signature " - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#http_post", - "title": "http_post" - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#get-usage", - "title": "Usage " - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#get-signature", - "title": "Signature " - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#http_get", - "title": "http_get" - }, - { - "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#resources", - "title": "Resources" - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#limitations", - "title": "Limitations" - }, - { - "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/database/extensions/pg_net#execute-pg_net-in-a-trigger", - "title": "Execute pg_net in a trigger" - }, - { - "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/database/extensions/pg_net#invoke-a-supabase-edge-function", - "title": "Invoke a Supabase Edge Function" - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#examples", - "title": "Examples" - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#alter-settings", - "title": "Alter settings" - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#get-current-settings", - "title": "Get current settings" - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#configuration", - "title": "Configuration" - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#inspecting-failed-requests", - "title": "Inspecting failed requests" - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#inspecting-request-data", - "title": "Inspecting request data" - }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#post-signature-1", - "title": "Signature " - }, - { - "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/queues/quickstart", - "title": "Quickstart" - }, - { - "url": "https://supabase.com/docs/guides/queues/quickstart#pull-based-queue", - "title": "Pull-Based Queue" - }, - { - "url": "https://supabase.com/docs/guides/queues/quickstart#create-queues", - "title": "Create Queues" - }, - { - "url": "https://supabase.com/docs/guides/queues/quickstart#queue-types", - "title": "Queue types" - }, - { - "url": "https://supabase.com/docs/guides/queues/quickstart#message", - "title": "Message" - }, - { - "url": "https://supabase.com/docs/guides/queues/quickstart#concepts", - "title": "Concepts" - }, - { - "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#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#expose-queues-to-client-side-consumers", - "title": "Expose Queues to client-side consumers" - }, - { - "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/cron/quickstart", - "title": "Quickstart" - }, - { - "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/cron/quickstart#delete-data-every-week", - "title": "Delete data every week" - }, - { - "url": "https://supabase.com/docs/guides/cron/quickstart#caution-scheduling-system-maintenance", - "title": "Caution: Scheduling system maintenance" - }, - { - "url": "https://supabase.com/docs/guides/cron/quickstart#examples", - "title": "Examples" - }, - { - "url": "https://supabase.com/docs/guides/cron/quickstart#unschedule-a-job", - "title": "Unschedule a job" - }, - { - "url": "https://supabase.com/docs/guides/cron/quickstart#inspecting-job-runs", - "title": "Inspecting job runs" - }, - { - "url": "https://supabase.com/docs/guides/cron/quickstart#activatedeactivate-a-job", - "title": "Activate/Deactivate a job" - }, - { - "url": "https://supabase.com/docs/guides/cron/quickstart#edit-a-job", - "title": "Edit a job" - }, - { - "url": "https://supabase.com/docs/guides/cron/quickstart#schedule-a-job", - "title": "Schedule a job" - }, - { - "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/cron/quickstart#call-a-database-stored-procedure", - "title": "Call a database stored procedure" - }, - { - "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/cron/install", - "title": "Install" - }, - { - "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/queues/pgmq", - "title": "PGMQ Extension" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#drop_queue", - "title": "drop_queue" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#sending-messages", - "title": "Sending messages" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#send", - "title": "send" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#send_batch", - "title": "send_batch" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#reading-messages", - "title": "Reading messages" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#read", - "title": "read" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#read_with_poll", - "title": "read_with_poll" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#pop", - "title": "pop" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#deletingarchiving-messages", - "title": "Deleting/Archiving messages" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#delete-single", - "title": "delete (single)" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#delete-batch", - "title": "delete (batch)" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#purge_queue", - "title": "purge_queue" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#archive-single", - "title": "archive (single)" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#archive-batch", - "title": "archive (batch)" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#utilities", - "title": "Utilities" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#set_vt", - "title": "set_vt" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#list_queues", - "title": "list_queues" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#metrics", - "title": "metrics" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#metrics_all", - "title": "metrics_all" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#types", - "title": "Types" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#message_record", - "title": "message_record" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#resources", - "title": "Resources" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#features", - "title": "Features" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#enable-the-extension", - "title": "Enable the extension" - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#get-usage", - "title": "Usage " - }, - { - "url": "https://supabase.com/docs/guides/queues/pgmq#queue-management", - "title": "Queue management" - }, + "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", + "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 row level security authenticated role select policy anon no rows seed data\", limit: 5) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } } } }", + "hasContent": true, + "pages": [ { - "url": "https://supabase.com/docs/guides/queues/pgmq#create", - "title": "create" + "url": "https://supabase.com/docs/guides/database/postgres/row-level-security", + "title": "Row Level Security" }, { - "url": "https://supabase.com/docs/guides/queues/pgmq#create_unlogged", - "title": "create_unlogged" + "url": "https://supabase.com/docs/guides/local-development/cli-workflows", + "title": "Local development workflow" }, { - "url": "https://supabase.com/docs/guides/queues/pgmq#detach_archive", - "title": "detach_archive" + "url": "https://supabase.com/docs/guides/api/securing-your-api", + "title": "Securing your API" }, { - "url": "https://supabase.com/docs/guides/queues", - "title": "Supabase Queues" + "url": "https://supabase.com/docs/guides/auth/auth-anonymous", + "title": "Anonymous Sign-Ins" }, { - "url": "https://supabase.com/docs/guides/queues#features", + "url": "https://supabase.com/docs/guides/getting-started/features", "title": "Features" - }, - { - "url": "https://supabase.com/docs/guides/queues#resources", - "title": "Resources" - }, - { - "url": "https://supabase.com/docs/guides/queues/quickstart", - "title": "Quickstart" - }, - { - "url": "https://supabase.com/docs/guides/queues/quickstart#queue-types", - "title": "Queue types" - }, - { - "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#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/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/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_publicreadqueue_name-sleep_seconds-n", - "title": "pgmq_public.read(queue_name, sleep_seconds, n)" - }, - { - "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/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" - }, + } + ], + "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", + "supabase-postgres-best-practices" + ] + }, + "docs": { + "calls": [ + { + "source": "search_docs", + "query": "query { searchDocs(query: \"declarative database schemas local development schema_paths generate migration db diff\", limit: 5) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } } } }", + "hasContent": true, + "pages": [ { - "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions#concepts", - "title": "Concepts" + "url": "https://supabase.com/docs/guides/local-development/declarative-database-schemas", + "title": "Declarative database schemas" }, { - "url": "https://supabase.com/docs/guides/database/functions", - "title": "Database Functions" + "url": "https://supabase.com/docs/guides/deployment/database-migrations", + "title": "Database Migrations" }, { - "url": "https://supabase.com/docs/guides/database/functions#error-handling", - "title": "Error handling" + "url": "https://supabase.com/docs/guides/local-development/cli-workflows", + "title": "Local development workflow" }, { - "url": "https://supabase.com/docs/guides/database/functions#general-logging", - "title": "General logging" + "url": "https://supabase.com/docs/reference/cli/supabase-db-diff", + "title": "Diffs the local database for schema changes" }, { - "url": "https://supabase.com/docs/guides/database/functions#create-database-functions", - "title": "Create Database Functions" - }, + "url": "https://supabase.com/docs/guides/deployment/managing-environments", + "title": "Managing Environments" + } + ], + "resultChars": 72112 + }, + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"curl -fsSL https://supabase.com/changelog.md | rg -n -i 'breaking-change|declarative|migration|schema' | head -40; printf '\\\\n--- config ---\\\\n'; sed -n '1,220p' supabase/config.toml; printf '\\\\n--- schema ---\\\\n'; cat supabase/schemas/products.sql; printf '\\\\n--- migration ---\\\\n'; cat supabase/migrations/20260101000000_create_products.sql; printf '\\\\n--- status ---\\\\n'; supabase status || true\"", + "pages": [ { - "url": "https://supabase.com/docs/guides/database/functions#deep-dive", - "title": "Deep dive" - }, + "url": "https://supabase.com/changelog.md" + } + ], + "resultChars": 9703 + } + ] + }, + "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 1 -> 2" + }, + { + "name": "process-tasks function drains the queue", + "passed": true, + "notes": "function removed the seeded message (id 37) 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 local config verify_jwt\", limit: 8) { nodes { __typename title href content } } }", + "hasContent": true, + "pages": [ { - "url": "https://supabase.com/docs/guides/database/functions#resources", - "title": "Resources" + "url": "https://supabase.com/docs/guides/queues", + "title": "Supabase Queues" }, { - "url": "https://supabase.com/docs/guides/database/functions#advanced-logging", - "title": "Advanced logging" + "url": "https://supabase.com/docs/guides/functions/schedule-functions", + "title": "Scheduling Edge Functions" }, { - "url": "https://supabase.com/docs/guides/database/functions#function-privileges", - "title": "Function privileges" + "url": "https://supabase.com/docs/guides/cron", + "title": "Cron" }, { - "url": "https://supabase.com/docs/guides/database/functions#security-definer-vs-invoker", - "title": "Security definer vs invoker" + "url": "https://supabase.com/docs/guides/queues/quickstart", + "title": "Quickstart" }, { - "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/extensions/pg_net", + "title": "pg_net: Async Networking" }, { - "url": "https://supabase.com/docs/guides/database/functions#suggestions", - "title": "Suggestions" + "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#passing-parameters", - "title": "Passing parameters" + "url": "https://supabase.com/docs/guides/local-development/cli/testing-and-linting", + "title": "Testing and linting" }, { - "url": "https://supabase.com/docs/guides/database/functions#returning-data-sets", - "title": "Returning data sets" - }, + "url": "https://supabase.com/docs/guides/ai/automatic-embeddings", + "title": "Automatic embeddings" + } + ], + "resultChars": 70469 + }, + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"printf '%s\\\\n' '--- config.toml ---'; sed -n '1,260p' supabase/config.toml; printf '%s\\\\n' '--- migration ---'; cat supabase/migrations/20260101000000_enable_cron_and_queues.sql; printf '%s\\\\n' '--- git status ---'; git status --short; printf '%s\\\\n' '--- CLI ---'; supabase --version; printf '%s\\\\n' '--- changelog relevant ---'; curl -fsSL https://supabase.com/changelog.md | rg -i -C 2 'breaking-change|queue|cron|edge function' | sed -n '1,220p'\"", + "pages": [ { - "url": "https://supabase.com/docs/guides/database/functions#simple-functions", - "title": "Simple functions" - }, + "url": "https://supabase.com/changelog.md" + } + ], + "resultChars": 14016 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Queues API SQL pgmq.create pgmq.send pgmq.read pgmq.delete message_record Supabase queue quickstart\", 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", + "title": "Supabase Queues" }, { - "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/quickstart", + "title": "Quickstart" }, { - "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/consuming-messages-with-edge-functions", + "title": "Consuming Supabase Queue Messages with Edge Functions" }, { - "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/queues/pgmq", + "title": "PGMQ Extension" }, { - "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": 43726 } ] }, @@ -11818,24 +13774,29 @@ "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 existing Postgres database dump pg_restore local development Supabase CLI\", limit: 5) { nodes { __typename 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/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" @@ -11843,13 +13804,19 @@ { "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/neon", "title": "Migrate from Neon to Supabase" - }, + } + ], + "resultChars": 42943 + }, + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"set -o pipefail\nprintf '%s\\\\n' '--- workspace ---'\nls -la\nprintf '%s\\\\n' '--- versions ---'\nsupabase --version\npg_restore --version\npsql --version\nprintf '%s\\\\n' '--- dump file ---'\nfile source.dump\nls -lh source.dump\nprintf '%s\\\\n' '--- dump header/list preview ---'\npg_restore --list source.dump | sed -n '1,120p'\nprintf '%s\\\\n' '--- changelog migration/breaking entries ---'\ncurl -fsSL https://supabase.com/changelog.md | rg -n -i 'breaking-change|restore|migration|postgres' | head -80\"", + "pages": [ { - "url": "https://supabase.com/docs/guides/local-development/restoring-downloaded-backup", - "title": "Restoring a downloaded backup locally" + "url": "https://supabase.com/changelog.md" } ], - "resultChars": 42818 + "resultChars": 15064 } ] }, @@ -11915,14 +13882,15 @@ "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 service role RLS security\", limit: 5) { nodes { title href content } } }", "hasContent": true, "pages": [ { @@ -11934,23 +13902,23 @@ "title": "Integrating With Supabase Auth" }, { - "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/auth/auth-mfa", - "title": "Multi-Factor Authentication" + "url": "https://supabase.com/docs/guides/api/securing-your-api", + "title": "Securing your API" }, { - "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/buckets/fundamentals", + "title": "Storage Buckets" } ], - "resultChars": 85366 + "resultChars": 75066 }, { "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: \"Edge Functions authenticate user createClient Authorization header RLS SUPABASE_ANON_KEY getClaims\", limit: 8) { nodes { title href content } } }", "hasContent": true, "pages": [ { @@ -11962,31 +13930,36 @@ "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/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/database/secure-data", - "title": "Securing your data" + "url": "https://supabase.com/docs/guides/getting-started/api-keys", + "title": "Understanding API keys" }, { - "url": "https://supabase.com/docs/guides/auth/users", - "title": "Users" + "url": "https://supabase.com/docs/guides/auth/third-party/clerk", + "title": "Clerk" }, { - "url": "https://supabase.com/docs/guides/auth", - "title": "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/api/securing-your-api", - "title": "Securing your API" + "url": "https://supabase.com/docs/guides/functions/websockets", + "title": "Handling WebSockets" } ], - "resultChars": 98711 + "resultChars": 102061 + }, + { + "source": "web_search", + "query": "site:supabase.com/changelog Edge Functions JWT authentication breaking change 2026", + "pages": [] } ] }, @@ -12034,17 +14007,17 @@ { "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}]" + "notes": "status 200: [{\"user_id\":\"b5e6310e-01e1-4045-ad6e-5e40a635ca6a\",\"metric\":\"steps_a_msgive1n\",\"value\":111}]" }, { "name": "user cannot read another user's rows by passing user_id", "passed": true, - "notes": "status 200: [{\"user_id\":\"34e9425b-8b58-4aa6-9deb-31c762170653\",\"metric\":\"steps_a_ms6z3nra\",\"value\":111}]" + "notes": "status 200: [{\"user_id\":\"b5e6310e-01e1-4045-ad6e-5e40a635ca6a\",\"metric\":\"steps_a_msgive1n\",\"value\":111}]" }, { "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}]" + "notes": "status 200: [{\"user_id\":\"9dc0a147-e6ec-4a55-bbbb-dbf13a659109\",\"metric\":\"steps_b_msgive1n\",\"value\":222}]" }, { "name": "non-service key is not granted service access", @@ -12073,104 +14046,118 @@ "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: \"Edge Functions authentication Authorization header apikey service_role verify_jwt getUser Deno serve\", limit: 8) { 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/websockets", "title": "Handling WebSockets" }, { - "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/getting-started/migrating-to-new-api-keys", - "title": "Migrating to publishable and secret API keys" + "url": "https://supabase.com/docs/guides/functions/http-methods", + "title": "Routing" }, { - "url": "https://supabase.com/docs/guides/functions/auth-headers", - "title": "Authorization headers" + "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/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/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/getting-started/features", + "title": "Features" + } + ], + "resultChars": 72313 + }, + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"printf '%s\\\\n' '---CHANGELOG RELEVANT---'; curl -fsSL https://supabase.com/changelog.md | rg -i -C 2 'breaking-change|edge function|authorization|apikey|jwt' | head -160; printf '%s\\\\n' '---CONFIG---'; cat supabase/config.toml; printf '%s\\\\n' '---MIGRATION---'; cat supabase/migrations/0000_stats_schema.sql; printf '%s\\\\n' '---SECURITY REFERENCES---'; find .agents/skills/supabase-postgres-best-practices/references -maxdepth 1 -type f | sort | rg 'security|rls'\"", + "pages": [ { - "url": "https://supabase.com/docs/guides/functions/http-methods", - "title": "Routing" + "url": "https://supabase.com/changelog.md" } ], - "resultChars": 60939 + "resultChars": 15283 }, { "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: \"Securing Edge Functions service role secret key apikey header SUPABASE_SECRET_KEY environment getUser\", 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/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/getting-started/api-keys", - "title": "Understanding API keys" + "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/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/api-keys", + "title": "Understanding API keys" }, { - "url": "https://supabase.com/docs/guides/functions/function-configuration", - "title": "Function Configuration" + "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt", + "title": "Integrating With Supabase Auth" }, { - "url": "https://supabase.com/docs/guides/auth/jwts", - "title": "JSON Web Token (JWT)" + "url": "https://supabase.com/docs/guides/functions/quickstart-dashboard", + "title": "Getting Started with Edge Functions (Dashboard)" }, { - "url": "https://supabase.com/docs/guides/auth/signing-keys", - "title": "JWT Signing Keys" + "url": "https://supabase.com/docs/reference/javascript/auth-getuser" }, { "url": "https://supabase.com/docs/guides/auth/auth-mfa", "title": "Multi-Factor Authentication" }, { - "url": "https://supabase.com/docs/guides/functions/websockets", - "title": "Handling WebSockets" + "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" } ], - "resultChars": 122455 + "resultChars": 84317 }, { "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: \"SUPABASE_SECRET_KEYS Edge Functions validate incoming apikey @supabase/server verify API key\", 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" @@ -12180,45 +14167,41 @@ "title": "Understanding 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/functions/auth-legacy-jwt", - "title": "Integrating With Supabase Auth" + "url": "https://supabase.com/docs/guides/auth/jwts", + "title": "JSON Web Token (JWT)" }, { - "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/cloudflare-turnstile", + "title": "CAPTCHA support with Cloudflare Turnstile" }, { - "url": "https://supabase.com/docs/guides/auth/signing-keys", - "title": "JWT Signing Keys" + "url": "https://supabase.com/docs/guides/functions/quickstart-dashboard", + "title": "Getting Started with Edge Functions (Dashboard)" }, { "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets", "title": "Resumable WebSockets with Edge Functions" }, { - "url": "https://supabase.com/docs/guides/auth/jwt-fields", - "title": "JWT Claims Reference" + "url": "https://supabase.com/docs/guides/auth/signing-keys", + "title": "JWT Signing Keys" }, { - "url": "https://supabase.com/docs/guides/functions/function-configuration", - "title": "Function Configuration" + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-auth-keys", + "title": "New API Keys and Asymmetric Authentication" } ], - "resultChars": 114347 + "resultChars": 123124 } ] }, "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": "codex-gpt-5.6/build-functions-005-dual-auth-user-secret.json" }, { @@ -12259,7 +14242,7 @@ { "name": "user A lists only own files", "passed": true, - "notes": "saw: 019fb117-0187-77b3-8842-0d324488c642/receipt-alpha.pdf, 019fb117-0187-77b3-8842-0d324488c642/receipt-beta.pdf" + "notes": "saw: 019fd386-1823-752a-ad80-a92bf520bf36/receipt-alpha.pdf, 019fd386-1823-752a-ad80-a92bf520bf36/receipt-beta.pdf" }, { "name": "user B cannot read user A files", @@ -12280,7 +14263,7 @@ { "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." + "judgeNotes": "Meets rubric: private user-files bucket, authenticated owner-scoped SELECT and INSERT storage.objects policies with WITH CHECK for uploads, RLS remains enabled, and supabase-js createSignedUrl with expiry is provided." } ], "skills": { @@ -12289,65 +14272,94 @@ "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: \"Storage access control RLS policy foldername auth.uid createSignedUrl JavaScript\", limit: 8) { nodes { title href content } } }", "hasContent": true, "pages": [ { "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals", "title": "Storage Buckets" }, - { - "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/self-hosting/self-hosted-s3", - "title": "Configure S3 Storage" + "url": "https://supabase.com/docs/guides/storage/security/access-control", + "title": "Storage Access Control" + }, + { + "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsignedurls" }, { - "url": "https://supabase.com/docs/guides/storage/quickstart", - "title": "Storage Quickstart" - }, + "url": "https://supabase.com/docs/guides/storage/debugging/error-codes", + "title": "Error Codes" + }, + { + "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsignedurl" + }, + { + "url": "https://supabase.com/docs/guides/auth/third-party/clerk", + "title": "Clerk" + }, + { + "url": "https://supabase.com/docs/guides/realtime/getting_started", + "title": "Getting Started with Realtime" + } + ], + "resultChars": 52320 + }, + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"printf '%s\\\\n' '--- CHANGELOG STORAGE HITS ---'; curl -fsSL https://supabase.com/changelog.md | rg -i -C 2 'storage|breaking-change' | head -120; printf '%s\\\\n' '--- RLS REFERENCES ---'; rg --files .claude/skills/supabase-postgres-best-practices/references | rg 'security|rls'\"", + "pages": [ + { + "url": "https://supabase.com/changelog.md" + } + ], + "resultChars": 9008 + }, + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"cat .claude/skills/supabase-postgres-best-practices/references/security-rls-basics.md; printf '\\\\n--- PERFORMANCE ---\\\\n'; cat .claude/skills/supabase-postgres-best-practices/references/security-rls-performance.md; printf '\\\\n--- PRIVILEGES ---\\\\n'; cat .claude/skills/supabase-postgres-best-practices/references/security-privileges.md; printf '\\\\n--- CHANGE DETAIL ---\\\\n'; curl -fsSL https://supabase.com/changelog/34270-restricting-access-on-auth-storage-and-realtime-schemas-on-april-21-2025 | rg -i -C 3 'storage|policy|migration' | head -160\"", + "pages": [ { - "url": "https://supabase.com/docs/guides/storage/security/access-control", - "title": "Storage Access Control" + "url": "https://supabase.com/changelog/34270-restricting-access-on-auth-storage-and-realtime-schemas-on-april-21-2025" } ], - "resultChars": 28532 + "resultChars": 132175 }, { "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: \"JavaScript createSignedUrl storage private bucket expiresIn\", limit: 5) { nodes { 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/storage/serving/image-transformations", "title": "Storage Image Transformations" }, + { + "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/guides/platform/manage-your-usage/storage-image-transformations", - "title": "Manage Storage Image Transformations usage" + "url": "https://supabase.com/docs/reference/javascript/file-buckets-createsignedurls" + }, + { + "url": "https://supabase.com/docs/guides/storage/serving/downloads", + "title": "Serving assets from Storage" } ], - "resultChars": 31603 + "resultChars": 25918 } ] }, @@ -12381,17 +14393,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/tenant_isolation.test.sql" }, { "name": "pgTAP isolation tests ran and pass", "passed": true, - "notes": "9 passed, 0 failed" + "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 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": "The agent correctly identified `posts` as having a tenant isolation flaw: the posts policy checked membership without matching `org_id`, allowing authenticated members to read posts from organizations they are not in. It grounded this in pgTAP results, noting posts failures while notes isolation passed. It also mentioned a memberships leak, but that does not conflict with the required conclusion." } ], "skills": { @@ -12400,38 +14412,49 @@ "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: \"row level security testing pgTAP auth.uid set local request.jwt.claims tenant isolation\", 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/auth/auth-mfa", + "title": "Multi-Factor Authentication" + }, { "url": "https://supabase.com/docs/guides/database/extensions/pgtap", "title": "pgTAP: Unit Testing" }, { - "url": "https://supabase.com/docs/guides/database/testing", - "title": "Testing Your Database" + "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/ai/rag-with-permissions", + "title": "RAG with Permissions" + } + ], + "resultChars": 60129 + }, + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"printf '%s\\\\n' '--- CHANGELOG SECURITY/BREAKING ---'; curl -fsSL https://supabase.com/changelog.md | rg -i -C 2 'breaking-change|row level|rls|pgtap' | head -n 120; printf '%s\\\\n' '--- SECURITY RULES ---'; rg --files .agents/skills/supabase-postgres-best-practices/references | rg 'security|rls' | sort; for f in \"'$(rg --files .agents/skills/supabase-postgres-best-practices/references | rg '\"'security|rls' | sort); do echo \\\"--- \"'$f\"; cat \"$f\"; done; printf '\"'%s\\\\n' '--- PROJECT FILES ---'; find supabase -maxdepth 4 -type f -print | sort; printf '%s\\\\n' '--- CONFIG ---'; sed -n '1,240p' supabase/config.toml 2>/dev/null || true; printf '%s\\\\n' '--- SQL CONTENT ---'; for f in \"'$(find supabase -type f '\"\\\\( -name '*.sql' -o -name '*.toml' \\\\) | sort); do echo \\\"--- \"'$f\"; sed -n '\"'1,260p' \\\"\"'$f\"; done'", + "pages": [ + { + "url": "https://supabase.com/changelog.md" } ], - "resultChars": 70562 + "resultChars": 18066 } ] }, @@ -12471,12 +14494,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", @@ -12501,50 +14524,106 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "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: \"pgvector semantic search match_documents RPC HNSW vector cosine RLS\", 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/rag-with-permissions", - "title": "RAG with Permissions" - }, { "url": "https://supabase.com/docs/guides/ai/hybrid-search", "title": "Hybrid search" }, + { + "url": "https://supabase.com/docs/guides/ai/vector-columns", + "title": "Vector columns" + }, + { + "url": "https://supabase.com/docs/guides/ai/vector-indexes", + "title": "Vector indexes" + }, + { + "url": "https://supabase.com/docs/guides/storage/vector/introduction", + "title": "Vector Buckets" + } + ], + "resultChars": 41947 + }, + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"curl -fsSL https://supabase.com/changelog.md | rg -n -i 'breaking-change|vector|pgvector|rls' | head -80\"", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/changelog.md" + } + ], + "resultChars": 7754 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Supabase Edge Functions gte-small embedding dimensions 384 match_document_sections\", 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/semantic-search", + "title": "Semantic search" + }, { "url": "https://supabase.com/docs/guides/ai/automatic-embeddings", "title": "Automatic embeddings" }, { - "url": "https://supabase.com/docs/guides/ai/vector-columns", - "title": "Vector columns" + "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": 76193 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"pgvector HNSW filtering RLS iterative_scan Supabase\", limit: 5) { nodes { title href content } } }", + "hasContent": true, + "pages": [ + { + "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/rag-with-permissions", + "title": "RAG with Permissions" }, { - "url": "https://supabase.com/docs/guides/ai/vector-indexes", - "title": "Vector indexes" + "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/storage/security/access-control", + "title": "Storage Access Control" } ], - "resultChars": 97234 + "resultChars": 43837 } ] }, @@ -12560,7 +14639,7 @@ "agent": "codex", "modelProvider": "openai", "modelId": "gpt-5.6-sol", - "reasoningEffort": "low" + "reasoningEffort": "medium" }, "eval": "deploy-database-001-prometheus-metrics", "stage": "deploy", @@ -12580,12 +14659,12 @@ { "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." + "judgeNotes": "Meets requirements: preserves app scrape, adds HTTPS Supabase metrics scrape at /customer/v1/privileged/metrics for a project supabase.co target, uses HTTP Basic Auth with password_file, and docker-compose wires the password file via a Compose secret." }, { "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." + "judgeNotes": "README includes required steps: create a dedicated Supabase Secret API key, write it to the Compose secret file, restart the stack, and verify via Prometheus targets/query. Endpoint/auth and secret mounting match the config." } ], "skills": { @@ -12594,38 +14673,313 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" ] }, "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 } } }", + "query": "query { searchDocs(query: \"Supabase project Prometheus metrics endpoint authentication service role metrics\", limit: 8) { nodes { ... on Guide { title href content subsections { nodes { 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/telemetry/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/vendor-agnostic#1-define-the-scrape-job", + "title": "1. Define the scrape job" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic#components", + "title": "Components" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic#collector-specific-notes", + "title": "Collector-specific notes" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic#2-secure-the-credentials", + "title": "2. Secure the credentials" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic#3-downstream-dashboards", + "title": "3. Downstream dashboards" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic#4-alerts-and-automation", + "title": "4. Alerts and automation" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic#5-multi-project-setups", + "title": "5. Multi-project setups" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics", + "title": "Metrics API" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics#what-you-can-do-with-the-metrics-api", + "title": "What you can do with the Metrics API" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics#choose-your-monitoring-stack", + "title": "Choose your monitoring stack" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics#additional-resources", + "title": "Additional resources" + }, + { + "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-cloud#6-troubleshooting", + "title": "6. Troubleshooting" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#installation", + "title": "Installation" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#manual-setup", + "title": "Manual setup" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#prerequisites", + "title": "Prerequisites" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#1-create-a-grafana-cloud-stack", + "title": "1. Create a Grafana Cloud stack" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#2-install-the-supabase-integration-for-grafana-cloud", + "title": "2. Install the Supabase integration for Grafana Cloud" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#3-configure-the-supabase-integration", + "title": "3. Configure the Supabase integration" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#4-import-the-supabase-dashboard", + "title": "4. Import the Supabase dashboard" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#5-configure-alerts-optional", + "title": "5. Configure alerts (optional)" + }, + { + "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/grafana-self-hosted#architecture", + "title": "Architecture" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted#1-deploy-prometheus", + "title": "1. Deploy Prometheus" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted#2-deploy-grafana", + "title": "2. Deploy Grafana" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted#3-import-supabase-dashboards", + "title": "3. Import Supabase dashboards" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted#4-configure-alerting", + "title": "4. Configure alerting" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted#5-operating-tips", + "title": "5. Operating tips" + }, + { + "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/platform/read-replicas", + "title": "Read Replicas" + }, + { + "url": "https://supabase.com/docs/guides/platform/read-replicas#about-read-replicas", + "title": "About Read Replicas" + }, + { + "url": "https://supabase.com/docs/guides/platform/read-replicas#features", + "title": "Features" + }, + { + "url": "https://supabase.com/docs/guides/platform/read-replicas#dedicated-endpoints", + "title": "Dedicated endpoints" + }, + { + "url": "https://supabase.com/docs/guides/platform/read-replicas#api-load-balancer", + "title": "API load balancer" + }, + { + "url": "https://supabase.com/docs/guides/platform/read-replicas#dedicated-connection-pool", + "title": "Dedicated connection pool" + }, + { + "url": "https://supabase.com/docs/guides/platform/read-replicas#querying-through-the-sql-editor", + "title": "Querying through the SQL editor" + }, + { + "url": "https://supabase.com/docs/guides/platform/read-replicas#logging", + "title": "Logging" + }, + { + "url": "https://supabase.com/docs/guides/platform/read-replicas#metrics", + "title": "Metrics" + }, + { + "url": "https://supabase.com/docs/guides/platform/read-replicas#centralized-configuration-management", + "title": "Centralized configuration management" + }, + { + "url": "https://supabase.com/docs/guides/platform/read-replicas#pricing", + "title": "Pricing" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields", + "title": "JWT Claims Reference" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#jwt-structure-overview", + "title": "JWT structure overview" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#required-claims", + "title": "Required claims" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#optional-claims", + "title": "Optional claims" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#field-value-constraints", + "title": "Field value constraints" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#special-claims", + "title": "Special claims" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#related-documentation", + "title": "Related documentation" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#security-considerations", + "title": "Security considerations" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#validation-guidelines", + "title": "Validation guidelines" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#go", + "title": "Go" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#python", + "title": "Python" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#typescriptjavascript", + "title": "TypeScript/JavaScript" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#rust", + "title": "Rust" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#language-specific-considerations", + "title": "Language-Specific considerations" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#service-role-token", + "title": "Service role token" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#anonymous-user-token", + "title": "Anonymous user token" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#authenticated-user-token", + "title": "Authenticated user token" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#jwt-examples", + "title": "JWT examples" + }, + { + "url": "https://supabase.com/docs/guides/auth/jwt-fields#authentication-methods-amrmethod", + "title": "Authentication methods (amr.method)" }, { - "url": "https://supabase.com/docs/guides/telemetry/metrics", - "title": "Metrics API" + "url": "https://supabase.com/docs/guides/auth/jwt-fields#audience-values-aud", + "title": "Audience values (aud)" }, { - "url": "https://supabase.com/docs/guides/telemetry/metrics/vendor-agnostic", - "title": "Vendor-agnostic Metrics API setup" + "url": "https://supabase.com/docs/guides/auth/jwt-fields#role-values-role", + "title": "Role values (role)" }, { - "url": "https://supabase.com/docs/guides/telemetry/metrics/grafana-cloud", - "title": "Metrics API with Grafana Cloud" + "url": "https://supabase.com/docs/guides/auth/jwt-fields#authenticator-assurance-level-aal", + "title": "Authenticator assurance level (aal)" }, { - "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/connection-management", + "title": "Connection management" + }, + { + "url": "https://supabase.com/docs/guides/database/connection-management#grafana-dashboard", + "title": "Grafana Dashboard" + }, + { + "url": "https://supabase.com/docs/guides/database/connection-management#observing-live-connections", + "title": "Observing live connections" + }, + { + "url": "https://supabase.com/docs/guides/database/connection-management#connections", + "title": "Connections" + }, + { + "url": "https://supabase.com/docs/guides/database/connection-management#configuring-supavisors-pool-size", + "title": "Configuring Supavisor's pool size" + }, + { + "url": "https://supabase.com/docs/guides/database/connection-management#monitoring-connections", + "title": "Monitoring connections" + }, + { + "url": "https://supabase.com/docs/guides/database/connection-management#capturing-historical-usage", + "title": "Capturing historical usage" + }, + { + "url": "https://supabase.com/docs/guides/database/connection-management#dashboard-monitoring-charts", + "title": "Dashboard monitoring charts" + } + ], + "resultChars": 144806 + }, + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"printf '%s\\\\n' '--- git status ---'; git status --short; printf '%s\\\\n' '--- changelog metrics hits ---'; curl -fsSL https://supabase.com/changelog.md | rg -i -C 2 'metrics|prometheus|monitoring|breaking-change' | head -120 || true; printf '%s\\\\n' '--- compose ---'; sed -n '1,240p' observability/docker-compose.yml; printf '%s\\\\n' '--- prometheus ---'; sed -n '1,240p' observability/prometheus.yml; printf '%s\\\\n' '--- readme ---'; sed -n '1,280p' observability/README.md; printf '%s\\\\n' '--- datasource ---'; sed -n '1,160p' observability/grafana/provisioning/datasources/prometheus.yml; printf '%s\\\\n' '--- env/gitignore refs ---'; rg -n --hidden -g '\"'!node_modules'\"' -g '\"'!.git'\"' '(\\\\.env|env_file|PROMETHEUS|GRAFANA|SUPABASE)' . | head -240\"", + "pages": [ + { + "url": "https://supabase.com/changelog.md" } ], - "resultChars": 39702 + "resultChars": 8707 } ] }, @@ -12687,7 +15041,7 @@ "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 } } } }", + "query": "query { searchDocs(query: \"Edge Functions environment variables secrets set deploy function no verify jwt CORS invoke\", limit: 8) { nodes { ... on Guide { title href content } ... on CLICommandReference { title href content } } } }", "hasContent": true, "pages": [ { @@ -12702,16 +15056,66 @@ "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions", "title": "Self-Hosted Functions" }, - { - "url": "https://supabase.com/docs/guides/functions/storage-caching", - "title": "Integrating with Supabase Storage" - }, { "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt", "title": "Integrating With Supabase Auth" + }, + { + "url": "https://supabase.com/docs/guides/getting-started/features", + "title": "Features" + }, + { + "url": "https://supabase.com/docs/guides/database/secure-data", + "title": "Securing your data" + }, + { + "url": "https://supabase.com/docs/guides/functions/auth-headers", + "title": "Authorization headers" + } + ], + "resultChars": 54244 + }, + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"set -o pipefail\nprintf '%s\\\\n' '--- changelog relevant ---'\ncurl -fsSL https://supabase.com/changelog.md | rg -i -C 2 'breaking-change|edge function|secret' | head -120 || true\nprintf '%s\\\\n' '--- root files ---'\nls -la\nprintf '%s\\\\n' '--- git/status ---'\ngit status --short && git remote -v || true\nprintf '%s\\\\n' '--- project files ---'\nrg --files -g '\"'!node_modules'\"' -g '\"'!dist'\"' -g '\"'!build'\"' | sort | head -300\nprintf '%s\\\\n' '--- supabase tree ---'\nfind supabase -maxdepth 4 -type f -print 2>/dev/null | sort\nprintf '%s\\\\n' '--- weather refs ---'\nrg -n \\\"WeatherAPI|weatherapi|WEATHER_API|api\\\\.weather|weather\\\" . -g '\"'!node_modules'\"' -g '\"'!dist'\"' -g '\"'!build'\"' || true\nprintf '%s\\\\n' '--- env keys only ---'\nif [ -f .env ]; then sed -E 's/=.*\"'$/=/'\"' .env; fi\nprintf '%s\\\\n' '--- cli/version/link ---'\nsupabase --version\nsupabase functions --help\nsupabase secrets --help\nfind supabase/.temp -maxdepth 2 -type f -print -exec sh -c 'printf \\\" \\\"; cat \\\"\"'$1\"'\"' _ {} \\\\; 2>/dev/null || true\"", + "pages": [ + { + "url": "https://supabase.com/changelog.md" + } + ], + "resultChars": 3763 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Management API invoke deployed Edge Function endpoint project ref functions v1\", limit: 6) { nodes { ... on ManagementApiReference { title href content } ... on Guide { title href content } } } }", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/reference/api/v1-deploy-a-function", + "title": "Deploy a function" + }, + { + "url": "https://supabase.com/docs/reference/api/v1-create-a-function", + "title": "Create 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-a-function", + "title": "Retrieve a function" + }, + { + "url": "https://supabase.com/docs/reference/api/v1-update-a-function", + "title": "Update a function" + }, + { + "url": "https://supabase.com/docs/reference/api/v1-bulk-update-functions", + "title": "Bulk update functions" } ], - "resultChars": 36973 + "resultChars": 4409 } ] }, @@ -12765,13 +15169,26 @@ "supabase", "supabase-postgres-best-practices" ], - "loaded": [] + "loaded": [ + "supabase", + "supabase-postgres-best-practices" + ] }, "docs": { "calls": [ + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"sed -n '1,240p' .agents/skills/supabase/SKILL.md; printf '\\\\n--- remaining ---\\\\n'; sed -n '241,520p' .agents/skills/supabase/SKILL.md; printf '\\\\n--- project files (excluding agent metadata) ---\\\\n'; find . -maxdepth 2 -type f -not -path './.agents/*' -not -path './.claude/*' | sort | head -200; printf '\\\\n--- changelog scan ---\\\\n'; curl -fsSL https://supabase.com/changelog.md | rg -i -C 2 'breaking|self-host|docker' | head -120\"", + "pages": [ + { + "url": "https://supabase.com/changelog.md" + } + ], + "resultChars": 19933 + }, { "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 } } }", + "query": "query { searchDocs(query: \"self-hosting Docker compose install secrets JWT_SECRET ANON_KEY SERVICE_ROLE_KEY POSTGRES_PASSWORD POOLER_TENANT_ID latest\", limit: 8) { nodes { title href content } } }", "hasContent": true, "pages": [ { @@ -12779,8 +15196,12 @@ "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/docker", + "title": "Self-Hosting with Docker" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17", + "title": "Upgrade to Postgres 17" }, { "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy", @@ -12791,23 +15212,47 @@ "title": "Configure Social Login (OAuth) Providers" }, { - "url": "https://supabase.com/docs/guides/self-hosting/docker", - "title": "Self-Hosting with Docker" + "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-functions", "title": "Self-Hosted Functions" }, { - "url": "https://supabase.com/docs/guides/functions/secrets", - "title": "Environment Variables" + "url": "https://supabase.com/docs/guides/auth/signing-keys", + "title": "JWT Signing Keys" + } + ], + "resultChars": 159960 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Docker self-hosting quick start Linux docker compose .env generate-keys.sh reverse proxy production security\", limit: 5) { nodes { 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-s3", - "title": "Configure S3 Storage" + "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-proxy-https", + "title": "Configure Reverse Proxy and HTTPS" + }, + { + "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", + "title": "Configure Social Login (OAuth) Providers" } ], - "resultChars": 154701 + "resultChars": 105681 } ] }, @@ -12866,7 +15311,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": "The answer identifies the soft-delete-only bug, implements deletion of auth.users with cascading sessions/refresh tokens/identities, adds RLS active-account checks that close the Data API path for protected tables, consistently caveats that JWTs remain locally valid until expiry for getClaims/custom local validation and recommends mitigations, and correctly distinguishes publishable frontend/RLS keys from secret backend-only RLS-bypassing keys." } ], "skills": { @@ -12875,51 +15320,12 @@ "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 } } }", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/auth/third-party/clerk", - "title": "Clerk" - }, - { - "url": "https://supabase.com/docs/guides/auth/oauth-server/token-security", - "title": "Token Security and Row Level Security" - }, - { - "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/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/storage/security/ownership", - "title": "Ownership" - }, - { - "url": "https://supabase.com/docs/guides/auth/oauth-server/getting-started", - "title": "Getting Started with OAuth 2.1 Server" - } - ], - "resultChars": 95765 - }, { "source": "web_search", "query": "https://supabase.com/changelog.md", @@ -12931,56 +15337,76 @@ }, { "source": "web_search", - "query": "site:supabase.com/changelog Supabase auth delete user session API keys publishable secret", + "query": "site:supabase.com/changelog Supabase auth delete user session revoke JWT", "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: \"delete user does not sign out JWT remains valid revoke sessions auth.sessions delete_account security definer publishable secret keys RLS\", limit: 8) { 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/managing-user-data", + "title": "User Management" }, { - "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/sessions", + "title": "User sessions" }, { - "url": "https://supabase.com/docs/guides/auth/third-party/clerk", - "title": "Clerk" + "url": "https://supabase.com/docs/guides/storage/security/ownership", + "title": "Ownership" }, { - "url": "https://supabase.com/docs/guides/auth/sessions", - "title": "User sessions" + "url": "https://supabase.com/docs/guides/auth/signing-keys", + "title": "JWT Signing Keys" }, { - "url": "https://supabase.com/docs/guides/auth/auth-anonymous", - "title": "Anonymous Sign-Ins" + "url": "https://supabase.com/docs/guides/storage/management/delete-objects", + "title": "Delete Objects" }, { - "url": "https://supabase.com/docs/guides/ai/rag-with-permissions", - "title": "RAG with Permissions" + "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/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/auth/oauth-server/token-security", + "title": "Token Security and Row Level Security" + } + ], + "resultChars": 91284 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Understanding API keys publishable secret key frontend RLS anon authenticated service_role bypass browser\", 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/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/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" } ], - "resultChars": 137238 + "resultChars": 82940 } ] }, @@ -13035,7 +15461,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 correctly identified the root cause as orders missing from the supabase_realtime publication despite SUBSCRIBED, added only public.orders with ALTER PUBLICATION, verified courier_locations remained, and did not weaken RLS/policies or blame client/RLS/networking." } ], "skills": { @@ -13044,14 +15470,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 Realtime add table supabase_realtime publication INSERT events\", limit: 5) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } } } }", "hasContent": true, "pages": [ { @@ -13063,19 +15490,19 @@ "title": "Postgres Changes" }, { - "url": "https://supabase.com/docs/guides/realtime/benchmarks", - "title": "Benchmarks" + "url": "https://supabase.com/docs/guides/realtime/architecture", + "title": "Realtime Architecture" }, { - "url": "https://supabase.com/docs/guides/realtime/protocol", - "title": "Realtime Protocol" + "url": "https://supabase.com/docs/guides/realtime/getting_started", + "title": "Getting Started with Realtime" }, { - "url": "https://supabase.com/docs/guides/realtime/authorization", - "title": "Realtime Authorization" + "url": "https://supabase.com/docs/guides/realtime/benchmarks", + "title": "Benchmarks" } ], - "resultChars": 119071 + "resultChars": 91663 } ] }, @@ -13108,17 +15535,17 @@ { "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": "Identified `image-transform` as affected and described eight intermittent 503s across 07:00–12:00 UTC on 2026-04-28, distinguishing them from other issues." }, { "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." + "judgeNotes": "The assistant clearly attributes the recurring image-transform 503s to the Edge Functions gateway/platform layer, not function code, and grounds this in valid observations: 503s appear in gateway logs but not execution logs, nearby successful requests used the same deployment, and the avatar-upload 500 is treated as a distinct in-function error." }, { "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": "Recommended concrete next steps: open Supabase Support ticket with project ref, route, timestamps, and gateway log IDs; ask Supabase to correlate with regional platform events; add retries and monitor specific isolated error." } ], "skills": { @@ -13127,15 +15554,65 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" + ] + }, + "docs": { + "calls": [ + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Edge Functions 503 gateway request never reaches function logs causes\", limit: 5) { nodes { title href content } } }", + "hasContent": true, + "pages": [ + { + "url": "https://supabase.com/docs/guides/functions/status-codes", + "title": "Status codes" + }, + { + "url": "https://supabase.com/docs/guides/troubleshooting/edge-function-503-response", + "title": "Edge Function 503 error response" + }, + { + "url": "https://supabase.com/docs/guides/troubleshooting/edge-function-504-error-response", + "title": "Edge Function 504 error response" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/debugging", + "title": "Debugging guide" + }, + { + "url": "https://supabase.com/docs/guides/troubleshooting/edge-function-404-error-response", + "title": "Edge Function 404 error response" + } + ], + "resultChars": 46555 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"internal_failure execution_id null function_id null Edge Function 503 platform issue\", limit: 3) { 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/troubleshooting/edge-function-504-error-response", + "title": "Edge Function 504 error response" + }, + { + "url": "https://supabase.com/docs/guides/functions/status-codes", + "title": "Status codes" + } + ], + "resultChars": 22986 + } ] }, - "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", - "attempts": 2, + "attempts": 1, "sourcePath": "codex-gpt-5.6/investigate-reliability-003-edge-function-5xx-correlation.json" }, { @@ -13189,7 +15666,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 deny-all due to no policies, kept RLS enabled, and created authenticated owner-scoped SELECT and INSERT policies using auth.uid() = user_id / WITH CHECK. Also avoided permissive anon/public policies." } ], "skills": { @@ -13198,52 +15675,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: \"Data API table grants authenticated RLS policies auth.uid insert select\", limit: 5) { 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/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/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" - } - ], - "resultChars": 114795 - }, - { - "source": "web_search", - "query": "https://supabase.com/changelog.md", - "pages": [ + "url": "https://supabase.com/docs/guides/resources/glossary", + "title": "Glossary" + }, { - "url": "https://supabase.com/changelog.md" + "url": "https://supabase.com/docs/guides/ai/rag-with-permissions", + "title": "RAG with Permissions" } - ] - }, - { - "source": "web_search", - "query": "site:supabase.com/changelog Supabase changelog Data API grants RLS", - "pages": [] + ], + "resultChars": 95184 } ] }, @@ -13296,7 +15760,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": "Passed: history was reconciled by adding the missing local migration file `supabase/migrations/20240115000000_add_profile_bio.sql`, then running `supabase db push --db-url \"$DB_URL\" --yes` in action #7. That same Supabase CLI push appears to have succeeded and finished, applying the pending avatar_url migration; action #8 then reported `Remote database is up to date`. No disallowed direct SQL mutation or prepared-statement reset workaround was shown." } ], "skills": { @@ -13305,38 +15769,49 @@ "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 db push migration history repair linked project deploy migrations\", 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/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/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/reference/cli/supabase-migration-list", - "title": "List local and remote migrations" + "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" + } + ], + "resultChars": 61657 + }, + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"set -o pipefail\nprintf '%s\\\\n' '--- CHANGELOG HEAD ---'\ncurl -fsSL https://supabase.com/changelog.md | sed -n '1,120p'\nprintf '%s\\\\n' '--- GIT ---'\ngit status --short && git log --oneline -5\nprintf '%s\\\\n' '--- CLI ---'\nsupabase --version\nprintf '%s\\\\n' '--- CONFIG ---'\nsed -n '1,240p' supabase/config.toml\nprintf '%s\\\\n' '--- MIGRATIONS ---'\nfor f in supabase/migrations/*.sql; do echo \\\"### \"'$f\"; nl -ba \"$f\"; done\nprintf '\"'%s\\\\n' '--- LOCAL METADATA ---'\nfind supabase/.temp -maxdepth 2 -type f -print -exec sh -c 'echo \\\"--- \"'$1\"; cat \"$1\"'\"' sh {} \\\\; 2>/dev/null || true\nprintf '%s\\\\n' '--- ENV NAMES ---'\nenv | cut -d= -f1 | sort | rg 'SUPABASE|POSTGRES|DATABASE|PG' || true\"", + "pages": [ + { + "url": "https://supabase.com/changelog.md" } ], - "resultChars": 50099 + "resultChars": 1405 } ] }, @@ -13395,14 +15870,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: \"query optimization explain indexes pg_stat_statements\", limit: 5) { nodes { title href content } } }", "hasContent": true, "pages": [ { @@ -13410,42 +15886,23 @@ "title": "Debugging and monitoring" }, { - "url": "https://supabase.com/docs/guides/database/query-optimization", - "title": "Query Optimization" + "url": "https://supabase.com/docs/guides/database/extensions/pg_stat_statements", + "title": "pg_stat_statements: Query Performance Monitoring" }, { - "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/query-optimization", + "title": "Query Optimization" }, { "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/database/postgres/indexes", + "title": "Managing Indexes in Postgres" } ], - "resultChars": 39586 - }, - { - "source": "web_search", - "query": "https://supabase.com/changelog.md", - "pages": [ - { - "url": "https://supabase.com/changelog.md" - } - ] - }, - { - "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", - "pages": [] + "resultChars": 33495 } ] }, @@ -13516,205 +15973,60 @@ ], "skills": { "available": [ - "supabase", - "supabase-postgres-best-practices" - ], - "loaded": [ - "supabase" - ] - }, - "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 } } } }", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/database/postgres/row-level-security", - "title": "Row Level Security" - }, - { - "url": "https://supabase.com/docs/guides/auth/users", - "title": "Users" - } - ], - "resultChars": 38609 - } - ] - }, - "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.6/resolve-security-002-rls-cross-tenant-leak.json" - }, - { - "experiment": "codex-gpt-5.6-no-skills", - "experimentSuite": "no-skills", - "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": [], - "loaded": [] - }, - "docs": { - "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 } } } }", - "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-reset", - "title": "Resets the local database to current migrations" - }, - { - "url": "https://supabase.com/docs/guides/database/postgres/column-level-security", - "title": "Column Level Security" - }, - { - "url": "https://supabase.com/docs/guides/deployment/branching/troubleshooting", - "title": "Troubleshooting" - }, - { - "url": "https://supabase.com/docs/guides/deployment/branching/working-with-branches", - "title": "Working with branches" - } - ], - "resultChars": 49117 - } - ] - }, - "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-no-skills/build-cli-001-bootstrap-app.json" - }, - { - "experiment": "codex-gpt-5.6-no-skills", - "experimentSuite": "no-skills", - "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": 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": true - }, - { - "name": "description column exists in the live database", - "passed": true - } - ], - "skills": { - "available": [], - "loaded": [] + "supabase", + "supabase-postgres-best-practices" + ], + "loaded": [ + "supabase", + "supabase-postgres-best-practices" + ] }, "docs": { "calls": [ + { + "source": "shell_fetch", + "query": "/bin/bash -lc \"find .claude/skills/supabase-postgres-best-practices/references -maxdepth 1 -type f -printf '%f\\\\n' | sort | rg 'security|index|schema' && printf '\\\\n--- RLS RULES ---\\\\n' && cat .claude/skills/supabase-postgres-best-practices/references/security-rls-performance.md .claude/skills/supabase-postgres-best-practices/references/security-rls.md 2>/dev/null || true && printf '\\\\n--- CHANGELOG TAGS ---\\\\n' && curl -fsSL https://supabase.com/changelog.md | rg -i -m 20 'breaking-change|row.level|rls|policy'\"", + "pages": [ + { + "url": "https://supabase.com/changelog.md" + } + ], + "resultChars": 7071 + }, { "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: \"row level security multi tenant team workspace membership policies auth.uid exists indexes\", limit: 5) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } } } }", "hasContent": true, "pages": [ { - "url": "https://supabase.com/docs/guides/deployment/database-migrations", - "title": "Database Migrations" + "url": "https://supabase.com/docs/guides/getting-started/features", + "title": "Features" }, { - "url": "https://supabase.com/docs/guides/local-development/database-migrations", - "title": "Database migrations" + "url": "https://supabase.com/docs/guides/resources/glossary", + "title": "Glossary" }, { - "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/auth/oauth-server/token-security", + "title": "Token Security and Row Level Security" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/column-level-security", + "title": "Column Level Security" } ], - "resultChars": 54403 + "resultChars": 68601 } ] }, - "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.6-no-skills/build-cli-002-declarative-schema.json" + "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.6/resolve-security-002-rls-cross-tenant-leak.json" }, { "experiment": "codex-gpt-5.6-no-skills", @@ -13725,598 +16037,820 @@ "modelId": "gpt-5.6-sol", "reasoningEffort": "medium" }, - "eval": "build-cli-003-pg-cron-queue-workflow", + "eval": "build-cli-001-bootstrap-app", "stage": "build", "product": [ "database", - "edge-functions", - "cron", - "queues" + "data-api" ], "topic": [ - "sql", - "sdk" + "migrations", + "rls" ], "suite": "benchmark", "interface": "cli", "passed": true, "checks": [ { - "name": "pg_cron job 'enqueue-tasks' scheduled to run every minute", + "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": "schedule='* * * * *', active=true" + "notes": "found 2 rows" }, { - "name": "cron command enqueues to the 'tasks' queue", + "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": "queue depth 0 -> 1" + "notes": "0 rows" }, { - "name": "process-tasks function drains the queue", + "name": "REST API returns the todos to authenticated requests", "passed": true, - "notes": "function removed the seeded message (id 36) from the queue" + "notes": "2 rows" } - ], - "skills": { - "available": [], - "loaded": [] - }, - "docs": { - "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 } } } }", - "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#when-to-use-edge-functions", - "title": "When to use Edge Functions" - }, - { - "url": "https://supabase.com/docs/guides/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?" - }, + ], + "skills": { + "available": [], + "loaded": [] + }, + "docs": { + "calls": [ + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Row Level Security authenticated users select policy migrations seed data local development\", limit: 5) { nodes { title href content } } }", + "hasContent": true, + "pages": [ { - "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/cli-workflows", + "title": "Local development workflow" }, { - "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/getting-started/features", + "title": "Features" }, { - "url": "https://supabase.com/docs/guides/functions/recursive-functions", - "title": "Recursive / Nested Function Calls" + "url": "https://supabase.com/docs/guides/api/securing-your-api", + "title": "Securing your API" }, { - "url": "https://supabase.com/docs/guides/functions/recursive-functions#what-gets-rate-limited", - "title": "What gets rate limited" + "url": "https://supabase.com/docs/guides/resources/glossary", + "title": "Glossary" }, { - "url": "https://supabase.com/docs/guides/functions/recursive-functions#rate-limit-budget", - "title": "Rate limit budget" - }, + "url": "https://supabase.com/docs/guides/database/postgres/row-level-security", + "title": "Row Level Security" + } + ], + "resultChars": 94724 + } + ] + }, + "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-no-skills/build-cli-001-bootstrap-app.json" + }, + { + "experiment": "codex-gpt-5.6-no-skills", + "experimentSuite": "no-skills", + "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": 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": true + }, + { + "name": "description column exists in the live database", + "passed": true + } + ], + "skills": { + "available": [], + "loaded": [] + }, + "docs": { + "calls": [ + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Supabase CLI create migration alter table add column local database migration up\", limit: 3) { nodes { title href content } } }", + "hasContent": true, + "pages": [ { - "url": "https://supabase.com/docs/guides/functions/recursive-functions#handling-rate-limit-errors", - "title": "Handling rate limit errors" + "url": "https://supabase.com/docs/guides/local-development/database-migrations", + "title": "Database migrations" }, { - "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/deployment/database-migrations", + "title": "Database Migrations" }, { - "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/local-development/cli-workflows", + "title": "Local development workflow" + } + ], + "resultChars": 54403 + } + ] + }, + "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.6-no-skills/build-cli-002-declarative-schema.json" + }, + { + "experiment": "codex-gpt-5.6-no-skills", + "experimentSuite": "no-skills", + "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 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": [ + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Supabase Queues pgmq create queue send read delete Edge Function pgmq_public cron schedule every minute local\", limit: 8) { nodes { __typename title href content } } }", + "hasContent": true, + "pages": [ { - "url": "https://supabase.com/docs/guides/functions/recursive-functions#2-limit-recursion-depth", - "title": "2. Limit recursion depth" + "url": "https://supabase.com/docs/guides/queues", + "title": "Supabase Queues" }, { - "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/queues/api", + "title": "API" }, { - "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/functions/schedule-functions", + "title": "Scheduling Edge Functions" }, { - "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", + "title": "pg_net: Async Networking" }, { - "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/cron", + "title": "Cron" }, { - "url": "https://supabase.com/docs/guides/functions/recursive-functions#increasing-rate-limits", - "title": "Increasing rate limits" + "url": "https://supabase.com/docs/guides/queues/expose-self-hosted-queues", + "title": "Expose Queues for local and self-hosted Supabase" }, { - "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets", - "title": "Resumable WebSockets with Edge Functions" + "url": "https://supabase.com/docs/guides/queues/quickstart", + "title": "Quickstart" }, { - "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets#architecture", - "title": "Architecture" - }, + "url": "https://supabase.com/docs/guides/cron/quickstart", + "title": "Quickstart" + } + ], + "resultChars": 44703 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Supabase Queues quickstart SQL pgmq.create queue create example pgmq.send\", limit: 5) { nodes { __typename title href content } } }", + "hasContent": true, + "pages": [ { - "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets#database-schema", - "title": "Database schema" + "url": "https://supabase.com/docs/guides/queues", + "title": "Supabase Queues" }, { - "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/queues/quickstart", + "title": "Quickstart" }, { - "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets#browser-client", - "title": "Browser client" + "url": "https://supabase.com/docs/guides/queues/api", + "title": "API" }, { - "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/pgmq", + "title": "pgmq: Queues" }, { - "url": "https://supabase.com/docs/guides/functions/examples/resumable-websockets#next-steps", - "title": "Next steps" + "url": "https://supabase.com/docs/guides/queues/consuming-messages-with-edge-functions", + "title": "Consuming Supabase Queue Messages with Edge Functions" } ], - "resultChars": 105925 - }, + "resultChars": 19923 + } + ] + }, + "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.6-no-skills/build-cli-003-pg-cron-queue-workflow.json" + }, + { + "experiment": "codex-gpt-5.6-no-skills", + "experimentSuite": "no-skills", + "experimentDisplay": { + "agent": "codex", + "modelProvider": "openai", + "modelId": "gpt-5.6-sol", + "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": [ { "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 } } } } } }", + "query": "query { searchDocs(query: \"Supabase CLI local development restore pg_dump custom format database dump\", 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/cron/quickstart#call-a-database-function-every-5-minutes", - "title": "Call a database function every 5 minutes" + "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/postgres", + "title": "Migrate from Postgres to Supabase" }, { - "url": "https://supabase.com/docs/guides/cron/quickstart#schedule-a-job", - "title": "Schedule a job" + "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/cron/quickstart#edit-a-job", - "title": "Edit a job" + "url": "https://supabase.com/docs/guides/local-development/restoring-downloaded-backup", + "title": "Restoring a downloaded backup locally" }, { - "url": "https://supabase.com/docs/guides/cron/quickstart#activatedeactivate-a-job", - "title": "Activate/Deactivate a job" + "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/cron/quickstart#unschedule-a-job", - "title": "Unschedule a job" - }, + "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/neon", + "title": "Migrate from Neon to Supabase" + } + ], + "resultChars": 42818 + } + ] + }, + "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.6-no-skills/build-database-001-migrate-postgres-to-supabase.json" + }, + { + "experiment": "codex-gpt-5.6-no-skills", + "experimentSuite": "no-skills", + "experimentDisplay": { + "agent": "codex", + "modelProvider": "openai", + "modelId": "gpt-5.6-sol", + "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": [], + "loaded": [] + }, + "docs": { + "calls": [ + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Edge Functions Authorization header createClient RLS auth.getUser SUPABASE_ANON_KEY\", limit: 5) { nodes { ... on Guide { title href content } ... on ClientLibraryFunctionReference { title href content language methodName } } } }", + "hasContent": true, + "pages": [ { - "url": "https://supabase.com/docs/guides/cron/quickstart#inspecting-job-runs", - "title": "Inspecting job runs" + "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt", + "title": "Integrating With Supabase Auth" }, { - "url": "https://supabase.com/docs/guides/cron/quickstart#examples", - "title": "Examples" + "url": "https://supabase.com/docs/guides/functions/auth", + "title": "Securing Edge Functions" }, { - "url": "https://supabase.com/docs/guides/cron/quickstart#delete-data-every-week", - "title": "Delete data every week" + "url": "https://supabase.com/docs/guides/getting-started/api-keys", + "title": "Understanding API keys" }, { - "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/self-hosting/self-hosted-auth-keys", + "title": "New API Keys and Asymmetric Authentication" + } + ], + "resultChars": 43320 + } + ] + }, + "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-no-skills/build-functions-004-service-role-bypass.json" + }, + { + "experiment": "codex-gpt-5.6-no-skills", + "experimentSuite": "no-skills", + "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\":\"430ac236-7163-489e-b085-ae34d465eda7\",\"metric\":\"steps_a_msgix536\",\"value\":111}]" + }, + { + "name": "user cannot read another user's rows by passing user_id", + "passed": true, + "notes": "status 200: [{\"user_id\":\"430ac236-7163-489e-b085-ae34d465eda7\",\"metric\":\"steps_a_msgix536\",\"value\":111}]" + }, + { + "name": "service key bypasses RLS to read the target user's rows", + "passed": true, + "notes": "status 200: [{\"user_id\":\"77e1ecdc-2cfd-43ce-82a5-bf2d301962e7\",\"metric\":\"steps_b_msgix536\",\"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: {\"error\":\"Unauthorized\"}" + }, + { + "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": [], + "loaded": [] + }, + "docs": { + "calls": [ + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Edge Functions authenticate JWT Authorization header service_role key apikey header SUPABASE_SERVICE_ROLE_KEY environment variables createClient\", limit: 8) { nodes { title href content } } }", + "hasContent": true, + "pages": [ { - "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/getting-started/migrating-to-new-api-keys", + "title": "Migrating to publishable and secret API keys" }, { - "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/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/cron/quickstart#caution-scheduling-system-maintenance", - "title": "Caution: Scheduling system maintenance" + "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt", + "title": "Integrating With Supabase Auth" }, { - "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/database/extensions/pg_net#delete-usage", - "title": "Usage " + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions", + "title": "Self-Hosted Functions" }, { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#enable-the-extension", - "title": "Enable the extension" + "url": "https://supabase.com/docs/guides/getting-started/api-keys", + "title": "Understanding API keys" }, { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#debugging-requests", - "title": "Debugging requests" + "url": "https://supabase.com/docs/reference/javascript/oauth-admin-createclient" }, { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#analyzing-responses", - "title": "Analyzing responses" - }, + "url": "https://supabase.com/docs/guides/functions/auth", + "title": "Securing Edge Functions" + } + ], + "resultChars": 68089 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Supabase Edge Functions @supabase/server combining auth modes user secret config verify_jwt false local development\", limit: 5) { nodes { title href content } } }", + "hasContent": true, + "pages": [ { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#http_get", - "title": "http_get" + "url": "https://supabase.com/docs/guides/functions/auth", + "title": "Securing Edge Functions" }, { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#get-signature", - "title": "Signature " + "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt", + "title": "Integrating With Supabase Auth" }, { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#get-usage", - "title": "Usage " + "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#http_post", - "title": "http_post" + "url": "https://supabase.com/docs/guides/functions/function-configuration", + "title": "Function Configuration" }, { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#post-signature", - "title": "Signature " - }, + "url": "https://supabase.com/docs/guides/functions/architecture", + "title": "Edge Functions Architecture" + } + ], + "resultChars": 36511 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"@supabase/server userClaims id authMode TypeScript Edge Function withSupabase userClaims\", limit: 5) { nodes { title href content } } }", + "hasContent": true, + "pages": [ { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#post-usage", - "title": "Usage " + "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/database/extensions/pg_net#http_delete", - "title": "http_delete" + "url": "https://supabase.com/docs/guides/functions/auth", + "title": "Securing Edge Functions" }, { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#post-signature-1", - "title": "Signature " + "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/extensions/pg_net#inspecting-request-data", - "title": "Inspecting request data" + "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/extensions/pg_net#inspecting-failed-requests", - "title": "Inspecting failed requests" - }, + "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-react", + "title": "Build a User Management App with React" + } + ], + "resultChars": 125127 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"config.toml functions entrypoint verify_jwt edge function entrypoint\", limit: 8) { nodes { title href content } } }", + "hasContent": true, + "pages": [ { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#configuration", - "title": "Configuration" + "url": "https://supabase.com/docs/guides/functions/function-configuration", + "title": "Function Configuration" }, { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#get-current-settings", - "title": "Get current settings" + "url": "https://supabase.com/docs/guides/functions/development-tips", + "title": "Development tips" }, { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#alter-settings", - "title": "Alter settings" + "url": "https://supabase.com/docs/guides/functions/deploy", + "title": "Deploy to Production" }, { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#examples", - "title": "Examples" + "url": "https://supabase.com/docs/guides/functions/auth-headers", + "title": "Authorization headers" }, { - "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/functions/auth", + "title": "Securing Edge Functions" }, { - "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/functions/examples/mcp-server-mcp-lite", + "title": "Building an MCP Server with mcp-lite" }, { - "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/self-hosting/self-hosted-functions", + "title": "Self-Hosted 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/functions/examples/resumable-websockets", + "title": "Resumable WebSockets with Edge Functions" + } + ], + "resultChars": 52465 + } + ] + }, + "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-no-skills/build-functions-005-dual-auth-user-secret.json" + }, + { + "experiment": "codex-gpt-5.6-no-skills", + "experimentSuite": "no-skills", + "experimentDisplay": { + "agent": "codex", + "modelProvider": "openai", + "modelId": "gpt-5.6-sol", + "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: 019fd386-15d9-740f-80f4-7967080ed661/receipt-alpha.pdf, 019fd386-15d9-740f-80f4-7967080ed661/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": "The assistant created a private user-files bucket, kept RLS enabled, added authenticated SELECT and INSERT policies scoped to bucket_id and the user's UID as the first folder segment, and provided supabase-js createSignedUrl code with a 15-minute expiry. No public bucket, public URL, anon policy, RLS disabling, or client service-role use was present." + } + ], + "skills": { + "available": [], + "loaded": [] + }, + "docs": { + "calls": [ + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Supabase Storage RLS policy foldername auth.uid private bucket createSignedUrl supabase-js\", limit: 5) { nodes { title href content } } }", + "hasContent": true, + "pages": [ { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#resources", - "title": "Resources" + "url": "https://supabase.com/docs/guides/storage/serving/downloads", + "title": "Serving assets from Storage" }, { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net#limitations", - "title": "Limitations" + "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals", + "title": "Storage Buckets" }, { - "url": "https://supabase.com/docs/guides/functions/schedule-functions", - "title": "Scheduling Edge Functions" + "url": "https://supabase.com/docs/guides/storage/schema/helper-functions", + "title": "Storage Helper Functions" }, { - "url": "https://supabase.com/docs/guides/functions/schedule-functions#resources", - "title": "Resources" + "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/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/firebase-storage", + "title": "Migrated from Firebase Storage to Supabase" + } + ], + "resultChars": 20384 + }, + { + "source": "search_docs", + "query": "query { searchDocs(query: \"Storage access control policy storage.foldername(name) auth.uid insert select update delete\", limit: 8) { nodes { title href content } } }", + "hasContent": true, + "pages": [ { - "url": "https://supabase.com/docs/guides/functions/schedule-functions#examples", - "title": "Examples" + "url": "https://supabase.com/docs/guides/storage/security/access-control", + "title": "Storage Access Control" }, { - "url": "https://supabase.com/docs/guides/cron", - "title": "Cron" + "url": "https://supabase.com/docs/guides/security/product-security", + "title": "Secure configuration of Supabase products" }, { - "url": "https://supabase.com/docs/guides/cron#resources", - "title": "Resources" + "url": "https://supabase.com/docs/guides/storage/schema/helper-functions", + "title": "Storage Helper Functions" }, { - "url": "https://supabase.com/docs/guides/cron#how-does-cron-work", - "title": "How does Cron work?" + "url": "https://supabase.com/docs/guides/storage/quickstart", + "title": "Storage Quickstart" }, { - "url": "https://supabase.com/docs/guides/auth/auth-hooks/send-email-hook", - "title": "Send Email Hook" + "url": "https://supabase.com/docs/guides/storage/management/copy-move-objects", + "title": "Copy Objects" }, { - "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/self-hosting/self-hosted-s3", + "title": "Configure S3 Storage" }, { - "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/storage/buckets/fundamentals", + "title": "Storage Buckets" }, { - "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/troubleshooting/supabase-storage-inefficient-folder-operations-and-hierarchical-rls-challenges-b05a4d", + "title": "Supabase Storage: Inefficient folder operations and hierarchical RLS challenges" } ], - "resultChars": 176011 + "resultChars": 39230 } ] }, - "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", + "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-no-skills/build-cli-003-pg-cron-queue-workflow.json" + "sourcePath": "codex-gpt-5.6-no-skills/build-storage-001-private-bucket-access.json" }, { "experiment": "codex-gpt-5.6-no-skills", @@ -14327,37 +16861,33 @@ "modelId": "gpt-5.6-sol", "reasoningEffort": "medium" }, - "eval": "build-database-001-migrate-postgres-to-supabase", + "eval": "build-tests-001-rls-tenant-isolation", "stage": "build", "product": [ "database" ], "topic": [ - "migrations" + "tests", + "rls" ], "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": "pgTAP test file(s) written under supabase/tests/", + "passed": true, + "notes": "1 file(s): supabase/tests/tenant_isolation.sql" }, { - "name": "tasks_team_status_idx index survived the restore", - "passed": true + "name": "pgTAP isolation tests ran and pass", + "passed": true, + "notes": "9 passed, 0 failed" }, { - "name": "sequences synced (next insert won't conflict with existing IDs)", - "passed": true + "name": "agent correctly identifies the posts isolation bug from test results", + "passed": true, + "judgeNotes": "The agent correctly identified `posts` as having cross-tenant read access due to a missing `org_id` membership comparison, and grounded the conclusion in pgTAP failures. It did not blame `notes` or dismiss the test results." } ], "skills": { @@ -14368,38 +16898,38 @@ "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: \"database testing RLS pgTAP auth.uid tenant isolation Supabase\", 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/local-development/testing/pgtap-extended", + "title": "Advanced pgTAP Testing" }, { - "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/overview", + "title": "Testing Overview" }, { - "url": "https://supabase.com/docs/guides/local-development/restoring-downloaded-backup", - "title": "Restoring a downloaded backup locally" + "url": "https://supabase.com/docs/guides/database/secure-data", + "title": "Securing your data" }, { - "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/postgres/row-level-security", + "title": "Row Level Security" }, { - "url": "https://supabase.com/docs/guides/platform/migrating-to-supabase/neon", - "title": "Migrate from Neon to Supabase" + "url": "https://supabase.com/docs/guides/auth", + "title": "Auth" } ], - "resultChars": 42818 + "resultChars": 69363 } ] }, - "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", + "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-no-skills/build-database-001-migrate-postgres-to-supabase.json" + "sourcePath": "codex-gpt-5.6-no-skills/build-tests-001-rls-tenant-isolation.json" }, { "experiment": "codex-gpt-5.6-no-skills", @@ -14410,46 +16940,50 @@ "modelId": "gpt-5.6-sol", "reasoningEffort": "medium" }, - "eval": "build-functions-004-service-role-bypass", + "eval": "build-vectors-001-rag-with-permissions", "stage": "build", "product": [ - "edge-functions", - "auth", - "database" + "database", + "vectors" ], "topic": [ - "rls", - "security", - "sdk" + "sql", + "rls" ], "suite": "benchmark", "interface": "mcp", "passed": true, "checks": [ { - "name": "rejects missing auth", + "name": "document_sections.embedding is vector(384)", "passed": true, - "notes": "status=401" + "notes": "vector(384)" }, { - "name": "user A reads own note", + "name": "HNSW index on the embedding column", "passed": true, - "notes": "status=200" + "notes": "CREATE INDEX document_sections_embedding_hnsw_idx ON public.document_sections USING hnsw (embedding vector_ip_ops)" }, { - "name": "reads only with the caller's JWT", + "name": "index operator class matches the search operator", "passed": true, - "notes": "bearer_tokens=2, all_match=true" + "notes": "function operators: <#>\nindexes: CREATE INDEX document_sections_embedding_hnsw_idx ON public.document_sections USING hnsw (embedding vector_ip_ops)" }, { - "name": "user A cannot force-read user B note", - "passed": true, - "notes": "status=200" + "name": "user A search returns only own sections, best match first", + "passed": true }, { - "name": "user B cannot force-read user A note", - "passed": true, - "notes": "status=200" + "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": { @@ -14460,34 +16994,38 @@ "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: \"pgvector semantic search match_documents vector(384) row level security security invoker RPC\", limit: 5) { nodes { ... on Guide { title href content } ... on ClientLibraryFunctionReference { title href content language methodName } } } }", "hasContent": true, "pages": [ { - "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt", - "title": "Integrating With Supabase Auth" + "url": "https://supabase.com/docs/guides/ai/rag-with-permissions", + "title": "RAG with Permissions" }, { - "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/examples/semantic-search", + "title": "Semantic Search" }, { - "url": "https://supabase.com/docs/guides/functions/auth", - "title": "Securing Edge Functions" + "url": "https://supabase.com/docs/guides/ai/semantic-search", + "title": "Semantic search" }, { - "url": "https://supabase.com/docs/guides/functions", - "title": "Edge Functions" + "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" } ], - "resultChars": 70238 + "resultChars": 51314 } ] }, - "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", + "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-no-skills/build-functions-004-service-role-bypass.json" + "sourcePath": "codex-gpt-5.6-no-skills/build-vectors-001-rag-with-permissions.json" }, { "experiment": "codex-gpt-5.6-no-skills", @@ -14498,67 +17036,30 @@ "modelId": "gpt-5.6-sol", "reasoningEffort": "medium" }, - "eval": "build-functions-005-dual-auth-user-secret", - "stage": "build", + "eval": "deploy-database-001-prometheus-metrics", + "stage": "deploy", "product": [ - "edge-functions", - "auth", "database" ], "topic": [ - "sdk", - "rls", - "security" + "observability" ], "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: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}" - }, - { - "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}]" - }, - { - "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}]" - }, - { - "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}]" - }, - { - "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": "preserved existing app scrape job", + "passed": true }, { - "name": "a user token in the apikey slot is not treated as the service key", + "name": "configured the Supabase Metrics API scrape correctly", "passed": true, - "notes": "status 401: {\"message\":\"Invalid credentials\",\"code\":\"INVALID_CREDENTIALS\"}" + "judgeNotes": "Meets all requirements: app scrape preserved, Supabase HTTPS metrics endpoint configured with Basic Auth password_file, valid project target, and Compose secret wiring mounts the password file." }, { - "name": "implementation uses @supabase/server", + "name": "documented live deployment and verification steps", "passed": true, - "notes": "imports @supabase/server / withSupabase" + "judgeNotes": "README includes creating a Supabase Secret API key, writing it to the Docker secret file matching the Compose secret, recreating the stack, and verifying via Prometheus targets and Grafana queries." } ], "skills": { @@ -14569,525 +17070,495 @@ "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: \"Prometheus project metrics endpoint customer v1 privileged metrics authentication service role\", limit: 8) { nodes { title href content ... on Guide { subsections { 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/monitoring-and-debugging/metrics/vendor-agnostic", + "title": "Vendor-agnostic Metrics API setup" }, { - "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/monitoring-and-debugging/metrics/vendor-agnostic#2-secure-the-credentials", + "title": "2. Secure the credentials" }, { - "url": "https://supabase.com/docs/guides/functions/auth", - "title": "Securing Edge Functions" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic#collector-specific-notes", + "title": "Collector-specific notes" }, { - "url": "https://supabase.com/docs/guides/getting-started/api-keys", - "title": "Understanding API keys" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic#1-define-the-scrape-job", + "title": "1. Define the scrape job" }, { - "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/monitoring-and-debugging/metrics/vendor-agnostic#components", + "title": "Components" }, { - "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/monitoring-and-debugging/metrics/vendor-agnostic#5-multi-project-setups", + "title": "5. Multi-project setups" }, { - "url": "https://supabase.com/docs/guides/auth/third-party/firebase-auth", - "title": "Firebase Auth" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic#4-alerts-and-automation", + "title": "4. Alerts and automation" }, { - "url": "https://supabase.com/docs/guides/auth/jwt-fields", - "title": "JWT Claims Reference" - } - ], - "resultChars": 87163 - }, - { - "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 } } }", - "hasContent": true, - "pages": [ + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/vendor-agnostic#3-downstream-dashboards", + "title": "3. Downstream dashboards" + }, { - "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/monitoring-and-debugging/metrics/grafana-self-hosted", + "title": "Metrics API with Prometheus & Grafana (self-hosted)" }, { - "url": "https://supabase.com/docs/guides/functions/auth", - "title": "Securing Edge Functions" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted#architecture", + "title": "Architecture" }, { - "url": "https://supabase.com/docs/guides/getting-started/api-keys", - "title": "Understanding API keys" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted#1-deploy-prometheus", + "title": "1. Deploy Prometheus" }, { - "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/monitoring-and-debugging/metrics/grafana-self-hosted#2-deploy-grafana", + "title": "2. Deploy Grafana" }, { - "url": "https://supabase.com/docs/guides/functions/examples/cloudflare-turnstile", - "title": "CAPTCHA support with Cloudflare Turnstile" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted#3-import-supabase-dashboards", + "title": "3. Import Supabase dashboards" }, { - "url": "https://supabase.com/docs/guides/functions/secrets", - "title": "Environment Variables" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted#4-configure-alerting", + "title": "4. Configure alerting" }, { - "url": "https://supabase.com/docs/guides/auth/passkeys", - "title": "Passkey authentication" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted#5-operating-tips", + "title": "5. Operating tips" }, { - "url": "https://supabase.com/docs/guides/functions/quickstart-dashboard", - "title": "Getting Started with Edge Functions (Dashboard)" + "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/secure-data", - "title": "Securing your data" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#1-create-a-grafana-cloud-stack", + "title": "1. Create a Grafana Cloud stack" }, { - "url": "https://supabase.com/docs/guides/getting-started/tutorials/with-ionic-angular", - "title": "Build a User Management App with Ionic Angular" - } - ], - "resultChars": 114420 - }, - { - "source": "search_docs", - "query": "query { searchDocs(query: \"@supabase/server validateApiKey Edge Function SUPABASE_SECRET_KEYS\", limit: 5) { nodes { title href content } } }", - "hasContent": true, - "pages": [ + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#installation", + "title": "Installation" + }, { - "url": "https://supabase.com/docs/guides/functions/auth", - "title": "Securing Edge Functions" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#manual-setup", + "title": "Manual setup" }, { - "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/monitoring-and-debugging/metrics/grafana-cloud#prerequisites", + "title": "Prerequisites" }, { - "url": "https://supabase.com/docs/guides/getting-started/api-keys", - "title": "Understanding API keys" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#2-install-the-supabase-integration-for-grafana-cloud", + "title": "2. Install the Supabase integration for Grafana Cloud" }, { - "url": "https://supabase.com/docs/guides/functions/secrets", - "title": "Environment Variables" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#3-configure-the-supabase-integration", + "title": "3. Configure the Supabase integration" }, { - "url": "https://supabase.com/docs/guides/auth/passkeys", - "title": "Passkey authentication" - } - ], - "resultChars": 51999 - }, - { - "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 } } }", - "hasContent": true, - "pages": [ + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#4-import-the-supabase-dashboard", + "title": "4. Import the Supabase dashboard" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#5-configure-alerts-optional", + "title": "5. Configure alerts (optional)" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#6-troubleshooting", + "title": "6. Troubleshooting" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics", + "title": "Metrics API" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics#what-you-can-do-with-the-metrics-api", + "title": "What you can do with the Metrics API" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics#additional-resources", + "title": "Additional resources" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics#choose-your-monitoring-stack", + "title": "Choose your monitoring stack" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit", + "title": "PGAudit: Postgres Auditing" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#enable-the-extension", + "title": "Enable the extension" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#configure-the-extension", + "title": "Configure the extension" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#session-mode-categories", + "title": "Session mode categories" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#session-logging", + "title": "Session logging" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#user-logging", + "title": "User logging" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#global-logging", + "title": "Global logging" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#object-logging", + "title": "Object logging" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#interpreting-audit-logs", + "title": "Interpreting Audit Logs" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#finding-and-filtering-audit-logs", + "title": "Finding and filtering audit logs" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#practical-examples", + "title": "Practical examples" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#monitoring-api-events", + "title": "Monitoring API events" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#monitoring-the-authusers-table", + "title": "Monitoring the auth.users table" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#best-practices", + "title": "Best practices" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#disabling-excess-logging", + "title": "Disabling excess logging" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#faq", + "title": "FAQ" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#downloading-database-logs", + "title": "Downloading database logs" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#using-pgaudit-to-debug-database-functions", + "title": "Using PGAudit to debug database functions" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#resources", + "title": "Resources" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#does-pgaudit-support-system-wide-configurations", + "title": "Does PGAudit support system wide configurations?" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#logging-function-parameters", + "title": "Logging function parameters" + }, + { + "url": "https://supabase.com/docs/guides/database/extensions/pgaudit#logging-observed-table-rows", + "title": "Logging observed table rows" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles", + "title": "Postgres Roles" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#preventing-inheritance", + "title": "Preventing inheritance" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#supabase-roles", + "title": "Supabase roles" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#postgres", + "title": "postgres" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#anon", + "title": "anon" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#authenticator", + "title": "authenticator" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#authenticated", + "title": "authenticated" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#service_role", + "title": "service_role" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#supabase_auth_admin", + "title": "supabase_auth_admin" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#supabase_storage_admin", + "title": "supabase_storage_admin" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#supabase_etl_admin", + "title": "supabase_etl_admin" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#dashboard_user", + "title": "dashboard_user" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#supabase_admin", + "title": "supabase_admin" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#resources", + "title": "Resources" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#users-vs-roles", + "title": "Users vs roles" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#creating-roles", + "title": "Creating roles" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#creating-users", + "title": "Creating users" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#passwords", + "title": "Passwords" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#special-symbols-in-passwords", + "title": "Special symbols in passwords" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#changing-your-project-password", + "title": "Changing your project password" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#granting-permissions", + "title": "Granting permissions" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#revoking-permissions", + "title": "Revoking permissions" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#role-hierarchy", + "title": "Role hierarchy" + }, + { + "url": "https://supabase.com/docs/guides/database/postgres/roles#role-inheritance", + "title": "Role inheritance" + }, + { + "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#before-you-begin", + "title": "Before you begin" + }, + { + "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/self-hosting/self-hosted-envoy#verify", + "title": "Verify" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#architecture", + "title": "Architecture" + }, + { + "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#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#routes", + "title": "Routes" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#authentication", + "title": "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/self-hosting/self-hosted-envoy#dashboard-basic-auth", + "title": "Dashboard basic auth" }, { - "url": "https://supabase.com/docs/guides/functions/auth-legacy-jwt", - "title": "Integrating With Supabase Auth" + "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/functions/auth", - "title": "Securing Edge Functions" + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#opaque-key-translation", + "title": "Opaque key translation" }, { - "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#forwarded-headers-and-cors", + "title": "Forwarded headers and CORS" }, { - "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#x-forwarded-headers", + "title": "X-Forwarded headers" }, { - "url": "https://supabase.com/docs/guides/auth/choosing-a-server-package", - "title": "Which package to use" + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#cors", + "title": "CORS" }, { - "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-envoy#security-hardening", + "title": "Security hardening" }, { - "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-functions", - "title": "Self-Hosted Functions" - } - ], - "resultChars": 73001 - } - ] - }, - "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-no-skills/build-functions-005-dual-auth-user-secret.json" - }, - { - "experiment": "codex-gpt-5.6-no-skills", - "experimentSuite": "no-skills", - "experimentDisplay": { - "agent": "codex", - "modelProvider": "openai", - "modelId": "gpt-5.6-sol", - "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: 019fb129-6dc4-779f-a3a1-a1c86804f6c6/receipt-alpha.pdf, 019fb129-6dc4-779f-a3a1-a1c86804f6c6/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": "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." - } - ], - "skills": { - "available": [], - "loaded": [] - }, - "docs": { - "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 } } }", - "hasContent": true, - "pages": [ + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#customizing-the-configuration", + "title": "Customizing the configuration" + }, { - "url": "https://supabase.com/docs/guides/storage/buckets/fundamentals", - "title": "Storage Buckets" + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#admin-interface", + "title": "Admin interface" }, { - "url": "https://supabase.com/docs/guides/storage/schema/helper-functions", - "title": "Storage Helper Functions" + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#troubleshooting", + "title": "Troubleshooting" }, { - "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-envoy#logs", + "title": "Logs" }, { - "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-envoy#common-issues", + "title": "Common issues" }, { - "url": "https://supabase.com/docs/guides/storage/serving/downloads", - "title": "Serving assets from Storage" - } - ], - "resultChars": 23009 - } - ] - }, - "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-no-skills/build-storage-001-private-bucket-access.json" - }, - { - "experiment": "codex-gpt-5.6-no-skills", - "experimentSuite": "no-skills", - "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/tenant_isolation.test.sql" - }, - { - "name": "pgTAP isolation tests ran and pass", - "passed": true, - "notes": "8 passed, 3 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." - } - ], - "skills": { - "available": [], - "loaded": [] - }, - "docs": { - "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 } } }", - "hasContent": true, - "pages": [ + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-envoy#see-also", + "title": "See also" + }, { - "url": "https://supabase.com/docs/guides/realtime/authorization", - "title": "Realtime Authorization" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports", + "title": "Reports" }, { - "url": "https://supabase.com/docs/guides/auth/auth-mfa", - "title": "Multi-Factor Authentication" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#auth", + "title": "Auth" }, { - "url": "https://supabase.com/docs/guides/ai/rag-with-permissions", - "title": "RAG with Permissions" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#auth-api-gateway", + "title": "Auth API Gateway" }, { - "url": "https://supabase.com/docs/guides/database/extensions/pgaudit", - "title": "PGAudit: Postgres Auditing" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#database", + "title": "Database" }, { - "url": "https://supabase.com/docs/guides/getting-started/features", - "title": "Features" - } - ], - "resultChars": 72236 - } - ] - }, - "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-no-skills/build-tests-001-rls-tenant-isolation.json" - }, - { - "experiment": "codex-gpt-5.6-no-skills", - "experimentSuite": "no-skills", - "experimentDisplay": { - "agent": "codex", - "modelProvider": "openai", - "modelId": "gpt-5.6-sol", - "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)" - }, - { - "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)" - }, - { - "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": [ - { - "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 } } } }", - "hasContent": true, - "pages": [ + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#advanced-telemetry", + "title": "Advanced Telemetry" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#memory-usage", + "title": "Memory usage" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#memory-commitment", + "title": "Memory commitment" + }, { - "url": "https://supabase.com/docs/guides/ai/rag-with-permissions", - "title": "RAG with Permissions" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#cpu-usage", + "title": "CPU usage" }, { - "url": "https://supabase.com/docs/guides/ai/semantic-search", - "title": "Semantic search" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#using-reports", + "title": "Using reports" }, { - "url": "https://supabase.com/docs/guides/ai/hybrid-search", - "title": "Hybrid search" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#storage", + "title": "Storage" }, { - "url": "https://supabase.com/docs/guides/ai/automatic-embeddings", - "title": "Automatic embeddings" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#disk-inputoutput-operations-per-second-iops", + "title": "Disk input/output operations per second (IOPS)" }, { - "url": "https://supabase.com/docs/guides/ai/vector-columns", - "title": "Vector columns" - } - ], - "resultChars": 80299 - } - ] - }, - "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-no-skills/build-vectors-001-rag-with-permissions.json" - }, - { - "experiment": "codex-gpt-5.6-no-skills", - "experimentSuite": "no-skills", - "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": "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." - }, - { - "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." - } - ], - "skills": { - "available": [], - "loaded": [] - }, - "docs": { - "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 } } }", - "hasContent": true, - "pages": [ + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#realtime-api-gateway", + "title": "Realtime API Gateway" + }, { - "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/reports#realtime", + "title": "Realtime" }, { - "url": "https://supabase.com/docs/guides/telemetry/metrics", - "title": "Metrics API" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#postgrest", + "title": "PostgREST" }, { - "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/reports#edge-functions", + "title": "Edge Functions" }, { - "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/reports#database-size", + "title": "Database size" }, { - "url": "https://supabase.com/docs/guides/platform/read-replicas", - "title": "Read Replicas" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#disk-usage", + "title": "Disk Usage" }, { - "url": "https://supabase.com/docs/guides/database/connection-management", - "title": "Connection management" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#shared-pooler-supavisor-client-connections", + "title": "Shared Pooler (Supavisor) Client Connections" }, { - "url": "https://supabase.com/docs/guides/database/postgres/roles", - "title": "Postgres Roles" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#dedicated-pooler-pgbouncer-client-connections", + "title": "Dedicated Pooler (PgBouncer) Client Connections" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#database-connections", + "title": "Database connections" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#query-performance", + "title": "Query Performance" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#disk-size", + "title": "Disk size" }, { - "url": "https://supabase.com/docs/guides/security/security-testing", - "title": "Security testing of your Supabase projects" + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#disk-throughput", + "title": "Disk throughput" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/reports#api-gateway", + "title": "API gateway" } ], - "resultChars": 48186 + "resultChars": 271385 } ] }, @@ -15129,7 +17600,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": "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,17 +17615,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: \"Edge Functions environment variables secrets set 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" - }, { "url": "https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys", "title": "Migrating to publishable and secret API keys" @@ -15164,11 +17627,19 @@ "title": "Environment Variables" }, { - "url": "https://supabase.com/docs/guides/functions/examples/upstash-redis", - "title": "Upstash Redis" + "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/ai/examples/openai", + "title": "Generating OpenAI GPT3 completions" + }, + { + "url": "https://supabase.com/docs/guides/functions/function-configuration", + "title": "Function Configuration" } ], - "resultChars": 35184 + "resultChars": 28019 } ] }, @@ -15225,7 +17696,7 @@ "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 } } }", + "query": "query { searchDocs(query: \"self-hosting Docker compose environment secrets JWT_SECRET ANON_KEY SERVICE_ROLE_KEY POSTGRES_PASSWORD dashboard username password pooler secret encryption key\", limit: 8) { nodes { __typename title href content } } }", "hasContent": true, "pages": [ { @@ -15233,39 +17704,39 @@ "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/remove-superuser-access", + "title": "Remove Superuser Access from Studio" + }, + { + "url": "https://supabase.com/docs/guides/auth/signing-keys", + "title": "JWT Signing Keys" }, { "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-functions", "title": "Self-Hosted Functions" }, { - "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-oauth", + "title": "Configure Social Login (OAuth) Providers" }, { - "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-saml-sso", - "title": "Configure SAML SSO" + "url": "https://supabase.com/docs/guides/self-hosting/postgres-upgrade-17", + "title": "Upgrade to Postgres 17" } ], - "resultChars": 171411 + "resultChars": 155675 }, { "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 } } }", + "query": "query { searchDocs(query: \"Docker self-hosting quick start Linux clone supabase docker .env.example generate-keys.sh\", limit: 5) { nodes { __typename title href content } } }", "hasContent": true, "pages": [ { @@ -15277,15 +17748,19 @@ "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/local-development/cli/getting-started", + "title": "Supabase CLI" }, { - "url": "https://supabase.com/docs/guides/self-hosting", - "title": "Self-Hosting" + "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", + "title": "Restore a Platform Project to Self-Hosted" } ], - "resultChars": 79242 + "resultChars": 97692 } ] }, @@ -15344,7 +17819,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: diagnoses soft-delete-only flow, implements auth user deletion/session revocation via cascade plus RLS active-user checks, explains stale JWT validity/window consistently with implemented RLS mitigation, and correctly distinguishes publishable vs secret keys." } ], "skills": { @@ -15355,7 +17830,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 auth user database function JWT remains valid until expiry sessions revoke 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": [ { @@ -15363,27 +17838,39 @@ "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/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", + "title": "Row Level Security" + }, + { + "url": "https://supabase.com/docs/guides/ai/rag-with-permissions", + "title": "RAG with Permissions" + }, + { + "url": "https://supabase.com/docs/guides/auth/third-party/firebase-auth", + "title": "Firebase Auth" + }, + { + "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/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/auth/signing-keys", + "title": "JWT Signing Keys" } ], - "resultChars": 40980 + "resultChars": 123853 }, { "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 RLS bypass frontend sb_publishable sb_secret\", limit: 5) { nodes { ... on Guide { title href content } ... on TroubleshootingGuide { title href content } } } }", "hasContent": true, "pages": [ { @@ -15391,43 +17878,55 @@ "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/database/secure-data", + "title": "Securing your data" }, { "url": "https://supabase.com/docs/guides/database/postgres/row-level-security", "title": "Row Level Security" }, { - "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/getting-started/api-keys", - "title": "Understanding API keys" + "url": "https://supabase.com/docs/guides/storage/security/access-control", + "title": "Storage Access Control" } ], - "resultChars": 91501 + "resultChars": 64416 }, { "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: \"delete user auth.users SQL database cascading signed in access token valid\", limit: 6) { 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/auth/managing-user-data", "title": "User Management" }, - { - "url": "https://supabase.com/docs/guides/database/extensions/pgaudit", - "title": "PGAudit: Postgres Auditing" - }, { "url": "https://supabase.com/docs/guides/auth/auth-anonymous", "title": "Anonymous Sign-Ins" + }, + { + "url": "https://supabase.com/docs/guides/auth/sessions", + "title": "User sessions" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers", + "title": "Multiple SSO Providers" + }, + { + "url": "https://supabase.com/docs/guides/auth/users", + "title": "Users" + }, + { + "url": "https://supabase.com/docs/guides/troubleshooting/scan-error-on-column-confirmation_token-converting-null-to-string-is-unsupported-during-auth-login-a0c686", + "title": "'Scan error on column confirmation_token: converting NULL to string is unsupported' during Auth login" } ], - "resultChars": 38021 + "resultChars": 65918 } ] }, @@ -15482,7 +17981,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": "The assistant correctly identified orders missing from the supabase_realtime publication as the root cause, added only public.orders via ALTER PUBLICATION, verified courier_locations remained, and did not weaken RLS/policies or blame client/RLS/networking." } ], "skills": { @@ -15521,17 +18020,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": "The assistant identified image-transform as the affected function and described the recurring pattern of eight HTTP 503 gateway failures on 2026-04-28 from 07:00Z through 12:00Z, matching the rubric." }, { "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 recurring 503s to gateway/platform before application code and grounds this in no corresponding function execution records, unchanged deployment/successful nearby retries, and distinguishes avatar-upload's runtime 500 as a separate function-level error." }, { "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": "The assistant recommended concrete next steps, including opening a Supabase support case with timestamps, deployment ID, and API log IDs, pinning/redeploying a dependency, adding structured logging, and investigating the separate runtime 500." } ], "skills": { @@ -15597,7 +18096,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": "The assistant correctly diagnosed RLS enabled with no policies causing deny-all Data API results, kept RLS enabled, and created authenticated-only SELECT and INSERT policies scoped to user_id = auth.uid(), with INSERT enforced via WITH CHECK." } ], "skills": { @@ -15608,7 +18107,7 @@ "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 } } }", + "query": "query { searchDocs(query: \"Row Level Security auth.uid SELECT INSERT policy authenticated using with check\", limit: 3) { nodes { title href content } } }", "hasContent": true, "pages": [ { @@ -15616,15 +18115,15 @@ "title": "Row Level Security" }, { - "url": "https://supabase.com/docs/guides/getting-started/features", - "title": "Features" + "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/getting-started/features", + "title": "Features" } ], - "resultChars": 46550 + "resultChars": 62707 } ] }, @@ -15677,7 +18176,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": "Applied pending avatar_url migration through Supabase CLI with `supabase db push --db-url \"$DB_URL\"`, which output `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`, after which CLI migration listing aligned and the subsequent `supabase db push` proceeded. No disallowed direct SQL mutation or prepared-statement reset workaround was used." } ], "skills": { @@ -15688,31 +18187,31 @@ "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 db push migration history repair remote database migrations\", 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/reference/cli/supabase-db-push", + "title": "Push new migrations to the remote database" }, { - "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/guides/local-development/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/reference/cli/supabase-db-push", - "title": "Push new migrations to the remote database" + "url": "https://supabase.com/docs/guides/platform/migrating-within-supabase/backup-restore", + "title": "Backup and Restore using the CLI" } ], - "resultChars": 74715 + "resultChars": 84771 } ] }, @@ -15758,7 +18257,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 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": "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_desc (cost=0.00..5.03 rows=100 width=0)\n Index Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)" }, { "name": "inserts still work", @@ -15773,9 +18272,13 @@ "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 } } }", + "query": "query { searchDocs(query: \"Postgres composite index WHERE equality ORDER BY DESC LIMIT query performance\", limit: 3) { 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/database/orioledb", "title": "OrioleDB Overview" @@ -15783,13 +18286,9 @@ { "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 + "resultChars": 26611 } ] }, @@ -15903,7 +18402,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 +18420,7 @@ { "name": "REST API returns the todos to authenticated requests", "passed": true, - "notes": "2 rows" + "notes": "3 rows" } ], "skills": { @@ -15945,7 +18444,7 @@ "url": "https://supabase.com/changelog.md" } ], - "resultChars": 93411 + "resultChars": 93795 } ] }, @@ -15973,23 +18472,25 @@ ], "suite": "benchmark", "interface": "cli", - "passed": true, + "passed": false, "checks": [ { "name": "supabase db diff used to generate the migration", - "passed": true + "passed": false }, { "name": "schema file updated to include description column", - "passed": true + "passed": false, + "notes": "description not found in any schema file" }, { "name": "a new migration was generated for the change", - "passed": true + "passed": false, + "notes": "found 1 migration file(s)" }, { "name": "description column exists in the live database", - "passed": true + "passed": false } ], "skills": { @@ -15997,28 +18498,14 @@ "supabase", "supabase-postgres-best-practices" ], - "loaded": [ - "supabase" - ] + "loaded": [] }, "docs": { - "calls": [ - { - "source": "web_fetch", - "query": "https://supabase.com/changelog.md", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/changelog.md" - } - ], - "resultChars": 93411 - } - ] + "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, + "attempts": 2, "sourcePath": "opencode-kimi-k3/build-cli-002-declarative-schema.json" }, { @@ -16043,22 +18530,22 @@ ], "suite": "benchmark", "interface": "cli", - "passed": true, + "passed": false, "checks": [ { "name": "pg_cron job 'enqueue-tasks' scheduled to run every minute", - "passed": true, - "notes": "schedule='* * * * *', active=true" + "passed": false, + "notes": "job not found in cron.job" }, { "name": "cron command enqueues to the 'tasks' queue", - "passed": true, - "notes": "queue depth 0 -> 1" + "passed": false, + "notes": "job not found, so its command can't run" }, { "name": "process-tasks function drains the queue", - "passed": true, - "notes": "function removed the seeded message (id 37) from the queue" + "passed": false, + "notes": "couldn't enqueue a test message. Is the 'tasks' queue created? query failed: ERROR: relation \"pgmq.q_tasks\" does not exist\nLINE 2: INSERT INTO pgmq.q_tasks (vt, message, headers)\n ^\nQUERY: \n INSERT INTO pgmq.q_tasks (vt, message, headers)\n VALUES ($2, $1, $3)\n RETURNING msg_id;\n \nCONTEXT: PL/pgSQL function pgmq.send(text,jsonb,jsonb,timestamp with time zone) line 14 at RETURN QUERY\nSQL function \"send\" statement 1\n" } ], "skills": { @@ -16066,69 +18553,14 @@ "supabase", "supabase-postgres-best-practices" ], - "loaded": [ - "supabase" - ] + "loaded": [] }, "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 } } }", - "hasContent": true, - "pages": [ - { - "url": "https://supabase.com/docs/guides/database/extensions/pg_net", - "title": "pg_net: Async Networking" - }, - { - "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/queues/quickstart", - "title": "Quickstart" - } - ], - "resultChars": 18714 - } - ] + "calls": [] }, "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,7 +18610,8 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" ] }, "docs": { @@ -16252,31 +18685,22 @@ "calls": [ { "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 authenticated user from Authorization header auth.getUser\", limit: 3) { 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/functions/auth", - "title": "Securing Edge Functions" - }, - { - "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-headers", + "title": "Authorization headers" } ], - "resultChars": 21680 + "resultChars": 9611 } ] }, @@ -16308,7 +18732,7 @@ "suite": "benchmark", "interface": "cli", "cliVersion": "2.109.1", - "passed": true, + "passed": false, "checks": [ { "name": "seed rows present", @@ -16318,42 +18742,42 @@ { "name": "rejects request with no credentials", "passed": true, - "notes": "status 401: {\"message\":\"Invalid credentials\"}" + "notes": "status 404: Function not found" }, { "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}]" + "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\":\"37806d0f-f274-4021-aea2-77e34259085f\",\"metric\":\"steps_a_ms6x7jy9\",\"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\":\"ff362a6e-3573-4069-b30d-24e34c6a5e04\",\"metric\":\"steps_b_ms6x7jy9\",\"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\"}" + "notes": "status 404: Function not found" }, { "name": "rejects an unverified (forged) user token", "passed": true, - "notes": "status 401: {\"message\":\"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\"}" + "notes": "status 404: Function not found" }, { "name": "implementation uses @supabase/server", - "passed": true, - "notes": "imports @supabase/server / withSupabase" + "passed": false, + "notes": "could not locate function source to inspect" } ], "skills": { @@ -16361,49 +18785,14 @@ "supabase", "supabase-postgres-best-practices" ], - "loaded": [ - "supabase" - ] + "loaded": [] }, "docs": { - "calls": [ - { - "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 } } }", - "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-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/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" - } - ], - "resultChars": 42813 - } - ] + "calls": [] }, "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/build-functions-005-dual-auth-user-secret.json" }, { @@ -16443,7 +18832,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: 019fd387-6b1e-732b-8b71-a5420dfd72c1/receipt-alpha.pdf, 019fd387-6b1e-732b-8b71-a5420dfd72c1/receipt-beta.pdf" }, { "name": "user B cannot read user A files", @@ -16464,7 +18853,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 WITH CHECK policies on storage.objects, no public/permissive policies or RLS disabling, and supabase-js createSignedUrl with expiry for temporary sharing." } ], "skills": { @@ -16473,47 +18862,29 @@ "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: \"storage access control bucket RLS policies owner folder\") { nodes { title href content } } }", + "query": "{ searchDocs(query: \"storage access control RLS policies user folders private bucket signed URL\", 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/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/platform/migrating-within-supabase/backup-restore", - "title": "Backup and Restore using the CLI" - }, { "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-s3", "title": "Configure S3 Storage" @@ -16521,112 +18892,9 @@ { "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/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": 25926 } ] }, @@ -16654,22 +18922,22 @@ ], "suite": "benchmark", "interface": "cli", - "passed": true, + "passed": false, "checks": [ { "name": "pgTAP test file(s) written under supabase/tests/", - "passed": true, - "notes": "1 file(s): supabase/tests/rls_tenant_isolation_test.sql" + "passed": false, + "notes": "no .sql files found under supabase/tests/" }, { "name": "pgTAP isolation tests ran and pass", - "passed": true, - "notes": "9 passed, 6 failed" + "passed": false, + "notes": "no test summary found; exit 0; output: Connecting to local database...\nFiles=0, Tests=0, 0 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)\nResult: NOTESTS\nA new version of Supabase CLI is available: v2.111.0 (currently installed v2.67.1)\nWe recommend updating regularly for new features and bug fixes: https://supabase.com/docs/guides/cli/getting-started#updating-the-supabase-cli\n" }, { "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 identifies the posts table as having a broken tenant isolation policy, specifically that authenticated members can read posts from organizations they are not a member of, and bases this on the pgTAP/test results rather than migration comments. It does not incorrectly blame notes or claim both tables are isolated." } ], "skills": { @@ -16677,16 +18945,14 @@ "supabase", "supabase-postgres-best-practices" ], - "loaded": [ - "supabase" - ] + "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, + "attempts": 2, "sourcePath": "opencode-kimi-k3/build-tests-001-rls-tenant-isolation.json" }, { @@ -16709,38 +18975,40 @@ ], "suite": "benchmark", "interface": "mcp", - "passed": true, + "passed": false, "checks": [ { "name": "document_sections.embedding is vector(384)", - "passed": true, - "notes": "vector(384)" + "passed": false, + "notes": "no embedding column" }, { "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": "match_document_sections not found" }, { "name": "user A search returns only own sections, best match first", - "passed": true + "passed": false, + "notes": "Could not find the function public.match_document_sections(match_count, query_embedding) in the schema cache" }, { "name": "user B search returns only own sections, best match first", - "passed": true + "passed": false, + "notes": "Could not find the function public.match_document_sections(match_count, query_embedding) in the schema cache" }, { "name": "user A reads only own sections through the API", - "passed": true + "passed": false }, { "name": "user A reads only own documents through the API", - "passed": true + "passed": false } ], "skills": { @@ -16748,52 +19016,10 @@ "supabase", "supabase-postgres-best-practices" ], - "loaded": [ - "supabase" - ] + "loaded": [] }, "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 } } }", - "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/ai/vector-columns", - "title": "Vector columns" - }, - { - "url": "https://supabase.com/docs/guides/functions/examples/semantic-search", - "title": "Semantic Search" - } - ], - "resultChars": 71630 - } - ] + "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", @@ -16826,12 +19052,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": "Meets all requirements: HTTPS Supabase Metrics API scrape at the correct path for a supabase.co project target, basic_auth with password_file, app scrape preserved, and docker-compose mounts the secrets directory containing the password file." }, { "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 correct Secret API key setup, matching password_file path, apply/reload steps for the Compose stack, and concrete verification via Prometheus targets/PromQL." } ], "skills": { @@ -16847,51 +19073,31 @@ "calls": [ { "source": "search_docs", - "query": "{ searchDocs(query: \"metrics endpoint prometheus scrape project metrics\") { nodes { title href content } } }", + "query": "{ searchDocs(query: \"metrics endpoint prometheus scrape observability\", limit: 8) { 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", + "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/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 + "resultChars": 20183 } ] }, @@ -16951,24 +19157,14 @@ "docs": { "calls": [ { - "source": "search_docs", - "query": "{ searchDocs(query: \"edge function secrets environment variables supabase secrets set env file\", limit: 3) { nodes { title href content } } }", - "hasContent": true, + "source": "shell_fetch", + "query": "curl -s https://supabase.com/changelog.md | grep -i -B2 -A2 'edge function\\|breaking' | head -40", "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": 2908 } ] }, @@ -17036,7 +19232,7 @@ "url": "https://supabase.com/changelog.md" } ], - "resultChars": 93411 + "resultChars": 93795 }, { "source": "web_fetch", @@ -17047,7 +19243,135 @@ "url": "https://supabase.com/docs/guides/self-hosting/docker.md" } ], - "resultChars": 30212 + "resultChars": 30709 + }, + { + "source": "search_docs", + "query": "{ searchDocs(query: \"self-hosting with Docker compose setup guide\") { nodes { 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-oauth", + "title": "Configure Social Login (OAuth) Providers" + }, + { + "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/postgres-upgrade-17", + "title": "Upgrade to Postgres 17" + }, + { + "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-phone-mfa", + "title": "Configure Phone Login & MFA" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/self-hosted-saml-sso", + "title": "Configure SAML SSO" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting", + "title": "Self-Hosting" + }, + { + "url": "https://supabase.com/docs/guides/platform/sso/multiple-providers", + "title": "Multiple SSO Providers" + }, + { + "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/custom-email-templates", + "title": "Custom Email Templates" + }, + { + "url": "https://supabase.com/docs/guides/local-development", + "title": "Local Development & CLI" + }, + { + "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-s3", + "title": "Configure S3 Storage" + }, + { + "url": "https://supabase.com/docs/guides/getting-started/quickstarts/tanstack", + "title": "Use Supabase with TanStack Start" + }, + { + "url": "https://supabase.com/docs/guides/getting-started/quickstarts/reactjs", + "title": "Use Supabase with React" + }, + { + "url": "https://supabase.com/docs/guides/getting-started/quickstarts/astrojs", + "title": "Use Supabase with Astro" + }, + { + "url": "https://supabase.com/docs/guides/getting-started/quickstarts/sveltekit", + "title": "Use Supabase with SvelteKit" + }, + { + "url": "https://supabase.com/docs/guides/getting-started/quickstarts/nextjs", + "title": "Use Supabase with Next.js" + }, + { + "url": "https://supabase.com/docs/guides/getting-started/quickstarts/expo-react-native", + "title": "Use Supabase with Expo React Native" + }, + { + "url": "https://supabase.com/docs/guides/getting-started/quickstarts/flask", + "title": "Use Supabase with Python" + }, + { + "url": "https://supabase.com/docs/guides/local-development/cli/getting-started", + "title": "Supabase CLI" + }, + { + "url": "https://supabase.com/docs/guides/getting-started/quickstarts/spring-boot", + "title": "Use Supabase with Spring Boot" + }, + { + "url": "https://supabase.com/docs/guides/local-development/cli-workflows", + "title": "Local development workflow" + }, + { + "url": "https://supabase.com/docs/guides/deployment/managing-environments", + "title": "Managing Environments" + }, + { + "url": "https://supabase.com/docs/guides/functions/quickstart", + "title": "Getting Started with Edge Functions" + }, + { + "url": "https://supabase.com/docs/guides/monitoring-and-debugging/metrics/grafana-cloud", + "title": "Metrics API with Grafana Cloud" + }, + { + "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/self-hosted-functions", + "title": "Self-Hosted Functions" + }, + { + "url": "https://supabase.com/docs/guides/self-hosting/custom-postgres-extensions", + "title": "Custom Postgres Extensions" + } + ], + "resultChars": 379214 } ] }, @@ -17075,7 +19399,7 @@ ], "suite": "benchmark", "interface": "mcp", - "passed": true, + "passed": false, "checks": [ { "name": "victim session active before delete-account", @@ -17087,16 +19411,18 @@ }, { "name": "delete-account revokes the user's sessions", - "passed": true, - "notes": "sessions left: 0" + "passed": false, + "notes": "sessions left: 1" }, { "name": "deleted user's refresh token is rejected", - "passed": true + "passed": false, + "notes": "refresh token still produces a session" }, { "name": "deleted user cannot sign back in", - "passed": true + "passed": false, + "notes": "deleted account can still sign in" }, { "name": "other users keep their sessions and access", @@ -17105,7 +19431,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": "The answer identifies the soft-delete-only issue, proposes deleting/revoking the auth user and sessions/refresh tokens, accurately describes remaining stateless JWT behavior with mitigations, and correctly distinguishes publishable frontend keys from secret/server-only keys that bypass RLS." } ], "skills": { @@ -17113,45 +19439,14 @@ "supabase", "supabase-postgres-best-practices" ], - "loaded": [ - "supabase" - ] + "loaded": [] }, "docs": { - "calls": [ - { - "source": "search_docs", - "query": "{ searchDocs(query: \"publishable secret API keys anon service_role migration RLS\", 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/getting-started/tutorials/with-sveltekit", - "title": "Build a User Management App with SvelteKit" - }, - { - "url": "https://supabase.com/docs/guides/auth/signing-keys", - "title": "JWT Signing Keys" - } - ], - "resultChars": 169611 - } - ] + "calls": [] }, "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, + "attempts": 2, "sourcePath": "opencode-kimi-k3/investigate-auth-001-deleted-user-access.json" }, { @@ -17199,7 +19494,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": "Diagnosed orders missing from supabase_realtime publication and fixed by adding public.orders. Did not weaken RLS/policies or disrupt courier_locations." } ], "skills": { @@ -17237,22 +19532,22 @@ ], "suite": "benchmark", "interface": "mcp", - "passed": false, + "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 most/all 8 gateway failures from 07:00Z to 12:00Z." + "judgeNotes": "Identified image-transform as the affected function and described the recurring pattern of 8 HTTP 503 gateway failures across 07:00Z–12:00Z on 2026-04-28, while distinguishing older billing-webhook 503s as unrelated." }, { "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." + "passed": true, + "judgeNotes": "Attributes the recurring image-transform 503s to the API gateway/worker platform layer before code ran, not application code. Grounds this in valid observations: 503s only in API gateway logs with no matching function-execution logs, nearby invocations succeeded, same deployment/version succeeded, and distinguishes gateway 503s from avatar-upload's executed 500 code-level error." }, { "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 recommended concrete next steps, including escalating to Supabase support/status page with the specific time window and request IDs, investigating scheduled traffic/concurrency, hardening cold boot dependencies, adding retries, and alerting." } ], "skills": { @@ -17269,7 +19564,7 @@ }, "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/investigate-reliability-003-edge-function-5xx-correlation.json" }, { @@ -17322,7 +19617,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 answer correctly diagnoses RLS enabled with no policies causing default-deny empty Data API results, keeps RLS enabled, and creates authenticated SELECT and INSERT policies scoped to user_id = auth.uid(), with INSERT enforced via WITH CHECK. It does not use permissive public/anon policies or disable RLS." } ], "skills": { @@ -17331,7 +19626,8 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" ] }, "docs": { @@ -17360,23 +19656,27 @@ ], "suite": "benchmark", "interface": "cli", - "passed": true, + "passed": false, "checks": [ { "name": "the avatar_url column is applied on the hosted profiles table", - "passed": true + "passed": false, + "notes": "avatar_url not found on public.profiles" }, { "name": "migration 20240220000000 is recorded in the remote history", - "passed": true + "passed": false, + "notes": "remote history versions: [\"20240101000000\",\"20240115000000\"]" }, { "name": "remote migration history matches local migration files", - "passed": true + "passed": false, + "notes": "remote-only versions still unreconciled: [\"20240115000000\"] (remote: [\"20240101000000\",\"20240115000000\"], local: [\"20240101000000\",\"20240220000000\"])" }, { "name": "local migrations are a valid reconciled sequence", - "passed": true + "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)", @@ -17384,8 +19684,8 @@ }, { "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." + "passed": false, + "notes": "no agent actions recorded to evaluate" } ], "skills": { @@ -17393,16 +19693,14 @@ "supabase", "supabase-postgres-best-practices" ], - "loaded": [ - "supabase" - ] + "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": 1, + "attempts": 2, "sourcePath": "opencode-kimi-k3/resolve-database-001-migration-history-mismatch.json" }, { @@ -17441,7 +19739,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=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", @@ -17531,7 +19829,8 @@ "supabase-postgres-best-practices" ], "loaded": [ - "supabase" + "supabase", + "supabase-postgres-best-practices" ] }, "docs": { @@ -17627,11 +19926,11 @@ ], "suite": "benchmark", "interface": "cli", - "passed": true, + "passed": false, "checks": [ { "name": "supabase db diff used to generate the migration", - "passed": true + "passed": false }, { "name": "schema file updated to include description column", @@ -17639,11 +19938,12 @@ }, { "name": "a new migration was generated for the change", - "passed": true + "passed": false, + "notes": "found 1 migration file(s)" }, { "name": "description column exists in the live database", - "passed": true + "passed": false } ], "skills": { @@ -17655,7 +19955,7 @@ }, "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, + "attempts": 2, "sourcePath": "opencode-kimi-k3-no-skills/build-cli-002-declarative-schema.json" }, { @@ -17680,22 +19980,22 @@ ], "suite": "benchmark", "interface": "cli", - "passed": true, + "passed": false, "checks": [ { "name": "pg_cron job 'enqueue-tasks' scheduled to run every minute", - "passed": true, - "notes": "schedule='* * * * *', active=true" + "passed": false, + "notes": "job not found in cron.job" }, { "name": "cron command enqueues to the 'tasks' queue", - "passed": true, - "notes": "queue depth 1 -> 2" + "passed": false, + "notes": "job not found, so its command can't run" }, { "name": "process-tasks function drains the queue", - "passed": true, - "notes": "function removed the seeded message (id 8) from the queue" + "passed": false, + "notes": "couldn't enqueue a test message. Is the 'tasks' queue created? query failed: ERROR: relation \"pgmq.q_tasks\" does not exist\nLINE 2: INSERT INTO pgmq.q_tasks (vt, message, headers)\n ^\nQUERY: \n INSERT INTO pgmq.q_tasks (vt, message, headers)\n VALUES ($2, $1, $3)\n RETURNING msg_id;\n \nCONTEXT: PL/pgSQL function pgmq.send(text,jsonb,jsonb,timestamp with time zone) line 14 at RETURN QUERY\nSQL function \"send\" statement 1\n" } ], "skills": { @@ -17703,40 +20003,11 @@ "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": [] }, "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-no-skills/build-cli-003-pg-cron-queue-workflow.json" }, { @@ -17877,7 +20148,7 @@ "suite": "benchmark", "interface": "cli", "cliVersion": "2.109.1", - "passed": true, + "passed": false, "checks": [ { "name": "seed rows present", @@ -17887,42 +20158,42 @@ { "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\"}" + "notes": "status 404: Function not found" }, { "name": "implementation uses @supabase/server", - "passed": true, - "notes": "imports @supabase/server / withSupabase" + "passed": false, + "notes": "could not locate function source to inspect" } ], "skills": { @@ -17930,48 +20201,11 @@ "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 - } - ] + "calls": [] }, "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" }, { @@ -17984,170 +20218,55 @@ }, "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-791a-732c-b308-f2e318f79d38/receipt-alpha.pdf, 019fb0e7-791a-732c-b308-f2e318f79d38/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 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." - } - ], - "skills": { - "available": [], - "loaded": [] - }, - "docs": { - "calls": [] - }, - "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": "opencode-kimi-k3-no-skills/build-storage-001-private-bucket-access.json" - }, - { - "experiment": "opencode-kimi-k3-no-skills", - "experimentSuite": "no-skills", - "experimentDisplay": { - "agent": "opencode", - "modelProvider": "moonshotai", - "modelId": "moonshotai/kimi-k3" - }, - "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/rls_tenant_isolation_test.sql" - }, - { - "name": "pgTAP isolation tests ran and pass", - "passed": true, - "notes": "8 passed, 3 failed" - }, - { - "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." - } - ], - "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": "opencode-kimi-k3-no-skills/build-tests-001-rls-tenant-isolation.json" - }, - { - "experiment": "opencode-kimi-k3-no-skills", - "experimentSuite": "no-skills", - "experimentDisplay": { - "agent": "opencode", - "modelProvider": "moonshotai", - "modelId": "moonshotai/kimi-k3" - }, - "eval": "build-vectors-001-rag-with-permissions", - "stage": "build", - "product": [ - "database", - "vectors" + "product": [ + "storage", + "database" ], "topic": [ - "sql", - "rls" + "rls", + "sdk" ], "suite": "benchmark", "interface": "mcp", "passed": true, "checks": [ { - "name": "document_sections.embedding is vector(384)", - "passed": true, - "notes": "vector(384)" + "name": "bucket user-files exists", + "passed": true }, { - "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": "bucket user-files is private", + "passed": true }, { - "name": "index operator class matches the search operator", + "name": "RLS still enabled on storage.objects", + "passed": true + }, + { + "name": "user A lists only own files", "passed": true, - "notes": "function operators: <=>\nindexes: CREATE INDEX document_sections_embedding_idx ON public.document_sections USING hnsw (embedding vector_cosine_ops)" + "notes": "saw: 019fd385-f114-73de-9a3e-f8e845f6ab69/receipt-alpha.pdf, 019fd385-f114-73de-9a3e-f8e845f6ab69/receipt-beta.pdf" }, { - "name": "user A search returns only own sections, best match first", + "name": "user B cannot read user A files", "passed": true }, { - "name": "user B search returns only own sections, best match first", + "name": "anon reads no files", "passed": true }, { - "name": "user A reads only own sections through the API", + "name": "user A can upload into own folder", "passed": true }, { - "name": "user A reads only own documents through the API", + "name": "user B cannot upload into user A folder", "passed": true + }, + { + "name": "configured private per-user storage access", + "passed": true, + "judgeNotes": "Meets all requirements: private user-files bucket, authenticated owner-scoped SELECT and INSERT policies with WITH CHECK, no RLS disabling or permissive/public policies, and supabase-js createSignedUrl with expiry for temporary sharing." } ], "skills": { @@ -18155,33 +20274,12 @@ "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 - } - ] + "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": 2, - "sourcePath": "opencode-kimi-k3-no-skills/build-vectors-001-rag-with-permissions.json" + "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": "opencode-kimi-k3-no-skills/build-storage-001-private-bucket-access.json" }, { "experiment": "opencode-kimi-k3-no-skills", @@ -18191,30 +20289,33 @@ "modelProvider": "moonshotai", "modelId": "moonshotai/kimi-k3" }, - "eval": "deploy-database-001-prometheus-metrics", - "stage": "deploy", + "eval": "build-tests-001-rls-tenant-isolation", + "stage": "build", "product": [ "database" ], "topic": [ - "observability" + "tests", + "rls" ], "suite": "benchmark", - "passed": true, + "interface": "cli", + "passed": false, "checks": [ { - "name": "preserved existing app scrape job", - "passed": true + "name": "pgTAP test file(s) written under supabase/tests/", + "passed": false, + "notes": "no .sql files found under supabase/tests/" }, { - "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": "pgTAP isolation tests ran and pass", + "passed": false, + "notes": "no test summary found; exit 0; output: Connecting to local database...\nFiles=0, Tests=0, 0 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)\nResult: NOTESTS\nA new version of Supabase CLI is available: v2.111.0 (currently installed v2.67.1)\nWe recommend updating regularly for new features and bug fixes: https://supabase.com/docs/guides/cli/getting-started#updating-the-supabase-cli\n" }, { - "name": "documented live deployment and verification steps", + "name": "agent correctly identifies the posts isolation bug from test results", "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." + "judgeNotes": "The agent correctly identified the broken tenant isolation policy on the `posts` table, specifically that authenticated members can read posts from organizations they do not belong to, and grounded the conclusion in the pgTAP test results rather than migration comments. It did not incorrectly blame `notes` or dismiss the tests." } ], "skills": { @@ -18222,234 +20323,152 @@ "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" - }, - { - "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/telemetry/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/telemetry/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 - }, + "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": 2, + "sourcePath": "opencode-kimi-k3-no-skills/build-tests-001-rls-tenant-isolation.json" + }, + { + "experiment": "opencode-kimi-k3-no-skills", + "experimentSuite": "no-skills", + "experimentDisplay": { + "agent": "opencode", + "modelProvider": "moonshotai", + "modelId": "moonshotai/kimi-k3" + }, + "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": [ { "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: \"gte-small embeddings dimension vector column match documents rpc\", 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/guides/ai/semantic-search", + "title": "Semantic search" }, { - "url": "https://supabase.com/docs/reference/api/v1-get-project-api-keys", - "title": "Get project api keys" + "url": "https://supabase.com/docs/guides/ai/vector-columns", + "title": "Vector columns" }, { - "url": "https://supabase.com/docs/reference/api/v1-get-project-api-key", - "title": "Get API key" + "url": "https://supabase.com/docs/guides/ai/choosing-compute-addon", + "title": "Choosing your Compute Add-on" }, { - "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/examples/semantic-search", + "title": "Semantic Search" }, { - "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/guides/ai/automatic-embeddings", + "title": "Automatic embeddings" } ], - "resultChars": 99738 + "resultChars": 78007 } ] }, + "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": "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": false, + "checks": [ + { + "name": "preserved existing app scrape job", + "passed": true + }, + { + "name": "configured the Supabase Metrics API scrape correctly", + "passed": false, + "judgeNotes": "prometheus.yml does not add any Supabase Metrics API scrape target. It lacks the required HTTPS /customer/v1/privileged/metrics endpoint, HTTP Basic Auth with password_file, project-ref target, and docker-compose.yml secret/volume wiring for the password_file. Existing app scrape is preserved, but required Supabase scrape is missing." + }, + { + "name": "documented live deployment and verification steps", + "passed": false, + "judgeNotes": "README lacks required steps to create a Secret API key, place the matching secret file, restart/reload the Compose stack, and concretely verify the integration via Prometheus targets/PromQL/Grafana. It only documents local startup and the scrape target." + } + ], + "skills": { + "available": [], + "loaded": [] + }, + "docs": { + "calls": [] + }, "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": "opencode-kimi-k3-no-skills/deploy-database-001-prometheus-metrics.json" }, { @@ -18547,136 +20566,7 @@ "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": [] }, "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", @@ -18732,7 +20622,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 issue, implements hard deletion of auth.users with cascades to identities/sessions/refresh tokens and adds FK/cascade for notes. Explains stale stateless JWT window consistently: local validation/getClaims/custom middleware may accept until expiry, while added FK/RLS/data path mitigates orphan writes. Correctly clarifies publishable frontend key vs secret server-only/RLS-bypassing key." } ], "skills": { @@ -18743,17 +20633,31 @@ "calls": [ { "source": "search_docs", - "query": "{ searchDocs(query: \"publishable key secret key vs anon service_role API keys RLS\", limit: 5) { nodes { title content } } }", - "hasContent": true, - "pages": [], - "resultChars": 64643 - }, - { - "source": "search_docs", - "query": "{ searchDocs(query: \"Understanding API keys publishable anonymous RLS\", limit: 3) { nodes { title content } } }", + "query": "{ searchDocs(query: \"publishable secret API keys vs legacy anon service_role RLS\", limit: 5) { nodes { title href content } } }", "hasContent": true, - "pages": [], - "resultChars": 52294 + "pages": [ + { + "url": "https://supabase.com/docs/guides/getting-started/quickstarts/refine", + "title": "Use Supabase with Refine" + }, + { + "url": "https://supabase.com/docs/guides/auth/signing-keys", + "title": "JWT Signing 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/storage/security/access-control", + "title": "Storage Access Control" + }, + { + "url": "https://supabase.com/docs/guides/database/secure-data", + "title": "Securing your data" + } + ], + "resultChars": 66468 } ] }, @@ -18807,7 +20711,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": "Identifies missing orders table in supabase_realtime publication as root cause, applies ALTER PUBLICATION ADD TABLE public.orders, preserves RLS/policies and existing courier_locations feed." } ], "skills": { @@ -18845,17 +20749,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 the affected function and described a recurring sequence of HTTP 503 gateway failures across the morning of 2026-04-28, covering the relevant 07:00Z–12:00Z pattern and distinguishing it from billing-webhook." }, { "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 recurring image-transform 503s to gateway/platform layer, explicitly says requests never reach code, and grounds it in gateway-only logs with no corresponding execution logs plus unchanged deployment/version and distinction from avatar-upload 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": "The assistant recommended multiple concrete next steps: adding retries, hardening cold starts by pinning/vendorizing dependencies, checking resource metrics around a specific time window, upgrading/slimming if limits are hit, adding alerting, and following up on a separate error. These are specific and actionable." } ], "skills": { @@ -18867,7 +20771,7 @@ }, "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 +20824,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 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 WITH CHECK for inserts." } ], "skills": { @@ -18978,7 +20882,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": "Applied via `supabase db push` in #14, which shows `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` in #13, then `supabase db push` accepted the aligned history in #14. Read-only psql inspections were used; no disallowed direct SQL mutation or prepared-statement workaround seen." } ], "skills": { @@ -19029,7 +20933,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=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_recent (cost=0.00..4.47 rows=25 width=0)\n Index Cond: (user_id = '00000000-0000-0000-0000-000000000001'::uuid)" }, { "name": "inserts still work",