---
id: MATRIZ-INTEGRACOES
tipo: matriz
onda: 5
status: concluido
unidades: []
fontes:
  - V2/Core/Providers/
  - V2/Core/Middleware/
  - V2/Services/
  - V2/Modules/
  - config/app.php
  - config/v2.php
depende_de: [CORE-BOOT, CORE-AUTH, MATRIZ-ENTIDADES, MATRIZ-PERMISSOES]
consumidores: [MATRIZ-SINGULARIDADES, REIMPL-ORDEM, REIMPL-PARIDADE]
criticidade: alta
dono: Matriz
---

# Integrações e contratos: quem depende de quem

Este documento mede as dependências entre Core, serviços e módulos, cataloga os
contratos HTTP (interna, regional, OpenAPI, serviços), os hooks de model e os
composers de view, e diz o que quebra quando cada elo é removido. As contagens
abaixo vêm de `use V2\...` nos arquivos PHP (ocorrências e arquivos distintos),
não de impressão.

## 1. Efeito

### Ficha de identidade

| Campo | Valor |
|---|---|
| Efeito primário | Define a direção real das dependências do V2 e os contratos de entrada/saída que cruzam fronteiras de unidade, incluindo os acoplamentos reversos de Galeria e Busca. |
| Entrada | `use` de namespaces; 44 route files; middlewares; hooks `saved/deleted`; `View::composer`; `config/app.php`. |
| Saída | Mapa Core→serviços→módulos; matriz de contratos HTTP/API; tabela de eventos e efeitos de quebra. |
| Efeitos colaterais | Nenhum em runtime; documento de contrato. |
| Particularidade central | A direção “limpa” (módulos → serviços → Core) **não é a única**: 11 arestas de serviço importam models de módulos, e o Dashboard importa 16 models de 10 módulos. |
| Como se integra | `MATRIZ-ENTIDADES` (dados), `MATRIZ-PERMISSOES` (auth), `REIMPL-ORDEM` (sequência de build). |
| Se removido, quebra | A ordem de reimplementação fica sem base; acoplamentos reversos passam despercebidos e viram dependência circular na reconstrução. |
| Superfície pública | Contratos listados em §3; hooks em §4. |

### 1.1 Números medidos

| Medida | Valor | Fonte |
|---|---|---|
| Arestas Core → serviço | 6 (4 serviços distintos) | §2.2 |
| Arestas módulo → serviço | 166 importações em 76 pares | §2.3 |
| Arestas serviço → módulo (reversas) | 12 importações em 11 pares | §2.4 |
| Arestas módulo → módulo | 17 pares (46 importações) | §2.5 |
| Módulos que importam ao menos 1 serviço | 18 dos 20 | §2.3 |
| Serviços importados por módulos | 11 dos 13 (12 com Dashboard via FQCN) | §2.3 |
| Contratos HTTP de serviço | 27 endpoints | §3.4 |
| Rotas de API de negócio | 15 (8 regional + 2 interna + 5 mail) | §3.1–3.3 |
| Hooks de model que escrevem índice/feed/slug | 10 models (8 com índice/feed + 2 de slug) | §4.1 |

## 2. Abordagem

### 2.1 Ordem de boot (contrato de inicialização)

```text
config/app.php
  ├─ SEOServiceProvider            (171)  → singleton + composer de metadata
  ├─ V2ServiceProvider             (185)  → helpers, views, rotas, migrations
  ├─ ExcelImporterServiceProvider  (186)  → views + singletons
  └─ FeedRssServiceProvider        (187)  → singleton do feed
```

`V2ServiceProvider::boot()` executa, nesta ordem
(`V2/Core/Providers/V2ServiceProvider.php:30-200`):

1. diretivas `@v2can`/`@endv2can`;
2. views `v2-cms` e `v2-portal`;
3. `SidebarComposer` em `v2-cms::layouts.sidebar`;
4. composer global de `v2-portal::*` (favicon, `siteTitle`, `portalConfigs` vazios);
5. migrations do Core;
6. rotas do Core (`mapCoreRoutes`);
7. varredura de `V2/Modules`: `ModuleProvider`, migrations, views e rotas por módulo;
8. `v2.modules.configs` no container;
9. fallback `/{slug}` (`mapFallbackRoutes`);
10. `refreshNameLookups`/`refreshActionLookups`;
11. catch-up de busca de BasicPage (apenas CLI);
12. varredura de `V2/Services`: migrations, views e rotas.

