# Revisão do backlog — veredito consolidado (2026-10-23)

> **O que é:** um julgamento único de `wiki/backlog/` contra `AGENTS.md` (ADR-001..045) e o código
> real. Substitui a leitura item a item; **não cria escopo** nem substitui ADR/plano.
> **O que não é:** aprovação. Cada linha abaixo é uma decisão que só o humano toma.
> **Atualização (2026-10-23):** §7 reescrito com a evidência do dossiê `dossie_modules/lotep-v2/` —
> o que **de fato** dá para construir, em que ordem e com qual prova de desenho.
>
> **Plano executável:** [`wiki/implementation-phases/`](../implementation-phases/README.md) —
> fases **P0–P29** (plataforma → módulos → conformidade PNTP 2026; **P5.5** é o motor de dados
> abertos antes dos módulos), o catálogo
> [`MODULOS.md`](../implementation-phases/MODULOS.md) (módulo → fase) e a matriz
> [`PNTP.md`](../implementation-phases/PNTP.md).

Escopo: os 22 itens de topo + os dois corpora (`dossie_modules/`, `sucesu_analise/`). Os corpora são
**engenharia reversa do V5/V6**, não propostas: deles foram julgadas apenas as recomendações
explícitas. Legenda: `JÁ IMPLEMENTADO` · `PODE` · `PODE (condicionado)` · `NÃO VALE` · `NÃO PODE` ·
`DESCARTADO`.

## 1. Veredito item a item

