PD-284 — Décomposition (Step 6a)
Stratégie de parallélisation
Mode : sequential — 15 composants fortement interdépendants (C2→C1, C3→C1, C4→C1+C2, C5→C1+C2+C4, C7→C3+C4+C5+C6, C8→C5+C6, C9→C5, C10→C1+C5, C14→C8+C9+C10+C5, C15→C14). La chaîne critique traverse 7 niveaux ; la parallélisation apporterait un speedup < 1.3x pour une complexité de merge significative.
Graphe de dépendances (DAG)
Level 0 : T1(C1), T13(C13) ← indépendants (types + telemetry)
Level 1 : T2(C2→C1), T3(C3→C1), T6(C6→C1), T12(C12→C1) ← dépendent de C1
Level 2 : T4(C4→C1,C2), T5(C5→C1,C2,C4) ← dépendent de C2
Level 3 : T7(C7→C3,C4,C5,C6), T8(C8→C5,C6) ← orchestration + bouton
Level 4 : T9(C9→C5), T10(C10→C1,C5), T11(C11→C1) ← UI cards + notifications
Level 5 : T14(C14→C8,C9,C10,C5), T15(C15→C14) ← écran + navigation
Level 6 : T16(Tests→all) ← tests unitaires + intégration
Manifest des tâches
Level 0 — Fondations (types + telemetry)
T1 — seal-types (C1)
- Agent : agent-developer
- Module : seal-types
- Contract : CC seal-types
- Fichiers :
src/types/seal.ts - Description : Types TypeScript : union littérale SealState (7 états), branded types SealId/DocumentId, types événements SSE, payloads, DegradationFlag, ExpertFields, SealConfig, FailureReason, TsaTimestamp, PositionInQueue. Regex de validation par champ (§5.6).
- Dépendances : aucune
- Branche :
feature/PD-284-t01-seal-types - Critères de done :
src/types/seal.ts créé - Union
SealState couvre exactement les 7 états §5.7 - Branded types
SealId, DocumentId non substituables à string - Compilation TypeScript sans erreur
T13 — seal-telemetry (C13)
- Agent : agent-developer
- Module : seal-telemetry
- Contract : CC seal-telemetry
- Fichiers :
src/seal/telemetry.ts - Description : Journalisation structurée
{ event_type, seal_id, timestamp, details }. Fonctions : logControlledError, logDeduplication, logSequenceGap, logTransitionRejected. Dédup loguée uniquement en mode debug. - Dépendances : aucune (types primitifs suffisants, couplage C1 ajouté au level 1 si nécessaire)
- Branche :
feature/PD-284-t13-seal-telemetry - Critères de done :
src/seal/telemetry.ts créé - 4 fonctions exportées (logControlledError, logDeduplication, logSequenceGap, logTransitionRejected)
- Aucun artefact sensible dans les logs
- Compilation TypeScript sans erreur
Level 1 — Modules dépendant de C1
T2 — seal-state-machine (C2)
- Agent : agent-developer
- Module : seal-state-machine
- Contract : CC seal-state-machine
- Fichiers :
src/seal/state-machine.ts - Description : Machine d'états monotone.
ALLOWED_TRANSITIONS en Record<SealState, readonly SealState[]> exhaustif. SEALED et FAILED_TIMEOUT terminaux (tableau vide). canTransition() et transition() avec log. Aucune transition retour. - Dépendances : T1 (C1 — SealState)
- Branche :
feature/PD-284-t02-state-machine - Critères de done :
src/seal/state-machine.ts créé ALLOWED_TRANSITIONS couvre les 7 états comme clé (exhaustiveness TS) - INV-284-06, INV-284-07, INV-284-08 couverts
- Transition invalide lève une erreur (pas d'acceptation silencieuse)
- Compilation TypeScript sans erreur
T3 — seal-sse-client (C3)
- Agent : agent-developer
- Module : seal-sse-client
- Contract : CC seal-sse-client
- Fichiers :
src/seal/sse-client.ts - Description : Client SSE fetch-based (ou wrapper CE-SSE-01 si HT-03 invalidée). Backoff exponentiel
delay = base × factor^attempt (1s/2s/4s). Failover polling 5s après 3 échecs. Plafond cumulé 30s. Tentative SSE parallèle à chaque cycle polling. Retour SSE → arrêt polling. - Dépendances : T1 (C1 — types événements)
- Branche :
feature/PD-284-t03-sse-client - Critères de done :
src/seal/sse-client.ts créé - Interface
SSEClient + SSEClientConfig exportées - Backoff exponentiel implémenté avec paramètres configurables
- INV-284-09 respecté (pas de badge offline sur échec SSE seul)
- Compilation TypeScript sans erreur
T6 — seal-api (C6)
- Agent : agent-developer
- Module : seal-api
- Contract : CC seal-api
- Fichiers :
src/seal/api-client.ts - Description : Client API :
postUrgentSeal({ document_id }) et getSealStatus(sealId). Validation Zod sur réponses. Timeout 30s. Aucun endpoint hors contrat (INV-284-13). - Dépendances : T1 (C1 — branded types, schemas)
- Branche :
feature/PD-284-t06-seal-api - Critères de done :
src/seal/api-client.ts créé - 2 fonctions exportées (
postUrgentSeal, getSealStatus) - Validation Zod sur chaque réponse
- INV-284-13 couvert (aucun endpoint additionnel)
- Compilation TypeScript sans erreur
T12 — seal-secure-storage (C12)
- Agent : agent-developer
- Module : seal-secure-storage
- Contract : CC seal-secure-storage
- Fichiers :
src/seal/secure-storage.ts - Description : Persistance
tsa_token_ref, clés SSE, tokens auth via expo-secure-store avec kSecAttrAccessibleWhenUnlockedThisDeviceOnly. Fonctions : storeSensitiveArtifact, getSensitiveArtifact, purgeSealArtifacts, purgeAllSealData, purgeStaleSealArtifacts. Purge à logout/deleteAccount/fermeture SSE. - Dépendances : T1 (C1 — types artefacts)
- Branche :
feature/PD-284-t12-secure-storage - Critères de done :
src/seal/secure-storage.ts créé - 5 fonctions exportées
- INV-284-10 couvert (artefacts sensibles en SecureStore uniquement)
- INV-284-11 couvert (artefacts publics NON stockés ici)
- Attribut iCloud restore désactivé
- Compilation TypeScript sans erreur
Level 2 — Event processor + Store
T4 — seal-event-processor (C4)
- Agent : agent-developer
- Module : seal-event-processor
- Contract : CC seal-event-processor
- Fichiers :
src/seal/event-processor.ts - Description : Cache FIFO ring buffer N=100 pour
event_id. Ordonnancement sequence_number avec fenêtre de grâce 200ms (performance.now()). Gap persistant → GET resync. Validation Zod payload par état (§5.12). Guard seal_id != actif. Transition validée via C2. - Dépendances : T1 (C1), T2 (C2 — canTransition)
- Branche :
feature/PD-284-t04-event-processor - Critères de done :
src/seal/event-processor.ts créé - Cache FIFO ring buffer (pas LRU, pas Set)
- Fenêtre grâce 200ms avec
performance.now() (pas Date.now()) - Validation Zod des champs obligatoires par état
- INV-284-06 couvert (transition interdite → rejet + toast)
- Compilation TypeScript sans erreur
T5 — seal-store (C5)
- Agent : agent-developer
- Module : seal-store
- Contract : CC seal-store
- Fichiers :
src/store/useSealStore.ts - Description : Zustand store : état scellement actif, progression,
degradationFlag brut serveur, mode transport (SSE/polling), artefacts publics en mémoire. Sélecteurs granulaires par champ (perf CA-284-14). Flag degradation_flag inconnu → none + telemetry silencieuse. - Dépendances : T1 (C1), T2 (C2 — SealStateMachine), T4 (C4 — EventProcessor)
- Branche :
feature/PD-284-t05-seal-store - Critères de done :
src/store/useSealStore.ts créé - INV-284-05 couvert (aucun calcul local de seuil dégradation)
- INV-284-11 couvert (artefacts publics en state, pas en SecureStore)
- Sélecteurs granulaires exportés (pas de sélecteur monolithique)
- Pas de persistance AsyncStorage
- Compilation TypeScript sans erreur
Level 3 — Orchestrateur + Bouton
T7 — seal-orchestrator (C7)
- Agent : agent-developer
- Module : seal-orchestrator
- Contract : CC seal-orchestrator
- Fichiers :
src/seal/orchestrator.ts - Description : Coordination flux A : POST → GET status → init store → SSE. Debounce 2s (SEC-02). Disable optimistic bouton. R-02 : GET échoue → toast + init RECEIVED + SSE. Notification terminale via C11. Cleanup SSE/polling à destruction.
purgeStaleSealArtifacts() au démarrage (learning PD-283/PD-262). - Dépendances : T3 (C3 — SSEClient), T4 (C4 — EventProcessor), T5 (C5 — SealStore), T6 (C6 — API)
- Branche :
feature/PD-284-t07-orchestrator - Critères de done :
src/seal/orchestrator.ts créé - CA-284-05 couvert (séquence POST→GET→SSE stricte)
- R-02 implémenté (fallback RECEIVED si GET échoue)
- Debounce 2s sur déclenchement
- Cleanup SSE/polling complet
- Compilation TypeScript sans erreur
- Agent : agent-developer
- Module : urgent-button
- Contract : CC urgent-button
- Fichiers :
src/components/seal/UrgentSealButton.tsx - Description : Bouton scellement urgent.
account_type = minor → return null (INV-284-02). != minor → bouton visible (INV-284-01). Disabled si quota <= 0 OU has_active_urgent_seal (INV-284-03). Tooltips contractuels exacts (INV-284-04). R-03 : has_active_urgent_seal absent → false + telemetry. Debounce onPress. - Dépendances : T5 (C5 — store pour état), T6 (C6 — API pour déclenchement)
- Branche :
feature/PD-284-t08-urgent-button - Critères de done :
src/components/seal/UrgentSealButton.tsx créé - INV-284-01 à INV-284-04 couverts
- Tooltip
Quota épuisé ce mois (texte exact) - Tooltip
Scellement urgent déjà en cours (texte exact) - Debounce 2s sur handler onPress
- Compilation TypeScript sans erreur
Level 4 — Composants UI
T9 — seal-progress-card (C9)
- Agent : agent-developer
- Module : seal-progress-card
- Contract : CC seal-progress-card
- Fichiers :
src/components/seal/SealProgressCard.tsx - Description : Carte de progression 5 étapes visuelles (Capture, TSA, Merkle, Blockchain, Scellé). Mapping §2.1b. Badges dégradation (
delayed → jaune, critical → rouge). Badge Hors ligne via NetInfo (INV-284-09). position_in_queue en QUEUED_PRIORITY. failure_reason overlay en FAILED_TIMEOUT. React.memo sur sous-composants. - Dépendances : T5 (C5 — store)
- Branche :
feature/PD-284-t09-progress-card - Critères de done :
src/components/seal/SealProgressCard.tsx créé - 5 étapes visuelles conformes au mapping §2.1b
- INV-284-05 couvert (badges = flags serveur, pas de calcul local)
- INV-284-09 couvert (badge offline = perte réseau seule)
React.memo sur sous-composants - Compilation TypeScript sans erreur
T10 — expert-panel (C10)
- Agent : agent-developer
- Module : expert-panel
- Contract : CC expert-panel
- Fichiers :
src/components/seal/ExpertPanel.tsx - Description : Panneau mode expert. Absent si
mode_expert=false (CA-284-15). Map EXPERT_FIELDS_BY_STATE : hash_document dès RECEIVED, tsa_token_ref dès TSA_SEALED (via C12.getSensitiveArtifact), merkle_root dès ANCHOR_PENDING, blockchain_tx_hash + proof_package_url à SEALED. Donnée invalide (regex §5.6) → champ masqué + toast 5s. Ajout mode_expert: boolean dans useSettingsStore. - Dépendances : T1 (C1 — types), T5 (C5 — store)
- Branche :
feature/PD-284-t10-expert-panel - Critères de done :
src/components/seal/ExpertPanel.tsx créé - CA-284-15 couvert (panneau absent si mode_expert=false)
- CA-284-16 couvert (champs progressifs par état)
- INV-284-11 couvert (artefacts publics non traités comme sensibles)
mode_expert ajouté dans useSettingsStore - Compilation TypeScript sans erreur
T11 — seal-notifications (C11)
- Agent : agent-developer
- Module : seal-notifications
- Contract : CC seal-notifications
- Fichiers :
src/seal/notifications.ts - Description :
sendSealNotification(type, sealId) et buildSealDeepLink(sealId). Notification succès à SEALED, échec à FAILED_TIMEOUT. Titre max 50 chars, body max 100 chars (troncature). Deep-link schéma interne probatiovault://seal/{uuid} (SEC-01 whitelist). - Dépendances : T1 (C1 — types)
- Branche :
feature/PD-284-t11-notifications - Critères de done :
src/seal/notifications.ts créé - INV-284-12 couvert (deep-link valide vers seal_id)
- Troncature titre/body respectée
- Validation whitelist schéma URL interne
- Compilation TypeScript sans erreur
Level 5 — Écran + Navigation
T14 — seal-detail-screen (C14)
- Agent : agent-developer
- Module : seal-detail-screen
- Contract : CC seal-detail-screen
- Fichiers :
src/screens/vault/SealDetailScreen.tsx - Description : Écran détail scellement intégrant C8 (UrgentSealButton), C9 (SealProgressCard), C10 (ExpertPanel). useEffect cleanup : arrêt SSE/polling + purge artefacts sensibles session. Navigation deep-link via route
seal/:id. - Dépendances : T8 (C8), T9 (C9), T10 (C10), T5 (C5)
- Branche :
feature/PD-284-t14-seal-detail-screen - Critères de done :
src/screens/vault/SealDetailScreen.tsx créé - Intégration C8, C9, C10 dans un layout cohérent
- useEffect cleanup complet (pas de memory leak SSE/polling)
- Route
seal/:id résolvable - Compilation TypeScript sans erreur
T15 — seal-navigation (C15)
- Agent : agent-developer
- Module : seal-navigation
- Contract : CC seal-navigation
- Fichiers :
src/navigation/seal-linking.ts - Description : Config linking Expo : route
seal/:id → SealDetailScreen avec paramètre sealId. Validation UUID du paramètre. SEC-01 : whitelist schéma URL interne (probatiovault://seal/{uuid}), rejet schémas externes. - Dépendances : T14 (C14 — SealDetailScreen)
- Branche :
feature/PD-284-t15-seal-navigation - Critères de done :
src/navigation/seal-linking.ts créé - Route
seal/:id résolue vers SealDetailScreen - Validation UUID sur paramètre sealId
- Whitelist schéma URL stricte
- Compilation TypeScript sans erreur
Level 6 — Tests
T16 — Suite de tests (tous TC-*)
- Agent : agent-qa-unit-integration
- Module : tous (C1-C15)
- Contract : tous les CC
- Fichiers :
src/types/__tests__/seal.test.ts src/seal/__tests__/state-machine.test.ts src/seal/__tests__/sse-client.test.ts src/seal/__tests__/event-processor.test.ts src/store/__tests__/useSealStore.test.ts src/seal/__tests__/api-client.test.ts src/seal/__tests__/orchestrator.test.ts src/components/seal/__tests__/UrgentSealButton.test.tsx src/components/seal/__tests__/SealProgressCard.test.tsx src/components/seal/__tests__/ExpertPanel.test.tsx src/seal/__tests__/notifications.test.ts src/seal/__tests__/secure-storage.test.ts src/seal/__tests__/telemetry.test.ts src/screens/vault/__tests__/SealDetailScreen.test.tsx src/navigation/__tests__/seal-linking.test.ts - Description : Tests unitaires + intégration couvrant tous les TC contractuels (TC-NOM-01 à TC-NOM-18, TC-ERR-01 à TC-ERR-09, TC-INV-09 à TC-INV-11, TC-NEG-01 à TC-NEG-10, TC-NR-01 à TC-NR-09). Couverture >= 80% lignes et branches.
- Dépendances : T1-T15 (toutes les tâches)
- Branche :
feature/PD-284-t16-tests - Critères de done :
- Tous les fichiers de test créés
- TC-NOM-01 à TC-NOM-18 implémentés avec
// TC-NOM-XX dans le nom ou commentaire - TC-ERR-01 à TC-ERR-09 implémentés
- TC-INV-09, TC-INV-10, TC-INV-11 implémentés
- TC-NEG-01 à TC-NEG-10 implémentés
- TC-NR-01 à TC-NR-09 implémentés
- Couverture >= 80% lignes et branches
- 0 erreur ESLint
npm test passe sans échec
Matrice de couverture composant → invariant
| Composant | Invariants couverts | TC principaux |
| C1 (seal-types) | INV-284-06 (types états) | TC-NOM-18 |
| C2 (state-machine) | INV-284-06, INV-284-07, INV-284-08 | TC-NOM-05, TC-ERR-04, TC-ERR-06 |
| C3 (sse-client) | INV-284-09 | TC-NOM-08, TC-NOM-09, TC-NR-03 |
| C4 (event-processor) | INV-284-06 | TC-NOM-16, TC-NOM-17, TC-ERR-03, TC-ERR-05, TC-ERR-09 |
| C5 (seal-store) | INV-284-05, INV-284-11 | TC-NOM-10, TC-INV-11 |
| C6 (seal-api) | INV-284-13 | TC-ERR-01, TC-ERR-02, TC-INV-10 |
| C7 (orchestrator) | CA-284-05 | TC-NOM-04, TC-NR-04 |
| C8 (urgent-button) | INV-284-01, INV-284-02, INV-284-03, INV-284-04 | TC-NOM-01, TC-NOM-02, TC-NOM-03, TC-NOM-15 |
| C9 (progress-card) | INV-284-05, INV-284-09 | TC-NOM-10, TC-NOM-14 |
| C10 (expert-panel) | INV-284-11, CA-284-15, CA-284-16 | TC-NOM-11, TC-NOM-12, TC-ERR-07 |
| C11 (notifications) | INV-284-12 | TC-NOM-06, TC-NOM-07, TC-ERR-08 |
| C12 (secure-storage) | INV-284-10, INV-284-11 | TC-INV-09 |
| C13 (telemetry) | — | TC-ERR-03, TC-ERR-04, TC-ERR-05 |
| C14 (detail-screen) | — | TC-NR-05, TC-NR-06 |
| C15 (navigation) | INV-284-12 (deep-link) | TC-NOM-06, TC-NOM-07 |
Parallelization
strategy: sequential
levels:
- level: 0
tasks: [1, 13]
agents: [agent-developer, agent-developer]
branches:
- "feature/PD-284-t01-seal-types"
- "feature/PD-284-t13-seal-telemetry"
- level: 1
tasks: [2, 3, 6, 12]
agents: [agent-developer, agent-developer, agent-developer, agent-developer]
branches:
- "feature/PD-284-t02-state-machine"
- "feature/PD-284-t03-sse-client"
- "feature/PD-284-t06-seal-api"
- "feature/PD-284-t12-secure-storage"
- level: 2
tasks: [4, 5]
agents: [agent-developer, agent-developer]
branches:
- "feature/PD-284-t04-event-processor"
- "feature/PD-284-t05-seal-store"
- level: 3
tasks: [7, 8]
agents: [agent-developer, agent-developer]
branches:
- "feature/PD-284-t07-orchestrator"
- "feature/PD-284-t08-urgent-button"
- level: 4
tasks: [9, 10, 11]
agents: [agent-developer, agent-developer, agent-developer]
branches:
- "feature/PD-284-t09-progress-card"
- "feature/PD-284-t10-expert-panel"
- "feature/PD-284-t11-notifications"
- level: 5
tasks: [14, 15]
agents: [agent-developer, agent-developer]
branches:
- "feature/PD-284-t14-seal-detail-screen"
- "feature/PD-284-t15-seal-navigation"
- level: 6
tasks: [16]
agents: [agent-qa-unit-integration]
branches:
- "feature/PD-284-t16-tests"
total_tasks: 16
total_components: 15
git_strategy: sequential_branch_per_task
Decision Trace
| Décision | Alternatives considérées | Justification |
| sequential vs by_level | by_level (parallélisation L0-L1) | 15 composants avec chaîne de dépendances longue (C1→C2→C4→C5→C7→C14→C15). Speedup parallèle < 1.3x pour complexité merge significative. Séquentiel recommandé par l'instruction. |
| Tests en level 6 séparé | Tests intégrés dans chaque tâche | Agent QA dédié pour cohérence inter-composants, couverture TC contractuels croisée, et matrice de couverture unifiée |
| C13 (telemetry) en L0 | C13 en L1 avec dépendance C1 | La telemetry utilise des types primitifs (string, object). Le couplage C1 est faible (seal_id: string dans les logs). Mise en L0 pour paralléliser avec C1. |
| C12 (secure-storage) en L1 | C12 en L4 avec les UI | C12 est un module utilitaire bas-niveau (SecureStore), pas un composant UI. Les composants UI (C10) et l'orchestrateur (C7) en dépendent — le placer tôt débloque la chaîne. |
| 1 branche par tâche | 1 branche par niveau | Tâches dans un même niveau touchent des fichiers distincts, isolation des merges, rollback granulaire |