---
id: MATRIZ-RECONCILIACAO
tipo: matriz
onda: 5
status: concluido
unidades: []
fontes:
  - V2/Modules/
  - V2/Services/
  - V2/Core/Routes/
depende_de: [MATRIZ-SINGULARIDADES, MATRIZ-ENTIDADES, MATRIZ-INTEGRACOES, MATRIZ-FLAGS]
consumidores: [REIMPL-PARIDADE, REIMPL-ORDEM]
criticidade: alta
dono: Matriz
---

# Reconciliação dos índices: 44/308 × 301, 386 × 386, 87 × 60

Este documento fecha a conta entre o que existe no código e o que os índices
canônicos registram. Toda diferença é classificada (grupo, redirect, duplicata,
blade de layout, página de erro, arquivo morto) e o que falta é listado com
nome. Números medidos em 2026-10-21, depois da consolidação da Onda 5.

## 1. Efeito

### Ficha de identidade

| Campo | Valor |
|---|---|
| Efeito primário | Prova que os índices canônicos cobrem (ou não) 100% das rotas, blades, tabelas, permissões, configs e seeds, e lista exatamente o que falta. |
| Entrada | 44 route files / 308 chamadas `Route::*`; 386 blades; 87 migrations; 20 `ModuleProvider`; 159 índices parciais. |
| Saída | Tabela de reconciliação por dimensão; diferenças explicadas; `_indices/arquivos.csv` com mortos; lista de lacunas para paridade. |
| Efeitos colaterais | `arquivos.csv` passa de 0 para 4 linhas; nenhum índice canônico além dele foi alterado. |
| Particularidade central | A contagem do enunciado (277 rotas / 57 tabelas / 325 componentes) era o estado **antes** da consolidação; o estado atual é **301 / 60 / 386**. A diferença não é erro de contagem: é a Onda 5 integrando Sobre Nós, Homepage, ExemploAPI, SEO e seeds. |
| Como se integra | Alimenta `09_reimplementacao/paridade.md`; referencia `MATRIZ-ENTIDADES` e `MATRIZ-FLAGS`. |
| Se removido, quebra | Não há como afirmar paridade: as lacunas voltam a ser invisíveis. |
| Superfície pública | Documento markdown + `_indices/arquivos.csv`. |

### 1.1 O quadro geral

| Dimensão | No código | No índice | Delta | Situação |
|---|---|---|---|---|
| Arquivos de rota | 44 | 44 mapeados por unidade | 0 | todos os arquivos pertencem a uma unidade |
| Chamadas `Route::*` | 308 | 301 linhas em `rotas.csv` | **7** | 8 grupos faltando, 1 grupo espúrio; endpoints completos |
| Endpoints registrados | 268 | 268 (262 `endpoint` + 4 `redirect` + 2 `rota`) | **0** | cobertura completa |
| Wrappers (grupo/prefix/middleware) | 40 | 33 `grupo` | **7** líquidos | 8 faltando, 1 espúrio |
| Blades | 386 | 386 linhas | **0** | 386 caminhos do disco; sem `.bak` e sem ausência |
| Migrations | 87 | — | — | 47 create, 26 rename/drop, 1 alter, 13 outros |
| Tabelas atuais | 57 | 57 + 3 históricas = 60 | 0 | cobertura completa |
| Permissões | 20 chaves de módulo (+ aliases) | 67 linhas | — | 27 linhas de `CORE-AUTH` são atores/aliases |
| Configs | 166 chaves | 166 linhas | 0 | consolidado |
| Serviços | 13 | 13 linhas | 0 | — |
| Seeds | 15 seeders | 15 linhas | 0 | consolidado |
| `arquivos.csv` | 4 mortos identificados | 4 linhas | 0 | criado nesta onda |

## 2. Abordagem

### 2.1 Rotas: 308 chamadas → 301 linhas

Contagem das 308 chamadas não comentadas nos 44 arquivos:

