Skip to content

12 — Portal/Mural: superfície pública e cargas de pico

Pergunta: o Portal (Mural Olímpico) é a única superfície pública com tráfego não autenticado — como ele escala em janela de divulgação (10k acessos em 1 hora)?

Diferenças em relação ao admin

EixoAdmin/CoordPortal/Mural
AutenticaçãoSempre (cookie JWT)Mista: anônimo (lookup escola) + OTP (mural autenticado)
TráfegoLinear no número de usuários (~10–50 simultâneos)Pulso: divulgação de resultado pode levar 5k–10k acessos/hora
CacheReact Query no clienteEdge cache + snapshots (já existe mural_dados_publicados)
Custo de RLSPor usuário, com filtro de escolaPor request anônimo, sem JWT — usa supabasePublic

Edge functions no perímetro

  • mural-escola/ — endpoint público do mural por slug
  • portal-escola/ — login do portal (CPF + OTP / matrícula + DN)
  • mural-publicacoes — gestão (coord)
  • mural-liberacoes — gate de publicação (coord)

Pontos de pressão

P1 — Lookup público pré-login

Toda chamada anônima ao mural exige supabasePublic (ver mem://architecture/mural-pre-login-privilege-requirement). Sob pico:

  • Cada request faz um SELECT no banco para resolver slug → escola_id → snapshot.
  • Sem cache de borda, 10k requests = 10k roundtrips ao Postgres.
  • Hipótese: usar CDN cache (Cloudflare) com TTL curto (30s–5min) para o snapshot público — invalidado por edge function ao publicar.

P2 — Snapshot de resultados

mural_dados_publicados armazena snapshots imutáveis por publicação. Bom design — a leitura é O(1) por publicação. Confirmar que o JSONB do snapshot:

  • Não embute lista gigante (10k alunos) num único registro — se sim, fragmentar por nível/turma.
  • Tem índice em (escola_id, publicacao_id).

P3 — Rate limiting do OTP

portal_otps + portal_rate_metrics + portal_login_tentativas — bom; já tem cooldown. Conferir se:

  • A contagem de tentativas usa Redis (Upstash) e não SQL.
  • O rate limit é por (IP, identificador) e não só por IP (proxy NAT compartilha).

P4 — Rotas privadas do mural

Após login do portal, queries são por aluno_id (poucos registros por aluno) — baixo risco.

Hipóteses

  • H1: Sem edge cache, divulgação simultânea de resultados é o pior cenário de carga da plataforma — maior que qualquer ação interna do coord.
  • H2: A latência percebida no Portal hoje (com carga baixa) é puramente cold-start de Edge Function (~150ms) — vai colapsar em pico.
  • H3: O snapshot JSONB monolítico vai virar problema quando uma escola publicar 5k+ resultados num único nível.

Próximas etapas (auditoria, não fix)

  • Medir tamanho real dos snapshots já publicados (select pg_column_size(snapshot_jsonb) from mural_dados_publicados order by 1 desc limit 10).
  • Cruzar com mem://features/mural-olimpico/publicacao-parcial-silenciosa (já endereçou correção de UX) — esta auditoria é performance, não correção lógica.
  • Avaliar Cloudflare cache para a rota pública.
  • mem://architecture/mural-olimpico-snapshot-and-release-standard-v2
  • mem://infrastructure/cloudflare-worker-v2-specifications
  • mem://infrastructure/upstash-redis-standard