| Item | Declara | Realidade verificada | Veredito | Base |
|---|---|---|---|---|
| `modulo-noticias.md` | Alto · Aberto | núcleo entregue: portal, CMS, API, export, sitemap, `NewsArticle`, 4 locales, `content` em AST/`jsonb`; **sem** categorias como tabela (coluna `text` com lista fixa no model), tags, destaque, galeria ordenada e preview | **JÁ IMPLEMENTADO** o núcleo; **PODE** a paridade editorial (§7 A2) | `Database/Migrations/2026_10_07_120000_create_noticias_table.php:50`; `Database/Models/Noticia.php:45-48` |
| `backup-recuperacao.md` | Promovido (F6.I2) | executado: dump antes do migrate, restore drill, PITR, poda, offsite | **JÁ IMPLEMENTADO** → mover para `concluido/` | `up_prod.sh`; `tools/db-backup.sh`, `db-restore-drill.sh`, `pitr-drill.sh`; `wiki/runbooks/deploy-e-recuperacao.md` |
| `servico-theme.md` | service (ADR-015) | tema já é **dado do layout**: tokens, presets, schema, `/theme.css` | **JÁ IMPLEMENTADO — não é service** | `src/layout/Engine/Theme{Resolver,Tokens,Schema}.php`; `src/layout/Http/ThemeStylesheetController.php`; `config/design.php` |
| `ui-ativacao-modulos.md` | tela no CMS pendente | comando + guard + invalidação existem; rotas CMS só têm login/painel/logout | **PODE** — §7 A1 (fecha a ADR-034) | `src/core/Internal/ModuleDiscovery/{ActivateModuleCommand,ModuleActivation}.php` |
| `servico-search.md` | FTS nativo (PG) | inexistente; o Seo já condiciona `SearchAction` a uma URL configurada; Notícias já é consumidor | **PODE** — desenho fechado em §7 A4 | `src/services/Seo/Actions/BuildSeoGraph.php:113-125`; `config/seo.php:26-28` |
| `servico-notifications.md` | mail/database | inexistente; nenhum consumidor hoje | **PODE (condicionado)** — só quando Ouvidoria/e-SIC pedirem | — |
| `servico-feedrss.md` | RSS/Atom | inexistente; Notícias já entrega sitemap e SEO | **PODE (condicionado)** — XMLWriter, sem dependência | — |
| `servico-landing-sections.md` | service | a **capacidade não existe**: Home é hero estático; `WidgetRegistry` sem nenhuma fonte; slots existem (ADR-016) | **PODE** — §7 B1: capacidade do layout + módulo (emenda à ADR-016), **não** service | `src/modules/Portal/Home/Layout/Views/index.blade.php`; `src/core/Internal/Widgets/`; ADR-016 |
| `servico-excel-importer.md` | provável descarte | órfão no `sucesu-cms`, mas **carga em lote é operação real** (fiscal, dados abertos, tabelas); ADR-042 proíbe ETL de legado, não importação | **PODE** — §7 B2: ferramenta de operação (CSV nativo), **não** ETL de conteúdo | `servico-excel-importer.md:36-38`; `src/modules/Portal/DadosAbertos/**` |
| `assinatura-digital-icp-brasil.md` | PAdES + TSA | depende de ato oficial, que hoje não existe (Legislação/DO não entregues) | **PODE** depois de Legislação; risco = lib permissiva | — |
| `govbr-sso.md` | OAuth2 gov.br | ADR-037 já o lista como backlog; login local é o break-glass | **PODE (externo)** — credenciamento e cliente OAuth | ADR-037 |
| `email-deliverability.md` | SPF/DKIM/DMARC | é **operação/DNS**, não código; dev tem Mailpit | **PODE (externo)** — não fecha por PR | `config/mail.php` |
| `cdn-borda-multicdn.md` | borda Multi-CDN | single-container; sem medição de origem | **NÃO VALE agora** — medir antes; contrato comercial | ADR-022 |
| `google-indexing-api.md` | API do Google | ADR-027 **descarta** a API e adota **IndexNow** — que **não está implementado** | **NÃO VALE como escrito**; **PODE** como IndexNow (§7 A5) | ADR-027 §9; `grep -ri indexnow src` = 0 |
| `cripto-auditoria-avancada.md` | YARA/WORM/crypto-shredding | removido do código; BLAKE3 permanece | **DESCARTADO** (manter o registro) | `cripto-auditoria-avancada.md:34-40`; ADR-029 |
| `modulo-legislacao.md` | 2º módulo | não implementado | **PODE** — exige ADR de versionamento/consolidação | — |
| `modulo-ouvidoria.md` | 3º | não implementado | **PODE** — LGPD + rate limit já existem | — |
| `modulo-esic.md` | 4º | não implementado; mesmo maquinário de protocolo da Ouvidoria | **PODE** — **depois** da Ouvidoria, reusando o protocolo | ADR-001 (duplicação só é aceitável quando o domínio difere) |
| `modulo-transparencia-fiscal.md` | 5º | não implementado; `DadosAbertos` (datasets + export) já existe | **PODE** — maior esforço; integração contábil externa fica fora | `src/modules/Portal/DadosAbertos/**` |
| `modulo-usuarios.md` | 6º, "ADR própria (RBAC)" | RBAC **já decidido** (ADR-033): `cms_users` + `core_roles.permissoes` | **PODE só como UI** — ADR própria seria duplicação | ADR-033; `modulo-usuarios.md:13` |
| `README.md` | índice | status divergem dos arquivos (ver §4) | **CORRIGIR** | — |
| `dossie_modules/` | dossiês V5 | contradição interna: "não migrar" × "resgate obrigatório" | **FONTE, não plano** — ADR-042 decide; filtrar §2 | `06b:74-94` × `README.md:100-101` |
| `sucesu_analise/` | análise V5 (read-only) | o próprio QA diz "não há pleno alinhamento" | **FONTE, não plano** — aplicar A/B antes de codar | `_qa/alignment-public-v7.md:13-17` |

### 1.1 Capacidades que o dossiê Lotep V2 revela (ainda sem arquivo de backlog)

| Capacidade | Realidade no V7 | Veredito | Base na V2 |
|---|---|---|---|
| **Licitações** (`Publicacoes/Licitacoes`) | não existe; o portal só tem Notícias/DadosAbertos/LGPD | **PODE** — domínio pequeno (5 tabelas), sem dependência legal nova | `dossie_modules/lotep-v2/publicacoes-licitacoes/09` |
| **Formulários dinâmicos** | não existe; nenhum consumidor hoje | **PODE (condicionado)** — só com demanda; módulo primeiro, **sem** service | `.../infraestrutura-formulariosdinamicos/09 §2` |
| **UI de papéis/permissões** | RBAC existe no Core (ADR-033), **sem tela**; só `core:user:create` | **PODE** — fecha a ADR-033 com a matriz que a V2 já exercitou | `.../infraestrutura-gestaopermissoes/09 §7` |
| **Importação operacional de planilha** | `servico-excel-importer.md` (já julgado) | **PODE** — a V2 prova o fluxo em Legislação/Licitações/Transparência | `.../publicacoes-legislacao/09 §1`; `.../publicacoes-licitacoes/09 §3` |

