---
id: MATRIZ-ENTIDADES
tipo: matriz
onda: 5
status: concluido
unidades: []
fontes:
  - V2/Core/Migrations/
  - V2/Services/
  - V2/Modules/
depende_de: [CORE-DATA, CORE-AUTH, SVC-GALLERY, SVC-SEARCH, MOD-PUBLICACOES-NOTICIAS]
consumidores: [MATRIZ-INTEGRACOES, MATRIZ-SINGULARIDADES, REIMPL-MIGRACAO]
criticidade: alta
dono: Matriz
---

# Entidades e propriedade: as 57 tabelas e quem manda em cada uma

Este documento responde, para cada tabela criada por migration no V2: **quem é
o dono funcional**, **quem escreve**, **quem lê**, **quais FKs lógicas cruzam
módulos**, **o que é legado/órfão** e **onde os tipos divergem**. A fonte
primária é `_indices/tabelas.csv` (60 linhas: 57 tabelas atuais + 3 linhas
históricas); o código foi usado para separar o que é tabela viva do que é backup.

## 1. Efeito

### Ficha de identidade

| Campo | Valor |
|---|---|
| Efeito primário | Define o mapa de persistência do V2: 57 tabelas atuais, seus donos, escritores, leitores e as FKs — reais e lógicas — que ligam módulos. |
| Entrada | 87 migrations em `V2/**/Migrations`; 57 `Schema::create`; models e `DB::table` dos controllers/serviços. |
| Saída | Catálogo de entidades + matriz de propriedade + lista de conflitos de tipo e tabelas fora de uso. |
| Efeitos colaterais | Nenhum em runtime; é documento de leitura e contrato para migração de dados. |
| Particularidade central | O dono no índice é o **diretório da migration**, não o módulo que usa a tabela: `v2_module_flags` está em `MOD-PUBLICACOES-TRABALHECONOSCO`, mas nasce em `SupportConfigs`; os pivôs de tag estão em `CORE-DATA`, mas pertencem a Conexões. |
| Como se integra | `08_matriz/integracoes-e-contratos.md` (quem chama quem); `09_reimplementacao/migracao-de-dados.md` (ordem de carga). |
| Se removido, quebra | Não há como reconstruir o schema nem saber quem escreve em cada tabela; a migração de dados perde a ordem de dependência. |
| Superfície pública | Documento markdown; os contratos reais são as migrations e os models. |

### 1.1 Números

| Medida | Valor | Fonte |
|---|---|---|
| Arquivos de migration | 87 | `00_inventario/manifest.json` |
| Migrations com `Schema::create` | 47 | `grep -c Schema::create` em `V2/**/Migrations` |
| Tabelas criadas | 57 | 47 migrations com `Schema::create` |
| Linhas no índice canônico | 60 | `_indices/tabelas.csv` |
| Tabelas atuais sem linha no índice | 0 | §3.8 |
| Linhas do índice que não são tabela atual | 3 | §3.8 / §4.3 |
| Tabelas com soft delete | 31 | `softDeletes` nos blocos `Schema::create` |
| Tabelas com PK `uuid`/`string(36)` | 43 | idem |
| Tabelas com PK inteira (`increments`) | 8 | idem |
| Tabelas com PK composta (pivôs) | 6 | idem |
| Grupos de colunas de mídia com tipo divergente | 6 (`uuid`, `varchar(36)`, `bigint`, `integer`, `unsignedInteger`, `uuid→unsignedInteger`) | §4.4 |

## 2. Abordagem

### 2.1 Como a propriedade foi determinada

1. **Criação:** a migration que executa `Schema::create` define o dono nominal.
2. **Escrita:** o controller/serviço que faz `insert/update/delete` define o
   dono efetivo. Exemplo: `v2_gallery_media` é criada por `SVC-GALLERY` e escrita
   só por `GalleryService` (`V2/Services/Gallery/Services/GalleryService.php:65`).
3. **Leitura:** os hooks de model, composers e controllers que consultam a
   tabela definem os consumidores. Exemplo: `v2_portal_configs` é lida por 8
   pontos do portal e escrita por 6 (`_indices/tabelas.csv`).
4. **Confronto:** quando o dono nominal e o dono efetivo divergem, a linha é
   marcada em §4.2.

### 2.2 Regras de persistência

