Aller au contenu

PD-101 — Scénarios de tests contractuels

1. Références

  • Spécification : PD-101-specification.md
  • Epic : EPIC-XX
  • JIRA : PD-101

2. Matrice de couverture

ID Invariant ID Critère ID Test Couverture Commentaire
INV-01-zero-knowledge CA-03 TC-INV-01 Oui Vérifie absence de payload clair en transit.
INV-02-pre-encryption CA-03 TC-INV-02 Oui Vérifie ordre strict chiffrement FILE-LEVEL avant upload.
INV-03-probatory-fidelity-default CA-01 TC-NOM-01 Oui Hash probatoire = hash fichier soumis (reçu par l'app) en mode fidèle.
INV-04-explicit-optimized-consent CA-02 TC-NOM-03 Oui Consentement explicite + traçabilité optimized=true + preuve §3.4.
INV-05-hash-functional-validation CA-11 TC-INV-05 Oui Validation fonctionnelle côté mobile (recalcul post-chiffrement).
INV-06-nonce-uniqueness CA-04 TC-INV-06 Oui Nonce unique par doc_id, un seul nonce FILE-LEVEL.
INV-07-sensitive-purge CA-10 TC-NOM-06 Oui purgeStale() exécuté avant chiffrement. Purge disque stricte, RAM best-effort (H-06).
INV-08-envelope-encryption CA-13 TC-INV-08 Oui Vérifie absence de secret en clair au repos en DB.
INV-09-state-transitions CA-08, CA-09 TC-INV-09 Oui Vérifie transitions autorisées/interdites UI+backend, y compris READY→CANCELLED.
INV-10-no-sensitive-logs CA-14 TC-INV-10 Oui Vérifie redaction logs sensibles.
CA-05 TC-ERR-01 Oui Refus >500 MB avant chiffrement/upload.
CA-06 TC-NOM-02 Oui Seuil 10 MB strict (9.99 simple / 10.00 multipart).
CA-07 TC-ERR-03 Oui Retry simple global vs multipart par chunk.
CA-08 TC-ERR-07 Oui Annulation orchestrée complète + état final.
CA-09 TC-NOM-05 Oui Continuité background + unicité notification.
CA-12 TC-NR-03 Oui Campagne perf P95 sur environnement contractuel.
CA-13 TC-INV-08 Oui Aucun secret crypto en clair en DB.
CA-14 TC-INV-10 Oui Aucun log avec plaintext/clé/nonce/hash corrélable.

3. Scénarios de test – Flux nominaux

TEST-ID: TC-NOM-01
Référence spec: INV-03, CA-01, Flux 5.1

GIVEN
  - Fichier de 20 MB valide (<= 500 MB), source File picker
  - Mode par défaut actif (optimized=false)
  - Connectivité réseau stable
WHEN
  - L'utilisateur confirme le dépôt
THEN
  - Le flux utilise multipart (>=10 MB)
  - L'état UI final est COMPLETED
  - Les états backend observés sont PENDING -> READY -> PENDING_SEAL
AND
  - Le hash probatoire stocké est identique au hash du fichier soumis (reçu par l'app)
  - Le chiffrement est FILE-LEVEL (un seul nonce pour tout le fichier)
TEST-ID: TC-NOM-02
Référence spec: CA-06, Flux 5.1, Paramètres 5.5

GIVEN
  - Fichier A de 9 999 999 bytes (< 10 000 000 bytes)
  - Fichier B de 10 000 000 bytes (= 10 MB SI base 10)
WHEN
  - L'upload est lancé pour A puis pour B
THEN
  - A est traité en upload simple
  - B est traité en upload multipart
AND
  - Aucun basculement de stratégie contraire au seuil fixe de 10 MB (SI base 10) n'est observé
TEST-ID: TC-NOM-03
Référence spec: INV-04, CA-02, Flux 5.2, §3.4

GIVEN
  - Fichier valide
  - Option "Capture optimisée" disponible mais inactive
WHEN
  - L'utilisateur active le mode optimisé et confirme explicitement l'avertissement
THEN
  - Le dépôt est marqué optimized=true
  - Le hash probatoire correspond à la version transformée
AND
  - Le journal d'audit contient la preuve de consentement explicite horodatée au format §3.4
  - Les metadata backend contiennent la preuve de consentement au format §3.4
  - Toute tentative de retour au mode fidèle pour ce dépôt est refusée
TEST-ID: TC-NOM-04
Référence spec: Flux 5.1 étape 4, ST-06

GIVEN
  - Asset Photos iOS connu comme transcodé
  - Parcours via Photos picker
WHEN
  - L'utilisateur sélectionne l'asset et choisit de continuer malgré l'avertissement
THEN
  - Un avertissement de transcodage est affiché avant poursuite
AND
  - ios_transcoded=true est enregistré dans les metadata backend
  - Le hash probatoire porte sur le fichier reçu par l'app (post-transcodage)
  - Le choix utilisateur (continuer/changer de source) est journalisé dans le journal d'audit
TEST-ID: TC-NOM-05
Référence spec: CA-09, Flux 5.3

GIVEN
  - Upload en état UPLOADING
  - App passant en arrière-plan puis retour au premier plan
WHEN
  - L'upload se termine pendant l'arrière-plan
THEN
  - Une seule notification locale est émise (succès ou échec)
  - Au retour foreground, l'état affiché correspond à l'état réel
AND
  - Aucun doublon de notification ni perte de progression n'est observé
TEST-ID: TC-NOM-06
Référence spec: INV-07, CA-10, ST-07

GIVEN
  - Présence d'artefacts sensibles obsolètes sur disque simulant un crash précédent
WHEN
  - Un nouveau flux d'upload démarre
THEN
  - purgeStale() est exécuté avant toute opération de chiffrement
AND
  - Les artefacts obsolètes sur disque sont supprimés et tracés dans le journal d'audit
  - Les références mémoire aux buffers sensibles sont nullifiées (best-effort Hermes, cf. H-06)
TEST-ID: TC-NOM-07
Référence spec: Flux 5.1 étape 5, ST-10

GIVEN
  - Fichier contenant des métadonnées EXIF (photo JPEG avec géolocalisation, modèle appareil)
WHEN
  - L'utilisateur sélectionne le fichier pour dépôt
THEN
  - Un disclaimer EXIF est affiché indiquant que les métadonnées seront conservées dans le fichier probatoire
  - L'upload ne peut PAS démarrer tant que l'utilisateur n'a pas confirmé explicitement
AND
  - La confirmation EXIF est journalisée dans le journal d'audit
TEST-ID: TC-NOM-08
Référence spec: Flux 5.4, ST-09

GIVEN
  - Un flux d'upload précédent terminé en état FAILED
WHEN
  - L'utilisateur retente le dépôt du même fichier
THEN
  - Un nouveau flux complet démarre avec un nouveau doc_id et un nouveau nonce
  - L'ancien enregistrement backend reste inchangé (état PENDING/FAILED)
AND
  - Aucune réutilisation de doc_id ou nonce de l'ancien flux
  - Le nouveau flux suit le parcours nominal complet (chiffrement, upload, finalisation)

4. Scénarios de test – Cas d'erreur

TEST-ID: TC-ERR-01
Référence spec: ERR-01, CA-05

GIVEN
  - Fichier de 700 MB
WHEN
  - L'utilisateur tente le dépôt
THEN
  - Rejet immédiat côté UX avec message explicite
  - Aucun chiffrement déclenché
  - Aucune initialisation backend/upload
AND
  - L'état UI n'entre pas en UPLOADING
TEST-ID: TC-ERR-02
Référence spec: ERR-02, INV-02, INV-07

GIVEN
  - Fichier valide
  - Injection d'un échec chiffrement local
WHEN
  - Le chiffrement est lancé
THEN
  - Le flux est interrompu immédiatement
  - L'état UI devient FAILED
AND
  - Les artefacts sensibles sont purgés
  - Aucune requête d'upload n'est émise
TEST-ID: TC-ERR-03
Référence spec: ERR-03/04/05, CA-07, Paramètres 5.5

GIVEN
  - Cas A: upload simple avec erreur retryable
  - Cas B: upload multipart avec erreur retryable sur un chunk
WHEN
  - L'erreur survient
THEN
  - Cas A: retry appliqué au niveau global du fichier
  - Cas B: retry appliqué uniquement au chunk en échec
AND
  - Nombre max de tentatives respecte Retry max configuré
  - Backoff exponentiel 1/2/4 + jitter actif observé
TEST-ID: TC-ERR-04
Référence spec: ERR-06, ERR-09

GIVEN
  - Requête API contenant métadonnée invalide (ex: sha3_256 non conforme)
WHEN
  - La requête est soumise
THEN
  - Réponse 400 est retournée
  - L'état backend READY n'est jamais atteint
AND
  - Le motif de validation est traçable dans le journal d'audit
TEST-ID: TC-ERR-05
Référence spec: ERR-08, CA-09

GIVEN
  - Upload terminé en background
  - Séquence de reprise foreground multiple
WHEN
  - Les événements de reprise sont déclenchés
THEN
  - Au plus une notification locale est émise pour la session d'upload
AND
  - Aucune duplication d'état COMPLETED/FAILED n'est présentée en UI
TEST-ID: TC-ERR-06
Référence spec: ERR-06

GIVEN
  - Upload en cours (simple ou multipart)
  - Le backend retourne un HTTP 4xx fonctionnel (400, 403, 404, 409, 413, 422)
WHEN
  - La réponse 4xx est reçue par le client
THEN
  - Aucun retry n'est tenté (erreur non retryable)
  - L'état UI passe immédiatement à FAILED
AND
  - Un message d'erreur explicite mappé au code HTTP est affiché à l'utilisateur
  - L'erreur est tracée dans le journal d'audit avec le code HTTP et le motif
TEST-ID: TC-ERR-07
Référence spec: ERR-07, CA-08, INV-09

GIVEN
  - Upload multipart en cours avec parts actives
WHEN
  - L'utilisateur annule explicitement
THEN
  - L'envoi client s'arrête
  - Le backend passe à CANCELLED
AND
  - AbortMultipartUpload est déclenché (best-effort, cf. §5.9)
  - Les parts multipart S3 restantes seront nettoyées par le job de réconciliation ou la lifecycle policy
  - Aucun retour vers un état non terminal n'est observé
TEST-ID: TC-ERR-08
Référence spec: ERR-10, §5.7 race condition, ST-11

GIVEN
  - Document en état backend READY
  - Worker d'ancrage prêt à transitionner READY -> PENDING_SEAL
WHEN
  - L'utilisateur demande l'annulation simultanément au worker d'ancrage
THEN
  - Un seul des deux réussit (atomicité UPDATE WHERE status='READY')
  - Si le worker gagne : l'annulation échoue, le client reçoit un message d'erreur explicite
  - Si l'annulation gagne : le backend passe à CANCELLED, le worker ne trouve plus de document READY
AND
  - Aucun état incohérent n'est observé (pas de CANCELLED + PENDING_SEAL simultanés)

5. Tests d'invariants (non négociables)

TEST-ID: TC-INV-01
Référence spec: INV-01-zero-knowledge, CA-03

GIVEN
  - Fichier valide de 5 MB (upload simple)
  - Fichier valide de 15 MB (upload multipart)
  - Proxy d'inspection réseau actif entre le client et le backend/S3
WHEN
  - Les deux uploads sont exécutés
THEN
  - Aucun payload réseau ne contient le contenu document en clair
  - Tous les payloads transmis sont du ciphertext AES-256-GCM
AND
  - Le proxy confirme l'absence de tout octet du plaintext original dans les requêtes HTTP
TEST-ID: TC-INV-02
Référence spec: INV-02-pre-encryption, CA-03

GIVEN
  - Fichier valide
  - Instrumentation des appels réseau et du module de chiffrement (timestamps)
WHEN
  - Le flux d'upload est exécuté
THEN
  - Le timestamp de fin de chiffrement FILE-LEVEL est strictement antérieur au timestamp du premier appel réseau d'upload
AND
  - Aucune requête d'upload n'est émise tant que le chiffrement n'est pas terminé
  - Le chiffrement produit un seul ciphertext pour l'ensemble du fichier (FILE-LEVEL)
TEST-ID: TC-INV-03
Référence spec: INV-03-probatory-fidelity-default, CA-01

GIVEN
  - Fichiers de formats variés (JPEG, PDF, DOCX, MP4) en mode par défaut
WHEN
  - Chaque fichier est soumis au flux de dépôt
THEN
  - Pour chaque fichier, le hash SHA3-256 du fichier soumis (reçu par l'app) est identique au hash probatoire stocké
AND
  - Aucune transformation (compression, conversion, redimensionnement) n'est appliquée
TEST-ID: TC-INV-04
Référence spec: INV-04-explicit-optimized-consent, CA-02

GIVEN
  - Fichier valide
  - Mode optimisé désactivé par défaut
WHEN
  - Tentative de dépôt en mode optimisé SANS confirmation explicite de l'avertissement
THEN
  - Le dépôt est bloqué
  - optimized reste false
AND
  - Aucune transformation n'est appliquée au fichier
  - Le journal d'audit ne contient pas de preuve de consentement
TEST-ID: TC-INV-05
Référence spec: INV-05-hash-functional-validation, CA-11

GIVEN
  - Fichier valide dont le contenu est connu
  - Corruption simulée : 1 bit modifié dans le plaintext après le premier calcul de hash
WHEN
  - Le mobile effectue le recalcul de vérification (étape 7 du flux 5.1)
THEN
  - La divergence entre le hash initial et le hash recalculé est détectée
  - Le flux est aborté (ERR-02)
AND
  - Le backend ne reçoit pas de requête d'upload
  - L'erreur de vérification d'intégrité est tracée dans le journal d'audit
TEST-ID: TC-INV-06
Référence spec: INV-06-nonce-uniqueness, CA-04

GIVEN
  - 100 dépôts successifs de fichiers valides (même fichier ou fichiers différents)
WHEN
  - Le nonce AES-GCM est généré pour chaque dépôt
THEN
  - Aucune collision de nonce n'est observée sur l'ensemble des 100 dépôts
AND
  - Chaque nonce est exactement 12 bytes
  - Un seul nonce est utilisé par fichier (chiffrement FILE-LEVEL, pas chunk-level)
TEST-ID: TC-INV-07
Référence spec: INV-07-sensitive-purge, CA-10

GIVEN
  - Artefacts sensibles simulés sur disque (fichier clair, clé temporaire, buffer intermédiaire)
  - Simulation de crash précédent (artefacts résiduels)
WHEN
  - Un nouveau flux d'upload démarre
THEN
  - purgeStale() est exécuté en premier, avant toute opération de chiffrement
  - Tous les fichiers sensibles résiduels sur disque sont supprimés
AND
  - Les suppressions sont tracées dans le journal d'audit
  - Les références mémoire sont nullifiées (vérification best-effort sur Hermes, cf. H-06)
TEST-ID: TC-INV-08
Référence spec: INV-08-envelope-encryption, CA-13

GIVEN
  - Un dépôt complété avec succès (état READY ou PENDING_SEAL)
  - Accès lecture à la base de données backend
WHEN
  - Inspection directe des colonnes contenant des données cryptographiques
THEN
  - Aucune DEK, KEK ou nonce brut n'est stocké en clair
  - Tous les secrets sont chiffrés par envelope encryption (AES-256-GCM ou HSM envelope)
AND
  - La requête SQL `SELECT * FROM ... WHERE column LIKE '%plaintext_pattern%'` ne retourne aucun résultat pour les colonnes crypto
TEST-ID: TC-INV-09
Référence spec: INV-09-state-transitions, §5.7

GIVEN
  - Machine à états UI (UPLOADING, FAILED, COMPLETED, CANCELLED)
  - Machine à états backend (PENDING, READY, PENDING_SEAL, CANCELLED)
WHEN
  - Tentative de chaque transition possible (autorisée et interdite) selon la table §5.7
THEN
  - Toutes les transitions autorisées réussissent
  - Toutes les transitions interdites sont rejetées
AND
  - COMPLETED et CANCELLED (UI) sont terminaux : aucune sortie possible
  - CANCELLED (backend) est terminal : aucune sortie possible
  - READY -> CANCELLED est autorisée avec garde atomique (UPDATE WHERE status='READY')
  - PENDING_SEAL -> CANCELLED est interdite
  - FAILED -> UPLOADING crée un nouveau flux (nouveau doc_id, cf. §5.4)
TEST-ID: TC-INV-10
Référence spec: INV-10-no-sensitive-logs, CA-14

GIVEN
  - Un flux d'upload complet (de la sélection à la finalisation)
  - Collecte de tous les journaux applicatifs et d'audit
WHEN
  - Scan automatisé des journaux avec patterns de détection :
    - Plaintext du fichier original
    - Clés de chiffrement (DEK, KEK)
    - Nonces bruts (12 bytes en hex ou base64)
    - Hash corrélable au contenu sans justification métier
THEN
  - Aucun pattern sensible n'est détecté dans les journaux
AND
  - Les identifiants de corrélation (doc_id, correlation_id) sont présents mais ne permettent pas de reconstituer le contenu

6. Tests de non-régression

Test ID Objet Observable Commentaire
TC-NR-01 Seuil multipart fixe 10 MB (10 000 000 bytes SI) Comportement inchangé 9 999 999 / 10 000 000 bytes Empêche dérive de seuil produit.
TC-NR-02 Règles de transitions terminales Absence de sortie depuis COMPLETED/CANCELLED Protection machine à états.
TC-NR-03 Performance 100 MB P95 <= 30 s (WiFi iPhone 12/A14) Rapport campagne P95 Non bloquant métier mais suivi qualité.
TC-NR-04 Retry + jitter Backoff observé et jitter actif Évite régression réseau/thundering herd.
TC-NR-05 purgeStale au démarrage Trace d'exécution systématique Évite fuite post-crash au fil versions.
TC-NR-06 Chiffrement FILE-LEVEL (un seul nonce par fichier) Vérification qu'aucun chiffrement chunk-level n'est introduit Empêche régression sécurité GCM.

7. Tests négatifs et adversariaux

Test ID Entrée invalide / abus Résultat attendu Observable
TC-NEG-01 doc_id non UUID v4 Rejet 400 Code retour + motif validation
TC-NEG-02 sha3_256 uppercase ou longueur != 64 Rejet 400 Journal d'audit validation + absence READY
TC-NEG-03 nonce longueur != 12 bytes Échec chiffrement ou rejet 400 selon point de contrôle Trace erreur crypto/validation
TC-NEG-04 auth_tag longueur != 16 bytes Rejet 400 Réponse API déterministe
TC-NEG-05 optimized non booléen ("true") Rejet 400 Contrôle type strict
TC-NEG-06 mime_type invalide RFC Rejet 400 Absence de transition upload
TC-NEG-07 Tentative transition backend PENDING_SEAL -> CANCELLED Transition refusée Journal d'audit état invariant
TC-NEG-08 Désactivation jitter en configuration Non-conformité contractuelle Vérification config + exécution retry
TC-NEG-09 Tentative upload en clair injectée Rejet/échec conformité Analyse trafic + journal d'audit sécurité
TC-NEG-10 Logs incluant nonce brut/clé/hash sensible Non-conformité sécurité Scan journaux et rapport violation
TC-NEG-11 Tentative de chiffrement chunk-level (nonce par chunk) Rejet/non-conformité Vérification qu'un seul nonce est utilisé par doc_id

8. Observabilité requise pour les tests

  • État système : machine d'états UI (UPLOADING/FAILED/COMPLETED/CANCELLED) et backend (PENDING/READY/PENDING_SEAL/CANCELLED) horodatées.
  • Réponse API : codes HTTP, payload de validation, identifiants corrélables de session/test.
  • Journal d'audit : consentement optimisé (format §3.4), confirmation EXIF, déclenchement annulation, transitions d'états, trace purgeStale(), ios_transcoded, race condition READY→CANCELLED.
  • Événement signé / horodaté : finalisation upload, passage READY -> PENDING_SEAL, notification background.
  • Export probatoire : métadonnées contractuelles (doc_id, optimized, ios_transcoded, hash probatoire, taille, mime, timestamps).
  • Télémétrie réseau : inspection payload (absence clair), retries, backoff, jitter, latences.
  • Télémétrie sécurité : détection secrets en logs et contrôle artefacts au repos.
  • Télémétrie chiffrement : timestamps chiffrement, nombre de nonces générés par flux, vérification FILE-LEVEL.

9. Règles non testables

Règle Raison Impact
TTL URL pré-signées (Q-02) Paramètre contractuel absent (défaut/min/max/comportement expiration non défini) Majeur
Liste blanche MIME/UTType (Q-03) Politique d'acceptation non spécifiée Majeur
Persistance états UI après redémarrage (Q-04) Comportement cible non défini Majeur
Contrat backend exact des champs probatoires (Q-05) Schéma de vérité backend non fourni Majeur
Exigence formelle de nettoyage mémoire RAM (Q-06) Critère d'audit mesurable non défini ; purge RAM best-effort sur Hermes (H-06) Majeur
Référence épique nominale (Q-01) Référencement documentaire incomplet (non bloquant test exécutable) Mineur

10. Verdict QA

  • ⚠️ Testable partiellement (avec réserves listées)

Motif : - Les invariants et critères d'acceptation sont couverts par des scénarios déterministes et automatisables. - Les tests d'invariants (TC-INV-01 à TC-INV-10) disposent désormais de scénarios GIVEN/WHEN/THEN complets. - La conformité complète reste conditionnée à la levée des points non testables (TTL, whitelist MIME, persistance UI, contrat backend, protocole d'audit mémoire).