# MeowSpool Backend — TODO > Última atualização: 14/03/2026 --- ## Crítico — Funcionalidades Quebradas ### Auth: Email e Reset de Senha Todos os três handlers abaixo retornam `200 OK` sem executar nenhuma lógica real. Dependem de infraestrutura compartilhada que ainda não existe (ver "Bloqueadores"). - [ ] **`forgot_password_handler`** (`src/adapters/inbound/auth_handler.rs:131`) - Gerar token de reset seguro (UUID v4 ou CSPRNG) - Salvar na tabela `password_reset_tokens` (ver migration abaixo) - Enviar email com link de reset via serviço de email - Token deve ter TTL de 1h e ser invalidado após uso - [ ] **`verify_email_handler`** (`src/adapters/inbound/auth_handler.rs:138`) - Validar token recebido contra tabela `email_verification_tokens` - Chamar `user_repo.verify_email(user_id)` (método já implementado no repo) - Marcar token como usado / deletar após validação - Retornar `400 Bad Request` para token inválido ou expirado - [ ] **`reset_password_handler`** (`src/adapters/inbound/auth_handler.rs:143`) - Validar token recebido contra tabela `password_reset_tokens` - Verificar TTL e se já foi usado - Hash da nova senha com Argon2id - Atualizar `password_hash` via `user_repo.update()` - Invalidar token após uso ### Bloqueadores das features de Auth acima - [ ] **Migration: `password_reset_tokens`** ```sql CREATE TABLE password_reset_tokens ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, token TEXT NOT NULL UNIQUE, used_at TIMESTAMPTZ, expires_at TIMESTAMPTZ NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX ON password_reset_tokens (token); ``` - [ ] **Migration: `email_verification_tokens`** ```sql CREATE TABLE email_verification_tokens ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, token TEXT NOT NULL UNIQUE, used_at TIMESTAMPTZ, expires_at TIMESTAMPTZ NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX ON email_verification_tokens (token); ``` - [ ] **Serviço de email** (`src/infrastructure/email_service.rs` — novo arquivo) - Adicionar dependência: `lettre` (SMTP) ou integração com API (Resend, SendGrid, Mailgun) - Adicionar vars de ambiente no `config.rs`: `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`, `EMAIL_FROM` - Implementar `send_password_reset_email(to, reset_link)` - Implementar `send_verification_email(to, code)` ### Perfil de Usuário - [ ] **`update_me_handler`** (`src/adapters/inbound/user_handler.rs:64`) - Handler valida formato de email mas não persiste nada - Implementar chamada a `user_repo.update()` com os campos recebidos - Considerar campos permitidos: `name` (se adicionado ao domínio), `email` - Revalidar unicidade de email antes de atualizar --- ## Médio — Segurança - [ ] **Google OAuth: validar `aud` claim** (`src/adapters/inbound/auth_handler.rs:159`) - O parâmetro `_client_id` é recebido mas ignorado - Após obter o payload do tokeninfo do Google, verificar que `aud == GOOGLE_CLIENT_ID` - Rejeitar com `401 Unauthorized` se o `aud` não corresponder - Sem isso, qualquer Google token válido de qualquer app é aceito - [ ] **Logout: invalidar refresh token** (`src/adapters/inbound/auth_handler.rs:121`) - Atualmente retorna `204 No Content` sem nenhuma ação - Opção A (simples): tabela `revoked_tokens` no PostgreSQL com TTL via `expires_at` - Opção B (recomendada): Redis com `SET revoked:{jti} 1 EX ` - Middleware de auth deve checar blocklist ao validar tokens - Adicionar campo `jti` (JWT ID) aos tokens para identificação única --- ## Baixo — Qualidade e Completude - [ ] **Sort de filamentos não aplicado** (`src/adapters/outbound/postgres_filament_repo.rs`) - `SortOrder` enum está definido em `ports/filament_repository.rs` - SQL em `list()` sempre usa `ORDER BY created_at DESC`, ignorando o campo `sort` - `filament_handler.rs:203` tem `// TODO: parse sort string para SortOrder` — completar o parse - Aplicar o `SortOrder` no SQL com match: `net_weight_g ASC`, `net_weight_g DESC`, `created_at DESC` - [ ] **Paginação: retornar total de itens** - `FilamentRepository::count()` está implementado no repo mas nunca é chamado - `list_filaments_handler` não retorna metadados de paginação - Adicionar ao response: `{ data: [...], total: N, page: N, per_page: N }` - Chamar `repo.count(user_id, filter)` em paralelo com `repo.list()` - [ ] **`GET /spool-presets/:id` — handler ausente** - Rota está registrada no `router.rs` - Nenhum handler correspondente existe em `spool_preset_handler.rs` - Implementar `get_preset_handler` ou remover a rota do router - [ ] **Testes** - Sem nenhum teste unitário ou de integração no projeto - Prioridade: `AuthService` (hash, JWT), `FilamentService` (cálculos de peso, conflito offline), handlers de auth - Usar `sqlx::test` para testes de repositório com banco real em transação --- ## Referência Rápida — Arquivos por Área | Área | Arquivo | | --------------------- | ------------------------------------------------- | | Handlers de auth | `src/adapters/inbound/auth_handler.rs` | | Handler de usuário | `src/adapters/inbound/user_handler.rs` | | Handler de filamentos | `src/adapters/inbound/filament_handler.rs` | | Handler de presets | `src/adapters/inbound/spool_preset_handler.rs` | | Repo de usuário | `src/adapters/outbound/postgres_user_repo.rs` | | Repo de filamentos | `src/adapters/outbound/postgres_filament_repo.rs` | | Serviço de auth | `src/application/auth_service.rs` | | Config / env vars | `src/config.rs` | | Migrations | `backend/migrations/` |