padronizacao: foundation Fase 0+0.5 — blueprints + auditoria + clinical_notes

Pre-MVP: 3 blueprints canonicos (repository, composable, quick-create
overlay), AUDIT_BASELINE com 51 divergencias em 6 modulos, estrategia
PADRONIZACAO de 4 fases, DESIGN_BILLING_ORCHESTRATOR. Schema clinical
notes pronto pra Fase B (4 migrations + seed templates). AgendaEvent
Dialog.vue.bak deletado (lixo de refator anterior).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Leonardo
2026-05-21 04:19:45 -03:00
parent 5b345c5598
commit f94a4ae97f
12 changed files with 2857 additions and 3522 deletions
@@ -0,0 +1,111 @@
-- ============================================================================
-- 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;