Files
DeskcommCRM/CHANGELOG.md
T
Rafael MelgaçoandClaude Opus 5 4aa65590e0 feat(orcamento): a tela deixa de mentir, e a IA que para avisa gente
Ondas 4 e 5, que fecham o conserto: o controle da tela passa a valer, o sistema
paralelo morto sai, e um bloqueio deixa de abandonar o lead.

`DESKCOMM_GOV_INVARIANTS_EDIT=1` — dois invariantes MODIFICADOS, e a razão:
`vocabulario-banco-x-typescript` ganhou o par `ModoDeOrcamento` (coluna nova com
CHECK precisa de par no TypeScript, senão o job `invariants` reprova), e
`orcamento-apos-backfill` acompanhou a mudança do piso. O invariante NOVO
(`orcamento-nasce-desarmado`) não precisa da flag.

## Os três achados que valeram mais que a feature

**1. A escolta era inalcançável no caso dominante.** `classifyStage` roda em
todo turno e estourava ANTES da escolta — que, portanto, nunca protegia o
caminho normal. Movida para `runAgentTurn`, que envolve o turno inteiro. A
guarda antiga contava `runModelCall(` no texto e era cega para helpers; agora
conta call sites e a fronteira dos auxiliares.

**2. A escada era contornável pela REST do Supabase** (migration 0160). O PATCH
exige `off → avisar → bloquear`, mas `ai_budgets` aceitava escrita direta de
`authenticated` — qualquer cliente com a anon key pulava a escada e armava
bloqueio imediato. `revoke insert/update/delete`, SELECT fica.

**3. O texto mandava clicar num botão que não existe.** A mensagem que o cliente
lê quando a IA para dizia "Retomar atendimento automático"; o componente
renderiza **"Devolver ao automático"**. Corrigido em 7 arquivos, e a guarda nova
**lê o rótulo do componente** em vez de guardar uma cópia — cópia de rótulo é a
próxima mentira esperando envelhecer.

## O dropdown decorativo saiu

"Ação ao atingir 100%" oferecia "Pausar" vs "Desabilitar" e o produto entregava
sempre a mesma coisa. Era o defeito que este trabalho existe para matar,
sobrevivendo dentro do conserto — um juiz reprovou um desenho inteiro por
mantê-lo. Ou entrega os dois futuros, ou sai. Saiu.

## O lead não fica mais no vácuo

Quando o orçamento barra, o turno vai para `performHumanHandoff` com contexto, e
o job é **cancelado** (`cancelJob`), não falhado com retry: repetir uma chamada
que o teto recusa é gastar de novo para receber a mesma recusa. O caminho legado
ganhou o mesmo veto — e depois dos gates que reconhecem "quero falar com um
atendente", não antes, senão pedir humano viraria silêncio.

## Sabotagem: 10 previsões, 10 acertos

escolta fora do turno 3×3 · piso só para bloquear 3×3 · não zerar a carência 2×2
· veto antes dos gates 1×1 · sem handoff 1×1 · ressalva de medição sumida 1×1 ·
rótulo do período revertido 2×2 · flag de gasto incompleto fixa 1×1 · janela do
mês removida 1×1 · botão renomeado 3×3.

## Uma discordância mantida, com evidência

O KPI de plataforma fica na coluna acumulada. A alternativa barata seria um
`group by` inline — a segunda régua de gasto que `orcamento-uma-regua-de-gasto`
existe para impedir, e o gate provou o ponto reprovando o próprio comentário do
implementador quando ele escreveu a query em PROSA. Mitigado: nunca `critical`,
rótulo "acumulado", divergência escrita no arquivo e link para a tela que tem a
régua certa.

## Bateria

typecheck 0 · lint 0 erros · lint:channels 0 · test:shell 0 · build 0 ·
test:unit **3347 passam**, 1 falha — a baseline do `.env.local` deste worktree,
que não cita orçamento, budget, handoff nem money.

## NÃO MEDIDO, declarado

- `tests/invariants/orcamento-nasce-desarmado.test.ts` é **novo e nunca foi
  executado** (15 casos, e é a primeira vez que `SQL_ORCAMENTO` roda contra
  Postgres em todo o repo). É o maior risco de CI vermelho desta entrega, e está
  escrito aqui porque dívida declarada não é defeito — dívida presumida é.
