---
id: REIMPL-MIGRACAO
tipo: reimplementacao
onda: 5
status: concluido
unidades: []
fontes:
  - V2/
  - app/
  - config/
  - database/
  - public/
  - .env.example
depende_de: [REIMPL-ORDEM, REIMPL-RISCOS, CORE-DATA, SVC-STORAGE, SVC-DIGITALSIGNATURE]
consumidores: [equipe-de-reconstrucao, dba, devops]
criticidade: alta
dono: agente-reimplementacao
---

## Efeito

Define o que precisa ser **migrado** (dados e arquivos que não podem ser recriados), o
que precisa ser **recriado** (schema, configuração, índices) e o que deve ser
**descartado** (restos de rollback, tabelas sem consumidor, cache). O efeito esperado é
uma troca de sistema sem perda de conteúdo editorial, mídia, certificados ou credenciais.

Premissa de leitura: migrar não é copiar o schema. O schema-alvo é o **schema novo**
(nomes canônicos, sem `v2_*`), semanticamente equivalente ao do legado; o dado é copiado
com transformação explícita. As duas coisas têm ordens diferentes.

**Modalidade.** Este documento descreve o **Modo A** (cutover com ETL). O **Modo B**
(base nova, conteúdo entrado à mão pelo CMS, `301` curados) está em
`pilha-alvo-public-v7.md` §7; a escolha é de produto e deve ser registrada antes da M0.
No Modo B, M1–M9 não se aplicam; restam custódia de segredos, redesign do schema e
curadoria editorial.

## Abordagem

### 1. Classificação do acervo

| Classe | O que é | Ação | Evidência |
|---|---|---|---|
| **D1 — migrar verbatim** | conteúdo editorial e cadastros: notícias, categorias, tags, eventos, páginas fixas, marcos, planos, parceiros, associados, unidades regionais, vagas, leads, mensagens | copiar com IDs preservados | `_indices/tabelas.csv` |
| **D2 — migrar com transformação** | JSONB (`metadata`, `payload`, `variants`), flags, tipos de mídia, pivôs de tags, `metadata` duplo-encode | decodificar/reencodar uma vez; converter tipos | `05_modulos/Layouts/BasicPage/spec.md:242,409`; `05_modulos/Institucional/AssocieSe/dados.md:78` |
| **D3 — migrar com segredo** | certificados (PEM + chave cifrada), senhas SMTP, `APP_KEY`, chaves de API | copiar ciphertext + custodiar a chave antiga; re-criptografar se a pilha mudar | `02_servicos-base/digital-signature/spec.md:25,203-216`; `_indices/config.csv:12,139` |
| **D4 — reconstruir** | schema, índices de busca, feed, cache de página, assets derivados (variantes) | gerar por comando/processo, não copiar | `03_servicos-ui/search/spec.md:23,100`; `02_servicos-base/feed-rss.md:120` |
| **D5 — descartar** | `backup_*`, tabelas órfãs, cache, arquivos `.bak`, duplicatas | não migrar; registrar decisão | `_indices/tabelas.csv:16,20,37,39`; `01_arquitetura/12-migracoes-inventario.md:390-407` |

### 2. O que migrar, por grupo

#### 2.1 Tabelas (57 no índice canônico)

O índice lista 57 tabelas (54 ativas + 3 arquivadas/removidas); as 87 migrations incluem alters, cópias e backups
(`01_arquitetura/12-migracoes-inventario.md:109-121,263`). Grupos e ordem:

| Grupo | Tabelas | Observação de migração |
|---|---|---|
| Identidade | `users`, `roles`, `role_users`, `persistences`, `activations`, `reminders`, `throttle`, `v2_roles`, `v2_internal_api_keys` | preservar IDs e hashes de senha se o algoritmo for compatível; caso contrário, forçar reset. `v2_internal_api_keys` guarda `sha256`, não o segredo |
| Mídia | `v2_gallery_media`, `v2_unidade_regional_media`, `v2_news_gallery_media`, `v2_membership_plan_gallery`, `v2_associado_instituicao_gallery` | `v2_gallery_media.id` é **integer**; os pivôs de Associados (`varchar(36)`) e AssocieSe (`uuid`) não têm o mesmo tipo e precisam de correção/validação |
| Conteúdo | `v2_news`, `v2_news_categories`, `v2_news_tags`, `v2_news_tag_pivot`, `v2_eventos`, `v2_basic_pages`, `v2_basic_page_assets`, `v2_historia_milestones`, `v2_job_openings`, `v2_job_applications` | IDs e slugs preservados; `v2_basic_pages` tem 5 linhas de migration + ~6 de seeders |
| Conexões | `v2_unidade_regionais`, `v2_unidade_regional_empresas`, `v2_associado_instituicoes`, `v2_parceiros_institucionais`, `v2_associado_tags`, `v2_conexao_tags`, pivôs | decidir o catálogo único de tags antes de copiar os pivôs |
| Institucional | `v2_membership_plans`, `v2_membership_leads`, `v2_mensagens_contato` | `v2_membership_leads` **não tem** a coluna `metadata` referenciada pelo model; criar a coluna ou remover a referência antes de copiar |
| Configuração | `v2_portal_configs`, `v2_cms_theme_configs`, `v2_system_controls`, `v2_module_flags`, `v2_system_mail_configs`, `v2_layout_base_configs`, `v2_structural_portal_contents`, `v2_sle_assets` | copiar valores, não defaults; senha SMTP cifrada |
| Operação | `activity_log`, `v2_mail_logs`, `v2_signature_logs`, `v2_seo_page_visits`, `v2_digital_certificates`, `v2_news_import_keys`, `v2_feed_rss_items`, `v2_public_search_index`, `v2_cms_links_index` | logs/índices: decidir retenção; feed e busca são reconstruíveis |
| Órfãs | `v2_contato_configs`, `v2_chapters` (backup), `v2_news_approvers` (backup), `v2_news_configs` (backup) | **não migrar**; ver D5 |

#### 2.2 Seeds (15 arquivos)

`00_inventario/manifest.json` registra três unidades de seed:

| Unidade | Arquivos | Papel | Ordem |
|---|---|---|---|
| `DATA-SEEDS-SLE` | `SleAssetSeeder`, `SleConfigsSeeder`, `SleFooterSeeder`, `SleHeaderSeeder`, `StructuralPortalSeeder` | ativos e conteúdo estrutural do portal | 1 |
| `DATA-SEEDS-BASICPAGES` | `AgendaSeeder`, `AssociadosSeeder`, `ConveniosSeeder`, `FaleConoscoSeeder`, `HistoriaMilestonesSeeder`, `NoticiasSeeder`, `ParceirosInstitucionaisSeeder`, `ProcessesGalleryImages`, `SucesuHomepageSeeder` | páginas sombra + imagens de exemplo | 2 |
| `DATA-SEEDS-CONTENT` | `DemoContentSeeder` | conteúdo de demonstração | 3 |

Regra: **seed não é caminho de migração**. Em base com dados legados, os seeders só rodam
para completar o que não existe (assets de SLE, imagens de exemplo); rodar `db:seed`
inteiro pode duplicar/reescrever conteúdo. Em instalação nova, a ordem acima é a única
válida porque os seeders usam `seedFromPath`, `createFromGallery` e payloads de SLE.
Evidência: `05_modulos/Layouts/BasicPage/spec.md:29,337,354,394-396`;
`00_inventario/manifest.json`.

#### 2.3 Configuração (156 chaves + `.env`)

| Origem | O que migrar | Cuidado |
|---|---|---|
| `.env` | `APP_KEY`, `APP_ENV`, `APP_URL`, `DB_*`, `REDIS_*`, `CACHE_DRIVER`, `SESSION_*`, `MAIL_*`, `AWS_*`, `V2_*` | `APP_ENV` do compose é `prod`; a guarda do canal IA só reconhece `production` (`_qa/security-g1.md:48-63`) |
| `config/*.php` | 13 arquivos; timezone `America/Fortaleza`, locale `pt-br`, `cache.prefix=laravel`, `database.default=pgsql` | não copiar valores de segredo do repositório |
| Banco | 18 chaves de `v2_portal_configs`; 7 flags; 3 controles; 3 perfis de tema CMS; SMTP | `theme_secondary_color`, `cms_brand_name`, `cms_brand_logo` e `cms_favicon` não têm seed (`05_modulos/Support/SupportConfigs/dados.md:284,304,483`) |
| Chaves sensíveis | `APP_KEY`, `V2_INTERNAL_API_ACCESS_KEY`, `V2_SUPPORT_EMAIL`, credenciais AWS/SMTP | `V2_SUPPORT_EMAIL` é identidade com bypass total; não copiar sem decisão (`_indices/config.csv:139`) |

