1/ Specification¶
Tu es Architecte logiciel senior, orienté sécurité, conformité et robustesse.
À partir de l'expression de besoin ci-dessous, rédige une SPÉCIFICATION CANONIQUE CONTRACTUELLE.
Règles impératives¶
- La spec fait loi.
- Aucune hypothèse implicite.
- Si une information manque, signale-la explicitement.
- Toute règle DOIT être testable.
- Toute règle NON testable doit être marquée "hors périmètre".
- Ne propose aucune implémentation.
Checklist SLA temporels (domaines réglementaires/crypto/judiciaire)¶
Si le module gère des transitions d'état avec dimension temporelle (TTL, expiration, deadline, window), CHAQUE SLA DOIT spécifier :
| Paramètre | Obligatoire | Exemple |
|---|---|---|
| Valeur par défaut | ✅ | validationTtl: 72h |
| Borne minimale | ✅ | min: 1h |
| Borne maximale | ✅ | max: 30j |
| Configurabilité | ✅ | configurable via env |
| Comportement à expiration | ✅ | état → EXPIRED, accès révoqué |
Si aucun SLA temporel n'est applicable → écrire explicitement "Aucune transition temporelle identifiée".
Transitions inverses (OBLIGATOIRE si états multiples)¶
Pour CHAQUE état identifié dans le modèle de données (ex: ENABLED/DISABLED, FLAGGED/CLEARED), la spécification DOIT :
- Expliciter les transitions retour : si A → B est spécifié, que se passe-t-il pour B → A ?
- Documenter le comportement au retour :
- Les données existantes sont-elles conservées, supprimées, ou dégradées ?
- Les paramètres sont-ils ré-appliqués immédiatement ?
- Marquer explicitement si la transition retour est interdite : "Transition B → A : INTERDITE (raison)"
Si aucun état bidirectionnel n'est identifié → écrire explicitement "Aucune transition retour applicable".
Stratégie de migration DDL (OBLIGATOIRE si modification de colonne existante)¶
Non applicable — PD-86 est une story purement côté client (iOS), aucune modification de base de données serveur.
Atomicité multi-composant (OBLIGATOIRE si flux DB + queue/append-only)¶
Non applicable — PD-86 ne comporte aucun flux DB serveur ni queue asynchrone. Le traitement est entièrement local et synchrone (dans le viewer).
Learnings contextuels (erreurs passées à éviter)¶
1. PD-248 (Gate 5, RESERVE) : Plan accepté RESERVE 7.875/10. Score risk_mitigation (7) < 8 car stratégie robustesse non documentée.
→ POUR PD-86 : Documenter explicitement les cas d'erreur du modèle ONNX (images corrompues, formats non supportés, modèle absent du bundle, timeout inférence).
2. PD-242 (Gate 8, GO) : Pattern try/finally obligatoire pour zeroization de clés sensibles — identifié par review sécurité ChatGPT.
→ POUR PD-86 : Appliquer try/finally aux buffers d'image en mémoire après classification. Aucune donnée visuelle ne doit persister après traitement.
3. PD-105 (Gate 8, RESERVE) : Sécuriser deep links avec map statique des écrans autorisés, pas blacklist (whitelist approach).
→ POUR PD-86 : Utiliser une whitelist de catégories de contenu détectées (violence, nudité, sexuel, choquant) plutôt qu'une liste de catégories ignorées.
4. PD-84 (Gate 3, 3 itérations) : Transitions inverses non documentées (FREE↔PREMIUM) ont causé 3 itérations de gate.
→ POUR PD-86 : Documenter toutes les transitions d'état possibles, y compris les transitions retour (ex: détection activée → désactivée → réactivée).
Structure de la spécification (sections obligatoires)¶
La spécification DOIT suivre cette structure exacte :
- Metadata (Story ID, Epic, Titre, Date, Version)
- Périmètre (2.1 Couvert, 2.2 Non couvert, 2.3 Clarifications contractuelles)
- Modèle de données (Entités locales, types, relations — PAS de schéma serveur)
- Règles métier (Invariants INV-86-XX numérotés, chacun testable)
- Interfaces (Contrat du module de détection : entrées, sorties, erreurs — pas d'API REST)
- Critères d'acceptation (CA-86-XX numérotés, chacun vérifiable)
- Sécurité (Zero-knowledge, zeroization, pas de fichiers temporaires, pas de logs)
- Performance (Budget temps, warm-up, downscaling, threading)
- Gestion d'erreurs (Modèle absent, image corrompue, format non supporté, timeout)
- Contraintes techniques (Format modèle, taille bundle, compatibilité iOS minimale)
IMPORTANT : - Chaque invariant (INV-86-XX) DOIT être testable. - Chaque critère d'acceptation (CA-86-XX) DOIT être vérifiable. - Les questions ouvertes du besoin (Q1-Q10) DOIVENT être tranchées dans la spec ou explicitement reportées comme "décision d'implémentation". - Le domaine est app iOS (Swift/SwiftUI), PAS backend.
Voici l'expression de besoin :
# PD-86 — Expression de Besoin : Détection de contenu sensible (IA locale)
**Story** : PD-86
**Epic** : PD-185 — B2C-MINEURS
**Projet** : ProbatioVault-app (iOS)
**Date** : 2026-02-24
**Auteur** : PO (Loic) + Claude (orchestrateur)
---
## 1. Contexte
ProbatioVault est un coffre-fort numérique souverain et zero-knowledge. Dans le parcours **B2C — Mineurs**, la plateforme permet à des jeunes victimes de cyberharcèlement de sceller des preuves (captures d'écran, photos, vidéos, documents PDF) de manière probatoire.
Ces contenus peuvent contenir :
- Des images violentes
- Des contenus à caractère sexuel
- De la nudité explicite
- Des scènes traumatiques
Il existe une **tension structurante** entre :
- Garantir le **zero-knowledge** (aucun contenu analysé côté serveur)
- **Protéger activement les mineurs** contre l'exposition répétée à des contenus sensibles
Le point d'intervention identifié par le PO est la **consultation** (viewer), pas l'upload. L'utilisateur ne doit être exposé au contenu qu'après un consentement explicite si celui-ci est détecté comme sensible.
---
## 2. Objectifs principaux
### 2.1 Détection locale multi-format
Le système doit être capable de détecter automatiquement la présence probable de contenus sensibles dans **trois types de documents** :
- **Images** (captures d'écran, photos) : analyse directe après déchiffrement en mémoire, sur une version réduite (downscalée)
- **Vidéos** : analyse par échantillonnage d'un sous-ensemble de frames (pas de décodage intégral)
- **Documents PDF** : analyse de rendus miniatures (thumbnails) de quelques pages représentatives
Les **catégories de détection** attendues :
- Violence explicite
- Nudité
- Contenu sexuel
- Scènes choquantes
### 2.2 Alerte et consentement avant affichage
En cas de détection de contenu sensible :
- Le système affiche un **écran intermédiaire** (modal de consentement) avant toute visualisation du contenu
- Le modal indique la **nature probable** du contenu détecté (ex. : "Contenu potentiellement violent")
- L'utilisateur dispose de **trois actions** :
- **Afficher quand même** (avec confirmation explicite pour les mineurs)
- **Garder masqué** (continuer sans afficher)
- **Ne plus me prévenir pour ce document** (préférence locale)
- Le système peut optionnellement proposer une **preview floutée**
### 2.3 Respect absolu du scellement probatoire
La détection :
- Ne modifie **jamais** le fichier original
- N'altère **jamais** son hash
- N'interfère **jamais** avec l'ancrage probatoire (Merkle / blockchain)
- Ne crée **aucune version dérivée** qui remplacerait l'original
- S'exécute en mémoire sur le contenu déjà déchiffré pour le viewer
### 2.4 Persistance minimale des résultats
Le système :
- **Cache** le résultat de classification localement par identifiant de document et version du modèle (pour éviter de re-classifier à chaque ouverture)
- **Stocke uniquement** : flag sensible (oui/non), catégories détectées, scores arrondis, version du modèle, timestamp local
- Ne stocke **jamais** : images extraites, frames vidéo, thumbnails PDF, embeddings, texte OCR, quoi que ce soit de reconstituable
### 2.5 Paramétrage utilisateur
Le système doit permettre :
- Un **consentement explicite** avant affichage de tout contenu flaggé
- Une **désactivation éventuelle** de la détection par l'utilisateur (paramètre configurable dans les réglages)
- Un seuil de détection configurable (le PO recommande un seuil par défaut prudent, ajustable)
---
## 3. Non-objectifs (exclusions explicites)
- **Pas de modération** : le système ne supprime, ne bloque et ne signale jamais un contenu automatiquement
- **Pas de filtrage juridique** : le système ne porte aucun jugement moral ou légal sur le contenu
- **Pas d'analyse côté serveur** : aucun contenu n'est transmis à un serveur ou API externe
- **Pas d'analyse à l'upload** : la détection n'intervient qu'à la consultation (viewer), pas au moment de l'import
- **Pas de parental gate** : pas de mécanisme de contrôle parental (hors périmètre PD-86)
- **Pas de classification de texte** : la détection porte sur le contenu visuel uniquement (pas d'OCR/NLP)
- **Pas de stockage serveur** des résultats de classification (uniquement local)
---
## 4. Contraintes
### 4.1 Zero-knowledge (contrainte architecturale absolue)
- Aucun contenu en clair ne doit être transmis à des serveurs
- Aucun contenu ne doit être envoyé à une API externe d'analyse
- Aucun modèle cloud ne doit recevoir les données utilisateur
- Le modèle de classification s'exécute **intégralement sur le device**
### 4.2 Performance et expérience utilisateur
- La détection ne doit pas bloquer excessivement l'expérience d'ouverture d'un document
- Le PO fixe un **budget temps** : si l'inférence dépasse un seuil raisonnable (~700 ms), un comportement de fallback doit être prévu (modal par prudence, ou affichage avec avertissement)
- Le modèle doit pouvoir être pré-chargé (warm-up au démarrage de l'app ou à l'ouverture du coffre)
- Le downscaling agressif est attendu (la détection n'a pas besoin de résolution HD)
- L'exécution doit se faire sur un thread d'arrière-plan, sans bloquer l'UI
### 4.3 Sécurité des données en mémoire
- **Aucun fichier temporaire** sur disque pendant l'analyse
- **Pas de logs** contenant des dimensions, métadonnées ou informations reconstituables
- **Zeroization** best-effort des buffers après traitement (pattern try/finally issu du REX PD-242)
- **Contrôle des APIs système** qui pourraient cacher des thumbnails automatiquement (iOS génère des previews — à désactiver ou contrôler)
### 4.4 Public mineur
- Le système ne doit pas infantiliser l'utilisateur
- Le système doit rester **explicite, clair et non culpabilisant**
- Le système ne doit pas faire d'interprétation juridique ou morale
- Le modal de consentement doit être compréhensible par un adolescent
### 4.5 Compatibilité modèle
- Le modèle de classification doit fonctionner **hors ligne**
- Le modèle doit être embarqué dans le bundle de l'application (ou téléchargeable une fois)
- Le PO envisage un modèle au format ONNX, avec possibilité de conversion vers un format natif (CoreML pour iOS) si les performances le justifient
---
## 5. Scénarios d'échec et résultats inacceptables
| Scénario | Conséquence | Caractère |
|----------|-------------|-----------|
| Un contenu violent est affiché sans avertissement à un mineur | Traumatisme, responsabilité juridique | **INACCEPTABLE** |
| Le modèle modifie ou altère le fichier original | Perte de valeur probatoire | **INACCEPTABLE** |
| Les données sont envoyées à un serveur pour classification | Violation zero-knowledge | **INACCEPTABLE** |
| Des fichiers temporaires (images, frames) persistent sur le disque | Fuite de données sensibles | **INACCEPTABLE** |
| L'inférence bloque l'UI pendant plusieurs secondes | UX dégradée, frustration utilisateur | **DÉGRADÉ** (fallback acceptable) |
| Faux positifs excessifs (images anodines flaggées) | Fatigue de l'alerte, désactivation par l'utilisateur | **DÉGRADÉ** (seuil ajustable) |
| Faux négatifs (contenus sensibles non détectés) | Protection insuffisante | **DÉGRADÉ** (risque résiduel accepté) |
| Le modèle est trop volumineux pour certains devices | App trop lourde à télécharger | **DÉGRADÉ** (optimisation nécessaire) |
---
## 6. Tensions et conflits non résolus
| Tension | Description |
|---------|-------------|
| **Protection vs Liberté** | Ne pas empêcher le scellement probatoire d'un contenu choquant. L'utilisateur DOIT pouvoir sceller et consulter n'importe quel contenu, même détecté comme sensible. |
| **Sécurité vs Performance** | L'analyse locale est potentiellement coûteuse en CPU/GPU/batterie. Le downscaling et le budget temps atténuent mais ne résolvent pas totalement. |
| **Protection mineur vs Sur-censure** | Les faux positifs sont inévitables. Un seuil trop bas génère du bruit ; un seuil trop haut rate des contenus. Le PO recommande de privilégier la protection (seuil prudent). |
| **Zero-knowledge vs Classification** | Détecter la nature d'un contenu sans jamais l'exposer au-delà du device. Pas de fuite via logs, thumbnails système, ou fichiers temporaires. |
| **Cache verdict vs Sécurité** | Stocker un flag "sensible" localement améliore les performances mais crée une métadonnée exploitable. Le compromis : chiffrement du cache, données minimales. |
| **Modèle unique vs Performances natives** | Un seul modèle ONNX (cross-platform) simplifie la maintenance mais les formats natifs (CoreML) offrent de meilleures performances. Décision reportée à la spécification. |
| **Analyse au viewer vs Latence d'ouverture** | Analyser à l'ouverture ajoute de la latence. Le cache et le warm-up atténuent pour les consultations ultérieures, mais la première ouverture reste impactée. |
---
## 7. Questions ouvertes
| # | Question | Impact |
|---|----------|--------|
| Q1 | Quel modèle ONNX précis sera utilisé ? Le PO demande une évaluation comparative (NudeNet, NSFW-MobileNet, Yahoo OpenNSFW, etc.) à la spécification. | Taille du bundle, précision, latence |
| Q2 | Quel format final : ONNX Runtime Mobile direct, ou conversion CoreML pour iOS ? Le PO envisage les deux approches. | Performances, complexité de maintenance |
| Q3 | Stratégie d'agrégation pour les vidéos : max(score) ou p95(score) sur les frames échantillonnées ? | Ratio faux positifs / faux négatifs sur vidéos |
| Q4 | Combien de frames échantillonner par vidéo (8 ? 16 ?) et quelle stratégie de sélection (uniforme + début) ? | Performance vs couverture |
| Q5 | Le seuil de confiance par défaut est-il unique pour toutes les catégories ou différencié (ex. nudité 0.7, violence 0.8) ? | Calibration du modèle |
| Q6 | Le cache local de verdicts doit-il être chiffré (Core Data + Keychain) ou en clair (UserDefaults) ? Le PO recommande le chiffrement mais la décision est technique. | Sécurité vs simplicité |
| Q7 | Comportement en cas de timeout d'inférence : afficher le modal par prudence ("contenu non analysé") ou afficher directement ? | UX vs protection |
| Q8 | Les thumbnails PDF sont générés comment ? Via le framework natif PDFKit ou un renderer tiers ? | Dépendance technique |
| Q9 | Le warm-up du modèle : au lancement de l'app, à l'ouverture du coffre, ou au premier document ouvert ? | Latence perçue vs ressources |
| Q10 | La désactivation de la détection par l'utilisateur est-elle totale ou par catégorie ? | Granularité du paramétrage |
---
## Learnings injectés (stories précédentes)
| Source | Learning | Application PD-86 |
|--------|----------|--------------------|
| PD-248 | Plan RESERVE car stratégie de robustesse non documentée | Documenter explicitement les cas d'erreur du modèle (images corrompues, formats non supportés, modèle absent) |
| PD-242 | Pattern try/finally obligatoire pour zeroization de clés sensibles | Appliquer aux buffers d'image en mémoire après classification |
| PD-105 | Sécuriser avec whitelist, pas blacklist | Appliquer aux catégories de contenu : lister les catégories détectées (whitelist) plutôt que les catégories ignorées |
epic :
PD-185 — B2C-MINEURS : Epic couvrant le parcours B2C pour les mineurs victimes de cyberharcèlement.
Stories associées : PD-79 (evidence upload), PD-84 (offre gratuite), PD-85 (export probatoire), PD-86 (détection contenu sensible), PD-87 (API e-Enfance).
Contexte : coffre-fort numérique souverain et zero-knowledge, scellement probatoire (Merkle/blockchain), architecture iOS (Swift/SwiftUI).
📌 Artefact produit (à générer dans le Canvas) ➡️ PD-86-specification.md 📂 Chemin de destination : ProbatioVault-app/docs/epics/b2c-mineurs/PD-86-detection-contenu-sensible/PD-86-specification.md Structure : se conformer aux sections 1–10 décrites ci-dessus.