- O `revoke` da 0160 não foi provado contra PostgREST vivo: o achado veio de
  leitura de grants.
- **DoD 12 (prova pela tela): NÃO MEDIDO.** Radio, kill switch e badge estão
  provados por unidade em jsdom e por `build`, não por browser em ambiente fresco
  estilo VPS.
- `test:db`, `e2e` e `build-and-size`: quem prova é o CI.

Nota de release em `docs/release/teto-de-orcamento.md`; mapa vivo em
`docs/architecture/teto-de-orcamento.architecture.json` (26 nós, 43 arestas).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TCiffR3ugjQbxsfceQE2GB
2026-08-15 10:58:07 -03:00

25 KiB
Raw Blame History

Changelog

Todas as mudanças relevantes deste projeto são documentadas aqui.

O formato segue Keep a Changelog e o versionamento segue SemVer.

Se você roda o DeskcommCRM numa VPS, leia a seção da versão para a qual está atualizando antes de rodar bash update.sh. Mudanças que exigem ação manual aparecem sob ⚠️ Requer atenção.

Não lançado

Adicionado

  • O agente de atualização passa a fixar sozinho a versão que ficou solta, em até 5 minutos, sem você fazer nada — ele grava a versão que já está rodando. O que ele nunca faz é mexer numa configuração que você escreveu à mão: se você escolheu acompanhar um canal de propósito, ele respeita e só avisa.

    Isso não vale para quem está na 1.3.0 — entrou depois dela. Até a próxima versão sair, a instrução da 1.3.0 continua sendo a única verdadeira: rode o update.sh duas vezes.

  • O limite de gasto com IA passa a valer de verdade — e nasce desligado. Até agora a tela de Uso de IA › Orçamento deixava você escrever um limite mensal, mas quem barrava a chamada olhava para outro lugar: nenhuma instalação estava protegida, e a tela dizia que estava. Agora o número que você digita é o número que decide. Para que ligar isso não corte o atendimento de ninguém por engano, a proteção começa desligada em todo mundo e só liga em três passos, na tela: Só acompanhar → Me avisar → Parar a IA no limite. Não dá para pular direto para a parada, e quando você a arma ela só começa a valer 72 horas depois (dá para renunciar a essa espera marcando a caixa). Você não precisa fazer nada — quem não abrir essa tela continua exatamente como está hoje.

  • Quando o limite para a IA, ninguém fica sem resposta. As conversas que estavam sendo atendidas vão para a fila de atendimento humano, com um aviso na Central explicando o que aconteceu. Cada uma volta ao automático pelo botão "Devolver ao automático" no cabeçalho da conversa. Aumentar o limite evita paradas novas, mas não devolve sozinho as conversas que já pararam.

  • Um aviso na Central quando o gasto passa do ponto que você escolheu, antes de qualquer parada — e ele se apaga sozinho quando o gasto volta para baixo do limite ou o mês vira.

Corrigido

  • ⚠️ Requer atenção — o valor do orçamento de IA sempre foi em DÓLAR, e a tela dizia real. Quem lia "R$ 50,00" tinha, na verdade, um limite de US$ 50,00 — cerca de cinco vezes maior do que imaginava. Nada mudou no seu gasto nem no seu limite: mudou o que a tela confessa. O rótulo agora diz US$ nas telas de Uso de IA, Execuções, Evolução e nos painéis de administração. Confira o número antes de ligar a parada automática: se você escolheu "50" pensando em reais, o que está armado é cinco vezes isso.
  • O gasto exibido era o acumulado desde a instalação, não o do mês. O contador antigo somava tudo e nunca zerava, então numa instalação com alguns meses de uso o card comparava meses de gasto contra um limite mensal. Agora o número é o do mês corrente, e é o mesmo número que decide se a IA para.
  • O seletor "Ação ao atingir 100%" saiu da tela. Ele oferecia "Pausar" e "Desabilitar" como se fossem coisas diferentes; não eram — nada no produto os distinguia, e a escolha não tinha efeito nenhum. Quem quiser que a IA pare no limite usa a opção "Parar a IA" da escada nova.
  • Os avisos de orçamento apareciam e não sumiam. O alerta de "limite atingido" ficava aceso mesmo depois de o mês virar ou de você aumentar o limite. Agora ele se retrata sozinho.
  • No painel de administração, o alerta de orçamento parou de gritar "crítico" sobre um número que não é o do mês. Ele continua avisando, com o rótulo dizendo que o valor é acumulado, e leva direto para a tela de saúde do cliente, que mostra o número real.