| Tipo de chamada | Quantidade | Vira linha? | Como o CSV representa |
|---|---|---|---|
| `Route::get` | 134 | sim | `endpoint`, método `GET` |
| `Route::post` | 94 | sim | `endpoint`, método `POST` |
| `Route::delete` | 22 | sim | `endpoint`, método `DELETE` |
| `Route::match` | 14 | sim (1 linha por chamada) | `endpoint`, método `PUT/POST`, `PUT,POST` etc. |
| `Route::put` | 2 | sim | `endpoint`, `PUT` |
| `Route::redirect` | 2 | sim | `redirect`, método `ANY` |
| `Route::group` | 38 | sim (metadado) | `grupo` |
| `Route::prefix(...)->group` | 1 | sim (metadado) | `grupo` (Homepage) |
| `Route::middleware(...)->group` | 1 | sim (metadado) | `grupo` (MailService) |
| **Total** | **308** | — | — |

Linhas do CSV: `262 endpoint + 4 redirect + 33 grupo + 2 rota = 301`.

#### 2.1.1 Endpoints: 268 no código × 268 no CSV

O código registra **268** endpoints (134 GET + 94 POST + 22 DELETE + 14 match
+ 2 PUT + 2 `Route::redirect`). O CSV tem **268** (262 `endpoint` + 4
`redirect` + 2 `rota`). O ExemploAPI entrou na consolidação com 2 endpoints e 1
grupo (`R-EXEMPLOAPI-01/02/03`), fechando a conta:

| Unidade | Endpoints no CSV | Situação |
|---|---|---|
| `MOD-_EXEMPLOS-EXEMPLOAPI` | 2 (`GET /cms/exemplo-api`, `POST /cms/exemplo-api/demo-store`) | coberto |
| demais 26 unidades | 266 | cobertas |

As duas linhas do SEO (`SEO-R01` `/robots.txt`, `SEO-R02` `/sitemap.xml`) estão
com `tipo=rota`, que **não é um valor da taxonomia** (`endpoint|grupo|redirect`).
São endpoints reais e contam em §2.1.1; a correção é retipar para `endpoint`.

Os 4 `redirect` do CSV são:

| Linha | URI | Origem | Observação |
|---|---|---|---|
| `R-CORE-01` | `/login` | `Route::redirect` | `V2/Core/Routes/cms.php:11` |
| `R-CORE-09` | `/cms/dashboard` | `Route::redirect` | `V2/Core/Routes/cms.php:24` |
| `R-SOBRENOS-14` | `/diretoria` | `Route::get` + resposta 301 do controller | `V2/Modules/Institucional/SobreNos/Routes/web.php:14-15` |
| `R-SOBRENOS-15` | `/diretoria/{slug}` | `Route::get` + resposta 301 do controller | `V2/Modules/Institucional/SobreNos/Routes/web.php:17-18` |

Ou seja: o CSV classifica como `redirect` dois GETs que o código conta como
endpoint. Isso não cria delta porque ambos os lados somam 4 e 2
respectivamente; a diferença é de **tipo**, não de quantidade.

#### 2.1.2 Wrappers: 40 no código × 33 no CSV

O código tem **40** wrappers (38 `Route::group` + 1 `Route::prefix` + 1
`Route::middleware`). O CSV tem **33** linhas `tipo=grupo`. Faltam **8** e há
**1** espúrio:

