Keep an audit log of who did what, and how they came in

Written from model events, spatie's role events and panel sign-ins, only for
what a person did, with secrets masked; pruned after a year.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-01 10:08:01 +02:00
parent 9bdbf834f6
commit 1fe1e67773
18 changed files with 744 additions and 1 deletions

View File

@@ -1402,6 +1402,29 @@ media; veinte fallos seguidos lo apagan hasta que alguien lo vuelve a activar.
Los datos de quien escribe al buzón (nombre, correo, mensaje) solo viajan a los
webhooks con `include_personal_data`.
### Registro de auditoría
`GET /api/v1/audit` (permiso `audit.view_any`, solo admin): quién hizo qué,
cuándo y **por dónde entró** —`panel`, `api`, `token` (con qué token),
`console`— y desde qué IP. Filtros: `user_id`, `action` (exacta o un prefijo
como `pages.`), `subject_type`, `subject_id`, `via`, `from`, `to`.
El historial de cada ficha contesta «qué le pasó a esto»; esto contesta «qué
ha estado haciendo esta persona», en todo, incluido lo que no tiene historial
propio: roles (los eventos de spatie están activados para eso), ajustes,
tokens, webhooks, medios, el buzón. Lo escribe
[`Auditor`](app/Support/Audit/Auditor.php) desde los eventos de los modelos,
así que no depende de que cada controlador se acuerde.
Solo lo que hace una persona: una sincronización o una publicación programada
son la aplicación trabajando y enterrarían lo que se viene a buscar, y el
`content.version` que sube con cada edición tampoco cuenta. Los secretos
(contraseñas, hashes de token, secretos de webhook) salen como `••••`, y los
valores largos se recortan: el detalle completo está en el historial de la
ficha. Como nombra a personas y sus direcciones, se borra pasados
`AUDIT_RETENTION_DAYS` (365 por defecto) con `model:prune`, programado a
diario.
### Lotes e importación
```