[1.3.0] — 2026-08-13

Esta versão mexe em como o sistema chega e se atualiza no seu servidor. Em uso, três coisas mudam para melhor: a instalação deixa de ter uma etapa que podia falhar por falta de memória no meio (o servidor não compila mais nada — tudo vem pronto), fica bem mais rápida, e o agente de IA passa a receber as correções de cada versão. A recomendação de servidor continua exatamente a mesma: o que consome memória é operar o sistema no dia a dia — 7 serviços e cerca de 150 MB por número de WhatsApp conectado —, e isso não mudou nem um pouco.

Corrigido

  • O agente de IA nunca recebia atualização. O worker — o processo que faz o agente atender 24 horas por dia — era compilado dentro do seu servidor no dia da instalação, e nenhuma atualização o reconstruía. Na prática: você atualizava o CRM, o site mudava, e o agente continuava rodando exatamente o código do dia em que você instalou, para sempre. Correções e melhorias do agente não chegavam. Agora ele é uma imagem pronta, publicada junto com o resto, e o update.sh a traz como traz o app.
  • Duas instalações "na mesma versão" rodavam código diferente. Uma instalação nova ficava apontada para o canal latest, que — apesar do nome — acompanha o desenvolvimento em andamento, não a última versão lançada. Quem instalou em semanas diferentes tinha software diferente, e não havia como dizer qual. Agora o instalador grava o número da versão (ex.: 1.2.1), e é essa versão que fica no seu servidor até você decidir atualizar.
  • O CRM podia não subir por causa de um serviço externo fora do ar. A configuração pedia ao Docker que verificasse o registro de imagens a cada subida; se ele não respondesse, o contêiner não subia — mesmo com a imagem já baixada no seu disco. Agora que o seu servidor fica numa versão fixa, essa verificação deixa de ser feita na sua instalação (quem acompanha um canal móvel continua com ela, que é onde ela serve para alguma coisa).
  • O agendador de tarefas dependia da internet para voltar. A cada reinício ele baixava dois programas antes de começar. Sem internet no momento do reboot — justo quando a máquina está se recuperando de alguma coisa —, as tarefas automáticas não voltavam. Agora já vêm dentro da imagem.
  • A versão mostrada em /api/v1/health era sempre 0.1.0, em qualquer instalação. Agora é a versão de verdade.
  • O WhatsApp (WAHA) e o serviço de limites deixaram de acompanhar automaticamente qualquer versão nova publicada por terceiros. Passam a mudar só quando nós testamos e lançamos.

⚠️ Requer atenção

Se o seu servidor foi instalado antes desta versão, rode o update.sh DUAS vezes.

As duas execuções são necessárias nesta versão. O agente que corrige isso sozinho entrou depois da 1.3.0 (está em Não lançado) — se você está atualizando para a 1.3.0, ele não existe no que você vai instalar. Esta nota já disse o contrário, e a frase teria feito você esperar cinco minutos por algo que nunca ia acontecer. Medido em ensaio numa VPS: a primeira execução traz o agente novo, mas deixa a versão dele "solta" — acompanhando o canal em vez de ficar fixa, como o resto do sistema. Isso faria o agente saltar sozinho para a versão seguinte num reinício futuro, enquanto o resto do servidor continuaria onde está. A segunda execução fixa tudo na mesma versão.

Para saber em que pé você está, sem mexer em nada:

curl -fsSL https://raw.githubusercontent.com/melgarafael/DeskcommCRM/main/hostgator-setup-kit/diagnostico.sh | bash

