Added1
O canal oficial pode apontar para um servidor de testes próprio
Quem opera a instalação pode, pela primeira vez, mandar o canal oficial do WhatsApp falar com um servidor diferente do da Meta, definindo META_GRAPH_BASE_URL no ambiente. Sem essa variável, nada muda: o sistema continua enviando, validando credenciais, baixando mídia, sincronizando modelos e registrando webhook exatamente para onde mandava.
O que se abre com ela é a PROVA EM TELA do canal oficial. Até aqui não havia para onde a instalação falar durante um teste de ponta a ponta, porque o endereço do provedor estava escrito dentro do código, em onze lugares: a jornada de conectar e enviar era coberta só por testes de unidade, que provam a lógica e não a conversa de verdade com o outro lado. Com a variável apontando para um servidor local, a mesma jornada passa a poder ser exercitada na tela, contra um destino que responde. A conta de anúncios tem a sua própria variável, META_ADS_GRAPH_BASE_URL, justamente para que apontar o canal para o servidor de testes não leve junto o relatório de conversão.
Dois cuidados escritos na própria configuração: o endereço precisa ser uma base http:// ou https:// de verdade (endereço colado sem esquema, ftp://, file:// ou caminho relativo é recusado, com aviso no log, e a instalação volta a falar com o endereço de sempre), e ele é decisão da instalação inteira — não existe campo na tela nem valor por organização, porque destino de chamada definido por tenant mandaria o token de uma empresa por um servidor escolhido pela outra.
Crédito: @webtecnica (#817).
Contribuição de @webtecnica (#1787, issue #817).
Changed2
Os 12 HANDOFF da raiz foram para docs/handoffs/ e um gate impede a volta
Os arquivos HANDOFF*.md de épico saíram da raiz do repositório para docs/handoffs/, com índice em docs/handoffs/README.md, e um teste impede que voltem. A regra antiga ("épico vivo mantém o handoff na raiz") saiu do docs/index.md: item de doutrina envelhece, teste reprova.
Nada muda para quem opera a instalação.
Contribuição de @webtecnica (#1771).
O caso de aceite que passa pelo agente agora mede o par
A doutrina mandava provar pela tela, e era o que ela cobrava. Só que um caso de aceite que atravessa um agente de IA não se prova com o verde do agente: em setembro, na validação da v1.12.0, o caso "quero 2 iphone 15" passou por uma bateria que o esperava reprovar — o agente perguntou se era o 128 ou o 256 — e a ferramenta, medida direto com o mesmo texto, devolvia zero. O verde media o modelo, não a ferramenta.
Agora todo caso de aceite que atravessa o agente vem em par com a medição direta da ferramenta, com o mesmo texto cru, e só conta como prova quando os dois lados concordam. A regra está escrita nos guias de aceite, no pré-voo e no checklist da triagem, e um teste impede que ela suma sem ninguém ver.
Nada muda para quem opera a VPS: nenhuma tela, nenhum dado e nenhuma variável de ambiente foi tocada.
Contribuição de @webtecnica (#1781, issue #489).
Fixed7
A fila de remoção de mídia avisa quantas linhas ela expurgou
O cron diário de retenção de mídia deixa de apagar a fila em silêncio. Ele já expurgava as linhas de mídia que saíram do bucket havia mais de 90 dias — o que impedia a fila de crescer sem teto — mas não dizia quantas: a contagem saía só da função interna, não chegava nem no registro de auditoria nem na resposta do cron. Agora quem administra o sistema vê, na trilha de auditoria e no retorno da rotina, quantas linhas da fila saíram na rodada, inclusive nas rodadas em que o expurgo foi a única coisa que aconteceu. Nada a fazer para quem já roda o sistema: é contabilidade, não mudança de comportamento do que é removido.
Contribuição de @webtecnica (#1777, issue #1765).
A prova de tela passa a ser versionada junto com o repositório
A documentação de QA mandava gravar a evidência visual (screenshots e traces de Playwright) numa pasta que o .gitignore ignorava. A prova ficava só no computador de quem rodou o teste: quem clonasse o repositório recebia o mapa de jornadas apontando para imagens que não existiam, e nenhuma imagem aparecia.
Agora as specs gravam na pasta evidence/, que é versionada — quem clona recebe a prova. Um teste novo impede que a documentação volte a mandar gravar fora do versionamento.
Nada muda para quem opera a VPS: nenhuma tela, nenhum dado e nenhuma variável de ambiente foi tocada.
Contribuição de @webtecnica (#1770, issue #533).
Quem já tinha o DeskcommCRM rodando em ARM (VPS aarch64) volta a conseguir atualizar
Quem já tinha o DeskcommCRM instalado numa VPS ARM (Oracle Ampere, aarch64) volta a conseguir rodar update.sh. Desde a v1.35.0 a atualização era recusada logo na primeira linha, dizendo que só existe VPS x86_64, mesmo onde o CRM já estava funcionando. Agora, onde já existe instalação, a recusa vira um aviso e as imagens da versão nova são construídas na própria VPS (leva de 15 a 25 minutos a mais).
A instalação NOVA continua recusada: quem ainda não instalou precisa de uma VPS x86_64, como antes.
Se a sua VPS ARM está numa versão anterior à v1.35.0, a atualização normal já traz este conserto. Se ela já está na v1.35.0 ou mais nova e a atualização vinha sendo recusada, o update.sh que está no disco é o antigo e continua recusando, tanto no terminal quanto no botão "Atualizar". Para sair, rode uma vez na pasta do CRM, trocando vX.Y.Z pelo número desta versão:
git fetch --tags origin
git checkout vX.Y.Z
bash hostgator-setup-kit/update.sh --to vX.Y.Z --forceDepois disso as atualizações seguintes voltam a rodar sozinhas.
Contribuição de @webtecnica (#1775).
Instalar pela primeira vez numa VPS ARM volta a ser recusado, mesmo com o .env já preenchido
Se você começou a instalar o DeskcommCRM numa VPS ARM (Oracle Ampere, aarch64) com o .env já preenchido — copiado de outra máquina, gerado por automação, ou deixado por uma instalação que parou no meio —, o install.sh não recusava como devia: confundia a pasta com uma instalação que já estava no ar e passava 15 a 25 minutos construindo as imagens na própria VPS. Agora ele recusa logo no começo e orienta a usar uma VPS x86_64/amd64.
A instalação passa a ser reconhecida pelo que ela deixou de verdade: os contêineres do DeskcommCRM (ou do seu Supabase) no Docker, parados ou rodando, ou o arquivo .deskcomm-instalado que o próprio instalador grava quando termina. Quem já tem o CRM numa VPS ARM continua atualizando normalmente, com o aviso e o build local de sempre. Para quem instalou antes desta versão e ainda não tem o arquivo, o update.sh desta versão em diante o grava sempre que termina com o app no ar. Se nessa VPS ARM você derrubou os contêineres (docker compose down sem -v) antes de atualizar, suba-os de novo com docker compose ... up -d e rode a atualização.
Se você usa o comando de "recomeçar" (docker compose down -v && rm -f .env), ele passou a apagar esse arquivo junto — ele faz parte do estado da instalação.
Contribuição de @webtecnica (#1783, issue #1778).
A poda do arquivo de webhooks passa a ordenar o lote e a dizer quando falha
A limpeza automática do arquivo de webhooks passou a apagar em lotes ordenados (pelo identificador, do mais antigo ao mais novo — a mesma ordem que a limpeza do histórico de captação já usa) e a falha do banco deixou de ser engolida: ela sobe, responde 500, grava a linha falhou na trilha e chega ao Sentry — em vez de virar um "não havia nada para apagar" que não era verdade.
A ordem não é enfeite. O banco de dados usado nas instalações novas recusa apagar um lote sem ordem definida, e nenhuma linha do arquivo era removida — com o arquivo sendo 468 MB de um banco de 545 MB medido numa instalação real, crescendo ~23 MB/dia contra o teto de 500 MB do plano gratuito. Onde a limpeza funcionava, a ordem torna o ritmo de esvaziamento reproduzível: hoje ela apaga sempre as mesmas linhas mais antigas primeiro.
Sem ação para quem opera: as duas tabelas, os dois prazos e o tamanho do lote são os mesmos. O efeito é que uma instalação em que o banco recusa a limpeza passa a ser vista — na trilha e no Sentry — em vez de acumular arquivo em silêncio.
Contribuição de @webtecnica (#1784, issue #1769).
A poda do histórico de captação passa a ordenar o lote e a dizer quando falha
A retenção do histórico de leads captados passou a apagar em lotes ordenados (id ascendente, a mesma coluna e a mesma direção da poda de rascunhos), e a falha do banco deixou de ser engolida: ela sobe, responde 500, grava a linha falhou na trilha e chega ao Sentry — em vez de virar um "não havia nada vencido" que não era verdade.
Sem ação para quem opera: as duas tabelas e os dois horizontes são os mesmos. O efeito é que a poda deixa de poder escolher um subconjunto arbitrário a cada lote, e uma instalação em que o banco recusa o DELETE passa a ser vista.
Contribuição de @webtecnica (#1768, issue #1721).
Voltar e avançar numa spec e2e também esperam a revelação da página
A suíte de e2e passa a esperar o streaming SSR terminar de revelar a página também depois de voltar (goBack) e avançar (goForward), como carregar e recarregar já esperavam desde o #1706; uma spec que volta a uma tela deixa de poder achar a cópia escondida da revelação e reprovar sozinha.
Nada a fazer para quem já roda o sistema: a mudança é na suíte de testes, e o aplicativo se comporta exatamente como antes.
Contribuição de @webtecnica (#1782, issue #884).