Files
khadhroony-solana-project/docs/plans/028-V0_3_7_BACKFILL_DESK_PLAN.md
2026-09-03 06:26:49 +02:00

35 KiB
Raw Blame History

Plan v0.3.7 — Backfill Desk

1. But de la version

La v0.3.7 crée ksp-app-backfill-desk, application Tauri spécialisée qui compose Config, Transport, Store et ksp-job-backfill-lib afin de lancer, observer, annuler et reprendre un backfill historique borné.

L'application reste une couche de composition et d'interface. Elle ne possède ni découverte RPC, ni retry/rate-limit, ni persistance, ni frontier/checkpoint, ni navigation Store générale.

Chaîne cible :

Config composite/profile
  -> Logging
  -> Transport HTTP
  -> Store
  -> AppState Rust
       -> BackfillRequest
       -> BackfillJobRuntime
       -> BackfillJobHandle
       -> BackfillSnapshotSource
  -> DTO Tauri sûrs
  -> UI latest-value

2. Base et audits de pre.001

Base autoritaire : archive stable v0.3.6, workspace.package.version = 0.3.6, avec deltas/0.3.6/rel.001.md, ksp-job-api, ksp-job-backfill-lib et les trois Desks existants.

Les deux archives ont été testées intégralement avant utilisation et extraites dans des arbres séparés. kbot3 reste une référence fonctionnelle/UX ; aucun code, DTO, commande Tauri ou algorithme n'en est repris.

Sources internes relues : règles racine et docs/rules/, architectures Layers/Dependencies/Components/Jobs/Apps, clôture complète de v0.3.6, surfaces Rust Job/Backfill/Config/Transport/Store et gabarits des Desks Config, Wallet et SOL Prices.

L'audit externe du 2026-09-02 confirme que le socle Tauri v2, son modèle capabilities/runtime authority et les versions courantes restent compatibles avec les contraintes existantes. Le workspace résout déjà tauri 2.11.5, tauri-build 2.6.3, tauri-plugin-tracing 0.3.4 et ts-rs 12.0.1; les manifests frontend utilisent @tauri-apps/api ^2.11, @tauri-apps/cli ^2.11, TypeScript ^7.0 et Vite ^8.2. Une version plus récente de Vite existe, mais aucun besoin fonctionnel ne justifie une mise à niveau en v0.3.7.

3. Surface Backfill réellement disponible

ksp-job-backfill-lib expose déjà les quatre scopes LatestAddress, BeforeAddress, AfterAddress et ExplicitSignatures, les commitments Confirmed/Finalized, les bornes publiques, BackfillRequest, BackfillCheckpoint, BackfillJobRuntime, BackfillJobHandle et BackfillSnapshotSource.

Le snapshot sûr expose phase, scope kind, boundary, candidats selected/admitted/finished, entities inserted/existing/purged, missing, conflicts, observations inserted/existing, cancelled candidates, holes, maximum in-flight, contiguous completed, présence d'un checkpoint et failure code. L'UI ne fabrique aucun pourcentage global lorsque le dénominateur n'est pas connu.

Bornes backend-owned :

Paramètre Borne publique
page size 1..=1000
max pages 1..=10000
max candidates 1..=10000
hydration concurrency 1..=64
signature Base58 64..=88 octets texte, validation Rust exacte

min_context_slot est admis pour les scopes adresse et rejeté pour ExplicitSignatures par BackfillRequest.

4. Matrice kbot3

