Aller au contenu

PD-282 — Retour d'experience (REX)

1. Resume executif

Metrique Valeur
Objectif initial ProofEnvelope auto-verifiable : scellement HSM global (PROOF-14) + materiel validation eIDAS/OCSP embarque (PROOF-05b)
Resultat obtenu Conforme apres corrections majeures (3 BLOQUANTS resolus entre Gate 8 v1 et v2)
Verdict final GO (9.125/10 — Gate 8 v2)
Tests contractuels 259/259 passes dans le module legal-pre (247 unitaires + 12 integration PD-282)
Complexite medium (5h actif, 8 iterations de gate — plus eleve que la moyenne pour une story medium)

2. Metriques de convergence

2.1 Temps et iterations

Etape Duree estimee Duree reelle Iterations Ecart
0 - Besoin 30 min 15 min 1 -50%
1 - Specification 2h 4 min 1 -97%
2 - Tests 1h 3 min 1 -95%
3 - Gate spec 1h 55 min 3 -8%
4 - Plan 1h 25 min 1 -58%
5 - Gate plan 1h 25 min 3 -58%
6 - Implementation 4h 1h 20 min 1 -67%
7 - Acceptabilite 2h 14 min 1 -88%
8 - Gate acceptabilite 1h 31 min 2 -48%
9 - REX 30 min 30 min 1 0%
TOTAL ~14h ~5h 14 -64%

