Aller au contenu

PD-283 — Expression de besoin

1. Contexte et motivation

PD-85 (backend) prépare le dossier probatoire logique : validation des ProofEnvelopes (RFC PV-PROOF-001 v1.2.0), génération du manifest d'intégrité, chronologie consolidée, URLs signées de téléchargement, guide de procédure statique et README de vérification.

PD-283 est le dernier maillon : côté client, en mode Zero-Knowledge, l'app télécharge les artefacts chiffrés, les déchiffre localement, et assemble le ZIP final prêt à être remis à un commissariat, un avocat ou un procureur.

Pourquoi maintenant

  • PD-85 (backend export) est en cours de finalisation — l'API POST /exports/complaint-file sera disponible.
  • PD-282 (ProofEnvelope seal eIDAS) a finalisé le format d'enveloppe auto-vérifiable.
  • PD-34 (key derivation) et PD-242 (recovery envelope) fournissent l'infrastructure cryptographique client pour le déchiffrement local.
  • Le cadre juridique français (art. 1366 Code civil) rend l'auto-portance du dossier critique : un ZIP dont l'intégrité est vérifiable indépendamment a une valeur probante supérieure à des captures d'écran.

Learnings injectés

  • PD-276 : Zero-knowledge validation pattern — validate-only, no key derivation côté serveur.
  • PD-262 : Injection fichiers natifs Swift/ObjC obligatoire pour reviews LLM (stories app avec composant natif).
  • PD-276 : Qualifier INV probatoire partiel dès v1.

2. Objectif

Permettre à un utilisateur (ou son représentant légal) d'assembler localement un dossier probatoire complet, auto-porteur et vérifiable au format .pvproof (conteneur ZIP avec extension dédiée), à partir des données fournies par l'API PD-85, sans qu'aucun contenu en clair ne transite par le serveur.

Format .pvproof — RFC PV-PACK-001

Le fichier exporté est conforme au RFC PV-PACK-001 v1.0.0 (ProbatioVault Proof Package Format).

Résumé du RFC : - Extension .pvproof (conteneur ZIP avec extension dédiée) - Fichier pvproof.json en première entrée de l'archive (mode STORED, sans compression) - Structure normalisée : preuves/, enveloppes/, manifest, chronology, readme, guide - 6 invariants de format (INV-PACK-01 à INV-PACK-06) - Règles de validation structurelle (12 règles, 13 codes d'erreur) - Sanitisation obligatoire des noms de fichiers (path traversal, zip slip) - Passthrough strict des artefacts backend

Référence complète : ProbatioVault-doc/docs/normes/pv-pack/RFC-PV-PACK.md

3. Périmètre V1 — Must-have

3.1 Appel API backend (PD-85)

L'app appelle POST /exports/complaint-file avec la liste des proofIds sélectionnés par l'utilisateur. Le backend retourne :

  • manifest.json (inventaire, integrityHash SHA3-256)
  • chronology.json (événements probatoires ordonnés)
  • signedUrls[] (URLs pré-signées S3, TTL ≤ 30 min)
  • guideUrl (guide_plainte_france.pdf)
  • readmeVerification (texte de vérification inline)
  • rejectedProofs[] (preuves rejetées avec motifs)

3.2 Téléchargement des fichiers chiffrés

  • Téléchargement séquentiel des fichiers via les URLs signées
  • Retry automatique : maxRetries = 3, délai exponentiel (1s, 2s, 4s)
  • Si URL expirée → demander un refresh au backend (nouvel appel API)
  • Si fichier introuvable → abort de l'export avec message explicite
  • Si échec final après retries → proposer à l'utilisateur de réessayer

3.3 Déchiffrement local (Zero-Knowledge)

  • Dérivation de K_doc à partir de kmaster (PD-34) pour chaque fichier
  • Déchiffrement AES-256-GCM en mémoire (1 fichier à la fois)
  • Aucun contenu en clair ne persiste sur disque en dehors du ZIP final
  • Les fichiers temporaires déchiffrés sont écrits directement dans le stream ZIP

3.4 Assemblage ZIP structuré (streaming disque)

Architecture obligatoire : assemblage en streaming, 1 fichier en mémoire max. Pas de ZIP en mémoire (crash mobile garanti sur 500 MB).

Processus par fichier : 1. Download fichier chiffré 2. Decrypt en mémoire 3. Append au ZIP sur disque 4. Delete fichier temporaire

Structure interne du conteneur .pvproof :

