# P0.S1 — configuração tipada: `core_settings`, `SettingsSchema` e contrato

| Campo | Valor |
|---|---|
| **Fase** | P0 — Fundação do painel: configurações tipadas e primitivas |
| **Issue** | P0.S1 — schema + migração + contrato (ADR-046) |
| **`kd` task** | `task_004op123` (épico `epic_00j5mhqf`) |
| **Âncora** | `wiki/implementation-phases/P0-fundacao-painel.md` · `wiki/adr/ADR-046-configuracoes-tipadas-por-escopo.md` |
| **Status da revisão** | ✅ revisado |

## O que foi implementado

- Migração `core.core_settings`: um documento JSON por seção (`section` única), `payload jsonb`
  objeto, `schema_version`, `encrypted_payload` para segredos, `updated_by` FK `cms_users`
  (`nullOnDelete`) e timestamps `NOT NULL`. `CHECK` de formato da seção, objeto do payload e
  versão; `down()` renomeia para `backup_core_settings_<ts>`.
- `Core\Settings\SettingsSchema`: seções iniciais `institution`, `theme`, `cms`, `seo`, `system`,
  `support`; campos com tipo, default, required, max, enum, cifra, label/help e fallback de
  `config/`. `normalize()` percorre o schema em ordem determinística e descarta chave/valor
  inválido; `defaults`, `requiredKeys`, `encryptedKeys` e `fallbacks` são expostos.
- `Core\Contracts\Settings`: porta `get`, `section`, `put`, `flush`.
- Migração registrada em `CoreServiceProvider`; `migrate` aplicado no runtime e coberto por teste.
- Fora desta fatia: cache, auditoria, segredos, implementação de leitura/escrita e comando (P0.S2);
  UI, FormRequest e permissões (P0.S3).

## Arquivos para revisar

- `src/core/Internal/Settings/Database/Migrations/2026_10_23_000004_create_core_settings_table.php`
- `src/core/Settings/SettingsSchema.php`
- `src/core/Contracts/Settings.php`
- `src/core/CoreServiceProvider.php`
- `src/core/Settings/Test/SettingsSchemaTest.php`
- `src/core/Internal/Settings/Test/SettingsTableTest.php`

## Pontos de revisão

### PHP 8.4 / D1
- [ ] `declare(strict_types=1)`; tipos nativos; sem trait/abstract/generic/`Result`.
- [ ] Schema declarativo e determinístico; nenhum `new`/`resolve`/`app()` no domínio.
- [ ] PHPStan `max` 0; sem código morto; `match` fechado para tipos.

### Laravel 12 / D2
- [ ] Migração idempotente (`Schema::hasTable`), `down()` não-destrutivo, `text`/`jsonb`/`timestamptz`.
- [ ] Nenhum `env()` fora de `config/`; sem closure de rota.
- [ ] `CoreServiceProvider` carrega a migração por convenção.

### Dados / D10
- [ ] `section` UNIQUE e `CHECK` de formato; `payload` objeto; `schema_version >= 1`.
- [ ] `updated_by` FK com `SET NULL`; `id` default `uuidv7()`; timestamps `NOT NULL`.
- [ ] Nenhum HTML/CSS/Blade no payload (schema é dado, não apresentação).
- [ ] `encrypted_payload` reservado a campos `secret`; o payload público não contém segredo.

### Determinismo / D3
- [ ] Ordem de seções e campos explícita; defaults determinísticos; nenhum `now()`/`rand()` no domínio.
- [ ] Teste não depende de ordem de banco nem de relógio real.

### i18n / D8
- [ ] Labels são **chaves** i18n (`settings.*`), não texto; traduções entram com a UI (P0.S3/S4).
- [ ] Nenhuma string visível hardcoded na camada de schema.

### Segurança / D11
- [ ] Valores inválidos não viram exceção de request na leitura; segredo nunca no payload público.
- [ ] Sem PII em log/auditoria nesta fatia (auditoria entra na S2).

### Testes / D13
- [ ] Teste do schema (normalização/rejeição) e do contrato físico (UNIQUE/CHECK/FK/default).
- [ ] `make check` 2×; `make check E2E=1` fica para a UI (S3/S4).

### Específicos da fatia
- [ ] `SettingsSchema::normalize` não inclui defaults (não mascara ausência de dado).
- [ ] `seo.site_logo` aceita path/URL (fallback de `config/seo.php`), não só media id.
- [ ] Nenhum endpoint de chave avulsa; nenhuma seção fora das seis iniciais.

## Comandos úteis

```bash
make check
make exec cmd='vendor/bin/phpunit src/core/Settings/Test/SettingsSchemaTest.php src/core/Internal/Settings/Test/SettingsTableTest.php'
make exec cmd='vendor/bin/phpstan analyse --no-progress --memory-limit=1G'
make exec cmd='php tools/migration-check'
make exec cmd='php artisan migrate:status'
make exec cmd='php artisan db:table core.core_settings'
```

## Notas da revisão

| Data | Revisor | Resultado | Observações |
|---|---|---|---|
| 2026-10-24 | agente revisor P0-S1 | ✅ | Revisão adequada. **F1 (alto) corrigido:** `down()` renomeia também o índice `core_settings_section_unique`; teste `down()→up()` verde. **F2 corrigido:** migração incluída no `MigrationIdempotencyTest`. **F3 (médio) deferido:** `theme.*` será validado pelo `ThemeSchema` (P1), com `@debt [task_01uq1k4y]` e sem acoplar Core→Layout. **F4 corrigido:** FK `updated_by` e DEFAULT de `payload` cobertos. |
