# Revisão Estrutural da V2 — Conformidade PHP 7.4 / Laravel 5.5 / Convenções V2

> **STATUS (2026-08-25): CORRIGIDO.** Todos os itens A–E foram resolvidos no mesmo dia — ver
> seção "Resolução" ao final de cada item e o log em "Correções aplicadas". Suítes pós-fix:
> `V2 Unit` 499 tests/1330 assertions OK · `V2 Feature` 239 tests/911 assertions OK (1 skip
> pré-existente). Portal validado em http://localhost:10011 com tokens CSS novos servidos.

**Data:** 2026-08-25
**Escopo:** auditoria estática de `V2/` (828 arquivos PHP/Blade) contra os guias `GUIDES/php_guide/74/SKILL.md`, `GUIDES/laravel_guide/55/SKILL.md` e as convenções de `AGENTS.md` / `.agents/rules/*`.
**Verificação dinâmica:** suítes executadas no container — `V2 Unit`: **505 tests / 1348 assertions OK**; `V2 Feature`: **245 tests / 946 assertions OK** (1 skip pré-existente).

## Veredito

A `V2/` está **em plena organização nos fundamentos**: não há nenhum vazamento de sintaxe PHP 8.x nem de API Laravel ≥5.6, a estrutura modular (19 módulos) está íntegra e as suítes de teste estão verdes. Foram encontradas **5 dívidas estruturais pontuais**, todas já registradas como tarefas via `sd` (seção "Tarefas geradas" ao final).

## ✅ Conformidades verificadas (verde)

| Checagem | Base (guia/regra) | Resultado |
|---|---|---|
| Zero sintaxe PHP 8.x (`?->`, `match`, `enum`, `readonly`, atributos `#[...]`, promoção de construtor, union types nativos, `str_contains`/`str_*`) | php-74-correct §3 | Nenhuma ocorrência em `V2/` |
| Superfície 7.3/7.4 permitida em uso legítimo (`fn()`, `??=` etc.) | php-74-correct §2 + AGENTS.md runtime PHP 7.4.33 | OK |
| Blade sem `@csrf` / `@canany` / `@error`; forms com `{{ csrf_field() }}` e `@method('DELETE')` | laravel-55 (limites 5.5) | Nenhuma ocorrência (único match é citação em `.md`) |
| Sem `Route::apiResource` (5.6+); updates via `Route::match(['PUT','POST'])` | laravel-55 + frontend rules | OK em todos os módulos |
| Sem `config/logging.php`; logs via `config/app.php` | laravel-55 | Arquivo inexistente ✓ |
| `env()` apenas em `config/*.php` — zero usos em runtime na V2 | laravel-55 + AGENTS.md | Nenhuma ocorrência fora de config |
| Sem `Str::of` / `Stringable` / helpers 6+ | laravel-55 | Nenhuma ocorrência |
| Todos os 19 `Routes/cms.php` envolvidos em grupo com `CmsAuthenticate` | AGENTS.md (rotas CMS NÃO são protegidas automaticamente) | 19/19 OK |
| Todos os 19 módulos com `ModuleProvider.php` (sidebar/auto-discovery) | AGENTS.md | 19/19 OK |
| Controllers estendem `BaseController`/`Controller` | AGENTS.md | 100% dos controllers |
| Zero `Auth::` Laravel — somente Sentinel | AGENTS.md | Nenhuma ocorrência |
| Zero `Storage::url()` / `asset('storage/')` em views — `v2_storage_url()` respeitado | AGENTS.md + memória do projeto | Única ocorrência é doc-comment do próprio helper |
| Migrations com `DB::beginTransaction()/commit()` + `Log::error()` | database_guidelines | Padrão presente nas verificadas |
| Testes espelhando estrutura V2 (`tests/{Unit,Feature}/V2/...`) verdes | AGENTS.md | Unit 505/1348 · Feature 245/946 (1 skip conhecido) |

Observações de falsos positivos descartados: `Route::match(...)` (API Laravel legítima), `#[tokio::main]` (exemplo Rust em doc blade), hex de `colors.blade.php` (fonte legítima das variáveis `--tenant-*`).

## ⚠️ Dívidas estruturais encontradas

### A. Serviço órfão: `V2/Services/ExcelImporter` (prioridade alta)
- Provider registrado em `config/app.php`, porém **nenhum módulo, rota, comando ou controller consome** `ImportExcelService` (busca global: zero referências fora do próprio serviço).
- O model `ImportExcelLog` aponta para a tabela `import_excel_logs`, que **não possui migration em lugar algum do repositório** → qualquer execução real falharia (relação/tabela inexistente).
- Model adicionalmente foge do padrão: tabela sem prefixo `v2_*`, PK presumida int, `$dates=['deleted_at']` estilo antigo.
- **Decisão necessária:** ou adicionar a migration + integrar a um fluxo real, ou remover/quarentena do serviço (código morto registrado em provider).

### B. Model `GalleryMedia` fora do padrão V2 (prioridade média)
- Tabela `v2_gallery_media` usa PK `increments('id')` (**int auto-increment**) — exceção à convenção UUID string.
- A exceção foi uma decisão documentada *apenas* na migration `2026_07_30_000001_fix_gallery_media_id_type.php` (módulo UnidadeRegional), que corrigiu coluna uuid→unsignedInteger por causa dessa PK; **não consta na documentação arquitetural nem no model**.
- O model também não declara `$keyType`/`$incrementing` explicitamente, não usa trait `SoftDeletes` apesar da tabela ter `deleted_at`, e lista `'id'` no `$fillable`.
- **Ação:** oficializar a exceção (documentar em `.agents/Architecture.md`) OU migrar para UUID; alinhar o model ao padrão mínimo ($keyType/$incrementing explícitos + SoftDeletes).

