# Delta `0.3.10-pre.004` — HTTP observed block + matériau RAW block ## Base requise ```text 0.3.10-pre.003 workspace.package.version = 0.3.10-pre.3 ``` Le gate opérateur communiqué le 2026-09-06 ferme intégralement `pre.003` : audits statiques propres, `cargo check --workspace` PASS, Clippy workspace `--all-targets --all-features -- -D warnings` PASS, tests de `ksp-raw-transaction-lib` PASS, tests de `ksp-job-backfill-lib` PASS avec 51 tests unitaires et 20 tests d’intégration, arbres normal/features conformes. ## Objectif Fermer `TR-B` et la preuve HTTP block de `TR-C` sans ouvrir le Worker : ```text getBlock pool HTTP -> valeur observée + provider/endpoint winner -> SolanaConfirmedBlock -> N SolanaBlockTransaction full Base64 -> matériau RAW source-neutral ``` La tranche ne crée aucun adapter productif Transport -> common. Conformément à `TR-C2`, cet adapter reste producer-owned et sera matérialisé dans le futur `ksp-worker-raw-transaction-ingest-lib`. ## Version ```text workspace.package.version = 0.3.10-pre.4 ``` Le header du `Cargo.toml` racine passe de `493` à `494`. Le nombre de membres workspace reste `20`. ## `get_block_observed` `ksp-onchain-transport-lib` ajoute : ```text HttpTransportPool::get_block_observed(...) ``` Le wrapper : ```text réutilise exactement la validation/config moderne de get_block utilise le routing/admission/timeout/retry standard du pool retourne HttpObservedValue> conserve endpoint_name + provider du winner réel après retry/reroute préserve result = null comme None n’expose ni URL, ni headers, ni raw HTTP body réutilise le décodage typé SolanaConfirmedBlock ``` `get_block(...)` et `get_block_observed(...)` partagent désormais le même helper privé de paramètres et la même validation du commitment `processed`. ## Provenance winner déterministe Le canari Transport configure deux endpoints : ```text endpoint 1 -> HTTP 429 endpoint 2 -> getBlock success ``` La valeur observée doit reporter exclusivement : ```text endpoint_name = winner-endpoint provider = winner-provider ``` Le Debug conserve uniquement la projection sûre et ne rend pas le transaction wire Base64. ## Matériau Base64 source-neutral `ksp-raw-transaction-lib` ajoute `base64` à son graphe common et expose : ```text extract_raw_transaction_signature_from_binary_base64(...) RawTransactionMaterial::binary_base64_with_embedded_signature(...) ``` L’extracteur lit directement le wire transaction Solana Base64 sans dépendance à une crate transaction runtime : ```text borne la représentation textuelle avant décodage exige Base64 STANDARD canonique lit un short_vec de signature count borné et canonique refuse count = 0 refuse short_vec tronqué/non canonique refuse tableau de signatures tronqué exige au moins un byte de message après les signatures déclarées retourne uniquement la première signature exacte de 64 octets ne copie jamais le transaction wire dans erreur/Debug ``` Le constructeur common réutilise cette signature puis conserve les dimensions RAW v1 existantes : ```text network slot block_time transaction Base64 meta omitted/null/value version omitted/null/legacy/number transaction_index ``` Le format canonique reste strictement `ksp.solana.raw_transaction` v1. ## Preuve cross-layer sans nouveau couplage de production Le nouveau canari test-only : ```text crates/ksp-job-backfill-lib/tests/http_block_material.rs ``` utilise une crate qui dépend déjà de Transport et de common pour prouver la composition future sans créer d’edge architectural supplémentaire : ```text get_block_observed -> SolanaConfirmedBlock -> 2 SolanaBlockTransaction distinctes -> full Base64 + meta + version + transactionIndex 0/1 -> RawTransactionMaterial::binary_base64_with_embedded_signature -> canonicalize_raw_transaction ``` Les deux transaction wires minimales font `66` octets chacune et utilisent des signatures distinctes : ```text transaction 0 -> signature [0; 64] transaction 1 -> signature [1; 64] ``` Le canari vérifie que ces signatures et les index 0/1 restent associés à la bonne transaction, avec le slot et le block time communs du bloc. Cette preuve reste strictement test-only. Aucun symbole `ksp_raw_transaction_lib` n’est ajouté aux sources de production de `ksp-onchain-transport-lib`. ## Dépendances common Le graphe runtime direct de `ksp-raw-transaction-lib` devient exactement : ```text base64 ksp-core-lib ksp-store-api serde_json sha2 ``` Restent interdits : ```text ksp-store-lib ksp-onchain-transport-lib ksp-config-lib ksp-job-api ksp-job-backfill-lib ksp-worker-api tokio futures ``` La règle `DEP-PIPE-006` reste donc respectée. ## Documentation durable `crates/ksp-onchain-transport-lib/USAGE.md` documente la différence entre : ```text get_block(...) get_block_observed(...) ``` sans transformer le guide en journal de prerelease. `docs/architecture/011-RAW_TRANSACTION_ACQUISITION.md` ferme `TR-B`, conserve `TR-C2` producer-owned et corrige le graphe common vers `ksp-store-api`. Le plan `031` et la validation `027` enregistrent également la fermeture opérateur de `pre.003` et le périmètre exact de `pre.004`. ## Fichiers ajoutés ```text crates/ksp-job-backfill-lib/tests/http_block_material.rs crates/ksp-onchain-transport-lib/fixtures/http/get_block.observed_material.success.json deltas/0.3.10/pre.004.md ``` ## Fichiers modifiés ```text Cargo.toml crates/ksp-onchain-transport-lib/USAGE.md crates/ksp-onchain-transport-lib/src/rpc_blocks.rs crates/ksp-onchain-transport-lib/tests/public_api.rs crates/ksp-onchain-transport-lib/unit_tests/rpc_blocks.rs crates/ksp-raw-transaction-lib/Cargo.toml crates/ksp-raw-transaction-lib/src/canonical.rs crates/ksp-raw-transaction-lib/src/error.rs crates/ksp-raw-transaction-lib/src/lib.rs crates/ksp-raw-transaction-lib/src/signature.rs crates/ksp-raw-transaction-lib/tests/dependency_boundary.rs crates/ksp-raw-transaction-lib/tests/public_api.rs crates/ksp-raw-transaction-lib/unit_tests/canonical.rs crates/ksp-raw-transaction-lib/unit_tests/signature.rs docs/architecture/011-RAW_TRANSACTION_ACQUISITION.md docs/plans/031-V0_3_10_RAW_TRANSACTION_INGEST_PLAN.md docs/validation/027-V0_3_10_RAW_TRANSACTION_INGEST.md ``` ## Fichiers supprimés Aucun. ## Validations exécutées 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 Markdown table audit: clean (339 table(s), 757 file(s)) ``` L’environnement d’assemblage ne fournit ni `cargo`, ni `rustc`, ni `rustfmt`. ## Gate opérateur demandé ```bash 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 cargo check --workspace cargo clippy --workspace --all-targets --all-features -- -D warnings cargo test -p ksp-raw-transaction-lib cargo test -p ksp-onchain-transport-lib cargo test -p ksp-job-backfill-lib --test http_block_material cargo tree -p ksp-raw-transaction-lib --edges normal cargo tree -p ksp-onchain-transport-lib --edges normal ``` ## Validations non exécutées localement ```text cargo fmt --all cargo check --workspace cargo clippy --workspace --all-targets --all-features -- -D warnings cargo test -p ksp-raw-transaction-lib cargo test -p ksp-onchain-transport-lib cargo test -p ksp-job-backfill-lib --test http_block_material cargo tree -p ksp-raw-transaction-lib --edges normal cargo tree -p ksp-onchain-transport-lib --edges normal smokes live : non requis pour cette tranche déterministe ``` ## Décisions prises ```text TR-B est fermé par get_block_observed get_block et get_block_observed partagent validation + décodage la common extrait la signature d’un transaction wire Base64 complet aucune dépendance Solana transaction runtime n’est ajoutée à la common aucun adapter productif Transport -> common dans Transport TR-C2 reste Worker-owned la preuve block -> common est cross-layer et test-only RAW v1 reste inchangé aucun Worker live n’est ouvert dans pre.004 ``` ## Questions ouvertes Aucune question ne bloque le gate de `pre.004`. `pre.005` reste dédiée à la parité WS `blockSubscribe` + Helius `transactionSubscribe`, avec golden parity ou fallback hydration explicitement qualifié selon la représentation réellement disponible.