CSRF: novo app/csrf.py + middleware em app/main.py garantem um cookie
csrf_token por navegador; todo formulario que muda estado (criar/editar/
excluir cliente, adicionar/editar/excluir contato) embute esse valor
como campo oculto, e Depends(exigir_csrf) confere no POST que o valor
enviado bate com o cookie antes de deixar a rota executar. Verificado
ponta a ponta com o app real rodando (curl): token errado -> 403,
token correto -> 303.
Paginacao: db_clientes.listar_clientes ganha offset, nova
contar_clientes(); GET /clientes aceita ?pagina=N (100 clientes por
pagina), template mostra Anterior/Proxima e o total.
53/53 testes passando (8 novos).
- Fix 1 (critico): cliente_form.html agora tem required/type por campo
(date/number) e o router captura DataError/IntegrityError em
criar/editar, reexibindo o form com erro_gravacao em vez de 500.
- Fix 2 (importante): auth.py falha fechado quando ADMIN_USER/
ADMIN_PASSWORD nao estao configurados (nao tenta mais compare_digest
com string vazia).
- Fix 3 (importante): avisos de codigo duplicado e DV invalido agora
carregam a flag de confirmacao um do outro adiante, quebrando o loop
quando ambos disparam no mesmo cliente.
- Fix 4 (menor): corrige precedencia 'or 42' -> 'and 42' no lambda de
teste de criar_cliente.
- Fix 5 (menor): desabilita /docs, /redoc, /openapi.json no FastAPI().
- Fix 6 (menor): comentario explicando o valor de Prorrogacao no fixture
de teste de chaves.
- Fix 7 (menor): .env.example usa host.docker.internal por padrao,
docker-compose.yml ganha extra_hosts para Linux, README.md novo com
quickstart real.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>