Referências: `_indices/config.csv:12,31,45,52-59,84,99,125-126,139`;
`01_arquitetura/11-satelites-build-config.md:89,98`.

#### 2.4 Arquivos em storage

| Caminho | Conteúdo | Migração |
|---|---|---|
| `storage/app/public/gallery/<owner_module>/` | originais da galeria | copiar preservando `file_path` exato; a URL é `/storage/<path>` |
| `storage/app/public/.../variants/` | WebP `360/720/1200/1920` ou `original`; PDF `temp_cover_*` | copiar; se faltar, regenerar por `v2:populate-variants` |
| `storage/app/public/...` de assets de página/SLE | File Library | copiar + conferir snippets |
| `storage/app/imports/AAAA/MM/` | uploads do importador de planilhas | copiar ou descartar (arquivo operacional) |
| `storage/app/resumes/<hash>` | currículos de Trabalhe Conosco | copiar se houver retenção legal; disco `local`, não público |
| `public/assets/**` | CSS/JS/fontes/vendor versionados | copiar como estão; não há build (`01_arquitetura/11-satelites-build-config.md:41,57,268`) |
| `public/storage` | symlink para `storage/app/public` | recriar com `storage:link`; o código não cria |

Referências: `02_servicos-base/storage.md:43-44,286-287,332,468`;
`03_servicos-ui/media/spec.md:38,55,290`;
`05_modulos/Layouts/BasicPage/spec.md:337`;
`_indices/config.csv:51-53`.

#### 2.5 Certificados e assinaturas

| Item | O que existe | Como migrar |
|---|---|---|
| `v2_digital_certificates` | `certificate_pem` + `private_key_encrypted` + `private_key_iv`; sem coluna de senha/PFX | copiar o ciphertext e o `user_id`; **não** tentar reexportar PFX (não é guardado) |
| Chave de decifragem | `sha256(APP_KEY . "\|v2-digital-signature\|" . user_id)` | custodiar a `APP_KEY` antiga; sem ela a chave privada é irrecuperável |
| `v2_signature_logs` | auditoria de tentativas | copiar com retenção definida; `document_hash` e `signature_algorithm` são evidência |
| PDFs assinados | arquivos externos ao banco | migrar apenas se houver storage definido; a assinatura não é revalidável sem o PDF original |

Referências: `02_servicos-base/digital-signature/spec.md:25,70,148,203-216,240`;
`PC-SVC-DIGITALSIGNATURE-04`.

### 3. Ordem de execução

| Fase | Ação | Pré-requisito | Saída verificável |
|---|---|---|---|
| **M0 — Congelar e custodiar** | parar escrita; snapshot do banco e do storage; separar `APP_KEY` e senhas em cofre | — | backup restaurável + hashes |
| **M1 — Schema** | reconstruir as 54 tabelas ativas por migrations equivalentes, com PK/FK/unique/índices | esquema-alvo aprovado | `migrate` limpo; nenhuma `backup_*` |
| **M2 — Fundação** | roles/perfis, permissões, categorias base, tags (`geral`), configs, flags, controles, tema, 5 páginas fixas | M1 | login funciona; tema e flags presentes |
| **M3 — Mídia** | `v2_gallery_media` + arquivos + variantes | M1, M2 (config de disco), storage montado | `SELECT count(*)` bate; cada `file_path` existe |
| **M4 — Conexões** | Unidades Regionais, Associados, Parceiros, tags e pivôs | M2, M3 | categoria `regional-<sigla>` por UR; tags sem duplicata |
| **M5 — Publicações** | Notícias (+ pivôs, galeria, chaves de importação), Agenda, Trabalhe Conosco | M3, M4 | contagens e integridade referencial |
| **M6 — Institucional e páginas** | História, Fale Conosco, AssocieSe, BasicPage, SLE/LSE payloads | M3, M4 | `metadata` decodificado uma vez; payloads renderizam |
| **M7 — Operação e segredos** | certificados, assinaturas, mail logs, activity log, visitas SEO | M2 (APP_KEY) | decifragem de amostra OK |
| **M8 — Reconstruir derivados** | índice público/CMS, feed, cache de página | M5–M7 | reindexação e feed coerentes |
| **M9 — Seeds complementares** | SLE assets, BasicPages, DemoContent (apenas o ausente) | M6, M8 | idempotência em segunda execução |

