Atualização de Read.me e \correção da autorização no primeiro login

This commit is contained in:
2026-08-28 02:19:08 -03:00
parent ab126d13db
commit b20299dd6b
4 changed files with 222 additions and 6 deletions

153
README.md
View File

@@ -3360,3 +3360,156 @@ config/routes.rb # POST atualizar_logo
```
</details>
---
<details>
<summary><strong>🩺 28/08/2026 — "A primeira vez que entra dá tela de erro" + os assets 404 que o Cloudflare escondia</strong></summary>
Dois problemas achados a partir de **um** relato ("a primeira vez que entra dá a
tela de erro, em `/auth/login`"). O primeiro era o relatado; o segundo apareceu
com o navegador aberto na mesma tela e era o mais grave dos dois.
| Sintoma na tela | Causa real | Onde se resolveu |
|---|---|---|
| Primeira entrada do dia parece falha do sistema | `devise.failure.unauthenticated` sai como `flash[:alert]` — vermelho, e **duas vezes** | `Users::SessionsController#new` |
| Carrossel e editor de romaneio mortos no teste | `RAILS_ENV=production` + **nada no deploy pré-compilava assets** | `bin/docker-boot` (passo 5) |
## 1. O "erro" que era só o Devise pedindo login
Quem abre `teste.reemtransportes.com.br` deslogado — ou seja, **toda** primeira
entrada — passa por `authenticate_user!`, que redireciona para `/auth/login`
gravando `flash[:alert] = "Para continuar, faça login."`. Como `alert`, a
mensagem saía **em vermelho e em dois lugares ao mesmo tempo**: o toast com
triângulo de alerta no canto superior direito (`layouts/application.html.erb`) e
a caixa vermelha acima do formulário (`devise/sessions/new.html.erb`).
Entrar no sistema pelo caminho normal ficava com a cara de sistema quebrado. E
como na segunda visita a pessoa já está em `/auth/login` sem flash nenhum, a tela
aparecia limpa — daí o "só na primeira vez", que fazia parecer bug intermitente.
A mensagem agora é **descartada**: a tela já é o formulário de login, o aviso não
acrescenta nada.
```ruby
# app/controllers/users/sessions_controller.rb
flash.delete(:alert) if flash[:alert] == I18n.t('devise.failure.unauthenticated', default: nil)
```
⚠️ **O filtro é pela mensagem exata, e não `flash.delete(:alert)` seco.** Senha
errada, conta desativada e `timeout` ("Sua sessão expirou") chegam ao mesmo
`#new` pelo mesmo caminho — essas **precisam** continuar vermelhas. Apagar o
alerta inteiro no `new` deixaria a pessoa digitando a senha errada para sempre
sem entender por quê.
## 2. Os assets 404 — e por que ninguém tinha visto
O console da tela de login acusava dois módulos:
```
Failed to fetch dynamically imported module:
/assets/controllers/carrossel_controller-913b47f7.js -> 404
/assets/controllers/romaneio_controller-0105d794.js -> 404
```
Não é pouco: `carrossel_controller` é a **paginação por tamanho de tela** (a
regra 3 do `CLAUDE.md`) e `romaneio_controller` é o editor de romaneio inteiro.
Os dois estavam mortos no ambiente de teste.
### O disfarce
À primeira vista pareciam só dois arquivos com problema — os outros dez
controllers respondiam 200. **Não respondiam.** Os 200 vinham do **cache do
Cloudflare**:
```
$ curl -sI .../validacao_controller-ca4de84f.js
cache-control: public, max-age=31536000, immutable
age: 275844 # ~3,2 dias em cache
cf-cache-status: HIT # ← nunca chegou no servidor
```
Os assets saem com `max-age` de **um ano**. Os dez que "funcionavam" eram cópias
guardadas na borda dias antes; os dois quebrados eram os dois arquivos alterados
**depois** dessa fotografia. Batendo direto na origem (com querystring, para
furar o cache), **todos** davam 404.
> **Lição de diagnóstico:** ao investigar asset em produção, olhe
> `cf-cache-status` antes de concluir qualquer coisa. `HIT` não é prova de que o
> servidor está servindo — é prova de que ele serviu **algum dia**.
### A causa
O corpo do 404 era `public/404.html`, ou seja, a requisição chegou no **roteador
do Rails**: o servidor de assets do Propshaft nem estava montado. E a resposta do
HTML não trazia o cabeçalho `Server-Timing`, que só existe em development
(`config.server_timing`). Somando os dois: **o servidor roda
`RAILS_ENV=production`**.
Em production o Propshaft **não compila sob demanda** — ele resolve o caminho
pelo `public/assets/.manifest.json` e o arquivo digerido tem que existir em
disco. E nada no deploy gerava isso:
- a linha `RUN bundle exec rails assets:precompile` do `Dockerfile` estava
**comentada** (e não adiantaria descomentar: o compose monta `.:/app` por cima
e apagaria o `public/assets` da imagem);
- `bin/docker-boot` não tocava no assunto;
- `/public/assets` é **gitignorado**.
Resultado: o que existia no servidor era o resto de algum `precompile` manual
antigo. Todo JS alterado depois dele virava 404 silencioso — silencioso porque a
tela **continua abrindo** (o Tailwind vem de CDN e os ícones são `public/`
direto), só sem comportamento.
### A correção
Novo **passo 5** no `bin/docker-boot`, que roda em todo start de container — logo,
em todo deploy:
```bash
if [ "${RAILS_ENV:-development}" = "production" ]; then
rm -rf public/assets tmp/cache/assets
bundle exec rails assets:precompile
else
rm -rf public/assets # em dev o Propshaft calcula o digest ao vivo
fi
```
- **Limpa antes de pré-compilar**: sem isso um manifesto antigo convive com
arquivos novos e a divergência volta na primeira alteração de JS. Assim
manifesto e arquivos saem sempre da **mesma execução**. (`rm -rf` em vez de
`rails assets:clobber`: faz o mesmo sem pagar outro boot do Rails.)
- **Falha não derruba o boot**: `exit 1` aqui viraria loop de reinício com o
`restart: unless-stopped` e deixaria todo mundo de fora. O erro é gritado no
log — o que não podia continuar é a falha **muda**.
- **Em development apaga `public/assets`**: sobra de precompile faz o Propshaft
voltar a resolver pelo manifesto, e aí alteração de JS só aparece depois de
recompilar — parece cache do navegador quando não é.
### Como conferir depois do deploy
```bash
# 1. os assets do HTML respondem na ORIGEM (querystring fura o cache do CDN)
curl -s https://teste.reemtransportes.com.br/auth/login \
| grep -o '/assets/controllers/[a-z_]*-[a-f0-9]*\.js' | sort -u \
| while read a; do
printf "%s -> " "$a"
curl -s -o /dev/null -w "%{http_code}\n" "https://teste.reemtransportes.com.br$a?cb=$RANDOM"
done
# 2. o passo apareceu no log do boot
docker compose logs app | grep '\[boot\] assets'
```
Todos têm que responder **200**. Se algum der 404, o `precompile` não rodou ou
falhou — o log do passo 5 diz qual dos dois.
## 📂 Arquivos
```
app/controllers/users/sessions_controller.rb # descarta o "faça login" vermelho
bin/docker-boot # passo 5: clobber + precompile
Dockerfile # tira a linha de precompile morta e explica por quê
```
</details>