Capacité historique Preuve fonctionnelle kbot3 Équivalent KSP v0.3.6 Décision
Formulaire de campagne demo_backfill.html + request TS/Rust BackfillRequest explicite et borné REPRENDRE FONCTIONNELLEMENT
Signatures explicites textarea + mode explicit_signatures BackfillScope::explicit_signatures REPRENDRE FONCTIONNELLEMENT
Adresse + direction address, anchor, before/after Latest/Before/After address distincts REDESSINER POUR KSP
Commitment sélecteur confirmed/finalized BackfillCommitment REPRENDRE FONCTIONNELLEMENT
Rôle logique rôle HTTP sélectionnable HttpRoleName + Transport REDESSINER POUR KSP
Provider/endpoint affichés options et summary Transport possède routage physique REJETER
Retry opérateur maxRetries UI Transport possède retry/pacing REJETER
Page size/max pages/limit inputs bornés constantes Backfill publiques REPRENDRE FONCTIONNELLEMENT
Concurrency input opérateur hydration_concurrency REPRENDRE FONCTIONNELLEMENT
Program/token/pool modes accordéons dédiés scopes génériques adresse/signatures REJETER comme types KSP
Progression live événements textuels + log snapshots latest-value structurés REDESSINER POUR KSP
Annulation bool atomique + commande BackfillJobHandle::cancel() REDESSINER POUR KSP
Résumé terminal payload summary notification/snapshot terminal REPRENDRE FONCTIONNELLEMENT
Compteurs inserted/existing/missing/failed/observations summary compteurs BackfillJobSnapshot REDESSINER POUR KSP
Cursor older-history resume_before_signature BackfillCheckpoint opaque REDESSINER POUR KSP
Reprise durable cursor texte retourné aucun checkpoint sérialisable public REPORTER
Single-run UI flag running runtime single-run + handle REPRENDRE FONCTIONNELLEMENT
Store browsing demo desktop monolithique futur Store Desk v0.3.8 REJETER

5. Screen map

Un seul écran principal responsive suffit en V1, en plus du splash commun.

main
├─ header : Backfill Desk + statut runtime/config
├─ readiness : profil composite, réseau, rôle(s) compatibles, Store/Transport ready
├─ campaign form
│  ├─ scope kind
│  ├─ address / anchor / signatures selon scope
│  ├─ commitment + rôle logique
│  └─ page size / max pages / max candidates / concurrency / min_context_slot
├─ active job
│  ├─ lifecycle + phase
│  ├─ boundary/frontier
│  ├─ compteurs structurés
│  ├─ checkpoint présent + contiguous completed
│  └─ Start / Cancel selon état
├─ terminal summary
│  ├─ outcome/lifecycle
│  ├─ failure code sûr
│  └─ Resume / New campaign selon checkpoint et scope
└─ diagnostics sûrs : codes, jamais secrets/URL/RAW

États UI explicites : booting, ready, starting, running, cancelling, completed, cancelled, failed, resume-ready. cancelling ne prétend jamais que la persistance déjà soumise est interrompue.

6. DTO et command map

Les DTOs sont possédés par l'application et dérivés TS-RS uniquement à cette frontière.

Élément Direction Contenu Validation / source de vérité Sensibilité
BackfillDeskOptionsDto Rust -> UI réseau, rôles, commitments, scopes, bornes, readiness, Program IDs autocomplete Config + Transport + Core + Backfill sûre
BackfillRequestLimitsDto Rust -> UI defaults + maxima de campagne constantes publiques Backfill sûre
BackfillStartRequestDto UI -> Rust scope inputs, commitment, rôle, bornes, optional min context slot conversion stricte vers types KSP métier borné
BackfillRequestPreviewDto Rust -> UI request validée sans valeur d'adresse/signature mapping applicatif + BackfillRequest sûre
BackfillStartResponseDto Rust -> UI JobId backend + état initial slot single-run sûre
BackfillRunStatusDto Rust -> UI job state, phase, compteurs, boundary, checkpoint_present, contiguous_completed, failure code BackfillSnapshotSource sûre
BackfillCancelResponseDto Rust -> UI accepted + JobId ciblé + état BackfillJobHandle sûre
BackfillResumeResponseDto Rust -> UI accepted + nouveau JobId + état checkpoint Rust détenu par BackfillRunState sûre
ProgramIdAutocompleteOptionDto Rust -> UI program_id + metadata publiques de taxonomie ksp_core_lib::entries() publique
CommandErrorDto Rust -> UI domain/code + message app maîtrisé mapping applicatif sûre

