diff --git a/supabase/migrations/20260524210002_harden_password_reset_requests_rls.sql b/supabase/migrations/20260524210002_harden_password_reset_requests_rls.sql index 16c4a9813..fb79ba9a9 100644 --- a/supabase/migrations/20260524210002_harden_password_reset_requests_rls.sql +++ b/supabase/migrations/20260524210002_harden_password_reset_requests_rls.sql @@ -40,9 +40,12 @@ COMMENT ON INDEX public.password_reset_requests_one_pending_per_email IS 'Anti-spam: máximo 1 solicitação pendente por email (case-insensitive). ' 'Conflict 23505 sinaliza ao app "já existe pedido aguardando revisão".'; --- 3) Drop policy permissiva atual +-- 3) Drop policy permissiva atual (nome antigo + novo p/ replay idempotente: +-- em prod a policy validada já existe, então dropamos antes de recriar) DROP POLICY IF EXISTS "Anyone can request a password reset" ON public.password_reset_requests; +DROP POLICY IF EXISTS "Anyone can request a password reset (validated)" + ON public.password_reset_requests; -- 4) Recria policy com validação defensiva CREATE POLICY "Anyone can request a password reset (validated)" diff --git a/supabase/migrations/20260524210300_kill_switches_fk_index_and_policy_consolidation.sql b/supabase/migrations/20260524210300_kill_switches_fk_index_and_policy_consolidation.sql index a9be0b3d1..22bd03036 100644 --- a/supabase/migrations/20260524210300_kill_switches_fk_index_and_policy_consolidation.sql +++ b/supabase/migrations/20260524210300_kill_switches_fk_index_and_policy_consolidation.sql @@ -19,18 +19,22 @@ CREATE INDEX IF NOT EXISTS idx_system_kill_switches_updated_by ON public.system_kill_switches (updated_by); --- 2) Consolidação de policies +-- 2) Consolidação de policies (DROP IF EXISTS antes de cada CREATE p/ replay +-- idempotente: em prod as policies admin já existem) DROP POLICY IF EXISTS kill_switches_write_admin ON public.system_kill_switches; +DROP POLICY IF EXISTS kill_switches_insert_admin ON public.system_kill_switches; CREATE POLICY kill_switches_insert_admin ON public.system_kill_switches FOR INSERT TO authenticated WITH CHECK (public.is_admin_or_above((SELECT auth.uid()))); +DROP POLICY IF EXISTS kill_switches_update_admin ON public.system_kill_switches; CREATE POLICY kill_switches_update_admin ON public.system_kill_switches FOR UPDATE TO authenticated USING (public.is_admin_or_above((SELECT auth.uid()))) WITH CHECK (public.is_admin_or_above((SELECT auth.uid()))); +DROP POLICY IF EXISTS kill_switches_delete_admin ON public.system_kill_switches; CREATE POLICY kill_switches_delete_admin ON public.system_kill_switches FOR DELETE TO authenticated USING (public.is_admin_or_above((SELECT auth.uid()))); diff --git a/supabase/migrations/20260525063000_restore_smoke_test_observability_contract.sql b/supabase/migrations/20260525063000_restore_smoke_test_observability_contract.sql index e0f3c6c5a..0867d93f2 100644 --- a/supabase/migrations/20260525063000_restore_smoke_test_observability_contract.sql +++ b/supabase/migrations/20260525063000_restore_smoke_test_observability_contract.sql @@ -70,7 +70,11 @@ $function$; REVOKE ALL ON FUNCTION public.fn_run_and_persist_smoke_tests() FROM PUBLIC; GRANT EXECUTE ON FUNCTION public.fn_run_and_persist_smoke_tests() TO authenticated; -CREATE OR REPLACE VIEW public.v_smoke_tests_latest_run +-- DROP+CREATE (não OR REPLACE): em prod a view já existe com colunas count(*) +-- em bigint; CREATE OR REPLACE não pode mudar o tipo p/ integer. DROP recria +-- limpo (nada depende destas views — verificado em pg_depend). +DROP VIEW IF EXISTS public.v_smoke_tests_latest_run; +CREATE VIEW public.v_smoke_tests_latest_run WITH (security_invoker = on) AS SELECT ran_at, @@ -89,7 +93,8 @@ ORDER BY END, test_name; -CREATE OR REPLACE VIEW public.v_smoke_tests_trend +DROP VIEW IF EXISTS public.v_smoke_tests_trend; +CREATE VIEW public.v_smoke_tests_trend WITH (security_invoker = on) AS SELECT ran_at,