PD-37 — Retour d'expérience¶
Navigation User Story
| Document | | | ---------- | -- | | [Spécification](PD-37-specification.md) | | | [Plan d'implémentation](PD-37-plan.md) | | | [Critères d'acceptation](PD-37-acceptability.md) | | | **Retour d'expérience** | *(ce document)* | [Retour à crypto-proof](../PD-189-epic.md) · [Index User Story](index.md)1. Résumé exécutif¶
Objectif : Implémenter un service de signature HSM des journaux d'audit probatoires, garantissant non-répudiation, intégrité et auditabilité conformément aux normes NF Z42-013 et ISO 14641.
Résultat : Service livré et fonctionnel après correction de deux écarts identifiés lors de la revue d'acceptabilité. La vérification indépendante des signatures (E-01 BLOQUANT) et la gestion des échecs via Dead Letter Queue (E-03 MAJEUR) ont nécessité des développements complémentaires non prévus dans le plan initial.
Verdict : ACCEPTÉ le 2025-12-22, après refus initial le 2025-12-18.
2. Points fluides¶
- Canonicalisation RFC 8785 : Implémentation directe via bibliothèque
canonicalize, tests unitaires avec vecteurs RFC conformes. - Intégration HsmService : L'abstraction PKCS#11 existante a permis une intégration transparente de la signature ECDSA P-256.
- SHA3-256 : HashService déjà disponible, réutilisé sans modification.
- Table append-only : Trigger PostgreSQL simple et efficace pour bloquer UPDATE/DELETE.
- Queue BullMQ : Configuration standard avec retry exponentiel, intégration NestJS fluide.
- Types d'audit : Enum exhaustif couvrant l'ensemble des actions métier identifiées.
3. Points difficiles¶
3.1 Vérification indépendante du HSM (E-01)¶
- Contexte : La spécification exige une preuve « vérifiable de façon indépendante, sans dépendre du backend ». Le plan d'implémentation proposait
verifyAuditEntry()appelantHsmService.verify(), ce qui maintient la dépendance au HSM. - Impact : Écart BLOQUANT détecté en revue d'acceptabilité.
- Résolution : Ajout de trois composants non planifiés :
- Table
hsm_public_keyspour persister les clés publiques exportées AuditVerificationServiceutilisant Node.jscryptoau lieu du HSM- Outil CLI standalone
verify-audit-proof.tspour tiers vérificateurs
3.2 Gestion des échecs définitifs (E-03)¶
- Contexte : Le plan mentionnait explicitement « Dead Letter Queue » comme hors périmètre. La configuration BullMQ (
removeOnFail: 1000) supprimait silencieusement les jobs après 3 échecs. - Impact : Violation de l'exigence de robustesse (« Aucune entrée partielle ne doit être créée »).
- Résolution : Ajout d'une couche DLQ complète :
- Entité
AuditSignatureDlqet migration associée AuditDlqServicepour gestion manuelle et automatique- Flow Prefect
audit_dlq_retry.pypour orchestration (cron */15 min) - Playbook Ansible
audit_dlq_monitoring.ymlpour déploiement
3.3 Coordination multi-repos¶
- Contexte : La correction E-03 a nécessité des modifications dans deux dépôts distincts (backend + infra).
- Impact : Synchronisation des déploiements requise, documentation dispersée.
4. Hypothèses révélées tardivement¶
| Hypothèse implicite | Découverte |
|---|---|
| La vérification peut utiliser le HSM en production | Faux : les auditeurs externes n'ont pas accès au HSM |
| BullMQ gère nativement la DLQ | Faux : removeOnFail supprime les jobs, pas de DLQ intégrée |
| Le plan couvre tous les invariants de la spec | Faux : l'exclusion explicite de la DLQ contredit l'exigence de robustesse |
| La clé publique HSM peut être récupérée à tout moment | Vrai mais insuffisant : nécessite persistance pour vérification offline |
5. Invariants complexes¶
| Invariant | Complexité |
|---|---|
| Append-only absolu | Simple (trigger SQL), mais contraint les corrections de données |
| Signature HSM-only | Simple en signature, complexe en vérification indépendante |
| Aucune perte d'entrée | Complexe : nécessite DLQ + monitoring + retry automatique + retry manuel |
| Vérification sans backend | Complexe : export clé publique + outil standalone + format de preuve documenté |
6. Dette technique¶
| Élément | Description | Priorité |
|---|---|---|
| Tests E2E DLQ | Pas de test d'intégration complet du flow Prefect avec le backend | Moyenne |
Endpoint /audit/proof/status | Placeholder non implémenté (retourne toujours 0) | Basse |
| Format preuve exportée | Pas de schéma JSON formel documenté pour les tiers | Moyenne |
| Authentification API DLQ | Les endpoints /audit/proof/dlq/* ne sont pas protégés | Haute |
7. Risques résiduels¶
| Risque | Probabilité | Impact | Mitigation actuelle |
|---|---|---|---|
| Perte d'entrée si insertion DLQ échoue | Faible | Élevé | Log CRITICAL avec payload complet, récupérable manuellement |
| Désynchronisation clé publique | Faible | Moyen | Export automatique à chaque rotation (non testé en rotation réelle) |
| Prefect indisponible | Moyenne | Moyen | Retry manuel possible via API, alertes si pending > seuil |
| Saturation DLQ | Faible | Moyen | Alertes Prefect si > 10 entrées ou > 24h en attente |
8. Améliorations processus¶
| Suggestion | Justification |
|---|---|
| Revue spec vs plan systématique | L'écart E-01 aurait pu être détecté en comparant la spec (« vérifiable indépendamment ») et le plan (HsmService.verify) |
| Checklist invariants | Vérifier explicitement chaque contrainte de la spec avant validation du plan |
| Éviter « hors périmètre » contradictoire | La DLQ était hors périmètre du plan mais requise par la spec — cette incohérence devait être levée |
| Documentation multi-repo | Prévoir un README de coordination quand une US touche plusieurs dépôts |
9. Enseignements clés¶
-
« Vérification indépendante » signifie vraiment indépendante : tout composant de preuve doit pouvoir être vérifié sans accès au système source ni au HSM.
-
La robustesse inclut la récupération des échecs : « aucune entrée partielle » implique de gérer le cycle de vie complet, y compris les échecs définitifs après retry.
-
« Hors périmètre » ne suspend pas les invariants : exclure une fonctionnalité du plan ne la rend pas optionnelle si la spec l'exige.
-
Le premier verdict d'acceptabilité est rarement le dernier : prévoir des itérations entre revue et correction est normal sur les US à forte exigence de conformité.
-
L'orchestration (Prefect/Ansible) fait partie du livrable : une fonctionnalité backend sans son déploiement automatisé n'est pas complète.
Historique du document¶
| Date | Auteur | Modification |
|---|---|---|
| 2025-12-22 | Claude | Création initiale du REX |