Commandes finales :

backfill_options() -> BackfillDeskOptionsDto
backfill_status() -> Option<BackfillRunStatusDto>
backfill_validate_request(request) -> BackfillRequestPreviewDto
backfill_start(request) -> BackfillStartResponseDto
backfill_cancel(job_id) -> BackfillCancelResponseDto
backfill_resume() -> BackfillResumeResponseDto

Le monitoring continu ne dépend pas du parsing de logs. Le backend possède un bridge latest-value depuis BackfillSnapshotSource, projette le snapshot et émet l'événement Tauri stable ksp-backfill-status. backfill_status reste le chemin de resynchronisation initiale/explicite.

Aucun BackfillCheckpoint, Store, HttpTransportPool, sender/receiver Tokio ni payload RAW n'est sérialisé vers le frontend.

7. Config et composition

Le composite cible est config/composite.ksp-app-backfill-desk.json avec trois profils cohérents :

Profil composite Logging Transport Store Réseau
devnet supertrace devnet_public devnet devnet
mainnet supertrace mainnet_backfill_pool mainnet mainnet-beta
testnet console_info publicnode_testnet testnet testnet

Le default V1 est désormais mainnet, conformément à la finalité lecture seule du Backfill Desk. devnet et testnet restent sélectionnables par reconfiguration du composite. Pendant le développement de 0.3.7, Mainnet conserve le profil Logging supertrace. Aucun std.job_backfill.json n'est créé : les paramètres de campagne restent opérationnels et backend-validés.

Au bootstrap, l'application charge le composite, résout Logging/Transport/Store via ksp-config-lib, construit HttpTransportPool et ouvre ksp_store_lib::Store. Elle compare le réseau Store au(x) cluster(s) HTTP activés et refuse le readiness si une composition mélange des réseaux.

Les routes HTTP présentées à l'UI sont dérivées des snapshots/settings Transport, dédupliquées, puis validées côté Rust comme capables de sélectionner à la fois getSignaturesForAddress et getTransaction. Sur Mainnet, backfill_pool regroupe Solana Public et PublicNode à priorité égale, tandis que backfill_solana_public et backfill_publicnode ciblent un provider unique. Le frontend ne reçoit que le rôle logique et les labels provider sûrs ; URL, credentials, rate-limit interne et retry restent possédés par Transport.

Le packaging Config suit le contrat atomique déjà détenu par ksp-config-lib::prepare_packaged_runtime() : il traverse l'intégralité de ConfigFileRegistry::defaults(). L'ajout du composite Backfill Desk fait donc passer le registre de 13 à 14 descriptors et impose que les quatre applications Desk qui utilisent ce packaging embarquent les 14 resources Config/schema du registre. Backfill Desk embarque ainsi également les documents Wallet/offchain sans les consommer au runtime ; leur présence satisfait le contrat de packaging partagé et n'ouvre aucune dépendance, permission frontend ou responsabilité métier supplémentaire.

8. Dependency map

Dépendances Rust normales envisagées :

ksp-app-backfill-desk
├─ ksp-core-lib              # erreurs, Pubkey/app DTO si requis
├─ ksp-logging-lib           # façade logging
├─ ksp-config-lib            # composition et packaging Config
├─ ksp-job-api               # JobState/JobSnapshotSource consommés directement
├─ ksp-job-backfill-lib      # request/runtime/handle/snapshot
├─ ksp-onchain-transport-lib # construction HttpTransportPool + role/method readiness
├─ ksp-store-lib             # Store::open et ressource runtime
├─ serde                     # DTO IPC
├─ tauri
├─ tauri-plugin-tracing
├─ tokio                     # spawn/synchronisation app si gabarit Tauri l'exige
└─ ts-rs                     # bindings DTO applicatifs