Ele só lê e explica — não escreve, não reinicia, não atualiza. Se disser que está afetada, o passo a passo (com como voltar atrás) está em docs/runbooks/remediar-worker-congelado.md.

Fora isso, nada exige ação sua. Um .env antigo continua funcionando: as configurações novas têm valor padrão e o próprio update.sh as acrescenta.

1.2.1 — 2026-08-12

Versão de segurança. Se você roda o DeskcommCRM numa VPS, atualize.

Um usuário da comunidade auditou o código e mandou um relatório. Parte do que ele apontou já tinha sido corrigida nas versões seguintes à que ele analisou — mas seis problemas estavam de pé, e um deles deixava dados de uma empresa visíveis para outra. Todos foram corrigidos, cada um com um teste automático que impede o problema de voltar.

Corrigido

  • Uma empresa conseguia ler a base de conhecimento de outra, e escrever no histórico dela. Duas funções internas aceitavam o identificador da empresa como se fosse confiável, sem conferir se quem pediu era mesmo de lá. O isolamento entre empresas estava de pé em todo o resto — o furo era só nessas duas portas, e elas agora conferem.
  • Quem tinha permissão de apenas visualizar conseguia mudar configurações importantes. Um usuário "visualizador" podia reescrever as instruções do agente de IA (o texto que ele fala com o seu cliente), desligar o canal de WhatsApp, mexer no limite de gastos e apagar a chave do provedor de IA — bastava falar direto com o banco de dados, sem passar pelas telas. Agora essas mudanças exigem administrador, como as telas já exigiam.
  • A verificação em duas etapas do administrador valia só na tela. Quem tinha a senha de um administrador, mas não o segundo fator, ficava barrado na interface e mesmo assim alcançava as funções sensíveis por fora dela — criar chave de API, convidar gente para a equipe, pedir exportação de dados. Agora o servidor confere o segundo fator em todas elas.
  • Link de login podia levar para um site estranho. Um endereço preparado por terceiros fazia você digitar a senha no site certo e, logo depois de entrar, ser jogado para outro lugar — o momento em que se confia mais na próxima tela.
  • Envio de arquivo na conversa não conferia permissão. Era a única ação de escrita da conversa sem essa checagem; um usuário "visualizador" podia enviar arquivos de até 50 MB.
  • Automação de webhook podia alcançar a rede interna do servidor. A checagem olhava só o texto do endereço; um domínio preparado para apontar "para dentro" passava, e alcançava serviços internos e a área de credenciais do provedor de nuvem. Agora o endereço é resolvido de verdade antes de qualquer envio.

⚠️ Requer atenção

  • Administradores vão precisar entrar de novo, com o código do aplicativo. Se você já tem a verificação em duas etapas cadastrada e está com a sessão aberta, as ações de administrador passam a pedir o segundo fator. Sair e entrar novamente resolve. Quem ainda não cadastrou o segundo fator não é afetado e continua conseguindo cadastrá-lo normalmente.
  • Usuários "visualizador" e "gerente" perdem a escrita em configuração de IA e canais. Se alguém do seu time mexia nessas telas sem ser administrador, promova a pessoa a administrador antes de atualizar — ou ela vai encontrar as ações bloqueadas.
  • Nenhuma ação manual no banco é necessária. O update.sh aplica tudo sozinho.

1.2.0 — 2026-08-11

A maior versão até aqui: 126 novidades e 205 correções desde a 1.1.0 (contadas por commit). Dois temas.

O primeiro é o agente de IA deixar de ser um respondedor e virar parte da operação: ele ganha papéis separados, capacidades declaradas, um follow-up que não deixa conversa morrer no silêncio, e um painel onde você escolhe qual inteligência atende cada parte do sistema.

O segundo é o sistema parar de mentir quando algo dá errado: falha de IA deixa rastro em vez de sumir, botão que não controlava nada foi ligado (ou removido), e erro de rede diz onde mexer em vez de mandar reiniciar o que nunca caiu.

Adicionado

