Aller au contenu

PD-275 — Retour d'expérience (REX)

1. Résumé exécutif

Métrique Valeur
Objectif initial Conformité PV Anchor ANCHOR-16/17 (finality depth + signer revocation) — 32/32 checks Prolog
Résultat obtenu Conforme avec réserves (Sonar non disponible, Q-01/Q-03/Q-04 non résolues)
Verdict final GO (Gate 8 : 9.0/10)
Tests contractuels 260/260 passés (13 suites)

2. Métriques de convergence

2.1 Temps et itérations

Étape Durée estimée Durée réelle Itérations Écart
0 - Besoin 30 min 38 min 1 +27%
1 - Spécification 2h 5 min 1 -96%
2 - Tests 1h 4 min 1 -93%
3 - Gate spec 1h 2h03 3 +105%
4 - Plan 1h 10 min 1 -83%
5 - Gate plan 1h 17 min 2 -72%
6 - Implémentation 4h 30 min 1 -88%
7 - Acceptabilité 2h 13 min 1 -89%
8 - Gate acceptabilité 1h 6 min 1 -90%
9 - REX 30 min 30 min 1 0%
TOTAL ~14h ~4h20 13 -69%

2.2 Scores de convergence par gate

Gate Score v1 Score final Delta Itérations
Gate 3 7.875/10 9.062/10 +1.187 3
Gate 5 8.438/10 9.312/10 +0.874 2
Gate 8 9.0/10 9.0/10 0 1

2.3 Écarts par catégorie

Catégorie d'écart Gate 3 Gate 5 Gate 8 Total
ECT (complétude/testabilité) 1 0 0 1
DIV (divergence spec/impl) 3 7 4 14
AMB (ambiguïté) 1 0 1 2
SEC (sécurité) 0 0 1 1
PERF (performance) 0 0 0 0
TOTAL écarts 5 7 6 18

3. Points fluides

  • Gate 8 GO en v1 : aucune itération nécessaire sur la gate de clôture ; la qualité d'implémentation était suffisante dès le premier passage.
  • Implémentation rapide (30 min) : le plan détaillé avec 11 composants et les code contracts ont permis une exécution directe sans ambiguïté.
  • Convergence Gate 5 (delta +0.874) : les corrections du plan (suppression C8 SignerActiveGuard, BLK-01 pré-check signer, MAJ-02 double protection rôles) ont résolu des écarts structurels en une seule itération.
  • Coverage élevée : ~95% statements, ~82% branches sur les fichiers PD-275 sans effort de rattrapage.
  • Pattern fail-closed éprouvé : la réutilisation du pattern PD-177/PD-238 pour les gardes sécurité a été fluide.

4. Points difficiles

  • Gate 3 à 3 itérations : la spec initiale (8 INV) a nécessité l'ajout de 4 invariants (INV-275-09 à INV-275-12) pour couvrir l'autorisation, l'anti-usurpation, la concurrence et l'unicité d'audit — ces exigences n'étaient pas dans le besoin initial.
  • Convergence Gate 3 v2 stagnante (delta=0.25, action STOP) : la v2 a corrigé les écarts v1 mais introduit de nouveaux écarts (IST-05, testability chutée à 7.0). Débloqué par une correction tests v2 alignant la matrice avec les 4 nouveaux invariants.
  • Sonar Phase 1.5 indisponible : le token Sonar absent du Vault a forcé une dérogation de fait sur la phase BLOQUANTE. Atténuation par lint+tsc+tests+coverage, mais violation procédurale persistante.
  • 5 questions ouvertes (Q-01 à Q-05) héritées de la spec : aucune n'a été résolue formellement durant le workflow. Q-02 résolue de facto par le code existant (enum BatchStatus).

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

  • Double fenêtre de vérification signer (pré-check + re-check) — découverte à l'étape 5 : la spec décrit une fenêtre unique de sérialisation pour submitBatch(), mais le plan a introduit un pré-check hors transaction avant createBatch() pour éviter le travail inutile. Accepté comme optimisation by design (DIV-05 Gate 5).
  • SignerActiveGuard HTTP non pertinent pour BullMQ — découverte à l'étape 5 : le plan v1 incluait un guard NestJS HTTP (C8) alors que submitBatch() est appelé depuis un worker BullMQ. Supprimé en v2 (MAJ-01/MAJ-03).
  • Codes HTTP sur erreurs internes worker — découverte à l'étape 8 : les codes HTTP (409, 404) attribués aux erreurs signer ne transitent jamais par HTTP dans le flux de soumission (worker BullMQ). Incohérence de présentation documentée.