ksp-job-backfill-lib dépend déjà de Store avec default-features = false. Le Desk devra cependant ouvrir le Store concret ; la feature backend de ksp-store-lib doit donc être explicitement auditée au scaffold. Le pattern cible est une dépendance sur ksp-store-lib uniquement, avec le backend compilé par la feature de façade adéquate, jamais une dépendance directe sur ksp-store-postgres-lib.

Dépendances interdites : ksp-store-api direct, ksp-store-postgres-lib, tokio-postgres, reqwest, tonic, yellowstone-grpc-proto, SDK provider.

9. Single-run lifecycle et races

AppState conserve au plus : ressources runtime stables, un slot de run actif, le dernier snapshot terminal et le dernier checkpoint sûr associé à la requête/backend state nécessaires à une reprise en session.

Règles :

  • start atomique : refus si un run est starting/running/cancelling ;
  • le handle est installé avant spawn afin que Cancel ne perde pas la course au démarrage ;
  • Cancel cible le job_id backend affiché par le monitoring afin qu'une requête IPC retardée ne puisse jamais annuler un run ultérieur ;
  • Cancel répété est idempotent au niveau UX, mais le retour expose si la demande a été acceptée ;
  • un terminal publié gagne sur un Cancel tardif ; un Cancel visant l'ancien JobId après admission d'un nouveau run est rejeté comme mismatch ;
  • la source latest-value est conservée jusqu'à projection du terminal ;
  • reset/new campaign n'est autorisé qu'en absence de run actif ;
  • fermeture de l'application déclenche une demande d'annulation coopérative best-effort puis laisse la destruction du process terminer les ressources ; aucune promesse de drain crash-safe n'est faite ;
  • aucun registry multi-job générique n'est introduit.

10. Reprise et checkpoint

V1 conserve le dernier BackfillCheckpoint et la requête sémantique terminale uniquement dans Rust. L'UI voit checkpoint_present et contiguous_completed, jamais les octets/identité internes du checkpoint.

Le checkpoint concret reste lié au JobId qui l'a produit. Pour créer un nouveau lifecycle sans affaiblir cette garantie, ksp-job-backfill-lib valide d'abord le checkpoint contre la requête terminale d'origine puis BackfillRequest::resume_for_job le réémet sur le nouveau JobId backend en conservant exactement scope fingerprint, frontier et cursor interne. La Desk ne fabrique ni ne modifie ces éléments.

Resume exige en outre que la composition Transport/Store courante reste compatible avec le réseau et le rôle logique de la requête retenue. Toute modification de scope/commitment/bornes sémantiques appartient à une nouvelle campagne et n'utilise pas Resume.

Aucun JSON, fichier ou table checkpoint n'est inventé. La reprise après crash/redémarrage est reportée à une évolution explicite du contrat Backfill si un besoin durable est démontré.

11. Threat model

Menace Surface Contrôle v0.3.7
fuite URI Store Config/backend jamais projetée en DTO/log frontend
fuite URL/token provider Transport/Config rôle + labels provider sûrs uniquement ; aucune URL/credential
fuite RAW transaction snapshots/IPC snapshot existant ne contient aucun payload ; aucun Store read général
fuite liste signatures request/logging input transmis au command, non journalisé ; DTO retour n'en contient pas
fuite adresse instrumentation ne pas journaliser la valeur ; seulement scope kind/action code
frontend falsifie bornes IPC validation Rust + BackfillRequest autoritaire
rôle incompatible Config/Transport inventory + select_for_method pour les deux RPC avant Start
réseau incohérent Config rejet bootstrap/readiness avant création de request
double Start AppState admission atomique single-run
Cancel/terminal race AppState/runtime handle installé avant spawn, terminal autoritaire
checkpoint forgé frontend checkpoint jamais traverse IPC
permissions Tauri excessives capabilities core:default + tracing:default, aucune permission fs/dialog/network frontend sans besoin
browser storage de secrets frontend interdit ; aucun secret ne doit atteindre JS

