v0.5.2-pre.001

This commit is contained in:
2026-08-10 14:09:39 +02:00
parent 9849aa7084
commit 0bd5bbf1c4
6 changed files with 737 additions and 87 deletions

View File

@@ -1,11 +1,11 @@
<!-- file: ks-wallet/USAGE.md -->
<!-- version: 3 -->
<!-- version: 6 -->
# Utilisation de ks-wallet
## Objectif
## Statut
La crate fournit des wallets temporaires en mémoire ou persistés localement pour les démonstrations et tests dintégration.
En `0.5.2-pre.001`, cette page décrit l'API runtime **actuelle**. La cible multi-wallet/password/`.kswallet` est planifiée mais n'est pas encore implémentée.
## Valider un alias
@@ -24,7 +24,7 @@ assert_eq!(alias.as_str(), "devnet-operator");
Un alias doit contenir entre 1 et 64 octets, commencer par un caractère alphanumérique ASCII et ne contenir ensuite que des caractères alphanumériques, `_` ou `-`.
## Générer un wallet en mémoire
## Générer un wallet temporaire en mémoire
```rust
let alias = match ks_wallet::WalletAlias::parse(
@@ -36,14 +36,15 @@ let alias = match ks_wallet::WalletAlias::parse(
},
};
let wallet =
ks_wallet::TemporaryWallet::generate(alias);
let wallet = ks_wallet::TemporaryWallet::generate(alias);
let summary = wallet.summary();
assert!(summary.storage_path.is_none());
println!("public key={}", summary.public_key);
```
Cette capacité est durable : `0.5.2` doit continuer à permettre des wallets temporaires/jetables pour tests, démonstrations et scénarios sans imposer une persistance ou un mot de passe.
## Signer un message
```rust
@@ -61,9 +62,11 @@ println!("signature={signature}");
`as_signer()` retourne une référence au trait Solana `Signer` sans exposer les octets du keypair.
Pour une API async qui conserve la référence au travers dun `await` et impose un futur `Send`, `as_sync_signer()` préserve explicitement le marqueur `Sync` du keypair concret. Cette vue ne change ni la clé utilisée ni les règles dautorisation de la couche dexécution.
Pour une API async qui conserve la référence au travers d'un `await` et impose un futur `Send`, `as_sync_signer()` préserve explicitement le marqueur `Sync` du keypair concret.
## Créer un stockage local
Cette frontière de signature doit rester disponible après restructuration : les consommateurs ne doivent pas connaître le format persistant.
## Stockage legacy actuel
```rust
let store = match ks_wallet::TemporaryWalletStore::new(
@@ -74,14 +77,17 @@ let store = match ks_wallet::TemporaryWalletStore::new(
return std::result::Result::Err(error);
},
};
println!(
"wallet directory={}",
store.directory().display()
);
```
## Créer un wallet persistant
Le store actuel persiste un keypair au format Solana JSON dans :
```text
<alias>.json
```
Ce format est **legacy** pour `0.5.2`.
### Créer un wallet legacy persistant
```rust
let alias = match ks_wallet::WalletAlias::parse(
@@ -104,9 +110,9 @@ let summary = wallet.summary();
assert!(summary.storage_path.is_some());
```
`create` refuse décraser un fichier existant.
`create` refuse d'écraser un fichier existant.
## Charger ou créer atomiquement
### Charger ou créer sans écrasement
```rust
let alias = match ks_wallet::WalletAlias::parse(
@@ -128,57 +134,67 @@ let wallet = match store.load_or_create(alias).await {
println!("wallet={}", wallet.public_key());
```
## Vérifier lexistence et le chemin
`load_or_create` utilise une création exclusive et reprend la lecture lorsqu'une création concurrente a déjà réservé le même alias.
```rust
let path = store.wallet_path(&alias);
let exists = match store.exists(&alias).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(error);
},
};
Le contenu legacy est toutefois écrit directement dans le chemin final. La publication n'est pas encore crash-safe/atomique par fichier temporaire + renommage.
println!("path={}, exists={exists}", path.display());
## Cible persistante `0.5.2`
Le nouveau stockage natif doit utiliser :
```text
<alias>.kswallet
```
## Politique non secrète
Le fichier `.kswallet` sera un conteneur binaire versionné protégé par le mot de passe propre au wallet.
```rust
let policy = ks_wallet::WalletPolicy {
signing_enabled: true,
lamport_spend_limit: std::option::Option::Some(
1_000_000,
),
};
L'API cible doit permettre conceptuellement :
assert!(policy.signing_enabled);
```text
create persistent(alias, password)
open/unlock(alias, password)
change password(alias, old password, new password)
scan/discover <alias>.kswallet
list identities
lookup by alias
sign without exposing private bytes
```
`WalletPolicy` transporte une intention de politique. Son application effective appartient à la couche dexécution.
Le store découvrira les wallets persistants en scannant son répertoire résolu (racine `KS_WALLETS_DIRECTORY`, `wallets` par défaut, puis éventuel sous-répertoire configuré) pour les `<alias>.kswallet` valides. Le scan ne doit pas faire confiance au seul nom du fichier.
## Erreurs et invariants
Le changement de mot de passe rechiffre la même keypair. Il n'existe pas de rotation normale du secret Ed25519 conservant la même pubkey : une nouvelle clé secrète signifie une nouvelle identité Solana.
- les octets secrets ne sont jamais exposés par lAPI publique ;
- les résumés ne contiennent que lalias, la clé publique et le chemin ;
- un fichier existant nest pas écrasé ;
Les noms Rust définitifs et le modèle runtime exact seront décidés dans les prereleases d'implémentation.
## Import/export cible
`ks-wallet` doit obligatoirement importer **et exporter** le format keypair JSON standard des binaires Solana, en plus de son import legacy qui correspond actuellement à ce même wire format. Il doit aussi pouvoir convertir vers/depuis les autres formats explicitement supportés.
Un export public peut exposer les données autorisées telles que l'alias et la pubkey.
**Tout export contenant ou permettant de reconstruire la clé privée doit obligatoirement demander et valider le mot de passe du wallet.**
L'export vers Solana CLI utilise son tableau JSON de 64 octets. Pour Phantom, Solflare, Backpack, Trust Wallet, Coinbase/Base et les autres wallets examinés, une matrice de compatibilité doit d'abord confirmer le contrat exact depuis des sources officielles. Un seul adaptateur wallet tiers sera implémenté dans `0.5.2` à titre d'exemple ; les autres formats techniquement faisables seront reportés au TODO. Aucun format universel externe n'est supposé, et une recovery phrase ne doit jamais être synthétisée en prétendant représenter une keypair arbitraire si la seed/mnemonic d'origine n'est pas disponible.
## Invariants
- les octets secrets ne sont pas exposés par l'API publique par commodité ;
- aucun mot de passe ni secret n'est projeté vers Tauri ;
- `ks-config` ne stocke pas les mots de passe ;
- les résumés publics ne doivent pas exposer inutilement les chemins locaux ;
- un fichier existant n'est pas écrasé silencieusement ;
- les liens symboliques et fichiers non réguliers sont refusés ;
- sur Unix, les permissions privées sont vérifiées ;
- les buffers secrets temporaires sont effacés ;
- les buffers secrets temporaires sont effacés lorsque possible ;
- cette crate ne décide pas si une transaction est autorisée.
## Tests de référence
## Tests de référence actuels
- validation des alias ;
- génération et signature sans persistance ;
- création, chargement et `load_or_create` ;
- refus décrasement ;
- création exclusive, chargement et `load_or_create` ;
- refus d'écrasement ;
- rejet des keypairs corrompus ;
- vérification des permissions Unix privées ;
- rejet des liens symboliques et permissions trop ouvertes.
- vérification des permissions Unix privées.
## Limites durables
- le format persistant actuel est le tableau JSON standard du keypair Solana ;
- la crate ne signe pas automatiquement une transaction ;
- elle ne transmet aucun secret à une interface frontend.
La matrice `0.5.2` ajoutera notamment : legacy externalisé, `.kswallet`, password/changement de password, multi-wallet, migration, import/export, atomicité et canaris de non-divulgation.