Aller au contenu

PD-284 — Plan d'implémentation : Revue (Gate 5 v1)

1. Références

  • Spécification : PD-284-specification.md (v3)
  • Tests contractuels : PD-284-tests.md (v3)
  • Plan d'implémentation : PD-284-plan.md
  • Code contracts : PD-284-code-contracts.yaml
  • Specification Review (Gate 3 v2) : PD-284-specification-review.md
  • Date de revue : 2026-03-13
  • Reviewer : Claude (mode factuel, Gate 5 AMBIGUITY)

2. Constatations (écarts)

E-01 — Contradiction HT-03 vs code contract seal-sse-client : lib tierce à la fois mitigation et interdite

Champ Valeur
Type Hypothèse implicite
Référence Plan §8 HT-03 / CC seal-sse-client forbidden
Description HT-03 admet que Expo SDK 54 peut ne pas supporter fetch en mode streaming (pour SSE custom). La mitigation proposée est « nécessiterait une lib native tierce ». Or le code contract du module seal-sse-client interdit explicitement « Utiliser une lib EventSource tierce (implémentation fetch-based custom) ». Si HT-03 est invalidée, la seule mitigation documentée viole le contrat du module. Aucune alternative contractuellement autorisée n'est prévue.
Impact Plan non exécutable si l'hypothèse HT-03 est invalidée — impasse architecturale sans issue contractuelle.
Gravité MAJEUR

E-02 — Mapping 7 états → 5 étapes visuelles non documenté

Champ Valeur
Type Ambiguïté
Référence Plan §1 C9, CC seal-progress-card / Spec §5.7 (7 états)
Description Le plan et le code contract de seal-progress-card déclarent 5 étapes visuelles : « Capture, TSA, Merkle, Blockchain, Scellé ». La spec §5.7 définit 7 états (RECEIVED, QUEUED_PRIORITY, TSA_PENDING, TSA_SEALED, ANCHOR_PENDING, SEALED, FAILED_TIMEOUT). Le mapping états → étapes visuelles n'est documenté ni dans le plan, ni dans les code contracts, ni dans la spec. Exemples d'ambiguïtés : RECEIVED et QUEUED_PRIORITY correspondent-ils tous deux à « Capture » ? ANCHOR_PENDING correspond-il à « Merkle » ou « Blockchain » ? FAILED_TIMEOUT est-il une 6e étape visuelle ou un overlay sur l'étape courante ?
Impact L'implémenteur doit inventer le mapping état↔étape visuelle sans contrat — risque d'incohérence entre composants C2 et C9.
Gravité MAJEUR

E-03 — failure_reason (FAILED_TIMEOUT) : champ contractuel non exploité

Champ Valeur
Type Couverture manquante
Référence Spec §5.12 (payload FAILED_TIMEOUT) / Plan §1-§6
Description La spec §5.12 liste failure_reason comme champ obligatoire additionnel pour l'état FAILED_TIMEOUT. Le plan §6 mentionne « message de contact support » pour cet état terminal mais ne référence jamais failure_reason. Aucun composant (C9, C10, C14), aucun code contract, aucun mapping §3-§5 ne consomme ni n'affiche ce champ. Le code contract seal-types (C1) ne le liste pas dans ses interfaces.
Impact Donnée contractuelle obligatoire reçue et ignorée — l'utilisateur ne voit pas la raison d'échec fournie par le backend.
Gravité MAJEUR

E-04 — Absence de purge proactive (purgeStale) au démarrage

Champ Valeur
Type Risque sécu/conformité
Référence Plan §7 / CC seal-secure-storage / Learnings PD-283, PD-262
Description Le plan repose uniquement sur useEffect cleanup (unmount de SealDetailScreen, C14) et sur la purge à la déconnexion/suppression de compte pour supprimer les artefacts sensibles en SecureStore. Un crash app (OOM, kill signal, force-quit iOS) bypass le cleanup React et les hooks. Les artefacts sensibles (tsa_token_ref, clés session SSE) restent en SecureStore jusqu'au prochain logout explicite. Les learnings PD-283 et PD-262 imposent explicitement un mécanisme purgeStale() au démarrage du flux (pas seulement en cleanup) pour garantir le zero-residuel après crash. Aucun composant ni code contract ne prévoit cette purge proactive.
Impact Artefacts sensibles résiduels après crash app — violation potentielle de INV-284-10 et de la politique de purge §5.11.
Gravité MAJEUR

E-05 — Section « Contraintes techniques » absente du plan