6. Invariants complexes

  • INV-275-11 (signer-concurrency-serialization) — TC-NOM-10, TC-NOM-11 : la sérialisation par SELECT ... FOR UPDATE entre revokeSigner() et submitBatch() concurrents nécessite des tests d'intégration PostgreSQL réels avec deux connexions parallèles. Pattern Promise.all([revoke, submit]) sur connexions distinctes.
  • INV-275-12 (single-revocation-audit-event) — TC-NOM-11 : prouver qu'un seul audit trail est émis lors de deux revocations concurrentes. Dépend directement du verrou pessimiste (INV-275-11) et de la vérification de statut sous verrou.
  • INV-275-10 (revokedBy-auth-derived) — TC-ERR-09 : l'anti-usurpation nécessite une validation DTO qui rejette les champs non déclarés + extraction depuis le contexte auth. Complexité dans la couverture des trois vecteurs d'injection (body, query, header).

7. Dette technique

  • Token Sonar absent du Vault — ✅ RÉSOLU (2026-02-28) — Credentials présents dans Vault à kv/data/ci/sonarqube (login/password). URL corrigée dans Vault. Scripts de gouvernance mis à jour. probe-capabilities.sh confirme sonar: available.
  • Questions ouvertes non résolues (Q-01 FINALITY_DEPTH, Q-03 normalisation adresse, Q-04 format revokedBy) — impact: moyen — conformité numérique et audit trail hétérogène possibles en production.
  • Seed initial signer_registry non livré — impact: élevé — toute soumission bloquée fail-closed si le registre est vide au déploiement. Script de seed à prévoir.
  • Rôle SIGNER_ADMIN non provisionné dans Keycloak — impact: moyen — seul ADMIN peut révoquer tant que non configuré.
  • Spec T11 et TC-ERR-09 avec ambiguïté "refus OU ignore" — impact: faible — le code est déterministe (refus strict 400) mais la documentation n'est pas alignée.

8. Risques résiduels

Risque Type Probabilité Impact Mitigation
Registre signer_registry vide au déploiement → toute soumission bloquée ops élevé élevé Script de seed avec adresses wallet actives de production
FINALITY_DEPTH non configuré par environnement tech moyen moyen Valeur configurable via ConfigService, défaut conservateur 12
Collision d'adresses signer (casse EIP-55) tech faible moyen Normalisation EIP-55 dans SignerRegistryService
Token Sonar absent → Phase 1.5 contournée durablement ops élevé moyen Configurer kv/data/ci/sonar dans Vault

8bis. Matrice de délégation inter-PD

Story Direction Statut Nature de la dépendance Problème rencontré
PD-177 ← dépend de DONE AnchorBatch.signerAddress peuplé pour résolution signer RAS — champ disponible
PD-55 ← dépend de DONE finalizeBatch() existant avec verrou pessimiste et transitions d'état RAS — intégration fluide
PD-52 ← dépend de DONE ConfirmationTracker existant fournit les confirmations RAS — interface stable
PD-264 ← dépend de DONE Enum AnchorBatchStatus et constante VALID_ANCHOR_STATUS_TRANSITIONS RAS

8ter. Bugs de tests

Aucun bug de test rencontré.

8quater. Corrections post-Gate 8

Aucune correction post-Gate 8 nécessaire. Gate 8 GO en v1.

9. Patterns récurrents détectés

