Mapa Completo de Notificações e Alertas Push
Última atualização: 2026-03-07
O sistema possui dois canais de notificação independentes:
- Notificações in-app — inseridas na tabela
notificacoes, entregues via Supabase Realtime ao frontend (sino no header) - Alertas push (ntfy.sh) — enviados via HTTP para o app ntfy da equipe técnica/admin (celular/desktop)
Alguns cenários também disparam mensagens WhatsApp via Wasender como canal complementar.
Canal 1: Notificações In-App (tabela notificacoes)
1.1 Fatura Gerada
| Campo | Valor |
|---|---|
| Tipo | fatura_proxima |
| Origem | faturamento-cron (action gerar_faturas) |
| Destinatários | Gestores (escola) + Diretores da escola |
| Trigger | CRON mensal gera fatura e link MercadoPago |
| Título | Fatura gerada - FAT-YYYY-MM-NNN |
| Canais extras | WhatsApp ao gestor (fatura_gerada) |
| Como testar | Dashboard Admin > CRON Monitor > Trigger Manual faturamento-cron com action gerar_faturas. Requer escola com assinatura ativa e dia de vencimento compatível. |
1.2 Lembrete D-5 (Fatura vence em 5 dias)
| Campo | Valor |
|---|---|
| Tipo | fatura_proxima |
| Origem | faturamento-cron (action lembrete_d5) |
| Destinatários | Gestores + Diretores da escola |
| Trigger | CRON diário encontra fatura pendente com vencimento em exatamente 5 dias |
| Título | Fatura vence em 5 dias - FAT-... |
| Canais extras | WhatsApp ao gestor (lembrete_fatura) |
| Como testar | Criar fatura pendente com vencimento_em = hoje + 5 dias, link_pagamento preenchido, lembrete_d5_enviado_em = null. Trigger manual lembrete_d5. |
1.3 Pagamento Confirmado (via Webhook)
| Campo | Valor |
|---|---|
| Tipo | pagamento_confirmado |
| Origem | mercadopago-webhook |
| Destinatários | Gestores + Diretores da escola |
| Trigger | MercadoPago envia webhook payment.created/payment.updated com status approved |
| Título | Pagamento confirmado - FAT-... |
| Canais extras | WhatsApp ao gestor (pagamento_confirmado) |
| Como testar | Simular webhook POST para mercadopago-webhook com payload de pagamento aprovado (requer fatura real com gateway_preference_id). Alternativa: usar sandbox do MercadoPago com cartão de teste. |
1.4 Pagamento Confirmado (via Polling)
| Campo | Valor |
|---|---|
| Tipo | pagamento_confirmado |
| Origem | mercadopago-preference (action check_status) |
| Destinatários | Gestores + Diretores da escola |
| Trigger | Frontend chama check_status após usuário retornar da tela de pagamento |
| Canais extras | WhatsApp ao gestor (pagamento_confirmado) |
| Como testar | Fazer pagamento real no sandbox, depois chamar check_status com o fatura_id. |
1.5 Solicitação de Alteração de Plano
| Campo | Valor |
|---|---|
| Tipo | sistema |
| Origem | escola-pagamentos (action request_plan_change) |
| Destinatários | Todos os administradores da plataforma |
| Trigger | Gestor da escola solicita troca de plano na tela de Pagamentos |
| Canais extras | WhatsApp aos admins (solicitacao_plano) |
| Como testar | Logar como gestor de escola > Pagamentos > Solicitar alteração de plano (selecionar plano diferente + período). |
1.6 Cadastro de Escola (Solicitação de Ativação)
| Campo | Valor |
|---|---|
| Tipo | sistema |
| Origem | cadastro-escola-publica |
| Destinatários | Todos os administradores da plataforma |
| Trigger | Escola completa formulário de cadastro público |
| Título | Nova solicitação de cadastro |
| Canais extras | Nenhum (sem SMS) |
| Como testar | Acessar /cadastro > Preencher formulário completo > Submeter. Verificar notificação no painel admin. |
1.7 Solicitação de Vínculo (Convite)
| Campo | Valor |
|---|---|
| Tipo | solicitacao_vinculo |
| Origem | gestao-usuarios-escola (action criar_solicitacao) |
| Destinatários | Usuário convidado |
| Trigger | Gestor envia convite de vínculo a um usuário existente |
| Título | Solicitação de Vínculo |
| Canais extras | Nenhum |
| Como testar | Logar como gestor > Usuários > Vincular usuário existente (por CPF). O usuário destinatário deve ver a notificação. |
1.8 Resposta ao Vínculo (Aceite/Recusa)
| Campo | Valor |
|---|---|
| Tipo | solicitacao_vinculo |
| Origem | gestao-usuarios-escola (action responder_solicitacao) |
| Destinatários | Gestor que enviou o convite (solicitante) |
| Trigger | Usuário aceita ou recusa a solicitação de vínculo |
| Título | Vínculo Aceito ou Vínculo Recusado |
| Canais extras | Nenhum |
| Como testar | Logar como usuário convidado > Notificações > Aceitar/Recusar vínculo. Verificar notificação no painel do gestor. |
1.9 Falha Crítica de CRON (Alerta Admin)
| Campo | Valor |
|---|---|
| Tipo | cron_falha |
| Origem | faturamento-cron e maintenance-cron (função criarAlertaAdmins) |
| Destinatários | Todos os administradores da plataforma |
| Trigger | Job CRON falha 2+ vezes consecutivas (alerta) ou 3+ vezes (crítico) |
| Canais extras | WhatsApp aos admins (3+ falhas) + ntfy push |
| Como testar | Forçar falha no CRON (ex: revogar permissão de tabela temporariamente) > Trigger manual > Repetir até 3 falhas. |
1.10 Notificação Manual do Admin (create_internal / create_batch)
| Campo | Valor |
|---|---|
| Tipo | equipe_olp ou sistema (configurável) |
| Origem | notificacoes (actions create_internal e create_batch) |
| Destinatários | Usuário específico (internal) ou todos de um papel (batch) |
| Trigger | Admin envia notificação manualmente via painel |
| Canais extras | Nenhum |
| Como testar | Logar como admin > Enviar Notificação > Selecionar destinatários > Enviar. |
Canal 2: Alertas Push (ntfy.sh) — Equipe Técnica
2.1 Brute Force Detectado (Login Sistema)
| Campo | Valor |
|---|---|
| Origem | verify-otp/index.ts |
| Prioridade | high |
| Tags | warning, lock |
| Trigger | Usuário atinge 5+ tentativas falhas de OTP em 15 min (lockout ativado) |
| Como testar | Fazer 5 tentativas de login com OTP errado para o mesmo CPF. |
2.2 Falha no Envio de SMS OTP (Login Sistema)
| Campo | Valor |
|---|---|
| Origem | send-otp/index.ts |
| Prioridade | high |
| Tags | warning, phone |
| Trigger | Wasender retorna erro ao tentar enviar OTP via WhatsApp |
| Como testar | Configurar telefone inválido para um usuário > Tentar login. Ou desconectar sessão Wasender temporariamente. |
2.3 Lockout Severo no Portal (10+ falhas)
| Campo | Valor |
|---|---|
| Origem | portal-escola/index.ts (função checkLockout) |
| Prioridade | high |
| Tags | rotating_light, lock |
| Trigger | Identificador (matrícula/CPF) atinge 10+ falhas no portal (lockout de 60min) |
| Como testar | Fazer 10+ tentativas de login com matrícula/data errados no portal de uma escola. |
2.4 Rate Limit OTP Aluno por Escola
| Campo | Valor |
|---|---|
| Origem | portal-escola/index.ts (handler login_aluno_b_send) |
| Prioridade | high |
| Tags | warning, school |
| Trigger | Escola atinge 100 OTPs de aluno em 15 minutos (possível abuso de SMS) |
| Como testar | Enviar 100+ OTPs para alunos da mesma escola em 15 min (difícil em produção — testar reduzindo o limite temporariamente ou via script). |
2.5 Rate Limit OTP Responsável por Escola
| Campo | Valor |
|---|---|
| Origem | portal-escola/index.ts (handler login_responsavel_send) |
| Prioridade | high |
| Tags | warning, school |
| Trigger | Escola atinge 100 OTPs de responsável em 15 minutos |
| Como testar | Mesmo cenário do 2.4 mas para responsáveis. |
2.6 Token Revogado Reutilizado (Sistema)
| Campo | Valor |
|---|---|
| Origem | _shared/auth-helpers.ts (função extractAuthenticatedUser) |
| Prioridade | urgent |
| Tags | rotating_light, skull |
| Trigger | JWT do sistema (olp_auth) com jti presente em token_blacklist tenta acesso |
| Como testar | Revogar sessão de um usuário via banco (token_blacklist insert) > Tentar acessar com o cookie antigo. |
2.7 Token Portal Revogado Reutilizado
| Campo | Valor |
|---|---|
| Origem | _shared/jwt-portal.ts (função verifyPortalToken) |
| Prioridade | urgent |
| Tags | rotating_light, skull |
| Trigger | JWT do mural (olp_mural) com jti presente em token_blacklist tenta acesso |
| Como testar | Mesmo processo do 2.6 mas para token de portal. |
2.8 CRON Crítico — Manutenção
| Campo | Valor |
|---|---|
| Origem | maintenance-cron/index.ts (função escalarFalhaCron) |
| Prioridade | urgent |
| Tags | rotating_light, warning, skull |
| Trigger | Job de manutenção falha 3+ vezes consecutivas |
| Como testar | Forçar falha persistente no CRON de manutenção > Trigger manual 3x. |
2.9 CRON Crítico — Faturamento
| Campo | Valor |
|---|---|
| Origem | faturamento-cron/index.ts (função escalarFalhaCron) |
| Prioridade | urgent |
| Tags | rotating_light, warning, skull |
| Trigger | Job de faturamento falha 3+ vezes consecutivas |
| Como testar | Forçar falha no CRON de faturamento > Trigger manual 3x. |
2.10 Sessão WhatsApp Desconectada
| Campo | Valor |
|---|---|
| Origem | maintenance-cron/index.ts (função checkWhatsAppSession) |
| Prioridade | high |
| Tags | money_with_wings, warning |
| Trigger | Sessão Wasender desconectada ou inativa |
| Canais extras | Alerta push ntfy para admins |
| Como testar | Dashboard Admin > CRON Monitor > Trigger manual maintenance-cron. |
Resumo por Canal
| Canal | Total de cenários | Destinatário |
|---|---|---|
In-app (notificacoes) | 10 cenários | Usuários finais (gestores, diretores, admins, usuários convidados) |
Push (ntfy.sh) | 10 cenários | Equipe técnica/admin (celular/desktop) |
| WhatsApp (Wasender) | 8 cenários | Gestores de escola + admins (subconjunto dos in-app) |
Tipos de Notificação (enum notification_type)
| Tipo | Cenários | Contexto |
|---|---|---|
fatura_proxima | 1.1, 1.2 | Faturamento |
fatura_vencida | — | Reservado (não implementado) |
pagamento_confirmado | 1.3, 1.4 | Pagamento |
inscricao | — | Reservado |
resultado | — | Reservado |
mensagem | — | Reservado |
sistema | 1.5, 1.6 | Administrativo |
cron_falha | 1.9 | Operações |
equipe_olp | 1.10 | Comunicação interna |
solicitacao_vinculo | 1.7, 1.8 | Gestão de usuários |
Fluxo de Entrega — In-App
Edge Function insere em `notificacoes`
↓
Supabase Realtime (Postgres Changes)
↓
useRealtimeNotificacoes (filter: usuario_id=eq.{userId})
↓
notifications-panel.tsx (sino com badge)
↓
notification-detail-modal.tsx (detalhe)Tab Focus Management: Canais Realtime são desconectados após 5 min de inatividade em background e reconectados ao retornar foco.
Referências
supabase/functions/_shared/ntfy-helper.ts— Helper de alertas pushsupabase/functions/_shared/sms-templates.ts— Templates de SMSsupabase/functions/_shared/wasender-whatsapp.ts— Envio de mensagens via WhatsApp (Wasender)src/hooks/useRealtimeNotificacoes.ts— Listener Realtimesrc/hooks/useNotificacoes.ts— CRUD de notificaçõessrc/components/notifications-panel.tsx— UI do sinodocs/operations/ALERTAS_PUSH.md— Setup do ntfy.shdocs/architecture/REALTIME.md— Arquitetura Realtime