# Delta `0.2.6-pre.004` — inventory `.kspwallet` et inspection locked ## Base requise ```text 0.2.6-pre.003-fix.004 appliquée workspace.package.version = 0.2.6-pre.3.fix.4 ``` Les preuves opérateur de `pre.003-fix.004` sont vertes : `cargo fmt --all`, audit structurel Python, `cargo check --workspace`, `cargo clippy --workspace --all-targets`, `cargo test -p ksp-app-config-desk`, `cargo test --workspace` et `cargo tauri dev -c crates/ksp-app-wallet-desk/tauri.conf.json`. Le runtime utilise le profil composite Logging `supertrace` et démarre correctement. ## Type de livraison ```text ksp-general-0.2.6-pre.004.zip ``` Cette tranche ajoute une dépendance interne Wallet et du runtime Rust/frontend ; le signal technique devient : ```text workspace.package.version = 0.2.6-pre.4 commit = v0.2.6-pre.004 ``` Aucun tag stable. ## Objet Brancher l'inventory réel des fichiers natifs `.kspwallet` dans Wallet Desk sans introduire encore de password, de handle VIEW/OWNER ni de projection d'identité protégée. ## Frontière Wallet `ksp-app-wallet-desk` dépend désormais directement de `ksp-wallet-lib` et délègue l'inspection locked à : ```text ksp_wallet_lib::inspect_locked_wallet_file_v1 ``` Aucune crypto, parser `.kspwallet`, keypair ou signature n'est réimplémenté dans l'application. ## Inventory filesystem La racine unique est : ```text ResolvedWalletConfig::effective_wallets_directory ``` Politique : ```text read_dir asynchrone non récursif filename UTF-8 suffixe exact .kspwallet un seul composant filename slash et backslash rejetés pour les sélections frontend fichiers réguliers uniquement symlinks d'entrée exclus répertoires même nommés *.kspwallet exclus tri déterministe par filename ``` Le bootstrap Config durcit aussi la racine globale : un `wallets_directory` existant sous forme de symlink est désormais refusé au lieu d'être suivi par `metadata()`. Une erreur de lecture de la racine fait échouer la commande avec `wallet_desk.wallet_inventory_failed`. Une entrée `.kspwallet` présente mais invalide ne fait pas échouer tout l'inventory : elle reste visible avec état `error`, inspection `invalid` et `CommandErrorDto` sans context/source. ## DTOs locked La tranche ajoute : ```text WalletInventoryEntryDto WalletInventoryStateDto WalletInspectionStatusDto LockedWalletDto WalletSelectionRequestDto ``` Une ligne valide expose uniquement : ```text wallet_id / filename format_version view_enabled state = locked inspection_status = valid ``` Une ligne invalide expose filename + diagnostic sûr. Aucun DTO ne porte Pubkey, alias, notes, password, path complet ou handle Wallet. ## Commandes Tauri ```text list_wallets refresh_wallets select_wallet ``` `select_wallet` reçoit uniquement un `wallet_id`/filename, reconstruit le path sous la racine effective, rejette traversal/séparateurs/symlink/non-file puis relance l'inspection locked avant de répondre. La sélection n'installe pas encore un `WalletSession` durable ; celui-ci reste `pre.005`. ## Frontend Le tableau Wallet devient un vrai DataTable alimenté par le backend : ```text État -> fa-lock ou fa-triangle-exclamation Filename -> texte DOM sûr Format -> version ou — VIEW -> enabled / disabled / — Inspection -> Valide ou code diagnostic sûr ``` Le bouton Refresh appelle `refresh_wallets`. La sélection d'une ligne valide appelle `select_wallet` et affiche seulement filename/format/VIEW dans la carte « Wallet courant ». Les lignes invalides restent visibles mais ne sont pas sélectionnables. Un refresh purge la projection sélectionnée frontend afin de ne pas conserver une vue stale. Le rendu utilise `textContent`/création DOM pour les valeurs issues du filesystem ; aucun filename n'est injecté par HTML. ## Logging Les opérations suivantes sont instrumentées : ```text inventory refresh start/completion invalid locked inspection non-regular/symlink skip selection accepted/rejected frontend inventory load/render/refresh/row selection ``` Le profil composite reste `supertrace`; aucun changement de `std.logging` n'est requis. ## Tests Les canaris ajoutés couvrent : ```text valid .kspwallet + invalid .kspwallet dans le même inventory wrong extension ignorée subdirectory *.kspwallet ignoré tri déterministe traversal slash/backslash rejeté symlink Wallet ignoré et non sélectionnable sur Unix root wallets_directory symlink rejeté sur Unix DTO locked sans Pubkey/alias/notes/password commands Tauri list/refresh/select présentes frontend DataTable réellement branché sur les DTOs Wallet ``` ## Dépendances Cargo : ```text ksp-wallet-lib = { path = "../ksp-wallet-lib" } tokio features += fs, rt ``` Aucune dépendance npm et aucun script npm ne changent. **Aucune commande npm directe n'est nécessaire pour cette tranche.** ## Validation opérateur requise ```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 KSP_WALLETS_DIRECTORY=var/wallet-desk-pre004 cargo tauri dev -c crates/ksp-app-wallet-desk/tauri.conf.json ``` Pour la vérification UI, placer si souhaité un ou plusieurs `.kspwallet` existants dans `var/wallet-desk-pre004`, ainsi qu'un fichier `invalid.kspwallet` non valide, puis tester recherche/tri, Refresh et sélection des lignes valides. Toujours aucun `cargo tauri build` à ce stade. ## Suite Après validation de `pre.004`, `pre.005` introduira la création de Wallet et le lifecycle/session Rust sans avancer encore la balance HTTP.