PD-284 — Agent Developer : seal-expert-panel (C10)
1. Module implemente
Fichier : src/components/seal/SealExpertPanel.tsx
Responsabilite : Panneau Mode expert affichant les artefacts cryptographiques probatoires (hash document, TSA token, merkle root, blockchain tx, proof package URL) aux jalons contractuels definis par EXPERT_FIELDS_BY_STATE. Masque completement si mode_expert=false.
2. Invariants couverts
| Invariant | Mecanisme | Fichier:ligne |
| INV-284-03 | Aucun seuil local — le panneau ne calcule aucune degradation, il affiche les champs disponibles par etat | SealExpertPanel.tsx:computeVisibleFields |
| INV-284-09 | tsa_token_ref fourni par le parent via prop tsaTokenRef (charge depuis SecureStore), JAMAIS lu depuis le Zustand store | SealExpertPanel.tsx:SealExpertPanelProps |
| INV-284-11 | Artefacts publics (hash, merkle_root, blockchain_tx_hash, proof_package_url) lus depuis le store memoire app — pas de persistance | SealExpertPanel.tsx via selecteurs granulaires |
3. Criteres d'acceptation couverts
| CA | Mecanisme | Observable |
| CA-284-11 | modeExpert=false => return null en premiere instruction — panneau absent de l'arbre UI | testID="seal-expert-panel" absent du DOM |
| CA-284-12 | computeVisibleFields() filtre par EXPERT_FIELDS_BY_STATE[currentState] — seuls les champs autorises au jalon courant sont rendus | Champs apparaissent progressivement : hash_document des RECEIVED, tsa_token_ref a TSA_SEALED, merkle_root a ANCHOR_PENDING, blockchain_tx_hash + proof_package_url a SEALED |
| CA-284-14 | 6 selecteurs granulaires (un par champ), React.memo sur ExpertFieldRow, useMemo sur derivations | Re-renders isoles par champ modifie |
4. Tests contractuels mappes
| Test ID | Couvert | Mecanisme |
| TC-NOM-12 | Oui | modeExpert=false => return null — panneau completement absent |
| TC-NOM-13 | Oui | computeVisibleFields() filtre par EXPERT_FIELDS_BY_STATE — apparition progressive des champs aux jalons contractuels |
| TC-ERR-03 | Oui | isValidHashDocument(), isValidMerkleRoot(), isValidBlockchainTxHash() — champ invalide masque, carte fonctionnelle, telemetry emise |
| TC-NEG-03 | Oui | SEAL_VALIDATION_PATTERNS.HASH_DOCUMENT rejette uppercase ou longueur != 64 — champ masque |
| TC-NEG-04 | Oui | SEAL_VALIDATION_PATTERNS.BLOCKCHAIN_TX_HASH rejette sans prefixe 0x — lien explorateur absent |
| TC-INV-09 | Oui | tsa_token_ref est un prop injecte depuis SecureStore par le parent — pas lu depuis le store Zustand |
| TC-NR-04 | Oui | Ordre d'apparition derive de EXPERT_FIELDS_BY_STATE (table importee de types/seal.ts) — deterministe |
5. Decisions architecturales
5.1 tsaTokenRef comme prop vs hook SecureStore interne
- Decision : Prop
tsaTokenRef: string | null fournie par le parent - Justification : INV-284-09 interdit le stockage en clair dans le store Zustand. Le parent (SealDetailScreen C14) charge la valeur depuis SecureStore (C12) et l'injecte via prop. Le panneau expert ne doit pas connaitre les mecanismes de stockage securise.
- Alternatives considerees : (1) Hook interne
useSecureStore("tsa_token_ref") — rejete car couple C10 a C12 et viole la separation des responsabilites. (2) Selecteur store specialise — rejete car INV-284-09 interdit le stockage dans le store. - Trade-offs : Le panneau ne peut pas afficher
tsa_token_ref si le parent ne le fournit pas. Acceptable car C14 est le seul consommateur.
5.2 merkle_proof non affiche dans le panneau
- Decision :
merkle_proof (tableau de hash) n'est pas affiche dans le panneau expert - Justification : Le tableau peut contenir N elements (profondeur de l'arbre Merkle). L'afficher en panneau compact n'apporte pas de valeur UX. La verification est faite via
proof_package_url (dossier de preuve telecharegable). - Alternatives considerees : Afficher le nombre d'elements — rejete car information non actionnable pour l'utilisateur.
- Trade-offs : Un utilisateur tres avance ne voit pas les hash individuels. Le dossier de preuve complet reste accessible.
6. Hypotheses
- H-DEV-01 : Le parent (C14) charge
tsa_token_ref depuis SecureStore (C12) et le fournit en prop uniquement quand l'etat courant l'autorise. Si le parent fournit null, le champ n'apparait pas. - H-DEV-02 : Le store (
useSealStore) est initialise avant le rendu du panneau. Si currentState === null, le panneau ne rend rien. - H-DEV-03 : Les traductions i18n pour le namespace
seal.expertPanel.* seront ajoutees dans les fichiers de locale. Les defaultValue servent de fallback FR. - H-DEV-04 :
logControlledError (importe de ../../seal/telemetry) est disponible pour tracer les champs invalides (TC-ERR-03, TC-NEG-03, TC-NEG-04).
7. Fichiers modifies
| Fichier | Action | Justification |
src/components/seal/SealExpertPanel.tsx | Cree | Composant C10 — panneau mode expert |
8. Dependances
| Composant | Direction | Nature |
| C1 (seal-types) | Import | EXPERT_FIELDS_BY_STATE, SEAL_VALIDATION_PATTERNS, types branded |
| C5 (seal-store) | Import | Selecteurs granulaires Zustand (hashDocument, merkleRoot, etc.) |
| C12 (SecureStore) | Indirect | tsaTokenRef injecte par le parent depuis C12 |
| C14 (seal-detail-screen) | Consommateur | Integre C10 et fournit modeExpert + tsaTokenRef |
9. Signalements
- Hors perimetre C10 : La preference utilisateur
mode_expert doit etre lue depuis les settings utilisateur (probable useUserSettings() hook). C14 est responsable de l'injection. - Hors perimetre C10 : Le chargement de
tsa_token_ref depuis SecureStore est la responsabilite de C12/C14. C10 ne fait que l'afficher si valide. - Limitation
merkle_proof : Le store ne stocke pas merkle_proof dans des selecteurs individuels (il est recu dans l'event mais pas persiste au meme niveau que les autres champs). Si un affichage futur est souhaite, un selecteur selectMerkleProof devra etre ajoute au store.