| Regra | Valor | Evidência |
|---|---|---|
| Geração de PK | `v2_uuid()` em PHP, `Uuid::uuid4()` nos models e `v2_gen_uuid()` no Postgres | `V2/Core/Migrations/2026_06_01_000001_create_v2_uuid_function.php:17-37`; `01_arquitetura/05-persistencia-uuid-migracoes.md:24-30` |
| Soft delete | `deleted_at` em **31** tabelas; a lista completa está em `_indices/tabelas.csv` (coluna `soft_delete`) | `_indices/tabelas.csv` |
| Rollback | Renomeia para `backup_<tabela>_<YmdHis>` em vez de `DROP` | `V2/Modules/Publicacoes/Noticias/Migrations/2026_07_26_000002_remove_approval_workflow.php:27-32` |
| Índice de busca | Sem FK e sem fila; cada model escreve a projeção | `03_servicos-ui/search/spec.md:22-28` |
| Auditoria | Polimórfica (`subject_type/subject_id`, `causer_id` string) | `V2/Services/ActivityLogger/Migrations/2026_06_14_100000_create_activity_log_table.php:20-31` |

## 3. Catálogo de tabelas

Legenda: **Dono** = unidade que cria/mantém; **Escrita** = quem grava;
**Leitura** = consumidores principais; **FK lógica** = referência sem
constraint (a menos que marcada “real”).

### 3.1 Identidade, sessão e RBAC (9)

| Tabela | Dono | Escrita | Leitura | FK lógica | Estado |
|---|---|---|---|---|---|
| `activations` | `CORE-AUTH` | Sentinel `registerAndActivate`; `DatabaseSeeder` | `LoginCmsController` (`completed`), `CmsAuthenticate` | `user_id → users.id` | ativa |
| `persistences` | `CORE-AUTH` | Sentinel (login/logout) | `CmsAuthenticate`, views | `user_id → users.id` | ativa |
| `reminders` | `CORE-AUTH` | Sentinel (se usado) | nenhum consumidor V2 | `user_id → users.id` | **órfã funcional** |
| `role_users` | `CORE-AUTH` | `DatabaseSeeder`, `ensureSentinelRole`, Sentinel | `CmsAuthenticate`, `inRole()` | `user_id → users.id`, `role_id → roles.id` | ativa |
| `roles` | `CORE-AUTH` | `DatabaseSeeder` (`admin`), Gestão de Permissões | `CmsAuthenticate`, `inRole()` | — | ativa |
| `throttle` | `CORE-AUTH` | Sentinel | `Sentinel::authenticate` | `user_id → users.id` | ativa |
| `users` | `CORE-AUTH` | Sentinel (login), `DatabaseSeeder`, Gestão de Permissões | Auth, RBAC, Sidebar, escopo regional | `v2_role_id → v2_roles.id`; `unidade_regional_id → v2_unidade_regionais.id` | ativa |
| `v2_roles` | `CORE-AUTH` | `PermissionService`, migration regional | RBAC, sidebar, UI de perfis | `users.v2_role_id` (sem constraint) | ativa |
| `v2_internal_api_keys` | `CORE-AUTH` | `InternalApiKey::issue/markUsed/revoke` | `InternalApiAuth`, comando de chave | — | ativa |

### 3.2 Catálogo de tags (5)

| Tabela | Dono | Escrita | Leitura | FK lógica | Estado |
|---|---|---|---|---|---|
| `v2_conexao_tags` | `CORE-DATA` | `ConexaoTagCmsController@store`; migrations 000001/000002 | `ConexaoTag::parceiros/unidadesRegionais`; Parceiros e UR | — | ativa |
| `v2_associado_tags` | `CORE-DATA` (nominal) / `MOD-CONEXOES-ASSOCIADOS` (efetivo) | `AssociadoInstituicao::syncTagsFromArray`; migration 000019 | portal e CMS de Associados | — | **legado em uso** |
| `v2_associado_tag_pivot` | `CORE-DATA` | `syncTagsFromArray` (`sync`) | `AssociadoInstituicao::tags/primaryTag` | `associado_id → v2_associado_instituicoes.id`; `tag_id → v2_associado_tags.id` | ativa |
| `v2_parceiro_tag_pivot` | `CORE-DATA` | só `detach`/`syncWithoutDetaching` no destroy de tag | `Parceiro::tags`; `ConexaoTag::parceiros` | `parceiro_id → v2_parceiros_institucionais.id`; `tag_id → v2_conexao_tags.id` | **meio-órfã** (sem attach no CRUD) |
| `v2_unidade_regional_tag_pivot` | `CORE-DATA` | só `detach`/`syncWithoutDetaching` | `UnidadeRegional::tags` | `unidade_regional_id → v2_unidade_regionais.id`; `tag_id → v2_conexao_tags.id` | **meio-órfã** |

