# Plan `0.2.9` — Yellowstone gRPC standard/provider-neutral > **Statut : `0.2.9-pre.001` — gate audit/sizing positif. Aucune implémentation gRPC lourde ni dépendance Yellowstone/Tonic n'est introduite dans cette tranche. La stratégie cible est `yellowstone-grpc-proto` publié + client/lifecycle KSP autour de Tonic, avec PublicNode comme premier smoke live Mainnet/Testnet et OrbitFlare comme second smoke Devnet authentifié.** ## 1. Objet, base et état d'ouverture `0.2.9` introduit dans `ksp-onchain-transport-lib` une première fondation Yellowstone gRPC **standard et provider-neutral**, distincte de HTTP et de WebSocket. Base autoritaire auditée à l'ouverture : ```text archive opérateur = khadhroony-solana-project-v0.2.8-full-from-gitea.zip workspace.package.version initial = 0.2.8 deltas/0.2.8/rel.001.md présent prompts/014-V0_2_9_START_PROMPT.md présent prompt fourni = byte-identique au prompt embarqué metadata .git = absente de l'archive opérateur ``` Le signal d'ouverture est : ```text workspace.package.version = 0.2.9-pre.1 commit attendu = v0.2.9-pre.001 aucun tag prerelease ``` État hérité à ne pas régresser : ```text HTTP Solana 52/52 current typed + 14 historiques Deprecated/Removed KSP-TRANSPORT-007 appliqué WebSocket standard 9 familles / 18 subscribe-unsubscribe Helius LaserStream WS 7 familles standard + transactionSubscribe/unsubscribe Helius heartbeat Ping control frame 60 s, actor-owned Config Transport V1 HTTP + V2 HTTP/WS backward-readable Config -> Transport autorisé Transport -> Config interdit ``` ## 2. Résultat du gate `pre.001` Le gate est **positif avec scope borné**. `0.2.9` peut raisonnablement porter : ```text backend Yellowstone gRPC séparé settings/runtime bounds gRPC TLS + metadata générique et redacted 7 RPC unary du service Geyser courant hors SubscribeDeshred Subscribe bidirectionnel standard 7 familles de filtres top-level 9 variantes SubscribeUpdate DTOs KSP provider-neutral backpressure/half-close/shutdown bornés reconnect/resubscribe KSP-owned from_slot + SubscribeReplayInfo avec observabilité gap/duplicate/equivocation Config V3 dédiée gRPC, tout en lisant V1/V2 smokes live opt-in PublicNode puis OrbitFlare compliance HTTP/WS/Helius non régressée ``` Sont explicitement exclus : ```text SubscribeDeshred et pré-exécution/deshred adapters publics PublicNode/Allnodes/OrbitFlare/Tatum/Helius/Triton/etc. client autoreconnect upstream comme contrat public KSP pool/scheduler automatique complexe de sessions gRPC exactly-once / lossless / ordre global garanti serveur Geyser/plugin validator Store/workers/backfill historique ``` La présence de PublicNode et OrbitFlare **ne nécessite donc pas une couche provider-specific publique**. Ils entrent dans la release comme environnements d'interopérabilité et profils Config derrière le même backend Yellowstone standard. ## 3. Sources internes relues Le gate a relu les règles et documents imposés par le prompt depuis la base stable : ```text RULES.md docs/000-README.md docs/rules/RULES_GENERAL.md docs/rules/RULES_KSP.md docs/rules/RULES_RUST.md docs/rules/RULES_DEPENDENCIES.md docs/rules/RULES_DOCUMENTATION.md docs/rules/FILE_CONTRACTS.md docs/rules/VERSION_WORKFLOW.md docs/rules/PROMPT_STRUCTURE.md docs/architecture/000-README.md docs/architecture/002-LAYERS_AND_DEPENDENCIES.md docs/architecture/003-COMPONENT_CONTRACTS.md docs/architecture/004-COMPONENT_INVENTORY.md docs/architecture/005-DEPENDENCY_GRAPH.md docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md docs/architecture/010-APPS_SERVICES_SCENARIOS_AND_CONTROL.md docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md docs/plans/007-V0_2_0_SERIES_PLANNING.md docs/plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md docs/plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md docs/plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md docs/validation/003-V0_2_1_ONCHAIN_HTTP.md docs/validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md docs/validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md docs/validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md deltas/0.2.8/rel.001.md ``` Le code réel audité confirme notamment : - Transport possède déjà HTTP et WebSocket dans une seule crate ; - Config dépend de Transport, l'inverse est interdit ; - le schéma Transport V2 est fermé par `additionalProperties: false` et distingue `endpoints` / `ws_endpoints` ; - aucun contrat gRPC n'existe encore ; - les abstractions WebSocket ne doivent pas être réutilisées pour gRPC. ## 4. Baseline stable enregistrée La preuve opérateur fournie juste avant l'ouverture enregistre sur `v0.2.8` : ```text cargo fmt --all OK python3 scripts/audit_rust_workspace_rules.py OK / clean cargo check --workspace OK cargo clippy --workspace --all-targets OK cargo test --workspace OK cargo tree -p ksp-onchain-transport-lib fourni cargo tree --duplicates fourni ``` Sous-ensembles Transport observés pendant `cargo test --workspace` : ```text unit tests 335 passed public_api 41 passed release_completeness 34 passed doc-tests 4 passed live smokes opt-in / ignored par défaut ``` Dépendances directes Transport observées avant gRPC : ```text futures-util 0.3.34 reqwest 0.13.4 serde 1.0.229 serde_json 1.0.151 tokio 1.53.1 tokio-tungstenite 0.30.0 ksp-core-lib 0.2.8 ksp-logging-lib 0.2.8 ``` Le graphe existant contient déjà les familles modernes suivantes via HTTP/WS : ```text bytes 1.x http 1.x hyper 1.x hyper-util 0.1.x tower 0.5.x rustls 0.23.x tokio-rustls 0.26.x ``` Le coût réel de `tonic/prost/yellowstone-grpc-proto` devra néanmoins être mesuré après matérialisation en `pre.002`; aucun doublon n'est préjugé acceptable avant `cargo tree`. ## 5. Audit upstream Yellowstone au 2026-08-23 ### 5.1 Divergence du snapshot du prompt Le snapshot préparatoire du prompt mentionnait `v14.2.2+solana.4.1.0` comme release GitHub observée. Le réaudit courant trouve désormais : ```text release GitHub latest = v15.1.2+solana.4.2.0 publication release = 2026-08-18 Rust annoncé = 1.96.1 ``` Le changelog master indique en outre : ```text 2026-08-17 yellowstone-grpc-geyser 15.1.2 2026-08-10 yellowstone-grpc-proto 12.6.0 2026-07-31 yellowstone-grpc-client 13.3.0 ``` Cela confirme que **version du plugin GitHub, version du client crate et version du proto crate évoluent indépendamment**. Sources primaires : ```text https://github.com/rpcpool/yellowstone-grpc/releases https://github.com/rpcpool/yellowstone-grpc/blob/master/CHANGELOG.md https://github.com/rpcpool/yellowstone-grpc/blob/master/yellowstone-grpc-proto/proto/geyser.proto https://docs.rs/crate/yellowstone-grpc-proto/latest https://docs.rs/crate/yellowstone-grpc-client/latest ``` ### 5.2 Crates publiées retenues pour le gate État publié observé : ```text yellowstone-grpc-client = 13.3.0, publié 2026-07-31 yellowstone-grpc-proto = 12.6.0, publié 2026-08-13 sur docs.rs prost/prost-types = 0.14.x tonic = 0.14.x ``` `yellowstone-grpc-client 13.3.0` dépend notamment de : ```text bytes ^1.10.1 futures ^0.3.24 hyper ^1.4.1 hyper-util ^0.1.7 tokio ^1.47.1 tonic ^0.14.0 tonic-health ^0.14.0 tower ^0.5.0 yellowstone-grpc-proto ^12.5.0 ``` Il expose désormais un `AutoReconnect`, une politique de reconnexion et de la déduplication/replay. Ces capacités sont utiles comme référence, mais ne doivent pas posséder la sémantique publique KSP. `yellowstone-grpc-proto 12.6.0` dépend notamment de : ```text prost ^0.14.0 prost-types ^0.14.0 solana-pubkey ^4.0.0 thiserror ^2.0.16 siphasher ^1 tonic ^0.14.0 optionnel tonic-prost ^0.14.0 optionnel bytes ^1.10.1 optionnel ``` Le `solana-pubkey ^4.0` du proto est compatible en gamme avec le `^4.3` déjà utilisé par KSP ; l'unification exacte sera vérifiée par Cargo en `pre.002`. ### 5.3 Licences Le dépôt upstream déclare : ```text licence par défaut du repository = AGPL-3.0-only ``` mais `LICENSING.md` affecte explicitement **Apache-2.0** aux sous-arbres : ```text examples/ yellowstone-grpc-client/ yellowstone-grpc-client-nodejs/ yellowstone-grpc-proto/ ``` Conséquence du gate : - dépendre de la crate publiée `yellowstone-grpc-proto` est compatible avec la distribution MIT de KSP sous réserve des obligations Apache usuelles ; - aucun fichier provenant des zones AGPL du repository ne sera copié dans KSP ; - KSP ne vendore pas les `.proto` dans la stratégie retenue ; - si un fichier upstream devait être copié ultérieurement, sa provenance et sa licence seraient réauditées fichier par fichier avant incorporation. Sources : ```text https://github.com/rpcpool/yellowstone-grpc/blob/master/LICENSING.md https://docs.rs/crate/yellowstone-grpc-proto/latest ``` ### 5.4 MSRV / build Observations pertinentes : ```text plugin release 15.1.2 Rust 1.96.1 tonic 0.14.6 rust-version 1.88 prost 0.14.x MSRV publié actuellement 1.85 proto crate 12.6.0 génération incluse dans la crate publiée ``` Le build de `yellowstone-grpc-proto` utilise une chaîne de génération avec `protoc` vendored côté crate publiée ; KSP n'a donc pas à ajouter son propre `build.rs` ni à exiger un `protoc` système pour la stratégie B. Le MSRV du **plugin Geyser** n'est pas le MSRV automatique du client KSP. Le gate technique final reste la toolchain réellement utilisée par le workspace et la compilation des dépendances choisies en `pre.002`. ## 6. Matrice du service `Geyser` courant Le proto publié `yellowstone-grpc-proto 12.6.0` et le proto master exposent le même inventaire de service observé pendant le gate : | RPC | Forme | Statut | Cible `0.2.9` | Décision | | --- | --- | --- | --- | --- | | `Subscribe` | bidi stream | standard Yellowstone | **oui** | fondation principale | | `SubscribeDeshred` | bidi stream | présent dans proto, trajectoire Triton extension/pré-exécution | **non** | report explicite | | `SubscribeReplayInfo` | unary | standard | **oui** | information de replay, pas garantie lossless | | `Ping` | unary | standard | **oui** | canari/liveness unary | | `GetLatestBlockhash` | unary | standard | **oui** | canari typed | | `GetBlockHeight` | unary | standard | **oui** | canari typed | | `GetSlot` | unary | standard | **oui** | canari typed | | `IsBlockhashValid` | unary | standard | **oui** | canari typed | | `GetVersion` | unary | standard | **oui** | canari typed | `SubscribeDeshred` est techniquement publié dans le proto, mais le changelog upstream le rattache explicitement aux **Triton Extension Patches** et décrit la réception de transactions avant exécution. Il reste donc hors fondation provider-neutral `0.2.9`. ## 7. Matrice `SubscribeRequest` Surface standard retenue intégralement : | Champ | Type / sémantique | `0.2.9` | | --- | --- | --- | | `accounts` | map nom -> `SubscribeRequestFilterAccounts` | oui | | `slots` | map nom -> `SubscribeRequestFilterSlots` | oui | | `transactions` | map nom -> `SubscribeRequestFilterTransactions` | oui | | `transactions_status` | même famille de filtre transaction | oui | | `blocks` | map nom -> `SubscribeRequestFilterBlocks` | oui | | `blocks_meta` | map nom -> filtre vide | oui | | `entry` | map nom -> filtre vide | oui | | `commitment` | optional Processed/Confirmed/Finalized | oui | | `accounts_data_slice` | repeated offset/length | oui | | `ping` | optional request ping/id | oui | | `from_slot` | optional u64 | oui, sémantique prudente | ### 7.1 Accounts ```text account[] owner[] filters[] nonempty_txn_signature? cuckoo_accounts_filter? ``` Filtres account : ```text memcmp { offset, oneof bytes | base58 | base64 } datasize token_account_state lamports { oneof eq | ne | lt | gt } ``` Les formes Cuckoo actuelles sont conservées parce qu'elles appartiennent au proto publié standard observé, pas parce qu'un provider particulier les demande. ### 7.2 Slots ```text filter_by_commitment? interslot_updates? ``` `SlotStatus` courant : ```text processed confirmed finalized first_shred_received completed created_bank dead ``` ### 7.3 Transactions / transaction_status ```text vote? failed? signature? account_include[] account_exclude[] account_required[] cuckoo_account_include? token_accounts? = ALL | BALANCE_CHANGED ``` L'optional `token_accounts` contrôle l'expansion vers les owners de token accounts dans les balances pre/post ; son absence est distincte de ses deux valeurs connues. ### 7.4 Blocks ```text account_include[] include_transactions? include_accounts? include_entries? cuckoo_account_include? ``` ### 7.5 BlocksMeta / Entry Les deux filtres sont actuellement des messages vides : leur **présence nommée** active la famille ; KSP doit donc conserver la distinction absence / map vide / entrée nommée vide au niveau de son contrat logique. ### 7.6 Common ```text commitment? Processed | Confirmed | Finalized accounts_data_slice offset + length ping? id from_slot? u64 ``` KSP appliquera des bornes déterministes avant I/O sur les noms, cardinalités, listes de comptes/owners, memcmp, data slices et tailles de payload. Les valeurs exactes sont un contrat KSP et non une copie aveugle des quotas d'un provider ; elles seront matérialisées avec tests en `pre.004`. ## 8. Matrice `SubscribeUpdate` Le `oneof update_oneof` standard contient exactement neuf variantes observées : | Variante | Champs structurants à préserver | | --- | --- | | `account` | account info + slot + `is_startup` | | `slot` | slot + optional parent + status + optional dead_error | | `transaction` | signature/is_vote/transaction/meta/index + slot | | `transaction_status` | slot/signature/is_vote/index/error | | `block` | slot/hash/rewards/time/height/parent/counts + transactions/accounts/entries | | `ping` | marker server ping | | `pong` | id | | `block_meta` | block metadata/counts sans tableaux complets | | `entry` | slot/index/num_hashes/hash/transaction counts/index | Le top-level contient aussi : ```text filters[] noms de filtres correspondants created_at google.protobuf.Timestamp ``` Les types imbriqués `solana-storage.proto` nécessaires aux transactions/blocs seront projetés dans des types KSP sans perte arbitraire de champs utiles. Les types Prost/Yellowstone générés restent internes au backend et ne sont pas réexportés dans l'API publique. ## 9. RPCs unary retenus | RPC | Request | Response | Notes | | --- | --- | --- | --- | | `SubscribeReplayInfo` | vide | `first_available?` | information de disponibilité seulement | | `Ping` | `count` | `count` | exact echo attendu | | `GetLatestBlockhash` | `commitment?` | slot, blockhash, last_valid_block_height | typed | | `GetBlockHeight` | `commitment?` | block_height | typed | | `GetSlot` | `commitment?` | slot | typed | | `IsBlockhashValid` | blockhash + `commitment?` | slot + valid | typed | | `GetVersion` | vide | version | opaque string bornée | Les unary ne remplacent pas les méthodes HTTP équivalentes : ce sont des capacités du backend Yellowstone et restent séparées des wrappers JSON-RPC HTTP existants. ## 10. Replay, reconnexion et continuité Le changelog upstream contient deux signaux qui interdisent une promesse simpliste : ```text 2026-07-22 : correction d'un replay blocks from_slot accepté mais reprenant live avec state gap 2026-06-15 : auto-reconnect upstream modifié pour mettre le replay en quarantaine et comparer les blockhashes afin de traiter l'equivocation entre nodes ``` Décision KSP : ```text reconnect automatique oui, borné et KSP-owned resubscribe déterministe oui from_slot oui, sans promesse lossless SubscribeReplayInfo oui, informatif exactly-once non garanti lossless non garanti ordre global sans gap non garanti duplicate possible oui, observable/traité selon scope gap possible oui, observable equivocation node/fork observable quand preuve disponible ``` Observabilité cible : ```text reconnect_count continuity_gap_count duplicate_update_count replay_attempt_count last_requested_from_slot last_observed_slot terminal error code safe ``` Une détection d'equivocation peut nécessiter une preuve de blockhash ; si elle ne peut pas être généralisée proprement à toutes les familles, le plan exige de documenter sa couverture exacte au lieu de l'annoncer globalement. ## 11. Stratégie dépendances — A/B/C ### A. `yellowstone-grpc-client + yellowstone-grpc-proto` Avantages : client prêt, TLS/connect/reconnect déjà implémentés. Inconvénients : - sémantique autoreconnect/replay/dedup upstream importée implicitement ; - davantage de dépendances et types upstream ; - risque de fuite de types/client brut dans l'API KSP ; - contrôle moindre sur redaction, backpressure et lifecycle. **Décision : non retenue comme stratégie principale.** Le client reste une référence et peut servir ponctuellement à vérifier le wire dans les tests/outils si nécessaire, sans devenir contrat public. ### B. `yellowstone-grpc-proto + client KSP autour de tonic` Avantages : - proto publié Apache-2.0, pas de copie vendored ; - wire officiel généré disponible ; - Tonic 0.14 aligné avec l'écosystème HTTP/2 moderne déjà présent ; - KSP garde reconnect/backpressure/errors/redaction ; - types upstream cachés derrière les DTOs KSP ; - `solana-pubkey` reste dans la même major actuelle. **Décision : stratégie cible retenue.** Matérialisation attendue en `pre.002` : ```text yellowstone-grpc-proto ^12.6 workspace dependency, features minimales tonic ^0.14 workspace dependency, features client/TLS minimales prost/prost-types pas de direct dependency KSP sauf besoin démontré tokio-stream/futures seulement si nécessaire et sans doublon gratuit ``` L'exacte feature set sera déterminée par compilation et `cargo tree`, pas par anticipation documentaire. ### C. proto/génération KSP minimale bornée Avantage : contrôle maximum du code généré. Inconvénients : copie/licence/synchronisation du proto, `build.rs`, protoc et dette de suivi plus forte. **Décision : reportée/fallback uniquement si B bloque une exigence KSP démontrée.** ## 12. Architecture publique cible ### 12.1 Séparation des backends ```text HTTP TransportSettings / EndpointClient / pool HTTP existants WebSocket Ws* existants Yellowstone gRPC nouveaux Grpc*/Yellowstone* dédiés ``` Interdictions : ```text pas de WsProtocolKind pour gRPC pas de WsEndpointSettings réutilisé pas de WsSession déguisée pas de client Tonic brut réexporté ``` ### 12.2 Noms et ownership Noms cibles, affinables sans casser le principe : ```text YellowstoneGrpcEndpointUrl YellowstoneGrpcEndpointSettings YellowstoneGrpcSessionSettings YellowstoneGrpcTransportSettings YellowstoneGrpcSession YellowstoneSubscriptionHandle YellowstoneSubscribeRequest / filters KSP YellowstoneUpdate / typed update projections ``` Le backend wire Tonic/Prost reste privé. Tous les types publics nécessaires sont réexportés au crate root conformément aux règles KSP. ### 12.3 Metadata/auth provider-neutral Transport reçoit : ```text metadata publique bornée metadata sensible via wrapper opaque/redacted ``` Il ne connaît : ```text aucun nom KSP_SECRET_* aucun std::env aucun header PublicNode/OrbitFlare/Tatum hardcodé comme contrat standard ``` Les clés metadata sont validées avant I/O ; les valeurs sensibles ne sont jamais dans `Debug`, `Display`, `KspError`, logs ou snapshots. ## 13. Config V3 cible Le schéma V2 actuel est fermé et possède : ```text profiles[].endpoints profiles[].ws_endpoints ``` Ajouter gRPC dans V2 ferait évoluer silencieusement une shape fermée. Le gate retient donc **une V3 explicite**, tout en conservant V1/V2 backward-readable. Shape conceptuelle cible : ```text format_version = 3 globals.grpc_defaults profiles[].grpc_endpoints[] ``` Chaque endpoint gRPC doit pouvoir porter au minimum : ```text name enabled provider descriptif cluster descriptif url metadata publique optionnelle secret_metadata optionnelle session/runtime overrides bornés optionnels ``` Règle de sensibilité : - `metadata` ne contient que des valeurs non secrètes ; - `secret_metadata` est une classe séparée ; - Config résout les placeholders et exige une provenance/sensibilité secret appropriée avant mapping ; - Transport reçoit une valeur opaque/redacted et ne sait pas quel env l'a produite. `grpc_defaults` porte les defaults génériques utiles : ```text connect timeout unary timeout close timeout max inbound/outbound message size request/update channel capacities max logical filter groups/names reconnect attempts/backoff ``` La forme JSON exacte et les bornes sont matérialisées en `pre.010`, mais **la décision V3 + `grpc_endpoints` séparés + metadata publique/secrète séparée est fermée par `pre.001`**. ## 14. Audit fournisseurs gRPC gratuits et durables L'objectif n'est pas de sélectionner un SDK provider mais de disposer de smokes accessibles sans abonnement payant éphémère. ### 14.1 PublicNode / Allnodes — priorité 1 PublicNode annonce explicitement des endpoints « free-est » et liste pour Solana : ```text Mainnet: Yellowstone GRPC Testnet: GRPC ``` Endpoint Mainnet affiché officiellement au gate : ```text solana-yellowstone-grpc.publicnode.com:443 ``` PublicNode est un service soutenu/opéré par Allnodes dans l'écosystème actuel ; il ne faut pas modéliser « PublicNode » et « Allnodes » comme deux protocoles Yellowstone distincts. Décision `0.2.9` : ```text pas de PublicNodeGrpcSession publique pas de AllnodesGrpcSession publique PublicNode Mainnet = premier smoke live opt-in sans secret PublicNode Testnet = second cluster du même smoke/provider si endpoint exact confirmé live ``` La page officielle confirme l'existence de Testnet GRPC, mais le hostname exact n'est pas figé dans ce gate tant qu'il n'a pas été confirmé depuis la surface officielle/live. Il sera vérifié avant ajout d'un profil committé. Sources : ```text https://publicnode.com/ https://solana-yellowstone-grpc.publicnode.com/ ``` ### 14.2 OrbitFlare — priorité 2 Le pricing officiel courant annonce pour le plan Free : ```text $0/mo 10 RPS 1 TPS gRPC Access = Devnet only Credit Limits = Unlimited ``` Cela répond au besoin « gratuit durable » mieux qu'un trial de quelques jours, mais nécessite un compte/credential. Décision `0.2.9` : ```text OrbitFlare Devnet = smoke live opt-in secondaire auth = via generic secret metadata Config -> Transport aucun OrbitFlareGrpc* public aucun header provider hardcodé avant vérification exacte de la doc/live ``` Source : ```text https://orbitflare.com/pricing ``` ### 14.3 Tatum — candidat tertiaire, non gate Tatum documente un endpoint Yellowstone Solana Mainnet et un plan Free utilisable sans abonnement payant, mais le plan courant impose : ```text 3 RPS 100K lifetime credits 5 subscriptions ``` Le caractère « forever » du plan n'en fait donc pas une ressource illimitée dans le temps : le quota de crédits est lifetime. Décision : **candidat manuel tertiaire**, utile pour interop Mainnet authentifiée, mais pas dépendance du gate `0.2.9`. Sources : ```text https://docs.tatum.io/reference/solana-grpc https://tatum.io/pricing ``` ### 14.4 Fournisseurs vérifiés mais non retenus comme gratuits gRPC État courant vérifié : ```text Helius Free: pas de LaserStream gRPC ; Devnet à partir de Developer, Mainnet Business Shyft Free: No gRPC Access Alchemy Yellowstone gRPC: PAYG ou Enterprise requis QuickNode Yellowstone gRPC: Scale/Business ou add-on payant Chainstack Yellowstone gRPC: add-on payant à partir de 49 USD/mois, Growth+ ERPC Geyser gRPC payant ; seulement trial 1 jour sur le plan Standard NodeFlare endpoint Yellowstone publié, mais plan Yellowstone à forfait mensuel Bitquery CoreCast gRPC n'est pas Yellowstone ; accès stream gratuit non garanti et offre publique payante/trial ``` Candidat non validé comme gratuit durable : ```text Solinfra site public = free tier + Yellowstone annoncés, mais entitlement gRPC du free tier non explicite ``` Solinfra pourra être revalidé en `pre.011` si une grille publique ou le dashboard confirme un droit Yellowstone durable à 0 USD. Triton et d'autres providers peuvent également être réaudités si leur offre change, mais aucun autre accès Yellowstone gratuit durable n'a été confirmé avec une preuve publique suffisante pendant ce gate. ## 15. Smoke ownership Le smoke live reste opt-in et n'autorise aucune violation architecturale. Hiérarchie cible : ```text 1. Transport pur programmatic -> PublicNode Mainnet, sans secret 2. Transport pur programmatic -> PublicNode Testnet, si endpoint exact confirmé 3. composition Config V3 -> Transport -> OrbitFlare Devnet, secret résolu par Config 4. Tatum Mainnet authentifié, opérateur-only si utile ``` Le smoke 1/2 peut vivre dans `ksp-onchain-transport-lib/tests` car il construit ses settings programmatiquement et ne teste que Transport. Le smoke 3 ne doit pas être ajouté à `ksp-config-lib` par facilité. Si aucune surface d'intégration dédiée n'existe encore, il peut rester une procédure opérateur/documentée ou être placé sur une surface de composition déjà légitime ; le plan doit revalider l'owner au moment de `pre.010/pre.011`. Aucun secret provider n'est versionné. ## 16. Threat model et bornes ### 16.1 Secrets / diagnostics Menaces : ```text URI avec credential metadata gRPC sensible Status/message/details provider arbitraires Debug dérivé de requests/filtres TLS/connect errors réémettant URI/metadata ``` Réponse : projections sûres, error codes KSP, contexts allowlistés et redaction testée. ### 16.2 Ressources À borner avant I/O : ```text URL/metadata key/value lengths connect/unary/close timeouts max inbound/outbound message sizes request/update channel capacities nombre de filter groups longueur et unicité des filter names account/owner/include/exclude/required counts memcmp filters + payload size data slices Cuckoo filter dimensions/data size block/account/transaction update payload reconnect attempts/backoff ``` ### 16.3 Backpressure Politique : ```text aucune queue non bornée aucun drop silencieux présenté lossless overflow observable slow logical subscription isolée si possible shutdown déterministe ``` ### 16.4 Lifecycle adversarial Tester au minimum : ```text server half-close client close remote Status malformed/unknown enum oneof absent/inattendu oversized inbound/outbound stream flood mutation de filtres pendant updates late update après mutation/unsubscribe reconnect loop shutdown during reconnect reconnect sur node divergent duplicate/gap après from_slot/replay TLS/certificate failure unary timeout ``` ## 17. Forecast souple recalibré Prévision courante : ```text pre.001 DONE — audit upstream/service/proto + providers gratuits + licences/deps + architecture + threat model + sizing preuve : plan + matrice + stratégie B + Config V3 décidée + forecast recalibré pre.002 proto/dependencies matérialisés + settings/errors/façade gRPC minimale provider-neutral preuve : features justifiées + compile/tests + redaction + cargo tree direct/duplicates pre.003 channel/TLS/metadata générique + fixture serveur local + 7 unary RPCs preuve : connect/TLS/timeouts/Status safe + wire unary exact pre.004 Subscribe foundation : maps, commitment, ping, from_slot, data slices, Cuckoo/token controls, validations/bounds preuve : omitted/empty/oneof exact + rejects avant I/O pre.005 Accounts + Slots : filters + typed updates preuve : fixtures exactes + enum/optional/malformed/adversarial pre.006 Transactions + transaction_status + solana-storage wire utile preuve : include/exclude/required/Cuckoo/token expansion + tx/meta sans perte arbitraire pre.007 Blocks + block_meta + entry + rewards/storage nested types preuve : counts/arrays/optional/oneof/payload bounds exacts pre.008 stream bidirectionnel : mutations, Ping/Pong, half-close, backpressure, shutdown preuve : actor/session local + bounded queues + cleanup déterministe pre.009 reconnect/resubscribe + from_slot/ReplayInfo + gaps/duplicates/equivocation observability preuve : reconnect local déterministe + aucune promesse lossless implicite pre.010 Config Transport V3 : grpc_defaults/grpc_endpoints + public/secret metadata + backward V1/V2 preuve : schema/fixtures/mapping/redaction + Config -> Transport uniquement pre.011 interop live + compliance : PublicNode Mainnet puis Testnet, OrbitFlare Devnet secondaire, Tatum optionnel preuve : smokes opt-in architecture-safe + HTTP 52/14 + WS 18/18 + Helius + API/firewall + cargo graph final pre.012 README/USAGE + matrice finale + workspace final + indexes + prompt 0.2.10 preuve : workspace final vert + documentation version-neutral + prompt autonome rel.001 publication stable stricte ``` Chaque tranche vise nominalement **15–20 minutes** de travail effectif. Le forecast n'est pas une deadline. ### Critères de split Scinder avant dette silencieuse si l'un de ces cas apparaît : 1. `yellowstone-grpc-proto + tonic` impose un conflit MSRV ou un doublon majeur de stack réseau impossible à justifier ; 2. les DTOs transactions/blocs exigent une réexposition massive des types upstream ou une réimplémentation disproportionnée ; 3. l'upstream modifie encore matériellement le proto pendant la release ; 4. le replay/reconnect devient un sous-système plus grand que la foundation ; 5. les smokes provider nécessitent des comportements non standard qui contamineraient l'API publique. En cas de split, le noyau prioritaire à conserver dans `0.2.9` est : ```text connexion/TLS/metadata + unary + Subscribe standard canonique + lifecycle borné ``` et le reste est replanifié explicitement dans la séquence ; aucune capacité n'est abandonnée silencieusement. ## 18. Fichiers attendus par tranche Cibles probables, sans imposer artificiellement le découpage source : ```text crates/ksp-onchain-transport-lib/src/grpc_settings.rs crates/ksp-onchain-transport-lib/src/grpc_session.rs crates/ksp-onchain-transport-lib/src/grpc_protocol.rs crates/ksp-onchain-transport-lib/src/grpc_subscribe.rs crates/ksp-onchain-transport-lib/src/grpc_updates.rs crates/ksp-onchain-transport-lib/src/grpc_unary.rs unit_tests/ correspondants tests/public_api.rs tests/release_completeness.rs tests/yellowstone_grpc_*_smoke.rs crates/ksp-config-lib/src/transport.rs config/std.transport.json config/schemas/std.transport.schema.json .env.example si des variables provider committées sont introduites ``` Les noms exacts restent soumis aux règles de structure du code réel ; ce plan ne force pas un fichier par concept si une composition plus claire apparaît. ## 19. Gates de validation Après chaque changement Rust : ```bash cargo fmt --all python3 scripts/audit_rust_workspace_rules.py cargo check --workspace cargo clippy --workspace --all-targets ``` Tests ciblés : ```bash cargo test -p ksp-onchain-transport-lib cargo test -p ksp-config-lib # seulement si Config modifiée ``` À la fermeture technique d'une prerelease : ```bash cargo test --workspace ``` Après ajout/modification de la stack gRPC : ```bash cargo tree -p ksp-onchain-transport-lib cargo tree -p ksp-onchain-transport-lib --duplicates cargo tree --duplicates ``` Inspecter en particulier : ```text yellowstone-grpc-proto tonic / tonic-prost prost / prost-types bytes / http / hyper / hyper-util tower rustls / tokio-rustls solana-* transitifs ``` ## 20. Conditions de clôture `0.2.9` ne devient stable que si : ```text inventaire service/proto courant réconcilié SubscribeDeshred explicitement exclu/classifié 7 unary RPCs retenus validés Subscribe standard retenu sans perte arbitraire 9 update variants traitées provider-neutral API sans raw client escape hatch metadata/secrets redacted resource bounds et backpressure testés reconnect/from_slot/replay documentés sans promesse lossless Config V3 backward V1/V2 si Config intégrée PublicNode interop Mainnet validée opt-in ou impossibilité externe documentée OrbitFlare Devnet validé si credential opérateur disponible, sinon procédure documentée HTTP 52+14 non régressé standard WS 18/18 non régressé Helius WS non régressé cargo graphs inspectés README/USAGE synchronisés matrice `012` fermée prompt 0.2.10 prêt workspace final vert ``` ## 21. Release suivante `0.2.10` reste dédiée à `ksp-offchain-transport-lib` et aux prix, sans être anticipée dans la stack Yellowstone.