## 2. Conflitos de abordagem (e a resolução)

| # | Conflito | Evidência | Resolução |
|---|---|---|---|
| C1 | Índice × arquivos: `backup` já é Promovido, `cripto` é Descartado e **não aparece no índice**, `noticias` está Aberto mas entregue, `assinatura` aparece em **duas** tabelas | `README.md` (Infra + Services) vs cabeçalho de cada item | arquivo do item é a fonte; índice só reflete; Promovido/entregue sai do índice |
| C2 | **Theme**: AGENTS/ADR-015 listam como service de backlog, mas o layout já o implementa | `AGENTS.md` "Backlog: … Theme …"; `src/layout/Engine/ThemeResolver.php` | remover `Theme` da lista de services; manter em `layout` (ADR-016) |
| C3 | **LandingSections** × builder de widgets do plano 16: dois nomes para o mesmo motor | `servico-landing-sections.md:37`; `src/core/Internal/Widgets/` | **um motor só**, mas a capacidade é necessária: engine no layout + módulo que registra `SlotProvider`; sem service próprio |
| C4 | **Search**: service cross-module × busca local do módulo; `SearchAction` só evita 404 por convenção | `servico-search.md:33-35`; `config/seo.php:26-28` | começar local no módulo; service só com 2º consumidor; validar `search_path` contra rota existente |
| C5 | **Notifications** × **email-deliverability**: dois itens para um pipeline | `servico-notifications.md:13-19`, `email-deliverability.md:9-15` | mantê-los separados (código × operação), com a dependência explícita só para o canal `mail` |
| C6 | `modulo-usuarios` propõe "ADR própria (RBAC)" — RBAC já é ADR-033 | `modulo-usuarios.md:13`; ADR-033 | o módulo é **UI de gestão** sobre Core; MFA/2FA continuam backlog (ADR-037) |
| C7 | `google-indexing-api` descreve o que a ADR-027 já descartou, e **IndexNow (adotado) não existe no código** | `google-indexing-api.md:9-18`; ADR-027 §9 | item vira "IndexNow"; API do Google = descartada |
| C8 | `excel-importer` aberto × ADR-042 (sem ETL) × o próprio doc ("provável descarte") | `servico-excel-importer.md:1,36-38`; ADR-042 | **não é ETL**: é ferramenta de admin para carga operacional (CSV, idempotente, dry-run); conteúdo editorial continua entrando pelo CMS |
| C9 | **Dossiês**: "10 módulos v5 não migram" × "resgate obrigatório na reconstrução" | `06b:74-94` × `README.md:100-101`, `10-INVENTARIO:70-72` | ADR-042 decide: **não migra**. Corpus é registro, não ordem |
| C10 | **Dossiês**: Filament, Livewire, Spatie, trait `HasSlug`, soft delete global, HTML em coluna | `14:57`; `_protocolo/04:102`; `agenda/06:104`; `17c:102`; `a-instituicao/02:13` | **NÃO PODE** — conflita com ADR-001/002/009/028. Documento é fonte de comportamento, não de stack |
| C11 | **Sucesu**: ETL Modo A, Sentinel, CSP com nonce, `HtmlMinify`, `activity_log` do Spatie, tokens `v2.*` | `pilha-alvo-public-v7.md:163`; `ordem-de-construcao.md:110-111`; `paridade.md:114,124` | **NÃO PODE** — o próprio QA lista como A-01..A-05/B-01..B-11; ADR-042/033/022/035 vencem |
| C12 | **Sucesu** afirma "o V7 ainda não existe" | `_qa/review-v7-implementation.md:64-66` | afirmação **defasada**: `src/` tem 6 services e 6 módulos |
| C13 | Duplicidade de domínio nos dossiês: config-da-instituição × outras-configurações; drive × arquivo; publicações × diário oficial; transparência × relatório do e-SIC | `17c:90-92`; `18b:17`; `publicacoes/00:33-36`; `transparencia/00:15-17` | um dono por domínio; o relatório do e-SIC pertence ao **e-SIC**, não à Transparência |
| C14 | Nomes de estado/flag do corpus (`module.active`, `position` inerte) × ADR-034 (`modules_activation`) | `alignment-public-v7.md:33-36`; `flags-e-navegacao.md:37-48` | vocabulário do V7 vence: `modules_activation`, `{module}.{action}` |
| C15 | **Landing** como `src/services/Landing` (`lotep-v2/support-structurallandingeditor/09 §4`) × ADR-015/simplicidade | `09 §4`; ADR-015 | **não** criar service: catálogo/parser no `layout` + seções no módulo `Portal/Home`; service só com 2º consumidor |
| C16 | **Formulários** como service **e** módulo (`lotep-v2/infraestrutura-formulariosdinamicos/09 §2`) × "service só com demanda real" | `09 §2`; ADR-001/ADR-015 | módulo primeiro; o motor vira service apenas quando AutoTeste/pesquisas reais existirem |
| C17 | Permissões da V2: `fail-open`, bypass por e-mail fixo, `GET/HEAD` sempre liberados | `lotep-v2/infraestrutura-gestaopermissoes/09 §5`; ADR-033 | **UI** sim; **modelo** não. Deny-by-default, tokens do manifesto, sem bypass |
| C18 | Transparência: módulo irmão × estender `DadosAbertos` (`lotep-v2/dadosabertos-transparenciafiscal/09 §7`) | `09 §7`; `src/modules/Portal/DadosAbertos/**` | começar **estendendo** (categorias + competência + filtro); módulo irmão só se houver `/transparencia` e recorte editorial próprio |

