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

156 lines
5.5 KiB
Markdown

<!-- file: deltas/0.2.5/pre.006.md -->
<!-- version: 1 -->
# Delta `0.2.5-pre.006` — persistence native async/no-clobber
## Base
```text
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
```text
workspace.package.version = 0.2.5-pre.6
```
## Objet
Cette tranche matérialise la persistence native `.kspwallet` sans Config, environnement, Transport ou Tauri :
```text
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 :
```text
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
```text
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
```text
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
```text
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
```bash
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 :
```text
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
```