### 3.3 Editorial, agenda e vagas (12)

| Tabela | Dono | Escrita | Leitura | FK lógica | Estado |
|---|---|---|---|---|---|
| `v2_news` | `MOD-PUBLICACOES-NOTICIAS` | CMS, importação, API regional | portal, sitemap, feed, busca, widgets | `unidade_regional_id → v2_unidade_regionais.id` (**real**, ON DELETE SET NULL); `category_id → v2_news_categories.id`; `author_id → users.id`; `cover_image_id → v2_gallery_media.id` | ativa |
| `v2_news_categories` | `MOD-PUBLICACOES-NOTICIAS` | CMS, `RegionalIdentityService`, API, importação | CMS, portal, importação | `parent_id → v2_news_categories.id` | ativa |
| `v2_news_tags` | `MOD-PUBLICACOES-NOTICIAS` | CMS, importação | CMS, portal | — | ativa |
| `v2_news_tag_pivot` | `MOD-PUBLICACOES-NOTICIAS` | `tags()->sync`; importação | `News::tags` | `news_id → v2_news.id`; `tag_id → v2_news_tags.id` | ativa |
| `v2_news_gallery_media` | `MOD-PUBLICACOES-NOTICIAS` | `gallery()->sync`; importação | CMS, portal | `news_id → v2_news.id`; `gallery_media_id → v2_gallery_media.id` | ativa |
| `v2_news_import_keys` | `MOD-PUBLICACOES-NOTICIAS` | `NoticiasImportService::registerKey` | `NoticiasImportService` | `news_id → v2_news.id` | ativa |
| `v2_news_approvers` | `MOD-PUBLICACOES-NOTICIAS` | nenhuma | nenhum | — | **removida** (renomeada para `backup_`) |
| `v2_news_configs` | `MOD-PUBLICACOES-NOTICIAS` | nenhuma | nenhum | — | **removida** (renomeada para `backup_`) |
| `v2_eventos` | `MOD-PUBLICACOES-AGENDA` | CMS, seed, `PopulateMissingImages` | portal, home, dashboard, sitemap, feed | `image_id → v2_gallery_media.id`; `created_by → users.id` | ativa |
| `v2_job_openings` | `MOD-PUBLICACOES-TRABALHECONOSCO` | CMS, hooks, seed | portal, CMS, dashboard, busca/feed | `created_by → users.id`; `cover_image_id`/`attachment_pdf_id → v2_gallery_media.id` | ativa |
| `v2_job_applications` | `MOD-PUBLICACOES-TRABALHECONOSCO` | portal, CMS | CMS, dashboard | `job_opening_id → v2_job_openings.id` (**real**, CASCADE) | ativa |
| `v2_module_flags` | `MOD-PUBLICACOES-TRABALHECONOSCO` (nominal) / `MOD-SUPPORT-SUPPORTCONFIGS` (efetivo) | migration 000002; `SystemMaintenanceService::toggleModule` | `ModuleFlagService`, sidebar, middleware, dashboard | — | ativa |

### 3.4 Conexões e tenancy (7)

| Tabela | Dono | Escrita | Leitura | FK lógica | Estado |
|---|---|---|---|---|---|
| `v2_associado_instituicoes` | `MOD-CONEXOES-ASSOCIADOS` | CMS, API regional, seed | portal, home, dashboard, busca | `unidade_regional_id` via pivô de empresas; `created_by → users.id` | ativa |
| `v2_associado_instituicao_gallery` | `MOD-CONEXOES-ASSOCIADOS` | `uploadGallery/syncGalleryMediaIds/destroyGallery` | CMS, portal (detalhe) | `instituicao_id → v2_associado_instituicoes.id` (**real**, CASCADE); `gallery_media_id → v2_gallery_media.id` | ativa |
| `v2_chapters` | `MOD-CONEXOES-ASSOCIADOS` | rename para `backup_v2_chapters_<YmdHis>` | nenhum | — | **legada/arquivada** |
| `v2_parceiros_institucionais` | `MOD-CONEXOES-PARCEIROSINSTITUCIONAIS` | CMS, seed, `PopulateMissingImages` | portal, home, dashboard, sitemap, busca | `logo_id → v2_gallery_media.id`; `created_by → users.id` | ativa |
| `v2_unidade_regionais` | `MOD-CONEXOES-UNIDADEREGIONAL` | CMS, API, seed | portal, sitemap, busca, `RegionalIdentityService` | `created_by → users.id`; token hash interno | ativa |
| `v2_unidade_regional_empresas` | `MOD-CONEXOES-UNIDADEREGIONAL` | API (`linkEmpresa`), CMS | CMS, portal, `RegionalScopeService` | `unidade_regional_id → v2_unidade_regionais.id`; `empresa_id → v2_associado_instituicoes.id` | ativa |
| `v2_unidade_regional_media` | `MOD-CONEXOES-UNIDADEREGIONAL` (efetivo) / `SVC-GALLERY` (nominal) | `uploadGallery/syncGalleryMediaIds` | CMS, portal regional | `unidade_regional_id → v2_unidade_regionais.id`; `gallery_media_id → v2_gallery_media.id` | ativa |

