Aller au contenu

PD-17 — Retour d'Expérience


Navigation User Story | Document | | | ---------- | -- | | [Spécification](PD-17-specification.md) | | | [Plan d'implémentation](PD-17-plan.md) | | | [Critères d'acceptation](PD-17-acceptability.md) | | | **Retour d'expérience** | *(ce document)* | [Retour à backend-core](../PD-186-epic.md) · [Index User Story](index.md)

1. Résumé exécutif

PD-17 visait à implémenter une extension probatoire du journal PD-37 pour tracer les accès ALLOW/DENY avec un payload canonique signé HSM.

La première revue d'acceptabilité a identifié deux écarts : E-01 (BLOQUANT) — flux ALLOW/DENY non implémentés ; E-02 (MAJEUR) — schéma canonique non validé.

Ces écarts ont été corrigés par la création de AccessAuditService, AccessAuditGuard, AccessAuditInterceptor, et d'une taxonomie Pd17DenyCode avec validation stricte.

Le verdict final est ACCEPTÉ avec 56 tests unitaires couvrant les composants PD-17.


2. Points fluides

  • Les contre-mesures de sécurité (§14 du plan) étaient déjà implémentées : AuditViolationListenerService, AuditSecurityMonitorService, prohibition dblink
  • Les action types ACCESS_ALLOW et ACCESS_DENY existaient déjà dans audit-action.types.ts
  • L'architecture NestJS (Guard + Interceptor + Decorator) est adaptée au pattern de logging déclaratif
  • La réutilisation de AuditLogService.logAsync() a permis l'intégration transparente avec le pipeline de signature HSM
  • La structure RFC 8785 (JSON canonique) de PD-37 accepte directement le payload PD-17 dans metadata
  • Les 56 tests ont été écrits rapidement grâce aux patterns de mock établis par PD-37

3. Points difficiles

Obstacle Contexte
Écart E-01 détecté tardivement La revue d'acceptabilité a révélé l'absence totale des flux ALLOW/DENY alors que les contre-mesures sécurité étaient présentes
Divergence taxonomie deny_code La spec §10.1 proposait AUTH_INVALID, ACL_DENY, etc. ; l'implémentation utilise UNAUTHORIZED, FORBIDDEN, etc. (plus proche HTTP)
Structure context différente La spec §5.0 prévoyait actor_type, entity_type ; l'implémentation utilise resource_type, action, http_method (plus REST-centric)
Absence de mode strict Le plan §4.2 prévoyait un rejet d'accès si HSM indisponible ; l'implémentation utilise logAsync() avec queue fallback

4. Hypothèses révélées tardivement

Hypothèse Découverte
La taxonomie deny_code pouvait être adaptée Les codes HTTP (401, 403, 404, 429) sont plus universels que les codes métier proposés
Le guard devait s'exécuter APRÈS la décision d'accès Le pattern NestJS impose Guard avant Controller ; l'Interceptor capture le résultat après
context.actor_type n'était pas nécessaire L'information est déduite de actorId (UUID = USER, 'system' = SYSTEM)
Les JWT claims devaient être inclus Nécessaire pour renforcer la validation actor_id (contre-mesure §14.3)

5. Invariants complexes

Invariant Difficulté
Primauté PD-37 Aucune modification de AuditLog entity ni des colonnes signées — respecté
Encodage unique dans entry_canonical Le payload PD-17 est dans metadata, sérialisé dans entry_canonical — conforme
Signature obligatoire ALLOW et DENY Les deux passent par AuditLogService.log() → signature HSM — conforme
Neutralité décisionnelle AccessAuditService reçoit la décision (exception catchée par interceptor), ne la prend pas — conforme

6. Dette technique

Dette Justification Impact
Taxonomie deny_code divergente de la spec Codes HTTP plus universels, mais incohérence documentaire MINEUR — à harmoniser dans la spec
Structure context simplifiée resource_type/action au lieu de actor_type/entity_type MINEUR — clarifier dans la spec
Pas de mode strict implémenté logAsync() avec queue préféré pour résilience ACCEPTABLE — comportement PD-37
@AuditedResource non appliqué aux endpoints Décorateur créé mais non déployé sur les contrôleurs À PLANIFIER — intégration endpoints

7. Risques résiduels

Risque Probabilité Mitigation
Endpoints non décorés génèrent 0 événement PD-17 Élevée (aucun endpoint n'utilise @AuditedResource) Déploiement progressif sur DocumentsController, FoldersController
Volumétrie DENY non monitorée Moyenne Ajouter métriques Prometheus sur ACCESS_DENY
Taxonomie deny_code incomplète Faible (11 codes couvrent les cas HTTP) Extensible via enum
Guard global non activé Élevée (guard exporté mais non APP_GUARD) Décision architecturale à prendre

8. Améliorations processus

Suggestion Bénéfice attendu
Revue d'acceptabilité AVANT corrections Évite de découvrir des écarts BLOQUANTS en fin d'implémentation
Valider la taxonomie avec les équipes API/front Aligne les codes DENY sur les besoins UX (messages utilisateur)
Template de payload PD dans les specs Évite les divergences structure context/deny_code
Tests d'intégration end-to-end Vérifie que le payload signé contient effectivement pd: 'PD-17'
Checklist "invariants PD-37" dans chaque PR Garantit la non-régression des colonnes probatoires

9. Enseignements clés

  1. Les contre-mesures de sécurité ne remplacent pas les flux métier — PD-17 avait dblink prohibition et pg_notify, mais pas le cœur fonctionnel (ALLOW/DENY)

  2. La taxonomie spec doit être challengée tôt — Les codes métier (ACL_DENY) sont moins universels que les codes HTTP (FORBIDDEN)

  3. Le pattern Guard+Interceptor est adapté au logging déclaratif — Le Guard capture le contexte avant, l'Interceptor log après

  4. 56 tests en < 2h grâce aux patterns PD-37 — La réutilisation des mocks AuditLogService, AuditSignatureService accélère le développement

  5. Le mode strict (accès refusé si HSM down) n'est pas implémenté — Décision implicite de privilégier la disponibilité via queue fallback


Annexe — Fichiers livrés

Fichier Lignes Tests
types/pd17-access-audit.types.ts 194 18
services/access-audit.service.ts 188 13
guards/access-audit.guard.ts 120 14
interceptors/access-audit.interceptor.ts 140 11
decorators/audited-resource.decorator.ts 25
Total 667 56