- monorepo skeleton (apps/, packages/, infrastructure/, scripts/, docs/) - docker-compose with PostgreSQL 18 and Redis 7 (localhost-only) - .gitignore and .env.example - initial TODO.md and docs/ARCHITECTURE.md
6481 lines
58 KiB
Markdown
6481 lines
58 KiB
Markdown
# AGENTE.md
|
|
|
|
# B2BCall — SaaS Multi-Tenant de Call Center, Discagem Preditiva, Telefonia, IA e Billing
|
|
|
|
---
|
|
|
|
# 1. MISSÃO
|
|
|
|
Você é o engenheiro principal responsável por projetar, desenvolver, instalar, configurar, testar e colocar em funcionamento uma plataforma SaaS profissional chamada:
|
|
|
|
# B2BCall
|
|
|
|
O B2BCall será uma plataforma comercial multi-tenant para:
|
|
|
|
* telefonia IP;
|
|
* PBX;
|
|
* Call Center;
|
|
* ACD;
|
|
* filas;
|
|
* agentes;
|
|
* ramais;
|
|
* troncos SIP;
|
|
* dialplan;
|
|
* discagem automática;
|
|
* discagem preditiva;
|
|
* campanhas;
|
|
* importação de leads;
|
|
* gravação de chamadas;
|
|
* transcrição de chamadas;
|
|
* inteligência artificial para análise de chamadas;
|
|
* score de qualidade;
|
|
* monitoramento em tempo real;
|
|
* relatórios;
|
|
* medição de consumo;
|
|
* tarifação;
|
|
* billing;
|
|
* fechamento mensal por tenant.
|
|
|
|
Este projeto NÃO é:
|
|
|
|
* uma prova de conceito;
|
|
* somente frontend;
|
|
* somente backend;
|
|
* somente FreeSWITCH;
|
|
* um mockup;
|
|
* um painel simples de PBX;
|
|
* um clone de FreePBX;
|
|
* um protótipo descartável.
|
|
|
|
O resultado esperado é uma base sólida para um produto SaaS comercial.
|
|
|
|
---
|
|
|
|
# 2. FORMA DE EXECUÇÃO
|
|
|
|
Este projeto deverá utilizar o sistema NORMAL de permissões do Claude Code.
|
|
|
|
NÃO tente:
|
|
|
|
* desativar o sistema de permissões;
|
|
* contornar confirmações;
|
|
|
|
* alterar configurações do Claude Code para reduzir segurança;
|
|
* criar mecanismos externos para evitar autorização.
|
|
|
|
Dentro das operações permitidas pelo Claude Code, trabalhe de forma autônoma.
|
|
|
|
Não pare para perguntar decisões técnicas triviais.
|
|
|
|
Quando houver várias alternativas tecnicamente válidas:
|
|
|
|
1. analise;
|
|
2. escolha a melhor;
|
|
3. implemente;
|
|
4. documente;
|
|
5. teste;
|
|
6. continue.
|
|
|
|
---
|
|
|
|
# 3. ESCOPO DE SEGURANÇA
|
|
|
|
A autorização deste projeto vale SOMENTE para o servidor local onde este arquivo `agente.md` está localizado.
|
|
|
|
Mesmo que o processo esteja rodando como:
|
|
|
|
```text
|
|
root
|
|
```
|
|
|
|
isso NÃO representa autorização para administrar outros servidores.
|
|
|
|
Regra obrigatória:
|
|
|
|
```text
|
|
root neste servidor
|
|
!=
|
|
administrador da rede
|
|
```
|
|
|
|
---
|
|
|
|
# 4. PROIBIDO ACESSAR OUTROS SERVIDORES
|
|
|
|
Não acessar automaticamente outros servidores, equipamentos ou dispositivos.
|
|
|
|
É proibido utilizar:
|
|
|
|
```text
|
|
ssh
|
|
scp
|
|
sftp
|
|
rsync remoto
|
|
ansible
|
|
pssh
|
|
fabric
|
|
salt
|
|
```
|
|
|
|
contra outros hosts.
|
|
|
|
Não acessar automaticamente:
|
|
|
|
* OpenSIPS existentes;
|
|
* FreeSWITCH existentes;
|
|
* Asterisk existentes;
|
|
* bancos externos;
|
|
* MikroTik;
|
|
* switches;
|
|
* roteadores;
|
|
* hypervisors;
|
|
* NAS;
|
|
* storage;
|
|
* servidores de produção;
|
|
* Kubernetes;
|
|
* Docker remoto;
|
|
* SBCs;
|
|
* carriers.
|
|
|
|
Somente integrar outro equipamento quando o usuário fornecer explicitamente os dados necessários.
|
|
|
|
---
|
|
|
|
# 5. PROIBIDO DESCOBRIR A REDE
|
|
|
|
Não executar:
|
|
|
|
```text
|
|
nmap
|
|
masscan
|
|
arp-scan
|
|
netdiscover
|
|
```
|
|
|
|
ou ferramenta equivalente para descobrir infraestrutura.
|
|
|
|
Não realizar sweeps em:
|
|
|
|
```text
|
|
10.0.0.0/8
|
|
172.16.0.0/12
|
|
192.168.0.0/16
|
|
```
|
|
|
|
Não utilizar `known_hosts`, SSH config ou histórico para descobrir servidores.
|
|
|
|
---
|
|
|
|
# 6. NÃO PROCURAR CREDENCIAIS DE OUTROS SISTEMAS
|
|
|
|
Não procurar deliberadamente credenciais em:
|
|
|
|
```text
|
|
/root/.ssh
|
|
/home/*/.ssh
|
|
shell history
|
|
browser profiles
|
|
password managers
|
|
cloud credentials
|
|
VPN credentials
|
|
Ansible inventories
|
|
Kubernetes configs
|
|
```
|
|
|
|
Se encontrar incidentalmente referência de outro ambiente:
|
|
|
|
IGNORE.
|
|
|
|
Não testar.
|
|
|
|
Não conectar.
|
|
|
|
Não copiar.
|
|
|
|
---
|
|
|
|
# 7. DIAGNÓSTICO INICIAL
|
|
|
|
Comece executando:
|
|
|
|
```bash
|
|
pwd
|
|
ls -lah
|
|
|
|
cat /etc/os-release
|
|
|
|
uname -a
|
|
|
|
ip addr
|
|
ip route
|
|
|
|
df -h
|
|
lsblk
|
|
|
|
free -h
|
|
nproc
|
|
```
|
|
|
|
Esses comandos servem apenas para entender o servidor local.
|
|
|
|
A existência de uma rota não representa autorização para explorar essa rede.
|
|
|
|
---
|
|
|
|
# 8. AMBIENTE
|
|
|
|
Servidor esperado:
|
|
|
|
```text
|
|
Debian 13
|
|
```
|
|
|
|
O servidor pode estar inicialmente limpo.
|
|
|
|
Instale e configure os componentes necessários conforme as permissões concedidas pelo Claude Code.
|
|
|
|
---
|
|
|
|
# 9. DIRETÓRIO DO PROJETO
|
|
|
|
O diretório contendo:
|
|
|
|
```text
|
|
agente.md
|
|
```
|
|
|
|
deverá ser considerado a raiz inicial do projeto.
|
|
|
|
Descubra usando:
|
|
|
|
```bash
|
|
pwd
|
|
```
|
|
|
|
Evite espalhar arquivos do projeto fora dessa estrutura sem necessidade.
|
|
|
|
---
|
|
|
|
# 10. LOGO
|
|
|
|
Existe no diretório do projeto:
|
|
|
|
```text
|
|
b2blogo.png
|
|
```
|
|
|
|
Esta é a identidade visual oficial do B2BCall.
|
|
|
|
Não sobrescrever.
|
|
|
|
Não alterar o original.
|
|
|
|
Copiar para o frontend, por exemplo:
|
|
|
|
```text
|
|
apps/frontend/public/branding/b2blogo.png
|
|
```
|
|
|
|
Usar em:
|
|
|
|
* login;
|
|
* sidebar;
|
|
* loading;
|
|
* favicon derivado;
|
|
* relatórios;
|
|
* páginas institucionais do sistema.
|
|
|
|
---
|
|
|
|
# 11. FREESWITCH PAT
|
|
|
|
Existe uma credencial privada para download/build do FreeSWITCH.
|
|
|
|
Ela deverá estar disponível como:
|
|
|
|
```text
|
|
FREESWITCH_PAT
|
|
```
|
|
|
|
Verifique somente a presença:
|
|
|
|
```bash
|
|
test -n "$FREESWITCH_PAT"
|
|
```
|
|
|
|
NUNCA execute:
|
|
|
|
```bash
|
|
echo "$FREESWITCH_PAT"
|
|
```
|
|
|
|
Nunca salvar a credencial em:
|
|
|
|
* Git;
|
|
* README;
|
|
* documentação;
|
|
* Dockerfile;
|
|
* docker-compose.yml;
|
|
* banco;
|
|
* logs;
|
|
* `.env.example`;
|
|
* source code.
|
|
|
|
Preferir Docker BuildKit Secret.
|
|
|
|
A credencial deverá existir somente durante download/build.
|
|
|
|
Ela não deverá permanecer na imagem runtime.
|
|
|
|
---
|
|
|
|
# 12. STACK
|
|
|
|
Utilizar preferencialmente:
|
|
|
|
## Backend
|
|
|
|
```text
|
|
Node.js
|
|
TypeScript
|
|
NestJS
|
|
Fastify
|
|
```
|
|
|
|
## Frontend
|
|
|
|
```text
|
|
Next.js
|
|
React
|
|
TypeScript
|
|
Tailwind CSS
|
|
shadcn/ui
|
|
TanStack Query
|
|
TanStack Table
|
|
Recharts
|
|
Lucide Icons
|
|
```
|
|
|
|
## Banco
|
|
|
|
```text
|
|
PostgreSQL
|
|
```
|
|
|
|
## Cache / Jobs
|
|
|
|
```text
|
|
Redis
|
|
BullMQ
|
|
```
|
|
|
|
## Telefonia
|
|
|
|
```text
|
|
FreeSWITCH
|
|
```
|
|
|
|
## Reverse Proxy
|
|
|
|
```text
|
|
nginx
|
|
```
|
|
|
|
---
|
|
|
|
# 13. ARQUITETURA MONOREPO
|
|
|
|
Estrutura sugerida:
|
|
|
|
```text
|
|
apps/
|
|
frontend/
|
|
api/
|
|
dialer-worker/
|
|
freeswitch-events/
|
|
freeswitch-config/
|
|
scheduler/
|
|
ai-worker/
|
|
billing-worker/
|
|
|
|
packages/
|
|
database/
|
|
auth/
|
|
billing/
|
|
ai/
|
|
telephony/
|
|
shared/
|
|
types/
|
|
ui/
|
|
|
|
infrastructure/
|
|
docker/
|
|
freeswitch/
|
|
postgres/
|
|
redis/
|
|
nginx/
|
|
|
|
scripts/
|
|
|
|
docs/
|
|
```
|
|
|
|
Pode adaptar se houver justificativa técnica.
|
|
|
|
---
|
|
|
|
# 14. SERVIÇOS DOCKER
|
|
|
|
Criar aproximadamente:
|
|
|
|
```text
|
|
b2bcall-frontend
|
|
|
|
b2bcall-api
|
|
|
|
b2bcall-dialer
|
|
|
|
b2bcall-fs-events
|
|
|
|
b2bcall-fs-config
|
|
|
|
b2bcall-scheduler
|
|
|
|
b2bcall-ai-worker
|
|
|
|
b2bcall-billing-worker
|
|
|
|
b2bcall-freeswitch
|
|
|
|
b2bcall-postgres
|
|
|
|
b2bcall-redis
|
|
|
|
b2bcall-nginx
|
|
```
|
|
|
|
---
|
|
|
|
# 15. FREESWITCH
|
|
|
|
Utilizar FreeSWITCH como núcleo de telefonia.
|
|
|
|
Módulos importantes:
|
|
|
|
```text
|
|
mod_sofia
|
|
mod_event_socket
|
|
mod_callcenter
|
|
mod_xml_curl
|
|
mod_odbc_cdr
|
|
mod_commands
|
|
mod_dptools
|
|
mod_local_stream
|
|
mod_avmd
|
|
mod_curl
|
|
```
|
|
|
|
Carregar somente o necessário.
|
|
|
|
---
|
|
|
|
# 16. PRINCÍPIO FUNDAMENTAL DE TELEFONIA
|
|
|
|
Não recriar dentro de Node.js funcionalidades que o FreeSWITCH já possui.
|
|
|
|
Separação:
|
|
|
|
```text
|
|
B2BCall Predictive Engine
|
|
=
|
|
decide quantas chamadas iniciar
|
|
|
|
FreeSWITCH mod_callcenter
|
|
=
|
|
decide para qual agente entregar chamadas atendidas
|
|
```
|
|
|
|
---
|
|
|
|
# 17. TOPOLOGIA SIP
|
|
|
|
Arquitetura esperada:
|
|
|
|
```text
|
|
Internet
|
|
|
|
|
OpenSIPS
|
|
|
|
|
Rede SIP privada
|
|
|
|
|
FreeSWITCH
|
|
```
|
|
|
|
O FreeSWITCH NÃO deverá depender de IP SIP público.
|
|
|
|
Troncos poderão estar em rede privada:
|
|
|
|
```text
|
|
FreeSWITCH
|
|
|
|
|
Rede privada
|
|
|
|
|
Carrier / SBC
|
|
```
|
|
|
|
---
|
|
|
|
# 18. RTP
|
|
|
|
Separar claramente:
|
|
|
|
```text
|
|
SIP signaling
|
|
```
|
|
|
|
de:
|
|
|
|
```text
|
|
RTP media
|
|
```
|
|
|
|
Preparar arquitetura compatível com:
|
|
|
|
```text
|
|
OpenSIPS + RTPengine
|
|
```
|
|
|
|
quando necessário.
|
|
|
|
Não assumir que OpenSIPS manipula RTP.
|
|
|
|
---
|
|
|
|
# 19. CONTAINER FREESWITCH
|
|
|
|
Criar imagem própria/controlada pelo projeto.
|
|
|
|
Não depender cegamente de imagem pública abandonada.
|
|
|
|
Avaliar:
|
|
|
|
```text
|
|
network_mode: host
|
|
```
|
|
|
|
ou:
|
|
|
|
```text
|
|
macvlan / ipvlan
|
|
```
|
|
|
|
considerando SIP e grande range UDP de RTP.
|
|
|
|
Documentar decisão em:
|
|
|
|
```text
|
|
docs/NETWORK_ARCHITECTURE.md
|
|
```
|
|
|
|
---
|
|
|
|
# 20. SOFIA PROFILES
|
|
|
|
Criar separação lógica como:
|
|
|
|
```text
|
|
internal
|
|
opensips
|
|
carriers
|
|
```
|
|
|
|
quando adequado.
|
|
|
|
Configurações:
|
|
|
|
* IP;
|
|
* porta;
|
|
* transport;
|
|
* codecs;
|
|
* context;
|
|
* ACL;
|
|
* NAT;
|
|
* timers.
|
|
|
|
---
|
|
|
|
# 21. MOD_EVENT_SOCKET
|
|
|
|
Utilizar:
|
|
|
|
```text
|
|
mod_event_socket
|
|
```
|
|
|
|
como principal integração de controle.
|
|
|
|
Criar serviço:
|
|
|
|
```text
|
|
b2bcall-fs-events
|
|
```
|
|
|
|
Manter conexão ESL permanente.
|
|
|
|
Não executar `fs_cli` via shell para cada ação operacional.
|
|
|
|
---
|
|
|
|
# 22. EVENT SOCKET SECURITY
|
|
|
|
Porta padrão:
|
|
|
|
```text
|
|
8021
|
|
```
|
|
|
|
NÃO pública.
|
|
|
|
Criar:
|
|
|
|
* password forte;
|
|
* ACL;
|
|
* firewall;
|
|
* acesso somente pela aplicação autorizada.
|
|
|
|
Nunca usar senha padrão.
|
|
|
|
---
|
|
|
|
# 23. EVENTOS FREESWITCH
|
|
|
|
Consumir no mínimo:
|
|
|
|
```text
|
|
HEARTBEAT
|
|
|
|
CHANNEL_CREATE
|
|
CHANNEL_ORIGINATE
|
|
|
|
CHANNEL_PROGRESS
|
|
CHANNEL_PROGRESS_MEDIA
|
|
|
|
CHANNEL_ANSWER
|
|
|
|
CHANNEL_BRIDGE
|
|
CHANNEL_UNBRIDGE
|
|
|
|
CHANNEL_HANGUP
|
|
CHANNEL_HANGUP_COMPLETE
|
|
CHANNEL_DESTROY
|
|
|
|
CHANNEL_STATE
|
|
CHANNEL_CALLSTATE
|
|
|
|
BACKGROUND_JOB
|
|
```
|
|
|
|
CUSTOM relevantes:
|
|
|
|
```text
|
|
callcenter::info
|
|
|
|
sofia::register
|
|
sofia::unregister
|
|
sofia::expire
|
|
sofia::gateway_state
|
|
```
|
|
|
|
Para AVMD:
|
|
|
|
```text
|
|
avmd::start
|
|
avmd::beep
|
|
avmd::stop
|
|
```
|
|
|
|
---
|
|
|
|
# 24. NORMALIZAÇÃO DOS EVENTOS
|
|
|
|
Criar eventos internos B2BCall.
|
|
|
|
Exemplo:
|
|
|
|
```text
|
|
CALL_CREATED
|
|
CALL_RINGING
|
|
CALL_ANSWERED
|
|
CALL_BRIDGED
|
|
CALL_ENDED
|
|
|
|
EXTENSION_REGISTERED
|
|
EXTENSION_UNREGISTERED
|
|
|
|
AGENT_STATUS_CHANGED
|
|
|
|
GATEWAY_UP
|
|
GATEWAY_DOWN
|
|
```
|
|
|
|
Não espalhar headers ESL pelo domínio inteiro.
|
|
|
|
---
|
|
|
|
# 25. TELEPHONY PROVIDER
|
|
|
|
Criar interface:
|
|
|
|
```typescript
|
|
interface TelephonyProvider {
|
|
originate(): Promise<void>;
|
|
killCall(): Promise<void>;
|
|
transfer(): Promise<void>;
|
|
bridge(): Promise<void>;
|
|
|
|
getChannels(): Promise<unknown>;
|
|
getCalls(): Promise<unknown>;
|
|
|
|
getRegistrations(): Promise<unknown>;
|
|
getGateways(): Promise<unknown>;
|
|
|
|
getQueues(): Promise<unknown>;
|
|
|
|
setAgentStatus(): Promise<void>;
|
|
setAgentContact(): Promise<void>;
|
|
|
|
addAgentToQueue(): Promise<void>;
|
|
removeAgentFromQueue(): Promise<void>;
|
|
|
|
reloadXml(): Promise<void>;
|
|
}
|
|
```
|
|
|
|
Implementação:
|
|
|
|
```text
|
|
FreeSwitchTelephonyProvider
|
|
```
|
|
|
|
---
|
|
|
|
# 26. MOD_XML_CURL
|
|
|
|
Utilizar principalmente para:
|
|
|
|
```text
|
|
Directory
|
|
Dialplan
|
|
```
|
|
|
|
Criar:
|
|
|
|
```text
|
|
b2bcall-fs-config
|
|
```
|
|
|
|
Fluxo:
|
|
|
|
```text
|
|
FreeSWITCH
|
|
↓
|
|
mod_xml_curl
|
|
↓
|
|
B2BCall fs-config
|
|
↓
|
|
PostgreSQL
|
|
↓
|
|
XML
|
|
```
|
|
|
|
Não colocar todas as configurações críticas via XML Curl.
|
|
|
|
---
|
|
|
|
# 27. CONFIGURAÇÕES DE BOOT
|
|
|
|
Manter localmente quando adequado:
|
|
|
|
```text
|
|
event_socket.conf.xml
|
|
modules.conf.xml
|
|
sofia bootstrap
|
|
xml_curl.conf.xml
|
|
switch.conf.xml
|
|
```
|
|
|
|
O FreeSWITCH precisa conseguir subir mesmo se a API estiver temporariamente indisponível.
|
|
|
|
---
|
|
|
|
# 28. SAAS MULTI-TENANT DESDE O PRIMEIRO COMMIT
|
|
|
|
O B2BCall é MULTI-TENANT desde sua arquitetura inicial.
|
|
|
|
Isso deve existir em:
|
|
|
|
* banco;
|
|
* API;
|
|
* autenticação;
|
|
* RBAC;
|
|
* WebSocket;
|
|
* FreeSWITCH;
|
|
* ramais;
|
|
* agentes;
|
|
* filas;
|
|
* trunks;
|
|
* campanhas;
|
|
* chamadas;
|
|
* leads;
|
|
* gravações;
|
|
* IA;
|
|
* billing;
|
|
* relatórios.
|
|
|
|
---
|
|
|
|
# 29. TENANTS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
tenants
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
id UUID
|
|
|
|
code
|
|
slug
|
|
|
|
legal_name
|
|
trade_name
|
|
|
|
tax_id
|
|
|
|
status
|
|
|
|
timezone
|
|
locale
|
|
|
|
billing_currency
|
|
|
|
telephony_domain
|
|
|
|
created_at
|
|
updated_at
|
|
deleted_at
|
|
```
|
|
|
|
Status:
|
|
|
|
```text
|
|
TRIAL
|
|
ACTIVE
|
|
SUSPENDED
|
|
PAST_DUE
|
|
CANCELLED
|
|
```
|
|
|
|
---
|
|
|
|
# 30. TENANT ID
|
|
|
|
Toda tabela tenant-scoped deverá possuir:
|
|
|
|
```text
|
|
tenant_id UUID NOT NULL
|
|
```
|
|
|
|
Exemplos:
|
|
|
|
```text
|
|
extensions
|
|
agents
|
|
queues
|
|
trunks
|
|
campaigns
|
|
leads
|
|
calls
|
|
recordings
|
|
ai_jobs
|
|
usage_events
|
|
```
|
|
|
|
---
|
|
|
|
# 31. NÃO CONFIAR NO TENANT_ID DO FRONTEND
|
|
|
|
Nunca confiar em:
|
|
|
|
```json
|
|
{
|
|
"tenant_id": "..."
|
|
}
|
|
```
|
|
|
|
enviado pelo browser.
|
|
|
|
Resolver tenant a partir de:
|
|
|
|
```text
|
|
authenticated user
|
|
+
|
|
tenant membership
|
|
+
|
|
authorized tenant context
|
|
```
|
|
|
|
---
|
|
|
|
# 32. POSTGRESQL RLS
|
|
|
|
Implementar:
|
|
|
|
```text
|
|
ROW LEVEL SECURITY
|
|
```
|
|
|
|
nas tabelas críticas tenant-scoped.
|
|
|
|
Defense-in-depth:
|
|
|
|
```text
|
|
RBAC
|
|
+
|
|
object authorization
|
|
+
|
|
tenant repositories
|
|
+
|
|
PostgreSQL RLS
|
|
```
|
|
|
|
---
|
|
|
|
# 33. TENANT CONTEXT
|
|
|
|
Criar mecanismo seguro de tenant na conexão/transaction PostgreSQL.
|
|
|
|
Exemplo conceitual:
|
|
|
|
```text
|
|
app.current_tenant_id
|
|
```
|
|
|
|
Policies deverão utilizar esse contexto.
|
|
|
|
Platform Super Admin deverá possuir fluxo privilegiado explícito e auditado.
|
|
|
|
---
|
|
|
|
# 34. UNIQUENESS
|
|
|
|
Não utilizar:
|
|
|
|
```text
|
|
UNIQUE(extension_number)
|
|
```
|
|
|
|
globalmente.
|
|
|
|
Utilizar:
|
|
|
|
```text
|
|
UNIQUE(tenant_id, extension_number)
|
|
```
|
|
|
|
O mesmo vale para:
|
|
|
|
* agentes;
|
|
* filas;
|
|
* campanhas;
|
|
* trunks;
|
|
* pausas;
|
|
* dispositions.
|
|
|
|
---
|
|
|
|
# 35. TELEPHONY NODES
|
|
|
|
Mesmo começando com um FreeSWITCH, criar:
|
|
|
|
```text
|
|
telephony_nodes
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
id
|
|
|
|
name
|
|
hostname
|
|
internal_ip
|
|
|
|
esl_host
|
|
esl_port
|
|
|
|
instance_id
|
|
|
|
status
|
|
|
|
max_sessions
|
|
max_cps
|
|
|
|
enabled
|
|
```
|
|
|
|
---
|
|
|
|
# 36. TENANT TELEPHONY ASSIGNMENT
|
|
|
|
Criar:
|
|
|
|
```text
|
|
tenant_telephony_assignments
|
|
```
|
|
|
|
Inicialmente:
|
|
|
|
```text
|
|
tenant
|
|
→
|
|
FreeSWITCH principal
|
|
```
|
|
|
|
Arquitetura deve permitir expansão futura.
|
|
|
|
---
|
|
|
|
# 37. MOD_CALLCENTER
|
|
|
|
Utilizar:
|
|
|
|
```text
|
|
mod_callcenter
|
|
```
|
|
|
|
como ACD.
|
|
|
|
FreeSWITCH controla:
|
|
|
|
```text
|
|
queues
|
|
agents
|
|
tiers
|
|
offering
|
|
distribution
|
|
bridging
|
|
wrap-up
|
|
```
|
|
|
|
B2BCall controla:
|
|
|
|
```text
|
|
users
|
|
permissions
|
|
campaigns
|
|
leads
|
|
predictive pacing
|
|
billing
|
|
AI
|
|
reports
|
|
audit
|
|
```
|
|
|
|
---
|
|
|
|
# 38. CALLCENTER DATABASE
|
|
|
|
Evitar SQLite como banco operacional de produção.
|
|
|
|
Utilizar PostgreSQL via ODBC quando adequado.
|
|
|
|
Separar schemas:
|
|
|
|
```text
|
|
app
|
|
freeswitch
|
|
```
|
|
|
|
ou solução equivalente.
|
|
|
|
---
|
|
|
|
# 39. RAMAIS
|
|
|
|
Criar tela:
|
|
|
|
```text
|
|
Telefonia → Ramais
|
|
```
|
|
|
|
Tabela:
|
|
|
|
```text
|
|
extensions
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
tenant_id
|
|
|
|
number
|
|
name
|
|
domain
|
|
|
|
sip_password
|
|
|
|
caller_id_name
|
|
caller_id_number
|
|
|
|
context
|
|
sofia_profile
|
|
|
|
codecs
|
|
|
|
max_registrations
|
|
|
|
enabled
|
|
```
|
|
|
|
Gerar senha SIP forte.
|
|
|
|
Criptografar em repouso.
|
|
|
|
Nunca mostrar novamente a senha inteira.
|
|
|
|
---
|
|
|
|
# 40. STATUS DOS RAMAIS
|
|
|
|
Consumir eventos:
|
|
|
|
```text
|
|
sofia::register
|
|
sofia::unregister
|
|
sofia::expire
|
|
```
|
|
|
|
Atualizar via WebSocket.
|
|
|
|
Evitar polling frequente.
|
|
|
|
---
|
|
|
|
# 41. TRONCOS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
Telefonia → Troncos
|
|
```
|
|
|
|
Tabela:
|
|
|
|
```text
|
|
trunks
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
tenant_id
|
|
|
|
name
|
|
description
|
|
|
|
sofia_profile
|
|
|
|
host
|
|
proxy
|
|
realm
|
|
|
|
register
|
|
|
|
username
|
|
password
|
|
|
|
from_user
|
|
from_domain
|
|
|
|
register_proxy
|
|
outbound_proxy
|
|
|
|
expire_seconds
|
|
retry_seconds
|
|
|
|
caller_id_name
|
|
caller_id_number
|
|
|
|
codecs
|
|
|
|
dtmf_mode
|
|
|
|
ping
|
|
ping_frequency
|
|
|
|
transport
|
|
|
|
inbound_context
|
|
|
|
max_cps
|
|
max_channels
|
|
|
|
enabled
|
|
```
|
|
|
|
Suportar:
|
|
|
|
```text
|
|
IP Authentication
|
|
Registration
|
|
Username/Password
|
|
```
|
|
|
|
---
|
|
|
|
# 42. STATUS DOS TRONCOS
|
|
|
|
Mostrar estados reais:
|
|
|
|
```text
|
|
UP
|
|
DOWN
|
|
REGISTERED
|
|
TRYING
|
|
FAILED
|
|
UNREGISTERED
|
|
UNKNOWN
|
|
```
|
|
|
|
Consumir:
|
|
|
|
```text
|
|
sofia::gateway_state
|
|
```
|
|
|
|
e comandos seguros quando necessário.
|
|
|
|
---
|
|
|
|
# 43. DIALPLAN
|
|
|
|
Criar:
|
|
|
|
```text
|
|
Telefonia → Dialplan
|
|
```
|
|
|
|
Não fazer somente textarea.
|
|
|
|
Editor estruturado:
|
|
|
|
```text
|
|
Context
|
|
|
|
Extension Name
|
|
|
|
Condition Field
|
|
Condition Expression
|
|
|
|
Actions
|
|
|
|
Anti-Actions
|
|
|
|
Continue
|
|
Order
|
|
Enabled
|
|
```
|
|
|
|
Salvar no PostgreSQL.
|
|
|
|
Gerar XML.
|
|
|
|
---
|
|
|
|
# 44. VERSIONAMENTO DIALPLAN
|
|
|
|
Criar:
|
|
|
|
```text
|
|
dialplan_versions
|
|
```
|
|
|
|
Fluxo:
|
|
|
|
1. gerar;
|
|
2. validar XML;
|
|
3. versionar;
|
|
4. ativar;
|
|
5. `reloadxml`;
|
|
6. verificar;
|
|
7. rollback se necessário.
|
|
|
|
---
|
|
|
|
# 45. AGENTES
|
|
|
|
Separar:
|
|
|
|
```text
|
|
User
|
|
Agent
|
|
Extension
|
|
```
|
|
|
|
Criar:
|
|
|
|
```text
|
|
agents
|
|
agent_sessions
|
|
agent_state_events
|
|
```
|
|
|
|
Todos tenant-scoped.
|
|
|
|
---
|
|
|
|
# 46. ESTADOS DOS AGENTES
|
|
|
|
Estados canônicos:
|
|
|
|
```text
|
|
OFFLINE
|
|
LOGGED_IN
|
|
AVAILABLE
|
|
RESERVED
|
|
RINGING
|
|
IN_CALL
|
|
WRAP_UP
|
|
PAUSED
|
|
```
|
|
|
|
Mapear estados FreeSWITCH corretamente.
|
|
|
|
---
|
|
|
|
# 47. LOGIN DO AGENTE
|
|
|
|
Fluxo:
|
|
|
|
```text
|
|
Login B2BCall
|
|
↓
|
|
Validar usuário
|
|
↓
|
|
Validar ramal
|
|
↓
|
|
Criar agent_session
|
|
↓
|
|
Configurar agent contact
|
|
↓
|
|
Configurar mod_callcenter
|
|
↓
|
|
Configurar tiers
|
|
↓
|
|
AVAILABLE
|
|
```
|
|
|
|
---
|
|
|
|
# 48. PAUSAS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
Call Center → Pausas
|
|
```
|
|
|
|
Tabelas:
|
|
|
|
```text
|
|
pause_reasons
|
|
agent_pause_events
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
tenant_id
|
|
|
|
name
|
|
code
|
|
description
|
|
|
|
max_duration
|
|
|
|
paid
|
|
|
|
enabled
|
|
```
|
|
|
|
Ao pausar:
|
|
|
|
```text
|
|
FreeSWITCH → On Break
|
|
B2BCall → PAUSED
|
|
```
|
|
|
|
---
|
|
|
|
# 49. TELA DO AGENTE
|
|
|
|
Criar interface específica.
|
|
|
|
Mostrar:
|
|
|
|
```text
|
|
Agente
|
|
Ramal
|
|
Fila
|
|
Campanha
|
|
|
|
Status
|
|
Tempo no status
|
|
|
|
Lead
|
|
Telefone
|
|
|
|
Tempo da chamada
|
|
```
|
|
|
|
Botões:
|
|
|
|
```text
|
|
DISPONÍVEL
|
|
|
|
PAUSA
|
|
|
|
FINALIZAR PAUSA
|
|
|
|
LOGOUT
|
|
```
|
|
|
|
---
|
|
|
|
# 50. FILAS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
Call Center → Filas
|
|
```
|
|
|
|
Campos relevantes:
|
|
|
|
```text
|
|
tenant_id
|
|
|
|
name
|
|
description
|
|
|
|
strategy
|
|
|
|
moh
|
|
|
|
announce_sound
|
|
announce_frequency
|
|
|
|
max_wait_time
|
|
max_wait_time_with_no_agent
|
|
|
|
agent_no_answer_status
|
|
|
|
tier_rules
|
|
|
|
discard_abandoned_after
|
|
|
|
abandoned_resume_allowed
|
|
|
|
skip_agents_with_external_calls
|
|
|
|
recording_enabled
|
|
|
|
enabled
|
|
```
|
|
|
|
---
|
|
|
|
# 51. ESTRATÉGIAS
|
|
|
|
Suportar:
|
|
|
|
```text
|
|
longest-idle-agent
|
|
|
|
round-robin
|
|
|
|
top-down
|
|
|
|
agent-with-least-talk-time
|
|
|
|
agent-with-fewest-calls
|
|
|
|
sequentially-by-agent-order
|
|
|
|
ring-all
|
|
|
|
ring-progressively
|
|
```
|
|
|
|
Mostrar tooltip explicativo.
|
|
|
|
---
|
|
|
|
# 52. TIERS
|
|
|
|
Criar relação:
|
|
|
|
```text
|
|
Queue
|
|
↓
|
|
Tier
|
|
↓
|
|
Agent
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
tenant_id
|
|
queue_id
|
|
agent_id
|
|
level
|
|
position
|
|
```
|
|
|
|
---
|
|
|
|
# 53. WRAP-UP
|
|
|
|
Utilizar:
|
|
|
|
```text
|
|
wrap-up-time
|
|
```
|
|
|
|
Enquanto em wrap-up:
|
|
|
|
```text
|
|
agente não está disponível
|
|
```
|
|
|
|
O Predictive Dialer deve considerar isso.
|
|
|
|
---
|
|
|
|
# 54. MONITORAMENTO DAS FILAS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
Monitoramento → Filas
|
|
```
|
|
|
|
Mostrar em tempo real:
|
|
|
|
```text
|
|
Chamadas esperando
|
|
|
|
Agentes logados
|
|
Disponíveis
|
|
Reservados
|
|
Ringing
|
|
Em chamada
|
|
Wrap-up
|
|
Pausados
|
|
Offline
|
|
|
|
Maior espera
|
|
|
|
TME
|
|
TMA
|
|
|
|
Atendidas
|
|
Abandonadas
|
|
|
|
Service Level
|
|
Abandon Rate
|
|
```
|
|
|
|
---
|
|
|
|
# 55. MONITORAMENTO DOS RAMAIS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
Monitoramento → Ramais
|
|
```
|
|
|
|
Cada ramal deverá aparecer em card.
|
|
|
|
Convenção obrigatória:
|
|
|
|
```text
|
|
CINZA
|
|
offline
|
|
|
|
VERDE
|
|
disponível
|
|
|
|
LARANJA
|
|
ocupado
|
|
|
|
AZUL
|
|
agente logado
|
|
|
|
VERMELHO
|
|
agente em pausa
|
|
```
|
|
|
|
Prioridade:
|
|
|
|
```text
|
|
PAUSA
|
|
>
|
|
EM CHAMADA
|
|
>
|
|
AGENTE LOGADO
|
|
>
|
|
DISPONÍVEL
|
|
>
|
|
OFFLINE
|
|
```
|
|
|
|
Mostrar:
|
|
|
|
```text
|
|
Ramal
|
|
Nome
|
|
Agente
|
|
Fila
|
|
Status
|
|
Tempo no estado
|
|
Campanha
|
|
Duração da chamada
|
|
```
|
|
|
|
---
|
|
|
|
# 56. QUOTAS SAAS
|
|
|
|
Criar sistema genérico de:
|
|
|
|
```text
|
|
entitlements
|
|
```
|
|
|
|
Não espalhar regras:
|
|
|
|
```text
|
|
if plan == PRO
|
|
```
|
|
|
|
pelo código.
|
|
|
|
Entitlements:
|
|
|
|
```text
|
|
max_extensions
|
|
|
|
max_agents
|
|
|
|
max_trunks
|
|
|
|
max_queues
|
|
|
|
max_campaigns
|
|
|
|
max_cps
|
|
|
|
max_concurrent_calls
|
|
|
|
max_daily_calls
|
|
|
|
max_monthly_calls
|
|
|
|
max_recording_storage_gb
|
|
|
|
recording_enabled
|
|
|
|
ai_enabled
|
|
|
|
ai_transcription_enabled
|
|
|
|
ai_analysis_enabled
|
|
|
|
api_access_enabled
|
|
```
|
|
|
|
---
|
|
|
|
# 57. QUOTA DE RAMAIS
|
|
|
|
Antes de criar:
|
|
|
|
```text
|
|
active_extensions < max_extensions
|
|
```
|
|
|
|
Caso ultrapasse:
|
|
|
|
retornar erro de quota.
|
|
|
|
---
|
|
|
|
# 58. QUOTA DE AGENTES
|
|
|
|
Antes de criar agente:
|
|
|
|
```text
|
|
active_agents < max_agents
|
|
```
|
|
|
|
---
|
|
|
|
# 59. QUOTA DE TRONCOS
|
|
|
|
Antes de criar trunk:
|
|
|
|
```text
|
|
active_trunks < max_trunks
|
|
```
|
|
|
|
---
|
|
|
|
# 60. CPS TENANT
|
|
|
|
Cada tenant possui:
|
|
|
|
```text
|
|
max_cps
|
|
```
|
|
|
|
Esse limite deve considerar a soma de todas as campanhas do tenant.
|
|
|
|
---
|
|
|
|
# 61. CHAMADAS SIMULTÂNEAS TENANT
|
|
|
|
Cada tenant possui:
|
|
|
|
```text
|
|
max_concurrent_calls
|
|
```
|
|
|
|
Mesmo que tenha várias campanhas, o total não pode ultrapassar.
|
|
|
|
---
|
|
|
|
# 62. HIERARQUIA DE LIMITES
|
|
|
|
Toda originação deve respeitar:
|
|
|
|
```text
|
|
GLOBAL
|
|
↓
|
|
TELEPHONY NODE
|
|
↓
|
|
TENANT
|
|
↓
|
|
TRUNK
|
|
↓
|
|
CAMPAIGN
|
|
```
|
|
|
|
CPS efetivo:
|
|
|
|
```text
|
|
MIN(
|
|
global_available_cps,
|
|
node_available_cps,
|
|
tenant_available_cps,
|
|
trunk_available_cps,
|
|
campaign_available_cps
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
# 63. CAMPANHAS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
Discador → Campanhas
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
tenant_id
|
|
|
|
name
|
|
description
|
|
|
|
queue_id
|
|
trunk_id
|
|
|
|
caller_id_name
|
|
caller_id_number
|
|
|
|
timezone
|
|
|
|
start_date
|
|
end_date
|
|
|
|
days_of_week
|
|
|
|
start_time
|
|
end_time
|
|
|
|
max_cps
|
|
|
|
max_concurrent_calls
|
|
|
|
pacing_initial
|
|
pacing_min
|
|
pacing_max
|
|
|
|
target_abandon_rate
|
|
|
|
ring_timeout
|
|
|
|
max_attempts
|
|
|
|
recording_enabled
|
|
|
|
avmd_enabled
|
|
|
|
ai_transcription_enabled
|
|
|
|
ai_analysis_enabled
|
|
```
|
|
|
|
---
|
|
|
|
# 64. STATUS CAMPANHAS
|
|
|
|
```text
|
|
DRAFT
|
|
READY
|
|
WAITING_SCHEDULE
|
|
RUNNING
|
|
PAUSED
|
|
DRAINING
|
|
STOPPED
|
|
COMPLETED
|
|
ERROR
|
|
```
|
|
|
|
---
|
|
|
|
# 65. DRAINING
|
|
|
|
Ao selecionar:
|
|
|
|
```text
|
|
DRAIN
|
|
```
|
|
|
|
não originar novas chamadas.
|
|
|
|
Permitir finalizar as existentes.
|
|
|
|
---
|
|
|
|
# 66. STOP
|
|
|
|
Por padrão:
|
|
|
|
```text
|
|
STOP
|
|
=
|
|
não originar novas chamadas
|
|
+
|
|
deixar chamadas já conectadas terminarem
|
|
```
|
|
|
|
Não derrubar chamadas ativas automaticamente.
|
|
|
|
---
|
|
|
|
# 67. LEADS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
leads
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
tenant_id
|
|
campaign_id
|
|
|
|
name
|
|
|
|
phone_original
|
|
phone_normalized
|
|
|
|
status
|
|
|
|
attempt_count
|
|
|
|
last_attempt_at
|
|
next_attempt_at
|
|
|
|
last_result
|
|
|
|
custom_fields JSONB
|
|
|
|
created_at
|
|
updated_at
|
|
```
|
|
|
|
---
|
|
|
|
# 68. STATUS LEAD
|
|
|
|
```text
|
|
NEW
|
|
READY
|
|
RESERVED
|
|
ORIGINATING
|
|
RINGING
|
|
ANSWERED
|
|
QUEUEING
|
|
CONNECTED_AGENT
|
|
|
|
BUSY
|
|
NO_ANSWER
|
|
FAILED
|
|
|
|
VOICEMAIL
|
|
|
|
CALLBACK
|
|
|
|
COMPLETED
|
|
|
|
DO_NOT_CALL
|
|
|
|
MAX_ATTEMPTS
|
|
```
|
|
|
|
---
|
|
|
|
# 69. IMPORTAÇÃO CSV
|
|
|
|
Suportar formato mínimo:
|
|
|
|
```csv
|
|
nome,telefone
|
|
Joao Silva,48999999999
|
|
Maria Souza,11999999999
|
|
```
|
|
|
|
Wizard:
|
|
|
|
```text
|
|
Upload
|
|
↓
|
|
Preview
|
|
↓
|
|
Mapeamento
|
|
↓
|
|
Validação
|
|
↓
|
|
Normalização
|
|
↓
|
|
Duplicados
|
|
↓
|
|
Importação
|
|
```
|
|
|
|
Mostrar:
|
|
|
|
```text
|
|
Total
|
|
Válidos
|
|
Inválidos
|
|
Duplicados
|
|
Importados
|
|
```
|
|
|
|
Processar em streaming/batches.
|
|
|
|
---
|
|
|
|
# 70. NORMALIZAÇÃO DE TELEFONE
|
|
|
|
Criar serviço dedicado.
|
|
|
|
Não espalhar regexes.
|
|
|
|
Guardar:
|
|
|
|
```text
|
|
phone_original
|
|
phone_normalized
|
|
```
|
|
|
|
Inicialmente preparado para Brasil.
|
|
|
|
Arquitetura preparada para E.164.
|
|
|
|
---
|
|
|
|
# 71. LISTA DE BLOQUEIO
|
|
|
|
Criar:
|
|
|
|
```text
|
|
Discador → Lista de Bloqueio
|
|
```
|
|
|
|
Tabela:
|
|
|
|
```text
|
|
suppression_list
|
|
```
|
|
|
|
Tenant-scoped.
|
|
|
|
Antes de qualquer chamada:
|
|
|
|
```text
|
|
CHECK SUPPRESSION LIST
|
|
```
|
|
|
|
obrigatório.
|
|
|
|
---
|
|
|
|
# 72. PREDICTIVE DIALER
|
|
|
|
Criar serviço:
|
|
|
|
```text
|
|
PredictiveDialerEngine
|
|
```
|
|
|
|
Não implementar apenas:
|
|
|
|
```text
|
|
for lead -> originate
|
|
```
|
|
|
|
Isso não é discador preditivo.
|
|
|
|
---
|
|
|
|
# 73. DADOS DO PREDICTIVE ENGINE
|
|
|
|
Considerar:
|
|
|
|
```text
|
|
available_agents
|
|
|
|
reserved_agents
|
|
|
|
ringing_agents
|
|
|
|
agents_in_call
|
|
|
|
agents_in_wrapup
|
|
|
|
agents_paused
|
|
|
|
calls_originating
|
|
|
|
calls_ringing
|
|
|
|
answered_waiting_agent
|
|
|
|
answer_probability
|
|
|
|
average_answer_delay
|
|
|
|
average_talk_time
|
|
|
|
abandon_rate
|
|
|
|
current_cps
|
|
|
|
max_cps
|
|
|
|
max_concurrent_calls
|
|
```
|
|
|
|
---
|
|
|
|
# 74. PREVISÃO DE LIBERAÇÃO
|
|
|
|
Utilizar:
|
|
|
|
```text
|
|
elapsed_talk_time
|
|
+
|
|
historical talk time distribution
|
|
```
|
|
|
|
para estimar agentes disponíveis em:
|
|
|
|
```text
|
|
5 segundos
|
|
|
|
10 segundos
|
|
|
|
15 segundos
|
|
|
|
20 segundos
|
|
```
|
|
|
|
Não precisa Machine Learning inicialmente.
|
|
|
|
Preferir algoritmo estatístico determinístico e explicável.
|
|
|
|
---
|
|
|
|
# 75. EWMA
|
|
|
|
Utilizar EWMA ou equivalente para:
|
|
|
|
```text
|
|
answer_probability
|
|
|
|
average_answer_delay
|
|
|
|
TMA
|
|
|
|
abandon_rate
|
|
```
|
|
|
|
Evitar oscilações violentas do pacing.
|
|
|
|
---
|
|
|
|
# 76. CÁLCULO CONCEITUAL
|
|
|
|
```text
|
|
expected_agent_capacity =
|
|
available_agents
|
|
+
|
|
predicted_agents_becoming_available
|
|
```
|
|
|
|
```text
|
|
expected_answers =
|
|
calls_to_originate * answer_probability
|
|
```
|
|
|
|
Objetivo:
|
|
|
|
```text
|
|
expected_answers
|
|
≈
|
|
expected_agent_capacity
|
|
```
|
|
|
|
Aplicando:
|
|
|
|
```text
|
|
pacing_factor
|
|
```
|
|
|
|
e limites.
|
|
|
|
---
|
|
|
|
# 77. CPS DISTRIBUÍDO
|
|
|
|
Implementar token bucket ou equivalente.
|
|
|
|
Utilizar Redis.
|
|
|
|
Deve funcionar com múltiplos workers.
|
|
|
|
Não utilizar somente:
|
|
|
|
```text
|
|
sleep()
|
|
```
|
|
|
|
como controle.
|
|
|
|
---
|
|
|
|
# 78. RESERVA DE LEADS
|
|
|
|
Evitar duplicidade.
|
|
|
|
Utilizar PostgreSQL:
|
|
|
|
```sql
|
|
FOR UPDATE SKIP LOCKED
|
|
```
|
|
|
|
ou solução transacional equivalente.
|
|
|
|
Fluxo:
|
|
|
|
```text
|
|
READY
|
|
↓
|
|
RESERVED
|
|
↓
|
|
ORIGINATING
|
|
```
|
|
|
|
atômico.
|
|
|
|
---
|
|
|
|
# 79. LOCK DE CAMPANHA
|
|
|
|
Criar:
|
|
|
|
```text
|
|
dialer:campaign:{id}
|
|
```
|
|
|
|
com:
|
|
|
|
```text
|
|
TTL
|
|
ownership token
|
|
renewal
|
|
safe release
|
|
```
|
|
|
|
---
|
|
|
|
# 80. ORIGINATE
|
|
|
|
Utilizar:
|
|
|
|
```text
|
|
bgapi originate
|
|
```
|
|
|
|
via ESL.
|
|
|
|
Não originar milhares de chamadas sincronamente.
|
|
|
|
---
|
|
|
|
# 81. IDENTIFICADORES DA CHAMADA
|
|
|
|
Criar antes do originate:
|
|
|
|
```text
|
|
tenant_id
|
|
|
|
call_id
|
|
|
|
attempt_id
|
|
|
|
campaign_id
|
|
|
|
lead_id
|
|
|
|
origination_uuid
|
|
```
|
|
|
|
Enviar como channel variables:
|
|
|
|
```text
|
|
b2bcall_tenant_id
|
|
|
|
b2bcall_call_id
|
|
|
|
b2bcall_attempt_id
|
|
|
|
b2bcall_campaign_id
|
|
|
|
b2bcall_lead_id
|
|
```
|
|
|
|
---
|
|
|
|
# 82. STATE MACHINE
|
|
|
|
```text
|
|
CREATED
|
|
|
|
RESERVED
|
|
|
|
ORIGINATING
|
|
|
|
ORIGINATED
|
|
|
|
RINGING
|
|
|
|
ANSWERED
|
|
|
|
QUEUEING
|
|
|
|
AGENT_CONNECTED
|
|
|
|
COMPLETED
|
|
|
|
BUSY
|
|
|
|
NO_ANSWER
|
|
|
|
FAILED
|
|
|
|
ABANDONED
|
|
```
|
|
|
|
Persistir transições.
|
|
|
|
---
|
|
|
|
# 83. FLUXO DA CHAMADA PREDITIVA
|
|
|
|
```text
|
|
Lead
|
|
↓
|
|
Reserve
|
|
↓
|
|
Predictive Engine
|
|
↓
|
|
CPS Limiter
|
|
↓
|
|
FreeSWITCH bgapi originate
|
|
↓
|
|
Sofia Gateway
|
|
↓
|
|
PSTN
|
|
```
|
|
|
|
Se atender:
|
|
|
|
```text
|
|
ANSWER
|
|
↓
|
|
AVMD opcional
|
|
↓
|
|
mod_callcenter
|
|
↓
|
|
Queue
|
|
↓
|
|
Agent
|
|
↓
|
|
Bridge
|
|
```
|
|
|
|
---
|
|
|
|
# 84. ABANDONO
|
|
|
|
Se:
|
|
|
|
```text
|
|
abandon_rate > target
|
|
```
|
|
|
|
reduzir pacing.
|
|
|
|
Se continuar:
|
|
|
|
```text
|
|
modo conservador
|
|
```
|
|
|
|
Se atingir limite crítico:
|
|
|
|
```text
|
|
suspender temporariamente novas originations
|
|
```
|
|
|
|
---
|
|
|
|
# 85. NÃO DISCAGEM SEM CAPACIDADE
|
|
|
|
Não utilizar o sistema simplesmente para descobrir quais números atendem.
|
|
|
|
O objetivo é conectar clientes a agentes.
|
|
|
|
Não originar agressivamente sem capacidade prevista de agentes.
|
|
|
|
---
|
|
|
|
# 86. RETRY
|
|
|
|
Criar regras configuráveis.
|
|
|
|
Exemplo:
|
|
|
|
```text
|
|
BUSY -> 15 min
|
|
|
|
NO_ANSWER -> 60 min
|
|
|
|
CONGESTION -> 5 min
|
|
|
|
FAILED -> 30 min
|
|
```
|
|
|
|
Nunca retry infinito.
|
|
|
|
---
|
|
|
|
# 87. AVMD
|
|
|
|
Utilizar opcionalmente:
|
|
|
|
```text
|
|
mod_avmd
|
|
```
|
|
|
|
Não tratar como detector perfeito de humano/máquina.
|
|
|
|
Resultados internos quando possível:
|
|
|
|
```text
|
|
HUMAN
|
|
MACHINE_BEEP
|
|
UNKNOWN
|
|
```
|
|
|
|
---
|
|
|
|
# 88. CALLBACK
|
|
|
|
Criar:
|
|
|
|
```text
|
|
callbacks
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
tenant_id
|
|
lead_id
|
|
campaign_id
|
|
agent_id
|
|
|
|
scheduled_at
|
|
timezone
|
|
|
|
preferred_agent
|
|
|
|
notes
|
|
|
|
status
|
|
```
|
|
|
|
Scheduler deverá reativar corretamente.
|
|
|
|
---
|
|
|
|
# 89. DISPOSIÇÕES
|
|
|
|
Criar:
|
|
|
|
```text
|
|
Call Center → Disposições
|
|
```
|
|
|
|
Exemplos:
|
|
|
|
```text
|
|
VENDA
|
|
|
|
SEM INTERESSE
|
|
|
|
CALLBACK
|
|
|
|
NÚMERO ERRADO
|
|
|
|
DO_NOT_CALL
|
|
|
|
CAIXA POSTAL
|
|
|
|
OUTRO
|
|
```
|
|
|
|
Permitir personalização por tenant.
|
|
|
|
---
|
|
|
|
# 90. GRAVAÇÃO
|
|
|
|
Criar módulo profissional de gravações.
|
|
|
|
Tabela:
|
|
|
|
```text
|
|
recordings
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
tenant_id
|
|
call_id
|
|
|
|
storage_provider
|
|
|
|
object_key
|
|
|
|
format
|
|
|
|
duration_seconds
|
|
|
|
channels
|
|
|
|
size_bytes
|
|
|
|
checksum
|
|
|
|
recorded_at
|
|
|
|
retention_until
|
|
|
|
status
|
|
```
|
|
|
|
---
|
|
|
|
# 91. FREESWITCH RECORDING
|
|
|
|
Utilizar:
|
|
|
|
```text
|
|
record_session
|
|
```
|
|
|
|
ou mecanismo apropriado.
|
|
|
|
Preferencialmente gravar chamadas de Call Center em estéreo quando tecnicamente adequado:
|
|
|
|
```text
|
|
RECORD_STEREO=true
|
|
```
|
|
|
|
Objetivo:
|
|
|
|
```text
|
|
canal A
|
|
canal B
|
|
```
|
|
|
|
permitindo melhor identificação de agente e cliente.
|
|
|
|
Validar corretamente qual direção corresponde a qual speaker.
|
|
|
|
---
|
|
|
|
# 92. OBJECT STORAGE
|
|
|
|
Criar abstração:
|
|
|
|
```text
|
|
ObjectStorageProvider
|
|
```
|
|
|
|
Suportar:
|
|
|
|
```text
|
|
Local
|
|
S3 Compatible
|
|
```
|
|
|
|
Preparar para:
|
|
|
|
```text
|
|
AWS S3
|
|
MinIO
|
|
```
|
|
|
|
---
|
|
|
|
# 93. STORAGE PATH
|
|
|
|
Usar estrutura segura, por exemplo:
|
|
|
|
```text
|
|
tenants/{tenant_id}/recordings/YYYY/MM/DD/{call_id}.wav
|
|
```
|
|
|
|
Tenant nunca poderá fornecer object key arbitrário de outro tenant.
|
|
|
|
---
|
|
|
|
# 94. RETENÇÃO
|
|
|
|
Configurações:
|
|
|
|
```text
|
|
recording_retention_days
|
|
|
|
transcription_retention_days
|
|
```
|
|
|
|
por tenant/plano.
|
|
|
|
Scheduler deverá aplicar retenção.
|
|
|
|
---
|
|
|
|
# 95. INTELIGÊNCIA ARTIFICIAL
|
|
|
|
Criar módulo:
|
|
|
|
```text
|
|
IA
|
|
```
|
|
|
|
Submenus:
|
|
|
|
```text
|
|
Providers
|
|
|
|
Modelos
|
|
|
|
Prompts
|
|
|
|
Scorecards
|
|
|
|
Análises
|
|
|
|
Uso
|
|
|
|
Configurações
|
|
```
|
|
|
|
---
|
|
|
|
# 96. AI PROVIDER ABSTRACTION
|
|
|
|
Não hardcode OpenAI no domínio.
|
|
|
|
Criar abstração:
|
|
|
|
```typescript
|
|
interface AIProvider {
|
|
getCapabilities(): Promise<unknown>;
|
|
validateCredentials(): Promise<boolean>;
|
|
|
|
transcribe?(): Promise<unknown>;
|
|
analyze?(): Promise<unknown>;
|
|
summarize?(): Promise<unknown>;
|
|
structuredGenerate?(): Promise<unknown>;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
# 97. PROVIDERS INICIAIS
|
|
|
|
Preparar adapters para:
|
|
|
|
```text
|
|
OpenAI
|
|
|
|
Anthropic
|
|
```
|
|
|
|
Arquitetura deve permitir:
|
|
|
|
```text
|
|
Google
|
|
|
|
Azure OpenAI
|
|
|
|
AWS Bedrock
|
|
|
|
modelos locais
|
|
|
|
outros providers
|
|
```
|
|
|
|
futuramente.
|
|
|
|
---
|
|
|
|
# 98. NOMENCLATURA
|
|
|
|
Na integração utilizar:
|
|
|
|
```text
|
|
OpenAI API
|
|
```
|
|
|
|
e:
|
|
|
|
```text
|
|
Anthropic API
|
|
```
|
|
|
|
Não amarrar o domínio ao produto:
|
|
|
|
```text
|
|
ChatGPT
|
|
```
|
|
|
|
---
|
|
|
|
# 99. AI PROVIDERS TABLE
|
|
|
|
Criar:
|
|
|
|
```text
|
|
ai_providers
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
id
|
|
|
|
scope
|
|
|
|
tenant_id nullable
|
|
|
|
provider_type
|
|
|
|
name
|
|
|
|
base_url optional
|
|
|
|
encrypted_api_key
|
|
|
|
organization optional
|
|
|
|
project optional
|
|
|
|
enabled
|
|
|
|
created_at
|
|
updated_at
|
|
```
|
|
|
|
---
|
|
|
|
# 100. PROVIDER GLOBAL E BYOK
|
|
|
|
Permitir:
|
|
|
|
## Provider global
|
|
|
|
Configurado pelo platform admin.
|
|
|
|
## BYOK
|
|
|
|
```text
|
|
Bring Your Own Key
|
|
```
|
|
|
|
Tenant cadastra sua própria API key.
|
|
|
|
---
|
|
|
|
# 101. API KEYS
|
|
|
|
Criptografar em repouso usando:
|
|
|
|
```text
|
|
AES-256-GCM
|
|
```
|
|
|
|
ou equivalente moderno.
|
|
|
|
Master key fora do PostgreSQL.
|
|
|
|
Nunca mostrar key inteira após salvar.
|
|
|
|
---
|
|
|
|
# 102. CAPABILITIES
|
|
|
|
Criar conceito:
|
|
|
|
```text
|
|
TRANSCRIPTION
|
|
|
|
DIARIZATION
|
|
|
|
TEXT_ANALYSIS
|
|
|
|
STRUCTURED_OUTPUT
|
|
|
|
EMBEDDINGS
|
|
|
|
REALTIME_AUDIO
|
|
```
|
|
|
|
Nem todo provider terá todas as capacidades.
|
|
|
|
---
|
|
|
|
# 103. AI MODELS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
ai_models
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
provider_id
|
|
|
|
external_model_id
|
|
|
|
display_name
|
|
|
|
capabilities
|
|
|
|
input_cost
|
|
|
|
output_cost
|
|
|
|
audio_cost
|
|
|
|
enabled
|
|
```
|
|
|
|
Modelos devem ser configuráveis.
|
|
|
|
---
|
|
|
|
# 104. TRANSCRIPTION PROVIDER
|
|
|
|
Separar interface:
|
|
|
|
```text
|
|
TranscriptionProvider
|
|
```
|
|
|
|
Configuração:
|
|
|
|
```text
|
|
provider
|
|
|
|
model
|
|
|
|
language
|
|
|
|
diarization
|
|
```
|
|
|
|
---
|
|
|
|
# 105. ANALYSIS PROVIDER
|
|
|
|
Separar de transcrição.
|
|
|
|
Permitir exemplo:
|
|
|
|
```text
|
|
OpenAI → Transcrição
|
|
|
|
Anthropic → Análise
|
|
```
|
|
|
|
ou:
|
|
|
|
```text
|
|
OpenAI → Transcrição
|
|
OpenAI → Análise
|
|
```
|
|
|
|
---
|
|
|
|
# 106. PIPELINE IA
|
|
|
|
Após hangup:
|
|
|
|
```text
|
|
CALL COMPLETED
|
|
↓
|
|
Finalize Recording
|
|
↓
|
|
Upload Object Storage
|
|
↓
|
|
Create AI Job
|
|
↓
|
|
Transcription
|
|
↓
|
|
Speaker Mapping
|
|
↓
|
|
Analysis
|
|
↓
|
|
Structured Results
|
|
↓
|
|
Usage Metering
|
|
```
|
|
|
|
Tudo assíncrono.
|
|
|
|
Nunca bloquear a chamada esperando IA.
|
|
|
|
---
|
|
|
|
# 107. AI JOBS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
ai_jobs
|
|
```
|
|
|
|
Tipos:
|
|
|
|
```text
|
|
TRANSCRIPTION
|
|
ANALYSIS
|
|
REANALYSIS
|
|
```
|
|
|
|
Status:
|
|
|
|
```text
|
|
PENDING
|
|
PROCESSING
|
|
COMPLETED
|
|
FAILED
|
|
RETRYING
|
|
CANCELLED
|
|
```
|
|
|
|
---
|
|
|
|
# 108. RETRY IA
|
|
|
|
Implementar:
|
|
|
|
```text
|
|
retry
|
|
|
|
exponential backoff
|
|
|
|
dead-letter strategy
|
|
```
|
|
|
|
Limitar tentativas.
|
|
|
|
---
|
|
|
|
# 109. TRANSCRIÇÕES
|
|
|
|
Criar:
|
|
|
|
```text
|
|
call_transcriptions
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
tenant_id
|
|
call_id
|
|
|
|
provider_id
|
|
model
|
|
|
|
language
|
|
|
|
text
|
|
|
|
status
|
|
|
|
duration_seconds
|
|
|
|
provider_request_id
|
|
|
|
input_usage
|
|
output_usage
|
|
|
|
provider_cost
|
|
|
|
created_at
|
|
```
|
|
|
|
---
|
|
|
|
# 110. SEGMENTOS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
call_transcript_segments
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
transcription_id
|
|
|
|
speaker
|
|
|
|
start_ms
|
|
|
|
end_ms
|
|
|
|
text
|
|
|
|
confidence optional
|
|
```
|
|
|
|
Speaker:
|
|
|
|
```text
|
|
AGENT
|
|
CUSTOMER
|
|
UNKNOWN
|
|
```
|
|
|
|
---
|
|
|
|
# 111. SPEAKER MAPPING
|
|
|
|
Sempre que possível utilizar canais estéreo para identificar:
|
|
|
|
```text
|
|
Agent
|
|
Customer
|
|
```
|
|
|
|
Diarização pode ser apoio.
|
|
|
|
Não confiar cegamente em classificação probabilística quando direção de áudio permite identificação melhor.
|
|
|
|
---
|
|
|
|
# 112. ANÁLISE DA CHAMADA
|
|
|
|
Criar:
|
|
|
|
```text
|
|
call_ai_analyses
|
|
```
|
|
|
|
Resultado estruturado:
|
|
|
|
```text
|
|
summary
|
|
|
|
customer_intent
|
|
|
|
outcome
|
|
|
|
sentiment
|
|
|
|
topics
|
|
|
|
keywords
|
|
|
|
objections
|
|
|
|
questions
|
|
|
|
action_items
|
|
|
|
compliance_flags
|
|
|
|
quality_score
|
|
|
|
agent_score
|
|
|
|
customer_sentiment_score
|
|
|
|
risk_flags
|
|
|
|
sales_opportunity
|
|
|
|
next_best_action
|
|
```
|
|
|
|
---
|
|
|
|
# 113. OUTPUT ESTRUTURADO
|
|
|
|
Não usar somente texto livre.
|
|
|
|
Utilizar schemas.
|
|
|
|
Exemplo:
|
|
|
|
```json
|
|
{
|
|
"summary": "...",
|
|
"sentiment": "NEUTRAL",
|
|
"topics": [],
|
|
"objections": [],
|
|
"quality_score": 82,
|
|
"compliance_flags": [],
|
|
"action_items": []
|
|
}
|
|
```
|
|
|
|
Validar antes de persistir.
|
|
|
|
---
|
|
|
|
# 114. PROMPTS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
ai_prompt_templates
|
|
ai_prompt_versions
|
|
```
|
|
|
|
Prompts não devem ficar hardcoded.
|
|
|
|
---
|
|
|
|
# 115. PROMPT POR TENANT
|
|
|
|
Tenant poderá definir prompt próprio.
|
|
|
|
Exemplo:
|
|
|
|
```text
|
|
analise esta chamada como atendimento de suporte
|
|
```
|
|
|
|
---
|
|
|
|
# 116. PROMPT POR CAMPANHA
|
|
|
|
Campanha poderá sobrescrever.
|
|
|
|
Exemplo cobrança:
|
|
|
|
```text
|
|
promessa de pagamento
|
|
data prometida
|
|
objeções
|
|
```
|
|
|
|
Exemplo vendas:
|
|
|
|
```text
|
|
interesse
|
|
produto
|
|
objeções
|
|
intenção de compra
|
|
```
|
|
|
|
---
|
|
|
|
# 117. SCORECARD
|
|
|
|
Criar:
|
|
|
|
```text
|
|
quality_scorecards
|
|
quality_scorecard_items
|
|
quality_evaluations
|
|
```
|
|
|
|
Itens:
|
|
|
|
```text
|
|
Saudação
|
|
|
|
Identificação
|
|
|
|
Empatia
|
|
|
|
Entendimento
|
|
|
|
Apresentação
|
|
|
|
Objeções
|
|
|
|
Encerramento
|
|
|
|
Compliance
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
weight
|
|
description
|
|
evaluation_prompt
|
|
```
|
|
|
|
---
|
|
|
|
# 118. QA AUTOMÁTICO
|
|
|
|
Gerar:
|
|
|
|
```text
|
|
score 0-100
|
|
```
|
|
|
|
por chamada.
|
|
|
|
Guardar:
|
|
|
|
```text
|
|
score
|
|
criterion_scores
|
|
summary_justification
|
|
```
|
|
|
|
Não armazenar chain-of-thought do modelo.
|
|
|
|
---
|
|
|
|
# 119. DASHBOARD IA
|
|
|
|
Mostrar:
|
|
|
|
```text
|
|
Chamadas analisadas
|
|
|
|
Score médio
|
|
|
|
Sentimento
|
|
|
|
Principais assuntos
|
|
|
|
Principais objeções
|
|
|
|
Compliance alerts
|
|
|
|
Agentes com maior score
|
|
|
|
Agentes com menor score
|
|
```
|
|
|
|
---
|
|
|
|
# 120. DETALHE DA CHAMADA
|
|
|
|
Criar abas:
|
|
|
|
```text
|
|
Resumo
|
|
|
|
Timeline
|
|
|
|
Gravação
|
|
|
|
Transcrição
|
|
|
|
Análise IA
|
|
|
|
Eventos
|
|
|
|
Billing
|
|
```
|
|
|
|
---
|
|
|
|
# 121. PLAYER DE ÁUDIO
|
|
|
|
Implementar:
|
|
|
|
```text
|
|
play
|
|
pause
|
|
timeline
|
|
duration
|
|
```
|
|
|
|
Se possível sincronizar transcrição.
|
|
|
|
---
|
|
|
|
# 122. PRIVACIDADE IA
|
|
|
|
Permitir:
|
|
|
|
```text
|
|
AI OFF
|
|
|
|
TRANSCRIPTION ONLY
|
|
|
|
TRANSCRIPTION + ANALYSIS
|
|
```
|
|
|
|
por:
|
|
|
|
* tenant;
|
|
* campanha;
|
|
* fila.
|
|
|
|
---
|
|
|
|
# 123. REDACTION
|
|
|
|
Criar abstração:
|
|
|
|
```text
|
|
SensitiveDataRedactor
|
|
```
|
|
|
|
Preparar para mascarar:
|
|
|
|
```text
|
|
CPF
|
|
|
|
CNPJ
|
|
|
|
telefone
|
|
|
|
email
|
|
|
|
cartão
|
|
|
|
outros dados
|
|
```
|
|
|
|
antes de enviar ao provider quando política exigir.
|
|
|
|
---
|
|
|
|
# 124. AI USAGE METERING
|
|
|
|
Gerar usage:
|
|
|
|
```text
|
|
AI_TRANSCRIPTION_SECONDS
|
|
|
|
AI_ANALYSIS_REQUEST
|
|
|
|
AI_INPUT_TOKENS
|
|
|
|
AI_OUTPUT_TOKENS
|
|
```
|
|
|
|
---
|
|
|
|
# 125. BILLING SAAS
|
|
|
|
Criar billing desde o início.
|
|
|
|
Não tratar cobrança como relatório calculado posteriormente de maneira improvisada.
|
|
|
|
---
|
|
|
|
# 126. PLANOS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
plans
|
|
plan_versions
|
|
```
|
|
|
|
Exemplo:
|
|
|
|
```text
|
|
Starter
|
|
|
|
Professional
|
|
|
|
Enterprise
|
|
```
|
|
|
|
Preços e limites devem ser versionados.
|
|
|
|
---
|
|
|
|
# 127. SUBSCRIPTIONS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
tenant_subscriptions
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
tenant_id
|
|
|
|
plan_version_id
|
|
|
|
status
|
|
|
|
started_at
|
|
ends_at
|
|
|
|
billing_cycle_anchor
|
|
|
|
currency
|
|
```
|
|
|
|
---
|
|
|
|
# 128. PRICE BOOKS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
price_books
|
|
price_book_items
|
|
```
|
|
|
|
Tipos de preço:
|
|
|
|
```text
|
|
BASE_SUBSCRIPTION
|
|
|
|
EXTENSION_MONTH
|
|
|
|
AGENT_MONTH
|
|
|
|
TRUNK_MONTH
|
|
|
|
CALL
|
|
|
|
CALL_MINUTE
|
|
|
|
FIXED_MINUTE
|
|
|
|
MOBILE_MINUTE
|
|
|
|
INTERNATIONAL_MINUTE
|
|
|
|
AI_TRANSCRIPTION_MINUTE
|
|
|
|
AI_ANALYSIS_CALL
|
|
|
|
AI_INPUT_TOKEN
|
|
|
|
AI_OUTPUT_TOKEN
|
|
|
|
RECORDING_GB_MONTH
|
|
```
|
|
|
|
---
|
|
|
|
# 129. RATE DECKS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
rate_decks
|
|
rate_deck_entries
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
prefix
|
|
|
|
destination_name
|
|
|
|
destination_type
|
|
|
|
price_per_minute
|
|
|
|
billing_increment_seconds
|
|
|
|
minimum_seconds
|
|
|
|
connection_fee
|
|
|
|
valid_from
|
|
valid_until
|
|
```
|
|
|
|
Implementar longest prefix matching.
|
|
|
|
---
|
|
|
|
# 130. RATING ENGINE
|
|
|
|
Criar:
|
|
|
|
```text
|
|
RatingEngine
|
|
```
|
|
|
|
Responsável por:
|
|
|
|
```text
|
|
uso bruto
|
|
↓
|
|
regra de preço
|
|
↓
|
|
valor financeiro
|
|
```
|
|
|
|
Nunca calcular billing no frontend.
|
|
|
|
---
|
|
|
|
# 131. USAGE LEDGER
|
|
|
|
Criar tabela imutável:
|
|
|
|
```text
|
|
usage_events
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
id UUID
|
|
|
|
tenant_id
|
|
|
|
meter
|
|
|
|
quantity
|
|
|
|
unit
|
|
|
|
source_type
|
|
source_id
|
|
|
|
occurred_at
|
|
|
|
metadata
|
|
|
|
created_at
|
|
```
|
|
|
|
Exemplos:
|
|
|
|
```text
|
|
CALL_COUNT
|
|
|
|
CALL_SECONDS
|
|
|
|
EXTENSION_ACTIVE_DAY
|
|
|
|
AGENT_ACTIVE_DAY
|
|
|
|
TRUNK_ACTIVE_DAY
|
|
|
|
AI_TRANSCRIPTION_SECONDS
|
|
|
|
AI_ANALYSIS_REQUEST
|
|
|
|
AI_INPUT_TOKENS
|
|
|
|
AI_OUTPUT_TOKENS
|
|
|
|
RECORDING_BYTES
|
|
```
|
|
|
|
---
|
|
|
|
# 132. RATED USAGE
|
|
|
|
Criar:
|
|
|
|
```text
|
|
rated_usage_items
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
tenant_id
|
|
|
|
usage_event_id
|
|
|
|
price_book_item_id
|
|
|
|
quantity
|
|
|
|
unit_price
|
|
|
|
amount
|
|
|
|
currency
|
|
|
|
pricing_version
|
|
```
|
|
|
|
---
|
|
|
|
# 133. CHAMADA FATURÁVEL
|
|
|
|
Guardar:
|
|
|
|
```text
|
|
billable_seconds
|
|
|
|
billing_increment
|
|
|
|
rated_minutes
|
|
|
|
destination_rate
|
|
|
|
rated_amount
|
|
```
|
|
|
|
---
|
|
|
|
# 134. BILLING PERIOD
|
|
|
|
Criar:
|
|
|
|
```text
|
|
billing_periods
|
|
```
|
|
|
|
Status:
|
|
|
|
```text
|
|
OPEN
|
|
|
|
CALCULATING
|
|
|
|
READY
|
|
|
|
CLOSED
|
|
|
|
REOPENED
|
|
```
|
|
|
|
---
|
|
|
|
# 135. MONTHLY STATEMENTS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
billing_statements
|
|
billing_statement_items
|
|
```
|
|
|
|
Relatório mensal por tenant:
|
|
|
|
```text
|
|
Plano
|
|
Valor base
|
|
|
|
Ramais
|
|
Quantidade
|
|
Valor
|
|
|
|
Agentes
|
|
Quantidade
|
|
Valor
|
|
|
|
Troncos
|
|
Quantidade
|
|
Valor
|
|
|
|
Chamadas
|
|
Quantidade
|
|
|
|
Minutos
|
|
Quantidade
|
|
Valor
|
|
|
|
Transcrição IA
|
|
Quantidade
|
|
Valor
|
|
|
|
Análise IA
|
|
Quantidade
|
|
Valor
|
|
|
|
Tokens
|
|
Valor
|
|
|
|
Storage
|
|
Valor
|
|
|
|
Subtotal
|
|
|
|
Ajustes
|
|
|
|
Total
|
|
```
|
|
|
|
---
|
|
|
|
# 136. STATEMENT NÃO É NOTA FISCAL
|
|
|
|
O sistema deverá chamar isso de:
|
|
|
|
```text
|
|
Usage Statement
|
|
Billing Statement
|
|
Relatório de Consumo
|
|
```
|
|
|
|
Não afirmar automaticamente que se trata de:
|
|
|
|
```text
|
|
NFCom
|
|
NFS-e
|
|
Nota Fiscal
|
|
```
|
|
|
|
Integração fiscal é outro módulo.
|
|
|
|
---
|
|
|
|
# 137. FECHAMENTO IMUTÁVEL
|
|
|
|
Depois de:
|
|
|
|
```text
|
|
CLOSED
|
|
```
|
|
|
|
não recalcular silenciosamente.
|
|
|
|
Para corrigir:
|
|
|
|
```text
|
|
REOPEN
|
|
```
|
|
|
|
com:
|
|
|
|
```text
|
|
user
|
|
reason
|
|
audit
|
|
```
|
|
|
|
---
|
|
|
|
# 138. ESTIMATIVA DO MÊS
|
|
|
|
Tenant Dashboard deverá mostrar:
|
|
|
|
```text
|
|
Valor estimado do mês
|
|
```
|
|
|
|
Mas deixar claro que é valor em aberto.
|
|
|
|
---
|
|
|
|
# 139. DASHBOARD DE QUOTAS
|
|
|
|
Mostrar:
|
|
|
|
```text
|
|
Ramais
|
|
8 / 10
|
|
|
|
Agentes
|
|
15 / 20
|
|
|
|
Troncos
|
|
2 / 3
|
|
|
|
CPS
|
|
6 / 10
|
|
|
|
Chamadas simultâneas
|
|
18 / 25
|
|
```
|
|
|
|
---
|
|
|
|
# 140. PLATFORM SUPER ADMIN
|
|
|
|
Criar:
|
|
|
|
```text
|
|
platform_super_admin
|
|
```
|
|
|
|
Pode:
|
|
|
|
```text
|
|
criar tenant
|
|
|
|
suspender tenant
|
|
|
|
alterar plano
|
|
|
|
definir quota
|
|
|
|
definir preços
|
|
|
|
acessar consumo
|
|
|
|
executar fechamento
|
|
|
|
administrar FreeSWITCH
|
|
|
|
administrar AI providers globais
|
|
```
|
|
|
|
---
|
|
|
|
# 141. TENANT ADMIN
|
|
|
|
Criar:
|
|
|
|
```text
|
|
tenant_admin
|
|
```
|
|
|
|
Pode administrar somente seu tenant.
|
|
|
|
---
|
|
|
|
# 142. ROLES
|
|
|
|
Roles iniciais:
|
|
|
|
```text
|
|
platform_super_admin
|
|
|
|
tenant_admin
|
|
|
|
supervisor
|
|
|
|
agent
|
|
```
|
|
|
|
Mas utilizar RBAC configurável.
|
|
|
|
---
|
|
|
|
# 143. RBAC
|
|
|
|
Criar:
|
|
|
|
```text
|
|
roles
|
|
|
|
permissions
|
|
|
|
user_roles
|
|
|
|
role_permissions
|
|
```
|
|
|
|
Permitir roles customizadas.
|
|
|
|
---
|
|
|
|
# 144. ROLE SCOPE
|
|
|
|
Role possui:
|
|
|
|
```text
|
|
PLATFORM
|
|
```
|
|
|
|
ou:
|
|
|
|
```text
|
|
TENANT
|
|
```
|
|
|
|
Nunca permitir escopo global acidental.
|
|
|
|
---
|
|
|
|
# 145. PERMISSÕES
|
|
|
|
Criar permissões como:
|
|
|
|
```text
|
|
tenants.view
|
|
tenants.manage
|
|
|
|
billing.view
|
|
billing.manage
|
|
pricing.manage
|
|
|
|
dashboard.view
|
|
|
|
extensions.view
|
|
extensions.manage
|
|
|
|
trunks.view
|
|
trunks.manage
|
|
|
|
agents.view
|
|
agents.manage
|
|
|
|
queues.view
|
|
queues.manage
|
|
|
|
campaigns.view
|
|
campaigns.create
|
|
campaigns.update
|
|
campaigns.start
|
|
campaigns.pause
|
|
campaigns.stop
|
|
|
|
monitoring.view
|
|
|
|
reports.view
|
|
reports.export
|
|
|
|
recordings.view
|
|
recordings.download
|
|
|
|
ai.view
|
|
ai.manage
|
|
ai.analyze
|
|
|
|
freeswitch.view
|
|
freeswitch.configure
|
|
|
|
users.manage
|
|
roles.manage
|
|
|
|
audit.view
|
|
```
|
|
|
|
---
|
|
|
|
# 146. OBJECT-LEVEL AUTHORIZATION
|
|
|
|
Permissão:
|
|
|
|
```text
|
|
campaigns.view
|
|
```
|
|
|
|
não é suficiente.
|
|
|
|
Também verificar:
|
|
|
|
```text
|
|
campaign.tenant_id == user.tenant_id
|
|
```
|
|
|
|
---
|
|
|
|
# 147. PROTEÇÃO IDOR
|
|
|
|
Um usuário tenant A tentando:
|
|
|
|
```text
|
|
/api/calls/{uuid-tenant-b}
|
|
```
|
|
|
|
deve receber:
|
|
|
|
```text
|
|
403
|
|
```
|
|
|
|
ou:
|
|
|
|
```text
|
|
404
|
|
```
|
|
|
|
Nunca retornar dados.
|
|
|
|
---
|
|
|
|
# 148. AUTENTICAÇÃO
|
|
|
|
Login:
|
|
|
|
```text
|
|
email
|
|
senha
|
|
```
|
|
|
|
Hash:
|
|
|
|
```text
|
|
Argon2id
|
|
```
|
|
|
|
Implementar:
|
|
|
|
```text
|
|
access token
|
|
refresh token
|
|
refresh rotation
|
|
logout
|
|
session revocation
|
|
password reset
|
|
forced password change
|
|
```
|
|
|
|
---
|
|
|
|
# 149. RATE LIMIT
|
|
|
|
Login:
|
|
|
|
```text
|
|
5 tentativas/minuto/IP
|
|
```
|
|
|
|
ou estratégia segura equivalente.
|
|
|
|
Também:
|
|
|
|
```text
|
|
rate per user
|
|
progressive blocking
|
|
audit
|
|
```
|
|
|
|
---
|
|
|
|
# 150. AUDIT LOG
|
|
|
|
Criar:
|
|
|
|
```text
|
|
audit_logs
|
|
```
|
|
|
|
Campos:
|
|
|
|
```text
|
|
tenant_id nullable
|
|
|
|
user_id
|
|
|
|
action
|
|
|
|
entity_type
|
|
|
|
entity_id
|
|
|
|
before
|
|
|
|
after
|
|
|
|
ip_address
|
|
|
|
user_agent
|
|
|
|
created_at
|
|
```
|
|
|
|
Nunca salvar secrets.
|
|
|
|
---
|
|
|
|
# 151. EVENTOS DE AUDITORIA
|
|
|
|
Registrar:
|
|
|
|
```text
|
|
LOGIN
|
|
|
|
LOGIN_FAILED
|
|
|
|
TENANT_CREATE
|
|
|
|
TENANT_SUSPEND
|
|
|
|
PLAN_CHANGE
|
|
|
|
QUOTA_CHANGE
|
|
|
|
PRICE_CHANGE
|
|
|
|
BILLING_CLOSE
|
|
|
|
BILLING_REOPEN
|
|
|
|
USER_CREATE
|
|
|
|
ROLE_CHANGE
|
|
|
|
TRUNK_CREATE
|
|
|
|
EXTENSION_CREATE
|
|
|
|
AGENT_LOGIN
|
|
|
|
AGENT_PAUSE
|
|
|
|
CAMPAIGN_START
|
|
|
|
CAMPAIGN_PAUSE
|
|
|
|
CAMPAIGN_STOP
|
|
|
|
AI_PROVIDER_CHANGE
|
|
|
|
AI_ENABLED
|
|
|
|
FREESWITCH_CONFIG_CHANGE
|
|
|
|
RELOAD
|
|
```
|
|
|
|
---
|
|
|
|
# 152. MOD_ODBC_CDR
|
|
|
|
Utilizar preferencialmente:
|
|
|
|
```text
|
|
mod_odbc_cdr
|
|
```
|
|
|
|
com PostgreSQL via ODBC.
|
|
|
|
Configurar fallback/spool para evitar perda silenciosa de CDR.
|
|
|
|
---
|
|
|
|
# 153. MODELO DE CHAMADAS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
calls
|
|
call_legs
|
|
call_events
|
|
dial_attempts
|
|
```
|
|
|
|
---
|
|
|
|
# 154. FIELDS CALL
|
|
|
|
```text
|
|
tenant_id
|
|
|
|
call_id
|
|
|
|
attempt_id
|
|
|
|
freeswitch_uuid
|
|
|
|
sip_call_id
|
|
|
|
direction
|
|
|
|
campaign_id
|
|
lead_id
|
|
|
|
queue_id
|
|
agent_id
|
|
extension_id
|
|
trunk_id
|
|
|
|
caller
|
|
called
|
|
|
|
created_at
|
|
|
|
progress_at
|
|
|
|
answer_at
|
|
|
|
queue_enter_at
|
|
|
|
agent_answer_at
|
|
|
|
bridge_at
|
|
|
|
end_at
|
|
|
|
ring_time
|
|
|
|
wait_time
|
|
|
|
talk_time
|
|
|
|
duration_seconds
|
|
|
|
billable_seconds
|
|
|
|
hangup_cause
|
|
|
|
disposition
|
|
```
|
|
|
|
---
|
|
|
|
# 155. TME
|
|
|
|
Calcular para chamadas atendidas:
|
|
|
|
```text
|
|
agent_answer_at - queue_enter_at
|
|
```
|
|
|
|
Separar tempo médio até abandono.
|
|
|
|
---
|
|
|
|
# 156. TMA
|
|
|
|
Principal:
|
|
|
|
```text
|
|
SUM(talk_time) / answered_calls
|
|
```
|
|
|
|
Permitir indicador separado:
|
|
|
|
```text
|
|
Talk Time + Wrap-Up
|
|
```
|
|
|
|
---
|
|
|
|
# 157. RELATÓRIO DE CHAMADAS
|
|
|
|
Filtros:
|
|
|
|
```text
|
|
data
|
|
|
|
ramal
|
|
|
|
agente
|
|
|
|
fila
|
|
|
|
campanha
|
|
|
|
trunk
|
|
|
|
telefone
|
|
|
|
hangup cause
|
|
|
|
disposition
|
|
```
|
|
|
|
Platform admin poderá filtrar tenant.
|
|
|
|
Tenant normal não poderá escolher outro tenant.
|
|
|
|
---
|
|
|
|
# 158. RELATÓRIO AGENTES
|
|
|
|
Mostrar:
|
|
|
|
```text
|
|
Tempo logado
|
|
|
|
Tempo disponível
|
|
|
|
Tempo reservado
|
|
|
|
Tempo ringing
|
|
|
|
Tempo em chamada
|
|
|
|
Tempo wrap-up
|
|
|
|
Tempo pausado
|
|
|
|
Chamadas atendidas
|
|
|
|
TMA
|
|
```
|
|
|
|
---
|
|
|
|
# 159. RELATÓRIO FILAS
|
|
|
|
Mostrar:
|
|
|
|
```text
|
|
Recebidas
|
|
|
|
Atendidas
|
|
|
|
Abandonadas
|
|
|
|
TME
|
|
|
|
TMA
|
|
|
|
Service Level
|
|
|
|
Abandon Rate
|
|
```
|
|
|
|
---
|
|
|
|
# 160. RELATÓRIO CAMPANHA
|
|
|
|
Mostrar:
|
|
|
|
```text
|
|
Leads
|
|
|
|
Attempts
|
|
|
|
Answered
|
|
|
|
Agent Connected
|
|
|
|
Busy
|
|
|
|
No Answer
|
|
|
|
Failed
|
|
|
|
Callbacks
|
|
|
|
Answer Rate
|
|
|
|
Contact Rate
|
|
|
|
Abandon Rate
|
|
|
|
TME
|
|
|
|
TMA
|
|
|
|
Valor Telefonia
|
|
|
|
Valor IA
|
|
```
|
|
|
|
---
|
|
|
|
# 161. WEBSOCKET MULTI-TENANT
|
|
|
|
Eventos WebSocket devem ser tenant-scoped no servidor.
|
|
|
|
Não transmitir tudo e filtrar somente no browser.
|
|
|
|
---
|
|
|
|
# 162. DASHBOARD TENANT
|
|
|
|
Mostrar:
|
|
|
|
```text
|
|
Chamadas hoje
|
|
|
|
Atendidas
|
|
|
|
Em andamento
|
|
|
|
Esperando agente
|
|
|
|
Agentes disponíveis
|
|
|
|
Agentes ocupados
|
|
|
|
Agentes pausados
|
|
|
|
TME
|
|
|
|
TMA
|
|
|
|
Answer Rate
|
|
|
|
Abandon Rate
|
|
```
|
|
|
|
Também:
|
|
|
|
```text
|
|
Consumo do plano
|
|
|
|
Valor estimado no mês
|
|
```
|
|
|
|
---
|
|
|
|
# 163. DASHBOARD PLATFORM
|
|
|
|
Mostrar:
|
|
|
|
```text
|
|
Tenants ativos
|
|
|
|
Ramais totais
|
|
|
|
Agentes totais
|
|
|
|
Chamadas atuais
|
|
|
|
Chamadas hoje
|
|
|
|
FreeSWITCH nodes
|
|
|
|
CPS global
|
|
|
|
Consumo mensal
|
|
|
|
Receita estimada
|
|
|
|
Uso IA
|
|
|
|
Storage
|
|
```
|
|
|
|
---
|
|
|
|
# 164. INTERFACE
|
|
|
|
Este requisito é muito importante.
|
|
|
|
O B2BCall deverá parecer um produto SaaS moderno e profissional.
|
|
|
|
Não deve parecer:
|
|
|
|
```text
|
|
FreePBX
|
|
|
|
FusionPBX
|
|
|
|
painel Linux
|
|
|
|
Bootstrap antigo
|
|
|
|
sistema legado
|
|
```
|
|
|
|
---
|
|
|
|
# 165. DESIGN SYSTEM
|
|
|
|
Criar tokens para:
|
|
|
|
```text
|
|
colors
|
|
|
|
typography
|
|
|
|
spacing
|
|
|
|
border radius
|
|
|
|
shadows
|
|
|
|
status colors
|
|
|
|
buttons
|
|
|
|
forms
|
|
|
|
badges
|
|
|
|
cards
|
|
|
|
tables
|
|
|
|
dialogs
|
|
|
|
charts
|
|
```
|
|
|
|
---
|
|
|
|
# 166. LAYOUT
|
|
|
|
Criar:
|
|
|
|
```text
|
|
Sidebar
|
|
+
|
|
Topbar
|
|
+
|
|
Content
|
|
```
|
|
|
|
Sidebar recolhível.
|
|
|
|
---
|
|
|
|
# 167. LOGIN
|
|
|
|
Utilizar `b2blogo.png`.
|
|
|
|
Criar tela moderna.
|
|
|
|
Desktop poderá usar:
|
|
|
|
```text
|
|
Brand B2BCall
|
|
|
|
|
Login Form
|
|
```
|
|
|
|
Responsiva.
|
|
|
|
---
|
|
|
|
# 168. MENU PLATFORM
|
|
|
|
```text
|
|
Visão Geral
|
|
|
|
Clientes
|
|
├─ Tenants
|
|
├─ Planos
|
|
├─ Assinaturas
|
|
└─ Quotas
|
|
|
|
Billing
|
|
├─ Consumo
|
|
├─ Tarifas
|
|
├─ Fechamentos
|
|
└─ Relatórios
|
|
|
|
Infraestrutura
|
|
├─ FreeSWITCH
|
|
├─ SIP Profiles
|
|
├─ Nodes
|
|
└─ Saúde
|
|
|
|
IA
|
|
├─ Providers
|
|
├─ Modelos
|
|
├─ Uso
|
|
└─ Custos
|
|
|
|
Sistema
|
|
├─ Usuários
|
|
├─ Permissões
|
|
├─ Auditoria
|
|
└─ Configurações
|
|
```
|
|
|
|
---
|
|
|
|
# 169. MENU TENANT
|
|
|
|
```text
|
|
Dashboard
|
|
|
|
Discador
|
|
├─ Campanhas
|
|
├─ Leads
|
|
├─ Importações
|
|
├─ Callbacks
|
|
└─ Lista de Bloqueio
|
|
|
|
Call Center
|
|
├─ Agentes
|
|
├─ Filas
|
|
├─ Pausas
|
|
└─ Disposições
|
|
|
|
Telefonia
|
|
├─ Ramais
|
|
├─ Troncos
|
|
└─ Dialplan
|
|
|
|
Monitoramento
|
|
├─ Campanhas
|
|
├─ Filas
|
|
├─ Agentes
|
|
├─ Ramais
|
|
└─ Troncos
|
|
|
|
Gravações
|
|
|
|
IA
|
|
├─ Análises
|
|
├─ Scorecards
|
|
├─ Prompts
|
|
└─ Configurações
|
|
|
|
Relatórios
|
|
├─ Chamadas
|
|
├─ Agentes
|
|
├─ Filas
|
|
├─ Campanhas
|
|
└─ Consumo
|
|
|
|
Administração
|
|
├─ Usuários
|
|
├─ Perfis
|
|
└─ Configurações
|
|
```
|
|
|
|
Itens sem permissão não aparecem.
|
|
|
|
---
|
|
|
|
# 170. CAMPANHA WIZARD
|
|
|
|
Criar:
|
|
|
|
```text
|
|
1. Geral
|
|
↓
|
|
2. Telefonia
|
|
↓
|
|
3. Discagem
|
|
↓
|
|
4. Horários
|
|
↓
|
|
5. Gravação e IA
|
|
↓
|
|
6. Leads
|
|
↓
|
|
7. Revisão
|
|
```
|
|
|
|
---
|
|
|
|
# 171. DASHBOARD CAMPANHA
|
|
|
|
Mostrar:
|
|
|
|
```text
|
|
Status
|
|
|
|
CPS configurado
|
|
|
|
CPS atual
|
|
|
|
Concurrent
|
|
|
|
Pacing
|
|
|
|
Originando
|
|
|
|
Ringing
|
|
|
|
Atendidas
|
|
|
|
Esperando agente
|
|
|
|
Conectadas
|
|
|
|
Agentes disponíveis
|
|
|
|
Agentes ocupados
|
|
|
|
Wrap-up
|
|
|
|
Pausados
|
|
|
|
Answer Rate
|
|
|
|
Abandon Rate
|
|
|
|
TME
|
|
|
|
TMA
|
|
|
|
Leads restantes
|
|
|
|
Leads processados
|
|
```
|
|
|
|
---
|
|
|
|
# 172. STATUS UI
|
|
|
|
Utilizar badges consistentes.
|
|
|
|
Campanhas:
|
|
|
|
```text
|
|
DRAFT
|
|
cinza
|
|
|
|
READY
|
|
azul
|
|
|
|
RUNNING
|
|
verde
|
|
|
|
PAUSED
|
|
amarelo
|
|
|
|
DRAINING
|
|
laranja
|
|
|
|
STOPPED
|
|
vermelho
|
|
|
|
COMPLETED
|
|
verde escuro
|
|
|
|
ERROR
|
|
vermelho
|
|
```
|
|
|
|
---
|
|
|
|
# 173. TABELAS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
Search
|
|
|
|
Filters
|
|
|
|
Sort
|
|
|
|
Pagination
|
|
|
|
Column Visibility
|
|
|
|
Row Actions
|
|
|
|
Bulk Actions quando aplicável
|
|
|
|
Export
|
|
```
|
|
|
|
Paginação server-side.
|
|
|
|
---
|
|
|
|
# 174. LIGHT/DARK
|
|
|
|
Implementar se não comprometer prioridades:
|
|
|
|
```text
|
|
Light
|
|
|
|
Dark
|
|
|
|
System
|
|
```
|
|
|
|
---
|
|
|
|
# 175. RESPONSIVIDADE
|
|
|
|
Priorizar:
|
|
|
|
```text
|
|
Desktop
|
|
|
|
Notebook
|
|
|
|
Tablet
|
|
```
|
|
|
|
Tela do agente deve funcionar bem em resoluções menores.
|
|
|
|
---
|
|
|
|
# 176. ACESSIBILIDADE
|
|
|
|
Implementar:
|
|
|
|
```text
|
|
labels
|
|
|
|
keyboard navigation
|
|
|
|
focus states
|
|
|
|
ARIA
|
|
|
|
contraste
|
|
```
|
|
|
|
Status não podem depender apenas da cor.
|
|
|
|
---
|
|
|
|
# 177. SEGREDOS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
.env
|
|
.env.example
|
|
.gitignore
|
|
```
|
|
|
|
`.env` nunca no Git.
|
|
|
|
Secrets:
|
|
|
|
```text
|
|
POSTGRES
|
|
|
|
REDIS
|
|
|
|
JWT
|
|
|
|
ENCRYPTION KEY
|
|
|
|
ESL
|
|
|
|
FREESWITCH_PAT
|
|
|
|
AI provider keys
|
|
|
|
SMTP
|
|
|
|
S3
|
|
```
|
|
|
|
---
|
|
|
|
# 178. CREDENCIAIS SIP
|
|
|
|
Criptografar em repouso:
|
|
|
|
```text
|
|
AES-256-GCM
|
|
```
|
|
|
|
ou equivalente.
|
|
|
|
Master key fora do PostgreSQL.
|
|
|
|
---
|
|
|
|
# 179. AI KEYS
|
|
|
|
Mesmo tratamento.
|
|
|
|
Nunca logar.
|
|
|
|
Nunca devolver inteiro após salvar.
|
|
|
|
---
|
|
|
|
# 180. COMMAND INJECTION
|
|
|
|
Nunca concatenar input do usuário diretamente em:
|
|
|
|
```text
|
|
originate
|
|
|
|
uuid_transfer
|
|
|
|
bridge
|
|
|
|
sofia
|
|
|
|
callcenter_config
|
|
```
|
|
|
|
Criar builders seguros.
|
|
|
|
Validar:
|
|
|
|
```text
|
|
gateway
|
|
|
|
phone
|
|
|
|
queue
|
|
|
|
agent
|
|
|
|
extension
|
|
|
|
context
|
|
```
|
|
|
|
---
|
|
|
|
# 181. SQL SECURITY
|
|
|
|
Queries parametrizadas.
|
|
|
|
Nunca concatenar SQL com input.
|
|
|
|
---
|
|
|
|
# 182. HTTP SECURITY
|
|
|
|
Implementar:
|
|
|
|
```text
|
|
CSP
|
|
|
|
CORS restritivo
|
|
|
|
CSRF quando necessário
|
|
|
|
HSTS quando HTTPS
|
|
|
|
X-Content-Type-Options
|
|
|
|
Referrer-Policy
|
|
|
|
input validation
|
|
```
|
|
|
|
---
|
|
|
|
# 183. FIREWALL LOCAL
|
|
|
|
Utilizar nftables quando apropriado.
|
|
|
|
Antes de alterar:
|
|
|
|
```bash
|
|
ss -tnp
|
|
ip addr
|
|
ip route
|
|
```
|
|
|
|
Preservar SSH.
|
|
|
|
Não alterar firewalls externos.
|
|
|
|
---
|
|
|
|
# 184. PORTAS SENSÍVEIS
|
|
|
|
Não expor publicamente:
|
|
|
|
```text
|
|
5432 PostgreSQL
|
|
|
|
6379 Redis
|
|
|
|
8021 Event Socket
|
|
```
|
|
|
|
SIP deve ser restrito às origens necessárias.
|
|
|
|
---
|
|
|
|
# 185. DIALER SIMULATION
|
|
|
|
Inicialmente:
|
|
|
|
```text
|
|
DIALER_SIMULATION=true
|
|
```
|
|
|
|
Nesse modo:
|
|
|
|
NÃO realizar chamadas PSTN reais.
|
|
|
|
Simular:
|
|
|
|
```text
|
|
ANSWER
|
|
|
|
BUSY
|
|
|
|
NO_ANSWER
|
|
|
|
FAILED
|
|
|
|
RINGING
|
|
|
|
answer delay
|
|
|
|
talk time
|
|
```
|
|
|
|
---
|
|
|
|
# 186. REAL OUTBOUND SAFETY
|
|
|
|
Para habilitar chamadas reais exigir duas condições:
|
|
|
|
```text
|
|
DIALER_SIMULATION=false
|
|
```
|
|
|
|
e:
|
|
|
|
```text
|
|
ALLOW_REAL_OUTBOUND_CALLS=true
|
|
```
|
|
|
|
Não ativar automaticamente.
|
|
|
|
---
|
|
|
|
# 187. HEALTH CHECKS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
/api/health
|
|
|
|
/api/health/live
|
|
|
|
/api/health/ready
|
|
```
|
|
|
|
Verificar:
|
|
|
|
```text
|
|
API
|
|
|
|
PostgreSQL
|
|
|
|
Redis
|
|
|
|
FreeSWITCH
|
|
|
|
ESL
|
|
|
|
Object Storage
|
|
|
|
Workers
|
|
```
|
|
|
|
Falha de provider externo de IA não deve necessariamente tornar API indisponível.
|
|
|
|
---
|
|
|
|
# 188. PROMETHEUS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
/metrics
|
|
```
|
|
|
|
Métricas:
|
|
|
|
```text
|
|
b2bcall_calls_total
|
|
|
|
b2bcall_active_calls
|
|
|
|
b2bcall_tenant_active_calls
|
|
|
|
b2bcall_campaign_cps
|
|
|
|
b2bcall_campaign_pacing
|
|
|
|
b2bcall_agents_available
|
|
|
|
b2bcall_queue_waiting
|
|
|
|
b2bcall_ai_jobs_pending
|
|
|
|
b2bcall_ai_jobs_failed
|
|
|
|
b2bcall_ai_transcription_seconds
|
|
|
|
b2bcall_esl_connected
|
|
```
|
|
|
|
---
|
|
|
|
# 189. LOGGING
|
|
|
|
Logs JSON estruturados.
|
|
|
|
Contexto:
|
|
|
|
```text
|
|
request_id
|
|
|
|
tenant_id
|
|
|
|
user_id
|
|
|
|
call_id
|
|
|
|
attempt_id
|
|
|
|
campaign_id
|
|
|
|
ai_job_id
|
|
```
|
|
|
|
Nunca secrets.
|
|
|
|
---
|
|
|
|
# 190. Migrations
|
|
|
|
Toda alteração de banco deve usar migration.
|
|
|
|
Não fazer alterações manuais não versionadas.
|
|
|
|
---
|
|
|
|
# 191. TABELAS PRINCIPAIS
|
|
|
|
Planejar no mínimo:
|
|
|
|
```text
|
|
tenants
|
|
|
|
tenant_memberships
|
|
|
|
|
|
plans
|
|
plan_versions
|
|
|
|
tenant_subscriptions
|
|
|
|
entitlements
|
|
plan_entitlements
|
|
tenant_entitlement_overrides
|
|
|
|
price_books
|
|
price_book_items
|
|
|
|
rate_decks
|
|
rate_deck_entries
|
|
|
|
billing_periods
|
|
billing_statements
|
|
billing_statement_items
|
|
|
|
usage_events
|
|
rated_usage_items
|
|
|
|
|
|
users
|
|
sessions
|
|
|
|
roles
|
|
permissions
|
|
user_roles
|
|
role_permissions
|
|
|
|
|
|
telephony_nodes
|
|
tenant_telephony_assignments
|
|
|
|
|
|
extensions
|
|
|
|
trunks
|
|
|
|
sip_profiles
|
|
|
|
dialplans
|
|
dialplan_versions
|
|
|
|
|
|
agents
|
|
agent_sessions
|
|
agent_state_events
|
|
|
|
pause_reasons
|
|
agent_pause_events
|
|
|
|
queues
|
|
queue_agents
|
|
|
|
|
|
campaigns
|
|
campaign_schedules
|
|
campaign_agents
|
|
|
|
lead_imports
|
|
leads
|
|
|
|
dial_attempts
|
|
|
|
callbacks
|
|
|
|
dispositions
|
|
|
|
suppression_list
|
|
|
|
|
|
calls
|
|
call_legs
|
|
call_events
|
|
|
|
recordings
|
|
|
|
|
|
ai_providers
|
|
ai_models
|
|
|
|
ai_prompt_templates
|
|
ai_prompt_versions
|
|
|
|
ai_jobs
|
|
|
|
call_transcriptions
|
|
call_transcript_segments
|
|
|
|
call_ai_analyses
|
|
|
|
quality_scorecards
|
|
quality_scorecard_items
|
|
quality_evaluations
|
|
|
|
|
|
freeswitch_config_versions
|
|
|
|
audit_logs
|
|
|
|
application_settings
|
|
```
|
|
|
|
---
|
|
|
|
# 192. ÍNDICES
|
|
|
|
Criar índices tenant-aware:
|
|
|
|
```text
|
|
(tenant_id, status)
|
|
|
|
(tenant_id, created_at)
|
|
|
|
(tenant_id, campaign_id, status)
|
|
|
|
(tenant_id, phone_normalized)
|
|
|
|
(tenant_id, call_id)
|
|
|
|
(tenant_id, agent_id)
|
|
|
|
(tenant_id, queue_id)
|
|
```
|
|
|
|
---
|
|
|
|
# 193. GRANDES VOLUMES
|
|
|
|
Projetar para milhões de:
|
|
|
|
```text
|
|
calls
|
|
|
|
call_events
|
|
|
|
leads
|
|
|
|
usage_events
|
|
```
|
|
|
|
Não carregar tudo na memória.
|
|
|
|
Não usar relatórios sem paginação.
|
|
|
|
---
|
|
|
|
# 194. PARTITIONING READY
|
|
|
|
Preparar arquitetura futura para partição temporal:
|
|
|
|
```text
|
|
calls
|
|
|
|
call_events
|
|
|
|
usage_events
|
|
|
|
audit_logs
|
|
```
|
|
|
|
Sem complexidade prematura.
|
|
|
|
---
|
|
|
|
# 195. RECONCILIAÇÃO ESL
|
|
|
|
Se conexão cair:
|
|
|
|
```text
|
|
reconnect com exponential backoff
|
|
```
|
|
|
|
Após reconectar:
|
|
|
|
```text
|
|
resubscribe
|
|
|
|
reconcile calls
|
|
|
|
reconcile agents
|
|
|
|
reconcile queues
|
|
|
|
reconcile registrations
|
|
|
|
reconcile gateways
|
|
```
|
|
|
|
---
|
|
|
|
# 196. RECOVERY
|
|
|
|
Após restart dos workers:
|
|
|
|
```text
|
|
recover RUNNING campaigns
|
|
|
|
recover locks
|
|
|
|
release expired lead reservations
|
|
|
|
reconcile calls
|
|
|
|
resume safely
|
|
```
|
|
|
|
---
|
|
|
|
# 197. BACKUP
|
|
|
|
Criar:
|
|
|
|
```text
|
|
scripts/backup.sh
|
|
|
|
scripts/restore.sh
|
|
```
|
|
|
|
Backup:
|
|
|
|
```text
|
|
PostgreSQL
|
|
|
|
FreeSWITCH config
|
|
|
|
application config
|
|
```
|
|
|
|
Object Storage deve ter estratégia própria.
|
|
|
|
---
|
|
|
|
# 198. INSTALL SCRIPT
|
|
|
|
Criar:
|
|
|
|
```text
|
|
scripts/install.sh
|
|
```
|
|
|
|
Fluxo:
|
|
|
|
```text
|
|
verificar Debian
|
|
|
|
instalar dependências
|
|
|
|
instalar Docker
|
|
|
|
preparar diretórios
|
|
|
|
gerar secrets
|
|
|
|
subir PostgreSQL
|
|
|
|
subir Redis
|
|
|
|
build FreeSWITCH
|
|
|
|
migrations
|
|
|
|
seed
|
|
|
|
subir serviços
|
|
|
|
health checks
|
|
|
|
testes básicos
|
|
```
|
|
|
|
---
|
|
|
|
# 199. FIRST LOGIN
|
|
|
|
Criar Platform Super Admin inicial.
|
|
|
|
Senha aleatória forte.
|
|
|
|
Salvar uma única vez em:
|
|
|
|
```text
|
|
FIRST_LOGIN.txt
|
|
```
|
|
|
|
Permissão:
|
|
|
|
```text
|
|
600
|
|
```
|
|
|
|
Forçar troca no primeiro login.
|
|
|
|
---
|
|
|
|
# 200. SEED
|
|
|
|
Criar:
|
|
|
|
```text
|
|
platform_super_admin
|
|
|
|
tenant_admin
|
|
|
|
supervisor
|
|
|
|
agent
|
|
|
|
permissions
|
|
|
|
pausas básicas
|
|
|
|
dispositions básicas
|
|
```
|
|
|
|
---
|
|
|
|
# 201. DEMO DATA
|
|
|
|
Somente quando:
|
|
|
|
```text
|
|
SEED_DEMO_DATA=true
|
|
```
|
|
|
|
Em produção:
|
|
|
|
```text
|
|
false
|
|
```
|
|
|
|
---
|
|
|
|
# 202. TESTES
|
|
|
|
Criar:
|
|
|
|
```text
|
|
unit
|
|
|
|
integration
|
|
|
|
E2E
|
|
|
|
simulation
|
|
```
|
|
|
|
---
|
|
|
|
# 203. TESTE MULTI-TENANT
|
|
|
|
Criar:
|
|
|
|
```text
|
|
Tenant A
|
|
|
|
Tenant B
|
|
|
|
Tenant C
|
|
```
|
|
|
|
Garantir isolamento completo.
|
|
|
|
---
|
|
|
|
# 204. TESTE RLS
|
|
|
|
User Tenant A tentando acessar dado Tenant B:
|
|
|
|
resultado obrigatório:
|
|
|
|
```text
|
|
403
|
|
```
|
|
|
|
ou:
|
|
|
|
```text
|
|
404
|
|
```
|
|
|
|
Nunca dado do Tenant B.
|
|
|
|
---
|
|
|
|
# 205. TESTE QUOTA RAMAIS
|
|
|
|
Tenant:
|
|
|
|
```text
|
|
max_extensions = 10
|
|
```
|
|
|
|
Após 10:
|
|
|
|
11º deve falhar.
|
|
|
|
---
|
|
|
|
# 206. TESTE QUOTA AGENTES
|
|
|
|
Tenant:
|
|
|
|
```text
|
|
max_agents = 20
|
|
```
|
|
|
|
21º deve falhar.
|
|
|
|
---
|
|
|
|
# 207. TESTE CPS TENANT
|
|
|
|
Tenant:
|
|
|
|
```text
|
|
max_cps = 5
|
|
```
|
|
|
|
Múltiplas campanhas somadas não podem ultrapassar 5 CPS.
|
|
|
|
---
|
|
|
|
# 208. TESTE CONCURRENT TENANT
|
|
|
|
Tenant:
|
|
|
|
```text
|
|
max_concurrent_calls = 20
|
|
```
|
|
|
|
Duas campanhas juntas não podem ultrapassar 20.
|
|
|
|
---
|
|
|
|
# 209. TESTE LEAD DUPLICADO
|
|
|
|
Múltiplos workers concorrendo.
|
|
|
|
Resultado:
|
|
|
|
```text
|
|
nenhum lead originado duas vezes simultaneamente
|
|
```
|
|
|
|
---
|
|
|
|
# 210. TESTE PAUSE CAMPAIGN
|
|
|
|
Campaign:
|
|
|
|
```text
|
|
PAUSED
|
|
```
|
|
|
|
não deve gerar novo originate.
|
|
|
|
---
|
|
|
|
# 211. TESTE BILLING
|
|
|
|
Cenário:
|
|
|
|
```text
|
|
Tenant A
|
|
|
|
10 extensions
|
|
|
|
5 agents
|
|
|
|
2 trunks
|
|
|
|
100 calls
|
|
|
|
350 minutos
|
|
|
|
120 minutos transcription
|
|
|
|
50 AI analyses
|
|
```
|
|
|
|
Rating Engine deverá produzir itens financeiros correspondentes.
|
|
|
|
---
|
|
|
|
# 212. TESTE BILLING IMUTÁVEL
|
|
|
|
Depois de fechar mês:
|
|
|
|
alteração de preço não pode modificar statement fechado.
|
|
|
|
---
|
|
|
|
# 213. TESTE AI PROVIDERS
|
|
|
|
Criar mocks:
|
|
|
|
```text
|
|
OpenAIProvider Mock
|
|
|
|
AnthropicProvider Mock
|
|
```
|
|
|
|
CI não deve depender de APIs reais.
|
|
|
|
---
|
|
|
|
# 214. TESTE AI 429
|
|
|
|
Provider retorna:
|
|
|
|
```text
|
|
429
|
|
```
|
|
|
|
Worker deve:
|
|
|
|
```text
|
|
retry com backoff
|
|
```
|
|
|
|
e não perder job.
|
|
|
|
---
|
|
|
|
# 215. TESTE RECORDING
|
|
|
|
Validar:
|
|
|
|
```text
|
|
tenant_id
|
|
|
|
call_id
|
|
|
|
path
|
|
|
|
checksum
|
|
|
|
authorization
|
|
```
|
|
|
|
---
|
|
|
|
# 216. GIT
|
|
|
|
Inicializar Git.
|
|
|
|
Commits organizados:
|
|
|
|
```text
|
|
feat: bootstrap b2bcall saas architecture
|
|
|
|
feat: add multi tenant isolation
|
|
|
|
feat: add subscriptions and entitlements
|
|
|
|
feat: add freeswitch core
|
|
|
|
feat: add event socket integration
|
|
|
|
feat: add callcenter integration
|
|
|
|
feat: add predictive dialer
|
|
|
|
feat: add recording pipeline
|
|
|
|
feat: add ai provider abstraction
|
|
|
|
feat: add transcription pipeline
|
|
|
|
feat: add call intelligence
|
|
|
|
feat: add usage metering
|
|
|
|
feat: add rating engine
|
|
|
|
feat: add monthly billing
|
|
|
|
feat: add realtime monitoring
|
|
|
|
feat: harden tenant security
|
|
```
|
|
|
|
---
|
|
|
|
# 217. DOCUMENTAÇÃO
|
|
|
|
Criar:
|
|
|
|
```text
|
|
README.md
|
|
|
|
TODO.md
|
|
|
|
CHANGELOG.md
|
|
|
|
docs/ARCHITECTURE.md
|
|
|
|
docs/SAAS_MULTI_TENANCY.md
|
|
|
|
docs/TENANT_ISOLATION.md
|
|
|
|
docs/NETWORK_ARCHITECTURE.md
|
|
|
|
docs/FREESWITCH.md
|
|
|
|
docs/MOD_CALLCENTER.md
|
|
|
|
docs/EVENT_SOCKET.md
|
|
|
|
docs/XML_CURL.md
|
|
|
|
docs/OPENSIPS.md
|
|
|
|
docs/PREDICTIVE_DIALER.md
|
|
|
|
docs/RECORDING.md
|
|
|
|
docs/AI_ARCHITECTURE.md
|
|
|
|
docs/AI_PROVIDERS.md
|
|
|
|
docs/BILLING.md
|
|
|
|
docs/RATING_ENGINE.md
|
|
|
|
docs/DATABASE.md
|
|
|
|
docs/SECURITY.md
|
|
|
|
docs/OPERATIONS.md
|
|
|
|
docs/BACKUP_RESTORE.md
|
|
|
|
docs/TROUBLESHOOTING.md
|
|
```
|
|
|
|
---
|
|
|
|
# 218. TODO.MD
|
|
|
|
Criar imediatamente.
|
|
|
|
Fases:
|
|
|
|
```text
|
|
PHASE 01 Infrastructure
|
|
|
|
PHASE 02 SaaS Core
|
|
|
|
PHASE 03 Tenant Isolation
|
|
|
|
PHASE 04 Authentication / RBAC
|
|
|
|
PHASE 05 FreeSWITCH
|
|
|
|
PHASE 06 Telephony
|
|
|
|
PHASE 07 Call Center
|
|
|
|
PHASE 08 Predictive Dialer
|
|
|
|
PHASE 09 Recordings
|
|
|
|
PHASE 10 AI
|
|
|
|
PHASE 11 Usage Metering
|
|
|
|
PHASE 12 Billing
|
|
|
|
PHASE 13 Frontend
|
|
|
|
PHASE 14 Reports
|
|
|
|
PHASE 15 Security
|
|
|
|
PHASE 16 Tests
|
|
|
|
PHASE 17 Final Validation
|
|
```
|
|
|
|
Só marcar:
|
|
|
|
```text
|
|
[x]
|
|
```
|
|
|
|
depois de implementar e testar.
|
|
|
|
---
|
|
|
|
# 219. NÃO PARAR APÓS PLANEJAMENTO
|
|
|
|
Depois de criar:
|
|
|
|
```text
|
|
TODO.md
|
|
|
|
docs/ARCHITECTURE.md
|
|
```
|
|
|
|
continue imediatamente.
|
|
|
|
Não entregue somente arquitetura.
|
|
|
|
---
|
|
|
|
# 220. QUANDO ENCONTRAR ERRO
|
|
|
|
Processo:
|
|
|
|
```text
|
|
detectar
|
|
↓
|
|
diagnosticar
|
|
↓
|
|
corrigir
|
|
↓
|
|
testar
|
|
↓
|
|
documentar
|
|
↓
|
|
continuar
|
|
```
|
|
|
|
Não abandonar o projeto por erro em uma fase.
|
|
|
|
---
|
|
|
|
# 221. BLOQUEIOS NÃO GLOBAIS
|
|
|
|
Se FreeSWITCH ainda não puder ser instalado:
|
|
|
|
continue:
|
|
|
|
```text
|
|
database
|
|
|
|
SaaS core
|
|
|
|
RBAC
|
|
|
|
billing
|
|
|
|
frontend
|
|
|
|
AI abstraction
|
|
|
|
tests
|
|
```
|
|
|
|
Depois volte.
|
|
|
|
---
|
|
|
|
# 222. QUALITY GATE BACKEND
|
|
|
|
Executar:
|
|
|
|
```text
|
|
lint
|
|
|
|
typecheck
|
|
|
|
unit tests
|
|
|
|
integration tests
|
|
|
|
E2E tests
|
|
|
|
tenant isolation tests
|
|
|
|
quota tests
|
|
|
|
dialer simulation tests
|
|
|
|
billing tests
|
|
|
|
AI tests
|
|
```
|
|
|
|
---
|
|
|
|
# 223. QUALITY GATE INFRA
|
|
|
|
Executar:
|
|
|
|
```text
|
|
docker compose config
|
|
|
|
docker compose ps
|
|
|
|
health checks
|
|
```
|
|
|
|
FreeSWITCH:
|
|
|
|
```bash
|
|
fs_cli -x "status"
|
|
|
|
fs_cli -x "show calls"
|
|
|
|
fs_cli -x "show channels"
|
|
|
|
fs_cli -x "sofia status"
|
|
|
|
fs_cli -x "callcenter_config queue list"
|
|
```
|
|
|
|
---
|
|
|
|
# 224. SECURITY QUALITY GATE
|
|
|
|
Validar:
|
|
|
|
```text
|
|
tenant A não vê tenant B
|
|
|
|
PostgreSQL não público
|
|
|
|
Redis não público
|
|
|
|
ESL não público
|
|
|
|
AI keys criptografadas
|
|
|
|
SIP passwords criptografadas
|
|
|
|
FREESWITCH_PAT fora do Git
|
|
|
|
.env fora do Git
|
|
|
|
RBAC funcionando
|
|
|
|
RLS funcionando
|
|
|
|
rate limit funcionando
|
|
|
|
IDOR protegido
|
|
```
|
|
|
|
---
|
|
|
|
# 225. CRITÉRIO DE ACEITE SAAS
|
|
|
|
Preciso conseguir:
|
|
|
|
1. criar Tenant;
|
|
2. definir plano;
|
|
3. definir limite de ramais;
|
|
4. definir limite de agentes;
|
|
5. definir limite de trunks;
|
|
6. definir limite CPS;
|
|
7. definir chamadas simultâneas;
|
|
8. criar tenant admin;
|
|
9. entrar como tenant admin;
|
|
10. criar recursos isolados;
|
|
11. visualizar consumo;
|
|
12. visualizar valor estimado;
|
|
13. alterar plano;
|
|
14. suspender tenant.
|
|
|
|
---
|
|
|
|
# 226. CRITÉRIO DE ACEITE TELEFONIA
|
|
|
|
Preciso:
|
|
|
|
1. cadastrar ramal;
|
|
2. registrar;
|
|
3. visualizar status;
|
|
4. cadastrar trunk;
|
|
5. visualizar status;
|
|
6. cadastrar fila;
|
|
7. cadastrar agente;
|
|
8. login agente;
|
|
9. pausa;
|
|
10. retorno da pausa;
|
|
11. chamada de teste;
|
|
12. CDR.
|
|
|
|
---
|
|
|
|
# 227. CRITÉRIO DE ACEITE DISCADOR
|
|
|
|
Preciso:
|
|
|
|
1. criar campanha;
|
|
2. selecionar trunk;
|
|
3. selecionar fila;
|
|
4. configurar CPS;
|
|
5. importar CSV;
|
|
6. iniciar;
|
|
7. visualizar pacing;
|
|
8. respeitar CPS campanha;
|
|
9. respeitar CPS tenant;
|
|
10. respeitar concurrent tenant;
|
|
11. pausar;
|
|
12. drain;
|
|
13. stop;
|
|
14. gerar relatório.
|
|
|
|
---
|
|
|
|
# 228. CRITÉRIO DE ACEITE IA
|
|
|
|
Preciso:
|
|
|
|
1. abrir IA → Providers;
|
|
2. cadastrar OpenAI;
|
|
3. cadastrar Anthropic;
|
|
4. cadastrar API key;
|
|
5. testar provider;
|
|
6. cadastrar modelos;
|
|
7. selecionar provider de transcrição;
|
|
8. selecionar provider de análise;
|
|
9. habilitar por tenant;
|
|
10. habilitar por campanha;
|
|
11. gravar chamada;
|
|
12. transcrever;
|
|
13. gerar segmentos;
|
|
14. gerar resumo;
|
|
15. gerar sentimento;
|
|
16. gerar tópicos;
|
|
17. gerar score;
|
|
18. visualizar tudo;
|
|
19. contabilizar uso;
|
|
20. contabilizar custo.
|
|
|
|
---
|
|
|
|
# 229. CRITÉRIO DE ACEITE BILLING
|
|
|
|
Preciso:
|
|
|
|
1. criar plano;
|
|
2. criar versão;
|
|
3. criar price book;
|
|
4. configurar preço base;
|
|
5. preço por ramal;
|
|
6. preço por agente;
|
|
7. preço por trunk;
|
|
8. preço por minuto;
|
|
9. preço IA;
|
|
10. associar tenant;
|
|
11. registrar usage;
|
|
12. rated usage;
|
|
13. visualizar mês atual;
|
|
14. fechar período;
|
|
15. gerar statement;
|
|
16. exportar PDF/CSV;
|
|
17. manter fechamento imutável.
|
|
|
|
---
|
|
|
|
# 230. PRIMEIRA AÇÃO
|
|
|
|
Leia este arquivo inteiro.
|
|
|
|
Depois:
|
|
|
|
```bash
|
|
pwd
|
|
ls -lah
|
|
|
|
cat /etc/os-release
|
|
|
|
uname -a
|
|
|
|
ip addr
|
|
ip route
|
|
|
|
df -h
|
|
lsblk
|
|
|
|
free -h
|
|
nproc
|
|
```
|
|
|
|
Verifique:
|
|
|
|
```text
|
|
b2blogo.png
|
|
```
|
|
|
|
Verifique somente a presença de:
|
|
|
|
```text
|
|
FREESWITCH_PAT
|
|
```
|
|
|
|
Não exiba a chave.
|
|
|
|
---
|
|
|
|
# 231. PRIMEIROS ARQUIVOS
|
|
|
|
Criar:
|
|
|
|
```text
|
|
TODO.md
|
|
|
|
docs/ARCHITECTURE.md
|
|
|
|
docs/SAAS_MULTI_TENANCY.md
|
|
|
|
docs/DATABASE.md
|
|
|
|
docs/SECURITY.md
|
|
```
|
|
|
|
Não parar depois.
|
|
|
|
---
|
|
|
|
# 232. ORDEM DE IMPLEMENTAÇÃO
|
|
|
|
Executar aproximadamente:
|
|
|
|
```text
|
|
Inspect Server
|
|
↓
|
|
Git
|
|
↓
|
|
Docker
|
|
↓
|
|
PostgreSQL
|
|
↓
|
|
Redis
|
|
↓
|
|
Monorepo
|
|
↓
|
|
SaaS Core
|
|
↓
|
|
Tenant Isolation
|
|
↓
|
|
PostgreSQL RLS
|
|
↓
|
|
Plans / Entitlements
|
|
↓
|
|
Authentication
|
|
↓
|
|
RBAC
|
|
↓
|
|
FreeSWITCH
|
|
↓
|
|
Event Socket
|
|
↓
|
|
XML Curl
|
|
↓
|
|
Extensions
|
|
↓
|
|
Trunks
|
|
↓
|
|
Dialplan
|
|
↓
|
|
mod_callcenter
|
|
↓
|
|
Queues
|
|
↓
|
|
Agents
|
|
↓
|
|
Pauses
|
|
↓
|
|
Realtime Monitoring
|
|
↓
|
|
Campaigns
|
|
↓
|
|
Leads
|
|
↓
|
|
CPS Limiter
|
|
↓
|
|
Predictive Engine
|
|
↓
|
|
CDR
|
|
↓
|
|
Recording
|
|
↓
|
|
Object Storage
|
|
↓
|
|
AI Provider Layer
|
|
↓
|
|
Transcription
|
|
↓
|
|
Call Analysis
|
|
↓
|
|
Quality Scorecards
|
|
↓
|
|
Usage Metering
|
|
↓
|
|
Rating Engine
|
|
↓
|
|
Monthly Billing
|
|
↓
|
|
Frontend Polish
|
|
↓
|
|
Reports
|
|
↓
|
|
Security
|
|
↓
|
|
Simulation
|
|
↓
|
|
Tests
|
|
↓
|
|
Final Validation
|
|
```
|
|
|
|
---
|
|
|
|
# 233. PRINCÍPIOS FUNDAMENTAIS
|
|
|
|
Sempre prefira:
|
|
|
|
```text
|
|
multi-tenant desde o início
|
|
>
|
|
adicionar tenant depois
|
|
|
|
|
|
PostgreSQL RLS
|
|
+
|
|
authorization
|
|
>
|
|
confiar somente em WHERE
|
|
|
|
|
|
versioned pricing
|
|
>
|
|
editar preço histórico
|
|
|
|
|
|
immutable usage ledger
|
|
>
|
|
reconstruir billing de forma improvisada
|
|
|
|
|
|
FreeSWITCH native features
|
|
>
|
|
reinventar telefonia
|
|
|
|
|
|
mod_callcenter
|
|
>
|
|
ACD custom desnecessário
|
|
|
|
|
|
Event Socket
|
|
>
|
|
polling
|
|
|
|
|
|
bgapi
|
|
>
|
|
originates síncronos
|
|
|
|
|
|
predictive pacing
|
|
>
|
|
loop simples
|
|
|
|
|
|
provider abstraction
|
|
>
|
|
OpenAI hardcoded
|
|
|
|
|
|
async AI jobs
|
|
>
|
|
IA bloqueando call flow
|
|
|
|
|
|
stereo recording
|
|
>
|
|
speaker identification fraco
|
|
|
|
|
|
structured AI results
|
|
>
|
|
texto livre
|
|
|
|
|
|
encrypted secrets
|
|
>
|
|
plain text
|
|
|
|
|
|
real data
|
|
>
|
|
mock
|
|
|
|
|
|
tests
|
|
>
|
|
presunção
|
|
|
|
|
|
security controls
|
|
>
|
|
bypass de permissões
|
|
```
|
|
|
|
---
|
|
|
|
# 234. RESULTADO FINAL
|
|
|
|
O produto final deverá ser:
|
|
|
|
# B2BCall
|
|
|
|
um SaaS capaz de atender diversos tenants, cada um com:
|
|
|
|
```text
|
|
seus usuários
|
|
|
|
seus ramais
|
|
|
|
seus agentes
|
|
|
|
suas filas
|
|
|
|
seus trunks
|
|
|
|
suas campanhas
|
|
|
|
seus leads
|
|
|
|
suas chamadas
|
|
|
|
suas gravações
|
|
|
|
suas transcrições
|
|
|
|
suas análises IA
|
|
|
|
suas quotas
|
|
|
|
seu consumo
|
|
|
|
seu billing
|
|
```
|
|
|
|
com isolamento completo.
|
|
|
|
---
|
|
|
|
# 235. RELATÓRIO FINAL
|
|
|
|
Somente depois dos quality gates apresentar:
|
|
|
|
```text
|
|
B2BCall Version:
|
|
|
|
Git Commit:
|
|
|
|
Application URL:
|
|
|
|
|
|
Docker Version:
|
|
|
|
PostgreSQL Version:
|
|
|
|
Redis Version:
|
|
|
|
FreeSWITCH Version:
|
|
|
|
|
|
Containers:
|
|
|
|
...
|
|
|
|
|
|
FreeSWITCH:
|
|
|
|
ONLINE / OFFLINE
|
|
|
|
|
|
ESL:
|
|
|
|
CONNECTED / DISCONNECTED
|
|
|
|
|
|
Tenants:
|
|
|
|
...
|
|
|
|
|
|
AI Providers:
|
|
|
|
...
|
|
|
|
|
|
Billing:
|
|
|
|
OPERATIONAL / PARTIAL / FAILED
|
|
|
|
|
|
Tests:
|
|
|
|
Unit:
|
|
|
|
Integration:
|
|
|
|
E2E:
|
|
|
|
Tenant Isolation:
|
|
|
|
Dialer Simulation:
|
|
|
|
Billing:
|
|
|
|
AI:
|
|
|
|
|
|
Security Checks:
|
|
|
|
...
|
|
|
|
|
|
Remaining Issues:
|
|
|
|
...
|
|
```
|
|
|
|
Não esconder pendências.
|
|
|
|
---
|
|
|
|
# 236. REGRA FINAL
|
|
|
|
Trabalhe de forma autônoma dentro das permissões fornecidas pelo Claude Code.
|
|
|
|
Não tente burlar ou remover mecanismos de autorização.
|
|
|
|
Não acesse outros servidores.
|
|
|
|
Não escaneie a rede.
|
|
|
|
Não utilize SSH contra outros hosts.
|
|
|
|
Não procure credenciais externas.
|
|
|
|
Não habilite chamadas PSTN reais automaticamente.
|
|
|
|
Não entregue somente documentação.
|
|
|
|
Não entregue somente frontend.
|
|
|
|
Não entregue somente FreeSWITCH.
|
|
|
|
Implemente progressivamente.
|
|
|
|
Teste continuamente.
|
|
|
|
Corrija os erros.
|
|
|
|
Atualize o `TODO.md`.
|
|
|
|
Faça commits organizados.
|
|
|
|
Continue pelas próximas fases disponíveis.
|
|
|
|
O objetivo final é transformar este servidor em uma instalação funcional do:
|
|
|
|
# B2BCall
|
|
|
|
## SaaS Multi-Tenant + FreeSWITCH + Predictive Dialer + Call Center + Recording + AI + Billing
|