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).
This commit is contained in:
94
docs/ASTERISK.md
Normal file
94
docs/ASTERISK.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# B2BCall — Asterisk
|
||||
|
||||
## Versão e módulos
|
||||
|
||||
Asterisk **22.10.1**, compilado do fonte (Debian trixie não empacota
|
||||
`asterisk`) — `infrastructure/docker/asterisk.Dockerfile`. Módulos
|
||||
habilitados: `chan_pjsip` (nunca `chan_sip`, removido/depreciado),
|
||||
`res_odbc`/`res_config_odbc` (Realtime), `app_queue`, `cdr_adaptive_odbc`,
|
||||
`cel_odbc`, AMI, ARI.
|
||||
|
||||
## Realtime (PJSIP via Postgres)
|
||||
|
||||
Objetos PJSIP (`ps_endpoints`, `ps_auths`, `ps_aors`, `ps_contacts`,
|
||||
`ps_endpoint_id_ips`, `ps_registrations`) vivem no schema `asterisk` do
|
||||
mesmo Postgres da aplicação — nunca em arquivo estático. Escritos
|
||||
exclusivamente por `apps/api/src/telephony/pjsip-realtime.service.ts`
|
||||
quando um Tronco/Ramal é criado/editado pela API.
|
||||
|
||||
- DSN ODBC: `infrastructure/asterisk/config/odbc.ini.tpl` → conexão nomeada
|
||||
`asterisk`, `ConnSettings = SET search_path TO asterisk, public;`.
|
||||
- `sorcery.conf`/`extconfig.conf` apontam os tipos PJSIP para essa conexão.
|
||||
- Depois de criar/editar um objeto, a API dispara reload seletivo via AMI
|
||||
(`pjsip reload`), nunca `core restart`.
|
||||
|
||||
## Dialplan e filas (gerados, versionados)
|
||||
|
||||
- `infrastructure/asterisk/config/extensions.conf` inclui
|
||||
`/etc/asterisk-generated/b2bcall-dialplan.conf` — gerado por
|
||||
`DialplanService` a partir de `DialplanEntry`/`DialplanVersion`
|
||||
(Postgres). Toda alteração é uma nova `DialplanVersion` com validação
|
||||
(`dialplan reload` + checagem de erro) e rollback automático se falhar.
|
||||
- `infrastructure/asterisk/config/queues.conf` inclui
|
||||
`/etc/asterisk-generated/b2bcall-queues.conf` — gerado a partir de
|
||||
`Queue` (Postgres). **Membros nunca são estáticos** — adicionados/
|
||||
removidos via AMI `QueueAdd`/`QueueRemove` no login/logout do agente
|
||||
(`AgentConsoleService`), para nunca ter duas fontes de verdade
|
||||
divergentes sobre quem está em qual fila.
|
||||
- Ambos os arquivos gerados vivem no volume Docker `dialplan-generated`,
|
||||
compartilhado entre `api` (escreve) e `asterisk` (lê + recarrega).
|
||||
- **Nunca editar esses dois arquivos gerados manualmente** — qualquer
|
||||
edição é sobrescrita na próxima publicação pela aplicação.
|
||||
|
||||
## AMI / ARI
|
||||
|
||||
- AMI: client próprio em `packages/telephony` (TCP raw, sem biblioteca de
|
||||
terceiros — o protocolo de wire do Asterisk 22 para a action `Command`
|
||||
usa headers `Output:` repetidos, não o formato legado
|
||||
`Response: Follows`/`--END COMMAND--` documentado em versões antigas).
|
||||
- Usado para: Originate, Hangup, QueueAdd/Remove, QueuePause,
|
||||
QueueStatus, ExtensionState/DeviceState, PJSIP show endpoints/contacts,
|
||||
reloads seletivos.
|
||||
- ARI: reservado para controle fino de canais/bridges quando necessário —
|
||||
não usado extensivamente nesta fase (a maior parte das operações
|
||||
administrativas é feita via AMI).
|
||||
- **Nunca expostos além de `127.0.0.1`/rede interna** — bloqueados da LAN
|
||||
por nftables mesmo estando em `network_mode: host` (ver
|
||||
`docs/ARCHITECTURE.md` §3.1 e `infrastructure/nftables/`).
|
||||
|
||||
## Comandos úteis de diagnóstico
|
||||
|
||||
```bash
|
||||
docker exec b2bcall-asterisk asterisk -rx "core show uptime"
|
||||
docker exec b2bcall-asterisk asterisk -rx "pjsip show endpoints"
|
||||
docker exec b2bcall-asterisk asterisk -rx "pjsip show registrations"
|
||||
docker exec b2bcall-asterisk asterisk -rx "queue show"
|
||||
docker exec b2bcall-asterisk asterisk -rx "dialplan show b2bcall-healthcheck"
|
||||
docker exec b2bcall-asterisk asterisk -rx "module show like odbc"
|
||||
docker exec b2bcall-asterisk asterisk -rx "odbc show all"
|
||||
```
|
||||
|
||||
Um subconjunto seguro e auditado desses comandos também é exposto via
|
||||
`GET /api/asterisk/diagnostic/allowed-commands` +
|
||||
`POST /api/asterisk/diagnostic` (allowlist explícita — nunca shell livre,
|
||||
seção 18) para uso pela interface web sem precisar SSH no servidor.
|
||||
|
||||
## Rede
|
||||
|
||||
`network_mode: host` (necessário para a faixa de portas RTP — mapear porta
|
||||
a porta em bridge Docker é inviável). Implicações e mitigação em
|
||||
`docs/ARCHITECTURE.md` §3.1.
|
||||
|
||||
## Limitações conhecidas nesta fase
|
||||
|
||||
- `res_pjsip_outbound_registration` pode logar erro no boot se nenhum
|
||||
registration estiver configurado ainda (nenhum tronco cadastrado) — não é
|
||||
um erro real, some ao cadastrar o primeiro tronco com `registration`.
|
||||
- `res_config_ldap` loga ERROR no boot (LDAP não configurado/não usado
|
||||
neste projeto) — módulo carregado por padrão pelo build, inofensivo.
|
||||
- `cdr_pgsql`/`cel_pgsql` (variante não-ODBC) não compilam nesta imagem por
|
||||
falta de `libpq-dev` — não é um problema porque `cdr_adaptive_odbc`/
|
||||
`cel_odbc` (a variante realmente usada) funcionam normalmente.
|
||||
- Nenhuma correlação automática CDR↔`DialAttempt` para chamadas **reais**
|
||||
(não simuladas) além do timeout de segurança da reconciliação — ver
|
||||
`docs/PREDICTIVE_DIALER.md`.
|
||||
Reference in New Issue
Block a user