# Plan `0.2.9` — moteur Yellowstone gRPC + standard Solana + PublicNode **Statut courant : le couloir technique `0.2.9-pre.013` est fermé par `pre.013-fix.004` : gates déterministes et workspace verts, graphes Cargo finaux inspectés, et smoke Yellowstone PublicNode authentifié exécuté avec succès sur Mainnet et Testnet (`2/2 PASS`). `pre.014` est la réconciliation documentaire finale ; seule `pre.015` restera ensuite pour le prompt `0.2.10`, `CHANGELOG.md` et `ROADMAP.md`, avant `rel.001`.** ## 1. Objet et autorité de la release Base stable d'ouverture : ```text v0.2.8 ``` Release : ```text 0.2.9 — Yellowstone gRPC standard/provider-neutral ``` Le gate `pre.001`, ses fixes, les deltas techniques suivants et le code réel ont affiné le prompt de démarrage. L'ordre d'autorité utilisé pendant la release est : ```text règles normatives KSP code et fichiers réellement livrés nouveaux deltas immuables de 0.2.9 décisions courantes consolidées dans ce plan et la validation 012 prompt de démarrage pour les contraintes qui n'ont pas été explicitement supersédées ``` Les deltas historiques ne sont jamais réécrits pour refléter une décision ultérieure. ## 2. Résultat final attendu `0.2.9` doit fermer une première fondation Yellowstone gRPC exploitable sans devenir un SDK fournisseur : ```text backend gRPC distinct de HTTP et WebSocket moteur Tonic/Protobuf privé dans ksp-onchain-transport-lib façade Yellowstone standard provider-neutral 7 unary standard retenus Subscribe standard avec les familles/accounts/slots/transactions/blocks retenues 9 variantes SubscribeUpdate courantes stream bidirectionnel borné backpressure, half-close et shutdown déterministes reconnect KSP-owned et replay/from_slot prudent aucune promesse exactly-once/lossless non prouvée Config Transport V3 backward-readable V1/V2 provider et protocol distincts dans Config première intégration PublicNode strictement standard smoke live opt-in avec credential secret non versionné non-régressions HTTP, WebSocket standard et Helius WebSocket ``` ## 3. Scope fermé par `pre.001` ### 3.1 Inclus ```text N1 — moteur Yellowstone gRPC N2 — standard Solana Yellowstone N3 — première intégration PublicNode quand elle réutilise le standard sans divergence wire TLS et metadata provider-neutral 7 unary standards retenus Subscribe standard retenu reconnect/replay observables mais non lossless Config V3 si le mapping reste Config -> Transport smokes PublicNode architecture-safe ``` ### 3.2 Hors scope `0.2.9` ```text SubscribeDeshred / pré-exécution extensions Triton spécifiques adapter Helius LaserStream gRPC spécifique adapter OrbitFlare spécifique pool/scheduler automatique complexe de sessions gRPC serveur Geyser/plugin validator Store/persistence/backfill historique workers/jobs d'acquisition replay lossless garanti refonte HTTP ou WebSocket ``` Les intégrations provider futures ne dupliquent jamais le moteur N1. Une façade provider n'existe que si elle porte une divergence réelle : auth, capabilities, restriction, extension wire ou policy lifecycle. ## 4. Audit upstream et dépendances retenues ### 4.1 Snapshot normatif et réaudit final Le gate d'ouverture puis le réaudit final du 2026-08-24 confirment que les numéros du plugin, du client, du proto et des releases GitHub évoluent indépendamment. Il ne faut donc pas transformer un numéro de `master` en numéro de release publié. État observé au réaudit final : ```text latest release GitHub indexée v14.2.2+solana.4.1.0 — 2026-07-27 master yellowstone-grpc-geyser 15.1.2 master yellowstone-grpc-client 13.3.0 master yellowstone-grpc-proto 12.6.0 master Agave Geyser / storage 4.2.0 master prost / prost-types / tonic 0.14.x KSP yellowstone-grpc-proto direct ^12.6 ``` Le service `Geyser`, la shape de `SubscribeRequest` et les neuf variantes `SubscribeUpdate` retenues par KSP n'ont pas changé matériellement par rapport au gate `pre.001`. `SubscribeDeshred` reste explicitement hors scope `0.2.9`. Les sources primaires restent : ```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://github.com/rpcpool/yellowstone-grpc/blob/master/yellowstone-grpc-proto/proto/solana-storage.proto https://github.com/rpcpool/yellowstone-grpc/blob/master/LICENSING.md https://docs.rs/crate/yellowstone-grpc-proto/latest https://docs.rs/crate/yellowstone-grpc-client/latest ``` Le réaudit final a été exécuté en `pre.012`; aucun changement upstream matériel n’a remis en cause la surface retenue. ### 4.2 Licence Le repository upstream est globalement `AGPL-3.0-only`, mais `LICENSING.md` affecte explicitement Apache-2.0 à : ```text examples/ yellowstone-grpc-client/ yellowstone-grpc-client-nodejs/ yellowstone-grpc-proto/ ``` Décision : ```text dépendance publiée yellowstone-grpc-proto = acceptée .proto vendored dans KSP = non source provenant des zones AGPL = non copiée future copie upstream = nouveau gate provenance/licence obligatoire ``` ### 4.3 Stratégie client | Stratégie | Décision | Raison principale | |-------------------------------------------------------|--------------------|-----------------------------------------------------------------------| | `yellowstone-grpc-client + yellowstone-grpc-proto` | non retenue | importerait trop de lifecycle/reconnect upstream et de surface client | | `yellowstone-grpc-proto + client KSP autour de tonic` | **retenue** | wire officiel, moteur/lifecycle/redaction KSP-owned | | proto/génération KSP vendored | fallback seulement | dette licence/synchronisation/build plus forte | Matérialisation courante : ```text yellowstone-grpc-proto ^12.6 runtime sans feature tonic yellowstone-grpc-proto dev/test avec feature tonic pour GeyserServer fixture tonic ^0.14 channel + TLS runtime ; codegen/server dev/test tonic-prost ^0.14 ProstCodec bas niveau http ^1.5 PathAndQuery interne yellowstone-grpc-client absent prost/prost-types aucune dépendance KSP directe proto vendored absent ``` Les graphes Cargo inspectés pendant `pre.002/pre.003` n'ont pas révélé de seconde génération incompatible à corriger. Le graph final est réinspecté en `pre.012`. ## 5. Matrice protocolaire fermée ### 5.1 Service `Geyser` | RPC | Forme | Classification | Cible `0.2.9` | État | |-----------------------|-------------|------------------------------------------------------|---------------|----------------------------| | `Subscribe` | bidi stream | standard Yellowstone | oui | **DONE** `pre.009/pre.010` | | `SubscribeDeshred` | bidi stream | extension/pré-exécution Triton publiée dans le proto | non | **OUT** | | `SubscribeReplayInfo` | unary | standard | oui | **DONE** | | `Ping` | unary | standard | oui | **DONE** | | `GetLatestBlockhash` | unary | standard | oui | **DONE** | | `GetBlockHeight` | unary | standard | oui | **DONE** | | `GetSlot` | unary | standard | oui | **DONE** | | `IsBlockhashValid` | unary | standard | oui | **DONE** | | `GetVersion` | unary | standard | oui | **DONE** | `SubscribeDeshred` reste explicitement exclu même s'il existe dans le proto publié : sa présence wire n'en fait pas une capacité provider-neutral de la fondation KSP. ### 5.2 `SubscribeRequest` | Champ | Sémantique | État | |-----------------------|----------------------------------------|-------------------------------| | `accounts` | map nom -> filtre accounts | **DONE** | | `slots` | map nom -> filtre slots | **DONE** | | `transactions` | map nom -> filtre transactions | **DONE** | | `transactions_status` | même famille de filtre transaction | **DONE** | | `blocks` | map nom -> filtre blocks | **DONE** | | `blocks_meta` | map nom -> filtre marqueur vide | **DONE** | | `entry` | map nom -> filtre marqueur vide | **DONE** | | `commitment` | optional Processed/Confirmed/Finalized | **DONE** | | `accounts_data_slice` | repeated offset/length | **DONE** | | `ping` | optional request ping/id | **DONE** | | `from_slot` | optional u64 | **DONE**, sémantique prudente | Accounts : ```text account[] owner[] filters[] nonempty_txn_signature? cuckoo_accounts_filter? memcmp { offset, oneof bytes | base58 | base64 } datasize token_account_state lamports { oneof eq | ne | lt | gt } ``` Slots : ```text filter_by_commitment? interslot_updates? statuses = processed | confirmed | finalized | first_shred_received | completed | created_bank | dead ``` Transactions et `transaction_status` : ```text vote? failed? signature? account_include[] account_exclude[] account_required[] cuckoo_account_include? token_accounts? = ALL | BALANCE_CHANGED ``` Blocks : ```text account_include[] include_transactions? include_accounts? include_entries? cuckoo_account_include? ``` `blocks_meta` et `entry` conservent la distinction absence / map vide / filtre nommé vide. Bornes KSP communes matérialisées : ```text filter groups nommés total <= 1024 filter name 1..128 octets, trim exact, sans contrôle filter names uniques globalement entre les sept maps accounts_data_slice count <= 128 accounts_data_slice length <= 64 MiB offset + length sans overflow u64 ``` Les bounds spécifiques Accounts/Transactions/Blocks sont ceux désormais testés dans leurs tranches respectives ; ils ne sont pas dupliqués comme knobs Config. ### 5.3 `SubscribeUpdate` | Variante | Champs structurants conservés | État | |----------------------|-----------------------------------------------------------------------------|----------| | `account` | account info + slot + `is_startup` | **DONE** | | `slot` | slot + parent? + status + dead_error? | **DONE** | | `transaction` | signature/is_vote/transaction/meta/index + slot | **DONE** | | `transaction_status` | slot/signature/is_vote/index/error | **DONE** | | `block` | slot/hash/rewards/time/height/parent/counts + transactions/accounts/entries | **DONE** | | `ping` | marker server ping | **DONE** | | `pong` | id | **DONE** | | `block_meta` | block metadata/counts sans tableaux complets | **DONE** | | `entry` | slot/index/num_hashes/hash/transaction counts/index | **DONE** | Le top-level conserve également `filters[]` et `created_at`. Les types Prost/Yellowstone générés restent privés. ### 5.4 Unary standards | RPC | Request | Response KSP utile | État | |-----------------------|---------------------------|------------------------------------------|----------| | `SubscribeReplayInfo` | vide | `first_available?` | **DONE** | | `Ping` | `count` | `count` | **DONE** | | `GetLatestBlockhash` | `commitment?` | slot, blockhash, last_valid_block_height | **DONE** | | `GetBlockHeight` | `commitment?` | block_height | **DONE** | | `GetSlot` | `commitment?` | slot | **DONE** | | `IsBlockhashValid` | blockhash + `commitment?` | slot + valid | **DONE** | | `GetVersion` | vide | version bornée | **DONE** | Ces capacités ne remplacent pas les wrappers Solana JSON-RPC HTTP. ## 6. Architecture runtime actuelle ### 6.1 Séparation des backends ```text HTTP HttpTransportSettings / pool HTTP WebSocket engine WsSession actor partagé Solana standard WS SolanaStandardWsSession Helius LaserStream WS HeliusLaserStreamWsSession Yellowstone gRPC engine YellowstoneGrpcChannel + moteur bidi KSP Solana Yellowstone standard contrats typed KSP provider descripteur d'exécution/capability, pas nouveau protocole ``` Interdictions : ```text pas de WsProtocolKind pour gRPC pas de WsEndpointSettings pour gRPC pas de client Tonic brut réexporté pas de second moteur physique par provider pas de façade provider vide qui ne ferait que renommer le standard ``` ### 6.2 Contrats publics principaux matérialisés ```text YellowstoneGrpcEndpointUrl YellowstoneGrpcProviderName YellowstoneGrpcClusterName YellowstoneGrpcMetadataEntry YellowstoneGrpcReconnectSettings YellowstoneGrpcSessionSettings YellowstoneGrpcEndpointSettings YellowstoneGrpcTransportSettings YellowstoneGrpcChannel YellowstoneSubscribeRequest + filtres typed YellowstoneSubscribeUpdate + variantes typed SolanaYellowstoneGrpcSubscribeSession YellowstoneGrpcSubscribeSnapshot 7 unary typed ``` Le wire Tonic/Prost reste privé et n'est pas une escape hatch publique. ### 6.3 Credentials et diagnostics Transport reçoit des valeurs déjà résolues par son consumer. Il ne connaît : ```text aucun KSP_SECRET_* aucun KSP_PUBLIC_* aucun std::env aucun header commercial hardcodé dans le standard ``` Les URLs, metadata sensibles, messages/details de `tonic::Status` et payloads arbitraires ne sont pas recopiés dans `Debug`, `Display`, snapshots ou contexts KSP. ## 7. Lifecycle, backpressure et continuité ### 7.1 Stream bidi Acquis depuis `pre.009` : ```text une request mpsc bornée consommée par Tonic une update queue bornée côté KSP mutation du SubscribeRequest sur le même stream Ping serveur -> réponse automatique appropriée Pong décodé server half-close observable client explicit close borné Drop best-effort sans panic oversized inbound/outbound borné slow receiver overflow terminal et observable shutdown déterministe ``` Aucune queue non bornée et aucun drop silencieux n'est présenté comme lossless. ### 7.2 Reconnect/replay Acquis depuis `pre.010` : ```text reconnect automatique oui, borné et KSP-owned resubscribe dernier SubscribeRequest complet accepté from_slot de reprise max(from_slot explicite, dernier slot observé) quand applicable SubscribeReplayInfo informatif first_available clamp/prouve un gap seulement s'il dépasse le slot demandé exactly-once non garanti lossless non garanti ordre global sans gap non garanti duplicate possible, compté, non supprimé silencieusement gap compté seulement lorsqu'une preuve est disponible shutdown during backoff interrompt la reconnexion budget reconnect épuisé état terminal safe ``` Snapshot public safe : ```text reconnect_count replay_attempt_count continuity_gap_count duplicate_update_count last_requested_from_slot last_observed_slot terminal state/error code safe ``` La présence de `from_slot` ou `SubscribeReplayInfo` n'autorise aucune promesse de replay historique complet. ## 8. Config Transport V3 — tranche `pre.011` ### 8.1 Compatibilité documentaire Décision fermée : ```text V1 = HTTP-only, backward-readable V2 = HTTP + WebSocket, backward-readable V3 = HTTP + WebSocket + Yellowstone gRPC optionnel par profil ``` Le schema V3 conserve des branches strictes V1/V2 au lieu de relâcher leurs `additionalProperties`. Shape V3 : ```text format_version = 3 retry ws_defaults grpc_defaults default_profile profiles[] { profile_id endpoints[] ws_endpoints[] grpc_endpoints[]? # optionnel par profil } ``` L'absence de `grpc_endpoints` dans un profil V3 signifie `None`, pas un `YellowstoneGrpcTransportSettings` vide inventé. ### 8.2 `grpc_defaults` Les defaults Config correspondent uniquement à de vrais settings runtime Transport : ```text connect_timeout_ms unary_timeout_ms close_timeout_ms reconnect.max_retries reconnect.initial_backoff_ms reconnect.max_backoff_ms request_channel_capacity update_channel_capacity max_inbound_message_size_bytes max_outbound_message_size_bytes ``` Les bounds de filtres Subscribe restent un contrat Transport fixe et ne deviennent pas des options Config sans besoin démontré. ### 8.3 Endpoint gRPC Chaque `grpc_endpoints[]` porte : ```text name enabled provider cluster protocol = solana_yellowstone url metadata[]? # classe publique secret_metadata[]? # classe secrète session? # overrides bornés ``` Axes distincts : ```text protocol = contrat wire standard, actuellement solana_yellowstone provider = environnement d'exécution descriptif, par exemple publicnode ``` `provider = publicnode` ne crée donc pas un `PublicNodeGrpcProtocol` ni une façade provider sans divergence réelle. ### 8.4 Provenance des metadata Config est propriétaire de la résolution : ```text metadata -> interdit toute provenance KSP_SECRET_*/KSPB_SECRET_* secret_metadata -> exige au moins une provenance secret et interdit une variable non-secret littéraux autour d'un placeholder secret -> autorisés ; safe_value masque seulement le segment secret ``` Transport reçoit ensuite `YellowstoneGrpcMetadataEntry` public/secret et ne connaît jamais le nom de variable d'environnement. ### 8.5 API Config sans rupture V2 L'API existante reste : ```text http_settings() ws_settings() into_transport_settings() -> (HTTP, Option) ``` `pre.011` ajoute : ```text grpc_settings() into_all_transport_settings() -> (HTTP, Option, Option) ``` Le tuple historique n'est pas modifié silencieusement. ## 9. PublicNode dans `0.2.9` ### 9.1 Mainnet Endpoint retenu et validé en live : ```text https://solana-yellowstone-grpc.publicnode.com:443 ``` Le profil committé est : ```text profile_id = publicnode_mainnet provider = publicnode cluster = mainnet-beta protocol = solana_yellowstone metadata = x-token secret via KSP_SECRET_PUBLICNODE_MAINNET_GRPC_X_TOKEN ``` Les tentatives sans metadata ont atteint le service mais ont reçu `PERMISSION_DENIED`. Le profil final fournit donc le personal token PublicNode comme metadata gRPC secrète `x-token`; Transport ne connaît ni le nom de variable KSP ni sa provenance. ### 9.2 Testnet L'endpoint exact confirmé par l'opérateur et validé en live est : ```text https://solana-testnet-yellowstone-grpc.publicnode.com:443 ``` Le profil committé est : ```text profile_id = publicnode_testnet provider = publicnode cluster = testnet protocol = solana_yellowstone metadata = x-token secret via KSP_SECRET_PUBLICNODE_TESTNET_GRPC_X_TOKEN ``` Le smoke final prouve qu'un même personal token opérateur peut fonctionner sur Mainnet et Testnet. KSP conserve néanmoins deux variables de configuration distinctes afin de ne pas imposer une hypothèse de portée provider à long terme ; elles peuvent recevoir la même valeur. Cette séparation est une liberté de configuration KSP, pas une assertion que PublicNode délivre des tokens network-scoped. ## 10. Threat model et bornes Menaces couvertes : ```text credential dans URI/metadata Status/message/details provider arbitraires Debug dérivé de filtres/payloads TLS/connect error qui réémet l'URI message inbound/outbound hostile stream flood / slow consumer filter explosion / collision de noms unknown enum/oneof server/client half-close reconnect loop node divergent après reconnect duplicate/gap après replay mutation tardive du stream ``` Réponses : ```text wrappers redacted allowlist de contexts KSP validation/bounds avant I/O queues bornées états terminaux observables reconnect budget borné aucune promesse de continuité non prouvée Config sensitivity gate avant construction de metadata secret ``` ## 11. Smoke ownership Ordre de preuve : ```text Transport programmatic -> PublicNode Mainnet Yellowstone + secret x-token fourni au harness Transport programmatic -> PublicNode Testnet Yellowstone + secret x-token fourni au harness Config V3 -> Transport -> PublicNode via secret_metadata, jamais un smoke réseau placé dans Config par facilité ``` Un smoke Transport pur peut vivre dans `ksp-onchain-transport-lib/tests` puisqu'il construit ses settings programmatiquement. Un smoke cross-crates Config -> Transport ne doit pas devenir une responsabilité durable de `ksp-config-lib`. S’il n’existe pas encore de surface d’intégration appropriée, la preuve live reste un smoke Transport programmatique avec secret fourni uniquement au harness opérateur. Aucun secret provider n'est versionné. ## 12. État des tranches et historique compact Les preuves détaillées restent dans les fichiers `deltas/0.2.9/*.md`. Le plan ne duplique plus leurs journaux complets. | Tranche | Objet | État consolidé | |-------------------|----------------------------------------------------------|----------------------| | `pre.001` + fixes | audit upstream, licence, providers, architecture, sizing | **CLOSED** | | `pre.002` + fixes | dépendances, settings/errors, channel minimal | **CLOSED** | | `pre.003` + fix | TLS, metadata, fixture locale, 7 unary | **CLOSED** | | `pre.004` + fix | Subscribe foundation/common | **CLOSED** | | `pre.005` + fix | Accounts + Slots | **CLOSED** | | `pre.006` | namespace privé HTTP explicite | **CLOSED** | | `pre.007` | Transactions + transaction_status | **CLOSED** | | `pre.008` + fix | Blocks + block_meta + entry | **CLOSED** | | `pre.009` + fix | bidi, Ping/Pong, backpressure, half-close, shutdown | **CLOSED** | | `pre.010` + fix | reconnect, from_slot, ReplayInfo, gaps/duplicates | **CLOSED** | | `pre.011` | Config V3 + protocol/provider + PublicNode Mainnet | **CLOSED** | | `pre.012` | réaudit + smoke ajouté + docs préparatoires | **LOCAL GATE PASS** | | `pre.012-fix.001` | règles de séparation de fermeture + recalibrage | **CLOSED** | | `pre.013` + fixes | gate technique/live PublicNode + graphes finaux | **CLOSED** | | `pre.014` | réconciliation documentaire finale | **ACTIVE CANDIDATE** | | `pre.015` | prompt + CHANGELOG + ROADMAP | **PLANNED** | Gate opérateur déterministe de `pre.012` reçu le 2026-08-24 : ```text fmt/audit Rust PASS sans warning Markdown tables PASS, 87 tableaux / 252 fichiers cargo check PASS cargo clippy PASS sans warning Config unit 113/113 Config public API 15/15 Config ownership 5/5 Transport unit 383/383 Transport public API 49/49 Transport completeness 43/43 Transport doctests 4/4 workspace dependencies 3/3 cargo test --workspace PASS PublicNode live smoke NOT RUN, test ignored cargo tree final NOT PROVIDED / NOT RUN in supplied log ``` `pre.012` reste historiquement une tranche mixte créée avant l'adoption de la nouvelle règle. Son fix ne réécrit pas cette histoire : le prompt `0.2.10` déjà présent est désormais considéré comme un brouillon à finaliser seulement en `pre.015`, et les README/USAGE préparés sont réconciliés par la présente `pre.014`. Gate technique final `pre.013-fix.004` reçu le 2026-08-24 : ```text fmt/audit Rust PASS sans warning Markdown tables PASS, 87 tableaux / 258 fichiers cargo check PASS cargo clippy --all-targets PASS sans warning Transport unit 383/383 Transport public API 49/49 Transport completeness 43/43 Transport doctests 4/4 cargo test --workspace PASS cargo graphs finaux inspectés, stack Yellowstone unique tonic/prost 0.14 PublicNode Mainnet Subscribe + slot PASS PublicNode Testnet Subscribe + slot PASS live smoke total 2/2 PASS ``` Les graphes inspectés avant `fix.004` restent valides : ce fix n'a modifié ni dépendance ni feature Cargo. La stack Yellowstone résolue est `yellowstone-grpc-proto 12.6.0`, `tonic/tonic-prost 0.14.6`, `prost/prost-types 0.14.4`, sans `yellowstone-grpc-client` runtime. ## 13. Forecast restant recalibré ### `pre.013` — gate technique/live final — **CLOSED** Le couloir technique a finalement nécessité quatre fixes : découverte de l'auth PublicNode, ajout Testnet, adaptation de la fermeture live, puis conformité Clippy du harness. Le résultat consolidé est : ```text workspace.package.version final du couloir = 0.2.9-pre.13.fix.4 PublicNode Mainnet Subscribe + slot PASS PublicNode Testnet Subscribe + slot PASS secret wire metadata x-token secret versionné non harness deux lignes stdin, valeurs identiques autorisées close provider succès ou timeout KSP borné après slot reçu graphes Cargo inspectés clippy --all-targets PASS sans warning workspace PASS ``` Les essais intermédiaires `PERMISSION_DENIED` sans credential sont conservés dans les deltas `pre.013-fix.001` à `fix.003`; ils ne sont pas réinterprétés comme une régression du moteur standard. ### `pre.014` — réconciliation documentaire finale — **ACTIVE CANDIDATE** Payload : ```text workspace.package.version = 0.2.9-pre.14 plan 016 réconcilié avec le gate technique/live réel validation 012 fermée avec uniquement des preuves exécutées README/USAGE Transport relus et corrigés références durables liées à 0.2.9 réconciliées si nécessaire audit Markdown final des documents touchés aucune modification fonctionnelle/runtime aucune finalisation CHANGELOG/ROADMAP/prompt suivant ``` Si une correction de code ou de smoke apparaît ici, `pre.014` ne l'absorbe pas : une nouvelle tranche technique est ouverte, puis la réconciliation documentaire est rejouée. ### `pre.015` — préparation de publication minimale Payload fonctionnel strict : ```text workspace.package.version = 0.2.9-pre.15 prompt 0.2.10 OrbitFlare finalisé CHANGELOG.md synchronisé pour 0.2.9 ROADMAP.md état global 0.2.9 / suite synchronisé delta pre.015 ``` Aucun README, USAGE, plan, validation, règle, code, test, schema ou config n'est modifié dans cette tranche. Si l'un de ces fichiers nécessite encore une correction, la tranche de publication est décalée après une nouvelle prerelease dédiée. ### `rel.001` — publication stable `rel.001` ne sert qu'à la mécanique de publication stable : version Cargo finale `0.2.9`, delta de release, commit final et tag `v0.2.9` après gate. Aucun rattrapage technique ou documentaire n'y est mélangé. ## 14. Critères de split Scinder avant dette silencieuse si : 1. une évolution upstream matérielle invalide le wire retenu ; 2. PublicNode exige une divergence provider-specific significative ; 3. le replay nécessite un sous-système de fork/equivocation plus large que la foundation ; 4. une tranche dépasse nettement le budget nominal sans frontière claire ; 5. le gate technique/live montre une dette dépendance/licence ou une non-régression qui ne peut pas être corrigée proprement dans son couloir ; 6. une correction appartenant à un couloir déjà franchi est découverte pendant un couloir ultérieur. Le noyau à préserver reste : ```text moteur Yellowstone + façade Solana standard + Config provider-neutral + première intégration PublicNode minimale ``` ## 15. Gates opérateur restants Le gate `pre.013` est fermé. Gate `pre.014` : ```bash python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.2.9 cargo test --workspace ``` Gate `pre.015` : audit documentaire ciblé sur `prompts/`, `CHANGELOG.md` et `ROADMAP.md`, plus les validations minimales imposées par le changement de version Cargo. Aucun smoke n'est rejoué dans cette tranche en l'absence de changement technique. ## 16. Conditions de clôture `0.2.9` ```text service/proto courant réconcilié SubscribeDeshred explicitement OUT 7 unary verts Subscribe standard et 9 updates verts backend gRPC distinct de HTTP/WS raw Tonic/Prost privé secrets/metadata redacted bounds/backpressure/shutdown verts reconnect/replay documentés sans lossless implicite Config V3 backward V1/V2 provider/protocol distincts PublicNode Mainnet live Subscribe + slot PASS PublicNode Testnet live Subscribe + slot PASS auth PublicNode x-token secret documentée sans secret versionné HTTP 52+14 non régressé Standard WS 18/18 non régressé Helius WS non régressé cargo graphs finaux inspectés README/USAGE finaux réconciliés en pre.014 validation 012 fermée en pre.014 prompt/CHANGELOG/ROADMAP seuls finalisés en pre.015 workspace final vert ``` ## 17. Séquence après `0.2.9` La séquence active a été recalibrée par les fixes de `pre.001`; cette décision est conservée pendant le nettoyage documentaire : ```text 0.2.9 moteur Yellowstone + Solana standard + PublicNode 0.2.10 OrbitFlare Yellowstone gRPC 0.2.11 Helius LaserStream gRPC 0.2.12 off-chain price transport 0.2.13 Price Desk + intégration prix Wallet Desk 0.2.14 interface/wire foundation 0.2.15 program-api foundation ``` Les intégrations suivantes restent dans le backlog non numéroté tant qu'aucune décision d'implémentation ne les fait entrer dans la séquence active : ```text TODO eRPC TODO Triton TODO Alchemy TODO QuickNode TODO Chainstack IDEAS Tatum IDEAS Shyft IDEAS Solinfra IDEAS NodeFlare ``` OrbitFlare reste le provider dédié `0.2.10` et Helius LaserStream gRPC `0.2.11` selon la séquence recalibrée par les fixes de `pre.001`. Chaque release doit réauditer auth, capabilities, restrictions, extensions wire, replay/from_slot et lifecycle au lieu de supposer une équivalence complète avec N2.