Tauri capabilities restent le mécanisme de frontière IPC. La capability par défaut doit cibler seulement splash et main et ne pas ajouter de plugin filesystem/dialog/network sans besoin réel.

12. Gate fonctionnel/live

Obligatoire pendant la release : tests déterministes Rust/desktop/security/composition, gates workspace et cargo tauri build final lancé depuis crates/ksp-app-backfill-desk.

Un smoke Config -> Transport -> Store -> Backfill peut exister comme test ignoré/opt-in uniquement si l'opérateur dispose d'un PostgreSQL de test et d'un endpoint public sûr. Aucun compte payant, secret fournisseur ou ressource non reproductible n'est requis pour clôturer la release.

13. Prévision recalibrée

pre.001 — audit et planification

Archives/règles/surfaces, matrice kbot3, screen map, DTO/commands, Config/composition, dépendances, threat model, lifecycle single-run, role/network/resume et sizing. Aucun scaffold lourd.

pre.002 — scaffold desktop minimal

Créer package lib+bin, shell/splash/tracing/capability, frontend minimal, ports Vite/HMR 1436/1437 stricts et tests desktop de structure. Le scaffold réutilise strictement le gabarit des Desk existantes : mêmes assets splash/logo/font, mêmes familles SASS/Bootstrap/SimpleBar, mêmes dépendances frontend minimales et mêmes devDependencies. Le bridge Logging frontend trace dès cette tranche les clics/onglets/transitions significatives ; le bootstrap Logging standard reste transitoire jusqu'au composite Backfill Desk de pre.003.

pre.003 — Config composite et packaging

Ajouter le composite Backfill Desk et l'enregistrer dans Config, mettre à jour atomiquement les quatre bundles Desk vers les 14 resources du registre, puis brancher le bootstrap Config/Logging et ses canaries sans encore ouvrir Transport/Store réel. Pendant le développement de l'application, devnet sélectionne le profil Logging supertrace et le fallback local Backfill Desk reste au niveau trace; ce choix est local au Desk et devra être resserré avant publication stable.

Le gate opérateur de pre.003 ouvre pre.003-fix.001 pour quatre corrections strictement locales : ordre RUST-FMT-104 d'un bloc de constantes, return explicite dans un canari Clippy, réconciliation de la fixture composite Backfill avec les profils réellement disponibles dans le corpus de fixtures Config, et correction d'un canari de dépendance qui doit reconnaître la syntaxe path utilisée par les crates KSP internes. Le composite de production, son profil supertrace et les frontières runtime de pre.003 restent inchangés.

Le replay opérateur de pre.003-fix.001 est ensuite intégralement propre : audits Rust/Markdown, cargo check, Clippy, suites Config/Config Desk/Wallet Desk/SOL Prices Desk/Backfill Desk et arbres de dépendances Backfill. Ce gate ouvre pre.004.

pre.004 — Transport readiness

Construire HttpTransportPool, dériver l'inventaire sûr des réseaux/rôles, vérifier le support simultané de getSignaturesForAddress et getTransaction, puis exposer backfill_options() sans provider, endpoint physique ni URL. BackfillDeskOptionsDto apparaît ici comme sous-contrat Transport seulement (configured_networks, rôles compatibles, diagnostic sûr, readiness) ; pre.007 l'étendra avec commitments, scopes et bornes après stabilisation du choix HTTP de pre.006. Une composition Transport avec plusieurs clusters HTTP actifs ou sans rôle compatible reste non-ready. Une erreur de résolution/construction Transport est conservée comme diagnostic sûr afin que le shell puisse rester ouvrable.

Le replay opérateur de pre.004 est acquis : audits, cargo check --workspace, Clippy, toutes les suites ciblées Backfill Desk et les deux arbres de dépendances passent. Le lancement cargo tauri dev confirme également le profil Logging supertrace, le profil Transport devnet_public, un réseau HTTP unique, un rôle compatible et transport_ready = true; les clics de tabs frontend apparaissent bien au niveau DEBUG.

