Aller au contenu

PD-103 — Rapport d'audit Spécification v3 ↔ Tests v3

Auditeur : PMO indépendant | Date : 2026-04-03 | Documents : PD-103-specification.md (v3), PD-103-tests.md (v3)


Synthèse

Gravité Nombre
Bloquant 1
Majeur 4
Mineur 5

ECT-01 — upload_object_key non défini mais inclus dans le fingerprint canonique

Type : Ambiguïté + Incohérence Spec↔Tests Référence : Spec §5.12 (payload canonique JSON), §5.1 (modèle de données) Description : Le champ upload_object_key apparaît dans la définition normative du payload canonique d'idempotence (§5.12) mais : - N'est PAS défini dans le modèle de données §5.1 (aucune ligne dans le tableau) - N'a aucune validation (format, taille, jeu caractères) - N'est pas explicitement listé dans le corps requis du POST (§5.12 dit "références upload S3" sans nommer ce champ) - N'apparaît dans AUCUN test (TC-NOM-15, TC-INV-06 ne le mentionnent pas)

Impact : Le fingerprint canonique ne peut pas être calculé de manière déterministe sans ce champ. Toute implémentation devra deviner son format et sa provenance (mobile ou backend ?). De plus, si upload_object_key change entre un upload initial et un retry différé (nouvelle URL pré-signée = potentiellement nouveau S3 key), le fingerprint diverge et la reprise différée produit 409 Conflict au lieu de 200 idempotent — contradiction directe avec INV-103-24 et le flux §5.5 step 13.

Gravité : Bloquant


ECT-02 — Q-103-07 (rétention locale légale) silencieusement retiré sans résolution

Type : Risque sécu/conformité Référence : Tests v2 §9 (classé BLOQUANT), Spec v3 §10.2, Tests v3 §9 Description : Le point Q-103-07 ("Politique légale de conservation locale en mode différé au-delà du TTL") était classé Bloquant dans les tests v2 §9. En v3, il a été retiré de la liste §10.2 et de la liste §9 des règles non testables. La résolution invoquée (purge immédiate après UPLOADED, §5.3 postUploadLocalPurgeDelay) ne couvre que le cas post-upload. Le cas UPLOAD_DEFERRED conserve un payload chiffré localement jusqu'à 24h (§5.2 TTL 86400s) sans cadrage juridique formalisé.

Impact : Risque conformité RGPD/vie privée pour la rétention locale de données chiffrées sur device mobile pendant 24h sans politique légale validée.

Gravité : Majeur


ECT-03 — Pas d'annulation utilisateur depuis UPLOAD_DEFERRED

Type : Hypothèse dangereuse Référence : Spec §5.7 (machine à états), INV-103-38 Description : La machine à états v3 autorise depuis UPLOAD_DEFERRED uniquement : UPLOADING (reprise réseau) et CANCELLED (TTL expiré uniquement, INV-103-38). Il n'existe aucune transition d'annulation utilisateur explicite depuis UPLOAD_DEFERRED. Un utilisateur dont la capture est en différé doit attendre soit le retour réseau, soit l'expiration du TTL (jusqu'à 24h) sans pouvoir annuler manuellement. Aucun test ne couvre ce scénario car il n'est pas spécifié.