| Unidade | Wrapper no código | Linha no CSV? | Evidência |
|---|---|---|---|
| `CORE-BOOT` | grupo de autenticação `cms/login` | **falta** | `V2/Core/Routes/cms.php:14-19` |
| `CORE-BOOT` | grupo protegido `cms` | presente (`R-CORE-02`) | `:22-33` |
| `MOD-INFRAESTRUTURA-CERTIFICADODIGITAL` | grupo `cms/certificado-digital` | **falta** | `V2/Modules/Infraestrutura/CertificadoDigital/Routes/cms.php:13-16` |
| `MOD-INFRAESTRUTURA-FEEDRSS` | grupo `cms/v2/feed-rss` | **falta** | `V2/Modules/Infraestrutura/FeedRss/Routes/cms.php:5-8` |
| `MOD-INFRAESTRUTURA-GESTAOPERMISSOES` | grupo `cms/permissoes` | **falta** | `V2/Modules/Infraestrutura/GestaoPermissoes/Routes/cms.php:9` |
| `MOD-INFRAESTRUTURA-MAILAUDIT` | grupo `cms/mail-audit` | **falta** | `V2/Modules/Infraestrutura/MailAudit/Routes/cms.php:13-16` |
| `MOD-SUPPORT-STRUCTURALLANDINGEDITOR` | grupo `cms/infra/structural-editor` | presente (`SLE-ROTA-01`) | `V2/Modules/Support/StructuralLandingEditor/Routes/cms.php:17` |
| `MOD-SUPPORT-SUPPORTCONFIGS` | 2 grupos | presentes (`R-G01`,`R-G02`) | `V2/Modules/Support/SupportConfigs/Routes/cms.php:18,61` |
| `MOD-INSTITUCIONAL-SOBRENOS` | grupo CMS | presente | `V2/Modules/Institucional/SobreNos/Routes/cms.php:3-6` |
| `MOD-INSTITUCIONAL-SOBRENOS` | grupo web `/sobre-nos` | **falta** | `V2/Modules/Institucional/SobreNos/Routes/web.php:3-5` |
| `MOD-LAYOUTS-BASICPAGE` | grupo `cms/paginas-fixas` | presente | `V2/Modules/Layouts/BasicPage/Routes/cms.php:9` |
| `MOD-LAYOUTS-BASICPAGE` | **nenhum** na web | **espúrio** `R-BASICPAGE-16` `/` | a rota `/` foi removida da web (`V2/Modules/Layouts/BasicPage/Routes/web.php:8`) |
| `MOD-LAYOUTS-HOMEPAGE` | grupo `cms/homepage` | presente | `V2/Modules/Layouts/Homepage/Routes/cms.php:5` |
| `SVC-CONTENTRICHEDITOR` | grupo `cms/v2/editor` | presente | `V2/Services/ContentRichEditor/Routes/cms.php:9` |
| `SVC-LANDINGSECTIONSEDITOR` | grupo `cms/v2/landing-sections` | presente | `V2/Services/LandingSectionsEditor/Routes/cms.php:9` |
| `SVC-GALLERY` | grupo `cms/v2/gallery` | **falta** | `V2/Services/Gallery/Routes/cms.php:5` |
| `SVC-MAILSERVICE` | grupo `cms` da API | **falta** | `V2/Services/MailService/Routes/api.php:21` |

Conta: 33 linhas − 1 espúria + 8 ausentes = 40 wrappers. Como os endpoints estão
completos, o delta total é **7** (308 − 301).

#### 2.1.3 Duplicatas, comentários e arquivo vazio

| Caso | Fato | Efeito | Evidência |
|---|---|---|---|
| Duplicata funcional | `POST /cms/noticias/categorias` declarado **duas vezes** (uma com `categories.index`, outra com `categories.store`) | a primeira é engolida pelo `RouteCollection`; só a segunda responde | `V2/Modules/Publicacoes/Noticias/Routes/cms.php:111-119` |
| Duplicata no índice | as duas linhas existem (`R28` e `R20`) | o índice conta 2, o runtime executa 1 | `_indices/rotas.csv` |
| Comentários | 2 linhas `Route::` comentadas (`/` do Core, `/status` da API) | não contam nas 308 | `V2/Core/Routes/web.php:11`; `V2/Core/Routes/api.php:10` |
| Arquivo vazio | `V2/Core/Routes/api.php` registra 0 rotas | é um dos 44 arquivos, mas não gera linha | `V2/Core/Routes/api.php:1-10` |

#### 2.1.4 Os 44 arquivos (contagem de chamadas)