pre.005 — Store readiness

Ouvrir uniquement ksp-store-lib::Store depuis le profil Store sélectionné par le composite. La Desk résout d'abord les settings Store, dérive leur réseau logique et exige un unique réseau Transport identique avant Store::open; aucun URI, backend physique ni détail de pool n'est projeté vers l'IPC. Après ouverture, un unique Store::health() borné produit store_ready, tandis que network_coherent et composition_ready rendent la chaîne Transport + Store explicite. Une erreur Config, ouverture ou health conserve le shell utilisable avec un diagnostic sûr, sans inventer de readiness.

Le Store ouvert reste détenu côté Rust et doit être fermé explicitement via Store::close() lors d'une demande de fermeture de la fenêtre principale. La Desk intercepte cette fermeture une seule fois, empêche la destruction immédiate, lance le close borné puis quitte l'application. Aucun BackfillRequest, BackfillJobRuntime, accès backend PostgreSQL direct ou capability Tauri supplémentaire n'est admis dans cette tranche.

pre.006 — Mainnet par défaut + sélection route HTTP

Faire de mainnet le profil composite par défaut, conserver supertrace pendant le développement et ajouter un profil mainnet_backfill_pool HTTP-only. Exposer dans backfill_options() des routes sûres dérivées des rôles Transport : backfill_pool pour Solana Public + PublicNode, backfill_solana_public et backfill_publicnode pour un ciblage explicite. Le frontend rend ce choix avant Start et trace les changements ; aucune URL/clé ne traverse IPC et ksp-job-backfill-lib n'est pas encore ouvert par la Desk.

pre.007 — DTO/request mapping

Ajouter ksp-job-api et ksp-job-backfill-lib comme dépendances backend directes de la Desk, sans ouvrir encore BackfillJobRuntime. Les DTO TS-RS app-owned exposent les quatre scopes HTTP existants, les commitments, min_context_slot sous forme de texte décimal, les bornes publiques Job et des defaults applicatifs bornés (page_size=100, max_pages=10, max_candidates=1000, hydration_concurrency=4). Le request DTO ne contient ni réseau, ni provider, ni endpoint, ni URL, ni JobId.

Le mapping Rust dérive le réseau du Store configuré, revalide http_role contre BackfillDeskOptionsDto::http_routes, parse adresse/signatures et délègue l'autorité finale des bornes/cohérences à BackfillRequest::new. Une commande backfill_validate_request utilise exactement ce mapping pour produire une projection sûre réduite à présence/comptage et paramètres non sensibles ; elle ne lance aucun Job. Le frontend matérialise le formulaire de campagne et le bouton Valider la requête ; adresse, ancre, signatures explicites et min_context_slot ne sont jamais journalisés.

pre.008 — runtime + Start

Ouvrir le Start réel en réutilisant strictement le mapping pre.007 : JobId généré côté backend, état single-active-run, construction BackfillJobRuntime, handle installé atomiquement avant tout spawn, puis exécution non bloquante sur le pool HTTP courant et le Store déjà ouvert. Le Store est temporairement prêté au run puis remis dans le slot applicatif après terminal ; aucune dépendance backend Store supplémentaire n'est ouverte. La réponse Start reste minimale (job_id, état initial) et aucun snapshot détaillé n'est encore projeté. La fermeture pendant un run reste une limite transitoire jusqu'au couloir Cancel/races de pre.010.

pre.009 — monitoring latest-value

Bridge direct de BackfillJobHandle::snapshots() vers un DTO applicatif sûr et complet, sans parser les logs. Le slot single-run conserve la source latest-value pendant le run et retient le dernier terminal après libération afin que backfill_status puisse resynchroniser l'UI même si un événement a été manqué.

