# Plan `0.2.10` — OrbitFlare Yellowstone gRPC **Statut courant : le gate technique/live final `0.2.10-pre.003` est vert. OrbitFlare Devnet est validé avec la License Key `ORBIT-*` portée par la metadata secrète `x-token` ; le smoke final observe un Slot non nul puis le `SubscribeUpdate::Ping` Yellowstone standard et ferme proprement la session. N1 et N2 restent inchangés, aucune façade provider ni heartbeat N3 n’est nécessaire. `0.2.10-pre.004` est exclusivement la réconciliation documentaire finale.** ## 1. Base et autorité Base stable autoritaire : ```text v0.2.9 ``` État vérifié dans l'archive Gitea fournie : ```text workspace.package.version = 0.2.9 deltas/0.2.9/rel.001.md présent prompts/015-V0_2_10_START_PROMPT.md présent plan 016 Yellowstone présent validation 012 Yellowstone présente Config Transport V3 présente PublicNode Mainnet + Testnet présents ``` Ordre d'autorité pendant `0.2.10` : ```text règles normatives KSP archive stable v0.2.9 et code réellement livré décisions du présent plan et validation 013 deltas immuables de 0.2.10 prompt 015 pour les contraintes non supersédées sources provider/upstream actuelles pour les faits externes ``` Le présent gate supersède une hypothèse du prompt : une divergence lifecycle OrbitFlare ne doit jamais être résolue par modification du moteur N1. Si elle ne peut pas être proprement composée au-dessus du moteur, elle devient un blocker/split explicite. ## 2. Mission opérationnelle réelle L'objectif prioritaire de `0.2.10` est de disposer d'au moins un provider Yellowstone **gratuit et durable sur Solana Devnet** pour les validations futures de KSP. PublicNode/Allnodes a déjà validé le standard KSP sur : ```text Mainnet Testnet ``` OrbitFlare complète cette couverture avec : ```text Devnet ``` Le pricing OrbitFlare observé le 2026-08-25 confirme : ```text plan Free 0 USD/mois RPC 10 RPS transactions 1 TPS gRPC Devnet only credit limits unlimited carte bancaire non requise selon la page d'accueil ``` Sources principales : ```text https://orbitflare.com/pricing https://orbitflare.com/products/rpc-nodes https://docs.orbitflare.com/cli ``` Mainnet OrbitFlare payant n'est pas un gate de cette release. Le résultat minimal utile est un smoke Yellowstone standard KSP sur l'endpoint Devnet gratuit. ## 3. Invariant architectural renforcé ### 3.1 N1 gRPC immuable Les modules qui constituent le moteur Yellowstone livré par `0.2.9` ne doivent pas être modifiés pour OrbitFlare : ```text src/grpc_settings.rs src/grpc_channel.rs src/grpc_unary.rs src/grpc_subscribe.rs src/grpc_stream.rs ``` Le même principe vaut durablement pour les moteurs physiques : ```text moteur HTTP provider-neutral moteur WebSocket provider-neutral moteur gRPC provider-neutral ``` Une release provider peut modifier : ```text provider facade provider policy provider capability projection Config provider profile provider smoke/compliance provider-specific tests ``` Elle ne modifie pas le moteur pour faire rentrer une différence fournisseur. ### 3.2 N2 standard Yellowstone immuable La surface Solana Yellowstone standard publiée par `0.2.9` reste la seule surface wire de référence : ```text Subscribe SubscribeReplayInfo Ping GetLatestBlockhash GetBlockHeight GetSlot IsBlockhashValid GetVersion accounts slots transactions transactions_status blocks blocks_meta entry commitment accounts_data_slice ping from_slot 9 variantes SubscribeUpdate ``` OrbitFlare ne redéfinit aucun DTO, filtre, unary, request ou update standard. ### 3.3 N3 provider uniquement si divergence démontrée Architecture cible : ```text OrbitFlare N3 -> standard Yellowstone N2 inchangé -> moteur gRPC N1 inchangé ``` Une façade OrbitFlare publique n'est créée que si un consumer KSP doit réellement voir une restriction ou une extension provider. Un simple endpoint, un `provider = orbitflare`, une policy Config ou un smoke ne suffisent pas à justifier une nouvelle API publique. ## 4. Baseline opérateur `v0.2.9` Preuves fournies le 2026-08-25 : | Gate | Résultat | |-------------------------------------------|------------------------------------------| | `cargo fmt --all` | PASS | | audit Rust workspace | PASS, 0 candidate export | | audit Markdown tables | PASS, 97 tables et 233 files sur `pre.1` | | `cargo check --workspace` | PASS | | `cargo clippy --workspace --all-targets` | PASS | | `cargo test --workspace` | PASS | | Transport unit | 383 sur 383 PASS | | Transport public API | 49 sur 49 PASS | | Transport release completeness | 43 sur 43 PASS | | Config unit | 113 sur 113 PASS | | PublicNode Yellowstone live | ignored opt-in comme attendu | | `cargo tree --duplicates` Transport | fourni et inspecté | | `cargo tree -p ksp-onchain-transport-lib` | fourni sur `0.2.10-pre.1` | Versions visibles dans le graphe fourni : ```text yellowstone-grpc-proto 12.6.0 tonic 0.14.6 tonic-prost 0.14.6 prost 0.14.4 tokio 1.53.1 http 1.5.0 reqwest 0.13.4 ``` Aucune seconde génération Tonic/Prost/Yellowstone incompatible n'est observée. Les doublons restants ne justifient aucun changement pour `0.2.10`. ## 5. Réaudit Yellowstone upstream du 2026-08-25 État courant observé : ```text release GitHub courante v15.1.2+solana.4.2.0 publication 2026-08-18 yellowstone-grpc-proto publié 12.6.0 stack proto prost 0.14 / tonic 0.14 ``` Sources : ```text https://github.com/rpcpool/yellowstone-grpc/releases https://github.com/rpcpool/yellowstone-grpc/blob/master/README.md https://github.com/rpcpool/yellowstone-grpc/blob/master/yellowstone-grpc-proto/proto/geyser.proto https://crates.io/crates/yellowstone-grpc-proto ``` Aucune évolution matérielle n'impose de changer le contrat KSP de `0.2.9`. Il n'y a donc aucun bump de dependency Yellowstone/Tonic/Prost prévu dans `0.2.10`. ## 6. Endpoint et network OrbitFlare Les sources actuelles distinguent plusieurs formes de service. | Élément | Observation actuelle | Décision KSP | |------------------------|-----------------------------------------------|---------------------------------------------| | Devnet gRPC | `http://devnet.rpc.orbitflare.com:10000` | premier endpoint live à tester | | endpoint régional | `http://{region}.rpc.orbitflare.com:10000` | descriptif, pas de fallback inventé | | endpoint licence/dédié | `https://your-endpoint.grpc.orbitflare.com` | utiliser uniquement si Dashboard le fournit | | `http` | HTTP/2 plaintext | ne jamais présenter comme TLS | | `https` | HTTP/2 TLS | conserver tel quel | | Mainnet | disponible selon plan/service | non requis pour le gate gratuit | | Devnet | explicitement documenté | **IN** | | Testnet | CLI accepte le label mais endpoint non prouvé | non requis, ne rien inventer | Sources : ```text https://docs.orbitflare.com/cli https://docs.orbitflare.com/sdk/go-grpc https://docs.orbitflare.com/data-streaming/yellowstone-quickstart ``` L'endpoint Dashboard opérateur reste autoritaire lorsqu'il existe. KSP ne transforme jamais automatiquement une URL `http` en `https`, ne change pas de région et ne construit pas un hostname provider non documenté. ## 7. Auth OrbitFlare : classification live corrigée Le live `pre.002` et les sources OrbitFlare permettent désormais de séparer les credentials sans supposition. | Credential ou mécanisme | Usage observé | Classification après `pre.002` | |-------------------------|---------------------------|------------------------------------------------------| | `X-ORBIT-KEY` | Customer API | control-plane, interdit sur Yellowstone | | Bearer Device Flow | Customer API v2 | control-plane | | `api_key` RPC | Solana HTTP RPC | data-plane HTTP | | License Key `ORBIT-*` | produit Solana Free | data-plane provider | | metadata `x-token` | Yellowstone gRPC | transport prouvé de la License Key | | aucune metadata | premier smoke KSP | rejetée `Unauthenticated` au `SubscribeOpen` | | IP whitelist | autre mode d’auth produit | non retenu pour le service opérateur en API Key Mode | La référence Yellowstone OrbitFlare donne explicitement le modèle suivant : ```text ORBITFLARE_LICENSE_KEY -> metadata gRPC x-token -> Yellowstone ``` Le Dashboard opérateur confirme parallèlement que le produit `Solana Free` est en `API Key Mode Active`, donc utilisable depuis toute IP avec la License Key. Le `X-ORBIT-KEY` et le Bearer issus du Device Flow restent réservés au Customer API. Le CLI OrbitFlare courant ne constitue pas un canari gRPC d’auth fiable : son `ping` ouvre le canal sans injecter la License Key et reçoit `invalid x-token: api key not found`. Ce défaut du CLI ne modifie pas le contrat provider documenté. Décision : ```text ne jamais versionner la License Key réelle ne jamais injecter X-ORBIT-KEY dans Yellowstone représenter la License Key par secret_metadata x-token dans Config V3 faire lire le secret du smoke par stdin, jamais par argument CLI ne modifier ni N1 ni N2 pour cette auth provider ``` ## 8. Heartbeat : réconciliation KSP / Yellowstone / OrbitFlare ### 8.1 Faits upstream Yellowstone upstream documente que : ```text les load balancers peuvent fermer un stream si le client reste silencieux le serveur Yellowstone envoie un SubscribeUpdate::Ping périodique le client peut répondre par un SubscribeRequest::Ping le serveur répond alors par SubscribeUpdate::Pong ``` Source : ```text https://github.com/rpcpool/yellowstone-grpc/blob/master/README.md ``` ### 8.2 Faits OrbitFlare OrbitFlare documente : ```text idle timeout partagé environ 10 minutes client ping recommandé toutes les 30 secondes produit gRPC recommandation 15 à 30 secondes SDK Go PingInterval default 10 secondes SDK Go MaxMissedPongs 3 ``` Sources : ```text https://docs.orbitflare.com/data-streaming/yellowstone https://docs.orbitflare.com/authentication https://docs.orbitflare.com/sdk/go-grpc https://orbitflare.com/products/solana-grpc ``` ### 8.3 Couverture KSP déjà présente Le moteur `0.2.9` possède déjà exactement la réponse standard : ```text SubscribeUpdate::Ping reçu -> send_automatic_ping(...) -> SubscribeRequest::Ping envoyé sur le stream existant -> request de subscription mémorisée inchangée ``` Cette propriété est testée déterministiquement par le moteur N1. ### 8.4 Décision `pre.001` La décision initiale de ne pas modifier le moteur est confirmée par le live final. Le smoke authentifié `pre.002-fix.001`, puis son rerun dans `pre.003`, ont observé le `SubscribeUpdate::Ping` standard sur OrbitFlare Devnet : ```text OrbitFlare server Ping live + KSP N1 automatic Ping reply deterministic test = activité bidirectionnelle standard suffisante sans code provider supplémentaire ``` Résultat final : ```text heartbeat OrbitFlare N3 non nécessaire façade provider non nécessaire YellowstoneGrpcSessionSettings inchangé grpc_stream.rs inchangé latest_request reconnect sémantique N1 préservée ``` Il reste interdit d'ajouter un timer dans `grpc_stream.rs` ou `YellowstoneGrpcSessionSettings` pour OrbitFlare. La recommandation provider d’un ping client périodique ne devient pas une policy globale tant que le chemin standard serveur Ping -> réponse automatique N1 satisfait le service live. Le point de sécurité initial reste durable : envoyer naïvement une requête `ping` seule via la mutation publique remplacerait la dernière subscription mémorisée pour reconnect. Si un futur provider exige un heartbeat proactif indépendant, cette policy doit être composée au-dessus de N1 sans corrompre cette sémantique. ## 9. Capabilities OrbitFlare ### 9.1 Streaming documenté OrbitFlare documente actuellement : ```text accounts transactions slots blocks blocks_meta entry commitment accounts_data_slice ping ``` Le CLI/SDK montre également les filtres account/transaction/slot/block standard nécessaires aux canaris principaux. ### 9.2 Surface non encore prouvée provider Ces capacités existent dans N2 KSP mais n'ont pas été exhaustivement sondées sur le plan OrbitFlare Free pendant `0.2.10` : ```text SubscribeReplayInfo Ping unary GetLatestBlockhash GetBlockHeight GetSlot IsBlockhashValid GetVersion from_slot et retention réelle transactions_status complet champs récents compressed/cuckoo/token expansion selon endpoint déployé ``` La clôture de `0.2.10` ne transforme pas l'absence de probe en absence de support. Le live final requis portait sur le chemin opérationnel utile à la release : authentification, standard Subscribe, Slot, Ping serveur et close borné. Classification durable : ```text standard KSP disponible oui dans N2 provider support live prouvé Subscribe slots + commitment + Ping provider entitlement éventuel provider-owned reste unknown / non exhaustivement testé ``` Aucune capacité N2 n'est supprimée du standard global à cause d'une restriction ou d'un inconnu OrbitFlare. ## 10. Limits et quotas utiles La documentation actuelle des services partagés indique : | Limite | Valeur observée | Traitement KSP | |-----------------------------|------------------------------------------|---------------------------------------------| | connexions gRPC simultanées | 50 par IP | information provider, pas borne N1 | | portée du cap | globale par IP et régions gRPC partagées | éviter les reconnect storms | | subscriptions par connexion | unlimited | ne pas convertir en garantie universelle | | idle timeout | environ 10 minutes | chemin Ping standard validé live | | dépassement | gRPC `RESOURCE_EXHAUSTED` | status distant safe existant | | reconnect conseillé | exponential backoff | KSP N1 possède déjà un budget/backoff borné | Ces valeurs commerciales/opérationnelles ne deviennent pas des constantes du standard KSP. ## 11. Config V3 Le schéma V3 existant représente directement le contrat live corrigé : ```text provider = orbitflare cluster = devnet protocol = solana_yellowstone url = http://devnet.rpc.orbitflare.com:10000 metadata = [] secret_metadata = x-token <- ${KSP_SECRET_ORBITFLARE_DEVNET_GRPC_X_TOKEN} ``` La variable porte la License Key `ORBIT-*` du produit Solana Free. Elle ne porte jamais `X-ORBIT-KEY`. Décision : ```text pas de format_version 4 pas de champ region si l’URL suffit pas de heartbeat dans grpc_defaults secret provider géré par Config V3 existante redaction KSP obligatoire dans safe/debug projections ``` Le profil `orbitflare_devnet` conserve les companions HTTP/WS Solana Devnet standards et ajoute exactement un endpoint gRPC authentifié par secret metadata `x-token`. ## 12. Stratégie live Devnet ### 12.1 Résultat du premier canari `pre.002` Le smoke initial utilisait le standard N2 directement, sans Config et sans metadata. Le canal physique a atteint le service OrbitFlare, puis l’ouverture du Subscribe a retourné : ```text grpc_operation = SubscribeOpen grpc_status = Unauthenticated grpc_code = The request does not have valid authentication credentials ``` Cette preuve ferme l’hypothèse « Devnet Free sans metadata ». ### 12.2 Canari corrigé `pre.002-fix.001` Le même test reste provider-neutral et ne dépend toujours pas de Config. Il lit une seule License Key sur stdin puis construit la metadata secrète standard : ```text endpoint = http://devnet.rpc.orbitflare.com:10000 provider = orbitflare cluster = devnet protocol = solana_yellowstone auth = x-token <- License Key lue sur stdin request = Subscribe slots à commitment confirmed preuve = au moins un Slot non nul + SubscribeUpdate::Ping close = borné ``` La valeur secrète n'apparaît ni dans Debug ni dans la ligne de commande. Résultats opérateur : ```text pre.002-fix.001 Subscribe -> Slot + Ping PASS en 5.10 s pre.003 final Subscribe -> Slot + Ping PASS en 5.19 s ``` Le second passage ferme le gate live sur la version `0.2.10-pre.3` utilisée pour la clôture technique. ### 12.3 Preuve heartbeat Le `SubscribeUpdate::Ping` standard est observé live sur OrbitFlare Devnet avec l'auth correcte. La combinaison suivante est donc prouvée : ```text Subscribe authentifié -> Slot non nul -> SubscribeUpdate::Ping serveur -> chemin de réponse automatique N1 déjà couvert déterministiquement -> close borné ``` Verdict final : aucune divergence heartbeat OrbitFlare ne justifie une façade ou une policy provider. Le moteur gRPC et le standard Yellowstone restent inchangés. ### 12.4 Unary et replay Les sept unary N2, `SubscribeReplayInfo` et la retention `from_slot` n'ont pas été rendus obligatoires pour le gate OrbitFlare Free. Cette décision évite de confondre : ```text complétude du standard KSP N2 support/entitlement d'un provider particulier preuve minimale nécessaire à la mission Devnet de 0.2.10 ``` Le moteur N1 reste capable d'utiliser `SubscribeReplayInfo` quand il est disponible et tolère son indisponibilité pendant reconnect en poursuivant avec le `from_slot` conservateur demandé. Aucun comportement provider n'est introduit pour combler un inconnu de service. ## 13. Threat model recalibré Le gate retient : ```text Customer API key injectée sur le mauvais plan gRPC token confondu avec X-ORBIT-KEY secret metadata leak endpoint Dashboard sensible plaintext http présenté comme TLS IP/network entitlement mal classifié heartbeat ajouté au moteur global par erreur ping provider écrasant le last accepted full request ping flood missed pong surinterprété RESOURCE_EXHAUSTED et reconnect storm 50 connections par IP consommées par des smokes mal fermés region failover changeant de node/fork from_slot hors retention provider unary unavailable remote Status arbitraire SDK OrbitFlare introduit sans nécessité ``` ## 14. Surface de code autorisée et interdite ### 14.1 Interdit par défaut ```text modification grpc_stream.rs modification grpc_channel.rs pour une policy OrbitFlare modification grpc_settings.rs pour un heartbeat OrbitFlare modification des DTOs grpc_subscribe.rs second raw Tonic client orbitflare-sdk-rs dependency provider-specific proto Transport -> Config/env ``` ### 14.2 Autorisé si nécessaire ```text profil Config V3 orbitflare_devnet smoke provider utilisant les APIs N2 existantes provider capability descriptor sans wire nouveau petite façade OrbitFlare au-dessus de N2 seulement si divergence live prouvée provider-specific tests/compliance README/USAGE dans la tranche documentaire finale ``` ## 15. Forecast recalibré Le chemin effectif de `0.2.10` est désormais figé : ```text pre.001 audit actuel + architecture immuable N1/N2 + auth/endpoints + Free Devnet + heartbeat + sizing pre.002 profil Config V3 OrbitFlare Devnet + smoke de caractérisation sans metadata pre.002-fix.001 auth corrigée : License Key -> secret x-token ; live Subscribe -> Slot + Ping PASS pre.003 gate technique/live final ; workspace + graphes + rerun OrbitFlare PASS pre.004 réconciliation documentaire finale pre.005 publication minimale après décision explicite sur la release suivante rel.001 publication stable stricte ``` La branche de divergence heartbeat n'a pas été déclenchée. Aucun couloir supplémentaire n'est requis. Le numéro n'est jamais le critère de clôture ; l'ordre technique, documentaire puis publication reste obligatoire. ## 16. Critères de split Les critères de split définis pendant l'audit étaient : ```text OrbitFlare n'émet pas le Ping standard et exige un Ping client proactif l’auth x-token fonctionne mais révèle une exigence provider supplémentaire non composable au-dessus de N1/N2 le service requiert un mécanisme TLS/channel absent du moteur stable un method/filter standard est remplacé par une extension wire OrbitFlare le replay/from_slot exige une policy provider visible au consumer un failover provider impose une sémantique que N1 ne peut pas composer sans modification ``` **Aucun de ces critères n'a été déclenché par le gate live final.** Le principe reste durable pour les providers futurs : si une divergence ne peut pas être composée proprement au-dessus de N1/N2, ne pas modifier le moteur pour le provider ; qualifier le blocker et replanifier l'architecture. ## 17. Critères de clôture État à l'entrée de `pre.004` : ```text Devnet OrbitFlare Free atteint par KSP PASS N1 gRPC inchangé PASS N2 Yellowstone inchangé PASS aucun SDK OrbitFlare runtime PASS provider/auth correctement classifiés PASS aucune Customer API key sur le data-plane Yellowstone PASS heartbeat live classifié PASS Config V3 cohérente sans nouveau format PASS smoke provider architecture-safe PASS PublicNode non régressé déterministiquement PASS Yellowstone standard non régressé PASS HTTP 52+14 non régressé PASS WebSocket standard 18/18 non régressé PASS Helius WebSocket non régressé PASS workspace complet vert PASS graphes Cargo inspectés PASS réconciliation documentaire séparée EN COURS pre.004 publication minimale séparée À FAIRE pre.005 ``` Le gate technique est donc fermé. La stabilité `0.2.10` reste conditionnée à la validation documentaire `pre.004`, au couloir publication-minimal `pre.005`, puis à `rel.001`. ## 18. Release suivante La décision préalable à `pre.005` est désormais prise. L'ancien forecast : ```text 0.2.11 — Helius LaserStream gRPC ``` est reporté dans les TODO Yellowstone sans numéro de release. L'audit du 2026-08-25 conclut que la surface Helius reste largement wire-compatible Yellowstone et pourrait probablement se composer au-dessus de N1/N2, mais l'accès gRPC Helius exige actuellement un plan payant que l'opérateur ne retient pas uniquement pour ce test. La release provider est donc différée jusqu'à disponibilité d'un accès live permettant de valider réellement auth, endpoints, Subscribe, Ping, replay/from_slot et erreurs provider. Les extensions Helius non standard restent un sujet séparé. La séquence active avance d'un cran : ```text 0.2.11 — off-chain price transport 0.2.12 — Price Desk + intégration prix Wallet Desk 0.2.13 — interface/wire foundation 0.2.14 — program-api foundation ``` Décision de publication : ```text aucun prompt suivant dans pre.004 aucun changement CHANGELOG/ROADMAP dans pre.004 Helius gRPC -> TODO futur sans numéro 0.2.11 -> off-chain price transport pre.005 préparera seulement le prompt 0.2.11 + CHANGELOG + ROADMAP ``` Quel que soit le provider futur, l'invariant reste le même : N1 gRPC et N2 Yellowstone sont des fondations stables ; les différences provider se composent au-dessus et ne modifient jamais le moteur pour satisfaire un fournisseur.