| # | Arquivo | Endpoints | Wrappers |
|---|---|---|---|
| 1 | `V2/Core/Routes/api.php` | 0 | 0 |
| 2 | `V2/Core/Routes/cms.php` | 12 | 2 |
| 3 | `V2/Core/Routes/fallback.php` | 1 | 0 |
| 4 | `V2/Core/Routes/web.php` | 1 | 0 |
| 5 | `V2/Modules/Conexoes/Associados/Routes/cms.php` | 13 | 1 |
| 6 | `V2/Modules/Conexoes/Associados/Routes/web.php` | 3 | 1 |
| 7 | `V2/Modules/Conexoes/ParceirosInstitucionais/Routes/cms.php` | 9 | 1 |
| 8 | `V2/Modules/Conexoes/ParceirosInstitucionais/Routes/web.php` | 2 | 1 |
| 9 | `V2/Modules/Conexoes/UnidadeRegional/Routes/api.php` | 9 | 1 |
| 10 | `V2/Modules/Conexoes/UnidadeRegional/Routes/cms.php` | 16 | 1 |
| 11 | `V2/Modules/Conexoes/UnidadeRegional/Routes/web.php` | 2 | 1 |
| 12 | `V2/Modules/Infraestrutura/CertificadoDigital/Routes/cms.php` | 7 | 1 |
| 13 | `V2/Modules/Infraestrutura/FeedRss/Routes/cms.php` | 3 | 1 |
| 14 | `V2/Modules/Infraestrutura/GestaoPermissoes/Routes/cms.php` | 11 | 1 |
| 15 | `V2/Modules/Infraestrutura/MailAudit/Routes/cms.php` | 2 | 1 |
| 16 | `V2/Modules/Institucional/AssocieSe/Routes/cms.php` | 13 | 1 |
| 17 | `V2/Modules/Institucional/AssocieSe/Routes/web.php` | 3 | 1 |
| 18 | `V2/Modules/Institucional/FaleConosco/Routes/cms.php` | 4 | 1 |
| 19 | `V2/Modules/Institucional/FaleConosco/Routes/web.php` | 2 | 1 |
| 20 | `V2/Modules/Institucional/Historia/Routes/cms.php` | 11 | 1 |
| 21 | `V2/Modules/Institucional/Historia/Routes/web.php` | 1 | 1 |
| 22 | `V2/Modules/Institucional/SobreNos/Routes/cms.php` | 11 | 1 |
| 23 | `V2/Modules/Institucional/SobreNos/Routes/web.php` | 4 | 1 |
| 24 | `V2/Modules/Layouts/BasicPage/Routes/cms.php` | 15 | 1 |
| 25 | `V2/Modules/Layouts/BasicPage/Routes/web.php` | 4 | 0 |
| 26 | `V2/Modules/Layouts/Homepage/Routes/cms.php` | 3 | 1 |
| 27 | `V2/Modules/Layouts/Homepage/Routes/web.php` | 1 | 0 |
| 28 | `V2/Modules/Publicacoes/Agenda/Routes/cms.php` | 6 | 1 |
| 29 | `V2/Modules/Publicacoes/Agenda/Routes/web.php` | 2 | 1 |
| 30 | `V2/Modules/Publicacoes/Noticias/Routes/cms.php` | 21 | 2 |
| 31 | `V2/Modules/Publicacoes/Noticias/Routes/web.php` | 4 | 1 |
| 32 | `V2/Modules/Publicacoes/TrabalheConosco/Routes/cms.php` | 10 | 1 |
| 33 | `V2/Modules/Publicacoes/TrabalheConosco/Routes/web.php` | 3 | 1 |
| 34 | `V2/Modules/Support/NoticiasImport/Routes/api.php` | 2 | 1 |
| 35 | `V2/Modules/Support/NoticiasImport/Routes/cms.php` | 2 | 1 |
| 36 | `V2/Modules/Support/StructuralLandingEditor/Routes/cms.php` | 17 | 1 |
| 37 | `V2/Modules/Support/SupportConfigs/Routes/cms.php` | 11 | 2 |
| 38 | `V2/Modules/_Exemplos/ExemploAPI/Routes/cms.php` | 2 | 1 |
| 39 | `V2/Services/ContentRichEditor/Routes/cms.php` | 2 | 1 |
| 40 | `V2/Services/FeedRSS/Routes/web.php` | 1 | 0 |
| 41 | `V2/Services/Gallery/Routes/cms.php` | 7 | 1 |
| 42 | `V2/Services/LandingSectionsEditor/Routes/cms.php` | 10 | 1 |
| 43 | `V2/Services/MailService/Routes/api.php` | 3 | 1 |
| 44 | `V2/Services/SEO/Routes/web.php` | 2 | 0 |
| | **Total** | **268** | **40** |

Os 44 arquivos pertencem a **27 unidades** (1 Core, 6 serviços, 20 módulos);
nenhum arquivo é órfão de unidade.

### 2.2 Blades: 386 × 386

| Recorte | No disco | No CSV | Diferença |
|---|---|---|---|
| Layouts globais (`V2/layouts`) | 86 blades | 86 (36 UI-CMS + 50 UI-PORTAL) | 0 |
| Módulos e serviços | 300 | 300 | 0 |
| **Total** | **386** | **386** | **0** |

