# F5.I4.T1 — `MediaInputer` (entrada única) → AVIF/WebP `[360..2560]` com `width/height`

| Campo | Valor |
|---|---|
| **Fase** | F5 — Borda |
| **Issue** | F5.I4 — Media e Gallery (plano 19) |
| **kd task** | `task_01l7n3ll` |
| **Âncora** | `wiki/implementation/05-borda.md` |
| **Status da revisão** | 🔧 com correções |

## O que foi implementado

- MIME **real** (finfo) no serviço + allowlist fechada (`services.media.upload.mimes`); SVG fica
  vetorial (sem variantes); imagem `< 360` gera **1 variante na largura original**; nunca gera
  largura maior que a original; nome de objeto determinístico (UUIDv7 injetado) e `checksum` SHA-256.
- `StoreEditorMedia` emite AVIF (inputer) + WebP (mesma largura) com `width`/`height` (CLS 0).
- Política de tamanho por tipo (soft = aviso, hard = recusa) em `MediaLimits` + `config/media.php`,
  aplicada também fora do HTTP (fila/catálogo) e no `FormRequest` (`WithinMediaLimit`).

## Arquivos para revisar

- `src/services/Media/MediaInputer.php`
- `src/services/Media/Actions/StoreEditorMedia.php`
- `src/services/Media/Support/MediaLimits.php` · `DTOs/MediaLimit.php` · `Rules/WithinMediaLimit.php`
- `config/media.php` · `src/services/Media/Lang/{locale}/limits.php`
- `src/services/Media/Migrations/2026_10_23_1{2,4}0000_*`
- `src/services/Media/Test/{MediaInputerTest,MediaUploadTest,MediaLimitsTest}.php`

## Pontos de revisão

### PHP 8.4 / Laravel 12
- [ ] `declare(strict_types=1)`; DI por construtor (sem `new`/`app()`/`resolve()` no corpo); PHPStan `max`.
- [ ] Nativo primeiro; sem closure em rota; `env()` só em `config/`; validação em `FormRequest`.

### Determinismo (ADR-001)
- [ ] `Clock`/`IdGen` injetados; ordem explícita; idempotência provada por teste.

### Fronteiras (ADR-013/014/015)
- [ ] Camadas respeitadas; módulo consome `Services\{Name}\{Contracts,DTOs,Enums}\*`; nada de storage fora do Media.

### HTML/a11y (ADR-025) e CSS (ADR-010)
- [ ] Semântica, rótulos, alvos; sem `!important`/inline/CDN; `oklch`/`rem`.

### i18n (ADR-012)
- [ ] Nenhuma string visível fixa — inclusive **títulos de erro lançados em PHP** (o `ModuleI18nTest` só varre views).

### Dados (ADR-007/017) e segurança (ADR-020/021/026/030/035)
- [ ] `text`/`jsonb`/`uuidv7()`; `down()` → `backup_*`; CHECKs; PII cifrada; `throttle`; MIME real; `alt` obrigatório.

### Observabilidade/auditoria (ADR-024/035)
- [ ] Span + `log_event` com o **mesmo** `{service}.{action}`; auditoria via `AuditWriter`; sem PII.

### Específicos desta task

- [ ] MIME pelo **conteúdo** decide; extensão nunca decide.
- [ ] Variantes: `[360,720,1200,1920,2560]` ∩ largura original, ordem crescente, `width`/`height` reais.
- [ ] SVG sem rasterização; PDF com otimizador próprio; `checksum` no payload.
- [ ] Limites soft/hard por tipo; aviso persistido para o polling.

## Comandos úteis

```bash
make check              # caminho único (rápido)
make check E2E=1        # + Playwright/axe/perf (2× ao fechar o escopo)
```

---

> Revisar contra `AGENTS.md`, `wiki/adr/` e o plano citado. Registrar achados no `kd` (`kd write --anchor`) e, se houver correção, teste de regressão.

## Notas da revisão

| Data | Revisor | Resultado | Observações |
|---|---|---|---|
| 2026-10-19 | agente (PROTOCOLO v2.0) | 🔧 | **A** (médio, D8) mensagens de erro do inputer/limites em pt_BR fixo → chaves
`media::limits.error_*` nos 4 locales + `MediaInputer::unsupported()` (uma fonte) — `fact_01j4nvg7`.
**B** (baixo, D1) o `match` tinha um braço `UNKNOWN` que duplicava a exceção do
`assertAllowedMime` → ambos passam a usar o mesmo método. **Verificado OK**: finfo no serviço,
allowlist, SVG vetorial, imagem pequena com 1 variante, `checksum` SHA-256, `MediaLimitsTest`
(unit + HTTP + borda) e smoke de PDF grande. |

> Resultado: `✅ revisado` · `🔧 com correções` · `⏭️ delegado` (com justificativa).