## 3. O que já está implementado (e o backlog ainda pede)

| Capacidade | Evidência |
|---|---|
| Notícias (portal/CMS/API/export/sitemap/`NewsArticle`/4 locales/AST `jsonb`) | `src/modules/Publicacoes/Noticias/**` |
| Dados abertos (dataset, DCAT, CSV/JSON/XML, ETag) | `src/modules/Portal/DadosAbertos/**` |
| LGPD/DSAR + política de privacidade | `src/modules/Portal/Lgpd/**` |
| SEO (JSON-LD `@graph`, sitemap, robots, redirects 301, hreflang) | `src/services/Seo/**`; `seo:redirect` |
| Media/Gallery, RichText (AST), Security, Layout (tema/slots/a11y) | `src/services/*`, `src/layout/**` |
| Ativação de módulo por dado + guard 404 + cache | `ModuleActivation`, `CheckModuleActivation`, `core:module:activate` |
| Backup/restore/PITR + retenção + offsite | F6.I2 (ver §1) |
| Usuário CMS por comando (`core:user:create`, Argon2id, papel por slug) | `core:user:create` |

**Gap real:** IndexNow (ADR-027 §9) — decidido, não implementado.

## 4. Divergências concretas do índice

- `backup-recuperacao.md`: "Promovido em 2026-10-19" no arquivo; `README.md` ainda diz **Prioritário/Aberto**.
- `modulo-noticias.md`: Status **Aberto**; módulo entregue.
- `assinatura-digital-icp-brasil.md`: listado em **Infraestrutura** e **Services** (duas linhas).
- `cripto-auditoria-avancada.md`: Status **Descartado**; ausente do índice.
- `_template.md`: não é item; está na pasta (ok), mas o README não o distingue dos demais.
- Regra do próprio README — "Promovido → remover o arquivo" — não foi aplicada a nenhum dos dois casos.

## 5. Duplicidades e dono único