Note : le wall clock total est ~13h (incluant ~7h d'attente validation PO etape 0 et ~1h20 entre Gate 8 GO et lancement REX). Le temps actif est ~5h. Le pipeline post-merge a necessite 3 commits correctifs supplementaires (migration DDL — voir section 8quater).

2.2 Scores de convergence par gate

Gate Score v1 Score v2 Score final (v3) Delta total Iterations
Gate 3 6.56/10 (NON_CONFORME) 7.25/10 (RESERVE) 8.25/10 (RESERVE STOP) +1.69 3
Gate 5 6.69/10 (NON_CONFORME) 7.50/10 (RESERVE) 7.875/10 (RESERVE STOP) +1.19 3
Gate 8 7.19/10 (NON_CONFORME) 9.125/10 (GO) +1.94 2

Convergence moyenne finale : (8.25 + 7.875 + 9.125) / 3 = 8.42/10

Detail des scores par critere :

Gate Critere v1 Final
Gate 3 completeness 6.75 8.0
Gate 3 testability 4.75 7.5
Gate 3 clarity 6.75 8.5
Gate 3 traceability 8.0 9.0
Gate 5 feasibility 6.0 8.0
Gate 5 coverage 5.5 7.5
Gate 5 risk_mitigation 6.75 8.5
Gate 5 coherence 8.5 7.5
Gate 8 conformity 4.0 9.0
Gate 8 test_coverage 8.75 8.75
Gate 8 security 7.0 8.75
Gate 8 maintainability 9.0 10.0

2.3 Ecarts par categorie

Categorie d'ecart Gate 3 Gate 5 Gate 8 Total
ECT (completude/testabilite) 2 2 2 6
DIV (divergence spec/impl) 1 1 2 4
AMB (ambiguite) 1 1 0 2
SEC (securite) 0 0 3 3
PERF (performance) 0 0 0 0
TOTAL ecarts 4 4 7 15

Les 3 ecarts BLOQUANTS de Gate 8 v1 etaient tous de categorie SEC (E-01 double-hash) ou DIV (E-02 structure JSONB, S-01 trust anchor bypass). Leur resolution complete a permis de passer a GO en une seule iteration supplementaire.

3. Points fluides

  • La decomposition en 4 modules (entity, seal, verification, verifier) a fourni une structure claire et parallelisable. Chaque agent avait des frontieres de responsabilite nettes.
  • Le pattern INSERT-only impose par le trigger PD-272 a ete correctement anticipe dans le plan (DA-02), evitant un refactoring majeur lors de l'implementation.
  • La correction Gate 8 v1 → v2 a ete particulierement efficace (+1.94 en 1 iteration) grace a des ecarts bien identifies et actionnables par les reviews croisees ChatGPT.
  • Les 259 tests contractuels ont ete ecrits et passaient des la v1 de Gate 8 — la couverture contractuelle etait solide malgre les ecarts crypto.
  • La reutilisation des services existants (HashService, HsmSignatureService, JsonCanonicalizeService) a accelere l'implementation sans duplication.
  • Le mecanisme de detection de secrets (INV-282-06) a ete implemente proprement via pattern matching sur une liste exhaustive de tokens interdits.

4. Points difficiles

  • Double-hash crypto (E-01) : le pipeline sign/verify etait incompatible — createVerify('SHA3-384') re-hash le buffer deja hashe, tandis que le HSM utilise CKM_ECDSA (raw sign). La resolution via crypto.verify(null, hash, key, sig) est non triviale et non documentee dans la plupart des guides Node.js/HSM. Cout estime : ~30 min de debug.
  • Structure JSONB imbriquee (E-02) : le wrapper SealedProofEnvelope etait stocke dans la colonne envelope_seal au lieu de EnvelopeSeal directement. La confusion des niveaux d'abstraction (objet de transport vs objet persistable) est un bug silencieux — les tests mockaient la DB et ne detectaient pas le desalignement.
  • Bypass trust anchor (S-01) : trustedRoots optionnel dans le verifier permettait la verification avec un certificat auto-signe. L'hypothese H-01 etait documentee dans la spec mais l'implementation ne l'enforc,ait pas.
  • Gates interleaving avec implementation : les Gates 3v3 et 5v3 ont ete relancees apres le debut de l'implementation (step 6), creant un flux non lineaire inhabituel. La correction de la spec pendant l'impl cree de la confusion sur la version de reference.
  • Triple NON_CONFORME en v1 : les 3 gates ont demarre en dessous du seuil GO (6.56, 6.69, 7.19), necessitant 8 iterations totales — pattern caracteristique d'une story a complexite conceptuelle elevee.
  • Pipeline post-merge migration : apres merge sur main, la migration PD-279/PD-278 a echoue (PostgreSQL erreur 55P04 — ALTER TYPE ... ADD VALUE et clause WHERE dans la meme transaction). Resolution en 3 commits avec le pattern commitTransaction/startTransaction pour separer les phases DDL. Non lie a PD-282 mais impactant le pipeline CI.

5. Hypotheses revelees tardivement

  • H-01 (trust-store verificateur) : l'hypothese etait documentee dans la spec (section 9) mais l'implementation ne la respectait pas (trustedRoots optionnel) — decouverte a l'etape 7 lors de la review securite ChatGPT.
  • Interoperabilite SHA3-384 sign(HSM)/verify(Node.js) : la compatibilite du pattern pre-hash + raw sign n'etait pas prouvee avant l'implementation. Identifiee comme risque dans le plan (§8 risque 2) mais materialisee en ecart BLOQUANT.
  • INV-282-03 perimetre trop large : la formulation couvrait potentiellement envelopeSeal alors que INV-282-02 l'exclut explicitement — ambiguite clarifiee en Gate 5 v3.
  • CKM_ECDSA vs CKM_ECDSA_SHA3_384 : le HSM CloudHSM ne supporte que le raw sign (CKM_ECDSA). L'hypothese sur le mode de signature HSM n'etait pas explicite dans la spec et a conditionne toute la resolution du double-hash.

6. Invariants complexes

  • INV-282-01/02/03 (integrite cryptographique) — TC-NOM-01/02. Le trio canonicalisation JCS + exclusion envelopeSeal + SHA3-384 + ECDSA P-384 forme une chaine ou chaque maillon doit etre byte-identical entre sign et verify. Le moindre desalignement (algorithme de hash, encodage DER/IEEE-P1363, niveau de canonicalisation) invalide toute la preuve.
  • INV-282-04 (verification offline Mode A) — TC-NOM-04. La suffisance du verificationMaterial pour Mode A depend de la completude des chaines de certificats ET de la presence obligatoire de trusted roots — deux dimensions testees independamment. Mode A est satisfait. Mode B reste une dette technique.
  • INV-282-07 (artefacts crypto temporaires) — TC-INV-07. Satisfait par conception (pipeline full-memory, cle privee dans HSM) mais non testable par assertions I/O classiques — preuve par audit statique du code. Acceptable.
  • INV-282-09/10 (SEALED terminal) — relies au trigger PD-272. L'etat SEALED est terminal par construction DB (pas d'UPDATE possible). La machine a etats en memoire est coherente avec la persistance.

7. Dette technique

Elementde dette Impact Priorite resolution
ocsp-client.service.ts : couverture 9.83% moyen Story dediee OCSP reelle
offline-verification.service.ts : couverture 43.43% moyen Story Mode B OCSP live
Mode B : verification OCSP live non constitutive (S-02) moyen Story dediee a creer
Parsing OCSP heuristique au lieu de @peculiar/asn1-ocsp (S-04) faible Lors de l'integration OCSP reelle
Assertions generiques (toBeDefined, toBeTruthy) dans certains tests (T-04) faible Refactoring tests opportuniste
12 tests CI pre-existants en echec (destruction-audit: schema permissions, pd275-concurrency: missing table) moyen Stories dediees per module

