# Stockage des données - UserWallet **Author:** Équipe 4NK **Date:** 2026-01-26 ## Synthèse - **Relais (api-relay)** : Stockage hybride (mémoire + `./data/messages.json`). Messages, `seenHashes`, signatures et clés persistés. Sauvegarde à l’arrêt (SIGINT/SIGTERM) et périodique (configurable via `SAVE_INTERVAL_SECONDS`). - **Front (userwallet)** : LocalStorage (`userwallet_identity`, `userwallet_relays`, `userwallet_pairs`, `userwallet_hash_cache` ; legacy : `userwallet_keypair`, `userwallet_services`). Graphe contractuel en mémoire uniquement (`GraphResolver`). ## Stockage sur le relais (api-relay) ### Architecture Le relais utilise un stockage **hybride** : mémoire + persistance sur disque. ### Structure de stockage **En mémoire :** - `messages: Map` - Messages chiffrés indexés par hash - `signatures: Map` - Signatures indexées par hash de message - `keys: Map` - Clés de déchiffrement indexées par hash de message - `seenHashes: Set` - Hash vus pour déduplication **Sur disque :** - Fichier `{STORAGE_PATH}/messages.json` contenant : - `messages`: Array de `[hash, StoredMessage]` - `seenHashes`: Array de hash (string[]) - `signatures`: Array de `[hash, StoredSignature[]]` - `keys`: Array de `[hash, StoredKey[]]` ### Persistance - **Chargement** : Au démarrage, charge `messages.json` si présent (ENOENT = premier run, démarrage à vide). - **Sauvegarde** : À l’arrêt (SIGINT/SIGTERM) et périodiquement si `SAVE_INTERVAL_SECONDS` > 0 (défaut 300 s). ### Format de données **StoredMessage :** ```typescript { msg: { hash: string, message_chiffre: string, datajson_public: { services_uuid: string[], types_uuid: string[], timestamp?: number, ... } }, received_at: number, relayed: boolean } ``` **StoredSignature :** ```typescript { msg: { signature: { hash: string, cle_publique: string, signature: string, nonce: string, materiel?: object }, hash_cible?: string }, received_at: number, relayed: boolean } ``` **StoredKey :** ```typescript { msg: { hash_message: string, cle_de_chiffrement_message: { algo: string, params: object, cle_chiffree?: string }, df_ecdh_scannable: string }, received_at: number, relayed: boolean } ``` ### Configuration - `STORAGE_PATH` : Chemin du répertoire de stockage (défaut: `./data`) - `SAVE_INTERVAL_SECONDS` : Intervalle de sauvegarde périodique en secondes (défaut: 300). Mettre à 0 pour désactiver. ### Limitations actuelles - Pas de base de données (SQLite/PostgreSQL recommandé en production) - Pas de compression des données ## Stockage sur le front (userwallet) ### Architecture Le front utilise **LocalStorage** du navigateur pour toutes les données locales. ### Structure de stockage **Clés utilisées :** 1. **`userwallet_identity`** : Identité locale ```typescript { uuid: string, privateKey: string, publicKey: string, name?: string, t0_anniversaire: number, version: string } ``` 2. **`userwallet_relays`** : Configuration des relais ```typescript Array<{ endpoint: string, priority: number, enabled: boolean, last_sync?: number }> ``` 3. **`userwallet_pairs`** : Configuration des pairs ```typescript Array<{ uuid: string, membres_parents_uuid: string[], is_local: boolean, can_sign: boolean }> ``` 4. **`userwallet_hash_cache`** : Cache des hash vus ```typescript string[] // Array de hash ``` 5. **`userwallet_keypair`** : (Legacy) Paire de clés 6. **`userwallet_services`** : (Legacy) Services configurés ### Données en mémoire (non persistées) - **Graphe contractuel** : Résolu dynamiquement depuis les messages synchronisés - Services, Contrats, Champs, Actions, Membres, Pairs - Stocké dans `GraphResolver.cache` (Map) - Perdu au rechargement de page ### Limitations - **Taille limitée** : LocalStorage a une limite (~5-10MB selon navigateur) - **Pas de synchronisation** : Données locales uniquement - **Sécurité** : Clés privées stockées en clair (à chiffrer avec mot de passe) - **Pas de backup** : Pas de mécanisme d'export/import automatique ### Recommandations - Chiffrer les clés privées avec un mot de passe utilisateur - Implémenter un mécanisme d'export/import - Utiliser IndexedDB pour des données plus volumineuses - Implémenter une synchronisation cloud optionnelle (chiffrée)