diff --git a/.gitignore b/.gitignore index 04bbd11..d6b997b 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ yarn.lock *.swp *.swo *~ +.pydevproject # Operating system files .DS_Store diff --git a/.pydevproject b/.pydevproject deleted file mode 100644 index 2b04565..0000000 --- a/.pydevproject +++ /dev/null @@ -1,5 +0,0 @@ - - - Default - python interpreter - diff --git a/Cargo.toml b/Cargo.toml index 932117b..8185cf7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ # file: Cargo.toml -# version: 163 +# version: 164 [workspace] resolver = "3" members = ["crates/ksp-app-config-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-logging-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-wallet-lib"] [workspace.package] -version = "0.2.5" +version = "0.2.6-pre.1" edition = "2024" license = "MIT" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" diff --git a/ROADMAP.md b/ROADMAP.md index 8b1e878..44e6c15 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,5 +1,5 @@ - + # Roadmap KSP @@ -50,7 +50,7 @@ Le roadmap décrit les objectifs à atteindre et les grandes étapes prévues. U - [X] `0.2.3` — HTTP Transactions stable : 11/11 wrappers typés publiés, classification `8 Read / 2 WriteSubmission / 1 Simulation`, no-resend ambigu prouvé pour les write submissions, `KSP-TRANSPORT-007` réaudité conforme sur les 37 wrappers HTTP courants, graphes Cargo et deux smokes Devnet validés ; `0.2.4` reprend les 15 Blocks/Economics restants. - [X] `0.2.4` — HTTP Blocks + Economics stable : 15/15 wrappers `V0_2_4` publiés, surface typed complète à 52/52 méthodes courantes, 14/14 historiques conservées, réaudit SIMD/inventaire final et `KSP-TRANSPORT-007` global validés ; deux smokes Devnet passés avant publication. - [X] `0.2.5` — Wallet foundation stable : `.kspwallet` V1, VIEW/OWNER indépendants, Argon2id/XChaCha20-Poly1305, autorité Ed25519 OWNER, persistence no-clobber, signature, administration/rotations/révocation VIEW forte, import/export Solana CLI JSON + Base58, canaris adversariaux, interop externe et documentation durable publiés. La clôture `pre.010-fix.001`–`fix.003` ajoute `ed25519-dalek 3.0.0` direct, normalise le Rust workspace et installe l’audit structurel Python complémentaire à rustfmt/Clippy. `Pubkey` reste via `ksp-core-lib`, la keypair reste encapsulée dans Wallet et Config/Transport/ExecutionPolicy/Store/Tauri restent hors Wallet. -- [ ] `0.2.6` — Introduire `ksp-app-wallet-desk` utilisant Config composite + Wallet + transport HTTP, notamment pour afficher l'identité et le solde d'un wallet ; le prompt de démarrage est préparé par `0.2.5-pre.010`. +- [ ] `0.2.6` — Introduire `ksp-app-wallet-desk` utilisant Config composite + Wallet + transport HTTP. Le gate `pre.001` retient `cfg.std.wallet` + composite Wallet Desk, inventory `.kspwallet` root-scoped/symlink-safe, handles VIEW/OWNER côté Rust, identité autorisée + `getBalance`, administration OWNER/import/export déjà possédés par Wallet, CSP/capabilities Tauri minimales et un forecast regranularisé jusqu’à `pre.013`. - [ ] `0.2.7` — Étendre `ksp-onchain-transport-lib` au WebSocket Solana standard complet ; permettre plusieurs sessions sur une même URL sans imposer encore un pool automatique complexe. - [ ] `0.2.8` — Ajouter Helius LaserStream WebSocket comme extension du moteur WebSocket standard, sans duplication de client. - [ ] `0.2.9` — Ajouter une première fondation Yellowstone gRPC standard/provider-neutral ; dimensionner la surface exacte à `pre.001` selon la documentation normative actuelle. diff --git a/deltas/0.2.6/pre.001.md b/deltas/0.2.6/pre.001.md new file mode 100644 index 0000000..1c9c465 --- /dev/null +++ b/deltas/0.2.6/pre.001.md @@ -0,0 +1,222 @@ + + + +# Delta `0.2.6-pre.001` — audit Wallet Desk, composition, UX, sécurité et sizing + +## Base requise + +Release stable attendue : + +```text +v0.2.5 +``` + +L'archive stable fournie confirme `workspace.package.version = 0.2.5` avant ouverture, six crates membres et l'absence de `ksp-app-wallet-desk`/`std.wallet`. + +## Type de livraison + +```text +ksp-general-0.2.6-pre.001.zip +``` + +L'archive d'échange est un delta applicable depuis la racine de `v0.2.5`. Elle contient uniquement les fichiers ajoutés/modifiés par cette tranche. + +## Objet + +Ouvrir `0.2.6 — Wallet Desk` sans commencer l'implémentation UI lourde. Le gate : + +- réaudite Config Desk comme template Tauri sans le copier aveuglément ; +- réaudite les APIs finales Config, Wallet, Transport et Logging ; +- confirme qu'un vrai `std.wallet` exige une extension de `ksp-config-lib` ; +- fixe `cfg.std.wallet`, `schema.std.wallet` et `cfg.composite.ksp-app-wallet-desk` ; +- fixe `wallets_directory` global avec fallback `${KSP_WALLETS_DIRECTORY:-wallets}` et profil Config minimal `default` pour la composition ; +- confirme que `getBalance` stable fournit lamports + contexte RPC sans nouveau wrapper ; +- définit runtime state, screen map, command map et DTO map ; +- définit inventory/path safety, symlink policy et comportement root absent ; +- définit le threat model desktop/password/export/state conflict ; +- retient import, metadata OWNER, rotations, disable/recreate VIEW et export fichier dans `0.2.6` ; +- exclut un écran de signature arbitraire et tout prix offchain ; +- réaudite les dépendances Tauri/frontend actuelles ; +- impose une CSP explicite à Wallet Desk au lieu de recopier `csp = null` de Config Desk ; +- regranularise le forecast initial jusqu'à `pre.013`. + +## Décisions principales + +### Config + +```text +cfg.std.wallet +schema.std.wallet +cfg.composite.ksp-app-wallet-desk +component_id = logging / transport / wallet +``` + +Shape prévu : + +```text +wallets_directory global ++ default_profile = default ++ profiles = [{ profile_id = default }] +``` + +Le profil minimal est requis par le moteur composite réel ; aucune donnée Wallet sensible n'entre dans Config. + +### Inventory + +```text +root = ResolvedWalletConfig::wallets_directory +non récursif +.kspwallet exact +regular file only +symlink excluded +root missing = état explicite, aucune création silencieuse +wallet_id = filename validé mono-composant +aucun alias dérivé du filename +``` + +### Lifecycle + +```text +NoSelection -> Locked -> ViewOpen/OwnerOpen +``` + +`WalletView`/`WalletOwner` restent en Rust. Lock/deselect/state conflict drop le handle et purgent les projections protégées frontend. + +### Balance + +```text +authorized Wallet handle +-> Pubkey Rust +-> HttpTransportPool::get_balance(role=default, config=None) +-> lamports + slot + api_version +-> safe DTO +``` + +### Sécurité Tauri + +- CSP locale restrictive obligatoire ; +- capabilities minimales ; +- aucun password dans storage/log/Debug ordinaire ; +- aucun export secret IPC/clipboard ; +- export fichier OWNER uniquement ; +- native Dialog `open/save` ajouté seulement lorsqu'il est consommé ; +- Bootstrap modals pour confirmations privilégiées ; +- aucun plugin filesystem nécessaire. + +## Audit externe au 2026-08-20 + +Constats courants : + +```text +@tauri-apps/api 2.11.1 +@tauri-apps/plugin-dialog 2.7.2 +@fltsci/tauri-plugin-tracing 0.3.4 +Bootstrap 5.3.8 +``` + +Les ranges existants de Config Desk restent cohérents, mais Wallet Desk démarre sans DataTables/SimpleBar/resize polyfill. Le plugin Dialog sera réaudité au moment exact de son ajout. + +## Prévision souple révisée + +```text +pre.001 audit + Config/Wallet/Transport/Tauri + UX + threat model + sizing +pre.002 crate Tauri + frontend shell + splash/main + logging bridge + CSP + ports +pre.003 cfg.std.wallet + schema + ResolvedWalletConfig + composite Wallet Desk +pre.004 runtime state + inventory/path safety + locked inspection + DTO foundation +pre.005 create .kspwallet + OWNER session + explicit root-directory flow +pre.006 unlock VIEW/OWNER + lock/deselect + authorized details + purge guarantees +pre.007 Transport pool from composite + getBalance + diagnostics/refresh +pre.008 native Dialog open + inspect/import CLI JSON/Base58 + destination no-clobber +pre.009 OWNER metadata administration alias/notes + state_conflict UX +pre.010 rotations OWNER/VIEW + disable/recreate VIEW + capability/security UX +pre.011 OWNER file export + save picker + privileged confirmation + leak audit +pre.012 deterministic integration tests + frontend security checks + Devnet smoke opt-in + compliance +pre.013 README/USAGE/docs/graphs + dependency audit + production Tauri build candidate + prompt 0.2.7 +rel.001 publication stable stricte +``` + +Le plan détaillé est `docs/plans/013-V0_2_6_WALLET_DESK_PLAN.md`. + +## Fichiers ajoutés + +```text +docs/plans/013-V0_2_6_WALLET_DESK_PLAN.md +deltas/0.2.6/pre.001.md +``` + +## Fichiers modifiés + +```text +Cargo.toml +ROADMAP.md +docs/000-README.md +docs/plans/000-README.md +docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md +``` + +## Fichiers volontairement inchangés + +```text +CHANGELOG.md +.env.example +config/** +crates/** +docs/architecture/** +docs/formats/** +docs/validation/** +``` + +`std.wallet`, le composite et la crate Tauri sont planifiés mais non créés dans le gate documentaire. + +## Version technique + +Conformément à `VERSION_WORKFLOW.md`, le non-fix prerelease ouvre : + +```text +workspace.package.version = 0.2.6-pre.1 +``` + +L'identifiant de commit reste : + +```text +v0.2.6-pre.001 +``` + +Aucun tag Git n'est créé avant la release stable finale. + +## Validations exécutées avant modification + +- archive stable `v0.2.5` fournie extraite et auditée ; +- documents internes obligatoires relus ; +- APIs Config/Wallet/Transport/Logging/Config Desk réauditées ; +- archive bot3 inspectée uniquement comme référence historique ; +- `python3 scripts/audit_rust_workspace_rules.py` exécuté sur la base stable : `General Rust rule audit: clean`, `KSP workspace Rust rule audit: clean` ; +- le même audit structurel réexécuté sur l’état candidat `pre.001` après matérialisation : `General Rust rule audit: clean`, `KSP workspace Rust rule audit: clean` ; +- audit externe Tauri/frontend actuel réalisé. + +## Validations tentées mais impossibles dans le sandbox + +Le binaire `cargo` n'est pas installé dans le sandbox. Les trois commandes suivantes ont été tentées et ont échoué avec code `127` : + +```bash +cargo fmt --all +cargo check --workspace +cargo clippy --workspace --all-targets +``` + +Aucune de ces commandes n'est déclarée réussie. + +## Validation opérateur requise avant commit + +Après application du delta : + +```bash +cargo fmt --all +python3 scripts/audit_rust_workspace_rules.py +cargo check --workspace +cargo clippy --workspace --all-targets +``` + +Comme `pre.001` ne crée aucune crate/frontend, aucun `npm` ni build Tauri n'est requis dans cette tranche. + +Le gate `pre.001` n'est fermé qu'après réception de ces preuves opérateur vertes. Aucun travail `pre.002` ne doit être engagé avant ce checkpoint. diff --git a/docs/000-README.md b/docs/000-README.md index 9ccabfc..3c8c213 100644 --- a/docs/000-README.md +++ b/docs/000-README.md @@ -1,5 +1,5 @@ - + # Documentation KSP @@ -74,7 +74,7 @@ D'autres sous-répertoires seront ajoutés uniquement lorsque leur rôle aura é ## Documents de planification -Le plan historique de la phase fondatrice clôturée est conservé dans [`plans/001-V0_0_3_PLAN.md`](plans/001-V0_0_3_PLAN.md). La séquence active des premières releases fonctionnelles est définie dans [`plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md`](plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md). Le plan détaillé de la release stable `0.1.1` est conservé comme historique clôturé dans [`plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md`](plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.2` est conservé comme historique clôturé dans [`plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md`](plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.3 — Configuration foundation` est conservé comme historique clôturé dans [`plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md`](plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.4 — ksp-app-config-desk` est conservé comme historique clôturé dans [`plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md`](plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md), avec sa matrice finale [`validation/001-V0_1_4_CONFIG_DESKTOP.md`](validation/001-V0_1_4_CONFIG_DESKTOP.md). Son prompt d'ouverture historique reste [`../prompts/004-V0_1_4_START_PROMPT.md`](../prompts/004-V0_1_4_START_PROMPT.md). La release stable `0.2.0` clôt l'audit de bot3 et le découpage de la série. Son plan directeur est conservé comme historique clôturé dans [`plans/007-V0_2_0_SERIES_PLANNING.md`](plans/007-V0_2_0_SERIES_PLANNING.md), avec sa matrice finale [`validation/002-V0_2_0_SERIES_PLANNING.md`](validation/002-V0_2_0_SERIES_PLANNING.md). La release stable `0.2.1 — HTTP Solana foundation` a été ouverte par [`../prompts/006-V0_2_1_START_PROMPT.md`](../prompts/006-V0_2_1_START_PROMPT.md). Son gate de sizing et sa matrice exhaustive sont conservés dans [`plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md`](plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md), avec la validation finale [`validation/003-V0_2_1_ONCHAIN_HTTP.md`](validation/003-V0_2_1_ONCHAIN_HTTP.md), README/USAGE Transport et le smoke Devnet opt-in de composition Config -> Transport. Le prompt [`../prompts/007-V0_2_2_START_PROMPT.md`](../prompts/007-V0_2_2_START_PROMPT.md) a ouvert la release stable `0.2.2 — HTTP Accounts + Tokens + Cluster`. Son plan clôturé [`plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md`](plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md) conserve l'audit et l'implémentation des 22 wrappers typés, tandis que [`validation/004-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER.md`](validation/004-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER.md) enregistre les validations déterministes, les graphes Cargo et les deux smokes Devnet passés avant publication. Le prompt [`../prompts/008-V0_2_3_START_PROMPT.md`](../prompts/008-V0_2_3_START_PROMPT.md) a ouvert la release stable `0.2.3 — HTTP Transactions`. Son plan clôturé [`plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md`](plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md) conserve l'audit et l'implémentation des 11 wrappers ; le réaudit [`validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md`](validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md) confirme la complétude des 37 wrappers HTTP typés et [`validation/006-V0_2_3_HTTP_TRANSACTIONS.md`](validation/006-V0_2_3_HTTP_TRANSACTIONS.md) enregistre les validations finales, graphes Cargo et deux smokes Devnet passés avant publication. Le prompt [`../prompts/009-V0_2_4_START_PROMPT.md`](../prompts/009-V0_2_4_START_PROMPT.md) a ouvert la release stable `0.2.4 — HTTP Blocks + Economics + compliance HTTP finale`. Son plan clôturé [`plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md`](plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md) conserve l’implémentation des 15 wrappers et la compliance `52/52 + 14/14`; la matrice finale [`validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md`](validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md) enregistre le réaudit SIMD/inventaire, les canaries globales et les preuves opérateur avant publication. Le prompt [`../prompts/010-V0_2_5_START_PROMPT.md`](../prompts/010-V0_2_5_START_PROMPT.md), finalisé par `0.2.4-pre.009-fix.001`, ouvre `0.2.5 — Wallet foundation` sur la base stable `v0.2.4`. Son plan historique clôturé [`plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md`](plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md) part du gate `pre.001` (héritage, threat model offline, VIEW/OWNER indépendants et niveau B read-only), puis matérialise la crate en `pre.002`, le wire/transcript en `pre.003`, les primitives Argon2id/XChaCha20-Poly1305 en `pre.004`, les payloads/create/open en `pre.005`, la persistence en `pre.006`, l'administration/signature en `pre.007` et les adapters transfer en `pre.008`. `pre.009` ferme l'audit adversarial/interoperability/compliance dans [`validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md`](validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md) avant la documentation finale `pre.010` ; `pre.010` finalise [`../crates/ksp-wallet-lib/README.md`](../crates/ksp-wallet-lib/README.md), [`../crates/ksp-wallet-lib/USAGE.md`](../crates/ksp-wallet-lib/USAGE.md), la spec, les graphes et la matrice ; `pre.010-fix.001`–`fix.003` ferment ensuite la mise à niveau Dalek et la normalisation Rust/audit structurel. `0.2.5-rel.001` publie la release stable et [`../prompts/011-V0_2_6_START_PROMPT.md`](../prompts/011-V0_2_6_START_PROMPT.md) ouvre `0.2.6 — Wallet Desk`. +Le plan historique de la phase fondatrice clôturée est conservé dans [`plans/001-V0_0_3_PLAN.md`](plans/001-V0_0_3_PLAN.md). La séquence active des premières releases fonctionnelles est définie dans [`plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md`](plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md). Le plan détaillé de la release stable `0.1.1` est conservé comme historique clôturé dans [`plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md`](plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.2` est conservé comme historique clôturé dans [`plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md`](plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.3 — Configuration foundation` est conservé comme historique clôturé dans [`plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md`](plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.4 — ksp-app-config-desk` est conservé comme historique clôturé dans [`plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md`](plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md), avec sa matrice finale [`validation/001-V0_1_4_CONFIG_DESKTOP.md`](validation/001-V0_1_4_CONFIG_DESKTOP.md). Son prompt d'ouverture historique reste [`../prompts/004-V0_1_4_START_PROMPT.md`](../prompts/004-V0_1_4_START_PROMPT.md). La release stable `0.2.0` clôt l'audit de bot3 et le découpage de la série. Son plan directeur est conservé comme historique clôturé dans [`plans/007-V0_2_0_SERIES_PLANNING.md`](plans/007-V0_2_0_SERIES_PLANNING.md), avec sa matrice finale [`validation/002-V0_2_0_SERIES_PLANNING.md`](validation/002-V0_2_0_SERIES_PLANNING.md). La release stable `0.2.1 — HTTP Solana foundation` a été ouverte par [`../prompts/006-V0_2_1_START_PROMPT.md`](../prompts/006-V0_2_1_START_PROMPT.md). Son gate de sizing et sa matrice exhaustive sont conservés dans [`plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md`](plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md), avec la validation finale [`validation/003-V0_2_1_ONCHAIN_HTTP.md`](validation/003-V0_2_1_ONCHAIN_HTTP.md), README/USAGE Transport et le smoke Devnet opt-in de composition Config -> Transport. Le prompt [`../prompts/007-V0_2_2_START_PROMPT.md`](../prompts/007-V0_2_2_START_PROMPT.md) a ouvert la release stable `0.2.2 — HTTP Accounts + Tokens + Cluster`. Son plan clôturé [`plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md`](plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md) conserve l'audit et l'implémentation des 22 wrappers typés, tandis que [`validation/004-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER.md`](validation/004-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER.md) enregistre les validations déterministes, les graphes Cargo et les deux smokes Devnet passés avant publication. Le prompt [`../prompts/008-V0_2_3_START_PROMPT.md`](../prompts/008-V0_2_3_START_PROMPT.md) a ouvert la release stable `0.2.3 — HTTP Transactions`. Son plan clôturé [`plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md`](plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md) conserve l'audit et l'implémentation des 11 wrappers ; le réaudit [`validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md`](validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md) confirme la complétude des 37 wrappers HTTP typés et [`validation/006-V0_2_3_HTTP_TRANSACTIONS.md`](validation/006-V0_2_3_HTTP_TRANSACTIONS.md) enregistre les validations finales, graphes Cargo et deux smokes Devnet passés avant publication. Le prompt [`../prompts/009-V0_2_4_START_PROMPT.md`](../prompts/009-V0_2_4_START_PROMPT.md) a ouvert la release stable `0.2.4 — HTTP Blocks + Economics + compliance HTTP finale`. Son plan clôturé [`plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md`](plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md) conserve l’implémentation des 15 wrappers et la compliance `52/52 + 14/14`; la matrice finale [`validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md`](validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md) enregistre le réaudit SIMD/inventaire, les canaries globales et les preuves opérateur avant publication. Le prompt [`../prompts/010-V0_2_5_START_PROMPT.md`](../prompts/010-V0_2_5_START_PROMPT.md), finalisé par `0.2.4-pre.009-fix.001`, ouvre `0.2.5 — Wallet foundation` sur la base stable `v0.2.4`. Son plan historique clôturé [`plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md`](plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md) part du gate `pre.001` (héritage, threat model offline, VIEW/OWNER indépendants et niveau B read-only), puis matérialise la crate en `pre.002`, le wire/transcript en `pre.003`, les primitives Argon2id/XChaCha20-Poly1305 en `pre.004`, les payloads/create/open en `pre.005`, la persistence en `pre.006`, l'administration/signature en `pre.007` et les adapters transfer en `pre.008`. `pre.009` ferme l'audit adversarial/interoperability/compliance dans [`validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md`](validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md) avant la documentation finale `pre.010` ; `pre.010` finalise [`../crates/ksp-wallet-lib/README.md`](../crates/ksp-wallet-lib/README.md), [`../crates/ksp-wallet-lib/USAGE.md`](../crates/ksp-wallet-lib/USAGE.md), la spec, les graphes et la matrice ; `pre.010-fix.001`–`fix.003` ferment ensuite la mise à niveau Dalek et la normalisation Rust/audit structurel. `0.2.5-rel.001` publie la release stable et [`../prompts/011-V0_2_6_START_PROMPT.md`](../prompts/011-V0_2_6_START_PROMPT.md) ouvre `0.2.6 — Wallet Desk`. Le gate `0.2.6-pre.001` est matérialisé dans [`plans/013-V0_2_6_WALLET_DESK_PLAN.md`](plans/013-V0_2_6_WALLET_DESK_PLAN.md) : il réaudite Config Desk et les APIs finales, fixe `std.wallet`/composite, inventory/path safety, lifecycle VIEW/OWNER, screen/command/DTO maps, threat model desktop, balance HTTP et regranularise la release jusqu’à `pre.013` avant implémentation Tauri lourde. ## Spécifications de formats diff --git a/docs/plans/000-README.md b/docs/plans/000-README.md index 58cc38d..22b1367 100644 --- a/docs/plans/000-README.md +++ b/docs/plans/000-README.md @@ -1,5 +1,5 @@ - + # Plans KSP @@ -21,6 +21,7 @@ Un plan décrit le périmètre, les décisions déjà acquises, les questions ou - [`010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md`](010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md) — plan historique clôturé de la release stable `0.2.3 — HTTP Transactions`, ouvert par `pre.001`, exécuté jusqu'à `pre.009` puis publié par `rel.001`; il couvre les 11 méthodes, la classification `8 Read / 2 WriteSubmission / 1 Simulation`, `KSP-TRANSPORT-007`, le no-resend et la préparation de `0.2.4`. - [`011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md`](011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md) — plan historique clôturé de la release stable `0.2.4`, ouvert par `pre.001`, exécuté jusqu’à `pre.009`, complété par le fix documentaire Wallet `pre.009-fix.001` puis publié par `rel.001`; il couvre les 10 Blocks + 5 Economics et la compliance finale `52/52 + 14/14` sous `KSP-TRANSPORT-007`. - [`012-V0_2_5_WALLET_FOUNDATION_PLAN.md`](012-V0_2_5_WALLET_FOUNDATION_PLAN.md) — plan historique clôturé de la release stable `0.2.5 — Wallet foundation`, ouvert par `pre.001`, livré jusqu’à `pre.010`, renforcé par `pre.010-fix.001`–`fix.003` pour Dalek 3 et la normalisation Rust/audit structurel, puis publié par `rel.001`; il couvre `.kspwallet` V1, VIEW/OWNER, crypto, persistence, administration, transfer et compliance. +- [`013-V0_2_6_WALLET_DESK_PLAN.md`](013-V0_2_6_WALLET_DESK_PLAN.md) — plan actif de `0.2.6 — Wallet Desk`, ouvert par `pre.001`; il fixe la composition Config/Wallet/Transport/Logging, `std.wallet`, inventory/path safety, lifecycle VIEW/OWNER, screen/command/DTO maps, threat model Tauri, balance HTTP, administration retenue et forecast regranularisé jusqu’à `pre.013`. Le `pre.001` de chaque release fonctionnelle peut introduire son propre plan détaillé lorsque la release s'ouvre. diff --git a/docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md b/docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md index 6b4fae7..42921ed 100644 --- a/docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md +++ b/docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md @@ -1,5 +1,5 @@ - + # Séquence des releases fonctionnelles KSP @@ -428,6 +428,8 @@ Le solde d'un wallet constitue un premier cas de validation réseau obligatoire. Le prompt [`../../prompts/011-V0_2_6_START_PROMPT.md`](../../prompts/011-V0_2_6_START_PROMPT.md), préparé par `0.2.5-pre.010`, impose un `pre.001` d'audit/sizing couvrant Config `std.wallet`/composite, inventory/path safety, lifecycle VIEW/OWNER, balance `getBalance`, bridge Tauri/TS-RS, sécurité password/export, logging et validation finale Tauri. +`0.2.6-pre.001` confirme que le registre Config doit être étendu pour `cfg.std.wallet`/`schema.std.wallet` et `cfg.composite.ksp-app-wallet-desk`; `wallets_directory` reste global avec fallback `${KSP_WALLETS_DIRECTORY:-wallets}` tandis qu'un profil `default` minimal préserve le contrat de résolution composite. Le gate retient une inventory non récursive `.kspwallet`, sans symlink, root-scoped, les handles VIEW/OWNER exclusivement côté Rust, une CSP Tauri explicite, `getBalance` via la Pubkey du handle autorisé et les flows OWNER metadata/rotations/revocation/export fichier déjà possédés par Wallet. Le scope tient dans `0.2.6` mais le forecast initial est regranularisé jusqu'à `pre.013`; le plan actif est `docs/plans/013-V0_2_6_WALLET_DESK_PLAN.md`. + ## `0.2.7` — WebSocket Solana standard Mission : couvrir la surface WebSocket standard officielle ciblée. diff --git a/docs/plans/013-V0_2_6_WALLET_DESK_PLAN.md b/docs/plans/013-V0_2_6_WALLET_DESK_PLAN.md new file mode 100644 index 0000000..17af7a5 --- /dev/null +++ b/docs/plans/013-V0_2_6_WALLET_DESK_PLAN.md @@ -0,0 +1,1137 @@ + + + +# Plan `0.2.6` — Wallet Desk + +## 1. Objet et statut du gate `pre.001` + +`0.2.6` crée `ksp-app-wallet-desk`, application Tauri spécialisée et mince chargée de valider la composition réelle : + +```text +ksp-config-lib ++ Config composite ++ ksp-wallet-lib ++ ksp-onchain-transport-lib HTTP ++ ksp-logging-lib +``` + +La base auditée est la release stable fournie `v0.2.5`, avec `workspace.package.version = 0.2.5` avant ouverture. Aucune crate `ksp-app-wallet-desk`, aucun `std.wallet` et aucun composite Wallet Desk n'existent encore dans cette base. + +`0.2.6-pre.001` est volontairement une tranche de **conception, inventaire, sécurité et sizing**. Elle n'ajoute ni crate Tauri, ni configuration runtime Wallet, ni dépendance frontend, ni command applicative. L'implémentation lourde commence seulement après validation opérateur du gate. + +Le sandbox d'audit ne fournit pas le binaire `cargo`. Le script structurel KSP a été exécuté et est propre, mais `cargo fmt --all`, `cargo check --workspace` et `cargo clippy --workspace --all-targets` ont échoué à l'invocation avec le code `127`. Le présent plan est donc une candidate `pre.001` matérialisée, **non commit-ready tant que l'opérateur n'a pas fourni les validations Cargo requises**. + +## 2. Sources relues et hiérarchie appliquée + +La conception suit l'ordre d'autorité demandé : + +1. archive KSP stable `v0.2.5` fournie ; +2. règles KSP versionnées ; +3. architecture, plans et validations actuels ; +4. contrats publics réellement exposés par les crates ; +5. sources officielles actuelles Tauri/frontend ; +6. archive bot3 fournie, uniquement comme référence historique. + +Les documents obligatoires du prompt d'ouverture ont été relus avant conception. Les surfaces ont ensuite été réauditées dans `ksp-core-lib`, `ksp-logging-lib`, `ksp-config-lib`, `ksp-onchain-transport-lib`, `ksp-wallet-lib` et `ksp-app-config-desk`. + +`docs/plans/007-V0_2_0_SERIES_PLANNING.md` conserve volontairement l'ancien forecast de `0.2.0` dans lequel Wallet Desk était numéroté `0.2.3`. Son en-tête le marque explicitement comme **plan historique clôturé**. La séquence active est celle de `ROADMAP.md` et `docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md`, où Wallet Desk est bien `0.2.6`. Ce décalage historique n'est donc pas utilisé comme autorité courante et ne justifie pas de réécrire l'historique `0.2.0`. + +## 3. Frontières non négociables + +Direction autorisée : + +```text +ksp-app-wallet-desk + -> ksp-config-lib + -> ksp-wallet-lib + -> ksp-onchain-transport-lib + -> ksp-core-lib si types/erreurs partagés nécessaires + -> ksp-logging-lib + -> Tauri / frontend +``` + +Interdictions : + +```text +ksp-wallet-lib -X-> Config / Transport / Tauri / Store / execution policy +ksp-app-wallet-desk -X-> crypto Wallet directe +ksp-app-wallet-desk -X-> solana-keypair / solana-signer / solana-signature directs +ksp-app-wallet-desk -X-> client RPC Solana alternatif +frontend -X-> keypair ou secret key material +frontend -X-> persistence password localStorage/sessionStorage +``` + +La seule exception Tauri au principe « pas de tracing direct hors `ksp-logging-lib` » reste l'adapter imposé par `tauri-plugin-tracing`; les événements applicatifs Rust et frontend sont réémis par la façade KSP. + +## 4. Audit de `ksp-app-config-desk` comme template Tauri + +### 4.1 Éléments à reprendre + +La structure existante est une bonne référence pour : + +```text +frontend/ +frontend/ts/ +frontend/sass/ +frontend/ts/bindings/ +Vite + TypeScript +Bootstrap + Font Awesome +splash + main +TS-RS aux frontières DTO applicatives +Tauri capabilities explicites +bridge frontend -> command Rust -> ksp-logging-lib +build frontend Tauri via beforeBuildCommand +npm run check = tsc --noEmit +``` + +Le port Config Desk est `1430`, avec WebSocket/HMR `1431`. Wallet Desk réservera **1432** pour Vite et **1433** pour HMR afin d'éviter toute collision locale avec la première app. + +### 4.2 Éléments à ne pas copier automatiquement + +Config Desk possède des dépendances DataTables, selection, SimpleBar et `resize-observer-polyfill` liées à ses écrans de management. Aucun besoin Wallet Desk ne justifie ces dépendances au gate `pre.001`. + +Le shell Wallet Desk démarre donc sans : + +```text +datatables.net-bs5 +datatables.net-select-bs5 +simplebar +resize-observer-polyfill +``` + +Elles ne seront ajoutées ultérieurement que si un besoin mesuré apparaît. + +Config Desk utilise actuellement `security.csp = null`. Ce point n'est **pas** repris. Wallet Desk porte des passwords et déclenche des opérations OWNER ; une CSP locale explicite et restrictive est donc un critère de `pre.002`. + +### 4.3 Logging à reprendre/refondre + +Le bridge éprouvé de Config Desk valide le pattern : + +```text +frontend helper +-> invoke emit_frontend_log +-> DTO validé côté Rust +-> ksp-logging-lib::{trace,debug,info,warn,error}! +``` + +Wallet Desk doit reprendre le mécanisme, mais le formatter frontend ne doit jamais sérialiser aveuglément des objets contenant password, secret, export ou URL credentialée. Les helpers Wallet doivent journaliser des **événements sémantiques sans payload sensible**, par exemple `wallet_unlock_started`, `wallet_unlock_succeeded`, `balance_refresh_failed`. + +## 5. Audit de la surface publique `ksp-wallet-lib` + +La release stable `0.2.5` fournit déjà les contrats nécessaires ; Wallet Desk ne doit pas les dupliquer. + +### 5.1 Locked et authorized projections + +`LockedWalletInfo` expose seulement : + +```text +format_version +view_enabled +``` + +Il n'expose ni Pubkey, ni alias, ni notes. Cette projection est la seule donnée Wallet autorisée avant unlock, hors filename/path décidé par la policy applicative. + +`WalletInfo` expose après autorisation : + +```text +format_version +capability +pubkey +alias +notes +``` + +### 5.2 Handles Rust + +`WalletView` possède la capability VIEW et expose lecture de Pubkey/alias/notes ainsi que rotation de son credential VIEW. + +`WalletOwner` possède OWNER et expose : + +```text +sign +update_alias +add_note +update_note +delete_note +rotate_owner_password +rotate_view_password +disable_view +recreate_view +export_transfer +export_transfer_file +``` + +Les handles ne sont ni sérialisés ni envoyés au frontend. Ils restent possédés par l'état Rust Tauri. + +### 5.3 Fichier et transfer + +Les APIs publiques stables couvrent déjà : + +```text +create_wallet_file_v1 +inspect_locked_wallet_file_v1 +open_wallet_view_file_v1 +open_wallet_owner_file_v1 +inspect_wallet_transfer_file +import_wallet_transfer_file_v1 +export_wallet_transfer_file +``` + +Les formats transfer stables engagés sont : + +```text +Solana CLI JSON +Solana keypair Base58 complet +``` + +L'import crée un nouveau `.kspwallet` no-clobber. L'export fichier OWNER est no-clobber et permet de garder les octets secrets côté Rust. Le texte secret ne doit donc pas être exposé au frontend par défaut. + +### 5.4 Conflit d'état + +Les mutations persistence peuvent retourner `wallet.state_conflict`. Wallet Desk le traite comme un état stale : + +1. message explicite de conflit ; +2. abandon du handle VIEW/OWNER courant ; +3. purge des projections protégées ; +4. refresh/inspection locked du fichier ; +5. nouvel unlock requis. + +Aucun retry aveugle ni remplacement forcé n'est autorisé. + +## 6. Audit Config : besoin exact de `std.wallet` + +### 6.1 Constat + +`ConfigFileRegistry::defaults()` ne connaît aujourd'hui que : + +```text +cfg.std.logging +schema.std.logging +cfg.std.transport +schema.std.transport +schema.composite +``` + +`ConfigFileDescriptor::new` et `build_registry` sont crate-private. Wallet Desk ne peut donc pas enregistrer proprement `std.wallet` et son composite depuis l'application. **La tranche Config doit modifier `ksp-config-lib`**, puis l'application consommera uniquement la façade publique. + +### 6.2 Identifiants retenus + +```text +cfg.std.wallet +schema.std.wallet +cfg.composite.ksp-app-wallet-desk +``` + +Fichiers physiques par défaut : + +```text +config/std.wallet.json +config/schemas/std.wallet.schema.json +config/examples/std.wallet.example.json +config/composite.ksp-app-wallet-desk.json +config/examples/composite.ksp-app-wallet-desk.example.json +``` + +Le composite utilise le schéma générique déjà existant `schema.composite`. + +### 6.3 Shape `std.wallet` + +Le moteur composite résout chaque `cfg.std.*` via `load_resolved_profile_with_source`; un document référencé doit donc fournir `default_profile` et `profiles` même lorsque sa seule valeur métier est globale. + +Shape V1 retenu pour `0.2.6` : + +```json +{ + "format_version": 1, + "wallets_directory": "${KSP_WALLETS_DIRECTORY:-wallets}", + "default_profile": "default", + "profiles": [ + { + "profile_id": "default" + } + ] +} +``` + +`wallets_directory` reste global parce qu'il ne varie pas par profil. Le profil vide ne porte aucune valeur métier artificielle ; il existe uniquement pour satisfaire le contrat homogène de composition/profil de Config. + +Aucun OWNER/VIEW password, keypair, alias, note ou secret Wallet n'entre dans Config. + +### 6.4 Adapter Config -> Wallet Desk + +`ksp-config-lib` doit ajouter un contrat analogue à `ResolvedLoggingConfig` / `ResolvedTransportConfig`, par exemple `ResolvedWalletConfig`, contenant au minimum : + +```text +file_id +source_path +profile_id +selection_source +effective safe/real Config view +wallets_directory: PathBuf +``` + +L'adapter : + +- résout `${KSP_WALLETS_DIRECTORY:-wallets}` via `ConfigEnvironment` ; +- rejette une valeur vide ; +- ancre un chemin relatif sur le current working directory comme le fait déjà l'adapter Logging ; +- accepte un root absent sans le créer implicitement ; +- rejette un chemin existant qui n'est pas un répertoire ; +- ne dépend pas de `ksp-wallet-lib` : il produit uniquement un chemin de composition. + +Le nom `ResolvedWalletConfig` est retenu car le document appartient à Config et décrit la racine Wallet de l'application, sans déplacer de logique Wallet dans Config. + +### 6.5 Composite Wallet Desk + +Shape de référence : + +```json +{ + "format_version": 1, + "default_profile": "devnet", + "profiles": [ + { + "profile_id": "devnet", + "documents": [ + { + "component_id": "logging", + "file_id": "cfg.std.logging" + }, + { + "component_id": "transport", + "file_id": "cfg.std.transport", + "profile_id": "devnet_public" + }, + { + "component_id": "wallet", + "file_id": "cfg.std.wallet" + } + ] + }, + { + "profile_id": "mainnet", + "documents": [ + { + "component_id": "logging", + "file_id": "cfg.std.logging" + }, + { + "component_id": "transport", + "file_id": "cfg.std.transport", + "profile_id": "mainnet_public" + }, + { + "component_id": "wallet", + "file_id": "cfg.std.wallet" + } + ] + } + ] +} +``` + +Les composants sont identifiés par `logging`, `transport`, `wallet`; les filenames ne traversent jamais le composite. Les overrides `--cfgpath`, `--schemapath` et `--filemap` restent ceux de Config. + +Le bootstrap Wallet Desk charge d'abord le composite, récupère les profils sélectionnés de ses trois composants, puis appelle les adapters spécialisés Config avec ces `profile_id`. Logging est initialisé une seule fois avec le profil choisi par le composite ; aucun profil Logging parallèle n'est inventé dans l'application. + +## 7. Audit Transport : balance minimale + +Aucun nouveau wrapper Transport n'est nécessaire. La surface stable expose : + +```text +HttpTransportPool::get_balance( + &HttpRoleName, + &ksp_core_lib::Pubkey, + Option<&GetBalanceConfig>, +) -> Result +``` + +`GetBalanceResult` expose : + +```text +value() -> u64 lamports +context().slot() -> u64 +context().api_version() -> Option<&str> +``` + +Le cas Wallet Desk utilise le rôle Transport `default` du profil composite et `config = None` pour le MVP, sauf besoin démontré ultérieurement. Le frontend ne fournit jamais la Pubkey à la command de refresh : Rust la prend depuis le handle VIEW/OWNER autorisé. + +Le DTO balance conserve les lamports en entier exact ; aucune conversion flottante n'est nécessaire à la frontière. L'UI peut afficher SOL comme format dérivé tout en conservant `lamports` comme autorité. + +## 8. Runtime Rust et machine d'état + +État conceptuel : + +```text +NoSelection +Locked +ViewOpen +OwnerOpen +PrivilegedOperation +``` + +Une représentation Rust possible est : + +```text +WalletSession + NoSelection + Locked { wallet_id, path, locked_info } + View { wallet_id, path, wallet: WalletView } + Owner { wallet_id, path, wallet: WalletOwner } +``` + +Le chemin complet reste côté Rust. Le frontend manipule un `wallet_id` applicatif dérivé du **nom de fichier validé**, jamais un chemin arbitraire pour les opérations root-scoped. + +L'état Tauri doit sérialiser les opérations sur le handle, typiquement par `tokio::sync::Mutex`. Une requête réseau extrait/copie seulement la Pubkey nécessaire puis libère le verrou session avant l'I/O HTTP afin de ne pas bloquer les commandes Wallet pendant l'attente RPC. + +`lock` / `close` : + +```text +drop WalletView/WalletOwner Rust +-> conserver seulement sélection + nouvelle inspection Locked +-> purger WalletAuthorizedDto et balance côté frontend +-> vider immédiatement les champs password DOM +``` + +Le changement de wallet sélectionné impose la même purge avant de charger la nouvelle projection locked. + +## 9. Stratégie inventory et chemins + +### 9.1 Racine + +La racine effective vient exclusivement de `ResolvedWalletConfig::wallets_directory()`. + +Si elle n'existe pas : + +- l'inventaire retourne un état `directory_missing` et zéro wallet ; +- aucune création silencieuse n'est effectuée au bootstrap ; +- une action explicite « Créer le répertoire Wallet » crée **exactement** la racine configurée, sans chemin fourni par le frontend. + +### 9.2 Enumeration + +L'inventaire est : + +```text +non récursif +extension exacte .kspwallet +fichiers réguliers seulement +symlinks exclus +répertoires exclus +refresh manuel +refresh automatique après opération locale réussie +pas de filesystem watcher en 0.2.6 +``` + +Chaque fichier candidat est inspecté avec `inspect_locked_wallet_file_v1`. Un fichier invalide peut apparaître comme entrée diagnostique sûre avec code d'erreur, mais jamais avec contenu brut. + +### 9.3 Résolution root-scoped + +Create/import/select utilisent un `wallet_id`/filename validé : + +```text +un seul composant de chemin +pas de / ou \\ +pas de . ni .. +extension .kspwallet requise +pas de chemin absolu +root.join(filename) +``` + +Pour une racine existante, la résolution vérifie aussi que la cible régulière canonique reste sous la racine canonique. La logique n'utilise jamais `metadata()` pour suivre implicitement un symlink d'inventaire. + +Le filename est une identité de stockage affichable. Il n'est jamais présenté comme alias et aucun alias n'est dérivé du filename. + +### 9.4 Import/export hors racine + +La **destination native `.kspwallet` d'un import** reste root-scoped. La source externe est choisie par un file picker natif. + +L'**export OWNER** est volontairement une destination externe choisie par l'utilisateur via un save picker natif. Il n'est donc pas root-scoped, mais reste : + +```text +OWNER only +confirmation Bootstrap avant ouverture du picker +format explicite +no-clobber dans ksp-wallet-lib +aucun contenu secret renvoyé au frontend +aucun log du chemin si sa divulgation n'est pas nécessaire +``` + +Aucun export clipboard/texte secret n'est prévu dans `0.2.6`. + +## 10. Screen map + +### 10.1 Shell principal + +Le shell est mono-fenêtre après splash : + +```text +Header + runtime/profile status + current wallet state + lock action when authorized + +Sidebar / navigation + Dashboard + Wallets + Create / Import + Details + Security (OWNER only) + Diagnostics +``` + +Les écrans sont des panels d'une même fenêtre, pas une multiplication de WebViews. + +### 10.2 Dashboard + +Affiche sans secret : + +```text +Config composite profile +Logging status +Transport profile / cluster +Wallet root status +selected filename si présent +Locked / VIEW / OWNER state +last balance status si autorisé +``` + +### 10.3 Wallets + +Inventaire root-scoped avec : + +```text +filename +format_version +VIEW enabled/disabled +inspection status +``` + +Aucune Pubkey/alias/note locked. + +### 10.4 Locked wallet + +Actions : + +```text +Unlock VIEW si view_enabled +Unlock OWNER +Deselect +``` + +Le password est contenu dans le modal/form actif seulement et purgé après invocation. + +### 10.5 Create / Import + +Create : filename, OWNER password, confirmation OWNER, VIEW optionnel, alias/notes initiales seulement si le contrat public les accepte sans duplication. + +Import : format/source inspectés côté Rust, destination `.kspwallet` root-scoped, nouveaux OWNER/VIEW passwords, metadata initiales explicitement choisies. + +### 10.6 Details + +Après VIEW ou OWNER : + +```text +capability +Pubkey +alias +notes +balance lamports +RPC slot / API version +transport profile +refresh balance +``` + +Les controls de mutation metadata n'apparaissent que sous OWNER. + +### 10.7 Security OWNER + +```text +rotate OWNER password +rotate VIEW password +disable VIEW +recreate VIEW +export OWNER file +``` + +Chaque action destructive/privileged passe par modal Bootstrap et affiche les effets attendus avant exécution. + +### 10.8 Diagnostics + +Surface bornée : profils Config sûrs, état pool/cluster non credentialé, dernier code d'erreur par domaine, outil de log contrôlé. Pas d'affichage de Config secret, URL réelle credentialée, password, keypair ou export. + +## 11. Command map + +Les noms restent applicatifs et expriment une action, pas l'implémentation interne : + +| Command | Capability | Entrée | Sortie sûre | Délégation principale | +|---|---|---|---|---| +| `get_runtime_status` | aucune | — | `WalletRuntimeStatusDto` | Config/app state | +| `list_wallets` | aucune | — | `Vec` | app filesystem + Wallet inspect | +| `create_wallets_directory` | aucune | modal UI | `WalletOperationResultDto` | app root config | +| `select_wallet` | aucune | `WalletSelectionRequestDto` | `LockedWalletDto` | app resolver + Wallet inspect | +| `deselect_wallet` | aucune | — | `WalletSessionDto` | app state | +| `create_wallet` | aucune | `WalletCreateRequestDto` | `WalletAuthorizedDto` OWNER | Wallet create file | +| `inspect_import_source` | aucune | native picker path | `WalletTransferInspectionDto` | Wallet transfer inspect | +| `import_wallet` | aucune | `WalletImportRequestDto` | `WalletAuthorizedDto` OWNER | Wallet import file | +| `unlock_wallet_view` | Locked | `WalletUnlockPasswordDto` | `WalletAuthorizedDto` VIEW | Wallet open VIEW | +| `unlock_wallet_owner` | Locked | `WalletUnlockPasswordDto` | `WalletAuthorizedDto` OWNER | Wallet open OWNER | +| `lock_wallet` | VIEW/OWNER | — | `LockedWalletDto` | drop handle + inspect | +| `refresh_wallet_balance` | VIEW/OWNER | — | `WalletBalanceDto` | Transport getBalance | +| `update_wallet_alias` | OWNER | `WalletAliasMutationDto` | `WalletAuthorizedDto` | Wallet OWNER | +| `add_wallet_note` | OWNER | `WalletNoteCreateDto` | `WalletAuthorizedDto` | Wallet OWNER | +| `update_wallet_note` | OWNER | `WalletNoteUpdateDto` | `WalletAuthorizedDto` | Wallet OWNER | +| `delete_wallet_note` | OWNER | note id | `WalletAuthorizedDto` | Wallet OWNER | +| `rotate_owner_password` | OWNER | `WalletPasswordRotationDto` | operation result | Wallet OWNER | +| `rotate_view_password` | OWNER | `WalletPasswordRotationDto` | operation result | Wallet OWNER | +| `disable_view` | OWNER | confirmation token logique UI | `WalletAuthorizedDto` | Wallet OWNER | +| `recreate_view` | OWNER | new VIEW password | `WalletAuthorizedDto` | Wallet OWNER | +| `export_wallet_owner` | OWNER | format + native save path | operation result | Wallet export file | +| `emit_frontend_log` | aucune | redacted log payload | `()` | Logging facade | + +Le « confirmation token logique UI » ne constitue pas une sécurité cryptographique : l'autorisation réelle reste OWNER côté Rust. Il sert seulement à empêcher une exécution accidentelle dans l'UX. Les commands ne font jamais confiance au frontend pour déclarer sa capability. + +Aucune command `sign` générique n'est exposée en `0.2.6` : Wallet Desk n'est ni un transaction builder ni une execution policy. Le contrat de signature Wallet reste validé par la crate elle-même. + +## 12. DTO map et règles de secret + +### 12.1 DTOs principaux + +```text +WalletRuntimeStatusDto +WalletInventoryEntryDto +WalletSessionDto +LockedWalletDto +WalletAuthorizedDto +WalletBalanceDto +WalletCreateRequestDto +WalletSelectionRequestDto +WalletUnlockPasswordDto +WalletImportRequestDto +WalletTransferInspectionDto +WalletAliasMutationDto +WalletNoteCreateDto +WalletNoteUpdateDto +WalletPasswordRotationDto +WalletSecurityStatusDto +WalletOperationResultDto +CommandErrorDto +FrontendLogPayloadDto +``` + +### 12.2 Locked DTO + +`LockedWalletDto` contient au maximum : + +```text +wallet_id / filename +format_version +view_enabled +``` + +Aucune identité Solana ou metadata. + +### 12.3 Authorized DTO + +`WalletAuthorizedDto` contient : + +```text +wallet_id / filename +format_version +capability +pubkey +alias +notes +security status sûr +``` + +Il n'inclut jamais les handles, key slots, ciphertexts, salts, password ou secret key material. + +### 12.4 DTOs contenant password en entrée + +Les request DTOs password : + +- sont `Deserialize` + TS-RS uniquement selon besoin ; +- n'utilisent jamais un `Debug` dérivé révélant les valeurs ; +- ne sont pas `Clone` sans nécessité démontrée ; +- sont immédiatement convertis en `OwnerPassword` / `ViewPassword` ; +- ne sont jamais inclus dans `CommandErrorDto` ni les logs. + +Le frontend remet la valeur du champ à `""` dans un `finally` après `invoke`, succès ou erreur. + +## 13. Threat model desktop + +| Menace | Mesure `0.2.6` | +|---|---| +| XSS / script injecté dans WebView | CSP restrictive, assets locaux, capabilities minimales, aucune CDN | +| Password conservé frontend | aucun storage, champ vidé après invoke, pas de state global contenant le password | +| Password dans logs | logging sémantique sans payload de request, DTO Debug redacted/absent | +| Secret Wallet renvoyé via IPC | aucun getter/export texte ; export fichier entièrement Rust | +| Identity leak locked | DTO construit exclusivement depuis `LockedWalletInfo` + filename policy | +| Path traversal root-scoped | filename mono-composant validé, extension stricte, résolution Rust sous root | +| Symlink escape | symlinks exclus par `symlink_metadata`, contrôle canonical lorsque possible | +| TOCTOU/state stale | Wallet no-clobber/state conflict + drop handle sur conflit | +| RPC credential leak | Config/Transport safe diagnostics, aucune URL brute dans DTO/error UI | +| Privileged click accidentel | Bootstrap modal explicite, OWNER revalidé côté Rust | +| Frontend forge capability | capability lue depuis handle Rust, jamais depuis une valeur envoyée par TS | +| Export accidentel | OWNER + modal + save picker + format explicite + no-clobber | +| Clipboard/history fuite secret | aucun export secret clipboard/texte en `0.2.6` | +| Filesystem watcher race | aucun watcher automatique ; refresh explicite et après opérations locales | + +La compromission complète du processus desktop ou de l'OS reste hors du modèle de sécurité de l'application ; Wallet Desk ne promet pas de protéger un secret déjà déchiffré contre un attaquant contrôlant la mémoire du processus. + +## 14. Tauri capabilities et file picker + +### 14.1 Baseline `pre.002` + +Capabilities initiales minimales : + +```text +core:default +tracing:default +``` + +Le shell n'ajoute ni filesystem plugin ni dialog plugin tant qu'aucun picker n'est consommé. + +### 14.2 Import/export + +Lorsque l'import/export est ajouté, utiliser le plugin officiel Tauri Dialog. Les permissions doivent être granulaires : + +```text +dialog:allow-open +dialog:allow-save +``` + +Ne pas utiliser `dialog:default`, car celui-ci accorde aussi les message dialogs inutiles. Les confirmations applicatives restent des modals Bootstrap. + +Aucun `@tauri-apps/plugin-fs` n'est nécessaire : l'inventory et toutes les opérations Wallet restent côté Rust. + +## 15. Dépendances frontend/Tauri réauditées le 2026-08-20 + +Sources primaires/éditeur auditées : documentation Tauri v2, npm Tauri, npm `@fltsci`, Bootstrap officiel. + +Constats : + +```text +@tauri-apps/api latest 2.11.1 +@tauri-apps/plugin-dialog latest 2.7.2 +@fltsci/tauri-plugin-tracing latest 0.3.4 +Bootstrap stable 5.3.8 +``` + +Les ranges workspace/template existants `^2.11`, `^0.3`, `^5.3` restent donc cohérents avec les publications actuelles auditées. + +Dépendances runtime initiales envisagées pour Wallet Desk : + +```text +@fltsci/tauri-plugin-tracing ^0.3 +@fortawesome/fontawesome-free ^7.3 +@tauri-apps/api ^2.11 +bootstrap ^5.3 +``` + +Le plugin Dialog est ajouté seulement dans la tranche qui consomme réellement import/export, après réaudit exact Rust+npm de ce moment. + +Dev dependencies : reprendre les générations actuelles de Config Desk seulement si nécessaires : + +```text +@tauri-apps/cli ^2.11 +@types/bootstrap ^5.2 +@types/node ^26.1 +sass-embedded ^1.102 +typescript ^7.0 +vite ^8.2 +``` + +Aucun DataTables/SimpleBar/resize polyfill dans la baseline. + +Sources : + +```text +https://v2.tauri.app/security/ +https://v2.tauri.app/security/capabilities/ +https://v2.tauri.app/security/csp/ +https://v2.tauri.app/plugin/dialog/ +https://www.npmjs.com/package/@tauri-apps/api +https://www.npmjs.com/package/@tauri-apps/plugin-dialog +https://www.npmjs.com/org/fltsci +https://blog.getbootstrap.com/2025/08/25/bootstrap-5-3-8/ +``` + +## 16. CSP retenue pour le shell + +`pre.002` doit livrer une CSP explicite adaptée aux assets locaux et à l'IPC Tauri. Le texte exact sera validé contre le bundle réel, mais les invariants sont : + +```text +default-src self/local protocols only +script-src self + mécanismes Tauri générés +style-src self (+ unsafe-inline seulement si Bootstrap/Vite l'impose réellement) +font-src self +img-src self/data uniquement si nécessaire +connect-src IPC Tauri + dev server uniquement en dev +aucune CDN / aucun remote script +``` + +La CSP de production ne doit pas autoriser directement les endpoints RPC Solana : le WebView n'effectue jamais la requête réseau ; Transport la fait côté Rust. + +## 17. Tests déterministes + +### 17.1 Config + +Couvrir : + +```text +registre cfg.std.wallet/schema/composite +schema std.wallet +KSP_WALLETS_DIRECTORY process/.env/fallback +wallets_directory global hors profils +relative path anchoring +existing non-directory rejected +composite devnet/mainnet -> profiles logging/wallet/transport exacts +filemap overrides conservés +``` + +### 17.2 Inventory/path + +Couvrir : + +```text +root missing +regular .kspwallet accepted +wrong extension ignored +subdirectory ignored +symlink ignored +../ traversal rejected +absolute filename rejected +separator rejected +no-clobber create/import +filename != alias +invalid wallet safe diagnostic +``` + +### 17.3 Session/DTO/security + +Couvrir : + +```text +Locked DTO sans pubkey/alias/notes +VIEW projection +OWNER projection +lock drops capability projection +selection change drops capability projection +password request Debug non révélant +serialized response DTOs sans secret fields +state_conflict -> forced lock/refresh +VIEW cannot invoke OWNER mutation successfully +``` + +### 17.4 Balance + +Serveur HTTP local/fixture : + +```text +VIEW -> pubkey from Rust handle -> getBalance +OWNER -> same +0 lamport accepted +lamports exact +slot/api_version mapped +Transport error categorized safely +RPC credential absent from UI error/Debug +``` + +### 17.5 Commands + +Les tests doivent prouver que les commands délèguent : + +- ouverture/create/import/export/admin à `ksp-wallet-lib` ; +- balance à `HttpTransportPool::get_balance` ; +- Config/env aux adapters `ksp-config-lib` ; +- logging à `ksp-logging-lib`. + +Aucune duplication crypto/JSON-RPC/Config parsing n'est tolérée. + +## 18. Tests frontend + +Baseline obligatoire : + +```bash +npm run check --prefix crates/ksp-app-wallet-desk +``` + +Ce script reste type-check/lint/tests et ne construit pas le bundle de production. + +Tests ciblés à valeur élevée à considérer : + +```text +password input cleared in finally +locked -> authorized -> locked DOM purge +OWNER controls hidden/disabled under VIEW +privileged modal required before destructive action +balance refresh state transitions +``` + +Ils ne justifient pas à eux seuls l'introduction d'un framework frontend lourd si des tests simples suffisent. + +## 19. Smoke Devnet opt-in + +Wallet Desk est la première surface appropriée pour un smoke durable de composition : + +```text +Config composite Devnet +-> wallet test-only/éphémère +-> open VIEW ou OWNER +-> Pubkey +-> HttpTransportPool getBalance role default +-> réponse RPC valide, y compris 0 lamport +``` + +Le smoke : + +- est opt-in ; +- utilise un wallet créé dans un répertoire temporaire ; +- ne nécessite aucun secret de production ; +- ne nécessite aucun wallet financé ; +- ne persiste pas de password dans Config/.env ; +- distingue skip/absence de réseau d'un résultat exécuté avec succès. + +Ce smoke remplace conceptuellement la destination transitoire Config des anciens smokes cross-crates ; il ne déplace rien dans `ksp-config-lib`. + +## 20. Logging et redaction + +Chaque interaction importante produit un événement debug/trace sans contenu secret : + +```text +navigation +inventory refresh +wallet select/deselect +create/import result +unlock VIEW/OWNER result +lock +balance refresh result +metadata mutation result +rotation/disable/recreate result +modal open/confirm/cancel +export start/result +state conflict +DOM/state replacement significatif +``` + +Interdictions absolues dans message/champs : + +```text +password +secret bytes / keypair +transfer payload secret +owner/view key material +RPC URL credentialée +Config KSP_SECRET value +notes/alias en contenu brut sauf besoin diagnostic explicitement autorisé +``` + +Les fichiers de logs gardent la politique KSP unique par lancement. + +## 21. Import/export UX retenue + +### Import + +Flow : + +```text +Open native picker +-> Wallet inspect transfer (Pubkey + format only) +-> choose destination filename under configured root +-> enter new OWNER password + optional VIEW password +-> optional alias/notes +-> import_wallet_transfer_file_v1 +-> authorized OWNER projection +``` + +La source externe n'est jamais transformée côté TypeScript. + +### Export + +Flow : + +```text +OWNER open +-> choose format +-> Bootstrap privileged confirmation +-> native Save picker +-> export_wallet_transfer_file +-> success status only +``` + +Le frontend ne reçoit jamais les octets exportés. + +## 22. Administration OWNER retenue pour `0.2.6` + +Le sizing est positif pour inclure dans la release : + +```text +alias mutation +notes CRUD +rotate OWNER password +rotate VIEW password +disable VIEW strong +recreate VIEW strong +OWNER file export CLI JSON/Base58 +``` + +L'import CLI JSON/Base58 est également retenu parce que la surface Wallet est déjà stable et qu'il valide un workflow réel de migration vers `.kspwallet`. + +La signature arbitraire n'obtient pas d'écran dédié en `0.2.6` : elle appartient au contrat Wallet mais ne sert pas la mission Wallet Desk identité/administration/balance et pourrait être confondue avec une future execution policy. + +## 23. Sizing détaillé + +Le forecast initial `pre.002`–`pre.010` est trop dense si chaque tranche doit rester petite. Les points qui justifient une regranularisation sont : + +- Config nécessite une modification réelle de `ksp-config-lib`, schema, adapter et composite ; +- inventory/path safety mérite une tranche autonome avant les secrets ; +- create et unlock/session sont séparés ; +- import ajoute une nouvelle surface native Dialog ; +- metadata et credential security doivent être testées séparément ; +- export secret mérite sa propre revue ; +- integration/security/smoke doit rester distinct de la documentation/build final. + +Prévision souple recalibrée : + +```text +pre.001 audit + Config/Wallet/Transport/Tauri + UX + threat model + sizing +pre.002 crate Tauri + frontend shell + splash/main + logging bridge + CSP + ports +pre.003 cfg.std.wallet + schema + ResolvedWalletConfig + composite Wallet Desk +pre.004 runtime state + inventory/path safety + locked inspection + DTO foundation +pre.005 create .kspwallet + OWNER session + explicit root-directory flow +pre.006 unlock VIEW/OWNER + lock/deselect + authorized details + purge guarantees +pre.007 Transport pool from composite + getBalance + diagnostics/refresh +pre.008 native Dialog open + inspect/import CLI JSON/Base58 + destination no-clobber +pre.009 OWNER metadata administration alias/notes + state_conflict UX +pre.010 rotations OWNER/VIEW + disable/recreate VIEW + capability/security UX +pre.011 OWNER file export + save picker + privileged confirmation + leak audit +pre.012 deterministic integration tests + frontend security checks + Devnet smoke opt-in + compliance +pre.013 README/USAGE/docs/graphs + final dependency audit + production Tauri build candidate + prompt 0.2.7 +rel.001 publication stable stricte +``` + +Ce forecast reste souple. Un `fix` ou une prerelease supplémentaire est préférable à regrouper artificiellement des surfaces sensibles. + +## 24. Gates par tranche + +### `pre.002` + +Pas de Wallet métier. Gate : app démarre, splash/main/logging/CSP/capabilities/build layout corrects. + +### `pre.003` + +Pas d'inventory Wallet avant que Config soit capable de produire le root + composite de manière normative. + +### `pre.004` + +Pas de password avant que la résolution des chemins et la projection locked soient testées. + +### `pre.005` / `pre.006` + +Pas de balance avant que le lifecycle Rust VIEW/OWNER + purge soit fiable. + +### `pre.007` + +MVP fonctionnel minimal atteint quand un wallet VIEW/OWNER ouvert affiche identité autorisée + balance HTTP. + +### `pre.008+` + +Administration enrichie sans réduire les garanties du MVP. + +### `pre.012` + +Aucune clôture sans audit secret/DTO/paths/capabilities/CSP/state conflict et workspace tests. + +### `pre.013` + +`cargo tauri build` est la dernière opération de validation de la candidate, conformément aux règles KSP. + +## 25. Validation opérateur prévue + +Après chaque tranche Rust : + +```bash +cargo fmt --all +python3 scripts/audit_rust_workspace_rules.py +cargo check --workspace +cargo clippy --workspace --all-targets +``` + +Tests ciblés pendant le développement ; checkpoints globaux : + +```bash +cargo test --workspace +``` + +Candidate finale Wallet Desk : + +```bash +cargo fmt --all +python3 scripts/audit_rust_workspace_rules.py +cargo check --workspace +cargo clippy --workspace --all-targets +cargo test -p ksp-app-wallet-desk +cargo test --workspace +npm run check --prefix crates/ksp-app-wallet-desk +cargo tauri build -c crates/ksp-app-wallet-desk/tauri.conf.json +``` + +Le smoke Devnet opt-in est exécuté séparément avec sa commande documentée. + +## 26. Hors périmètre confirmé + +```text +modification .kspwallet V1 sans défaut démontré +WalletPolicy / execution policy +transaction build/simulate/send +WebSocket / gRPC +Store +hardware wallet / Ledger +remote signer +mobile / browser extension +cloud custody +trading +clipboard/text secret export +filesystem watcher +RPC direct depuis frontend +prix offchain pendant 0.2.6 +``` + +## 27. TODO `0.2.11` — intégration prix offchain + +La visualisation de prix reste explicitement hors `0.2.6`. + +`0.2.10` doit d'abord produire le transport/service offchain spécialisé puis `0.2.11` une application de visualisation/validation. Une fois ces contrats stabilisés, `0.2.11` intégrera cette capacité dans Wallet Desk sans dupliquer récupération, normalisation, cache ou policy de refresh. + +Wallet Desk `0.2.6` ne prépare aucune API fictive de prix et n'ajoute aucune dépendance offchain anticipée. + +## 28. Critères de sortie `0.2.6` + +La release stable n'est clôturable que si : + +- Config composite sélectionne Logging/Wallet/Transport par `file_id` ; +- `KSP_WALLETS_DIRECTORY` est résolu uniquement par Config ; +- inventory/path safety est root-scoped et symlink-safe selon la policy ci-dessus ; +- Locked ne révèle ni Pubkey, ni alias, ni notes ; +- VIEW/OWNER sont détenus uniquement côté Rust ; +- lock/deselect/state conflict purgent les projections protégées ; +- create/select/open VIEW/OWNER fonctionnent sur `.kspwallet` réel ; +- Pubkey/alias/notes apparaissent seulement après autorisation ; +- `getBalance` fonctionne avec VIEW et OWNER via le Transport du composite ; +- metadata/rotations/disable/recreate/import/export retenus délèguent à Wallet ; +- aucun password/secret key/export payload n'entre dans Config, logs ou storage frontend ; +- CSP et capabilities Tauri sont minimales et auditées ; +- validations Rust/frontend/Tauri sont vertes avec preuves opérateur ; +- smoke Devnet opt-in est disponible et documenté ; +- README/USAGE, roadmap, plan et prompt `0.2.7` sont synchronisés. + +## 29. Suite immédiate après validation de `pre.001` + +Après application de ce delta, l'opérateur doit exécuter la validation d'ouverture sur sa machine Cargo. Si elle est verte, `pre.001` peut être commitée sous : + +```text +v0.2.6-pre.001 +``` + +`pre.002` commence alors par la crate/shell Tauri, le bridge Logging, les ports 1432/1433 et la CSP — **sans encore implémenter Wallet/Config métier**.