Consequência: **todo módulo é registrado antes de todo serviço**, mas as rotas de
serviço são registradas depois do fallback. Um serviço que registre `/{slug}`
ficaria inalcançável; nenhum registra.

### 2.2 Core → serviços (6 importações, 4 serviços)

| Origem | Destino | Arquivos | Para quê |
|---|---|---|---|
| `CORE` | `SVC-ACTIVITYLOGGER` | 3 | `PermissionService`, `RegionalScopeService`, `ConexaoTagCmsController` |
| `CORE` | `SVC-DASHBOARD` | 1 | `DashboardCmsController` |
| `CORE` | `SVC-SEARCH` | 1 | `SearchController` |
| `CORE` | `SVC-STORAGE` | 1 | `UploadService` |

Fonte: `V2/Core/Controllers/ConexaoTagCmsController.php:7`;
`V2/Core/Controllers/DashboardCmsController.php:7`;
`V2/Core/Controllers/SearchController.php:9`;
`V2/Core/Controllers/UploadService.php` (namespace `V2\Core\Services`);
`V2/Core/Services/UploadService.php:8`.

O Core **não** importa models de módulo por `use`, mas usa FQCN em três pontos:
`ConexaoTag` (relações com Parceiro e UnidadeRegional),
`RegionalIdentityService` (NewsCategory/UnidadeRegional) e o fallback
(BasicPagePortalController). Isso é acoplamento reverso do Core com módulos
(`V2/Core/Models/ConexaoTag.php:34,41`;
`V2/Core/Services/RegionalIdentity/RegionalIdentityService.php:5-6`;
`V2/Core/Routes/fallback.php:17`).

### 2.3 Módulos → serviços (166 importações em 76 pares)

Serviços mais consumidos (arquivos distintos):

| Serviço | Arquivos de módulo | Unidades consumidoras |
|---|---|---|
| `SVC-GALLERY` | 18 | Associados, Parceiros, Unidade Regional, Associe-se, Sobre Nós, História, BasicPage, Homepage, Notícias, Agenda, Trabalhe Conosco, SLE, SupportConfigs |
| `SVC-LANDINGSECTIONSEDITOR` | 19 | Homepage (12), Sobre Nós (7) |
| `SVC-SEO` | 24 | Associe-se, Trabalhe Conosco, Associados, Parceiros, Unidade Regional, Fale Conosco, História, Sobre Nós, BasicPage, Homepage, Agenda, Feed RSS, Notícias |
| `SVC-ACTIVITYLOGGER` | 33 | SupportConfigs, Associe-se, SLE, Unidade Regional, Sobre Nós, BasicPage, Notícias, Trabalhe Conosco, Associados, Parceiros, Certificado, Gestão de Permissões, Fale Conosco, História, Homepage, Agenda |
| `SVC-SEARCH` | 9 | Notícias (2), Sobre Nós, BasicPage, Associados, Parceiros, Unidade Regional, Agenda, Trabalhe Conosco |
| `SVC-CONTENTRICHEDITOR` | 15 | Parceiros (3), Associados (2), História (2), Notícias (2), Unidade Regional, Associe-se, Agenda, Trabalhe Conosco, Sobre Nós |
| `SVC-STORAGE` | 9 | Parceiros (2), SLE (2), Associados, Unidade Regional, BasicPage, SupportConfigs |
| `SVC-MEDIA` | 3 | SLE (2), BasicPage |
| `SVC-MAILSERVICE` | 4 | Fale Conosco (2), Associe-se |
| `SVC-FEEDRSS` | 4 | Agenda, Notícias, Trabalhe Conosco, Feed RSS |
| `SVC-DIGITALSIGNATURE` | 1 | Certificado Digital (4 importações) |
| `SVC-EXCELIMPORTER` | 0 | nenhum módulo usa o fluxo de importação |

Fonte: `02_servicos-base/*.md`, `03_servicos-ui/**/*.md`, `_indices/servicos.csv`
e a varredura de `use V2\Services\...` em `V2/Modules`.

### 2.4 Serviços → módulos (acoplamento reverso: 12 importações, 11 pares)