| Domínio | Arquivos que disputam | Dono proposto |
|---|---|---|
| Tema | `servico-theme.md` × `src/layout/Engine` × ADR-016 | **layout** (fechado) |
| Seções/landing + widgets | `servico-landing-sections.md` × plano 16 × `WidgetRegistry` | plano 16 + módulo (um motor, sem service) |
| Busca | `servico-search.md` × `sucesu_analise/03_servicos-ui/search` × `SearchAction` do Seo | módulo primeiro; service depois |
| Feed | `servico-feedrss.md` × `MOD-INFRAESTRUTURA-FEEDRSS` do corpus | um item (`servico-feedrss`) |
| Importação de planilha | `servico-excel-importer.md` × E4 do corpus | `servico-excel-importer` como ferramenta de operação (CSV) |
| Configurações da instituição | `configuracoes-da-instituicao/` × `outras-configuracoes/` | um módulo (corpus manda unificar) |
| Arquivo | `arquivo/` × `drive/` | arquivo (Drive é nome v6) |
| Notificações | `servico-notifications.md` × `MailService`/`v2_mail_logs` do corpus | service + Laravel::Notifications (nativo) |

## 6. Do corpus, só isto vira requisito (o resto é registro)

- **Não** reproduzir soft delete global; quando houver soft delete, o índice único precisa ser
  **parcial** (`WHERE deleted_at IS NULL`) — senão o bug do feed (G4-03) volta.
- **Não** aceitar HTML em coluna: AST em `jsonb` (ADR-028).
- Feed que consome feed externo: bloquear rede privada (SSRF — SEC-G4-01) e testar recreate/prune.
- Slug único **case-insensitive** por escopo (G4-02 invertia o slug de Associados).
- `Authorization`/permissões: vocabulário ADR-033, deny-by-default, sem bypass por e-mail fixo.
- Planilha: bloquear CSV injection (célula iniciada por `=`, `+`, `-`, `@`), ler em streaming, limite de
  linhas/bytes e `key_hash` idempotente com dry-run + relatório de falhas parciais.
- Seção de landing: schema por bloco (mesmo padrão do `ThemeSchema`); valor inválido é **ignorado**,
  nunca renderizado; sem HTML livre (ADR-028).
- Busca: `tsvector` **gerado** com pesos A/B/C + GIN; sanitizar `%`/`_`; a fonte indexa por evento,
  não por trigger no `save()` (evita duplicação com o índice).
- Notícias: super-destaque único garantido por índice parcial `WHERE super_destacada`; prev/next por
  chave `(publicado_seq, id)` (keyset), não `OFFSET`.
- Licitações: `show_value=false` vale em listagem, detalhe, JSON-LD e sitemap; arquivar não apaga
  anexos; número+título+objeto obrigatórios.
- Landing: `hide` preserva posição e configuração; header é configuração, não seção; **nenhum**
  `template`/HTML do banco é executado.
- Formulários: versão imutável após a 1ª submissão; `ip_hash` com pepper versionado; resultado por
  URL assinada (sem token permanente).
- Dataset fiscal: competência `YYYY-MM`; dinheiro como **string decimal** no `jsonb` (nunca `float`).
- Importação: chave natural (`número+ano`) com `upsert` idempotente e relatório de falhas parciais.

## 7. O que dá para fazer de fato (ordem executável)

Critério: **escopo fechado + desenho já provado em código + nenhuma dependência externa**. Cada item
abaixo tem tabelas, rotas e critérios de aceite nomeados nos dossiês; o que não tem, fica fora da fila.
Legenda de tamanho: **P** = 1 tela/comando · **M** = tabelas + rotas + testes · **G** = módulo completo.

### Onda A — desbloqueado (sem ADR nova)

