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.
162 lines
7.1 KiB
Markdown
162 lines
7.1 KiB
Markdown
# B2BCall — Relatório Final da Implementação
|
|
|
|
Formato conforme agente.md seção 96. Gerado em 2026-08-27 contra o ambiente
|
|
real em execução (`Lab-FSCore-API`, 10.10.32.142).
|
|
|
|
```text
|
|
B2BCall version: 0.1.0
|
|
Asterisk version: 22.10.1
|
|
Node version: v24.20.0
|
|
PostgreSQL version: 17 (postgres:17-alpine)
|
|
Docker version: 29.7.2 (Compose v5.5.0)
|
|
```
|
|
|
|
## Containers
|
|
|
|
| Container | Status |
|
|
|---|---|
|
|
| b2bcall-postgres | healthy |
|
|
| b2bcall-redis | healthy |
|
|
| b2bcall-asterisk | healthy |
|
|
| b2bcall-api | healthy |
|
|
| b2bcall-frontend | healthy |
|
|
| b2bcall-nginx | healthy |
|
|
| b2bcall-asterisk-events | up (sem healthcheck HTTP formal — worker sem porta exposta) |
|
|
| b2bcall-dialer-worker | up (idem) |
|
|
|
|
## URLs
|
|
|
|
- Interface web: `http://10.10.32.142/`
|
|
- API: `http://10.10.32.142/api`
|
|
- Health: `http://10.10.32.142/api/health`
|
|
- Métricas (Prometheus, autenticado, uso interno): `http://10.10.32.142/api/metrics`
|
|
|
|
## Super admin
|
|
|
|
Ver arquivo local `CREDENCIAIS.txt` (fora do git, entregue separadamente —
|
|
nunca colocamos senha em texto puro em um arquivo versionado, mesmo em um
|
|
Git privado). Contém: usuário/senha do `super_admin` web e as credenciais
|
|
do PostgreSQL/Redis.
|
|
|
|
## Health
|
|
|
|
```text
|
|
$ bash scripts/healthcheck.sh
|
|
docker compose ps: 8/8 containers up
|
|
/api/health: {"status":"ok","postgres":"up","redis":"up","asterisk":"up"}
|
|
Asterisk core show uptime: OK
|
|
pjsip show endpoints: OK (comando responde; sem endpoints — fixtures de teste removidos)
|
|
nftables (b2bcall_fw): ativo
|
|
```
|
|
|
|
### Aceite Asterisk (seção 93)
|
|
|
|
```text
|
|
$ asterisk -rx "core show version"
|
|
Asterisk 22.10.1 built by root @ buildkitsandbox on a x86_64 running Linux on 2026-08-27 13:32:29 UTC
|
|
|
|
$ asterisk -rx "core show uptime"
|
|
System uptime: 5 hours, 43 minutes, 19 seconds
|
|
Last reload: 6 minutes, 54 seconds
|
|
|
|
$ asterisk -rx "pjsip show endpoints"
|
|
No objects found.
|
|
(esperado: todos os troncos/ramais de teste foram removidos ao final de cada fase)
|
|
|
|
$ asterisk -rx "pjsip show contacts"
|
|
No objects found.
|
|
|
|
$ asterisk -rx "queue show"
|
|
No queues.
|
|
```
|
|
|
|
**Comunicação API → AMI → Asterisk**: validada via
|
|
`GET /api/asterisk/status` →
|
|
`{"amiControlConnection":"up","asteriskEventsHeartbeat":"up",...}`.
|
|
|
|
## Tests
|
|
|
|
```text
|
|
Build/typecheck (pnpm -r build, 7 workspaces): PASS
|
|
Lint (api, frontend): PASS
|
|
Unit tests:
|
|
apps/api 13/13 PASS
|
|
apps/dialer-worker 33/33 PASS
|
|
docker compose config: válida
|
|
docker compose ps: 8/8 up
|
|
scripts/healthcheck.sh: PASS
|
|
```
|
|
|
|
### Aceite de segurança (seção 92) — verificado ao vivo, não só por inspeção
|
|
|
|
| Item | Resultado |
|
|
|---|---|
|
|
| Nenhuma senha no Git | ✅ (`git log --all -- .env` vazio) |
|
|
| Nenhum `.env` commitado | ✅ |
|
|
| PostgreSQL não público | ✅ (`127.0.0.1:5432` apenas) |
|
|
| Redis não público | ✅ (nenhuma porta publicada) |
|
|
| AMI não público | ✅ (nftables bloqueia `ens18:5038`) |
|
|
| ARI não público | ✅ (nftables bloqueia `ens18:8088/8089`) |
|
|
| Rate limit funcionando | ✅ (7ª tentativa de login seguida → HTTP 429) |
|
|
| RBAC funcionando no backend | ✅ (papel `agent` → 403 em `/asterisk/status`, `/trunks`, `/users`) |
|
|
| Agent não acessa configuração do Asterisk | ✅ |
|
|
| Agent não eleva a própria permissão | ✅ |
|
|
| SQL injection protegida | ✅ (Prisma parametrizado em toda parte) |
|
|
| Path traversal protegido | ✅ (nenhum path de arquivo construído a partir de input do usuário) |
|
|
| Logs sem credenciais | ✅ (redação do pino confirmada, varredura real sem vazamento) |
|
|
|
|
### Prova do dialer (seção 91)
|
|
|
|
- CPS configurado nunca excedido em nenhuma janela de 1s: ✅ (`simulation-harness.spec.ts`)
|
|
- Concorrência máxima da campanha nunca excedida: ✅ (idem)
|
|
- Pacing reage/reduz quando abandono sobe: ✅ (idem + bug real corrigido durante o desenvolvimento, ver `docs/PREDICTIVE_DIALER.md`)
|
|
- Reprodutibilidade (mesma seed → mesmo resultado): ✅
|
|
- Reserva de lead atômica (sem discagem dupla): ✅ (`FOR UPDATE SKIP LOCKED`, testado na Fase 6 contra Postgres real)
|
|
- Campanha pausada não gera chamada nova: ✅ (testado na Fase 6)
|
|
- Lead suprimido não é discado: ✅ (`isSuppressed` pré-originação, testado na Fase 6)
|
|
- Campanha fora do horário não discou: ✅ (`schedule.spec.ts`, 6 testes)
|
|
- Worker reiniciado recupera operação: ⚠️ parcial — `reconciliation.ts` tem teste unitário e roda em produção a cada 60s, mas o cenário "matar o processo de verdade no meio de uma chamada" não foi exercitado nesta sessão (ver Pending).
|
|
|
|
## Pending
|
|
|
|
Itens genuinamente pendentes, nunca escondidos:
|
|
|
|
1. **Integration tests automatizados** (Postgres/Redis/AMI reais via
|
|
testcontainers ou equivalente) não existem como suíte formal — toda a
|
|
verificação de integração foi feita manualmente contra containers reais
|
|
a cada fase (real, mas não repetível em CI sem intervenção).
|
|
2. **Recuperação após kill real do worker** não foi testada nesta sessão
|
|
(só via teste unitário da lógica de reconciliação).
|
|
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~~ — 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
|
|
tela dedicada para visualizar a fila de callbacks pendentes.
|
|
6. **AMD** (detecção de secretária eletrônica) — campo existe no schema,
|
|
detecção real via app AMD do Asterisk não integrada à originação.
|
|
7. **Correlação automática CDR↔DialAttempt** para chamadas reais (não
|
|
simuladas) além do timeout de segurança de reconciliação.
|
|
8. **WebSocket real** — painéis de monitoramento usam polling
|
|
(5-15s), não um gateway WebSocket dedicado.
|
|
9. **OpenSIPS** não implantado — decisão documentada em `docs/OPENSIPS.md`
|
|
(não resolve nenhum problema real do ambiente atual de instância única).
|
|
10. **HTTPS** não configurado (rede privada, sem IP público) — passo a
|
|
passo em `docs/OPERATIONS.md`.
|
|
11. `asterisk-events`/`dialer-worker` não têm healthcheck Docker formal
|
|
(workers em background sem porta HTTP própria).
|
|
12. Rotação de `SECRETS_MASTER_KEY` não é automatizada — exigiria
|
|
redescriptografar todos os segredos de tronco/ramal manualmente.
|
|
|
|
Nenhum destes itens bloqueia o uso do sistema para o que foi pedido
|
|
(discador preditivo funcional, call center completo, frontend completo,
|
|
segurança e backup); são lacunas de robustez/automação a considerar antes
|
|
de operar com volume real de produção.
|