O agente ganha papéis

  • Três papéis em vez de um — Conversador, Operador e Segurança. Quem fala não é quem executa, e o disparo de ação passou a ser imposto pelo sistema, não decidido pelo modelo. Efeito medido: a taxa de resposta em que dado interno vazava para o cliente (URL de sistema, UUID, jargão de CRM) caiu de 3 em 10 turnos para 1 em 10 — mesmos cenários, ferramentas executadas contra dados reais, controle calibrado contra a linha de base.
  • O agente publicado tem lugar próprio, entre atendente e gerente: assume o lead, devolve para uma pessoa quando precisa, e a volta aparece na linha do tempo em vez de sumir.
  • Capacidades declaradas. Você escolhe o que ele pode fazer, vê quantas vezes usou cada uma, e ele avisa quando falta uma capacidade em vez de falhar calado.
  • Roteador de intenção por número — um WhatsApp só passa a atender vários assuntos — agora com escolha do modelo (e do provedor) que identifica a intenção.

Follow-up: nenhuma conversa morre no silêncio

  • O follow-up nasce sozinho quando o negócio entra numa etapa do funil, ou quando o agente abre um caso pedindo ajuda — e morre quando o caso fecha.
  • Ramos nomeados no canvas: cada regra é uma bolinha com nome, e publicar exige cobertura por ramo, dizendo qual ramo ficou descoberto.
  • Pausar, retomar, adiar e pular um follow-up sem matá-lo.
  • Tempo adaptativo — a IA escolhe o intervalo e a tela mostra qual foi, e se bateu no seu limite.
  • Dossiê do follow-up: o que já foi tentado, com o que o motor realmente fez.
  • O painel inteiro fala português — UUID saiu da tela.

Escolher a sua IA

  • Painel de Provedores (Agente de IA → Provedores): a tela onde se vê e se escolhe qual inteligência atende cada uma das 23 partes do sistema que usam IA — conversar, classificar sentimento, indexar conhecimento, ouvir áudio. Antes disso a escolha existia só no .env.
  • OpenRouter completa — uma chave só, com catálogo que se atualiza sozinho contra a origem (cerca de 400 modelos na sincronização de referência; o número acompanha o que eles publicam).
  • O instalador pergunta qual IA vai atender (OpenRouter, Anthropic ou OpenAI) e valida a chave na hora, em vez de assumir uma e falhar semanas depois.
  • Catálogo de modelos atualizado nos provedores — quem instala não escolhe mais entre modelos de duas gerações atrás, pagando mais caro por pior.

Ver o que a IA fez

  • Tela de Execuções (Agente de IA → Execuções): o que a IA fez e, quando falhou, o que aconteceu e o que fazer a respeito.
  • Falha de IA deixa rastro. Antes, um erro no meio do caminho sumia — o log mentia por omissão e a operação não tinha como saber que algo não rodou.

A conversa vira CRM sozinha

  • A conversa vira lead sem alguém transcrever nada à mão.
  • A IA propõe o dado que o cliente disse — telefone, e-mail, nome — e não grava nada: o dado espera numa fila até uma pessoa confirmar na tela.
  • Demandas viram entidade de primeira classe: nascem no ponto de entrada, aparecem no painel de quem atende, e o Radar mostra as que estão sem próximo passo — o que corre risco de morrer sem resposta.
  • Escopo de funil do agente: você marca em quais funis ele mexe, e ele só escreve nesses.

Medir a operação

  • Índice de Atrito (Desempenho) — o sistema passa a medir o próprio propósito.
  • Abandono, repergunta e espera calada — as perdas de que ninguém reclama, agora contadas.

Atendimento

  • Fila de leads por atendente, com rodízio. A distribuição deixa de ser combinada por fora e vira porta na tela.
  • Colar imagem no composer com Ctrl+V.
  • Declarar desde quando o número é usado e poder pular o aquecimento — um número antigo não precisa ser tratado como recém-nascido.
  • Aviso de mensagem presa. Uma tarefa automática detecta mensagem que ficou "enviando" e abre um aviso na Central, em vez de deixar o cliente sem resposta em silêncio.

