docs: registrar bugs encontrados na verificação real em navegador
Usuário testou em produção e confirmou que os dois bugs do commit anterior (Content-Type em requisições sem corpo, DELETE de supressão sem motivo) estão corrigidos. Atualiza TODO.md/RELATORIO_FINAL.md para refletir a verificação visual como concluída, e documenta a lição em TROUBLESHOOTING.md: teste via curl prova que o backend funciona, não que o frontend consegue falar com ele.
This commit is contained in:
30
TODO.md
30
TODO.md
@@ -321,20 +321,22 @@ banco. Todos os fixtures de teste foram removidos/desativados ao final.
|
||||
aceite) não exige essa tela. Criar uma tela sem a API por trás seria
|
||||
construir um mockup, o que a diretriz do projeto proíbe. Fica
|
||||
registrado como pendência explícita, não descartado silenciosamente.
|
||||
- [ ] **Verificação visual em navegador não foi possível nesta sessão** —
|
||||
ambiente é um servidor Debian headless sem display/browser. A
|
||||
verificação feita foi: `tsc --noEmit` limpo, `eslint` limpo, build de
|
||||
produção (`next build`) gerando as 27 rotas sem erro, e testes
|
||||
funcionais via `curl` reproduzindo exatamente as chamadas que o
|
||||
navegador faria — login via `/api/auth/login`, cookie de sessão
|
||||
validado pelo middleware (`/` redireciona para `/login` sem cookie,
|
||||
libera com cookie), todas as 24 páginas protegidas retornando HTTP
|
||||
200 através do Nginx, e os endpoints de dados (`/api/dashboard`,
|
||||
`/api/reports/*`, `/api/compliance/*` etc.) retornando dados reais
|
||||
com o mesmo cookie de sessão. O que **não** foi verificado: renderização
|
||||
visual real, interações de clique/formulário no DOM, responsividade,
|
||||
tema escuro na prática. Recomenda-se ao usuário abrir
|
||||
`http://10.10.32.142/` em um navegador para essa validação final.
|
||||
- [x] **Verificação visual em navegador** — não foi possível durante a
|
||||
construção (ambiente headless, sem display/browser); feita depois
|
||||
pelo usuário real em `http://10.10.32.142/`, e **encontrou dois bugs
|
||||
reais que o teste via curl nunca teria pego**: (1) o cliente HTTP do
|
||||
frontend mandava `Content-Type: application/json` em requisições sem
|
||||
corpo, e o Fastify rejeitava com 400 "body is empty" — quebrava
|
||||
**todo** botão de ação sem payload (disponibilizar agente, pausar,
|
||||
publicar dialplan, iniciar/pausar campanha, redefinir senha de
|
||||
ramal); (2) botão "Desbloquear" da lista de bloqueio sempre falhava
|
||||
porque a API exige motivo no corpo do DELETE e o cliente não tinha
|
||||
como enviá-lo. Ambos corrigidos na raiz (função `request()` central)
|
||||
e confirmados pelo usuário: "testei, funcionou". Detalhes em
|
||||
`docs/TROUBLESHOOTING.md`. **Lição registrada**: testes via curl
|
||||
provam que o backend funciona, não que o frontend consegue falar com
|
||||
ele — teste real em navegador continua sendo necessário antes de dar
|
||||
uma tela por concluída.
|
||||
|
||||
## Fase 9 — Segurança e produção
|
||||
- [x] Criptografia de segredos de trunk (AES-256-GCM) — já implementado na
|
||||
|
||||
@@ -130,8 +130,12 @@ Itens genuinamente pendentes, nunca escondidos:
|
||||
3. **`scripts/install.sh`/`update.sh`** não foram testados de ponta a ponta
|
||||
num servidor limpo (o servidor atual já estava provisionado) — validados
|
||||
por inspeção linha a linha contra os comandos manuais já executados.
|
||||
4. **Verificação visual em navegador real** não foi feita (ambiente
|
||||
headless) — validado via `curl` reproduzindo as chamadas do navegador.
|
||||
4. ~~Verificação visual em navegador real~~ — feita posteriormente pelo
|
||||
usuário em produção. Confirmou que o `curl` sozinho não é suficiente:
|
||||
achou dois bugs reais de integração frontend↔API invisíveis a testes
|
||||
via curl (Content-Type em requisições sem corpo quebrando todo botão de
|
||||
ação; DELETE de supressão sem forma de enviar o motivo exigido). Ambos
|
||||
corrigidos, usuário confirmou funcionamento. Ver `docs/TROUBLESHOOTING.md`.
|
||||
5. **Tela de Callbacks** no frontend não existe — o agendamento e a
|
||||
reativação automática funcionam via API/worker (`POST /agent-console/
|
||||
dispose`, `GET /api/callbacks`, `callback-sweep.ts`), mas não há uma
|
||||
|
||||
@@ -3,6 +3,39 @@
|
||||
Problemas reais encontrados durante o desenvolvimento deste projeto e como
|
||||
foram diagnosticados/resolvidos — mantido como referência para o futuro.
|
||||
|
||||
## "Body cannot be empty when content-type is set to 'application/json'" em quase todo botão de ação
|
||||
|
||||
**Sintoma**: usuário real testando no navegador (não `curl`) relatou erro
|
||||
"body is empty" ao clicar em redefinir senha de um ramal. Investigação
|
||||
mostrou que o mesmo bug afetava **todo** botão de ação sem payload:
|
||||
disponibilizar agente, pausar/despausar, publicar dialplan, iniciar/
|
||||
pausar/parar campanha, etc.
|
||||
|
||||
**Causa**: o cliente HTTP central do frontend
|
||||
(`apps/frontend/src/lib/api-client.ts`) sempre enviava
|
||||
`Content-Type: application/json` mesmo em requisições sem corpo. O
|
||||
Fastify rejeita isso com 400 antes de a requisição chegar ao controller
|
||||
— o `@Body()` do NestJS nem entra em cena, o parser de body do Fastify já
|
||||
barra antes.
|
||||
|
||||
**Por que passou despercebido por tanto tempo**: todo teste de API deste
|
||||
projeto, em toda fase anterior, foi feito via `curl` — e `curl -X POST`
|
||||
sem `-H 'Content-Type: ...'` e sem `-d` não define esse header. O
|
||||
`fetch()` do navegador (usado pelo cliente HTTP real do frontend) sempre
|
||||
define o header por padrão. Ou seja: **testar só via curl não teria
|
||||
pegado nunca esse bug** — só apareceu quando um usuário de verdade clicou
|
||||
em botões reais no navegador. Lição: `curl` prova que o *backend*
|
||||
funciona: não prova que o *frontend* consegue falar com ele.
|
||||
|
||||
**Fix**: só incluir o header `Content-Type` quando `body !== undefined`,
|
||||
na única função `request()` usada por `get`/`post`/`patch`/`delete`.
|
||||
|
||||
**Bug relacionado, achado na mesma revisão**: `DELETE /api/suppression/:id`
|
||||
exige `removalReason` no corpo, mas `api.delete()` nem aceitava um
|
||||
argumento de corpo — o botão "Desbloquear" da lista de bloqueio sempre
|
||||
falhava com 403. Mesma causa raiz (função de ação sem forma de levar
|
||||
payload), mesmo tipo de bug que só um clique real revela.
|
||||
|
||||
## "Argument calledNumber is missing" ao originar chamada
|
||||
|
||||
**Sintoma**: `PrismaClientValidationError` ao reservar um lead, mesmo a
|
||||
|
||||
Reference in New Issue
Block a user