### 3.5 Institucional (8)

| Tabela | Dono | Escrita | Leitura | FK lógica | Estado |
|---|---|---|---|---|---|
| `v2_membership_leads` | `MOD-INSTITUCIONAL-ASSOCIESE` | portal, CMS | CMS, dashboard | — | ativa (sem `metadata`, apesar do cast) |
| `v2_membership_plans` | `MOD-INSTITUCIONAL-ASSOCIESE` | CMS | portal, CMS | — | ativa |
| `v2_membership_plan_gallery` | `MOD-INSTITUCIONAL-ASSOCIESE` | `plans/{id}/gallery/sync` | CMS, portal | `plan_id → v2_membership_plans.id`; `gallery_media_id → v2_gallery_media.id` | ativa (tipo divergente) |
| `v2_mensagens_contato` | `MOD-INSTITUCIONAL-FALECONOSCO` | portal, CMS | CMS, dashboard | `created_by → users.id` | ativa |
| `v2_contato_configs` | `MOD-INSTITUCIONAL-FALECONOSCO` | **nenhuma** | **nenhum** | — | **órfã** (`@deprecated`) |
| `v2_historia_milestones` | `MOD-INSTITUCIONAL-HISTORIA` | CMS, seed | portal, sitemap | `image_id → v2_gallery_media.id`; `created_by → users.id` | ativa |
| `v2_bienniums` | `MOD-INSTITUCIONAL-SOBRENOS` | seeder/CRUD de biênios | `Biennium::current`, `SobreNosDataIntegrator` | — | ativa |
| `v2_board_members` | `MOD-INSTITUCIONAL-SOBRENOS` | `BoardMemberController` | `/sobre-nos`, `/equipe/{slug}`, busca | `biennium_id → v2_bienniums.id` (**real**, CASCADE); `photo_id → v2_gallery_media.id`; `created_by → users.id` | ativa |

### 3.6 Layout, tema e plataforma (10)

| Tabela | Dono | Escrita | Leitura | FK lógica | Estado |
|---|---|---|---|---|---|
| `v2_basic_pages` | `MOD-LAYOUTS-BASICPAGE` | CMS, migration, seeds, `ImageRedigestService` | catch-all, sitemap, busca, SEO | — | ativa |
| `v2_basic_page_assets` | `MOD-LAYOUTS-BASICPAGE` | `BasicPageAssetManagerService` | runtime, File Library | `gallery_media_id → v2_gallery_media.id` | ativa |
| `v2_layout_base_configs` | `MOD-SUPPORT-STRUCTURALLANDINGEDITOR` | SLE, Homepage, Sobre Nós, seeds | `LayoutBaseComposer`, `BlockRenderer`, módulos | — | ativa |
| `v2_sle_assets` | `MOD-SUPPORT-STRUCTURALLANDINGEDITOR` | `AssetManagerService` | SLE, portal | `gallery_media_id → v2_gallery_media.id` | ativa |
| `v2_structural_portal_contents` | `MOD-SUPPORT-STRUCTURALLANDINGEDITOR` | SLE, seeds | `BlockRenderer`, layout do portal | — | ativa |
| `v2_portal_configs` | `MOD-SUPPORT-SUPPORTCONFIGS` | `PortalConfigsService`, AssocieSe, História, seeds | portal (tema/SEO/features), SEO, feed | — | ativa |
| `v2_system_controls` | `MOD-SUPPORT-SUPPORTCONFIGS` | `SystemMaintenanceService` | `MaintenanceMiddleware`, dashboard | — | ativa |
| `v2_system_mail_configs` | `MOD-SUPPORT-SUPPORTCONFIGS` | `MailService::setConfig`, `UserConfigsService` | `MailService` | — | ativa |
| `v2_cms_theme_configs` | `MOD-SUPPORT-SUPPORTCONFIGS` | `SystemMaintenanceService` | `CmsThemeComposer`, SLE | — | ativa |
| `v2_homepage_sections` | `MOD-LAYOUTS-HOMEPAGE` | nenhuma em runtime | nenhum (model existe) | — | ativa no banco; **morta em runtime** |