| Serviço | Módulo importado | Arquivo | Classe(s) |
|---|---|---|---|
| `SVC-GALLERY` | `MOD-CONEXOES-ASSOCIADOS` | `Console/Commands/PopulateMissingImages.php:7-8` | `AssociadoInstituicao`, `AssociadoInstituicaoGallery` |
| `SVC-GALLERY` | `MOD-CONEXOES-PARCEIROSINSTITUCIONAIS` | `:9` | `Parceiro` |
| `SVC-GALLERY` | `MOD-CONEXOES-UNIDADEREGIONAL` | `:10` | `UnidadeRegional` |
| `SVC-GALLERY` | `MOD-PUBLICACOES-AGENDA` | `:11` | `Evento` |
| `SVC-GALLERY` | `MOD-PUBLICACOES-NOTICIAS` | `:12` | `News` |
| `SVC-GALLERY` | `MOD-PUBLICACOES-TRABALHECONOSCO` | `:13` | `JobOpening` |
| `SVC-SEARCH` | `MOD-CONEXOES-ASSOCIADOS` | `Console/Commands/ReindexPublicSearch.php:7` | `AssociadoInstituicao` |
| `SVC-SEARCH` | `MOD-CONEXOES-UNIDADEREGIONAL` | `:8` | `UnidadeRegional` |
| `SVC-SEARCH` | `MOD-PUBLICACOES-NOTICIAS` | `:9` | `News` |
| `SVC-SEO` | `MOD-SUPPORT-SUPPORTCONFIGS` | `Providers/SEOServiceProvider.php:7` | `PortalConfigsService` |
| `SVC-LANDINGSECTIONSEDITOR` | `MOD-SUPPORT-SUPPORTCONFIGS` | `Controllers/LandingSectionsEditorController.php:15` | `PortalConfigsService` |
| `SVC-FEEDRSS` | `MOD-SUPPORT-SUPPORTCONFIGS` | `Services/FeedRssService.php:122` | `PortalConfigsService` (FQCN inline) |
| `SVC-DASHBOARD` | 10 módulos | `Services/Dashboard/DashboardStatsService.php` | 16 models via FQCN (`News`, `Evento`, `Parceiro`, `UnidadeRegional`, `JobOpening`, `JobApplication`, `MembershipLead`, `MembershipPlan`, `MensagemContato`, `Milestone`, `Biennium`, `BoardMember`, `BasicPage`, `HomepageSection`, `StructuralPortalContent`, `DigitalCertificate`) |

Os três primeiros blocos são **comandos de console**; não rodam no request. Os
três seguintes (SEO, LSE, Feed) são dependências de runtime para ler o título do
portal. O Dashboard é o maior acoplamento reverso: qualquer mudança de model de
módulo pode quebrar `GET /cms`.

### 2.5 Módulos → módulos (17 pares)

| Origem | Destino | Arquivos | Motivo |
|---|---|---|---|
| Unidade Regional | Notícias | 4 | criar notícia regional, categoria, scopes |
| Associados | Unidade Regional | 3 | vínculo empresa↔regional |
| Sobre Nós | SLE | 4 | `LayoutBaseConfig` para `sobre_nos_sections` |
| Homepage | Notícias | 3 | widgets `sucesu-news/noticias` |
| Homepage | Parceiros | 3 | widget `sucesu-brands` |
| Homepage | Agenda | 3 | widget `sucesu-agenda` |
| Notícias | Unidade Regional | 3 | derivar regional da categoria |
| SLE | SupportConfigs | 2 | tema/mail/portal configs |
| Unidade Regional | Associados | 2 | empresas da regional |
| Unidade Regional | SupportConfigs | 2 | configs de tema/portal |
| Sobre Nós | Associados | 2 | contadores de impacto |
| Sobre Nós | Unidade Regional | 1 | contadores/regionais |
| Homepage | SLE | 2 | `LayoutBaseConfig` |
| NoticiasImport | Notícias | 1 | serviço de importação |
| Associados | SupportConfigs | 1 | portal configs |
| Fale Conosco | SLE | 1 | layout/config |
| NoticiasImport | Unidade Regional | 1 | `consumer`/regional |

Fonte: varredura de `use V2\Modules\...`; docs de unidade citados em
`05_modulos/**`.

