Files
agenciapsilmno/database-novo/migrations/20260419000017_addons_central_saas_hardening.sql
T
Leonardo d6eb992f71 Sessoes 6cont-10: hardening em 6 areas + scan completo do SaaS
Continuacao de 7c20b51. Esta etapa fechou TODA revisao senior do SaaS
(15 areas auditadas) + refator parcial de pacientes.

Ver commit.md para descricao completa por sessao.

# Estado final do projeto
- A# auditoria abertos: 1 (A#31 Deploy real)
- V# verificacoes abertos: 14 (todos medios/baixos adiados com plano)
- Criticos: 0
- Altos: 0
- Vitest: 208/208 (era 192, +16 nos novos composables)
- SQL integration: 33/33
- E2E (Playwright): 5/5
- Areas auditadas: 15

# Highlights
- Documentos 100% fechado (V#50/51/52: portal-paciente policy + content_sha256 + 4 cron jobs retention)
- Tenants V#1 P0: tenant_invites com RLS off + 0 policies (mesmo padrao A#30)
- Calendario 100% fechado: feriados WITH CHECK
- Addons V#1 P0 (dinheiro): addon_transactions WITH CHECK saas_admin
- Central SaaS V#1: faq write so saas_admin (era tenant_admin)
- Servicos/Prontuarios 100% fechado: services/medicos/insurance_plans + cascades
- Pacientes V#9: 2 composables novos (useCep, usePatientSupportContacts) + repo estendido + script extraido (template intocado, fica para quando houver E2E)

# 8 migrations novas neste commit
- 20260419000011_documents_portal_patient_policy.sql
- 20260419000012_documents_content_hash.sql
- 20260419000013_cron_retention_jobs.sql
- 20260419000014_financial_security_hardening.sql
- 20260419000015_communication_security_hardening.sql
- 20260419000016_tenants_calendario_hardening.sql
- 20260419000017_addons_central_saas_hardening.sql
- 20260419000018_servicos_prontuarios_hardening.sql

Total acumulado: 18 migrations (Sessoes 1-10).

# A#31 reformulado pra proxima sessao
"Deploy real" muda escopo: como nao ha cloud Supabase nem secrets reais
ainda (MVP), proxima sessao vira "Preparacao completa pra deploy" (DEPLOY.md,
validar migrations num container limpo, audit edge functions, listar env vars,
script db.cjs deploy-check).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 22:00:06 -03:00

66 lines
3.3 KiB
SQL

-- =============================================================================
-- Migration: 20260419000017_addons_central_saas_hardening
-- Sessão 8 — Addons + Central SaaS scan.
--
-- Resolve:
-- • Addons V#1 (CRÍTICO — dinheiro real): addon_transactions sem WITH CHECK
-- • Addons V#2: addon_credits sem CHECK contra saldo negativo
-- • Central SaaS V#1: saas_faq write permite tenant_admin/clinic_admin
--
-- Auditoria prévia: 0 addon_credits com balance < 0 (seguro CHECK).
-- Edge functions consomem créditos via service_role (bypass RLS) — nova
-- restrição não quebra pipeline.
-- =============================================================================
-- ─────────────────────────────────────────────────────────────────────────
-- Addons V#1: addon_transactions INSERT WITH CHECK (saas_admin only)
-- -----------------------------------------------------------------------------
DROP POLICY IF EXISTS addon_transactions_admin_insert ON public.addon_transactions;
CREATE POLICY addon_transactions_admin_insert ON public.addon_transactions
FOR INSERT TO authenticated
WITH CHECK (
EXISTS (SELECT 1 FROM public.saas_admins sa WHERE sa.user_id = auth.uid())
);
-- ─────────────────────────────────────────────────────────────────────────
-- Addons V#2: addon_credits CHECK contra saldo negativo
-- -----------------------------------------------------------------------------
ALTER TABLE public.addon_credits
DROP CONSTRAINT IF EXISTS addon_credits_balance_nonneg_chk;
ALTER TABLE public.addon_credits
ADD CONSTRAINT addon_credits_balance_nonneg_chk
CHECK (balance >= 0);
-- Aproveita: total_consumed também não deve ser negativo
ALTER TABLE public.addon_credits
DROP CONSTRAINT IF EXISTS addon_credits_consumed_nonneg_chk;
ALTER TABLE public.addon_credits
ADD CONSTRAINT addon_credits_consumed_nonneg_chk
CHECK (total_consumed >= 0);
ALTER TABLE public.addon_credits
DROP CONSTRAINT IF EXISTS addon_credits_purchased_nonneg_chk;
ALTER TABLE public.addon_credits
ADD CONSTRAINT addon_credits_purchased_nonneg_chk
CHECK (total_purchased >= 0);
-- ─────────────────────────────────────────────────────────────────────────
-- Central SaaS V#1: saas_faq + saas_faq_itens write SÓ saas_admin
-- -----------------------------------------------------------------------------
DROP POLICY IF EXISTS faq_admin_write ON public.saas_faq;
CREATE POLICY faq_saas_admin_write ON public.saas_faq
FOR ALL TO authenticated
USING (public.is_saas_admin())
WITH CHECK (public.is_saas_admin());
DROP POLICY IF EXISTS faq_itens_admin_write ON public.saas_faq_itens;
CREATE POLICY faq_itens_saas_admin_write ON public.saas_faq_itens
FOR ALL TO authenticated
USING (public.is_saas_admin())
WITH CHECK (public.is_saas_admin());
-- (Policies de leitura — faq_auth_read, faq_public_read, faq_itens_auth_read — permanecem)