- docs/ARCHITECTURE.md: decisoes de arquitetura (monorepo, rede Asterisk host mode, realtime PJSIP, camada de telefonia, seguranca desde o design) - TODO.md: checklist vivo de implementacao por fases - estrutura inicial do monorepo (apps/, packages/, infrastructure/, scripts/) - docker-compose.yml: postgres 17 + redis 7 com healthchecks, sem portas publicadas no host, schema 'asterisk' dedicado no Postgres - .env.example + scripts/generate-secrets.sh
3535 lines
48 KiB
Markdown
3535 lines
48 KiB
Markdown
|
|
# PROMPT MESTRE — B2BCall
|
|
|
|
Você é o arquiteto principal, engenheiro de software sênior, DevOps, DBA PostgreSQL e especialista em telefonia VoIP/Call Center responsável por projetar e implementar **do zero** uma plataforma profissional de discagem preditiva chamada:
|
|
|
|
# B2BCall
|
|
|
|
Você está trabalhando diretamente em um servidor:
|
|
|
|
* Debian 13
|
|
* Instalação limpa
|
|
* Servidor dedicado à aplicação
|
|
* Diretório principal: `/opt/b2bcall`
|
|
* Logo existente em: `/opt/b2bcall/b2bcall.png`
|
|
* Banco de dados: PostgreSQL
|
|
* Telefonia: Asterisk
|
|
* SIP: PJSIP
|
|
* Frontend e backend preferencialmente em TypeScript
|
|
* Toda a aplicação deve funcionar em containers Docker
|
|
* O Asterisk não possuirá IP público
|
|
* O Asterisk ficará atrás de um OpenSIPS
|
|
* Os troncos SIP serão acessados através de IPs privados
|
|
* Nenhuma porta SIP, AMI, ARI, PostgreSQL ou Redis deve ficar desnecessariamente exposta à Internet
|
|
|
|
A aplicação deve ser moderna, segura, modular, escalável e adequada para ambiente de produção.
|
|
|
|
---
|
|
|
|
# 1. REGRA PRINCIPAL DE EXECUÇÃO
|
|
|
|
NÃO produza apenas documentação.
|
|
|
|
NÃO faça apenas mockups.
|
|
|
|
NÃO faça somente o frontend.
|
|
|
|
NÃO pare depois de criar a estrutura inicial.
|
|
|
|
NÃO deixe funções principais marcadas como TODO.
|
|
|
|
Você deve efetivamente:
|
|
|
|
1. analisar o servidor;
|
|
2. preparar o ambiente;
|
|
3. instalar Docker e dependências necessárias;
|
|
4. criar a estrutura do projeto;
|
|
5. criar os containers;
|
|
6. configurar PostgreSQL;
|
|
7. configurar Redis se necessário;
|
|
8. instalar/configurar Asterisk;
|
|
9. construir backend;
|
|
10. construir frontend;
|
|
11. construir o motor do discador;
|
|
12. integrar o backend ao Asterisk;
|
|
13. implementar autenticação;
|
|
14. implementar RBAC/permissões;
|
|
15. implementar todas as telas solicitadas;
|
|
16. implementar métricas;
|
|
17. implementar relatórios;
|
|
18. implementar monitoramento em tempo real;
|
|
19. implementar auditoria;
|
|
20. implementar segurança;
|
|
21. criar migrations;
|
|
22. criar testes;
|
|
23. executar os testes;
|
|
24. corrigir os problemas encontrados;
|
|
25. subir o ambiente;
|
|
26. validar os health checks;
|
|
27. documentar;
|
|
28. continuar até que o sistema esteja operacional.
|
|
|
|
Trabalhe de maneira AUTÔNOMA.
|
|
|
|
Quando houver mais de uma abordagem tecnicamente válida, escolha a solução que considerar mais adequada para produção e documente a decisão.
|
|
|
|
Não interrompa o desenvolvimento a cada decisão pequena para perguntar ao usuário.
|
|
|
|
Somente pare por algo realmente impossível de resolver sem informação externa, como uma senha de uma operadora que não foi fornecida.
|
|
|
|
---
|
|
|
|
# 2. OBJETIVO DO PRODUTO
|
|
|
|
O B2BCall será uma plataforma profissional de Call Center e discagem preditiva.
|
|
|
|
Deve possuir:
|
|
|
|
* Asterisk integrado;
|
|
* ramais;
|
|
* agentes;
|
|
* filas;
|
|
* pausas;
|
|
* troncos;
|
|
* dialplans;
|
|
* campanhas;
|
|
* leads;
|
|
* discador preditivo;
|
|
* controle CPS;
|
|
* monitoramento em tempo real;
|
|
* dashboards;
|
|
* TME;
|
|
* TMA;
|
|
* relatórios;
|
|
* RBAC;
|
|
* administração completa;
|
|
* configuração do Asterisk;
|
|
* auditoria;
|
|
* segurança;
|
|
* observabilidade.
|
|
|
|
Não quero um simples sistema de “click to call”.
|
|
|
|
Quero um verdadeiro:
|
|
|
|
**Predictive Dialer / Automatic Call Distribution System.**
|
|
|
|
---
|
|
|
|
# 3. ARQUITETURA TECNOLÓGICA
|
|
|
|
Use preferencialmente um monorepo TypeScript.
|
|
|
|
Uma arquitetura recomendada é:
|
|
|
|
```text
|
|
/opt/b2bcall
|
|
├── apps
|
|
│ ├── frontend
|
|
│ ├── api
|
|
│ ├── dialer-worker
|
|
│ ├── asterisk-events
|
|
│ └── scheduler
|
|
├── packages
|
|
│ ├── database
|
|
│ ├── shared
|
|
│ ├── types
|
|
│ ├── ui
|
|
│ └── telephony
|
|
├── infrastructure
|
|
│ ├── asterisk
|
|
│ ├── nginx
|
|
│ ├── postgres
|
|
│ └── docker
|
|
├── scripts
|
|
├── docs
|
|
├── docker-compose.yml
|
|
├── .env.example
|
|
├── .gitignore
|
|
└── README.md
|
|
```
|
|
|
|
Pode adaptar a estrutura se houver justificativa técnica.
|
|
|
|
## Stack sugerida
|
|
|
|
### Frontend
|
|
|
|
* Next.js
|
|
* React
|
|
* TypeScript
|
|
* Tailwind CSS
|
|
* shadcn/ui ou componentes equivalentes
|
|
* TanStack Query
|
|
* WebSocket para dados em tempo real
|
|
|
|
### Backend
|
|
|
|
Preferencialmente:
|
|
|
|
* Node.js
|
|
* TypeScript
|
|
* NestJS
|
|
|
|
Pode utilizar Fastify como HTTP adapter.
|
|
|
|
### Banco
|
|
|
|
* PostgreSQL 17 ou versão estável compatível
|
|
* migrations obrigatórias
|
|
* índices corretamente planejados
|
|
* transactions
|
|
* constraints
|
|
* foreign keys
|
|
* JSONB apenas quando fizer sentido
|
|
|
|
### Cache/mensageria
|
|
|
|
Redis pode ser utilizado para:
|
|
|
|
* filas internas;
|
|
* locks;
|
|
* presença;
|
|
* sessões em tempo real;
|
|
* workers;
|
|
* campanhas;
|
|
* rate limit;
|
|
* eventos.
|
|
|
|
Pode utilizar BullMQ.
|
|
|
|
### Telefonia
|
|
|
|
Use:
|
|
|
|
**Asterisk 22 LTS**
|
|
|
|
com:
|
|
|
|
* PJSIP;
|
|
* AMI;
|
|
* ARI quando realmente necessário;
|
|
* CDR;
|
|
* CEL;
|
|
* queue_log;
|
|
* app_queue.
|
|
|
|
Não utilize `chan_sip`.
|
|
|
|
---
|
|
|
|
# 4. DOCKER
|
|
|
|
Toda a solução deve ser containerizada.
|
|
|
|
Criar no mínimo serviços equivalentes a:
|
|
|
|
```text
|
|
b2bcall-frontend
|
|
b2bcall-api
|
|
b2bcall-worker
|
|
b2bcall-asterisk-events
|
|
b2bcall-scheduler
|
|
b2bcall-asterisk
|
|
b2bcall-postgres
|
|
b2bcall-redis
|
|
b2bcall-nginx
|
|
```
|
|
|
|
Avalie cuidadosamente a rede do Asterisk.
|
|
|
|
Como RTP possui uma quantidade significativa de portas UDP, considere utilizar `network_mode: host` para o container do Asterisk caso isso simplifique e torne a operação mais confiável.
|
|
|
|
Se utilizar host network, documente detalhadamente os impactos.
|
|
|
|
Os outros containers devem permanecer em redes Docker privadas sempre que possível.
|
|
|
|
PostgreSQL e Redis não devem ficar expostos publicamente.
|
|
|
|
Adicionar:
|
|
|
|
* restart policies;
|
|
* health checks;
|
|
* volumes persistentes;
|
|
* logging;
|
|
* dependency checks;
|
|
* resource considerations.
|
|
|
|
---
|
|
|
|
# 5. TOPOLOGIA SIP
|
|
|
|
A arquitetura é:
|
|
|
|
```text
|
|
INTERNET
|
|
|
|
|
[ OpenSIPS ]
|
|
|
|
|
rede SIP privada
|
|
|
|
|
[ Asterisk ]
|
|
|
|
|
[ B2BCall ]
|
|
```
|
|
|
|
E para operadoras:
|
|
|
|
```text
|
|
Asterisk
|
|
|
|
|
rede privada
|
|
|
|
|
Troncos SIP
|
|
```
|
|
|
|
O Asterisk NÃO possui IP público.
|
|
|
|
Nunca assuma que ele precisa registrar troncos pela Internet.
|
|
|
|
Permitir troncos:
|
|
|
|
* IP Authentication;
|
|
* Username/password quando necessário;
|
|
* PJSIP registration quando necessário.
|
|
|
|
Permitir configuração de:
|
|
|
|
* IP;
|
|
* porta;
|
|
* transporte;
|
|
* codecs;
|
|
* DTMF;
|
|
* From User;
|
|
* From Domain;
|
|
* Contact User;
|
|
* Outbound Proxy;
|
|
* identificação por IP;
|
|
* autenticação;
|
|
* caller ID;
|
|
* limites;
|
|
* context;
|
|
* qualify;
|
|
* timers.
|
|
|
|
Criar ACLs e configurações de segurança.
|
|
|
|
AMI e ARI jamais deverão estar publicamente acessíveis.
|
|
|
|
---
|
|
|
|
# 6. ASTERISK REALTIME
|
|
|
|
Avalie utilizar Asterisk Realtime + ODBC/PostgreSQL para objetos PJSIP.
|
|
|
|
Exemplos:
|
|
|
|
* ps_endpoints
|
|
* ps_auths
|
|
* ps_aors
|
|
* ps_contacts
|
|
* ps_endpoint_id_ips
|
|
* ps_registrations
|
|
|
|
O banco de aplicação deve continuar possuindo seu próprio modelo de domínio.
|
|
|
|
Não misture indiscriminadamente tabelas da aplicação com tabelas internas do Asterisk.
|
|
|
|
Uma boa estratégia é utilizar schemas separados:
|
|
|
|
```text
|
|
public/application
|
|
asterisk
|
|
```
|
|
|
|
ou configuração equivalente.
|
|
|
|
---
|
|
|
|
# 7. INTEGRAÇÃO ASTERISK
|
|
|
|
O backend deve possuir uma camada:
|
|
|
|
```text
|
|
TelephonyProvider
|
|
```
|
|
|
|
e implementação:
|
|
|
|
```text
|
|
AsteriskTelephonyProvider
|
|
```
|
|
|
|
Não espalhe comandos AMI dentro de controllers da aplicação.
|
|
|
|
Criar serviço central responsável por:
|
|
|
|
* Originate;
|
|
* Hangup;
|
|
* QueuePause;
|
|
* QueueAdd;
|
|
* QueueRemove;
|
|
* ExtensionState;
|
|
* DeviceState;
|
|
* QueueStatus;
|
|
* PJSIPShowEndpoints;
|
|
* PJSIPShowContacts;
|
|
* reload;
|
|
* eventos;
|
|
* canais;
|
|
* bridges;
|
|
* chamadas.
|
|
|
|
Utilize AMI principalmente para eventos administrativos e controle.
|
|
|
|
Utilize ARI quando o controle de canais/bridges exigir ARI.
|
|
|
|
---
|
|
|
|
# 8. EVENTOS EM TEMPO REAL
|
|
|
|
Criar serviço dedicado que permaneça conectado ao AMI.
|
|
|
|
Ele deve consumir eventos como:
|
|
|
|
* Newchannel;
|
|
* DialBegin;
|
|
* DialEnd;
|
|
* BridgeEnter;
|
|
* BridgeLeave;
|
|
* Hangup;
|
|
* Newstate;
|
|
* DeviceStateChange;
|
|
* QueueMemberStatus;
|
|
* QueueMemberPause;
|
|
* AgentConnect;
|
|
* AgentComplete;
|
|
* QueueCallerJoin;
|
|
* QueueCallerLeave;
|
|
* QueueCallerAbandon;
|
|
* ContactStatus;
|
|
* PeerStatus/PJSIP equivalentes.
|
|
|
|
Normalizar esses eventos.
|
|
|
|
Persistir eventos importantes.
|
|
|
|
Transmitir dados do estado atual para o frontend utilizando WebSocket.
|
|
|
|
Nunca fazer o frontend executar polling a cada segundo no Asterisk.
|
|
|
|
---
|
|
|
|
# 9. AUTENTICAÇÃO
|
|
|
|
Criar autenticação profissional.
|
|
|
|
Login:
|
|
|
|
* e-mail;
|
|
* senha.
|
|
|
|
Implementar:
|
|
|
|
* Argon2id para hash;
|
|
* access token;
|
|
* refresh token;
|
|
* cookies HttpOnly quando aplicável;
|
|
* Secure;
|
|
* SameSite;
|
|
* rotação de refresh token;
|
|
* logout;
|
|
* revogação de sessão;
|
|
* recuperação de senha;
|
|
* token de recuperação com validade;
|
|
* auditoria;
|
|
* proteção contra enumeração de usuários.
|
|
|
|
Nunca armazenar senha em texto puro.
|
|
|
|
Nunca armazenar JWT em localStorage se puder ser evitado.
|
|
|
|
---
|
|
|
|
# 10. RATE LIMIT
|
|
|
|
É obrigatório implementar proteção contra força bruta.
|
|
|
|
Exemplo:
|
|
|
|
```text
|
|
5 tentativas de login / minuto / IP
|
|
```
|
|
|
|
com bloqueio progressivo.
|
|
|
|
Implementar também limites por:
|
|
|
|
* IP;
|
|
* usuário;
|
|
* endpoint sensível.
|
|
|
|
Registrar tentativas excessivas no audit log.
|
|
|
|
Redis poderá ser utilizado para rate limiting distribuído.
|
|
|
|
---
|
|
|
|
# 11. RBAC — PERMISSÕES
|
|
|
|
Criar RBAC completo.
|
|
|
|
Não faça simplesmente:
|
|
|
|
```text
|
|
if user.role == admin
|
|
```
|
|
|
|
Criar:
|
|
|
|
```text
|
|
users
|
|
roles
|
|
permissions
|
|
user_roles
|
|
role_permissions
|
|
```
|
|
|
|
Perfis iniciais:
|
|
|
|
```text
|
|
super_admin
|
|
admin
|
|
supervisor
|
|
agent
|
|
```
|
|
|
|
Porém os níveis NÃO devem ser fixos.
|
|
|
|
O `super_admin` precisa possuir uma tela de:
|
|
|
|
**Perfis e Permissões**
|
|
|
|
onde possa definir exatamente o que cada perfil pode acessar.
|
|
|
|
Exemplos:
|
|
|
|
```text
|
|
dashboard.view
|
|
|
|
trunks.view
|
|
trunks.create
|
|
trunks.update
|
|
trunks.delete
|
|
|
|
extensions.view
|
|
extensions.create
|
|
extensions.update
|
|
extensions.delete
|
|
|
|
dialplans.view
|
|
dialplans.create
|
|
dialplans.update
|
|
dialplans.delete
|
|
|
|
queues.view
|
|
queues.create
|
|
queues.update
|
|
queues.delete
|
|
|
|
agents.view
|
|
agents.create
|
|
agents.update
|
|
agents.delete
|
|
|
|
campaigns.view
|
|
campaigns.create
|
|
campaigns.start
|
|
campaigns.pause
|
|
campaigns.stop
|
|
campaigns.update
|
|
campaigns.delete
|
|
|
|
reports.view
|
|
reports.export
|
|
|
|
monitoring.view
|
|
|
|
asterisk.view
|
|
asterisk.configure
|
|
asterisk.reload
|
|
|
|
users.view
|
|
users.create
|
|
users.update
|
|
|
|
roles.manage
|
|
|
|
audit.view
|
|
|
|
settings.manage
|
|
```
|
|
|
|
O frontend deve esconder funcionalidades sem permissão.
|
|
|
|
MAS:
|
|
|
|
**a segurança sempre deve ser validada novamente pelo backend.**
|
|
|
|
Nunca confie apenas no frontend.
|
|
|
|
---
|
|
|
|
# 12. AUDITORIA
|
|
|
|
Criar `audit_logs`.
|
|
|
|
Registrar no mínimo:
|
|
|
|
* login;
|
|
* logout;
|
|
* login inválido;
|
|
* criação;
|
|
* edição;
|
|
* exclusão;
|
|
* início de campanha;
|
|
* pausa de campanha;
|
|
* encerramento de campanha;
|
|
* alteração de trunk;
|
|
* alteração de ramal;
|
|
* alteração de fila;
|
|
* alteração de agente;
|
|
* alteração do Asterisk;
|
|
* reload;
|
|
* alteração de permissões.
|
|
|
|
Guardar:
|
|
|
|
```text
|
|
user_id
|
|
action
|
|
entity_type
|
|
entity_id
|
|
before
|
|
after
|
|
ip_address
|
|
user_agent
|
|
created_at
|
|
```
|
|
|
|
Para campos sensíveis, nunca salvar segredos abertos no `before/after`.
|
|
|
|
---
|
|
|
|
# 13. TELA DE TRONCOS
|
|
|
|
Criar menu:
|
|
|
|
**Telefonia → Troncos**
|
|
|
|
Permitir:
|
|
|
|
* adicionar;
|
|
* editar;
|
|
* ativar;
|
|
* desativar;
|
|
* duplicar;
|
|
* excluir;
|
|
* testar.
|
|
|
|
Campos:
|
|
|
|
* Nome
|
|
* Tecnologia: PJSIP
|
|
* Tipo:
|
|
|
|
* IP
|
|
* autenticação
|
|
* registration
|
|
* Host
|
|
* Porta
|
|
* Transporte
|
|
* Username
|
|
* Password
|
|
* From User
|
|
* From Domain
|
|
* Contact User
|
|
* Outbound Proxy
|
|
* Context
|
|
* Caller ID
|
|
* Codecs
|
|
* DTMF mode
|
|
* Qualify
|
|
* Max Channels
|
|
* CPS máximo
|
|
* ACL
|
|
* IPs permitidos
|
|
* Enabled
|
|
|
|
Mostrar status:
|
|
|
|
```text
|
|
ONLINE
|
|
OFFLINE
|
|
UNREACHABLE
|
|
UNKNOWN
|
|
```
|
|
|
|
Nunca mostrar a senha completa depois de salva.
|
|
|
|
---
|
|
|
|
# 14. TELA DE RAMAIS
|
|
|
|
Criar:
|
|
|
|
**Telefonia → Ramais**
|
|
|
|
Campos:
|
|
|
|
* número;
|
|
* nome;
|
|
* senha SIP;
|
|
* caller ID;
|
|
* contexto;
|
|
* codecs;
|
|
* transporte;
|
|
* max contacts;
|
|
* qualify;
|
|
* enabled.
|
|
|
|
Gerar senha SIP segura automaticamente.
|
|
|
|
Permitir resetar a senha.
|
|
|
|
Mostrar status em tempo real.
|
|
|
|
---
|
|
|
|
# 15. PAINEL VISUAL DE RAMAIS
|
|
|
|
Criar uma tela específica:
|
|
|
|
**Monitoramento → Ramais**
|
|
|
|
Cada ramal deverá aparecer em um card/quadrado.
|
|
|
|
Exemplo:
|
|
|
|
```text
|
|
┌──────────────────┐
|
|
│ RAMAL 1001 │
|
|
│ João Silva │
|
|
│ DISPONÍVEL │
|
|
│ 00:04:32 │
|
|
└──────────────────┘
|
|
```
|
|
|
|
Utilizar EXATAMENTE esta convenção principal:
|
|
|
|
```text
|
|
CINZA = ramal offline
|
|
VERDE = ramal disponível
|
|
LARANJA = ramal ocupado
|
|
AZUL = agente logado
|
|
VERMELHO = agente em pausa
|
|
```
|
|
|
|
Como alguns estados podem coexistir, implementar a seguinte prioridade visual:
|
|
|
|
```text
|
|
PAUSA
|
|
↓
|
|
EM CHAMADA
|
|
↓
|
|
AGENTE LOGADO
|
|
↓
|
|
REGISTRADO/DISPONÍVEL
|
|
↓
|
|
OFFLINE
|
|
```
|
|
|
|
Ou seja:
|
|
|
|
```text
|
|
pausa -> vermelho
|
|
ocupado -> laranja
|
|
agente -> azul
|
|
disponível -> verde
|
|
offline -> cinza
|
|
```
|
|
|
|
Mostrar opcionalmente:
|
|
|
|
* agente;
|
|
* ramal;
|
|
* fila;
|
|
* duração do estado;
|
|
* duração da chamada;
|
|
* campanha atual.
|
|
|
|
Atualização via WebSocket.
|
|
|
|
---
|
|
|
|
# 16. AGENTES
|
|
|
|
Separar claramente:
|
|
|
|
**usuário da aplicação**
|
|
|
|
de:
|
|
|
|
**agente de Call Center**
|
|
|
|
Uma pessoa pode possuir usuário e agente associados.
|
|
|
|
Criar:
|
|
|
|
```text
|
|
agents
|
|
agent_sessions
|
|
```
|
|
|
|
Campos do agente:
|
|
|
|
* código;
|
|
* nome;
|
|
* usuário associado;
|
|
* ativo;
|
|
* filas;
|
|
* campanhas permitidas;
|
|
* ramal atual.
|
|
|
|
Permitir login dinâmico de agente.
|
|
|
|
---
|
|
|
|
# 17. TELA DO AGENTE
|
|
|
|
Após login, o agente deve possuir uma interface simplificada.
|
|
|
|
Mostrar:
|
|
|
|
```text
|
|
Agente
|
|
Ramal
|
|
Fila
|
|
Campanha
|
|
Estado
|
|
Tempo no estado
|
|
Chamada atual
|
|
Telefone
|
|
Nome do lead
|
|
```
|
|
|
|
Botões:
|
|
|
|
```text
|
|
DISPONÍVEL
|
|
PAUSA
|
|
FINALIZAR PAUSA
|
|
```
|
|
|
|
Quando clicar em PAUSA, abrir os motivos cadastrados.
|
|
|
|
Exemplo:
|
|
|
|
```text
|
|
Banheiro
|
|
Almoço
|
|
Lanche
|
|
Reunião
|
|
Treinamento
|
|
Suporte
|
|
Particular
|
|
```
|
|
|
|
Registrar:
|
|
|
|
* início;
|
|
* fim;
|
|
* duração;
|
|
* motivo;
|
|
* usuário;
|
|
* agente;
|
|
* ramal.
|
|
|
|
O agente deve conseguir logar e deslogar das filas conforme suas permissões.
|
|
|
|
---
|
|
|
|
# 18. CADASTRO DE PAUSAS
|
|
|
|
Criar:
|
|
|
|
**Call Center → Motivos de Pausa**
|
|
|
|
Campos:
|
|
|
|
```text
|
|
Nome
|
|
Código
|
|
Descrição
|
|
Tempo máximo opcional
|
|
Remunerada SIM/NÃO
|
|
Ativa SIM/NÃO
|
|
```
|
|
|
|
Permitir relatórios de pausas posteriormente.
|
|
|
|
---
|
|
|
|
# 19. FILAS
|
|
|
|
Criar:
|
|
|
|
**Call Center → Filas**
|
|
|
|
Configurar:
|
|
|
|
* Nome
|
|
* Número
|
|
* Strategy
|
|
* Timeout
|
|
* Retry
|
|
* Wrap-up time
|
|
* Max length
|
|
* Music on Hold
|
|
* Announce
|
|
* Service Level
|
|
* Auto Fill
|
|
* Ring in use
|
|
* Weight
|
|
* Members
|
|
|
|
Strategies:
|
|
|
|
```text
|
|
ringall
|
|
leastrecent
|
|
fewestcalls
|
|
random
|
|
rrmemory
|
|
rrordered
|
|
linear
|
|
wrandom
|
|
```
|
|
|
|
Mostrar explicação amigável de cada strategy na interface.
|
|
|
|
---
|
|
|
|
# 20. MONITORAMENTO DE FILAS
|
|
|
|
Criar:
|
|
|
|
**Monitoramento → Filas**
|
|
|
|
Cada fila deve mostrar em tempo real:
|
|
|
|
* chamadas aguardando;
|
|
* agentes logados;
|
|
* agentes disponíveis;
|
|
* agentes ocupados;
|
|
* agentes pausados;
|
|
* agentes offline;
|
|
* maior tempo de espera atual;
|
|
* TME;
|
|
* TMA;
|
|
* abandonos;
|
|
* chamadas atendidas;
|
|
* service level;
|
|
* taxa de abandono.
|
|
|
|
Permitir expandir uma fila e visualizar agentes individualmente.
|
|
|
|
---
|
|
|
|
# 21. DIALPLAN
|
|
|
|
Criar:
|
|
|
|
**Telefonia → Dialplan**
|
|
|
|
Não criar somente um textarea.
|
|
|
|
Criar editor estruturado permitindo:
|
|
|
|
```text
|
|
Context
|
|
Extension
|
|
Priority
|
|
Application
|
|
Arguments
|
|
Enabled
|
|
Order
|
|
```
|
|
|
|
Por exemplo:
|
|
|
|
```text
|
|
Context: outbound
|
|
Extension: _X.
|
|
Application: Dial
|
|
Arguments: PJSIP/${EXTEN}@trunk01
|
|
```
|
|
|
|
Também disponibilizar um modo:
|
|
|
|
**Advanced**
|
|
|
|
somente para `super_admin` ou permissão equivalente.
|
|
|
|
Antes de aplicar um dialplan:
|
|
|
|
1. gerar nova configuração;
|
|
2. validar;
|
|
3. manter backup;
|
|
4. tentar reload seguro;
|
|
5. verificar resultado;
|
|
6. caso inválido, não ativar;
|
|
7. permitir rollback.
|
|
|
|
Versionar alterações.
|
|
|
|
Criar:
|
|
|
|
```text
|
|
dialplan_versions
|
|
```
|
|
|
|
---
|
|
|
|
# 22. ADMINISTRAÇÃO DO ASTERISK
|
|
|
|
Criar menu:
|
|
|
|
**Sistema → Asterisk**
|
|
|
|
Quero uma interface de administração suficientemente completa para gerenciar os parâmetros necessários ao B2BCall.
|
|
|
|
Separar por abas.
|
|
|
|
## Geral
|
|
|
|
* system name;
|
|
* language;
|
|
* default context;
|
|
* timezone;
|
|
* sounds;
|
|
* MOH.
|
|
|
|
## PJSIP
|
|
|
|
* transports;
|
|
* UDP/TCP/TLS;
|
|
* bind;
|
|
* local_net;
|
|
* external signaling;
|
|
* external media;
|
|
* timers;
|
|
* codecs;
|
|
* endpoint defaults.
|
|
|
|
## RTP
|
|
|
|
* RTP start;
|
|
* RTP end;
|
|
* ICE se necessário;
|
|
* symmetric RTP;
|
|
* configurações relevantes.
|
|
|
|
## Filas
|
|
|
|
Parâmetros globais.
|
|
|
|
## CDR
|
|
|
|
Configuração.
|
|
|
|
## CEL
|
|
|
|
Configuração.
|
|
|
|
## Logs
|
|
|
|
Configuração e nível de log.
|
|
|
|
## AMI
|
|
|
|
Exibir STATUS da integração.
|
|
|
|
Não mostrar senha AMI aberta.
|
|
|
|
## ARI
|
|
|
|
Exibir STATUS da integração.
|
|
|
|
## Modules
|
|
|
|
Listar módulos carregados.
|
|
|
|
## Diagnóstico
|
|
|
|
Permitir executar comandos seguros e previamente permitidos como:
|
|
|
|
```text
|
|
core show uptime
|
|
core show channels
|
|
pjsip show endpoints
|
|
pjsip show contacts
|
|
queue show
|
|
module show
|
|
```
|
|
|
|
NÃO implemente uma shell Linux arbitrária pela interface web.
|
|
|
|
Isso seria uma vulnerabilidade crítica.
|
|
|
|
---
|
|
|
|
# 23. VERSIONAMENTO DAS CONFIGURAÇÕES DO ASTERISK
|
|
|
|
Toda alteração gerada pela aplicação deve possuir versão.
|
|
|
|
Criar algo como:
|
|
|
|
```text
|
|
asterisk_config_versions
|
|
```
|
|
|
|
Guardar:
|
|
|
|
* usuário;
|
|
* data;
|
|
* tipo;
|
|
* configuração anterior;
|
|
* nova configuração;
|
|
* status;
|
|
* resultado do reload.
|
|
|
|
Disponibilizar:
|
|
|
|
**Rollback**
|
|
|
|
para versões anteriores.
|
|
|
|
---
|
|
|
|
# 24. CAMPANHAS
|
|
|
|
Criar:
|
|
|
|
**Discador → Campanhas**
|
|
|
|
Campos mínimos:
|
|
|
|
```text
|
|
Nome
|
|
Descrição
|
|
Fila
|
|
Tronco
|
|
Caller ID
|
|
Dialplan/context
|
|
Status
|
|
Data inicial
|
|
Data final
|
|
Dias da semana
|
|
Horário inicial
|
|
Horário final
|
|
Timezone
|
|
CPS
|
|
Máximo de chamadas simultâneas
|
|
Pacing inicial
|
|
Pacing mínimo
|
|
Pacing máximo
|
|
Taxa alvo de abandono
|
|
Tempo máximo aguardando agente
|
|
Tempo de ring
|
|
Número máximo de tentativas
|
|
Intervalo entre tentativas
|
|
Retry BUSY
|
|
Retry NO ANSWER
|
|
Retry CONGESTION
|
|
AMD ligado/desligado
|
|
```
|
|
|
|
Status:
|
|
|
|
```text
|
|
DRAFT
|
|
READY
|
|
RUNNING
|
|
PAUSED
|
|
DRAINING
|
|
STOPPED
|
|
COMPLETED
|
|
```
|
|
|
|
Botões:
|
|
|
|
```text
|
|
INICIAR
|
|
PAUSAR
|
|
RETOMAR
|
|
PARAR
|
|
DRENAR
|
|
```
|
|
|
|
`DRAINING` significa:
|
|
|
|
* não originar novas chamadas;
|
|
* deixar as existentes terminarem.
|
|
|
|
---
|
|
|
|
# 25. CPS — CALLS PER SECOND
|
|
|
|
CPS é requisito obrigatório.
|
|
|
|
Cada campanha deve possuir:
|
|
|
|
```text
|
|
campaign.max_cps
|
|
```
|
|
|
|
Cada trunk também:
|
|
|
|
```text
|
|
trunk.max_cps
|
|
```
|
|
|
|
O limite real deve ser:
|
|
|
|
```text
|
|
min(campaign.max_cps, trunk.available_cps)
|
|
```
|
|
|
|
Implementar token bucket ou algoritmo equivalente.
|
|
|
|
Não pode simplesmente executar um loop com `sleep`.
|
|
|
|
Tem que funcionar de maneira correta mesmo com múltiplos workers.
|
|
|
|
Utilize Redis para coordenação distribuída se necessário.
|
|
|
|
---
|
|
|
|
# 26. LEADS
|
|
|
|
Cada campanha possuirá leads.
|
|
|
|
Criar tabela `leads`.
|
|
|
|
Campos mínimos:
|
|
|
|
```text
|
|
id
|
|
campaign_id
|
|
name
|
|
phone
|
|
normalized_phone
|
|
status
|
|
attempt_count
|
|
last_attempt_at
|
|
next_attempt_at
|
|
last_result
|
|
created_at
|
|
updated_at
|
|
```
|
|
|
|
Permitir dados adicionais:
|
|
|
|
```text
|
|
custom_fields JSONB
|
|
```
|
|
|
|
Status possíveis:
|
|
|
|
```text
|
|
NEW
|
|
READY
|
|
RESERVED
|
|
DIALING
|
|
RINGING
|
|
ANSWERED
|
|
CONNECTED_AGENT
|
|
BUSY
|
|
NO_ANSWER
|
|
FAILED
|
|
INVALID
|
|
VOICEMAIL
|
|
CALLBACK
|
|
COMPLETED
|
|
DO_NOT_CALL
|
|
MAX_ATTEMPTS
|
|
```
|
|
|
|
---
|
|
|
|
# 27. IMPORTAÇÃO CSV
|
|
|
|
Criar na campanha:
|
|
|
|
**Importar Leads**
|
|
|
|
Formato mínimo:
|
|
|
|
```csv
|
|
nome,telefone
|
|
Joao Silva,48999999999
|
|
Maria Souza,11999999999
|
|
```
|
|
|
|
Interface deve permitir:
|
|
|
|
1. upload;
|
|
2. detectar delimitador;
|
|
3. preview;
|
|
4. mapear colunas;
|
|
5. validar;
|
|
6. normalizar telefones;
|
|
7. detectar duplicados;
|
|
8. importar.
|
|
|
|
Mostrar:
|
|
|
|
```text
|
|
Total: 10.000
|
|
Válidos: 9.850
|
|
Inválidos: 100
|
|
Duplicados: 50
|
|
```
|
|
|
|
Permitir baixar CSV dos registros rejeitados.
|
|
|
|
Não carregar arquivo gigantesco inteiro na memória.
|
|
|
|
Faça processamento streaming/batch.
|
|
x
|
|
---
|
|
|
|
# 28. NORMALIZAÇÃO DE TELEFONE
|
|
|
|
Criar serviço dedicado de normalização.
|
|
|
|
Não espalhar regexes pelo código.
|
|
|
|
Preparar inicialmente para números brasileiros.
|
|
|
|
Guardar:
|
|
|
|
```text
|
|
phone_original
|
|
phone_normalized
|
|
```
|
|
|
|
Arquitetura deve permitir suporte futuro a E.164 internacional.
|
|
|
|
---
|
|
|
|
# 29. LISTA DE SUPRESSÃO
|
|
|
|
Implementar:
|
|
|
|
**Do Not Call / Lista de Bloqueio**
|
|
|
|
Uma campanha não deve discar um número presente nessa lista.
|
|
|
|
Criar:
|
|
|
|
```text
|
|
suppression_list
|
|
```
|
|
|
|
Permitir:
|
|
|
|
* adicionar manualmente;
|
|
* importar CSV;
|
|
* pesquisar;
|
|
* remover com permissão;
|
|
* informar motivo;
|
|
* auditoria.
|
|
|
|
Antes de originar:
|
|
|
|
```text
|
|
CHECK SUPPRESSION
|
|
```
|
|
|
|
obrigatoriamente.
|
|
|
|
---
|
|
|
|
# 30. MOTOR DO DISCADOR PREDITIVO
|
|
|
|
Este é um dos componentes MAIS IMPORTANTES do projeto.
|
|
|
|
NÃO implemente simplesmente:
|
|
|
|
```text
|
|
for lead:
|
|
originate()
|
|
```
|
|
|
|
Isso NÃO é discador preditivo.
|
|
|
|
Criar um serviço:
|
|
|
|
```text
|
|
PredictiveDialerEngine
|
|
```
|
|
|
|
responsável por decidir continuamente quantas chamadas devem ser originadas.
|
|
|
|
Deve considerar:
|
|
|
|
* agentes logados;
|
|
* agentes disponíveis;
|
|
* agentes ocupados;
|
|
* agentes em wrap-up;
|
|
* agentes pausados;
|
|
* chamadas atualmente discando;
|
|
* chamadas tocando;
|
|
* chamadas atendidas aguardando agente;
|
|
* answer rate histórico;
|
|
* taxa de chamadas ocupadas;
|
|
* taxa de não atendimento;
|
|
* tempo médio até atendimento;
|
|
* TMA;
|
|
* agentes que provavelmente ficarão disponíveis;
|
|
* abandono recente;
|
|
* CPS disponível;
|
|
* limite de concorrência;
|
|
* pacing configurado.
|
|
|
|
---
|
|
|
|
# 31. ALGORITMO PREDITIVO
|
|
|
|
Implementar inicialmente um algoritmo conservador e adaptativo.
|
|
|
|
Mantenha estatísticas por campanha.
|
|
|
|
Exemplo:
|
|
|
|
```text
|
|
answer_probability
|
|
average_answer_delay
|
|
average_talk_time
|
|
abandon_rate
|
|
available_agents
|
|
busy_agents
|
|
dialing_calls
|
|
ringing_calls
|
|
```
|
|
|
|
Utilize EWMA ou método estatístico equivalente para evitar variações violentas.
|
|
|
|
Calcular aproximadamente:
|
|
|
|
```text
|
|
expected_agent_supply =
|
|
agentes_disponiveis
|
|
+
|
|
agentes_com_probabilidade_de_liberacao_no_horizonte
|
|
```
|
|
|
|
Depois estimar:
|
|
|
|
```text
|
|
expected_answers = calls_to_dial * answer_probability
|
|
```
|
|
|
|
e ajustar para que:
|
|
|
|
```text
|
|
expected_answers ~= capacidade prevista de agentes
|
|
```
|
|
|
|
Adicionar multiplicador:
|
|
|
|
```text
|
|
pacing_factor
|
|
```
|
|
|
|
Porém sempre respeitando:
|
|
|
|
```text
|
|
CPS
|
|
max_concurrent_calls
|
|
max_pacing
|
|
max_abandon_rate
|
|
available_agents
|
|
trunk capacity
|
|
campaign schedule
|
|
```
|
|
|
|
---
|
|
|
|
# 32. PREVISÃO DE LIBERAÇÃO DE AGENTES
|
|
|
|
Para tornar o discador realmente preditivo, utilize:
|
|
|
|
```text
|
|
TMA histórico
|
|
tempo atual da chamada
|
|
distribuição histórica de duração
|
|
```
|
|
|
|
para estimar quais agentes podem ficar disponíveis dentro de um horizonte curto.
|
|
|
|
Não precisa construir machine learning.
|
|
|
|
Uma abordagem estatística eficiente, explicável e determinística é preferível inicialmente.
|
|
|
|
Documentar detalhadamente o algoritmo em:
|
|
|
|
```text
|
|
docs/PREDICTIVE_DIALER.md
|
|
```
|
|
|
|
---
|
|
|
|
# 33. CONTROLE DE ABANDONO
|
|
|
|
O motor deve possuir proteção contra abandono excessivo.
|
|
|
|
Se:
|
|
|
|
```text
|
|
abandon_rate > target_abandon_rate
|
|
```
|
|
|
|
o pacing deve cair automaticamente.
|
|
|
|
Se subir muito:
|
|
|
|
```text
|
|
pacing -> modo conservador
|
|
```
|
|
|
|
Se necessário:
|
|
|
|
```text
|
|
suspender novas originações
|
|
```
|
|
|
|
Nunca desenhar o sistema para originar milhares de chamadas sem agentes com o objetivo de verificar se números atendem.
|
|
|
|
A intenção do discador é estabelecer comunicação real entre lead e agente.
|
|
|
|
---
|
|
|
|
# 34. PROTEÇÃO REGULATÓRIA / COMPLIANCE
|
|
|
|
Criar uma área:
|
|
|
|
**Sistema → Compliance de Chamadas**
|
|
|
|
Não hardcode regras de uma única legislação dentro do motor.
|
|
|
|
Criar parâmetros configuráveis.
|
|
|
|
Registrar:
|
|
|
|
```text
|
|
total_calls
|
|
answered_calls
|
|
short_calls
|
|
abandoned_calls
|
|
calls_per_number
|
|
calls_per_day
|
|
calls_per_month
|
|
```
|
|
|
|
Criar alertas relacionados a:
|
|
|
|
* volume excessivo;
|
|
* chamadas curtas;
|
|
* abandono;
|
|
* excesso de tentativas;
|
|
* horário permitido;
|
|
* supressão;
|
|
* caller ID.
|
|
|
|
Para operação brasileira, preparar indicadores considerando que chamadas de curta duração são particularmente relevantes para fiscalização.
|
|
|
|
Adicionar suporte de configuração de identificação/caller ID apropriado para campanhas de telemarketing, inclusive numeração 0303 quando aplicável ao caso de uso.
|
|
|
|
Adicionar contador mensal para identificar operações de alto volume que possam exigir mecanismos adicionais de autenticação de chamadas pela rede.
|
|
|
|
O sistema deve AJUDAR a cumprir regras.
|
|
|
|
Nunca implementar funcionalidades destinadas a burlar mecanismos antispam, autenticação, identificação de origem ou bloqueios das operadoras.
|
|
|
|
---
|
|
|
|
# 35. RESERVA CONCORRENTE DE LEADS
|
|
|
|
É obrigatório evitar que dois workers disquem para o mesmo lead.
|
|
|
|
Utilizar mecanismo transacional como:
|
|
|
|
```sql
|
|
SELECT ...
|
|
FOR UPDATE SKIP LOCKED
|
|
```
|
|
|
|
ou solução equivalente.
|
|
|
|
Transição:
|
|
|
|
```text
|
|
READY
|
|
↓
|
|
RESERVED
|
|
↓
|
|
DIALING
|
|
```
|
|
|
|
Tem que ser atômica.
|
|
|
|
Implementar timeout de reservation para recuperar leads caso um worker morra.
|
|
|
|
---
|
|
|
|
# 36. IDEMPOTÊNCIA
|
|
|
|
Originação deve possuir:
|
|
|
|
```text
|
|
attempt_id
|
|
call_id
|
|
uniqueid
|
|
linkedid
|
|
```
|
|
|
|
Nunca originar novamente uma tentativa já confirmada simplesmente porque houve timeout da API.
|
|
|
|
Construir chamadas como state machine.
|
|
|
|
Exemplo:
|
|
|
|
```text
|
|
CREATED
|
|
RESERVED
|
|
ORIGINATING
|
|
RINGING
|
|
ANSWERED
|
|
QUEUED
|
|
AGENT_CONNECTED
|
|
COMPLETED
|
|
FAILED
|
|
```
|
|
|
|
Persistir as transições relevantes.
|
|
|
|
---
|
|
|
|
# 37. CALL FLOW PREDITIVO
|
|
|
|
Fluxo esperado:
|
|
|
|
```text
|
|
Lead
|
|
↓
|
|
PredictiveDialer
|
|
↓
|
|
CPS limiter
|
|
↓
|
|
Asterisk Originate
|
|
↓
|
|
Trunk
|
|
↓
|
|
Destino
|
|
```
|
|
|
|
Quando a chamada atende:
|
|
|
|
```text
|
|
ANSWER
|
|
↓
|
|
opcional AMD
|
|
↓
|
|
humano
|
|
↓
|
|
Fila Asterisk
|
|
↓
|
|
Agente disponível
|
|
↓
|
|
Bridge
|
|
```
|
|
|
|
Persistir todos os timestamps.
|
|
|
|
---
|
|
|
|
# 38. AMD
|
|
|
|
Adicionar Answering Machine Detection como recurso OPCIONAL.
|
|
|
|
Nunca deixar AMD obrigatório.
|
|
|
|
Configurar por campanha.
|
|
|
|
Possíveis resultados:
|
|
|
|
```text
|
|
HUMAN
|
|
MACHINE
|
|
NOT_SURE
|
|
HANGUP
|
|
```
|
|
|
|
Criar parâmetros avançados apenas para administrador.
|
|
|
|
Registrar resultado para posterior otimização.
|
|
|
|
---
|
|
|
|
# 39. AFTER CALL / WRAP-UP
|
|
|
|
Implementar:
|
|
|
|
```text
|
|
wrap_up_time
|
|
```
|
|
|
|
Durante wrap-up o agente não deve ser tratado pelo predictive engine como imediatamente disponível.
|
|
|
|
Mostrar estado:
|
|
|
|
```text
|
|
WRAP UP
|
|
```
|
|
|
|
e tempo restante.
|
|
|
|
---
|
|
|
|
# 40. DISPOSIÇÃO DA CHAMADA
|
|
|
|
Após atendimento, permitir ao agente classificar a ligação.
|
|
|
|
Exemplos:
|
|
|
|
```text
|
|
VENDA
|
|
SEM INTERESSE
|
|
CALLBACK
|
|
NÚMERO ERRADO
|
|
NÃO LIGAR NOVAMENTE
|
|
CAIXA POSTAL
|
|
OUTRO
|
|
```
|
|
|
|
Criar tela administrativa para configurar disposições.
|
|
|
|
Uma disposição pode possuir ações.
|
|
|
|
Exemplo:
|
|
|
|
```text
|
|
CALLBACK
|
|
-> solicitar data/hora
|
|
```
|
|
|
|
```text
|
|
DO_NOT_CALL
|
|
-> adicionar automaticamente à suppression_list
|
|
```
|
|
|
|
---
|
|
|
|
# 41. CALLBACK
|
|
|
|
Permitir agendar retorno.
|
|
|
|
Campos:
|
|
|
|
```text
|
|
lead
|
|
agent
|
|
campaign
|
|
scheduled_at
|
|
timezone
|
|
notes
|
|
```
|
|
|
|
O scheduler deve colocar o lead novamente em condição de discagem no horário correto.
|
|
|
|
Permitir callback:
|
|
|
|
```text
|
|
para qualquer agente
|
|
```
|
|
|
|
ou:
|
|
|
|
```text
|
|
preferencialmente para o mesmo agente
|
|
```
|
|
|
|
---
|
|
|
|
# 42. CDR / HISTÓRICO DE CHAMADAS
|
|
|
|
Criar modelo consolidado próprio.
|
|
|
|
Capturar:
|
|
|
|
```text
|
|
call_id
|
|
asterisk_uniqueid
|
|
linkedid
|
|
campaign
|
|
lead
|
|
queue
|
|
agent
|
|
extension
|
|
trunk
|
|
caller
|
|
called
|
|
start_at
|
|
ring_at
|
|
answer_at
|
|
queue_enter_at
|
|
agent_answer_at
|
|
end_at
|
|
duration
|
|
billsec
|
|
talk_time
|
|
wait_time
|
|
disposition
|
|
hangup_cause
|
|
amd_result
|
|
```
|
|
|
|
Nunca depender exclusivamente do CDR nativo para reconstruir toda a jornada do Call Center.
|
|
|
|
Utilizar:
|
|
|
|
* CDR;
|
|
* CEL;
|
|
* AMI Events;
|
|
* queue_log.
|
|
|
|
---
|
|
|
|
# 43. RELATÓRIO DE CHAMADAS
|
|
|
|
Criar:
|
|
|
|
**Relatórios → Chamadas**
|
|
|
|
Filtros:
|
|
|
|
* data inicial;
|
|
* data final;
|
|
* ramal;
|
|
* agente;
|
|
* fila;
|
|
* campanha;
|
|
* tronco;
|
|
* telefone;
|
|
* status;
|
|
* disposição.
|
|
|
|
Colunas:
|
|
|
|
```text
|
|
Data
|
|
Origem
|
|
Destino
|
|
Campanha
|
|
Fila
|
|
Agente
|
|
Ramal
|
|
Tronco
|
|
Espera
|
|
Conversação
|
|
Duração
|
|
Resultado
|
|
Hangup Cause
|
|
```
|
|
|
|
Permitir exportar CSV.
|
|
|
|
Paginação obrigatoriamente server-side.
|
|
|
|
Não carregar milhões de registros de uma vez no browser.
|
|
|
|
---
|
|
|
|
# 44. TME
|
|
|
|
Implementar TME — Tempo Médio de Espera.
|
|
|
|
Calcular principalmente:
|
|
|
|
```text
|
|
agent_answer_at - queue_enter_at
|
|
```
|
|
|
|
para chamadas atendidas.
|
|
|
|
Separadamente mostrar:
|
|
|
|
```text
|
|
tempo médio antes do abandono
|
|
```
|
|
|
|
Não misturar as duas métricas silenciosamente.
|
|
|
|
Documentar a definição utilizada.
|
|
|
|
---
|
|
|
|
# 45. TMA
|
|
|
|
Implementar:
|
|
|
|
**TMA — Tempo Médio de Atendimento**
|
|
|
|
Calcular principalmente:
|
|
|
|
```text
|
|
SUM(talk_time) / answered_calls
|
|
```
|
|
|
|
Permitir futuramente visualizar:
|
|
|
|
```text
|
|
Talk Time
|
|
Talk + Wrap-Up
|
|
```
|
|
|
|
como indicadores separados.
|
|
|
|
---
|
|
|
|
# 46. DASHBOARD
|
|
|
|
Criar um dashboard moderno.
|
|
|
|
Cards principais:
|
|
|
|
```text
|
|
Chamadas hoje
|
|
Chamadas atendidas
|
|
Chamadas em andamento
|
|
Chamadas aguardando
|
|
Agentes disponíveis
|
|
Agentes ocupados
|
|
Agentes pausados
|
|
TME
|
|
TMA
|
|
Taxa de atendimento
|
|
Taxa de abandono
|
|
```
|
|
|
|
Gráficos:
|
|
|
|
### Chamadas por hora
|
|
|
|
Line/area chart.
|
|
|
|
### Atendidas x abandonadas
|
|
|
|
### TME ao longo do dia
|
|
|
|
### TMA ao longo do dia
|
|
|
|
### Agentes por estado
|
|
|
|
### Campanhas
|
|
|
|
Mostrar:
|
|
|
|
```text
|
|
Discando
|
|
Ringing
|
|
Atendidas
|
|
Conectadas
|
|
CPS atual
|
|
Pacing
|
|
Answer Rate
|
|
Abandono
|
|
```
|
|
|
|
Não criar gráficos falsos.
|
|
|
|
Todos devem utilizar informações reais do banco/Asterisk.
|
|
|
|
---
|
|
|
|
# 47. DASHBOARD DO DISCADOR
|
|
|
|
Criar painel específico por campanha mostrando em tempo real:
|
|
|
|
```text
|
|
CPS configurado
|
|
CPS atual
|
|
Chamadas discando
|
|
Chamadas tocando
|
|
Atendidas
|
|
Na fila
|
|
Conectadas em agente
|
|
Agentes disponíveis
|
|
Pacing atual
|
|
Answer rate
|
|
Abandon rate
|
|
TME
|
|
TMA
|
|
Leads restantes
|
|
Leads processados
|
|
```
|
|
|
|
Isso será extremamente importante para operação.
|
|
|
|
---
|
|
|
|
# 48. STATUS DOS AGENTES
|
|
|
|
Estados canônicos:
|
|
|
|
```text
|
|
OFFLINE
|
|
LOGGED_IN
|
|
AVAILABLE
|
|
RINGING
|
|
IN_CALL
|
|
WRAP_UP
|
|
PAUSED
|
|
```
|
|
|
|
Não inferir tudo diretamente de uma única variável do Asterisk.
|
|
|
|
Criar máquina de estados consistente.
|
|
|
|
Registrar início/fim de cada estado.
|
|
|
|
Isso permitirá calcular produtividade posteriormente.
|
|
|
|
---
|
|
|
|
# 49. RELATÓRIO DE AGENTES
|
|
|
|
Criar:
|
|
|
|
**Relatórios → Agentes**
|
|
|
|
Exibir:
|
|
|
|
```text
|
|
Tempo logado
|
|
Tempo disponível
|
|
Tempo em chamada
|
|
Tempo pausado
|
|
Tempo wrap-up
|
|
Chamadas atendidas
|
|
TMA
|
|
```
|
|
|
|
Detalhar pausas:
|
|
|
|
```text
|
|
motivo
|
|
início
|
|
fim
|
|
duração
|
|
```
|
|
|
|
---
|
|
|
|
# 50. QUEUE_LOG
|
|
|
|
Utilizar os dados do `queue_log` porque ele contém eventos específicos de ACD que um CDR tradicional não representa corretamente.
|
|
|
|
Capturar eventos relevantes como:
|
|
|
|
* ENTERQUEUE;
|
|
* CONNECT;
|
|
* COMPLETEAGENT;
|
|
* COMPLETECALLER;
|
|
* ABANDON;
|
|
* RINGNOANSWER;
|
|
* TRANSFER;
|
|
* PAUSE;
|
|
* UNPAUSE.
|
|
|
|
Normalizar no PostgreSQL.
|
|
|
|
Não basear TME/TMA exclusivamente em parsing periódico de arquivo.
|
|
|
|
Preferencialmente capturar eventos em tempo real e utilizar queue_log também para reconciliação/auditoria.
|
|
|
|
---
|
|
|
|
# 51. RECONCILIAÇÃO
|
|
|
|
Eventos podem eventualmente ser perdidos por restart de algum worker.
|
|
|
|
Criar rotina de reconciliação.
|
|
|
|
Ela deve comparar informações recentes com:
|
|
|
|
* CDR;
|
|
* CEL;
|
|
* queue_log;
|
|
* estados persistidos.
|
|
|
|
Corrigir chamadas que ficaram indevidamente em:
|
|
|
|
```text
|
|
RINGING
|
|
IN_PROGRESS
|
|
CONNECTED
|
|
```
|
|
|
|
após falha/restart.
|
|
|
|
---
|
|
|
|
# 52. INTERFACE
|
|
|
|
Quero uma aplicação:
|
|
|
|
* bonita;
|
|
* moderna;
|
|
* clean;
|
|
* corporativa;
|
|
* rápida;
|
|
* responsiva;
|
|
* com excelente UX.
|
|
|
|
Utilizar a logo:
|
|
|
|
```text
|
|
/opt/b2bcall/b2bcall.png
|
|
```
|
|
|
|
Copiar/processar para o diretório apropriado do frontend.
|
|
|
|
Não modificar a logo original.
|
|
|
|
Menu sugerido:
|
|
|
|
```text
|
|
Dashboard
|
|
|
|
Discador
|
|
├─ Campanhas
|
|
├─ Leads
|
|
├─ Importações
|
|
├─ Callbacks
|
|
└─ Lista de Bloqueio
|
|
|
|
Call Center
|
|
├─ Agentes
|
|
├─ Filas
|
|
├─ Motivos de Pausa
|
|
└─ Disposições
|
|
|
|
Telefonia
|
|
├─ Ramais
|
|
├─ Troncos
|
|
└─ Dialplan
|
|
|
|
Monitoramento
|
|
├─ Filas
|
|
├─ Agentes
|
|
├─ Ramais
|
|
└─ Campanhas
|
|
|
|
Relatórios
|
|
├─ Chamadas
|
|
├─ Agentes
|
|
├─ Filas
|
|
└─ Campanhas
|
|
|
|
Sistema
|
|
├─ Usuários
|
|
├─ Perfis e Permissões
|
|
├─ Asterisk
|
|
├─ Compliance
|
|
├─ Auditoria
|
|
└─ Configurações
|
|
```
|
|
|
|
---
|
|
|
|
# 53. BANCO DE DADOS
|
|
|
|
Planejar pelo menos entidades equivalentes a:
|
|
|
|
```text
|
|
users
|
|
sessions
|
|
|
|
roles
|
|
permissions
|
|
user_roles
|
|
role_permissions
|
|
|
|
agents
|
|
agent_sessions
|
|
agent_state_events
|
|
|
|
pause_reasons
|
|
agent_pause_events
|
|
|
|
extensions
|
|
|
|
trunks
|
|
|
|
queues
|
|
queue_members
|
|
|
|
dialplans
|
|
dialplan_versions
|
|
|
|
campaigns
|
|
campaign_schedules
|
|
campaign_agents
|
|
|
|
lead_imports
|
|
leads
|
|
|
|
dial_attempts
|
|
|
|
calls
|
|
call_events
|
|
|
|
queue_events
|
|
|
|
call_dispositions
|
|
call_callbacks
|
|
|
|
suppression_list
|
|
|
|
asterisk_config_versions
|
|
|
|
audit_logs
|
|
|
|
application_settings
|
|
```
|
|
|
|
Adicionar tabelas auxiliares necessárias.
|
|
|
|
Criar índices para consultas de alto volume.
|
|
|
|
Especial atenção para índices envolvendo:
|
|
|
|
```text
|
|
campaign_id
|
|
status
|
|
next_attempt_at
|
|
created_at
|
|
phone_normalized
|
|
call_id
|
|
linkedid
|
|
queue_id
|
|
agent_id
|
|
extension_id
|
|
```
|
|
|
|
---
|
|
|
|
# 54. VOLUME DE DADOS
|
|
|
|
Projetar desde o início considerando milhões de registros de chamadas.
|
|
|
|
Não criar relatórios que façam:
|
|
|
|
```sql
|
|
SELECT * FROM calls;
|
|
```
|
|
|
|
Implementar:
|
|
|
|
* paginação;
|
|
* índices;
|
|
* filtros;
|
|
* agregações;
|
|
* query plans razoáveis.
|
|
|
|
Avaliar particionamento temporal posteriormente para:
|
|
|
|
```text
|
|
calls
|
|
call_events
|
|
queue_events
|
|
audit_logs
|
|
```
|
|
|
|
Não precisa particionar prematuramente se não houver necessidade, mas documentar estratégia de crescimento.
|
|
|
|
---
|
|
|
|
# 55. SEGURANÇA DE SEGREDOS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
.env
|
|
.env.example
|
|
```
|
|
|
|
`.env` obrigatoriamente em `.gitignore`.
|
|
|
|
Segredos:
|
|
|
|
* PostgreSQL;
|
|
* Redis;
|
|
* JWT;
|
|
* encryption key;
|
|
* AMI;
|
|
* ARI;
|
|
* SIP;
|
|
* SMTP.
|
|
|
|
Nunca commitar.
|
|
|
|
Nunca imprimir em logs.
|
|
|
|
Credenciais de trunk devem ser criptografadas em repouso quando forem mantidas pelo aplicativo.
|
|
|
|
Utilizar AES-256-GCM ou mecanismo equivalente com master key externa ao banco.
|
|
|
|
---
|
|
|
|
# 56. FIREWALL
|
|
|
|
Configurar firewall utilizando nftables ou abordagem adequada ao Debian 13.
|
|
|
|
Princípio:
|
|
|
|
**default deny para serviços administrativos/telefônicos sensíveis.**
|
|
|
|
Permitir SIP no Asterisk somente de:
|
|
|
|
* OpenSIPS autorizado;
|
|
* operadoras privadas;
|
|
* redes explicitamente configuradas.
|
|
|
|
AMI:
|
|
|
|
somente aplicação.
|
|
|
|
ARI:
|
|
|
|
somente aplicação.
|
|
|
|
PostgreSQL:
|
|
|
|
somente containers/localhost necessário.
|
|
|
|
Redis:
|
|
|
|
somente containers.
|
|
|
|
Não bloquear SSH durante a instalação.
|
|
|
|
---
|
|
|
|
# 57. HTTP SECURITY
|
|
|
|
Implementar:
|
|
|
|
* Content Security Policy;
|
|
* X-Content-Type-Options;
|
|
* Referrer-Policy;
|
|
* HSTS quando HTTPS;
|
|
* CORS restritivo;
|
|
* CSRF quando necessário;
|
|
* Helmet ou equivalente;
|
|
* input validation;
|
|
* DTO validation.
|
|
|
|
Não confiar em entrada do usuário.
|
|
|
|
---
|
|
|
|
# 58. SQL SECURITY
|
|
|
|
Nunca concatenar SQL manualmente com dados fornecidos pelo usuário.
|
|
|
|
Utilizar queries parametrizadas/ORM.
|
|
|
|
Importação de CSV também deve ser tratada como entrada não confiável.
|
|
|
|
---
|
|
|
|
# 59. ASTERISK CONFIG SECURITY
|
|
|
|
O editor avançado de configuração é uma área sensível.
|
|
|
|
Antes de gravar:
|
|
|
|
* validar seção;
|
|
* validar formato;
|
|
* impedir path traversal;
|
|
* nunca aceitar caminho arbitrário;
|
|
* nunca permitir gravar fora de diretórios permitidos;
|
|
* criar backup;
|
|
* versionar;
|
|
* validar;
|
|
* reload controlado.
|
|
|
|
Nunca transformar a interface do Asterisk em uma execução remota de comandos Linux.
|
|
|
|
---
|
|
|
|
# 60. LOGS
|
|
|
|
Utilizar logs estruturados JSON no backend.
|
|
|
|
Campos úteis:
|
|
|
|
```text
|
|
timestamp
|
|
level
|
|
service
|
|
request_id
|
|
user_id
|
|
campaign_id
|
|
call_id
|
|
attempt_id
|
|
message
|
|
```
|
|
|
|
Nunca registrar:
|
|
|
|
* senha;
|
|
* SIP password;
|
|
* JWT;
|
|
* refresh token;
|
|
* credencial AMI;
|
|
* credencial ARI.
|
|
|
|
---
|
|
|
|
# 61. CORRELATION ID
|
|
|
|
Cada request HTTP deve possuir:
|
|
|
|
```text
|
|
request_id
|
|
```
|
|
|
|
Cada tentativa:
|
|
|
|
```text
|
|
attempt_id
|
|
```
|
|
|
|
Cada chamada:
|
|
|
|
```text
|
|
call_id
|
|
```
|
|
|
|
Relacionar com:
|
|
|
|
```text
|
|
Asterisk UNIQUEID
|
|
Asterisk LINKEDID
|
|
```
|
|
|
|
Isso será fundamental para troubleshooting.
|
|
|
|
---
|
|
|
|
# 62. HEALTH CHECKS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
/api/health
|
|
/api/health/live
|
|
/api/health/ready
|
|
```
|
|
|
|
Verificar:
|
|
|
|
* API;
|
|
* PostgreSQL;
|
|
* Redis;
|
|
* AMI;
|
|
* Asterisk.
|
|
|
|
Dashboard administrativo deve mostrar:
|
|
|
|
```text
|
|
API OK
|
|
Postgres OK
|
|
Redis OK
|
|
Asterisk OK
|
|
AMI OK
|
|
```
|
|
|
|
---
|
|
|
|
# 63. BACKUP
|
|
|
|
Criar scripts/documentação para backup de:
|
|
|
|
* PostgreSQL;
|
|
* configurações Asterisk;
|
|
* `.env` de maneira segura;
|
|
* uploads relevantes.
|
|
|
|
Adicionar procedimento de restore.
|
|
|
|
---
|
|
|
|
# 64. TESTES
|
|
|
|
Criar testes reais.
|
|
|
|
## Unit tests
|
|
|
|
Principalmente:
|
|
|
|
* predictive engine;
|
|
* CPS limiter;
|
|
* permissions;
|
|
* phone normalization;
|
|
* retry strategy;
|
|
* state machines;
|
|
* TME/TMA;
|
|
* scheduling.
|
|
|
|
## Integration
|
|
|
|
* PostgreSQL;
|
|
* Redis;
|
|
* repositories;
|
|
* API;
|
|
* AMI adapter mockado.
|
|
|
|
## E2E
|
|
|
|
Pelo menos:
|
|
|
|
```text
|
|
login
|
|
criar agente
|
|
criar ramal
|
|
criar fila
|
|
criar trunk
|
|
criar campanha
|
|
importar CSV
|
|
iniciar campanha em modo simulado
|
|
pausar campanha
|
|
relatórios
|
|
RBAC
|
|
```
|
|
|
|
---
|
|
|
|
# 65. MODO DE SIMULAÇÃO
|
|
|
|
Criar um recurso muito importante:
|
|
|
|
```text
|
|
DIALER_SIMULATION=true
|
|
```
|
|
|
|
Neste modo:
|
|
|
|
**NÃO realizar chamadas externas.**
|
|
|
|
Simular:
|
|
|
|
```text
|
|
ANSWER
|
|
BUSY
|
|
NO ANSWER
|
|
ANSWER DELAY
|
|
TALK TIME
|
|
```
|
|
|
|
Isso permitirá testar o predictive engine sem gerar milhares de chamadas reais.
|
|
|
|
Criar testes utilizando esse modo.
|
|
|
|
---
|
|
|
|
# 66. TESTE DO PREDICTIVE ENGINE
|
|
|
|
Criar simulador com, por exemplo:
|
|
|
|
```text
|
|
20 agentes
|
|
10 CPS
|
|
30% answer rate
|
|
10 segundos answer delay
|
|
180 segundos TMA
|
|
```
|
|
|
|
Verificar:
|
|
|
|
* pacing;
|
|
* disponibilidade;
|
|
* abandono;
|
|
* CPS;
|
|
* estabilização.
|
|
|
|
Gerar logs/estatísticas.
|
|
|
|
O motor não pode oscilar violentamente.
|
|
|
|
---
|
|
|
|
# 67. GIT
|
|
|
|
Inicializar Git em:
|
|
|
|
```text
|
|
/opt/b2bcall
|
|
```
|
|
|
|
Criar `.gitignore`.
|
|
|
|
Commits organizados por etapas.
|
|
|
|
Exemplos:
|
|
|
|
```text
|
|
feat: bootstrap b2bcall architecture
|
|
|
|
feat: add authentication and RBAC
|
|
|
|
feat: add asterisk pjsip integration
|
|
|
|
feat: add call center queues
|
|
|
|
feat: add campaign management
|
|
|
|
feat: implement predictive dialing engine
|
|
|
|
feat: add realtime monitoring
|
|
|
|
feat: add call reports
|
|
|
|
feat: add security hardening
|
|
|
|
test: add predictive dialer simulation
|
|
```
|
|
|
|
Nunca versionar segredos.
|
|
|
|
---
|
|
|
|
# 68. DOCUMENTAÇÃO
|
|
|
|
Criar:
|
|
|
|
```text
|
|
README.md
|
|
docs/ARCHITECTURE.md
|
|
docs/INSTALL.md
|
|
docs/ASTERISK.md
|
|
docs/OPENSIPS.md
|
|
docs/PREDICTIVE_DIALER.md
|
|
docs/DATABASE.md
|
|
docs/SECURITY.md
|
|
docs/OPERATIONS.md
|
|
docs/BACKUP_RESTORE.md
|
|
docs/API.md
|
|
docs/TROUBLESHOOTING.md
|
|
CHANGELOG.md
|
|
```
|
|
|
|
---
|
|
|
|
# 69. TODO OPERACIONAL
|
|
|
|
Durante o desenvolvimento mantenha:
|
|
|
|
```text
|
|
TODO.md
|
|
```
|
|
|
|
Exemplo:
|
|
|
|
```text
|
|
[x] Docker
|
|
[x] PostgreSQL
|
|
[x] Redis
|
|
[x] Authentication
|
|
[x] RBAC
|
|
[x] Asterisk
|
|
[x] Extensions
|
|
[x] Trunks
|
|
[ ] Queues
|
|
[ ] Agents
|
|
[ ] Campaigns
|
|
[ ] Predictive Engine
|
|
```
|
|
|
|
Quando terminar um item:
|
|
|
|
* testar;
|
|
* marcar `[x]`;
|
|
* continuar para o próximo.
|
|
|
|
Não utilize o TODO como desculpa para deixar funcionalidades incompletas.
|
|
|
|
No final, nenhum requisito principal deste documento deve permanecer pendente.
|
|
|
|
---
|
|
|
|
# 70. BOOTSTRAP DO SUPER ADMIN
|
|
|
|
Na primeira instalação criar um usuário `super_admin`.
|
|
|
|
Nunca utilizar senha padrão como:
|
|
|
|
```text
|
|
admin
|
|
123456
|
|
password
|
|
```
|
|
|
|
Gerar senha aleatória forte.
|
|
|
|
Mostrar apenas uma vez ao final da instalação.
|
|
|
|
Idealmente criar:
|
|
|
|
```text
|
|
/opt/b2bcall/FIRST_LOGIN.txt
|
|
```
|
|
|
|
com:
|
|
|
|
```bash
|
|
chmod 600
|
|
```
|
|
|
|
Orientar que o arquivo seja removido após primeiro acesso.
|
|
|
|
Forçar troca da senha no primeiro login.
|
|
|
|
---
|
|
|
|
# 71. SEED
|
|
|
|
Criar seed inicial contendo:
|
|
|
|
* permissões;
|
|
* perfil super_admin;
|
|
* admin;
|
|
* supervisor;
|
|
* agent;
|
|
* motivos básicos de pausa;
|
|
* disposições padrão.
|
|
|
|
Mas tudo deve poder ser alterado posteriormente.
|
|
|
|
---
|
|
|
|
# 72. NÃO CRIAR DADOS FAKE EM PRODUÇÃO
|
|
|
|
Dados demonstrativos somente quando:
|
|
|
|
```text
|
|
SEED_DEMO_DATA=true
|
|
```
|
|
|
|
Por padrão:
|
|
|
|
```text
|
|
false
|
|
```
|
|
|
|
Dashboard de produção nunca deve apresentar números inventados.
|
|
|
|
---
|
|
|
|
# 73. UX DE ERROS
|
|
|
|
Não mostrar ao usuário:
|
|
|
|
```text
|
|
500 Internal Server Error
|
|
```
|
|
|
|
sem contexto.
|
|
|
|
Mostrar mensagem amigável e gerar:
|
|
|
|
```text
|
|
request_id
|
|
```
|
|
|
|
para suporte técnico.
|
|
|
|
No log técnico, manter detalhes.
|
|
|
|
---
|
|
|
|
# 74. PERFORMANCE
|
|
|
|
Evitar:
|
|
|
|
* N+1 queries;
|
|
* polling desnecessário;
|
|
* carregamento completo de tabelas;
|
|
* processamento pesado dentro de HTTP request;
|
|
* bloqueio do event loop;
|
|
* originação síncrona de milhares de chamadas.
|
|
|
|
Utilizar workers.
|
|
|
|
---
|
|
|
|
# 75. CONTROLE DE CAMPANHA DISTRIBUÍDO
|
|
|
|
O motor deve impedir dois workers de controlarem simultaneamente a mesma campanha.
|
|
|
|
Criar distributed lock.
|
|
|
|
Exemplo conceitual:
|
|
|
|
```text
|
|
dialer:campaign:{id}:lock
|
|
```
|
|
|
|
com:
|
|
|
|
* TTL;
|
|
* renewal;
|
|
* ownership token.
|
|
|
|
Se worker morrer, outro poderá assumir posteriormente.
|
|
|
|
---
|
|
|
|
# 76. PAUSA IMEDIATA
|
|
|
|
Quando administrador clicar:
|
|
|
|
```text
|
|
PAUSAR CAMPANHA
|
|
```
|
|
|
|
não originar nenhuma nova chamada.
|
|
|
|
As chamadas já existentes podem continuar.
|
|
|
|
Em:
|
|
|
|
```text
|
|
STOP
|
|
```
|
|
|
|
definir comportamento de maneira clara e segura.
|
|
|
|
Não derrubar ligações de clientes/agentes sem confirmação explícita.
|
|
|
|
---
|
|
|
|
# 77. MONITORAMENTO DO TRONCO
|
|
|
|
Monitorar:
|
|
|
|
* status;
|
|
* chamadas atuais;
|
|
* CPS atual;
|
|
* CPS limite;
|
|
* channels limit;
|
|
* tentativas;
|
|
* falhas;
|
|
* congestion;
|
|
* SIP response codes quando disponíveis.
|
|
|
|
Mostrar no dashboard.
|
|
|
|
---
|
|
|
|
# 78. HANGUP CAUSE
|
|
|
|
Guardar informações de encerramento.
|
|
|
|
Normalizar resultados como:
|
|
|
|
```text
|
|
ANSWERED
|
|
BUSY
|
|
NO_ANSWER
|
|
REJECTED
|
|
CONGESTION
|
|
INVALID_NUMBER
|
|
NETWORK_FAILURE
|
|
CANCELLED
|
|
```
|
|
|
|
Mas preservar também o código original recebido do Asterisk/rede.
|
|
|
|
---
|
|
|
|
# 79. RETRY ENGINE
|
|
|
|
Criar regras por campanha.
|
|
|
|
Exemplo:
|
|
|
|
```text
|
|
BUSY -> 15 minutos
|
|
NO ANSWER -> 60 minutos
|
|
CONGESTION -> 5 minutos
|
|
FAILED -> 30 minutos
|
|
```
|
|
|
|
Limitar quantidade máxima de tentativas.
|
|
|
|
Permitir personalização.
|
|
|
|
Nunca rediscagem infinita.
|
|
|
|
---
|
|
|
|
# 80. HORÁRIO DE CAMPANHA
|
|
|
|
Scheduler deve impedir discagem fora do período configurado.
|
|
|
|
Considerar timezone.
|
|
|
|
Por exemplo:
|
|
|
|
```text
|
|
America/Sao_Paulo
|
|
```
|
|
|
|
Configurar:
|
|
|
|
* segunda;
|
|
* terça;
|
|
* quarta;
|
|
* quinta;
|
|
* sexta;
|
|
* sábado;
|
|
* domingo.
|
|
|
|
Campanha fora do horário:
|
|
|
|
```text
|
|
WAITING_SCHEDULE
|
|
```
|
|
|
|
---
|
|
|
|
# 81. ARQUITETURA DE FRONTEND
|
|
|
|
Criar componentes reutilizáveis.
|
|
|
|
Evitar páginas gigantes com milhares de linhas.
|
|
|
|
Separar:
|
|
|
|
```text
|
|
components
|
|
features
|
|
hooks
|
|
services
|
|
schemas
|
|
types
|
|
```
|
|
|
|
Usar tabelas com:
|
|
|
|
* busca;
|
|
* filtros;
|
|
* paginação;
|
|
* ordenação;
|
|
* loading;
|
|
* empty state;
|
|
* error state.
|
|
|
|
---
|
|
|
|
# 82. DESIGN
|
|
|
|
A aparência deve lembrar sistemas SaaS/Contact Center modernos.
|
|
|
|
Utilizar:
|
|
|
|
* sidebar;
|
|
* topbar;
|
|
* cards;
|
|
* tabelas profissionais;
|
|
* badges;
|
|
* tooltips;
|
|
* gráficos;
|
|
* skeleton loading;
|
|
* dialogs;
|
|
* toast notifications.
|
|
|
|
Evitar aparência de:
|
|
|
|
* sistema antigo;
|
|
* FreePBX clone;
|
|
* formulário HTML cru;
|
|
* bootstrap antigo.
|
|
|
|
A identidade visual deve utilizar a logo do B2BCall.
|
|
|
|
Criar light/dark mode se não prejudicar o desenvolvimento.
|
|
|
|
---
|
|
|
|
# 83. API
|
|
|
|
Utilizar REST bem estruturada inicialmente.
|
|
|
|
Exemplos:
|
|
|
|
```text
|
|
/api/auth
|
|
/api/users
|
|
/api/roles
|
|
/api/permissions
|
|
|
|
/api/extensions
|
|
/api/trunks
|
|
/api/dialplans
|
|
|
|
/api/agents
|
|
/api/queues
|
|
/api/pause-reasons
|
|
|
|
/api/campaigns
|
|
/api/campaigns/:id/leads
|
|
/api/campaigns/:id/start
|
|
/api/campaigns/:id/pause
|
|
/api/campaigns/:id/stop
|
|
|
|
/api/reports/calls
|
|
/api/reports/agents
|
|
|
|
/api/monitoring/extensions
|
|
/api/monitoring/queues
|
|
/api/monitoring/campaigns
|
|
|
|
/api/asterisk
|
|
/api/compliance
|
|
/api/audit
|
|
```
|
|
|
|
Gerar OpenAPI/Swagger.
|
|
|
|
Swagger administrativo deve poder ser desabilitado em produção.
|
|
|
|
---
|
|
|
|
# 84. VALIDATION
|
|
|
|
Usar validação forte de schemas/DTO.
|
|
|
|
Exemplo:
|
|
|
|
CPS:
|
|
|
|
```text
|
|
>= 1
|
|
```
|
|
|
|
Telefone:
|
|
|
|
validar e normalizar.
|
|
|
|
Datas:
|
|
|
|
validar timezone.
|
|
|
|
UUID:
|
|
|
|
validar.
|
|
|
|
IDs fornecidos pelo usuário nunca devem ser confiados sem validação.
|
|
|
|
---
|
|
|
|
# 85. MIGRATIONS
|
|
|
|
Nenhuma alteração de banco manual sem migration.
|
|
|
|
Criar comandos:
|
|
|
|
```bash
|
|
npm run db:migrate
|
|
npm run db:seed
|
|
```
|
|
|
|
ou equivalentes.
|
|
|
|
---
|
|
|
|
# 86. DEPLOYMENT
|
|
|
|
Criar script:
|
|
|
|
```text
|
|
scripts/install.sh
|
|
```
|
|
|
|
para servidor Debian 13 limpo.
|
|
|
|
Ele deve:
|
|
|
|
1. verificar permissões;
|
|
2. instalar dependências;
|
|
3. instalar Docker;
|
|
4. instalar Compose plugin;
|
|
5. criar diretórios;
|
|
6. gerar secrets;
|
|
7. preparar `.env`;
|
|
8. buildar containers;
|
|
9. iniciar PostgreSQL/Redis;
|
|
10. executar migrations;
|
|
11. iniciar Asterisk;
|
|
12. iniciar API/workers/frontend;
|
|
13. executar health checks;
|
|
14. mostrar resultado.
|
|
|
|
Também criar:
|
|
|
|
```text
|
|
scripts/update.sh
|
|
scripts/backup.sh
|
|
scripts/restore.sh
|
|
scripts/healthcheck.sh
|
|
```
|
|
|
|
---
|
|
|
|
# 87. NGINX / REVERSE PROXY
|
|
|
|
Criar reverse proxy.
|
|
|
|
Expor para a LAN preferencialmente apenas:
|
|
|
|
```text
|
|
80
|
|
443
|
|
```
|
|
|
|
WebSocket precisa funcionar corretamente.
|
|
|
|
Preparar suporte HTTPS.
|
|
|
|
Se nenhum domínio/certificado estiver disponível inicialmente, documentar como ativar certificado posteriormente.
|
|
|
|
Não inventar domínio.
|
|
|
|
---
|
|
|
|
# 88. RESTART SEGURO
|
|
|
|
Restart da API não deve destruir campanhas.
|
|
|
|
Estado importante sempre no:
|
|
|
|
* PostgreSQL;
|
|
* Redis quando apropriado.
|
|
|
|
Ao reiniciar worker:
|
|
|
|
* recuperar campanhas RUNNING;
|
|
* reconciliar chamadas;
|
|
* limpar reservations expiradas;
|
|
* reassumir locks;
|
|
* continuar operação corretamente.
|
|
|
|
---
|
|
|
|
# 89. OBSERVABILIDADE
|
|
|
|
Criar no mínimo:
|
|
|
|
* logs estruturados;
|
|
* health checks;
|
|
* métricas internas.
|
|
|
|
Preparar endpoint Prometheus:
|
|
|
|
```text
|
|
/metrics
|
|
```
|
|
|
|
Métricas úteis:
|
|
|
|
```text
|
|
b2bcall_calls_total
|
|
b2bcall_calls_answered_total
|
|
b2bcall_calls_abandoned_total
|
|
|
|
b2bcall_campaign_cps
|
|
|
|
b2bcall_agents_available
|
|
b2bcall_agents_busy
|
|
b2bcall_agents_paused
|
|
|
|
b2bcall_queue_waiting
|
|
|
|
b2bcall_dialer_active_calls
|
|
```
|
|
|
|
Pode adicionar outras.
|
|
|
|
---
|
|
|
|
# 90. REQUISITOS DE ACEITE
|
|
|
|
O projeto NÃO está terminado enquanto eu não conseguir realizar, pela interface:
|
|
|
|
1. fazer login;
|
|
2. cadastrar usuário;
|
|
3. cadastrar perfil;
|
|
4. alterar permissões;
|
|
5. cadastrar ramal;
|
|
6. visualizar seu status;
|
|
7. cadastrar trunk;
|
|
8. cadastrar dialplan;
|
|
9. cadastrar fila;
|
|
10. cadastrar agente;
|
|
11. associar agente a fila;
|
|
12. cadastrar pausa;
|
|
13. logar como agente;
|
|
14. colocar agente em pausa;
|
|
15. retirar pausa;
|
|
16. cadastrar campanha;
|
|
17. configurar CPS;
|
|
18. importar CSV;
|
|
19. iniciar campanha;
|
|
20. pausar campanha;
|
|
21. visualizar discagem;
|
|
22. visualizar agentes;
|
|
23. visualizar fila;
|
|
24. visualizar TME;
|
|
25. visualizar TMA;
|
|
26. pesquisar chamadas;
|
|
27. filtrar por ramal;
|
|
28. filtrar por fila;
|
|
29. exportar relatório;
|
|
30. administrar configurações necessárias do Asterisk;
|
|
31. consultar audit log.
|
|
|
|
---
|
|
|
|
# 91. ACEITE DO DIALER
|
|
|
|
Além da interface, provar através de teste/simulação que:
|
|
|
|
```text
|
|
configured CPS = 5
|
|
```
|
|
|
|
não origina mais de 5 novas chamadas em qualquer janela apropriada de 1 segundo.
|
|
|
|
Provar que:
|
|
|
|
```text
|
|
campaign max concurrent = 20
|
|
```
|
|
|
|
não ultrapassa 20 chamadas simultâneas.
|
|
|
|
Provar que:
|
|
|
|
* lead não é discado duas vezes simultaneamente;
|
|
* campanha pausada não gera novas chamadas;
|
|
* worker reiniciado recupera operação;
|
|
* pacing cai quando abandono sobe;
|
|
* lead bloqueado não é chamado;
|
|
* campanha fora do horário não chama.
|
|
|
|
---
|
|
|
|
# 92. ACEITE DE SEGURANÇA
|
|
|
|
Verificar:
|
|
|
|
* nenhuma senha no Git;
|
|
* nenhum `.env` commitado;
|
|
* PostgreSQL não público;
|
|
* Redis não público;
|
|
* AMI não público;
|
|
* ARI não público;
|
|
* rate limit funcionando;
|
|
* RBAC funcionando no backend;
|
|
* usuário agent não acessa configuração Asterisk;
|
|
* agent não consegue elevar a própria permissão;
|
|
* SQL injection protegida;
|
|
* path traversal protegido;
|
|
* logs sem credenciais.
|
|
|
|
---
|
|
|
|
# 93. ACEITE ASTERISK
|
|
|
|
Executar e documentar resultado de:
|
|
|
|
```text
|
|
asterisk -rx "core show version"
|
|
asterisk -rx "core show uptime"
|
|
asterisk -rx "pjsip show endpoints"
|
|
asterisk -rx "pjsip show contacts"
|
|
asterisk -rx "queue show"
|
|
```
|
|
|
|
Validar comunicação:
|
|
|
|
```text
|
|
API -> AMI -> Asterisk
|
|
```
|
|
|
|
---
|
|
|
|
# 94. QUALITY GATE
|
|
|
|
Antes de declarar terminado:
|
|
|
|
Executar:
|
|
|
|
```text
|
|
lint
|
|
typecheck
|
|
unit tests
|
|
integration tests
|
|
e2e tests
|
|
docker compose config
|
|
docker compose ps
|
|
health checks
|
|
```
|
|
|
|
Corrigir erros.
|
|
|
|
Não simplesmente informar que existem erros conhecidos.
|
|
|
|
---
|
|
|
|
# 95. README FINAL
|
|
|
|
No final atualizar README com:
|
|
|
|
## B2BCall
|
|
|
|
### Architecture
|
|
|
|
### Requirements
|
|
|
|
### Installation
|
|
|
|
### First Login
|
|
|
|
### Configuration
|
|
|
|
### OpenSIPS Integration
|
|
|
|
### Trunks
|
|
|
|
### Agents
|
|
|
|
### Queues
|
|
|
|
### Campaigns
|
|
|
|
### Predictive Dialer
|
|
|
|
### Reports
|
|
|
|
### Backup
|
|
|
|
### Update
|
|
|
|
### Troubleshooting
|
|
|
|
---
|
|
|
|
# 96. RELATÓRIO FINAL DA IMPLEMENTAÇÃO
|
|
|
|
Somente depois de efetivamente terminar, apresentar um resumo contendo:
|
|
|
|
```text
|
|
B2BCall version:
|
|
Asterisk version:
|
|
Node version:
|
|
PostgreSQL version:
|
|
Docker version:
|
|
|
|
Containers:
|
|
...
|
|
|
|
URLs:
|
|
...
|
|
|
|
Super admin:
|
|
...
|
|
|
|
Health:
|
|
...
|
|
|
|
Tests:
|
|
...
|
|
|
|
Pending:
|
|
...
|
|
```
|
|
|
|
Se existir algo pendente, explicar claramente.
|
|
|
|
---
|
|
|
|
# 97. DECISÕES TÉCNICAS IMPORTANTES
|
|
|
|
Tenha especialmente em mente:
|
|
|
|
### Asterisk não é banco de negócio
|
|
|
|
O estado de campanhas/leads/agentes deve estar no PostgreSQL.
|
|
|
|
### Redis não é fonte permanente
|
|
|
|
Informações importantes devem sobreviver à perda do Redis.
|
|
|
|
### AMI events são assíncronos
|
|
|
|
Não presuma que Originate HTTP concluído significa chamada completada.
|
|
|
|
### LINKEDID é importante
|
|
|
|
Uma chamada poderá possuir múltiplos canais Asterisk.
|
|
|
|
### Calls devem possuir ID próprio
|
|
|
|
Não utilize `UNIQUEID` do Asterisk como primary key de negócio.
|
|
|
|
### WebSocket é para visualização
|
|
|
|
O banco continua sendo fonte persistente.
|
|
|
|
### O predictive dialer precisa ser controlável
|
|
|
|
Sempre permitir:
|
|
|
|
```text
|
|
PAUSE
|
|
DRAIN
|
|
STOP
|
|
```
|
|
|
|
### Segurança deve existir desde a arquitetura
|
|
|
|
Não adicionar segurança apenas no final.
|
|
|
|
---
|
|
|
|
# 98. PRIMEIRA TAREFA
|
|
|
|
Comece AGORA.
|
|
|
|
Primeiro:
|
|
|
|
```bash
|
|
cd /opt/b2bcall
|
|
```
|
|
|
|
Analise:
|
|
|
|
```bash
|
|
pwd
|
|
ls -lah
|
|
cat /etc/os-release
|
|
uname -a
|
|
ip addr
|
|
df -h
|
|
free -h
|
|
```
|
|
|
|
Verifique a existência:
|
|
|
|
```text
|
|
/opt/b2bcall/b2bcall.png
|
|
```
|
|
|
|
Depois crie:
|
|
|
|
```text
|
|
docs/ARCHITECTURE.md
|
|
TODO.md
|
|
```
|
|
|
|
Defina a arquitetura inicial.
|
|
|
|
Em seguida inicialize o Git e comece efetivamente a implantação.
|
|
|
|
NÃO pare após criar os documentos.
|
|
|
|
Continue imediatamente para:
|
|
|
|
```text
|
|
Docker
|
|
↓
|
|
PostgreSQL
|
|
↓
|
|
Redis
|
|
↓
|
|
Asterisk
|
|
↓
|
|
Backend
|
|
↓
|
|
Authentication
|
|
↓
|
|
RBAC
|
|
↓
|
|
Telefonia
|
|
↓
|
|
Call Center
|
|
↓
|
|
Campanhas
|
|
↓
|
|
Predictive Dialer
|
|
↓
|
|
Frontend
|
|
↓
|
|
Monitoring
|
|
↓
|
|
Reports
|
|
↓
|
|
Security
|
|
↓
|
|
Tests
|
|
↓
|
|
Production validation
|
|
```
|
|
|
|
Trabalhe até alcançar os critérios de aceite.
|
|
|
|
---
|
|
|
|
# 99. PRINCÍPIO FINAL
|
|
|
|
Este projeto será usado como uma plataforma real de Call Center.
|
|
|
|
Portanto, sempre prefira:
|
|
|
|
```text
|
|
correto > rápido
|
|
seguro > conveniente
|
|
transacional > improvisado
|
|
observável > caixa-preta
|
|
configurável > hardcoded
|
|
testado > presumido
|
|
```
|
|
|
|
Não entregue apenas uma demonstração.
|
|
|
|
Construa o **B2BCall** como uma aplicação que possa realmente evoluir para produção.
|