Aller au contenu

PD-264 — Dossier d'acceptabilité

Story : PD-264 — Nonce anti-rejeu + interopérabilité TSA RFC 3161 Projet : ProbatioVault-backend Date : 2026-02-24 Branche : feature/PD-264-nonce-tsa-rfc3161


Prérequis acceptabilité

  • Tests CI : 95/95 tests PD-264 passent (6 suites)
  • Coverage : 95.38% stmts, 82.35% branches, 100% functions, 95.16% lines (seuil : 80%)
  • TODO non tracés : aucun dans le code PD-264
  • Code DEV ONLY : aucun scaffolding non déclaré

Note : Le Quality Gate global backend retourne ko en raison de tests pre-existants échoués dans deposit.controller.spec.ts et delete-account-rate-limit.service.spec.ts (hors périmètre PD-264). Les 95 tests PD-264 passent à 100%.


Phase 1 — Reviews automatisées

Résultats Quality Gates (PD-264 scope)

Check Résultat Détails
ESLint OK 0 erreur, 0 warning dans les fichiers PD-264
Format (Prettier) OK Tous les fichiers conformes
TypeScript (tsc) OK Compilation sans erreur
Tests PD-264 OK 95/95 tests passent (6 suites)
Coverage OK 95.38% stmts > 80% seuil

Coverage détaillé PD-264

Fichier Stmts Branch Func Lines
nonce.service.ts 100% 100% 100% 100%
nonce-validation.service.ts 100% 85.71% 100% 100%
batch-timestamp.processor.ts 88.46% 75% 100% 87.5%
tsa-error-code.enum.ts 100% 100% 100% 100%
Migration 100% 100% 100% 100%
Total PD-264 95.38% 82.35% 100% 95.16%

Phase 1.5 — Analyse Sonar

  • Quality Gate : Non exécuté (token Sonar indisponible depuis Vault local)
  • Action : Sera vérifié par le pipeline CI/CD après merge sur dev
  • Risque résiduel : Faible — le code suit les patterns Sonar-safe (pas de Math.random, pas d'injection SQL, crypto.randomBytes exclusif)

Phase 2 — Reviews LLM (validation croisée)

Review Code (développeur senior) — claude -p

Verdict : CONFORME

Critère Statut
Patterns NestJS OK
Qualité code OK
Gestion erreurs OK
Maintenabilité OK

Points forts : Séparation des responsabilités exemplaire, sécurité cryptographique rigoureuse (CSPRNG, timingSafeEqual), migration DDL robuste et réversible, automate d'états déclaratif, défense en profondeur (applicatif + DB).

Écarts identifiés :

ID Description Gravité
R-01 Le catch global du processor utilise QTSA_UNREACHABLE comme code d'erreur par défaut pour toutes les exceptions, même non-QTSA MINEUR
R-02 Early-return dans compareEqual() si tailles différentes (avant timingSafeEqual) — risque négligeable car la taille est toujours 16 après validatePresence MINEUR
R-03 Placeholder QTSA retourne QTSA_UNREACHABLE — dette intentionnelle documentée Suggestion

Review Tests (QA engineer) — claude -p

Verdict : CONFORME

Critère Statut
Couverture TC-* 19/19 (+ 3 TC-MIG + 5 NR)
Qualité assertions OK
Isolation OK
Edge cases OK
Nommage descriptif OK

Écarts identifiés :

ID Description Gravité
T-01 TC-264-06 (concurrence) : mock séquentiel, pas de vraie concurrence PG MINEUR
T-02 TC-264-09 (immutabilité) : couvert conceptuellement par TC-MIG-03 mais pas de test UPDATE réel MINEUR
T-03 TC-264-14/15/17 : 3 placeholders expect(true).toBe(true) — justifiés (QTSA non implémenté, Prolog hors Jest, nightly) MINEUR
T-04 TC-264-08 : Chi² non implémenté — proxy CSPRNG comportemental uniquement MINEUR
T-05 TC-264-19 (atomicité) : crash simulé au niveau mock, pas fault injection PG MINEUR
T-06 TC-264-07 : Cliff's delta comme seul critère bloquant, p-values informatives — diverge légèrement du protocole spec MINEUR

Review Sécurité (pentester adversarial) — claude -p

Verdict : RÉSERVES (aucune vulnérabilité MAJEURE ou CRITIQUE)

Contrôles positifs : - Forbidden patterns : tous absents (0 violation) - CSPRNG : crypto.randomBytes(16) exclusif, Math.random() absent - Timing attacks : crypto.timingSafeEqual utilisé, Buffer.equals() absent - Anti-rejeu : double protection (applicative + index UNIQUE DB) - Immutabilité : trigger PostgreSQL réactivé post-migration - Injection SQL : aucune — ORM paramétré exclusivement

Écarts identifiés :

ID Description Gravité
S-01 errorCode forcé à QTSA_UNREACHABLE dans le catch global du processor (masque les codes d'erreur spécifiques) MINEUR
S-02 errorMessage brut renvoyé dans le résultat de job (risque de fuite d'info si exposé en API) MINEUR

Dettes documentées : - D-01 : Client QTSA non implémenté (stub explicite, retour contrôlé) - D-02 : Automate d'états non exercé end-to-end dans le processor (flux futur commenté)


Synthèse des écarts

Tableau consolidé

ID Source Description Gravité Action
R-01 Code QTSA_UNREACHABLE comme code d'erreur par défaut MINEUR Sera corrigé avec PD-265 (client QTSA réel)
R-02 Code Early-return tailles différentes dans compareEqual MINEUR Accepté — validatePresence garantit taille 16 en amont
R-03 Code Placeholder QTSA Suggestion Dette intentionnelle, ticket PD-265
S-01 Sécu errorCode masqué dans catch global MINEUR = R-01, corrigé avec client QTSA
S-02 Sécu errorMessage brut dans résultat job MINEUR BullMQ jobs non exposés en API directement — risque acceptable
T-01 Tests Mock concurrence (pas vraie PG) MINEUR Accepté — contrainte UNIQUE testée via TC-MIG-01
T-02 Tests TC-264-09 conceptuel uniquement MINEUR Accepté — trigger testé via TC-MIG-03
T-03 Tests 3 placeholders TC-264-14/15/17 MINEUR Justifiés — dépendances QTSA/Prolog/nightly
T-04 Tests Chi² non implémenté MINEUR Proxy CSPRNG suffisant — Chi² planifié nightly
T-05 Tests Crash simulé au niveau mock MINEUR PG garantit l'atomicité transactionnelle
T-06 Tests Cliff's delta seul critère bloquant MINEUR Pragmatique — MWU trop puissant à N=100K

Statistiques

  • Écarts CRITIQUE : 0
  • Écarts MAJEUR : 0
  • Écarts MINEUR : 11 (dont 2 doublons R-01=S-01, R-03=D-01)
  • Suggestions : 1
  • Écarts uniques : 9 MINEUR + 1 suggestion

Verdict global

CONFORME AVEC RÉSERVES MINEURES

Tous les écarts sont de gravité MINEUR. Aucun écart ne constitue un blocage pour Gate 8.

Les réserves de la review sécurité (S-01, S-02) sont acceptables : - S-01 sera résolu avec l'implémentation du client QTSA (PD-265) - S-02 n'est pas exposé en API (BullMQ interne)

Recommandation : GO pour Gate 8 CLOSURE.