**Por que mídia antes de conteúdo:** `v2_news.cover_image_id`, galerias de notícia, logo de
UR, imagem de plano e assets de BasicPage referenciam IDs de `v2_gallery_media`. Copiar
conteúdo antes da mídia deixa FKs lógicas quebradas — e o legado tem várias sem constraint
física (`_indices/tabelas.csv:32,40,57`).

**Por que configs antes de mídia:** `filesystems.media_disk` decide o adaptador; copiar
arquivos com o disco errado grava no bucket/disco errado
(`_indices/config.csv:52-59`; `02_servicos-base/storage.md:286-287`).

### 4. Riscos de perda e decisões

| ID | Risco de perda | Causa | Decisão |
|---|---|---|---|
| M-01 | Chave privada de certificado irrecuperável | troca de `APP_KEY` ou de `user_id` | custodiar a chave antiga; re-criptografar com a nova **antes** de descartar a antiga; teste CT-SIGN-02 |
| M-02 | Senha SMTP vira ciphertext de ciphertext | migration de encrypt roda de novo com `APP_KEY` nova | rodar a migration só com a chave correta; validar `Crypt::decrypt` em amostra (`05_modulos/Support/SupportConfigs/dados.md:210,296`) |
| M-03 | `metadata` duplamente codificado | `json_encode` + cast `array` | decodificar uma vez na importação e gravar array; validar tipo no banco (`05_modulos/Layouts/BasicPage/spec.md:242,409`) |
| M-04 | Leads de AssocieSe não migram | coluna `metadata` inexistente no schema | criar coluna ou remover a atribuição antes do INSERT (`05_modulos/Institucional/AssocieSe/spec.md:32,410`) |
| M-05 | Imagem de plano/associado não carrega | `gallery_media_id` é `uuid` no plano e `varchar(36)` no associado, enquanto o PK da galeria é integer | converter para integer e validar órfãos (`05_modulos/Institucional/AssocieSe/dados.md:78`; `_indices/tabelas.csv:10,32`) |
| M-06 | Arquivo sobrescrito | dois uploads com o mesmo nome em `gallery/<owner_module>/` | deduplicar por hash antes de copiar; renomear colisões (`03_servicos-ui/gallery/spec.md:458`) |
| M-07 | Variantes ausentes | arquivo copiado sem `variants/` | regenerar por comando; validar `variants` JSON (`PC-GALLERY-11`) |
| M-08 | Tags duplicadas/perdidas | dois catálogos + pivô não migrado | escolher catálogo, migrar os dois pivôs, unique por slug (`01_arquitetura/05-persistencia-uuid-migracoes.md:184,289`) |
| M-09 | Índice de busca desatualizado | cópia direta de `v2_public_search_index` | reconstruir por `v2:reindex-public`; o comando legado não cobre todos os módulos (`03_servicos-ui/search/spec.md:72,332`) |
| M-10 | Feed quebrado ao republicar | unique sem filtro + soft delete | reconstruir itens ativos; não copiar removidos (`02_servicos-base/feed-rss.md:25,291`) |
| M-11 | Auditoria perdida | `activity_log`/`v2_mail_logs` tratados como cache | migrar com retenção explícita; a retenção de 365 dias nunca rodou (`02_servicos-base/activity-logger.md:83,292`) |
| M-12 | Dados pessoais expostos | `v2_mail_logs.body`, leads, candidaturas, currículos | copiar para ambiente restrito; definir prazo e base legal antes de migrar |
| M-13 | IDs regenerados quebram referências | inserir sem `id` e deixar default | copiar IDs; reajustar sequences de PK integer depois |
| M-14 | Rollback recria `backup_*` | `down()` renomeia tabelas | não usar rollback como plano de migração; restaurar snapshot (`01_arquitetura/12-migracoes-inventario.md:406-407`) |

### 5. Validação pós-migração

Rodar nesta ordem; qualquer falha bloqueia o cutover.

