fix(db): guard DDL on out-of-band (orphan) tables for clean replay #333
Supabase / Supabase Preview
failed
May 25, 2026 in 2m 58s
Supabase Preview
ERROR: column q.assigned_to does not exist (SQLSTATE 42703)
At statement: 0
-- =================================================================
-- Onda 18a: Isolamento de orcamentos por vendedor (audit gap 6.1 redirecionado)
--
-- Regra de negocio (Joaquim PO):
-- - VENDEDOR/AGENTE: ve SO os PROPRIOS orcamentos (seller_id ou created_by ou assigned_to = self)
-- - SUPERVISOR/COORDENADOR: ve TODOS os orcamentos (via is_coord_or_above)
-- - ADMIN: ve tudo (incluido no is_coord_or_above por decisao Q1=A)
-- - DEV: ve tudo (incluido no is_coord_or_above)
--
-- Antes desta migration: qualquer membro da org via TODOS os orcamentos
-- (gap concreto: comercial03@/comercial05@ viam quotes do adm01@ que NAO eram suas)
--
-- Tabelas afetadas: quotes, quote_items, quote_comments, quote_versions
-- DELETE de quotes mantem is_org_owner_or_admin (controle org-level distinto)
-- INSERT de quotes mantem user_is_org_member (qualquer membro pode criar)
-- =================================================================
-- 1. NOVA FUNCAO: can_access_quote(quote_id)
-- Encapsula logica em SSOT, SECURITY DEFINER pra evitar recursao RLS
CREATE OR REPLACE FUNCTION public.can_access_quote(_quote_id uuid)
RETURNS boolean
LANGUAGE sql
STABLE
SECURITY DEFINER
SET search_path TO 'public'
AS $$
SELECT EXISTS (
SELECT 1 FROM public.quotes q
WHERE q.id = _quote_id
AND user_is_org_member(q.organization_id)
AND (
is_coord_or_above(auth.uid())
OR q.seller_id = auth.uid()
OR q.created_by = auth.uid()
OR q.assigned_to = auth.uid()
^
Loading