# Implementation Plan: Sistema de Autenticação de Clientes **Branch**: `005-authentication` | **Date**: 2026-04-13 | **Spec**: [spec.md](spec.md) **Input**: Sistema de autenticação para clientes: login com e-mail + senha (JWT, sem OAuth), auto-cadastro público. ## Summary Adiciona autenticação JWT ao SaaS imobiliário. Backend: novo model `ClientUser` na tabela `client_users`, hashing de senha com bcrypt, emissão de token PyJWT com TTL de 7 dias, blueprint `/api/v1/auth` com endpoints register/login/me, e decorator `require_auth` reutilizável para proteger rotas. Frontend: `AuthContext` com persistência em `localStorage`, páginas Login e Cadastro no tema Linear escuro do projeto, interceptor Axios automático para injeção do header `Authorization`, e `ProtectedRoute` que guarda `/area-do-cliente/*`. ## Technical Context **Language/Version**: Python 3.12 (backend) · TypeScript 5.5 (frontend) **Primary Dependencies**: Flask 3.x, SQLAlchemy 2.x, Pydantic v2, PyJWT>=2.9, bcrypt>=4.2, pydantic[email]; React 18, react-router-dom v6, Axios **Storage**: PostgreSQL 16 via Flask-SQLAlchemy — nova tabela `client_users` via migration Alembic **Testing**: pytest + pytest-flask (backend); nenhum teste automatizado de frontend nesta fase **Target Platform**: Linux/Docker (servidor) + navegadores modernos (SPA) **Project Type**: Web service REST + Single Page Application **Performance Goals**: <200ms p95 nos endpoints de autenticação **Constraints**: Stateless JWT, TTL de 7 dias, sem refresh token, sem verificação de e-mail, sem rate limiting (escopo MVP definido na spec) **Scale/Scope**: MVP, ~100 usuários iniciais, single-tenant ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* | Princípio | Status | Justificativa | |-----------|--------|---------------| | **I. Design-First** | ✅ PASS | LoginPage e RegisterPage seguem DESIGN.md: fundo `#08090a`, panel `#0f1011`, tipografia Inter Variable, accent `#5e6ad2`/`#7170ff`, bordas `rgba(255,255,255,0.06)`. Mesmo estilo do PropertiesPage existente. | | **II. Separation of Concerns** | ✅ PASS | Flask retorna JSON puro; React é SPA. CORS configurado explicitamente em `create_app()`. Sem Jinja2 nas rotas da API. | | **III. Spec-Driven** | ✅ PASS | spec.md aprovado. Ciclo spec → plan → tasks → implement respeitado. | | **IV. Data Integrity** | ✅ PASS | Todos os inputs validados por Pydantic (`RegisterIn`/`LoginIn`). Migration Alembic. Tipos corretos (`String`, `UUID`, `DateTime`). `nullable=False` declarado explicitamente em todos os campos obrigatórios. | | **V. Security** | ✅ PASS | `JWT_SECRET_KEY` lido exclusivamente de variável de ambiente. bcrypt irreversível. 401 genérico em credenciais inválidas (SC-006). `password_hash` ausente em todas as respostas. | | **VI. Simplicity First** | ✅ PASS | 2 novos pacotes com razão clara (PyJWT para JWT, bcrypt para hashing). Sem refresh token, verificação de e-mail ou rate limiting (YAGNI — fora do escopo MVP conforme assumptions da spec). Sem flask-jwt-extended (overhead desnecessário). | **Gate Result**: ✅ PASS — nenhuma violação. Prosseguir para Phase 0. ## Project Structure ### Documentation (this feature) ```text .specify/features/005-authentication/ ├── plan.md # Este arquivo ├── research.md # Fase 0 — resolução de unknowns (gerado) ├── data-model.md # Fase 1 — modelo de dados (gerado) ├── quickstart.md # Fase 1 — como rodar e testar (gerado) ├── contracts/ │ └── auth-api.md # Contratos dos endpoints /api/v1/auth (gerado) └── tasks.md # Fase 2 — gerado pelo /speckit.tasks ``` ### Source Code ```text backend/ ├── app/ │ ├── models/ │ │ └── user.py # ClientUser — NOVO │ ├── schemas/ │ │ └── auth.py # RegisterIn, LoginIn, UserOut, AuthTokenOut — NOVO │ ├── routes/ │ │ └── auth.py # auth_bp (/api/v1/auth) — NOVO │ ├── utils/ │ │ └── auth.py # require_auth decorator — NOVO │ └── __init__.py # ATUALIZADO: user model import + auth blueprint + JWT_SECRET_KEY ├── migrations/versions/ │ └── _add_client_users.py # NOVO — gerado via flask db migrate └── pyproject.toml # ATUALIZADO: PyJWT>=2.9, bcrypt>=4.2, pydantic[email] frontend/ └── src/ ├── types/ │ └── auth.ts # User, AuthState — NOVO ├── contexts/ │ └── AuthContext.tsx # AuthProvider, useAuth — NOVO ├── services/ │ ├── api.ts # ATUALIZADO: interceptor Authorization header │ └── auth.ts # registerUser, loginUser, getMe — NOVO ├── pages/ │ ├── LoginPage.tsx # rota /login — NOVO │ └── RegisterPage.tsx # rota /cadastro — NOVO ├── components/ │ ├── ProtectedRoute.tsx # redireciona se !isAuthenticated — NOVO │ └── Navbar.tsx # ATUALIZADO: Entrar / avatar + Sair └── App.tsx # ATUALIZADO: AuthProvider wrap + novas rotas ``` ## Complexity Tracking *Sem violações de constituição — esta seção não se aplica.*