Este documento descreve os controles de segurança efetivamente implementados no código. Itens planejados/futuros estão marcados como tal.
- JWT (HS256) — assinado com
SECRET_KEY(obrigatória; a app não sobe sem ela).JWTHandleremsrc/infrastructure/security/jwt_handler.py. - Login:
POST /api/v1/auth/logincom{email, password}(e-mail validado porEmailStr) retorna{access_token, refresh_token, token_type:"bearer", expires_in}. - Access token de curta duração (≈15 min;
expires_in=900) + refresh token. - Senhas: hash bcrypt com 12 rounds (
PasswordHasher(rounds=12),src/infrastructure/security/password_hasher.py). Senhas nunca são armazenadas em claro.
JWTContextMiddlewaredecodifica o token uma única vez e popularequest.state(tenant_id,user_id,email,roles) antes dos demais middlewares. Requisições à superfície protegida (/api/v1/*, exceto/api/v1/healthe/api/v1/auth/*) sem token válido recebem 401.TenantMiddlewaregarante que toda requisição protegida esteja escopada a um tenant; tentativas de acessar outro tenant via path/query retornam 403.- RBAC: dependência
require_roles(...)(src/api/dependencies.py) protege endpoints por papel; os papéis vêm do JWT (roles).
RateLimitMiddleware(token bucket por tenant/IP). Default 100 req/min (RATE_LIMIT_REQUESTS_PER_MINUTE/RATE_LIMIT_PER_MINUTE). Excedido → 429 comRetry-After. Estático/SPA e healthcheck ficam fora do limite.
Emitidos para toda resposta (src/api/main.py):
X-Content-Type-Options: nosniffX-Frame-Options: DENYStrict-Transport-Security: max-age=63072000; includeSubDomainsServer: ConciliaAI
Nota: não são emitidos hoje
Content-Security-Policy,Referrer-PolicynemX-XSS-Protection. Adicioná-los é melhoria recomendada.
Origens explícitas (não wildcard, pois allow_credentials=True). Em
desenvolvimento: localhost:3000/5173. Em produção, definidas via
CORS_ORIGINS. Na imagem única (mesma origem), CORS é irrelevante para o app.
- Toda resposta carrega
X-Request-ID. - Erros seguem o envelope
{ detail, error_code, request_id }(src/api/errors.py) — base para correlação em logs estruturados (structlog).
- Valores monetários: colunas
Numeric(15,2)no banco eMoney/Decimalno domínio. Na fronteira da API são tipados comoDecimale serializados como número JSON (src/api/serialization.py), sem perda na lógica de negócio.
SECRET_KEYdeve ser gerada por ambiente (openssl rand -hex 32) e nunca versionada. Odocker-compose.ymltraz um default APENAS para desenvolvimento; definaSECRET_KEYem produção.- Credenciais da Cielo Conciliator são opcionais no boot (a app sobe sem elas; as rotas Cielo retornam 503 até serem configuradas).
Os controles abaixo não existem no código atual e são candidatos a roadmap:
- Account lockout / bloqueio por tentativas de login.
- Row-Level Security (RLS) no PostgreSQL — o isolamento hoje é feito na
camada de aplicação (middleware + filtros por
tenant_idnas queries), não por policies do banco. Content-Security-Policy/Referrer-Policy.- Rotação automática de segredos / KMS.
Reporte de forma responsável (não abra issue pública com detalhes exploráveis). Use o canal de segurança do repositório.