Files
DeskcommCRM/lib/waha
2a663e7a4e Merge da main no #1647 + migration dos grupos vira 0478, depois da 0477
A 0445 regravava fn_lgpd_cascade_redact_contact a partir do corpo de antes
da 0477 e tinha carimbo anterior ao dela: aplicada num banco que ja tem a
0477, tirava as propostas (PDF no bucket `propostas` e colunas redigidas)
da anonimizacao; na cadeia em ordem, a 0477 vinha por ultimo e apagava o
passo dos grupos. As duas coisas saem de uma vez:

- migration renumerada para 20260928150000_0478 (depois da 0477), com a
  cascata = corpo da 0477 inteiro + so o passo de channel_session_groups;
- apendice do baseline = o texto da migration (menos a chamada das travas
  do suporte, que o ultimo bloco do arquivo ja cobre), antes da varredura
  de anon; baseline.sql partiu do lado da main (conflito resolvido pelo
  lado autoritativo, nao hunk a hunk);
- linha do MANIFEST movida para depois da 0477; prosa e comentarios
  0445 -> 0478.

tests/invariants/lgpd-redact-unificado-alcanca-pelo-catalogo.test.ts
entra com o resultado do 3-way do git (git merge-file HEAD base main,
exit 0, sem edicao propria): os dois lados tocaram o arquivo, e o
freeze-invariants so dispensa quando a branch nao o tocou. Por isso a
valvula DESKCOMM_GOV_INVARIANTS_EDIT=1 neste commit. A troca 0445 -> 0478
na razao dele vai num commit proprio, a seguir.

Contribuicao de @bossprt (#1647).

Co-authored-by: Josicleuton da Silva Braga <josicleuton.braga@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 14:51:34 -03:00
..
…

lib/waha/

Placeholder. Cliente real virá da Spec 03 — WhatsApp via WAHA Plus.

Escopo previsto:

  • client.ts — wrapper HTTP do WAHA (auth via X-Api-Key plaintext; nunca query string)
  • signature.ts — verificação HMAC SHA512 dos webhooks com crypto.timingSafeEqual
  • throttle.ts — anti-banimento (1 msg/1.2s + jitter ≤800ms; campanha 1 msg/5s)
  • stop-detection.ts — regex /STOP|PARAR|SAIR|UNSUBSCRIBE/i
  • media.ts — upload pro Supabase Storage primeiro, URL ao WAHA
  • types.ts — tipos canônicos de payloads WAHA (Zod-validados)

Regras críticas (Spec 03 — adiantadas aqui)

  1. Auth: env do WAHA recebe hash SHA512 hex; client envia plaintext em X-Api-Key
  2. Engine NOWEB default; subscrever message.any (não só message); tratar fromMe=true sem duplicar
  3. Grupos (chatId.endsWith("@g.us")): nunca viram contato/lead nem passam pelo 1:1. Grupo ligado em channel_session_groups entra na inbox por lib/grupos/ingest.ts (sender é p.author, a IA nunca responde); grupo desligado é descartado. O filtro ignore.groups da sessão é decidido por definirRecebimentoDeGrupos (lê antes, só escreve quando difere) e ressincronizado na conexão/reconexão (lib/grupos/sincronizar-filtro.ts)
  4. Idempotência: unique (organization_id, external_id) + captura code === "23505"
  5. Cron recover-stuck-messages: status='sending' há >5min → failed

Sessões e reserva local

lib/channels/connect-waha.ts reserva a identidade por organização e Idempotency-Key antes de criar/iniciar remoto. Erro desconhecido 409/422 não é sucesso; o cliente exige envelope conhecido, identidade exata e pós-condição. Falha preserva FAILED e a identidade; nova tentativa reutiliza a mesma sessão via reserva. Não há compensação destrutiva automática. tier=CORE não implica limite de uma sessão; a prova 2026.7.2/NOWEB chega somente a duas SCAN_QR_CODE, sem pairing ou envio.