Corrigido

  • Duas partes do sistema respondiam à mesma mensagem do cliente. Agora há um dono só.
  • "O WhatsApp está fora do ar" quando o serviço estava de pé. Toda falha de rede caía na mesma frase, mandando reiniciar um container que nunca havia caído. Agora a mensagem distingue endereço errado de serviço parado e diz onde mexer.
  • Escolher OpenRouter ou OpenAI no instalador tornava a instalação impossível — e, num segundo defeito, a escolha era decorativa: aceita na pergunta e ignorada depois.
  • O instalador perdia a chave que você tinha configurado à mão no .env, e a segunda execução desfazia a entrevista já respondida.
  • O papel Operador escrevia no CRM depois de o humano assumir a conversa — era o único turno sem a guarda.
  • A telemetria da IA voltou a dizer a verdade (5 defeitos de uma unificação anterior), e a troca de modelo voltou a ser auditada — o registro era engolido em silêncio.
  • Duas mutações perdiam a auditoria caladas por chave natural gravada em coluna uuid.
  • A aba "Minhas" mostrava tudo que o atendente já tinha fechado.
  • O filtro por tag da tela não filtrava — a rota ignorava o parâmetro.
  • O menu passava da dobra em telas de 900px depois que as telas novas entraram.
  • O roteador recusava um número que existia, com a mensagem "não encontrado nesta organização", quando na verdade a consulta é que havia falhado.
  • A tela de funis misturava organizações do mesmo usuário.
  • Excluir um canal apagava o roteador junto, sem avisar, e deixava a Meta ainda entregando mensagens. Reconectar dizia "conectado" com a linha ainda arquivada.
  • Erro ao publicar o agente no onboarding criava um agente novo a cada clique.
  • O custo de IA sem agente dono sumia da auditoria — as telas de consumo mostravam zero numa instalação com tráfego real e provedor pago.
  • Mover um lead pelo assistente deixou de pular o que mover pela mão aciona.
  • Telefone descoberto depois estourava a restrição de unicidade e a mensagem do cliente sumia.
  • O update.sh inventava gasto de IA e podia pausar o agente de quem estava atualizando.
  • Uma migration anterior apagou três tipos de aviso da Central — corrigido, e agora há um gate que compara.

Segurança

  • 8 de 25 funções internas do banco estavam executáveis pela chave pública que vai para o navegador, incluindo uma que escreve recebendo a organização por parâmetro, sem checar se você pertence a ela. Todas fechadas, com uma varredura que reprova a próxima.
  • Desligar uma camada de proteção do agente era escrita de qualquer membro da organização — agora exige papel de gestão.
  • Expressão regular vulnerável a ReDoS na leitura do telefone dentro da conversa.
  • O limitador de requisições vazava uma chave por janela em memória.
  • O Sentry da comunidade recebia sessão além de erro — agora recebe só o relatório de erro, como o README sempre descreveu.

⚠️ Requer atenção

Esta versão traz 51 mudanças de banco (migrations 0087 a 0148). O update.sh aplica tudo sozinho e faz backup antes — você não precisa rodar nada à mão. Se a sua instalação está há muito tempo sem atualizar, é normal a etapa do banco demorar mais e imprimir vários avisos de "já existe": eles são esperados, e o script só destaca o que não for.

Se você instalou entre 30/07 e hoje, seu servidor já roda este código (a instalação acompanha a main) — esta tag existe para que a atualização pela tela e o update.sh voltem a ter um alvo publicado para comparar.

1.1.0 — 2026-07-30

Adicionado

  • Atualização pela própria tela. O dono da instalação vê a versão instalada no rodapé do menu e, quando há versão nova, atualiza com um clique — sem abrir terminal. A tela mostra o que muda, avisa quanto tempo o sistema fica fora do ar e faz uma cópia de segurança antes.

Alterado

  • A atualização passa a instalar a última versão publicada, não o topo do código em desenvolvimento. O update.sh recusa instalar uma versão anterior à que já está no servidor (voltar no tempo continua possível com --force) e grava a imagem escolhida no .env — assim um docker compose up -d rodado depois não traz o app de volta para a latest.

⚠️ Requer atenção

