Aller au contenu

PD-298 — Review de spécification

Auditeur : technique indépendant — contractualisation, testabilité, conformité. Documents audités : - PD-298-specification.md - PD-298-tests.md (audit limité : ambiguïtés, contradictions, règles non testables a priori, hypothèses dangereuses, risques sécurité/conformité — sans conclure sur la couverture).


1. Ambiguïtés

A-01 — Regex D-287-03 non fournie mais contractualisée comme référence

  • Type : Ambiguïté
  • Référence : spec §5.1 (recipientEmail, eventRecipientEmail), spec §10.2 PC-298-01, spec H-298-01, tests TC-NOM-02 / TC-ERR-01 / TC-NEG-03 / §9 NON TESTABLE
  • Description : La colonne « Regex / Validation » de recipientEmail indique Regex exacte D-287-03 requise (non fournie ici). L'invariant INV-298-01, le critère CA-298-02 et plusieurs tests (TC-NOM-02, TC-ERR-01, TC-NEG-03) reposent tous sur cette règle. Aucun motif normatif n'est donné dans la spec, ni dans une annexe, ni par renvoi résolvable.
  • Impact : Impossible de valider contractuellement le rejet local d'un email invalide. L'implémentation UI fabriquera sa propre regex, créant un risque de divergence backend/UI silencieuse. Toute revue de couverture est circulaire (on teste une règle par rapport à elle-même).
  • Gravité : Bloquant

A-02 — Règle de masquage IPv6 partiellement définie

  • Type : Ambiguïté
  • Référence : spec §5.1 (eventIpMasked), spec §10.2 PC-298-05, tests §9 "règle normative précise de masquage IPv6", tests TC-NOM-12 / TC-NEG-07
  • Description : Le format IPv6 masqué est décrit par 4 hextets + *:*:*:*. Sur les 8 hextets d'une adresse IPv6, la spec ne précise ni lesquels sont conservés (préfixe réseau, suffixe interface, etc.) ni l'ordre du rendu. Aucune règle canonique (ex : RFC 5952) n'est citée.
  • Impact : Deux implémentations UI peuvent produire deux masques différents à partir de la même IP brute, tous « conformes » à la description textuelle. CA-298-09 et TC-NOM-12 sont non reproductibles.
  • Gravité : Majeur

A-03 — Stockage local drmWarningSeen non spécifié

  • Type : Ambiguïté
  • Référence : spec INV-298-03, spec §5.1 (drmWarningSeen), spec F-298-01 §4 / F-298-06, tests TC-NOM-03 / TC-NR-06
  • Description : L'invariant parle de « mémorisé localement » et la table data mentionne « Booléen persistant local par compte », sans préciser le mécanisme (AsyncStorage, MMKV, SecureStore…), la politique de reset (logout ? uninstall ?), ni la granularité (par userId mais que se passe-t-il après changement de compte sur le même device ?).
  • Impact : TC-NOM-03 vérifie la persistance mais ne peut prouver l'exhaustivité sans définir le mécanisme. Comportement imprévisible au logout/reinstall/multi-device.
  • Gravité : Majeur

A-04 — Contenu de l'encart RGPD inconnu

  • Type : Ambiguïté
  • Référence : spec INV-298-06, spec §10.2 PC-298-06, spec H-298-07, tests §9 "Texte RGPD exact", tests TC-NOM-04
  • Description : INV-298-06 et CA-298-11/CA-287-27 exigent l'affichage d'un « encart RGPD visible avant soumission » mais la spec ne contient ni le texte, ni les champs minimaux (finalité, base légale, durée de rétention, destinataires, droits), ni la valeur chiffrée de la durée de rétention.
  • Impact : TC-NOM-04 ne vérifie que la présence positionnelle d'un encart, pas son contenu normatif. L'invariant est une coquille vide côté testabilité.
  • Gravité : Bloquant

A-05 — Textes ARB-7 et ARB-8 absents

  • Type : Ambiguïté
  • Référence : spec §3 (ARB-7, ARB-8), spec INV-298-02, spec INV-298-03, tests §9 "Comparaison stricte ARB-7/ARB-8", tests TC-NOM-09
  • Description : INV-298-02 exige le « texte ARB-7 exact » et INV-298-03 implique un texte DRM (ARB-8). Aucun de ces textes n'est reproduit dans la spec. La spec renvoie à PD-287 sans inclusion effective.
  • Impact : TC-NOM-09 ne peut comparer « strictement » un texte qu'il ne possède pas. La règle est auto-référentielle.
  • Gravité : Bloquant

