Aller au contenu

PD-101 — Review Step 3 v2 : Analyse des écarts résiduels

Story : PD-101 — Upload probatoire mobile chiffré avec progression, reprise et annulation orchestrée Gate : 3 — CONFORMITY_CHECK Itération : v2 (après corrections v1) Date : 2026-03-10 Mode : Factuel — aucune spéculation, aucune correction proposée

Rappel verdict v1

  • Verdict : NON_CONFORME
  • Scores : completeness 6.0, testability 5.5, clarity 7.0, traceability 7.5 (moyenne 6.5)
  • Écarts : E-01 à E-16 (3 bloquants, 9 majeurs, 4 mineurs)

Analyse écart par écart : v1 → v2

E-01 (Majeur v1) — Photos picker + transcodage : ambiguïté fichier original vs fichier soumis

Statut v2 : CORRIGÉ

La v2 introduit les définitions explicites en §3 : - Fichier original : fichier binaire présent dans la photothèque avant interaction app. - Fichier soumis : fichier binaire reçu par l'app après sélection (peut différer si transcodage iOS). - Fichier probatoire : fichier sur lequel porte le hash. En mode par défaut = fichier soumis.

INV-03 est reformulé : « En mode par défaut, le fichier probatoire est bit-à-bit identique au fichier soumis (reçu par l'app) ». Le flux §5.1 étape 4 précise que si transcodage détecté et utilisateur continue, ios_transcoded: true est enregistré et INV-03 s'applique au fichier soumis. TC-NOM-04 et ST-06 couvrent ce scénario.


E-02 (Bloquant v1) — Contradiction READY → CANCELLED

Statut v2 : CORRIGÉ

La table §5.7 v2 autorise explicitement READY -> CANCELLED avec garde : « si PENDING_SEAL non encore atteint ». La race condition est documentée avec mécanisme atomique UPDATE ... WHERE status = 'READY'. ERR-10 couvre le cas où le worker gagne. ST-11 et TC-ERR-08 testent ce scénario.


E-03 (Majeur v1) — Format preuve consentement non défini

Statut v2 : CORRIGÉ

Le §3.4 v2 définit un format JSON explicite pour la preuve de consentement (action, timestamp ISO 8601 UTC, doc_id, user_confirmed). Le flux §5.2 référence §3.4. TC-NOM-03 vérifie le format §3.4 dans le journal d'audit et les metadata backend.


E-04 (Mineur v1) — Seuil 10 MB ambigu (SI vs binaire)

Statut v2 : CORRIGÉ

La v2 précise partout « 10 MB (10 000 000 bytes, SI base 10) » dans §3 (Upload simple/multipart), §5.5 (seuil multipart), TC-NOM-02 (9 999 999 / 10 000 000 bytes).


E-05 (Bloquant v1) — Hash validation fonctionnelle vs zero-knowledge

Statut v2 : CORRIGÉ

INV-05 v2 est reformulé : le hash SHA3-256 est validé fonctionnellement côté mobile par recalcul (hash avant chiffrement, puis recalcul sur le plaintext conservé en mémoire pour vérifier l'intégrité du pipeline). Le backend ne fait que valider le format (regex + longueur). Le flux §5.1 étape 7 décrit le mécanisme. TC-INV-05 teste la corruption détectée côté mobile.


E-06 (Majeur v1) — Disclaimer EXIF sans test

Statut v2 : CORRIGÉ

Le flux §5.1 étape 5 mentionne le disclaimer EXIF. ST-10 et TC-NOM-07 couvrent ce scénario avec GIVEN/WHEN/THEN complet (confirmation explicite requise, journalisation audit).


E-07 (Mineur v1) — Terminologie journal incohérente

Statut v2 : CORRIGÉ

La v2 utilise uniformément « journal d'audit » dans toutes les sections (TC-NOM-03, TC-NOM-04, TC-NOM-06, TC-NOM-07, TC-ERR-04, TC-ERR-06, TC-ERR-07, TC-INV-05, TC-INV-07, TC-INV-10, §8 Observabilité).


E-08 (Majeur v1) — AbortMultipartUpload atomicité et parts orphelines

Statut v2 : CORRIGÉ

Le §5.9 v2 documente explicitement : 1. S3 Lifecycle Policy (expiration automatique des uploads multipart incomplets, recommandé 7 jours). 2. Job de réconciliation backend (périodique, liste ListMultipartUploads, aborte ceux associés à CANCELLED/FAILED > 24h).

Le §5.8 contractualise AbortMultipartUpload comme async best-effort. TC-ERR-07 mentionne les deux mécanismes de nettoyage.


E-09 (Majeur v1) — INV-08 (envelope encryption) sans critère d'acceptation

Statut v2 : CORRIGÉ

CA-13 v2 couvre INV-08 : « Aucun secret cryptographique (DEK, KEK, nonce brut) n'est persisté en clair en base de données. » TC-INV-08 teste via inspection directe des colonnes DB avec requête SQL pattern.


E-10 (Majeur v1) — INV-10 (no-sensitive-logs) sans critère d'acceptation

Statut v2 : CORRIGÉ

CA-14 v2 couvre INV-10 : « Aucun log ne contient de plaintext, clé, nonce brut, ou hash corrélable au contenu. » TC-INV-10 teste via scan automatisé des journaux avec patterns de détection.


E-11 (Majeur v1) — TC-INV-01 à TC-INV-10 sans GIVEN/WHEN/THEN

Statut v2 : CORRIGÉ

Tous les tests d'invariants TC-INV-01 à TC-INV-10 disposent désormais de scénarios GIVEN/WHEN/THEN complets en §5 du document tests.


E-12 (Majeur v1) — Purge mémoire Hermes best-effort vs INV-07 strict

Statut v2 : CORRIGÉ

INV-07 v2 différencie explicitement : « La purge mémoire RAM est best-effort sur Hermes/React Native (cf. H-06). » H-06 documente la contrainte. TC-NOM-06 et TC-INV-07 vérifient la purge disque stricte et la nullification mémoire best-effort. La distinction est contractualisée.


E-13 (Majeur v1) — FAILED → UPLOADING non spécifié

Statut v2 : CORRIGÉ

Le §5.4 v2 documente le flux de retry : « Le retry crée un nouveau flux complet : nouveau doc_id, nouveau nonce, nouveau chiffrement, nouvel upload. L'ancien enregistrement reste en état FAILED/PENDING. » La table §5.7 liste FAILED -> UPLOADING (nouveau flux complet, cf. §5.4). TC-NOM-08 et ST-09 testent ce scénario.


E-14 (Mineur v1) — TC-ERR-06 manquant

Statut v2 : CORRIGÉ

TC-ERR-06 existe dans la v2 et couvre les erreurs HTTP 4xx non retryables (400, 403, 404, 409, 413, 422) avec GIVEN/WHEN/THEN complet.


E-15 (Mineur v1) — Transport base64 nonce/auth_tag sans contractualisation

Statut v2 : CORRIGÉ

La table §3.2 v2 spécifie pour nonce et auth_tag : « binaire (base64 en transport) ». H-05 complète : « Le format de transport des champs binaires (nonce, auth_tag) est base64 côté API. »


E-16 (Bloquant v1) — Granularité nonce non spécifiée (file-level vs chunk-level)

Statut v2 : CORRIGÉ

Le §3.3 v2 introduit « Architecture de chiffrement (FILE-LEVEL) » avec règle explicite : « Un seul nonce par fichier. Interdit : chiffrement chunk-level (un nonce par chunk avec la même clé créerait une réutilisation de (key, nonce) et briserait la sécurité GCM). » INV-06 est reformulé avec « Un seul nonce par fichier (chiffrement FILE-LEVEL) ». TC-INV-06, TC-NR-06, TC-NEG-11 testent cette contrainte.


Écarts résiduels v2 (nouveaux ou non couverts par E-01→E-16)

ER-01 — TTL URL pré-signées : toujours non spécifié

Type : Non testable Référence : §5.6 SLA temporels, Q-02 Description : Le §5.6 mentionne « TTL des URL pré-signées non fourni dans le besoin (impact sécurité/disponibilité) » et Q-02 le liste comme point à clarifier. Aucune valeur contractuelle n'est fournie (défaut, min, max, comportement à expiration). Impact : Impossible de tester le comportement à expiration d'URL pré-signée. Risque sécurité (exposition temporelle indéfinie) et disponibilité (échecs upload silencieux). Gravité : Majeur (identique à v1, reconnu dans Q-02 mais non résolu)

ER-02 — Liste blanche MIME/UTType : toujours non spécifiée

Type : Non testable Référence : Q-03 Description : Q-03 est toujours ouvert. Aucune liste blanche de types MIME/UTType autorisés n'est fournie. Les tests de format MIME (TC-NEG-06) ne peuvent valider que la syntaxe RFC 6838, pas l'acceptabilité métier. Impact : Impossible de valider les types de fichiers autorisés au dépôt. Risque sécurité (upload de formats exécutables ?). Gravité : Majeur (identique à v1, reconnu dans Q-03 mais non résolu)

ER-03 — Persistance états UI après redémarrage app : toujours non définie

Type : Non testable Référence : Q-04 Description : Q-04 est toujours ouvert. Le comportement des états UI après un kill/redémarrage de l'app n'est pas spécifié. TC-NOM-05 teste seulement la continuité background → foreground, pas le redémarrage complet. Impact : Incohérence potentielle expérience utilisateur après force-quit. Gravité : Majeur (identique à v1)

ER-04 — Contrat backend exact des champs probatoires : toujours non fourni

Type : Non testable Référence : Q-05 Description : Q-05 est toujours ouvert. La table/schéma backend exact pour optimized, ios_transcoded et les champs probatoires n'est pas fourni. Impact : Risque de divergence mobile/backend sur la traçabilité légale. Gravité : Majeur (identique à v1)

ER-05 — Protocole d'audit mémoire RAM : toujours non défini

Type : Non testable Référence : Q-06, H-06 Description : Q-06 est toujours ouvert. H-06 documente la contrainte (purge RAM best-effort sur Hermes) mais aucun protocole d'audit mesurable n'est défini. Les tests vérifient la nullification des références (best-effort) mais pas l'effacement physique. Impact : La partie RAM de INV-07 n'est vérifiable que de manière symbolique. Gravité : Majeur (identique à v1, mais atténué par la contractualisation explicite du best-effort dans INV-07 et H-06)

ER-06 — Détection de transcodage iOS : mécanisme non spécifié

Type : Ambiguïté Référence : §5.1 étape 4, TC-NOM-04 Description : Le flux §5.1 étape 4 dit « Si source Photos et transcodage détecté ». Le mécanisme de détection du transcodage n'est pas contractualisé (comparaison UTType demandé vs reçu ? Vérification magic bytes ? API PHAsset ?). TC-NOM-04 suppose un « Asset Photos iOS connu comme transcodé » sans définir le critère de détection. Impact : L'implémenteur ne sait pas comment détecter un transcodage. Le test n'est pas reproductible sans ce critère. Gravité : Mineur (le comportement post-détection est bien spécifié, seul le critère de détection manque — acceptable comme détail d'implémentation si l'équipe mobile le connaît)

ER-07 — Transformation en mode capture optimisée : nature non spécifiée

Type : Ambiguïté Référence : §5.2 étape 3, §2 (Inclus) Description : Le flux §5.2 mentionne « le fichier probatoire devient la version transformée » et §3 définit le mode optimisé comme « version transformée ». Mais la nature de la transformation n'est jamais définie (compression JPEG ? Conversion de format ? Redimensionnement ?). Le §2 (Inclus) mentionne « Mode "capture optimisée" explicite » sans préciser le type de transformation. Impact : Les tests TC-NOM-03 et TC-INV-04 vérifient le consentement et la traçabilité mais pas la transformation elle-même. L'implémenteur ne sait pas quelle transformation appliquer. Gravité : Mineur (le consentement et la traçabilité sont contractualisés, la nature exacte de la transformation peut être considérée comme un détail produit à spécifier séparément)


Synthèse v2

Écarts v1 corrigés : 16/16

Écart v1 Gravité v1 Statut v2
E-01 Photos picker ambiguïté Majeur CORRIGÉ
E-02 READY→CANCELLED contradiction Bloquant CORRIGÉ
E-03 Format preuve consentement Majeur CORRIGÉ
E-04 Seuil 10 MB SI/binaire Mineur CORRIGÉ
E-05 Hash validation zero-knowledge Bloquant CORRIGÉ
E-06 Disclaimer EXIF sans test Majeur CORRIGÉ
E-07 Terminologie journal Mineur CORRIGÉ
E-08 AbortMultipartUpload orphelines Majeur CORRIGÉ
E-09 INV-08 sans CA Majeur CORRIGÉ
E-10 INV-10 sans CA Majeur CORRIGÉ
E-11 TC-INV sans GIVEN/WHEN/THEN Majeur CORRIGÉ
E-12 Purge mémoire Hermes strict/best-effort Majeur CORRIGÉ
E-13 FAILED→UPLOADING non spécifié Majeur CORRIGÉ
E-14 TC-ERR-06 manquant Mineur CORRIGÉ
E-15 Transport base64 sans contrat Mineur CORRIGÉ
E-16 Nonce file-level vs chunk-level Bloquant CORRIGÉ

Écarts résiduels v2 : 7

ID Type Gravité Résumé
ER-01 Non testable Majeur TTL URL pré-signées non spécifié (Q-02)
ER-02 Non testable Majeur Liste blanche MIME/UTType absente (Q-03)
ER-03 Non testable Majeur Persistance états UI après redémarrage (Q-04)
ER-04 Non testable Majeur Contrat backend champs probatoires (Q-05)
ER-05 Non testable Majeur Protocole audit mémoire RAM (Q-06)
ER-06 Ambiguïté Mineur Mécanisme détection transcodage iOS
ER-07 Ambiguïté Mineur Nature transformation mode optimisé

Observation

Les 7 écarts résiduels se répartissent en deux catégories : 1. ER-01 à ER-05 : Points déjà identifiés comme « à clarifier » (Q-01 à Q-06) dans la spec elle-même. La spec les reconnaît explicitement. Ce sont des dépendances externes (décisions produit/backend) et non des défauts de la spec. 2. ER-06, ER-07 : Ambiguïtés mineures sur des détails d'implémentation qui ne compromettent ni la testabilité des invariants ni la conformité sécurité.

Aucun écart bloquant résiduel. Les 3 bloquants v1 (E-02, E-05, E-16) sont tous corrigés. Les 5 majeurs résiduels sont des points explicitement reconnus comme non résolus (Questions Q-02 à Q-06) — la spec ne prétend pas les couvrir.