Impact : Expérience utilisateur dégradée. L'utilisateur ne peut pas supprimer une capture différée qu'il souhaite annuler. Incohérence avec la philosophie de contrôle utilisateur (INV-103-21 permet l'annulation depuis CAPTURED, INV-103-29 depuis UPLOADING).

Gravité : Majeur


ECT-04 — Idempotence fragile si upload_object_key varie entre retries

Type : Contradiction Référence : Spec §5.12 (canonical payload), §5.5 step 10 (redemande URL pré-signée), INV-103-24 Description : Le flux de reprise différée (§5.5 step 10) exige de redemander une nouvelle URL pré-signée S3 à chaque reprise. Si la nouvelle URL pointe vers un S3 object key différent (comportement courant avec les clés pré-signées horodatées ou UUID-based), alors le champ upload_object_key du payload canonique change, produisant un fingerprint SHA-256 différent. Le backend répondrait 409 Conflict au lieu de 200 idempotent, bloquant la reprise.

Impact : Contradiction entre le contrat d'idempotence (INV-103-37) et le contrat de reprise différée (INV-103-24). Aucun test ne couvre ce cas de figure.

Gravité : Majeur


ECT-05 — Champs timestamp_device, device_id, app_version exclus du canonique sans justification

Type : Hypothèse dangereuse Référence : Spec §5.12 (payload canonique), §5.1 Description : Le payload canonique d'idempotence (§5.12) exclut timestamp_device, device_id et app_version sans justification explicite. Un replay avec le même capture_id et content_hash mais un timestamp_device différent (ou un device_id différent) sera considéré 200 idempotent. Ceci pourrait masquer un scénario d'attaque où un attaquant ayant capturé un capture_id le rejoue depuis un autre device.

Impact : Risque d'usurpation si un capture_id est intercepté. L'exclusion peut être légitime (le capture_id étant UUID v4 aléatoire) mais la décision n'est pas documentée ni testée (aucun test adversarial couvrant replay cross-device).

Gravité : Majeur


DIV-01 — Diagramme de séquence ne montre pas la purge locale post-upload

Type : Incohérence Spec↔Tests (5bis — cohérence diagrammes) Référence : Spec §5bis (diagramme de séquence), §5.5 step 7, INV-103-38, CA-103-27 Description : Le diagramme de séquence montre UPLOADING -> UPLOADED + purge locale immediate dans le bloc alt "unwrap OK", mais comme annotation inline du participant App Mobile. L'action de purge n'est pas un message séparé et n'apparaît pas comme une étape distincte vérifiable dans le diagramme. Les tests (TC-NOM-17) testent cette purge comme un comportement distinct.

Impact : Un implémenteur lisant uniquement le diagramme pourrait manquer l'obligation de purge immédiate.

Gravité : Mineur


DIV-02 — Diagramme de séquence ne couvre pas le flux multipart

Type : Incohérence Spec↔Tests (5bis — cohérence diagrammes) Référence : Spec §5bis, §5.5bis Description : Le diagramme de séquence ne montre que le flux single-part (un seul PUT S3). Le flux multipart (§5.5bis) avec ses spécificités (upload_id, parts multiples, CompleteMultipartUpload, AbortMultipartUpload, reprise partielle) n'a pas de diagramme de séquence dédié. La spec a >= 2 services et des opérations crypto impliqués dans le multipart.

Impact : Lisibilité réduite pour les implémenteurs du flux multipart.

Gravité : Mineur


DIV-03 — Terminologie incohérente "bloquées" vs "orphelines" dans TC-INV-07

Type : Ambiguïté terminologique Référence : Tests §5 TC-INV-07 GIVEN ("captures non terminales bloquées"), Spec §5.9 réconciliation ("scan états non-terminaux") Description : TC-INV-07 utilise "captures non terminales bloquées injectées" dans le GIVEN, tandis que la spec parle de "scan états non-terminaux" et de "captures orphelines" (seuil orphelin). Le terme "bloquées" n'est pas défini dans le glossaire §3. TC-INV-11 utilise correctement "orphelin S3" pour le GC.

Impact : Ambiguïté mineure sur les conditions d'entrée du test.

Gravité : Mineur


DIV-04 — device_id : casse "insensitive hex" sans normalisation explicite

Type : Ambiguïté Référence : Spec §5.1 (device_id casse "insensitive hex"), §5.1 (capture_id casse "canonical lower") Description : capture_id a une politique de normalisation explicite (INV-103-31 : lowercase avant stockage/comparaison). device_id est marqué "insensitive hex" mais aucun invariant ni aucune règle de normalisation n'est définie. Le comportement de comparaison backend (lookup par device_id) n'est pas spécifié. Aucun test ne couvre la normalisation de device_id.

Impact : Risque de duplicats ou lookups échoués si le backend compare device_id de manière case-sensitive.

Gravité : Mineur


DIV-05 — Échec AbortMultipartUpload non couvert

Type : Hypothèse dangereuse Référence : Spec INV-103-29, §5.5bis step 8, ER-103-16 Description : INV-103-29 et §5.5bis step 8 exigent l'annulation de l'upload S3 multipart (AbortMultipartUpload) lors d'une annulation utilisateur. Aucun cas d'erreur ne couvre la situation où l'appel AbortMultipartUpload échoue (réseau KO, S3 indisponible). Les parts uploadées resteraient orphelines sur S3 jusqu'au GC (INV-103-33) après orphanTtl. Aucun test ne couvre ce scénario.

Impact : Fenêtre de rétention non maîtrisée d'artefacts chiffrés sur S3 si l'abort échoue. Le GC orphelins finit par nettoyer, mais le comportement intermédiaire n'est pas contractualisé.

Gravité : Mineur


Matrice récapitulative

ID Type Gravité Résumé
ECT-01 Ambiguïté + Incohérence Spec↔Tests Bloquant upload_object_key non défini dans §5.1, inclus dans fingerprint canonique, absent des tests
ECT-02 Risque sécu/conformité Majeur Q-103-07 (rétention légale locale 24h) retiré de BLOQUANT sans résolution pour UPLOAD_DEFERRED
ECT-03 Hypothèse dangereuse Majeur Aucune annulation utilisateur possible depuis UPLOAD_DEFERRED
ECT-04 Contradiction Majeur upload_object_key variable casse l'idempotence en reprise différée
ECT-05 Hypothèse dangereuse Majeur Exclusion de timestamp_device/device_id du canonique non justifiée ni testée adversarialement
DIV-01 Incohérence diagramme Mineur Purge locale post-upload non visible comme étape distincte dans le diagramme de séquence
DIV-02 Incohérence diagramme Mineur Absence de diagramme de séquence pour le flux multipart
DIV-03 Ambiguïté terminologique Mineur "bloquées" (tests) vs "non-terminaux" (spec) dans TC-INV-07
DIV-04 Ambiguïté Mineur device_id sans règle de normalisation contrairement à capture_id
DIV-05 Hypothèse dangereuse Mineur Échec AbortMultipartUpload non contractualisé ni testé