Note sur les echecs CI pre-existants : les 12 echecs CI identifie en post-merge sont independants de PD-282 et appartiennent a deux suites de tests pre-existantes (destruction-audit — permissions schema, pd275-concurrency — table manquante). Ils n'affectent pas les 259 tests du module legal-pre.

8. Risques residuels

Risque Type Probabilite Impact Mitigation
OCSP responders intermittents en production ops moyen moyen Policy OCSP_UNAVAILABLE + monitoring 10% seuil alerte
Mode B non constitutif (OCSP live manquant) tech eleve moyen Story dediee pour implementer verification OCSP live constitutive
SSRF via AIA certificate extensions sec faible eleve Allowlist URLs OCSP recommandee (S-03, non corrige)
Interop SHA3-384 sur CloudHSM reel non prouvee en production tech faible eleve Test d'interoperabilite CI requis sur environnement avec HSM reel (DA-03)
Echecs CI pre-existants masquant des regressions futures ops moyen moyen Correction prioritaire des 12 echecs pre-existants dans leurs stories respectives

8bis. Matrice de delegation inter-PD

Story Direction Statut Nature de la dependance Probleme rencontre
PD-272 depend de DONE Trigger immutabilite (UPDATE/DELETE refuses) RAS — le trigger couvre automatiquement la nouvelle colonne envelope_seal
PD-81 depend de DONE Token TSA dans ProofEnvelope RAS — tsaCertificateChain verifie le token existant
PD-280 depend de DONE Modele d'etats PENDING/INDETERMINATE RAS — pas de contradiction avec SEALED terminal
PD-37 depend de DONE JsonCanonicalizeService (RFC 8785) RAS — service reutilise tel quel
PD-279/PD-278 adjacent DONE Migration DDL partagee Erreur 55P04 PostgreSQL post-merge (ADD VALUE enum + WHERE clause meme transaction). Resolu en 3 commits.
Mode B OCSP live bloque TODO Verification en ligne constitutive Story dediee a creer pour implementer les requetes OCSP/CRL publics constitutives

8ter. Bugs de tests et corrections crypto

Pattern incorrect Pattern correct Cause Cout resolution
createVerify('SHA3-384').update(hash).verify(key, sig) crypto.verify(null, hash, key, sig) createVerify ajoute son propre hash au buffer deja hashe (double-hash) ~30 min
Stocker SealedProofEnvelope {envelopeSeal, verificationMaterial} dans colonne Stocker EnvelopeSeal directement Confusion wrapper de transport vs objet persistable ~20 min

8quater. Corrections post-Gate 8

Corrections Gate 8 v1 → v2 (3 BLOQUANTS)

Correction Fichier(s) Nature Gravite originale
Alignement crypto sign/verify via crypto.verify(null) (E-01) envelope-seal.service.ts, offline-verification.service.ts Fix pipeline crypto (elimination double-hash) BLOQUANT
Structure envelope_seal directe dans colonne JSONB (E-02) legal-composite-proof.service.ts Fix stockage JSONB (EnvelopeSeal direct, pas wrapper) BLOQUANT
trustedRoots obligatoire dans verify() (S-01) offline-verification.service.ts Fix bypass securite trust anchor BLOQUANT

Corrections pipeline post-merge (migration DDL)

Probleme Cause Resolution Commits
PostgreSQL erreur 55P04 (migration PD-279/PD-278) ALTER TYPE ADD VALUE et clause WHERE dans la meme transaction Pattern commitTransaction/startTransaction pour separer phases DDL enum 3 commits correctifs

Reserves restantes apres Gate 8 v2 (MAJEUR — non bloquantes)

ID Description Reference
DIV-04 Policy OCSP degradee incoh. (E-03) : GENERATION_TIME_SNAPSHOT avec ocspResponses=[] INV-282-05, ERR-05
DIV-07 Mode B verification OCSP live non constitutive (S-02) INV-282-04, §Mode B
DIV-09 SSRF via AIA certificate extensions (S-03) Defense-in-depth
DIV-08 Duplication verificationMaterial (E-05) Maintenabilite

9. Patterns recurrents detectes

