v0.5.2-pre.007
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/README.md -->
|
||||
<!-- version: 36 -->
|
||||
<!-- version: 37 -->
|
||||
|
||||
# Documentation active de Khadhroony Bot3
|
||||
|
||||
@@ -92,13 +92,15 @@ Les douze crates possèdent `README.md`, `TODO.md`, `USAGE.md` et `CHANGELOG.md`
|
||||
- [RPC, backfill et WebSocket](guides/RPC_BACKFILL_AND_WEBSOCKET.md) ;
|
||||
- [Extraction Core, replay et matérialisation](guides/REPLAY_CORE_EXTRACTION_AND_MATERIALIZATION.md) ;
|
||||
- [PostgreSQL et stockage](guides/POSTGRES_STORAGE.md) ;
|
||||
- [Validation Devnet](guides/DEVNET_VALIDATION.md).
|
||||
- [Validation Devnet](guides/DEVNET_VALIDATION.md) ;
|
||||
- [Wallets, sécurité et opérations](guides/WALLETS.md).
|
||||
|
||||
## 9. Rapports de validation actifs
|
||||
|
||||
- [Validation Metaplex Token Metadata 0.4.7](validation/V0_4_7_METAPLEX_TOKEN_METADATA_VALIDATION_REPORT.md) ;
|
||||
- [Validation Metadata on-chain et clôture 0.4.8](validation/V0_4_8_METADATA_VALIDATION_REPORT.md) ;
|
||||
- [Validation de fondation et clôture 0.5.1](validation/V0_5_1_FOUNDATION_VALIDATION_REPORT.md) ;
|
||||
- [Validation wallet et clôture 0.5.2](validation/V0_5_2_WALLET_VALIDATION_REPORT.md) ;
|
||||
- [`validation/WEBSOCKET_MAINNET_RESEARCH_VALIDATION_REPORT.md`](validation/WEBSOCKET_MAINNET_RESEARCH_VALIDATION_REPORT.md) ;
|
||||
- [`validation/MAINNET_RESEARCH_BACKFILL_VALIDATION_SCENARIO.md`](validation/MAINNET_RESEARCH_BACKFILL_VALIDATION_SCENARIO.md).
|
||||
|
||||
@@ -106,10 +108,10 @@ Les preuves détaillées de `0.4.8-pre.*` restent accessibles sous `../olddocs/a
|
||||
|
||||
## 10. Plans de version actifs
|
||||
|
||||
Les plans temporaires `0.5.0` et `0.5.1` sont clôturés et archivés sous `../olddocs/archivekbot3/docs/plans/`.
|
||||
Les plans temporaires `0.5.0`, `0.5.1` et `0.5.2` sont clôturés et archivés sous `../olddocs/archivekbot3/docs/plans/`.
|
||||
|
||||
Le plan temporaire détaillé de `0.5.2` est actif sous [`plans/V0_5_2_KS_WALLET_RESTRUCTURING_PLAN.md`](plans/V0_5_2_KS_WALLET_RESTRUCTURING_PLAN.md) et sera archivé lors de la dernière prerelease de `0.5.2`.
|
||||
Le plan détaillé de `0.5.3` sera créé par `0.5.3-pre.001` après audit de `ks-store`.
|
||||
|
||||
## 11. Prompt de reprise
|
||||
|
||||
- [`Prompt actif 0.5.2`](../prompts/031_v0_5_2_ks_wallet_restructuring.md).
|
||||
- [`Prompt actif 0.5.3`](../prompts/032_v0_5_3_ks_store_normalization.md).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/WALLET_FORMAT_COMPATIBILITY.md -->
|
||||
<!-- version: 1 -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Compatibilité import/export des wallets Solana
|
||||
|
||||
@@ -104,3 +104,13 @@ Les adaptations suivantes sont volontairement reportées vers une version ultér
|
||||
- ajouter d'autres wallets uniquement à partir d'un format privé explicitement documenté et testable.
|
||||
|
||||
Ces reports ne bloquent pas `0.5.2` : le format Solana CLI obligatoire et l'adaptateur tiers Base58 de référence sont couverts dans `pre.005`.
|
||||
|
||||
## Emplacement des exports de démonstration
|
||||
|
||||
`ks-wallet` accepte un chemin de destination explicite fourni par son consommateur. La démo desktop `0.5.2` borne volontairement ses exports opérateur au répertoire :
|
||||
|
||||
```text
|
||||
data/wallets/
|
||||
```
|
||||
|
||||
Cette convention appartient à `kb-app-demo-desktop`; elle ne devient pas une dépendance ou une constante générale de `ks-wallet`.
|
||||
|
||||
324
docs/guides/WALLETS.md
Normal file
324
docs/guides/WALLETS.md
Normal file
@@ -0,0 +1,324 @@
|
||||
<!-- file: docs/guides/WALLETS.md -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Wallets, sécurité et opérations
|
||||
|
||||
## 1. Objet
|
||||
|
||||
Ce guide décrit le contrat opérationnel de `ks-wallet` à partir de `0.5.2`.
|
||||
|
||||
`ks-wallet` possède :
|
||||
|
||||
- le stockage local des wallets Solana persistants ;
|
||||
- la protection par mot de passe ;
|
||||
- l'ouverture authentifiée ;
|
||||
- la capacité de signature ;
|
||||
- les imports/exports de formats secrets explicitement supportés.
|
||||
|
||||
Il ne possède pas :
|
||||
|
||||
- la politique d'autorisation d'une transaction ;
|
||||
- les plafonds de dépense ;
|
||||
- le routage RPC ;
|
||||
- la classification on-chain d'une pubkey ;
|
||||
- les DTO frontend d'une application Tauri.
|
||||
|
||||
## 2. Modèle de données
|
||||
|
||||
### 2.1 Identité publique
|
||||
|
||||
Une identité publique contient uniquement :
|
||||
|
||||
- alias ;
|
||||
- pubkey ;
|
||||
- persistance temporaire ou persistante.
|
||||
|
||||
Une identité publique ne contient jamais le secret, le mot de passe, le ciphertext ou un chemin local.
|
||||
|
||||
### 2.2 Wallet temporaire
|
||||
|
||||
`TemporaryWallet::generate()` crée un keypair en mémoire. Il ne nécessite ni mot de passe ni fichier.
|
||||
|
||||
Cette surface reste adaptée aux tests synthétiques et signers jetables. Les fixtures/keypairs persistées uniquement pour les campagnes historiques restent sous `wallets/temporary/**`; elles ne doivent pas être confondues avec les `.kswallet` persistants de `wallets/`.
|
||||
|
||||
### 2.3 Wallet persistant
|
||||
|
||||
Le format natif est :
|
||||
|
||||
```text
|
||||
<alias>.kswallet
|
||||
```
|
||||
|
||||
Le layout exact est défini dans [`../NATIVE_FORMAT.md`](../NATIVE_FORMAT.md).
|
||||
|
||||
Le store automatique de `WalletManager` :
|
||||
|
||||
- scanne uniquement son répertoire configuré ;
|
||||
- ne descend pas récursivement ;
|
||||
- ignore les extensions étrangères ;
|
||||
- refuse symlinks et fichiers non réguliers ;
|
||||
- exige des permissions privées sous Unix ;
|
||||
- valide le conteneur complet avant de retourner un handle.
|
||||
|
||||
## 3. Protection cryptographique
|
||||
|
||||
Le format v1 utilise :
|
||||
|
||||
| Élément | Contrat v1 |
|
||||
| ----------------- | ---------------------------------- |
|
||||
| KDF | Argon2id v19 |
|
||||
| Profil d'écriture | 64 MiB, 3 passes, 4 lanes |
|
||||
| Sel | 16 octets |
|
||||
| Clé dérivée | 32 octets |
|
||||
| AEAD | XChaCha20-Poly1305 |
|
||||
| Nonce | 24 octets |
|
||||
| Plaintext | keypair Solana exacte de 64 octets |
|
||||
| Ciphertext + tag | 80 octets |
|
||||
| AAD | header + alias + sel + nonce |
|
||||
|
||||
Les paramètres lus sont bornés avant l'exécution du KDF.
|
||||
|
||||
La pubkey présente dans le header n'est pas considérée comme authentifiée avant l'unlock. Après déchiffrement, `ks-wallet` reconstruit le keypair et vérifie que sa pubkey correspond exactement au header avant de produire une capacité de signature.
|
||||
|
||||
## 4. Mot de passe et cycle de vie
|
||||
|
||||
`WalletPassword` :
|
||||
|
||||
- prend possession de sa chaîne ;
|
||||
- n'est pas clonable ;
|
||||
- n'est pas sérialisable ;
|
||||
- possède un `Debug` redacted ;
|
||||
- zéroïse la valeur qu'il possède à la destruction.
|
||||
|
||||
`WalletManager::create()` crée un wallet natif et retourne `UnlockedWallet`.
|
||||
|
||||
`WalletManager::unlock()` ouvre un wallet du store par alias.
|
||||
|
||||
`WalletManager::unlock_file()` ouvre un `WalletFileHandle` obtenu par inspection explicite d'un fichier externe.
|
||||
|
||||
`UnlockedWallet` :
|
||||
|
||||
- possède le keypair authentifié ;
|
||||
- n'est pas clonable ;
|
||||
- expose `Signer` / `Signer + Sync` ;
|
||||
- n'expose pas les 64 octets privés ;
|
||||
- est verrouillé par consommation explicite avec `lock()` ou par fin de portée.
|
||||
|
||||
Un changement de mot de passe ne change pas la keypair. Il produit un nouveau sel et un nouveau nonce, puis reprotège exactement la même identité Solana.
|
||||
|
||||
Une `UnlockedWallet` déjà remise à un consommateur n'est pas révoquée rétroactivement par un changement de mot de passe. Son propriétaire doit la détruire ou appeler `lock()`.
|
||||
|
||||
## 5. Écriture et permissions
|
||||
|
||||
Les nouveaux `.kswallet` sont publiés sans écrasement silencieux.
|
||||
|
||||
Sous Unix :
|
||||
|
||||
- répertoire wallet : `0700` ;
|
||||
- fichier `.kswallet` : `0600` ;
|
||||
- exports secrets : `0600`.
|
||||
|
||||
Les écritures natives utilisent un fichier temporaire privé dans le même répertoire, `sync_all`, puis une publication atomique/no-clobber. Le changement de mot de passe remplace le fichier après authentification de l'ancien secret.
|
||||
|
||||
Les collisions concurrentes de création d'un même alias doivent produire exactement un gagnant et conserver une destination native valide.
|
||||
|
||||
## 6. Configuration
|
||||
|
||||
`wallet.config.json` contient une racine globale `wallets_directory` et des profils.
|
||||
|
||||
Un profil peut sélectionner :
|
||||
|
||||
```json
|
||||
{
|
||||
"wallet_alias": "operator"
|
||||
}
|
||||
```
|
||||
|
||||
ou laisser :
|
||||
|
||||
```json
|
||||
{
|
||||
"wallet_alias": null
|
||||
}
|
||||
```
|
||||
|
||||
L'alias est une sélection non sensible. Aucun mot de passe n'est stocké dans `ks-config`.
|
||||
|
||||
Lorsqu'un alias persistant est configuré, un consommateur ne doit pas retomber silencieusement sur un wallet temporaire : il doit acquérir explicitement le mot de passe et appeler l'API d'unlock.
|
||||
|
||||
## 7. Migration legacy
|
||||
|
||||
Le legacy historique est :
|
||||
|
||||
```text
|
||||
<alias>.json
|
||||
```
|
||||
|
||||
avec le tableau JSON des 64 octets du keypair Solana.
|
||||
|
||||
`WalletManager::migrate_legacy()` :
|
||||
|
||||
1. lit la source legacy privée ;
|
||||
2. valide le keypair ;
|
||||
3. crée `<alias>.kswallet` ;
|
||||
4. vérifie que la pubkey est identique ;
|
||||
5. conserve la source JSON intacte.
|
||||
|
||||
La suppression du legacy reste une décision explicite de l'opérateur après validation.
|
||||
|
||||
`TemporaryWalletStore` reste disponible pour les scénarios historiques. Ses erreurs, logs et `Debug` ne doivent pas projeter les chemins locaux, même si ses getters explicites `directory()` et `wallet_path()` restent nécessaires aux outils de fixtures.
|
||||
|
||||
## 8. Import et export
|
||||
|
||||
Les formats secrets actuellement supportés sont :
|
||||
|
||||
| Format | Import | Export | Mot de passe requis à l'export |
|
||||
| ---------------------------------------------- | :----: | :----: | :----------------------------: |
|
||||
| `WalletTransferFormat::SolanaCliJson` | oui | oui | oui |
|
||||
| `WalletTransferFormat::SolanaPrivateKeyBase58` | oui | oui | oui |
|
||||
|
||||
La matrice détaillée est dans [`../WALLET_FORMAT_COMPATIBILITY.md`](../WALLET_FORMAT_COMPATIBILITY.md).
|
||||
|
||||
L'import refuse :
|
||||
|
||||
- source non régulière ou symlink ;
|
||||
- permissions trop ouvertes sous Unix ;
|
||||
- format invalide ;
|
||||
- keypair de taille incorrecte ;
|
||||
- alias déjà occupé ;
|
||||
- pubkey déjà gérée sous un autre alias natif.
|
||||
|
||||
L'export authentifie d'abord le `.kswallet`, puis seulement après crée la destination. Il n'écrase jamais silencieusement un fichier existant.
|
||||
|
||||
## 9. Keypair, wallet, mint et authority
|
||||
|
||||
Une keypair Solana ne contient pas son rôle métier.
|
||||
|
||||
Le même type de secret Ed25519 peut servir comme :
|
||||
|
||||
- payer/opérateur ;
|
||||
- mint authority ;
|
||||
- freeze authority ;
|
||||
- clé utilisée lors de la création d'un mint ;
|
||||
- recipient possédant lui-même un signer ;
|
||||
- autre authority ou signer de fixture.
|
||||
|
||||
Il est donc incorrect de décider « ce fichier est un mint et non un wallet » uniquement à partir du tableau JSON de 64 octets.
|
||||
|
||||
La future inspection de `wallets/temporary/**` prévue avec `0.5.4` doit produire un inventaire local factuel :
|
||||
|
||||
```text
|
||||
format détecté
|
||||
keypair valide / invalide / format non supporté
|
||||
pubkey si valide
|
||||
```
|
||||
|
||||
Un consommateur peut ensuite interroger un réseau donné avec cette pubkey et classifier l'état actuel de l'adresse, par exemple :
|
||||
|
||||
- compte absent ;
|
||||
- compte système ;
|
||||
- mint SPL Token ;
|
||||
- mint Token-2022 ;
|
||||
- compte token ;
|
||||
- programme ou autre compte.
|
||||
|
||||
Cette classification reste réseau-dépendante et ne prouve pas tous les rôles historiques du signer.
|
||||
|
||||
`ks-wallet` ne doit pas dépendre de `ks-onchain-transport` pour réaliser cette classification.
|
||||
|
||||
## 10. Desktop de démonstration
|
||||
|
||||
`kb-app-demo-desktop` possède ses propres DTO Tauri et ne sérialise pas les types secrets de `ks-wallet`.
|
||||
|
||||
La fenêtre Wallets permet :
|
||||
|
||||
- inventaire des `.kswallet` de `wallets/` ;
|
||||
- création d'un wallet natif avec un secret backend-only ;
|
||||
- inspection d'un `.kswallet` externe ;
|
||||
- inspection/import d'un keypair Solana CLI JSON ou Base58 sans exposer son secret au frontend ;
|
||||
- export secret authentifié vers `data/wallets/` avec nom de fichier borné et sans chemin arbitraire côté frontend ;
|
||||
- sélection explicite d'un profil RPC pour les lectures publiques ;
|
||||
- consultation du solde SOL, des comptes SPL Token/Token-2022, des signatures récentes et du détail `getTransaction` ;
|
||||
- sélection session-only du `.kswallet` utilisé par les démos Devnet.
|
||||
|
||||
Le mot de passe de démonstration est lu uniquement côté backend depuis :
|
||||
|
||||
```text
|
||||
KB_SECRET_DEMO_WALLET_PASSWORD
|
||||
```
|
||||
|
||||
La sélection runtime du wallet d'exécution est authentifiée avant activation et ne réécrit pas `wallet.config.json`. L'ordre de résolution est :
|
||||
|
||||
```text
|
||||
override session demo_wallet
|
||||
-> wallet_alias du profil
|
||||
-> wallet temporaire uniquement si aucun alias persistant n'est sélectionné
|
||||
```
|
||||
|
||||
Lorsqu'un alias persistant est effectif, les adaptateurs Devnet System/SPL/Metadata utilisent une capacité `UnlockedWallet` et ne retombent pas silencieusement sur le JSON temporaire. La validation opérateur `0.5.2` a observé `persistence="persistent"` avec la pubkey sélectionnée.
|
||||
|
||||
Le profil RPC choisi dans la fenêtre Wallets ne modifie ni le profil actif global ni le store wallet actif ; il borne uniquement les lectures on-chain de cette fenêtre.
|
||||
|
||||
### 10.1 Répertoires opérateur
|
||||
|
||||
La convention du desktop est :
|
||||
|
||||
```text
|
||||
wallets/
|
||||
<alias>.kswallet
|
||||
temporary/<profil>/...
|
||||
|
||||
data/wallets/
|
||||
<exports secrets explicites>
|
||||
```
|
||||
|
||||
`wallets/` est la racine persistante native. `wallets/temporary/**` appartient aux fixtures/keypairs historiques. `data/wallets/` contient les exports explicites destinés à des outils externes et ne doit pas être rescanné automatiquement comme store natif.
|
||||
|
||||
### 10.2 Validation du changement de mot de passe
|
||||
|
||||
Le changement de mot de passe n'est volontairement pas exposé dans le frontend. La crate `ks-wallet-demo-scenarios` valide ce cycle comme consommateur externe de l'API publique :
|
||||
|
||||
```text
|
||||
A -> B
|
||||
A rejeté
|
||||
B ouvre et signe
|
||||
B -> A
|
||||
A ouvre et signe
|
||||
```
|
||||
|
||||
Le test utilise un `.kswallet` synthétique dans un répertoire temporaire privé et ne modifie aucun wallet réel de l'opérateur.
|
||||
|
||||
## 11. Non-divulgation
|
||||
|
||||
Ne jamais placer un secret wallet dans :
|
||||
|
||||
- `wallet.config.json` ;
|
||||
- `KS_PUBLIC_*` ou `KB_PUBLIC_*` ;
|
||||
- un payload Tauri ;
|
||||
- un DTO TS-RS généraliste ;
|
||||
- un log ;
|
||||
- un message d'erreur normal ;
|
||||
- un `Debug` automatique d'un type sensible.
|
||||
|
||||
Les chemins locaux ne sont pas des secrets cryptographiques, mais ils restent des informations internes et ne doivent pas apparaître inutilement dans les logs, erreurs et DTO fonctionnels.
|
||||
|
||||
## 12. Modèle de menace borné
|
||||
|
||||
`0.5.2` protège le secret persistant contre la lecture directe du fichier sans mot de passe et impose des permissions privées ainsi qu'un chiffrement authentifié.
|
||||
|
||||
Cette version ne prétend pas protéger contre :
|
||||
|
||||
- une machine déjà compromise pendant qu'un wallet est déverrouillé ;
|
||||
- un processus disposant des mêmes droits utilisateur et capable de lire la mémoire ;
|
||||
- la saisie volontaire du mot de passe dans un programme malveillant ;
|
||||
- la copie volontaire d'un `.kswallet` et de son mot de passe vers une autre installation compatible ;
|
||||
- hardware wallet, Ledger, KMS ou HSM.
|
||||
|
||||
## 13. Références
|
||||
|
||||
- [`../../ks-wallet/README.md`](../../ks-wallet/README.md)
|
||||
- [`../../ks-wallet/USAGE.md`](../../ks-wallet/USAGE.md)
|
||||
- [`../../ks-wallet-demo-scenarios/README.md`](../../ks-wallet-demo-scenarios/README.md)
|
||||
- [`../NATIVE_FORMAT.md`](../NATIVE_FORMAT.md)
|
||||
- [`../WALLET_FORMAT_COMPATIBILITY.md`](../WALLET_FORMAT_COMPATIBILITY.md)
|
||||
- [`../validation/V0_5_2_WALLET_VALIDATION_REPORT.md`](../validation/V0_5_2_WALLET_VALIDATION_REPORT.md)
|
||||
@@ -1,625 +0,0 @@
|
||||
<!-- file: docs/plans/V0_5_2_KS_WALLET_RESTRUCTURING_PLAN.md -->
|
||||
<!-- version: 11 -->
|
||||
|
||||
# Plan `0.5.2` — restructuration de `ks-wallet`
|
||||
|
||||
## 1. Objet du plan
|
||||
|
||||
Ce document est le plan temporaire de `0.5.2`.
|
||||
|
||||
`0.5.2-pre.001` reste une prerelease de caractérisation et de cadrage. Elle ne modifie encore aucune API runtime, aucun wallet persistant et aucun format de stockage.
|
||||
|
||||
L'objectif fonctionnel de `0.5.2` est simple : faire de `ks-wallet` le composant Solana généraliste chargé de créer, conserver, ouvrir, signer avec, importer, exporter et gérer plusieurs wallets sans exposer directement leur matériau secret aux consommateurs.
|
||||
|
||||
Le plan doit rester centré sur ce besoin. Les détails cryptographiques ou de concurrence ne deviennent des choix d'implémentation qu'au moment où ils sont nécessaires.
|
||||
|
||||
## 2. Cible fonctionnelle
|
||||
|
||||
À la fin de `0.5.2`, `ks-wallet` doit pouvoir couvrir les responsabilités suivantes.
|
||||
|
||||
### 2.1 Plusieurs wallets persistants
|
||||
|
||||
`ks-wallet` doit pouvoir :
|
||||
|
||||
- créer plusieurs wallets ;
|
||||
- les identifier et y accéder par alias ;
|
||||
- lister leurs identités non sensibles ;
|
||||
- charger un wallet existant ;
|
||||
- refuser les collisions ou écrasements silencieux ;
|
||||
- supprimer un wallet uniquement via une opération explicite si cette surface est retenue pendant l'implémentation.
|
||||
|
||||
Un consommateur ne doit pas avoir besoin de connaître le chemin réel du fichier ou son format interne pour travailler avec un wallet.
|
||||
|
||||
La découverte des wallets persistants doit être faite par `ks-wallet` directement dans la racine globale `wallet.config.json.wallets_directory`, surchargeable par `KS_WALLETS_DIRECTORY` et valant `wallets` par défaut. Les sous-répertoires propres aux profils sont réservés aux wallets/keypairs temporaires et sont exposés séparément par `temporary_wallet_dir`.
|
||||
|
||||
Le store doit donc pouvoir scanner son répertoire résolu à la recherche des fichiers :
|
||||
|
||||
```text
|
||||
<alias>.kswallet
|
||||
```
|
||||
|
||||
Le scan doit être borné au répertoire possédé par le store, non récursif par défaut, refuser les symlinks/fichiers non réguliers et ne considérer un candidat comme wallet qu'après validation de l'alias, du suffixe, du magic et de la version du conteneur. Le nom de fichier n'est pas à lui seul une preuve de validité.
|
||||
|
||||
Cette découverte automatique n'interdit pas l'ouverture explicite d'un fichier natif situé ailleurs. Un consommateur, par exemple `kb-app-demo-desktop` après sélection via un file browser, doit pouvoir fournir un chemin arbitraire vers un `.kswallet` à `ks-wallet`. Ce chemin explicite ne modifie pas le répertoire configuré, n'enregistre pas automatiquement le fichier dans le store et ne doit pas être projeté dans une identité publique ou un DTO frontend. L'ouverture réelle utilisera le mot de passe fourni au moment de l'appel ou dans l'étape d'ouverture immédiatement associée.
|
||||
|
||||
### 2.2 Wallets temporaires ou jetables
|
||||
|
||||
`ks-wallet` doit conserver la capacité actuelle de générer des wallets temporaires en mémoire pour :
|
||||
|
||||
- tests synthétiques ;
|
||||
- scénarios Devnet ;
|
||||
- démonstrations ;
|
||||
- comptes intermédiaires ou jetables.
|
||||
|
||||
Un wallet temporaire n'a pas besoin d'être persisté ni protégé par mot de passe tant qu'il reste purement en mémoire.
|
||||
|
||||
La possibilité de convertir explicitement un wallet temporaire en wallet persistant pourra être retenue si elle simplifie l'API sans créer de nouveau risque.
|
||||
|
||||
### 2.3 Mot de passe par wallet persistant
|
||||
|
||||
Chaque wallet persistant géré nativement par `ks-wallet` doit être protégé par un mot de passe propre au conteneur `ks-wallet`.
|
||||
|
||||
Ce mot de passe n'est pas un « mot de passe Solana ». Il sert à protéger le matériau secret persistant géré par `ks-wallet`.
|
||||
|
||||
L'API doit permettre au minimum :
|
||||
|
||||
- création d'un wallet avec mot de passe ;
|
||||
- ouverture/déverrouillage avec mot de passe ;
|
||||
- fermeture/verrouillage lorsqu'une capacité ouverte est conservée en mémoire ;
|
||||
- changement du mot de passe en fournissant l'ancien mot de passe ;
|
||||
- conservation exacte de la même clé publique après changement de mot de passe.
|
||||
|
||||
Le changement de mot de passe **ne change pas la keypair Solana** : il rechiffre le même matériau secret dans le conteneur `.kswallet`.
|
||||
|
||||
Une rotation du secret Ed25519 tout en conservant la même pubkey n'est pas une fonctionnalité valide à prévoir. Pour une keypair Solana standard, la clé publique est dérivée du secret ; changer réellement le secret produit donc un autre wallet/public key. Une éventuelle rotation de clé future serait une opération distincte impliquant une nouvelle identité et, selon les usages, la migration des fonds/authorities.
|
||||
|
||||
La représentation runtime exacte d'un wallet ouvert sera décidée pendant l'implémentation. Le plan n'impose pas prématurément une hiérarchie complexe de sessions.
|
||||
|
||||
### 2.4 Signature sans exposition du secret
|
||||
|
||||
Les consommateurs doivent demander une capacité de signature à `ks-wallet` plutôt que les octets privés.
|
||||
|
||||
`ks-lib` utilise déjà `solana_signer::Signer` sans dépendre de `ks-wallet`. Cette frontière est saine et doit être préservée :
|
||||
|
||||
```text
|
||||
ks-wallet
|
||||
-> fournit/adapte une capacité de signature
|
||||
ks-lib / exécuteurs
|
||||
-> utilisent Signer
|
||||
-> ne connaissent pas le stockage wallet
|
||||
```
|
||||
|
||||
La manière exacte de fournir cette capacité doit respecter les contraintes `Send`/`Sync` réellement nécessaires, sans rendre le matériau secret clonable par commodité.
|
||||
|
||||
### 2.5 Import et export
|
||||
|
||||
`ks-wallet` doit servir d'intermédiaire entre son format natif et les formats externes explicitement supportés.
|
||||
|
||||
L'import doit obligatoirement couvrir le format fichier standard des binaires Solana (`solana-keygen`, `solana`, outils SPL), actuellement utilisé comme legacy par le workspace : tableau JSON des 64 octets de la keypair. L'export vers ce même format standard est également obligatoire dans `0.5.2`.
|
||||
|
||||
Les formats des wallets tiers doivent être inventoriés à partir de documentation officielle ou d'une spécification/source officielle suffisamment précise. D'autres formats pourront être ajoutés uniquement après caractérisation de leurs contrats réels.
|
||||
|
||||
L'export doit distinguer :
|
||||
|
||||
- les données strictement publiques, qui peuvent être exportées sans révéler de secret ;
|
||||
- tout format contenant ou permettant de reconstruire la clé privée.
|
||||
|
||||
**Tout export secret doit obligatoirement demander et valider le mot de passe du wallet.**
|
||||
|
||||
Il ne doit exister aucun export privé implicite simplement pour satisfaire un consommateur interne.
|
||||
|
||||
L'objectif est notamment de pouvoir exporter volontairement un wallet vers un format accepté par des outils ou wallets externes comme les formats Solana réellement compatibles avec Solflare ou d'autres logiciels. Chaque format doit être vérifié avant implémentation ; il ne faut pas inventer un format externe générique supposé universel.
|
||||
|
||||
## 3. Format natif persistant cible
|
||||
|
||||
Le format legacy `<alias>.json` ne doit pas rester le format natif de `ks-wallet`.
|
||||
|
||||
L'orientation retenue pour `0.5.2` est un fichier natif :
|
||||
|
||||
```text
|
||||
<alias>.kswallet
|
||||
```
|
||||
|
||||
Le conteneur `.kswallet` doit être **binaire**, auto-identifiable et versionné.
|
||||
|
||||
Le caractère binaire n'est pas une mesure cryptographique en lui-même. La confidentialité doit venir d'un mécanisme de chiffrement authentifié standard et d'une dérivation de clé adaptée au mot de passe.
|
||||
|
||||
Le format binaire devra au minimum permettre d'identifier sans ambiguïté :
|
||||
|
||||
- un magic/signature de format ;
|
||||
- une version ;
|
||||
- les paramètres nécessaires au déchiffrement ;
|
||||
- le payload protégé ;
|
||||
- les informations d'intégrité/authentification nécessaires.
|
||||
|
||||
`pre.003` ferme cette décision technique pour le format v1 après vérification des dépendances et des références cryptographiques :
|
||||
|
||||
- KDF : Argon2id version 19 ;
|
||||
- profil d'écriture par défaut : 64 MiB, 3 passes, 4 lanes, sel 16 octets, sortie 32 octets ;
|
||||
- AEAD : XChaCha20-Poly1305, clé 32 octets, nonce 24 octets, tag 16 octets ;
|
||||
- header fixe : 72 octets little-endian avant l'alias ;
|
||||
- plaintext v1 : exactement les 64 octets du keypair Solana ;
|
||||
- ciphertext v1 : exactement 80 octets avec le tag AEAD ;
|
||||
- taille totale v1 : 193 à 256 octets selon la longueur de l'alias ;
|
||||
- paramètres KDF acceptés : mémoire 64 à 256 MiB, 3 à 10 passes, 1 à 8 lanes, avec les relations Argon2 de mémoire validées ;
|
||||
- données authentifiées : header complet + alias + sel + nonce.
|
||||
|
||||
Le layout normatif exact est documenté dans `docs/NATIVE_FORMAT.md`. `pre.003` a fermé la lecture/validation structurelle ; `pre.004` active l'encodage, la publication, la dérivation Argon2id, le chiffrement XChaCha20-Poly1305 et l'ouverture authentifiée sans modifier ce wire.
|
||||
|
||||
## 4. Caractérisation du legacy actuel
|
||||
|
||||
Le stockage persistant actuel de `ks-wallet` utilise :
|
||||
|
||||
```text
|
||||
<alias>.json
|
||||
```
|
||||
|
||||
Le contenu est le tableau JSON standard des **64 octets** d'un keypair Solana.
|
||||
|
||||
### 4.1 Alias
|
||||
|
||||
Le contrat actuel impose :
|
||||
|
||||
- longueur de 1 à 64 octets ;
|
||||
- premier caractère ASCII alphanumérique ;
|
||||
- caractères suivants ASCII alphanumériques, `_` ou `-`.
|
||||
|
||||
Ces règles sont compatibles avec le futur nom `<alias>.kswallet` et doivent être conservées sauf raison explicite découverte pendant les tests de caractérisation.
|
||||
|
||||
### 4.2 Permissions Unix
|
||||
|
||||
Le comportement actuel impose :
|
||||
|
||||
- répertoire wallet privé en `0700` ;
|
||||
- fichier wallet privé en `0600` ;
|
||||
- refus des symlinks et fichiers non réguliers ;
|
||||
- refus des permissions trop ouvertes lors de la lecture.
|
||||
|
||||
Ces propriétés doivent rester au minimum aussi strictes pour `.kswallet` et les exports privés.
|
||||
|
||||
### 4.3 Création et écrasement
|
||||
|
||||
La création actuelle utilise `create_new`, donc réserve exclusivement le nom final et refuse l'écrasement.
|
||||
|
||||
En revanche, le contenu legacy est écrit directement dans le fichier final. La publication n'est donc pas encore une écriture atomique crash-safe par fichier temporaire + renommage.
|
||||
|
||||
Le nouveau format devra être écrit atomiquement et ne jamais écraser silencieusement un wallet existant.
|
||||
|
||||
### 4.4 Lecture et corruption
|
||||
|
||||
Les tests de caractérisation doivent figer le comportement actuel pour :
|
||||
|
||||
- fichier absent ;
|
||||
- fichier déjà présent ;
|
||||
- contenu corrompu ;
|
||||
- contenu tronqué/incomplet ;
|
||||
- mauvais nombre d'octets ;
|
||||
- permissions incorrectes ;
|
||||
- fichier non régulier ou symlink.
|
||||
|
||||
La fixture doit toujours utiliser une clé synthétique.
|
||||
|
||||
## 5. Migration du legacy
|
||||
|
||||
La migration doit être une **importation** du legacy vers le nouveau format `.kswallet`, pas une réécriture destructive in-place du `.json`.
|
||||
|
||||
Le contrat minimal est :
|
||||
|
||||
1. lire et valider le legacy ;
|
||||
2. reconstruire le keypair ;
|
||||
3. vérifier sa clé publique ;
|
||||
4. demander le mot de passe destiné au nouveau wallet ;
|
||||
5. construire le nouveau `.kswallet` ;
|
||||
6. l'écrire atomiquement dans un nouveau fichier ;
|
||||
7. rouvrir et vérifier le nouveau fichier ;
|
||||
8. confirmer que la clé publique est strictement identique ;
|
||||
9. conserver le legacy tant que la migration n'est pas prouvée complète.
|
||||
|
||||
Aucune migration ne doit transformer automatiquement le legacy en place.
|
||||
|
||||
Si un `.kswallet` existe mais est invalide, `ks-wallet` ne doit pas masquer cette corruption en basculant silencieusement sur un ancien `.json`.
|
||||
|
||||
Le nettoyage éventuel du legacy doit être une opération séparée et explicite, après validation de la migration.
|
||||
|
||||
## 6. Import et export : contrat attendu
|
||||
|
||||
### 6.1 Import
|
||||
|
||||
L'import reçoit une source externe, la valide, récupère le matériau secret uniquement en mémoire, puis crée un nouveau wallet natif `.kswallet` protégé par le mot de passe choisi.
|
||||
|
||||
Les collisions doivent être définies séparément pour :
|
||||
|
||||
- alias déjà utilisé ;
|
||||
- même clé publique déjà gérée sous un autre alias.
|
||||
|
||||
Aucun import ne doit écraser silencieusement un wallet existant.
|
||||
|
||||
### 6.2 Export public
|
||||
|
||||
Une identité publique peut exposer ou exporter uniquement des données sûres, par exemple :
|
||||
|
||||
- alias ;
|
||||
- clé publique ;
|
||||
- type/source si utile ;
|
||||
- état logique non sensible.
|
||||
|
||||
### 6.3 Export secret
|
||||
|
||||
Tout export permettant de reconstruire la clé privée doit :
|
||||
|
||||
- demander le mot de passe du wallet ;
|
||||
- vérifier ce mot de passe avant de produire l'export ;
|
||||
- viser un format explicitement demandé ;
|
||||
- appliquer des permissions privées ;
|
||||
- utiliser une écriture atomique ;
|
||||
- refuser l'écrasement silencieux ;
|
||||
- ne jamais loguer le matériau exporté ni le mot de passe.
|
||||
|
||||
Le mot de passe du conteneur `.kswallet` n'a pas à devenir le mot de passe d'un format externe. L'adaptateur d'export doit respecter le contrat du format cible.
|
||||
|
||||
### 6.4 Matrice de compatibilité externe à établir
|
||||
|
||||
`0.5.2` doit produire une matrice documentée des formats d'entrée/sortie réellement utilisables avec les principaux wallets Solana. L'inventaire doit au minimum examiner :
|
||||
|
||||
- Solana CLI / `solana-keygen` ;
|
||||
- Phantom ;
|
||||
- Solflare ;
|
||||
- Backpack ;
|
||||
- Trust Wallet ;
|
||||
- Coinbase Wallet / Base app ;
|
||||
- tout autre wallet Solana majeur dont un format d'import privé est officiellement documenté et techniquement exploitable à partir d'une keypair `ks-wallet`.
|
||||
|
||||
Pour chaque cible, la matrice doit distinguer :
|
||||
|
||||
- import par clé privée brute ;
|
||||
- import par fichier/keystore ;
|
||||
- import par recovery phrase ;
|
||||
- format/encodage exact lorsqu'il est documenté ;
|
||||
- possibilité réelle de produire ce format à partir d'une keypair Solana arbitraire ;
|
||||
- conservation garantie ou non de la même pubkey ;
|
||||
- disponibilité d'une documentation/spécification officielle suffisamment précise pour écrire et tester l'adaptateur.
|
||||
|
||||
La matrice finalisée de `pre.005` se trouve dans [`docs/WALLET_FORMAT_COMPATIBILITY.md`](../WALLET_FORMAT_COMPATIBILITY.md). Les décisions retenues sont :
|
||||
|
||||
| Cible | Surface officiellement documentée | Décision `pre.005` |
|
||||
|-------------------------------|-------------------------------------------------------------------------------|----------------------------------------------------------------|
|
||||
| Solana CLI / `solana-keygen` | fichier keypair JSON standard | import + export `SolanaCliJson` |
|
||||
| Phantom | import/export d'une private key Solana ; private key Base58 documentée Solana | adaptateur tiers de référence `SolanaPrivateKeyBase58` |
|
||||
| Solflare | import d'une private key copiée depuis Phantom | compatible avec le même wire Base58 ; pas de codec séparé |
|
||||
| Solflare Keystore | import de fichier keystore | TODO version ultérieure non déterminée |
|
||||
| Backpack | import avancé par private key ou recovery phrase | TODO : wire Solana exact à caractériser |
|
||||
| Trust Wallet | restauration/export de private keys | TODO : wire Solana exact à caractériser |
|
||||
| Base app / ex-Coinbase Wallet | restauration principalement documentée par recovery phrase | aucun adaptateur ; aucune mnemonic synthétique |
|
||||
| Coinbase Developer Platform | API d'import/export de clés Solana, distincte de Base app | information de compatibilité seulement, hors adaptateur wallet |
|
||||
|
||||
Une recovery phrase n'est pas interchangeable avec une keypair arbitraire. Si `ks-wallet` ne possède que la keypair finale et pas la mnemonic/seed d'origine avec son chemin de dérivation, il ne doit pas inventer une phrase qui prétend restaurer la même pubkey.
|
||||
|
||||
Dans `0.5.2`, après l'adaptateur Solana CLI obligatoire, **un seul adaptateur vers un wallet tiers** est retenu comme exemple de la mécanique d'interopérabilité : `SolanaPrivateKeyBase58`, avec Phantom comme cible de référence documentée. Les autres formats jugés faisables sont ajoutés au `TODO.md` pour une version ultérieure non déterminée.
|
||||
|
||||
Tout adaptateur tiers reste soumis à la règle générale : un export contenant le secret est impossible sans validation du mot de passe du `.kswallet`.
|
||||
|
||||
## 7. Modèle public simple de `ks-wallet`
|
||||
|
||||
Les noms Rust principaux sont désormais stabilisés par les tranches exécutables ; la responsabilité peut être représentée ainsi :
|
||||
|
||||
```text
|
||||
ks-wallet
|
||||
|
|
||||
+-- manager / store
|
||||
| +-- create persistent(alias, password)
|
||||
| +-- create temporary(...)
|
||||
| +-- scan/discover <alias>.kswallet
|
||||
| +-- list identities
|
||||
| +-- find/open by alias
|
||||
| +-- remove explicitement si retenu
|
||||
|
|
||||
+-- password
|
||||
| +-- unlock/open
|
||||
| +-- lock/close
|
||||
| +-- change password
|
||||
|
|
||||
+-- signing
|
||||
| +-- public key
|
||||
| +-- signer capability
|
||||
|
|
||||
+-- import
|
||||
| +-- legacy Solana JSON
|
||||
| +-- autres formats validés
|
||||
|
|
||||
+-- export
|
||||
+-- public
|
||||
+-- secret + password obligatoire
|
||||
```
|
||||
|
||||
Le stockage réel, les bytes privés et les paramètres cryptographiques restent internes à la crate.
|
||||
|
||||
## 8. Multi-wallet et configuration
|
||||
|
||||
`ks-wallet` doit être capable de gérer plusieurs wallets sans notion globale mutable de « wallet actif ».
|
||||
|
||||
La sélection appartient au consommateur :
|
||||
|
||||
```text
|
||||
worker A -> alias A
|
||||
worker B -> alias B
|
||||
application -> alias C
|
||||
```
|
||||
|
||||
`ks-config` peut transporter un alias ou une sélection non sensible, mais ne devient jamais gestionnaire du mot de passe ou du matériau secret.
|
||||
|
||||
Un profil peut continuer à sélectionner un alias lorsqu'un consommateur n'en attend qu'un, mais `ks-wallet` ne doit pas imposer qu'il existe un « alias principal » universel.
|
||||
|
||||
## 9. Consommateurs actuels
|
||||
|
||||
L'inventaire `pre.001` montre deux dépendants directs de `ks-wallet` :
|
||||
|
||||
- `ks-pipeline-demo-scenarios` ;
|
||||
- `kb-app-demo-desktop`.
|
||||
|
||||
`ks-lib` n'a pas de dépendance directe vers `ks-wallet` et consomme des `solana_signer::Signer`. Cette séparation doit être conservée.
|
||||
|
||||
Le desktop ne doit jamais recevoir directement un type runtime sensible de `ks-wallet` :
|
||||
|
||||
```text
|
||||
ks-wallet runtime
|
||||
-> DTO possédé par kb-app-demo-desktop
|
||||
-> TS-RS
|
||||
-> frontend
|
||||
```
|
||||
|
||||
Le DTO peut exposer alias, pubkey et état logique lorsque ces données sont explicitement sûres.
|
||||
|
||||
## 10. Compatibilité avec les outils Solana existants
|
||||
|
||||
Le workspace utilise encore le fichier keypair legacy brut avec certains outils externes, notamment les workflows Devnet autour de `solana-keygen` / `spl-token` et `KS_DEVNET_WALLET`.
|
||||
|
||||
Un `.kswallet` ne doit pas être présenté directement à ces outils.
|
||||
|
||||
La transition doit donc choisir explicitement entre :
|
||||
|
||||
- import/export volontaire vers le format keypair JSON standard accepté par les binaires Solana ;
|
||||
- adaptation d'un scénario pour signer directement via `ks-wallet` ;
|
||||
- maintien borné du legacy pour un workflow de transition.
|
||||
|
||||
Il ne faut pas créer un export privé automatique ou caché juste pour conserver un ancien script.
|
||||
|
||||
## 11. Sécurité et non-divulgation
|
||||
|
||||
Les contraintes suivantes restent non négociables :
|
||||
|
||||
- aucun secret wallet dans un fichier de configuration source ;
|
||||
- aucun secret dans `KS_PUBLIC_*` ou `KB_PUBLIC_*` ;
|
||||
- aucun secret dans Tauri ou TS-RS générique ;
|
||||
- aucun mot de passe, octet privé, payload chiffré ou keypair dans logs/erreurs/diagnostics normaux ;
|
||||
- aucun `Debug` automatique d'un type possédant du matériau secret ;
|
||||
- aucun getter public arbitraire des bytes privés ;
|
||||
- zéroïsation des buffers secrets temporaires lorsque les types et dépendances le permettent ;
|
||||
- les erreurs publiques ne doivent pas inclure inutilement le chemin local complet du wallet.
|
||||
|
||||
Le fait que `.kswallet` soit binaire ne remplace aucune de ces protections.
|
||||
|
||||
## 12. Tests minimums de `0.5.2`
|
||||
|
||||
### 12.1 Legacy
|
||||
|
||||
- fixture synthétique 64 octets ;
|
||||
- alias et nom `<alias>.json` ;
|
||||
- pubkey conservée après lecture/import ;
|
||||
- absent, déjà présent, corrompu, tronqué, longueur invalide ;
|
||||
- permissions Unix ;
|
||||
- symlink et fichier non régulier.
|
||||
|
||||
### 12.2 Format `.kswallet`
|
||||
|
||||
- magic et version ;
|
||||
- version inconnue ;
|
||||
- troncature/corruption ;
|
||||
- mauvais mot de passe ;
|
||||
- intégrité/authentification ;
|
||||
- permissions privées ;
|
||||
- écriture atomique ;
|
||||
- refus d'écrasement ;
|
||||
- persistance puis réouverture ;
|
||||
- absence de secret dans `Debug`, erreurs et logs.
|
||||
|
||||
### 12.3 Multi-wallet et password
|
||||
|
||||
- création de plusieurs aliases ;
|
||||
- lookup par alias ;
|
||||
- collision d'alias ;
|
||||
- collision de pubkey selon le contrat retenu ;
|
||||
- changement de mot de passe ;
|
||||
- ancien mot de passe refusé après changement ;
|
||||
- nouveau mot de passe accepté ;
|
||||
- pubkey inchangée ;
|
||||
- vérification que la keypair est strictement identique avant/après changement de mot de passe ;
|
||||
- absence d'API prétendant faire tourner le secret Ed25519 en conservant la pubkey.
|
||||
|
||||
### 12.4 Temporaire et signature
|
||||
|
||||
- génération purement mémoire ;
|
||||
- signature valide ;
|
||||
- aucune persistance involontaire ;
|
||||
- capacité de signature utilisable par les consommateurs réels sans exposition des bytes ;
|
||||
- contraintes thread-safety des chemins effectivement utilisés.
|
||||
|
||||
### 12.5 Import/export
|
||||
|
||||
- import du fichier Solana CLI JSON préservant la pubkey ;
|
||||
- export vers le fichier Solana CLI JSON avec mot de passe valide ;
|
||||
- round-trip `.kswallet` -> Solana CLI JSON -> import préservant la pubkey ;
|
||||
- import corrompu refusé ;
|
||||
- collision refusée ;
|
||||
- export secret impossible sans mot de passe valide ;
|
||||
- export secret avec mot de passe valide vers chaque format effectivement supporté ;
|
||||
- matrice Phantom/Solflare/Backpack/Trust/Coinbase-Base et autres cibles retenues ;
|
||||
- un adaptateur wallet tiers d'exemple implémenté et testé ;
|
||||
- autres adaptateurs faisables reportés explicitement au TODO ;
|
||||
- permissions privées et écriture atomique de l'export ;
|
||||
- aucun secret dans les erreurs/logs.
|
||||
|
||||
### 12.6 Configuration et desktop
|
||||
|
||||
- sélection d'un alias sans secret dans `ks-config` ;
|
||||
- aucune dépendance inverse vers une application ;
|
||||
- DTO desktop non sensible ;
|
||||
- canaris de non-divulgation des mots de passe, bytes privés, chemins internes et payloads protégés.
|
||||
|
||||
## 13. Découpage proposé des prereleases
|
||||
|
||||
Le découpage reste borné mais peut être ajusté si une tranche devient trop large après compilation/tests.
|
||||
|
||||
### `0.5.2-pre.001` — plan et caractérisation
|
||||
|
||||
- audit du code et des consommateurs ;
|
||||
- caractérisation legacy ;
|
||||
- besoins multi-wallet, temporary wallet, password, import/export ;
|
||||
- orientation `.kswallet` binaire ;
|
||||
- contrat migration/rollback ;
|
||||
- plan temporaire.
|
||||
|
||||
**Aucun nouveau format n'est écrit dans cette prerelease.**
|
||||
|
||||
### `0.5.2-pre.002` — caractérisation exécutable et API de base
|
||||
|
||||
- tests externes du legacy ;
|
||||
- identité publique minimale sans chemin local ;
|
||||
- manager/scan/listing/lookup multi-wallet sur le répertoire configuré ;
|
||||
- inspection explicite d'un `.kswallet` hors store sans mutation de la configuration ni auto-enregistrement ;
|
||||
- préambule d'identification natif minimal `magic + version`, uniquement pour rendre la découverte exécutable ;
|
||||
- contrat de wallet temporaire ;
|
||||
- frontière de signature compatible avec `ks-lib`.
|
||||
|
||||
Le préambule d'identification introduit ici ne définit pas encore le payload protégé : le codec complet, les bornes du conteneur, KDF et AEAD restent dans `pre.003`.
|
||||
|
||||
### `0.5.2-pre.003` — format et décodage `.kswallet`
|
||||
|
||||
- [x] spécification binaire v1 documentée dans `docs/NATIVE_FORMAT.md` ;
|
||||
- [x] Argon2id v19 + XChaCha20-Poly1305 retenus et identifiés explicitement dans le header ;
|
||||
- [x] profil KDF par défaut 64 MiB / 3 passes / 4 lanes et bornes anti-DoS ;
|
||||
- [x] décodage/validation stricts avec rejet des versions, flags, algorithmes, réserves et longueurs inconnus ;
|
||||
- [x] plaintext keypair v1 fixé à 64 octets, ciphertext/tag à 80 octets et fichier total à 193..256 octets ;
|
||||
- [x] lecture bornée avant allocation et détection d'une croissance concurrente ;
|
||||
- [x] alias du header vérifié contre le nom `<alias>.kswallet` ;
|
||||
- [x] `WalletFileHandle` enrichi de la pubkey déclarée et de la version sans exposer le chemin ;
|
||||
- [x] validation des permissions privées à la lecture ;
|
||||
- [x] encodage de création et publication atomique/no-clobber explicitement reportés à `pre.004` ;
|
||||
- [x] tests du wire v1, truncation, trailing bytes, KDF hors bornes, alias mismatch et réouverture bornée.
|
||||
|
||||
La tranche `pre.003` reste structurelle ; le cycle de vie protégé est activé par `pre.004` ci-dessous.
|
||||
|
||||
### `0.5.2-pre.004` — password et cycle de vie persistant
|
||||
|
||||
- [x] `WalletPassword` possédé, non clonable, redacted et consommé par une opération ;
|
||||
- [x] création persistante avec password et publication atomique/no-clobber ;
|
||||
- [x] dérivation Argon2id et XChaCha20-Poly1305 effectifs hors du runtime async ;
|
||||
- [x] ouverture/déverrouillage par alias ;
|
||||
- [x] ouverture authentifiée d'un `WalletFileHandle` sélectionné hors store ;
|
||||
- [x] `UnlockedWallet` comme capacité de signature non clonable ;
|
||||
- [x] fermeture/verrouillage par consommation explicite ou fin de portée de `UnlockedWallet` ;
|
||||
- [x] changement de mot de passe après authentification de l'ancien, avec nouveau sel/nonce et même keypair/pubkey ;
|
||||
- [x] contrat explicite : la rotation du mot de passe reprotège le fichier mais ne révoque pas une `UnlockedWallet` déjà remise à un consommateur ;
|
||||
- [x] vérification de la pubkey déchiffrée contre le header authentifié avant exposition du signer ;
|
||||
- [x] zéroïsation des buffers secrets possédés et activation de la zéroïsation du cipher ;
|
||||
- [x] tests d'ancien/nouveau mot de passe, signature, ouverture externe, AAD altéré et canaris de non-divulgation.
|
||||
|
||||
### `0.5.2-pre.005` — migration, import et export
|
||||
|
||||
- [x] import legacy/Solana CLI JSON vers `.kswallet` sans modification de la source ;
|
||||
- [x] export `.kswallet` vers le format Solana CLI JSON après authentification du mot de passe ;
|
||||
- [x] rollback d'une destination native nouvelle si la vérification post-publication échoue et conservation du legacy ;
|
||||
- [x] matrice officielle finalisée dans `docs/WALLET_FORMAT_COMPATIBILITY.md` ;
|
||||
- [x] adaptateur tiers `SolanaPrivateKeyBase58`, avec Phantom comme cible de référence et compatibilité Phantom -> Solflare documentée ;
|
||||
- [x] report Backpack/Trust/Solflare Keystore/Base app au TODO pour une version ultérieure non déterminée ;
|
||||
- [x] password obligatoire pour tout export secret ;
|
||||
- [x] collisions d'alias et de pubkey refusées sans écrasement ;
|
||||
- [x] tests de round-trip Solana CLI JSON/Base58, migration non destructive, permissions privées, collision et mauvais mot de passe.
|
||||
|
||||
### `0.5.2-pre.006` — configuration et consommateurs
|
||||
|
||||
- [x] `wallet_alias` optionnel/nullable dans les profils `wallet.config.json`, propagé dans `WalletConfig` sans secret et rétrocompatible avec les documents `0.5.1` qui omettent ce champ ;
|
||||
- [x] sélection/inspection/unlock du wallet natif configuré dans `ks-pipeline-demo-scenarios`, avec password fourni uniquement à l'API runtime ;
|
||||
- [x] fallback temporaire interdit lorsqu'un alias persistant est explicitement sélectionné ;
|
||||
- [x] DTO desktop possédés par `kb-app-demo-desktop` pour liste/inspection : alias, pubkey déclarée, version et sélection uniquement ;
|
||||
- [x] aucune commande Tauri de password/unlock et aucun type runtime sensible `ks-wallet` sérialisé vers le frontend ;
|
||||
- [x] workflow CLI Token-2022 explicitement limité au format Solana CLI JSON et rejet des `.kswallet` ;
|
||||
- [x] tests de configuration, sélection persistante, unlock explicite, refus du fallback et canaris de non-divulgation ;
|
||||
- [x] séparation de `wallet_dir` persistant (`wallets_directory`, donc `wallets/` par défaut) et `temporary_wallet_dir` propre au profil (`wallets/temporary/<profil>` par défaut) ;
|
||||
- [x] résolution d'une capacité `DevnetExecutionWallet` commune : `.kswallet` authentifié quand `wallet_alias` est défini, wallet temporaire uniquement quand aucune sélection persistante n'existe ;
|
||||
- [x] propagation de cette capacité aux démos System, Memo, ATA, SPL Token, Token-2022, Solana Program Metadata, Token-2022 Metadata et à toutes les campagnes Metaplex qualifiées ;
|
||||
- [x] sélection session-only d'un alias `.kswallet` par profil Devnet depuis `demo_wallet`, prioritaire sur `wallet_alias` sans réécriture de la configuration et authentifiée avant activation ;
|
||||
- [x] export secret desktop contraint au répertoire applicatif `data/wallets/`, avec nom de fichier borné et permissions privées ;
|
||||
- [x] conservation des keypairs réellement secondaires et jetables — mints, delegates, destinations et authorities de fixtures — dans le répertoire temporaire.
|
||||
|
||||
Cette tranche ne devient pas la refonte générale des scénarios prévue pour `0.5.4`. Lorsque `wallet_alias = null`, les campagnes conservent leur comportement temporaire historique ; lorsqu'il est défini, le signer opérateur/payer doit provenir du `.kswallet` et aucun fallback JSON n'est autorisé.
|
||||
|
||||
### `0.5.2-pre.007` — finalisation
|
||||
|
||||
- réconciliation des contrats ;
|
||||
- validations finales ;
|
||||
- README/USAGE/TODO/changelogs/guides ;
|
||||
- report des tâches restantes vers une version identifiée ;
|
||||
- mise à jour du ROADMAP ;
|
||||
- archivage du plan et du prompt `0.5.2` sous `olddocs/archivekbot3/` ;
|
||||
- préparation du prompt `0.5.3` consacré à `ks-store`.
|
||||
|
||||
## 14. Critères de clôture
|
||||
|
||||
`0.5.2` est terminée lorsque :
|
||||
|
||||
- plusieurs wallets persistants peuvent être découverts dans le store et gérés par alias ;
|
||||
- les wallets temporaires restent disponibles pour tests/scénarios ;
|
||||
- le format natif persistant est `.kswallet`, binaire, versionné et protégé par mot de passe ;
|
||||
- le changement de mot de passe conserve exactement la même keypair et donc la pubkey ;
|
||||
- un consommateur peut signer sans obtenir les bytes privés ;
|
||||
- le legacy peut être importé sans perte ni écrasement destructif ;
|
||||
- le format Solana CLI JSON dispose d'un import/export testé ;
|
||||
- un adaptateur vers un wallet tiers documenté est implémenté et testé ;
|
||||
- les autres formats tiers faisables identifiés sont consignés au TODO ;
|
||||
- tout export secret exige un mot de passe valide ;
|
||||
- `ks-config` ne contient que de la sélection non sensible ;
|
||||
- `ks-lib` reste indépendant du stockage wallet ;
|
||||
- le desktop ne reçoit que des DTO sûrs ;
|
||||
- permissions, atomicité, corruption, collisions et non-divulgation sont testées ;
|
||||
- la documentation finale décrit le contrat réellement implémenté.
|
||||
|
||||
## 15. Hors périmètre
|
||||
|
||||
Restent hors `0.5.2` :
|
||||
|
||||
- migration SQL `kb_sol_*` -> `k_sol_*` ;
|
||||
- audit temporel/provenance de `ks-store` ;
|
||||
- centralisation générale des scénarios `0.5.4` ;
|
||||
- nouvelle couverture Anchor/DEX ;
|
||||
- stockage d'un secret wallet dans PostgreSQL ;
|
||||
- hardware wallets / Ledger ;
|
||||
- KMS/HSM ;
|
||||
- remote signers ;
|
||||
- secret manager universel ;
|
||||
- cloud backup ;
|
||||
- protection contre un utilisateur qui transfère volontairement un fichier `.kswallet` avec son mot de passe à une autre installation capable de comprendre ce format.
|
||||
|
||||
## 16. Décisions validées pour poursuivre après `pre.001`
|
||||
|
||||
Le plan est désormais centré sur les décisions suivantes :
|
||||
|
||||
1. `ks-wallet` gère plusieurs wallets accessibles par alias ;
|
||||
2. `ks-wallet` conserve des wallets temporaires/jetables ;
|
||||
3. chaque wallet persistant natif possède un mot de passe modifiable ;
|
||||
4. le format natif cible est un conteneur **binaire** `<alias>.kswallet` ;
|
||||
5. le format binaire utilise des primitives cryptographiques standard, pas une cryptographie propriétaire ;
|
||||
6. les consommateurs signent via une capacité contrôlée sans accéder aux bytes privés ;
|
||||
7. `ks-lib` reste indépendant de `ks-wallet` et du stockage ;
|
||||
8. import et export vers des formats externes font partie du périmètre `0.5.2` ;
|
||||
9. tout export secret exige le mot de passe valide du wallet ;
|
||||
10. la migration legacy crée un nouveau `.kswallet`, valide la pubkey et conserve le legacy jusqu'à preuve de réussite ;
|
||||
11. `ks-config` peut sélectionner des aliases mais ne gère aucun secret ;
|
||||
12. la découverte persistante scanne le répertoire wallet résolu pour les `<alias>.kswallet`, sans faire confiance au seul nom de fichier ;
|
||||
13. changer le password rechiffre la même keypair ; il n'existe pas de rotation du secret Ed25519 conservant la même pubkey ;
|
||||
14. le format keypair JSON des binaires Solana est obligatoire en import et en export dans `0.5.2` ;
|
||||
15. la matrice officielle des formats Phantom/Solflare/Backpack/Trust/Coinbase-Base est finalisée dans `docs/WALLET_FORMAT_COMPATIBILITY.md` ;
|
||||
16. `SolanaPrivateKeyBase58` est l'adaptateur tiers unique de `0.5.2`, avec Phantom comme référence ; les autres formats faisables sont reportés au TODO sans version déterminée ;
|
||||
17. le format v1 utilise Argon2id v19 et XChaCha20-Poly1305 selon `docs/NATIVE_FORMAT.md`, et `pre.004` ferme le modèle runtime avec `WalletPassword` + `UnlockedWallet` ;
|
||||
18. le scan automatique reste limité au répertoire configuré, tandis qu'un consommateur peut fournir explicitement un autre chemin `.kswallet` à `ks-wallet` sans modifier le store ni enregistrer ce fichier automatiquement.
|
||||
|
||||
Ces décisions ont permis d'ouvrir `0.5.2-pre.002`.
|
||||
185
docs/validation/V0_5_2_WALLET_VALIDATION_REPORT.md
Normal file
185
docs/validation/V0_5_2_WALLET_VALIDATION_REPORT.md
Normal file
@@ -0,0 +1,185 @@
|
||||
<!-- file: docs/validation/V0_5_2_WALLET_VALIDATION_REPORT.md -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Validation `ks-wallet` — clôture 0.5.2
|
||||
|
||||
## 1. Périmètre
|
||||
|
||||
`0.5.2` transforme `ks-wallet` en frontière Solana réutilisable pour :
|
||||
|
||||
- wallets temporaires en mémoire ;
|
||||
- plusieurs wallets persistants accessibles par alias ;
|
||||
- conteneur natif `.kswallet` binaire, versionné et protégé par mot de passe ;
|
||||
- capacité de signature sans exposition des bytes privés ;
|
||||
- migration/inspection legacy ;
|
||||
- import/export Solana CLI JSON et Base58 ;
|
||||
- sélection non sensible depuis `ks-config` ;
|
||||
- validation intégrée indépendante de Tauri via `ks-wallet-demo-scenarios` ;
|
||||
- intégration opérateur desktop via DTO applicatifs sûrs.
|
||||
|
||||
La version ne transforme pas `ks-wallet` en client RPC et ne migre pas en masse les keypairs de fixtures sous `wallets/temporary/**`.
|
||||
|
||||
## 2. Organisation des données
|
||||
|
||||
La séparation validée est :
|
||||
|
||||
```text
|
||||
wallets/
|
||||
<alias>.kswallet
|
||||
temporary/<profil>/...
|
||||
|
||||
data/wallets/
|
||||
<exports JSON/Base58 explicites>
|
||||
```
|
||||
|
||||
- `wallets/` : store natif persistant ;
|
||||
- `wallets/temporary/**` : fixtures/keypairs historiques ou jetables ;
|
||||
- `data/wallets/` : exports secrets explicites destinés à des outils externes.
|
||||
|
||||
Le desktop n'utilise pas `data/wallets/` comme store natif automatique.
|
||||
|
||||
## 3. Format natif et sécurité
|
||||
|
||||
Le format v1 validé utilise :
|
||||
|
||||
| Contrat | Valeur |
|
||||
|-------------------|------------------------------------|
|
||||
| Extension | `.kswallet` |
|
||||
| Magic | `KSWALLET` |
|
||||
| KDF | Argon2id v19 |
|
||||
| Profil par défaut | 64 MiB / 3 passes / 4 lanes |
|
||||
| AEAD | XChaCha20-Poly1305 |
|
||||
| Sel | 16 octets |
|
||||
| Nonce | 24 octets |
|
||||
| Plaintext | keypair Solana exacte de 64 octets |
|
||||
| Ciphertext + tag | 80 octets |
|
||||
| AAD | header + alias + sel + nonce |
|
||||
| Répertoire Unix | `0700` |
|
||||
| Fichier Unix | `0600` |
|
||||
|
||||
Le codec rejette versions/algorithmes inconnus, réserves non nulles, troncatures, suffixes, longueurs incorrectes et paramètres KDF hors bornes. La pubkey du header n'est considérée authentifiée qu'après déchiffrement et comparaison avec la pubkey réellement dérivée du keypair.
|
||||
|
||||
La prerelease de clôture retire également les chemins locaux inutiles du `Debug`, des logs et des erreurs du `TemporaryWalletStore` legacy et ajoute un canari externe de non-divulgation.
|
||||
|
||||
## 4. Cycle de vie du mot de passe
|
||||
|
||||
Les surfaces validées comprennent :
|
||||
|
||||
- création native ;
|
||||
- unlock par alias ;
|
||||
- unlock d'un fichier externe inspecté explicitement ;
|
||||
- signature avec `UnlockedWallet` ;
|
||||
- `lock()` par consommation ;
|
||||
- changement de mot de passe avec conservation exacte de l'alias/pubkey ;
|
||||
- refus de l'ancien mot de passe ;
|
||||
- altération des données authentifiées refusée avant capacité de signature ;
|
||||
- refus d'écrasement natif ;
|
||||
- test concurrent de création d'un même alias avec un seul gagnant et une destination valide.
|
||||
|
||||
`ks-wallet-demo-scenarios` valide le cycle ordonné suivant dans un seul test indépendant de Tauri :
|
||||
|
||||
```text
|
||||
A -> B
|
||||
A doit échouer
|
||||
B ouvre et signe
|
||||
B -> A
|
||||
A restauré ouvre et signe
|
||||
```
|
||||
|
||||
La fixture est synthétique et temporaire ; aucun wallet réel de l'opérateur n'est modifié.
|
||||
|
||||
## 5. Migration et transferts
|
||||
|
||||
Les tests externes valident :
|
||||
|
||||
- migration legacy `<alias>.json` non destructive ;
|
||||
- conservation exacte de la pubkey ;
|
||||
- inspection d'un fichier de transfert sans import ;
|
||||
- import/export `SolanaCliJson` ;
|
||||
- import/export `SolanaPrivateKeyBase58` ;
|
||||
- refus des sources invalides ;
|
||||
- collision de pubkey ;
|
||||
- export impossible avec un mauvais mot de passe ;
|
||||
- permissions privées ;
|
||||
- absence d'écrasement silencieux.
|
||||
|
||||
Aucune recovery phrase n'est synthétisée depuis une keypair arbitraire.
|
||||
|
||||
La validation opérateur a confirmé les exports :
|
||||
|
||||
```text
|
||||
data/wallets/local-devnet-operator2.json
|
||||
data/wallets/local-devnet-operator2.txt
|
||||
```
|
||||
|
||||
## 6. Configuration et signer Devnet
|
||||
|
||||
`wallet.config.json` sépare `wallets_directory` de `profile.directory` :
|
||||
|
||||
```text
|
||||
wallet_dir = wallets
|
||||
temporary_wallet_dir = wallets/temporary/<profil>
|
||||
```
|
||||
|
||||
Un profil peut définir `wallet_alias`, sans mot de passe. Le desktop peut aussi définir un override session-only par profil Devnet. La résolution effective est runtime override -> alias configuré -> temporaire seulement lorsqu'aucun alias persistant n'est sélectionné.
|
||||
|
||||
La validation opérateur a confirmé que les démos Devnet utilisent bien le `.kswallet` sélectionné avec une trace `persistence="persistent"`, au lieu du JSON temporaire.
|
||||
|
||||
## 7. Desktop Wallets
|
||||
|
||||
La fenêtre Wallets couvre : inventaire, création, inspection externe, inspection/import de keypairs, export borné sous `data/wallets/`, sélection de profil RPC, balance SOL, comptes SPL Token/Token-2022, signatures récentes, détail de transaction et sélection session-only du wallet d'exécution.
|
||||
|
||||
Les secrets restent backend-only via `KB_SECRET_DEMO_WALLET_PASSWORD`; aucun password n'entre dans HTML, TypeScript ou les DTO Tauri.
|
||||
|
||||
## 8. Validation workspace — base `0.5.2-pre.006 + fix-010`
|
||||
|
||||
L'opérateur a validé :
|
||||
|
||||
```bash
|
||||
cargo fmt --all
|
||||
cargo check --workspace
|
||||
cargo clippy --all-targets
|
||||
python3 scripts/audit_rust_workspace_rules.py
|
||||
cargo test --workspace
|
||||
```
|
||||
|
||||
Résultats :
|
||||
|
||||
- `cargo check --workspace` : succès ;
|
||||
- `cargo clippy --all-targets` : succès sans warning ;
|
||||
- audit Rust général : clean ;
|
||||
- export completeness : `0 candidate(s)` ;
|
||||
- audit Khadhroony workspace : clean ;
|
||||
- `cargo test --workspace` : succès sur toutes les crates et doc-tests ;
|
||||
- `kb-app-demo-desktop` : 185 tests ;
|
||||
- `ks-config` : 35 tests ;
|
||||
- `ks-lib` : 606 tests ;
|
||||
- `ks-logging` : 25 tests ;
|
||||
- `ks-onchain-transport` : 124 tests ;
|
||||
- `ks-pipeline` : 109 tests ;
|
||||
- `ks-pipeline-demo-scenarios` : 109 tests + 2 tests CLI ;
|
||||
- `ks-program-ids` : 6 tests ;
|
||||
- `ks-store` : 84 tests ;
|
||||
- `ks-wallet` : 22 unitaires + 7 legacy + 3 password natif + 2 API publique + 6 transfert ;
|
||||
- `ks-wallet-demo-scenarios` : 1 test d'intégration password ;
|
||||
- doc-tests : succès.
|
||||
|
||||
La `pre.007` ajoute seulement les canaris de non-divulgation legacy, le test concurrent natif et la clôture documentaire ; elle doit donc être rejouée avec la campagne standard avant le passage à `0.5.2` final.
|
||||
|
||||
## 9. Reports explicites
|
||||
|
||||
### `0.5.4`
|
||||
|
||||
- diagnostiquer/réparer la régression `unable to read configured Token-2022 fixture` observée après la séparation des racines wallet/fixtures ;
|
||||
- scanner/inventorier bornément `wallets/temporary/**` ;
|
||||
- extraire format/validité/pubkey sans inventer de rôle métier ;
|
||||
- migrer sélectivement les signers devant devenir persistants ;
|
||||
- laisser toute classification on-chain au consommateur, sans dépendance `ks-wallet -> ks-onchain-transport`.
|
||||
|
||||
### Version ultérieure non déterminée
|
||||
|
||||
- nouveaux formats Backpack, Trust Wallet, Solflare Keystore ou autres uniquement lorsqu'un wire suffisamment spécifié peut être validé et testé.
|
||||
|
||||
## 10. Statut
|
||||
|
||||
**Base fonctionnelle `0.5.2-pre.006 + fix-010` validée. `0.5.2-pre.007` est la prerelease de clôture à valider avant la release finale `0.5.2`.**
|
||||
Reference in New Issue
Block a user