# Validation v0.3.7 — Backfill Desk ## 1. Gate pre.001 - [X] Archive KSP v0.3.6 testée intégralement avant travail. - [X] Archive kbot3 testée intégralement et extraite dans un arbre séparé. - [X] Aucune entrée ZIP absolue, traversal, séparateur inversé ou lien symbolique détecté. - [X] `workspace.package.version = 0.3.6` confirmé sur la base. - [X] `deltas/0.3.6/rel.001.md` confirmé. - [X] `ksp-job-api`, `ksp-job-backfill-lib` et les trois Desks existants confirmés. - [X] Règles générales, Rust, dépendances, documentation, file contracts, version workflow et prompt structure relus. - [X] Architectures Layers/Dependencies/Components/Jobs/Apps relues. - [X] README/USAGE/plan/validation/delta v0.3.6 relus. - [X] Surfaces publiques Job/Backfill auditées depuis le code stable. - [X] Config composite/Transport/Store audités. - [X] Gabarits Config Desk, Wallet Desk et SOL Prices Desk audités. - [X] Ports 1436/1437 confirmés libres dans les gabarits existants ; 1434/1435 appartiennent à SOL Prices. - [X] kbot3 audité uniquement comme référence fonctionnelle/UX. - [X] Matrice REPRENDRE/REDESSINER/REPORTER/REJETER produite. - [X] Screen map, DTO/command map, Config/composition map et dependency map produits. - [X] Threat model produit. - [X] Single-run lifecycle, rôle HTTP, validation réseau et reprise in-session tranchés. - [X] Gate Tauri/live tranché sans dépendance payante obligatoire. - [X] Forecast scindé afin d'éviter une tranche Transport+Store manifestement trop large. - [X] Aucun scaffold Tauri, code Rust/TS/HTML ou composite runtime ajouté en pre.001. ## 2. Preuve des archives | Source | SHA-256 | Résultat | Usage | |-----------------------------------------------------------|--------------------------------------------------------------------|---------------------------|--------------------------------| | `khadhroony-solana-project-v0.3.6.zip` | `90eceb9fd28d87e580e3881cdd3eda935784532caac07d0ba3fb845be664c845` | 1 594 entrées, ZIP propre | source exclusive de code | | `khadhroony-bot3_v0.5.3-pre.005-fix010-thelatest1(2).zip` | `ee47643b9f8b582ee8db97b2381ec107e45aef8c009fee44757531514615d318` | 2 501 entrées, ZIP propre | référence fonctionnelle isolée | | `Texte collé(20260901-220002).txt` | `f70930be652d2532e2403f01227af9870fd31ec0603e64ddadca4a44d910d8cc` | journal opérateur | preuve externe baseline v0.3.6 | Le journal opérateur fourni rapporte `cargo clean`, `cargo fmt`, audits Rust/Markdown, `cargo check --workspace`, Clippy, suites ciblées de toutes les crates, arbres Job/Backfill et `cargo tree --duplicates` sur v0.3.6. Cette preuve est conservée comme externe ; elle n'est pas assimilée à une exécution locale de pre.001. ## 3. Baseline locale - [X] `python3 scripts/audit_rust_workspace_rules.py` : propre, zéro candidat d'export. - [X] `python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas` : 295 tables / 652 fichiers propres avant modification. - [ ] `cargo fmt --all` : non exécuté localement, exécutable `cargo` absent. - [ ] `cargo check --workspace` : non exécuté localement, exécutable `cargo` absent. - [ ] `cargo clippy --workspace --all-targets` : non exécuté localement, exécutable `cargo` absent. ## 4. Surface KSP acquise à préserver - [X] `BackfillRequest` reste l'autorité des bornes et de la cohérence des scopes. - [X] Latest/Before/After/Explicit restent les seuls scopes V1. - [X] `BackfillJobRuntime` reste single-run. - [X] `BackfillJobHandle` reste la primitive de contrôle. - [X] `BackfillSnapshotSource` latest-value reste la primitive d'observation. - [X] `BackfillCheckpoint` reste opaque et Rust-only. - [X] Transport reste propriétaire retry/reroute/rate-limit/provider/endpoint. - [X] Store reste propriétaire backend/persistence/idempotence. - [X] Config reste propriétaire documents/env/secrets/composites. ## 5. Décisions de composition - [X] Composite dédié `config/composite.ksp-app-backfill-desk.json` prévu. - [X] Profils `devnet`, `mainnet`, `testnet` prévus avec couples Transport/Store de même réseau. - [X] Default final : `mainnet` depuis `pre.006`; Devnet/Testnet restent disponibles par reconfiguration du composite. - [X] Aucun `std.job_backfill.json` en V1. - [X] Les rôles sont dérivés de Transport et validés pour `getSignaturesForAddress` + `getTransaction`. - [X] Aucun rôle `history_backfill` n'est hardcodé ; `pre.006` expose les rôles logiques `backfill_pool`, `backfill_solana_public` et `backfill_publicnode` depuis Transport. - [X] Une incohérence réseau est rejetée avant Start. - [X] Le Desk ouvre Store via `ksp-store-lib`, jamais via backend direct. ## 6. Contrat IPC prévu - [X] DTO applicatifs spécifiques au Desk ; aucune contrainte serde/TS-RS ajoutée aux crates Job. - [X] Options DTO : réseau sûr, rôles, commitments, scopes, bornes, readiness. - [X] Request DTO : inputs campagne uniquement. - [X] Status DTO : lifecycle/phase/boundary/compteurs/checkpoint-present/contiguous/failure code. - [X] Cancel/Resume responses sûres. - [X] Aucun checkpoint opaque, Store, Transport, channel Tokio, URL, secret ou RAW payload ne traverse IPC. - [X] Monitoring prévu via latest-value + événement Tauri, avec commande status de resynchronisation. ## 7. Threat model - [X] URI Store et secrets Config restent backend-only. - [X] Endpoint URLs/provider credentials restent backend-only. - [X] Signatures et adresse ne sont pas loggées côté frontend. - [X] RAW transaction data n'est pas projetée. - [X] Bornes et signatures sont revalidées côté Rust. - [X] Double Start est rejeté atomiquement. - [X] Cancel/terminal race est résolue par lifecycle réel et handle installé avant spawn. - [X] Checkpoint frontend forgé impossible : aucun checkpoint n'est sérialisé. - [X] Capabilities Tauri prévues minimales : core + tracing seulement tant qu'aucun autre besoin n'est démontré. ## 8. Gates futures - [X] Package Rust lib + bin conforme. - [X] Ports Vite/HMR 1436/1437 stricts. - [X] Splash/main + tracing conformes. - [X] Composite Backfill Desk packagé et valide. - [X] Transport readiness et role inventory sûrs. - [X] Store readiness et cohérence réseau. - [X] Quatre scopes + commitments + bornes mappés. - [X] Single active run + Start. - [X] Snapshot latest-value bridge. - [X] Cancel + races terminales. - [X] Checkpoint/frontier projection + Resume in-session. - [X] Frontend/security/composition tests verts. - [X] `cargo test --workspace --all-targets --all-features` final vert. - [X] `(cd crates/ksp-app-backfill-desk && cargo tauri build)` final vert. - [X] Smokes Mainnet opérateur antérieurs suffisants ; aucun nouveau smoke final requis. - [X] Réconciliation README/USAGE/plan/validation/architecture dans `pre.016`. - [ ] Prompt 0.3.8 + CHANGELOG + ROADMAP uniquement dans la lane de publication. ## 9. pre.002 — scaffold desktop Le scaffold `ksp-app-backfill-desk` matérialise le gabarit Desk avant toute ouverture Transport/Store/Backfill : lib+bin, verrou single-instance, Config/Logging standard transitoire, splash commun, bridge Logging frontend, shell `Backfill / Diagnostics`, ports 1436/1437 et capabilities `core:default + tracing:default`. Contraintes de gabarit vérifiées statiquement : mêmes assets splash/logo/DOS Amazigh que les trois Desk existantes, corps des cinq fichiers SASS partagés identique à SOL Prices Desk, splash HTML/SCSS identique hors identité Backfill et métadonnées de fichier, shell commun `header + sidebar + content + footer`, dépendances frontend minimales `@fltsci/tauri-plugin-tracing`, Font Awesome, Tauri API, Bootstrap, ResizeObserver polyfill et SimpleBar, plus les mêmes `devDependencies` que les trois Desk. Les clics, tabs, transitions de vue, refresh diagnostic et IPC sont instrumentés sans payload Backfill, adresse, signature, endpoint ou secret. ### Gate statique local - [X] audit Rust workspace propre, zéro candidat d'export ; - [X] audit Markdown propre : 270 tableaux / 149 fichiers ; - [X] 4 manifests JSON et 2 manifests TOML parsés ; - [X] 6 dépendances frontend minimales aux versions du gabarit ; - [X] `devDependencies` strictement identiques dans Config Desk, Wallet Desk, SOL Prices Desk et Backfill Desk ; - [X] 5 assets binaires strictement identiques dans les quatre Desk ; - [X] 5 fichiers SASS partagés identiques à SOL Prices Desk hors header de propriété ; - [X] splash commun et shell sidebar contrôlés ; - [X] capabilities `core:default + tracing:default` seulement ; - [X] aucune dépendance Transport/Store/Backfill ouverte en `pre.002` ; - [X] audit frontend interaction/security propre ; - [X] audit syntaxique TypeScript propre sur 5 fichiers ; - [X] diff `pre.001 -> pre.002` borné à 46 ajouts, 3 modifications et aucune suppression ; - [ ] `cargo fmt/check/clippy/test` : non exécutés, `cargo`/`rustfmt` absents du sandbox ; - [ ] typecheck npm complet / build Tauri : non exécutés dans le sandbox. Le contrôle TypeScript local est syntaxique avec le compilateur global disponible ; il ne remplace pas le typecheck complet avec dépendances npm et bindings TS-RS générés. Toute correction révélée par le gate opérateur reste dans la lane `pre.002-fix.NNN`. ## 10. pre.003 — composite Config et packaging Le composite `cfg.composite.ksp-app-backfill-desk` est enregistré dans `ksp-config-lib` avec `devnet` par défaut. Il sélectionne `supertrace + devnet_public + devnet`, tandis que `mainnet` et `testnet` conservent des couples Transport/Store cohérents. Le bootstrap Backfill Desk valide les trois composants requis mais ne résout encore que Logging : aucun `HttpTransportPool`, `Store::open`, `BackfillRequest` ou `BackfillJobRuntime` n'est ouvert dans cette tranche. Le niveau de développement est volontairement verbeux pour cette application : `devnet` utilise `supertrace`, et le fallback Logging propre à Backfill Desk utilise `LogFilterLevel::Trace`. Les autres applications Desk ne changent pas de profil Logging. La découverte du contrat réel de `prepare_packaged_runtime()` a réconcilié le plan : la fonction traverse tout `ConfigFileRegistry::defaults()`. Le registre compte désormais 14 descriptors, de sorte que Config Desk, Wallet Desk, SOL Prices Desk et Backfill Desk embarquent toutes les 14 resources Config/schema. Les documents Wallet/offchain présents dans le bundle Backfill ne sont pas consommés par son runtime et n'élargissent ni ses capabilities ni ses dépendances Rust. ### Gate pre.002 opérateur acquis - [X] audits Rust et Markdown propres ; - [X] `cargo check --workspace` propre ; - [X] `cargo clippy --workspace --all-targets` propre ; - [X] `cargo test -p ksp-app-backfill-desk` : 12 unitaires + 5 desktop contract + 4 desktop security + 1 public API, aucun échec. ### Gate statique local pre.003 - [X] composite Backfill Desk ajouté au source Config et aux fixtures Config ; - [X] registre Config porté à 14 descriptors avec exports publics associés ; - [X] profils `devnet/mainnet/testnet` et références Logging/Transport/Store couplés conformément au plan ; - [X] les quatre `tauri.conf.json` Desk embarquent le registre Config complet de 14 resources ; - [X] release packaging Backfill Desk appelle `prepare_packaged_runtime()` avant l'initialisation applicative ; - [X] bootstrap Backfill valide Logging/Transport/Store puis ne résout que Logging ; - [X] niveau de développement Backfill Desk verrouillé à `supertrace` via Config et `trace` en fallback ; - [X] aucune dépendance `ksp-job-backfill-lib`, `ksp-onchain-transport-lib`, `ksp-store-lib` ou backend Store ajoutée au manifeste Backfill Desk ; - [X] audit Rust workspace propre, zéro candidat d'export ; - [X] audit Markdown propre : 270 tableaux / 150 fichiers ; - [X] parsing JSON/TOML, validation JSON Schema et audit structurel Config/package propres ; - [X] gate opérateur `pre.003` exécuté le 2026-09-02 : **FIX REQUIRED** ; `cargo check --workspace` passe, mais l'audit Rust, Clippy, Config Desk et un canari Backfill Desk isolent quatre défauts locaux détaillés ci-dessous. ## 11. Correctif `pre.003-fix.001` Le gate opérateur de `pre.003` a isolé quatre défauts qui appartiennent tous au couloir Config/composition de `pre.003` : - `RUST-FMT-104` dans `src/errors.rs` : `ERROR_CODE_CONFIG_COMPOSITE_INVALID` précédait les constantes `ERROR_CODE_APP_STATE_*` ; le bloc est remis dans l'ordre alphabétique sans changer aucune valeur ; - Clippy `implicit_return` dans `tests/desktop_contract.rs` : la closure qui lit `bundle.resources` utilise désormais un `return` explicite, conformément aux lints workspace ; - la fixture `composite.ksp-app-backfill-desk.json` reprenait les profils de production (`supertrace`, `devnet_public`, `mainnet_public`, `publicnode_testnet`) alors que les fixtures réduites Logging/Transport n'exposent que `local_dev` et `secret_test` pour ces besoins ; comme les fixtures Wallet/SOL Prices existantes, la fixture Backfill utilise donc les profils disponibles du corpus de test, sans modifier le composite de production ; - `tests/desktop_security.rs` attendait littéralement `ksp-config-lib.workspace = true`, alors que les Desk KSP déclarent leurs dépendances internes par chemin local ; le canari vérifie désormais la forme réelle `ksp-config-lib = { path = "../ksp-config-lib" }` et conserve les interdictions des couches Transport/Store/Backfill. Le correctif ne modifie ni le profil `supertrace` de production, ni les 14 resources packagées, ni le bootstrap runtime, ni les capabilities Tauri, ni les dépendances fonctionnelles de Backfill Desk. La version Cargo devient `0.3.7-pre.3.fix.1` conformément à `VER-ID-007` et `VER-ID-010`, car le correctif touche des fichiers Rust compilés. ### Gate opérateur ayant déclenché le fix ```text cargo fmt --all exécuté python3 scripts/audit_rust_workspace_rules.py FAIL — 1 x RUST-FMT-104 python3 scripts/audit_markdown_tables.py ... deltas/0.3.7 PASS cargo check --workspace PASS cargo clippy --workspace --all-targets FAIL — implicit_return dans desktop_contract.rs cargo test -p ksp-config-lib PASS — 128 tests unitaires + suites associées cargo test -p ksp-app-config-desk FAIL — fixture Backfill / profil supertrace absent cargo test -p ksp-app-wallet-desk PASS cargo test -p ksp-app-solprices-desk PASS cargo test -p ksp-app-backfill-desk FAIL — canari Cargo.toml obsolète ``` ### Gate du fix - [X] audits statiques Rust/Markdown rejoués dans l'environnement d'assemblage ; - [X] replay opérateur du 2026-09-02 : audits Rust/Markdown propres, `cargo check --workspace` propre, Clippy propre ; - [X] `cargo test -p ksp-config-lib` : 128 tests unitaires + suites ownership/public API, aucun échec ; - [X] `cargo test -p ksp-app-config-desk` : 63 tests unitaires + desktop/security/public API, aucun échec ; - [X] `cargo test -p ksp-app-wallet-desk` et `cargo test -p ksp-app-solprices-desk` : suites ciblées propres ; - [X] `cargo test -p ksp-app-backfill-desk` : 13 unitaires + 2 composition + 7 desktop contract + 5 desktop security + 1 public API, aucun échec ; - [X] arbres `cargo tree` Backfill Desk exécutés sans anomalie rapportée. ## 12. `pre.004` — Transport readiness Backfill Desk dépend désormais directement de `ksp-onchain-transport-lib` au niveau backend uniquement. `initialize_transport()` résout le profil Transport déjà sélectionné par le composite, construit `HttpTransportPool`, dérive les clusters HTTP activés et déduplique les rôles logiques à partir des snapshots sûrs. Chaque rôle candidat doit réussir `select_for_method()` pour `getSignaturesForAddress` **et** `getTransaction` avant d'être exposé comme compatible. Le sous-contrat `BackfillDeskOptionsDto` expose uniquement : réseaux configurés, rôles compatibles, readiness Transport et diagnostic applicatif sûr. Il ne contient ni provider, URL, endpoint physique, token, checkpoint, payload RAW ou objet Transport. La commande Tauri `backfill_options` est centralisée dans `tauri.rs`. Les scopes, commitments et bornes restent hors de cette tranche et seront ajoutés en `pre.007` après la stabilisation du routage HTTP de `pre.006`. Une seule network distincte et au moins un rôle compatible sont requis pour `transport_ready = true`. Une erreur Config/Transport n'empêche pas le shell de démarrer : elle produit une options projection non-ready avec `CommandErrorDto`, tandis que le pool n'est pas conservé. La cohérence avec le réseau Store reste explicitement réservée à `pre.005`. ### Gate statique local `pre.004` - [X] dépendance `ksp-onchain-transport-lib` ajoutée à Backfill Desk ; - [X] aucune dépendance `ksp-store-lib`, `ksp-store-api`, `ksp-store-postgres-lib` ou `ksp-job-backfill-lib` ajoutée ; - [X] `HttpTransportPool` construit uniquement dans `transport_runtime.rs`, pas dans le bootstrap Config/Logging ; - [X] inventaire des clusters dérivé sans URL/provider ; - [X] rôles candidats dédupliqués et vérifiés sur les deux RPC requis ; - [X] le profil standard `devnet_public` possède un unique cluster `devnet` et le rôle wildcard `default` ; - [X] capabilities Tauri inchangées : `core:default + tracing:default` ; - [X] tracing de développement Backfill inchangé : Config `supertrace`, fallback `trace` ; - [X] audit Rust workspace local propre, zéro candidat d'export ; - [ ] `cargo fmt/check/clippy/test` de `pre.004` à rejouer par l'opérateur ; `cargo`/`rustfmt` restent absents du sandbox. ## 13. `pre.005` — Store readiness et cohérence réseau ### Gate opérateur `pre.004` acquis - [X] audits Rust/Markdown propres ; - [X] `cargo check --workspace` propre ; - [X] `cargo clippy --workspace --all-targets` propre ; - [X] `cargo test -p ksp-app-backfill-desk` : 17 unitaires + 3 composition + 8 desktop contract + 5 desktop security + 1 public API, aucun échec ; - [X] arbres `cargo tree` Backfill Desk exécutés sans anomalie rapportée ; - [X] `cargo tauri dev` démarre le shell sur le profil Logging `supertrace` et le profil Transport `devnet_public` ; - [X] le runtime réel rapporte un seul réseau, un rôle compatible et `transport_ready = true` ; - [X] les changements de tabs sont visibles dans le tracing frontend `DEBUG`. ### Gate statique local `pre.005` - [X] dépendance directe `ksp-store-lib` ajoutée à Backfill Desk ; - [X] aucune dépendance directe `ksp-store-api`, `ksp-store-postgres-lib`, `ksp-job-backfill-lib`, `reqwest` ou `tokio-postgres` ajoutée ; - [X] le réseau Store est dérivé des settings Config résolus et comparé au réseau Transport unique avant `Store::open` ; - [X] une incohérence ou l'absence de réseau Transport cohérent empêche l'ouverture Store ; - [X] `Store::health()` est exécuté une fois après ouverture et sa projection reste backend-neutre ; - [X] `BackfillDeskOptionsDto` expose seulement réseau Store, `network_coherent`, `store_ready`, `composition_ready` et diagnostics sûrs en plus du sous-contrat Transport ; - [X] aucune URI PostgreSQL, URL Transport, identité provider, credential ou objet Store n'est projeté vers l'IPC ; - [X] le `Store` est détenu côté Rust derrière une fermeture one-shot et `Store::close()` ; - [X] la fermeture de la fenêtre principale est interceptée pour exécuter le close Store borné avant la sortie applicative ; - [X] capabilities Tauri inchangées : `core:default + tracing:default` ; - [X] tracing de développement Backfill inchangé : Config `supertrace`, fallback `trace` ; - [X] aucun `BackfillRequest`, `BackfillJobRuntime`, Start/Cancel/Resume n'est ouvert ; - [X] audit Rust workspace local propre, zéro candidat d'export ; - [ ] `cargo fmt/check/clippy/test` de `pre.005` à rejouer par l'opérateur ; `cargo`/`rustfmt` restent absents du sandbox. ## 14. Correctif `pre.005-fix.001` Le gate opérateur de `pre.005` confirme que les audits Rust/Markdown, `cargo check --workspace` et Clippy sont propres, puis isole un seul échec déterministe dans `tests/config_composition.rs` : le canari de cohérence réseau essayait de mapper intégralement le profil Transport `publicnode_testnet`, ce qui résout aussi son endpoint Yellowstone gRPC et exige donc `KSP_SECRET_PUBLICNODE_TESTNET_GRPC_X_TOKEN` même si le test ne vérifiait que l'identité du réseau HTTP. Le correctif ne modifie aucun runtime, aucun composite Config, aucun profil Transport/Store et aucune capability. Le canari lit désormais uniquement les champs non secrets déjà validés des profils composés : clusters des endpoints HTTP activés et réseau logique Store. Les tests runtime unitaires restent responsables de la comparaison effective avant `Store::open`, tandis que les tests Config/Transport propriétaires couvrent séparément la résolution des secrets gRPC. ### Gate du fix - [X] correction strictement limitée au couloir Store/composition de `pre.005` ; - [X] aucune modification du composite de production ni des settings Transport/Store ; - [X] aucun secret provider requis par le test déterministe de cohérence réseau ; - [X] audits statiques Rust/Markdown rejoués dans l'environnement d'assemblage ; - [X] replay opérateur `cargo fmt/check/clippy/test` de `pre.005-fix.001` propre. La décision utilisateur de faire de Mainnet le profil Backfill par défaut et de tester plusieurs familles de transport Backfill (HTTP standard, HTTP provider tel que Helius, Yellowstone gRPC ; WebSocket exclu de V1 sauf besoin démontré) appartient à des couloirs Config/Transport antérieurs. Conformément à `VER-LIFECYCLE-010`, elle n'est pas introduite dans ce fix et doit ouvrir une prerelease dédiée après validation du correctif. ## `0.3.7-pre.006` — Mainnet par défaut et routage HTTP opérateur La décision post-`pre.005` est appliquée dans une nouvelle tranche dédiée : le composite Backfill Desk utilise `mainnet` par défaut, avec Logging `supertrace` pendant le développement et un profil Transport `mainnet_backfill_pool`. Ce profil expose deux endpoints HTTP sans secret obligatoire au démarrage : Solana Public et PublicNode. Trois rôles logiques sont proposés : `backfill_pool` pour le pool multi-provider, `backfill_solana_public` et `backfill_publicnode` pour le ciblage explicite. L'IPC expose uniquement le rôle et les labels provider sûrs ; aucune URL ni credential. Le frontend charge `backfill_options()` au démarrage, rend le sélecteur et trace le changement de route. Aucun Start n'est ajouté dans cette tranche. Le support Yellowstone gRPC de `ksp-job-backfill-lib`/Backfill Desk est retiré du périmètre `0.3.7` et reporté à une version ultérieure (`0.3.12+` comme cible indicative). WebSocket reste hors Backfill V1. ### Gate `pre.006` - [X] Mainnet est le profil composite par défaut et conserve `supertrace` pendant le développement ; - [X] le profil `mainnet_backfill_pool` expose Solana Public + PublicNode en HTTP avec rôles pool/ciblés ; - [X] aucun endpoint gRPC n'est introduit dans ce profil ; - [X] l'IPC expose uniquement rôle logique et labels provider sûrs ; - [X] le frontend charge/rend le sélecteur et trace son changement ; - [X] aucun Start ni dépendance `ksp-job-backfill-lib` n'est ouvert par la Desk ; - [X] audits statiques Rust/Markdown, JSON Schema et syntaxe TypeScript propres dans l'environnement d'assemblage ; - [X] replay opérateur `cargo fmt/check/clippy/test` de `pre.006` exécuté ; un fix Clippy strictement local a été requis puis traité. ## Correctif `pre.006-fix.001` Le gate opérateur de `pre.006` confirme que les audits Rust/Markdown et `cargo check --workspace` sont propres, puis Clippy isole trois closures de `tests/config_composition.rs` qui violaient `clippy::implicit_return`. Les tests exécutés après cet arrêt restent propres, mais le gate global est bloqué tant que Clippy échoue. Le correctif reste strictement dans la responsabilité de `pre.006` : il ajoute uniquement les `return` explicites exigés par les lints workspace dans le canari Mainnet/pool HTTP. Aucun profil Config, rôle Transport, DTO, frontend, runtime Store/Transport ou contrat Job n'est modifié. ### Gate du fix - [X] trois closures `filter_map`/`flat_map` utilisent désormais un `return` explicite ; - [X] aucun contenu fonctionnel de `pre.006` n'est modifié ; - [X] version Cargo synchronisée en `0.3.7-pre.6.fix.1` conformément à `VER-ID-007` et `VER-ID-010` ; - [X] audits statiques Rust/Markdown rejoués dans l'environnement d'assemblage ; - [X] replay opérateur `cargo fmt/check/clippy/test` du fix propre : audits, check, Clippy, Config et toutes les suites Backfill Desk passent. ## 15. `pre.007` — DTO et mapping de requête Le replay opérateur de `pre.006-fix.001` est acquis : audits Rust/Markdown propres, `cargo check --workspace` et Clippy propres, `ksp-config-lib` intégralement vert, puis Backfill Desk vert sur ses 21 tests unitaires, 5 tests de composition, 10 desktop contract, 6 desktop security et 1 public API. Les arbres Cargo ont également été exécutés sans anomalie rapportée. `pre.007` ouvre `ksp-job-api` et `ksp-job-backfill-lib` uniquement pour construire et valider le contrat de requête. `BackfillStartRequestDto` reste app-owned et ne transporte ni network, provider, endpoint, URL, credential, checkpoint ou JobId. Le backend dérive le réseau depuis le Store déjà composé et refuse tout `http_role` absent de l'inventaire sûr courant. Le formulaire expose les quatre scopes HTTP V1 (`latest_address`, `before_address`, `after_address`, `explicit_signatures`), `finalized`/`confirmed`, les quatre bornes numériques et `min_context_slot`. Ce dernier traverse l'IPC comme texte décimal afin d'éviter toute perte de précision JavaScript avant parsing `u64` côté Rust. Les maxima proviennent exclusivement des constantes publiques de `ksp-job-backfill-lib`; les defaults de Desk restent strictement inférieurs ou égaux à ces maxima. La commande `backfill_validate_request` construit un JobId interne uniquement pour satisfaire le contrat `BackfillRequest`, applique le même mapping qui sera réutilisé par Start, puis renvoie une `BackfillRequestPreviewDto` sûre. La preview contient le réseau, le rôle logique, commitment/scope, bornes et seulement présence/comptage pour les valeurs sensibles. Aucun Job n'est créé ni lancé dans cette tranche. ### Gate statique local `pre.007` - [X] dépendances directes `ksp-job-api` et `ksp-job-backfill-lib` ajoutées à Backfill Desk ; - [X] aucune dépendance directe backend Store, `reqwest`, `tonic` ou Yellowstone ajoutée ; - [X] request DTO sans network/provider/endpoint/URL/JobId ; - [X] réseau dérivé du Store configuré et rôle HTTP revalidé contre l'inventaire courant ; - [X] quatre scopes et deux commitments mappés explicitement ; - [X] `min_context_slot` transporté comme texte puis parsé en `u64` côté Rust ; - [X] bornes maxima dérivées des constantes publiques Job et defaults applicatifs vérifiés ; - [X] preview sûre sans adresse ni signature ; - [X] formulaire frontend + validation backend disponibles, sans bouton Start ni `BackfillJobRuntime` ; - [X] instrumentation frontend limitée aux codes/rôle/scope et métadonnées de contrôle ; - [X] capabilities Tauri inchangées : `core:default + tracing:default` ; - [ ] `cargo fmt/check/clippy/test` de `pre.007` à rejouer par l'opérateur ; `cargo`/`rustfmt` restent absents du sandbox. ## 16. Correctif `pre.007-fix.001` Le gate opérateur de `pre.007` confirme que les audits Rust/Markdown et `cargo check --workspace` sont propres et que `ksp-job-backfill-lib` passe intégralement ses suites. Le blocage est limité au test unitaire Backfill Desk `explicit_signatures_reject_address_context_and_deduplicate_in_job_contract` : une variable locale nommée `job_id` masquait le helper `job_id()`, rendant l'appel suivant illégal au compile-time. Le correctif renomme uniquement cette variable locale en `request_job_id`. Aucun code de production, DTO, mapping `BackfillRequest`, formulaire frontend, runtime Transport/Store ou contrat Job n'est modifié. ### Gate du fix - [X] shadowing `job_id` supprimé dans le test concerné ; - [X] aucun fichier fonctionnel de `pre.007` modifié ; - [X] version Cargo synchronisée en `0.3.7-pre.7.fix.1` conformément à `VER-ID-007` et `VER-ID-010` ; - [X] audits statiques Rust/Markdown rejoués dans l'environnement d'assemblage ; - [X] replay opérateur `cargo fmt/check/clippy/test` du fix propre : audits, check, Clippy, `ksp-job-backfill-lib` et toutes les suites Backfill Desk passent. ## 17. `pre.008` — runtime et Start réel Le replay opérateur de `pre.007-fix.001` est acquis. `pre.008` ouvre l'exécution réelle sans modifier le contrat de requête : `backfill_start` réutilise `map_backfill_request`, génère le `JobId` côté backend, construit `BackfillJobRuntime`, capture son `BackfillJobHandle` puis installe ce handle dans un slot single-active-run avant le spawn Tauri. Un second Start est rejeté par `backfill_run_active`. Le pool HTTP est clonable et reste possédé par Transport. Le Store backend-neutre, non clonable, est temporairement retiré de son slot applicatif pour être déplacé dans le task du run ; après terminal, il est restauré avant libération du slot actif. La réponse IPC Start contient uniquement `job_id` et l'état initial `created`. Le monitoring détaillé, les événements latest-value et la projection terminale restent réservés à `pre.009`. Cancel et la fermeture coopérative d'un run actif restent réservés à `pre.010`. La note UX ajoutée pendant cette tranche est reportée à `pre.012` : l'input adresse restera libre mais utilisera un `datalist` HTML construit depuis le registre canonique `ksp-core-lib::entries()`/`ProgramIdEntry`, sur le principe fonctionnel de l'ancien `ks-program-ids` de kbot3 sans en reprendre le code. ### Gate statique local `pre.008` - [X] `BackfillJobRuntime::new` est appelé uniquement après le mapping autoritaire `pre.007` ; - [X] `BackfillJobHandle` est obtenu et installé dans le slot actif avant `tauri::async_runtime::spawn` ; - [X] admission single-run atomique avec erreur stable `backfill_run_active` ; - [X] JobId généré côté backend, jamais reçu du frontend ; - [X] pool HTTP cloné depuis `TransportRuntime`, sans URL/provider physique supplémentaire ; - [X] Store temporairement prêté au run puis restauré après terminal ; - [X] `BackfillStartResponseDto` limité à `job_id` + état initial ; - [X] frontend conserve le bouton de validation et ajoute un bouton Start distinct, activé seulement si `composition_ready` ; - [X] aucune adresse, signature, ancre ou `min_context_slot` ajoutée aux logs Start ; - [X] capabilities Tauri inchangées : `core:default + tracing:default` ; - [X] audits statiques Rust/Markdown propres dans l'environnement d'assemblage ; - [ ] `cargo fmt/check/clippy/test` de `pre.008` à rejouer par l'opérateur ; `cargo`/`rustfmt` restent absents du sandbox. ## 18. Correctif `pre.008-fix.001` — futures Job Backfill `Send` Le gate opérateur de `pre.008` confirme que les audits Rust/Markdown sont propres, puis `cargo check --workspace` bloque l'intégration Tauri du Start : `tauri::async_runtime::spawn` exige une future `Send + 'static`, alors que deux alias privés de `ksp-job-backfill-lib` effaçaient la propriété `Send` des futures discovery et candidate-processing. `StoreApiFuture` était déjà `Send`; le défaut se trouvait uniquement dans `SignaturePageFuture` et `CandidateProcessFuture`. Le correctif ajoute `std::marker::Send` à ces deux objets future privés et verrouille ce contrat par deux canaries compile-time dédiées. ### Gate du fix - [X] `SignaturePageFuture` impose `Future + Send` ; - [X] `CandidateProcessFuture` impose `Future + Send` ; - [X] canary discovery compile-time `Send` ajoutée ; - [X] canary execution compile-time `Send` ajoutée ; - [X] aucune API publique Job, logique de requête, Start Desk, Store, Transport ou frontend n'est modifiée ; - [X] audits statiques Rust/Markdown rejoués dans l'environnement d'assemblage ; - [ ] replay opérateur `cargo fmt/check/clippy/test` de `pre.008-fix.001` à exécuter. ## 19. `pre.008-fix.002` — canari d'ordre Start local au bon spawn Le replay opérateur de `pre.008-fix.001` confirme que la correction `Send` est effective : audits, `cargo check --workspace`, Clippy et `ksp-job-backfill-lib` passent. La suite Backfill Desk atteint alors le canari `pre_008_start_installs_handle_before_non_blocking_spawn_and_keeps_single_run_backend_owned`, qui échoue sur `prepare_index < spawn_index`. La production respecte pourtant l'invariant : `AppState::prepare_backfill_start` construit le runtime, récupère son handle, installe le slot single-run, acquiert Transport/Store puis retourne `BackfillRunLaunch`; ensuite seulement la commande Tauri `backfill_start` appelle `tauri::async_runtime::spawn`. Le défaut vient du test, qui utilisait `tauri.find("tauri::async_runtime::spawn(async move")` sur tout `src/tauri.rs` et capturait ainsi le spawn antérieur du shutdown Store. Le fix rend le canari contextuel : après localisation de `state.prepare_backfill_start(request)`, la recherche du spawn est limitée au suffixe de source qui suit cette admission. Aucun code de production, DTO, frontend, contrat Job, Store ou Transport n'est modifié. Gate opérateur requis après application : ```text 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.3.7 cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-job-backfill-lib cargo test -p ksp-app-backfill-desk cargo tree -p ksp-app-backfill-desk --edges normal cargo tree -p ksp-app-backfill-desk -e features ``` ## 20. `pre.008-fix.003` — canaris sécurité bornés aux DTO exacts Le replay opérateur de `pre.008-fix.002` confirme que les corrections précédentes sont effectives : audits Rust/Markdown, `cargo check --workspace`, Clippy et `ksp-job-backfill-lib` passent, puis le canari d'ordre Start corrigé passe également. Le dernier blocage est limité à deux canaris `desktop_security`. Les DTO de production sont conformes. Les deux échecs sont des faux positifs causés par des fenêtres textuelles trop larges : le contrôle de `BackfillStartRequestDto` s'étendait jusqu'à `BackfillRequestPreviewDto` et incluait donc légitimement `BackfillStartResponseDto::job_id`; le contrôle de `BackfillStartResponseDto` incluait les commentaires de documentation du DTO suivant, qui contiennent les mots `address`/`signature`. Le correctif ajoute un helper de test qui extrait uniquement la déclaration de struct visée, de son marqueur `struct` jusqu'à son accolade fermante immédiate. Les deux canaris auditeront désormais exactement `BackfillStartRequestDto` et `BackfillStartResponseDto`, sans modifier les DTO ni aucun code de production. ### Gate du fix - [X] aucun fichier de production Backfill Desk, Job Backfill, Store ou Transport modifié ; - [X] le canari request ne peut plus inclure `BackfillStartResponseDto::job_id` ; - [X] le canari Start acknowledgement ne peut plus inclure la documentation de `BackfillRequestPreviewDto` ; - [X] les champs réellement interdits restent vérifiés dans le corps exact des DTO exposés ; - [X] version Cargo synchronisée en `0.3.7-pre.8.fix.3` ; - [X] audits statiques Rust/Markdown rejoués dans l'environnement d'assemblage ; - [ ] replay opérateur `cargo fmt/check/clippy/test` de `pre.008-fix.003` à exécuter ; aucun `cargo tree` requis car dépendances/features inchangées. ## 21. `pre.009` — monitoring latest-value et resynchronisation Le replay opérateur de `pre.008-fix.003` ferme le couloir Start : audits Rust/Markdown, `cargo check --workspace`, Clippy, les 49 tests unitaires `ksp-job-backfill-lib` et toutes les suites Backfill Desk passent. Aucun `cargo tree` supplémentaire n'était requis pour ce dernier fix test-only sans changement de dépendances/features. `pre.009` branche directement la source latest-value déjà possédée par `BackfillJobHandle`. `BackfillRunLaunch` conserve une `BackfillSnapshotSource` indépendante avant déplacement du runtime dans le task, tandis que `BackfillRunState` conserve le handle actif et retient la dernière notification terminale après `finish`. La commande `backfill_status` retourne donc soit la valeur active courante, soit le dernier terminal retenu, ce qui fournit une resynchronisation explicite sans dépendre de l'historique des événements frontend. Le bridge Tauri attend `JobSnapshotSource::wait_for_change` et émet `ksp-backfill-status`. Cette primitive latest-value coalesce les mises à jour intermédiaires : aucun event queue métier supplémentaire ni polling de logs n'est introduit. `BackfillRunStatusDto` expose uniquement des métadonnées sûres et bornées : JobId/kind, sequence en texte décimal, lifecycle/completion, phase/scope/boundary, compteurs candidates/entities/observations, missing/conflicts/cancelled/holes, maximum in-flight, `checkpoint_present`, `contiguous_completed` et éventuel `failure_domain/failure_code`. Adresse, signatures, endpoint/provider, payload RAW, contexte d'erreur et checkpoint concret restent backend-only. Le frontend installe le listener avant la resynchronisation startup, rend le dernier snapshot complet, propose un bouton manuel de resynchronisation et réactive Start lorsque le snapshot devient terminal. Cancel, état cancelling piloté par l'UI et races fermeture/Cancel/terminal restent réservés à `pre.010`. ### Gate statique local `pre.009` - [X] monitoring branché sur `JobSnapshotSource`, sans parsing de logs ; - [X] événement latest-value coalescé `ksp-backfill-status` ; - [X] commande `backfill_status` de resynchronisation ; - [X] dernier terminal retenu après libération du slot single-run ; - [X] sequence `u64` projetée comme texte décimal ; - [X] compteurs complets projetés avec conversion bornée vers `u32` ; - [X] checkpoint projeté seulement par présence + frontier contigu ; - [X] erreurs projetées seulement par domaine/code stables ; - [X] aucun payload métier, URL/provider/credential ou checkpoint concret exposé ; - [X] frontend réactive Start sur terminal et garde un resync manuel ; - [X] aucun Cancel/Resume ajouté prématurément ; - [ ] `cargo fmt/check/clippy/test` de `pre.009` à rejouer par l'opérateur ; `cargo`/`rustfmt` restent absents du sandbox. ## 22. Correctif `pre.009-fix.001` — helpers de canaris monitoring Le gate opérateur de `pre.009` confirme que les audits Rust/Markdown et `cargo check --workspace` sont propres. `ksp-job-backfill-lib` reste intégralement vert. Le blocage est limité à la compilation de deux nouveaux canaris Backfill Desk : `desktop_contract` appelle un helper inexistant `read`, tandis que `desktop_security` appelle `workspace_root` et `read`, helpers absents de ce fichier. Le smoke Tauri manuel confirme parallèlement le comportement fonctionnel de `pre.009` : avec le Store Mainnet joignable et `tls_mode = disabled` dans la configuration locale opérateur, le Store devient ready, un backfill `latest_address` est admis, dix candidats sont traités puis un snapshot terminal `finished` est retenu et resynchronisable via `backfill_status`. Cette configuration TLS locale n'appartient pas au delta du correctif de tests. Le correctif réutilise uniquement les helpers déjà possédés par chaque fichier de test : `app_root()` et `read_text()`. Aucun code de production, DTO, monitoring latest-value, runtime Job, Store, Transport, frontend ou configuration n'est modifié. ### Gate du fix - [X] `desktop_contract` utilise `app_root()` + `read_text()` pour les quatre sources `pre.009` ; - [X] `desktop_security` utilise `app_root()` + `read_text()` pour `backfill_status.rs` ; - [X] aucun nouveau helper de test redondant n'est introduit ; - [X] aucun fichier de production ou Config n'est modifié ; - [X] version Cargo synchronisée en `0.3.7-pre.9.fix.1` ; - [X] audits statiques Rust/Markdown rejoués dans l'environnement d'assemblage ; - [X] replay opérateur `cargo fmt/check/clippy/test` du fix propre : aucun warning, 50 tests unitaires Job Backfill et toutes les suites Backfill Desk passent ; aucun `cargo tree` requis car dépendances/features inchangées. ## 23. Correctif `pre.009-fix.002` — canari monitoring borné aux champs sérialisés Le replay opérateur de `pre.009-fix.001` confirme que les audits Rust/Markdown, `cargo check --workspace`, Clippy, `ksp-job-backfill-lib` et les suites `desktop_contract` sont propres. Le seul échec restant est le canari `pre_009_monitoring_projection_exposes_counters_and_codes_without_checkpoint_or_business_payloads`. Le DTO de production est conforme : il n'expose aucun champ adresse/signature. Le faux positif vient du canari, qui cherche les mots nus `address` et `signature` dans toute la source de `BackfillRunStatusDto`, y compris les commentaires de documentation. Or la documentation de `scope_kind` précise explicitement que ce champ est exposé « without address/signature payloads ». Le correctif conserve le même niveau de sécurité mais cible désormais les déclarations de champs réellement sérialisés : `pub(crate) address:`, `pub(crate) signature:`, `pub(crate) endpoint:`, `pub(crate) provider:`, `pub(crate) credential:`, `pub(crate) token:`, `pub(crate) checkpoint:`, `pub(crate) payload:` et `pub(crate) raw_transaction:`. `checkpoint_present` reste explicitement autorisé. ### Gate du fix - [X] aucun fichier de production, DTO, monitoring, frontend, Store, Transport ou Job n'est modifié ; - [X] le canari n'interprète plus les doc-comments comme des champs IPC ; - [X] les champs métier/sensibles restent interdits par leur déclaration exacte ; - [X] `checkpoint_present` reste autorisé tandis que `pub(crate) checkpoint:` reste interdit ; - [X] version Cargo synchronisée en `0.3.7-pre.9.fix.2` ; - [X] audits statiques Rust/Markdown rejoués dans l'environnement d'assemblage ; - [ ] replay opérateur `cargo fmt/check/clippy/test` du fix à exécuter ; aucun `cargo tree` requis car dépendances/features inchangées. ## 24. `pre.010` — Cancel ciblé, idempotence et races terminales Le replay opérateur de `pre.009-fix.002` ferme le monitoring latest-value : audits Rust/Markdown, `cargo check --workspace`, Clippy, les 49 tests unitaires `ksp-job-backfill-lib` et toutes les suites Backfill Desk passent. La surface `pre.010` peut donc ouvrir le contrôle coopératif sans rattrapage antérieur. `backfill_cancel(job_id)` cible explicitement le JobId backend actuellement observé. Cette cible empêche une requête Cancel IPC retardée, émise pour un run terminé, d'annuler un run ultérieur. Le slot single-run sérialise Start/Cancel/finish : le premier Cancel pré-terminal appelle `BackfillJobHandle::cancel()` et renvoie `accepted=true`; les répétitions renvoient `accepted=false`; un terminal déjà gagné reste terminal; un JobId qui ne correspond ni au run actif ni au terminal retenu est rejeté par un code `backfill_desk` stable. Le frontend ajoute un bouton **Annuler** au monitoring, transmet uniquement le JobId sûr, n'envoie aucun payload de campagne et se resynchronise immédiatement via `backfill_status`. La fermeture de la fenêtre principale gagne d'abord `begin_shutdown()`, ce qui interdit tout nouveau Start, puis demande best-effort l'annulation du run actif avant le shutdown Store et l'exit. Cette fermeture ne promet pas le drain crash-safe du travail déjà soumis ; le runtime Job conserve seul la sémantique de drain coopératif. ### Gate statique local `pre.010` - [X] Cancel ciblé par JobId backend, sans identité fournie au Start ; - [X] premier Cancel accepté et répétitions idempotentes ; - [X] stale JobId rejeté avant action sur un nouveau run ; - [X] terminal tardif prioritaire sur un Cancel non accepté ; - [X] shutdown bloque Start puis tente l'annulation active avant exit ; - [X] DTO Cancel limité à `accepted`, `job_id`, `state` ; - [X] frontend Cancel sans adresse/signature/provider/endpoint/checkpoint/payload ; - [X] aucune dépendance/feature Cargo ajoutée ; - [X] Resume non ouvert ; - [X] replay opérateur `cargo fmt/check/clippy/test` de `pre.010` propre ; smoke Tauri Mainnet confirme Cancel ciblé, terminalisation puis shutdown Store. ## 25. `pre.011` — checkpoint/frontier et Resume in-session Le replay opérateur de `pre.010` ferme le couloir Cancel : audits Rust/Markdown, `cargo check --workspace`, Clippy, les 49 tests unitaires `ksp-job-backfill-lib` et toutes les suites Backfill Desk passent. Le smoke Tauri Mainnet confirme également le chemin réel : Store ready, campagne HTTP active, Cancel ciblé accepté, transition `cancelling`, terminalisation du Job puis libération du slot avant shutdown. La phase `finished` observée est la phase terminale commune ; le lifecycle Job reste `cancelled`. `pre.011` ouvre la reprise in-session sans sérialisation du checkpoint. Le contrat existant lie volontairement `BackfillCheckpoint` au JobId qui l'a produit ; la Desk ne peut donc pas simplement attacher ce checkpoint à un nouveau Job. `ksp-job-backfill-lib` ajoute `BackfillRequest::resume_for_job` : le checkpoint est d'abord validé contre la requête d'origine puis réémis en interne pour le nouveau JobId, avec scope fingerprint, completed prefix et éventuel cursor Before inchangés. `BackfillRunState` retient maintenant la requête terminale avec la notification terminale, uniquement en mémoire Rust. `backfill_resume` n'accepte aucun argument frontend, alloue un nouveau JobId backend, exige un checkpoint présent, refuse tout run actif et revalide que réseau Store et rôle HTTP correspondent encore à la composition courante. La commande utilise le même chemin `spawn_backfill_launch` et le même monitoring latest-value que Start. Le frontend expose **Reprendre** uniquement pour un snapshot terminal avec `checkpoint_present=true`. `BackfillResumeResponseDto` contient uniquement `accepted`, `job_id` et `state`; aucun checkpoint, cursor, adresse, signature, provider, endpoint ou payload RAW ne traverse IPC. ### Gate statique local `pre.011` - [X] checkpoint original validé avant réémission vers un nouveau JobId ; - [X] scope fingerprint/frontier/cursor inchangés par `resume_for_job` ; - [X] requête terminale + checkpoint retenus uniquement dans `BackfillRunState` Rust ; - [X] Resume refusé sans terminal/checkpoint ou lorsqu'un run est déjà actif ; - [X] compatibilité réseau Store + rôle HTTP revalidée avant reprise ; - [X] nouveau JobId exclusivement backend ; - [X] chemin de spawn/monitoring partagé avec Start ; - [X] DTO Resume limité à `accepted`, `job_id`, `state` ; - [X] frontend Resume sans checkpoint ni payload de campagne ; - [X] aucun fichier/table/JSON de checkpoint durable ajouté ; - [X] aucune dépendance/feature Cargo ajoutée ; - [X] replay opérateur `cargo fmt/check/clippy/test` de `pre.011` propre : 50 tests unitaires Job Backfill et toutes les suites Backfill Desk passent. Le smoke Tauri `pre.011` confirme également le Resume réel : après un timeout Transport sur un run terminal, `backfill_resume` réémet le checkpoint Rust-only vers un nouveau JobId backend, le nouveau run est admis et repart sur le même rôle HTTP ; un Cancel ciblé ultérieur est accepté puis terminalise proprement le run repris. ## Pre.012 — frontend fonctionnel, summary terminal et autocomplete Program ID - [X] `BackfillDeskOptionsDto` expose un dataset Program ID dérivé exclusivement de `ksp-core-lib::entries()`. - [X] `ProgramIdAutocompleteOptionDto` ne contient que `program_id`, `code`, `name`, `domain`, `family` et `protocol`. - [X] L'input `backfillAddress` reste un champ texte libre et référence `backfillProgramIds` via l'attribut HTML `list`. - [X] Le frontend construit le `datalist` sans Program ID hardcodé et ajoute des `data-*` sûrs pour l'UX. - [X] La sélection autocomplete ne journalise jamais l'adresse, seulement le code KSP éventuel et un booléen `registryMatch`. - [X] Aucun `localStorage`, `sessionStorage`, IndexedDB ou cookie n'est ajouté. - [X] Le monitoring affiche un résumé terminal explicite et les erreurs Cancel/Resume sont rendues via la projection d'erreur sûre. - [X] Aucune dépendance/feature Cargo, aucun Store/Transport/Job runtime et aucun `std.store.json` modifié. - [ ] Gate opérateur `cargo fmt` + audits + check/clippy/tests Backfill à rejouer avant `pre.013`. ## Correctif `pre.012-fix.001` — accès crate-root du DTO autocomplete Le gate opérateur de `pre.012` est fonctionnel mais signale un warning `unused_imports` sur le réexport crate-root de `ProgramIdAutocompleteOptionDto`. Le réexport n'est pas superflu : `ProgramIdAutocompleteOptionDto` est `pub(crate)` et partagé dans la crate. Conformément à `RUST-IMPORT-009`, `RUST-IMPORT-012` et `RUST-API-004`, il doit rester réexporté par `lib.rs` et être consommé via `crate::ProgramIdAutocompleteOptionDto`, y compris depuis `dto_common.rs`, son module de déclaration. Le correctif conserve donc le réexport et normalise uniquement les trois usages introduits en `pre.012` : type de retour de `program_id_autocomplete_options`, construction du DTO et type du champ `BackfillDeskOptionsDto.program_id_options`. Aucun contrat IPC, dataset, frontend, Store, Transport, Job, dépendance ou feature ne change. ### Gate du fix - [X] réexport `pub(crate) use self::dto_common::ProgramIdAutocompleteOptionDto;` conservé au crate-root ; - [X] usages intra-module du DTO partagés via `crate::ProgramIdAutocompleteOptionDto` ; - [X] aucun élargissement/rétrécissement de visibilité ; - [X] aucune modification du contrat TS-RS ou du dataset Program ID ; - [X] version Cargo synchronisée en `0.3.7-pre.12.fix.1` ; - [X] audits statiques Rust/Markdown rejoués dans l'environnement d'assemblage ; - [ ] replay opérateur `cargo fmt/check/clippy/test` du fix à exécuter ; aucun `cargo tree` requis car dépendances/features inchangées. ## 27. `pre.013` — hardening et complétude V1 Le gate opérateur de `pre.012-fix.001` ferme la tranche frontend : audits Rust/Markdown, `cargo check --workspace`, Clippy, les 50 tests unitaires `ksp-job-backfill-lib` et toutes les suites Backfill Desk passent sans warning. `pre.013` n'ouvre donc aucune capacité et ajoute uniquement des canaries de clôture V1. ### Gate statique local `pre.013` - [X] suite `dependency_boundary.rs` ajoutée avec inventaire exact des dépendances KSP normales ; - [X] `ksp-store-api`, backend PostgreSQL direct, `tokio-postgres`, `reqwest`, `tonic` et Yellowstone interdits dans le manifest/app production ; - [X] suite `release_completeness.rs` ajoutée avec inventaire exact des 17 modules de production et des 6 suites d’intégration ; - [X] surface Tauri finale bornée à 9 commandes, sans reset/retry/scheduler/history V1 ; - [X] contrôles frontend finaux Start/Cancel/Resume/Refresh/autocomplete présents ; - [X] scan sécurité agrégé : aucune URL physique, browser storage, checkpoint concret ou client/backend physique dans IPC/frontend ; - [X] composite final borné à `devnet`, `mainnet`, `testnet`, avec exactement `logging`, `transport`, `store` ; - [X] `ProgramIdAutocompleteOptionDto` reste réexporté et consommé via `crate::ProgramIdAutocompleteOptionDto` ; - [X] aucun code runtime, DTO/IPC, frontend, Config, Store, Transport ou Job modifié ; - [X] aucune dépendance/feature Cargo ajoutée ; - [X] audits statiques Rust/Markdown propres dans l'environnement d'assemblage ; - [ ] replay opérateur `cargo fmt/check/clippy/test` de `pre.013` à exécuter avant le gate technique final `pre.014`. ## 28. `pre.013-fix.001` — inventaire frontend borné aux IDs réels Le replay opérateur de `pre.013` confirme les audits Rust/Markdown, `cargo check --workspace`, Clippy et les 50 tests `ksp-job-backfill-lib`. La suite Backfill Desk s'arrête toutefois sur le nouveau canari `pre_013_final_v1_command_and_frontend_control_inventory_is_exact` : le test cherchait cinq noms de contrôles synthétiques (`backfillStart`, `backfillCancel`, `backfillResume`, `backfillRefresh`, `backfillProgramIds`) alors que les quatre premiers ne correspondent pas aux IDs HTML réels. Le correctif conserve la règle d'inventaire exacte et remplace uniquement ces marqueurs par les IDs réellement possédés par le frontend : `startBackfillRequest`, `cancelBackfillRun`, `resumeBackfillRun`, `refreshBackfillStatus`, `backfillProgramIds`. Aucun HTML, TypeScript, runtime, DTO, IPC, Config ou manifest de crate n'est modifié. Le même replay opérateur a également révélé un échec distinct de `ksp-config-lib` : le fichier `config/std.store.json` local a été passé à TLS `disabled` alors que le test committed et sa fixture attendent encore `verify_full`. Cette incohérence est antérieure à `pre.013` et n'est volontairement pas mélangée dans ce fix de hardening ; elle devra être réconciliée dans une prerelease dédiée avant le gate technique final. ### Gate du fix - [X] inventaire Tauri inchangé à neuf commandes ; - [X] IDs frontend canariés sur les identifiants HTML réels ; - [X] suites `dependency_boundary.rs` et `release_completeness.rs` réauditées statiquement ; - [X] aucun code de production/frontend/Config modifié ; - [X] aucune dépendance/feature Cargo ajoutée ; - [X] version Cargo synchronisée en `0.3.7-pre.13.fix.1` ; - [X] audits statiques Rust/Markdown propres dans l'environnement d'assemblage ; - [ ] replay opérateur `cargo fmt/check/clippy/test` du fix à exécuter avant toute nouvelle prerelease. ## 29. `pre.014` — réconciliation TLS Store committed avant gate final Le replay opérateur de `pre.013-fix.001` ferme le hardening Backfill Desk : audits Rust/Markdown, `cargo check --workspace`, Clippy, les 50 tests `ksp-job-backfill-lib` et toutes les suites `ksp-app-backfill-desk`, y compris `dependency_boundary`, `desktop_security` et `release_completeness`, passent. L'échec workspace distinct observé pendant le replay étendu vient de `ksp-config-lib` : `config/std.store.json` utilisé par l'opérateur a été passé à TLS `disabled` pour PostgreSQL local, mais la fixture committed et le test `committed_store_profile_maps_exact_runtime_settings_and_secret_fallback` attendaient encore `VerifyFull`. Le smoke Backfill Desk Mainnet confirme également l'ouverture Store avec `tls_mode="disabled"`. Cette divergence Config/runtime, antérieure au hardening, est donc réconciliée dans une nouvelle prerelease et non dans un fix `pre.013`. `pre.014` synchronise les trois profils committed `devnet`, `mainnet` et `testnet` sur `tls.mode = "disabled"`, met la fixture Config à l'identique et exige `PostgresTlsMode::Disabled` dans les assertions committed, y compris pour les trois cibles nommées. Le schema et le runtime continuent à supporter les autres modes TLS, notamment `verify_full`; aucune capacité Store n'est supprimée. ### Gate statique local `pre.014` - [X] `config/std.store.json` : trois profils committed en TLS `disabled` ; - [X] fixture `ksp-config-lib` byte-for-byte cohérente sur la politique TLS ; - [X] test committed par défaut synchronisé sur `PostgresTlsMode::Disabled` ; - [X] cibles `devnet`/`mainnet`/`testnet` canariées sur le même mode TLS ; - [X] aucune modification du schema TLS ni de `ksp-store-lib`/`ksp-store-postgres-lib` ; - [X] aucun runtime/DTO/IPC/frontend Backfill modifié ; - [X] aucune dépendance/feature Cargo ajoutée ; - [X] gate technique final décalé à `pre.015`. ## 30. `pre.015` — gate technique final Le gate opérateur de `pre.014` ferme la réconciliation TLS Store : audits Rust/Markdown, `cargo check --workspace`, Clippy, `ksp-config-lib`, `ksp-job-backfill-lib` et toutes les suites `ksp-app-backfill-desk` passent sans échec. Les profils Store committed, leur fixture et leurs assertions sont désormais cohérents sur `PostgresTlsMode::Disabled`. `pre.015` n'ajoute ni capacité, ni test, ni dépendance, ni Config. La tranche ne fait qu'ouvrir la preuve technique finale de `0.3.7`. Tout défaut découvert par ce gate doit ouvrir `pre.015-fix.NNN` avant la réconciliation documentaire `pre.016`. ### Gate opérateur attendu ```bash cargo fmt --all -- --check 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.3.7 cargo check --workspace cargo clippy --workspace --all-targets --all-features -- -D warnings cargo test --workspace --all-targets --all-features cargo tree -p ksp-app-backfill-desk --edges normal cargo tree -p ksp-app-backfill-desk -e features cargo tree -p ksp-job-backfill-lib --edges normal cargo tree -p ksp-job-backfill-lib -e features cargo tree --duplicates (cd crates/ksp-app-backfill-desk && cargo tauri build) ``` Un `cargo clean` préalable est optionnel : il peut être utilisé pour une reconstruction froide mais n'est pas une condition du gate. Le smoke Mainnet HTTP/Store reste opt-in ; les smokes déjà fournis sur Start/monitoring/Cancel/Resume constituent des preuves fonctionnelles, mais aucun nouveau résultat live n'est revendiqué par l'archive `pre.015`. ### Statut de préparation - [X] `pre.014` fermé par gate opérateur ciblé ; - [X] aucun `src/**`, test, Config ou frontend rouvert dans `pre.015` ; - [X] aucune dépendance/feature Cargo modifiée ; - [X] gate final borné au workspace, arbres Cargo et build Tauri ; - [ ] gate opérateur final à exécuter ; - [ ] `pre.016` interdit tant que ce gate n'est pas intégralement vert. ## 32. `pre.015` — gate technique final Le gate opérateur final est intégralement vert sur `0.3.7-pre.15` : - [X] `cargo fmt --all -- --check` ; - [X] audits Rust/exports/workspace et Markdown ; - [X] `cargo check --workspace` ; - [X] `cargo clippy --workspace --all-targets --all-features -- -D warnings` sans warning ; - [X] `cargo test --workspace --all-targets --all-features` : 1 494 tests passés, 0 échec, 15 tests ignorés explicitement opt-in/operator-only ; - [X] arbres normal/features de `ksp-app-backfill-desk` et `ksp-job-backfill-lib` produits ; - [X] `cargo tree --duplicates` exécuté et revu ; - [X] `cargo tauri build` final réussi ; - [X] bundles Linux `.deb`, `.rpm` et `.AppImage` produits ; - [X] aucun smoke live supplémentaire requis, les smokes Mainnet précédents ayant déjà prouvé Start, monitoring, Cancel et Resume réels. Aucun défaut technique n'est reporté vers la réconciliation documentaire. ## 33. `pre.016` — réconciliation documentaire finale La surface candidate est réconciliée sans rouvrir le runtime : - [X] `crates/ksp-app-backfill-desk/README.md` décrit responsabilités, composition, frontières et build de manière durable ; - [X] `crates/ksp-app-backfill-desk/USAGE.md` décrit l'utilisation sans journal de prerelease ni preuve de gate ; - [X] le plan est réaligné sur les commandes réellement livrées et l'événement `ksp-backfill-status` ; - [X] les index `docs/000-README.md` et `docs/validation/000-README.md` référencent `0.3.7` ; - [X] l'inventaire d'architecture fixe `ksp-app-backfill-desk` comme composant implémenté ; - [X] Layers/Contracts/Dependency Graph/Apps & Services décrivent la composition finale et les firewalls ; - [X] README racine mentionne la surface desktop Backfill sans faire de la documentation durable un changelog ; - [X] CHANGELOG et ROADMAP restent réservés à `pre.017` ; - [X] aucun code, test, frontend, Config ou manifest de crate n'est modifié.