# Validation `0.2.12` — SOL Prices Desk + intégration Wallet Desk ## 1. Objet Cette matrice est ouverte par `0.2.12-pre.001`. Elle suit la création de `ksp-app-solprices-desk`, sa composition Config/Off-chain Transport puis l'intégration provider-neutral dans Wallet Desk. Statuts utilisés : ```text PASS preuve acquise PENDING attendu dans une tranche ultérieure OUT explicitement hors scope NOT RUN commande non exécutée dans le contexte indiqué ``` ## 2. Gate `0.2.12-pre.001` | Critère | Statut | Preuve | |-------------------------------------------------|--------|--------------------------------------------------------------------| | archive stable `v0.2.11` utilisée | PASS | archive Gitea opérateur fournie | | `workspace.package.version = 0.2.11` à l’entrée | PASS | inspection `Cargo.toml` | | `deltas/0.2.11/rel.001.md` présent | PASS | inspection archive | | prompt `017-V0_2_12_START_PROMPT.md` présent | PASS | inspection archive | | metadata `.git` disponible | OUT | archive source sans `.git`; tag non revérifiable localement | | baseline Cargo stable | PASS | preuve opérateur 2026-08-26: fmt/check/clippy/test workspace verts | | audits Python sandbox sur archive | PASS | Rust rules clean; Markdown tables clean avant modification | | règles/architecture obligatoires relues | PASS | audit `pre.001` + plan 019 | | surface Off-chain réelle inventoriée | PASS | plan 019 sections 3/9/10 | | surface Config/composite/packaging inventoriée | PASS | plan 019 section 4 | | gabarits Config/Wallet Desk inventoriés | PASS | plan 019 section 5 | | sources officielles Tauri/TS-RS réauditées | PASS | plan 019 section 6 | | screen map Price Desk + Wallet | PASS | plan 019 section 8 | | DTO/command map | PASS | plan 019 sections 9/10 | | état de présentation décidé | PASS | backend mémoire uniquement; plan 019 section 7 | | Config/composite map | PASS | nouveau composite + extension Wallet; plan 019 section 4 | | threat model desktop | PASS | plan 019 section 16 | | Wallet integration map | PASS | plan 019 section 12 | | auto-refresh | OUT | hors scope confirmé | | équivalent USD du solde | PASS | demandé opérateur; calcul backend exact depuis moyenne du refresh | | forecast souple recalibré | PASS | fermeture normative `pre.010` docs + `pre.011` publication + rel | | scope clôturable | PASS | pas de redécoupage requis avant `pre.002` | | code/scaffold fonctionnel ajouté en `pre.001` | OUT | interdit par le gate | ## 3. Screen/feature matrix | Surface | Contrat | Statut | |------------------------|-----------------------------------------|--------| | splash Price Desk | lifecycle KSP commun | PASS | | main shell Price Desk | header/navigation KSP | PASS | | table providers | registry provider-neutral, ordre stable | PASS | | table responsive UX | sticky/badges/timestamps distincts | PASS | | prix exact | String issue de `MarketPriceDecimal` | PASS | | availability/fraîcheur | état générique + timestamps réels | PASS | | refresh row | `MarketPriceService::refresh` | PASS | | refresh selected/many | `MarketPriceService::refresh_many` | PASS | | refresh all | `MarketPriceService::refresh_all` | PASS | | Diagnostics | profils/counts sûrs seulement | PASS | | Wallet prix moyen | `SOL/USD moyen` / `N.A.` | PASS | | auto-refresh | aucun scheduler/polling | OUT | | Wallet équivalent USD | calcul Rust exact / `N.A.` | PASS | ## 4. DTO/command matrix | Contrat | Entrée/sortie sûre | Statut | |----------------------------------------|--------------------------------------------------------------------|--------| | `MarketPriceRuntimeStatusDto` | profiles/counts sans secret | PASS | | `MarketPriceProviderRowDto` | ID/display/pair/semantics/auth/availability/price/timestamps/retry | PASS | | single refresh direct | provider_id opaque seulement | PASS | | `MarketPriceRefreshManyRequestDto` | liste d’IDs opaques ; garde app `1..=64` avant parsing | PASS | | `MarketPriceRefreshResultDto` | rows/outcome classifiés | PASS | | runtime/list/refresh/many/all commands | aucun URL/header/API key/body | PASS | | TS-RS exports | bindings générés non versionnés | PASS | | provider-specific type dans IPC | interdit | OUT | | prix `f64` comme vérité IPC | interdit | OUT | ## 5. Config/composite matrix | Contrat | Valeur attendue | Statut | |---------------------------------------|--------------------------------------------------------------|--------| | Price Desk composite file | `config/composite.ksp-app-solprices-desk.json` | PASS | | Price Desk file_id | `cfg.composite.ksp-app-solprices-desk` | PASS | | schema | `schema.composite` existant | PASS | | components | `logging`, `offchain_transport` | PASS | | default profile | `public_keyless` | PASS | | optional profile | `all_free` | PASS | | test profile | `tests` -> offchain `public_keyless` | PASS | | Wallet composite | ajoute offchain `public_keyless` à devnet/temporary/tests | PASS | | registry/resource count | 11 après nouveau composite | PASS | | registry + resources atomiques | Config + Config Desk + Wallet Desk + Price Desk même tranche | PASS | | nouveau schema Config | inutile | OUT | | modification `std.offchain_transport` | pas de lacune identifiée | OUT | ## 6. Provider-agnostic boundary matrix | Canari | Attendu | Statut | |--------------------------------------------|------------------|--------| | app dépend du service/registry générique | oui | PASS | | branche `coingecko`/`kraken`/etc. dans app | aucune | PASS | | SDK provider dans app | aucun | PASS | | reqwest/provider fetch frontend | aucun | PASS | | endpoint/header/API key dans DTO | aucun | PASS | | rate limiter/sleep/retry provider dans app | aucun | PASS | | refresh many ordre service | préservé | PASS | | semantics provider-neutral visibles | oui, sans fusion | PASS | | prix canonique/fallback/moyenne | aucun | OUT | ## 7. Security matrix | Risque/canari | Attendu | Statut | |--------------------------------|-------------------------------------------------------|--------| | URL arbitraire depuis frontend | impossible par contrat command | PASS | | extraction API key/header | aucune projection/log | PASS | | provider_id inconnu | erreur KSP sûre | PASS | | batch duplicate | rejet avant dispatch | PASS | | batch oversized | garde app `1..=64` avant parsing/dispatch | PASS | | refresh spam | limites/cooldown Off-chain toujours actifs | PASS | | stale observation | timestamps/état distingués | PASS | | double-click race | in-flight/order contrôlés | PASS | | close pendant refresh | état uniquement mémoire ; aucune persistance frontend | PASS | | CWD/resource confusion | frontendDist/cwd/ports/resources canarisés par app | PASS | | Price Desk capabilities | `core:default`, `tracing:default` uniquement | PASS | | plugin dialog Price Desk | absent | PASS | | frontend sensitive logging | action/ID/count/code seulement | PASS | | Wallet VIEW/OWNER/secrets | suite Wallet + compliance inchangées | PASS | ## 8. Wallet integration matrix | Contrat | Attendu | Statut | |----------------------------|--------------------------------------------------------------------------|--------| | Cargo dependency | Wallet Desk -> `ksp-offchain-transport-lib` | PASS | | Config component | Wallet composite -> `cfg.std.offchain_transport/public_keyless` | PASS | | runtime | Config -> `ResolvedOffchainTransportConfig` -> `MarketPriceService` | PASS | | command | `refresh_wallet_balance` existante, aucun input prix/provider | PASS | | DTO | moyenne + équivalent USD en `Option` exacts | PASS | | moyenne | observations réussies du refresh courant, backend sans `f64`, 8 déc. max | PASS | | UI | résumé compact `SOL/USD moyen` + `Équivalent USD` / `N.A.` | PASS | | balance HTTP On-chain | `getBalance` inchangé et toujours autoritatif | PASS | | dégradation prix | échec/absence prix -> `N.A.` sans faire échouer la balance | PASS | | WalletSession VIEW/OWNER | inchangée | PASS | | Wallet secret projections | aucune nouvelle | PASS | | provider ID frontend | aucun | PASS | | command prix Wallet | aucune | PASS | | USD balance multiplication | calcul Rust exact depuis lamports + moyenne du refresh courant | PASS | ## 9. Tauri/package matrix | Contrat | Attendu | Statut | |------------------------------------|--------------------------------------|--------| | Price Desk ports | 1434/1435 strict | PASS | | windows | splash + main | PASS | | Rust package | lib + bin; `main.rs` mince | PASS | | commands | centralisées `tauri.rs` | PASS | | frontendDist | hors source, path Price Desk dédié | PASS | | hooks | npm dev/build cwd crate | PASS | | backend cross-app | aucune référence Wallet par erreur | PASS | | resources | registry complet packagé | PASS | | bundle | targets/icons cohérents | PASS | | version bundle Tauri | dérivée de Cargo; pas de duplication | PASS | | Tauri production build Price Desk | pre.009 TS6133; fix retest | RETEST | | Tauri production build Wallet Desk | pre.009 .deb/.rpm/.AppImage | PASS | ## 10. Gates techniques/live finaux | Gate | Statut | |--------------------------------------------------------------|--------| | `cargo fmt --all` | PASS | | `python3 scripts/audit_rust_workspace_rules.py` | PASS | | `python3 scripts/audit_markdown_tables.py ... deltas/0.2.12` | PASS | | `cargo check --workspace` | PASS | | `cargo clippy --workspace --all-targets` | PASS | | `cargo test --workspace` | PASS | | Price Desk functional dev path | PASS | | Wallet Desk functional price path | PASS | | keyless app-composition live smoke | PASS | | Price Desk `cargo tauri build` | RETEST | | Wallet Desk `cargo tauri build` | PASS | Le live `0.2.12` valide la composition applicative générique; il ne répète pas l'audit provider `7/7` de `0.2.11` sans raison. ## 11. Validations exécutées pour `pre.001` ```text inspection archive/version/rel/prompt PASS python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... crates PASS sources officielles Tauri/TS-RS PASS audit cargo fmt/check/clippy/test dans sandbox NOT RUN — cargo indisponible cargo fmt/check/clippy/test opérateur sur base stable fournie PASS ``` Après écriture du présent delta, les audits Rust structurel et Markdown ont été rejoués avec `deltas/0.2.12` inclus et sont propres. ## 12. Forecast de clôture recalibré Après décision opérateur de simplifier Wallet Desk, les responsabilités restantes sont condensées sans supprimer les gates de sortie : ```text pre.008 intégration Wallet minimale + moyenne SOL/USD pre.009 hardening transversal + gate technique/live + builds finaux pre.010 réconciliation documentaire finale pre.011 prompt suivant + CHANGELOG + ROADMAP uniquement rel.001 publication stable ``` ## 13. Gate `0.2.12-pre.002` Le scaffold strict est matérialisé sans avancer la composition Off-chain : ```text crate mixte lib/bin ksp-app-solprices-desk PASS ports Vite/HMR 1434/1435 strict PASS fenêtres splash + main PASS frontendDist/hook/backend propres PASS bridge Logging + tauri-plugin-tracing PASS capabilities core:default + tracing:default PASS plugin dialog/fs/http/shell frontend absent resources Config 10/10 registry courant; 11e composite réservé à pre.003 MarketPriceService / refresh / table prix absent par contrat pre.002 ``` Validations sandbox après matérialisation : ```text python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... deltas PASS cargo fmt/check/clippy/test NOT RUN — cargo indisponible dans le sandbox ``` Le retour opérateur du `27 août 2026` clôt le gate de tranche : `cargo fmt --all`, installation npm, audits Rust/Markdown, `cargo check --workspace`, Clippy workspace, `cargo test -p ksp-app-solprices-desk` et `cargo tauri dev` passent. Le test applicatif exécute 12 unit tests, 4 canaris `desktop_contract`, 3 canaris `desktop_security` et 1 canari `public_api`, tous PASS. ## 14. Gate `0.2.12-pre.002-fix.001` Le correctif réaligne le nouveau Desk sur le gabarit desktop commun sans ouvrir le runtime prix : ```text package frontend commun : tracing + ResizeObserver + Bootstrap/SimpleBar PASS structurel ResizeObserver installé avant SimpleBar PASS structurel getCurrentWindow() utilisé au bootstrap main PASS structurel commande Tauri get_runtime_status PASS structurel footer commun PASS structurel police DOS_Amazigh + manifeste de provenance PASS structurel partials SCSS communs identiques hors headers de fichier PASS structurel _app.scss réutilise le vocabulaire app-runtime-list/app-placeholder PASS structurel TRACING_DOMAIN_SHELL réellement consommé PASS structurel MarketPriceService / composite / refresh / table prix absent par contrat ``` Le gate opérateur du `27 août 2026` sur `0.2.12-pre.2.fix.1` est propre : audits Rust/Markdown, `cargo check --workspace`, `cargo clippy --workspace --all-targets` et `cargo test -p ksp-app-solprices-desk` passent sans les deux warnings précédents. `cargo tauri dev` démarre Vite sur `1434` puis le backend Rust sans warning. `cargo test --workspace` n'a pas été rejoué dans ce retour précis et n'est donc pas revendiqué ici. ## 15. Gate `0.2.12-pre.003` La tranche matérialise uniquement la composition Config et le bootstrap Off-chain provider-neutral : ```text composite cfg.composite.ksp-app-solprices-desk PASS structurel profils public_keyless / all_free / tests PASS structurel composants logging + offchain_transport par file_id PASS structurel registry Config 11 descriptors resources Config Desk / Wallet Desk / SOL Prices Desk 11/11 chacune Logging SOL Prices Desk résolu depuis le composite PASS structurel ResolvedOffchainTransportConfig construit au bootstrap PASS structurel service provider-neutral public_keyless 8 entrées attendues par canari MarketPriceRuntime / rows / observations / refresh commands absent par contrat pre.003 navigation et contrôles frontend existants journalisés en debug PASS structurel/canari IPC frontend request/completion debug / trace ``` Le contrat de logging frontend est volontairement durable : action utilisateur et transition de vue en `debug`, étapes techniques fréquentes/fin d'IPC en `trace`, sans sérialiser prix, credentials, headers ni payloads métier. Les futurs boutons de refresh devront reprendre le même bridge et le même niveau de discipline. Validations sandbox après matérialisation : ```text python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... deltas PASS validation syntaxique des JSON modifiés PASS cargo fmt/check/clippy/test NOT RUN — cargo indisponible dans le sandbox ``` ## 16. Gate `0.2.12-pre.003-fix.001` Le gate opérateur du `27 août 2026` sur `0.2.12-pre.3` a établi : ```text cargo fmt --all PASS python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py ... deltas/0.2.12 PASS cargo check --workspace PASS cargo clippy --workspace --all-targets FAIL — compilation du test config_composition cargo test -p ksp-app-solprices-desk FAIL — même défaut de compilation ``` Le défaut est limité au canari `solprices_desk_default_composite_builds_provider_neutral_offchain_service` : son message `assert!` formatait `{environment:?}` sur un `Result`. Comme `ConfigEnvironment` n'implémente volontairement pas `Debug`, ce formatage imposait un contrat non requis au type de succès. `pre.003-fix.001` retire uniquement cette interpolation et conserve le `is_ok()` suivi du `match` explicite existant. Aucun `Debug` n'est ajouté à `ConfigEnvironment`, aucun `unwrap`/`expect`/`panic` n'est introduit, et aucun comportement runtime n'est modifié. Validations sandbox après matérialisation du fix : ```text python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... deltas PASS cargo fmt/check/clippy/test NOT RUN — cargo indisponible dans le sandbox ``` ## 17. Gate `0.2.12-pre.004` La tranche introduit la première projection prix applicative sans effectuer de requête provider : ```text MarketPriceRuntime backend implémenté état présentation mémoire backend uniquement registry -> lignes provider-neutral implémenté MarketPriceProviderRowDto implémenté MarketPriceRuntimeStatusDto implémenté prix exact Option, jamais f64 timestamps observation/retry Option exactes en millisecondes Unix list_market_prices implémenté, aucun dispatch réseau états frontend loading / empty / table implémentés refresh row/many/all absent par contrat pre.004 frontend fetch/localStorage/sessionStorage absent logging chargement/rendu registry trace sans prix/payload ``` Le gate opérateur précédent est désormais fermé après `pre.003-fix.001` : ```text cargo fmt --all PASS python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py ... deltas/0.2.12 PASS cargo check --workspace PASS cargo clippy --workspace --all-targets PASS cargo test -p ksp-app-solprices-desk PASS (cd crates/ksp-app-solprices-desk && cargo tauri dev) PASS cargo test --workspace NOT RUN dans ce retour précis ``` Validations sandbox après matérialisation de `pre.004` : ```text python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... deltas PASS cargo fmt/check/clippy/test NOT RUN — cargo indisponible dans le sandbox ``` ## 18. Fix `0.2.12-pre.004-fix.001` Le gate opérateur de `pre.004` confirme : ```text cargo fmt --all PASS python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py ... deltas/0.2.12 PASS cargo check --workspace PASS cargo clippy --workspace --all-targets PASS cargo test -p ksp-app-solprices-desk PASS cargo tauri dev SOL Prices Desk PASS cargo test --workspace FAIL ``` L'échec workspace est unique et externe au runtime prix : `ksp-app-config-desk::profiles::profile_inventory_exposes_registered_profile_documents` construit son `ConfigManagement` sur `crates/ksp-config-lib/unit_tests/fixtures`. Depuis l'enregistrement de `cfg.composite.ksp-app-solprices-desk`, l'inventory parcourt onze descriptors et tente donc de charger : ```text crates/ksp-config-lib/unit_tests/fixtures/composite.ksp-app-solprices-desk.json ``` Cette fixture n'avait pas été ajoutée, ce qui produit `config/json_file_read_failed`. Le correctif : ```text ajoute composite.ksp-app-solprices-desk.json dans les fixtures Config conserve les profils composite public_keyless / all_free / tests utilise logging/local_dev, réellement disponible dans la fixture Logging utilise offchain_transport/public_keyless ou all_free selon le profil ajoute au canari Config Desk l'assertion explicite du nouveau composite ne modifie aucun runtime prix, DTO, adapter provider ou frontend ``` La version technique devient `0.2.12-pre.4.fix.1` parce qu'un test Rust compilé est modifié. Les versions applicatives SOL Prices Desk de `package.json` et `tauri.conf.json` sont synchronisées. Validations sandbox après matérialisation du fix : ```text python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... deltas PASS cargo fmt/check/clippy/test NOT RUN — cargo indisponible dans le sandbox ``` Gate opérateur attendu après application : ```bash cargo fmt --all python3 scripts/audit_rust_workspace_rules.py python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.2.12 cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-app-config-desk cargo test -p ksp-app-solprices-desk cargo test --workspace ``` ## 19. Fix `0.2.12-pre.004-fix.002` Le gate opérateur de `pre.004-fix.001` confirme : ```text cargo fmt --all PASS python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py ... deltas/0.2.12 PASS cargo check --workspace PASS cargo clippy --workspace --all-targets PASS cargo test -p ksp-app-solprices-desk FAIL ``` L'échec est limité à `pre_002_shell_uses_reserved_ports_windows_and_owned_backend_paths` : le test attend encore littéralement `0.2.12-pre.4`, alors que `pre.004-fix.001` a correctement synchronisé `package.json` et `tauri.conf.json` sur `0.2.12-pre.4.fix.1`. Le comportement runtime n'est pas en cause. Le correctif aligne SOL Prices Desk sur les contrats déjà utilisés par Config Desk et Wallet Desk : ```text parse SemVer core des versions desktop implémenté plancher version >= 0.2.6 implémenté égalité tauri.conf.json / package.json implémentée chaîne exacte 0.2.12-pre.4 dans le canari supprimée runtime prix / DTO / provider / frontend inchangés ``` La version technique devient `0.2.12-pre.4.fix.2`. Le gate attendu doit confirmer que le canari reste vert avec ce suffixe et continuera de l'être lors des prochaines prereleases. ## 20. Gate `0.2.12-pre.005` Le gate opérateur de clôture de `pre.004-fix.002` est intégralement vert : ```text cargo fmt --all PASS python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py ... deltas/0.2.12 PASS cargo check --workspace PASS cargo clippy --workspace --all-targets PASS cargo test -p ksp-app-solprices-desk PASS cargo test --workspace PASS cargo tauri dev SOL Prices Desk PASS ``` La tranche `pre.005` ajoute uniquement le refresh individuel : ```text MarketPriceService::refresh branché par provider_id opaque mutex présentation détenu pendant await non loading backend par ligne oui observation réussie exacte conservée sous forme string via DTO existant absence de nouvelle observation dernière observation réussie conservée availability/retry source Off-chain Transport, sans réinterprétation app refresh_market_price implémenté refresh_market_prices absent jusqu'à pre.006 refresh_all_market_prices absent jusqu'à pre.006 bouton Refresh par ligne implémenté clic refresh frontend debug, provider_id opaque uniquement IPC request/completion debug / trace via invokeKsp prix/payload/header/URL/API key dans les logs absent par contrat polling / scheduler consommateur absent ``` Validations sandbox après matérialisation : ```text python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... deltas PASS cargo fmt/check/clippy/test NOT RUN — cargo indisponible dans le sandbox ``` ## 21. Fix `0.2.12-pre.005-fix.001` Le gate opérateur de `pre.005` confirme que le runtime de refresh individuel fonctionne : ```text cargo fmt --all PASS python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py ... deltas/0.2.12 PASS cargo check --workspace PASS cargo test -p ksp-app-solprices-desk FAIL — canari desktop_security uniquement cargo tauri dev SOL Prices Desk PASS refresh individuel manuel PASS ``` L'unique échec est `pre_005_tauri_commands_remain_centralized_and_only_single_refresh_is_present`. Le test recherchait la chaîne `refresh_market_price` dans tous les fichiers Rust hors `tauri.rs`, ce qui classe à tort `AppState::refresh_market_price` comme plumbing Tauri alors que cette méthode est la frontière applicative appelée par la commande centralisée. Le correctif vérifie désormais la centralisation sur les marqueurs structurels Tauri : ```text #[tauri::command] hors tauri.rs interdit tauri::generate_handler! hors tauri.rs interdit méthode applicative refresh_market_price dans AppState autorisée refresh_market_prices toujours absent avant pre.006 refresh_all_market_prices toujours absent avant pre.006 runtime prix / frontend / providers inchangés ``` La version technique devient `0.2.12-pre.5.fix.1`. Le gate attendu doit confirmer le test ciblé puis le workspace complet avant d'ouvrir `pre.006`. ## 22. Gate `0.2.12-pre.006` Le gate opérateur de `pre.005-fix.001` fourni le 2026-08-27 confirme la fermeture de la tranche précédente : ```text cargo fmt --all PASS python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py ... deltas/0.2.12 PASS cargo check --workspace PASS cargo clippy --workspace --all-targets PASS cargo test -p ksp-app-solprices-desk PASS cargo test --workspace PASS ``` `pre.006` matérialise ensuite le batch manuel provider-neutral : ```text MarketPriceRefreshManyRequestDto implémenté, IDs opaques uniquement MarketPriceRefreshResultDto implémenté, rows + requested/refreshed counts refresh_market_prices implémenté via MarketPriceService::refresh_many refresh_all_market_prices implémenté via MarketPriceService::refresh_all ordre selected ordre courant des rows / requête conservé ordre all ordre stable provider-id du service in-flight backend validation atomique avant mutation doublon / ID inconnu rejet sûr avant état loading partiel mutex présentation pendant await non cooldown / retry_at projection Off-chain existante Refresh selected / Refresh all frontend implémentés logging clic sélection/selected/all debug, compte/ID opaque seulement logging résultat batch trace, requested/refreshed counts seulement polling / setInterval / scheduler / sleep consommateur absent fallback / consensus / moyenne absent ``` Validations sandbox après matérialisation : ```text python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... deltas PASS cargo fmt/check/clippy/test NOT RUN — cargo indisponible dans le sandbox ``` Le gate opérateur de `pre.006` fourni le 2026-08-27 ferme ensuite cette tranche : audits, `cargo check`, Clippy, test ciblé et `cargo test --workspace` passent, `cargo tauri dev` démarre correctement et le parcours manuel confirme que le multi-refresh fonctionne. Les lignes `refresh selected/many`, `refresh all`, les deux DTOs batch, l'ordre many, le rejet des doublons et le conflit `in_flight` passent donc à `PASS`. La borne hostile d'une requête batch artificiellement surdimensionnée reste volontairement `PENDING` pour le hardening `pre.009`. ## 23. Gate `0.2.12-pre.007` La tranche finalise l'UX et l'instrumentation sans modifier le moteur Off-chain ni ajouter de nouvelle commande métier : ```text résumé Providers / Ready / Observed / Attention / Refreshing implémenté header table sticky + scroll horizontal borné implémenté Semantics/Auth secondaires adaptatifs implémenté availability générique par badge implémenté prix exact String inchangée, aucune coercition float timestamp provider absent Not supplied, jamais remplacé par received_at timestamps présents local/ISO + millisecondes exactes visibles select all / clear selection frontend uniquement clics select-all / clear / row / selected / all / navigation debug rendu table + comptes sûrs trace échec command backend command + error_domain + error_code seulement nouvelle command IPC aucune prix/timestamp/payload/URL/header/API key dans les logs aucun auto-refresh / setInterval / setTimeout / requestAnimationFrame absent localStorage / sessionStorage / fetch / XMLHttpRequest absent ``` Canaris statiques ajoutés : table responsive et états génériques, absence de coercition du prix, instrumentation de tous les contrôles, projection sûre des erreurs backend et maintien du fonctionnement exclusivement manuel. Validations sandbox après matérialisation : ```text python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... deltas PASS TypeScript syntax transpile main.ts PASS cargo fmt/check/clippy/test NOT RUN — cargo indisponible dans le sandbox ``` Le gate opérateur du `27 août 2026` ferme `pre.007` : `cargo fmt --all`, audits Rust/Markdown, `cargo check --workspace`, Clippy workspace, `cargo test -p ksp-app-solprices-desk`, `cargo test --workspace` et `cargo tauri dev` passent. Le parcours visuel confirme la table finale avec 8 providers, états Ready/Disabled/Cooling down, observations distinctes, timestamps provider/KSP et les contrôles de refresh. ## 24. Gate `0.2.12-pre.008` — intégration Wallet minimale La décision opérateur réduit le besoin Wallet à une seule information auxiliaire liée au refresh de balance : ```text composite Wallet + offchain_transport/public_keyless implémenté ksp-app-wallet-desk -> ksp-offchain-transport-lib implémenté runtime Off-chain Wallet best-effort, erreur -> N.A. refresh_wallet_balance input inchangé getBalance + refresh_all lancés dans la même opération backend observations prises pour moyenne uniquement succès du refresh courant moyenne backend, aucune conversion f64, 8 décimales max WalletBalanceDto.sol_usd_average Option WalletBalanceDto.sol_usd_equivalent Option, calcul exact backend UI Wallet moyenne + équivalent dans Dashboard/Details, sinon N.A. provider_id / URL / credential / command prix dans frontend absent calcul de valorisation frontend / f64 absent WalletSession / VIEW / OWNER / secrets inchangés ``` Le runtime prix est auxiliaire : une indisponibilité Config/Off-chain ou zéro observation ne doit pas invalider une réponse `getBalance` réussie. Aucun état provider détaillé n'est dupliqué dans Wallet Desk ; l'inspection avancée reste dans SOL Prices Desk. Validations sandbox après matérialisation : ```text python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... deltas PASS TypeScript syntax transpile Wallet main.ts PASS cargo fmt/check/clippy/test NOT RUN — cargo indisponible dans le sandbox ``` ## 25. Gate `0.2.12-pre.008-fix.001` — correction compilation des canaris Le premier gate opérateur de `pre.008` a produit les résultats suivants : ```text cargo fmt --all FAIL — littéraux Rust invalides dans desktop_contract.rs python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... deltas PASS cargo check --workspace PASS cargo clippy --workspace --all-targets FAIL — desktop_contract.rs + manual_is_multiple_of ``` `pre.008-fix.001` corrige ces deux défauts mécaniques. Son gate opérateur du `27 août 2026` donne ensuite : ```text cargo fmt --all PASS python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... deltas PASS cargo check --workspace PASS cargo clippy --workspace --all-targets PASS cargo test -p ksp-app-wallet-desk FAIL — 1 canari desktop historique cargo test --workspace NOT RUN après l'échec ciblé cargo tauri dev Wallet Desk PASS ``` Le test ciblé passe `61` unit tests, `3` tests de composition et `18/19` tests `desktop_contract`. L'unique échec est : ```text pre_018_packaged_runtime_bundles_config_resources_and_keeps_wallet_desk_version_coherent assertion failed: main.contains(packaged_version) ``` Le runtime manuel confirme en parallèle que le chemin métier est opérationnel : ```text provider_count=8 observed_provider_count=6 average_available=true sol_usd_average_available=true getBalance succès cargo tauri dev succès ``` Deux écarts restent donc à corriger dans `pre.008-fix.002` : le badge principal est encore figé à `0.2.6`, et la vue Details ne montre pas l'information prix auxiliaire. La demande opérateur précise en outre que l'équivalent USD de la balance doit être visible. ## 26. Gate `0.2.12-pre.008-fix.002` — équivalent USD et version dynamique Le correctif attendu reste dans la responsabilité Wallet condensée de `pre.008` : ```text WalletBalanceDto.sol_usd_average conservé WalletBalanceDto.sol_usd_equivalent ajouté, Option source de l'équivalent lamports + moyenne du refresh courant calcul Rust/u128, aucun f64/f32/JS arrondi équivalent half-up, 8 décimales max prix auxiliaire indisponible moyenne N.A. + équivalent N.A. balance SOL autoritative inchangée Dashboard moyenne + équivalent Details moyenne + équivalent badge 0.2.6 statique supprimé version affichée RuntimeStatusDto.application_version canari packaging version-neutral, vérifie le binding dynamique provider_id / URL / credential / command prix Wallet absent ``` Gate opérateur à rejouer : ```bash cargo fmt --all python3 scripts/audit_rust_workspace_rules.py python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.2.12 cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-app-wallet-desk cargo test --workspace (cd crates/ksp-app-wallet-desk && cargo tauri dev) ``` ## 27. Gate `0.2.12-pre.008-fix.003` — correction finale du canari desktop Le gate opérateur de `pre.008-fix.002` confirme le comportement fonctionnel attendu : ```text Dashboard moyenne SOL/USD + équivalent USD visibles Details moyenne SOL/USD + équivalent USD visibles version affichée 0.2.12-pre.8.fix.2 refresh balance succès observed_provider_count 6 sol_usd_average_available true sol_usd_equivalent_available true ``` Le gate technique donne : ```text cargo fmt --all PASS python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... deltas PASS cargo check --workspace PASS cargo clippy --workspace --all-targets FAIL — desktop_contract.rs uniquement ``` La cause est purement syntaxique dans le canari version-neutral : ```text r#"setText("#appVersionBadge", status.applicationVersion);"# ``` Le délimiteur `"#` présent dans `"#appVersionBadge"` termine la raw string avant la fin du motif. `pre.008-fix.003` remplace ce motif par une chaîne Rust standard avec guillemets échappés. Aucun code runtime, frontend ou calcul financier n'est modifié. Gate opérateur à rejouer : ```bash cargo fmt --all python3 scripts/audit_rust_workspace_rules.py python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.2.12 cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-app-wallet-desk cargo test --workspace ``` ## 28. Gate `0.2.12-pre.009` — hardening transversal et gate final Le gate opérateur de `pre.008-fix.003` ferme définitivement la tranche Wallet condensée : ```text cargo fmt --all PASS python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... deltas PASS cargo check --workspace PASS cargo clippy --workspace --all-targets PASS cargo test -p ksp-app-wallet-desk PASS cargo test --workspace PASS ``` Le parcours fonctionnel avait déjà confirmé sous `fix.002` puis `fix.003` la moyenne SOL/USD, l'équivalent USD, la version dynamique et le refresh balance réel. `pre.009` ajoute les hardenings finaux suivants sans ouvrir de nouvelle fonctionnalité : ```text Price Desk batch IPC garde 1..=64 avant parsing des provider IDs batch vide rejet KSP sûr batch hostile 65 IDs rejet KSP sûr avant parsing provider Price Desk manual refresh aucun scheduler/fetch/browser persistence Price Desk version bundle Cargo autoritatif; Tauri config sans version Wallet version bundle Cargo autoritatif; Tauri config sans version Wallet frontendDist chemin Wallet dédié canarisé Wallet provider-neutrality aucun type provider concret dans src/ Wallet exactness aucun f64/f32 backend, aucun calcul flottant frontend keyless live composition nouveau smoke opt-in SOL Prices Desk ``` Le smoke live dédié est : ```bash cargo test -p ksp-app-solprices-desk --test market_price_composition_live_smoke -- --ignored --nocapture ``` Validations sandbox après matérialisation de la tranche : ```text python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... deltas PASS JSON package/tauri des deux apps modifiées PASS contrôles statiques versions/resources/frontières PASS cargo fmt/check/clippy/test/workspace opérateur PASS smoke live composition keyless opérateur PASS Wallet Desk cargo tauri build PASS — deb/rpm/AppImage SOL Prices Desk cargo tauri build FAIL — TS6133 fonction frontend inutilisée ``` Il doit résoudre le composite committed `public_keyless`, mapper `ResolvedOffchainTransportConfig`, conserver exactement les huit entrées génériques du registry, exécuter `MarketPriceService::refresh_all` et obtenir au moins une observation SOL/USD. Il ne réaudite pas les huit wire adapters individuellement. Gate opérateur final à exécuter, dans cet ordre : ```bash cargo fmt --all python3 scripts/audit_rust_workspace_rules.py python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.2.12 cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-app-solprices-desk cargo test -p ksp-app-wallet-desk cargo test --workspace cargo test -p ksp-app-solprices-desk --test market_price_composition_live_smoke -- --ignored --nocapture (cd crates/ksp-app-solprices-desk && cargo tauri build) (cd crates/ksp-app-wallet-desk && cargo tauri build) ``` Conformément à `KSP-APP-034`, les deux `cargo tauri build` restent les dernières opérations lourdes. ## 29. Fix `0.2.12-pre.009-fix.001` — build Price Desk et version Tauri Cargo-owned Le gate opérateur de `pre.009` est techniquement propre jusqu'aux builds finaux : ```text cargo fmt --all PASS audits Rust/Markdown PASS cargo check --workspace PASS cargo clippy --workspace --all-targets PASS cargo test -p ksp-app-solprices-desk PASS cargo test --workspace PASS market_price_composition_live_smoke PASS cargo tauri build — Wallet Desk PASS cargo tauri build — SOL Prices Desk FAIL ``` L'échec Price Desk est strictement frontend/build : ```text TS6133: appendMarketPriceCell is declared but its value is never read ``` La fonction n'est plus utilisée depuis le rendu UX de `pre.007`; elle est supprimée sans remplacement. Le même gate a conduit à supprimer le couplage artificiel des trois sources de version desktop. Le contrat retenu est : ```text workspace.package.version / Cargo package source de vérité KSP tauri.conf.json.version absent Tauri bundle version dérivée automatiquement de Cargo package.json manifest frontend privé, non autoritatif ``` Conséquence opérateur : un bump du workspace ne demande plus de modifier `tauri.conf.json` ou `package.json` d'une app hors scope. Les trois Desks utilisent le même contrat et leurs canaris vérifient l'absence de version Tauri dupliquée ainsi que `private: true` côté npm. Gate attendu après application : ```bash cargo fmt --all python3 scripts/audit_rust_workspace_rules.py python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.2.12 cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-app-solprices-desk cargo test --workspace cargo test -p ksp-app-solprices-desk --test market_price_composition_live_smoke -- --ignored --nocapture (cd crates/ksp-app-solprices-desk && cargo tauri build) ``` Le build Wallet n'a pas besoin d'être rejoué pour valider la correction TypeScript Price Desk, mais un build opportuniste reste autorisé pour confirmer le fallback Cargo sur une autre app. ## 30. Gate `0.2.12-pre.009-fix.001` — clôture technique complète Le gate opérateur final confirme la correction TypeScript et la nouvelle source de vérité de version desktop : ```text cargo fmt --all PASS python3 scripts/audit_rust_workspace_rules.py PASS python3 scripts/audit_markdown_tables.py README.md ... deltas PASS cargo check --workspace PASS cargo clippy --workspace --all-targets PASS cargo test -p ksp-app-solprices-desk PASS cargo test --workspace PASS market_price_composition_live_smoke PASS cargo tauri build — SOL Prices Desk PASS — deb/rpm/AppImage 0.2.12-pre.9.fix.1 cargo tauri build — Wallet Desk PASS — deb/rpm/AppImage 0.2.12-pre.9.fix.1 cargo tauri build — Config Desk PASS — deb/rpm/AppImage 0.2.12-pre.9.fix.1 ``` Le build Config est supplémentaire au gate minimal mais confirme le contrat `VER-ID-015/016` : son `package.json` reste à `0.2.6`, tandis que le bundle Tauri prend correctement `0.2.12-pre.9.fix.1` depuis Cargo sans champ `tauri.conf.json.version`. Le couloir technique/live/build est donc fermé. Aucun test réseau ou build Tauri supplémentaire n'est requis dans la réconciliation documentaire `pre.010`, sauf découverte d'une anomalie documentaire qui invaliderait une preuve technique. ## 31. Réconciliation `0.2.12-pre.010` — documents durables La réconciliation finale doit figer les documents durables avant la tranche de publication minimale : ```text SOL Prices Desk README final provider-neutral/manual refresh SOL Prices Desk USAGE guide opérateur créé Wallet Desk README/USAGE moyenne SOL/USD + équivalent USD documentés architecture Component Contracts Price Desk actuel + moyenne consumer-owned architecture Component Inventory Off-chain/Price Desk stables pour 0.2.11/0.2.12 architecture Dependency Graph Wallet -> Off-chain Transport explicite architecture Apps/Services Price Desk et dépendances directes explicites Functional Release Sequence scope réel 0.2.12 réconcilié docs/000-README candidate 0.2.12 récapitulée plan 019 / validation 015 gates réels et fermeture séparée ``` Conformément à `PROMPT_STRUCTURE.md`, `CHANGELOG.md`, `ROADMAP.md` et le prompt `0.2.13` restent intacts dans `pre.010`. Ils appartiennent exclusivement à `pre.011`.