### 3.7 Serviços transversais (9)

| Tabela | Dono | Escrita | Leitura | FK lógica | Estado |
|---|---|---|---|---|---|
| `activity_log` | `SVC-ACTIVITYLOGGER` | `ActivityLoggerService::log` (explícito) | timeline, `ActivityLoggerService::getHistory` | polimórfica (`subject`, `causer`) | ativa |
| `v2_gallery_media` | `SVC-GALLERY` | `GalleryService` | 16 unidades, LSE, SLE, BasicPage, SEO | — | ativa |
| `v2_cms_links_index` | `SVC-SEARCH` | `CMSIndexerService` | `SearchService::cmsSearch` | polimórfica (`module`, `edit_url`) | ativa |
| `v2_public_search_index` | `SVC-SEARCH` | `PublicIndexerService` (hooks de 8 models) | `/busca`, CRE, SEO, dashboard | polimórfica (`entity_type`, `entity_id`) | ativa |
| `v2_seo_page_visits` | `SVC-SEO` | `SEOService::flushBuffer` (lote de 50) | `getPageRanking`, dashboard | — | ativa |
| `v2_mail_logs` | `SVC-MAILSERVICE` | `MailService::logMail` | MailAudit, `/api/v2/mail/history` | — | ativa |
| `v2_feed_rss_items` | `SVC-FEEDRSS` | `FeedRssService` | `/feed.xml`, painel Feed RSS | polimórfica (`entity_type`, `entity_id`) | ativa |
| `v2_digital_certificates` | `SVC-DIGITALSIGNATURE` | `CertificateRepository` | Certificado Digital | `user_id → users.id` (**real**, CASCADE) | ativa |
| `v2_signature_logs` | `SVC-DIGITALSIGNATURE` | `SignatureLogRepository::log` | Certificado Digital | `certificate_id → v2_digital_certificates.id`; `user_id → users.id` (**real**) | ativa |

### 3.8 Tabelas recém-consolidadas no índice

O índice de 2026-10-21 já contém as três tabelas que faltavam na versão anterior
(57 → 60 linhas). Elas merecem ressalva de schema:

| Tabela | Dono | Colunas-chave | Ressalva |
|---|---|---|---|
| `v2_bienniums` | `MOD-INSTITUCIONAL-SOBRENOS` | `id uuid`, `label`, `start_year`, `end_year`, `is_current`, `metadata jsonb`, soft delete | PK UUID; `is_current` sem unique parcial (mais de um biênio pode ser corrente) |
| `v2_board_members` | `MOD-INSTITUCIONAL-SOBRENOS` | `id uuid`, `biennium_id uuid`, `name`, `position`, `bio jsonb`, `photo_id string(36)`, `slug`, `is_active`, soft delete | `photo_id` string(36) contra `v2_gallery_media.id` int; `created_by` string(36) contra `users.id` int |
| `v2_homepage_sections` | `MOD-LAYOUTS-HOMEPAGE` | `id uuid`, `section_key`, `type`, `sort_order`, `source_type`, `source_config`, `parameters`, soft delete | **morta em runtime**: nenhum leitor; a home usa `v2_layout_base_configs.payload` |

Evidência: `V2/Modules/Institucional/SobreNos/Migrations/2025_01_01_000001_create_v2_bienniums_table.php:18-31`;
`V2/Modules/Institucional/SobreNos/Migrations/2025_01_01_000002_create_v2_board_members_table.php:18-44`;
`V2/Modules/Layouts/Homepage/Migrations/2026_07_22_000001_create_v2_homepage_sections_table.php:16-27`.

## 4. Particularidades

### 4.1 FKs lógicas entre módulos (mapa)

