PD-248 — Plan d'implémentation¶
Vue d'ensemble¶
| Attribut | Valeur |
|---|---|
| Story | PD-248 — Protection screenshot native iOS |
| Complexité | Low-Medium |
| Fichiers estimés | 8-12 |
| Tâches | 6 |
| Dépendance externe | expo-screen-capture |
Architecture technique¶
Composants¶
src/
├── hooks/
│ └── useScreenshotProtection.ts # Hook principal (INV-248-01..08)
├── components/
│ └── ScreenshotProtectedView.tsx # Wrapper HOC optionnel
├── services/
│ └── screenshotProtection.ts # Service de logging/erreurs
└── __tests__/
├── hooks/
│ └── useScreenshotProtection.test.ts
└── e2e/
└── screenshot-protection.e2e.ts
Flux de données¶
┌─────────────────┐
│ Navigation │
│ (écran sensible)│
└────────┬────────┘
│ onFocus
▼
┌─────────────────┐
│ useScreenshot │
│ Protection() │
│ - useFocusEffect│
└────────┬────────┘
│
▼
┌─────────────────┐ ┌─────────────────┐
│ preventScreen │────▶│ protection_state│
│ Capture() │ │ = ACTIVE │
└────────┬────────┘ └─────────────────┘
│
│ onBlur (écran non sensible)
▼
┌─────────────────┐ ┌─────────────────┐
│ allowScreen │────▶│ protection_state│
│ Capture() │ │ = INACTIVE │
└─────────────────┘ └─────────────────┘
Tâches d'implémentation¶
TASK-1 : Installation et configuration expo-screen-capture¶
Agent : agent-sre Fichiers : - package.json (dépendance) - app.json ou app.config.ts (plugin Expo si nécessaire)
Actions : 1. npx expo install expo-screen-capture 2. Vérifier compatibilité EAS Build 3. Ajouter au .gitignore si fichiers natifs générés
Invariants couverts : INV-248-07
TASK-2 : Hook useScreenshotProtection¶
Agent : agent-developer Fichiers : - src/hooks/useScreenshotProtection.ts
Contrat de code : CC-248-01
Actions : 1. Implémenter le hook avec useFocusEffect 2. Appeler preventScreenCapture() sur focus 3. Appeler allowScreenCapture() sur blur (sauf transition sensible→sensible) 4. Gérer les erreurs avec fallback (ERR-248-001, ERR-248-002)
Invariants couverts : INV-248-01, INV-248-02, INV-248-03, INV-248-04, INV-248-08
TASK-3 : Intégration dans les écrans sensibles¶
Agent : agent-developer Fichiers : - src/screens/recovery/MnemonicDisplay.tsx (SCR-248-01) - src/screens/settings/MFASetupScreen.tsx (SCR-248-02) - src/components/mfa/TOTPCodeDisplay.tsx (SCR-248-03) - src/screens/settings/APIKeyDisplay.tsx (SCR-248-04, si existant)
Contrat de code : CC-248-02
Actions : 1. Ajouter useScreenshotProtection() à chaque composant 2. Vérifier que l'appel est au niveau du composant racine de l'écran 3. Pas de props/configuration — comportement automatique
Invariants couverts : INV-248-02, INV-248-05
TASK-4 : Service de logging technique¶
Agent : agent-developer Fichiers : - src/services/screenshotProtection.ts
Contrat de code : CC-248-03
Actions : 1. Créer fonctions de logging pour ERR-248-001..004 2. Pas d'alerte utilisateur (INV-248-04) 3. Compatible avec système de télémétrie existant
Invariants couverts : INV-248-04, ERR-248-001..004
TASK-5 : Tests unitaires¶
Agent : agent-qa-unit-integration Fichiers : - src/__tests__/hooks/useScreenshotProtection.test.ts
Contrat de code : CC-248-04
Actions : 1. Tester activation sur focus 2. Tester désactivation sur blur 3. Tester maintien en transition sensible→sensible 4. Mocker expo-screen-capture
Tests couverts : TC-248-NOM-01..07, TC-248-SIL-01
TASK-6 : Tests E2E avec OCR¶
Agent : agent-qa-e2e Fichiers : - src/__tests__/e2e/screenshot-protection.e2e.ts - Scripts OCR Tesseract (si nécessaire)
Contrat de code : CC-248-05
Actions : 1. Capturer screenshot de chaque écran sensible 2. Exécuter OCR Tesseract sur les captures 3. Vérifier absence des données sensibles 4. Test de performance (< 10ms activation)
Tests couverts : CA-248-01..08, TC-248-PERF-01
Code Contracts¶
CC-248-01 : useScreenshotProtection¶
/**
* Hook de protection screenshot pour écrans sensibles.
*
* @invariants
* - INV-248-01: Si protection active, capture = BLOCKED
* - INV-248-02: Activation automatique sur focus
* - INV-248-03: Désactivation sur blur (sauf sensible→sensible)
* - INV-248-04: Silencieux (pas d'alerte utilisateur)
* - INV-248-08: Activation < 10ms
*
* @usage
* ```tsx
* function MnemonicDisplay() {
* useScreenshotProtection();
* return <View>...</View>;
* }
* ```
*/
export function useScreenshotProtection(): void;
Signature : - Pas de paramètres - Pas de retour (effet de bord uniquement) - Doit utiliser useFocusEffect de React Navigation
CC-248-02 : Intégration écrans sensibles¶
/**
* Chaque écran sensible DOIT appeler useScreenshotProtection()
* au niveau racine du composant.
*
* @screens SCR-248-01..04
*/
// Pattern d'intégration
function SensitiveScreen() {
useScreenshotProtection(); // OBLIGATOIRE, première ligne
// ... reste du composant
}
Règles : - Appel en première ligne après les autres hooks - Pas de condition (toujours actif pour écrans sensibles) - Pas de props de configuration
CC-248-03 : Service de logging¶
/**
* Service de logging technique pour erreurs de protection.
*
* @invariant INV-248-04: Aucune alerte utilisateur
*/
export interface ScreenshotProtectionLogger {
logActivationError(screen: ScreenId, error: Error): void; // ERR-248-001
logMaintainError(from: ScreenId, to: ScreenId, error: Error): void; // ERR-248-002
logUnregisteredComponent(component: string): void; // ERR-248-003
logIncompatibleEnvironment(): void; // ERR-248-004
}
Règles : - Logging technique uniquement (console, Sentry, etc.) - Jamais d'UI visible utilisateur - Format structuré avec error_code
CC-248-04 : Tests unitaires¶
/**
* Tests unitaires du hook useScreenshotProtection.
*
* @coverage INV-248-01..08
*/
describe('useScreenshotProtection', () => {
it('should call preventScreenCapture on focus', () => {});
it('should call allowScreenCapture on blur to non-sensitive', () => {});
it('should maintain protection on sensitive→sensitive transition', () => {});
it('should not show any UI alert', () => {});
it('should activate in less than 10ms', () => {});
});
CC-248-05 : Tests E2E avec OCR¶
/**
* Tests E2E avec vérification OCR.
*
* @tool Tesseract 5.x
* @coverage CA-248-01..04
*/
describe('Screenshot protection E2E', () => {
it('should block screenshot on MnemonicDisplay (OCR verification)', async () => {
// 1. Navigate to MnemonicDisplay
// 2. Take screenshot
// 3. Run Tesseract OCR
// 4. Assert no mnemonic word detected
});
// ... repeat for SCR-248-02..04
});
Contraintes techniques¶
Dépendances inter-PD¶
| Story | Statut | Nature de la dépendance |
|---|---|---|
| PD-242 | DONE | MnemonicDisplay (composant cible) |
| PD-106 | DONE | MFASetupScreen, TOTPCodeDisplay (composants cibles) |
Framework de test¶
- Runner : Vitest (compatible ESM)
- E2E : Detox (si disponible) ou tests manuels simulateur
- OCR : Tesseract 5.x via script shell ou intégration CI
Compatibilité¶
- iOS : 15.0+
- Expo SDK : Compatible version courante
- EAS Build : Profil production requis pour validation finale
Diagrammes Mermaid¶
Graphe de dépendances des tâches¶
graph TD
T1["TASK-1<br/>Installation expo-screen-capture<br/>(agent-sre)"]
T2["TASK-2<br/>Hook useScreenshotProtection<br/>(agent-developer)"]
T3["TASK-3<br/>Intégration écrans sensibles<br/>(agent-developer)"]
T4["TASK-4<br/>Service de logging<br/>(agent-developer)"]
T5["TASK-5<br/>Tests unitaires<br/>(agent-qa-unit-integration)"]
T6["TASK-6<br/>Tests E2E + OCR<br/>(agent-qa-e2e)"]
T1 --> T2
T2 --> T3
T2 --> T4
T1 --> T4
T3 --> T5
T4 --> T5
T3 --> T6
T4 --> T6
T5 --> T6
classDef sre fill:#e1f5fe,stroke:#0288d1
classDef dev fill:#e8f5e9,stroke:#388e3c
classDef qa fill:#fff3e0,stroke:#f57c00
class T1 sre
class T2,T3,T4 dev
class T5 qa
class T6 qa Diagramme de séquence — Activation / désactivation de la protection¶
sequenceDiagram
participant Nav as Navigation<br/>(React Navigation)
participant Hook as useScreenshotProtection
participant ESC as expo-screen-capture
participant Log as ScreenshotProtectionLogger
Note over Nav: Utilisateur navigue vers<br/>écran sensible (MnemonicDisplay)
Nav->>Hook: useFocusEffect (focus)
Hook->>ESC: preventScreenCapture()
alt Activation OK
ESC-->>Hook: void (protection ACTIVE)
else Erreur native
ESC-->>Hook: Error
Hook->>Log: logActivationError(SCR-248-01, err)
Note over Log: ERR-248-001<br/>Log technique uniquement,<br/>pas d'alerte utilisateur
end
Note over Nav: Utilisateur navigue vers<br/>écran sensible (MFASetupScreen)
Nav->>Hook: useFocusEffect (focus)
Hook->>Hook: Transition sensible→sensible<br/>maintien protection (INV-248-03)
Note over ESC: preventScreenCapture()<br/>reste actif, pas de toggle
Note over Nav: Utilisateur navigue vers<br/>écran NON sensible
Nav->>Hook: useFocusEffect cleanup (blur)
Hook->>ESC: allowScreenCapture()
ESC-->>Hook: void (protection INACTIVE) Mapping INV/CA → TASK¶
| Invariant/CA | Tâche couvrant | Test couvrant |
|---|---|---|
| INV-248-01 | TASK-2 | TC-248-NOM-01..04 |
| INV-248-02 | TASK-2, TASK-3 | TC-248-NOM-01..04 |
| INV-248-03 | TASK-2 | TC-248-NOM-05, TC-248-NOM-06 |
| INV-248-04 | TASK-2, TASK-4 | TC-248-SIL-01 |
| INV-248-05 | TASK-3 | TC-248-NOM-07, TC-248-REG-01 |
| INV-248-06 | TASK-6 | TC-248-ENV-02 |
| INV-248-07 | TASK-1 | TC-248-CFG-01 |
| INV-248-08 | TASK-2, TASK-6 | TC-248-PERF-01 |
| CA-248-01 | TASK-3, TASK-6 | TC-248-NOM-01 |
| CA-248-02 | TASK-3, TASK-6 | TC-248-NOM-02 |
| CA-248-03 | TASK-3, TASK-6 | TC-248-NOM-03 |
| CA-248-04 | TASK-3, TASK-6 | TC-248-NOM-04 |
| CA-248-05 | TASK-3 | TC-248-NOM-05, TC-248-NOM-07 |
| CA-248-06 | TASK-6 | TC-248-PERF-01 |
| CA-248-07 | TASK-4 | TC-248-SIL-01 |
| CA-248-08 | TASK-6 | TC-248-ENV-02 |
| CA-248-09 | TASK-1 | TC-248-CFG-01 |
| CA-248-10 | TASK-5, TASK-6 | TC-248-ENV-01 |
Références¶
- Spécification : PD-248-specification.md
- Tests : PD-248-tests.md
- Verdict Gate 3 : PD-248-verdict-step3-v1.yaml
- expo-screen-capture : https://docs.expo.dev/versions/latest/sdk/screen-capture/