Simpl-Resultat/docs/adr/0005-multi-profile-db.md
le king fu 02fca2ad3c docs: ADR 0021, guide and changelog for the profile catch-up (#390)
ADR 0021 records the catch-up rules and amends ADR 0003 and 0005, whose
claims about secondary profiles were false. architecture.md, CLAUDE.md
and the migration rule describe the two migration paths; the guide tells
where the pre-update copy lives and how to remove a database a deletion
on Linux left behind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:35:00 -04:00

49 lines
3.2 KiB
Markdown

# ADR-0005 : Architecture multi-profils avec bases de données séparées
- **Date** : 2025-08
- **Statut** : Accepté
## Contexte
L'application doit supporter plusieurs profils utilisateur (par exemple, un profil personnel et un profil professionnel) avec une isolation complète des données. Chaque profil a ses propres catégories, transactions, budgets et paramètres.
Les options considérées :
- **Base unique avec colonne `profile_id`** : simple, mais risque de fuite de données entre profils
- **Bases de données séparées** : isolation totale, mais gestion plus complexe
- **Schémas SQLite** (ATTACH DATABASE) : isolation partielle, API complexe
## Décision
Chaque profil possède sa **propre base de données SQLite**. La liste des profils est stockée dans un fichier `profiles.json` dans le répertoire de données de l'application.
Architecture :
- `profiles.json` : métadonnées des profils (nom, chemin de la BDD, hash du PIN)
- `ProfileContext` (React) : état global du profil actif, liste des profils, fonctions de switching
- `ProfileSelectionPage` : page affichée quand aucun profil n'est actif (gate)
- Les nouveaux profils sont initialisés avec `consolidated_schema.sql` (via la commande `get_new_profile_init_sql`)
- Chaque profil peut être protégé par un PIN (hashé avec Argon2)
## Conséquences
### Positives
- **Isolation totale** : aucun risque de fuite de données entre profils
- **Suppression simple** : supprimer un profil = supprimer un fichier `.db`
- **Sauvegarde indépendante** : chaque profil peut être exporté/importé séparément
- **Pas de migration croisée** : les migrations s'appliquent indépendamment à chaque base
### Négatives
- **Reconnexion nécessaire** : le changement de profil nécessite la fermeture et la réouverture de la connexion SQLite
- **Pas de vue agrégée** : impossible de voir les données de tous les profils en même temps
- **Synchronisation du schéma** : chaque base doit être au même niveau de migration (géré par le plugin sql au démarrage)
- **Fichier `profiles.json` externe** : les métadonnées des profils ne sont pas dans SQLite, ce qui crée une dépendance à un fichier JSON séparé
## Amendement #390 (2026-10-06)
Deux affirmations des conséquences étaient fausses jusqu'à #390 :
- « Les migrations s'appliquent indépendamment à chaque base » et « géré par le plugin sql au démarrage » : le plugin ne migre que la base du profil par défaut. Un profil secondaire gardait le schéma de la version qui l'avait créé. Il rattrape désormais ses migrations à chaque ouverture ([ADR 0021](0021-migrations-profils-secondaires.md)).
- « Supprimer un profil = supprimer un fichier `.db` » : sous Linux, la commande cherchait la base sous `app_data_dir()` alors que le plugin la range sous `app_config_dir()`, et le fichier restait sur le disque. La suppression vise désormais le dossier du plugin et emporte aussi les fichiers annexes de SQLite et les copies prises avant un rattrapage.
`profiles.json` reste dans le répertoire de données de l'application (`app_data_dir()`) ; les bases sont dans le répertoire de configuration (`app_config_dir()`), qui n'est le même dossier que sous Windows et macOS.