| # | Verificação | Como | Critério |
|---|---|---|---|
| V1 | Contagens por tabela | `SELECT count(*)` origem × destino para cada uma das 54 ativas | igual, exceto D4/D5 declaradas |
| V2 | Integridade referencial lógica | consultas de órfãos em `cover_image_id`, `gallery_media_id`, `category_id`, `unidade_regional_id`, pivôs | zero órfãos |
| V3 | Tipos e JSON | amostra de `metadata`, `payload`, `variants` | objeto/array, não string dupla |
| V4 | Arquivos | para cada `file_path`, `Storage::exists`; para cada variante, exists | 100% dos ativos |
| V5 | Decifragem | importar 1 PFX de teste; `getConfig` de SMTP | chave decifra; senha autentica |
| V6 | Busca | `v2:reindex-public` + `GET /busca?q=` | resultados dos 8 modelos previstos |
| V7 | Feed | `GET /feed.xml` | XML válido, itens ativos, limite configurado |
| V8 | Permissões | CT-PERM-01..07 | matriz verde |
| V9 | Front | smoke de `/`, `/{slug}`, `/noticias`, `/agenda`, `/regionais`, `/cms` | 200 e conteúdo |
| V10 | Reexecução | `migrate:fresh --seed` em base de teste | sem `backup_*` (`PC-CORE-DATA-23`) |

## Particularidades

1. **A `APP_KEY` é dado de migração, não configuração.** Ela decifra cookies, senhas SMTP
   e chaves privadas de certificado. Perdê-la perde três classes de dado de uma vez
   (`_indices/config.csv:12`; `02_servicos-base/digital-signature/spec.md:25`).
2. **Certificado não é reexportável.** O legado guarda PEM + chave cifrada; o PFX original
   não é persistido. A migração só funciona com o ciphertext e a chave antiga
   (`02_servicos-base/digital-signature/spec.md:240`).
3. **Nem tudo que tem tabela é dado.** `v2_feed_rss_items`, `v2_public_search_index`,
   `v2_cms_links_index` e o cache de página são projeções; copiá-los congela bugs
   (unique de feed, índice incompleto).
4. **Cinco páginas fixas nascem de migration, não de seed.** `homepage`, `lgpd`,
   `acessibilidade`, `mapa-do-site`, `ouvidoria` existem com `content=''` e SEO de fábrica
   (`05_modulos/Layouts/BasicPage/spec.md:354`). Se a reconstrução as criar por seed, a
   ordem muda e o rollback se comporta diferente.
5. **Páginas sombra são intencionais.** Os seeders criam `is_runtime=true` para
   `noticias`, `associados`, `convenios`, `agenda`, `fale-conosco`,
   `parceiros-institucionais`; o portal serve a rota do módulo, não o `content`
   (`05_modulos/Layouts/BasicPage/spec.md:394`). Não “limpar” essas linhas na migração.
6. **A homepage semeada é um caso especial.** O seeder zera `content` e remove o runtime
   (`05_modulos/Layouts/BasicPage/spec.md:415`); migrar o valor antigo pode reativar um
   tema estático que não é mais usado.
7. **`activity_log` cresce para sempre.** A retenção de 365 dias é só configuração; não há
   job agendado (`02_servicos-base/activity-logger.md:83,292`). Migrar sem política de
   retenção transfere o problema.
8. **O storage pode ser S3.** `media_disk='s3'` só troca de adaptador com credenciais;
   sem elas, o serviço usa `LocalAdapter('s3')` e grava local (`02_servicos-base/storage.md:286-287`).
9. **Arquivos e banco podem divergir.** O legado tem colunas de path duplicadas
   (`v2_unidade_regional_media.image`, `v2_associado_instituicao_gallery.path`,
   `v2_membership_plan_gallery.image`) que podem apontar para outro arquivo que não o
   `file_path` da galeria. A migração deve escolher uma fonte e registrar a divergência.
10. **O rollback não é limpeza.** `down()` renomeia para `backup_<tabela>_<timestamp>`; um
    rollback completo deixa dezenas de backups (`01_arquitetura/12-migracoes-inventario.md:406-407`).

## Integrabilidade

### Receitas de uso

**1. Ensaio de migração completo.**

```bash
# 1. snapshot e custódia
pg_dump -Fc origem > origem.dump
tar -czf storage.tgz storage/app/public storage/app/imports storage/app/resumes
# 2. subir schema-alvo
php artisan migrate --force
# 3. importar por fase M2..M7 (scripts idempotentes, um por grupo)
# 4. reconstruir derivados
php artisan v2:reindex-public
php artisan v2:populate-variants
# 5. validar
php artisan migrate:status
```