### 2.6 Seeds → serviços e módulos

| Seeder | Importa | Efeito |
|---|---|---|
| `DATA-SEEDS-CONTENT` | 9 models de módulos | popula demonstração |
| `DATA-SEEDS-BASICPAGES` | `GalleryService`, models de História | páginas + mídia |
| `DATA-SEEDS-SLE` | `GalleryService`, `AssetManagerService` | blocos + assets |

Fonte: `V2/Seeds/Content/DemoContentSeeder.php:8-20`;
`V2/Seeds/BasicPages/ProcessesGalleryImages.php:5-6`;
`V2/Seeds/StructuralPortalSeeder.php:20-71`.

## 3. Integrabilidade: contratos HTTP/API

### 3.1 API interna (máquina-a-máquina)

| Item | Contrato | Evidência |
|---|---|---|
| Endpoints | `GET /api/v2/noticiasimport/health`; `POST /api/v2/noticiasimport/run` | `V2/Modules/Support/NoticiasImport/Routes/api.php:12-18` |
| Prefixo | aplicado pelo provider: `api/v2/` + `strtolower($moduleName)` | `V2/Core/Providers/V2ServiceProvider.php:309-312` |
| Auth | header `X-Access-Key` (também `X-Internal-Key` legado e `Authorization: Bearer`) | `V2/Core/Middleware/InternalApiAuth.php:57-75` |
| Escopo | `noticias:import` (ou `abilities`/`*`/`dominio:*`) | `V2/Core/Security/InternalApiKey.php:185-204` |
| Ciclo | revogação, expiração, IP allow-list, `last_used_at` | `V2/Core/Middleware/InternalApiAuth.php:82-103` |
| Throttle | 30/min por prefixo de token; 100/min por IP no grupo | `V2/Modules/Support/NoticiasImport/Routes/api.php:16-18` |
| Payload | `dir`, `regional`, `status`, `apply`; diretório restrito a `storage/app/imports` ou TMP | `V2/Modules/Support/NoticiasImport/Controllers/NoticiasImportController.php:84-108` |
| Resposta | relatório por item; `422 invalid_dir`; `403 consumer_mismatch` | `05_modulos/Support/NoticiasImport/contrato-api.md:26-32` |
| Chave estática | `config('v2.internal_api.access_key')`, sem registro, nunca logada | `config/v2.php:24-36` |

### 3.2 API regional (token por unidade)

| Item | Contrato | Evidência |
|---|---|---|
| Endpoints | 8: `GET/POST /noticias`, `POST /noticias/{id}`, `DELETE /noticias/{id}`, `GET/POST /associados`, `POST /associados/{id}`, `DELETE /associados/{id}` | `V2/Modules/Conexoes/UnidadeRegional/Routes/api.php:3-31` |
| Prefixo | `api/v2/unidaderegional` | `V2/Core/Providers/V2ServiceProvider.php:309-312` |
| Auth | `Authorization: Bearer asc_...`; hash em `v2_unidade_regionais.api_token_hash` | `V2/Modules/Conexoes/UnidadeRegional/Controllers/UnidadeRegionalNewsApiController.php:445-470` |
| Escopo | **nenhum**: um token vale para todos os 8 endpoints da unidade | `05_modulos/Conexoes/UnidadeRegional/api.md:25-31` |
| TTL | `config('v2.unidade_regional.api_token_ttl_days', 365)`, mas a chave não existe em `config/v2.php` → 365 fixo | `V2/Modules/Conexoes/UnidadeRegional/Models/UnidadeRegional.php:283-285` |
| Throttle | `throttle.api:30,1` + `throttle:100,1` nas escritas | `V2/Modules/Conexoes/UnidadeRegional/Routes/api.php:7-24` |
| Regra de domínio | notícia regional nasce `pending_approval`; categoria é derivada e o `category_id` do payload é ignorado | `05_modulos/Conexoes/UnidadeRegional/api.md:25-31` |
| Envelope | `{ok, error, data, message}` via `ApiResponse` | `V2/Core/Traits/ApiResponse.php`; `01_arquitetura/05-persistencia-uuid-migracoes.md:24-30` |
| OpenAPI | `GET /api/v2/unidaderegional/openapi.json`, **sem autenticação**; OpenAPI 3.0.3, 8 paths | `V2/Modules/Conexoes/UnidadeRegional/Routes/api.php:33-38`; `V2/Modules/Conexoes/UnidadeRegional/Controllers/UnidadeRegionalApiController.php:25-48` |

