# Plano 03 — Esqueleto: Laravel típico na raiz + domínio isolado em `/src`

> **Milestone:** M1 · **Depende de:** 02 · **Habilita:** 04–15
> **Objetivo:** materializar a topologia do ADR-003 — raiz é Laravel 12 enxuto,
> `/src` contém **somente** `core`, `services`, `layout`, `modules` e `tests-e2e`,
> e a fronteira entre módulos é **física**, não apenas combinada.

---

## 1. Estrutura-alvo

```text
public-v7/                       # Laravel 12 típico (campo do framework)
├── app/                         # APENAS bootstrap (Providers/AppServiceProvider)
├── bootstrap/                   # app.php + cache
├── config/                      # config nativa do Laravel
├── database/                    # apenas o exigido pelo framework (o domínio traz o seu)
├── public/                      # DocumentRoot (index.php, .htaccess, assets públicos)
├── resources/                   # bootstrap de assets; views base do framework (quase vazio)
├── lang/                        # traduções nativas (pt_BR, en, es, fr) — ADR-012
├── routes/                      # web.php/api.php finos, delegando às áreas
├── storage/                     # logs/cache/sessões/uploads
├── vendor/                      # dependências (imutável, nunca editar)
├── artisan  composer.json  package.json  vite.config.*  pint.json
├── Makefile  docker/  docker-compose.yml
├── src/                         # SÓ DOMÍNIO
│   ├── core/                    # auditoria, bus, discovery, erros, observabilidade
│   ├── services/                # serviços agnósticos/headless sempre disponíveis
│   ├── layout/                  # estrutura de front-end, slots, presets, tema
│   ├── modules/                 # casos de uso autocontidos: modules/{Grupo}/{Modulo}/
│   └── tests-e2e/               # Playwright isolado (histórias + sniff/axe)
└── wiki/                        # TODA a documentação (plan, adr, specs, ARQUITETURA)
```

> **Regra física:** dentro de `/src` só existem `core`, `services`, `layout`,
> `modules` e `tests-e2e`. Nada mais. Testes PHPUnit são **co-localizados** em cada
> camada (ex.: `src/modules/Publicacoes/Noticias/Test/`), como no `cms/`.

## 2. Decisões de esqueleto

- **Autoload PSR-4 por camada** no `composer.json`:

  ```json
  "autoload": {
    "psr-4": {
      "Core\\":     "src/core/",
      "Services\\": "src/services/",
      "Layout\\":   "src/layout/",
      "Modules\\":  "src/modules/"
    }
  }
  ```

- **`app/` enxuto**: só `AppServiceProvider` (e, se preciso, `Providers/*` de bootstrap).
  Nenhuma regra de negócio em `app/`.
- **Limpeza do scaffold** (remover o que não se usa): `app/Models/User.php`,
  `app/Http/Controllers/*` default, `resources/views/welcome.blade.php`,
  `database/migrations` default, `tests/` default, `app/Http/Kernel.php` (Laravel 12 usa
  `bootstrap/app.php`), assets de exemplo.
- **Identidade/User** passam a viver no core (`src/core/Identity/...`) e o
  `config/auth.php` aponta para esse model.
- **Rotas**: `routes/web.php` e `routes/api.php` são *thin* — apenas carregam os
  arquivos de rota das áreas/módulos via os providers.
- **Views**: o framework lê views de `src/layout` (registradas por `LayoutServiceProvider`);
  `resources/views` fica quase vazio (só o necessário).
- **Migrations**: cada camada registra as suas via `loadMigrationsFrom()`
  (`src/*/*/Database/Migrations`). `database/` na raiz não guarda domínio.
- **Fronteira testável**: nenhum `use Modules\Outro` fora de testes; o gate do plano 05
  varre a AST e falha o build.
- **Sem reinvenção**: FormRequest, Validation, Eloquent, Events, Jobs, Cache, Gate,
  Blade Components, Flysystem — nativo primeiro (ADR-001).
- **i18n (ADR-012)**: `lang/{locale}/*.php` nativo + `__()`; módulos/services expõem
  `Lang/{locale}/*.php` com namespace = token; um middleware de locale no Core.
- **PHP 8.4 idiomático** (skill `php-84-correct`): `readonly` classes/props, `enum`,
  property hooks e visibilidade assimétrica quando fizer sentido, tipos DNF,
  `#[\Override]`, first-class callables, `array_all/any/find`, `Random\Randomizer`;
  proibido o que saiu da linguagem (`create_function`, `each`, `mcrypt_*`,
  `FILTER_SANITIZE_STRING`, `rand/mt_rand` para segredos).

