21 KiB
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 compatibles, commitments, scopes, bornes, readiness | Config + Transport + constantes Backfill | sûre |
BackfillStartRequestDto |
UI -> Rust | scope inputs, commitment, rôle, bornes, optional min context slot | conversion stricte vers types KSP | métier borné |
BackfillRunStatusDto |
Rust -> UI | job state, phase, compteurs, boundary, checkpoint_present, contiguous_completed, failure code | JobNotification<BackfillJobSnapshot> |
sûre |
BackfillCancelResponseDto |
Rust -> UI | accepted + état courant | BackfillJobHandle |
sûre |
BackfillResumeResponseDto |
Rust -> UI | accepted/new job status | checkpoint Rust détenu par AppState | sûre |
SafeAppErrorDto |
Rust -> UI | domain/code + message app maîtrisé | mapping applicatif | sûre |
Commandes prévues :
backfill_options() -> BackfillDeskOptionsDto
backfill_status() -> BackfillRunStatusDto
backfill_start(request) -> BackfillRunStatusDto
backfill_cancel() -> BackfillCancelResponseDto
backfill_resume() -> BackfillResumeResponseDto
backfill_reset() -> BackfillRunStatusDto
Le monitoring continu ne dépend pas du parsing de logs. Le backend possède un bridge latest-value qui attend JobSnapshotSource::wait_for_change, projette le snapshot et émet un événement Tauri borné, par exemple backfill-status-changed. 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 |
console_info |
mainnet_public |
mainnet |
mainnet-beta |
testnet |
console_info |
publicnode_testnet |
testnet |
testnet |
Le default V1 est devnet, afin de ne pas lancer implicitement une campagne mainnet. 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 rôles présentés à l'UI sont dérivés des snapshots/settings Transport, dédupliqués, puis validés côté Rust comme capables de sélectionner à la fois getSignaturesForAddress et getTransaction. Le rôle default est actuellement le seul rôle des profils standard, mais il n'est pas codé en dur comme contrat du Desk.
Les resources bundle minimales sont le composite Backfill Desk, std.logging.json, std.transport.json, std.store.json et leurs schemas, plus composite.schema.json. Les documents Wallet/offchain ne sont pas embarqués sans besoin démontré.
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 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 ;
- 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 uniquement dans Rust. L'UI voit checkpoint_present et contiguous_completed, jamais les octets/identité internes du checkpoint.
Resume reconstruit une requête sémantiquement identique avec un nouveau lifecycle contrôlé et réattache le checkpoint via BackfillRequest::with_checkpoint. Le backend doit préserver les éléments participant au scope fingerprint ; toute modification de scope/commitment/bornes sémantiques force une nouvelle campagne et invalide 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 | uniquement rôle/cluster/readiness sûrs ; aucune URL |
| 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 composite Backfill Desk, resources minimales, bootstrap Config/Logging et canaries packaging/composition sans encore ouvrir réseau/Store réel.
pre.004 — Transport readiness
Construire HttpTransportPool, dériver réseau/role inventory sûr, vérifier support des deux RPC et produire options DTO sans provider/URL.
pre.005 — Store readiness
Ouvrir ksp-store-lib::Store, vérifier réseau Store/Transport avant run, lifecycle de fermeture et erreurs sûres. Scinder ici plutôt que mélanger Transport + Store dans une seule tranche large.
pre.006 — DTO/request mapping
DTO TS-RS app-owned, quatre scopes, commitments, min context slot, bornes backend-owned, signatures hostiles et validation de rôle/réseau.
pre.007 — runtime + Start
Single-active-run state, construction BackfillJobRuntime, spawn non bloquant, handle installé avant exécution et snapshot initial/terminal.
pre.008 — monitoring latest-value
Bridge de snapshots, status DTO, événements coalescés, compteurs complets, resynchronisation et absence de log parsing.
pre.009 — Cancel et races terminales
Cancel, état cancelling, idempotence UX, concurrence Start/Cancel/terminal, sémantique de drain Store et fermeture app.
pre.010 — checkpoint/frontier et Resume
Projection sûre, conservation Rust-only du checkpoint, reprise in-session et invariants par scope.
pre.011 — frontend fonctionnel et polish
Formulaire complet, états responsive, instrumentation sûre, summary terminal, erreurs, boutons contextuels, aucun secret/browser storage.
pre.012 — hardening et complétude
Tests desktop/security/dependency/composition/release completeness, canaries DTO et scan des dépendances/interdictions.
pre.013 — gate technique final
cargo fmt, audits, check/clippy/tests workspace, arbres Cargo utiles, cargo tauri build, smoke opt-in si environnement sûr disponible.
pre.014 — réconciliation documentaire
README/USAGE/plan/validation et architecture seulement si la surface finale l'exige. Aucun nouveau runtime.
pre.015 — préparation publication
Prompt 0.3.8, CHANGELOG et 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.