Adicionado
-
Chamada de voz pelo WhatsApp — desligada por padrão, e com botão de desligar de verdade O sistema passa a poder fazer e receber chamadas de voz pelo WhatsApp, e ela chega
desligada. Atualizar não liga nada: nenhum número seu é conectado a nada, nenhum serviço
novo sobe na sua VPS, e nada muda na sua tela até você decidir.A razão de tanto cuidado está escrita na própria tela, antes do botão: para fazer chamadas, o
sistema precisa conectar um segundo aparelho ao mesmo número de WhatsApp que você já usa
para atender — e essa conexão não é feita pelo caminho oficial do WhatsApp. Se ele entender
isso como uso indevido, quem é bloqueada é a conta, não só a chamada: você perde também as
mensagens desse número. Por isso ligar é decisão de quem administra a empresa, exige marcar
que leu o aviso, e fica registrado quem aceitou e quando.E desligar desliga mesmo. Antes, o único botão que existia era o de conectar — não havia
caminho de volta: apagar a configuração escondia a tela e deixava o aparelho vinculado ao seu
número para sempre, do lado do WhatsApp. Agora, ao desligar, o sistema desconecta o aparelho
de verdade e só então marca como desligado; se a desconexão falhar, ele avisa e mantém tudo
como estava, em vez de dizer que acabou com o aparelho ainda lá.No servidor, o serviço de chamada de voz também nasce desligado: ele só é criado quando quem
administra a instalação o liga no arquivo de configuração. Quem não usar a chamada de voz não
paga por ela — nem em memória da VPS, nem em superfície exposta. O serviço usado é o oficial
do projeto WaCalls, fixado por versão exata e com login obrigatório; ele não é acessível pela
internet, apenas pelo próprio sistema.Trabalho original de @eudanielhenrique.
-
Os e-mails de acesso passam a funcionar (e a ter marca) num Supabase próprio Quem roda Supabase self-hosted ganha o que só existia na nuvem: e-mail de confirmação de conta e de redefinição de senha com a marca da instalação, e — o que importa mais — com o link que fecha a sessão.
O app passa a servir os dois moldes em
/email-templates/confirmatione/email-templates/recovery. Aponte o GoTrue para eles:GOTRUE_MAILER_TEMPLATES_CONFIRMATION=https://SEU_DOMINIO/email-templates/confirmation GOTRUE_MAILER_TEMPLATES_RECOVERY=https://SEU_DOMINIO/email-templates/recovery GOTRUE_MAILER_SUBJECTS_CONFIRMATION="Confirme seu e-mail · SUA MARCA" GOTRUE_MAILER_SUBJECTS_RECOVERY="Redefinir sua senha · SUA MARCA"
Nada muda para quem não apontar, e nada muda na nuvem do Supabase — lá o caminho continua sendo o
marca-emails.shpela Management API.O kit ensina e confere, mas não escreve — e o motivo é honesto. O GoTrue não é serviço deste compose: o kit sobe
app,worker,scheduler,waha,redis,srhecaddy, e o Supabase próprio é outra stack, que pode nem estar na mesma máquina. Escrever nela seria o instalador editar instalação de terceiro. Então oinstall.shpassa a imprimir as quatro linhas exatas quando a topologia é própria (antes ele mandava o self-hoster parasupabase.com/dashboard, que ele não tem), ebash hostgator-setup-kit/healthcheck.shganhou uma seção que mede o estado: se o app serve o molde, se algum GoTrue desta máquina aponta para ele, e se o valor configurado é URL — acusando em vermelho o caminho de arquivo que falha calado.Por que isso conserta e não só embeleza. O modelo padrão do GoTrue linka para
/auth/v1/verify, que devolve umcodePKCE. O verificador desse code vive num cookieSameSite=Strict, e clique vindo de webmail é navegação cross-site: o cookie não viaja e a sessão nunca fecha. A conta é confirmada, a pessoa entra pela senha, e fica sem organização e sem menu. Os moldes do app linkam comtoken_hash, que não depende de cookie nenhum.A marca passa a seguir o banco. O
marca-emails.shlê o.env, então trocar nome ou cor em Configurações › Marca não reescrevia os e-mails de acesso. Servindo pelo app, a marca é resolvida a cada busca e o GoTrue re-busca sozinho a cada 10 minutos (GOTRUE_MAILER_TEMPLATE_MAX_AGE) — sem reiniciar nada e sem rodar script.Se você seguiu a receita antiga, troque as variáveis. Até esta versão,
docs/deploy-selfhost/README.mde omarca-emails.shmandavam apontarGOTRUE_MAILER_TEMPLATES_*para um caminho de arquivo. Isso não funciona e falha calado: o GoTrue cola o que não começa comhttpno fim doSITE_URLe faz um GET, então ele buscahttps://SEU_DOMINIO/opt/.../confirmation.html, recebe o HTML da tela de login e manda isso para a caixa de entrada do cliente. Medido em 2026-09-09; o Gmail marcou como phishing.Achado instalando numa VPS com Supabase próprio, seguindo a documentação do produto do começo ao fim.
-
Guias do assistente para quem instala, opera e contribui com um CLI de IA Com o repositório aberto no Claude Code, Codex, Cursor, OpenCode ou Antigravity, cinco guias carregam sozinhos na hora certa: instalar e consertar a instalação, montar um cliente por nicho (agentes, roteadores, follow-ups, base de conhecimento), analisar as métricas sem expor dado pessoal, afinar o prompt de um agente com dados, e contribuir com um PR que passa na triagem de primeira. O roteiro do kit de instalação foi corrigido (a verificação em duas etapas é opcional; três provedores de IA; token do Supabase) e o banner final do instalador passa a refletir a escolha de telemetria.
-
Chamada de voz pelo WhatsApp — ligar e atender de dentro do CRM O CRM passa a fazer e receber ligações de voz pelo WhatsApp. Quem administra pareia um
segundo aparelho no mesmo número, em Configurações › Conexões, e o botão Chamar
aparece na ficha de todo contato com telefone. Chamada recebida toca para o time inteiro,
como um telefone de escritório; o painel da ligação em andamento, com mudo e desligar, é só
de quem está na linha.O que o sistema faz por conta própria enquanto isso acontece:
- O assistente se cala durante a ligação naquela conversa e volta a falar quando você
desliga. Ele não responde por cima de alguém que está ao telefone com o cliente. - Ligação atendida conta como contato feito. O negócio deixa de aparecer como parado no
Radar de Risco, e o assistente para de propor "retomar contato" com quem você acabou de
atender. - Ligação atendida conta como trabalho seu no relatório de atendentes.
- Chamada perdida vira aviso na Central, com o número de quem ligou, o motivo em
português e um botão para ligar de volta. - A linha do tempo do negócio diz quem atendeu, não "Sistema".
Três recusas deliberadas, porque o certo é não fazer:
- Contato que pediu para não ser incomodado não recebe ligação. Quem mandou "PARAR" já
não recebia mensagem; agora também não recebe telefonema. - Só quem está na linha desliga. Ninguém derruba a ligação de um colega.
- Apagar o canal não apaga o histórico de ligações — a exclusão vira arquivamento, e o
diálogo diz quantas chamadas estão penduradas antes de você confirmar.
Quem exercer o direito de ser esquecido tem o telefone das chamadas apagado junto com o
resto; quem pedir seus dados recebe o registro das ligações no relatório.Nada muda para quem não parear o recurso: ele é opcional e nasce desligado.
Trabalho original de @eudanielhenrique.
- O assistente se cala durante a ligação naquela conversa e volta a falar quando você
Alterado
-
A marca do produto ganha símbolo e logotipo Instalação que não configurou marca própria passa a mostrar o logotipo do
Deskcomm no menu lateral, na tela de entrada e no ícone da aba do navegador —
no lugar do nome em texto e da letra "D" sobre a cor de destaque. Quem já
definiu nome ou logo próprio em Marca não vê nenhuma diferença: a marca
configurada continua valendo em todos esses lugares. -
No editor de follow-up, dá para organizar o fluxo e excluir um nó ou uma aresta Montar um follow-up no canvas exigia arrastar cada bloco à mão, e o único botão de
apagar era o do fluxo inteiro. Quem errava uma ligação tinha que desfazer o rascunho
ou começar de novo.Agora, no editor, Organizar empilha o fluxo conectado de cima para baixo;
Excluir nó e Excluir aresta saem no painel do item selecionado e na barra de
cima — sem apagar o fluxo. As ligações passam a ser em degrau (não diagonais por
cima dos blocos), e os botões de zoom do canvas seguem o tema escuro em vez de
sumirem no fundo branco da biblioteca.
Corrigido
-
Webhook de captação agora reconhece o formato de lead do RD Station Ao apontar um webhook do RD Station para uma fonte de captação de leads, os
envios reais não viravam lead: o RD Station empacota os dados dentro de uma
lista (leads: [...]), e o leitor de campos do webhook só olhava o nível de
cima, então nome, e-mail e telefone chegavam "em branco" e a captação era
recusada. O botão interno "Enviar lead de teste" funcionava porque manda os
campos soltos — o que escondia o problema.Agora o webhook reconhece esse formato: extrai o nome, o e-mail e o telefone
(inclusive quando o telefone vem no campo de celular do RD, e não no campo de
telefone comercial, que costuma vir vazio) e cria o lead na fonte/funil/etapa
configurados. Reenvio do mesmo evento pelo RD Station não gera lead duplicado.Os formatos que já funcionavam (campos soltos, Respondi) continuam iguais. Você
não precisa fazer nada para adotar — a partir desta versão os leads do RD
Station passam a entrar sozinhos. -
Preferências de aviso param de divergir entre o servidor e o navegador A tela de configurações de notificação abria com o navegador discordando do HTML que o servidor tinha mandado. Quem havia desligado o push de mensagem via, por um instante, o interruptor ligado — e o React reagia a essa discordância descartando e refazendo a árvore da tela no cliente.
O valor era lido dentro do inicializador de
useState, que roda de novo na hidratação. Semwindow, essa leitura devolve o padrão (tudo ligado); comwindow, devolve o que está nolocalStorage. Os dois lados não tinham como concordar para quem tivesse mudado qualquer preferência — em dez interruptores e no identificador que a tela de alertas procura.A tela passou a ler as preferências por
useSyncExternalStore, o mesmo mecanismo que o seletor de tema já usa desde o #666: existe um valor determinístico para a comparação de hidratação, e só depois do commit o React troca para o valor real. O interruptor continua respondendo na hora, sem recarregar a página.Sem mudança de configuração: nada a editar no
.enve nenhum passo a mais na atualização.Achado a partir do relato de que a divergência reaparecia a cada conserto — a leitura do navegador voltava para dentro de um inicializador novo. Junto vem a guarda que reprova esse padrão, para que a terceira instância não nasça igual.
-
Quem é convidado entra na empresa ao confirmar o e-mail, sem mais um clique Confirmar o e-mail vindo de um convite passa a criar o vínculo e abrir o CRM já dentro da empresa. Antes, a confirmação levava a uma tela com um botão "Aceitar convite" — e quem não o apertava terminava autenticado, sem organização e sem menu, num CRM vazio.
Três consertos, todos no ciclo de vida do vínculo:
- O convite é aceito na própria confirmação. A rota já sabia tudo o que o botão exigia, e com garantia mais forte: o e-mail do convite é comparado com o que o provedor de autenticação acabou de confirmar. Se o vínculo falhar (convite revogado, banco fora), a tela de aceite continua existindo e recebe a pessoa — nada fica sem saída.
- Clicar duas vezes no link do e-mail não desloga mais ninguém. O token é de uso único: o segundo clique falhava e mandava para a tela de login quem já estava logado pelo primeiro, com o cookie de sessão intacto. A pessoa reentrava pela senha e perdia o fio do convite. Agora a rota reconhece a sessão que já existe e segue.
- Acesso revogado deixa de virar convite para abrir empresa. Quem tinha o vínculo retirado caía numa tela vazia oferecendo "Configure sua organização" — uma revogação virando criação de tenant. Agora vê uma tela que nomeia o que aconteceu, e a ação de recuperação recusa com o motivo certo, em vez da mensagem sobre convite pendente que aparecia por acaso.
Nada muda na configuração: não há variável nova, passo de atualização nem mudança de schema.
Achado instalando numa VPS com Supabase self-hosted, com dois convidados reais que não conseguiram entrar.
-
Conectar um número de WhatsApp voltou a funcionar Conectar um número de WhatsApp novo — no onboarding ou pela Central de Conexões — e reconectar
um número que caiu falhavam com "Falha na comunicação com o WhatsApp (WAHA)" (waha_create_400),
e o canal ficava preso em "Parado" pedindo reparo.A causa: o identificador interno que o sistema gera para a sessão no WAHA tinha 69 caracteres, e
a versão do WAHA que o kit usa recusa identificadores com mais de 54 — então nenhuma sessão nova
chegava a ser criada do outro lado. O identificador passou a ter 45 caracteres.Canais que já ficaram presos por causa disso são consertados na atualização (o identificador é
regravado no formato novo); nenhum número já pareado é tocado. Depois de atualizar, quem estava
travado é só clicar em Conectar/Reconectar de novo. -
Revogar um membro deixa de ser uma porta que só abre por fora Revogar sumia com a pessoa. Ela desaparecia da lista de Equipe, e a única forma de devolver o acesso era emitir um convite novo — um caminho longo, com três becos, todos medidos numa instalação real com alguém de verdade preso neles.
O que muda:
- O membro revogado continua na lista, com o estado
Revogado, e quem administra devolve o acesso pelo menu da própria linha. Antes ele simplesmente sumia. - Quem já tem conta e clica num convite deixa de receber "Não foi possível criar a conta. Tente novamente." — instrução impossível, porque tentar de novo nunca funciona. Passa a ler que já tem conta, com um botão que entra e cai direto no aceite.
- A tela de acesso revogado deixa de ser beco: ela diz que, se chegou convite novo, o link do e-mail funciona mesmo dali.
Nada disso mudou o banco. O comando que aceita convite já sabia reativar quem foi revogado, desde que o convite seja posterior à revogação — e foi exatamente isso que a prova em tela confirmou. O que faltava era caminho até ele.
Reativar não promove. Ela devolve o papel que a pessoa tinha; trocar papel continua sendo outra ação, com outra rota. Juntar as duas faria uma reativação distraída virar promoção silenciosa.
Quem devolveu o acesso fica registrado (
member.reactivated). A coluna que guarda a revogação volta a ficar vazia e não conta história nenhuma — a trilha é a única resposta para "quem readmitiu esta pessoa, e quando?". - O membro revogado continua na lista, com o estado
-
Uma requisição que demora demais não vira mais um erro genérico na tela Quando uma chamada à API não respondia a tempo, o navegador mostrava um erro genérico ("signal is aborted without reason") em vez de dizer que foi um tempo esgotado. Agora o motivo do cancelamento vem explícito, com o mesmo nome que o resto do produto já usa para timeout — quem lida com o erro consegue reconhecê-lo, e quem só vê a tela entende o que aconteceu.
-
A chamada de voz avisa quando não há áudio, em vez de contar o tempo em silêncio O painel da ligação em andamento mostrava o cronômetro correndo assim que o WhatsApp
atendia — e o cronômetro continuava correndo mesmo quando o som não chegava ao navegador.
Uma ligação muda tinha exatamente a mesma aparência de uma ligação perfeita: nenhum aviso,
nenhum sinal, só o relógio. Quem instalou numa VPS ficava sem saber se o problema era o
microfone, a rede do escritório ou o produto.Agora o painel escuta a conexão de áudio de verdade. Enquanto ela está abrindo, ele diz
"Abrindo o áudio…". Se ela não abrir, ele diz "Sem áudio: o canal de voz não abriu"
— e o cronômetro continua, porque a ligação existe mesmo e o outro lado está esperando. O
silêncio deixa de se disfarçar de normalidade.Se o servidor de voz demorar demais para responder, o aviso aparece em até 12 segundos, em
vez de "Abrindo o áudio…" para sempre. E se a conexão se restabelecer depois de um soluço
de rede, o aviso some sozinho.Nada muda para quem não usa chamada de voz.
Trabalho original da chamada de voz de @eudanielhenrique.
-
O laço rápido do worker volta a montar o admin client
@react-pdf/hyphenateé ESM puro e não expunha a condiçãorequireno seuexports. Como o worker roda viatsx(CommonJS), qualquer import de@react-pdf/renderer(usado pela exportação de dados LGPD) derrubavacarregarDeps()do drain loop comERR_PACKAGE_PATH_NOT_EXPORTED— e comoregister-handlers.tsregistra os 12 handlers doevent_lognum só import chain, isso tirava o laço rápido de TODOS eles, não só do LGPD, caindo pro cron de 1×/min como única rede de segurança.Patch (
patches/@react-pdf__hyphenate.patch) acrescenta a condiçãorequireao exports map — Node 22.12+/24 já sabe carregar ESM viarequire()quando o mapa permite. Provado no worker real: o warning "event-log drain OFF" some do log de boot.