Le backend émet ksp-backfill-status à partir de JobSnapshotSource::wait_for_change; cette primitive coalesce nativement les mises à jour intermédiaires et transporte toujours la dernière valeur complète. Le DTO expose JobId/kind, sequence décimale, lifecycle/completion, phase/scope/boundary, compteurs candidates/entities/observations/anomalies, maximum in-flight, checkpoint_present, contiguous_completed et code d'échec stable. Il n'expose ni adresse, signature, endpoint/provider, payload RAW, contexte d'erreur ni checkpoint lui-même. La terminaison réactive le Start frontend ; Cancel reste absent jusqu'à pre.010.

pre.010 — Cancel et races terminales

Ajouter backfill_cancel(job_id) avec BackfillCancelResponseDto { accepted, job_id, state }. Le JobId est celui généré par le backend et projeté par le monitoring ; il cible le slot actif pour empêcher un Cancel IPC retardé d'atteindre un run suivant. Le premier Cancel pré-terminal est accepté, les répétitions sont idempotentes et renvoient accepted=false, un terminal gagne sur un Cancel tardif et un JobId périmé est rejeté sans toucher au run courant.

Le frontend expose Annuler uniquement pour un status actif, trace seulement JobId/état/acceptation et se resynchronise par backfill_status. L'état cancelling reste l'intention coopérative : le runtime arrête les nouvelles admissions mais draine le travail déjà soumis au Store. À la fermeture de la fenêtre principale, le one-shot shutdown bloque d'abord les nouveaux Starts, demande ensuite best-effort l'annulation du run actif, puis poursuit le shutdown Store/process sans promettre un drain crash-safe. Resume reste hors tranche.

pre.011 — checkpoint/frontier et Resume

Conserver avec le dernier terminal la requête KSP ayant produit le checkpoint, uniquement dans l'état Rust de la Desk. ksp-job-backfill-lib ajoute BackfillRequest::resume_for_job : l'opération valide le checkpoint contre son JobId et son scope fingerprint d'origine, puis réémet uniquement l'identité Job pour le nouveau lifecycle sans exposer ni modifier cursor/frontier.

La commande backfill_resume() alloue un nouveau JobId backend, refuse un run actif ou l'absence de checkpoint, revalide la compatibilité réseau/rôle avec la composition courante, reconstruit BackfillJobRuntime et réutilise le même chemin de spawn/monitoring que Start. Le frontend expose Reprendre seulement sur un terminal avec checkpoint_present. Aucun checkpoint, adresse, signature ou paramètre de campagne ne traverse cette commande IPC.

pre.012 — frontend fonctionnel et polish

Formulaire complet, états responsive, instrumentation sûre, summary terminal, erreurs, boutons contextuels, aucun secret/browser storage. L'adresse reste une saisie libre, mais reçoit un autocomplete HTML via datalist alimenté depuis le registre canonique ksp-core-lib::entries()/ProgramIdEntry : aucune copie locale de Program IDs, et une valeur arbitraire valide reste toujours acceptée. Le comportement fonctionnel recherché est celui de l'ancien dataset ks-program-ids de kbot3, sans reprise de son code.

La tranche matérialise ce contrat via ProgramIdAutocompleteOptionDto, ajouté à BackfillDeskOptionsDto. Chaque <option> du datalist reçoit le Program ID canonique comme value et des data-* sûrs (code, name, domain, family, protocol) uniquement pour l'UX. Une sélection issue du registre ne journalise que le code KSP et le booléen de correspondance, jamais l'adresse saisie. La carte de monitoring reçoit en plus un résumé terminal explicite et les échecs Cancel/Resume sont projetés dans des feedbacks sûrs sans contexte arbitraire.

pre.013 — hardening et complétude

