# Validation v0.3.6 — Job API et premier backfill RAW ## 1. Statut de `pre.001` et de son fix - [X] Archive v0.3.5 testée intégralement avant extraction. - [X] Archive kbot3 testée intégralement et isolée de l'arbre source KSP. - [X] Noms d'entrées contrôlés contre chemins absolus, traversées et liens symboliques ZIP. - [X] Règles canoniques, architecture, roadmap, changelog et deltas antérieurs lus. - [X] Surfaces Core, Transport et Store réelles auditées. - [X] Documentation officielle Solana des deux appels RPC auditée. - [X] kbot3 utilisé uniquement comme référence fonctionnelle et corpus de scénarios. - [X] Matrice reprendre, redessiner, reporter ou rejeter consignée. - [X] Ownership, limites, notifications, retry, annulation, provenance et checkpoint décidés. - [X] Plan découpé en tranches atomiques de 15 à 20 minutes. - [X] Aucun code de crate, manifeste de crate ou test Rust généré en `pre.001`. - [X] Version workspace ouverte en `0.3.6-pre.1`. - [X] Sizing converti en sous-sections `### pre.NNN` et `#### pre.NNN-fix.MMM`. - [X] Faux négatif du validateur Markdown reproduit avec une ligne séparatrice espacée. - [X] Reconnaissance des séparateurs plausibles corrigée avant validation d'alignement. - [X] Alignements gauche, droit et centré reliés aux marqueurs de la ligne séparatrice. - [X] Cinq tests de régression positifs et négatifs ajoutés au validateur. - [X] Treize documents durables révélés par le validateur corrigé réalignés mécaniquement. - [X] Audit général corrigé : 264 tables et 141 fichiers propres. - [X] Anciens deltas publiés laissés byte-inchangés. - [X] Version workspace du correctif d'outillage synchronisée en `0.3.6-pre.1.fix.1`. ## 2. Preuve des archives d'entrée | Archive | SHA-256 | Résultat ZIP | Usage | |--------------------------------------------------------|--------------------------------------------------------------------|-------------------------------------|--------------------------------| | `khadhroony-solana-project-v0.3.5-thelatest1.zip` | `c395efb6a09c786069aa5063a7a414b55f8ae24e2b9d6eaa414b2f312cd62588` | 1 515 entrées, test intégral propre | Source exclusive de code | | `khadhroony-bot3_v0.5.3-pre.005-fix010-thelatest1.zip` | `ee47643b9f8b582ee8db97b2381ec107e45aef8c009fee44757531514615d318` | 2 501 entrées, test intégral propre | Référence fonctionnelle isolée | | `Texte collé.txt` | `0b86c7107349bcbf0a80319ba8cf9aabdd2809f27af9459592667f3e425e8d58` | Sans objet | Journal opérateur v0.3.5 | Aucune entrée absolue, traversée, avec séparateur inversé ou lien symbolique ZIP n'a été trouvée dans les deux archives. ## 3. Baseline v0.3.5 observée - [X] `scripts/audit_rust_workspace_rules.py` : propre avant modification. - [X] Le résultat historique `240 tables / 150 fichiers` est identifié comme incomplet : les séparateurs espacés n'étaient pas reconnus. - [X] Audits Rust workspace post-modification : propres, aucune crate Rust ajoutée. - [X] Le résultat historique `240 tables / 153 fichiers` de `pre.001` est identifié comme faux positif pour les nouveaux tableaux non alignés. - [X] Contrats et tailles des trois nouveaux fichiers vérifiés. - [X] Le journal opérateur fourni rapporte `cargo fmt`, audits, `cargo check`, `cargo clippy` et suites Interface ou Program verts sur v0.3.5. - [X] Gate opérateur de `pre.001-fix.001` : 5 tests Python, audit Markdown 264/141, audit Rust et `cargo check --workspace` verts. - [X] Gate opérateur de `pre.002` : `cargo fmt`, audits Rust/Markdown, `cargo check --workspace` et arbres Cargo normal/features verts. - [X] Échec de `pre.002` constaté dans la preuve opérateur : Clippy `--all-targets` et les tests compilent `unit_tests/lifecycle.rs`, où le helper `lifecycle()` est masqué par une variable homonyme (`E0618`, puis `E0282`). - [X] `pre.002-fix.001` renomme uniquement le helper en `new_lifecycle()` et synchronise ses six appels sans modifier le contrat public ni la matrice de transitions. - [X] Gate opérateur de `pre.002-fix.001` : `cargo fmt`, audits Rust/Markdown, `cargo check`, Clippy, dix unitaires + onze canaries `ksp-job-api`, toutes les suites workspace, `cargo test --workspace` et arbres Cargo Job API verts. - [X] L'environnement d'assemblage ne fournit pas l'exécutable `cargo` ; aucune validation Rust locale de `pre.003` ou de son fix n'est annoncée comme exécutée. - [X] Gate opérateur de `pre.003` : `cargo fmt`, audits Rust/Markdown et `cargo check --workspace` verts ; Clippy `--all-targets` et `cargo test -p ksp-job-api` échouent uniquement sur `E0423` dans le helper `exhausted_notification_sequence()`. - [X] Les arbres Cargo normal/features de ce gate confirment que `ksp-job-api` dépend toujours uniquement de `ksp-core-lib` et n'ouvre aucune feature. - [X] `pre.003-fix.001` remplace uniquement la construction via le re-export racine par le constructeur privé directement visible dans le module `notification`, sans changer l'API publique ni le nombre de tests. - [X] Gate opérateur de `pre.003-fix.001` : `cargo fmt`, audits Rust/Markdown, `cargo check`, Clippy, treize unitaires + quatorze canaries `ksp-job-api` et arbres Cargo normal/features verts. - [X] `pre.004` matérialise une voie observée additive de `getTransaction` sans modifier le client, les settings, le routage ni la politique de retry Transport ; gate opérateur vert. - [X] Le workspace comptait 14 crates avant `pre.005`; `ksp-job-backfill-lib` devient la 15e crate membre sans créer d'exécutable ni de Worker. - [X] Gate opérateur de `pre.005` : `cargo fmt`, audits Rust/Markdown et `cargo check --workspace` verts ; les 11 tests unitaires et 6 canaries `ksp-job-backfill-lib` sont verts. - [X] Le même gate révèle un unique échec Clippy `clippy::implicit_return` dans la closure privée qui dérive le curseur `before`; les arbres Cargo normal/features sont néanmoins exécutés et cohérents avec le graphe prévu. - [X] `pre.005-fix.001` ajoute uniquement le `return` explicite exigé dans cette closure et ne modifie ni valeur, ni pagination, ni identité réseau, ni dépendance, ni API publique. - [X] Gate opérateur de `pre.005-fix.001` : `cargo fmt`, audits Rust/Markdown, `cargo check`, Clippy, 11 unitaires + 6 canaries `ksp-job-backfill-lib` et arbres Cargo normal/features verts sur `0.3.6-pre.5.fix.1`. - [X] Versions d'en-tête du `Cargo.toml` racine et de `discovery.rs` corrigées dans la base opérateur avant `pre.006`. ## 4. Autorités et cohérence documentaire - [X] `RULES.md` et la hiérarchie documentaire ont été appliqués. - [X] Les chemins canoniques réels sous `docs/rules/` ont été retenus lorsque le prompt utilisait un chemin abrégé. - [X] Le nom fixé est `ksp-job-backfill-lib`. - [X] Les documents d'architecture courants sont réconciliés sur `ksp-job-backfill-lib`; les anciens plans historiques restent historiques et ne sont pas réécrits. - [X] `ksp-job-api` et `ksp-job-backfill-lib` sont obligatoires en parallèle dans la release finale. - [X] Worker API, application et pipeline RAW partagé sont explicitement hors v0.3.6. - [ ] Architecture, README, roadmap et contrats finaux réconciliés avant publication. ## 5. Contrat `ksp-job-api` - [X] `JobId` borné à 128 octets, validé, opaque et redacted en `Debug`. - [X] `JobKindCode` stable, borné et limité à l'alphabet sûr KSP. - [X] `JobCompletion` distingue `Complete` et `Partial` sans texte libre. - [X] Transitions `Created`, `Running`, `Cancelling`, `Completed`, `Cancelled` et `Failed` contrôlées. - [X] États terminaux immuables et lifecycle producteur non cloneable. - [X] `JobCancellationToken` cloneable, idempotent, `Send + Sync` et sans Tokio public. - [X] `JobNotificationSequence` strictement monotone avec overflow traité sans panic. - [X] `JobNotification` contient identité, kind, séquence, état et snapshot complet ; son `Debug` masque le snapshot et le contrat impose au snapshot concret de rester sûr et borné. - [X] `JobSnapshotSource` permet lecture courante et attente abstraite d'une valeur plus récente sans callback producteur ni type Tokio public. - [X] Aucun type Transport, Store, Logging, Tokio, serde, Worker ou Backfill dans l'API publique de `pre.003`; le futur abstrait utilise uniquement `std`. - [X] Canaries externes de construction, lifecycle, annulation, notifications latest-value, firewalls, complétude et sécurité matérialisées. - [X] Dix unitaires et onze canaries de `pre.002-fix.001` exécutés avec `cargo test -p ksp-job-api` par l'opérateur. ## 6. Notifications multi-listeners `pre.003` fige le contrat public et ses canaries de resynchronisation. `pre.009` matérialise maintenant le producer concret `ksp-job-backfill-lib` avec un `tokio::sync::watch` privé, un handle clonable et des canaries latest-value ; leur gate Rust opérateur reste à rejouer, donc les critères comportementaux ci-dessous restent ouverts jusqu'à exécution. - [ ] Stockage O(1) de la dernière valeur, sans historique non borné. - [ ] Un listener lent ne bloque jamais le producteur. - [ ] Plusieurs listeners progressent indépendamment. - [ ] Une séquence manquée se résout par resynchronisation du snapshot courant. - [ ] L'abandon ou l'échec d'un listener n'affecte pas le Job. - [ ] Le snapshot terminal reste disponible tant que le handle existe. - [ ] Aucun secret, URL, body RPC, liste massive ou message fournisseur n'est exposé. ## 7. Admission et portées `pre.005` matérialise les contrats et leurs tests. Le gate du fix confirme les 11 unitaires et 6 canaries avec Clippy vert. L'identité candidate est `(RawNetworkId, signature)` ; rôle HTTP, provider, endpoint et protocole ne participent ni à cette identité ni au fingerprint sémantique du scope. - [X] `LatestAddress`, `BeforeAddress`, `AfterAddress` et `ExplicitSignatures` couverts. - [X] Adresse validée par le type Core existant. - [X] Signature Base58 décodée vers exactement 64 octets, prouvée par le gate `pre.006-fix.002`. - [X] Engagement limité à `Confirmed` ou `Finalized`. - [X] Taille de page entre 1 et 1 000. - [X] Nombre de pages entre 1 et 10 000. - [X] Nombre de candidats entre 1 et 10 000. - [X] Concurrence d'hydratation entre 1 et 64. - [X] `min_context_slot` transmis sans en changer le sens. - [X] Checkpoint rejeté si son JobId ou son fingerprint de scope diffère ; canarie `pre.008-fix.001` exécutée avec succès. - [X] Aucun défaut d'application silencieux dans la bibliothèque. ## 8. Pagination, ordre et déduplication - [X] Latest respecte l'ordre officiel du plus récent au plus ancien. - [X] Before utilise une ancre exclusive et avance vers l'historique plus ancien. - [X] After atteint l'ancre, garde les plus proches candidats plus récents et produit un ordre déterministe. - [X] Ancre before absente acceptée comme curseur. - [X] Ancre after non atteinte bornée et signalée comme résultat partiel. - [X] Doublons inter-pages retirés à première occurrence. - [X] Doublons explicites retirés sans réordonner la liste. - [X] Limites de pages et candidats respectées sur tous les chemins. ## 9. Acquisition Transport et retry - [X] Les wrappers typés officiels restent l'unique chemin RPC, confirmé par audit de source jusqu'à `pre.008`. - [X] Retour observé additif de `getTransaction` matérialisé et gate opérateur vert. - [X] Canarie déterministe : un `429` sur le premier endpoint reroute et rapporte le second provider/endpoint victorieux ; gate opérateur vert. - [X] `HttpObservedValue` ne contient que valeur typée, endpoint sûr et provider ; URL, headers et body HTTP brut restent privés. - [X] Aucun retry, pacing ou sélection d'endpoint dans Job, confirmé par audit de source `pre.008`. - [X] Aucune détection d'erreur par chaîne dans la composition Backfill `pre.008`. - [ ] Une erreur Transport finale arrête les admissions avec un code Job sûr ; exécuteur et test `pre.008` matérialisés, gate opérateur à rejouer. ## 10. RAW v1 et provenance `pre.006` matérialise cette surface et ses tests statiques/unitaires. Le gate opérateur confirme les audits, `cargo check`, les 19 unitaires et les 7 canaries, mais Clippy émet `clippy::large_enum_variant` sur `BackfillHydrationOutcome` : `Available(BackfillRawAcquisition)` contient au moins 560 octets alors que `Missing(reference)` en contient environ 88. Le résultat fonctionnel est vert, mais la tranche n'est pas considérée warning-free. `pre.006-fix.001` conserve l'API publique de l'enum et introduit une seule indirection privée dans `BackfillRawAcquisition`. Aucun `#[allow]` n'est ajouté. Les getters et `into_parts` conservent leurs signatures, et une canarie vérifie que `BackfillRawAcquisition` reste de la taille d'un pointeur. Le gate opérateur du fix confirme ensuite les audits, `cargo check`, les 20 unitaires et les 7 canaries, mais Clippy signale encore deux `clippy::explicit_auto_deref` dans `transaction()` et `observation()`. `pre.006-fix.002` remplace uniquement `&(*self.inner).transaction` et `&(*self.inner).observation` par les accès auto-deref idiomatiques `&self.inner.transaction` et `&self.inner.observation`. La Box privée unique, l'API publique et tous les invariants RAW/provenance restent inchangés. Le gate opérateur de `fix.002` est intégralement vert : audits Rust/Markdown, `cargo check`, Clippy sans warning, 20 unitaires, 7 canaries d'intégration et arbres Cargo passent sur `0.3.6-pre.6.fix.2`. - [X] Identité logique future auditée : transaction/signature scoping par `RawNetworkId`, jamais par rôle/provider/endpoint/protocole. - [X] Le Store PostgreSQL actuel est mono-réseau via `ksp_store_identity`; un futur backend multi-réseaux devra préserver `(network, signature)` par clé/partition équivalente. - [X] Format `ksp.solana.raw_transaction`, version `1`, figé. - [X] `getTransaction` demandé en `base64` avec version maximale `0`. - [X] Bytes JSON compacts déterministes et golden tests stables. - [X] Transaction binaire conservée sans décodage métier. - [X] `meta`, `version` et `transactionIndex` distinguent absent, `null` et valeur. - [X] Slot et block time non dupliqués dans le payload. - [X] Block time négatif rejeté explicitement. - [X] Hash SHA-256 et taille calculés sur les bytes exacts. - [X] Provenance contient fournisseur, protocole, méthode, endpoint sûr, engagement et réception. - [X] Clé d'observation domain-separated et déterministe, couverte par le gate `pre.006-fix.002`. - [X] Endpoint différent produit une nouvelle observation légitime. ## 11. Persistance Store `pre.007` matérialise la composition Store normale sans élargir les responsabilités. Le chemin public consomme un `BackfillHydrationOutcome`, contrôle d'abord le réseau logique du Store, puis utilise exclusivement l'écriture atomique transaction + observation de `ksp-store-lib`. `Missing` ne déclenche aucune écriture. Un conflit de contenu Store est converti en outcome Backfill explicite afin que les tranches de frontier/snapshot puissent le compter puis le traiter comme trou/échec, sans le confondre avec l'idempotence. Le gate opérateur `pre.007` est intégralement vert : audits, `cargo check`, Clippy sans warning, 29 unitaires, 8 canaries et arbres Cargo passent. - [X] Dépendance unique vers `ksp-store-lib`, jamais vers backend ou API directement, confirmée par audit de manifeste/source. - [X] Écriture atomique transaction plus observation composée en mode `Normal` dans l'unique chemin de persistance. - [X] Aucune prélecture de présence avant hydratation ou persistance. - [X] Entités insérée, déjà présente et purgée distinguées au gate Rust `pre.007`. - [X] Observations insérée, déjà présente et non enregistrée distinguées au gate Rust `pre.007`. - [X] `getTransaction = null` ne produit aucune écriture fabriquée au gate Rust `pre.007`. - [X] Conflit Store reste un outcome terminal visible, distinct d'un succès idempotent, au gate Rust `pre.007`. - [X] Même JobId et même endpoint donnent une relance idempotente au gate Rust `pre.007`. - [X] `ForceRehydrate` absent du chemin normal `pre.007` par audit de source. ## 12. Concurrence, frontière et checkpoint `pre.008` matérialise un checkpoint opaque caller-owned, sans table Store ni promesse de reprise crash-safe. `BackfillRequest::with_checkpoint` valide `JobId` et fingerprint avant usage. L'exécuteur utilise une collection `FuturesUnordered` strictement bornée par `hydration_concurrency`, réconcilie les fins hors ordre par index stable et draine les futures déjà admises après la première erreur fatale. Le gate initial révèle uniquement un shadowing de helper dans une canarie ; `pre.008-fix.001` le corrige sans changer le contrat. Le gate réduit du fix est intégralement vert : audits, `cargo check`, Clippy sans warning, 39 unitaires et 9 canaries d'intégration passent sur `0.3.6-pre.8.fix.1`. - [X] Nombre d'hydratations en vol borné par la requête, prouvé par `pre.008-fix.001`. - [X] Aucune file de candidats non bornée dans l'exécuteur `pre.008`; les notifications concrètes restent à valider avec `pre.009`. - [X] Résultats hors ordre réconciliés par index stable. - [X] Frontière avance sur insert, already present et purged skip durables. - [X] Missing, conflit, conversion, Transport et Store créent un trou ; la branche annulation est matérialisée dans `pre.009` et reste à exécuter. - [X] Frontière ne saute jamais un trou même si des résultats ultérieurs terminent. - [X] Latest rejoue la vue courante de façon idempotente. - [X] Before reprend au curseur contigu. - [X] After et explicite rejouent le scope borné avec préfixe validé. ## 13. Annulation et résultats terminaux `pre.009` matérialise le runtime concret, le canal latest-value et les chemins d'annulation/drainage. Le gate opérateur exécute avec succès les 47 unitaires et 10 canaries couvrant l'attente RPC de découverte, une future pré-Store longue, le drainage des candidats déjà admis, les listeners lents/indépendants, la rétention terminale et les arbitrations terminales. La qualité Rust reste néanmoins bloquée : `pre.009-fix.001` corrige les chemins crate-root/visibilités et le warning Clippy de la canarie publique, puis son gate révèle `E0423` sur la construction du fingerprint public opaque ; `pre.009-fix.002` corrige ce dernier point et reste à valider. - [ ] Annulation idempotente et état `Cancelling` observable. - [ ] Admissions arrêtées après observation du token. - [ ] Attente de page et hydratation RPC longues abandonnables. - [ ] Persistance déjà soumise drainée jusqu'à un résultat connu. - [ ] Course complétion contre annulation déterministe. - [ ] Course erreur fatale contre annulation déterministe. - [ ] Missing seul donne `Completed` avec résultat `Partial`. - [ ] Conflit, conversion ou infrastructure donnent `Failed`. - [ ] Checkpoint final cohérent avec le dernier préfixe durable. ## 14. Firewalls et qualité Rust - [X] `ksp-job-api` dépend exactement de Core et n'a aucune feature, dev-dependency ou build-dependency. - [X] `ksp-job-backfill-lib` ne dépend pas de Config, App, Wallet, Program, Interface ou backend Store ; `ksp-store-lib` est consommée avec `default-features = false`. - [ ] Aucun retour de dépendance vers Job depuis les couches basses. - [X] Versions/features auditées : aucune nouvelle version externe ; `sha2`, `futures-util` et `tokio` réutilisent les entrées workspace existantes. `futures-util` reste un détail normal privé depuis `pre.008` et `pre.009` promeut Tokio en dépendance normale privée limitée à `macros` + `sync`; aucun type Tokio n'est exposé. - [X] `pre.005` matérialise 11 tests unitaires et 6 canaries d’intégration ; le gate opérateur les exécute tous avec succès. - [X] `pre.006` matérialise 19 tests unitaires et 7 canaries d’intégration ; le gate opérateur les exécute tous avec succès, avec uniquement le warning Clippy corrigé par `pre.006-fix.001`. - [X] `pre.009` : `cargo check --workspace` vert et 47 unitaires + 10 canaries vertes ; Clippy signale 3 warnings de normalisation/API de test, corrigés par `pre.009-fix.001`; le gate de ce fix révèle ensuite `E0423`, corrigé par `pre.009-fix.002` et encore à revalider. - [X] Audit manuel `pre.009-fix.001` : les items partagés de `ksp-job-backfill-lib` passent par `crate::Item`; `BackfillRuntimeControl`/`TerminalClaim` restent privés et les unit tests runtime utilisent `super::Item`, conformément à RUST-IMPORT-009/012 et RUST-API-007. - [ ] `pre.009-fix.002` : `E0423` corrigé en confinant la construction du champ privé dans `BackfillScopeFingerprint::from_bytes`; gate opérateur Rust à rejouer. - [ ] `cargo fmt --all -- --check` vert. - [X] `scripts/audit_rust_workspace_rules.py` vert sur `pre.005` dans l'environnement d'assemblage et dans le gate opérateur. - [X] `scripts/audit_markdown_tables.py` vert sur `pre.005` dans le gate opérateur (264 tables / 147 fichiers, delta inclus). - [X] Contrats de fichiers de `FILE_CONTRACTS.md` vérifiés sur chaque ajout de `pre.001`. - [X] `cargo check --workspace` vert sur `pre.005`; le fix ne change qu'une closure privée refusée par Clippy. - [ ] `cargo clippy --workspace --all-targets --all-features -- -D warnings` vert. - [ ] `cargo test --workspace --all-targets --all-features` vert. - [ ] `cargo tree -d` examiné et doublons justifiés. ## 15. Preuves d'intégration et fermeture - [X] Fake Transport et fake Store déterministes sans backend direct exécutés avec succès au gate `pre.007`; fake processor concurrent `pre.008-fix.001` exécuté avec succès. - [ ] Vertical découverte, hydratation, conversion, persistance et observation couvert. - [ ] Smoke Devnet plus PostgreSQL configuré exécuté si l'environnement explicite est disponible. - [ ] Aucun endpoint payant, credential ou donnée sensible requis par les tests normaux. - [ ] Gates technique, documentaire et de publication séparés. - [ ] CHANGELOG et ROADMAP alignés seulement après preuve technique. - [ ] Archives de release minimales et vérifiées. - [ ] Version stable publiée uniquement après tous les critères obligatoires. ## 16. Règle de vérité Une case n'est cochée que par une preuve effectivement exécutée ou un audit effectivement réalisé. L'absence de `cargo`, de PostgreSQL configuré ou d'accès live est rapportée comme non exécutée ; elle n'est jamais convertie en succès implicite.