A-06 — Borne maximale maxViews inconnue

  • Type : Ambiguïté
  • Référence : spec §5.1 / §5.2 (maxViews), spec §10.2 PC-298-02, spec H-298-05
  • Description : maxViews est optionnel, mais la borne maximale backend n'est pas fournie. La spec affiche Non défini dans besoin/PD-287 accessible. Le seul comportement prévu est « >max backend: erreur backend propagée », ce qui revient à ne pas valider côté client.
  • Impact : Aucun test n'est spécifié pour la borne haute. Critère d'acceptation CA-298-03 ne couvre que TTL.
  • Gravité : Majeur

A-07 — Mapping eventType backend→UI non figé

  • Type : Ambiguïté
  • Référence : spec §5.1 (eventType), spec §10.2 PC-298-03
  • Description : L'enum est donné {CREATION, ACTIVATION, CONSULTATION, EXPORT, ECHEC_OTP, REVOCATION} mais annoté « mapping backend à figer ». Le lien entre code API et libellé FR i18n n'est pas défini.
  • Impact : Le journal peut afficher des codes bruts au lieu de libellés traduits. TC-NOM-11 vérifie les colonnes, pas la qualité des libellés.
  • Gravité : Majeur

A-08 — Terme normaliser(email) non contractualisé

  • Type : Ambiguïté (terminologique — voir aussi §2 Contradictions)
  • Référence : spec §5.1 (recipientEmail, "comparaison case-insensitive"), spec §5bis Diagramme de séquence ("normaliser(email)")
  • Description : Le diagramme de séquence introduit une étape normaliser(email) distincte de valider(regex D-287-03). La spec textuelle parle uniquement de « comparaison case-insensitive ». Aucun invariant ne formalise la normalisation (lowercase ? trim ? Unicode NFC ? dot-removal Gmail ?).
  • Impact : Si la normalisation est faite, risque d'écart entre l'email saisi et l'email réellement envoyé au backend (différent de ce que l'utilisateur croit avoir tapé). Si elle n'est pas faite, diagramme trompeur.
  • Gravité : Mineur

A-09 — « Appel exploratoire » non défini

  • Type : Ambiguïté
  • Référence : spec INV-298-16, tests TC-NEG-01 / TC-NEG-08
  • Description : « Le client NE DOIT PAS effectuer d'appels exploratoires pour inférer des partages non autorisés » ne définit ni la notion d'exploration (pattern de requêtes ? cadence ? scope hors compte ?) ni le mode de détection côté test.
  • Impact : TC-NEG-08 vise un « pattern d'énumération » dans les traces réseau, sans définir ce qui qualifie un pattern. Critère subjectif.
  • Gravité : Majeur

