Files
khadhroony-solana-project/docs/plans/033-V0_3_12_YELLOWSTONE_HYDRATION_CONTINUITY_PLAN.md
2026-09-09 11:44:36 +02:00

34 KiB
Raw Permalink Blame History

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 :

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 :

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 :

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 :

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 :

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 <= 1520 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 :

admission
error
identity
persistence
runtime
settings
snapshot
lib

La façade stable contient exactement la fondation nécessaire :

RawTransactionIngestSettings
RawTransactionIngestWorker
RawTransactionIngestHandle
RawTransactionIngestSnapshot
RawTransactionIngestSnapshotSource
RawTransactionIngestTerminalFuture
bornes et defaults runtime
ErrorCodes Worker

L'implémentation possède déjà :

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 :

RawTransactionIngestWorker::start(settings, Arc<Store>) -> RawTransactionIngestHandle

Il démarre volontairement sans adapter réseau productif.

4.2 Common RAW

ksp-raw-transaction-lib reste la seule propriété de :

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 :

YellowstoneGrpcChannel
SolanaYellowstoneGrpcSubscribeSession
YellowstoneSubscribeRequest
YellowstoneSubscribeUpdate
YellowstoneTransactionUpdate
YellowstoneTransactionStatusUpdate
YellowstoneBlockUpdate
YellowstoneBlockMetaUpdate
YellowstoneSlotUpdate
YellowstoneGrpcSubscribeSnapshot
YellowstoneReplayInfo

Le moteur possède déjà :

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 :

HttpTransportPool
HttpRoleName
get_transaction_observed
get_block_observed
HttpObservedValue<T>

HttpObservedValue préserve l'identité sûre du winner réel :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

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<u64>.

Décision :

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 :

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 :

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 :

ksp-worker-raw-transaction-ingest-lib -> ksp-onchain-transport-lib

Aucun edge nouveau vers :

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 :

RawTransactionIngestYellowstoneSource
RawTransactionIngestRuntimeResources

RawTransactionIngestYellowstoneSource::new reçoit conceptuellement :

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<Store>) 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 :

RawTransactionIngestWorker::start_with_runtime_resources(
    settings,
    Arc<Store>,
    RawTransactionIngestRuntimeResources,
) -> RawTransactionIngestHandle

Les décisions suivantes sont closes :

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 :

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 :

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 :

(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 :

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 :

block_time
meta
slot
transaction
transaction_index
version

10.2 Mismatch source/hydration

Avant admission :

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 :

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 :

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 :

protocol = yellowstone_http
provider = ys.<grpc_provider>:http.<http_provider>
endpoint_id = ys.<grpc_endpoint>:http.<http_endpoint>
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 :

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é :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

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 1520 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 :

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

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

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 :

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.