Fase 9 (segurança e produção): - GET /api/metrics: endpoint Prometheus com métricas reais (chamadas, agentes, filas, CPS por campanha), protegido por permissão - scripts/backup.sh, restore.sh, healthcheck.sh, install.sh, update.sh — testados contra o ambiente real (backup.sh e healthcheck.sh rodados de verdade; install.sh/update.sh validados por inspeção, ambiente atual já provisionado) - POST /api/agent-console/dispose: aplica disposição de chamada de verdade (lacuna deixada aberta desde a Fase 6), com ações CALLBACK (agenda retorno) e DO_NOT_CALL (suprime automaticamente) - apps/dialer-worker/src/callback-sweep.ts: reativa leads com callback vencido; GET /api/callbacks para consulta - apps/dialer-worker/src/wrap-up-sweep.ts: transição automática WRAP_UP -> AVAILABLE + despausa real na fila do Asterisk. Exigiu corrigir main.ts para conectar ao AMI mesmo em DIALER_SIMULATION=true (DIALER_SIMULATION deve impedir só originação de chamada, não ações administrativas de fila) - nftables revisado (sem alterações necessárias) - Documentação completa: INSTALL, OPERATIONS, BACKUP_RESTORE, SECURITY, DATABASE, API, ASTERISK, OPENSIPS (não implementado, motivo documentado), TROUBLESHOOTING - README.md e CHANGELOG.md reescritos Fase 10 (testes e aceite): - Quality gate completo executado: build/typecheck (7 workspaces), lint, 46 testes unitários, docker compose config/ps, healthcheck — tudo verde - Aceite de segurança (seção 92): 13 itens verificados ao vivo contra o sistema real, não só por inspeção de código - Aceite Asterisk (seção 93): os 5 comandos executados e documentados, comunicação API->AMI->Asterisk validada - docs/RELATORIO_FINAL.md: relatório final no formato da seção 96 Todos os fixtures de teste desta fase foram removidos/desativados ao final. Credenciais de acesso entregues separadamente em CREDENCIAIS.txt (fora do git, nunca versionado).
3.6 KiB
3.6 KiB
B2BCall — Banco de Dados
PostgreSQL 17, um único cluster/instância com dois schemas que nunca se
misturam (ver docs/ARCHITECTURE.md §3.3):
public— domínio da aplicação (este documento). Gerenciado 100% por Prisma (packages/database/prisma/schema.prisma+prisma/migrations/).asterisk— objetos de Realtime do Asterisk (ps_endpoints,ps_auths,ps_aors,ps_contacts,ps_endpoint_id_ips,ps_registrations,cdr,cel). Criado porinfrastructure/postgres/init/002-asterisk-realtime.sqle escrito exclusivamente porapps/api/src/telephony/pjsip-realtime.service.ts(nunca por SQL solto em outro lugar da aplicação).
Modelos (schema public)
| Modelo | Propósito |
|---|---|
User, Session, PasswordResetToken |
Autenticação (Fase 3) |
Role, Permission, UserRole, RolePermission |
RBAC |
AuditLog |
Auditoria de todas as ações sensíveis |
Trunk, Extension, ExtensionState |
Telefonia (Fase 4) — Trunk/Extension são o CRUD da aplicação; os objetos PJSIP reais ficam no schema asterisk |
DialplanEntry, DialplanVersion |
Dialplan estruturado versionado |
Queue, QueueMember, PauseReason |
Call Center (Fase 5) |
Agent, AgentSession, AgentStateEvent, AgentPauseEvent |
Máquina de estados do agente — sempre exatamente um AgentStateEvent aberto (ended_at IS NULL) por agente |
Campaign, LeadImport, Lead, DialAttempt |
Discador preditivo (Fase 6). DialAttempt é a "chamada" como state machine (seção 36) — id próprio, nunca o UNIQUEID do Asterisk como PK de negócio |
CallDisposition, Callback |
Disposição de chamada e agendamento de retorno |
SuppressionEntry |
Lista de bloqueio (DNC) |
ComplianceSettings |
Parâmetros de compliance (singleton) |
Decisões importantes
- Prisma como ORM (não Drizzle/TypeORM) — ver justificativa em
docs/ARCHITECTURE.md§3.6.1. - Índices de alto volume:
Lead(campaignId, status, nextAttemptAt),DialAttemptporcampaignId/state/asteriskUniqueId,AuditLog(createdAt),AuditLog(entityType, entityId). Consultas de relatório usam paginação server-side sempre (nuncaSELECT *sem filtro — seção 54). - Reserva concorrente de leads:
SELECT ... FOR UPDATE SKIP LOCKEDvia$queryRawemapps/dialer-worker/src/lead-repository.ts— não modelado via Prisma de alto nível porque a transição atômica READY→RESERVED precisa de controle fino de lock que o ORM não expõe com segurança suficiente sob concorrência real. - Particionamento: avaliado, não implementado (volume atual não
justifica).
DialAttempt/AuditLogsão os candidatos naturais quando o volume crescer — desenhados para permitir particionamento porstarted_at/created_atsem migração destrutiva. - Segredos:
Trunk.secretEncryptedeExtension.sipPasswordEncryptedsão cifrados com AES-256-GCM (packages/shared/src/secret-crypto.ts), chave mestra emSECRETS_MASTER_KEY(.env, nunca no banco).
Migrations
cd packages/database
pnpm exec prisma migrate dev --name <descrição> # desenvolvimento
pnpm exec prisma migrate deploy # produção (usado por scripts/update.sh)
pnpm run seed # permissões, perfis, bootstrap super_admin
Nenhuma alteração de schema é feita manualmente em produção — sempre via migration versionada e commitada (seção 85).
Backup / Restore
Ver docs/BACKUP_RESTORE.md. Resumo: pg_dump -Fc do banco inteiro cobre
public e asterisk num único arquivo, já que ambos vivem na mesma
instância Postgres.