| # | Item | Escopo que fecha | Prova no V2 | Tam. |
|---|---|---|---|---|
| A1 | **UI de ativação de módulos** | `/cms/modulos`: listar, ativar/desativar, auditoria. Reusa `core:module:activate` e o guard `module.activation`; nenhum estado novo. | — | P |
| A2 | **Notícias — paridade editorial** | `noticias_categorias` (auto-FK + `position`), `noticias_tags` + pivot, `noticias_galeria` (ordem), super-destaque único (índice parcial), preview por `temporarySignedRoute`, prev/next keyset por `(publicado_seq, id)`; a coluna `category` atual (lista fixa no model) vira tabela. | `publicacoes-noticias/09` P2–P6 | M |
| A3 | **Permissões — matriz de papéis** | `/cms/papeis`: CRUD de `core_roles` + matriz `{modulo}.{ação}` validada contra o manifesto; perfil `Suporte` reservado/protegido; **sem** `PermissionService`. | `infraestrutura-gestaopermissoes/09` §6–§7 | M |
| A4 | **Busca local (Notícias)** | `noticias.search_text` (texto extraído do AST pela Action, determinístico) + `tsv` **gerado** com `setweight` A/B/C sobre título/resumo/`search_text` (`to_tsvector('portuguese', …)`) + GIN; portal e CMS filtram por `tsquery` (sanitizando `%`/`_`). Sem tabela nova, sem sincronização, sem serviço. | índice `v2_public_search_index` (pesos A/B/C + GIN), adaptado ao escopo local; `publicacoes-noticias/09` A4 | M |
| A5 | **IndexNow** | comando + ping no evento de publicação; chave em `seo.settings`; substitui o item "Google Indexing API". | — | P |
| A6 | **Licitações** | 5 tabelas (licitação, anexos, órgãos, pivot, status), portal + API + CMS, anexos via Media, `show_value`, arquivamento reversível, JSON-LD `@graph`. | `publicacoes-licitacoes/09` §6 (contratos que não podem regredir) | G |

A4 começa **local no módulo** (C4): o índice compartilhado — e o service — só nascem quando
Legislação/Licitações forem a 2ª fonte.

A2–A6 não pedem ADR: usam ADR-014/017/026/027/028/033 e ADR-008. A2, A3 e A4 fecham buracos
**verificados no código atual** (categoria fixa, nenhuma tela de papéis, zero FTS) — é o maior
retorno por risco.

### Onda B — uma decisão curta antes de codar

| # | Item | Decisão (1 ADR/emenda) | Escopo depois da decisão |
|---|---|---|---|
| B1 | **Landing sections** | Emenda à ADR-016: catálogo no `layout`, seções da Home no módulo `Portal/Home` (`jsonb`), **não** em service. | parser `{type, params, hide}` + 9 widgets + editor + preview de sessão; nenhum template/HTML em banco; toda rota de escrita com Gate. |
| B2 | **ExcelImporter** | Confirmar "ferramenta de operação" (ADR-042 já exclui ETL) e o local: `Infraestrutura/Importador`, CMS-only. | CSV → preview → relatório → apply em lote; `key_hash` idempotente; bloqueio de CSV injection; limite de linhas/bytes. |
| B3 | **Formulários** | Decidir se há demanda (pesquisa/autoavaliação). Se sim: **módulo** + motor local; service só com 2º consumidor. | 4 tabelas, versão imutável, scoring por faixas, consentimento, resultado assinado. |

### Onda C — depende de terceiro ou ato oficial

**Legislação** (ADR de versionamento/consolidação), **Ouvidoria** (prazos + e-mail ao manifestante),
**e-SIC** (prazos legais da LAI), **Transparência fiscal** (fonte contábil externa), **ICP-Brasil**
(TSA/OCSP), **gov.br SSO** (credenciamento). Nenhum bloqueia a operação atual.

Fora Licitações (A6), a ordem dos módulos é **Ouvidoria → e-SIC → Legislação → Transparência → Usuários**. A V2
prova que protocolo/dicionários são reutilizáveis **por convenção** (sem trait/abstract); a fronteira
Ouvidoria × e-SIC continua separada porque as bases legais e os prazos diferem.

### Não fazer

`Theme` como service (é layout), `Landing`/`Formularios`/`Notifications` como service sem 2º
consumidor, CDN, API do Google (IndexNow), ETL do legado (ADR-042), cripto avançada (ADR-029).

## 8. Ações no backlog (sem código)

- [ ] Mover `backup-recuperacao.md` para `concluido/` e removê-lo do índice. **Notícias não sai**
      (o núcleo está pronto, mas a paridade editorial de §7 A2 continua aberta).
- [ ] `servico-theme.md`: registrar como implementado no layout e sair da tabela de services;
      corrigir a lista "Backlog" em `AGENTS.md`.
- [ ] `servico-landing-sections.md`: reescrever o escopo como **capacidade do layout + módulo** (motor
      único com o plano 16), com a emenda à ADR-016 de §7 B1; sair da tabela de *services* e não criar
      `src/services/Landing`.
