# CMS-001-01 — Schema, models, catálogo, logger, prune

| Campo | Valor |
|---|---|
| **status** | feita |
| **spec** | [`docs/specs/cms/001-admin.md`](../specs/cms/001-admin.md) §§4–5 |
| **depende de** | — |
| **primo** | migrations `perfis` / `permissoes` / `perfil_permissao` / `activity_logs` / `users.role`; models `Perfil`, `Permissao`, `ActivityLog`; `ActivityLogger`; `PruneActivityLogs`; seeders `PermissaoSeeder`, `PerfilSeeder` |

## Objetivo

Base de dados e PHP do NeoCMS **sem** UI Filament nesta task. Front do site não muda.

## Fazer

1. Migrations (espelhar o primo; catálogo de chaves é o da spec Omni, não o do holding):
   - `perfis`, `permissoes`, `perfil_permissao`
   - `users.role` enum `root` \| `usuario` default `usuario`
   - `users.perfil_id` nullable FK `perfis` `nullOnDelete`
   - `activity_logs` (sem `updated_at`)
2. Models: `Perfil`, `Permissao` (`catalogo()` + `syncCatalog()` da spec §5.1), `ActivityLog`.
3. `User`: `role`, `perfil_id`, `perfil()`, `isRoot()`, `hasPermission()`. **Ainda não** `FilamentUser` / `canAccessPanel` (task 03).
4. `App\Services\ActivityLogger` igual ao primo.
5. Comando `activity-logs:prune --days=90` + `Schedule` diário em `routes/console.php`. Sitemap do primo **não**.
6. Seeders: `PermissaoSeeder` (`syncCatalog`), `PerfilSeeder` (Administrador = todas; Operador = menos Usuários e Sistema). `DatabaseSeeder` chama os dois **antes** do user de teste atual. Root `admin@omni.com.br` fica na **task 05**.
7. `UserFactory`: `role` default `usuario`, `perfil_id` nullable.

## Testes (Pest ou PHPUnit, o que o repo já usa)

- `Permissao::syncCatalog()` cria as chaves da spec (pelo menos `paginas.home.editar`, `usuarios.criar`, `sistema.logs.visualizar`).
- Perfil Operador **não** recebe módulo Usuários nem Sistema.
- `hasPermission`: root true; usuario com chave true; sem chave false.
- Prune: log antigo some, recente fica.
- Logger grava `action` + `user_id`.

## Fora

Filament pages/resources, logos, Breeze, `Manage*Page`.
