# Correção: caches de bootstrap do Laravel no deploy (L2.1 + L2.1.1)

- **Branch:** grupo de correções `infra-update` (camada L2 — terceira camada do EPIC; P1 do roadmap)
- **Stack:** Laravel 5.5.50 / PHP 7.2.34 (cPanel/AlmaLinux/Apache 2.4 + EasyApache4)
- **Arquivos alterados:**
  - `routes/basepro.php` (remove 6 Closures de rota → habilita `route:cache`)
  - `app/Http/Controllers/Portal/InformationController.php` (`env()` → `config('gemini.*')`)
  - `app/Http/Controllers/Admin/ActivationController.php` (`env('APP_URL')` → `config('app.url')`)
  - `config/gemini.php` (novo — centraliza config do Gemini para `config:cache`)
  - `deploy.sh` (adiciona `config:cache`, `route:cache`, `optimize`, `opcache:clear`)
- **Categoria:** performance / cache de aplicação (tarefa #23410)
- **Seeds:** plano `pl-cc49` (rev 4) — L2.1/L2.1.1 (P1, junto de L1.1)

---

## 1. Problema

No baseline o `origem` estava em ~1594 ms (92% do TTFB). O `deploy.sh` **não** rodava
`config:cache`/`route:cache`/`optimize`, então a cada request o Laravel:

- re-parseava todos os arquivos de config (`config/*.php`) em runtime;
- re-resolvia todas as rotas (varria `routes/*.php`) por request;
- re-bootstrapava o container de serviços.

Para Laravel 5.5 isso é um miss grande de CPU/origem.

## 2. Causa real / pré-requisitos que bloqueavam o cache

### 2.1 `route:cache` falhava (Closures como ação de rota)

`php artisan route:cache` **serializa todas as rotas e falha se qualquer rota usar Closure
como ação** (2º argumento) ou como 3º argumento "after". Em `routes/basepro.php` havia 6
rotas bloqueadoras (todas no grupo `cms`/admin):

| Linha | Rota | Closure | Correção |
|---|---|---|---|
| `logout` | `Route::get('logout', '...@logout', function(){ abort(404); })` | 3º arg sobrescrevia o logout (bug) | removido o 3º arg |
| `activate` | `Route::get('/activate/...', '...@activate', function(){})` | 3º arg vazio | removido, mantido `->name('activate')` |
| `cms` `/` | `Route::get('/', function(){ return redirect()->route('dashboard.index'); })` | ação Closure | `Route::redirect('/', '/cms/dashboard')` |
| `acidade.getByState` | `Route::get('/acidade/get/byState/{state_id}', '...@getByState', function($state_id){})` | 3º arg vazio | removido, mantido o nome |
| `usuario.addRoles` (x2) | `Route::get('/usuario/.../add/roles', '...@addRules', function($user){})` | 3º arg vazio | removido, mantido o nome |

> Grupos `Route::group(..., function(){})` (em `web.php`, `api.php`, `basepro.php`) **não** bloqueiam
> `route:cache` — só ação/after Closure. Breadcrumbs (`routes/breadcrumbs.php`) e channels
> (`routes/channels.php`) também não afetam `route:cache`.

### 2.2 `config:cache` falhava (`env()` fora de `config/`)

`config:cache` faz `env()` retornar `null` em runtime (exceto dentro de `config/*`). Havia
`env()` em código de app:

- `app/Http/Controllers/Portal/InformationController.php` (GEMINI_API_URL/MODEL/KEY)
- `app/Http/Controllers/Admin/ActivationController.php` (`APP_URL`)

Corrigido para ler de `config()`:
- novo `config/gemini.php` expõe `gemini.api_url/api_model/api_key` (lê `env()` no build do cache);
- `InformationController` → `config('gemini.*')`;
- `ActivationController` → `config('app.url')`.

Após isso, **nenhum** `env()` resta fora de `config/` e `vendor/` → `config:cache` seguro.

## 3. Correção real

### 3.1 `routes/basepro.php` — L2.1.1

Removidos os 6 Closures (ver tabela 2.1). Nenhuma mudança de comportamento:
- `logout` agora executa `LoginController@logout` (o Closure `abort(404)` era um bug que impedia logout);
- `cms` `/` redireciona para `/cms/dashboard` (antes `redirect()->route('dashboard.index')`);
- rotas nomeadas mantêm os mesmos nomes (CSRF/admin inalterados).

### 3.2 `app/` + `config/gemini.php` — desbloqueio de `config:cache`

`env()` → `config()` (ver 2.2).

### 3.3 `deploy.sh` — L2.1

Após `storage:link` (e com `.env` presente), antes de servir:
```bash
php artisan config:cache
php artisan route:cache
php artisan optimize          # L5.5: cache de services/packages
php artisan opcache:clear 2>/dev/null || true   # se a ext opcache estiver presente
```

## 4. Retrocompatibilidade

- Rota `logout` **corrige um bug** (antes sempre 404).
- `cms` `/` continua redirecionando para o dashboard (agora via `Route::redirect`, URL literal `/cms/dashboard`).
- Nenhuma rota nomeada foi renomeada; admin/CSRF inalterados.
- `config:cache` exige rebuild ao mudar `.env` — já é o caso no deploy (roda no `deploy.sh`).
- Em desenvolvimento, **não** manter `route:cache`/`config:cache` (usa `php artisan route:clear`/`config:clear`).

## 5. Verificação (canário — `php` ausente neste sandbox)

```bash
# Pré-requisito (no canário/staging, após o deploy):
php artisan route:cache      # deve gerar bootstrap/cache/routes.php sem erro de Closure
php artisan config:cache     # deve gerar bootstrap/cache/config.php

# Sanidade de rotas (idêntico ao pré-cache):
php artisan route:list | grep -E 'logout|activate|cms|acidade.getByState|usuario.addRoles'

# Gemini continua funcional (usa config('gemini.*')):
curl -sI https://infra-update.devs.maxima.inf.br/<pagina-com-ia>   # sem 500

# Medir e comparar vs baseline e vs L1:
ETAPA=02-bootstrap-cache DESCRICAO="L2 config+route cache" \
  bash runners/medir_estrutura.sh infra-update.devs.maxima.inf.br
python3 ../comparar/comparar.py measuring/results/2026-09-08-12-10 measuring/results/<nova-data>
# esperado: queda de origem/ttfb (resolução de rotas + parse de config deixam de ocorrer por request)
```

## 6. Notas de deploy

- `route:cache` é **all‑or‑nothing**: se surgir Closure nova em qualquer rota carregada, o
  comando falha e aponta a rota — corrigir e repetir.
- `config:cache` + `optimize` só valem com `.env` presente no deploy (já é o caso).
- Guardrail: manter HTTP/2, TLS 1.3, redirects=0, disponibilidade=100% e os headers de segurança.
- L2.2 (driver de cache) e L2.3 (FPC) seguem como próximas frentes de L2 (P1 ainda inclui L2.3).
