-- ============================================================================ -- RLS policies do prontuário clínico -- ---------------------------------------------------------------------------- -- Padrão MAIS RESTRITIVO que agenda — CFP exige sigilo profissional entre -- terapeutas do mesmo tenant. Default: APENAS o owner (terapeuta responsável) -- lê e escreve. Sem clinic-wide read. -- -- Compartilhamento com supervisor / outro terapeuta vai requerer policy -- específica baseada em tabela `clinical_note_shares` (Fase 2). -- -- Templates seguem regra mais aberta: -- • Sistema (is_system): todos authenticated leem -- • Tenant-wide (tenant_id): membros do tenant leem; tenant_admin edita -- • Owner: só o owner lê/edita -- ============================================================================ BEGIN; -- ────────────────────────────────────────────────────────────────────────── -- clinical_notes — owner only -- ────────────────────────────────────────────────────────────────────────── ALTER TABLE public.clinical_notes ENABLE ROW LEVEL SECURITY; CREATE POLICY clinical_notes_owner_select ON public.clinical_notes FOR SELECT TO authenticated USING (owner_id = auth.uid() AND deleted_at IS NULL); CREATE POLICY clinical_notes_owner_insert ON public.clinical_notes FOR INSERT TO authenticated WITH CHECK ( owner_id = auth.uid() AND public.is_tenant_member(tenant_id) ); CREATE POLICY clinical_notes_owner_update ON public.clinical_notes FOR UPDATE TO authenticated USING (owner_id = auth.uid()) WITH CHECK (owner_id = auth.uid()); -- DELETE só por soft-delete (UPDATE deleted_at). Hard delete bloqueado em RLS. -- Backup/admin pode dropar via psql -U supabase_admin se preciso. CREATE POLICY clinical_notes_no_hard_delete ON public.clinical_notes FOR DELETE TO authenticated USING (false); -- ────────────────────────────────────────────────────────────────────────── -- clinical_note_versions — read-only pelo owner da nota -- ────────────────────────────────────────────────────────────────────────── ALTER TABLE public.clinical_note_versions ENABLE ROW LEVEL SECURITY; CREATE POLICY clinical_note_versions_owner_select ON public.clinical_note_versions FOR SELECT TO authenticated USING ( EXISTS ( SELECT 1 FROM public.clinical_notes cn WHERE cn.id = clinical_note_versions.note_id AND cn.owner_id = auth.uid() ) ); -- INSERT só via trigger (SECURITY DEFINER). Sem policy de UPDATE/DELETE — -- versões são imutáveis. Trigger usa role bypass. CREATE POLICY clinical_note_versions_no_write ON public.clinical_note_versions FOR INSERT TO authenticated WITH CHECK (false); CREATE POLICY clinical_note_versions_no_update ON public.clinical_note_versions FOR UPDATE TO authenticated USING (false); CREATE POLICY clinical_note_versions_no_delete ON public.clinical_note_versions FOR DELETE TO authenticated USING (false); -- ────────────────────────────────────────────────────────────────────────── -- clinical_note_templates — escopo escalonado -- ────────────────────────────────────────────────────────────────────────── ALTER TABLE public.clinical_note_templates ENABLE ROW LEVEL SECURITY; -- SELECT: sistema (qualquer authenticated) + tenant-wide (membros) + owner (próprio) CREATE POLICY clinical_note_templates_select ON public.clinical_note_templates FOR SELECT TO authenticated USING ( active = true AND ( is_system = true OR (tenant_id IS NOT NULL AND public.is_tenant_member(tenant_id)) ) ); -- INSERT/UPDATE/DELETE: só owner ou tenant_admin do tenant -- Templates do sistema (is_system) nunca alteráveis via UI — só via seed/migration. CREATE POLICY clinical_note_templates_owner_write ON public.clinical_note_templates TO authenticated USING ( is_system = false AND ( owner_id = auth.uid() OR (owner_id IS NULL AND public.is_tenant_admin(tenant_id)) ) ) WITH CHECK ( is_system = false AND ( owner_id = auth.uid() OR (owner_id IS NULL AND public.is_tenant_admin(tenant_id)) ) ); COMMIT;