Skip to content

fix(db): guard DDL on out-of-band (orphan) tables for clean replay

ba5a589
Select commit
Loading
Failed to load commit list.
Closed

fix(db): guard DDL on out-of-band (orphan) tables for clean replay #333

fix(db): guard DDL on out-of-band (orphan) tables for clean replay
ba5a589
Select commit
Loading
Failed to load commit list.
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()
           ^