PV-Dossier-Plainte_{YYYY-MM-DD}_{exportId-short}.pvproof
├── pvproof.json                        ← déclaration de format (PREMIER fichier, obligatoire)
├── manifest.json                       ← inventaire + integrityHash (depuis backend)
├── chronology.json                     ← événements probatoires ordonnés (depuis backend)
├── README_VERIFICATION.txt             ← instructions de vérification (depuis backend)
├── guide_plainte_france.pdf            ← guide de procédure (depuis backend guideUrl)
├── preuves/
│   ├── {originalFilename-1}            ← fichier original déchiffré
│   ├── {originalFilename-2}
│   └── ...
└── enveloppes/
    ├── {proofId-1}-envelope.json       ← ProofEnvelope RFC PV-PROOF-001
    ├── {proofId-2}-envelope.json
    └── ...

Nommage du fichier : PV-Dossier-Plainte_{date}_{exportId-8chars}.pvproof Exemple : PV-Dossier-Plainte_2026-03-09_a1b2c3d4.pvproof

3.5 Calcul et affichage du hash SHA3-256

  • Après assemblage complet du .pvproof, calcul du hash SHA3-256 en streaming sur le fichier final (pas de chargement complet en mémoire — peut prendre 1-4s sur 500 MB mobile)
  • Affichage du hash à l'utilisateur (copier/coller possible)
  • Ce hash est informatif (vérification de transmission intacte). La force probante juridique repose sur les ProofEnvelopes individuelles (seal HSM, Merkle, TSA, blockchain anchor) — pas sur le hash du conteneur, qui n'est ni scellé ni ancré

3.6 UX — Progression multi-étapes

Progression obligatoire. Pas de spinner. L'export peut durer 10 à 60 secondes.

Écran de progression :

Préparation du dossier
──────────────────────

⬇ Téléchargement preuves (3 / 12)
🔓 Déchiffrement fichiers (5 / 12)
📦 Assemblage du dossier
✔ Finalisation

Chaque étape affiche le nombre traité / total. Si blocage détectable, l'utilisateur peut identifier l'étape en cause.

3.7 Partage et sauvegarde post-assemblage

Après génération du ZIP, écran avec 3 actions :

  • Partager → share sheet native iOS (AirDrop, Mail, Files, Drive, WhatsApp...)
  • Sauvegarder → enregistrer dans Files
  • Supprimer → suppression immédiate du ZIP

3.8 Rappel et suppression du .pvproof (privacy)

Rappel à 24h (notification locale) : "Votre dossier probatoire est toujours sur l'appareil. Pensez à le partager ou le sauvegarder."

Suppression manuelle uniquement — pas d'auto-suppression (risque de perte de preuve si l'utilisateur a oublié de partager).

L'écran du dossier affiche en permanence : "Données sensibles — supprimez ce fichier après l'avoir transmis à votre avocat ou aux autorités."

Justification : la suppression automatique est dangereuse pour un dossier probatoire que l'utilisateur pourrait avoir besoin de retransmettre.

3.9 Gestion des rejets partiels

Si le backend retourne des rejectedProofs :

  • Afficher la liste des preuves rejetées avec motifs
  • Proposer de continuer avec les preuves valides uniquement
  • Si l'utilisateur confirme → procéder à l'assemblage partiel
  • Si toutes les preuves sont rejetées (422) → message explicite, pas d'assemblage

4. Hors périmètre V1 — Reporté

Fonctionnalité Raison du report Story V2
Android Story dédiée À créer
PWA / Web Story dédiée À créer
Timeline PDF riche Moteur de rendu PDF complexe PD-283 V2
Script de vérification automatisé Complexité multi-plateforme V2 backend
Chiffrement du .pvproof lui-même Le conteneur contient des fichiers en clair — chiffrement optionnel V2 À évaluer
Outil CLI pv verify Vérificateur en ligne de commande pour .pvproof RFC PV-PACK-001 §10
Enregistrement MIME type application/vnd.probatiovault.proof Association OS pour ouverture automatique V2
Export en arrière-plan (background task) iOS limite les background tasks — V1 foreground uniquement V2

5. Use cases principaux

UC-01 : Export nominal (adulte, Premium, iOS)

  1. L'utilisateur Premium sélectionne 5 preuves scellées
  2. L'app appelle POST /exports/complaint-file avec les 5 proofIds
  3. Le backend retourne manifest + chronology + signedUrls + guide + readme
  4. Progression : téléchargement ⅕, ⅖... déchiffrement ⅕, ⅖... assemblage
  5. ZIP final assemblé sur disque (streaming)
  6. Hash SHA3-256 calculé et affiché
  7. Écran : Partager / Sauvegarder / Supprimer
  8. L'utilisateur partage le .pvproof via AirDrop à son avocat
  9. Rappel à 24h si le fichier est toujours présent

Identique à UC-01, avec ajouts : - Le représentant légal initie l'export pour le compte du mineur - Le manifest backend inclut automatiquement les évidences additionnelles (Mandate, Dual Validation, ReKey Lifecycle) - L'app assemble ces évidences dans le ZIP sans traitement spécifique (passthrough)

