# Sessões 6 (continuação) → 10 — hardening em 6 áreas + scan completo do SaaS

Continuação do commit `7c20b51` (Sessões 1-6 iniciais). Esta etapa fechou
**toda revisão sênior do SaaS** + refator parcial de pacientes.

**Estado final do projeto:**
- A# auditoria abertos: **1** (A#31 Deploy real)
- V# verificações abertos: 14 (todos médios/baixos adiados com plano completo no DB)
- 🔴 Críticos: **0** ✅
- 🟠 Altos: **0** ✅
- Vitest: **208/208** (era 192)
- SQL integration: **33/33**
- E2E (Playwright): **5/5**
- Áreas auditadas: **15** (todas as principais do SaaS)

---

## Sessão 6 (continuação) — Documentos pendentes + Pacientes V#3

### Documentos: 100% fechado (V#50, V#51, V#52)
- **V#50** — Policy `documents: portal patient read` adicional. Paciente lê documento via portal quando `compartilhado_portal=true` AND patient pertence a auth.uid AND não expirou.
- **V#51** — `documents.content_sha256` (nullable, índice parcial). `Documents.service.uploadDocument` calcula SHA-256 hex client-side via `crypto.subtle.digest`. Helper novo `verifyDocumentIntegrity(docId)` baixa arquivo e re-hash.
- **V#52** — Migration `...13` cron retention via pg_cron: 4 jobs (document_access_logs 1 ano, math_challenges 1h, public_submission_attempts 90 dias, submission_rate_limits 30 dias).

### Pacientes V#3 (parcial — fundação)
- `src/features/patients/services/patientsRepository.js` — list/get/create/update/softDelete + groups + tags + getSessionCounts.
- `src/features/patients/composables/usePatients.js` — wrapper reativo (rows/loading/error).
- PatientsListPage.hydrateAssociationsSupabase migrada — substitui 4 queries diretas por chamadas ao repo (paralelismo preservado).
- V#9 (PatientsCadastroPage 1991 linhas) → adiado pra Sessão 10.

---

## Sessão 7 — Tenants + Calendário

### Tenants (8 V#)
- 🔴 **V#1 P0** — `tenant_invites` com RLS off + 0 policies (mesmo padrão A#30 Sessão 5). Tabela tinha 0 rows. Migration: ENABLE RLS + 4 policies (SELECT tenant_admin/saas; INSERT WITH CHECK invited_by=auth.uid; UPDATE só revogação; DELETE tenant_admin/saas). Aceitar invite continua via RPC `tenant_accept_invite` SECURITY DEFINER.
- 🟠 **V#2** profiles INSERT WITH CHECK (id = auth.uid)
- 🟠 **V#3** support_sessions INSERT WITH CHECK (admin_id = auth.uid + saas_admin guard)
- 🟡 **V#4 (signup público)** verificado: RPC `ensure_personal_tenant` SECURITY DEFINER já existia (Signup.vue:232) → **ok**
- 🟡 **V#5 (accept_invite)** verificado: RPCs `tenant_accept_invite` + `tenant_invite_member_by_email` já existiam → **ok**
- 🟡 **V#6** user_settings INSERT WITH CHECK
- 🟢 V#7/V#8 baixos — adiados

### Calendário (2 V#) — 100% fechado
- 🔴 **V#1** feriados_insert + feriados_saas_insert ganharam WITH CHECK. Spam de feriado global bloqueado.
- 🟢 **V#2** feriados_delete agora permite tenant_admin (não só owner).

---

## Sessão 8 — Addons + Central SaaS

### Addons (4 V#)
- 🔴 **V#1 P0 (dinheiro)** — `addon_transactions_admin_insert` ganhou WITH CHECK (EXISTS saas_admins). Edge functions com service_role bypassam RLS, pipeline preservado. **Authenticated comum não cria mais transação fake.**
- 🟠 **V#2** — 3 CHECK constraints em `addon_credits`: balance >= 0, total_consumed >= 0, total_purchased >= 0. Saldo negativo silencioso eliminado.
- 🟡 V#3 (UI extrato) — adiado.
- 🟡 V#4 — verificado: `addon_products` não tem `tenant_id` (catálogo global por design) → **ok**.

### Central SaaS (3 V#)
- 🟠 **V#1** — `faq_admin_write` substituído por `faq_saas_admin_write` em `saas_faq` E `saas_faq_itens` — só saas_admin escreve. Tenant_admin lê via `faq_auth_read` (permanece).
- 🟢 V#2/V#3 médios/baixos — adiados.

---

## Sessão 9 — Serviços/Prontuários (100% fechado)

5/5 V# corrigidos:
- 🔴 **V#1** services + insurance_plans → 4 policies separadas (SELECT tenant_member; INSERT/UPDATE/DELETE owner+saas).
- 🔴 **V#2** medicos → 4 policies separadas (catálogo de médicos referenciadores compartilhado entre profissionais do tenant).
- 🟠 **V#3** commitment_services — cascade reescrito via JOIN com services (USING permite tenant_member; WITH CHECK só owner).
- 🟠 **V#4** insurance_plan_services — cascade reescrito via JOIN com insurance_plans.
- 🟡 **V#5** commitment_time_logs/determined_commitments/determined_commitment_fields ganharam WITH CHECK em INSERT.