### 3.3 API de serviço: MailService

| Item | Contrato | Evidência |
|---|---|---|
| Endpoints | `POST /api/v2/mail/send`, `POST /api/v2/mail/test`, `GET /api/v2/mail/history` | `V2/Services/MailService/Routes/api.php:21-25` |
| Auth | `CmsAuthenticate` (sessão Sentinel + papel), sem RBAC de módulo | `V2/Services/MailService/Routes/api.php:21` |
| Efeito | envia SMTP, grava `v2_mail_logs` (status `sent`/`failed`) e devolve `MailResult` | `02_servicos-base/mail-service.md:21-27` |
| Falha | nunca lança; o chamador precisa inspecionar `wasSuccessful()` | `02_servicos-base/mail-service.md:25-27` |

### 3.4 Contratos de serviço (UI/HTTP no CMS)

| Serviço | Prefixo | Endpoints | Auth | Evidência |
|---|---|---|---|---|
| `SVC-GALLERY` | `cms/v2/gallery` | 7 (index/store/update/rotate/download/archive/destroy) | **nenhuma**; subcaminhos isentos de CSRF (o POST raiz exige) | `V2/Services/Gallery/Routes/cms.php:5-13`; `app/Http/Middleware/VerifyCsrfToken.php:15-17` |
| `SVC-CONTENTRICHEDITOR` | `cms/v2/editor` | 2 (upload/search) | `CmsAuthenticate`, sem RBAC | `V2/Services/ContentRichEditor/Routes/cms.php:9-13` |
| `SVC-LANDINGSECTIONSEDITOR` | `cms/v2/landing-sections` | 10 (form/validate/preview/media) | `CmsAuthenticate`, sem RBAC | `V2/Services/LandingSectionsEditor/Routes/cms.php:9-24` |
| `SVC-MAILSERVICE` | `api/v2/mail` | 3 | `CmsAuthenticate` | `V2/Services/MailService/Routes/api.php:21-25` |
| `SVC-SEO` | `/` | 2 (`robots.txt`, `sitemap.xml`) | pública | `V2/Services/SEO/Routes/web.php:9-10` |
| `SVC-FEEDRSS` | `/` | 1 (`feed.xml`) | pública | `V2/Services/FeedRSS/Routes/web.php:5-8` |
| `SVC-EXCELIMPORTER` | nenhum | 0 (é biblioteca + views) | n/a | `03_servicos-ui/excel-importer/spec.md:25-27` |
| `SVC-SEARCH` | `/busca`, `cms/search` (Core) | 2 | pública / `CmsAuthenticate` | `V2/Core/Routes/web.php:14`; `V2/Core/Routes/cms.php:27` |
| `SVC-STORAGE` | nenhum | 0 | n/a | `02_servicos-base/storage.md:21-27` |
| `SVC-MEDIA` | nenhum | 0 (componentes) | n/a | `03_servicos-ui/media/spec.md:21-27` |
| `SVC-DIGITALSIGNATURE` | nenhum | 0 (consumido por Certificado) | n/a | `02_servicos-base/digital-signature/spec.md:21-27` |
| `SVC-ACTIVITYLOGGER` | nenhum | 0 (views) | n/a | `02_servicos-base/activity-logger.md:21-27` |
| `SVC-DASHBOARD` | nenhum | 0 (serviço) | n/a | `02_servicos-base/dashboard.md:21-27` |

Total de endpoints HTTP de serviço: **27** (7+2+10+3+2+1+1 `busca`+1 `cms/search`).

### 3.5 Contratos de página (portal)