| Origem | Coluna | Destino | Constraint? | Tipo origem → destino |
|---|---|---|---|---|
| `users` | `v2_role_id` | `v2_roles.id` | não | `uuid` → `uuid` |
| `users` | `unidade_regional_id` | `v2_unidade_regionais.id` | não | `uuid` → `uuid` |
| `v2_news` | `unidade_regional_id` | `v2_unidade_regionais.id` | **sim** (SET NULL) | `uuid` → `uuid` |
| `v2_news` | `category_id` | `v2_news_categories.id` | não | `varchar(36)` → `uuid` |
| `v2_news` | `author_id` | `users.id` | não | `varchar(36)` → `int` |
| `v2_news` | `cover_image_id` | `v2_gallery_media.id` | não | `varchar(36)` → `int` |
| `v2_news_gallery_media` | `news_id` / `gallery_media_id` | `v2_news.id` / `v2_gallery_media.id` | não | `uuid`/`bigint` |
| `v2_eventos` | `image_id` / `created_by` | `v2_gallery_media.id` / `users.id` | não | `varchar(36)` → `int` |
| `v2_job_openings` | `cover_image_id`, `attachment_pdf_id`, `created_by` | gallery / users | não | `varchar(36)` → `int` |
| `v2_job_applications` | `job_opening_id` | `v2_job_openings.id` | **sim** (CASCADE) | `uuid` → `uuid` |
| `v2_associado_instituicao_gallery` | `instituicao_id` | `v2_associado_instituicoes.id` | **sim** (CASCADE) | `uuid` → `uuid` |
| `v2_associado_instituicao_gallery` | `gallery_media_id` | `v2_gallery_media.id` | não | `varchar(36)` → `int` |
| `v2_parceiros_institucionais` | `logo_id` | `v2_gallery_media.id` | não | `varchar(36)` → `int` |
| `v2_unidade_regional_empresas` | `unidade_regional_id`, `empresa_id` | UR / associados | não | `uuid` → `uuid` |
| `v2_unidade_regional_media` | `gallery_media_id` | `v2_gallery_media.id` | não | `unsignedInteger` → `int` |
| `v2_membership_plan_gallery` | `plan_id`, `gallery_media_id` | plans / gallery | não | `uuid` → `uuid` / `int` |
| `v2_sle_assets`, `v2_basic_page_assets` | `gallery_media_id` | `v2_gallery_media.id` | não | `int` (correto) |
| `v2_board_members` | `biennium_id` | `v2_bienniums.id` | **sim** (CASCADE) | `uuid` → `uuid` |
| `v2_board_members` | `photo_id` | `v2_gallery_media.id` | não | `varchar(36)` → `int` |
| `v2_digital_certificates`, `v2_signature_logs` | `user_id` | `users.id` | **sim** | `int` → `int` |
| `activity_log`, índices de busca, feed | `*_id` / `entity_id` | polimórfico | não | `varchar`/`uuid` |

### 4.2 Propriedade nominal × efetiva (divergências)

| Tabela | Dono no CSV | Dono efetivo | Evidência | Consequência |
|---|---|---|---|---|
| `v2_module_flags` | `MOD-PUBLICACOES-TRABALHECONOSCO` | `MOD-SUPPORT-SUPPORTCONFIGS` | criação em `SupportConfigs/Migrations/2026_06_30_000002...:33-84`; Trabalhe Conosco só insere a própria flag | o índice atribui a tabela ao módulo que a consome, não a quem a define |
| `v2_unidade_regional_media` | `SVC-GALLERY` | `MOD-CONEXOES-UNIDADEREGIONAL` | criação em `UnidadeRegional/Migrations/2026_07_23_000003...:17-27` | o índice mistura “usa Gallery” com “é dono da tabela” |
| `v2_associado_tags` e pivôs | `CORE-DATA` | `MOD-CONEXOES-ASSOCIADOS` / `CORE-DATA` | `AssociadoInstituicao::tags()`; `ConexaoTag` | o catálogo compartilhado nasceu no Core, mas o domínio é de Conexões |
| `v2_chapters` | `MOD-CONEXOES-ASSOCIADOS` | nenhum (arquivada) | rename em `2024_01_01_000013...:18-28` | linha descreve tabela que não existe |
| `v2_news_approvers` / `v2_news_configs` | `MOD-PUBLICACOES-NOTICIAS` | nenhum (renomeadas para `backup_`) | `2026_07_26_000002...:27-32` | idem |

### 4.3 Tabelas órfãs, legadas ou renomeadas