Champ Valeur
Type Contrainte technique non documentée
Référence Plan (section absente) / Procédure Gate 5 axe 7
Description Le plan ne contient pas de section « Contraintes techniques » documentant : (a) Statut de PD-80 : dépendance principale, statut non déclaré (DONE / TODO / STUB). Le plan suppose que les endpoints POST /seals/urgent, GET /seals/{id}/status et le flux SSE existent, sans préciser s'ils sont implémentés ou stubbés. (b) Framework de test : ni Jest, ni Vitest, ni React Native Testing Library ne sont explicitement choisis. Le §12 mentionne des niveaux (Unit, Integration, Perf) sans framework. © Compatibilité ESM/CJS : l'implémentation SSE fetch-based custom peut dépendre de modules ESM-only (ReadableStream polyfill, etc.). Non documenté. (d) Variables CI : aucune variable d'environnement CI documentée pour les tests d'intégration avec mocks API.
Impact Risque de blocage CI (framework non compatible, ESM runner manquant) et de dépendance PD-80 non traçable.
Gravité MAJEUR

E-06 — TC-NOM-13 (P95 ≤ 100ms) exclu du CI — CA-284-14 non vérifiable en non-régression

Champ Valeur
Type Test irréalisable
Référence TC-NOM-13 / Plan §12 / CA-284-14
Description Le plan §12 exclut TC-NOM-13 du CI : « nécessite un iPhone 12+ physique. Exécution manuelle hors CI. Ticket de suivi : à créer post-Gate 8. » Le critère d'acceptation CA-284-14 (« Perf rendu événement→UI respecte P95 ≤ 100ms ») n'a donc aucune vérification automatisée. Toute régression de performance est silencieuse. Le « ticket de suivi » est un report sans engagement contractuel.
Impact CA-284-14 non vérifiable en non-régression automatisée. Dégradation perf invisible.
Gravité MAJEUR

E-07 — has_active_urgent_seal défaut false : fail-open sur hypothèse inter-story

Champ Valeur
Type Hypothèse implicite
Référence Plan §8 HT-06 / R-03 / Spec §5.6 / Gate 3 E-04
Description Le plan justifie le défaut false (fail-open) pour has_active_urgent_seal absent/invalide par l'idempotence de PD-80 sur POST /seals/urgent : « un second POST retourne le seal existant, pas de doublon ». Cette justification repose entièrement sur un comportement cross-story (PD-80) hors périmètre PD-284. L'idempotence de PD-80 n'est ni vérifiée ni contractualisée dans les documents d'entrée de PD-284. Gate 3 E-04 avait déjà signalé ce risque. Le plan le reconnaît (R-03) mais ne le mitige pas — il le déclare « acceptable ».
Impact Double déclenchement de scellement urgent si l'hypothèse d'idempotence PD-80 est fausse.
Gravité MAJEUR

E-08 — Contradiction interne : Set<number> vs ring buffer pour cache FIFO

Champ Valeur
Type Ambiguïté
Référence Plan §4 (CA-284-07) vs Plan §9 point 3 / CC seal-event-processor
Description Le mapping §4 pour CA-284-07 décrit le cache de déduplication comme « Cache FIFO Set<number> de taille N=100 ». Le §9 point 3 exige « un tableau circulaire (ring buffer) pour l'éviction FIFO » et interdit « Set avec delete aléatoire ». Le code contract seal-event-processor confirme « ring buffer, pas LRU ». Le plan propose deux structures de données mutuellement exclusives pour le même mécanisme. Un Set JavaScript n'a pas d'éviction FIFO native.
Impact L'implémenteur reçoit deux directives contradictoires — choix arbitraire nécessaire.
Gravité MINEUR

E-09 — position_in_queue : champ contractuel reçu sans exploitation

Champ Valeur
Type Couverture manquante
Référence Spec §5.12 (QUEUED_PRIORITY) / Plan §1-§5
Description La spec §5.12 liste position_in_queue comme champ obligatoire additionnel pour l'état QUEUED_PRIORITY. Aucun composant du plan (C9 carte, C10 expert, C5 store) ne mentionne ce champ. La validation Zod (C4/C6) le recevra mais aucun affichage ni stockage n'est prévu. Gate 3 E-09 avait signalé cette ambiguïté. Le plan ne la résout pas.
Impact Donnée contractuelle reçue et ignorée — l'utilisateur ne voit pas sa position dans la file d'attente.
Gravité MINEUR

E-10 — Flux lecture tsa_token_ref SecureStore → ExpertPanel non documenté

Champ Valeur
Type Code Contract — Cohérence
Référence CC expert-panel forbidden / CC seal-secure-storage
Description Le code contract C10 (expert-panel) interdit « Stocker tsa_token_ref en clair dans le state (doit être en SecureStore via C12) ». Le code contract C12 (seal-secure-storage) confirme que tsa_token_ref est en SecureStore uniquement. Mais C10 doit afficher ce champ en mode expert à l'état TSA_SEALED. Le mécanisme de lecture transitoire (SecureStore → affichage sans passage par le state Zustand) n'est documenté ni dans le plan ni dans les contrats. Aucune interface de C12 ne propose un getter pour l'affichage.
Impact L'implémenteur ne sait pas comment afficher un artefact sensible sans violer le contrat qui interdit de le mettre en state.
Gravité MINEUR

