diff --git a/deltas/0.2.6/pre.001-fix.001.md b/deltas/0.2.6/pre.001-fix.001.md new file mode 100644 index 0000000..8c8ffd5 --- /dev/null +++ b/deltas/0.2.6/pre.001-fix.001.md @@ -0,0 +1,185 @@ + + + +# Delta `0.2.6-pre.001-fix.001` — correction du plan Wallet Desk + +## Base requise + +```text +0.2.6-pre.001 appliquée +workspace.package.version = 0.2.6-pre.1 +``` + +Ce correctif part de la livraison `pre.001` réellement appliquée par l'opérateur. Il ne remplace ni ne réécrit `deltas/0.2.6/pre.001.md`. + +## Type de livraison + +```text +ksp-doc-0.2.6-pre.001-fix.001.zip +``` + +La livraison est documentaire : elle modifie uniquement le plan `0.2.6` et ajoute le présent delta. + +## Objet + +Corriger et compléter le sizing `0.2.6` après revue opérateur, sans ouvrir une nouvelle prerelease et sans modification code/build/runtime/configuration exécutable. + +## Corrections apportées + +### Gabarit Wallet Desk + +Le plan retient explicitement le gabarit validé de `ksp-app-config-desk` : + +```text +Bootstrap +Font Awesome +DataTables Bootstrap 5 +DataTables Select Bootstrap 5 +SimpleBar +resize-observer-polyfill +``` + +DataTables porte l'inventaire des `.kspwallet` et Font Awesome peut représenter les états verrouillé/déverrouillé avec un équivalent textuel/accessible. + +### Config Wallet + +Le modèle planifié devient : + +```text +wallets_directory global +profiles[].wallets_subdirectory optionnel et relatif +``` + +Les sous-répertoires de profil permettent d'isoler notamment les wallets de tests, temporaires et futurs scénarios sans dupliquer la racine globale. + +Le répertoire effectif absent doit être créé automatiquement par Wallet Desk après résolution Config : succès/prêt journalisé en `debug`, échec de création journalisé en `error` et surfacé comme erreur runtime. + +### Passwords Config / `.env` + +Les variables : + +```text +KSP_SECRET_WALLET_PASS_01 +KSP_SECRET_WALLET_PASS_ +KSP_SECRET_WALLET_PASS_ +``` + +sont possédées/résolues exclusivement par Config côté Rust. + +Le suffixe concerne un numéro, un filename/stem normalisé ou un **alias de filename/opérateur**. Il ne correspond jamais à l'alias interne protégé `WalletInfo.alias` du `.kspwallet` et aucune ouverture préalable du wallet n'est effectuée pour découvrir cet alias. + +### Sens de circulation des passwords Tauri + +La règle est explicitée : + +```text +password saisi dans HTML/TypeScript +-> request Tauri IPC frontend -> Rust +-> OwnerPassword / ViewPassword +-> opération Wallet +-> purge/drop +``` + +Les passwords nécessaires aux opérations `unlock`, create/import, rotation/changement et recreate VIEW peuvent donc être envoyés du frontend vers Rust dans des request DTOs dédiés. + +Interdictions conservées : + +```text +Rust -X-> frontend password +Rust -X-> frontend keypair/secret bytes +response DTO -X-> password +logs/Debug/storage frontend -X-> password +``` + +Les passwords provenant de `KSP_SECRET_WALLET_PASS_*` ne transitent pas par le frontend : Config les fournit directement côté Rust. + +### CSP + +Le plan ne transforme plus la CSP en chantier obligatoire. Wallet Desk conserve par défaut le comportement du gabarit Config Desk (`csp = null`) et ne réouvre ce sujet que si une surface WebView concrète le nécessite. + +### Forecast souple + +Le plan distingue désormais clairement la prévision souple des prereleases des critères de validation. Le forecast est détaillé par objectifs/livrables positifs et prévoit explicitement une dernière tranche documentaire : + +```text +pre.014 README/USAGE + docs/validation + dépendances + prompt 0.2.7 + + validations finales + cargo tauri build en dernière opération +``` + +Le numéro reste prévisionnel ; des prereleases/fixes supplémentaires peuvent être insérés si nécessaire. + +## Fichiers ajoutés + +```text +deltas/0.2.6/pre.001-fix.001.md +``` + +## Fichiers modifiés + +```text +docs/plans/013-V0_2_6_WALLET_DESK_PLAN.md +``` + +## Fichiers supprimés + +```text +aucun +``` + +## Version technique + +Conformément à `VER-ID-008`, ce correctif est strictement documentaire : + +```text +workspace.package.version = 0.2.6-pre.1 (inchangé) +commit = v0.2.6-pre.001-fix.001 +``` + +Aucun `Cargo.toml` n'est livré dans ce delta. + +## Validations opérateur de la base `pre.001` + +L'opérateur a exécuté le `2026-08-20` : + +```bash +cargo fmt --all +python3 scripts/audit_rust_workspace_rules.py +cargo check --workspace +cargo clippy --workspace --all-targets +``` + +Résultats communiqués : + +```text +General Rust rule audit: clean +Rust export completeness audit: 0 candidate(s) +KSP workspace Rust rule audit: clean +cargo check --workspace: vert +cargo clippy --workspace --all-targets: vert, aucun warning signalé +``` + +Ces validations établissent l'état de base `pre.001`. Le présent fix ne modifie aucun fichier Rust, Cargo, frontend, runtime ou Config exécutable. + +## Validations exécutées sur ce correctif + +- contrôle que le plan porte `version: 2`, à partir de la version `1` livrée dans `pre.001` ; +- contrôle de l'absence de `Cargo.toml` et de tout fichier code/runtime dans l'archive ; +- contrôle que l'archive contient uniquement le plan modifié et le nouveau delta ; +- contrôle des occurrences résiduelles concernant alias interne/alias de filename et sens IPC des passwords. + +## Validations non exécutées + +Aucune validation Cargo supplémentaire n'est revendiquée pour ce fix documentaire ; aucun fichier consommé par le build ou le runtime n'est modifié. + +## Décisions prises + +- un secret `KSP_SECRET_WALLET_PASS_*` est indexé par numéro/filename/alias de filename opérateur, jamais par l'alias interne du wallet ; +- les passwords saisis peuvent traverser l'IPC uniquement dans le sens frontend -> Rust et uniquement pour l'opération demandée ; +- aucun password n'est renvoyé Rust -> frontend ; +- Config reste l'unique propriétaire des secrets provenant de process env/`.env` ; +- `workspace.package.version` reste `0.2.6-pre.1` ; +- la prochaine tranche technique reste `pre.002` après enregistrement de ce fix. + +## Questions ouvertes + +Aucune question bloquante pour l'ouverture de `pre.002`. diff --git a/docs/plans/013-V0_2_6_WALLET_DESK_PLAN.md b/docs/plans/013-V0_2_6_WALLET_DESK_PLAN.md index 17af7a5..9feec9c 100644 --- a/docs/plans/013-V0_2_6_WALLET_DESK_PLAN.md +++ b/docs/plans/013-V0_2_6_WALLET_DESK_PLAN.md @@ -1,11 +1,11 @@ - + # Plan `0.2.6` — Wallet Desk -## 1. Objet et statut du gate `pre.001` +## 1. Objet et statut de `0.2.6-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 : +`0.2.6` crée `crates/ksp-app-wallet-desk`, une application Tauri spécialisée et mince qui valide la composition réelle : ```text ksp-config-lib @@ -15,15 +15,15 @@ ksp-config-lib + 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. +La base auditée est la release stable fournie `v0.2.5`, avec `workspace.package.version = 0.2.5` avant ouverture. La base ne contient encore ni crate `ksp-app-wallet-desk`, ni document `std.wallet`, ni composite Wallet Desk. -`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. +`0.2.6-pre.001` reste une tranche d'audit, conception, inventaire et sizing. Elle ne crée pas encore la crate Tauri ni les fichiers Config runtime. Son rôle est de produire une trajectoire suffisamment détaillée pour que les prereleases suivantes implémentent des objectifs positifs et mesurables sans renégocier les frontières au fil des corrections. -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**. +Les validations opérateur du `2026-08-20` ont ensuite confirmé la base `pre.001` : `cargo fmt --all`, `python3 scripts/audit_rust_workspace_rules.py`, `cargo check --workspace` et `cargo clippy --workspace --all-targets` sont verts, sans warning signalé. Le présent plan intègre les corrections documentaires de `pre.001-fix.001` sans modifier la version Cargo, car aucun fichier code/build/runtime/configuration exécutable n'est touché. ## 2. Sources relues et hiérarchie appliquée -La conception suit l'ordre d'autorité demandé : +L'audit suit l'ordre d'autorité demandé : 1. archive KSP stable `v0.2.5` fournie ; 2. règles KSP versionnées ; @@ -32,11 +32,20 @@ La conception suit l'ordre d'autorité demandé : 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`. +Les documents obligatoires du prompt d'ouverture ont été relus avant conception. Les surfaces ont ensuite été réauditées dans : -`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`. +```text +ksp-core-lib +ksp-logging-lib +ksp-config-lib +ksp-onchain-transport-lib +ksp-wallet-lib +ksp-app-config-desk +``` -## 3. Frontières non négociables +Le plan historique `docs/plans/007-V0_2_0_SERIES_PLANNING.md` reste historique. La séquence active est celle de `ROADMAP.md` et `docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md`. + +## 3. Frontières architecturales Direction autorisée : @@ -45,29 +54,30 @@ 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-core-lib lorsque nécessaire -> ksp-logging-lib - -> Tauri / frontend + -> Tauri / frontend dependencies ``` 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-> cryptographie 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 +frontend -X-> localStorage/sessionStorage pour les passwords +frontend -X-> lecture directe de .env ``` -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. +La seule intégration directe `tracing` tolérée reste l'adapter Tauri imposé par `tauri-plugin-tracing`. La façade applicative continue de passer par `ksp-logging-lib`. -## 4. Audit de `ksp-app-config-desk` comme template Tauri +## 4. `ksp-app-config-desk` comme gabarit Tauri -### 4.1 Éléments à reprendre +### 4.1 Structure réutilisée -La structure existante est une bonne référence pour : +Wallet Desk reprend le gabarit déjà validé : ```text frontend/ @@ -75,37 +85,63 @@ 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 +Bootstrap +Font Awesome +DataTables Bootstrap 5 +DataTables Select Bootstrap 5 +SimpleBar +resize-observer-polyfill +splash + main window +TS-RS à la frontière DTO applicative +capabilities Tauri explicites +bridge frontend -> Rust -> ksp-logging-lib npm run check = tsc --noEmit +beforeBuildCommand = build frontend de production par Tauri ``` -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. +`SimpleBar` et `resize-observer-polyfill` sont conservés comme éléments du gabarit desktop, même si Wallet Desk ne les consomme pas tous dès le premier écran métier. Ils évitent de recréer un shell divergent du template éprouvé. -### 4.2 Éléments à ne pas copier automatiquement +### 4.2 DataTables et sélection des wallets -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 tableau d'inventaire des wallets utilise `datatables.net-bs5`. `datatables.net-select-bs5` est également conservé afin que la sélection de ligne reste cohérente avec le template et qu'un wallet puisse être sélectionné sans implémenter une logique de table parallèle. -Le shell Wallet Desk démarre donc sans : +Le tableau doit fournir au minimum : ```text -datatables.net-bs5 -datatables.net-select-bs5 -simplebar -resize-observer-polyfill +état lock/unlock +filename +format_version +VIEW enabled/disabled +inspection status ``` -Elles ne seront ajoutées ultérieurement que si un besoin mesuré apparaît. +La recherche, le tri et la pagination sont fournis par DataTables. Les données locked ne contiennent jamais Pubkey, alias ni notes. -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 Font Awesome -### 4.3 Logging à reprendre/refondre +Font Awesome est utilisé pour les états lisibles rapidement : -Le bridge éprouvé de Config Desk valide le pattern : +```text +fa-lock wallet verrouillé +fa-lock-open wallet actuellement ouvert +fa-eye / eye-slash selon état VIEW si utile +fa-triangle-exclamation pour une entrée invalide/diagnostic +``` + +Une icône n'est jamais l'unique information accessible : texte, `title`/ARIA ou colonne d'état accompagne l'icône. + +### 4.4 Ports de développement + +Config Desk utilise `1430` et son HMR `1431`. Wallet Desk réserve : + +```text +Vite dev : 1432 +HMR : 1433 +``` + +### 4.5 Logging à reprendre/refondre + +Le pattern validé est : ```text frontend helper @@ -114,22 +150,36 @@ frontend helper -> 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`. +Les helpers Wallet journalisent des événements sémantiques sans payload sensible, par exemple : + +```text +wallet_inventory_refresh_started +wallet_selected +wallet_unlock_view_succeeded +wallet_unlock_owner_failed +wallet_balance_refresh_succeeded +wallet_directory_created +wallet_export_cancelled +``` + +Ils ne sérialisent jamais aveuglément les request DTOs. ## 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. +La release stable `0.2.5` possède déjà la logique métier nécessaire. Wallet Desk compose et projette ; il ne réimplémente rien. -### 5.1 Locked et authorized projections +### 5.1 Locked projection -`LockedWalletInfo` expose seulement : +`LockedWalletInfo` expose uniquement : ```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. +Aucune Pubkey, aucun alias et aucune note ne sont disponibles avant autorisation. + +### 5.2 Authorized projection `WalletInfo` expose après autorisation : @@ -141,11 +191,11 @@ alias notes ``` -### 5.2 Handles Rust +### 5.3 Handles Rust -`WalletView` possède la capability VIEW et expose lecture de Pubkey/alias/notes ainsi que rotation de son credential VIEW. +`WalletView` et `WalletOwner` restent possédés par l'état Rust de l'application. -`WalletOwner` possède OWNER et expose : +`WalletOwner` fournit déjà : ```text sign @@ -161,9 +211,9 @@ 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. +Le frontend ne reçoit aucun handle ni secret interne. -### 5.3 Fichier et transfer +### 5.4 Persistence et transfer Les APIs publiques stables couvrent déjà : @@ -177,44 +227,32 @@ import_wallet_transfer_file_v1 export_wallet_transfer_file ``` -Les formats transfer stables engagés sont : +Les formats transfer retenus 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.5 `wallet.state_conflict` -### 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 : +Un conflit d'état provoque : ```text -cfg.std.logging -schema.std.logging -cfg.std.transport -schema.std.transport -schema.composite +message UI explicite +-> abandon du handle courant +-> purge de la projection autorisée et de la balance +-> nouvelle inspection locked +-> unlock requis de nouveau ``` -`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. +Aucun retry aveugle ni overwrite forcé. -### 6.2 Identifiants retenus +## 6. Config Wallet : racine globale + sous-répertoire de profil + +### 6.1 Besoin d'étendre le registre Config + +`ConfigFileRegistry::defaults()` connaît actuellement Logging, Transport et le schéma composite, mais pas Wallet. La tranche Config doit donc ajouter durablement : ```text cfg.std.wallet @@ -222,7 +260,7 @@ schema.std.wallet cfg.composite.ksp-app-wallet-desk ``` -Fichiers physiques par défaut : +Fichiers physiques prévus : ```text config/std.wallet.json @@ -232,13 +270,9 @@ 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.2 Shape de `std.wallet` -### 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` : +`wallets_directory` est global. Chaque profil peut ajouter un sous-répertoire relatif optionnel : ```json { @@ -248,38 +282,73 @@ Shape V1 retenu pour `0.2.6` : "profiles": [ { "profile_id": "default" + }, + { + "profile_id": "tests", + "wallets_subdirectory": "tests" + }, + { + "profile_id": "temporary", + "wallets_subdirectory": "temporary" } ] } ``` -`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. +Le profil `default` utilise directement la racine globale. Les profils `tests`, `temporary` ou futurs profils de scénario peuvent isoler leurs wallets sans introduire une seconde variable globale ni dupliquer le root. -Aucun OWNER/VIEW password, keypair, alias, note ou secret Wallet n'entre dans Config. +Le champ `wallets_subdirectory` : -### 6.4 Adapter Config -> Wallet Desk +- est optionnel ; +- est relatif ; +- peut contenir plusieurs composants relatifs si le schema final le permet ; +- refuse chemin absolu, `..` et toute résolution hors de `wallets_directory` ; +- reste une donnée non secrète de Config. -`ksp-config-lib` doit ajouter un contrat analogue à `ResolvedLoggingConfig` / `ResolvedTransportConfig`, par exemple `ResolvedWalletConfig`, contenant au minimum : +Le nom exact est retenu comme `wallets_subdirectory` pour rendre explicite sa relation avec `wallets_directory`. + +### 6.3 `ResolvedWalletConfig` + +`ksp-config-lib` doit fournir un adapter public analogue aux adapters Logging/Transport, par exemple : ```text -file_id -source_path -profile_id -selection_source -effective safe/real Config view -wallets_directory: PathBuf +ResolvedWalletConfig + file_id + source_path + profile_id + selection_source + wallets_directory + wallets_subdirectory + effective_wallets_directory + provenance sûre ``` -L'adapter : +`effective_wallets_directory` est : -- 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. +```text +wallets_directory +ou +wallets_directory / wallets_subdirectory +``` -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. +Config résout et valide les chemins mais n'énumère pas les wallets. + +### 6.4 Création automatique des répertoires + +Après résolution Config, Wallet Desk garantit l'existence du répertoire global et du répertoire effectif de profil avec une opération Rust `create_dir_all` ou équivalente. + +Comportement : + +```text +absent -> tentative de création +créé/prêt -> debug +échec création -> error + erreur runtime explicite +existe mais n'est pas un répertoire -> error + refus d'inventory +``` + +Le log de succès inclut au minimum le profil et un indicateur `created=true/false`. Le log d'échec est `error`. Aucun échec de création n'est traité comme un inventaire vide normal. + +La création est une responsabilité de composition de Wallet Desk après résolution Config, pas une raison d'ajouter du filesystem Wallet dans `ksp-wallet-lib`. ### 6.5 Composite Wallet Desk @@ -293,48 +362,125 @@ Shape de référence : { "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" - } + {"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": "default"} ] }, { - "profile_id": "mainnet", + "profile_id": "tests", "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" - } + {"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": "tests"} ] } ] } ``` -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 composite référence des `file_id`, jamais des filenames physiques. -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. Passwords provenant de Config / `.env` -## 7. Audit Transport : balance minimale +### 7.1 Évolution du contrat d'ouverture + +Pour `0.2.6`, les passwords Wallet peuvent être fournis de deux façons : + +```text +1. saisie éphémère dans l'UI +2. secret KSP géré par Config depuis process env ou .env +``` + +Les secrets `.env` sont donc explicitement autorisés pour cette application sous le namespace : + +```text +KSP_SECRET_WALLET_PASS_* +``` + +Cela ne place pas les passwords dans les documents JSON Config : Config reste seulement le propriétaire de l'environnement et de `.env`. + +### 7.2 Noms supportés + +Exemples opérateur : + +```text +KSP_SECRET_WALLET_PASS_01 +KSP_SECRET_WALLET_PASS_02 +KSP_SECRET_WALLET_PASS_MY_WALLET +KSP_SECRET_WALLET_PASS_TREASURY +``` + +Les suffixes peuvent représenter un numéro, le filename ou son stem normalisé, ou un **alias de filename/opérateur**. Ils ne représentent jamais l'alias interne protégé stocké dans le `.kspwallet`. + +Le filename locked peut produire un candidat déterministe. La normalisation exacte doit être testée et documentée dans la tranche Config/secret-provider ; direction retenue : + +```text +strip .kspwallet +-> uppercase ASCII +-> caractères hors [A-Z0-9] remplacés par _ +-> runs de _ compactés +-> _ de bord supprimés +``` + +Les collisions de labels sont possibles et ne deviennent pas une identité Wallet. + +### 7.3 Alias de filename et alias interne Wallet + +L'alias interne du wallet (`WalletInfo.alias`) reste une metadata protégée et n'intervient **jamais** dans la résolution des `KSP_SECRET_WALLET_PASS_*`. Wallet Desk n'ouvre donc jamais un wallet pour découvrir cet alias afin de choisir un secret. + +Un suffixe nommé correspond uniquement au filename/stem normalisé ou à un **alias de filename/opérateur** défini pour identifier le fichier côté exploitation. Cet alias de filename n'est pas une identité interne du wallet et peut être connu avant unlock. Les noms de variables restent côté Rust/Config et ne sont pas renvoyés au frontend ni journalisés. + +### 7.4 Découverte et ordre des candidats + +Le moteur Config possède déjà une vue sûre des noms d'environnement présents. Wallet Desk utilise uniquement les APIs Config publiques ; aucun accès `std::env` direct n'est autorisé. + +Ordre de tentative proposé : + +```text +1. candidat correspondant au filename normalisé +2. candidats numériques (_01, _02, ...) dans l'ordre numérique +3. candidats correspondant aux alias de filename/opérateur dans un ordre déterministe +``` + +Les valeurs provenant de Config restent entièrement côté Rust. Chaque `String` obtenue de Config est déplacée immédiatement dans `ViewPassword` ou `OwnerPassword`, qui possède la zeroization à la destruction. Cette règle concerne les secrets Config/`.env` ; elle n'interdit pas les passwords saisis par l'utilisateur de transiter **du frontend vers Rust** dans la request Tauri qui exécute l'opération demandée. + +### 7.5 Tentative explicite, pas d'auto-unlock silencieux + +Argon2id rend chaque tentative volontairement coûteuse. Wallet Desk ne doit donc pas essayer toutes les variables au simple clic de sélection d'une ligne. + +L'UX distingue : + +```text +Unlock VIEW avec saisie +Unlock OWNER avec saisie +Unlock VIEW avec secret configuré +Unlock OWNER avec secret configuré +``` + +Une action « secret configuré » tente les candidats jusqu'au premier succès pour la capability demandée. Pour une saisie manuelle, le password est envoyé une seule fois par IPC **HTML/TypeScript -> Rust**, converti immédiatement en wrapper Wallet puis purgé côté frontend. Rust ne renvoie jamais ce password. Le frontend peut recevoir : + +```text +candidate_count +success/failure +capability obtenue +``` + +mais jamais la valeur d'un secret Config ni un password saisi. Les noms/suffixes de variables Config ne sont pas exposés au frontend. Les logs peuvent enregistrer le nombre de candidats et le résultat, pas leurs noms ni leurs valeurs. + +### 7.6 `.env.example` + +La tranche Config ajoute une documentation de pattern dans `.env.example`, par exemple : + +```text +# Wallet Desk password candidates. Values are secrets and never committed. +# Additional KSP_SECRET_WALLET_PASS_