Pings fantasma após o fim da sessão e falta de contexto de conexão

O que aconteceu

Uma cliente relatou que não conseguiu concluir sua sessão em 18/03/2026 às 20h por problemas de conexão. Ao investigar no Avo, o sistema mostrava 393 room_pings em 1h12min no dia 18 de março (presença contínua) mais 6 pings no dia 19 de março às 12h14–12h15 — 15 horas depois do fim da sessão.

O suporte não conseguiu confirmar ou negar o problema de conexão porque os pings não carregam contexto sobre câmera, microfone, qualidade de conexão ou tipo de rede.

Causa raiz

Duas questões independentes:

1. Pings fantasma (dia 19): O endpoint de ping (PATCH /api/v1/me/meetings/:meeting_id/pings) não valida meeting.can_join?. O endpoint de credenciais define joined: true permanentemente no MeetingParticipant. Uma vez definido, o frontend pode enviar pings indefinidamente — mesmo dias depois, se a aba do app ficar aberta ou o app mobile retomar em background.

2. Sem contexto de conexão: room_pings e wait_pings armazenam apenas timestamps Unix (arrays de string). Não há campo para capturar status de câmera, status de microfone, qualidade de conexão ou tipo de rede junto de cada ping. O suporte não consegue distinguir “a cliente estava presente” de “a cliente tinha áudio/vídeo funcionando”.

Correção ou decisão

  • Spec criada em .project/docs/ping-connection-data-and-audit.md com três branches planejadas:
    • feat/ping-connection-data — adicionar coluna room_ping_events jsonb com contexto de conexão por ping
    • feat/ping-audit-log — registrar todo ping na trilha de auditoria
    • feat/ping-avo-connection-display — exibir dados de conexão no Avo
  • fix/ping-outside-session-window — proteger o endpoint de ping com meeting.can_join? para rejeitar pings fora da janela da sessão

Como evitar

  • Nunca usar pings de presença isolados como prova de qualidade de sessão — pings confirmam que a cliente estava na sala, não que vídeo/áudio funcionaram
  • Sempre proteger endpoints de heartbeat com a mesma verificação de janela de tempo usada na entrada (can_join?), senão apps em background produzem dados fantasma
  • Ao investigar reclamações de sessão, procurar por gaps de ping > 1 minuto como sinal de desconexão real; pings isolados de um dia diferente quase sempre são artefato de app em background