| Tabela | Classificação | Prova | Destino na reimplementação |
|---|---|---|---|
| `v2_contato_configs` | órfã (`@deprecated`, zero leitores) | `ContatoConfig.php:8-12`; nenhum `DB::table`/model em controllers | não criar; usar `v2_portal_configs` (`contato_*`) |
| `v2_chapters` | legada/arquivada | `2024_01_01_000013...:18-28` | não criar; se migrar dados, ler `backup_v2_chapters_*` |
| `v2_news_approvers` | removida | `2026_07_26_000002...:27-30` | não criar |
| `v2_news_configs` | removida | idem | não criar |
| `reminders` | órfã funcional | nenhum consumidor V2 em `_indices/tabelas.csv` | criar só por compatibilidade Sentinel |
| `v2_homepage_sections` | morta em runtime | model `HomepageSection` sem consumidor; conteúdo real em `v2_layout_base_configs` | não criar, ou criar e ignorar |
| `v2_associado_tag_pivot` | legado em uso | portal filtra por `v2_associado_tags` | manter até migrar o portal para `v2_conexao_tags` |
| `v2_parceiro_tag_pivot` | meio-órfã | só `detach` no destroy de tag; nenhum attach no CRUD | criar, mas prever attach no CRUD |

### 4.4 Conflitos de tipo

| Coluna | Tipo | Alvo | Tipo do alvo | Tabelas afetadas | Risco |
|---|---|---|---|---|---|
| `gallery_media_id` | `uuid` | `v2_gallery_media.id` | `increments` (int) | `v2_membership_plan_gallery` | comparação/join falha ou exige cast |
| `gallery_media_id` | `varchar(36)` | `v2_gallery_media.id` | `int` | `v2_associado_instituicao_gallery` | idem |
| `gallery_media_id` | `unsignedBigInteger` | `v2_gallery_media.id` | `int` | `v2_news_gallery_media` | compatível por cast, mas tipo diverge |
| `gallery_media_id` | `integer` | `v2_gallery_media.id` | `int` | `v2_basic_page_assets` | correto |
| `gallery_media_id` | `unsignedInteger` | `v2_gallery_media.id` | `int` | `v2_sle_assets`, `v2_unidade_regional_media` | correto após fix |
| `gallery_media_id` | `uuid` → `unsignedInteger` | `v2_gallery_media.id` | `int` | `v2_unidade_regional_media` | migration de correção em base existente |
| `logo_id` | `varchar(36)` | `v2_gallery_media.id` | `int` | `v2_parceiros_institucionais` | idem |
| `image_id` | `varchar(36)` | `v2_gallery_media.id` | `int` | `v2_eventos`, `v2_historia_milestones` | idem |
| `cover_image_id`, `attachment_pdf_id` | `varchar(36)` | `v2_gallery_media.id` | `int` | `v2_news`, `v2_job_openings` | idem |
| `photo_id` | `varchar(36)` | `v2_gallery_media.id` | `int` | `v2_board_members` | idem |
| `author_id`, `created_by` | `varchar(36)` | `users.id` | `increments` (int) | 7 tabelas | idem; `created_by` aceita string numérica por acidente |

Evidência dos tipos: `V2/Services/Gallery/Migrations/2026_06_28_000000_create_v2_gallery_media_table.php:24`
(`$table->increments('id')`); `V2/Modules/Institucional/AssocieSe/Migrations/2025_07_20_000002_create_v2_membership_plan_gallery_table.php:26`
(`uuid('gallery_media_id')`); `V2/Modules/Publicacoes/Noticias/Migrations/2026_07_26_000001_create_v2_news_gallery_pivot_table.php:24`
(`unsignedBigInteger`); `V2/Modules/Conexoes/Associados/Migrations/2024_01_01_000011_add_gallery_media_id_to_associado_instituicao_gallery.php:17`
(`string 36`).

### 4.5 Índices e unicidade que mudam comportamento

| Tabela | Constraint | Efeito | Evidência |
|---|---|---|---|
| `v2_feed_rss_items` | unique `(entity_type, entity_id)` sem filtro de `deleted_at` | item removido não pode voltar (unique violation) | `02_servicos-base/feed-rss.md:25-27` |
| `v2_unidade_regional_empresas` | unique `(unidade_regional_id, empresa_id)` sem `deleted_at` | religar empresa soft-deleted viola unique | `_indices/tabelas.csv` |
| `v2_news` | unique `slug` + recálculo em PHP | slug digitado é ignorado; colisão é resolvida por sufixo | `05_modulos/Publicacoes/Noticias/dados.md:29-31` |
| `v2_cms_links_index` | unique `(module, edit_url)` | `remove` por id não remove (usa id onde espera URL) | `_indices/tabelas.csv` |
| `v2_public_search_index` | unique `(entity_type, entity_id)` + trigger tsvector | upsert por entidade; órfãos não são removidos | `03_servicos-ui/search/spec.md:22-28` |
| `v2_roles` | unique `slug` | bloqueio textual de `super-admin` na UI | `GestaoPermissoesRolesController.php:100-106` |

