> ⛔ **NE PAS COMMITER CE FICHIER TANT QUE LES MESURES NON ENCORE LIVRÉES NE LE SONT PAS.**
> Destiné à devenir la **déclaration de sécurité/confidentialité publique** de PhotoSync (utilisateurs + review App Store) une fois la v2.0.0 livrée. Tant qu'on y décrit du « prévu », il reste interne.

# Sécurité & confidentialité — PhotoSync

> **Principe directeur : privacy-by-design.** PhotoSync relie le téléphone de l'utilisateur à **son propre** serveur (NAS / Pi). **Aucune donnée (photo, identifiant, métadonnée) ne transite par le développeur.** Ce document trace **chaque décision de sécurité** et son état, pour prouver — preuve à l'appui dans le code — que les données des utilisateurs sont protégées, y compris celles qu'on **ne stocke pas**.
>
> 🔒 **Règle de travail** : toute nouvelle décision de sécurité DOIT être ajoutée ici, avec sa justification, son état et la référence au code.

---

## 1. Tableau des décisions de sécurité

| # | Décision | Pourquoi | État | Où (preuve) |
|---|---|---|---|---|
| 1 | **Mot de passe WebDAV dans le trousseau chiffré** (expo-secure-store), jamais en clair sur l'appareil | Un mot de passe de compte NAS est plus sensible qu'un token d'app | ✅ Implémenté | [mobile/lib/backend/config.js](mobile/lib/backend/config.js) + test [backend.config.test.js](mobile/__tests__/backend.config.test.js) (vérifie qu'il n'apparaît jamais dans AsyncStorage) |
| 2 | **Token agent NON sauvegardé dans la config sur le NAS** (re-saisi après réinstallation) | Ne pas stocker un secret derrière la porte qu'il ouvre | ✅ Implémenté | [mobile/lib/config.js](mobile/lib/config.js) (KEYS exclut le token) ; [mobile/lib/auth.js](mobile/lib/auth.js) |
| 3 | **Auth agent fail-closed + comparaison à temps constant** | Refuser tout sans token valide ; empêcher la devinette du token par timing | ✅ Implémenté | [pi-agent/src/server.js](pi-agent/src/server.js#L197-L213) (`authOk`, `crypto.timingSafeEqual`) |
| 4 | **Token masqué dans les journaux de l'agent** (`?token=***`) | Le secret ne doit pas finir en clair dans /logs | ✅ Implémenté | [pi-agent/src/server.js](pi-agent/src/server.js) (`redactQuery`) |
| 5 | **Aucune donnée ne transite par le développeur** | Téléphone ↔ NAS de l'utilisateur uniquement ; privacy label quasi vide | ✅ Par conception | Architecture (pas de backend dev) — cf. [CONFIGURATION.md](CONFIGURATION.md) |
| 6 | **Accès distant par tunnel chiffré de bout en bout** (Tailscale / WireGuard) | Le contenu des photos n'est jamais lisible en transit ; NAS non exposé | ✅ En place | [CONFIGURATION.md](CONFIGURATION.md) §5, [WIREGUARD-MIGRATION.md](WIREGUARD-MIGRATION.md) |
| 7 | **NAS jamais exposé directement sur Internet** (surtout NAS EOL) | Un NAS en fin de support sans correctifs ne doit pas être joignable depuis le net | ✅ En place | [README.md](README.md) (TS-228 EOL, myQNAPcloud désactivé) |
| 8 | **Passage à HTTPS (TLS)** pour protéger les identifiants en transit | En HTTP clair, mot de passe WebDAV / token circulent en clair sur le LAN | 🟠 Prévu | [HTTPS-MIGRATION.md](HTTPS-MIGRATION.md) |
| 9 | **Pas de kill-switch, pas de logs envoyés au développeur** | Ne pas se transformer en collecteur de données ; ne pas créer de mécanisme de contrôle à distance | ✅ Décidé (à ne pas implémenter) | [IOS-MIGRATION.md](IOS-MIGRATION.md) §8 ter |
| 10 | **Sécurité côté serveur de l'utilisateur** (logs d'accès, révocation/rotation de token sur SON agent) | La défense vit chez l'utilisateur, pas chez le développeur | ✅ Disponible (agent) | [pi-agent/src/server.js](pi-agent/src/server.js) |
| 11 | **Isolation multi-compte en mode Agent = 1 instance par utilisateur** (Model C : racine NAS dédiée cloisonnée par `safeJoin` + partage monté avec le compte QNAP de la personne) | Séparer les personnes en mode Agent sans token partagé donnant accès à tout ; **double barrière** (applicative + native QNAP) ; `server.js` inchangé (pas de refactor risqué du chemin de sécurité) | ✅ Implémenté (scaffolding), isolation **vérifiée empiriquement** (escape `../` → HTTP 400) | [pi-agent/photosync-agent@.service](pi-agent/photosync-agent@.service), [pi-agent/tools/add-photosync-user.sh](pi-agent/tools/add-photosync-user.sh), [pi-agent/MULTI-USER.md](pi-agent/MULTI-USER.md), `safeJoin` [server.js](pi-agent/src/server.js#L224) |
| 12 | **Aucune adresse personnelle en dur dans l'app livrée** (IP Tailscale/LAN, hostname tailnet retirés des défauts) | Un bundle partagé ne doit ni exposer les adresses du dev ni pointer vers son serveur ; chaque utilisateur configure le sien (QR/saisie) | ✅ Implémenté | défauts vides via `process.env.EXPO_PUBLIC_*` [mobile/lib/syncCore.js](mobile/lib/syncCore.js#L14) + [mobile/App.js](mobile/App.js#L41) ; [mobile/.env.example](mobile/.env.example) (gabarit, sans secret) |

Légende : ✅ implémenté / en place · 🟠 prévu (planifié, pas encore livré).

---

## 2. Ce qu'on protège même sans le stocker

- **Le mot de passe WebDAV** : si stocké (choix utilisateur), il l'est **chiffré** (#1) ; il ne quitte **jamais** l'appareil et n'est **jamais** envoyé au développeur.
- **Le token agent** : volontairement **non** sauvegardé sur le NAS (#2) — on accepte la petite gêne de le re-saisir après réinstallation **en échange** de ne jamais l'exposer.
- **Les photos** : ne sont **jamais** copiées chez le développeur ; en transit distant, elles sont **chiffrées de bout en bout** par le tunnel (#6).
- **Les métadonnées** (qui sauvegarde quoi, quand) : restent entre le téléphone et le NAS de l'utilisateur (#5).

---

## 2 bis. Modèle d'accès & multi-utilisateur (foyer) — IMPORTANT

Conforme à la conception du [README §181 « Rôles & permissions »](README.md#L181) : la séparation des accès est **gérée par le NAS**, en réutilisant les comptes QNAP.

| Mode | Qui s'authentifie | Séparation par personne | État |
|---|---|---|---|
| **WebDAV** | le **compte NAS** de la personne (login+mdp) | ✅ **OUI** — le NAS ne renvoie que ses dossiers autorisés. « La restriction marche toute seule, aucun bug logiciel ne peut la contourner. » | ✅ réalise le design §181 |
| **Agent (mono-instance)** | un **token partagé** ; l'agent monte le NAS comme **un seul compte** (`taaazzz`, large) | ❌ **NON** — quiconque a le token voit **TOUS** les dossiers du montage | défaut historique (propriétaire) |
| **Agent (multi-instance, Model C)** | **un token + un compte QNAP par utilisateur**, instance d'agent dédiée | ✅ **OUI** — racine NAS cloisonnée (`safeJoin`) + droits natifs QNAP du compte | ✅ scaffolding livré (#11), isolation vérifiée |

**Conséquences concrètes :**
- **Multi-utilisateur de foyer (ex. femme restreinte à ses dossiers) = mode WebDAV** : chacun met **son** compte NAS, le NAS filtre. C'est l'implémentation du design documenté.
- **Mode Agent mono-instance** : le token n'identifie **pas** la personne et donne accès à **tout** le montage. À ne **pas** partager avec quelqu'un qui ne doit voir qu'une partie — sauf à passer en **multi-instance**.
- **Mode Agent multi-instance (Model C) — RÉSOLU** : le par-utilisateur en Agent est désormais possible **sans** WebDAV, via une **instance d'agent par personne** (racine NAS dédiée + compte QNAP de la personne). Procédure : [pi-agent/MULTI-USER.md](pi-agent/MULTI-USER.md). C'est l'option recommandée pour un foyer qui veut garder les features riches de l'agent tout en isolant les comptes.

---

## 3. Ce qu'on s'interdit (anti-fonctionnalités)

- ❌ Aucun **serveur intermédiaire** du développeur qui verrait les photos ou les identifiants.
- ❌ Aucun **kill-switch** / contrôle à distance de l'app (#9).
- ❌ Aucun **envoi de logs/télémétrie** vers le développeur (#9).
- ❌ Aucun **secret en dur** dans l'app (les identifiants sont saisis par l'utilisateur).

---

*Voir aussi : [CONFIGURATION.md](CONFIGURATION.md), [HTTPS-MIGRATION.md](HTTPS-MIGRATION.md), [IOS-MIGRATION.md](IOS-MIGRATION.md), [MODES-INSTALLATION.md](MODES-INSTALLATION.md), [WIREGUARD-MIGRATION.md](WIREGUARD-MIGRATION.md).*
