# Delta `0.2.6-pre.003` — `std.wallet`, composite Wallet Desk et répertoires ## Base requise ```text 0.2.6-pre.002 appliquée workspace.package.version = 0.2.6-pre.2 ``` Les preuves opérateur de `pre.002` sont vertes : installation npm initiale, `cargo fmt --all`, audit structurel Python, `cargo check --workspace`, `cargo clippy --workspace --all-targets`, `cargo test -p ksp-app-wallet-desk` et `cargo tauri dev -c crates/ksp-app-wallet-desk/tauri.conf.json`. Le shell Tauri/Vite a démarré sur le port réservé `1432`. ## Type de livraison ```text ksp-general-0.2.6-pre.003.zip ``` Cette tranche modifie Config, le runtime Wallet Desk et les fichiers de configuration exécutables. Elle incrémente donc `workspace.package.version` vers `0.2.6-pre.3`. ## Objet Matérialiser la composition Config nécessaire à Wallet Desk sans ouvrir encore un fichier `.kspwallet` ni implémenter l'inventory de `pre.004`. Le delta fournit : ```text cfg.std.wallet schema.std.wallet cfg.composite.ksp-app-wallet-desk wallets_directory global wallets_subdirectory optionnel par profil profils Wallet default / temporary / tests ResolvedWalletConfig mapping d'un profil déjà résolu par composite vers Logging/Wallet préservation ConfigProfileSelectionSource::Composite bootstrap Wallet Desk logging + transport + wallet component validation création automatique du répertoire global/effectif rejet de root non-directory et de symlinks dans le sous-répertoire de profil logs debug sur directory ready/created logs error sur préparation impossible statut runtime/UI Config + chemins Wallet sûrs ``` ## `std.wallet` Le document standard est enregistré sous : ```text file_id = cfg.std.wallet schema_file_id = schema.std.wallet filename = std.wallet.json schema filename = std.wallet.schema.json ``` Shape runtime : ```json { "format_version": 1, "wallets_directory": "${KSP_WALLETS_DIRECTORY:-wallets}", "default_profile": "default", "profiles": [ {"profile_id": "default"}, {"profile_id": "temporary", "wallets_subdirectory": "temporary"}, {"profile_id": "tests", "wallets_subdirectory": "tests"} ] } ``` `wallets_directory` est global. `wallets_subdirectory` reste relatif, optionnel et peut contenir plusieurs composants normaux. Chemin absolu, `.` ou `..` sont rejetés. Les valeurs de sensibilité `Secret` sont refusées par l'adapter Wallet : un password ne peut donc pas être injecté comme path Config. `ksp-config-lib` résout et valide les paths mais ne crée aucun répertoire et n'énumère aucun wallet. ## Composite Wallet Desk Le premier composite runtime concret est : ```text file_id = cfg.composite.ksp-app-wallet-desk filename = composite.ksp-app-wallet-desk.json schema = schema.composite ``` Le profil autonome `devnet` sélectionne : ```text logging -> cfg.std.logging / local_dev transport -> cfg.std.transport / devnet_public wallet -> cfg.std.wallet / default ``` Les profils composites `temporary` et `tests` réutilisent Logging/Transport mais sélectionnent respectivement les profils Wallet `temporary` et `tests`. Wallet Desk exige les trois `component_id` et vérifie leurs `file_id` attendus avant de poursuivre son bootstrap. Le pool Transport n'est pas encore construit dans cette tranche ; cette composition est validée maintenant pour ne pas inventer une sélection parallèle plus tard. ## Adapters Config `ResolvedWalletConfig` expose : ```text file_id source_path profile_id selection_source effective Config sûr/réel selon contrat Config wallets_directory wallets_subdirectory effective_wallets_directory ``` Deux entrées complètent les adapters pour un profil déjà sélectionné par composite : ```text ConfigDocumentEngine::resolve_logging_config_profile ConfigDocumentEngine::resolve_wallet_config_profile ``` Elles évitent de recharger le même profil comme sélection `Explicit` et conservent `ConfigProfileSelectionSource::Composite`. Cette extension ne crée aucune dépendance Config -> `ksp-wallet-lib`. ## Répertoires Wallet Après initialisation du Logging, Wallet Desk résout le composant Wallet et prépare la filesystem surface applicative : ```text wallets_directory -> création si absent -> optional wallets_subdirectory composant par composant -> effective_wallets_directory prêt ``` Politique de cette tranche : ```text root déjà directory -> accepté root absent -> create_dir_all root existant non-directory -> wallet_desk.wallet_directory_invalid profile component absent -> create_dir profile component directory -> accepté profile component symlink -> wallet_desk.wallet_directory_invalid profile component fichier -> wallet_desk.wallet_directory_invalid inspection/création I/O KO -> wallet_desk.wallet_directory_prepare_failed ``` Un succès/prêt est journalisé en `debug`. Une impossibilité de préparation est journalisée en `error` puis surfacée au bootstrap. Les paths sont non secrets par contrat `std.wallet`. L'inventory `.kspwallet`, la canonicalisation des fichiers candidats et la policy complète de sélection de fichiers restent `pre.004`. ## Environnement `/.env.example` documente désormais : ```text KSP_WALLETS_DIRECTORY=wallets # KSP_SECRET_WALLET_PASS_01= ``` La seconde ligne documente uniquement le pattern prévu pour la future tranche d'unlock. Aucun provider de password n'est implémenté dans `pre.003` et aucune valeur `KSP_SECRET_WALLET_PASS_*` n'est lue par Wallet Desk à ce stade. ## UI/runtime status Le DTO `RuntimeStatusDto` et le Dashboard affichent maintenant : ```text version / phase nombre de ressources Config enregistrées profil composite profil Logging profil Wallet fallback Logging wallets_directory wallets_subdirectory répertoire Wallet effectif création du répertoire effectif au démarrage oui/non ``` Aucune Pubkey, aucun alias interne Wallet, aucune note et aucun secret ne sont ajoutés à cette projection. ## Tests ajoutés/étendus Config : ```text registre à 8 descripteurs cfg.std.wallet + schema + composite enregistrés schema std.wallet root global sans subdirectory profil tests -> subdirectory relatif precedence process > .env pour KSP_WALLETS_DIRECTORY rejet absolute / parent / current subdirectories rejet d'un path Wallet de sensibilité Secret profil Wallet sélectionné par composite conserve provenance Composite public API des nouveaux adapters/constants ownership des filenames Config-managed ``` Wallet Desk : ```text composite devnet -> logging/local_dev + transport/devnet_public + wallet/default création idempotente root + nested profile directory rejet root non-directory rejet symlink de profile path sur Unix statut frontend expose les projections Config prévues ``` ## Dépendances Aucune dépendance Cargo ou npm n'est ajoutée/modifiée dans cette tranche. `package.json` et `tauri.conf.json` changent uniquement leur version applicative vers `0.2.6-pre.3`. Il n'y a donc **aucune commande npm directe à exécuter pour `pre.003`**. ## Version technique ```text workspace.package.version = 0.2.6-pre.3 commit = v0.2.6-pre.003 ``` Aucun tag stable. ## Validation opérateur requise Après application : ```bash cargo fmt --all python3 scripts/audit_rust_workspace_rules.py cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-config-lib cargo test -p ksp-app-wallet-desk cargo test --workspace KSP_WALLETS_DIRECTORY=var/wallet-desk-pre003 cargo tauri dev -c crates/ksp-app-wallet-desk/tauri.conf.json ``` Le parcours Tauri doit vérifier que le Dashboard affiche le profil composite `devnet`, le profil Wallet `default`, la racine override `var/wallet-desk-pre003` résolue et le répertoire effectif prêt/créé, avec événement backend `debug` correspondant. Le répertoire `var/` est déjà ignoré par le repository. `cargo tauri build -c crates/ksp-app-wallet-desk/tauri.conf.json` **n'est pas exécuté en `pre.003`**. Il reste la toute dernière opération de validation de `0.2.6`. ## Suite `pre.004` branche l'inventory réel : enumeration non récursive `.kspwallet`, policy symlink/path, `inspect_locked_wallet_file_v1`, DTOs locked, DataTables, sélection de ligne et refresh, sans révéler Pubkey/alias/notes.