- [ ] `servico-excel-importer.md`: reescrever como **ferramenta de operação** (CSV, idempotente,
      dry-run); registrar que **não** é ETL de legado (ADR-042).
- [ ] `google-indexing-api.md`: reescrever como "IndexNow (ADR-027)" e registrar a API do Google
      como descartada.
- [ ] `modulo-usuarios.md`: reescrever o escopo como **UI sobre ADR-033**, incluindo a matriz de
      papéis de §7 A3 (a V2 tem a UX de referência; o modelo é o da ADR-033).
- [ ] `modulo-noticias.md`: reescrever como **paridade editorial** (§7 A2) — o núcleo já existe.
- [ ] `servico-search.md`: fixar o desenho de §7 A4 — busca **local** (`search_text` derivado do AST
      + `tsv` gerado + GIN); extrair índice/serviço compartilhado só com o 2º consumidor.
- [ ] Abrir `modulo-licitacoes.md` com o escopo de §7 A6 e os contratos de
      `dossie_modules/lotep-v2/publicacoes-licitacoes/09 §6`.
- [ ] Abrir `modulo-formularios.md` **condicionado à demanda** (§7 B3), deixando explícito que o
      motor nasce no módulo e só vira service com 2º consumidor.
- [ ] `modulo-transparencia-fiscal.md`: registrar a decisão C18 (estender `DadosAbertos` primeiro).
- [ ] `README.md`: deduplicar `assinatura-digital`, incluir `cripto-auditoria` como Descartado,
      corrigir prioridades e hrefs.
- [ ] `dossie_modules/README.md` e `sucesu_analise/README.md`: banner de "registro read-only — não é
      plano; ADR-042 vence" (§2 C9–C12), sem editar o conteúdo dos dossiês.

## 8.1 O que a V2 confirma, corrige e não muda

O dossiê [`dossie_modules/lotep-v2/`](./dossie_modules/lotep-v2/README.md) revisa uma implementação
**anterior** dos mesmos domínios (Laravel 5.5, fora deste repositório): 31 módulos e 15 serviços, com
8 dossiês completos. Não é plano — entra aqui apenas onde **muda uma decisão**.

### Confirma (agora com desenho, não só intenção)

| Item | O que a V2 prova | O que o V7 faz diferente |
|---|---|---|
| **Busca** | índice desnormalizado + `tsvector` ponderado (título/resumo/corpo) + GIN + upsert + reindex | começa **local** (coluna derivada + GIN, sem sincronização); índice compartilhado só com 2º consumidor |
| **Excel/CSV** | preview → relatório → apply; streaming NDJSON; log `jsonb` com falhas parciais; chave `número+ano` | validação no servidor, unicidade no banco, bloqueio de fórmulas |
| **Landing** | `{type, params, hide}` + schemas por bloco + `prepareSections` em 1 `whereIn` | `jsonb` + schema; **sem** Blade/HTML no banco |
| **Formulários** | versão imutável, scoring por faixas, consentimento, `ip_hash` | resultado assinado, i18n, agregação em SQL |
| **Licitações** | 5 tabelas, anexos ordenados, órgãos N:N, `show_value` | mídia no service, RBAC ADR-033, JSON-LD |
| **Notícias** | categorias/tags/destaque/galeria/preview | tabelas com FK, índice parcial, URL assinada |
| **Permissões** | matriz de papéis com UX testada | tokens ADR-033, deny-by-default |
| **Ouvidoria** | protocolo `OUV-{Ymd}-{8}`, dicionários como dado, anonimato | prazos, e-mail, acompanhamento por protocolo, LGPD |

### Corrige (o que **não** se copia)

- Permissão **fail-open** fora do módulo, bypass por e-mail fixo e `GET/HEAD` sempre liberados.
- Endpoint de render do editor de landing **sem permissão** além de estar autenticado: qualquer
  perfil do CMS executa `bloco-sle` (Blade vindo do banco) — achado B-01 do dossiê.
- `tsvector` mantido por **trigger** em paralelo ao índice (duas verdades para o mesmo dado).
- Importador que confia no cliente (`is_imported` vem do request).
- `status` inteiro mágico, protocolo gerado no `boot()`, IP cru, consentimento descartado.
- Motor de formulários dentro do módulo e `result_token` não assinado.