**2. Copiar uma tabela com ID preservado (exemplo).**

```sql
-- origem -> destino; nunca deixar o destino gerar ID
INSERT INTO v2_news (id, title, slug, content, status, published_at, category_id, cover_image_id)
SELECT id, title, slug, content, status, published_at, category_id, cover_image_id
FROM origem.v2_news;
-- depois: SELECT setval(pg_get_serial_sequence('v2_gallery_media','id'), max(id)) ...
```

**3. Re-criptografar segredo com a chave nova.**

```text
1. ler ciphertext com APP_KEY_OLD e o user_id original;
2. gravar com APP_KEY_NEW (mesmo algoritmo/IV novo);
3. validar decrypt com a chave nova;
4. só então descartar APP_KEY_OLD.
```

**4. Validar um arquivo de mídia ponta a ponta.**

```bash
test -f "storage/app/public/$FILE_PATH" && echo ok
php artisan v2:populate-variants --only=...   # só para imagens sem variants
```

## Anti-uso

1. **Copiar o schema com `pg_dump --schema-only`.** O alvo é o schema reconstruído; copiar
   DDL legado importa `backup_*`, tipos errados e constraints faltantes.
2. **Rodar `db:seed` sobre base migrada.** Os seeders criam páginas sombra e ativos; em
   base cheia, duplicam ou sobrescrevem conteúdo.
3. **Migrar `v2_feed_rss_items` e `v2_public_search_index` como verdade.** São caches;
   reconstrua. O feed tem unique sem filtro e o índice não cobre todos os módulos.
4. **Trocar `APP_KEY` antes de re-criptografar.** Perde SMTP e certificados sem erro
   visível.
5. **Converter `gallery_media_id` para UUID “por consistência”.** O PK real da galeria é
   integer; a conversão quebra os vínculos existentes.
6. **Apagar `activity_log`/`v2_mail_logs` para “limpar”.** São auditoria; a decisão de
   retenção precisa ser registrada.
7. **Usar rollback como plano B.** `down()` renomeia; o banco acumula backups e o
   `migrate` seguinte recria as originais.

## Lacunas

| ID | Lacuna | Impacto |
|---|---|---|
| `LG-REIMPL-16` | Não há snapshot do banco de produção neste corpus | contagens reais e dados sem seed não podem ser validados aqui |
| `LG-REIMPL-17` | `_indices/dados-iniciais.csv` vazio | ordem/idempotência dos 15 seeders foi derivada do manifest e dos docs |
| `LG-REIMPL-18` | Não há inventário de arquivos físicos em `storage/` | a validação V4 depende de coleta no ambiente de origem |
| `LG-REIMPL-19` | Não há decisão sobre retenção de dados pessoais (leads, currículos, mail logs) | M-12 fica sem prazo/base legal |
| `LG-REIMPL-20` | `v2_membership_leads.metadata` e `gallery_media_id` UUID não têm correção definida no corpus | M-04/M-05 exigem decisão de schema |

## Evidências

- Tabelas e tipos: `_indices/tabelas.csv` (57 linhas; órfãs em `:12-13,16,19-20,37,39,44,58`).
- Migrations e rollback: `01_arquitetura/12-migracoes-inventario.md:109-121,263,390-407,463-469`.
- UUID e tags: `01_arquitetura/05-persistencia-uuid-migracoes.md:40,160-184,289,414`.
- Config: `_indices/config.csv:12,31,45,52-59,84,99,125-126,139`;
  `01_arquitetura/11-satelites-build-config.md:89,98`.
- Storage: `02_servicos-base/storage.md:43-44,286-287,332,468`;
  `03_servicos-ui/media/spec.md:38,55,290`.
- Certificados: `02_servicos-base/digital-signature/spec.md:25,70,148,203-216,240`;
  `PC-SVC-DIGITALSIGNATURE-04`.
- Seeds/páginas: `05_modulos/Layouts/BasicPage/spec.md:29,337,354,394-396,415`;
  `05_modulos/Support/SupportConfigs/dados.md:210,284,304,483,573-618`.
- Busca/feed: `03_servicos-ui/search/spec.md:23,72,100,332`;
  `02_servicos-base/feed-rss.md:25,120,291`.
- Associação: `05_modulos/Institucional/AssocieSe/spec.md:32,410`;
  `05_modulos/Institucional/AssocieSe/dados.md:20,30,78`.
