# FASE 9 — Hardening e produção ## Objetivo Provar que o sistema aguenta o mundo real: testes ponta a ponta, carga no SFU, injeção de falhas, revisão de segurança e deploy documentado. ## Pré-requisitos FASES 0–8 concluídas. Ler `docs/06-LGPD-E-SEGURANCA.md` §5 e `docs/07-REQUISITOS-DE-CAMPO.md`. ## Tarefas ### 1. Testes ponta a ponta Playwright para os webs, Maestro para os apps. Cenários obrigatórios: 1. Visita completa: QR → aviso → permissões → foto → unidade → morador atende → autoriza → PIN 2. Entrega em um toque, resolvida pela notificação, em menos de 10s 3. Escalonamento completo: ninguém atende → outros moradores → fila → operador → autorizado 4. Recado: ninguém atende, sem módulo de operador → grava → morador resolve depois 5. Unidade inexistente: visita criada, ninguém notificado, expira — **resposta indistinguível de unidade válida** 6. Fora do geofence: bloqueado com mensagem acionável 7. Quiet hours: desvia sem tocar em ninguém 8. Dois moradores respondendo juntos: um vence, o outro vê quem resolveu 9. LiveKit fora: degrada para áudio, depois foto+texto 10. Backend reiniciado no meio de uma visita: escalonamento acontece mesmo assim O cenário 10 é o que valida o padrão de timeouts persistidos. O 5 valida a busca cega. ### 2. Teste de carga **SFU:** 50 chamadas simultâneas de 2 participantes, medindo banda, CPU e tempo até o primeiro frame. Confronte com o dimensionamento de `05-INFRA-DOCKER.md` §4. **API:** 100 visitas/minuto sustentadas — muito acima do real (~0,3 req/s), de propósito. **Fila:** 10 mil jobs agendados para o mesmo instante, verificando que nenhum é perdido ou executado duas vezes. **Banco:** tabela de auditoria com 1 milhão de visitas; a tela do admin precisa continuar fluida. ### 3. Injeção de falhas Derrube cada peça, uma por vez, com uma visita em andamento, e verifique o comportamento: | Peça derrubada | Comportamento esperado | |---|---| | LiveKit | Degrada para áudio → foto+texto → operador | | Redis | WebSocket degrada para polling; fila continua (está no Postgres) | | MinIO | Visita prossegue sem foto, com aviso; upload entra em retry | | FCM | WebSocket assume se o app está aberto; falha vai para o dashboard | | Uma réplica do backend | Outra assume; jobs pendentes executam | | Postgres (breve) | Erro claro ao visitante e contingência física acionada | **Teste do relógio:** atrase o relógio de uma réplica em 30s e confirme que ShedLock não permite execução dupla. ### 4. Revisão de segurança Percorra o modelo de ameaças de `06-LGPD-E-SEGURANCA.md` §5 e prove cada mitigação: - [ ] **A.1 Busca cega** — tempo de resposta constante medido estatisticamente, não no olho. Este é o teste mais importante da fase - [ ] **A.2 Geofence** — rejeita fora do raio; GPS falsificado é registrado - [ ] **A.3 DoS social** — rate limit e quiet hours funcionam; varredura gera alerta - [ ] **A.4 Mídia** — nenhuma URL pública; assinada expira; acesso auditado - [ ] **A.5 Auditoria** — `UPDATE`/`DELETE` em `audit_log` falham no banco - [ ] **A.6 Tokens** — JWT de visitante não serve para outra visita nem outra portaria - [ ] **A.7 QR** — incrementar `qr_version` invalida os códigos antigos Rode também: `pnpm audit`, `gradle dependencyCheck`, varredura de imagem Docker (Trivy), e headers verificados por observatório de segurança. **Grep obrigatório:** nenhuma biblioteca de detecção ou reconhecimento facial em `build.gradle.kts` ou `package.json`. A tentação aparece disfarçada de UX ("só para enquadrar o rosto") e tem consequência jurídica direta. ### 5. Checklist de produção **Infraestrutura** - [ ] Faixa UDP 50000–60000 aberta (esquecer isso conecta a chamada e nunca mostra vídeo) - [ ] TLS válido e renovação automática testada - [ ] Backup automático com **restore testado e cronometrado** - [ ] Segredos fora do repositório e fora das imagens - [ ] Healthchecks respondendo em todos os serviços - [ ] Alertas chegando em canal monitorado de verdade **Aplicação** - [ ] Perfil `prod`, sem stack trace exposto - [ ] Rate limits ativos - [ ] CORS restrito aos domínios reais - [ ] Logs sem dado pessoal (nome, foto, coordenada) — **verificar linha a linha** - [ ] Migrations aplicadas em ordem em banco limpo **Apps** - [ ] Builds de release assinados - [ ] Testados em dispositivo físico, Android e iOS - [ ] Ficha de privacidade da App Store e do Google Play preenchida - [ ] Justificativa de VoIP documentada para a App Review - [ ] Crash reporting **sem PII** **Conformidade** — checklist completo de `06-LGPD-E-SEGURANCA.md` §9. **Campo** — checklist de ativação de `07-REQUISITOS-DE-CAMPO.md` §2 para o condomínio piloto. ### 6. Deploy `docs/anexos/deploy.md` com provisionamento, primeiro deploy, atualização sem downtime (rolling com healthcheck), rollback, aplicação de migration com dado em produção, e o procedimento de crescer para HA. ### 7. Piloto assistido Antes da ativação definitiva, **duas semanas com o módulo de operador ligado**, monitoramento diário e reunião semanal com o síndico. O que se mede: taxa real de atendimento, tempo médio de resolução, abandono de entregador, incidentes, e feedback qualitativo de moradores e entregadores. **É esse número — não a expectativa comercial — que define se o condomínio fica no plano Autônomo ou no Assistido.** ## Critérios de aceite - [ ] Os 10 cenários E2E passam em CI - [ ] Carga do SFU dentro do dimensionamento previsto - [ ] Toda injeção de falha se comporta como na tabela - [ ] Todas as mitigações do modelo de ameaças verificadas - [ ] Busca cega com tempo constante comprovado estatisticamente - [ ] Checklist de produção 100% marcado - [ ] Restore de backup executado e cronometrado - [ ] Runbooks testados por alguém que não os escreveu - [ ] Piloto de duas semanas concluído com métricas coletadas ## Não faça nesta fase - Novas funcionalidades — se aparecer necessidade, vira v2 - Otimização sem métrica que a justifique