Aller au contenu

PD-284 — Confrontation Gate 8 (CLOSURE) — v1

Reviewer : claude -p (MODE FACTUEL) Date : 2026-03-13

Convergences (10)

  1. Machine d'états monotoneALLOWED_TRANSITIONS table exhaustive, pas de retour arrière
  2. Séquence POST→GET→SSE — Orchestrateur respecte la séquence contractuelle CA-284-05
  3. Branded types — SealId, DocumentId empêchent inversions UUID à la compilation
  4. Backoff/failover — SSE client avec backoff exponentiel 1s/2s/4s → failover polling
  5. Déduplication FIFO — Ring buffer avec éviction correcte, cache 100 entries
  6. Sécurité stockage — SecureStore + kSecAttrAccessibleWhenUnlockedThisDeviceOnly
  7. Validation Zod — Toute donnée entrante (API + SSE) validée avant consommation
  8. Badge hors ligne — TransportMode DISCONNECTED → badge visible dans ProgressCard
  9. Notifications terminales — SEALED/FAILED_TIMEOUT → push + deep-link
  10. Dégradation server-only — INV-284-05 respecté, pas de seuil local

Divergences (7)

ID Criticité Description Impact
DIV-01 MAJEUR Contradiction coverage UrgentSealButton : 100% dans jest vs "aucun test C8" dans review QA Artefact d'injection — le test urgent-button.test.tsx existe (199 lignes). La review QA n'avait pas les fichiers de test dans son contexte. Résolu par vérification.
DIV-02 MAJEUR merkle_proof[] non stocké dans le store Zustand, pas de mécanisme alternatif documenté L'ExpertPanel n'affiche pas merkle_proof (ligne merkle_proof: () => null dans FIELD_BUILDERS). Le proof est vérifiable via proof_package_url. Design intentionnel, pas un écart.
DIV-03 MINEUR Étape visuelle "Arbre Merkle" (index 2) jamais assignée dans STATE_TO_VISUAL_STEP L'état ANCHOR_PENDING est le seul à mapper sur cette étape. Si aucun event ANCHOR_PENDING n'est reçu (transition directe TSA_SEALED→SEALED), l'étape 2 est sautée visuellement. Acceptable — l'UI montre la progression réelle.
DIV-04 MINEUR resyncFromServer() contourne ALLOWED_TRANSITIONS sans exception dans la spec Le resync est un recalibrage forcé après détection de gap irréparable. La spec §5.14 prévoit le resync comme mécanisme de reprise. Le contournement est par design.
DIV-05 MINEUR Regex UUID /^[0-9a-fA-F-]{36}$/ accepte des formats invalides (36 tirets) Atténué par validation serveur PD-80. Le client sert de validation de confort.
DIV-06 MINEUR Store applyEvent ne re-valide pas les transitions (confiance en C4 EventProcessor) Architecture en couches : C4 valide les transitions, C5 (store) applique les events validés. Pas de double validation par design (séparation des responsabilités).
DIV-07 INFO 7 composants sur 15 sans livrable agent auditable Les composants non livrés par agent (orchestrator, SSE client, screen, deep-link, barrel exports) ont été implémentés directement par l'orchestrateur en Phase 6b/6c.

Zones d'ombre (7)

  1. Politique iOS hors foreground — Comportement SSE quand l'app passe en background non spécifié
  2. Quotas par planSEAL_QUOTAS_BY_PLAN hardcodé côté client, pas de sync serveur
  3. Heartbeat SSE — Pas de heartbeat côté serveur pour détecter connexion morte
  4. Purge au logout — Intégration de purgeSealArtifacts dans le flux de logout non documentée
  5. Timeout POST /seals/urgent — Pas de timeout explicite dans le fetch (config par défaut)
  6. Retry POST après 5xx — Pas de retry automatique côté client
  7. Locale TSA timestamp — Format d'affichage non spécifié (UTC vs local)

Recommandation

ACCEPTÉ AVEC RÉSERVES — Les 2 divergences MAJEUR (DIV-01, DIV-02) sont résolues/justifiées. Les 5 MINEUR sont atténués. Les zones d'ombre sont des points d'amélioration pour des stories futures, pas des écarts bloquants.