UC-03 : Export partiel avec preuves rejetées

  1. L'utilisateur sélectionne 10 preuves
  2. L'app appelle le backend → 2 preuves rejetées (INV-02, INV-03)
  3. L'app affiche : "2 preuves ne peuvent pas être incluses" + motifs
  4. L'utilisateur confirme : continuer avec les 8 preuves valides
  5. Assemblage du .pvproof avec 8 preuves

UC-04 : Échec réseau pendant téléchargement

  1. Téléchargement en cours (preuve 7/12)
  2. Perte réseau → retry automatique (1s, 2s, 4s)
  3. Si 3 retries échoués → message : "Impossible de télécharger 1 preuve. Voulez-vous réessayer ?"
  4. L'utilisateur réessaie → succès
  5. Assemblage continue

UC-05 : URL signée expirée

  1. L'utilisateur a mis l'app en background pendant le téléchargement
  2. Retour au premier plan → URL expirée (> 30 min)
  3. L'app détecte l'expiration → demande de nouvelles URLs au backend (nouvel appel API)
  4. Téléchargement reprend avec les nouvelles URLs

UC-06 : Export bloqué (utilisateur gratuit)

  1. L'utilisateur gratuit tente l'export
  2. Le backend retourne 403 (plan FREE)
  3. L'app affiche le message de blocage + CTA Premium (conformément à PD-84)
  4. Bouton export grisé pour les utilisateurs gratuits

6. Architecture haut niveau

6.1 Flux de données

┌──────────────┐    POST /exports/complaint-file    ┌──────────────┐
│              │ ─────────────────────────────────> │              │
│   App iOS    │                                    │   Backend    │
│  (PD-283)    │ <───────────────────────────────── │   (PD-85)    │
│              │   { manifest, chronology,          │              │
│              │     signedUrls, guide, readme }    │              │
│              │                                    │              │
│              │    GET signedUrl (x N preuves)     │   S3 WORM    │
│              │ ─────────────────────────────────> │   (PD-4/44)  │
│              │ <───────────────────────────────── │              │
│              │    fichiers chiffrés               │              │
└──────┬───────┘                                    └──────────────┘
       │ Pour chaque fichier :
       │   1. Download (chiffré)
       │   2. Decrypt (K_doc via kmaster, PD-34)
       │   3. Append au .pvproof (streaming disque)
       │   4. Delete temp
   .pvproof sur disque (conteneur ZIP, extension dédiée)
       │ SHA3-256(.pvproof)
   Share sheet / Save / Delete
   Auto-delete 24h

6.2 Responsabilités

Composant Responsabilité Justification
Backend (PD-85) Validation RFC, manifest, chronologie, URLs signées, guide, readme Cohérence probatoire, contrôle d'accès
App iOS (PD-283) Téléchargement, déchiffrement, assemblage .pvproof streaming, hash final, UX progression, share sheet Zero-Knowledge : le serveur ne voit jamais le clair
S3 WORM (PD-4/44) Stockage des fichiers chiffrés Immuabilité
Crypto client (PD-34) Dérivation K_doc depuis kmaster Infrastructure cryptographique

6.3 Choix multi-plateforme

Décision Choix V1 Compatibilité future
Plateforme cible iOS (React Native) Android + PWA dans stories dédiées
Librairie ZIP react-native-zip-archive ou JSZip streaming JSZip compatible web, zip-archive compatible Android
Crypto Existing crypto module PD-34 (kmaster derivation) Abstraction crypto cross-platform
Share iOS share sheet (react-native-share) Android share intent natif
Hash SHA3-256 js-sha3 ou noble-hashes Cross-platform JS
Stockage temp iOS app sandbox (tmp/) Android cache dir / Web Blob

7. Invariants et contraintes

7.1 Invariants propres à PD-283

ID Règle Justification
INV-283-01 Aucun contenu probatoire en clair ne persiste hors du .pvproof final Zero-Knowledge constitutionnel — fichiers temp supprimés immédiatement
INV-283-02 L'assemblage .pvproof est en streaming disque (1 fichier en mémoire max) Prévention OOM mobile (crash garanti à 500 MB en RAM)
INV-283-03 Le hash SHA3-256 est calculé en streaming sur le fichier .pvproof final complet Hash informatif (vérification de transmission) — pas de force probante juridique propre
INV-283-04 Un rappel de suppression est émis 24h après génération (notification locale) Privacy — données sensibles, mais suppression automatique interdite (risque perte preuve)
INV-283-05 Les fichiers temporaires chiffrés sont supprimés après déchiffrement Réduction surface d'exposition
INV-283-06 Le retry de téléchargement suit un backoff exponentiel (3 tentatives max) Résilience réseau sans boucle infinie
INV-283-07 L'app ne modifie aucun artefact reçu du backend (manifest, chronology, envelopes) Intégrité probatoire — passthrough strict
INV-283-08 Le fichier pvproof.json est le PREMIER entry de l'archive, écrit en mode STORED (sans compression) Convention conteneur identique à mimetype dans EPUB — détection de format par offset fixe
INV-283-09 L'extension du fichier exporté est .pvproof (jamais .zip) Identité protocolaire ProbatioVault
INV-283-10 Les noms de fichiers originaux sont sanitizés avant insertion dans l'archive (suppression ../, caractères spéciaux, longueur bornée) Prévention path traversal / zip slip — un fichier uploadé nommé ../../manifest.json ne doit jamais écraser un fichier racine