Aucune nouvelle capacité métier. La tranche ferme la surface V1 par des canaries dédiés : inventaire exact des dépendances KSP et interdictions des backends/clients physiques, inventaire exact des modules de production et suites dintégration, surface Tauri/contrôles frontend finaux, composition Config exacte sur devnet/mainnet/testnet, scan agrégé de sécurité IPC/frontend et contrôle de la discipline crate-root pour les DTO pub(crate) partagés introduits par la Desk.

Les nouvelles suites dependency_boundary.rs et release_completeness.rs complètent desktop_contract.rs, desktop_security.rs et config_composition.rs. Elles ne modifient ni runtime Job, ni Store, ni Transport, ni DTO/IPC, ni frontend.

Le replay workspace étendu après pre.013 a révélé une divergence antérieure du document Store committed : les profils réellement utilisés localement ont été passés à TLS disabled pour PostgreSQL local, tandis que la fixture et un test Config restaient sur verify_full. Cette divergence Config/runtime doit être réconciliée avant le gate final et consomme donc pre.014; le gate technique final est décalé à pre.015.

pre.014 — réconciliation TLS Store committed

Synchroniser config/std.store.json, sa fixture Config et les assertions committed sur PostgresTlsMode::Disabled pour les trois profils devnet/mainnet/testnet. Cette tranche ne change pas les capacités TLS du Store : verify_full reste supporté par le schema/runtime ; seule la politique des profils committed est réconciliée avec le PostgreSQL local réellement utilisé pour les smokes Backfill Desk. Aucun runtime Backfill n'est rouvert.

pre.015 — gate technique final

Le gate opérateur de pre.014 est propre : audits Rust/Markdown, cargo check --workspace, Clippy, les 128 tests unitaires et suites dintégration ksp-config-lib, les 50 tests unitaires et canaries ksp-job-backfill-lib, ainsi que toutes les suites ksp-app-backfill-desk passent. La divergence TLS committed est donc fermée avant la clôture technique.

La tranche pre.015 n'ajoute aucune capacité ni aucun test. Elle matérialise exclusivement le gate technique final : cargo fmt --all -- --check, audits, cargo check --workspace, Clippy workspace/all-targets/all-features avec -D warnings, tests workspace/all-targets/all-features, arbres Cargo ciblés de Backfill Desk et Job Backfill, inventaire des doublons workspace et cargo tauri build de ksp-app-backfill-desk. Un smoke Mainnet reste opt-in et non bloquant si l'environnement opérateur n'est pas explicitement sûr/disponible.

pre.016 — réconciliation documentaire

Le gate technique final pre.015 est intégralement vert : cargo fmt --check, audits, cargo check --workspace, Clippy workspace/all-targets/all-features avec -D warnings, cargo test --workspace --all-targets --all-features, arbres Cargo ciblés, cargo tree --duplicates et build Tauri Linux passent. Le run workspace agrège 1 494 tests passés, 0 échec et 15 tests ignorés explicitement opt-in/operator-only ; le build produit les bundles .deb, .rpm et .AppImage.

La tranche réconcilie exclusivement les documents durables : README/USAGE de Backfill Desk, index documentaires, plan/validation et architecture courante. Aucun runtime, test, frontend ou Config n'est rouvert.

pre.017 — préparation publication

Prompt suivant + CHANGELOG + ROADMAP uniquement avec le bump prerelease/delta requis.

rel.001 — publication stable

Mécanique de publication v0.3.7, sans rattrapage.

14. Hors périmètre

Store Desk/navigation RAW, Worker API/service daemon, scheduler/registry générique Job, checkpoint durable, retry Job, sélection provider physique, nouveau protocole Transport, migration Store, decoding/materialization, application globale/control desk.

15. Report transport gRPC

Le Backfill 0.3.7 reste HTTP-only. Une généralisation de ksp-job-backfill-lib et de Backfill Desk vers Yellowstone gRPC est reportée à une version ultérieure, avec 0.3.12+ comme cible indicative à réévaluer. WebSocket reste hors Backfill tant qu'un besoin historique concret ne le justifie pas.