Skip to content

Visão Geral da Arquitetura

Última atualização: 2026-03-26

Diagrama de Contexto

┌──────────────┐     HTTPS      ┌────────────────────┐
│   Browser    │◄──────────────►│  Cloudflare Worker  │ (gateway.olp.digital)
│  (React SPA) │                │  - Reescrita cookie │
│              │                │  - Geo headers      │
└──────┬───────┘                └─────────┬──────────┘
       │                                  │
       │ credentials: include             │ Proxy transparente
       │                                  ▼
       │                        ┌────────────────────┐
       │                        │   Supabase Edge     │ 59 functions
       │                        │   Functions (Deno)  │
       │                        └─────────┬──────────┘
       │                                  │
       │                    ┌─────────────┼─────────────┐
       │                    ▼             ▼             ▼
       │           ┌──────────┐  ┌──────────┐  ┌──────────┐
        │           │ Postgres │  │ Wasender  │  │ Storage  │
        │           │  (RLS)   │  │(WhatsApp) │  │ (Buckets)│
        │           │          │  │           │  │          │
        │           └──────────┘  └──────────┘  └──────────┘

       └──── Supabase Client direto (APENAS dados públicos, storage)

Papéis e Grupos

Grupo: Plataforma OLP

PapelDescriçãoEscopoFeature Flags
administradorGerencia escolas, usuários, planos, assinaturasGlobal — cross-escolaBypass de feature flags
especialistaCria olimpíadas, fases, calendários, cursos, templatesGlobal — conteúdoSujeito a feature flags

Grupo: Equipe da Escola

PapelDescriçãoEscopo
escola (Gestor)Admin máximo da escolaTudo da sua escola
escola_trialGestor em período de avaliaçãoTudo da sua escola (trial)
coordenadorGerencia olimpíadas, alunos, turmasCRUD na sua escola
coordenador_olimpiadasCoordena especificamente olimpíadasOlimpíadas na sua escola
coordenador_pedagogicoCoordena acompanhamento pedagógicoPedagógico na sua escola
diretorVisualiza financeiro, relatóriosLeitura na sua escola
pedagogicoAcompanha resultados pedagógicosLeitura na sua escola
professorVisualiza turmas e alunosLeitura na sua escola
marketingAcessa comunicação e muralEscopo reduzido

Grupo: Comunidade (Mural Olímpico)

PapelDescriçãoEscopo
alunoVê cronograma, provas, resultadosSeus próprios dados
responsavelAcompanha filhos vinculadosDados dos filhos

Hierarquia

administrador > especialista > escola > escola_trial > coordenador >
coordenador_olimpiadas > coordenador_pedagogico > diretor >
pedagogico > professor > marketing > aluno > responsavel

Regra fundamental: Login unificado — todos entram pela mesma tela. Se o usuário tem múltiplos perfis (ou o mesmo perfil em escolas diferentes), uma tela de seleção é apresentada. O papel e a escola ativos vêm do JWT.

Multi-Escola

Um mesmo usuário pode ter papéis em múltiplas escolas via usuario_papeis. Exemplo:

text
usuario_papeis:
  usuario_id=ABC, papel=coordenador, escola_id=ESCOLA_A
  usuario_id=ABC, papel=coordenador, escola_id=ESCOLA_B
  usuario_id=ABC, papel=diretor,     escola_id=ESCOLA_B

Cada combinação papel + escola é um perfil distinto na tela de login e no role-switcher. O JWT escola_id é derivado do perfil selecionado.


Fluxo de Dados Principal

1. Usuário digita código (CPF/INEP/CNPJ)
2. Frontend → Edge Function `send-otp`
3. Backend localiza usuário + telefone
4. Gera OTP (6 dígitos) → hash SHA-256 → salva em `login_otps`
5. Envia OTP via WhatsApp (Wasender)
6. Usuário digita OTP
7. Frontend → Edge Function `verify-otp`
8. Backend valida OTP → lê papéis → gera JWT customizado
9. Retorna cookie HttpOnly `olp_auth` (8h)
10. Requests subsequentes incluem cookie automaticamente
11. Edge Functions extraem token → validam → executam lógica