| Rota | Método | Contrato | Cache | Evidência |
|---|---|---|---|---|
| `/` | GET | Homepage por seções; fallback “Bem-vindo ao Portal” | Redis 5 min + `Cache-Control` 60 s | `V2/Modules/Layouts/Homepage/Routes/web.php:9`; `05_modulos/Layouts/Homepage/spec.md:24-34` |
| `/{slug}` | GET | BasicPage runtime; 404 se não existir | idem | `V2/Core/Routes/fallback.php:19-21` |
| `/noticias`, `/noticia/{slug}`, `/news-sitemap.xml` | GET | lista/detalhe/sitemap | page cache | `05_modulos/Publicacoes/Noticias/rotas.md:26-32` |
| `/agenda` | GET | agenda filtrável | page cache | `05_modulos/Publicacoes/Agenda/rotas.md:25-31` |
| `/associados`, `/associados/detalhe/{id}`, `/associado/{slug}` | GET | lista/fragmento/página | page cache | `V2/Modules/Conexoes/Associados/Routes/web.php:10-12` |
| `/regionais`, `/regional/{slug}` | GET | vitrine da regional | page cache | `V2/Modules/Conexoes/UnidadeRegional/Routes/web.php:3-5` |
| `/sobre-nos`, `/equipe/{slug}`, `/diretoria*` | GET | Sobre Nós + membros + 301 | page cache | `V2/Modules/Institucional/SobreNos/Routes/web.php:3-18` |
| `/fale-conosco` | GET/POST | formulário + persistência | cache excluído | `05_modulos/Institucional/FaleConosco/rotas.md:26-32` |
| `/associe-se*` | GET/POST | planos + lead | sem cache | `05_modulos/Institucional/AssocieSe/rotas.md:26-32` |
| `/historia` | GET | linha do tempo | page cache | `05_modulos/Institucional/Historia/rotas.md:26-32` |
| `/trabalhe-conosco*` | GET/POST | vagas + candidatura | page cache, exceto POST | `05_modulos/Publicacoes/TrabalheConosco/rotas.md:27-33` |
| `/parceiros-institucionais*` | GET | lista + fragmento | page cache | `V2/Modules/Conexoes/ParceirosInstitucionais/Routes/web.php:3-15` |
| `/busca` | GET | resultados (20) | page cache | `V2/Core/Routes/web.php:14` |
| `/feed.xml` | GET | RSS 2.0 (limite 50) | sem cache explícito | `V2/Services/FeedRSS/Routes/web.php:5-8` |
| `/robots.txt`, `/sitemap.xml` | GET | SEO dinâmico | sem cache | `V2/Services/SEO/Routes/web.php:9-10` |

## 4. Eventos e hooks

### 4.1 Escrita automática em índice/feed (model hooks)

| Model | Hook | Efeito | Evidência |
|---|---|---|---|
| `News` | `saving` (slug/regional), `saved` (search + feed), `deleted` | upsert no índice público/CMS e no feed; remove no delete | `V2/Modules/Publicacoes/Noticias/Models/News.php:267-329` |
| `Evento` | `saving`, `saved`, `deleted` | idem, módulo `agenda` | `V2/Modules/Publicacoes/Agenda/Models/Evento.php:83-153` |
| `AssociadoInstituicao` | `saving`, `saved`, `deleted` | índice público | `V2/Modules/Conexoes/Associados/Models/AssociadoInstituicao.php:186-212` |
| `Parceiro` | `saving`, `saved`, `deleted` | índice público | `V2/Modules/Conexoes/ParceirosInstitucionais/Models/Parceiro.php:60-87` |
| `UnidadeRegional` | `saving`, `saved`, `deleted` | índice público + categoria de notícias | `V2/Modules/Conexoes/UnidadeRegional/Models/UnidadeRegional.php:113-147` |
| `JobOpening` | `saving`, `saved`, `deleted` | índice público + feed | `V2/Modules/Publicacoes/TrabalheConosco/Models/JobOpening.php:111-166` |
| `BasicPage` | `saved` | índice público | `V2/Modules/Layouts/BasicPage/Models/BasicPage.php:141-142` |
| `BoardMember` | `saving`, `saved`, `deleted` | índice público + CMS (`diretoria`) | `V2/Modules/Institucional/SobreNos/Models/BoardMember.php:95-112` |
| `JobApplication` | hooks de status | estatística do dashboard | `05_modulos/Publicacoes/TrabalheConosco/dados.md:27-33` |
| `NewsTag`/`NewsCategory` | `saving` | slug único | `V2/Modules/Publicacoes/Noticias/Models/NewsTag.php:34`; `NewsCategory.php:41` |

