PD-37 — Rétrospective¶
1. Contexte¶
| Champ | Valeur |
|---|---|
| Story ID | PD-37 |
| Titre | Signature HSM des journaux d'audit |
| Domaine | crypto-proof |
| Projet | backend |
| Date complétion | 2025-12-22 |
| Verdict | ACCEPTÉ (après refus initial 2025-12-18) |
2. Métriques¶
| Métrique | Valeur |
|---|---|
| Écarts bloquants | 1 (E-01 vérification indépendante) |
| Écarts majeurs | 1 (E-03 DLQ) |
| Composants non planifiés | 3 (hsm_public_keys, AuditVerificationService, CLI) |
| Repos impactés | 2 (backend + infra) |
3. Learnings 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.
HsmService.verify()ne suffit pas. -
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. La DLQ est obligatoire.
-
"Hors périmètre" ne suspend pas les invariants : Exclure une fonctionnalité du plan ne la rend pas optionnelle si la spec l'exige. La DLQ était "hors périmètre" mais requise.
-
L'orchestration fait partie du livrable : Une fonctionnalité backend sans son déploiement automatisé (Prefect/Ansible) n'est pas complète.
4. Patterns applicables¶
Pattern existant : Canonicalisation RFC 8785¶
import { canonicalize } from 'canonicalize';
const canonical = canonicalize(auditEntry);
const hash = crypto.createHash('sha3-256').update(canonical).digest();
const signature = await this.hsmService.sign(keyLabel, hash);
Nouveau pattern : Vérification indépendante HSM¶
Pour permettre la vérification sans accès au HSM : 1. Exporter et persister les clés publiques (hsm_public_keys) 2. Service de vérification utilisant crypto natif, pas le HSM 3. Outil CLI standalone pour tiers vérificateurs
// AuditVerificationService - n'utilise PAS HsmService
const publicKey = await this.publicKeyRepository.findByKeyId(keyId);
const isValid = crypto.verify('sha3-256', data, publicKey, signature);
Nouveau pattern : Dead Letter Queue pour audit¶
@OnQueueFailed()
async handleFailure(job: Job, error: Error) {
if (job.attemptsMade >= this.maxRetries) {
await this.dlqService.add({
payload: job.data,
error: error.message,
failedAt: new Date(),
});
this.logger.critical('Audit entry moved to DLQ', { jobId: job.id });
}
}
5. Signal CLAUDE.md¶
Priorité haute : Revue spec vs plan systématique.
### Revue Spec vs Plan — Checklist (2026-02-XX)
Avant validation du plan, vérifier systématiquement :
1. Chaque invariant de la spec a une tâche correspondante
2. Aucune fonctionnalité "hors périmètre" ne contredit un invariant
3. Les dépendances externes (DLQ, monitoring, déploiement) sont identifiées
4. Les vérifications "indépendantes" sont vraiment indépendantes
**L'écart E-01 aurait pu être détecté en comparant "vérifiable indépendamment" et `HsmService.verify()`**
6. Conclusion¶
PD-37 a livré la signature HSM des journaux d'audit probatoires après correction de deux écarts bloquants. La vérification indépendante (sans HSM) et la DLQ complète ont nécessité des développements non planifiés. Le pattern "vérification indépendante HSM" est désormais standard pour toute preuve probatoire.
Rétrospective générée 2026-02-19 (Étape 10 batch crypto-proof)