ncantu 5689693507 UserWallet: Multiple feature implementations and updates
**Motivations:**
- Implement BIP39 mnemonic import for identity creation
- Add password-based key protection for enhanced security
- Improve pairing workflow with QR code and URL display
- Migrate hash cache from LocalStorage to IndexedDB for better scalability
- Update signet-dashboard and mempool components

**Root causes:**
- N/A (feature implementations)

**Correctifs:**
- N/A (no bug fixes in this commit)

**Evolutions:**
- BIP39 mnemonic import: Support for 12/24 word English mnemonics with BIP32 derivation path m/44'/0'/0'/0/0
- Key protection: Password-based encryption of private keys at rest with unlock/lock functionality
- Pairing workflow: QR code and URL display for device pairing, form-based word exchange between devices
- IndexedDB migration: Hash cache moved from LocalStorage to IndexedDB to avoid size limitations
- Global action bar: URL parameter support for navigation
- Pairing connection: Enhanced pairing status management

**Pages affectées:**
- userwallet/src/utils/identity.ts
- userwallet/src/utils/keyProtection.ts
- userwallet/src/utils/sessionUnlockedKey.ts
- userwallet/src/utils/indexedDbStorage.ts
- userwallet/src/utils/cache.ts
- userwallet/src/utils/pairing.ts
- userwallet/src/components/UnlockScreen.tsx
- userwallet/src/components/PairingDisplayScreen.tsx
- userwallet/src/components/PairingSetupBlock.tsx
- userwallet/src/components/GlobalActionBar.tsx
- userwallet/src/components/HomeScreen.tsx
- userwallet/src/components/ImportIdentityScreen.tsx
- userwallet/src/components/DataExportImportScreen.tsx
- userwallet/src/hooks/useIdentity.ts
- userwallet/src/hooks/usePairingConnected.ts
- userwallet/src/services/syncService.ts
- userwallet/src/services/pairingConfirm.ts
- userwallet/src/App.tsx
- userwallet/package.json
- userwallet/docs/specs.md
- userwallet/docs/storage.md
- userwallet/docs/synthese.md
- signet-dashboard/public/*.html
- signet-dashboard/public/app.js
- signet-dashboard/public/styles.css
- mempool (submodule updates)
- hash_list.txt, hash_list_cache.txt, utxo_list.txt, utxo_list_cache.txt, fees_list.txt
- features/*.md (documentation files)
2026-01-26 10:23:34 +01:00

190 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 à larrê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`). IndexedDB : `hash_cache`, `userwallet_pairing_confirm`. 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<string, StoredMessage>` - Messages chiffrés indexés par hash
- `signatures: Map<string, StoredSignature[]>` - Signatures indexées par hash de message
- `keys: Map<string, StoredKey[]>` - Clés de déchiffrement indexées par hash de message
- `seenHashes: Set<string>` - 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** : À larrê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,
publicKey?: string // clé publique identité de l'autre device (ECDH pairing)
}>
```
4. **`userwallet_hash_cache`** : Cache des hash vus (IndexedDB, store `kv`)
```typescript
string[] // Array de hash
```
5. **`userwallet_pairing_confirm`** : Confirmations de pairing (IndexedDB, store `kv`)
```typescript
Array<{ pairLocal: string, pairRemote: string, hash: string, version: number }>
```
6. **`userwallet_keypair`** : (Legacy) Paire de clés
7. **`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)
### Export / Import
- **Export** : Écran « Export / Import données » (`/data`). Télécharge un JSON (identité, relais, pairs, hash_cache, pairing_confirm, keypair, services). `hash_cache` et `pairing_confirm` lus depuis IndexedDB.
- **Import** : Même écran, bouton « Choisir un fichier ». Remplace les données locales (`hash_cache`, `pairing_confirm` écrits en IndexedDB si présents dans lexport) puis recharge la page.
### Protection par mot de passe
- **Activation** : Écran « Export / Import données » → section « Protection par mot de passe ». Mot de passe + confirmation (min. 8 caractères). Chiffrement AES-GCM (clé dérivée PBKDF2-HMAC-SHA256, 100k itérations).
- **Déverrouillage** : Si protection activée, écran « Déverrouiller » affiché tant que la session nest pas ouverte. Mot de passe → clé en session, puis accès aux écrans normaux.
- **Verrouillage** : Bouton « Verrouiller » (accueil ou /data). Vide la session uniquement ; stockage chiffré inchangé.
- **Désactivation** : /data → « Désactiver la protection » (mot de passe actuel). Déchiffrement et réécriture de lidentité avec clé en clair.
### IndexedDB
- **Base** : `userwallet`, store `kv` (key/value).
- **Utilisation** : `hash_cache`, `userwallet_pairing_confirm` (confirmations de pairing). `utils/indexedDbStorage` expose `idbGet`, `idbSet`, `idbRemove`.
- **Migration** : Au premier `HashCache.init()`, si IndexedDB vide et `localStorage` contient `userwallet_hash_cache`, copie vers IndexedDB puis suppression du localStorage.
Pas de synchronisation cloud (hors scope, jamais).