Os hooks são **síncronos** e dentro do request; falha de índice/feed é engolida
com `Log::error` (`News.php:380-382`), não reverte a transação.

### 4.2 Composers de view

| Composer | Views | Injeta | Evidência |
|---|---|---|---|
| `SidebarComposer` | `v2-cms::layouts.sidebar` | `v2SidebarGroups` filtrado | `V2/Core/Providers/V2ServiceProvider.php:48` |
| composer anônimo do Core | `v2-portal::*` | `faviconUrl`, `siteTitle`, `portalConfigs=[]`, `layoutConfigs=[]`, `logos=[]`, `path=''` | `V2/Core/Providers/V2ServiceProvider.php:55-76` |
| `LayoutBaseComposer` (SLE) | `v2-portal::*`, `v2-basicpage::*` | `layoutConfigs` real | `V2/Modules/Support/StructuralLandingEditor/ModuleProvider.php:24-25` |
| composer do SupportConfigs | `v2-portal::*` | `portalTheme`, `portalConfigs` reais | `V2/Modules/Support/SupportConfigs/ModuleProvider.php:19-67` |
| `CmsThemeComposer` | `v2-cms::*` | `$cmsThemeCss`, `$cmsThemeConfigs` | `V2/Modules/Support/SupportConfigs/ModuleProvider.php:69-73` |
| composer do SEO | 8 views de metadata/header/footer/print | `seo`, `seoTitle`, `seoGtagId`, scripts | `V2/Services/SEO/Providers/SEOServiceProvider.php:23-56` |

Ordem de execução em `v2-portal::*`: Core (valores default) → SLE
(`layoutConfigs`) → SupportConfigs (`portalTheme`) → SEO (metadata). O último a
escrever a mesma chave vence; `siteTitle` é escrito pelo Core e pelo SEO.

### 4.3 Efeitos de quebra

| Elo removido | Quebra imediatamente | Quebra em cascata |
|---|---|---|
| `V2ServiceProvider` | nenhuma rota/view/migration | todo o sistema |
| `SVC-GALLERY` | 7 rotas CMS e o picker global do layout | upload de 13 módulos + 3 seeders; `route('v2.gallery.*')` falha ao renderizar scripts |
| `SVC-SEARCH` | `/busca`, `/cms/search` (500) | seletor do CRE, iframe-summary, ranking do dashboard, 8 hooks |
| `SVC-SEO` | `<head>` do portal; `robots.txt`/`sitemap.xml` | 24 controllers e 28 arquivos fora do serviço referenciam `SEOService`; ranking do dashboard |
| `SVC-CONTENTRICHEDITOR` | formulários de 9 módulos | previews e renderização de conteúdo já gravado |
| `SVC-LANDINGSECTIONSEDITOR` | editores de Homepage/Sobre Nós | páginas públicas das duas + 36 widgets |
| `SVC-FEEDRSS` | `/feed.xml` (404) | painel Feed RSS e hooks de Notícias/Agenda/Vagas |
| `SVC-MAILSERVICE` | envio de e-mail | MailAudit, Fale Conosco, Associe-se, SLE |
| `SVC-STORAGE` | URLs e uploads | Media, Gallery, seeders de SLE/BasicPage |
| `CORE-AUTH` | login e RBAC | todo o CMS e APIs internas |
| `MOD-SUPPORT-SUPPORTCONFIGS` | tema/portal configs | FeedRSS (título), SEO (defaults), LSE (config), dashboard |
| `MOD-PUBLICACOES-NOTICIAS` | portal de notícias | importação, API regional, widgets da Home, sitemap |
| `MOD-LAYOUTS-BASICPAGE` | catch-all `/{slug}` | 404 global, 4 páginas institucionais, sitemap |
| `MOD-LAYOUTS-HOMEPAGE` | `/` | widgets da home; `/` cai no fallback |

## 5. Particularidades

### 5.1 Contradições e riscos medidos