## 3. Atividades

- [x] `composer create-project laravel/laravel:^12` na raiz `public-v7/`.
- [x] Limpar o scaffold default (lista da seção 2) e confirmar que o app sobe.
- [x] Configurar o autoload PSR-4 das 4 camadas + `src/*/Test/` fora do classmap de produção.
- [x] `composer dump-autoload` e `php artisan about` funcionando.
- [x] Ajustar `bootstrap/app.php` (Laravel 12: sem `Kernel.php`): `withRouting(health: '/up')`,
      `trustProxies` (faixas privadas via `config('app.trusted_proxies')`), `trustHosts`,
      `throttleWithRedis` (ADR-021), `URL::forceScheme('https')` por config (spec 16).
- [x] Configurar `config/app.php` com `trusted_proxies`/`trusted_hosts` (env, sem `*`).
- [ ] Registrador de exceções → RFC 7807 + listener `DiagnosingHealth` (PG + Valkey) no `/up`.
- [x] Configurar `config/auth.php` para o model de identidade do core.
- [x] Criar `src/core/`, `src/services/`, `src/layout/`, `src/modules/Exemplos/Blueprint/`.
- [x] `Blueprint` completo: `ModuleProvider.php`, rota, controller, action, model, migration,
      view, teste — o exemplo canônico de todas as camadas.
- [x] Aplicar o ADR-004 ao `Blueprint`: token canônico `blueprint`, com classe/função/
      view/migration/teste/rota prefixados (`BlueprintController`, `blueprint-edit.blade.php`).
- [x] Aplicar o ADR-017 à migration do `Blueprint`: transação+lock, `down()` para `backup_*`,
      `jsonb` para conteúdo, zero HTML/CSS/estilo e zero flag de UI no schema.
- [ ] Cada camada registra rotas/views/migrations no seu provider (via API nativa do Laravel);
      módulos são carregados **por convenção** pelo Core (ADR-014), sem `ServiceProvider` próprio.
- [ ] `phpunit.xml` com suites apontando para `src/*/Test/` (e.e.: `Unit`, `Feature`, `core`, `services`, `layout`, `modules`).
- [ ] Habilitar **fila nativa** (driver `redis`=Valkey); jobs `ShouldQueue` só quando necessário; sem Horizon/Supervisor (ADR-005).
- [x] `pint.json` + `.editorconfig`; `vite.config` com Tailwind 4.
- [ ] Aplicar os idiomas do PHP 8.4 (readonly/enum/`#[\Override]`) no esqueleto e travar
      o que foi removido da linguagem.
- [x] `.env` único e mínimo (identidade + segredos); perfis de ambiente por `APP_ENV`
      (ADR-032) e defaults documentados em `config/_OTHER_CONFIGS.md`.
- [ ] `git ls-files src | awk -F/ '{print $2}' | sort -u` retorna **exatamente**
      `core services layout modules tests-e2e`.

## 4. Testes e evidências

- [ ] `composer install` + `php artisan about` funcionam no container.
- [ ] Teste de fumaça: rota do `Blueprint` responde 200 e passa em lint/análise.
- [ ] `make check` roda e **falha de propósito** se `Blueprint` importar
      `Modules\Noticias` (teste do próprio gate).
- [ ] `make check term=Blueprint` retorna arquivos em todas as camadas do `Blueprint`.
- [ ] `tools/migration-check` passa na migration do `Blueprint` e falha num fixture com
      `dropColumn` no `down()` e coluna `*_html`.
- [ ] Verificação da topologia: nenhum diretório extra em `src/`.
- [ ] `git ls-files | grep -c "app/Http/Model"` = 0 (anti-padrão do legado ausente).

## 5. Definition of Done

- [ ] App Laravel 12 sobe e responde health-check.
- [ ] Raiz é Laravel típico, sem boilerplate desnecessário.
- [ ] As 4 camadas existem, com autoload nativo verificado.
- [ ] `/src` contém apenas os 5 elementos permitidos.
- [ ] `Blueprint` é um exemplo funcional e testado.
- [ ] Fronteiras verificáveis por comando único.

## 6. Riscos

| Risco | Mitigação |
|---|---|
| Laravel "puxar" código de volta para `app/` | Gate + revisão: `app/` só bootstrap |
| Remover arquivo default que o framework usa | Remover um a um com o app subindo; teste de fumaça |
| Stubs divergirem do esqueleto | Blueprint é a fonte; stubs derivam dele |
| Regras de fronteira serem ignoradas | Gate no CI desde o primeiro commit |
