Files
agenciapsilmno/Obsidian/Brain/wiki/Freemium PLG.md
T
Leonardo a73b82fa86 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>
2026-06-13 18:05:19 -03:00

3.8 KiB

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_freeclinic_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_tenantclone_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.