Detalhe:

- O `.bak` (`sidebar.blade.php.bak.20260724`) deixou de ser indexado como
  componente; não há caminho no CSV sem arquivo no disco.
- O blade do ExemploAPI (`V2/Modules/_Exemplos/ExemploAPI/Views/cms/index.blade.php`)
  entrou no índice; não há blade no disco sem linha.
- Portanto: **386 blades = 386 linhas**, cobertura 1:1.
- Nota: 386 = 86 layouts + 300 de módulos/serviços. Os 87 arquivos de layout do
  enunciado incluem 1 arquivo não-blade (o manifest conta 87 arquivos em
  `V2/layouts`, dos quais 86 são `.blade.php`).

Nenhum caminho aparece duplicado no CSV (`collections.Counter == 1`).

### 2.3 Migrations: 87 arquivos × 60 linhas

| Classe | Arquivos | Efeito | Exemplos |
|---|---|---|---|
| `Schema::create` | 47 | criam 57 tabelas (10 arquivos criam 2+) | Sentinel, News, Gallery |
| `Schema::rename`/drop/archive | 26 | renomeiam para `backup_*` em vez de apagar | `2024_01_01_000013_archive_v2_chapters_table.php` |
| `Schema::table` (alter) | 1 | adiciona `users.unidade_regional_id` | `2026_09_14_000001_add_unidade_regional_id_to_users_table.php` |
| Outros (dados/função/seed) | 13 | UUID function, migração de tags, seed de role, normalização, fix de tipos, encrypt | `2026_06_01_000001_create_v2_uuid_function.php` |
| **Total** | **87** | — | — |

Arquivos que criam mais de uma tabela (10 arquivos → +10 tabelas):

| Arquivo | Tabelas |
|---|---|
| `2026_06_01_000003_create_sentinel_tables.php` | 6 (`persistences`, `activations`, `reminders`, `throttle`, `role_users`, `roles`) |
| `2026_08_18_000001_create_v2_conexao_tags_table.php` | 3 (`v2_conexao_tags`, `v2_parceiro_tag_pivot`, `v2_unidade_regional_tag_pivot`) |
| `2026_07_22_000002_create_v2_news_tags_table.php` | 2 (`v2_news_tags`, `v2_news_tag_pivot`) |
| `2026_06_14_000000_create_search_indexes_tables.php` | 2 (`v2_cms_links_index`, `v2_public_search_index`) |
| `2024_01_01_000016_add_category_and_tags_to_associado_instituicoes.php` | 2 (`v2_associado_tags`, `v2_associado_tag_pivot`) |

47 + 10 = **57 tabelas atuais**. O CSV tem **60** linhas:

| Tipo de linha | Quantidade | Situação |
|---|---|---|
| Tabela atual | 57 | coberta |
| Histórica explícita | 3 (`v2_chapters`, `v2_news_approvers`, `v2_news_configs`) | linha descreve rename/remoção; não é tabela atual |
| Ausente | 0 | — |

As três linhas históricas estão marcadas no campo `papel` como “legada”,
“REMOVIDA” ou “removida”; não devem ser contadas como schema atual nem usadas
para gerar migrations de criação. A conta de migrations fecha: 47 create + 26
rename/drop + 1 alter + 13 outros = 87.

### 2.4 Config, permissões, seeds e serviços

| Índice | Linhas | Estado | Observação |
|---|---|---|---|
| `config.csv` | 166 | completo | cresceu de 156 com Sobre Nós/Homepage/ExemploAPI |
| `permissoes.csv` | 67 | completo | 20 chaves de módulo + 27 linhas de atores/aliases em `CORE-AUTH` |
| `dados-iniciais.csv` | 15 | completo | 9 `DATA-SEEDS-BASICPAGES`, 5 `DATA-SEEDS-SLE`, 1 `DATA-SEEDS-CONTENT` |
| `servicos.csv` | 13 | completo | 13 `SVC-*` |
| `arquivos.csv` | 4 | criado nesta onda | ver §2.5 |

### 2.5 `arquivos.csv`: mortos e gerados

O arquivo estava só com o cabeçalho. Foram adicionadas 4 linhas, todas com
`status=confirmado`:

