freemium F1: enforcement de limite de pacientes (schema-per-tenant)
- therapist_free ganha max_patients=20 (clinic_free ja tinha 30) - trigger BEFORE INSERT em patients le plan_features.limits em runtime, resolve tenant por TG_TABLE_SCHEMA, plano ativo (clinica via tenant_id + pessoal via owner user_id), conta vivos (status<>Arquivado) e da RAISE PLAN_LIMIT_REACHED|patients|<n> - helpers tenant_active_plan_id / plan_feature_limit (globais, sobrevivem F6.3) - wiring: tenants novos ganham via trg_attach_business_triggers; 9 existentes backfill - testado: clinic_free bloqueia em 30, therapist_free em 20, PRO ilimitado (rollback) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
# Freemium / PLG
|
||||
|
||||
Épico iniciado em 2026-06-13, branch `feat/freemium-plg` (sobre [[Migracao Schema-per-Tenant]]). Objetivo: qualquer visitante cria conta gratuita sozinho, confirma e-mail, e o ambiente do tenant é provisionado automaticamente. Plano gratuito limitado + botão "Upgrade PRO". Blueprint-diretor: `novo-rumo.txt` (raiz), vindo do sistema-irmão (sindicato) e adaptado a clínica.
|
||||
|
||||
## Descoberta (Fase 0) — o que já existia
|
||||
|
||||
O sistema já estava ~70-85% pronto:
|
||||
- **Planos free existem**: `clinic_free`, `therapist_free` (+ supervisor/patient) com `plan_features.limits` semeado (`clinic_free` → `clinic_calendar {max_patients:30, max_therapists:5}`, `online_scheduling {sessions_per_month:40}`, `reminders {reminders_per_month:50}`, `documents.upload {max_storage_mb:500}`; 14 features premium OFF).
|
||||
- **Feature gating completo**: `entitlementsStore.js` (views `v_tenant_entitlements`/`v_user_entitlements`), `FeatureGate.vue`, guard `meta.feature` → `/upgrade` (`guards.js:814`), badge PRO no menu.
|
||||
- **Provisionamento schema-per-tenant**: `ensure_personal_tenant`/`provision_account_tenant` → `clone_tenant_template`. Setup Wizard.
|
||||
- **Signup self-service**: `/lp` (pricing dinâmico de `v_public_pricing`) → `/auth/signup` (`Signup.vue:219` `signUp` inline, cria intent só no pago).
|
||||
- RPCs `activate_subscription_from_intent`, `change_subscription_plan`. `tenants.slug` 100% populado.
|
||||
|
||||
**Gap confirmado:** limites semeados mas **ninguém lê/enforça**. Sem confirmação de e-mail (`enable_confirmations=false`), sem /onboarding, signup só coleta email+senha, sem welcome email, sem os extras.
|
||||
|
||||
## Decisões (Fase 0.5)
|
||||
|
||||
1. **Modelo do blueprint** — confirmação de e-mail ON; signup grava escolha em `raw_user_meta_data` + signOut-local + tela "confirme e-mail"; provisionamento+intent viram RPCs idempotentes no 1º login (`auto_provision_free_tenant(p_slug_override)`, `processar_pos_signup`); guard manda logado-sem-tenant → `/onboarding`. Reescreve o signup inline.
|
||||
2. **Pacientes** = recurso limitado. Trigger BEFORE INSERT em `patients` lê limits em runtime, resolve tenant por `TG_TABLE_SCHEMA`, conta linhas vivas, `RAISE 'PLAN_LIMIT_REACHED|patients|<n>'`. clinic_free=30, therapist_free=20. No template + backfill 9 schemas.
|
||||
3. **Slug escolhido** no signup (sugestão sanitizada + `slug_disponivel(p_slug)→{ok,motivo}`), imutável, trava 3 camadas.
|
||||
4. **Todos os 4 extras**: /saas/usuarios + `notify_all_devs`; esqueci-email (magic link por slug, dica mascarada); blacklist (email|slug); root_redirect.
|
||||
|
||||
## Pegadinhas (do blueprint, ⚠️ caras no irmão)
|
||||
|
||||
- **#1** Signup sem sessão (confirmação ON) → tudo com `auth.uid()` quebra em silêncio. Gravar escolha em metadata, processar pós-confirmação.
|
||||
- **#2** signOut `scope:'local'` se não veio sessão — senão vaza sessão anterior e joga no painel errado.
|
||||
- **#3** Logado-sem-tenant nunca cai em painel quebrado → `/onboarding` resolve estados (provisionando, slug-colidiu, pago-aguardando, sem-acesso, erro).
|
||||
- **#4** Sino de notificação singleton precisa re-buscar ao trocar de user (logout+login).
|
||||
|
||||
## Divergência de infra
|
||||
|
||||
Blueprint pede welcome email via **Resend**; aqui é **SMTP/Mailpit** (`process-email-queue`). Reusar o pipeline SMTP existente (best-effort), não Resend.
|
||||
|
||||
## Fases
|
||||
|
||||
- **F1** — Fundação: ajustar limits free (therapist_free max_patients) + trigger de enforcement + toast PLAN_LIMIT_REACHED + botão Upgrade PRO.
|
||||
- **F2** — Self-service: `enable_confirmations`, RPCs idempotentes, signup rewrite (nome+slug+metadata), `/onboarding`, welcome email, plano free visível na vitrine.
|
||||
- **F3** — Extras (4).
|
||||
- **F4** — Deploy (hosted, dirigido pelo Leonardo).
|
||||
|
||||
Método: commits por assunto; cada migration testada em transação com ROLLBACK antes de aplicar; build a cada bloco front.
|
||||
@@ -31,3 +31,4 @@ _(synthesized answers to questions you've asked, filed back as pages)_
|
||||
|
||||
*This index is maintained by Claude via `/wiki-brain`. Do not edit by hand unless you know what you're doing.*
|
||||
- [[Migracao Schema-per-Tenant]] — migração RLS-only → schema físico por tenant (F0 done, aguardando Q1-Q4)
|
||||
- [[Freemium PLG]] — signup self-service + Upgrade PRO; plano gratuito limitado (pacientes); confirmação de e-mail + onboarding; branch feat/freemium-plg
|
||||
|
||||
Reference in New Issue
Block a user