| Fato | Evidência | Risco |
|---|---|---|
| A direção “módulos → serviços” tem 12 imports reversos | §2.4 | Reimplementar serviços antes dos models de módulo cria dependência circular; a ordem de build precisa incluir os models usados por Gallery/Search/Dashboard. |
| `SVC-GALLERY` não tem `CmsAuthenticate` e é isento de CSRF | `V2/Services/Gallery/Routes/cms.php:5-13`; `VerifyCsrfToken.php:15-17` | upload/download anônimo; SEC-G1-01. |
| `SVC-SEO` importa `PortalConfigsService` (módulo Support) | `SEOServiceProvider.php:7` | o serviço não é autônomo: precisa do módulo Support bootado. |
| Dois composers escrevem `siteTitle` | Core `V2ServiceProvider.php:59-70` e SEO `SEOServiceProvider.php:47,54` | o valor final depende da ordem de registro; o do SEO vence. |
| `SVC-FEEDRSS` tem unique sem filtro de soft delete | `02_servicos-base/feed-rss.md:25-27` | reinserir item removido falha com unique violation. |
| `SVC-DASHBOARD` importa 16 models por FQCN | `DashboardStatsService.php` | `GET /cms` quebra se qualquer model mudar de namespace/coluna. |
| `api/v2/unidaderegional/openapi.json` é pública | `UnidadeRegional/Routes/api.php:33-38` | expõe o contrato completo sem auth (intencional, mas é superfície). |
| `SVC-EXCELIMPORTER` não tem consumidor de módulo | `servicos.csv` | o fluxo de importação guiada não é usado em produção; só `ExcelTranspilerService` é consumido por Media. |
| O fallback é registrado antes dos serviços | `V2ServiceProvider.php:137` vs `:172-190` | um serviço que registrasse `/{slug}` ficaria sombreado; hoje nenhum registra. |

### 5.2 Anti-uso

- **Não** implemente Gallery/Search como bibliotecas puras: elas importam models
  de módulos em comandos; a reconstrução precisa decidir se mantém o comando ou
  o move para um adapter.
- **Não** registre rota de serviço em `/{slug}`: o fallback é registrado antes.
- **Não** dependa da ordem dos composers para `siteTitle`: defina uma fonte única
  (`v2_portal_configs.titulo_site`).
- **Não** chame `/api/v2/mail/*` esperando `MailResult` HTTP: a resposta é JSON
  do controller, e falha de transporte vem com status interno `failed`.
- **Não** use o token regional como se tivesse escopos: ele vale pelos 8
  endpoints da unidade.
- **Não** assuma que `POST /api/v2/noticiasimport/run` valida `consumer` no
  middleware: a checagem é no controller (`contrato-api.md:30-32`).

## 6. Lacunas

- `LG-INT-01` — não há mapa de dependências de **JS** (bundles, imports,
  inicialização por página); a varredura cobre PHP.
- `LG-INT-02` — não há teste de contrato para a API interna/regional; os
  payloads foram lidos do controller e do doc, não exercitados.
- `LG-INT-03` — a ordem real de execução dos composers em runtime não foi
  instrumentada; a conclusão vem da ordem de registro no provider.
- `LG-INT-04` — `SVC-DASHBOARD` importa 16 models por FQCN sem `use`; a lista
  foi extraída por regex e pode perder referências dinâmicas.
- `LG-INT-05` — não há contrato formal (JSON Schema) para `/api/v2/mail/*` nem
  para o relatório de importação; o OpenAPI cobre apenas a API regional.

## 7. Evidências

- Varredura de `use V2\...` em 860 arquivos PHP de `V2/` (2026-10-21).
- `config/app.php:171,185-187`; `V2/Core/Providers/V2ServiceProvider.php`;
  `V2/Core/Middleware/InternalApiAuth.php`; `V2/Core/Security/InternalApiKey.php`.
- Route files: `V2/Modules/Support/NoticiasImport/Routes/api.php`,
  `V2/Modules/Conexoes/UnidadeRegional/Routes/{api,cms}.php`,
  `V2/Services/{Gallery,ContentRichEditor,LandingSectionsEditor,MailService,SEO,FeedRSS}/Routes/*.php`.
- Docs: `02_servicos-base/*.md`, `03_servicos-ui/**/*.md`,
  `05_modulos/**/rotas.md`, `05_modulos/Support/NoticiasImport/contrato-api.md`,
  `05_modulos/Conexoes/UnidadeRegional/api.md`.
- Índices: `_indices/servicos.csv`, `_indices/rotas.csv`, `_indices/config.csv`.
- Snapshot: 2026-10-21; `git -C sucesu-cms status --porcelain V2` vazio.
