# ADR-042 — Sem retrocompatibilidade: base nova e conteúdo do legado migrado à mão

| Campo | Valor |
|---|---|
| **Status** | Aceito (2026-10-19) |
| **Data** | 2026-10-19 |
| **Plano de origem** | decisão do dono (revisão de F6, 2026-10-19) |
| **Relacionadas** | ADR-001, ADR-003, ADR-005, ADR-007, ADR-017, ADR-018, ADR-027, ADR-035, ADR-037, ADR-041 |

## Contexto

O plano 15 (e a fase F6 do `wiki/implementation/`) nasceu com a premissa de **migrar
`prefeituras_v5`**: dump do PG 10.23 para o 18, schema de quarentena `sys_migration`, adaptadores por
módulo (Notícias, Diário Oficial, Licitações/Contratos, Obras, Ouvidoria), tabela `legacy_mapping`
gerando `301`, `migrate:legacy --dry-run/--only=` e **transição de hash** de senha ("shadow auth" até
trocar para Argon2id).

Na revisão de 2026-10-19 o dono fixou a premissa oposta:

- O V7 é um **projeto novo, do zero**. Não há convivência com o v5, não há tráfego duplo, não há
  janela de corte com rollback de dados.
- **Não há retrocompatibilidade** — nem de código (model/tabela/rota/`User` do v5), nem de dado.
- O **conteúdo será migrado manualmente, caso a caso**, pela equipe editorial, pelo próprio CMS.

Com essa premissa, manter ETL é custo sem contrapartida: o volume é pequeno, a curadoria é humana de
qualquer forma (texto, mídia e imagem de capa precisam de revisão caso a caso) e um importador
automático arrastaria o schema sujo do v5 para dentro do domínio novo — exatamente o que a ADR-003 e
a ADR-017 proíbem.

## Decisão

1. **Nenhuma camada de compatibilidade.** Nada de `sys_migration`, `legacy_mapping`,
   `config/migration.php`, `migrate:legacy`, adaptadores por origem, shadow auth ou "modo legado" em
   model/rota. O domínio conhece **só** o schema novo.
2. **Banco novo.** A base nasce de `migrate` (+ dado de referência vindo de migration idempotente,
   ADR-017/ADR-041). Nada é restaurado do PG 10 do host; a migração PostgreSQL 10.23 → 18 **deixa de
   ser uma etapa do projeto** (emenda a ADR-007 §"Custos").
3. **Conteúdo = entrada manual pelo CMS** (TipTap/`jsonb`, Media, `DadosAbertos`), com revisão
   editorial. Sem importador, sem planilha como fonte de verdade, sem `dry-run` de lote.
4. **Usuários = recriados no CMS** (`cms_users`, Argon2id, um perfil por usuário — ADR-033/ADR-037).
   Sem transição de hash e sem `User` legado.
5. **301 é curadoria, não motor.** As URLs que importam são poucas e conhecidas: entram **à mão** em
   `seo.redirects` (ADR-027), que ganha uma **superfície mínima de operação** (comando `artisan` de
   console; UI de CMS fica no backlog). A rota viva **nunca** é sombreada e o `http.not_found` (ADR-024)
   é a fonte para descobrir o que ainda está quente.
6. **O que sobra de "migração" é operação de banco do V7**: backup antes de `migrate`
   (`pg_dump -Fc`), restore ensaiado em base limpa, PITR e retenção — F6.I2 reescrita com esse escopo.
7. **DoD de paridade muda de natureza**: deixa de ser "contagem de linhas migradas" e passa a ser
   **checklist de páginas críticas** (home, notícias, diário, licitações, obras, ouvidoria, dados
   abertos, privacidade) com 200 + metadata + a11y verdes.

## Justificativa (alternativas descartadas)

- **ETL com `dry-run` e reconciliação por contagem** — descartada: o conteúdo precisa de curadoria
  humana de qualquer forma (texto em HTML, mídia em disco, capa, autoria), então o "automático" só
  desloca o trabalho e adiciona um schema intermediário para manter.
- **Dual-run / shadow auth** — descartada: não há janela de convivência; o v5 sai do ar por decisão,
  não por corte gradual.
- **Importador one-off fora do repositório** (script descartável) — permitido como ferramenta de
  operação, mas **fora** de `src/` e fora do código de produção: nada no build depende dele.
- **Manter `legacy_mapping` para 301 em massa** — descartada: `seo.redirects` já resolve (ADR-027) e a
  curadoria manual é pequena.
- **Migrar o PG 10 do host junto** (dump/restore "só por segurança") — descartada: banco novo, sem
  histórico a preservar, e o PG 10 nunca esteve sob nosso domínio (ADR-007).

## Consequências

**Positivas**
- F6 encolhe para o que tem valor real: **deploy atômico/reversível**, **borda no WHM** e
  **backup/restore/PITR do V7**.
- Zero schema de quarentena, zero modelo legado, zero risco de "dado sujo" entrar no domínio novo
  (ADR-017).
- Superfície menor para auditar (ADR-035): o conteúdo entra pelo CMS, com trilha e ator.

**Custos / negativas**
- Trabalho editorial manual é **maior** (não há importação em massa) — custo aceito e explícito.
- Link antigo que ninguém mapeou vai para 404: mitigação é `http.not_found` + `seo.redirects` manual.
- Sem histórico do v5: relatórios/registros antigos não ficam consultáveis no V7 (decisão do dono).

## Exemplo mínimo (comparativo)

```php
// ❌ Padrão descartado (plan 15 original): ETL + quarentena + mapeamento
//    App\Console\Commands\MigrateLegacy { --dry-run --only=noticias }
//    Schema::create('sys_migration.noticias_legado', ...);
//    DB::table('legacy_mapping')->insert(['from_path' => ..., 'to_path' => ...]);

// ✅ Padrão aceito: o conteúdo entra pelo CMS; o 301 é um registro curado (ADR-027)
SeoRedirect::create(['from_path' => '/noticias/antiga-url', 'to_path' => '/noticias/nova-url', 'status' => 301]);
```

## Verificação

- Não existe `sys_migration`, `legacy_mapping`, `config/migration.php` nem comando `migrate:legacy`
  na árvore (`grep -rn "sys_migration\|legacy_mapping\|migrate:legacy" src/ config/` vazio).
- `seo.redirects` é a **única** fonte de redirect e continua coberta por `SeoRedirectTest`.
- `wiki/implementation/06-deploy-migracao.md` e `wiki/plan/15-cicd-deploy-legado.md` não prometem
  etapas de ETL; `wiki/specs/17-up-prod.md` (deploy) não cita migração de legado.
- F6.I2 tem backup/restore/PITR do PG 18 como escopo, não dump do PG 10.