Quem já tem o CRM instalado precisa rodar bash hostgator-setup-kit/update.sh duas vezes pelo terminal para ativar o botão. Não é engano: a primeira execução ainda é a do programa antigo, que baixa o novo mas não sabe ligar o agente da tela; a segunda já roda o programa atualizado e liga. Depois disso, nunca mais é preciso o terminal.

1.0.0 — 2026-07-27

Primeira versão marcada do DeskcommCRM. O projeto vinha sendo desenvolvido publicamente desde abril de 2026 sem tags; esta release estabelece o ponto a partir do qual toda mudança passa a ser versionada e descrita — porque quem hospeda o próprio sistema precisa saber o que muda antes de atualizar.

Plataforma

  • Multi-tenancy com RLS em toda tabela tenant-aware, resolvida por fn_user_org_ids().
  • RBAC de 4 papéis (viewer < agent < manager < admin), aplicado no servidor.
  • Autenticação via Supabase Auth com MFA TOTP obrigatório para administradores.
  • Log de auditoria append-only com retenção de 5 anos.
  • Onboarding de organização e ciclo completo de convite de membros.

Atendimento WhatsApp

  • Inbox de 3 painéis em tempo real, com múltiplos números via WAHA.
  • Mídia servida por Storage com URLs assinadas; transcrição de áudio.
  • Proteção anti-banimento: ritmo com variação, teto por número, janela de horário, aquecimento gradual e variação de texto.
  • Detecção de pedido de descadastro (STOP) no inbound, com bloqueio automático.

CRM

  • Funil kanban com indexação fracionária de posição.
  • Vocabulário configurável por funil — o mesmo núcleo atende e-commerce, clínica, imobiliária, infoproduto e serviços.
  • Customer 360, contatos, etiquetas e linha do tempo unificada.
  • Integração com Nuvemshop para a vertical de e-commerce.

Agentes de IA

  • Agentes com RAG por organização (pgvector), análise de sentimento e controle de orçamento por organização.
  • IA como responsável de primeira classe, sujeita às mesmas regras de governança de um humano.
  • Handoff IA→humano auditado, entregando resumo contextual (não a conversa crua).
  • Cadeia de 7 verificações antes de cada envio, em ordem fixa: descadastro, LGPD, anti-banimento, variação de texto, promessa determinística, promessa semântica e disclosure. Cada avaliação vira registro durável e auditável — inclusive as que barram o envio.
  • Servidor MCP interno.

Governança de atendimento

  • Atribuição e transferência auditadas, fila com posição e roteamento automático.
  • Escopo de visualização por papel, aplicado via RLS.
  • Métricas por atendente.

Automação

  • Fontes de captação: endpoint público por organização que recebe leads de landing pages, formulários e ferramentas externas.
  • Regras QUANDO/SE/ENTÃO, que nascem pausadas até revisão.
  • Webhooks de saída com proteção contra SSRF.
  • Nenhum trigger de banco faz HTTP: eventos vão para event_log e são drenados por rota agendada.

LGPD

  • Exportação e anonimização em cascata via workers, com anonimização preferida sobre exclusão.
  • Consentimento auditado.

Self-host

  • hostgator-setup-kit: instalação completa (app + WAHA + banco) com um comando.
  • baseline.sql idempotente e auto-curativo — atualização não quebra clone com dados legados.
  • 8 scripts de operação: install, update, backup, restore, reset-password, reset-mfa, healthcheck e o assistente de instalação em IA.
  • Imagem publicada em ghcr.io/melgarafael/deskcommcrm — a VPS não compila nada.

Qualidade

  • CI com dois portões obrigatórios: verify (typecheck, lint, testes unitários) e invariants.
  • O portão invariants sobe um Postgres limpo, aplica o baseline.sql em modo install e update, e roda 364 testes de invariante em 56 arquivos — incluindo o teste de isolamento entre organizações, que prova que um usuário de uma organização não enxerga nenhuma linha de outra.
  • Suíte end-to-end em Playwright dirigindo o frontend.

⚠️ Requer atenção

  • Node 22 é obrigatório para desenvolvimento. A suíte de invariantes instancia o cliente do Supabase, que exige o WebSocket global — nativo apenas a partir do Node 22. Isso não afeta quem apenas hospeda: a VPS roda a imagem pronta.