# Plan `0.2.10` — OrbitFlare Yellowstone gRPC **Statut courant : `0.2.10-pre.001` ouvre la release par un audit provider actuel. Le gate d'architecture est positif avec une contrainte renforcée : le moteur gRPC N1 et le standard Yellowstone N2 livrés par `0.2.9` sont immuables pour cette release. OrbitFlare doit être composé au-dessus de ces couches ; aucune modification du moteur n'est autorisée pour satisfaire une policy provider.** ## 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, 87 tables et 261 files | | `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` | à rejouer avant commit `pre.001` | 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 actuelle Les sources officielles restent hétérogènes, mais leur rôle peut être séparé sans supposition. | Credential ou mécanisme | Plan observé | Classification `pre.001` | |-------------------------|-----------------------------------------|-------------------------------------------------------| | `X-ORBIT-KEY` | Customer API | control-plane, jamais injecté automatiquement en gRPC | | Bearer Customer API | Customer API v2 | control-plane | | `api_key` RPC | Solana HTTP RPC | data-plane HTTP, pas Yellowstone | | API key du compte | login CLI / Customer API | ne prouve pas une auth Yellowstone | | token gRPC Dashboard | certains endpoints/licences gRPC | possible data-plane Yellowstone | | `x-token` Yellowstone | mécanisme standard upstream | utiliser seulement si le service OrbitFlare le prouve | | aucune metadata | SDK Go / endpoints régionaux documentés | premier mode à tester sur Devnet Free | | IP/network entitlement | certains services partagés/dédiés | provider/account dependent | Le quickstart TypeScript OrbitFlare demande un endpoint + token de licence et passe ce token au client Yellowstone. Le client upstream Yellowstone utilise classiquement la metadata `x-token`. Cela rend `x-token` plausible pour cette classe de service, mais **ne transforme pas la clé Customer API du compte en token gRPC**. Décision : ```text ne jamais demander ou versionner la clé opérateur Customer API ne jamais injecter X-ORBIT-KEY dans Yellowstone commencer le smoke Devnet Free sans metadata secrète si le Dashboard fournit un token gRPC distinct, classifier son wire avant Config ``` ## 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` **Aucun heartbeat OrbitFlare supplémentaire n'est retenu à ce stade.** Le premier smoke Devnet doit vérifier que l'endpoint OrbitFlare émet bien le `SubscribeUpdate::Ping` standard. Si ce Ping live est observé, la combinaison suivante suffit : ```text OrbitFlare server Ping live + KSP N1 automatic Ping reply deterministic test = client-side activity périodique sans code provider supplémentaire ``` Il est interdit d'ajouter un timer dans `grpc_stream.rs` ou `YellowstoneGrpcSessionSettings` pour OrbitFlare. Si le live montre qu'OrbitFlare ne produit pas le Ping standard ou exige réellement un heartbeat proactif indépendant, cela ouvre un **gate provider spécifique séparé**. La solution doit alors être composée au-dessus de N1 sans modifier le moteur et sans corrompre la requête de reconnect mémorisée. Point de sécurité important : appeler naïvement la mutation standard avec un request `ping` seul n'est pas acceptable, car le moteur mémorise la dernière mutation complète pour le replay/reconnect. Une éventuelle façade provider doit préserver cette sémantique au lieu de contourner N1. ## 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 ne sont pas déclarées supportées sur OrbitFlare sans preuve supplémentaire : ```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é ``` L'absence de documentation n'est pas une preuve d'absence. Le live provider doit distinguer : ```text standard KSP disponible provider support prouvé provider entitlement éventuel unknown non testé ``` Aucune capacité N2 n'est supprimée du standard global à cause d'une restriction 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 | gate heartbeat 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 sait déjà représenter le besoin minimal : ```text provider = orbitflare cluster = devnet protocol = solana_yellowstone url = http://devnet.rpc.orbitflare.com:10000 metadata = [] secret_metadata = [] ``` Décision : ```text pas de format_version 4 pas de champ region si l'URL suffit pas de heartbeat dans grpc_defaults pas de secret tant que le Devnet Free n'en exige pas ``` Profil prévu : ```text orbitflare_devnet ``` Si le service opérateur réel impose ensuite un token gRPC : ```text secret_metadata = x-token <- ${KSP_SECRET_ORBITFLARE_DEVNET_GRPC_X_TOKEN} ``` Cette variable n'est ajoutée à `.env.example` qu'après preuve qu'un secret data-plane est réellement requis. ## 12. Stratégie live Devnet ### 12.1 Premier canari Le premier canari doit utiliser **le standard N2 existant directement** : ```text endpoint = http://devnet.rpc.orbitflare.com:10000 provider = orbitflare cluster = devnet protocol = solana_yellowstone auth = aucune metadata en première tentative request = Subscribe slots à commitment confirmed preuve = au moins un Slot non nul close = borné ``` ### 12.2 Preuve heartbeat Le smoke de caractérisation doit aussi attendre suffisamment pour observer : ```text SubscribeUpdate::Ping ``` Un `Ping` serveur live, combiné au test déterministe N1 qui prouve la réponse automatique, ferme le besoin heartbeat sans code OrbitFlare. Le smoke final durable peut rester court après cette caractérisation ; il n'a pas besoin de patienter 10 minutes à chaque workspace run. ### 12.3 Unary et replay Après le canari Subscribe : ```text probe 7 unary N2 probe SubscribeReplayInfo probe from_slot si support observable ``` Les probes provider ne doivent pas rendre indisponible le smoke minimal `Subscribe -> Slot` si le plan gratuit restreint certaines unary. ## 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 nominal est plus court que le forecast du prompt. ```text pre.001 audit actuel + architecture immuable N1/N2 + auth/endpoints + free Devnet + heartbeat + sizing preuve : plan 017 + validation 013 + delta + baseline pre.002 profil Config V3 OrbitFlare Devnet + smoke de caractérisation standard N2 preuve : Subscribe -> Slot + observation Ping serveur si disponible + probes provider ciblés aucune modification moteur gRPC pre.003 soit gate technique final si OrbitFlare reste 100 pourcent standard, soit tranche provider-specific minimale uniquement si pre.002 démontre une divergence réelle pre.004 gate technique/live final si pre.003 a porté une divergence ; sinon cette responsabilité est absorbée par pre.003 pre.005 réconciliation documentaire finale après dernier gate technique plan + validation + README + USAGE + références durables pre.006 préparation de publication minimale si une pre.005 documentaire existe à ce numéro prompt 0.2.11 + CHANGELOG + ROADMAP seulement, hors Cargo/delta mécaniques rel.001 publication stable stricte ``` Numérotation effective : ```text chemin standard probable pre.001 -> pre.002 -> pre.003 technique -> pre.004 docs -> pre.005 publication -> rel.001 chemin divergence pre.001 -> pre.002 -> pre.003 provider -> pre.004 technique -> pre.005 docs -> pre.006 publication -> rel.001 ``` Le numéro n'est jamais le critère de clôture ; l'ordre des couloirs finaux reste obligatoire. ## 16. Critères de split Ouvrir une tranche provider dédiée avant le gate final si et seulement si le live démontre l'un de ces cas : ```text OrbitFlare n'émet pas le Ping standard et exige un Ping client proactif le token gRPC ne peut pas être représenté par secret_metadata V3 existant 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 ``` Dans le dernier cas, ne pas modifier N1 dans `0.2.10` : qualifier le blocker et replanifier l'architecture. ## 17. Critères de clôture `0.2.10` est stable seulement si : ```text Devnet OrbitFlare Free réellement atteint par KSP ou bloc externe qualifié N1 gRPC inchangé N2 Yellowstone inchangé aucun SDK OrbitFlare runtime provider/auth correctement classifiés aucune Customer API key sur le data-plane Yellowstone heartbeat live classifié Config V3 cohérente sans nouveau format inutile smoke provider architecture-safe PublicNode non régressé Yellowstone standard non régressé HTTP 52+14 non régressé WebSocket standard 18/18 non régressé Helius WebSocket non régressé workspace complet vert graphes Cargo inspectés réconciliation documentaire séparée publication minimale séparée ``` ## 18. Release suivante La release suivante reste : ```text 0.2.11 — Helius LaserStream gRPC ``` Elle doit appliquer le même invariant : le moteur gRPC `0.2.9` est une fondation stable ; Helius ne peut ajouter que des fonctionnalités provider au-dessus.