# Plano 07 — Core: Contratos, Discovery e Eventos

> **Milestone:** M2 · **Depende de:** 05, 06 · **Habilita:** 08–15
> **Objetivo:** entregar o "ponto central invisível" que orquestra o sistema e
> garante que módulos nunca se conheçam.

---

## 1. Responsabilidades do Core

1. **Descoberta de módulos** (manifesto em cache, zero DB no boot).
2. **Registro de navegação/menus** por auto-declaração do módulo.
3. **Eventos nativos + portas:** comunicação entre módulos via Laravel Events e interfaces do Core.
4. **Permissões** (vocabulário fixo por módulo, ADR-033) e **ativação de módulos** (feature flags, ADR-034) com cache quente.
5. **Erros e saída** (exceções nativas + RFC 7807) — implementados no plano 06.
6. **Saúde/versionamento**, área registry (`portal`, `cms`, `api`, `webhook`).

## 2. Descoberta de módulos (autodescoberta + agrupamento — ADR-014)

- Estrutura em **dois níveis**: `src/modules/{Grupo}/{Modulo}/` (o **grupo vem da pasta**).
- **Um único arquivo na raiz do módulo:** `ModuleProvider.php`, implementando
  `Core\Contracts\ModuleProvider`:
  - `register(): void` — bindings do módulo (portas/singletons), opcional;
  - `config(): array` — título, descrição, ícone, `position`, rota e submódulos.
- `Core\Internal\ModuleDiscovery\ModuleDiscoveryService` varre `src/modules/*/*`, instancia o
  provider, chama `register()`/`config()` e **injeta `group = basename(pasta)`**; carrega migrations/views/rotas
  por convenção — o módulo **não** tem `ServiceProvider` próprio.
- Gera `bootstrap/cache/modules_manifest.php` (título, grupo, ícone, rota, submódulos, status).
- Comando `core:cache-modules` (rebuild no deploy).
- Ativação/desativação é dado (`modules_activation`, ADR-034); a consulta é ao manifesto em memória,
  **nunca** ao banco por request.
- O CMS (plano 12) consome o manifesto: sidebar **agrupada** pelo grupo, ordenada por `position`,
  filtrada por permissões/flags.

## 3. Comunicação entre módulos (nativo + portas)

Um módulo **não** importa outro. Dois mecanismos, ambos **nativos**:

- **Eventos de domínio → Laravel Events/Listeners** (sem bus próprio): `NoticiaPublicada` é um
  `Event` nativo; listeners (`SeoIndexer`, `SearchIndexer`) reagem; entrega assíncrona via **fila
  nativa** (`ShouldQueue`) quando necessário.
- **Portas síncronas → interfaces do Core:** quando A precisa acionar B, A depende de uma
  **interface do Core** (`Core\Contracts\Ports\...`); o Core resolve a implementação registrada
  por B. A nunca vê a classe de B.

Regras:
- Payload em array/`readonly` simples — **sem genéricos nem hierarquias**.
- Idempotência via fila nativa; log de entrega em `core_messages` (opcional) — **sem reinventar
  o event bus**.
- Teste de contrato por porta (fakes no Core).

## 4. Erros de domínio (simples)

- Erros previsíveis → **exceções nativas** (ou exceção de domínio concreta, herdando de
  `RuntimeException`) — **sem `Result<T>`/genéricos**. Sucesso retorna valor/array simples.
- `ProblemDetails` (RFC 7807) para erros HTTP — plano 06.

## 5. Atividades

- [ ] `Core\Contracts\ModuleProvider` (interface) + `Core\Discovery\ModuleDiscovery`.
- [ ] Descoberta `src/modules/*/*` com injeção de `group` pela pasta + manifesto cacheado.
- [ ] `core:cache-modules` + carregamento por convenção (migrations/views/rotas).
- [ ] `CoreServiceProvider` registrando descoberta, eventos, portas, permissões e observabilidade.
- [ ] Eventos de domínio como **Laravel Events/Listeners** nativos (+ `ShouldQueue`); log de
      entrega em `core_messages` só se necessário.
- [ ] **`Core\Contracts\Service`** + `ServiceDiscoveryService`/`ServiceProvider`: cada service tem
      `src/services/{Nome}/ServiceProvider.php` com `contracts()`+`config()`, absorvido por convenção
      (ADR-015); catálogo acionável (`catalog()`).
- [ ] `Ports`: registro de implementações por módulo (`Core::port(Interface, Impl)`).
- [ ] `Permissions` (ADR-033): vocabulário fixo `{modulo}.{ver|editar|aprovar|arquivar}`; `core_roles`
      + `core_role_permissions` (um perfil por usuário); cache quente + `Gate` base — sem
      `PermissionService`/sentinel.
- [ ] **Ativação** de módulos (ADR-034): guard `CheckModuleActivation` (Valkey, TTL curto, **404**) +
      toggle do suporte com **invalidação imediata** — **não** é engine de flags (sem segmentação/rollout).
- [ ] `Areas`: registry das áreas `portal|cms|api` (enum `PlatformArea`) e prefixos de rota.
- [ ] Stubs `make:module` e `make:service` já gerando provider conformante e teste de contrato.

## 6. Testes e evidências

- [ ] Módulo A dispara um Event nativo; Listener registrado (fake) recebe — sem `use` cruzado.
- [ ] Teste de contrato de cada porta registrada.
- [ ] `core:cache-modules` gera manifesto e um boot não consulta o banco de módulos
      (assert de queries = 0 no boot).
- [ ] Sidebar do CMS exibe os módulos **agrupados** pela pasta e ordenados por `position`.
- [ ] Import cruzado entre módulos → `make check` falha; módulo→service só via
      `Contracts`/`DTOs`/`Enums` (fixtures `service-impl-invalid`).
- [ ] `ServiceDiscoveryService::catalog()` lista os services; `bootstrap/providers.php` não os registra à mão.
- [ ] Permissão cacheada: 2ª checagem não vai ao banco (assert de query count).

## 7. Definition of Done

- [ ] Um módulo novo é plugado só criando a pasta + provider (sem tocar no Core).
- [ ] Um service novo é plugado só criando a pasta + `ServiceProvider.php` (sem tocar no Core).
- [ ] Comunicação inter-módulo comprovadamente mediada.
- [ ] Permissões (ADR-033) e ativação (ADR-034) com cache quente e O(1).

## 8. Riscos

| Risco | Mitigação |
|---|---|
| Eventos virarem "sopa" difusa | Catálogo de eventos no `wiki/specs/01-arquitetura.md`; eventos explícitos |
| Manifesto stale | Rebuild no deploy + comando de verificação no CI |
| Porta sem implementação | Falha explícita e testada no container no boot |