9.1 Patterns confirmes (deja vus dans d'autres stories)

  • Double NON_CONFORME Gate 3+5 v1 = complexite conceptuelle elevee — aussi dans PD-280, PD-278. Confirme (3eme occurrence, pattern stable). Prevision fiable : 3+ iterations de gate et corrections structurelles requises.
  • Machine a etats explicite avec transitions interdites — SEALED terminal (INV-282-09/10). 11eme occurrence dans le projet.
  • Guard de securite fail-closed obligatoire — S-01 trust anchor bypass = absence de fail-closed. 11eme occurrence.
  • Format non contractualise dans spec v1 — testability 4.75 en Gate 3 v1 (regex/taille manquants pour envelopeSeal et verificationMaterial). 12eme occurrence.
  • Atomicite multi-composant : ACID sync + INSERT-only — pattern PD-272 trigger. 8eme occurrence.
  • Stubs inter-PD acceptes si documentes avec story destination — OCSP client stub, Mode B partiel. 11eme occurrence.
  • Faux positifs LLM en reviews — reviews securite signalant des INV dependant de PD-272 externe. 9eme occurrence.
  • Migration DDL + enum dans meme transaction = erreur PostgreSQL 55P04 — aussi dans PD-279/PD-278. 2eme occurrence. Pattern : separer toujours ALTER TYPE ADD VALUE dans une transaction distincte.

9.2 Nouveaux patterns identifies

  • Double-hash crypto pipeline (pre-hash + HSM raw sign)createVerify('ALG') de Node.js ajoute toujours un hash sur les donnees passees. Incompatible avec un HSM qui fait du CKM_ECDSA (raw sign sur hash pre-calcule). Solution : crypto.verify(null, hash, key, sig) qui bypass le hachage interne. A documenter comme invariant pour toutes les futures stories HSM.
  • Structure JSONB imbriquee (wrapper vs objet direct) — confondre le wrapper de transport (SealedProofEnvelope) avec l'objet a persister (EnvelopeSeal) cause un bug de lecture silencieux depuis la DB. Les tests avec mocks ne le detectent pas.
  • SSRF via AIA certificate extensions — les URLs de responders OCSP extraites des extensions AIA des certificats ne sont pas fiables. Tout appel HTTP vers ces URLs sans allowlist/denylist est un vecteur SSRF.
  • Gate 8 delta massif apres corrections BLOQUANTES multiples — corriger 3 ecarts BLOQUANTS en une iteration fait passer le score de 7.19 a 9.125 (+1.94). Les ecarts BLOQUANTS bien identifies et actionnables permettent une convergence rapide.
  • Spec corrigee pendant l'implementation = flux non lineaire — les Gates 3v3 et 5v3 ont ete relancees apres debut de step 6. Anti-pattern a eviter : terminer toutes les gates avant de demarrer l'implementation.

10. Ameliorations du workflow

10.1 Ameliorations des prompts/templates

Fichier Amelioration suggeree Priorite
templates/prompts/1 Specification.md Exiger la documentation explicite du pipeline sign ET verify (avec algorithme de hash, encodage, API Node.js) pour toute story avec signature HSM haute
templates/prompts/7c Review Security.md Verifier que le parametre trust-store (ou equivalent) est obligatoire dans tout service de verification de certificats — parametre optionnel = bypass possible haute
templates/prompts/7a Review Code.md Detecter l'usage de createVerify(ALG).update(hash) quand le HSM fait du raw sign — pattern double-hash systematique haute
templates/prompts/4 Plan implementation.md Pour les stories avec OCSP/CRL : contractualiser Mode A (offline) vs Mode B (online constitutif) avec les APIs concretes des la spec moyenne
templates/prompts/7c Review Security.md Verifier les URLs cibles des requetes OCSP : origin depuis les extensions AIA du certificat => SSRF potentiel, allowlist requise moyenne
templates/prompts/6b Agent task.md Pour les colonnes JSONB complexes : exiger un test de round-trip DB (INSERT + SELECT + assert structure) dans le contrat de l'agent-entity moyenne

10.2 Ameliorations des agents

Agent Amelioration suggeree Justification
config/agents step 6 (seal + verifier) Ajouter un check d'interoperabilite sign/verify HSM comme prerequis avant merge : signer avec l'HSM mock, verifier avec crypto.verify(null), asserter valid=true E-01 non detecte par les tests car mocks HSM ne valident pas la semantique de signature
config/agents step 1 Pour stories crypto-eIDAS : exiger la section "pipeline cryptographique" avec algorithme exact, encodage (DER/IEEE-P1363), API Node.js cible Pipeline incomplet = BLOQUANT systematique en Gate 8
config/agents step 6 (entity) Exiger un test round-trip DB pour chaque nouvelle colonne JSONB contenant des objets structures Detecte le bug wrapper vs objet direct avant Gate 8

10.3 Ameliorations du processus

  • Ne pas demarrer step 6 avant que Gates 3 et 5 soient terminales : le flux non lineaire (gates relancees pendant l'impl) cree de la confusion sur la version de reference de la spec et du rework. Le gain de temps illusoire est annule par les corrections.
  • Pour stories crypto : test d'interoperabilite sign/verify en CI avec HSM reel : les mocks HSM ne detectent pas les incompatibilites crypto reelles (double-hash, dsaEncoding, CKM algorithm).
  • Test round-trip DB pour toute colonne JSONB complexe : ajouter un test d'integration (INSERT + SELECT + asserter la structure attendue) avant soumission a Gate 8.
  • Pattern commitTransaction/startTransaction pour migrations DDL avec enum : documenter ce pattern dans les templates de migration pour eviter les erreurs PostgreSQL 55P04. ALTER TYPE ADD VALUE doit toujours etre dans une transaction separee.
  • Tracer les echecs CI pre-existants : maintenir un registre des tests CI en echec pre-existants par module pour ne pas les confondre avec des regressions introductes par la story en cours.

11. Enseignements cles

  1. crypto.verify(null) pour raw ECDSA matching CKM_ECDSAcreateVerify('SHA3-384').update(hash) applique SHA3-384 sur le buffer, produisant un double-hash quand le buffer est deja un hash SHA3-384. Pour un HSM qui signe en raw (CKM_ECDSA sans hachage interne), utiliser crypto.verify(null, hash, { key, dsaEncoding: 'ieee-p1363' }, signature) qui transmet le hash directement sans re-hashage. Ce pattern est distinct de createVerify et non-intuitif sans connaissance du fonctionnement interne de Node.js crypto.

  2. Stocker l'objet direct, pas le wrapper — une colonne JSONB doit contenir exactement l'objet attendu a la lecture (EnvelopeSeal), pas un wrapper de transport (SealedProofEnvelope {envelopeSeal, verificationMaterial}). La confusion entre objet de transport et objet persistable est un bug silencieux : les tests avec mocks DB ne le detectent pas car ils retournent le mock directement, pas une deserialisation JSON.

  3. trustedRoots optionnel = bypass silencieux — tout service de verification de certificats doit exiger un trust-store non vide et echouer explicitement si absent (raison: no_trusted_roots). Un parametre optionnel permet la verification avec des certificats auto-signes, annulant toute garantie d'ancrage de confiance.

  4. Triple NON_CONFORME v1 = indicateur fiable de complexite elevee — quand les 3 gates demarrent en NON_CONFORME (aucun GO ni RESERVE en v1), prevoir 8+ iterations totales et des corrections structurelles (pas incrementales). Ce pattern est maintenant confirme sur 3 stories (PD-280, PD-278, PD-282).

  5. Terminer les gates avant l'implementation — relancer des gates pendant l'implementation cree un flux non lineaire, du rework et de la confusion sur la version de reference de la spec. La tentation d'avancer en parallele nuit a la qualite globale du workflow.

  6. ALTER TYPE ADD VALUE PostgreSQL dans sa propre transaction — combiner ALTER TYPE ... ADD VALUE (enum extension) avec des clauses WHERE utilisant la nouvelle valeur dans la meme transaction provoque l'erreur PostgreSQL 55P04. Le pattern correct : commitTransaction() apres le ALTER TYPE, puis startTransaction() pour les operations suivantes. Documenter dans les templates de migration TypeORM.

12. Metriques cumulatives (auto-calculees)

Calculs bases sur les 9 stories mesurees avec donnees completes (PD-251, PD-277, PD-276, PD-275, PD-281, PD-279, PD-280, PD-278, PD-282) :

Metrique Cette story (PD-282) Moyenne du panel (9 stories) Tendance
Temps total (actif) 5.0h 6.3h inferieur a la moyenne
Iterations gates (G3+G5+G8) 8 5.4 superieur a la moyenne
Ecarts totaux detectes 15 19.0 inferieur a la moyenne
Score convergence Gate 3 8.25/10 8.44/10 dans la norme
Score convergence Gate 5 7.88/10 8.37/10 en dessous de la norme
Score convergence Gate 8 9.13/10 8.78/10 superieur a la norme
Score convergence moyen 8.42/10 8.53/10 dans la norme