# Review do Reviewer — dashboard-logistico

**Base**: main · **HEAD**: 5edaf2f9 · **Commits**: 5

## Veredito
Voltar pro dev. 4 blockers + 5 majors.

## Blockers

### B1 — Raw SQL no Laboratório
**Onde**: `componentes/Missoes/Dashboards/sinais/Expedicao/Laboratorios/AutoSetupExpedicaoLaboratorio.php` linhas 39, 60-68, 115-130, 147-169, 188-212, 219-229, 236-248, 258-273.
**Problema**: Todos os writes usam `(new Connect())->getInstance()->prepare(...)`. A Sonda `DashboardExpedicaoSetupSonda` foi criada como shell vazio e nunca utilizada. Viola `feedback_no_raw_sql`.
**Correção**: Implementar `findByBlock`/`make`/`save`/`atualizarStatus` na Sonda (espelhar `EdicaoRotaSonda`). Migrar Laboratório para usar a Sonda. Raw SQL apenas para SELECT em `grupos_regioes` é tolerado se não houver Sonda equivalente.

### B2 — Migration chumba `block_empresa_id = block`
**Onde**: `Migrations/001_dashboard_expedicao_setup.sql:40-48` + `Laboratorios/AutoSetupExpedicaoLaboratorio.php:151, 207, 261-263`.
**Problema**: Seed e upserts assumem `block_empresa_id == block` por coincidência histórica. Viola `feedback_block_columns`.
**Correção**: Remover o seed da migration. Nos writes via Sonda (B1), `customerControl=true`/`companyControl=true` injetam `block_*` automaticamente — não passar essas colunas no array.

### B3 — Block extraction sem helper canônico nem Validator
**Onde**: `Satelites/StatusSetupSatelite.php:27-28`; `Expedicao.php:69-70`.
**Problema**: `getSession('galaxiaUserInfo')->customerData->id` lido inline em 2 pontos sem Validator dedicado.
**Decisão arquitetural** (do usuário): manter o padrão existente (`customerData->id` é a fonte canônica de block neste codebase, conforme README do Expedicao e `Filtros.php`), mas **encapsular em helper** `obterBlockDaSessao(): int` chamado pelos 2 sites + adicionar `Validators/StatusSetupValidator.php`.

### B4 — Sonda vazia
**Onde**: `Sondas/DashboardExpedicaoSetupSonda.php`.
**Problema**: Shell V2 sem métodos de domínio. Consequência direta de B1.
**Correção**: Junto com B1, adicionar `findByBlock`, `atualizarStatus`, etc.

## Majors

### M1 — i18n falsa (en/es em pt)
**Onde**: `linguagens/{en,es}.json`.
**Problema**: `show()` gera chave por MD5 da string e auto-registra com texto idêntico nos 3 idiomas. en e es estão em português.
**Correção**: Traduzir manualmente as 7 entradas em `en.json` e `es.json`.

### M2 — `exec()` sem checagem de `disable_functions` + log path
**Onde**: `Laboratorios/AutoSetupExpedicaoLaboratorio.php:114-130`.
**Correção**: `if (in_array('exec', array_map('trim', explode(',', (string) ini_get('disable_functions'))), true)) {…}`. Mover log para `LOCAL_NOVO_SISTEMA . '/logs/...'`.

### M3 — Falta Validator dedicado
**Onde**: `Satelites/StatusSetupSatelite.php`.
**Correção**: Criar `Validators/StatusSetupValidator.php` (validar `$opcao in ['verificar','iniciar']`, `$blockSessao > 0`, ignorar block em `$data`).

### M4 — Race no `iniciar`
**Onde**: `AutoSetupExpedicaoLaboratorio.php:53-72, 99-130`.
**Problema**: `upsertSetup` usa `ON CONFLICT DO UPDATE` que sempre atualiza → 2 abas concorrentes disparam 2 `exec`.
**Correção**: `INSERT ... ON CONFLICT DO NOTHING` → checar rowCount → se 0, `UPDATE ... WHERE block=:b AND status IN ('aguardando','falhou')` → checar rowCount → só dispara `exec` se mexeu linha.

### M5 — `register_shutdown_function` não cobre `kill -9`
**Onde**: `crons/dashboard_expedicao_diario.php:71-83`.
**Correção**: Ajustar comentário/spec — watchdog de 10min é a única defesa contra SIGKILL. Opcional: tratar SIGTERM via `pcntl_signal`.

## Minors

- **m1** — Frontend não pausa polling em `visibilitychange`.
- **m2** — Sem cleanup de timers em `beforeunload`.
- **m3** — `processarResposta` não loga warning em estado retrógrado.
- **m4** — Cast `::jsonb` redundante quando coluna já é jsonb.
- **m5** — Numbers mágicos (99991-99995) nos testes sem constante centralizada.
- **m6** — Emoji `❌` no log do cron — remover.

## Nits

- **n1** — Spec menciona `sql/dashboard_expedicao_setup.sql`, código usa `Migrations/001_*.sql`. Atualizar spec.
- **n2** — `Expedicao.php:75` re-dispara `exec` em `falhou` sem throttle. Combinado com F5 do user, gera N processos.
- **n3** — `formatarResposta` retorna `mensagem` em pt hard-coded.

## Pontos fortes
- Estrutura V2 textbook.
- Cron bem segmentado entre `--modo-setup` e legado.
- TDD T1-T12 cobrem 1:1 os Critérios de Aceite.
- Sanity gate nos testes (`SELECT current_database()`).