E-11 — tsa_timestamp non typé dans seal-types

Champ Valeur
Type Code Contract — Complétude
Référence Spec §5.12 (TSA_SEALED) / CC seal-types interfaces
Description La spec §5.12 liste tsa_timestamp comme champ obligatoire additionnel pour l'état TSA_SEALED. Le code contract seal-types (C1) ne le liste pas dans ses interfaces. Il n'apparaît ni dans les types, ni dans les schémas de validation Zod. Un événement TSA_SEALED conforme à la spec mais contenant tsa_timestamp pourrait être rejeté ou accepté sans validation.
Impact Champ contractuel non couvert par le typage ni la validation — lacune de complétude dans le modèle de types.
Gravité MINEUR

E-12 — degradation_flag inconnu : interprétation silencieuse non justifiée

Champ Valeur
Type Ambiguïté
Référence Spec §5.3 vs Spec §3 (définition erreur contrôlée) / Plan §6
Description La spec §5.3 dit qu'un degradation_flag inconnu est « traité comme none + trace telemetry ». Le plan §6 confirme : telemetry unknown_degradation_flag, pas de toast. Mais la définition d'erreur contrôlée (spec §3) inclut « toast non bloquant affiché 5 secondes ». Le plan fait le choix d'une trace silencieuse (pas de toast) pour un flag inconnu. Ce choix semble raisonnable mais n'est pas formellement justifié : un flag inconnu est-il une « erreur contrôlée » au sens §3, ou un cas normal traité de façon conservatrice ? Le plan ne tranche pas explicitement.
Impact Ambiguïté mineure sur le comportement UX — risque d'écart en implémentation.
Gravité MINEUR

E-13 — Préférence mode_expert : tâche implicite hors contrat

Champ Valeur
Type Tâches manquantes
Référence Plan §9 (dette technique) / CC expert-panel
Description Le plan §9 reconnaît que « La préférence mode_expert n'existe pas encore dans le store settings. À ajouter dans useAuthStore ou un nouveau useSettingsStore ». Mais aucun composant du plan (C1-C15), aucun code contract, aucun fichier autorisé ne couvre cette modification. C10 (ExpertPanel) dépend de cette préférence via son guard if (!modeExpert) return null. La tâche est reconnue mais non formalisée : pas de module, pas de contrat, pas de fichier.
Impact Tâche implicite hors périmètre contractuel — risque d'oubli en implémentation step 6b.
Gravité MINEUR

3. Synthèse

Récapitulatif par gravité

Gravité Nombre IDs
BLOQUANT 0
MAJEUR 7 E-01, E-02, E-03, E-04, E-05, E-06, E-07
MINEUR 6 E-08, E-09, E-10, E-11, E-12, E-13

Récapitulatif par type

Type d'écart Nombre IDs
Hypothèse implicite 2 E-01, E-07
Ambiguïté 3 E-02, E-08, E-12
Couverture manquante 3 E-03, E-09, E-11
Risque sécu/conformité 1 E-04
Contrainte technique non documentée 1 E-05
Test irréalisable 1 E-06
Code Contract — Cohérence 1 E-10
Tâches manquantes 1 E-13

Points critiques

  1. Impasse architecturale SSE (E-01) : La mitigation de HT-03 viole le code contract du même module. Si Expo SDK 54 ne supporte pas le streaming fetch, le plan est bloqué sans alternative contractuellement autorisée.

  2. Mapping états→étapes visuelles (E-02) : 7 états backend → 5 étapes visuelles, sans table de correspondance. Risque d'incohérence entre la state machine (C2) et l'affichage (C9).

  3. Sécurité post-crash (E-04) : Le pattern purgeStale() issu de PD-283/PD-262 n'est pas appliqué. Les artefacts sensibles survivent aux crashs app.

  4. Performance non vérifiable (E-06) : CA-284-14 (P95 ≤ 100ms) sans vérification automatisée — toute régression est invisible.

  5. Section contraintes techniques absente (E-05) : Ni le statut de PD-80, ni le framework de test, ni la compatibilité ESM/CJS ne sont documentés.


4. Verdict de la revue

  • Statut : ⚠️ Accepté avec réserves
  • Motif synthétique : Le plan est globalement conforme à la spec et couvre les 13 invariants et 17 critères d'acceptation. L'architecture en 15 composants est cohérente et les code contracts sont complets en périmètre. Cependant, 7 écarts MAJEUR nécessitent une correction avant implémentation : contradiction interne sur la stratégie SSE (E-01), mapping états→visuels absent (E-02), champ failure_reason non exploité (E-03), absence de purge proactive post-crash (E-04), section contraintes techniques manquante (E-05), test perf non automatisé (E-06), et hypothèse fail-open inter-story non mitigée (E-07). Aucun écart n'est bloquant — tous sont résolvables par ajouts documentaires ou ajustements de contrats sans refonte de l'architecture.