PD-39 — Rétrospective¶
1. Contexte¶
| Champ | Valeur |
|---|---|
| Story ID | PD-39 |
| Titre | Intégration TSA RFC 3161 par Batch |
| Domaine | crypto-proof |
| Projet | backend |
| Date complétion | 2025-12-23 |
| Verdict | ACCEPTÉ |
2. Métriques¶
| Métrique | Valeur |
|---|---|
| Fichiers source | 41 |
| Tests unitaires | 307 tests passants |
| Suites de tests | 15 |
| Écarts bloquants résolus | 2 (E-01 WORM, E-02 NTS) |
| Dette technique | 6 items (services QTSA non implémentés) |
3. Learnings clés¶
-
Fail-closed par défaut : Tout mécanisme de sécurité probatoire doit rejeter en cas de doute. Le mode permissif initial de l'horloge NTS a causé l'écart E-02.
-
Protection API insuffisante : Les guards NestJS protègent les endpoints mais pas la base de données. L'immuabilité probatoire exige des contrôles au niveau DB (triggers, RLS).
-
Démons externes acceptables : L'absence de bibliothèque NTS Node.js a conduit à utiliser ntpd-rs. Cette architecture découplée fonctionne bien si correctement documentée.
-
URIs ETSI en HTTP : Les identifiants
http://uri.etsi.org/TrstSvc/...ne sont pas des URLs à appeler mais des chaînes de comparaison. Commentaires NOSONAR et documentation ETSI essentiels. -
Livrer l'infrastructure avant l'intégration externe : L'approche "entities + services internes + interfaces QTSA" permet de valider l'architecture avant la complexité ASN.1/TL.
4. Patterns applicables¶
Pattern existant : MerkleService RFC 6962¶
buildTree(leaves: Buffer[]): MerkleTree {
const sortedLeaves = [...leaves].sort(Buffer.compare);
const hashedLeaves = sortedLeaves.map(l =>
this.hashLeaf(l) // prefix 0x00
);
return this.buildFromHashes(hashedLeaves);
}
Nouveau pattern : WORM protection DB¶
-- Trigger DML
CREATE TRIGGER prevent_audit_modification
BEFORE UPDATE OR DELETE ON audit_entries
FOR EACH ROW EXECUTE FUNCTION raise_audit_immutable();
-- Event trigger DDL (superuser)
CREATE EVENT TRIGGER protect_audit_triggers
ON ddl_command_start
WHEN TAG IN ('DROP TRIGGER')
EXECUTE FUNCTION prevent_audit_trigger_drop();
Nouveau pattern : NTS fail-closed¶
async getAuthenticatedTimeStrict(): Promise<Date> {
const status = await this.readObserveJson();
if (!status.nts_ke_established) {
throw new NtsNotAuthenticatedError('NTS not authenticated');
}
if (!this.hasCorrectPermissions(status)) {
throw new NtsPermissionError('observe.json permissions invalid');
}
return new Date(status.time);
}
5. Signal CLAUDE.md¶
Priorité haute : Identifier les dépendances infra en amont.
### Dépendances Infrastructure — Identification amont (2026-02-XX)
Lors de la spécification d'une US, identifier explicitement :
1. **Démons externes** : ntpd-rs, Redis, PostgreSQL, HSM
2. **Permissions système** : fichiers observe.json, certificats HSM
3. **Superuser PostgreSQL** : event triggers, extensions
4. **Provisionnement HSM** : labels de clés requis
Ces dépendances doivent être documentées dans la section "Hypothèses" de la spec.
6. Conclusion¶
PD-39 a livré l'infrastructure TSA RFC 3161 avec batch cryptographique, arbre Merkle RFC 6962, et attestations NTS. Les écarts E-01 (WORM) et E-02 (NTS fail-closed) ont révélé l'importance de la protection multi-couches (API + DB + triggers). Les services QTSA externes restent à implémenter (PD-39-B/C/D).
Rétrospective générée 2026-02-19 (Étape 10 batch crypto-proof)