| Caminho | Unidade | Papel | Justificativa |
|---|---|---|---|
| `V2/layouts/cms/layouts/sidebar.blade.php.bak.20260724` | `UI-CMS` | morto | backup de blade; não é referenciado por `@include`/`@extends` |
| `V2/Core/Controllers/HomePortalController.php` | `CORE-CMS` | morto | única rota (`/`) está comentada; Homepage assumiu (`V2/Core/Routes/web.php:11`) |
| `V2/Core/Routes/api.php` | `CORE-BOOT` | morto | 0 `Route::*`; a rota `status` está comentada (`V2/Core/Routes/api.php:10`) |
| `V2/Modules/Layouts/Homepage/Models/HomepageSection.php` | `MOD-LAYOUTS-HOMEPAGE` | morto | nenhum consumidor; a home usa `v2_layout_base_configs` |

Não há arquivo **gerado** no manifest: o V2 não tem build de CSS/JS nem bundle
versionado; `V2/Services/ContentRichEditor/build-bundle.sh` não produz arquivo
dentro de `V2/`. Por isso nenhuma linha `gerado` foi criada.

### 2.6 Índices parciais × canônicos

`merge_indices.py --check` lê **159 arquivos parciais** e reporta:

| Índice | Parciais | Canônico | Diferença | Explicação |
|---|---|---|---|---|
| `rotas.csv` | 314 | 301 | +13 | linhas duplicadas por unidade (Sobre Nós/Homepage/Core reemitidos) |
| `tabelas.csv` | 72 | 60 | +12 | idem; o canônico deduplica e mantém 3 históricas |
| `componentes.csv` | 386 | 386 | 0 | consolidado |
| `permissoes.csv` | 93 | 67 | +26 | aliases/atores repetidos entre CORE-AUTH e módulos |
| `config.csv` | 329 | 166 | +163 | a mesma chave é emitida por mais de uma unidade (ex.: `v2.support.email` em CORE-AUTH e Support) |
| `dados-iniciais.csv` | 15 | 15 | 0 | consolidado |
| `servicos.csv` | 13 | 13 | 0 | consolidado |
| `arquivos.csv` | 4 | 4 | 0 | mortos registrados nesta onda |

Os parciais são **staging**, não fonte de verdade; o canônico é o resultado do
merge. O `--check` valida cabeçalhos e legibilidade, não igualdade de contagem.

## 3. Particularidades

### 3.1 O que a consolidação mudou (e por que o enunciado tem outros números)

| Dimensão | Enunciado | Estado atual | O que entrou |
|---|---|---|---|
| Rotas | 277 | 301 | Sobre Nós (16), Homepage (5) e ExemploAPI (3) consolidados |
| Tabelas | 57 | 60 | `v2_bienniums`, `v2_board_members`, `v2_homepage_sections` |
| Componentes | 325 | 386 | +61: Homepage (42), Sobre Nós (19) e ExemploAPI (1), menos o `.bak` removido (−1) |
| Permissões | 63 | 67 | Sobre Nós, Homepage, seeds |
| Config | 156 | 166 | Sobre Nós/Homepage/ExemploAPI |
| Seeds | 0 | 15 | docs de `07_dados-iniciais` |

A diferença é de **consolidação**, não de escopo: os arquivos sempre existiram
no manifest; os docs das unidades foram concluídos na Onda 5 e emitiram os
índices parciais que o merge absorveu.

### 3.2 Diferenças que ainda impedem paridade 100%

