docs: corrige README contraditorio sobre HTTP Basic e SESSION_SECRET

1. Frase de abertura ainda dizia 'login HTTP Basic em toda rota',
   contradizendo a secao 'Login e permissoes' mais abaixo no mesmo
   arquivo (ja correta, fala de login por sessao). Atualizada para
   'login por sessao em toda rota'.
2. A lista de variaveis de ambiente para rodar localmente (secao
   'Rodando localmente') nao mencionava SESSION_SECRET, mesmo a secao
   'Login e permissoes' ja instruindo a defini-la. Adicionada a lista,
   com nota de que e opcional em dev (chave aleatoria em memoria a cada
   start, sessoes caem a cada restart) mas deve ser fixa em producao.
3. A mencao ao ALTER TABLE FUNCIONARIO_PAINEL ADD COLUMN PERFIL estava
   em tom de fato passado. Ajustada para o mesmo padrao de aviso ja
   usado para LOG_PAINEL/FUNCIONARIO_PAINEL nesse README ('precisa ser
   rodado manualmente em producao tambem'), deixando explicito que sem
   rodar isso todo login falha com 500 (a query de autenticacao
   seleciona uma coluna PERFIL que nao existe na tabela antiga).

Sem teste automatizado - mudanca só de documentacao.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Gustavo
2026-08-13 21:19:09 -03:00
co-authored by Claude Sonnet 5
parent e5f5d4211c
commit 7656f2261e
+11 -7
View File
@@ -2,7 +2,7 @@
Painel administrativo (FastAPI + Jinja2) para gestão de `CLIENTE`, `CLIENTE_CONTATO` e geração manual de chave de licenciamento no MySQL do sistema legado.
Proteções: login HTTP Basic em toda rota, CSRF via cookie de duplo envio (`app/csrf.py` — todo formulário que muda estado embute o mesmo token do cookie `csrf_token`, definido pelo middleware em `app/main.py`) e a lista de clientes é paginada (100 por página), com busca e ordenação por código/razão/fantasia/CNPJ.
Proteções: login por sessão em toda rota (cookie assinado — ver seção "Login e permissões" abaixo), CSRF via cookie de duplo envio (`app/csrf.py` — todo formulário que muda estado embute o mesmo token do cookie `csrf_token`, definido pelo middleware em `app/main.py`) e a lista de clientes é paginada (100 por página), com busca e ordenação por código/razão/fantasia/CNPJ.
`CODIGO` de cliente não aceita duplicado (bloqueio duro, sem bypass) e o formulário de novo cliente já sugere o próximo código sequencial (editável). Só `CODIGO`, `CNPJ`, `RAZAO` e `FANTASIA` são obrigatórios — os campos de contrato (implantação, mensalidade, juros, datas) podem ficar em branco e recebem default (0,00 / data de hoje).
@@ -21,11 +21,15 @@ ser criada manualmente em produção também**, DDL no início de
`app/db/funcionarios.py`) tem um perfil: **admin** (gerencia outros
funcionários em `/funcionarios`: cadastra, edita, redefine senha,
ativa/desativa, promove/rebaixa perfil) ou **padrão** (sem acesso a
`/funcionarios`). Todo funcionário cadastrado antes dessa funcionalidade
existir virou admin automaticamente na migração (`ALTER TABLE
FUNCIONARIO_PAINEL ADD COLUMN PERFIL ...`, mesmo arquivo). O sistema nunca
deixa ficar sem nenhum admin ativo — rebaixar ou desativar o último admin é
bloqueado.
`/funcionarios`). Se `FUNCIONARIO_PAINEL` já existir de uma instalação
anterior sem a coluna `PERFIL`, rode o `ALTER TABLE FUNCIONARIO_PAINEL ADD
COLUMN PERFIL ...` (DDL completo em `app/db/funcionarios.py`) — **precisa
ser rodado manualmente em produção também**; sem essa coluna, todo login
falha com erro 500 (a query de autenticação seleciona `PERFIL`, que não
existe na tabela antiga). O `DEFAULT 'ADMIN'` desse `ALTER TABLE` é
intencional: todo funcionário cadastrado antes da migração vira admin
automaticamente. O sistema nunca deixa ficar sem nenhum admin ativo —
rebaixar ou desativar o último admin é bloqueado.
Qualquer usuário logado troca a própria senha em **Minha conta**
(`/minha-conta`), pedindo a senha atual antes de trocar.
@@ -42,7 +46,7 @@ a tabela ficar vazia. Login checa primeiro o admin do `.env`, depois
```
pip install -r requirements-dev.txt
```
2. Defina as variáveis de ambiente necessárias (`ADMIN_USER`, `ADMIN_PASSWORD`, `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD` — veja `.env.example`) diretamente no shell antes de subir a aplicação. **Importante:** apesar de `python-dotenv` estar nas dependências, nada no código chama `load_dotenv()` hoje — um arquivo `.env` sozinho NÃO é lido automaticamente fora do Docker. Exporte as variáveis manualmente (ex.: `set -a; source .env; set +a` no bash, ou `$env:...` no PowerShell) ou defina-as por outro meio.
2. Defina as variáveis de ambiente necessárias (`ADMIN_USER`, `ADMIN_PASSWORD`, `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD`, `SESSION_SECRET` — veja `.env.example`) diretamente no shell antes de subir a aplicação. `SESSION_SECRET` é opcional em dev — sem ela, uma chave aleatória é gerada em memória a cada start (sessões caem a cada restart); defina um valor fixo em produção. **Importante:** apesar de `python-dotenv` estar nas dependências, nada no código chama `load_dotenv()` hoje — um arquivo `.env` sozinho NÃO é lido automaticamente fora do Docker. Exporte as variáveis manualmente (ex.: `set -a; source .env; set +a` no bash, ou `$env:...` no PowerShell) ou defina-as por outro meio.
3. Rode a aplicação:
```
uvicorn app.main:app --reload