---

## Sessão 10 — Pacientes V#9 (script extraído)

PatientsCadastroPage.vue: 1991 → 1951 linhas (qualitativo > quantitativo).

### 2 composables novos
- **`useCep.js`** — busca ViaCEP reutilizável. 6 testes (sem rede, mock fetch).
- **`usePatientSupportContacts.js`** — CRUD de contatos de suporte encapsulado (load/save/add/remove/iniciaisFor). 10 testes com builder thenable.

### patientsRepository estendido
- `getPatientRelations(patientId)` — retorna {groupIds, tagIds}
- `replacePatientGroup(patientId, groupId, {tenantId})`
- `replacePatientTags(patientId, tagIds, {tenantId, ownerId})`

### PatientsCadastroPage refatorado
- 8 funções de query → delegação 1-linha ao patientsRepository
- onCepBlur → usa composable useCep
- Contatos de suporte → composable
- Template **não** foi tocado (zero risco de regressão visual)
- Quebra de template em sub-componentes Vue → adiado pra quando houver E2E cobrindo a página

---

## 📦 Migrations consolidadas neste commit (8)

```
20260419000011_documents_portal_patient_policy.sql      (V#50)
20260419000012_documents_content_hash.sql               (V#51)
20260419000013_cron_retention_jobs.sql                  (V#52 + math_challenges + submissions + rate_limits)
20260419000014_financial_security_hardening.sql         (5 V# financeiro — fechados na Sessão 6)
20260419000015_communication_security_hardening.sql     (5 V# comunicação — fechados na Sessão 6)
20260419000016_tenants_calendario_hardening.sql         (Tenants V#1-V#3,V#6 + Calendário V#1-V#2)
20260419000017_addons_central_saas_hardening.sql        (Addons V#1-V#2 + Central SaaS V#1)
20260419000018_servicos_prontuarios_hardening.sql       (Serviços V#1-V#5)
```

**Total acumulado de migrations no histórico: 18** (Sessões 1-10).

Várias dessas exigiram conexão direta como `supabase_admin` (ver memory `project_supabase_admin_gotcha.md` e `commit.md` anterior) por causa de tabelas owned por esse role.

---

## 🆕 Novos arquivos (código)

```
src/features/patients/composables/useCep.js
src/features/patients/composables/usePatientSupportContacts.js
src/features/patients/composables/usePatients.js
src/features/patients/composables/__tests__/useCep.spec.js                    (+6 testes)
src/features/patients/composables/__tests__/usePatientSupportContacts.spec.js (+10 testes)
src/features/patients/services/patientsRepository.js
```

---

## 🛠️ Modificações

- `src/features/patients/PatientsListPage.vue` — hydrateAssociationsSupabase usa repo
- `src/features/patients/cadastro/PatientsCadastroPage.vue` — script extraído (queries → repo, CEP → composable, contatos → composable). Template intocado.
- `src/services/Documents.service.js` — uploadDocument calcula content_sha256 + helper verifyDocumentIntegrity

---

## 📊 Áreas auditadas (estado final)

| Área | V# total | Estado |
|---|---|---|
| auth | 10 | 100% fechado/ok |
| router | 9 | 100% |
| stores | 1 | 100% |
| agenda | 11 | 100% |
| pacientes | 10 | **100% fechado** ✅ |
| seguranca | 1 | 100% |
| saas | 10 | 100% |
| documentos | 10 | **100% fechado** ✅ |
| financeiro | 11 | 5 fechados, 6 médios/baixos adiados |
| comunicacao | 10 | 5 fechados, 5 médios/baixos adiados |
| tenants | 8 | 6 fechados, 2 baixos adiados |
| calendario | 2 | **100% fechado** ✅ |
| addons | 4 | 3 resolvidos, 1 médio adiado |
| central_saas | 3 | 1 alto fechado, 2 médios adiados |
| servicos | 5 | **100% fechado** ✅ |

**Zero crítico/alto restante no sistema inteiro.**

---

## ⚠️ Pendências documentadas no DB (não esquecidas)

### A# (1 aberto)
- **A#31 Deploy real** — alto. Reformulação pendente: como ainda não há cloud Supabase nem secrets reais, próxima sessão é "Preparação completa pra deploy" (DEPLOY.md, validar migrations num container limpo, audit de edge functions, listar env vars, script `db.cjs deploy-check`).

### V# adiados (14)
Todos médios/baixos com plano completo em `dev_verificacoes_items.acao_sugerida`:
- financeiro (6): parcelamento CHECK, payouts flow, recurrence DELETE policy, composables, máscara PIX, dashboard inadimplência
- comunicacao (5): notifications/schedules silos, email_templates_global filtros, retention notification_logs, dashboard health, audit dismissals/preferences
- tenants (2): owner_users policies, company_profiles + dev_user_credentials
- central_saas (2): rate limit voto, valores tipo_acesso
- addons (1): UI de extrato

### Outros
- PatientsCadastroPage template breakdown — quando houver E2E
- Pacientes V#9 segue 100% no banco (script foi extraído; template é refator visual separado)
