Skip to main content
Status: sessão de 26/04 fechou os 7 ALTOS + BAIXOS rápidos + welcome email. Restam: 1 bloqueador (Stripe key) + 9 MÉDIOS + 2 itens estratégicos. Detalhes técnicos completos em auditoria-pre-launch-2026-04-26.mdx.

🚨 BLOQUEADOR — antes do launch público

Rotacionar Stripe live keys

Onde está vazado: SETUP_QUANDO_VOLTAR.md:13-14 (committed em 147fb2d, está no git history). Plano combinado: rotacionar DEPOIS de fazer 1 teste de compra real, pra não quebrar o fluxo de validação. Passo a passo (você faz):
  1. Stripe Dashboard → API Keys → roll do STRIPE_SECRET_KEY live
  2. Stripe Dashboard → Webhooks → roll do STRIPE_WEBHOOK_SECRET
  3. Atualizar ambos no Supabase Edge Functions Secrets
  4. Confirmar via curl que a chave antiga foi rejeitada
  5. Me chamar pra deletar SETUP_QUANDO_VOLTAR.md e reescrever git history (BFG ou git filter-repo)

📋 9 MÉDIOS — atacar amanhã (27/04/2026, ~3-4h)

Sugestão de ordem por impacto + tempo:

Lote 1 — quick wins (~30min)

1. Habilitar Leaked Password Protection (1 click no Supabase)
  • Supabase Dashboard → Auth → Policies → “Leaked password protection”
  • Sem código. Sem custo. Bloqueia signups com senhas comprometidas (HaveIBeenPwned).
2. Mover pg_net pro schema extensions
ALTER EXTENSION pg_net SET SCHEMA extensions;
  • Validar antes que cron jobs de mensalidades reminder não quebram (eles usam pg_net.http_post).
3. Policy explícita em rate_limit_log
  • Hoje RLS habilitado, zero policies → tabela inacessível por user (correto), mas Supabase advisor flagged.
  • Adicionar CREATE POLICY "deny_all" ON rate_limit_log FOR ALL USING (false); + comentário SQL explicando intenção.

Lote 2 — refactors (~1h)

4. Centralizar PLAN_LIMITS (eliminar duplicação 3-way)
  • Hoje espalhado em:
    • lib/constants.ts:30 (só OFX_IMPORTS_PER_MONTH)
    • hooks/use-subscription.ts:27-61 (PLANS completo com pricing)
    • app/crypto/_actions/crypto-actions.ts:34 (PLAN_LIMITS hardcoded)
  • Criar lib/plans.ts único com tipo PlanKey + getLimitsFor(plan). Remover duplicações.
5. PII em logs do Sentry (LGPD-relevante!)
  • app/cartoes/_actions/ofx-actions.ts linhas 307, 407, 416, 426, 602, 611, 695, 709, 843
  • Substituir userId por hash, valores por contadores ({ count: N }), nomes de assinaturas (Netflix/Spotify) por categorias agregadas.
  • Política de privacidade promete “sem dados de transações em logs públicos” — atual viola.

Lote 3 — security hardening (~1.5h)

6. CSRF em admin actions
  • Confirmar serverActions.allowedOrigins está configurado em next.config.js
  • Adicionar test de regression que dispara resetPassword de origem externa e espera reject
7. Race condition em limites por plano
  • app/cartoes/_actions/ofx-actions.ts:79-98 (assertMonthlyLimit) e app/crypto/_actions/crypto-actions.ts:34-76 (assertUnderLimit)
  • Hoje: SELECT count → check → INSERT (3 etapas, race possível em paralelo)
  • Fix: RPC PostgreSQL com SELECT ... FOR UPDATE na mesma transaction, ou unique constraint UNIQUE(user_id, date_trunc('month', created_at)).
8. Logout server-side revoke
  • components/auth-provider.tsx:116: hoje signOut({ scope: 'local' }) só limpa client
  • Adicionar server action que chama supabaseAdmin.auth.admin.signOut(userId, 'global') em background depois do local signOut. Sem bloquear UX.
9. Admin RPC timeout consistency
  • middleware.ts:46-58 faz timeout 5s na RPC is_super_admin (fail-closed, OK)
  • lib/admin-auth.ts:15-19 chama mesma RPC SEM timeout — pode pendurar action
  • Adicionar Promise.race com timeout 10s + throw AdminAuthError('FORBIDDEN')

🔍 ALTOS pendentes da sessão de 26/04

Estes ALTOS do relatório original ficaram para depois e merecem atenção:

A5. Edge Runtime warnings em @supabase/ssr

Build mostra:
@supabase/realtime-js usa process.versions (não suportado em Edge)
@supabase/supabase-js usa process.version (não suportado em Edge)
Middleware roda em Edge → pode lançar runtime error em request. Ação: verificar se @supabase/ssr@^0.7.0 (atual) tem fix. Se não, considerar pin em versão alternativa ou aceitar risco e monitorar Sentry.

A8. Silent failures padrão

Catches que só fazem console.warn/console.error sem reportar pra Sentry:
  • lib/email.ts:27-37 — Resend cair em prod = só descobre quando user reclama
  • lib/auth.ts (várias) — credential stuffing invisível
  • app/cartoes/_actions/ofx-actions.ts:404 — assinaturas falham silenciosamente após gastos OK
Padrão de fix:
} catch (err) {
  Sentry.captureException(err, { tags: { module: 'email' } })
  console.warn('[email] failed:', err)
  return { ok: false, error: ... }
}

✨ Estratégicos (não-bloqueantes pro launch)

Workspace invite por email

Hoje convite é link sharing puro (admin copia, manda manual). Pra wire o template workspace_invite do Resend, precisa:
  • Adicionar campo email opcional no WorkspaceInvitesPanel
  • Server action: gera invite + se email preenchido, dispara email
  • Decisão de produto: email opcional (mantém compatibilidade) ou obrigatório (UX limpa, breaking)?

Stripe webhook emails

Templates payment_received, payment_failed, subscription_canceled rodam na Edge Function Supabase do webhook do Stripe — fora do escopo do código Next.js. Você precisa wire essas no código Deno do webhook. Onde olhar: Supabase Dashboard → Edge Functions → stripe-webhook (ou similar).

✅ O que JÁ foi feito hoje (26/04)

  • 7 ALTOS: useMemo bug, sentry-example guard, env vars, open redirect, Sentry capture em error.tsx, server-only em supabase-admin, release+env Sentry
  • BAIXOS limpos: pin next 15.2.4, escapes, <img><Image> (7 instâncias), .gitignore + .vercelignore corrigidos
  • Welcome email: migration + server action idempotente + wire no /auth/callback
Estado: lint zero warnings/errors, tsc clean, build clean. 4 commits pushed pra main: 8ca1d8f, 5c598fb, 0eed6c1, 7bf3e80.