# Validation `0.3.5` — Interface passive acquisition events ## 1. Portée Ce document est ouvert par `0.3.5-pre.001`, corrigé par `0.3.5-pre.001-fix.001`, enrichi par `0.3.5-pre.002` puis par `0.3.5-pre.003`. `pre.002` matérialise `SlotLifecycleEvent`; `pre.003` ferme le gate `TransactionExecutionEvent` et admet la seconde famille passive minimale. Base : ```text v0.3.4 workspace.package.version = 0.3.4 ``` Version de travail : ```text 0.3.5-pre.3 ``` ## 2. Gate d'entrée `v0.3.4` Le log opérateur fourni avec l'archive indique un gate stable `v0.3.4` propre : audits Rust/Markdown, `cargo check`, Clippy, tests ciblés des crates, `cargo test --workspace`, `ksp-store-lib --no-default-features` et graphes Store ont été exécutés sans échec visible ; les smokes réseau restent explicitement ignorés/opt-in. Cette preuve est l'entrée de `0.3.5`. Elle n'est pas réétiquetée comme validation exécutée dans l'environnement d'assemblage de `pre.001`. ## 3. Gate de lecture `pre.001` | Contrôle | Résultat | Preuve / décision | | ------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------- | | règles globales relues | PASS | familles KSP-API/TRANSPORT/STORE/NOTIFY/PROC/REL et DEP applicables relues | | architecture durable relue | PASS | Interface passif, Transport protocol/runtime, Store persistant, composition owner des conversions | | fondation Interface stable relue | PASS | surface Program petite ; dépendance normale Core-only | | Store API RAW relu | PASS | `RawTransaction*` + `RawAccount*` restent Store-owned | | Store/PostgreSQL `0.3.2`–`0.3.4` relu | PASS | RAW physique 10/10 fermé ; aucune rétention account | | surfaces HTTP/WS/gRPC/Helius relues | PASS | status/log/slot/vote/account/transaction/block/Entry inventoriés | | documentation Solana courante auditée | PASS | `slotSubscribe`, `slotsUpdatesSubscribe`, status/log/vote/account/program, getTransaction/getBlock | | Yellowstone upstream courant audité | PASS | `SlotStatus` et familles SubscribeUpdate courantes | | Helius courant audité | PASS | standard WSS préserve wire Solana ; Enhanced `transactionSubscribe` reste extension provider | | producer/consumer inventory | PASS | lifecycle slot 7 stages admis ; TransactionExecutionEvent rouvert comme candidat actif | | threat model | PASS | mega enum, Option soup, Store duplication, mapping lifecycle explicite et provider promotion couverts | | sizing release | PASS | 8 prereleases prévues avant `rel.001` ; second candidat soumis à gate dédié | ## 4. Matrice de décision par famille | Famille | Décision | Owner | Motif déterminant | | ------------------------------------- | ------------------- | ------------------------------ | ---------------------------------------------------------------------------------------- | | slot lifecycle intersection | ADMIS | Interface | 7 faits compacts normalisés ; détails protocol/provider restent Transport | | transaction execution | ADMIS `pre.003` | Interface | `slot + TransactionSignature + Succeeded/Failed` multi-producer | | logs realtime | IDÉE DIFFÉRÉE | Interface si futur gate | payload variable/bornes/consumer non démontrés ; ne pas mélanger avec execution | | signature commitment/snapshot | REPORTÉ | Transport | HTTP snapshot != WS one-shot commitment ; distinct de l'exécution | | vote | REPORTÉ | Transport | gossip pré-consensus != transaction qualifiée `is_vote` | | account/program | REJET Interface | Store/Transport | risque de doublon `RawAccountState`/observation ou wrapper Transport | | transaction | REJET Interface | Store/Transport | `RawTransaction`/observation déjà persistants | | block | REJET Interface | Transport | conteneur/payload d'acquisition ; aucun besoin passif transversal démontré | | Yellowstone Entry | REPORTÉ | Transport DTO | mono-producer aujourd'hui ; un futur fait transversal KSP serait réaudité pour Interface | | persisted-data available notification | REJET Interface | Store API | ownership normatif `KSP-NOTIFY-001..006` | | Helius Enhanced transaction | PRODUCTEUR ADMIS | Transport DTO / Interface fact | DTO provider-specific ; projection conservative vers le fait commun admis | ## 5. Intersection lifecycle retenue | Stage Interface prévu | Producer Solana standard | Producer Yellowstone | Verdict | Détails exclus du contrat commun | | ------------------------- | -------------------------------------- | -------------------- | ------- | -------------------------------------------------------------------------------- | | `Processed` | `slotSubscribe` | `Processed` | PASS | WS parent/root ; Yellowstone filters/created_at/parent | | `FirstShredReceived` | `slotsUpdates::FirstShredReceived` | `FirstShredReceived` | PASS | timestamps/metadata source | | `Completed` | `slotsUpdates::Completed` | `Completed` | PASS | timestamps/metadata source | | `CreatedBank` | `slotsUpdates::CreatedBank` | `CreatedBank` | PASS | parent reste dans le DTO Transport riche | | `Dead` | `slotsUpdates::Dead` | `Dead` | PASS | diagnostic `err`/`dead_error` et timestamp restent Transport | | `OptimisticallyConfirmed` | `slotsUpdates::OptimisticConfirmation` | `Confirmed` | PASS | nom KSP conserve l'optimistic confirmation ; delivery/metadata restent Transport | | `Rooted` | `rootSubscribe` / `slotsUpdates::Root` | `Finalized` | PASS | nom KSP conserve le fait root ; `Finalized` reste un label Yellowstone source | | — | `slotsUpdates::Frozen` | — | FAIL | pas d'intersection | ## 6. Validation anti-Option-soup Les modèles suivants sont explicitement **non admis** par le gate : ```text TransactionStatusObservation { confirmations?: ..., confirmation_status?: ..., received?: ..., is_vote?: ..., transaction_index?: ..., logs?: ..., ... } SlotLifecycleEvent { parent?: ..., root?: ..., timestamp?: ..., dead_error?: ..., provider?: ..., ... } ``` La surface admise reste conceptuellement : ```text SlotLifecycleEvent { slot, stage } ``` Le candidat séparé, non encore admis, reste : ```text TransactionExecutionEvent { slot, signature, outcome } ``` ## 7. Validation anti-duplication Store | Modèle Store stable | Action `0.3.5` | Justification | | ------------------------------- | ------------------- | ---------------------------------------------- | | `RawTransaction` | inchangé | payload durable/replayable | | `RawTransactionObservation` | inchangé | provenance persistante | | `RawAccountState` | inchangé | état account durable | | `RawAccountObservation` | inchangé | observation persistante | | pagination/cursors RAW | inchangés | contrats de navigation Store | | retention/tombstone transaction | inchangés | lifecycle de persistence Store | | notification after commit | non implémentée ici | ownership Store API réservé par `KSP-NOTIFY-*` | Canari conceptuel : aucun futur fichier source Interface de `0.3.5` ne doit importer `ksp_store_api`, `ksp_store_lib` ou copier leurs modèles. ## 8. Validation dependency/ownership État de l'archive stable inspecté : ```text crates/ksp-interface-lib/Cargo.toml runtime dependency = ksp-core-lib seulement ``` Cible `0.3.5` : ```text ksp-interface-lib -> ksp-core-lib ksp-interface-lib -X-> ksp-onchain-transport-lib ksp-interface-lib -X-> ksp-store-api ksp-interface-lib -X-> ksp-store-lib ksp-interface-lib -X-> ksp-program-api ksp-interface-lib -X-> serde/tracing/tokio/channel runtime additions ``` Le gate opérateur de `pre.001` confirme `cargo check --workspace`, Clippy et les tests `ksp-interface-lib`. Les graphes `cargo tree` restent réservés au gate technique final de la release. ## 9. Consumer concret retenu Consumer proche documenté par l'architecture : futur worker RAW live / composition d'acquisition. Usage possible sans dépendance protocol-specific : ```text Solana standard WS -----------+ +-> converter composition -> SlotLifecycleEvent -> réaction lifecycle du consumer Yellowstone gRPC -------------+ ``` `0.3.6` backfill n'est pas forcé d'utiliser ce type ; il reste une composition historique Transport + Store. ## 10. Threat gates | Gate | Attendu `0.3.5` | Statut courant | | ------------------------------------ | ------------------------------------------------- | ------------------ | | mega enum | absent | PLAN PASS | | protocol/provider enum leakage | absent | PLAN PASS | | timestamp semantics conflated | absent | PLAN PASS | | root/finalized label confusion | évitée par le stage KSP `Rooted` | PLAN PASS | | optimistic/confirmed label confusion | évitée par le stage KSP `OptimisticallyConfirmed` | PLAN PASS | | dead diagnostic in shared API | absent | PLAN PASS | | RAW Store duplication | absent | PLAN PASS | | event persistence | absent | PLAN PASS | | event bus/runtime | absent | PLAN PASS | | network id duplicated from Store | absent | PLAN PASS | | cross-network use | composition doit conserver son scope réseau | À CANARIER | | public enum evolution | `SlotLifecycleStage` doit être non-exhaustive | IMPLÉMENTÉ pre.002 | | Core-only graph | aucune dependency nouvelle | PASS opérateur | | external consumer | type consommable depuis crate externe | CANARI pre.002 | ## 11. Fichiers de `pre.001` Ajoutés : ```text docs/plans/026-V0_3_5_INTERFACE_ACQUISITION_EVENTS_PLAN.md docs/validation/022-V0_3_5_INTERFACE_ACQUISITION_EVENTS.md deltas/0.3.5/pre.001.md ``` Modifié : ```text Cargo.toml ``` Aucun autre fichier ne doit changer dans cet overlay. ## 12. Validations statiques de l'overlay initial L'overlay `pre.001` avait exécuté les audits disponibles dans l'environnement d'assemblage : ```text python3 scripts/audit_rust_workspace_rules.py -> General Rust rule audit: clean -> Rust export completeness audit: 0 candidate(s) -> KSP workspace Rust rule audit: clean python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.5 -> Markdown table audit: clean (251 table(s), 137 file(s)) ``` ## 13. Gate opérateur `pre.001` reçu avant `fix.001` L'opérateur a rejoué depuis un `cargo clean` : ```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.5 cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-interface-lib ``` Résultat : **PASS intégral**. Preuves synthétiques : ```text General Rust rule audit: clean Rust export completeness audit: 0 candidate(s) KSP workspace Rust rule audit: clean Markdown table audit: clean (251 table(s), 137 file(s)) cargo check --workspace -> PASS cargo clippy --workspace --all-targets -> PASS ksp-interface-lib unit tests -> 10 passed ksp-interface-lib dependency_boundary -> 4 passed ksp-interface-lib external_consumer -> 1 passed ksp-interface-lib public_api -> 5 passed ksp-interface-lib release_completeness -> 3 passed doc-tests -> 0 failed ``` `pre.001-fix.001` est documentation-only ; il ne modifie ni Cargo ni Rust. L'opérateur doit néanmoins rejouer les deux audits Markdown/Rust après application du fix pour confirmer l'overlay final. ## 14. Exit gate `pre.001-fix.001` Le gate corrigé impose désormais : ```text workspace.package.version = 0.3.5-pre.1 inchangée SlotLifecycle admis avec 7 stages stages = Processed / FirstShredReceived / Completed / CreatedBank / Dead / OptimisticallyConfirmed / Rooted Frozen reste hors intersection TransactionExecutionEvent = candidat actif mais non encore admis TransactionLogEvent = idée différée, distincte de l'exécution getSignatureStatuses/signatureSubscribe = snapshot/commitment Transport, non fusionnés avec execution Helius transactionSubscribe et Yellowstone Entry restent des DTOs Transport un futur fait provider-neutral produit par une extension provider peut appartenir à Interface après gate aucun fichier Rust/Transport/Store/Cargo n'est modifié par le fix ``` ## 15. Gate opérateur post-`pre.001-fix.001` Avant l'ouverture de `pre.002`, l'opérateur a rejoué les audits demandés sur l'état corrigé : ```text 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.5 ``` Résultat fourni : **PASS**. ```text General Rust rule audit: clean Rust export completeness audit: 0 candidate(s) KSP workspace Rust rule audit: clean Markdown table audit: clean (240 table(s), 138 file(s)) ``` Ce résultat constitue le gate d'entrée immédiat de `0.3.5-pre.002`. ## 16. Implémentation `0.3.5-pre.002` `pre.002` ajoute exactement une famille passive provider-neutral à `ksp-interface-lib` : ```text SlotLifecycleStage Processed FirstShredReceived Completed CreatedBank Dead OptimisticallyConfirmed Rooted SlotLifecycleEvent new(slot, stage) slot() stage() ``` Propriétés de représentation matérialisées : ```text SlotLifecycleStage -> #[non_exhaustive] + Clone + Copy + Debug + Eq + PartialEq SlotLifecycleEvent -> champs privés + Clone + Copy + Debug + Eq + PartialEq slot -> u64 conservé exactement, y compris u64::MAX validation -> aucune admission faillible error code -> aucun nouvel error code serde/codec -> absent runtime/logging -> absent Transport/Store -> aucune dépendance ni conversion ``` Le graphe Cargo reste inchangé pour `ksp-interface-lib` : son manifest n'est pas modifié et sa seule dépendance normale demeure `ksp-core-lib`. Canaris ajoutés/ajustés : ```text unit_tests/slot_lifecycle.rs -> 7 stages distincts -> traits Copy/Eq attendus -> domaine u64 complet -> Debug borné et provider-neutral tests/slot_lifecycle_public_api.rs -> construction et getters depuis crate root -> match downstream avec wildcard imposé par #[non_exhaustive] tests/release_completeness.rs -> inventaire crate-root mis à jour à 8 reexports -> inventaire de modules mis à jour avec slot_lifecycle uniquement -> absence de serde/tracing/Transport/Store dans la racine Interface ``` `TransactionExecutionEvent` reste **non implémenté** et réservé au gate `pre.003`. ## 17. Fichiers de `pre.002` Modifiés : ```text Cargo.toml crates/ksp-interface-lib/src/lib.rs crates/ksp-interface-lib/tests/release_completeness.rs docs/validation/022-V0_3_5_INTERFACE_ACQUISITION_EVENTS.md ``` Ajoutés : ```text crates/ksp-interface-lib/src/slot_lifecycle.rs crates/ksp-interface-lib/unit_tests/slot_lifecycle.rs crates/ksp-interface-lib/tests/slot_lifecycle_public_api.rs deltas/0.3.5/pre.002.md ``` Explicitement inchangés : ```text crates/ksp-interface-lib/Cargo.toml crates/ksp-onchain-transport-lib/** crates/ksp-store-api/** crates/ksp-store-lib/** crates/ksp-store-postgres-lib/** README.md ROADMAP.md CHANGELOG.md ``` ## 18. Gate opérateur demandé pour `pre.002` Après application de l'overlay : ```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.5 cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-interface-lib cargo test -p ksp-program-api ``` Les validations Cargo de `pre.002` restent **à exécuter par l'opérateur** ; elles ne sont pas déclarées réussies par l'environnement d'assemblage. ## 19. Gate opérateur `pre.002` et correction `pre.002-fix.001` Le gate opérateur de `pre.002` confirme que le contrat fonctionnel `SlotLifecycleEvent` compile et que ses tests ciblés passent, mais la tranche n'est pas admissible en l'état : l'audit Rust détecte quinze violations `RUST-FMT-101` dans les nouveaux tests et Clippy rejette deux usages de `?` ainsi que des closures à retour implicite. Les deux nouveaux tests d'intégration exposent également un warning `missing_docs` au niveau crate. `pre.002-fix.001` corrige uniquement ces défauts de conformité : suppression des lignes vides à l'intérieur des fonctions, propagation d'erreur explicite par `match`, `return` explicite dans les closures concernées et documentation crate-level des tests d'intégration. Aucun contrat public `SlotLifecycleEvent` / `SlotLifecycleStage` n'est modifié. Comme le fix modifie des sources Rust, la version workspace évolue conformément à la politique KSP : ```text 0.3.5-pre.2.fix.1 ``` Le nom documentaire de la correction reste `0.3.5-pre.002-fix.001`. ## 20. Gate opérateur `pre.002-fix.001` Le gate opérateur du `2026-08-31` confirme : ```text General Rust rule audit: clean Rust export completeness audit: 0 candidate(s) KSP workspace Rust rule audit: clean cargo check --workspace: PASS cargo clippy --workspace --all-targets: PASS cargo test -p ksp-interface-lib: PASS cargo test -p ksp-program-api: PASS ``` Le seul défaut restant est documentaire : deux lignes vides consécutives dans ce fichier de validation. L'opérateur demande explicitement de ne pas créer un fix dédié pour ce seul défaut ; `pre.003` le corrige avec ses propres modifications. ## 21. Gate `TransactionExecutionEvent` — `pre.003` ### 21.1 Représentation de signature Verdict : `PASS`. La primitive admise est : ```text TransactionSignature([u8; 64]) ``` Contraintes : - construction depuis 64 octets déjà décodés uniquement ; - aucun base58/serde/codec dans Interface ; - `Debug` masque systématiquement les bytes ; - aucune dependency Solana supplémentaire ; - aucune capability de signature Wallet ; il s'agit uniquement d'une identité transactionnelle passive observée. `ksp-store-api::RawTransactionSignature` reste Store-owned. Aucun alias, reexport ou conversion implicite cross-domain n'est introduit. Une future composition peut effectuer explicitement la conversion via les 64 octets lorsque nécessaire. ### 21.2 Convergence producer | Producer | Slot | Signature | Outcome | Metadata volontairement exclue | Verdict | | -------------------------------------- | ----------------------- | ----------------------------------- | ----------------------------------- | -------------------------------------------------------------- | ------- | | Solana WS `logsSubscribe` | `context.slot` | base58, décodée par la composition | `err == null` / `err != null` | logs, commitment, subscription | PASS | | Yellowstone `TransactionStatus` | `slot` | 64 bytes | `err None` / `err Some` | filters, created_at, is_vote, index, opaque error bytes | PASS | | Helius `transactionSubscribe` | `slot` si forme typée | signature si forme typée | seulement si erreur déterminable | detail mode, transactionIndex, memo, blockTime, confirmation | PASS* | `PASS*` Helius signifie **projection conservative** : aucune `TransactionExecutionEvent` n'est fabriquée pour une forme `none`, inconnue ou dont l'erreur d'exécution est absente/indéterminable. Le DTO provider reste Transport-owned. ### 21.3 Outcome commun Le contrat n'encode pas les erreurs provider : ```text Solana `err: null` / Yellowstone `err: None` / Helius `err: null` explicite -> Succeeded Solana/Yellowstone/Helius erreur explicite -> Failed Helius `err` omis ou forme inconnue -> aucune projection ``` Cette normalisation décrit uniquement le résultat d'exécution observé. Elle ne prétend pas encoder un commitment, une finalité, une cause d'erreur, un index de transaction ou une garantie de replay. ### 21.4 Consumer concret Verdict : `PASS`. Le futur worker RAW live décrit dans `docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md` peut consommer le fait compact pour déclencher une hydratation/acquisition par signature sans dépendre du DTO source. Le premier backfill historique `0.3.6` ne dépend pas de cet event. ### 21.5 Anti-duplication Store Verdict : `PASS`. `TransactionExecutionEvent` ne contient ni payload RAW, format, content hash, block time, provenance, observation key, retention state ni network id durable. Il ne peut donc pas remplacer `RawTransaction`, `RawTransactionReference` ou `RawTransactionObservation`. ### 21.6 Décision finale ```text TransactionSignature TransactionExecutionOutcome TransactionExecutionEvent -> ADMIS Interface TransactionLogEvent -> idée différée TransactionCommitmentEvent -> non admis DTOs logsSubscribe / Yellowstone TransactionStatus / Helius transactionSubscribe -> Transport-owned ``` ## 22. Implémentation `0.3.5-pre.003` Surface ajoutée au crate-root : ```text TransactionSignature TransactionExecutionOutcome TransactionExecutionEvent ``` API : ```text TransactionSignature::new([u8; 64]) TransactionSignature::as_bytes() TransactionExecutionOutcome::{Succeeded, Failed} TransactionExecutionEvent::new(slot, signature, outcome) TransactionExecutionEvent::slot() TransactionExecutionEvent::signature() TransactionExecutionEvent::outcome() ``` `TransactionExecutionOutcome` est `#[non_exhaustive]`. Les deux `Debug` contenant une signature sont bornés et n'affichent aucun byte de signature. Le graphe normal visé reste : ```text ksp-interface-lib └── ksp-core-lib ``` Aucun converter Transport, aucune dependency Store, aucun `serde`, logging, runtime, channel ou codec n'est ajouté. ## 23. Fichiers de `pre.003` Modifiés : ```text Cargo.toml crates/ksp-interface-lib/src/lib.rs crates/ksp-interface-lib/tests/release_completeness.rs docs/plans/026-V0_3_5_INTERFACE_ACQUISITION_EVENTS_PLAN.md docs/validation/022-V0_3_5_INTERFACE_ACQUISITION_EVENTS.md ``` Ajoutés : ```text crates/ksp-interface-lib/src/transaction_execution.rs crates/ksp-interface-lib/unit_tests/transaction_execution.rs crates/ksp-interface-lib/tests/transaction_execution_public_api.rs deltas/0.3.5/pre.003.md ``` Explicitement inchangés : ```text crates/ksp-interface-lib/Cargo.toml crates/ksp-onchain-transport-lib/** crates/ksp-store-api/** crates/ksp-store-lib/** crates/ksp-store-postgres-lib/** README.md ROADMAP.md CHANGELOG.md ``` ## 24. Gate opérateur demandé pour `pre.003` ```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.5 cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-interface-lib cargo test -p ksp-program-api ``` Les gates Cargo de `pre.003` restent à exécuter par l'opérateur dans le repository réel.