7.2 Invariants hérités

ID Règle Source
INV-85-01 Le backend ne déchiffre jamais les documents exportés PD-85 (Zero-Knowledge)
INV-85-04 Les URLs signées expirent en ≤ 30 minutes PD-85
INV-85-07 Taille totale exportée : recommandé < 500 MB, supporté ≤ 1 GB PD-85 — 1 GB reste très lourd sur mobile (stockage, partage)

7.3 Contraintes produit

  • UX : progression multi-étapes obligatoire (pas de spinner)
  • Privacy : rappel 24h + suppression manuelle (pas d'auto-suppression)
  • Réseau : retry 3x avec backoff exponentiel
  • Mémoire : streaming obligatoire, jamais de ZIP en RAM complète
  • Multi-plateforme : choix techniques compatibles Android et PWA futurs

8. Dépendances

8.1 Dépendances amont (requises)

Story Composant Statut Impact
PD-85 Backend export dossier plainte En cours API POST /exports/complaint-file
PD-34 Key derivation (kmaster) DONE Dérivation K_doc pour déchiffrement local
PD-242 Recovery Envelope DONE Gestion des clés de récupération
PD-282 ProofEnvelope seal eIDAS DONE Format enveloppe auto-vérifiable
PD-84 Offre gratuite B2C-Mineurs DONE Contrôle Premium / CTA
PD-4/44 S3 WORM + Object Lock DONE Stockage des fichiers chiffrés

8.2 RFC et normes

Référence Usage
RFC PV-PACK-001 v1.0.0 Format conteneur .pvproof (structure, validation, invariants)
RFC PV-PROOF-001 v1.2.0 Format ProofEnvelope (passthrough)
RFC 8785 (JCS) Canonicalisation JSON (manifest, non modifié par l'app)
Art. 1366 Code civil Valeur probante de l'écrit électronique

9. Critères d'acceptation préliminaires

Fonctionnels

  • L'app appelle POST /exports/complaint-file et traite la réponse correctement
  • Les fichiers chiffrés sont téléchargés via les URLs signées avec retry (3x, backoff exponentiel)
  • Chaque fichier est déchiffré localement avec K_doc dérivée de kmaster
  • Le .pvproof est assemblé en streaming sur disque (pas en mémoire)
  • pvproof.json est le premier entry de l'archive, en mode STORED (sans compression)
  • La structure interne respecte l'arborescence définie (preuves/, enveloppes/, manifest, chronology, guide, readme)
  • Le hash SHA3-256 du .pvproof est calculé et affiché à l'utilisateur
  • Le fichier exporté porte l'extension .pvproof (jamais .zip)
  • La progression multi-étapes est affichée (téléchargement N/M, déchiffrement N/M, assemblage, finalisation)
  • Les rejets partiels sont affichés avec motifs, l'utilisateur peut continuer
  • La share sheet native est disponible après génération
  • Un rappel notification locale est émis 24h après génération
  • La suppression est manuelle uniquement (pas d'auto-suppression)

Sécurité

  • Aucun fichier en clair ne persiste hors du .pvproof final
  • Les fichiers temporaires sont supprimés immédiatement après usage
  • Aucun artefact backend n'est modifié par l'app (passthrough)
  • Le déchiffrement utilise K_doc dérivée (PD-34), jamais kmaster directement
  • Les noms de fichiers sont sanitizés avant insertion (pas de ../, caractères spéciaux supprimés, longueur bornée)

Erreurs

  • URL expirée → refresh automatique via nouvel appel API
  • Fichier introuvable → abort export avec message explicite
  • Échec réseau → retry 3x puis proposition utilisateur
  • 403 (FREE) → message + CTA Premium
  • 422 (toutes preuves rejetées) → message explicite, pas d'assemblage

Non-fonctionnels

  • Export de 12 preuves (50 MB total) en < 30s (Wi-Fi, P95)
  • Export de 50 preuves (200 MB total) en < 60s (Wi-Fi, P95)
  • Pic mémoire < 50 MB pendant l'assemblage (streaming)
  • Compatible React Native iOS, choix extensibles Android/PWA