# Plano 13 — Módulo Piloto e Blueprint (Stubs)

> **Milestone:** M4 · **Depende de:** 12 · **Habilita:** 14, 15
> **Objetivo:** provar a arquitetura de ponta a ponta num vertical real e congelá-la
> em stubs + blueprint, para que os demais módulos sejam mecânicos.

---

## 1. Por que Notícias como piloto

É o módulo mais transversal do domínio municipal (aparece na home, no SEO, na busca,
na acessibilidade, na API e no CMS), tem mídia (imagens), listagem/detalhe e RSS.
Validado em `sucesu-cms/V2/Modules/Publicacoes/Noticias`. Prova todos os eixos:
domínio, persistência, slots, tema, SEO, e2e e cache.

## 2. Estrutura do módulo (contrato físico)

```
src/modules/Publicacoes/Noticias/
├── ModuleProvider.php           # ÚNICO arquivo de declaração (register + config) — ADR-014
├── Database/
│   ├── Migrations/              # ADR-017: transação+lock, down()->backup_*, corpo jsonb
│   ├── Models/Noticia.php
│   └── (sem Seeders — demo vive em src/demonstration/Noticias/ — ADR-041)
├── Logic/
│   ├── Actions/                 # uma Action por arquivo, DI + span {modulo}.{acao} (ADR-024)
│   ├── DTOs/                    # NoticiaData, NoticiaFiltro (readonly simples, sem herança)
│   └── Controllers/             # Noticia*Controller (invocável; sem closure — ADR-008)
├── Routes/                      # `{area}.php` — carregadas por convenção pelo Core (ADR-014)
│   ├── portal.php
│   ├── cms.php
│   └── api.php
├── Layout/
│   └── Views/                   # namespace = snake(modulo); portal, cms/, partials, embed
│       ├── index.blade.php
│       ├── show.blade.php
│       ├── cms/…
│       └── partials/…
├── Lang/                        # ADR-012: tradução do módulo, junto às views (namespace = token)
│   ├── pt_BR/noticia.php
│   ├── en/noticia.php
│   ├── es/noticia.php
│   └── fr/noticia.php
├── CoreEvent/                   # (opcional) listeners de eventos de outros domínios
└── Test/                        # NoticiaPublicarActionTest, NoticiaFeatureTest, ...
```

> **Convenção de carregamento (Core, ADR-014/ADR-012):** migrations em `Database/Migrations`,
> views em `Layout/Views` (namespace `snake(modulo)`), rotas em `Routes/{portal,cms,api}.php` e
> traduções em `Lang/{locale}/*.php` (namespace = token canônico, `__('noticia::…')`)
> — o módulo **não** tem `ServiceProvider` próprio. `Logic/Routes/` **não** é usado.

**Token canônico (ADR-004):** `noticia` — toda classe, função, view, rota, migration,
tabela, teste, slot e log do módulo carrega esse prefixo. `grep -riE "noticia"` retorna a
árvore completa; o gate `tools/name-check` falha se algum arquivo do módulo escapar. A pasta de
**grupo** (`Publicacoes/`) é organizacional e **não** entra no token (ADR-014).

## 3. Casos de uso do piloto

- Listar (com filtro por categoria/tag/ano, paginação acessível, URL canônica).
- Ver detalhe (galeria, anexos, dados estruturados, relacionados).
- Criar/editar/publicar/despublicar no CMS (com preview e agendamento).
- Fornecer dados a slots da home e aside.
- Emitir evento `NoticiaPublicada` (SEO/indexação/busca via Core).
- Expor API/Feed (RSS/JSON) somente leitura.
- Export PDF/impressão acessível (versão de impressão).

## 4. Blueprint e stubs

- `src/modules/Exemplos/Blueprint/` é o módulo-exemplo canônico (plano 03); evolui para
  o padrão final após o piloto.
- `make:module Grupo/Modulo` gera `modules/{Grupo}/{Modulo}/ModuleProvider.php` + estrutura +
  testes de contrato.
- `make:service Nome` idem para services.
- Stubs versionados em `src/core/Stub/` e testados (geração → lint/análise/testes verdes).
- `MODULE.md` gerado por módulo: propósito, estrutura, dependências, rotas, eventos,
  slots, comandos e convenções.

## 5. Atividades

- [ ] Implementar o módulo `Noticias` completo (5 seções acima).
- [ ] Ações/DTOs com idiomas do PHP 8.4 (`readonly`, `enum`, `#[\Override]`) e
      dependências injetadas (sem `new`/`resolve` no corpo).
- [ ] Migration do `noticia` no template do ADR-017 (`corpo`/`metadados` em `jsonb`,
      `down()` → `backup_*`, zero HTML/CSS/estilo e zero flag de UI no schema).
- [ ] Registrar slots `home.destaques`, `home.ultimas`, `aside.relacionados`.
- [ ] Emitir `NoticiaPublicada`; consumir em `src/services/Seo` e `src/services/Search` via porta.
- [ ] Mídia de capa/galeria via `src/services/Media` (AVIF/WebP + `alt_text` obrigatório).
- [ ] Rotas de portal/CMS/API com nomes grep-friendly (`portal.noticia.show`, `cms.noticia.index`).
- [ ] Página de detalhe com JSON-LD e canonical.
- [ ] Feed RSS + endpoint JSON.
- [ ] Testes: unit (Actions), feature (rotas/DB), contrato (portas/slots), e2e (história).
- [ ] `make check term=noticia` retorna todas as camadas do módulo.
- [ ] `tools/migration-check` verde: `corpo` é `jsonb`, sem coluna `*_html`/flag de UI.
- [ ] Dados de referência do módulo (categorias de sistema etc.) idempotentes na migration;
      demo seeder separado, nunca pré-requisito e sem HTML/CSS/layout.
- [x] Gerar `MODULE.md` e atualizar o Blueprint com o aprendizado.

## 6. Testes e evidências

- [ ] `make create:module MODULE=Demo` gera módulo que passa em `make check` e em `tools/name-check`.
- [ ] E2E do piloto verde com a11y estrita.
- [ ] Teste: publicar notícia dispara indexação sem o módulo conhecer SEO/Search.
- [ ] Teste: notícia aparece na home via slot configurado no CMS.
- [ ] Cobertura do módulo ≥75% com Actions 100% cobertas.

## 7. Definition of Done

- [ ] Um vertical completo, acessível e observável em produção.
- [ ] Stubs provados: criar o 2º módulo é mecânico.
- [ ] `MODULE.md` como contrato de leitura para IA/humanos.

## 8. Riscos

| Risco | Mitigação |
|---|---|
| Piloto "inventar" padrões | Blueprint + revisão de fronteira + gate |
| Stubs ficarem defasados | Teste de geração no CI (stub → build verde) |
| Mídia/PDF travar o piloto | Fatiar: texto primeiro, mídia em seguida |