A-10 — Message contextuel « journal vide » non rédigé

  • Type : Ambiguïté
  • Référence : spec F-298-05 §4, spec ERR-298-06, spec §10.2 PC-298-07, tests TC-ERR-06
  • Description : ERR-298-06 impose un « message contextuel explicite » ; la spec mentionne trois variantes possibles (« jamais activé / pas d'événement / erreur réseau ») mais aucune clé i18n ni texte normatif. TC-ERR-06 ne peut donc pas vérifier l'adéquation contextuelle.
  • Impact : Test binaire dégénéré (présence d'un texte non-vide), sans garantie de couverture des 3 cas.
  • Gravité : Mineur

A-11 — Pull-to-refresh sans invariant

  • Type : Ambiguïté
  • Référence : spec F-298-02 §4 ("Pull-to-refresh force un rechargement réseau")
  • Description : Comportement listé dans le flux nominal mais non associé à un invariant, un CA ou un test. Statut contractuel flou (obligation ? bonus ?).
  • Impact : Non testable tel quel ; sera soit hors périmètre, soit source de régression silencieuse.
  • Gravité : Mineur

A-12 — Reconsultation DRM vs mémorisation

  • Type : Ambiguïté
  • Référence : spec INV-298-03, spec F-298-06 §1
  • Description : INV-298-03 dit « à la première ouverture ». F-298-06 dit « le propriétaire peut reconsulter ». Aucun invariant ne décrit le comportement du flag drmWarningSeen lors d'une reconsultation volontaire (reste true ? reset ? modal distinct ?).
  • Impact : TC-NR-06 présume une « reconsultation possible » sans définir son observable.
  • Gravité : Mineur

A-13 — Scope du guard propriété à l'écran détail preuve

  • Type : Ambiguïté
  • Référence : spec §5.8 ("Scope d'enregistrement du guard"), spec INV-298-12, tests TC-NOM-07
  • Description : La spec parle de « guard UI de propriété ». Le guard est-il un check à l'entrée du formulaire, un filtre sur la visibilité du CTA, ou une garde de navigation (route/screen) ? Les trois ont des implémentations et des tests différents.
  • Impact : TC-NOM-07 vérifie l'absence de CTA mais pas l'impossibilité de navigation programmatique. INV-298-12 sous-spécifie la défense.
  • Gravité : Mineur

2. Contradictions

C-01 — drmWarningSeen persistant local vs INV-298-05 « pas de cache local »

  • Type : Contradiction
  • Référence : spec INV-298-05, spec §5.1 (drmWarningSeen : "Booléen persistant local par compte"), spec F-298-01 §4
  • Description : INV-298-05 interdit toute mise en cache locale « des données de partage » et exige fraîcheur réseau à chaque affichage. Le flag drmWarningSeen est lui-même un état de partage persistant localement. La frontière « données de partage » vs « préférence utilisateur » n'est pas contractualisée.
  • Impact : Ambiguïté interprétative entre implémenteurs et auditeurs ; un lecteur strict peut considérer que INV-298-05 interdit aussi la persistance drmWarningSeen.
  • Gravité : Mineur

C-02 — PC-298-04 « à clarifier » vs matrice §5.5 déjà exhaustive

  • Type : Contradiction
  • Référence : spec §5.5 (matrice transitions), spec §10.2 PC-298-04
  • Description : La matrice §5.5 liste explicitement ACTIVE → OTP_BLOCKED : INTERDITE. Pourtant PC-298-04 donne ce même couple comme exemple de « comportement exact à clarifier, matrice backend non jointe ». Soit la matrice UI est définitive (et PC-298-04 est obsolète), soit elle est indicative (et INV-298-14/INV-298-15 sont faux).
  • Impact : Ambiguïté sur l'opposabilité contractuelle de la matrice. TC-NOM-16 et TC-NEG-04 s'appuient sur elle.
  • Gravité : Majeur

C-03 — Tests UI d'invariants de transitions backend

  • Type : Contradiction Spec ↔ Tests
  • Référence : spec INV-298-08 ("source de vérité unique backend"), spec INV-298-14 / INV-298-15, tests TC-NOM-16 / TC-NEG-04
  • Description : INV-298-08 établit le backend comme unique source de vérité d'état. INV-298-14/15 (transitions interdites, terminaux) sont des règles de la machine d'états backend. Les tests TC-NOM-16 et TC-NEG-04 prétendent vérifier que « les transitions non listées sont refusées » côté UI, alors que l'UI n'initie pas les transitions (sauf revoke) — elle affiche l'état retourné. Cela signifie, soit que l'UI doit dupliquer la FSM (et rejeter des payloads backend non conformes), soit que le test est hors périmètre UI.
  • Impact : Les invariants INV-298-14/15 sont contractuellement mal attribués à un composant UI. Les tests associés ne peuvent être réalisés de manière déterministe sans mock exhaustif des transitions backend.
  • Gravité : Majeur

C-04 — Payload POST /shares diagramme vs table §5.1

  • Type : Contradiction
  • Référence : spec §5bis (diagramme séquence), spec §5.1
  • Description : Le diagramme envoie {proofId, recipientEmail, ttlMinutes, maxViews?, notificationsEnabled}. La réponse 201 contient {shareId, state, expiresAt}. La table §5.1 liste aussi createdAt, ownerUserId, et les champs sont censés figurer dans la liste (CA-298-05/06). Il n'est pas clair si la réponse 201 sert à construire la ligne UI ou si un refresh GET /shares est obligatoire.
  • Impact : Risque d'incohérences d'affichage post-création (F-298-01 §8-9) ou d'appels réseau supplémentaires non spécifiés.
  • Gravité : Mineur

C-05 — INV-298-07 « jamais loggés » vs journal d'accès affichant l'email

  • Type : Contradiction (apparente — frontière imprécise)
  • Référence : spec INV-298-07, spec F-298-05 §3, spec §5.1 (eventRecipientEmail), spec CA-298-08
  • Description : INV-298-07 interdit « NE DOIVENT JAMAIS être loggés ». Le journal d'accès affiche le recipientEmail. Selon l'interprétation de « loggés » (logs applicatifs vs export probatoire vs affichage UI), un journal visible par le propriétaire contient bien l'email. Les tests incluent aussi « export probatoire : HAR réseau, captures écran » (§8) — un HAR réseau contiendra l'email de réponse API.
  • Impact : Frontière contradictoire entre PII non loguée et PII affichée/capturée. Risque RGPD si l'observabilité des tests (HAR) échappe à la règle « jamais loggés ».
  • Gravité : Majeur

C-06 — Diagramme d'état : self-loops INTERDITE absents de la matrice §5.5

  • Type : Contradiction diagramme ↔ spec
  • Référence : spec §5.5, spec §5bis Diagramme d'état (ACTIVE --> ACTIVE : INTERDITE, OTP_BLOCKED --> OTP_BLOCKED : INTERDITE, PENDING_ACTIVATION --> PENDING_ACTIVATION : INTERDITE)
  • Description : Le diagramme d'état ajoute des auto-transitions (self-loops) INTERDITE. La matrice §5.5 ne les liste pas (son axe « →État » ne couvre pas la même source, et l'INV-298-14 parle de transitions « non listées »). Incohérence entre les deux représentations censées décrire la même machine d'états.
  • Impact : Ambiguïté sur le fait qu'une réponse backend identique à l'état courant constitue ou non une violation d'invariant.
  • Gravité : Mineur

C-07 — Diagramme de séquence incomplet vs flux spécifiés

  • Type : Contradiction diagramme ↔ spec
  • Référence : spec §5.4 (F-298-02, F-298-03, F-298-04), spec INV-298-02 (ARB-7), spec §5bis Diagramme séquence
  • Description : Le diagramme de séquence ne couvre que la création et le journal. Il omet : la révocation (ARB-7 + POST /revoke, pourtant critique INV-298-02), la pagination (F-298-03 / INV-298-13), et les erreurs (401, 403, 400, offline).
  • Impact : La règle §5bis du prompt (« chaque transformation/appel crypto doit être explicite ») n'est pas respectée pour les flux sensibles. Les invariants INV-298-02, INV-298-13, ERR-298-11/12 n'ont pas de représentation graphique.
  • Gravité : Majeur

C-08 — INV-298-17 « aucune exécution offline » vs ERR-298-12 « timeout / perte connectivité »

  • Type : Contradiction / ambiguïté
  • Référence : spec INV-298-17, spec ERR-298-12, tests TC-NOM-17 / TC-ERR-12
  • Description : INV-298-17 dit « aucune exécution offline n'est autorisée » — interprétable comme « la feature refuse d'entrer en mode offline ». ERR-298-12 gère « timeout / offline pendant une action » par une « erreur réseau explicite » — interprétation différente (la feature tente quand même puis rend compte de l'échec). TC-NOM-17 et TC-ERR-12 testent ces deux comportements sans les séparer clairement.
  • Impact : Comportement UX ambigu : bloquer à l'entrée ou laisser entrer et gérer l'échec en cours ? Deux implémentations possibles, toutes les deux pass/fail selon l'interprétation.
  • Gravité : Mineur

3. Règles non testables

NT-01 — INV-298-10 « 100% des chaînes visibles »

  • Type : Non testable
  • Référence : spec INV-298-10, tests TC-NOM-14 / TC-NR-02
  • Description : « 100% » et « audit statique » sans définition d'outil, de scope (feature seule ? app entière ? screenshots d'accessibilité ?) ni de critère de décision sur les littéraux techniques (logs, clés de test, sentry breadcrumbs). CA-298-13 parle de « scope code UI de la feature partage » mais sans lister les fichiers/modules.
  • Impact : Verdict non reproductible d'une audit à l'autre.
  • Gravité : Majeur

NT-02 — INV-298-07 « NE DOIVENT JAMAIS être loggés »

  • Type : Non testable (partiellement)
  • Référence : spec INV-298-07, tests TC-NOM-15 / TC-ERR-04
  • Description : Le « jamais » est universel. Les tests couvrent les « logs applicatifs » et les « traces fonctionnelles », mais ne peuvent exhaustivement couvrir les pipelines externes (Sentry, crashlytics, analytics, logs OS, NSLog iOS, logcat Android, ShareSheet, clipboard, HAR).
  • Impact : Couverture partielle, verdict binaire impossible sans liste fermée de canaux.
  • Gravité : Majeur

NT-03 — INV-298-02 / INV-298-03 (ARB-7 / DRM) « texte exact »

  • Type : Non testable
  • Référence : spec INV-298-02 / INV-298-03, tests §9 "Comparaison stricte ARB-7/ARB-8"
  • Description : Le verdict QA liste ces règles comme « NON TESTABLE » faute de textes fournis. C'est un aveu de non-testabilité contractualisé, donc un écart à lever avant Gate 5 et non à accepter en l'état.
  • Impact : INV-298-02 non démontrable ; la révocation confirmée par l'utilisateur n'a aucune garantie de consentement éclairé.
  • Gravité : Bloquant

NT-04 — INV-298-16 « appels exploratoires »

  • Type : Non testable (critère subjectif)
  • Référence : cf. A-09.
  • Gravité : Majeur

NT-05 — INV-298-09 « IP partiellement masquée » pour IPv6

  • Type : Non testable
  • Référence : cf. A-02.
  • Gravité : Majeur

NT-06 — NON TESTABLE — qualification juridique RGPD

  • Type : Non testable (acté)
  • Référence : spec §3 / H-298-08, tests §9
  • Description : La spec et les tests reconnaissent explicitement la non-testabilité (hors périmètre fonctionnel UI). OK comme aveu, mais couplé à INV-298-06 / CA-287-27 / A-04 : l'encart RGPD fonctionnel repose sur un contenu juridique absent. On teste donc une coquille.
  • Impact : Le verdict « partiellement testable » du §10 Tests est optimiste. Sans texte RGPD et sans durée de rétention, l'invariant INV-298-06 est cosmétique.
  • Gravité : Majeur

NT-07 — TC-NOM-13 « état backend modifié entre deux consultations »

  • Type : Non testable (non déterministe)
  • Référence : tests TC-NOM-13
  • Description : Le scénario implique une mutation d'état depuis un « autre terminal ». Orchestration multi-acteurs non définie, pas de mécanisme de mock figé (clock, concurrence). Test non reproductible en CI sans harnais spécifique non spécifié.
  • Gravité : Mineur

NT-08 — TC-NOM-04 « visibilité vérifiable au moment exact de l'action »

  • Type : Non testable (observable flou)
  • Référence : tests TC-NOM-04
  • Description : Sur mobile, « visible » dépend du viewport, du scroll et de l'état du clavier. L'observable « visibilité à l'instant du clic CTA » n'est pas défini (bounding-box dans viewport ? opacity > 0 ? accessibility ? pourcentage visible ?).
  • Gravité : Majeur

4. Incohérences Spec ↔ Tests

I-01 — CA-287-27 référencée sans être redéfinie dans PD-298

  • Type : Incohérence Spec↔Tests
  • Référence : spec §3 (CA-287-27), tests TC-NOM-04 (colonne "Référence spec: CA-287-27")
  • Description : La matrice de couverture §2 des tests lie INV-298-06 à « CA-287-27 » — un CA appartenant à une autre story. Le tableau ne référence aucun CA de PD-298 alors que CA-298-11 existe pour INV-298-06. Couplage externe implicite non sourcé dans la spec PD-298.
  • Impact : Si PD-287 fait évoluer CA-287-27, les tests PD-298 deviennent incohérents sans changement dans PD-298. Traçabilité rompue.
  • Gravité : Majeur

I-02 — INV-298-11 / CA-298-15 et matrice §5.5 : actions UI non énumérées

  • Type : Incohérence
  • Référence : spec INV-298-11 / CA-298-15, spec §5.5 (matrice "INTERDITE/AUTORISÉE"), tests TC-NOM-08 / TC-NR-03
  • Description : La matrice §5.5 liste les transitions, pas les actions UI disponibles (boutons visibles). L'invariant INV-298-11 dit « actions disponibles DOIVENT dépendre de l'état (matrice contractuelle §5.5) ». La correspondance « transition autorisée backend ↔ bouton visible UI » n'est pas donnée explicitement (ex : pour OTP_BLOCKED, seul Revoke est autorisé côté transitions ; ça se traduit par quels boutons visibles/invisibles/disabled ?).
  • Impact : TC-NOM-08 et TC-NR-03 comparent à une matrice qui n'existe pas formellement. Verdict dépendant de l'interprétation du développeur.
  • Gravité : Majeur

I-03 — Matrice de couverture §2 tests : INV-298-11 et INV-298-14/15 liés au même CA et au même test

  • Type : Incohérence
  • Référence : tests §2 matrice
  • Description : INV-298-11 (actions disponibles selon état), INV-298-14 (transitions interdites) et INV-298-15 (terminaux) pointent toutes vers CA-298-15 et TC-NOM-16/TC-NOM-08. CA-298-15 parle de « boutons visibles/invisibles selon shareState » — ce qui couvre INV-298-11 mais pas INV-298-14/15 (lesquels parlent de transitions et de terminaux).
  • Impact : Couverture surjective ; un test seul prétend couvrir 3 invariants de natures différentes. Difficile de tracer une régression.
  • Gravité : Majeur

I-04 — INV-298-13 pagination, mais aucun test sur limit != 20 côté réponse

  • Type : Incohérence
  • Référence : spec INV-298-13, tests TC-NOM-05 / TC-NEG-02
  • Description : TC-NEG-02 « Tentative de forcer limit != 20 » teste le comportement UI (la requête envoyée). Aucun test ne couvre le cas où le backend répond avec une page non conforme à la demande (ex : limit=19). La règle « limit=20 fixe MVP » est une contrainte de requête, pas de réception.
  • Gravité : Mineur

I-05 — CA-298-02 « aucune requête réseau » mais aucune exclusion des requêtes latérales

  • Type : Incohérence
  • Référence : spec CA-298-02, tests TC-NOM-02 / TC-ERR-01
  • Description : Le test observe « 0 requête POST /shares ». L'invariant dit « un email invalide NE DOIT PAS être soumis ». Ni l'un ni l'autre n'exclut les requêtes latérales (analytics, telemetry de validation échouée, Sentry breadcrumbs HTTP). Testabilité non déterministe si le projet a un client analytics.
  • Gravité : Mineur

I-06 — Tests TC-NOM-07 (preuve non possédée) : prémisse d'accès incohérente

  • Type : Incohérence
  • Référence : tests TC-NOM-07, spec INV-298-12
  • Description : « A ouvre l'écran détail d'une preuve possédée par B ». La spec PD-298 ne précise pas si un utilisateur A peut consulter le détail d'une preuve de B (ce serait un autre module, proofs). Si c'est impossible par défaut, TC-NOM-07 est dégénéré (écran inatteignable). Si c'est possible (preuve partagée, admin, etc.), c'est un contexte pré-existant hors périmètre PD-298.
  • Impact : Le test dépend d'un contexte métier non établi dans la spec.
  • Gravité : Majeur

I-07 — §7 CA vs §2 matrice tests : champs « CA » manquants dans la matrice

  • Type : Incohérence
  • Référence : tests §2 matrice de couverture, spec §7 CA-298-01 à CA-298-15
  • Description : La matrice couvre les invariants INV mais toutes les colonnes « ID Critère » ne correspondent pas bijectivement aux CA §7. Ex : INV-298-06 est lié à CA-287-27 (externe) ; INV-298-17 à « N/A ». Aucune matrice CA→Test explicite.
  • Impact : Un CA non couvert peut passer inaperçu (ex : CA-298-08 figure en matrice mais la couverture CA-298-11 repose sur CA-287-27 plutôt que CA-298-11).
  • Gravité : Mineur

I-08 — ERR-298-11 (401) : test TC-ERR-11 présume un « flux auth existant »

  • Type : Incohérence / dépendance externe
  • Référence : spec ERR-298-11, tests TC-ERR-11
  • Description : Le test exige une « redirection vers flux auth existant ». Ni la spec ni les tests ne définissent ce flux (route, composant, état post-retour). Dépendance externe non tracée.
  • Gravité : Mineur

5. Hypothèses dangereuses

H-01 — H-298-02 / H-298-03 pagination offset/limit

  • Type : Hypothèse dangereuse
  • Référence : spec H-298-02 / H-298-03, spec INV-298-13
  • Description : La spec présume que PD-287 expose une pagination offset/limit avec limit=20 acceptable. Si le backend utilise cursor-based pagination, tout INV-298-13 et TC-NOM-05 sont inapplicables. Aucune vérification n'est planifiée avant implémentation.
  • Impact : Réécriture complète de la liste globale en cours d'implémentation. Glissement de périmètre.
  • Gravité : Majeur

H-02 — H-298-06 compatibilité matrice UI ↔ backend

  • Type : Hypothèse dangereuse
  • Référence : spec H-298-06, spec §5.5, spec §10.2 PC-298-04
  • Description : « Les transitions backend réelles sont compatibles avec la matrice §5.5 » — non vérifiée. PC-298-04 le dit aussi : matrice backend non jointe. Toute divergence = écart majeur post-implémentation.
  • Gravité : Majeur

H-03 — Idempotence POST /shares et POST /revoke non spécifiée

  • Type : Hypothèse dangereuse
  • Référence : spec F-298-01 §7, spec F-298-04 §4
  • Description : Aucune règle d'idempotence (clé idempotente, debounce UI, blocage pendant in-flight) n'est définie. Un double-tap créera potentiellement 2 shares, ou enverra 2 revokes. Le backend PD-287 peut ou non gérer cela.
  • Impact : Duplications, PII doublement envoyée, événements d'audit doublonnés, métriques biaisées.
  • Gravité : Majeur

H-04 — Normalisation / internationalisation de l'email

  • Type : Hypothèse dangereuse
  • Référence : spec §5.1 (recipientEmail "ASCII printable sans espace terminal"), spec §5bis ("normaliser(email)")
  • Description : L'ASCII-only interdit les emails IDN (RFC 6531/6532, courants en FR/EU). La normalisation non contractualisée peut altérer silencieusement l'input. Risque d'exclusion d'utilisateurs légitimes et divergence avec la regex D-287-03 (si D-287-03 autorise l'unicode).
  • Gravité : Majeur

H-05 — Horloge expiresAt affichée

  • Type : Hypothèse dangereuse
  • Référence : spec §5.1 (expiresAt), spec INV-298-04
  • Description : Aucune spec sur l'horloge affichée (device vs serveur). Le TTL côté UI peut diverger de la réalité backend (clock skew). Un lien affiché « expire dans 3 min » peut être déjà expiré serveur-side.
  • Impact : Confusion UX + risque de support client.
  • Gravité : Mineur

H-06 — INV-298-05 fraîcheur réseau : UX sur connexions lentes

  • Type : Hypothèse dangereuse
  • Référence : spec INV-298-05, spec §5.2 ("aucun objectif perf chiffré")
  • Description : Appel réseau obligatoire à chaque ouverture d'écran + pas de SLA perf = UX dégradée sur 3G/edge. Pas de mention de skeleton, de cache stale-with-indicator ou de timeout borné.
  • Impact : Risque d'abandon, risque de spinners infinis en timeout.
  • Gravité : Mineur

H-07 — Race condition état concurrent sur révocation

  • Type : Hypothèse dangereuse
  • Référence : spec F-298-04, spec INV-298-05
  • Description : Entre l'affichage de la modale ARB-7 et la confirmation, l'état peut avoir changé backend (EXPIRED, déjà REVOKED sur autre device). Aucun re-check avant POST /revoke. Pas de gestion du 409/410 dans la spec d'erreurs.
  • Impact : L'utilisateur peut confirmer une révocation sur un état périmé. Pas bloquant mais UX incohérente.
  • Gravité : Mineur

H-08 — H-298-08 qualification juridique RGPD « hors périmètre UI »

  • Type : Hypothèse dangereuse (acceptation silencieuse)
  • Référence : spec H-298-08, spec §9
  • Description : Hypothèse correcte en principe, mais elle conditionne INV-298-06 et CA-298-11 à un contenu juridique absent (cf. A-04, NT-06). Cantonner « hors périmètre UI » la qualification juridique ne dispense pas d'avoir le texte à afficher.
  • Gravité : Majeur

H-09 — « Aucun mécanisme de protection distribuée » (§5.6)

  • Type : Hypothèse dangereuse
  • Référence : spec §5.6
  • Description : La spec affirme « aucun mécanisme de protection distribuée applicable (module synchrone mono-instance) ». Pour la création de share depuis plusieurs devices du même utilisateur, il peut y avoir conflits, et anti-spam côté client absent. Affirmation sans analyse.
  • Gravité : Mineur

6. Risques sécurité / conformité

S-01 — Fuite PII via crash reports et analytics

  • Type : Risque sécurité/conformité
  • Référence : spec INV-298-07, tests §8 ("Export probatoire : HAR réseau, captures écran"), tests TC-NOM-15
  • Description : recipientEmail figure dans les payloads API (HAR), dans les rendus écran (captures), et potentiellement dans les breadcrumbs Sentry/analytics automatiques (URL, paramètres, screenshots de bug report). Aucune règle de scrubbing n'est imposée.
  • Impact : Fuite PII vers vendors externes (Sentry, Datadog, Firebase) sans base légale dédiée.
  • Gravité : Majeur

S-02 — Absence de scrubbing PII dans l'export probatoire des tests

  • Type : Risque sécurité/conformité
  • Référence : tests §8 (observabilité requise)
  • Description : HAR réseau + captures écran sont explicitement exigés comme artefacts. Ces artefacts contiendront emails et IP brutes avant masquage côté rendu. Aucun protocole de scrubbing avant archivage.
  • Gravité : Majeur

S-03 — Anti-enumeration INV-298-16 côté UI uniquement

  • Type : Risque sécurité/conformité
  • Référence : spec INV-298-16, tests TC-NEG-01 / TC-NEG-08
  • Description : L'invariant porte uniquement sur « le client NE DOIT PAS effectuer d'appels exploratoires ». Un attaquant avec l'app réverse-engineerée ou les endpoints documentés peut contourner l'UI. L'anti-enumeration est une obligation backend (PD-287), pas UI. L'invariant placé ici crée une fausse assurance.
  • Gravité : Majeur

S-04 — Absence de clearing in-memory au logout / session expirée

  • Type : Risque sécurité/conformité
  • Référence : spec ERR-298-11, spec INV-298-05
  • Description : ERR-298-11 gère le 401 par redirection vers le flux auth. Rien n'indique que les données de share en mémoire (liste, détail, journal) doivent être purgées au logout ou à l'expiration de session. Risque de persistance résiduelle.
  • Gravité : Majeur

S-05 — drmWarningSeen par userId côté device : multi-device et reset

  • Type : Risque sécurité/conformité / UX
  • Référence : spec INV-298-03, spec §5.1
  • Description : Le flag est local-par-compte-par-device. Un utilisateur qui se connecte sur un autre device ne verra pas l'avertissement DRM (il n'existe pas sur ce device). L'invariant « information explicite sur l'absence de DRM » n'est garanti qu'une fois par device, pas une fois par compte. La règle contractuelle est plus faible qu'annoncée.
  • Gravité : Majeur

S-06 — Pas de règle clipboard / share sheet pour l'email destinataire

  • Type : Risque sécurité/conformité
  • Référence : spec INV-298-07
  • Description : L'email figure à l'écran dans la liste et le détail. Rien n'interdit à l'OS (iOS share sheet, Android intent) de le véhiculer hors app, ou à l'utilisateur de le copier. Pas non plus de disclaimer RGPD utilisateur.
  • Gravité : Mineur

S-07 — Aucun rate-limit / throttling UI

  • Type : Risque sécurité/conformité
  • Référence : spec F-298-01 (flux création)
  • Description : Aucune règle anti-spam côté UI (délai entre 2 créations, blocage du bouton in-flight). Couplé à H-03 (idempotence absente), risque d'abus trivial et d'overwhelming du backend. Les abus documentés dans RGPD/logs peuvent aussi générer des notifications massives côté destinataires.
  • Gravité : Majeur

S-08 — 403 « géré sans fuite » non spécifié

  • Type : Risque sécurité/conformité
  • Référence : spec ERR-298-07, tests TC-ERR-07
  • Description : « 403 géré sans fuite » est un objectif, pas une règle : aucun message d'erreur normatif n'est défini, aucun mapping « 403 → message utilisateur ». Risque d'afficher le message d'erreur backend tel quel (ex : Forbidden: proof X not owned by user Y).
  • Gravité : Majeur

S-09 — Journal : export et watermark absent

  • Type : Risque sécurité/conformité
  • Référence : spec F-298-05, spec CA-298-08
  • Description : Le journal affiche email + IP masquée + device + horodatage. Aucune règle concernant la capture d'écran, l'export, ou le watermark de confidentialité. Risque de fuite de PII de destinataires dans des canaux non contrôlés.
  • Gravité : Mineur

S-10 — TC-NEG-05 / TC-NEG-06 : état/eventType inconnu non remonté

  • Type : Risque conformité
  • Référence : tests TC-NEG-05 / TC-NEG-06
  • Description : Une réponse backend avec un état ou un eventType non documenté est affichée comme erreur / UNKNOWN_EVENT, mais aucune règle n'impose de remontée observabilité (télémétrie interne, alerte). Dette silencieuse.
  • Gravité : Mineur

S-11 — Deep-linking / CSP mobile explicitement exclus, sans garde

  • Type : Risque sécurité/conformité
  • Référence : spec §2 (Exclu : deep linking)
  • Description : Exclure la feature ne suffit pas à garantir qu'un deeplink natif ne puisse déclencher l'écran de création partage (React Navigation expose ce comportement par défaut). Aucune garde de navigation explicite.
  • Gravité : Mineur

Synthèse des constats par gravité

Gravité Nombre IDs
Bloquant 4 A-01, A-04, A-05, NT-03
Majeur 25 A-02, A-03, A-06, A-07, A-09, A-13, C-02, C-03, C-05, C-07, NT-01, NT-02, NT-04, NT-05, NT-06, NT-08, I-01, I-02, I-03, I-06, H-01, H-02, H-03, H-04, H-08, S-01, S-02, S-03, S-04, S-05, S-07, S-08
Mineur 15 A-08, A-10, A-11, A-12, C-01, C-04, C-06, C-08, NT-07, I-04, I-05, I-07, I-08, H-05, H-06, H-07, H-09, S-06, S-09, S-10, S-11

(Totaux : 4 bloquants + 32 majeurs + 21 mineurs — certains écarts ont été indexés sous plusieurs sections.)


Remarques finales

  • Chemin critique bloquant : la spec repose sur quatre éléments contractuels absents (A-01 regex D-287-03, A-04 contenu RGPD, A-05 textes ARB-7/ARB-8, NT-03 qui recoupe A-05). Trois invariants non négociables (INV-298-01, INV-298-02, INV-298-06) ne peuvent être vérifiés contractuellement en l'état.
  • Glissement FSM : C-02, C-03 et H-02 concentrent un risque structurel — la matrice d'états est présentée à la fois comme autoritative (INV-298-14/15) et comme dépendante d'un backend non audité. À trancher en Gate 5 avant implémentation.
  • Enveloppe PII : S-01/S-02/S-04/S-05/S-07 convergent vers un manque de hardening transversal sur le traitement des emails destinataires. INV-298-07 nécessite au minimum : règles de scrubbing (Sentry/analytics/HAR), purge in-memory au logout, rate-limiting UI.
  • Diagrammes : C-07 et C-06 indiquent des écarts diagramme ↔ spec. Le diagramme de séquence doit au minimum couvrir la révocation (ARB-7) et la pagination ; la matrice §5.5 doit soit accueillir les self-loops, soit le diagramme doit les retirer.