feat(audit) : contexte forensique dans le journal d'activité (IP, appareil, device id) #33

Merged
tristan merged 23 commits from feature/SIRH-41-ajouter-plus-d-info-dans-le-journal-d-activite into develop 2026-06-24 11:56:43 +00:00
Owner

Contexte

Certains comptes sont partagés par plusieurs personnes (ex. compte « Usine »), y compris depuis des smartphones. Le journal d'activité ne stockait que le username → impossible de distinguer les intervenants. Cette PR ajoute un contexte forensique automatique à chaque entrée du journal.

Ce qui est ajouté (capté automatiquement, sans friction utilisateur)

  • Adresse IP de la requête
  • User-Agent brut (borné à 1024 caractères)
  • Libellé appareil lisible dérivé du User-Agent : Type · OS · Navigateur (ex. Mobile · Android · Chrome)
  • Identifiant d'appareil persistant envoyé par le front (header X-Device-Id, stocké en localStorage, borné à 64 car.) — distingue les appareils derrière un compte partagé

Implémentation

  • UserAgentParser (service maison, sans dépendance) — détection ordonnée OS/navigateur, testée
  • 4 colonnes nullable sur audit_logs + migration réversible (pas de backfill, rétro-compatible)
  • Capture centralisée dans AuditLogger::log() via RequestStack — aucun processor modifié
  • Champs exposés dans l'API lecture (AuditLogProvider + DTO TS aligné) via AuditLogReadRepositoryInterface (suit le pattern existant des autres read-repos)
  • Front : useDeviceId + injection du header X-Device-Id dans useApi (sur toutes les requêtes, SSR-safe)
  • framework.trusted_proxies documenté (commenté) pour une IP correcte derrière un reverse proxy
  • Docs : doc/audit-logging.md + CLAUDE.md

Hors périmètre (étapes suivantes)

  • Écran du journal (audit-logs.vue) non modifié — l'affichage des nouvelles colonnes fera l'objet d'une refonte séparée. Les données sont prêtes côté API.
  • La doc in-app (documentation-content.ts) n'est pas touchée : le journal est un outil caché ROLE_SUPER_ADMIN sans article existant ni niveau de doc super-admin.

À noter pour le déploiement

  • L'IP n'est fiable derrière un reverse proxy qu'une fois framework.trusted_proxies activé (livré commenté).

Tests

OK (249 tests, 533 assertions) — sortie PHPUnit propre (aucune notice).

🤖 Generated with Claude Code

## Contexte Certains comptes sont **partagés** par plusieurs personnes (ex. compte « Usine »), y compris depuis des smartphones. Le journal d'activité ne stockait que le `username` → impossible de distinguer les intervenants. Cette PR ajoute un **contexte forensique automatique** à chaque entrée du journal. ## Ce qui est ajouté (capté automatiquement, sans friction utilisateur) - **Adresse IP** de la requête - **User-Agent brut** (borné à 1024 caractères) - **Libellé appareil lisible** dérivé du User-Agent : `Type · OS · Navigateur` (ex. `Mobile · Android · Chrome`) - **Identifiant d'appareil persistant** envoyé par le front (header `X-Device-Id`, stocké en `localStorage`, borné à 64 car.) — distingue les **appareils** derrière un compte partagé ## Implémentation - `UserAgentParser` (service maison, sans dépendance) — détection ordonnée OS/navigateur, testée - 4 colonnes **nullable** sur `audit_logs` + migration réversible (pas de backfill, rétro-compatible) - Capture **centralisée** dans `AuditLogger::log()` via `RequestStack` — aucun processor modifié - Champs exposés dans l'API lecture (`AuditLogProvider` + DTO TS aligné) via `AuditLogReadRepositoryInterface` (suit le pattern existant des autres read-repos) - Front : `useDeviceId` + injection du header `X-Device-Id` dans `useApi` (sur toutes les requêtes, SSR-safe) - `framework.trusted_proxies` documenté (commenté) pour une IP correcte derrière un reverse proxy - Docs : `doc/audit-logging.md` + `CLAUDE.md` ## Hors périmètre (étapes suivantes) - **Écran du journal (`audit-logs.vue`) non modifié** — l'affichage des nouvelles colonnes fera l'objet d'une refonte séparée. Les données sont prêtes côté API. - La doc in-app (`documentation-content.ts`) n'est pas touchée : le journal est un outil caché `ROLE_SUPER_ADMIN` sans article existant ni niveau de doc super-admin. ## À noter pour le déploiement - L'IP n'est fiable derrière un reverse proxy qu'une fois `framework.trusted_proxies` activé (livré commenté). ## Tests `OK (249 tests, 533 assertions)` — sortie PHPUnit propre (aucune notice). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
tristan added 11 commits 2026-06-24 08:40:58 +00:00
tristan added 1 commit 2026-06-24 08:49:08 +00:00
Le front envoie X-Device-Id sur toutes les requêtes (cross-origin :3001 -> :8081).
Sans l'ajouter à allow_headers, le préflight CORS échoue et le navigateur bloque
toutes les requêtes API. Vérifié : préflight OPTIONS passe de 400 à 200.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tristan added 1 commit 2026-06-24 08:50:05 +00:00
tristan added 8 commits 2026-06-24 09:35:09 +00:00
tristan added 1 commit 2026-06-24 09:52:25 +00:00
tristan added 1 commit 2026-06-24 10:05:11 +00:00
Employé = recherche partielle sur nom/prénom (nouveau filtre back 'employee', LIKE via join) ;
Utilisateur = recherche partielle sur username. Remplace les selects par des champs texte.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tristan merged commit 832751d1ed into develop 2026-06-24 11:56:43 +00:00
tristan deleted branch feature/SIRH-41-ajouter-plus-d-info-dans-le-journal-d-activite 2026-06-24 11:56:44 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: MALIO-DEV/SIRH#33