9.1 Patterns confirmés (déjà vus dans d'autres stories)

  • Guard de sécurité fail-closed obligatoire — aussi dans PD-238, PD-240, PD-250, PD-251, PD-277, PD-276 (7e occurrence)
  • Machine à états explicite avec transitions autorisées/interdites — aussi dans PD-82, PD-250, PD-264, PD-251, PD-277, PD-276 (7e occurrence)
  • timingSafeEqual / opérations atomiques DB pour comparaisons crypto — pattern réutilisé via verrou pessimiste SELECT ... FOR UPDATE pour la sérialisation signer
  • Stubs inter-PD acceptés en Gate 8 si documentés avec story destination — pattern validé (pas de stubs dans PD-275, dépendances déjà livrées)
  • Sonar Phase 1.5 indisponible — dérogation de fait — aussi dans PD-277, PD-276 (3e occurrence consécutive)
  • Format non contractualisé dans spec v1 bloque en Gate 3 — format revokedBy (Q-04), autorisation revoke, vecteurs anti-spoofing non explicités dans spec v1

9.2 Nouveaux patterns identifiés

  • Guard HTTP non pertinent pour flux BullMQ worker — le plan v1 a créé un guard NestJS HTTP (SignerActiveGuard) pour un flux exécuté depuis un worker BullMQ. Supprimé en Gate 5. À surveiller pour toute story avec flux worker.
  • Double fenêtre de vérification (pré-check + re-check transactionnel) — optimisation by design pour éviter le travail inutile quand la vérification transactionnelle est coûteuse. Pattern documenté dans FT4.
  • Convergence Gate 3 stagnante (delta=0.25) débloquée par correction tests — la correction de la spec seule ne suffit pas si les tests ne sont pas réalignés simultanément.

10. Améliorations du workflow

10.1 Améliorations des prompts/templates

Fichier Amélioration suggérée Priorité
templates/prompts/1 Specification.md Ajouter checklist obligatoire pour stories blockchain/anchor : liste des états machine complets dès la spec (pas de Q-02 en questions ouvertes) moyenne
templates/prompts/1 Specification.md Exiger la contractualisation des vecteurs d'injection (body, query, header) pour toute validation anti-spoofing moyenne
templates/prompts/4 Plan d'implémentation.md Vérifier que les composants de type Guard sont pertinents pour le flux d'exécution réel (HTTP vs BullMQ worker) haute

10.2 Améliorations des agents

Agent Amélioration suggérée Justification
config/agents step 4 Injecter un check "ce composant est-il appelé depuis un endpoint HTTP ou un worker ?" pour chaque guard/middleware Guard HTTP inutile pour BullMQ (C8 supprimé)

10.3 Améliorations du processus

  • Configurer le token Sonar dans Vault : 3e story consécutive avec Phase 1.5 contournée. Bloquer le workflow si non résolu avant la prochaine story.
  • Résoudre les questions ouvertes AVANT Gate 3 v2 : les Q-01 à Q-05 ont traversé tout le workflow sans résolution formelle. Le PO doit statuer avant la gate.
  • Corriger spec ET tests simultanément en boucle de correction Gate 3 : la correction de la spec seule sans réalignement des tests provoque une stagnation (delta=0.25).

11. Enseignements clés

  1. Vérifier la pertinence HTTP/worker des guards — un guard NestJS HTTP est inutile et introduit un risque TOCTOU quand le flux passe par un worker BullMQ. La décision de sérialisation doit être dans le service layer avec transaction.
  2. Les questions ouvertes de spec doivent être bloquantes — 5 Q- ouvertes ont traversé 10 étapes sans résolution formelle, créant de la dette documentaire persistante.
  3. La convergence Gate 3 nécessite l'alignement simultané spec+tests — corriger la spec sans réaligner les tests provoque une stagnation (delta faible) car le revieweur voit de nouveaux invariants sans tests correspondants.
  4. Le pattern double fenêtre (pré-check + re-check) est un optimum pour les flux worker — le pré-check fail-fast évite le travail inutile, le re-check transactionnel garantit la sécurité. Documenter explicitement comme pattern by design dans le plan.
  5. Gate 8 GO en v1 corrèle avec une Gate 5 exigeante — les corrections structurelles (suppression C8, BLK-01, MAJ-02) effectuées en Gate 5 ont produit un plan suffisamment robuste pour une clôture sans itération.

12. Métriques cumulatives (auto-calculées)

Métrique Cette story Moyenne projet Tendance
Temps total 4.3h 4.1h
Itérations gates 6 5.3
Écarts totaux 18 20.3
Score convergence moyen 9.125/10 8.53/10