Aller au contenu

PD-98 — Retour d'expérience


📚 Navigation User Story | Document | | | ---------- | -- | | 📋 [Spécification](PD-98-specification.md) | | | 🛠️ [Plan d'implémentation](PD-98-plan.md) | | | ✅ [Critères d'acceptation](PD-98-acceptability.md) | | | 📝 **Retour d'expérience** | *(ce document)* | [← Retour à mobile-ios](../PD-195-epic.md) · [↑ Index User Story](index.md)

1. Résumé exécutif

La User Story PD-98 visait à implémenter le stockage sécurisé de K_master dans le iOS Keychain avec les attributs de sécurité maximaux (WHEN_UNLOCKED_THIS_DEVICE_ONLY, non exportable, non sync iCloud). L'implémentation est fonctionnelle et fournit une API CRUD complète avec logs sécurisés, mais présente 1 écart MINEUR (zeroization non systématique des buffers intermédiaires). Verdict : ACCEPTÉ AVEC RÉSERVES.


2. Points fluides

  • expo-secure-store : bibliothèque Expo bien documentée, API simple et fiable
  • Attributs Keychain : WHEN_UNLOCKED_THIS_DEVICE_ONLY correctement configuré
  • Helpers base64 natifs : implémentation manuelle sans dépendance à btoa/atob (non disponibles en RN)
  • API CRUD complète : storeMasterKey, getMasterKey, deleteMasterKey, existsMasterKey
  • Typage TypeScript strict : KeychainResult<T> avec union type KeychainError
  • Logs sécurisés : aucune valeur sensible dans les logs, uniquement événements génériques
  • Tests exhaustifs : 500+ lignes de tests couvrant tous les scénarios (succès, erreurs, sécurité)
  • Versioning clé : préfixe com.probatiovault.kmaster.v1 pour migration future
  • Gestion erreurs : mapping intelligent des erreurs SecureStore vers codes applicatifs
  • clearMasterKeyBuffer : fonction publique pour effacement explicite après usage

3. Points difficiles

Difficulté Contexte
btoa/atob absents React Native ne fournit pas ces fonctions standard, nécessitant une implémentation base64 manuelle
Plateforme web expo-secure-store ne supporte pas le web, fallback explicitement refusé par la spec
Mocking SecureStore Les tests nécessitent un mock complet de l'API avec simulation de storage interne
Détection device locked Les messages d'erreur iOS varient selon les versions, mapping heuristique nécessaire

4. Hypothèses révélées tardivement

Hypothèse initiale Réalité découverte
btoa/atob disponibles en React Native FAUX — Nécessite implémentation manuelle avec alphabet BASE64_CHARS
SecureStore supporte toutes les plateformes FAUX — iOS et Android uniquement, web explicitement non supporté
Messages d'erreur iOS standardisés FAUX — Variation selon versions iOS, mapping heuristique par mots-clés
Face ID/Touch ID intégrable simplement FAUX — Nécessite requireAuthentication: true mais laissé en TODO pour future US

5. Invariants complexes à implémenter

Invariant Complexité
Taille exacte 32 bytes Validation stricte à l'écriture ET à la lecture (détection corruption)
WHEN_UNLOCKED_THIS_DEVICE_ONLY Configuration expo-secure-store, non contournable
Pas de log sensible Revue manuelle de tous les console.log/error/warn, uniquement messages génériques
Idempotence delete deleteMasterKey() retourne success même si clé inexistante
Non-exportabilité Garantie par l'attribut iOS Keychain, pas de code applicatif nécessaire

6. Dette technique

Dette Impact Priorité
Zeroization non systématique Strings base64 en mémoire après encodage/décodage MOYENNE
clearBuffer simple Un seul fill(0), pas de double passe ni volatile write BASSE
Face ID/Touch ID désactivé requireAuthentication commenté, TODO pour future US BASSE
existsMasterKey lit la clé Lecture complète au lieu de simple check existence BASSE

7. Risques résiduels

Risque Probabilité Impact Mitigation suggérée
String base64 en mémoire Élevée FAIBLE Limitation JavaScript acceptée, documenter
Mapping erreurs incomplet Moyenne FAIBLE Ajouter nouveaux patterns si erreurs non reconnues
Pas de Face ID obligatoire Faible MOYEN Implémenter dans future US sécurité renforcée
Corruption données stockées Très faible MOYEN Détection taille à la lecture, logging explicite

8. Améliorations processus

Amélioration Bénéfice attendu
Documenter absence btoa/atob Éviter surprise aux futurs développeurs React Native
Activer requireAuthentication Protection Face ID/Touch ID pour accès K_master
Ajouter zeroize sur encoded Effacer string base64 après usage (best-effort via = '')
Test acceptance iOS réel Valider comportement sur device physique (simulator != real)
Monitoring erreurs UNKNOWN Logger pattern non reconnu pour améliorer mapError

9. Enseignements clés

  1. expo-secure-store est fiable — L'abstraction Expo au-dessus du Keychain iOS fonctionne bien et simplifie considérablement l'implémentation par rapport à l'API native.

  2. React Native n'est pas un navigateur — Les APIs standard comme btoa/atob ne sont pas disponibles. Toujours vérifier la disponibilité des primitives avant de les utiliser.

  3. Les logs sont un vecteur de fuite — La revue systématique des console.log est essentielle pour éviter d'exposer des données sensibles. Les messages doivent être génériques ("K_master stored successfully" pas "Stored key: xxx").

  4. L'effacement mémoire en JavaScript est best-effort — Les strings sont immutables et le GC non déterministe. Documenter cette limitation plutôt que prétendre une sécurité parfaite.

  5. Le versioning dès le départ évite la dette — Le préfixe v1 dans com.probatiovault.kmaster.v1 permet une migration future sans casser la compatibilité.