Files
khadhroony-solana-project/deltas/0.2.5/pre.006.md
2026-08-19 17:31:29 +02:00

5.5 KiB

Delta 0.2.5-pre.006 — persistence native async/no-clobber

Base

0.2.5-pre.5.fix.1

Le checkpoint opérateur de cette base a validé cargo fmt --all, cargo check --workspace, cargo clippy --workspace --all-targets, cargo test -p ksp-wallet-lib, cargo test --workspace et l'audit Cargo tree. Une seule génération ed25519-dalek 2.2.0 est utilisée et solana-address 2.7.0 est unifié entre Core et solana-keypair.

Version technique

workspace.package.version = 0.2.5-pre.6

Objet

Cette tranche matérialise la persistence native .kspwallet sans Config, environnement, Transport ou Tauri :

create_wallet_file_v1(path, ...)
open_wallet_view_file_v1(path, ...)
open_wallet_owner_file_v1(path, ...)
inspect_locked_wallet_file_v1(path)

Le chemin est toujours fourni explicitement par le caller. Wallet ne possède et ne découvre aucun répertoire par défaut.

Persistence retenue

tempfile ^3.27 est ajouté sous [workspace.dependencies] puis consommé par ksp-wallet-lib avec tempfile.workspace = true.

La création native suit :

create crypto in-memory
-> serialize locked JSON
-> NamedTempFile dans le même répertoire que la destination
-> write_all
-> sync_all(temp)
-> persist_noclobber(destination)
-> sync_all(fichier publié)
-> parent-directory sync best-effort sur Unix

create ne propose aucun overwrite. Une destination existante retourne wallet.destination_exists même sous concurrence.

La documentation upstream de tempfile 3.27.0 précise que persist_noclobber ne peut pas être présenté comme atomique sur absolument toutes les plateformes/filesystems et peut laisser un hard-link temporaire dans certains scénarios de crash. KSP conserve donc une documentation explicite de cette limite : no-clobber est le contrat, tandis que la durabilité power-loss universelle n'est pas revendiquée.

Async / lecture bornée

Les opérations filesystem bloquantes sont regroupées dans tokio::task::spawn_blocking; aucune feature Tokio filesystem supplémentaire n'est requise.

La lecture :

  • ouvre le fichier dans la frontière blocking ;
  • vérifie d'abord la taille metadata ;
  • utilise ensuite une lecture bornée à KSPWALLET_MAX_FILE_BYTES + 1 afin de couvrir aussi un fichier qui grossirait pendant la lecture ;
  • rejette un document surdimensionné avant parsing/KDF.

Les wrappers fichier délèguent ensuite aux flows pre.005 déjà validés et n'introduisent aucune seconde implémentation crypto.

Fault / concurrence

Nouveaux canaries déterministes :

  • première publication no-clobber conservée face à une seconde tentative ;
  • fault injecté après sync_all(temp) mais avant publication : aucune destination partielle ;
  • cleanup du temp lors d'un retour d'erreur ordinaire ;
  • huit créateurs concurrents : exactement un succès et sept destination_exists ;
  • rejet pré-parser d'un fichier supérieur à 1 MiB ;
  • création publique vers fichier puis projection locked ;
  • le vecteur complet pre.005 peut être publié puis ouvert par les nouvelles API VIEW et OWNER depuis fichier.

Un kill/power-loss brutal peut laisser un artifact temporaire selon l'OS/filesystem ; la tranche ne prétend pas simuler ni garantir le cleanup après arrêt non déroulé.

Frontières conservées

Wallet -> ksp-core-lib
Wallet -> ksp-logging-lib
Wallet -> primitives crypto/Solana retenues
Wallet -> tempfile

Wallet -X-> Config
Wallet -X-> Transport
Wallet -X-> ExecutionPolicy
Wallet -X-> Store
Wallet -X-> Tauri
Wallet -X-> tracing direct
Wallet -X-> solana-pubkey direct

Pubkey reste consommée exclusivement via ksp_core_lib::Pubkey. solana-keypair reste propriété de Wallet parce qu'il encapsule du matériau secret et une capacité de signature ; aucune keypair brute n'est remontée dans Core.

Replace administratif

pre.006 n'expose volontairement pas une primitive publique générale d'overwrite/replace. Le remplacement atomique d'un wallet existant sera introduit en pre.007 à travers les seules opérations autorisées : administration OWNER et self-rotation du password VIEW. Cela évite de donner à un consumer de niveau inférieur une primitive arbitraire replace(path, bytes).

Fichiers ajoutés

crates/ksp-wallet-lib/src/persistence.rs
crates/ksp-wallet-lib/unit_tests/persistence.rs
deltas/0.2.5/pre.006.md

Fichiers modifiés

Cargo.toml
ROADMAP.md
crates/ksp-wallet-lib/Cargo.toml
crates/ksp-wallet-lib/src/lib.rs
crates/ksp-wallet-lib/tests/dependency_boundary.rs
crates/ksp-wallet-lib/tests/public_api.rs
docs/formats/KSPWALLET_V1.md
docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md
docs/plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md

Validation opérateur requise

cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-wallet-lib
cargo test --workspace

cargo tree -p ksp-wallet-lib
cargo tree -p ksp-wallet-lib -d
cargo tree -i tempfile@3.27.0

Points à contrôler dans le tree : pas de nouvelle dépendance Config/Transport/Tauri, tempfile uniquement par Wallet dans cette tranche et aucune duplication crypto nouvelle injustifiée.

Suite

Après validation, 0.2.5-pre.007 porte :

signature Solana publique sans getter secret
alias/notes OWNER
rotation password VIEW par VIEW
rotation password VIEW par OWNER sans ancien password VIEW
rotation password OWNER
suppression/recréation VIEW
révocation forte VIEW avec rekey metadata
replace atomique lié aux mutations autorisées