| # | Lacuna | Dimensão | Prova | Correção necessária |
|---|---|---|---|---|
| 1 | 8 grupos sem linha | rotas | §2.1.2 | emitir as linhas `tipo=grupo` |
| 2 | 1 grupo espúrio (`BasicPage /`) | rotas | `R-BASICPAGE-16` | remover a linha (a rota foi removida do arquivo) |
| 3 | 2 endpoints SEO com `tipo=rota` | rotas | `SEO-R01`, `SEO-R02` | retipar para `endpoint` |
| 4 | 3 linhas históricas no índice de tabelas | tabelas | `v2_chapters`, `v2_news_approvers`, `v2_news_configs` | mover para seção histórica ou filtrar por `papel` |
| 5 | Duplicata `POST /categorias` contada 2× | rotas | `R28`/`R20` | marcar uma como `sombreada` (não removê-la do código sem decisão) |
| 6 | `position` sem efeito | navegação | §5 de `flags-e-navegacao.md` | decisão de produto: implementar ou remover o campo |
| 7 | `active_pattern` com `|` | permissões | `SupportConfigs` | trocar por array de 2 patterns |
| 8 | Tipos de mídia divergentes | dados | §4.4 de `entidades-e-propriedade.md` | migração de tipo + cast |
| 9 | TTL regional sem chave de config | integrações | `UnidadeRegional.php:283-285` | criar `v2.unidade_regional.api_token_ttl_days` |
| 10 | `dados-iniciais.csv` não cobre `DatabaseSeeder` (fora de `V2/`) | seeds | `database/seeds/DatabaseSeeder.php` | documentar como satélite, fora do manifest |

### 3.3 Anti-uso

- **Não** trate 33 linhas `grupo` como “rotas”: elas são metadados de prefixo e
  middleware; contá-las como endpoint infla a cobertura.
- **Não** remova `v2_chapters`/`v2_news_approvers`/`v2_news_configs` do índice
  sem mover a informação: elas documentam o rename e o rollback.
- **Não** use `arquivos.csv` como lista de 930 arquivos: ele registra apenas
  mortos/gerados; a cobertura total é do manifest.
- **Não** “conserte” a duplicata `POST /categorias` no índice sem decidir qual
  controller deve sobreviver; o runtime já escolheu a segunda.

## 4. Integrabilidade

### 4.1 Receita: verificar a conta

```bash
# chamadas de rota no código (não comentadas)
grep -rhE "^\s*Route::[a-zA-Z]+\(" V2 --include="*.php" | wc -l   # 308
# linhas do índice
python3 - <<'PY'
import csv, collections
r=list(csv.DictReader(open('_indices/rotas.csv')))
print(len(r), collections.Counter(x['tipo'] for x in r))
PY
```

### 4.2 Receita: fechar uma lacuna

```text
1. Edite o parcial da unidade (ex.: _indices/parcial-MOD-_EXEMPLOS-EXEMPLOAPI/rotas.csv).
2. Rode python3 tools/merge_indices.py --check.
3. Rode python3 tools/merge_indices.py para regravar o canônico.
4. Recalcule os deltas deste documento.
```

### 4.3 Receita: auditar um blade

```bash
# blade no disco sem linha no índice
comm -23 <(find V2 -name '*.blade.php' | sort) \
         <(python3 -c "import csv;[print(r['caminho_blade']) for r in csv.DictReader(open('_indices/componentes.csv'))]" | sort)
```

## 5. Lacunas

- `LG-REC-01` — os 8 grupos ausentes (§2.1.2) dependem dos índices parciais das
  unidades; nenhum endpoint ou blade falta.
- `LG-REC-02` — não há teste automatizado que compare `Route::*` do código com
  `rotas.csv`; a conta deste documento é manual e pode voltar a divergir.
- `LG-REC-03` — o tipo `rota` no CSV não é validado pelo `merge_indices.py`;
  qualquer valor é aceito.
- `LG-REC-04` — `arquivos.csv` cobre 4 mortos, mas não há varredura automática
  de referências (o `HomePortalController` só foi detectado por leitura).
- `LG-REC-05` — a contagem de 314/72/93/329 nos parciais não é deduplicada por
  chave; o merge canônico resolve, mas não há relatório de duplicatas.

## 6. Evidências

- 44 route files em `V2/**/Routes/*.php`; 308 chamadas contadas por regex
  `^\s*Route::(get|post|put|delete|match|redirect|group|prefix|middleware)\(`.
- 386 `*.blade.php` em `V2/`.
- 87 migrations em `V2/**/Migrations/*.php`; 57 blocos `Schema::create`.
- `_indices/{rotas,tabelas,componentes,permissoes,config,dados-iniciais,servicos,arquivos}.csv`.
- `tools/merge_indices.py --check` (Índices OK, 159 parciais).
- `tools/coverage.py --docs` → 56/56 unidades, 930/930 arquivos.
- Snapshot: 2026-10-21 02:30 -03; `git -C sucesu-cms status --porcelain V2` vazio.
