feat: add trunks and extensions CRUD with realtime PJSIP provisioning

- apps/api/src/telephony: TelephonyModule (conexao AMI da API para
  comandos de controle) + PjsipRealtimeService (unico ponto de escrita nas
  tabelas realtime do schema 'asterisk' via Prisma $executeRaw
  parametrizado)
- apps/api/src/trunks: CRUD completo (tipos IP/AUTH/REGISTRATION), secret
  cifrado em repouso (AES-256-GCM), endpoint de teste de status via
  PJSIPShowContacts/pjsip show registration
- apps/api/src/extensions: CRUD completo, senha SIP gerada
  automaticamente, endpoint de reset, nunca reexibe a senha apos a criacao
- apps/api/src/monitoring: GET /api/monitoring/extensions com prioridade
  de cor (agente.md secao 15) a partir do ExtensionState alimentado por
  apps/asterisk-events
- health check agora reporta status real do Asterisk/AMI via heartbeat do
  asterisk-events no Redis, sem precisar de conexao AMI propria para isso

Testado ponta a ponta contra o Asterisk real: ramal e tronco criados via
API aparecem imediatamente via 'pjsip show endpoint' sem reload (realtime
funcionando), secret nunca retornado pela API, exclusao em cascata
confirmada (ps_endpoints/ps_auths/ps_aors/ps_contacts/ps_registrations).
This commit is contained in:
2026-08-27 12:58:12 -03:00
parent 6f3d731581
commit 8a41b5d2b2
21 changed files with 1221 additions and 5 deletions

10
TODO.md
View File

@@ -105,8 +105,14 @@ mestre original (`agente.md`, seções 90-93).
heartbeat para health check — testado ponta a ponta com chamada real
- [x] Schema Prisma: Trunk, Extension, ExtensionState + criptografia de
segredos AES-256-GCM (packages/shared/secret-crypto.ts)
- [ ] CRUD Troncos (com CPS máximo, ACL, teste de status)
- [ ] CRUD Ramais (senha SIP gerada, reset, status tempo real)
- [x] CRUD Troncos (IP/AUTH/REGISTRATION, CPS máximo, ACL, secret cifrado
AES-256-GCM, teste de status) — testado: criado via API, verificado
que o Asterisk enxerga o endpoint via realtime SEM reload, status
consultado via PJSIPShowContacts, exclusão em cascata confirmada
- [x] CRUD Ramais (senha SIP gerada automaticamente, nunca reexibida exceto
na criação/reset, reset endpoint) — testado igual aos troncos
- [x] GET /api/monitoring/extensions — status com prioridade de cor
(offline/available/busy; pausa e agente logado chegam na Fase 5)
- [ ] Painel visual de Ramais (WebSocket, prioridade de cores) — backend
(gateway WS) pendente; ExtensionState/pub-sub já prontos como base
- [ ] Dialplan estruturado (versionado, modo Advanced, validação+rollback)