feat(ivr): editor visual do menu (canvas de nós, sem Node-RED)

Pedido do usuário: "ajusta o IVR para fazer o fluxo de maneira visual
usando nodeRED". Perguntei antes de construir: integrar Node-RED de
verdade significa rodar uma plataforma externa completa (motor de
execução próprio, nós "function" = execução de código arbitrário — o
mesmo tipo de risco corrigido no dialplan nesta sessão — e sem
multi-tenancy nativa), um projeto de vários dias com decisões de
arquitetura antes de começar a construir. O usuário escolheu a
alternativa: um editor visual próprio, sem dependência externa.

`@xyflow/react` (sucessor mantido do reactflow) — canvas de nós/setas
dentro da própria tela "Telefonia > IVR": 1 nó "Entrada" fixo conectado
a 1 nó por opção (dígito + select de ramal + descrição, editável direto
no nó, arrastável pro canvas). "Adicionar opção"/"Salvar alterações"
chamam o mesmo PATCH /ivr-menus/:id que já existia — nenhuma mudança de
backend necessária, só uma forma nova de editar o mesmo dado (o modelo
IvrMenu/IvrMenuOption continua sendo a fonte da verdade).

Testado ponta a ponta pela tela de verdade, não só leitura de código:
criado um menu real, enviado um prompt de VOZ real (WAV sintetizado com
espeak-ng dizendo uma saudação de verdade, não um tom sintético como nos
testes anteriores desta fase) e completada uma chamada real — a saudação
de ~6s tocou até o fim, o dígito foi capturado, o ramal certo atendeu
com áudio de verdade. Depois, uma segunda opção foi adicionada via PATCH
(a mesma chamada que o botão "Salvar" do editor visual faz) — confirmado
no banco que a versão 2 do dialplan compilou as duas opções
corretamente, superando a versão 1.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BFaBaBSQGhyXGEgtTYZGV8
This commit is contained in:
2026-08-30 18:21:26 -03:00
parent 486c39803a
commit 0148b926a0
7 changed files with 499 additions and 19 deletions

27
TODO.md
View File

@@ -2176,6 +2176,33 @@ tela de IVR no frontend")
confirma que áudio de qualquer sample rate/formato WAV comum
funciona sem transcodificação manual
## PHASE 60 — Editor visual do IVR (pedido do usuário: "ajusta o IVR
para fazer o fluxo de maneira visual usando nodeRED")
- [x] Node-RED de verdade avaliado e descartado por decisão do usuário
(pergunta explícita: integrar de verdade significa uma plataforma
externa completa — motor de execução próprio, nós "function" =
RCE, sem multi-tenancy nativa — vários dias de trabalho e
superfície de risco nova, não um ajuste na tela atual). Escolhido
em vez disso um editor visual PRÓPRIO, sobre o mesmo modelo já
existente, sem dependência de execução externa
- [x] `@xyflow/react` — canvas de nós/setas dentro da própria tela
"Telefonia > IVR": 1 nó "Entrada" fixo conectado a 1 nó por opção
(dígito + select de ramal + descrição, editável direto no nó,
arrastável). "Adicionar opção"/"Salvar alterações" chamam o mesmo
`PATCH /ivr-menus/:id` que já existia — nenhuma mudança de backend
necessária, só uma forma nova de editar o mesmo dado
- [x] Testado ponta a ponta pela tela de verdade: menu criado, prompt de
VOZ real enviado (WAV sintetizado com `espeak-ng` dizendo "Bem-
vindo a Acme Call Center...", não um tom sintético como nos testes
anteriores) e uma chamada real completa — a saudação de ~6s tocou
até o fim, o dígito foi capturado, e o ramal certo atendeu com
áudio de verdade. Depois, uma segunda opção foi adicionada via
`PATCH` (a mesma chamada que o botão "Salvar" do editor visual
faz) — confirmado no banco que a versão 2 do dialplan compilou as
duas opções corretamente, superando a versão 1
- [ ] Layout do canvas não persiste posição manual dos nós entre
recargas (recalculado a cada carga da página)
---
## Riscos conhecidos