diff --git a/docs/HANDOFF_E_TESTES.md b/docs/HANDOFF_E_TESTES.md new file mode 100644 index 0000000..3319d02 --- /dev/null +++ b/docs/HANDOFF_E_TESTES.md @@ -0,0 +1,157 @@ +# Handoff — Onde paramos, Riscos e Passo a passo de teste + +> Estado consolidado dos dois épicos grandes (schema-per-tenant + freemium/PLG). +> Última atualização: 2026-06-13. Branch de trabalho: **`feat/schema-per-tenant`** (base) +> e **`feat/freemium-plg`** (empilhada — contém tudo). `main` segue no modelo RLS antigo. + +--- + +## 1. Onde paramos (estado atual) + +### Branches +- `main` — modelo RLS-only (produção atual). Recebeu só F0/F1/F2 aditivos da schema-per-tenant. +- `feat/schema-per-tenant` — migração completa F0→F6.2 + wiring + F6.4. **F6.3 DROP NÃO aplicado.** +- `feat/freemium-plg` — **ramificada da schema-per-tenant**, contém TODO o freemium (F1/F2/F3) + + os dois runbooks de deploy + este handoff. **É a branch a deployar** (tem os dois épicos). + +### Banco LOCAL (Docker `supabase_db_agenciapsi-primesakai`) +Está no estado **schema-per-tenant + freemium aplicado**: +- Schemas `tenant_` existem (9 tenants clonados) + dados COPIADOS (espelho ainda em `public`). +- Todas as migrations + todos os `manual/*.supabase_admin.sql` aplicados, **EXCETO o F6.3 DROP**. +- `enable_confirmations` está `true` no `config.toml` mas **só ativa após reiniciar o stack**. + +### Schema-per-tenant — ✅ feito / ⏳ pendente +- ✅ Estrutura, helpers, template, clone/drop, provisionamento, 66 funções migradas, dados dos 9 tenants copiados+verificados, PostgREST dinâmico (local), frontend/edge roteando por schema. +- ⏳ **F6.3 DROP** (remove o espelho em `public`) — preparado, NÃO aplicado. Aguarda teste no browser + OK + backup fresco. (task #7) +- 📄 Deploy: `docs/DEPLOY_SCHEMA_PER_TENANT.md`. + +### Freemium/PLG — ✅ feito / ⏳ pendente +- ✅ **F1** limite de pacientes (trigger runtime + toast + Upgrade PRO). +- ✅ **F2** self-service (confirmação de e-mail, RPCs idempotentes, signup reescrito, /onboarding, + welcome email, vitrine "Grátis") + **fix de regressão** do audit em `tenant_members`. +- ✅ **F3** 4 extras (blacklist, /saas/usuarios + notify devs, esqueci-email, root_redirect). +- ⏳ **F4 deploy** (hosted) — runbook em `docs/DEPLOY_FREEMIUM_F4.md`. Não deployado. +- ⏳ **Teste local ponta-a-ponta** — exige reiniciar o stack (seção 3). + +### Tudo commitado e pushado em `feat/freemium-plg`. Nada pendente no working tree +(só `.env`/dashboard/`.claude` locais, intencionalmente fora). + +--- + +## 2. Riscos (todos) + +### 🔴 Críticos +1. **PostgREST dinâmico no hosted** — a exposição de schemas tenant usa `ALTER ROLE + authenticator SET pgrst.db_schemas`. Pode ser restrito no hosted. Se falhar, o app novo + recebe 404 nas tabelas tenant. **Testar cedo** (Fase C do runbook); fallback = Exposed + schemas no dashboard (estático → problema com signup self-service). **Decidir antes de + abrir signup.** +2. **F6.3 DROP é irreversível** — remove as tabelas tenant de `public`. Só após dias de soak + no modelo novo + backup fresco. Rollback = restore (`f6_3_ROLLBACK.md`). +3. **Confirmação de e-mail + SMTP do GoTrue (hosted)** — com `Confirm email = ON`, se o SMTP + do GoTrue não estiver configurado com provedor real, **ninguém consegue logar** (o link de + confirmação não chega). Configurar SMTP no dashboard ANTES de ligar a confirmação. + +### 🟠 Importantes +4. **Manual files fora do fluxo do `db.cjs`** — os `manual/*.supabase_admin.sql` NÃO são + aplicados pelo `db.cjs migrate`. São aplicados à mão (psql como `supabase_admin`). Fácil + esquecer um → função/trigger ausente. Os runbooks listam a ordem. +5. **`postgres` não é superuser no stack local** — por isso vários objetos são `supabase_admin`. + No hosted o `postgres` é mais privilegiado, mas o schema `auth` é de `supabase_admin`: + o trigger da blacklist em `auth.users` e os `OWNER TO supabase_admin` podem precisar de + SQL Editor ou troca pra `OWNER TO postgres`. +6. **`config.toml` é gitignored** — `enable_confirmations=true` está só no arquivo local + (não versionado). No hosted a confirmação vai pelo **dashboard** (Auth → Confirm email). +7. **Migração de dados (cutover)** — `f6_1` COPIA; conferir **paridade de contagens** por + tenant/tabela antes de confiar (e antes do DROP). +8. **Edge functions novas precisam deploy** — `recover-access` e `send-welcome-email` (freemium) + + as edges de roteamento por schema (schema-per-tenant). Esquecer = esqueci-email/welcome/ + webhooks quebram. +9. **Slug é IMUTÁVEL** — = nome do schema físico. Uma vez escolhido, não muda (trava em 3 + camadas). UX do signup deixa claro, mas é definitivo. + +### 🟡 Menores / a observar +10. **Enforcement de limite é por-linha** (BEFORE INSERT) — um bulk insert de pacientes numa + única statement pode passar marginalmente do limite (cada linha não vê as anteriores da + mesma statement). Na prática o cadastro é 1 a 1; ok. +11. **notify_all_devs dispara a cada subscription** (inclui a free do auto_provision) — em + escala, muitos avisos no sino do dev. Intencional; reavaliar se incomodar. +12. **send-welcome-email usa SMTP de sistema** (separado do canal do tenant) — precisa secrets + no hosted; é best-effort (falha não bloqueia login). +13. **auto_provision idempotente** retorna o 1º tenant ativo se o user já tem algum — usuário + multi-tenant que se cadastra de novo não ganha tenant novo (esperado). +14. **Local vs main inconsistente** — o banco local está no modelo novo; o código da `main` é + RLS. Se fizer `git checkout main`, o app antigo ainda funciona porque `public` tem as tabelas + (até o DROP). Não rodar `main` esperando o modelo novo (e vice-versa). + +--- + +## 3. Passo a passo — como testar TUDO (local) + +> Pré: Docker do Supabase rodando (portas 643xx). Frontend via `npm run dev`. + +### Passo 0 — Ativar a confirmação de e-mail +A confirmação só vale após reiniciar o stack (o volume do banco **persiste** — nada se perde): +```bash +supabase stop && supabase start # ou o tooling equivalente do projeto +``` +Conferir no Studio/Mailpit que está de pé. (Se preferir NÃO testar confirmação agora, pule — +o front trata os dois casos; mas o fluxo "confirme e-mail" só aparece com isto ligado.) + +### Passo 1 — Schema-per-tenant: tenants EXISTENTES ainda funcionam +1. `npm run dev`, logar num tenant existente (ex.: clínica Bem-Estar / um terapeuta). +2. Abrir **Agenda, Pacientes, Financeiro, Conversas** → tudo carrega (lendo de `tenant_`). +3. Criar/editar um registro (ex.: um bloqueio na agenda, editar um paciente) → salva sem erro. +4. Sino de notificações abre (dual-source tenant + sistema). +> Se algo não carregar, é sinal de roteamento de schema — anotar a tela/erro. + +### Passo 2 — Freemium: signup self-service NOVO (o fluxo principal) +1. Deslogar. Ir em **`/lp`** → conferir o cartão **"Grátis"** na vitrine. +2. **Criar conta grátis** → escolher tipo (terapeuta/clínica) + seu nome + nome do negócio + + **slug** (ver a checagem de disponibilidade ao vivo) + e-mail + senha. +3. Submeter → cai na tela **"Confirme seu e-mail"** (NÃO loga ainda). +4. Abrir o **Mailpit** (caixa de e-mail local) → achar o e-mail de confirmação → clicar no link. +5. Voltar/entrar em **`/auth/login`** → logar → cai em **`/onboarding`** → "Preparando seu + ambiente…" → provisiona → entra no painel do tenant novo. +6. Conferir no Mailpit o **e-mail de boas-vindas** (welcome — best-effort). +7. Conferir que o schema `tenant_` foi criado (Studio) e que você é master. + +### Passo 3 — Limite do plano gratuito +1. No tenant gratuito recém-criado (ou num clinic_free existente), cadastrar pacientes. +2. Ao passar do limite (clínica=30, terapeuta=20) → aparece o **toast "Limite do plano + gratuito"** com botão **"Fazer upgrade"** (não o erro cru). +3. Conferir o botão **"Upgrade PRO"** dourado no topbar (visível porque o plano é free). + +### Passo 4 — SaaS / dev (logar como saas_admin) +1. **`/saas/usuarios`** → o cliente novo aparece com selo **"Novo"** (verde, 24h), com slug/e-mail/plano. +2. **Sino do dev** → recebeu **"Nova assinatura"** (do provisionamento). +3. **`/saas/app-config`**: + - Adicionar um **e-mail na blacklist** (ex.: `bloqueado@x.com`). Depois, deslogar e tentar + **criar conta** com ele → bloqueado de verdade. + - Testar **`@dominio.com`** (domínio inteiro). + - Trocar **root_redirect** (landing↔login) e abrir **`/`** deslogado → confere o destino. + +### Passo 5 — Esqueci meu e-mail +1. **`/auth/login`** → **"Esqueci meu e-mail"** → digitar o **slug** do tenant criado no Passo 2. +2. Recebe a confirmação com a **dica mascarada** (jo****@gm****.com) e um **magic link** no Mailpit. +3. Clicar no magic link → entra. (O e-mail real nunca aparece na tela.) +4. ⚠️ Edge functions locais: precisam estar servidas (`supabase functions serve` ou o runtime + do stack). Se o esqueci-email/welcome não responder, é a edge não estar de pé localmente. + +### Passo 6 — Pegadinha #4 (sino ao trocar de usuário) +1. Logado como user A, com notificações no sino → **logout**. +2. Logar como user B → o sino **não** mostra notificações do A (foi resetado no logout). + +### Passo 7 (opcional, destrutivo, só quando confiante) — preparar o DROP +NÃO aplicar agora. Quando tudo acima estiver validado por dias: seguir a **Fase G** do +`docs/DEPLOY_SCHEMA_PER_TENANT.md` (backup fresco → `f6_3_drop_public_tenant_tables`). + +--- + +## 4. Atalhos / referências +- Runbooks: `docs/DEPLOY_SCHEMA_PER_TENANT.md`, `docs/DEPLOY_FREEMIUM_F4.md`. +- Rollback do DROP: `database-novo/manual/f6_3_ROLLBACK.md`. +- Migrations: `database-novo/migrations/` (aplicar via `node database-novo/db.cjs migrate`). +- Manual privilegiados: `database-novo/manual/*.supabase_admin.sql` (aplicar como `supabase_admin`). +- Wiki: `Obsidian/Brain/wiki/Migracao Schema-per-Tenant.md` e `Obsidian/Brain/wiki/Freemium PLG.md`. +- Portas locais: API 64321 · DB 64322 · Studio 64323 (stack shiftada +10000).