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.