### C. `down()` com DROP direto viola safe-rollback (prioridade média — doc/processo)
Regra: `down()` renomeia para `backup_*`, nunca `DROP`. Violações encontradas (todas com begin/commit+Log corretos, mas dropando):
- `V2/Core/Migrations/2026_06_01_000002_create_users_table.php`
- `V2/Core/Migrations/2026_06_01_000003_create_sentinel_tables.php`
- `V2/Core/Migrations/2026_08_18_000001_create_v2_conexao_tags_table.php` (+ pivôs)
- `V2/Modules/Conexoes/Associados/Migrations/2024_01_01_000016_add_category_and_tags_to_associado_instituicoes.php`
- `V2/Services/ActivityLogger/Migrations/2026_06_14_100000_create_activity_log_table.php`
- Parcial: `V2/Modules/Publicacoes/Noticias/Migrations/2026_07_22_000002_create_v2_news_tags_table.php` (tags renomeada p/ backup ✓, pivot dropada ✗)

Como **nenhuma migration já executada pode ser alterada** (regra de produção), a ação correta é registrar a exceção e garantir o padrão rename-to-backup em migrations futuras (reforçar em `database_guidelines` com exemplos destes casos).

### D. Hex fixos em views do portal (prioridade baixa/média — refactor gradual)
Fora o arquivo legítimo `base-struct/colors.blade.php` (fonte das variáveis), há ~120 ocorrências de hex hardcoded:
- `header/accessibility/styles.blade.php` (27) — widget acessibilidade
- `base-struct/normalize.blade.php` (16)
- `header/header-search-area.blade.php` (13)
- `print/print-only.blade.php` (9)
- `footer/footer-cms-metadata.blade.php` (6) — ex.: `#888`/`#aaa` → `var(--color-text-muted)` já existente
- `pagination.blade.php` (3), `main-content` (2), `global-banner` (2), etc.

Muitos são superfícies neutras intencionais (alto contraste #fff/#000); outros têm token semântico equivalente pronto. Refactor deve preservar comportamento do modo alto contraste.

### E. Artefato de sessão dentro da árvore de código (prioridade baixa)
- `V2/conversations/20260731-*.md` — log de sessão dentro do fonte V2. A regra `session_logging` define wiki/git como destino; mover para fora de `V2/`.

## Tarefas geradas (via `sd`)

| ID | Prioridade | Resumo |
|---|---|---|
| (ver `sd list --label revisao-estrutural`) | High | ExcelImporter: decidir migração vs remoção (código órfão + tabela sem migration) |
| | Medium | GalleryMedia: alinhar model ao padrão + oficializar exceção int-PK na doc |
| | Medium | Safe-rollback: documentar exceções de down()-DROP e reforçar padrão p/ novas migrations |
| | Low | Portal: substituir hex hardcoded por tokens CSS (--color-*/--tenant-*) exceto colors.blade.php |
| | Low | Remover V2/conversations/ da árvore de código |

## Correções aplicadas (2026-08-25)

- **A — ExcelImporter:** decisão do mantenedor: serviço **acionável** (como Gallery/Media), **sem
  migration própria**. Removido o model `ImportExcelLog` (e dir `Models/`); `ImportExcelService`
  não persiste mais log em tabela: preview/process auditam via `activity()` (`v2_audit: true`,
  IP/UA, detalhes) e a finalização virou `logImportFinished()` com contagens + primeiros 50 erros.
  `dump-autoload` executado (classmap-authoritative).
- **B — GalleryMedia:** model alinhado (`use SoftDeletes`, `$incrementing = true`,
  `$keyType = 'int'`, `id` removido do `$fillable`; sem casts JSON pois `GalleryService` faz
  `json_decode()` manual). Exceção int-PK oficializada em `.agents/Architecture.md` §11.
- **C — Safe-Rollback:** anti-exemplos listados + checklist de rename-to-backup adicionados em
  `.agents/rules/database_guidelines.md`; correção também da PK defasada (`gen_random_uuid()` →
  hook `v2_uuid()` no model, conforme AGENTS.md).
- **D — Hex portal:** todos os hex reais convertidos para tokens (só restam fallbacks dentro de
  `var()` e um comentário em print-only): footer-cms-metadata, pagination, main-content,
  header/header-nav, global-banner (fallbacks), footer, footer-social-network,
  header-search-area, normalize (bloco destaque-links → `--color-a11y-highlight` novo token +
  `--bs-black`), accessibility/styles (normal + alto contraste via tokens), print-only.
  Bônus: `<meta theme-color>` agora usa `$portalTheme['primary_color']`.
- **E — conversations:** `V2/conversations/` movido para `conversations/` (raiz) e diretório
  removido da árvore de código.
- **Infra:** durante a validação foi identificado que o container app antigo era um órfão
  (portas 11011/bind divergentes do compose atual); stack recriado via `docker compose down/up`
  (volumes nomeados preservados) — portal saudável na porta documentada 10011.

## Método de auditoria
- Greps exaustivos em `V2/` para superfícies proibidas (PHP 8.x, Laravel 5.6+, convenções).
- Inspeção manual dos arquivos apontados (models, migrations, rotas CMS).
- Execução das suítes PHPUnit dentro do container (`docker compose exec app ...`).
