v0.3.7-pre.001
This commit is contained in:
294
docs/plans/028-V0_3_7_BACKFILL_DESK_PLAN.md
Normal file
294
docs/plans/028-V0_3_7_BACKFILL_DESK_PLAN.md
Normal file
@@ -0,0 +1,294 @@
|
||||
<!-- file: docs/plans/028-V0_3_7_BACKFILL_DESK_PLAN.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# 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 :
|
||||
|
||||
```text
|
||||
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.
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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.
|
||||
|
||||
### 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.
|
||||
Reference in New Issue
Block a user