Dois Contextos de JWT

ContextoSecretCookieExpiraçãoEscopo
Sistema AdminOLP_JWT_SECRETolp_auth8hCRUD completo
Mural Olímpico (Aluno/Responsável)OLP_JWT_SECRET (unificado)olp_mural2hportal_readonly

Secret unificado: Sistema e Portal usam OLP_JWT_SECRET (mesmo valor). Isso é obrigatório porque o PostgREST do Supabase usa um único secret para verificar tokens e aplicar RLS. A diferenciação de acesso é feita via claims no JWT: tokens do sistema contêm principal_role, tokens do portal contêm portal_type + escopo: 'portal_readonly'. Cross-access é bloqueado: tokens de portal não possuem principal_role e vice-versa.

Claims do JWT (Sistema Admin)

json
{
  "sub": "uuid-usuario",
  "nome_completo": "Nome",
  "principal_role": "escola",
  "escola_id": "uuid-escola",
  "roles": [{ "nome": "escola", "escola_id": "uuid" }],
  "role": "authenticated",
  "aud": "authenticated"
}

Os claims role: authenticated e aud: authenticated são obrigatórios para que o PostgREST do Supabase reconheça o token e aplique RLS.


Clientes Supabase nas Edge Functions

ClienteFunçãoRLSUso
createSupabaseClient(req)ANON_KEY + Bearer token do cookie✅ AtivoOperações autenticadas com escopo de escola
createSupabasePublic()ANON_KEY sem auth✅ AtivoLogin, lookup público
createSupabaseSystem()SERVICE_ROLE_KEY❌ BypassStorage uploads, logs, admin cross-escola

Regra: Sempre preferir createSupabaseClient(req) para operações autenticadas. createSupabaseSystem() apenas quando justificado tecnicamente.


Ambientes

AmbienteURLGateway
Preview (Lovable)https://id-preview--b4188062-...lovable.appDireto para Supabase
Produçãohttps://olp.digitalhttps://gateway.olp.digital (Cloudflare Worker)
Localhosthttp://localhost:5173Direto para Supabase

Cloudflare Worker (Produção)

O Worker atua como proxy transparente e adiciona:

  1. Reescrita de cookies: Adiciona Domain=.olp.digital para funcionar cross-subdomain
  2. Headers de geolocalização: X-Geo-City, X-Geo-Region, X-Geo-Country, X-Geo-Timezone
  3. Roteamento: Encaminha requests para as Edge Functions do Supabase

Estrutura do Projeto

src/
  components/       # Componentes React (por funcionalidade)
    agenda/         # Exemplo de Feature Directory Pattern (7 arquivos)
    coordenador/    # Features do coordenador (ex: resultados/)
    diretor/        # Features do diretor
    mural-olimpico/ # Mural Olímpico (15+ arquivos)
    importacao-alunos/ # Importação inteligente (7 arquivos)
    ui/             # Design system (shadcn — não alterar)
  contexts/         # Auth context (sessão via cookie)
  hooks/            # Hooks customizados (1 por Edge Function)
  lib/              # Helpers (edge-function.ts, auth.ts, masks.ts)
    navigation/     # Registry centralizado de seções e permissões
  pages/            # Páginas de rota (portal, cadastro)
  types/            # Tipos TypeScript

supabase/
  functions/        # 59 Edge Functions
    _shared/        # Helpers compartilhados (auth, cors, jwt, logging)
  migrations/       # Migrações SQL (read-only)
  config.toml       # Configuração (verify_jwt = false global)

docs/               # Esta documentação

Regras de Integração

  1. Lógica de Supabase/Auth/Wasender → helpers/hooks (lib/auth, lib/edge-function, _shared/*), nunca em componentes React
  2. Mocks são transitórios — substituir por chamadas reais na mesma entrega
  3. Áreas sensíveis (não alterar sem instrução): components/ui/*, App.tsx, main.tsx, *.config.*