## 5. Integrabilidade

### 5.1 Ordem de criação (dependências reais)

```text
1. v2_uuid()                         (função SQL)
2. users, roles, role_users, ...     (Sentinel)
3. v2_roles                          (users.v2_role_id lógico)
4. v2_unidade_regionais              (users.unidade_regional_id lógico)
5. v2_gallery_media                  (mídia referenciada por 7 tabelas)
6. v2_conexao_tags + pivôs           (catálogo compartilhado)
7. v2_news_categories → v2_news → pivôs
8. v2_eventos, v2_job_openings → applications
9. v2_associado_instituicoes → gallery
10. v2_bienniums → v2_board_members
11. v2_layout_base_configs, v2_portal_configs, v2_system_*
12. índices de busca, SEO, mail, feed, assinatura
```

### 5.2 Receita: escrever em uma tabela de outro módulo

```php
// Correto: use o model/serviço dono, não DB::table de outro módulo.
$media = app(\V2\Services\Gallery\Services\GalleryService::class)
    ->find($galleryMediaId); // retorna array com variants/metadata

DB::table('v2_news_gallery_media')->insert([
    'news_id' => $news->id,
    'gallery_media_id' => (int) $media['id'], // alvo é int, não uuid
    'sort_order' => 1,
]);
```

### 5.3 Receita: consultar com escopo regional

```php
$query = \V2\Modules\Publicacoes\Noticias\Models\News::query();
app(\V2\Core\Services\RegionalScopeService::class)->applyScope($query);
// só aplica se o model implementar RegionalOwnable e o usuário tiver unidade_regional_id
```

### 5.4 Anti-uso

- **Não** crie FK física para `v2_gallery_media` sem antes corrigir o tipo das
  colunas: 7 tabelas usam `uuid`/`varchar(36)` contra `int`.
- **Não** use `v2_associado_tags` em código novo: o catálogo canônico é
  `v2_conexao_tags`; o legado só permanece pelo portal de Associados.
- **Não** apague linhas de `v2_module_flags` para “reativar”: a ausência de
  linha significa **ativo** (`ModuleFlagService.php:91-94`).
- **Não** confie em `v2_news_approvers`/`v2_news_configs`: foram renomeadas para
  `backup_` e não têm leitor.
- **Não** use `v2_homepage_sections` como fonte: o payload real é
  `v2_layout_base_configs.payload` (`HomepageCmsController.php:30-34`).

## 6. Lacunas

- `LG-ENT-01` — `_indices/tabelas.csv` agora tem 60 linhas: 57 tabelas atuais
  e 3 linhas históricas (`v2_chapters`, `v2_news_approvers`, `v2_news_configs`).
  A distinção está em `reconciliacao-indices.md`; consumidores automáticos devem
  filtrar pelo campo `papel`.
- `LG-ENT-02` — não há contagem de linhas por tabela (o banco não foi acessado);
  toda afirmação de volume seria inferência.
- `LG-ENT-03` — não há DDL completo de `v2_chapters` (tabela arquivada sem model
  nem schema no corpus).
- `LG-ENT-04` — os tipos de `created_by`/`author_id` não têm migration de
  correção; não se sabe se o banco real armazena id numérico ou UUID.
- `LG-ENT-05` — `v2_parceiro_tag_pivot` e `v2_unidade_regional_tag_pivot` não
  têm caminho de attach no CRUD; a intenção (tags por formulário) não está
  implementada.

## 7. Evidências

- `_indices/tabelas.csv` (60 linhas: 57 atuais + 3 históricas) e `_indices/rotas.csv` (para consumidores
  HTTP).
- 87 migrations em `V2/Core/Migrations`, `V2/Modules/*/*/Migrations`,
  `V2/Services/*/Migrations`.
- Models e serviços citados nas tabelas; `01_arquitetura/05-persistencia-uuid-migracoes.md`.
- Snapshot: 2026-10-21; `git -C sucesu-cms status --porcelain V2` vazio.
