Skip to content

Commit 7569b2a

Browse files
committed
Merge remote-tracking branch 'origin/main' into tri-w538
2 parents 245d34a + 0d28c0d commit 7569b2a

101 files changed

Lines changed: 9833 additions & 361 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
impacto: nada_mudou
3+
secao: corrigido
4+
titulo: A chave da OpenRouter passa a ser conferida de verdade antes de a tela dizer que está validada
5+
---
6+
7+
Ao cadastrar uma chave da OpenRouter em **Agente de IA › Credenciais**, o sistema conferia
8+
a chave contra o catálogo de modelos do provedor — um endereço que responde a
9+
qualquer um, com chave errada ou sem chave nenhuma. Na prática, qualquer texto
10+
colado ali era gravado como credencial validada, e o cartão passava a mostrar
11+
"Validada" com o final da chave ao lado.
12+
13+
O erro só aparecia depois, na primeira mensagem que o agente tentava responder,
14+
e aparecia como "User not found." — um texto que não fala em chave nem em
15+
credencial. Quem procurava a causa olhava o modelo, o provedor, o próprio
16+
atendimento; a tela, enquanto isso, afirmava que a peça quebrada estava boa.
17+
18+
Agora a prova é feita contra o endereço que exige a credencial. O catálogo
19+
continua sendo lido em seguida, porque é dele que sai a lista de modelos que a
20+
tela mostra — ali ele é dado, não prova. E catálogo fora do ar não recusa mais
21+
uma chave que já provou ser válida: seria trocar um erro de credencial por um de
22+
indisponibilidade, e mandar quem opera caçar defeito na chave certa.
23+
24+
Uma ressalva sobre em que versão isto entrou: a correção já está no ar desde a
25+
**1.13.0**. O que chega atrasado é esta nota — a mudança foi publicada sem ela,
26+
e por isso não apareceu na lista daquela versão.
27+
28+
Chave boa continua sendo aceita do mesmo jeito, e não há passo de atualização.
29+
A única coisa que vale conferir é o que foi cadastrado antes: se a sua chave da
30+
OpenRouter é anterior à 1.13.0 e o atendimento falha sem motivo aparente, abra
31+
**Agente de IA › Credenciais** e use o botão de revalidar — as setas em círculo, no
32+
cartão da credencial. A resposta que ele dá agora é real.
33+
34+
Isto veio da contribuição de **@Elevstudio-Dev**.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
impacto: nada_mudou
3+
secao: corrigido
4+
titulo: A troca de senha pela linha de comando volta a encontrar o usuário
5+
---
6+
7+
Quem perde o acesso a uma instalação sem SMTP — o estado normal de um self-host
8+
recém-instalado — só tem um caminho de volta: o `reset-password.sh` do kit. Ele
9+
não funcionava para **ninguém**. Não era intermitente nem dependia do e-mail:
10+
qualquer endereço, existente ou não, recebia a mesma resposta seca de "usuário
11+
não encontrado", e a pessoa ficava trancada do lado de fora do próprio sistema.
12+
13+
A causa era uma consulta escrita na sintaxe errada. O script pedia ao servidor de
14+
autenticação um filtro no formato do banco (`email.eq.<endereço>`), e esse
15+
servidor não fala esse formato — ele usa a expressão inteira como texto de busca.
16+
Como nenhum e-mail contém o pedaço `email.eq.`, a busca não achava nada, sempre.
17+
18+
Agora a consulta vai no formato que o servidor entende. E, como a busca dele é por
19+
trecho do endereço, o script passou a exigir o e-mail **inteiro** antes de aceitar
20+
o resultado: pedir `ana@empresa.com` também traz `mariana@empresa.com`, e entregar
21+
a pessoa errada a um comando que TROCA SENHA seria pior que não achar ninguém. Na
22+
dúvida ele não devolve nada — quem chama vê "não encontrado", que é ruim mas se
23+
resolve; a senha de outra pessoa trocada, não.
24+
25+
Quem opera uma VPS não precisa fazer nada além de atualizar. Nenhuma configuração
26+
muda, nenhum arquivo precisa ser editado à mão.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
impacto: nada_mudou
3+
secao: corrigido
4+
titulo: Anonimizar um contato retoma de onde parou, em vez de dizer que já foi
5+
---
6+
7+
A anonimização de um contato remove os dados pessoais em três lugares: o
8+
cadastro do contato, os títulos dos negócios dele e o histórico de atividades.
9+
Se a operação era interrompida no meio — o navegador desistindo, o servidor
10+
reiniciando —, o primeiro lugar ficava pronto e os outros dois não.
11+
12+
E não havia como terminar: clicar em "Anonimizar" de novo respondia **"já anonimizado"**
13+
e não fazia mais nada. O contato ficava para sempre com nome de
14+
cliente visível dentro dos negócios e do histórico — que é exatamente o dado que
15+
a anonimização existe para remover, e que a lei dá prazo para remover.
16+
17+
Pior: nesse estado a tela **não mostra botão nenhum** — assim que o contato
18+
consta como anonimizado, o botão dá lugar a um aviso. Não havia como pedir a
19+
retomada nem sabendo que ela era necessária.
20+
21+
Agora a verificação diária do sistema encontra sozinha as anonimizações que
22+
ficaram pela metade e termina o serviço, sem ninguém precisar procurar contato
23+
por contato. Como a lei dá prazo, esse conserto não podia depender de alguém
24+
lembrar de clicar. Rodar de novo num contato já inteiro não escreve nada, e o
25+
registro de auditoria mostra o que foi realmente feito, em qual contato e em que
26+
dia — separado da execução original, para a data em que o titular exerceu o
27+
direito não ser sobrescrita.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
impacto: capacidade_nova
3+
secao: adicionado
4+
titulo: A IA pode ser limitada a atender só leads de origem conhecida
5+
---
6+
7+
Num número de WhatsApp que também é usado para falar com clientes, fornecedores
8+
e contatos pessoais, a IA respondia todo mundo assim que um agente era
9+
publicado. Agora dá para ligar, por canal, o modo "só atende quem eu autorizei":
10+
a IA fica em silêncio por padrão e só assume a conversa quando o lead veio de
11+
uma origem elegível — uma submissão nova de formulário, uma campanha
12+
identificada, ou uma liberação manual pela tela. Histórico antigo, existência do
13+
contato, conversa anterior ou reinício de um worker nunca autorizam sozinhos.
14+
15+
Esse limite vale para TODOS os caminhos de resposta automática — o motor do
16+
agente, o follow-up, o texto fixo de fluxo, o worker de resposta legado e a
17+
passagem para humano por sentimento. Não há atalho: nenhum deles envia mensagem
18+
de IA para uma conversa não autorizada.
19+
20+
Além disso, e independentemente desse modo: quando você responde um cliente à
21+
mão pelo próprio WhatsApp (celular, ou outra plataforma na mesma conta), a IA
22+
para naquela conversa para não responder junto.
23+
**Essa pausa dura uma hora, e se renova a cada mensagem sua.**
24+
Enquanto você estiver atendendo, a IA continua calada; quando você para, a hora
25+
corre e ela volta a atender aquela conversa sozinha. Você não precisa lembrar de
26+
religar nada.
27+
28+
Se quiser a IA de volta antes da hora, é o botão "devolver ao automático" na
29+
conversa. E se quiser que ela fique parada por tempo indeterminado, é o mesmo de
30+
sempre: assumir a conversa pela tela — aí ela só volta quando você devolver.
31+
Nenhuma dessas coisas apaga a origem do lead.
32+
33+
Quem não ligar o modo "só atende quem eu autorizei" mantém o comportamento de
34+
antes para todo o resto.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
impacto: nada_mudou
3+
secao: corrigido
4+
titulo: A proteção de envio volta a aceitar a data de hoje
5+
---
6+
7+
Em **Conexões › Proteção de envio**, informar hoje em "este número é usado
8+
desde" era recusado durante a manhã inteira: até as 9h no relógio de quem
9+
opera no Brasil, salvar devolvia *"Campos inválidos."* e não gravava nada — nem
10+
a janela de horário, nem o intervalo entre envios, nem o teto diário que você
11+
tinha acabado de mudar na mesma tela.
12+
13+
O motivo: o campo pergunta um DIA, mas a verificação o comparava com a hora
14+
exata em Londres. Um dia não tem hora — ele começa em horários diferentes em
15+
cada parte do mundo —, e por isso "hoje" só era aceito depois do meio-dia
16+
londrino. Agora a verificação compara dias com dias, e só recusa a data que
17+
ainda não chegou em canto nenhum do planeta.
18+
19+
O calendário do campo também parou de oferecer o dia errado: depois das 21h ele
20+
mostrava amanhã como escolha possível.
21+
22+
Data futura continua recusada, e data antiga continua sendo o caso normal — é
23+
informando a data antiga que um número usado há meses deixa de ser tratado como
24+
recém-criado e sai do teto de 20 envios por dia.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
impacto: nada_mudou
3+
secao: corrigido
4+
titulo: Salvar o rascunho de um agente para de escrever por cima de um rascunho antigo
5+
---
6+
7+
Na tela de um agente, "Salvar rascunho" podia gravar numa versão **diferente**
8+
da que estava aberta na tela — e apagar, no caminho, um rascunho antigo que a
9+
própria tela prometia estar guardado.
10+
11+
O estado que produzia isso é comum e tem um gatilho conhecido: quem tinha
12+
trabalho em andamento num rascunho e usou o botão **Reverter**, na aba
13+
Histórico. Reverter cria uma versão nova e a publica na hora; o rascunho que
14+
existia fica, a partir dali, "atrás" da versão publicada. A tela sabe disso e
15+
avisa, no selo ao lado do nome do agente: *"o rascunho v5 é anterior a esta
16+
versão e foi superado por ela — ele continua no Histórico."*
17+
18+
Só que o servidor não sabia. Ele procurava "o rascunho de maior número" e
19+
gravava ali. Duas consequências, nenhuma delas com mensagem de erro:
20+
21+
- **O trabalho parecia sumir.** O aviso verde dizia "Rascunho v5 salvo.", a
22+
página recarregava, e a tela voltava a mostrar o texto anterior — porque ela
23+
não reabre um rascunho superado, e o botão de publicar também não o oferece.
24+
Quem estava editando via "salvo" e nada mudando, sem ter o que fazer a
25+
respeito.
26+
- **O Histórico perdia conteúdo, em silêncio.** Aquele rascunho v5 é um
27+
retrato: a linha dele no Histórico existe para mostrar o que estava escrito
28+
ali. Regravá-lo trocava esse conteúdo por um texto que ninguém rascunhou
29+
naquele momento, sem aviso e sem volta.
30+
31+
Agora o servidor decide em qual versão escrever pela **mesma regra** que a tela
32+
usa para decidir qual versão abrir. Quando o rascunho existente está superado,
33+
a gravação nasce numa versão nova — que é a que a tela reabre e o botão publica
34+
— e o rascunho antigo fica intacto no Histórico, como estava prometido.
35+
36+
Junto vem um cuidado que não aparece na tela mas decide o resultado: quem é a
37+
versão publicada passa a ser sempre o **ponteiro que o atendimento executa**, e
38+
não o rótulo "publicada" gravado na linha da versão. Os dois já se contradizem
39+
em instalações reais, e a resposta otimista era a errada.
40+
41+
Para quem opera uma instalação, nada muda no dia a dia: nenhuma configuração
42+
nova, nenhum passo de atualização, nenhuma mudança no banco. O que muda é que
43+
"salvei" volta a significar "está salvo onde você está vendo".
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
impacto: nada_mudou
3+
secao: corrigido
4+
titulo: Os e-mails de acesso deixam de apontar para um endereço que não existe
5+
---
6+
7+
Numa instalação feita pelo caminho documentado, os e-mails de recuperação de
8+
senha, de confirmação de cadastro e de aceite de convite chegavam com um link
9+
para `localhost:3000` — um endereço que só existe na máquina de quem programa.
10+
O e-mail chegava, a pessoa clicava, e o navegador dizia que a página não existe.
11+
Na prática, **ninguém conseguia redefinir a própria senha.**
12+
13+
O endereço certo mora no painel do Supabase, e o instalador já sabia configurá-lo
14+
sozinho — só que precisava de um token que ele nunca pedia. O aviso existia, mas
15+
saía no meio de um registro de dez minutos, logo antes de uma tela verde dizendo
16+
"Instalação concluída". Ninguém voltava para ler.
17+
18+
Agora o instalador pergunta esse token. Ele é opcional e **não fica salvo**
19+
abre a conta inteira do Supabase, então é usado uma vez e descartado, e nem
20+
sequer entra no rascunho que guarda suas respostas para o caso de a instalação
21+
ser interrompida. Por isso, se você recomeçar uma instalação, ele é a única
22+
pergunta que volta a ser feita; a tela diz isso na hora, e apertar Enter pula.
23+
24+
Quem preferir pular continua podendo: a instalação termina repetindo o passo que
25+
falta, com o seu domínio já preenchido, em vez de deixar a descoberta para o dia
26+
em que alguém esquecer a senha. E quando o passo automático roda mas o endereço
27+
não fica como este sistema precisa — porque o seu projeto já tinha outro
28+
endereço escolhido, por exemplo —, ele passou a dizer isso em vez de terminar
29+
com um "pronto" verde.
30+
31+
**Se você já tinha instalado antes desta versão**, a próxima atualização mostra
32+
esse mesmo passo uma vez, com o seu domínio preenchido, e não repete depois.