### Não muda

- **Sem ETL** (ADR-042): os módulos entram vazios; conteúdo é digitado no CMS.
- A V2 é fonte de **comportamento**, não de código: nenhuma linha de PHP, trait, Sentinel,
  `PermissionService` ou HTML-em-banco entra.
- A ordem dos módulos de §7 continua válida; a V2 só antecipa **Licitações** por não depender de
  prazo legal nem de credencial externa.

## 9. Por que estes dois mudaram de veredito

A primeira leitura julgou o **empacotamento** (um service, um ETL) e não a **capacidade**. Corrigido:

- **Landing sections** — a Home é um hero estático (`src/modules/Portal/Home/Layout/Views/index.blade.php`:
  um `<h1>`, um lead e `quick-links`); o `WidgetRegistry` existe **sem nenhuma fonte** e a ADR-016
  define o ponto de extensão (`SlotProvider`) que ninguém usa. Sem seções, cada campanha/banner/destaque
  vira alteração de código na view — o oposto de "conteúdo desacoplado da UI" (ADR-016/017). A
  capacidade é necessária; o que não se justifica é um **service** para ela.
- **ExcelImporter** — a ADR-042 proíbe **ETL de conteúdo do legado**, não **carga operacional em
  lote**. Transparência fiscal e dados abertos dependem de carga inicial/periódica a partir de
  exportações de planilha (sistemas contábeis raramente expõem API); fazer isso à mão é o risco real.
  Continua valendo: conteúdo editorial entra pelo CMS, e o importador nunca roda no deploy.

Nenhum dos dois exige arquitetura nova: seções usam `jsonb` + schema por bloco (mesmo padrão do
`ThemeSchema`) + `SlotProvider`; o importador usa CSV nativo + fila + `key_hash`. Ambos são
**habilitadores** (destravam conteúdo e dados), ao contrário de CDN/gov.br, que dependem de terceiros.

## 10. BPMN 2.0.2 — revisão do corpus (2026-10-23)

Veredito: **PODE (condicionado)** como **documentação** de processos transversais; **NÃO PODE** como
runtime. O corpus (`bpmn/spec/`) não entra no repositório da aplicação, não vira dependência e não
autoriza um motor BPMN. A justificativa está no item
[`bpmn-documentacao-processos.md`](./bpmn-documentacao-processos.md): a especificação define notação,
metamodelo e intercâmbio, mas declara simulação/monitoramento/deploy fora de escopo; a cláusula 13
(token, gateways, ciclo de vida) exigiria um motor que duplicaria as máquinas de estado e Actions do
Laravel (ADR-001/009); as cláusulas 10.10/10.11 são apenas *hooks* de auditoria/monitoramento, já
superados por ADR-024/035. O único uso defensável é um piloto documental (P6, P11, P25), com `.bpmn`
+ `.svg` estático + ficha textual acessível, sem visualizador e sem execução.

### 10.1 Demanda contratual de BPMS (Fundão 008476/2025, itens 166–244)

O cliente pede um **BPMS** para Ouvidoria/e-SIC: modeler BPMN, versionamento, formulários, task
inbox, grupos, documentos/templates, DMN, scripts, APIs e portal do cidadão. Veredito:
**PODE (condicionado)**, mas **não como extensão de P11** e **não** como “BPMN 2.0 completo” sem um
motor BPMS. A opção recomendada é um **subconjunto próprio** (estados/transições versionados,
tarefas humanas, XOR/AND, prazos, formulários declarativos, filas e inbox) com export BPMN para
documentação; se o contrato exigir motor BPMS, ele é um **serviço/produto separado** (Camunda
7/Flowable), com ADR, segunda stack e integração por API. Scripts JS/Groovy/Python e API arbitrária
são **hard no** sem sandbox/allowlist. Detalhes e conflitos em
[`bpms-ouvidoria-esic.md`](./bpms-ouvidoria-esic.md). A capacidade genérica, isolada e fora da
sequência está em [`workflow-bpm-isolado.md`](./workflow-bpm-isolado.md).

