🎯 Clinicafy — Auditoria cs-*

🖥️ cs-backend-engineer — Backend Engineer Review

Auditoria técnica e estratégica pela ótica cs-backend-engineer — Backend Engineer Review. Achados classificados por severidade, plano de ação e matriz de decisão.

Veredito: API REST funcional com auth bem implementada, mas sem rate limiting, rotas antigas sem auth e monólito sem connection pooling explícito.

O backend tem auth robusta com fallback duplo (Firebase Admin SDK + Identity Toolkit API, server.ts:204-249). MercadoPago e Meta CAPI integrados com sanitização. Problemas graves: rotas /api/pacientes e similares respondem sem verifyAuth (HANDOFF.md:91), sem rate limiting global, sem connection pooling explícito no Prisma e CORS totalmente aberto (Access-Control-Allow-Origin: *).

2911L
server.ts (sem router)
ABERTO
CORS Access-Control-Allow-Origin: *
SEM
Rate Limiting Global
ROTAS SEM AUTH
/api/pacientes (confirmado)
duplo
Fallback auth Firebase+Toolkit

Dimensões Analisadas

Pontuação por área de análise.

Autenticação

70

verifyAuth com fallback duplo é robusto. Problema: nem todas as rotas chamam verifyAuth.

1 achados 1 bloqueante(s)

CORS & Headers

20

CORS totalmente aberto. Helmet presente mas não configurado para landing estática.

2 achados 1 bloqueante(s)

Rate Limiting

10

Zero rate limiting detectado em qualquer rota. DDoS trivial.

1 achados 1 bloqueante(s)

Webhook Security

60

MercadoPago webhook tem validação de signature (server.ts:23-26). Mas fallback para token simples se webhook_secret ausente.

1 achados

🔎 Achados (5)

1 crítico(s) · 3 alto(s) · 3 bloqueante(s). Clique para expandir.

Rotas /api/pacientes sem verifyAuth — dados médicos expostos sem autenticaçãoCríticaBloqueanteEsforço medioOWASP A01 — Broken Access Control

O que é: HANDOFF.md:91-92 documenta explicitamente: 'rotas /api/pacientes etc. respondem SEM auth. Adicionar verifyAuth+tenant (as rotas novas de storage já validam; as antigas de dados não).' Dados médicos de pacientes (CPF, histórico, diagnósticos) acessíveis sem token.

Onde: HANDOFF.md:91-92 + server.ts (rotas /api/pacientes a identificar)

Impacto: Violação LGPD Artigo 11 (dados de saúde = categoria especial). Multa ANPD até R$50M. Exposição de prontuários de todos os pacientes de todos os tenants.

✅ Correção: Identificar todas as rotas app.get/post/put/delete sem verifyAuth. Adicionar: const user = await verifyAuth(req); if (!user) return res.status(401).json({error:'Unauthorized'}); Garantir filtro por userId=user.uid.
CORS totalmente aberto — Access-Control-Allow-Origin: *AltaBloqueanteEsforço baixoOWASP A05 — Security Misconfiguration

O que é: API em produção retorna Access-Control-Allow-Origin: * (confirmado via curl dos headers). Qualquer site pode fazer requests autenticados para a API se obtiver um token Bearer válido (ex: via XSS em outro site do mesmo browser).

Onde: server.ts:4 (cors import) + headers HTTP produção

Impacto: Facilita ataques CSRF e exfiltração de dados médicos via XSS em sites terceiros.

✅ Correção: Restringir CORS: cors({ origin: ['https://www.clinicafy.com.br', 'https://clinicafy.com.br'] }). Adicionar credentials: true apenas se necessário.
Zero rate limiting — API vulnerável a abuso e DDoSAltaBloqueanteEsforço baixoOWASP A04 — Insecure Design

O que é: server.ts não importa nem configura express-rate-limit ou similar. Qualquer endpoint pode ser chamado ilimitadamente — login brute force, scraping de pacientes, abuso de webhook MP.

Onde: server.ts:1-120 (imports — sem rate-limit)

Impacto: Custo operacional explosivo. Brute force de senhas Firebase Auth bypass pelo backend. Abuso de webhooks.

✅ Correção: npm install express-rate-limit. Adicionar: const limiter = rateLimit({ windowMs: 15*60*1000, max: 100 }); app.use('/api/', limiter); Rate específico para auth: max: 10/15min.
Prisma sem connection pooling explícito para serverlessAltaEsforço medioDatabase / Serverless Best Practices

O que é: src/lib/prisma.js importa PrismaClient diretamente. Em ambiente serverless (Vercel functions), cada invocação pode criar nova conexão MySQL — esgotando o pool do Hostinger rapidamente em pico de requisições.

Onde: src/lib/prisma.js (inferido de server.ts:11)

Impacto: Erros 'Too many connections' no Hostinger MySQL em pico. Timeouts para usuários.

✅ Correção: Usar Prisma Accelerate (free tier) OU implementar singleton pattern: if (!global.prisma) global.prisma = new PrismaClient(). Definir connection_limit na DATABASE_URL: ?connection_limit=5
Dunning D0/D3/D7/D10 hardcoded sem config por tenantMédiaEsforço medioRevOps / SaaS Architecture

O que é: server.ts:117-122 define DUNNING_STAGES como constante hardcoded. Não há personalização por plano ou configuração por tenant. Dunning cron depende de CLINICAFY_DUNNING_CRON_SECRET (server.ts:116) que pode estar ausente.

Onde: server.ts:116-122

Impacto: Impossível ajustar estratégia de dunning sem deploy. Se cron_secret estiver ausente, dunning nunca roda.

✅ Correção: Mover DUNNING_STAGES para tabela de configuração ou env var. Adicionar verificação de cron_secret com log de alerta se ausente.

📋 Plano de Ação

Cronograma de implementação recomendado.

1

Auth em todas as rotas (1 dia)

Auditar server.ts linha a linha para rotas sem verifyAuth. Adicionar middleware global de auth com whitelist de rotas públicas.
seguranca
1 dia · CRÍTICO
2

CORS restritivo (30min)

Mudar cors() para cors({ origin: ['https://www.clinicafy.com.br', 'https://clinicafy.com.br'] })
seguranca
30min · CRÍTICO
3

Rate limiting (2h)

express-rate-limit global + específico para auth e webhooks
seguranca
2h · CRÍTICO
4

Prisma connection pooling (2h)

Singleton pattern + connection_limit na DATABASE_URL
banco
2h

Matriz de Decisão

CritérioFonteStatusBloqueante
Auth Coveragecs-backend-engineerRotas sem verifyAuthSIM
CORS Policycs-backend-engineerTotalmente abertoSIM
Rate Limitingcs-backend-engineerAusenteSIM
Auth Implementationcs-backend-engineerFallback duplo robustonão
DB Connectioncs-backend-engineerSem pooling serverlessnão