d6eb992f71
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>
177 lines
8.9 KiB
Markdown
177 lines
8.9 KiB
Markdown
# 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)
|