# Plan v0.3.12 — Yellowstone + hydration HTTP + continuité de run du Worker RawTransaction ## 1. But de la version `0.3.12` étend la fondation stable `ksp-worker-raw-transaction-ingest-lib` de `0.3.11` avec une première famille réseau productive basée sur le moteur Yellowstone gRPC générique déjà présent dans `ksp-onchain-transport-lib` et sur une hydration HTTP `getTransaction` lorsque le signal Yellowstone ne suffit pas au RAW v1 complet. La verticale reste strictement : ```text Yellowstone live -> signal Worker privé -> hydration HTTP observée si nécessaire -> ksp-raw-transaction-lib -> admission/persistence Worker existante -> ksp-store-lib ``` La version ne recrée ni lifecycle, ni supervisor, ni queue d'admission, ni persistence, ni snapshots génériques. Elle ne transforme pas non plus le Worker en Job historique. ## 2. Base autoritaire auditée en `pre.001` Archive d'entrée : ```text khadhroony-solana-project-v0.3.11.zip SHA-256 : a6bb59935650a7f48630d12ef80fbd1a44a84819dd129b085ff7f467369535fc ZIP bytes : 8125100 ZIP entries : 1950 workspace members : 21 workspace.package.version : 0.3.11 stable delta : deltas/0.3.11/rel.001.md ``` Contrôles structurels exécutés avant modification : ```text unzip -t : PASS racine ZIP unique : khadhroony-solana-project/ entrée absolue : 0 path traversal : 0 symlink : 0 .git/ : 0 target/ : 0 node_modules/ : 0 Cargo.lock : 0 .env : 0 ``` Préconditions du prompt `031` confirmées : ```text ksp-worker-raw-transaction-ingest-lib présent et documenté aucune source réseau productive dans le Worker stable ksp-raw-transaction-lib présent et stable ksp-onchain-transport-lib expose le moteur Yellowstone générique ksp-store-lib reste la façade Store du Worker ksp-job-backfill-lib reste indépendant du Worker ``` ## 3. Audit humain des règles actives La lecture de `RULES.md`, des règles spécialisées, de `ROADMAP.md`, de `CHANGELOG.md`, de l'index documentaire et du prompt `031` ne révèle pas de contradiction normative active imposant une correction de règles pendant `pre.001`. Les contraintes bloquantes retenues sont : ```text Rust 2024 unsafe interdit unwrap / expect / panic interdits en production ? interdit en production retours explicites pas de pub mod pub/pub(crate) partagés réexportés au crate-root accès intra-crate partagé via crate::Item Config seul propriétaire des fichiers/profils/endpoints/secrets dépendance Worker -> Job interdite backend Store physique interdit au Worker ksp-store-lib seulement pour la persistence une prerelease non-fix synchronise workspace.package.version prerelease cible <= 15–20 minutes ; split avant tranche trop grande une release concrète doit rester clôturable dans une session ``` Aucune règle active n'est modifiée par `pre.001`. ## 4. Inventaire réel des frontières internes ### 4.1 Worker stable `0.3.11` La crate possède huit modules de production : ```text admission error identity persistence runtime settings snapshot lib ``` La façade stable contient exactement la fondation nécessaire : ```text RawTransactionIngestSettings RawTransactionIngestWorker RawTransactionIngestHandle RawTransactionIngestSnapshot RawTransactionIngestSnapshotSource RawTransactionIngestTerminalFuture bornes et defaults runtime ErrorCodes Worker ``` L'implémentation possède déjà : ```text supervisor privé unique JoinSet source privé JoinSet persistence privé mpsc admission borné stop signal privé canonicalisation Common RAW source_key privé observation key déterministe Store mode Normal concurrence persistence bornée content conflict terminal source/store/counter/drain faults snapshot latest-value concret + Worker API shutdown deadline + abort/join ``` Le point d'entrée stable reste : ```text RawTransactionIngestWorker::start(settings, Arc) -> RawTransactionIngestHandle ``` Il démarre volontairement sans adapter réseau productif. ### 4.2 Common RAW `ksp-raw-transaction-lib` reste la seule propriété de : ```text parsing signature RAW RawTransactionMaterial RawTransactionWireField canonicalisation RAW v1 hash de contenu assemblage RawTransaction + RawTransactionObservation ``` La common crate ne reçoit ni Transport, ni Worker, ni Config, ni provider. ### 4.3 Transport Yellowstone `ksp-onchain-transport-lib` expose déjà, sans SDK provider : ```text YellowstoneGrpcChannel SolanaYellowstoneGrpcSubscribeSession YellowstoneSubscribeRequest YellowstoneSubscribeUpdate YellowstoneTransactionUpdate YellowstoneTransactionStatusUpdate YellowstoneBlockUpdate YellowstoneBlockMetaUpdate YellowstoneSlotUpdate YellowstoneGrpcSubscribeSnapshot YellowstoneReplayInfo ``` Le moteur possède déjà : ```text connexion gRPC bornée metadata publique/secrète validée Subscribe bidirectionnel mutations bornées auto Ping/Pong reconnect borné from_slot au reconnect SubscribeReplayInfo snapshot reconnect/replay/gap/duplicate backpressure et message-size bounds close borné ``` Le Worker doit consommer cette façade. Il ne crée pas de second client Tonic ni de second actor gRPC. ### 4.4 Transport HTTP La façade HTTP possède : ```text HttpTransportPool HttpRoleName get_transaction_observed get_block_observed HttpObservedValue ``` `HttpObservedValue` préserve l'identité sûre du winner réel : ```text value endpoint_name provider ``` L'hydration `0.3.12` réutilise `get_transaction_observed`; elle ne suppose jamais quel endpoint a gagné le routage/retry Transport. ### 4.5 Store `ksp-store-lib` reste l'unique edge Store normal du Worker. Le contrat durable garde : ```text RawTransaction identity = (network, signature) une entité canonique plusieurs observations distinctes Normal persistence content conflict explicite purged tombstone respecté ``` Aucune migration Store n'est planifiée dans `0.3.12`. ### 4.6 Config `ksp-config-lib` sait déjà mapper `std.transport.json` vers les settings HTTP/WS/gRPC Transport, avec endpoint/provider/cluster/metadata et sensibilité des secrets. Le modèle retenu est : ```text Config/application/service owner -> résout Config -> construit Transport HTTP + Yellowstone -> injecte les ressources runtime au Worker ``` Le Worker ne dépend pas de Config et ne lit jamais `config/`, `.env` ou `KSP_*`/`KSPB_*`. ### 4.7 Backfill `ksp-job-backfill-lib` reste un producteur historique borné et paramétré. Sa conversion HTTP actuelle constitue une référence fonctionnelle interne pour `get_transaction_observed -> RawTransactionMaterial`, mais son code n'est pas déplacé tel quel dans le Worker et aucune dépendance Worker -> Backfill n'est créée. ## 5. Audit externe courant du 8 septembre 2026 ### 5.1 Solana JSON-RPC La documentation officielle courante de `getTransaction` confirme : ```text input : signature base58 + config commitment : confirmed/finalized encoding : base64 supporté result : null ou { blockTime, meta, slot, transaction, version } ``` Ces champs restent suffisants pour produire le RAW v1 actuel par la voie HTTP déjà qualifiée dans KSP. La documentation officielle de `getBlock` confirme : ```text slot + config blockTime transactions[] chaque transaction avec transaction + meta ``` `getBlock` reste disponible comme primitive Transport, mais n'est pas requis par le chemin P0 de `0.3.12` tant qu'une signature Yellowstone peut être hydratée par `getTransaction`. ### 5.2 Yellowstone upstream `yellowstone-grpc-proto 12.7.0` a été publié le 29 août 2026. Le workspace KSP utilise déjà `^12.7`; aucun bump de version externe n'est requis en ouverture. Le proto courant conserve : ```text Subscribe SubscribeReplayInfo SubscribeRequest.from_slot Transaction TransactionStatus Block BlockMeta Slot ``` `SubscribeReplayInfoResponse.first_available` reste une borne de rétention annoncée par le serveur, pas un journal des updates réellement livrées au filtre du caller. Le changelog upstream du 22 juillet 2026 documente un défaut important corrigé en `yellowstone-grpc-geyser 14.2.1` : avec un filtre `blocks`, une demande `from_slot` pouvait être acceptée sans livrer les messages Block rejoués, puis reprendre silencieusement au live head. Conséquence KSP durable : l'acceptation d'une souscription ou d'un `from_slot` ne prouve jamais à elle seule une continuité complète. Le changelog du 15 juin 2026 signale aussi un traitement d'équivocation au reconnect dans le client upstream. KSP n'utilise pas ce client comme runtime ; son moteur Transport propre reste donc responsable de ses garanties conservatrices. ### 5.3 OrbitFlare La documentation OrbitFlare courante expose encore : ```text Devnet RPC : http://devnet.rpc.orbitflare.com Devnet gRPC : http://devnet.rpc.orbitflare.com:10000 Free : Devnet gRPC only ``` La stable KSP contient déjà un smoke opt-in OrbitFlare utilisant un secret `x-token`. La présence effective d'une licence/token opérateur n'est pas prouvée par l'archive et ne peut donc pas être déclarée disponible en `pre.001`. ### 5.4 Helius LaserStream La documentation Helius courante annonce une compatibilité wire Yellowstone, les familles standard et `fromSlot`. Le service documente actuellement une fenêtre de replay d'environ 216 000 slots / 24 heures et un accès Devnet à partir du plan Developer, Mainnet à partir du plan Business. Ces valeurs sont temporelles et provider-specific. Elles ne deviennent ni constantes KSP ni précondition de `0.3.12`. Aucun SDK Helius/LaserStream n'est ajouté. ### 5.5 PublicNode La stable KSP contient déjà deux smokes opt-in programmatiques PublicNode, Mainnet et Testnet, avec endpoints TLS et `x-token` fourni sur stdin. L'audit externe `pre.001` n'a pas trouvé de documentation primaire indexée suffisamment précise pour promouvoir de nouvelles assertions sur profondeur de replay, quotas ou disponibilité actuelle. Décision : conserver PublicNode comme smoke opérateur conditionnel existant, sans figer de capacité provider nouvelle dans `0.3.12`. ## 6. Matrice exacte des signaux Yellowstone ### 6.1 `Transaction` Matériau KSP disponible : ```text slot signature 64 bytes is_vote transaction body typé complet transaction status meta typée complète transaction index filter names created_at optionnel ``` Gap RAW actuel : ```text block_time absent de TransactionUpdate meta Yellowstone typée non prouvée byte-identique au JSON meta du RAW v1 version/canonical JSON du RAW HTTP non prouvés directement par cette DTO ``` Décision `0.3.12` : ```text signal productif signature/slot/index utilisables immédiatement hydration getTransaction obligatoire avant admission RAW RAW-direct interdit tant qu'un canari byte-exact dédié ne ferme pas tous les champs ``` ### 6.2 `TransactionStatus` Matériau disponible : ```text slot signature is_vote index error opaque optionnelle filter names created_at optionnel ``` Gap RAW : transaction bytes, meta canonique, block_time et version absents. Décision : signal de discovery/hydration seulement. L'`error` remote n'est jamais recopiée dans un contexte d'erreur public ni dans les logs. ### 6.3 `Block` Matériau disponible : ```text slot blockhash / parent block_time optionnel block_height optionnel executed_transaction_count transactions[] avec signature/body/meta/index accounts/entries optionnels selon request filter names created_at optionnel ``` La présence du `block_time` ferme un gap de `Transaction`, mais la parité byte-exact du `meta` Yellowstone avec le JSON RAW v1 n'est pas prouvée. Décision : les transactions d'un Block deviennent des signaux d'hydration `getTransaction`; aucun second pipeline RAW block n'est créé. `get_block_observed` n'est pas nécessaire au P0. ### 6.4 `BlockMeta` Matériau disponible : slot, blockhash, parent, block_time, block_height, compteurs. Aucune signature transactionnelle n'est disponible. Décision : pas d'admission RAW. Utilisation uniquement pour observabilité/source boundary/continuité lorsque la request la fournit. Aucun claim de complétude transactionnelle n'est dérivé du seul compteur. ### 6.5 `Slot` Matériau disponible : slot, parent optionnel, status, diagnostic dead borné, filter names, created_at. Décision : pas d'admission RAW. Utilisation pour progression/health/continuité. Le texte `dead_error` ne traverse pas la frontière de diagnostic Worker. ### 6.6 `from_slot` `from_slot` est un input de Subscribe/reconnect. Il ne représente ni un checkpoint historique durable ni une campagne Backfill. Décision : la mécanique auto-reconnect Transport reste propriétaire de l'émission effective de `from_slot`. Le Worker observe la continuité mais ne construit pas un second mécanisme de reconnect. ### 6.7 `SubscribeReplayInfo` Matériau disponible : `first_available: Option`. Décision : ```text requested_from_slot < first_available => couverture replay indisponible prouvée requested_from_slot >= first_available => seulement éligibilité de rétention, jamais preuve de livraison complète first_available absent => aucune profondeur de replay revendiquée ``` ## 7. Décision RAW conservative La décision stable est maintenue : ```text Yellowstone signal -> HTTP getTransaction observed -> Common RAW -> Store ``` `0.3.12` ne tente pas de sérialiser le protobuf Yellowstone en JSON meta pour éviter l'hydration. Un éventuel RAW-direct futur exige au minimum : ```text Legacy fixture byte-exact V0 fixture byte-exact meta null/omitted/value parity version parity block_time parity ou source sûre équivalente transaction_index parity content hash identique provenance distincte sans ambiguïté ``` ## 8. Architecture d'injection Transport retenue ### 8.1 Edge Cargo `pre.002` peut ouvrir exactement : ```text ksp-worker-raw-transaction-ingest-lib -> ksp-onchain-transport-lib ``` Aucun edge nouveau vers : ```text ksp-config-lib ksp-job-backfill-lib ksp-store-api ksp-store-postgres-lib yellowstone-grpc-proto directement depuis le Worker reqwest/tonic directement depuis le Worker SDK provider ``` ### 8.2 Ressource Worker-owned La première tranche technique matérialise exactement deux types publics Worker-owned à champs privés : ```text RawTransactionIngestYellowstoneSource RawTransactionIngestRuntimeResources ``` `RawTransactionIngestYellowstoneSource::new` reçoit conceptuellement : ```text YellowstoneGrpcChannel déjà construit YellowstoneSubscribeRequest déjà construit HttpTransportPool déjà construit HttpRoleName d'hydration ``` `RawTransactionIngestRuntimeResources::new(yellowstone_source)` possède cette première source productive sans exposer de collection multi-source prématurée. Ses champs privés permettent d'ajouter ultérieurement d'autres familles sans enum provider fermée. Le caller supérieur reste responsable de Config/composition et de la construction de ces ressources. La ressource ne transporte jamais URL, token ou header en projection/Debug Worker. Elle s'appuie sur les redactions Transport existantes. ### 8.3 Point de démarrage Le `start(settings, Arc)` stable reste disponible pour préserver la fondation source-neutral et ses tests. `0.3.12` ajoute le point de démarrage explicite suivant, sans casser le start stable ni exposer une queue `enqueue` : ```text RawTransactionIngestWorker::start_with_runtime_resources( settings, Arc, RawTransactionIngestRuntimeResources, ) -> RawTransactionIngestHandle ``` Les décisions suivantes sont closes : ```text pas de closure publique source pas de public enqueue pas de JoinHandle public pas de Config public dans le Worker pas de backend Store public pas de client Tonic/reqwest public ``` ### 8.4 Validation de la request Le Worker valide seulement les invariants nécessaires à sa propre correction : ```text cluster Yellowstone cohérent avec settings.network au moins une famille ingestion-bearing : transactions / transactions_status / blocks commitment compatible avec hydration HTTP : confirmed ou finalized role HTTP réellement compatible avec getTransaction via Transport request déjà valide selon Transport ``` `processed` est exclu du chemin P0 car le `getTransaction` officiel ne fournit pas ce commitment. Cette restriction évite de transformer un signal processed en tempête de `null`/retry non bornée. ## 9. Signal privé et coalescence d'hydration Le Worker introduit un signal interne source-neutral au pipeline réseau, distinct de `RawTransactionIngress` : ```text network signature slot transaction_index optionnel source family safe source route identity matched filter fingerprint created_at optionnel ``` Les transactions complètes Yellowstone peuvent conserver une preuve fixture/cross-check privée, mais le pipeline productif ne doit pas dupliquer leurs payloads dans les diagnostics. La hydration est coalescée au maximum par : ```text (network, signature, commitment) ``` Coalescence signifie : un seul appel HTTP in-flight peut servir plusieurs signaux identiques. Elle ne signifie pas supprimer silencieusement les observations sémantiquement distinctes. La tranche hydration doit définir un fan-out déterministe vers la provenance finale sans cache non borné. Les structures de pending/coalescence sont bornées et soumises au stop. ## 10. Hydration HTTP ### 10.1 Requête Le chemin P0 utilise : ```text get_transaction_observed encoding = base64 commitment = même commitment confirmed/finalized que la source maxSupportedTransactionVersion = 0 ``` La conversion finale réutilise les mêmes champs déjà qualifiés par Backfill/Common RAW : ```text block_time meta slot transaction transaction_index version ``` ### 10.2 Mismatch source/hydration Avant admission : ```text signature HTTP doit égaler l'identité du signal network doit rester identique slot HTTP doit être cohérent avec le slot du signal lorsqu'il est connu transaction_index doit être comparé lorsque les deux côtés le fournissent ``` Un conflit déterministe de matériau source/hydration devient un fault source/conversion sûr, pas un content conflict Store inventé. ### 10.3 Missing `getTransaction -> null` à `confirmed/finalized` est classé comme missing d'hydration, pas comme succès RAW. Le Worker ne double pas la politique retry Transport. La politique P0 est : ```text Transport possède request retry/backoff/rate-limit Worker n'ajoute pas de boucle rapide autour d'une erreur Transport missing peut recevoir un retry Worker borné distinct seulement si la tranche pre.004 prouve un besoin temporel stop interrompt toute attente/retry Worker ``` Par défaut, `pre.004` doit commencer sans retry Worker additionnel et n'en ajouter un qu'avec test déterministe et borne explicite. ## 11. Provenance cross-transport ### 11.1 Contrainte du modèle Store existant `RawAcquisitionProvenance` contient un seul jeu de champs logiques : ```text provider protocol acquisition_method origin received_at capture_session_id commitment endpoint_id filter_id observed_at source_payload_hash/source_payload_size optionnels ``` Il n'existe pas de chaîne de provenance multi-hop native. `0.3.12` ne justifie pas une migration Store pour ce seul besoin. ### 11.2 Encoding composite retenu La provenance d'une acquisition hydratée représente explicitement une route composée à l'aide des codes bornés existants : ```text protocol = yellowstone_http provider = ys.:http. endpoint_id = ys.:http. acquisition_method = transaction_get_transaction | status_get_transaction | block_get_transaction origin = Live commitment = confirmed | finalized capture_session_id = source/session code Worker sûr filter_id = code direct si unique et sûr, sinon fingerprint déterministe borné des filters ``` Chaque code doit passer `RawProvenanceCode`; aucune concaténation non bornée n'est admise. Si les identités sûres ne peuvent pas être représentées sous `MAX_RAW_CODE_BYTES`, le start/source est rejeté plutôt que tronqué silencieusement. Le provider/endpoint HTTP proviennent exclusivement du `HttpObservedValue` gagnant. Les noms gRPC proviennent du `YellowstoneGrpcChannel`, jamais d'une URL ou metadata secrète. ### 11.3 Timestamp `received_at` est le timestamp KSP de l'acquisition complète/hydratée. `created_at` Yellowstone peut alimenter `observed_at` seulement si sa conversion respecte les bornes et l'ordre temporel du modèle Store. Aucun timestamp absent n'est inventé. ## 12. Frontier et continuité de run ### 12.1 Trois notions séparées `0.3.12` ne mélange pas : ```text transport observed high-watermark Worker processing frontier durable blockchain completeness ``` Le dernier point n'est pas revendiqué par cette release. ### 12.2 High-watermark Transport `YellowstoneGrpcSubscribeSnapshot.last_observed_slot` reste la vérité Transport de la plus haute slot-bearing update vue par la session. Le reconnect Transport peut demander un `from_slot` à partir de cette progression selon sa politique existante. ### 12.3 Processing frontier Worker Le Worker garde une frontier de run bornée liée uniquement au travail réellement observé : ```text slot observée nombre de signaux pending pour cette slot nombre de signaux settled pour cette slot plus ancienne slot encore pending plus haute slot sans pending parmi les slots réellement observées ``` Cette frontier sert à l'health et au diagnostic de backlog. Elle ne prouve jamais qu'aucun événement filtré n'existe dans les slots non vus. Le stockage est borné par la capacité d'admission/hydration ; aucune map de slots infinie n'est conservée. ### 12.4 Reconnect Reconnect signifie uniquement réouverture de la session Transport. Il ne signifie ni replay réussi, ni repair, ni Backfill. Le Worker continue de posséder ses hydrations/persistences déjà admises pendant un reconnect source. Il ne les abandonne pas uniquement parce que le flux est momentanément reconnecting. ### 12.5 Replay Un `replay_attempt_count` ou un `last_requested_from_slot` indique une tentative de replay Transport, pas une couverture complète. Si `continuity_gap_count` augmente parce que `SubscribeReplayInfo` prouve que la slot demandée est antérieure à `first_available`, `0.3.12` ne lance pas de campagne historique : le Worker publie un état/fault de continuité sûre et s'arrête selon son lifecycle existant. ### 12.6 Repair Aucun repair multi-source automatique n'est implémenté en `0.3.12`. Le repair final reste `0.3.14`. Une future réparation pourra utiliser la frontier de run, mais ne transformera pas le Worker en interface de requête historique arbitraire. ### 12.7 Restart process La frontier `0.3.12` est run-local. Aucun checkpoint persistant ou resume inter-process n'est promis. ## 13. Snapshot et health Nouveaux champs éventuels autorisés uniquement s'ils sont matérialisés par les tranches techniques : ```text source state code source reconnect total source replay attempt total source continuity gap total hydration pending gauge hydration success total hydration missing total hydration failure total processing frontier slot optionnelle oldest pending slot optionnelle ``` Ils restent latest-value/monotones avec arithmetic checked. Ils n'exposent jamais : ```text signature filter values transaction/meta URL credential/header remote error text raw protobuf/JSON ``` Les compteurs Transport ne sont pas recopiés si le Worker n'en a pas besoin pour son contrat concret. ## 14. Threat model live ### 14.1 Secrets Risque : URL/token/header dans Debug/error/snapshot/tracing. Garde : le Worker manipule uniquement les wrappers Transport déjà redacted et des codes sûrs. Scanner externe obligatoire. ### 14.2 Remote errors Risque : status/message/metadata arbitraire recopié dans `Error`. Garde : conserver seulement `ErrorCode` KSP et contexte stable. `dead_error` slot et `TransactionStatus.error` ne sont jamais recopiés. ### 14.3 Saturation Risque : flux Yellowstone plus rapide que hydration/Store. Garde : queue source/hydration bornée, coalescence bornée, backpressure, aucun unbounded channel, aucun spawn par update sans budget. ### 14.4 Duplicate signals Risque : `Transaction`, `Status`, `Block` et replay donnent la même signature. Garde : coalescence HTTP in-flight + Store idempotence + observation key déterministe. Aucun cache de déduplication infini. ### 14.5 Retry storm Risque : retry Transport × retry Worker. Garde : Transport possède les retries réseau. Le Worker ne retry pas une erreur Transport par défaut et tout retry missing futur est explicitement borné. ### 14.6 Reconnect race Risque : mutation de request pendant reconnect ou projection stale. Garde : le moteur Transport refuse déjà `try_update` pendant reconnect. Le Worker n'introduit pas de second actor request. ### 14.7 Stop pendant hydration/replay Risque : nouvelles admissions après stop ou tâches orphelines. Garde : stop prioritaire dans source/hydration, arrêt des nouvelles hydrations, drain des admissions déjà acceptées selon la frontière stable `0.3.11`, puis abort/join sous deadline. ### 14.8 Stale frontier Risque : annoncer une continuité blockchain à partir d'un high-watermark filtré. Garde : vocabulaire `processing frontier`/`observed high-watermark`; aucune claim de completeness. Gap prouvé => fault, pas auto-réparation implicite. ### 14.9 Provider replay bugs Risque : endpoint accepte `from_slot` mais omet des familles replay. Garde : `ReplayInfo` = borne de rétention seulement ; fixtures Transport + live smoke si disponible ; aucun PASS de continuité sur simple ouverture de stream. ## 15. Preuves déterministes requises ### 15.1 Source contract Canaris : ```text resource rejects network mismatch resource rejects processed hydration commitment resource requires one ingestion-bearing family Debug omits endpoint secret material public API exposes no enqueue/client inner ``` ### 15.2 Transaction/status/block Fixtures exactes : ```text Transaction -> signal signature/slot/index TransactionStatus -> signal sans payload inventé Block -> N transaction signals dans ordre source BlockMeta -> continuity-only Slot -> continuity-only ``` ### 15.3 Hydration Fixtures HTTP : ```text observed winner provenance null missing Legacy V0 meta null/value block_time null/value transaction_index present/absent network/signature/slot mismatch ``` ### 15.4 Duplicates/coalescence Canaris : ```text Transaction + Status même signature => au plus un HTTP in-flight Block + Transaction même signature => même propriété fan-out provenance déterministe Store idempotence préservée ``` ### 15.5 Continuity Canaris : ```text reconnect != replay replay attempt != proof first_available clamp/gap continuity_gap increase => Worker fault sûr pending hydration survives source reconnect frontier never advances through pending work stop while reconnecting stop while hydrating ``` ### 15.6 Dependency/security Canaris : ```text Worker manifest exact pas de Config/Job/backend/provider SDK pas de direct yellowstone-grpc-proto/tonic/reqwest crate-root discipline logs/errors/snapshots sans signature/payload/secret ``` ## 16. Smokes live accessibles et gates opérateur ### 16.1 Existant La stable possède : ```text yellowstone_orbitflare_smoke : Devnet, x-token sur stdin yellowstone_publicnode_smoke : Mainnet/Testnet, x-token sur stdin ``` Ils sont `#[ignore]` et restent operator-only. ### 16.2 Worker smoke `0.3.12` Le smoke final peut être ajouté uniquement lorsque le pipeline productif existe. Ordre de préférence : ```text 1. OrbitFlare Devnet si licence/token opérateur disponible 2. PublicNode réseau correspondant si token opérateur disponible 3. Helius LaserStream uniquement si accès réel fourni ; aucun abonnement acheté pour fermer la release ``` Le smoke doit prouver au minimum : ```text connexion Yellowstone au moins un signal transactionnel pertinent hydration HTTP observée persistence Store sur réseau cohérent stop borné aucun secret en sortie ``` Si aucun secret/provider live n'est disponible, le gate live reste explicitement NON EXÉCUTÉ ; les fixtures déterministes restent le gate de correction obligatoire. ## 17. Graphe Cargo cible Après `pre.002`, dépendances normales Worker attendues : ```text ksp-core-lib ksp-logging-lib ksp-onchain-transport-lib ksp-raw-transaction-lib ksp-store-lib default-features=false ksp-worker-api sha2 tokio macros,rt,sync,time ``` Aucune feature provider n'est ajoutée au Worker. Le Transport possède déjà Tonic/Yellowstone/Reqwest. Gates graphes : ```text 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 ``` ## 18. Sizing recalibré Le forecast du prompt est scindé une fois supplémentaire autour de la continuité pour éviter une tranche trop grosse. ### `pre.001` — audit/sizing/plan Archive/règles, inventaires, fraîcheur externe, matrice Yellowstone, injection, hydration, provenance, frontier, threats, smokes, graphe et plan. Aucune source productive. ### `pre.002` — edge Transport + resource/source contract Ajouter uniquement la dépendance Transport et les types runtime Worker-owned validés, plus public/dependency canaris. Aucun stream productif. ### `pre.003` — signaux Transaction + TransactionStatus Adapter les deux DTOs vers le signal Worker privé, sans HTTP ni persistence réseau. Fixtures exactes et redaction. ### `pre.004` — hydration `getTransaction` + provenance composite Fermer et qualifier déterministiquement signal -> HTTP observed -> Common RAW -> ingress existant, missing/mismatch/provenance, sans Block ni continuity. Tant que `pre.006` n'apporte pas le source task productif qui consomme cette chaîne, les adapters/hydration strictement privés sans consumer productif restent sous `#[cfg(test)]` conformément à `RUST-API-008`; `pre.004` ne crée pas artificiellement une surface publique pour contourner `dead_code`. ### `pre.005` — Block + BlockMeta + Slot Adapter Block en signaux transactionnels ; BlockMeta/Slot en signaux continuity-only. Pas encore de reconnect policy Worker. ### `pre.006` — source task productive + supervisor/coalescence Ouvrir la session Yellowstone via le moteur Transport, alimenter hydration/admission, borner coalescence/backpressure et intégrer au JoinSet sources existant. ### `pre.007` — processing frontier run-local Ajouter pending/settled/frontier bornés et projections strictement processing-only, sans replay repair. ### `pre.008` — reconnect / from_slot / ReplayInfo Brancher le snapshot Transport, distinguer reconnect/replay, fault sur gap de rétention prouvé, stop pendant reconnect. Aucun repair historique. ### `pre.009` — hardening races/retry/backpressure Stop pendant hydration, missing/error, duplicate storm, Store lent, source failure, counter exhaustion et no-orphan. ### `pre.010` — cross-layer completeness/security Fixtures Legacy/V0, dependency firewall, public API exact, redaction, release completeness et scanners. ### `pre.011` — gate technique + live opt-in Workspace complet, graphes Cargo, duplicates, suites ciblées et smokes réellement accessibles. Aucun nouveau scope. ### `pre.012` — réconciliation documentaire README/USAGE Worker et architectures/références réellement affectées. Pas de CHANGELOG/ROADMAP/prompt suivant. ### `pre.013` — préparation publication Prompt `0.3.13`, CHANGELOG, ROADMAP et fichiers mécaniques seulement. ### `rel.001` Publication stable mécanique après gate validé. Chaque tranche est volontairement dimensionnée sous environ 15–20 minutes. Si une tranche technique dépasse réellement ce budget, elle est scindée avant exécution sans élargir le scope. ## 19. Décision de sizing release Décision `pre.001` : **maintenir `0.3.12`**. Raisons : ```text moteur Yellowstone générique déjà complet HTTP observed déjà complet Common RAW déjà qualifiée supervisor/admission/persistence/snapshots déjà complets aucune migration Store aucune nouvelle Config nécessaire au P0 une seule source Yellowstone logique en P0 repair multi-source reporté WS/Helius-specific/HTTP polling reportés ``` Le split de la continuity en `pre.007` et `pre.008` maintient chaque tranche bornée. La release reste clôturable dans une session à condition de ne pas importer de scope `0.3.13+`. ## 20. Questions fermées par `pre.001` ```text Worker -> Transport est l'unique nouvel edge autorisé Worker -> Config reste interdit HTTP getTransaction est l'hydration P0 getBlock n'est pas requis pour le P0 processed est exclu de la source hydratée P0 Transaction/Status/Block produisent des candidats d'hydration BlockMeta/Slot ne produisent pas de RAW ReplayInfo ne prouve que la borne de rétention reconnect != replay != repair continuity gap prouvé => fault, pas backfill implicite frontier est processing-only et run-local provenance multi-hop est encodée dans les champs sûrs existants, sans migration Store aucun SDK provider ``` ## 21. Questions reportées sans blocage ```text RAW-direct Yellowstone après preuve byte-exact complète retry Worker spécifique pour getTransaction null source redundancy/failover multi-provider hot reconfiguration complète des listeners repair automatique via source secondaire/HTTP block checkpoint durable inter-process provider-specific replay depth/capabilities permanentes WS/Helius transactionSubscribe/HTTP live polling ``` Ces sujets ne bloquent pas la première tranche technique `pre.002`. ## 22. Sources externes consultées Audit de fraîcheur réalisé le 8 septembre 2026 à partir de sources primaires/courantes : ```text https://solana.com/docs/rpc/http/gettransaction https://solana.com/docs/rpc/http/getblock https://github.com/rpcpool/yellowstone-grpc/blob/master/CHANGELOG.md https://github.com/rpcpool/yellowstone-grpc/releases https://docs.rs/crate/yellowstone-grpc-proto/12.7.0 https://docs.rs/crate/yellowstone-grpc-proto/12.7.0/source/proto/geyser.proto https://docs.rs/crate/yellowstone-grpc-proto/12.7.0/source/proto/solana-storage.proto https://docs.orbitflare.com/cli https://docs.orbitflare.com/products https://www.helius.dev/docs/grpc https://www.helius.dev/docs/laserstream/grpc https://www.helius.dev/docs/laserstream/historical-replay ``` Les limites/prix/replay provider restent datés et doivent être revérifiés lorsqu'un gate live les utilise.