Status: épico ainda NÃO grelhado. Este issue é só o problema em si, para servir de ponto de partida do grilling. O design (user stories, decisões, testes) sai da sessão de grilling + domain-modeling, como no épico #8.
P4 (numeração da roadmap, após P1 pairing-code / P2 polls #16 / P3 auth-store #17). Relaciona-se com #8 (pairing-code / headless): fecha a lacuna do "recuperação pós-loggedOut é manual".
Problem Statement
O coletor headless (systemd --user, 24/7) não tem visibilidade proativa da saúde da sessão de WhatsApp. Quando a sessão cai (loggedOut), o serviço apenas loga FATAL no journald da VM e sai ≠ 0 — ninguém é avisado. A recuperação é manual (ADR-0003: operador roda pnpm pair e reinicia), mas só acontece quando alguém percebe que parou. Resultado: janela de coleta parada até alguém olhar os logs.
Não existe canal de push pro operador saber "a sessão morreu, precisa re-parear".
Solution (direção, a detalhar no grill)
Um sink de notificações no próprio wpp-tui que faz POST direto num incoming webhook de um canal do Discord (formato content/embeds do Discord), em paralelo ao webhook do Laravel (integration-whatsapp) já existente. Autônomo — não depende do monolito.
Escopo inicial: eventos de lifecycle de sessão/auth, derivados do connection.update do Baileys (o mesmo que src/collector/core.ts e src/pairing.ts já observam):
- Sessão conectada (
connection: 'open') — "coletor online".
- Sessão caiu /
loggedOut — "sessão morreu, precisa re-parear" (o alerta mais importante).
- (a decidir) código de pareamento pendente / aguardando pareamento.
Este webhook é independente do contrato do Laravel: sem HMAC X-Signature, formato é o do Discord, não o {type, chat_jid, payload} interno.
A grelhar (open questions)
- Conjunto exato de eventos: quais transições do
connection.update viram notificação (open, close com/sem loggedOut, restartRequired 515 é ruído?), e se entra o prompt de pairing-code.
- Formato:
content texto simples vs embeds (cor por severidade); @role/@here em alerta crítico (loggedOut)?
- Config:
DISCORD_WEBHOOK_URL por env (opcional — ausente = sink desligado, sem quebrar o coletor).
- Resiliência: Discord fora do ar → retry? drop? reusa a infra de
outbox/backoff do webhook-sender atual ou é fire-and-forget?
- Anti-flap: reconexões em loop (close→open) não podem spammar o canal — dedup/rate-limit/coalescing.
- Segurança: a URL do webhook do Discord é segredo (não logar; fora do stdout do headless).
Arquivos afetados (provável)
src/collector/core.ts (observa connection.update, emite os eventos de lifecycle)
- novo módulo tipo
src/collector/discord-sink.ts (formata + posta no webhook do Discord)
.env.example (DISCORD_WEBHOOK_URL), docs de deploy
Fora do escopo (inicial — futuros épicos)
Problem Statement
O coletor headless (systemd
--user, 24/7) não tem visibilidade proativa da saúde da sessão de WhatsApp. Quando a sessão cai (loggedOut), o serviço apenas loga FATAL no journald da VM e sai ≠ 0 — ninguém é avisado. A recuperação é manual (ADR-0003: operador rodapnpm paire reinicia), mas só acontece quando alguém percebe que parou. Resultado: janela de coleta parada até alguém olhar os logs.Não existe canal de push pro operador saber "a sessão morreu, precisa re-parear".
Solution (direção, a detalhar no grill)
Um sink de notificações no próprio wpp-tui que faz
POSTdireto num incoming webhook de um canal do Discord (formatocontent/embedsdo Discord), em paralelo ao webhook do Laravel (integration-whatsapp) já existente. Autônomo — não depende do monolito.Escopo inicial: eventos de lifecycle de sessão/auth, derivados do
connection.updatedo Baileys (o mesmo quesrc/collector/core.tsesrc/pairing.tsjá observam):connection: 'open') — "coletor online".loggedOut— "sessão morreu, precisa re-parear" (o alerta mais importante).Este webhook é independente do contrato do Laravel: sem HMAC
X-Signature, formato é o do Discord, não o{type, chat_jid, payload}interno.A grelhar (open questions)
connection.updateviram notificação (open, close com/semloggedOut,restartRequired515 é ruído?), e se entra o prompt de pairing-code.contenttexto simples vsembeds(cor por severidade);@role/@hereem alerta crítico (loggedOut)?DISCORD_WEBHOOK_URLpor env (opcional — ausente = sink desligado, sem quebrar o coletor).outbox/backoff do webhook-sender atual ou é fire-and-forget?Arquivos afetados (provável)
src/collector/core.ts(observaconnection.update, emite os eventos de lifecycle)src/collector/discord-sink.ts(formata + posta no webhook do Discord).env.example(DISCORD_WEBHOOK_URL), docs de deployFora do escopo (inicial — futuros épicos)