The sidebar "Fiscal" entry now goes to /sso/fiscal. For a logged-in,
active employee the panel issues a JWT signed with Ed25519 (the private
key exists only here; GTI Fiscal only holds the public key): iss/aud
fixed, sub = funcionario:<ID> (LOGIN is editable), 60 s lifetime, unique
jti that GTI Fiscal records to reject replays. No password, hash or panel
cookie leaves the panel.
The assertion is delivered in an auto-submitted POST, never in the URL,
so it stays out of proxy logs, browser history and Referer. That page
carries its own CSP allowing form-action only to the configured callback
origin; the security-headers middleware now keeps a route-defined CSP.
Without a session the employee goes through the normal login and comes
back; plain HTTP is redirected to the public HTTPS address; `next` only
accepts a relative path; the .env bootstrap account (no stable ID) is
refused.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- app/rate_limit.py: bloqueia por IP após 5 tentativas de senha erradas
em 5 minutos em POST /login (rota pré-autenticação, hoje sem nenhuma
proteção contra força bruta).
- Cookie de sessão (routers/auth.py) e cookie CSRF (main.py) passam a
sair com Secure quando a requisição chega em HTTPS (request.url.scheme)
— hoje é sempre False porque produção ainda serve HTTP puro, mas o
cookie passa a ficar protegido automaticamente assim que um TLS for
colocado na frente, sem precisar editar isso de novo.
- main.py: novo middleware de security headers (X-Content-Type-Options,
X-Frame-Options: DENY, Referrer-Policy, Content-Security-Policy,
Strict-Transport-Security condicional a HTTPS).
- requirements.txt: fastapi 0.115.0 -> 0.115.6 (starlette >=0.40.0,
corrige DoS por memória não limitada ao parsear multipart/form-data —
GHSA-f96h-pmfr-66vw), python-multipart 0.0.9 -> 0.0.20 (várias
vulnerabilidades de DoS corrigidas), jinja2 3.1.4 -> 3.1.6 (escapes de
sandbox). httpx/uvicorn/PyMySQL já estavam em versões sem CVE
conhecida — conferido via osv.dev.
- Dockerfile: container não roda mais como root.
Suíte completa (181 testes) passando, incluindo testes novos para o
rate limiter (unitários + integração via POST /login) e smoke test
manual confirmando headers, fluxo de login com CSRF e o bloqueio por
força bruta.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Tabela LOG_PAINEL (nova, ja criada no banco de dev) + app/db/log.py:
toda criacao/edicao/exclusao de cliente e contato fica registrada
(usuario, acao, sucesso/erro, detalhe). Tela /log mostra esse
historico.
- app/n8n_client.py: leitura opcional (N8N_API_URL/N8N_API_KEY) da
Data Table pagamentos_processados do n8n, mostrando os envios
automaticos de chave na mesma tela /log. Degrada de forma segura
(lista vazia) se nao configurado ou se a chamada falhar.
- Lista de clientes ganha ordenacao configuravel (codigo/razao/
fantasia/CNPJ) via whitelist, alem da busca que ja existia.
- CODIGO duplicado agora BLOQUEIA de verdade na criacao/edicao (sem
bypass) — antes so avisava com opcao de confirmar mesmo assim.
- Formulario de novo cliente sugere o proximo CODIGO sequencial
(editavel), ignorando a faixa reservada para dados de teste
(>= 900000) para nao ser contaminado por sobra de teste no banco.
- IMPLANTACAO/MENSALIDADE/JUROS_MORA/JUROS_MULTA/DATA_CONTRATO/
VENCIMENTO_CONTRATO deixam de ser obrigatorios — em branco, gravam
default (0,00 / hoje) em vez de bloquear o cadastro. Só CODIGO/CNPJ/
RAZAO/FANTASIA continuam obrigatorios.
- Limpeza: removidas 10 linhas de teste vazadas (CODIGO 999902) que
ficaram no banco de dev por sessoes de teste interrompidas.
69/69 testes passando (16 novos).