PD-283 — Retour d'expérience (REX)¶
1. Résumé exécutif¶
| Métrique | Valeur |
|---|---|
| Objectif initial | Assemblage local Zero-Knowledge du dossier probatoire .pvproof (iOS) |
| Résultat obtenu | Conforme avec réserves — 13/13 invariants couverts, 1 MAJEUR résiduel (URL refresh) |
| Verdict final | RESERVE |
| Tests contractuels | 191/191 passés (11 suites, coverage 77.18%) |
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 | 20 min | 1 | -33% |
| 1 - Spécification | 2h | 15 min | 1 | -88% |
| 2 - Tests | 1h | 10 min | 1 | -83% |
| 3 - Gate spec | 1h | 40 min | 2 | -33% |
| 4 - Plan | 1h | 30 min | 1 | -50% |
| 5 - Gate plan | 1h | 15 min | 1 | -75% |
| 6 - Implémentation | 4h | 3h30 | 1 | -13% |
| 7 - Acceptabilité | 2h | 1h | 1 | -50% |
| 8 - Gate acceptabilité | 1h | 30 min | 1 | -50% |
| 9 - REX | 30 min | 30 min | 1 | 0% |
| TOTAL | ~14h | ~7.5h | 11 | -46% |
2.2 Scores de convergence par gate¶
| Gate | Score v1 | Score final | Delta | Itérations |
|---|---|---|---|---|
| Gate 3 | 7.1/10 | 8.5/10 | +1.4 | 2 |
| Gate 5 | 8.7/10 | 8.7/10 | 0 | 1 |
| Gate 8 | 7.5/10 | 7.5/10 | 0 | 1 |
2.3 Écarts par catégorie¶
| Catégorie d'écart | Gate 3 | Gate 5 | Gate 8 | Total |
|---|---|---|---|---|
| ECT (complétude/testabilité) | 5 | 1 | 4 | 10 |
| DIV (divergence spec/impl) | - | - | 3 | 3 |
| AMB (ambiguïté) | 7 | 1 | - | 8 |
| SEC (sécurité) | 3 | - | 3 | 6 |
| PERF (performance) | - | - | - | 0 |
| TOTAL écarts | 15 | 2 | 10 | 27 |
3. Points fluides¶
Ce qui a bien fonctionné : - Gate 5 GO en v1 : Le plan d'implémentation était suffisamment détaillé dès la première soumission (11 composants, mappings complets INV→mécanismes et CA→mécanismes). Les corrections Gate 3 (machine à états clarifiée, gardes explicites) ont directement bénéficié au plan. - Couverture invariants complète : 13/13 invariants couverts à la livraison, dont les invariants crypto sensibles (INV-283-11 kmaster isolation, INV-283-13 zeroization). - Correction rapide Gate 8 : Les 2 MAJEURs sécurité (S-01 purgeStale, S-03 integrityHash) ont été corrigés dans le même commit (a6fc531) avant la confrontation finale. - Volume de tests conséquent : 191 tests sur 11 suites pour 11 composants — ratio test/composant élevé. - Spécification enrichie par les learnings PD-276/PD-262 : L'injection proactive au step 0 a évité les erreurs récurrentes sur machine à états et validation Zero-Knowledge.
4. Points difficiles¶
Obstacles rencontrés (sans justification) : - Gate 3 NON_CONFORME v1 (score 7.1) : 3 bloquants sur la machine à états (DELETED terminal vs retour IDLE, garde purge_ok absente, notification sans fallback). 8 majeurs additionnels sur la formalisation (tolérance 24h, exportId8, collision noms). - Coverage 77% sous l'objectif 80% : Les composants pvproof-assembler.ts (14%) et streaming-hasher.ts (17%) dépendent d'I/O natif (fflate ZIP, expo-file-system) difficilement mockable. - URL refresh automatique non implémenté (F-03/CA-03) : L'orchestrateur propage URL_EXPIRED comme erreur terminale au lieu d'un refresh automatique — limitation v1 documentée. - Passthrough sémantique vs byte-level : manifest/chronology sont parsés par Zod puis re-sérialisés — le passthrough n'est pas byte-identical (ordre des clés JSON non garanti).
5. Hypothèses révélées tardivement¶
Hypothèses non explicites découvertes en cours de workflow : - HT-02 (ZIP streaming en React Native) — découverte à l'étape 6 : Aucune lib ZIP mature en React Native ne garantit l'insertion séquentielle sans buffer RAM. Solution via fflate (streaming mode avec callback), validée par spike. - Disambiguation 403 FREE vs 403 URL — découverte à l'étape 5 : Le même code HTTP 403 a deux significations distinctes (plan FREE = pas de champ exportId vs URL expirée = contexte download). Nécessitait clarification dans le plan. - pvproof.json écrit avant la boucle de téléchargement — découverte à l'étape 4 : Les métadonnées du pvproof.json sont connues dès l'appel API, ce qui permet de l'écrire en premier (INV-283-08) avant le téléchargement des preuves.
6. Invariants complexes¶
Invariants difficiles à implémenter ou sensibles aux régressions : - INV-283-02 (streaming disque, 1 clair en mémoire max) — TC-INV-02 : Requiert une coordination fine entre CryptoDecryptPipeline (fichier disque) et PvproofAssembler (insertion séquentielle). Le choix de fflate vs lib ZIP classique (jszip, qui bufferise tout) était critique. - INV-283-08 (pvproof.json première entrée STORED) — TC-INV-08 : Dépend de l'ordre d'insertion dans la lib ZIP. Certaines libs trient par nom ou chemin — vérification explicite du central directory nécessaire. - INV-283-01 + INV-283-05 (aucun clair résiduel + suppression immédiate) — TC-INV-01, TC-INV-05 : Le registre TempFileManager doit survivre aux crashes (persistance AsyncStorage) pour la purge au redémarrage. - INV-283-11 (K_doc uniquement, jamais kmaster) — TC-INV-11 : Nécessite une discipline stricte dans CryptoDecryptPipeline — un raccourci développeur decrypt(kmaster, payload) est une violation silencieuse sans test contractuel dédié.
7. Dette technique¶
Compromis acceptés et non bloquants : - URL refresh automatique (F-03/CA-03) non implémenté — impact: moyen. L'utilisateur doit relancer manuellement l'export si une URL expire. STUB: PD-XXX. - Coverage 77% vs 80% — impact: faible. Les 2 fichiers à faible couverture (pvproof-assembler 14%, streaming-hasher 17%) dépendent d'I/O natif. La couverture effective hors I/O est >85%. - Passthrough sémantique (JSON re-sérialisé) — impact: faible. Acceptable car JSON ne garantit pas l'ordre des clés. Le contenu est préservé intégralement. - Zeroization strings JS immutables — impact: faible. Limitation connue du runtime JS (strings GC-managed). Documentée dans plan §9.5. - Sonar Quality Gate non exécuté — impact: faible. Substitution ESLint sonarjs plugin (0 erreurs).
8. Risques résiduels¶
| Risque | Type | Probabilité | Impact | Mitigation |
|---|---|---|---|---|
| URL expire pendant export lent (>30 min) | tech | moyen | moyen | STUB URL refresh auto (PD-XXX) |
| Crash mid-export perd fichiers temp | tech | faible | moyen | purgeStale() au démarrage + registre AsyncStorage |
| Lib fflate incompatible future Hermes | tech | faible | élevé | Fallback module natif iOS (ZIPFoundation) documenté |
| Espace disque insuffisant non détecté | ops | faible | moyen | Check getFreeDiskStorageAsync + marge ×1.5 |
| Passthrough sémantique invalide un artefact probatoire | métier | très faible | élevé | Monitoring post-déploiement SHA3-256 source vs archive |
8bis. Matrice de délégation inter-PD¶
| Story | Direction | Statut | Nature de la dépendance | Problème rencontré |
|---|---|---|---|---|
| PD-85 | ← dépend de | DONE | API POST /exports/complaint-file fournit les artefacts | API mockée, intégration E2E post-staging |
| PD-34 | ← dépend de | DONE | Module crypto keys.ts (deriveKDocFromMaster) | RAS — module stable |
| PD-242 | ← dépend de | DONE | Enveloppes recovery fournies par backend | Passthrough strict, pas de parsing |
| PD-282 | ← dépend de | DONE | ProofEnvelope seal eIDAS | Passthrough strict |
| PD-XXX | → bloque | TODO | URL refresh automatique (F-03/CA-03) | Feature non implémentée v1 |
8ter. Bugs de tests¶
Aucun bug de pattern de test rencontré.
8quater. Corrections post-Gate 8¶
| Correction | Fichier | Nature | Pipeline |
|---|---|---|---|
| purgeStale() ajouté au début de startExport() | orchestrator.ts | Fix sécurité (INV-283-05) | a6fc531 |
| Vérification integrityHash après téléchargement | orchestrator.ts | Fix sécurité (S-03) | a6fc531 |
| Typo SHA-256 → SHA3-256 dans acceptability | PD-283-acceptability.md | Fix doc | a6fc531 |
9. Patterns récurrents détectés¶
9.1 Patterns confirmés (déjà vus dans d'autres stories)¶
- Machine à états explicite avec transitions autorisées/interdites — aussi dans PD-82, PD-250, PD-264, PD-262, PD-265, etc. (21ème occurrence). PD-283 ajoute les gardes conditionnelles (purge_ok) et les transitions retour explicites (DELETED → IDLE).
- Faux positifs LLM systématiques en reviews — aussi dans PD-262, PD-85, PD-251, etc. (21ème occurrence). 2/6 écarts code review étaient des faux positifs (E-01 streaming fflate, E-02 Data Protection iOS).
- Stubs inter-PD acceptés si documentés — aussi dans PD-85, PD-262, PD-72, etc. (17ème occurrence). URL refresh tracé comme STUB: PD-XXX avec gate 8 RESERVE.
- Format non contractualisé bloque en Gate 3 — aussi dans PD-262, PD-277, PD-276, etc. (22ème occurrence). exportId8, collision noms, tolérance 24h non formalisés en v1.
- Sonar Phase 1.5 indisponible — aussi dans PD-262, PD-85, PD-72, etc. (12ème occurrence). Substitution ESLint sonarjs.
- Gate 3 NON_CONFORME v1 suivi de rebond qualité — aussi dans PD-72, PD-275, PD-280. Score +1.4 entre v1 et v2 (7.1 → 8.5).
9.2 Nouveaux patterns identifiés¶
- Passthrough sémantique vs byte-level pour artefacts probatoires — JSON re-sérialisé après parsing Zod n'est pas byte-identical. Pour des artefacts à valeur probatoire, la spec devrait contractualiser le niveau de passthrough (byte/sémantique).
- Coverage sous seuil par dépendance I/O natif React Native — pvproof-assembler (fflate) et streaming-hasher (expo-file-system) difficiles à mocker. Pattern similaire à PD-262 (DEV gating) mais cause différente (I/O lib vs build flag).
- Spike obligatoire pour lib ZIP streaming mobile — Le plan identifiait un risque critique (§9.1) qui s'est confirmé. Le spike précoce a évité un blocage tardif à l'implémentation.
10. Améliorations du workflow¶
10.1 Améliorations des prompts/templates¶
| Fichier | Amélioration suggérée | Priorité |
|---|---|---|
templates/prompts/1 Specification.md | Exiger la contractualisation du niveau de passthrough (byte vs sémantique) pour les artefacts à valeur probatoire | haute |
templates/prompts/1 Specification.md | Pour stories mobile avec crypto, exiger la contractualisation des limitations zeroization JS dès la spec | moyenne |
templates/prompts/7a Review Code.md | Injecter les contraintes fflate/expo-file-system pour éviter faux positifs sur streaming mobile | moyenne |
templates/prompts/4 Plan d'implémentation.md | Rendre obligatoire la section "Spike obligatoire" quand une hypothèse technique est identifiée à risque critique | haute |
10.2 Améliorations des agents¶
| Agent | Amélioration suggérée | Justification |
|---|---|---|
config/agents step 6 | Pour stories app avec assemblage fichier, injecter les contraintes I/O React Native (pas de writable stream, expo-file-system limitations) | Faux positif E-01 évitable |
config/agents step 7 | Injecter la stack React Native + Hermes + fflate pour les reviews code/tests mobile | 2 faux positifs sur 6 écarts code review |
10.3 Améliorations du processus¶
- Spike validation lib tier avant step 6 : Quand le plan identifie un risque critique sur une dépendance externe (HT-01, HT-02), exécuter le spike comme sous-étape 5.5 (entre Gate 5 GO et step 6). Évite la découverte tardive.
- Contractualisation passthrough dès step 0 : Pour toute story manipulant des artefacts probatoires, le PO doit trancher entre passthrough byte-level (copie binaire) et passthrough sémantique (re-sérialisation autorisée).
11. Enseignements clés¶
-
Spike précoce sur dépendances critiques — L'identification du risque ZIP streaming (plan §9.1) et la résolution via fflate avant l'implémentation ont évité un blocage potentiel de plusieurs heures. Toute hypothèse technique marquée "risque critique" devrait déclencher un spike avant step 6.
-
Machine à états : transitions retour et gardes conditionnelles — Les machines à états avec transitions retour (DELETED → IDLE, FAILED → PREPARING) nécessitent des gardes conditionnelles (purge_ok) pour éviter les cycles non sécurisés. Contractualiser les gardes dès la spec, pas au plan.
-
Passthrough byte-level vs sémantique est une décision architecturale — Pour des artefacts à valeur probatoire (manifest, chronology, enveloppes), la différence entre copie binaire et re-sérialisation JSON a des implications légales. Cette décision doit être prise par le PO au step 0.
-
Coverage mobile = coverage effective hors I/O natif — Les composants dépendant de libs I/O natives (fflate, expo-file-system) ont une couverture structurellement basse en test unitaire. La métrique pertinente est la couverture effective sur la logique métier testable.
-
Gate 3 enrichit toute la chaîne — Les 11 corrections de Gate 3 v1→v2 (machine à états, gardes, formats, fallbacks) ont directement bénéficié aux étapes suivantes : Gate 5 GO en v1, plan sans ambiguïté, implémentation alignée.
12. Métriques cumulatives (auto-calculées)¶
| Métrique | Cette story | Moyenne projet | Tendance |
|---|---|---|---|
| Temps total | 7.5h | 6.34h | ↑ |
| Itérations gates | 4 | 5.4 | ↓ |
| Écarts totaux | 27 | 23.8 | ↑ |
| Score convergence moyen | 8.23/10 | 8.46/10 | ↓ |