diff --git a/supabase/migrations/20260613000001_add_admin_utility_usage_fn.sql b/supabase/migrations/20260613000001_add_admin_utility_usage_fn.sql index f3d82c0..9a817de 100644 --- a/supabase/migrations/20260613000001_add_admin_utility_usage_fn.sql +++ b/supabase/migrations/20260613000001_add_admin_utility_usage_fn.sql @@ -1,3 +1,32 @@ +-- public.is_admin() predates this migration history — it was defined straight +-- in the production database — so a database built from these files alone does +-- not have it. This is the first migration that mentions it, and the guard sits +-- here rather than at the first migration that *breaks* because the two are not +-- the same place: a reference inside a function body resolves when the function +-- runs, while a policy's USING expression resolves as the policy is created. So +-- this file applied cleanly on a fresh database and 20260702000000 was the one +-- that failed, which is why preview branches have been erroring on +-- "function public.is_admin() does not exist" since July. +-- +-- Create a deny-all stub only when the function is missing: production keeps +-- its real definition, anything built from scratch gets a safe default where +-- nobody is an admin. +do $$ +begin + if not exists ( + select 1 + from pg_proc p + join pg_namespace n on n.oid = p.pronamespace + where n.nspname = 'public' and p.proname = 'is_admin' + ) then + create function public.is_admin() + returns boolean + language sql + stable + as 'select false'; + end if; +end $$; + -- Admin-only per-user utility usage breakdown. Joins usage rows with profile -- identity so an admin can see who launched what. Guarded by is_admin(); -- SECURITY DEFINER is required to read across all users past RLS. diff --git a/supabase/migrations/20260720000000_create_client_error_log.sql b/supabase/migrations/20260720000000_create_client_error_log.sql index 9d52625..f1ede04 100644 --- a/supabase/migrations/20260720000000_create_client_error_log.sql +++ b/supabase/migrations/20260720000000_create_client_error_log.sql @@ -6,10 +6,10 @@ -- identity — only the error itself and non-identifying context (route, tool, -- user agent, locale). Only admins may read; nobody may update or delete. -- public.is_admin() predates the migration history (defined directly in the --- production database), so fresh preview branches don't have it and every --- policy referencing it fails. Create a deny-all stub only when the function --- is missing: production keeps its real definition, preview branches get a --- safe default (nobody is admin). +-- production database), so a database built from these files alone does not +-- have it. The stub now goes up in 20260613000001, the first migration that +-- mentions the function at all; this block stays because it is already part of +-- applied history, and it no-ops once the earlier one has run. do $$ begin if not exists (