.env.example

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,15 @@ AI_BUDGET_ENFORCEMENT=on
152152
EVENT_LOG_DRAIN_INTERVAL_MS=2000
153153
EVENT_LOG_DRAIN_IDLE_INTERVAL_MS=10000
154154
EVENT_LOG_DRAIN_BATCH_SIZE=50
155+
156+
# --- Elegibilidade da IA por origem do lead ----------------------------------
157+
# Vale SÓ nos canais em que você ligou o modo "só atende quem eu autorizei"
158+
# (Configurações do canal › ai_gate = allowlist). Nesses canais, um contato fica
159+
# elegível para a IA quando vem de uma origem conhecida (formulário do Respondi,
160+
# campanha, liberação manual). Este número é por quantos DIAS essa autorização
161+
# vale — depois disso, uma submissão antiga não reativa a IA sozinha. Uma
162+
# conversa que segue viva renova o prazo a cada turno. Vazio = 21 dias.
163+
AI_ALLOWLIST_TTL_DAYS=21
155164
# Stub do endpoint de teste do agente: 'true' devolve trace fabricado em vez de
156165
# executar o agente. Deixe false — o runtime real já existe. Só ligue para
157166
# exercitar o render da UI sem gastar token.

.github/workflows/e2e.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ jobs:
179179
agenda-tela-do-produto.spec.ts
180180
notificacoes-diz-o-que-falta.spec.ts
181181
relogio-http-cron-externo.spec.ts
182+
j20-elegibilidade-respondi.spec.ts j20-elegibilidade-followup.spec.ts
183+
j20-elegibilidade-atendimento-manual.spec.ts
182184
# ⚠️ A ORDEM DESTA LISTA NÃO DECIDE A ORDEM DE EXECUÇÃO. O Playwright
183185
# ordena os arquivos por CAMINHO, não pela ordem em que são passados na
184186
# linha de comando. Medido no run 31838253496: `marca-logo.spec.ts` estava

0 commit comments

Comments
 (0)