Plano Futuro: Offload Argon2id para Cloudflare Worker (Pago)
Status: ARQUIVADO — Aguardando upgrade do Worker para plano pago (Workers Standard). Pré-requisito: Workers Standard (30s CPU time, mais memória). Contexto: Hoje tanto o Worker (free) quanto o Deno isolate (Supabase) têm 2s de CPU time. Não há ganho em mover processamento.
Progresso — Fase 1 (CONCLUÍDA)
A Fase 1 do plano de otimização foi implementada sem necessidade do Worker pago:
| Item | Status | Descrição |
|---|---|---|
| HIBP fire-and-forget | ✅ Concluído | change-password e reset-password moveram o HIBP check para após o response 200 |
| Notificação in-app | ✅ Concluído | Se breached, insere em notificacoes (tipo: sistema) |
| Log de incidente | ✅ Concluído | auth.senha_vazada_detectada registrado via registrarLog |
| set-password bloqueante | ✅ Mantido | Primeiro acesso tem budget de CPU sobrando — HIBP rejeita diretamente |
Ganho: ~200ms removidos do critical path de troca/reset de senha.
Quando ativar Fase 2 (Cache HIBP no Worker)
- Worker upgrade para plano pago (Workers Standard: 30s CPU)
- OU volume de trocas de senha justificar cache (reduzir chamadas HIBP externas)
Fase 2: Rota /hibp-check no Worker
text
Edge Function (fire-and-forget) Worker (proxy)
┌───────────────────────────┐ ┌───────────────────────────────┐
│ checkPasswordBreach() ───┼───>│ POST /hibp-check │
│ (após response 200) │ │ 1. SHA-1 prefix/suffix │
│ │ │ 2. Redis GET olp:hibp:{pfx} │
│ │ │ HIT → parse, return │
│ │ │ MISS → fetch HIBP API │
│ │ │ → Redis SET (TTL 24h)│
│ │ │ → return result │
│ │ │ │
│ │ │ Zero Argon2id. Só SHA-1 + I/O│
└───────────────────────────┘ └───────────────────────────────┘Redis key schema:
olp:hibp:{sha1_prefix_5chars}
Valor: response body HIBP (texto raw, ~30KB)
TTL: 86400 (24h)Quando ativar Fase 3 (Offload Argon2id)
- Worker upgrade para plano pago (Workers Standard: 30s CPU)
- OU se Supabase reduzir ainda mais o limite de CPU em Edge Functions
- OU se o fluxo de senha precisar de mais operações Argon2id (ex: histórico > 3)
Fase 3: Arquitetura proposta
text
┌──────────┐ ┌─────────────────────┐ ┌──────────────────┐
│ Frontend │───>│ Cloudflare Worker │───>│ Edge Function │
│ │ │ (30s CPU budget) │ │ (2s CPU budget) │
│ │ │ │ │ │
│ │ │ • verifyPassword() │ │ • SELECT hash │
│ │ │ • checkHistory() │ │ • UPDATE hash │
│ │ │ • hashPassword() │ │ • INSERT history │
│ │ │ • HIBP check+cache │ │ • registrarLog() │
│ │ │ │ │ │
│ │ │ Argon2id: ~1890ms │ │ Argon2id: 0ms │
│ │ │ (dentro de 30s) │ │ (só DB ops) │
└──────────┘ └─────────────────────┘ └──────────────────┘O que muda na Fase 3
| Componente | Antes | Depois |
|---|---|---|
Worker (gateway.olp.digital) | Proxy puro (forward) | Proxy + Argon2id compute para rotas de senha |
Edge Function change-password | 5x Argon2id (~1890ms CPU) | 0x Argon2id (~50ms CPU) |
Edge Function nova password-ops | N/A | CRUD de hashes (read/write only) |
hash-wasm no Worker | N/A | Importar e executar Argon2id |
Considerações
- OLP_PEPPER_SECRET precisa estar como env var no Cloudflare Dashboard
- Senhas em plaintext NÃO trafegam Worker→Edge Function — Worker faz hash localmente
- Worker passa de proxy puro para ter lógica de negócio (complexidade adicional)
- Manter fallback na Edge Function para caso de falha do Worker
Ganho estimado por fase
| Fase | Operação | Economia | Status |
|---|---|---|---|
| 1 | HIBP fire-and-forget | ~200ms do critical path | ✅ Concluído |
| 2 | Cache HIBP no Redis | ~195ms por cache hit | 🔮 Futuro |
| 3 | Offload Argon2id | ~1890ms → 0ms na EF | 🔮 Futuro |
Referências
- Limite CPU Supabase: 2s wall-clock (igual free e pago)
- Limite CPU Workers Free: 10ms CPU / Workers Standard: 30s CPU
- Memory: Supabase Deno isolate > Workers Free
- docs/security/PASSWORD_HASHING_ARCHITECTURE.md