Ping — dados de conexão e auditoria
TLDR: Cada ping de presença na sala de atendimento deve registrar o contexto de conexão do participante (câmera, microfone, qualidade, rede) e ser logado na auditoria, permitindo investigar problemas de conectividade retroativamente.
Draft — não implementado. Asana: https://app.asana.com/1/1208104128529800/task/1214640670041059
A parte de contexto de conexão foi entregue por outro caminho, em meeting_ping_diagnostics: uma tabela
meeting_participant_pingscomdiagnosticsjsonb, em vez da colunaroom_ping_eventsproposta aqui. O que continua pendente deste draft é a auditoria por ping (Branch 2) e a guarda de janela no endpoint.
Contexto
Ticket de suporte: uma cliente relatou que não conseguiu realizar a sessão do dia 18/03/2026 às 20h devido a instabilidade de conexão. Ao verificar no Avo, constam pings na sala das 20h às 21h12 (dentro da janela da sessão) e, no dia seguinte, das 12h14 às 12h15 — 15 horas após o fim da sessão.
Problema central: os pings não carregam nenhum dado de contexto (câmera, microfone, qualidade de conexão, tipo de rede), tornando impossível confirmar ou refutar o relato da cliente a partir dos dados do sistema.
Problema secundário: o endpoint de pings não verifica se a sessão ainda está dentro da janela permitida (can_join?), permitindo que pings sejam aceitos indefinidamente após joined: true ser setado.
Como funciona hoje
``` Cliente entra na sala → GET /api/v1/meetings/:id/credentials → MeetingsCredentialController#create → MeetingParticipant.update!(joined: true) ← verifica can_join?
Cliente envia heartbeat (a cada ~20s via frontend) → PATCH /api/v1/me/meetings/:meeting_id/pings → MeetingParticipants::CreatePingFlow → joined? → appenda Time.current.to_i em room_pings joined: false → appenda em wait_pings ← NENHUMA verificação de janela de tempo ← NENHUM dado de conexão capturado ```
Janela permitida (Meeting#can_join?): de start_at - 10min até start_at + 2h. Ignora sessões finished ou canceled.
Estrutura dos dados hoje:
meeting_participants
room_pings string[] — array de Unix timestamps
wait_pings string[] — array de Unix timestamps
Investigação em produção — resultado (11/05/2026)
Investigado via MeetingParticipant.find(547525) (meeting 274036, sessão 18/03/2026 20h–21h).
| Resultado | |
|---|---|
| room_pings dia 18 | 393 pings — 20:00:39 até 21:12:38, presença contínua confirmada |
| room_pings dia 19 | 6 pings — 12:14:02 até 12:15:29, fora de qualquer janela de sessão |
| wait_pings | 55 pings — cliente aguardou na sala de espera antes de entrar |
| Lacunas > 1min no dia 18 | 20:09:55→20:10:38 (43 s) e 20:25:53→20:27:16 (1min23s) — normais |
| Conclusão | Cliente esteve presente na sala durante toda a sessão. Pings do dia 19 são artefato de app em background. |
A sessão foi realizada. Não há evidência de queda de conexão nos dados disponíveis. Os pings fantasma do dia 19 confirmam o bug de ausência de guarda de janela no endpoint.
Objetivos
- Registrar o contexto de conexão do participante a cada ping
- Logar cada ping no audit trail, com action e metadata
- Exibir os dados de conexão e o audit trail no Avo, sem necessidade de console
- Rejeitar pings fora da janela da sessão
Fora de escopo
- Alterar a semântica dos arrays legados
room_pings/wait_pings
Mudanças
Branch 1 — feat/ping-connection-data
Adicionar uma nova coluna room_ping_events jsonb default '[]' em meeting_participants. Cada evento é um objeto JSON:
json
{
"t": 1742335836,
"camera": true,
"mic": false,
"quality": "unstable",
"network": "wifi"
}
| Campo | Tipo | Valores |
|---|---|---|
t |
integer | Unix timestamp |
camera |
boolean | true = câmera ativa |
mic |
boolean | true = microfone ativo |
quality |
string | good, unstable, poor |
network |
string | wifi, cellular, ethernet |
Todos os campos são opcionais no request — o frontend envia o que tiver disponível. O t é sempre preenchido pelo servidor.
Endpoint atualizado:
PATCH /api/v1/me/meetings/:meeting_id/pings
Body: {
camera_active: true,
microphone_active: false,
connection_quality: "unstable",
network_type: "wifi"
}
Arquivos afetados: db/migrate/ (nova migration), app/models/meeting_participant.rb, app/controllers/api/v1/meetings/participant_pings_controller.rb, app/use_cases/meeting_participants/create_ping.rb, app/serializers/meeting_participant_ping_serializer.rb, spec/requests/api/v1/meetings/participant_pings_update_spec.rb.
Superado: entregue de outra forma em meeting_ping_diagnostics — tabela
meeting_participant_pingscomdiagnosticsjsonb, em vez de colunaroom_ping_eventsnomeeting_participants.
Branch 2 — feat/ping-audit-log
Logar cada tentativa de ping no audit trail usando a gem audited, já utilizada no modelo Meeting.
Verificar se MeetingParticipant já está auditado. Se não, adicionar audited com escopo restrito aos campos relevantes, ou criar um evento manual via Audited::Audit com os dados do ping.
| Campo | Valor |
|---|---|
auditable |
MeetingParticipant |
action |
"room_ping" ou "wait_ping" |
user |
participante que enviou o ping |
audited_changes |
{ t:, camera:, mic:, quality:, network: } |
Arquivos afetados: app/models/meeting_participant.rb, app/use_cases/meeting_participants/create_ping.rb, spec/requests/api/v1/meetings/participant_pings_update_spec.rb.
Branch 3 — feat/ping-avo-connection-display
Atualizar o Avo para exibir os dados de conexão por ping e o audit trail:
- 18 de março de 2026 às 21:10:36 — câmera: ✓ mic: ✗ conexão: instável rede: wifi
- 18 de março de 2026 às 21:11:37 — câmera: ✓ mic: ✓ conexão: boa rede: wifi
Substituir ou complementar o painel atual de room_pings com o novo formato rico e adicionar painel de audit trail com eventos de ping.
Arquivos afetados: app/use_cases/meeting_participants/format_ping_dates.rb, app/avo/resources/meeting_participant.rb.
Superado: a exibição foi entregue em room_ping_network_quality_avo, com qualidade derivada de
network.rtte navegador via regex. O painel de audit trail continua pendente.
Melhoria adicional (separada)
Branch fix/ping-outside-session-window: adicionar verificação de meeting.can_join? no endpoint de pings para rejeitar pings fora da janela da sessão. Evita pings “fantasma” como os do dia 19 deste ticket. Continua pendente.
Como verificar
- [ ] Branch 1: migration criada, endpoint aceita dados de conexão,
room_ping_eventspopulado - [ ] Branch 1: factory atualizada com dados de conexão
- [ ] Branch 2: audit log criado a cada ping, com action e metadata corretos
- [ ] Branch 3: Avo exibe dados de conexão por ping e audit trail
- [ ] fix: guarda
can_join?no endpoint de pings implementada e testada - [ ]
make seedexecuta sem erro após as migrações
Documentação
Learning registrado em sessions_ghost_pings_and_missing_connection_data.