# Delta `0.3.12-pre.004` — hydration `getTransaction` et provenance composite Yellowstone + HTTP ## Base requise ```text 0.3.12-pre.003-fix.002 workspace.package.version = 0.3.12-pre.3.fix.2 ``` Le gate opérateur communiqué pour cette base est entièrement vert : ```text cargo fmt --all Rust rule audit : clean Markdown table audit : clean (340 tables, 805 fichiers) cargo check --workspace : PASS cargo clippy --workspace --all-targets --all-features -- -D warnings : PASS cargo test -p ksp-worker-raw-transaction-ingest-lib : PASS unit tests Worker : 45 PASS integration dependency_boundary : 4 PASS integration hardening : 10 PASS integration public_api : 8 PASS integration release_completeness : 3 PASS doc-tests : 0 fail ``` ## Objectif Fermer et qualifier déterministiquement, sans source task productive, la chaîne : ```text signal Yellowstone Transaction / TransactionStatus -> signature canonique 64 bytes -> Base58 commun -> get_transaction_observed Base64 confirmed | finalized maxSupportedTransactionVersion = 0 -> contrôles source/hydration -> RawTransactionMaterial commun -> RawTransactionIngress existant ``` La tranche ne branche ni Block, ni continuité/replay, ni session Yellowstone productive. ## Version ```text workspace.package.version = 0.3.12-pre.4 ``` ## Common RAW — formatage Base58 `ksp-raw-transaction-lib` expose désormais `format_raw_transaction_signature` depuis la racine de crate. La fonction encode exactement les 64 bytes de `RawTransactionSignature` vers le texte Base58 canonique attendu par les RPC Solana. Elle ne dépend d'aucune crate Transport ni d'un second codec externe. Les bornes restent celles déjà publiques : ```text MIN_RAW_TRANSACTION_SIGNATURE_TEXT_BYTES = 64 MAX_RAW_TRANSACTION_SIGNATURE_TEXT_BYTES = 88 ``` Le round-trip `bytes -> format -> parse -> bytes` est qualifié sur plusieurs signatures, dont la signature nulle représentée par exactement 64 caractères `1`. ## Hydration HTTP qualifiée Le helper privé de qualification construit `SolanaGetTransactionConfig` avec : ```text encoding = base64 commitment = confirmed | finalized maxSupportedTransactionVersion = 0 ``` La signature RPC est obtenue exclusivement via `ksp_raw_transaction_lib::format_raw_transaction_signature`. `HttpTransportPool::get_transaction_observed` reste propriétaire du routage, retry/backoff et rate-limit Transport. Le Worker n'ajoute aucune boucle retry autour d'une erreur Transport. ## Contrôles avant admission Avant de créer un ingress, la qualification impose : ```text network signal == network Worker == network source route signal == route source slot HTTP == slot signal transaction_index HTTP == index signal lorsque les deux côtés le fournissent transaction HTTP réellement encodée en Base64 signature extraite du wire Base64 HTTP == signature signal ``` Un mismatch devient `worker_raw_transaction_ingest.runtime_invalid` avec une condition `hydration.*` stable. Il n'est jamais converti en content conflict Store. Les erreurs Transport sont reclassées en `worker_raw_transaction_ingest.source_failed` en ne conservant que le domain/code lower-layer déjà sûrs. ## Missing `getTransaction -> null` retourne : ```text Missing(RawTransactionReference) ``` Aucun `RawTransactionMaterial`, aucune provenance et aucun ingress ne sont inventés. Aucun retry Worker supplémentaire n'est ajouté dans cette tranche. ## Provenance composite La provenance réutilise sans migration `RawAcquisitionProvenance` et `RawProvenanceCode` : ```text protocol = yellowstone_http provider = ys.:http. endpoint_id = ys.:http. acquisition_method = transaction_get_transaction | status_get_transaction origin = Live commitment = confirmed | finalized capture_session_id = WorkerId sûr filter_id = nom direct unique représentable | sha256. observed_at = created_at Yellowstone seulement si représentable et <= received_at ``` Le provider et l'endpoint HTTP proviennent exclusivement du `HttpObservedValue` gagnant. Les URL, headers, tokens, bodies HTTP bruts et remote errors ne sont pas recopiés. Le constructeur `RawTransactionIngestYellowstoneSource::new` valide maintenant que chaque route HTTP compatible peut former les codes composites provider/endpoint sans dépasser `RawProvenanceCode`. Aucune troncature n'est admise. ## Common RAW et wire Après contrôles, la réponse HTTP est projetée vers `RawTransactionMaterial::binary_base64` en préservant : ```text blockTime -> Option puis RawTimestamp commun en millisecondes meta omitted | null | value version omitted | null | legacy | numeric transactionIndex omitted | null | value ``` La signature réellement embarquée dans le wire Base64 est extraite via `extract_raw_transaction_signature_from_binary_base64` avant admission. Les fixtures couvrent notamment : ```text Legacy + meta valeur + block_time valeur + index présent V0 + meta null + block_time null + index omis ``` ## `RUST-API-008` Le source task productif n'est pas créé avant `pre.006`. Les adapters Transaction/TransactionStatus et la chaîne d'hydration, encore sans consumer productif, restent donc sous `#[cfg(test)]` conformément à `RUST-API-008`. Aucun `#[allow(dead_code)]` ni `#[expect(dead_code)]` n'est introduit et aucune surface publique artificielle n'est créée. Les éléments immédiatement productifs de `pre.004` sont limités à : ```text format_raw_transaction_signature dans la common RAW validation de représentabilité de provenance composite au constructeur de source ``` ## Canaris déterministes ajoutés ou étendus ```text Base58 formatter round-trip et crate-root API getTransaction confirmed/base64/max version 0 getTransaction finalized/base64/max version 0 commitment finalized conservé dans la provenance winner HTTP observé dans provider/endpoint composites provenance Transaction et TransactionStatus distincte filter unique direct multi-filter -> fingerprint sha256 borné created_at futur ignoré pour observed_at getTransaction null -> Missing sans ingress/retry Worker slot mismatch transaction index mismatch signature wire mismatch network mismatch avant I/O composite provider overflow rejeté sans troncature absence Block/getBlock/stream/source spawn absence Config/Backfill/backend/reqwest/tonic/proto direct dans le Worker ``` ## Décisions prises ```text aucune migration Store pour une chaîne de provenance multi-hop Base58 appartient à la common RAW, pas au Worker HTTP observed est la source de vérité du provider/endpoint gagnant processed reste exclu du P0 hydration missing n'ajoute pas de retry Worker par défaut mismatch source/hydration est un fault Worker avant Store pas de RAW direct Yellowstone avant qualification byte-exacte dédiée adapters/hydration restent test-only jusqu'au source task productif de pre.006 ``` ## Questions ouvertes Aucune question ouverte n'est bloquante pour `pre.004`. Les sujets suivants restent volontairement réservés aux tranches ultérieures : ```text Block / BlockMeta / Slot : pre.005 source task productive et coalescence : pre.006 processing frontier : pre.007 reconnect/from_slot/ReplayInfo : pre.008 races/retry/backpressure final : pre.009 ``` ## Fichiers ajoutés ```text deltas/0.3.12/pre.004.md ``` ## Fichiers modifiés ```text Cargo.toml crates/ksp-raw-transaction-lib/README.md crates/ksp-raw-transaction-lib/USAGE.md crates/ksp-raw-transaction-lib/src/lib.rs crates/ksp-raw-transaction-lib/src/signature.rs crates/ksp-raw-transaction-lib/tests/public_api.rs crates/ksp-raw-transaction-lib/unit_tests/signature.rs crates/ksp-worker-raw-transaction-ingest-lib/src/lib.rs crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs crates/ksp-worker-raw-transaction-ingest-lib/tests/dependency_boundary.rs crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs crates/ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs docs/plans/033-V0_3_12_YELLOWSTONE_HYDRATION_CONTINUITY_PLAN.md docs/validation/029-V0_3_12_YELLOWSTONE_HYDRATION_CONTINUITY.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 (340 table(s), 806 file(s)) ``` ## Validations non exécutées dans l'environnement d'assemblage `cargo`, `rustc` et `rustfmt` ne sont pas installés dans l'environnement d'assemblage. Aucun résultat Cargo local n'est déclaré PASS. Le gate opérateur requis reste : ```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-worker-raw-transaction-ingest-lib cargo tree -p ksp-worker-raw-transaction-ingest-lib --edges normal cargo tree -p ksp-worker-raw-transaction-ingest-lib -e features cargo tree --duplicates ``` ## Non-claims Cette tranche ne revendique pas : ```text open_standard_subscribe consommation d'une update réseau live source task Yellowstone productif persistence d'une acquisition issue d'un stream réel Block / BlockMeta / Slot getBlock hydration coalescence productive processing frontier from_slot / ReplayInfo repair historique smoke live Worker réconciliation documentaire finale de pre.012 ``` ## Suite Après gate opérateur vert, `pre.005` adapte `Block` en signaux transactionnels et `BlockMeta`/`Slot` en signaux continuity-only, sans encore introduire la politique reconnect Worker.