Files
b2bcall/docs/RELATORIO_FINAL.md
B2BCall Bootstrap 80e72881b2 feat: Fase 9/10 — métricas, scripts operacionais, callback/wrap-up e aceite final
Fase 9 (segurança e produção):
- GET /api/metrics: endpoint Prometheus com métricas reais (chamadas,
  agentes, filas, CPS por campanha), protegido por permissão
- scripts/backup.sh, restore.sh, healthcheck.sh, install.sh, update.sh —
  testados contra o ambiente real (backup.sh e healthcheck.sh rodados de
  verdade; install.sh/update.sh validados por inspeção, ambiente atual já
  provisionado)
- POST /api/agent-console/dispose: aplica disposição de chamada de verdade
  (lacuna deixada aberta desde a Fase 6), com ações CALLBACK (agenda
  retorno) e DO_NOT_CALL (suprime automaticamente)
- apps/dialer-worker/src/callback-sweep.ts: reativa leads com callback
  vencido; GET /api/callbacks para consulta
- apps/dialer-worker/src/wrap-up-sweep.ts: transição automática
  WRAP_UP -> AVAILABLE + despausa real na fila do Asterisk. Exigiu corrigir
  main.ts para conectar ao AMI mesmo em DIALER_SIMULATION=true
  (DIALER_SIMULATION deve impedir só originação de chamada, não ações
  administrativas de fila)
- nftables revisado (sem alterações necessárias)
- Documentação completa: INSTALL, OPERATIONS, BACKUP_RESTORE, SECURITY,
  DATABASE, API, ASTERISK, OPENSIPS (não implementado, motivo
  documentado), TROUBLESHOOTING
- README.md e CHANGELOG.md reescritos

Fase 10 (testes e aceite):
- Quality gate completo executado: build/typecheck (7 workspaces), lint,
  46 testes unitários, docker compose config/ps, healthcheck — tudo verde
- Aceite de segurança (seção 92): 13 itens verificados ao vivo contra o
  sistema real, não só por inspeção de código
- Aceite Asterisk (seção 93): os 5 comandos executados e documentados,
  comunicação API->AMI->Asterisk validada
- docs/RELATORIO_FINAL.md: relatório final no formato da seção 96

Todos os fixtures de teste desta fase foram removidos/desativados ao
final. Credenciais de acesso entregues separadamente em CREDENCIAIS.txt
(fora do git, nunca versionado).
2026-08-27 19:16:14 -03:00

6.8 KiB

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).

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

$ 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)

$ 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

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 não foi feita (ambiente headless) — validado via curl reproduzindo as chamadas do navegador.
  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.