diff --git a/Cargo.toml b/Cargo.toml index 1fedcbb..57dd2b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ # file: Cargo.toml -# version: 236 +# version: 237 [workspace] resolver = "3" members = ["crates/ksp-app-config-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-logging-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-wallet-lib"] [workspace.package] -version = "0.2.8" +version = "0.2.9-pre.1" edition = "2024" license = "MIT" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" diff --git a/deltas/0.2.9/pre.001.md b/deltas/0.2.9/pre.001.md new file mode 100644 index 0000000..1571883 --- /dev/null +++ b/deltas/0.2.9/pre.001.md @@ -0,0 +1,377 @@ + + + +# Delta `0.2.9-pre.001` — audit/sizing Yellowstone gRPC standard + +## 1. Base requise et vérifiée + +Archive autoritaire fournie : + +```text +khadhroony-solana-project-v0.2.8-full-from-gitea.zip +``` + +État vérifié : + +```text +workspace.package.version = 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 +``` + +Cette livraison ouvre : + +```text +workspace.package.version = 0.2.9-pre.1 +commit attendu = v0.2.9-pre.001 +aucun tag prerelease +``` + +## 2. Objet + +`pre.001` exécute le gate obligatoire : + +```text +lecture base/règles/architecture +baseline stable +réaudit Yellowstone actuel +matrice service/proto +licences/dependencies/MSRV +architecture provider-neutral +threat model/resources/backpressure/replay +sizing et forecast +récensement des providers gRPC gratuits durables +``` + +Aucune implémentation gRPC lourde n'est ajoutée. + +## 3. Baseline opérateur acquise + +Preuve fournie 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 +``` + +Transport pendant le workspace test : + +```text +335 unit +41 public_api +34 release_completeness +4 doctests +``` + +Les live smokes restent opt-in/ignored par défaut. + +## 4. Réaudit Yellowstone du 2026-08-23 + +Divergence importante par rapport au snapshot du start prompt : + +```text +prompt snapshot release = v14.2.2+solana.4.1.0 +release GitHub courante = v15.1.2+solana.4.2.0, publiée 2026-08-18, Rust 1.96.1 +client crate courant = yellowstone-grpc-client 13.3.0 +proto crate courant = yellowstone-grpc-proto 12.6.0 +``` + +Service Geyser courant inventorié : + +```text +Subscribe IN +SubscribeDeshred OUT — Triton extension / pre-execution +SubscribeReplayInfo IN +Ping IN +GetLatestBlockhash IN +GetBlockHeight IN +GetSlot IN +IsBlockhashValid IN +GetVersion IN +``` + +`SubscribeRequest` standard retenu : + +```text +accounts +slots +transactions +transactions_status +blocks +blocks_meta +entry +commitment +accounts_data_slice +ping +from_slot +``` + +Capacités nouvelles/actuelles retenues car présentes dans le proto publié standard : + +```text +CuckooFilter account/block/transaction include +TokenAccountExpansionControlFlag ALL/BALANCE_CHANGED +lamports eq/ne/lt/gt +slot interslot updates +``` + +`SubscribeUpdate` : + +```text +account +slot +transaction +transaction_status +block +ping +pong +block_meta +entry +``` + +## 5. Licence et dépendances + +Upstream : + +```text +repository default = AGPL-3.0-only +client subtree = Apache-2.0 +proto subtree = Apache-2.0 +``` + +Stratégies comparées : + +```text +A client upstream + proto -> rejetée comme default +B proto publié + client KSP autour de Tonic -> RETENUE +C proto vendored KSP -> fallback seulement +``` + +Raisons de B : + +```text +pas de copie proto +wire officiel disponible +licence Apache compatible MIT +reconnect/backpressure/redaction KSP-owned +upstream raw types cachés +stack tonic 0.14 cohérente avec HTTP/2 moderne existant +``` + +Aucune dependency n'est ajoutée dans `pre.001`. `pre.002` doit matérialiser les features minimales et produire les graphes Cargo. + +## 6. Replay/continuity + +L'upstream a corrigé en juillet 2026 un cas où `from_slot` pour blocks pouvait être accepté puis reprendre live avec un **state gap** ; l'autoreconnect upstream a aussi été renforcé pour traiter l'equivocation entre nodes. + +KSP ferme donc : + +```text +reconnect/resubscribe = oui, borné et KSP-owned +from_slot = oui +ReplayInfo = oui +exactly-once = non garanti +lossless = non garanti +gaps/duplicates = observables +node divergence = couverture explicite seulement si prouvée +``` + +## 7. Config / architecture + +Décisions : + +```text +backend gRPC distinct de HTTP/WS +pas de WsProtocolKind gRPC +pas de raw Tonic client public +Transport owns Yellowstone +Config -> Transport seulement +metadata publique et metadata sensible séparées +Transport ne lit aucun env +``` + +Le schéma V2 actuel étant fermé, l'ajout gRPC cible : + +```text +format_version = 3 +globals.grpc_defaults +profiles[].grpc_endpoints[] +metadata[] +secret_metadata[] +``` + +V1 et V2 restent backward-readable. + +## 8. Providers gRPC gratuits durables + +### PublicNode / Allnodes-backed — priorité 1 + +Confirmé officiellement : + +```text +Solana Mainnet Yellowstone GRPC +Solana Testnet GRPC +Mainnet endpoint = solana-yellowstone-grpc.publicnode.com:443 +service annoncé free/public +``` + +Décision : **dans `0.2.9`**, mais pas sous forme d'adapter public spécifique. PublicNode sert de premier smoke live standard provider-neutral. + +Le hostname Testnet exact n'est pas figé avant vérification officielle/live. + +### OrbitFlare — priorité 2 + +Plan Free officiel : + +```text +$0/mo +10 RPS +1 TPS +gRPC Devnet only +Unlimited credit limits +``` + +Décision : **dans `0.2.9` comme second smoke live**, via generic secret metadata Config -> Transport. Aucun type `OrbitFlareGrpc*` public. + +### Tatum — tertiaire + +```text +Mainnet Yellowstone gRPC +Free plan durable +3 RPS +100K lifetime credits +5 subscriptions +``` + +Décision : opérateur optionnel, pas gate durable principal à cause du quota lifetime. + +### Vérifiés non gratuits / non applicables + +```text +Helius Free sans gRPC +Shyft Free = No gRPC Access +Alchemy PAYG/Enterprise requis +QuickNode Scale/Business ou add-on payant +Chainstack add-on Yellowstone payant, Growth+ +ERPC Geyser payant ; trial seulement 1 jour +NodeFlare plan Yellowstone mensuel payant +Bitquery CoreCast custom, pas Yellowstone standard ; stream free non garanti +``` + +Candidat à revalider : + +```text +Solinfra = free tier + Yellowstone annoncés publiquement, mais accès gRPC inclus dans Free non confirmé +``` + +## 9. Threat model + +Le plan ferme explicitement : + +```text +metadata/URI credential leak +Tonic Status arbitraire +oversized messages +stream flood/backpressure +filter explosion / collisions de noms +unknown enum/oneof +server/client half-close +reconnect loop +node divergence +late updates après mutation +from_slot gaps/duplicates +TLS failures +unary timeout +``` + +## 10. Forecast recalibré + +```text +pre.001 DONE audit/sizing/provider/deps/license +pre.002 deps + settings/errors/facade + cargo tree +pre.003 TLS/metadata + local fixture + 7 unary +pre.004 Subscribe common + Cuckoo/token/from_slot/bounds +pre.005 Accounts + Slots +pre.006 Transactions + transaction_status +pre.007 Blocks + block_meta + entry +pre.008 bidi lifecycle/backpressure/half-close/shutdown +pre.009 reconnect/replay/gaps/duplicates/equivocation +pre.010 Config V3 +pre.011 PublicNode/OrbitFlare live + compliance + final cargo graphs +pre.012 docs/workspace final + prompt 0.2.10 +rel.001 stable +``` + +Chaque tranche vise ~15–20 minutes ; `pre.012` n'est pas une deadline. + +Critères de split : conflit MSRV/stack réseau, explosion DTO transaction/block, nouvelle évolution proto matérielle, replay trop large, ou comportement provider-specific contaminant le contrat standard. + +## 11. Fichiers ajoutés + +```text +docs/plans/016-V0_2_9_YELLOWSTONE_GRPC_PLAN.md +docs/validation/012-V0_2_9_YELLOWSTONE_GRPC.md +deltas/0.2.9/pre.001.md +``` + +## 12. Fichiers modifiés + +```text +Cargo.toml +docs/000-README.md +docs/plans/000-README.md +docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md +docs/validation/000-README.md +``` + +## 13. Fichiers volontairement inchangés + +```text +ROADMAP.md +CHANGELOG.md +.env.example +config/** +crates/** +docs/architecture/** +crates/ksp-onchain-transport-lib/README.md +crates/ksp-onchain-transport-lib/USAGE.md +``` + +Aucun gRPC runtime/config/dependency n'est introduit avant le gate positif de cette tranche. + +## 14. Validations du sandbox de préparation + +Le sandbox a pu exécuter : + +```text +inspection archive/version/rel/prompt OK +comparaison prompt fourni / prompt archive OK +lecture règles/architecture/plans/code/config OK +réaudit upstream Yellowstone/provider/dependencies OK +python3 scripts/audit_rust_workspace_rules.py OK / clean après overlay +``` + +Le sandbox ne dispose pas de Cargo ; aucun nouveau `cargo check/clippy/test/tree` n'est déclaré réussi localement après le changement de version/documentation. + +## 15. Validation opérateur attendue avant commit + +Comme `pre.001` ne modifie aucun Rust/dependency/config runtime, exécuter au minimum : + +```bash +cargo fmt --all +python3 scripts/audit_rust_workspace_rules.py +cargo check --workspace +cargo clippy --workspace --all-targets +cargo test --workspace +cargo tree -p ksp-onchain-transport-lib +cargo tree -p ksp-onchain-transport-lib --duplicates +``` + +Attendu : aucune nouvelle dependency gRPC avant `pre.002`. diff --git a/docs/000-README.md b/docs/000-README.md index 285975e..21231f5 100644 --- a/docs/000-README.md +++ b/docs/000-README.md @@ -1,5 +1,5 @@ - + # Documentation KSP @@ -51,7 +51,8 @@ docs/ │ ├── 012-V0_2_5_WALLET_FOUNDATION_PLAN.md │ ├── 013-V0_2_6_WALLET_DESK_PLAN.md │ ├── 014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md -│ └── 015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md +│ ├── 015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md +│ └── 016-V0_2_9_YELLOWSTONE_GRPC_PLAN.md ├── validation/ │ ├── 000-README.md │ ├── 001-V0_1_4_CONFIG_DESKTOP.md @@ -64,7 +65,8 @@ docs/ │ ├── 008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md │ ├── 009-V0_2_6_WALLET_DESK_COMPLIANCE.md │ ├── 010-V0_2_7_ONCHAIN_WEBSOCKET.md -│ └── 011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md +│ ├── 011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md +│ └── 012-V0_2_9_YELLOWSTONE_GRPC.md └── rules/ ├── FILE_CONTRACTS.md ├── PROMPT_STRUCTURE.md @@ -81,7 +83,7 @@ D'autres sous-répertoires seront ajoutés uniquement lorsque leur rôle aura é ## Documents de planification -Le plan historique de la phase fondatrice clôturée est conservé dans [`plans/001-V0_0_3_PLAN.md`](plans/001-V0_0_3_PLAN.md). La séquence active des premières releases fonctionnelles est définie dans [`plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md`](plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md). Le plan détaillé de la release stable `0.1.1` est conservé comme historique clôturé dans [`plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md`](plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.2` est conservé comme historique clôturé dans [`plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md`](plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.3 — Configuration foundation` est conservé comme historique clôturé dans [`plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md`](plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.4 — ksp-app-config-desk` est conservé comme historique clôturé dans [`plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md`](plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md), avec sa matrice finale [`validation/001-V0_1_4_CONFIG_DESKTOP.md`](validation/001-V0_1_4_CONFIG_DESKTOP.md). Son prompt d'ouverture historique reste [`../prompts/004-V0_1_4_START_PROMPT.md`](../prompts/004-V0_1_4_START_PROMPT.md). La release stable `0.2.0` clôt l'audit de bot3 et le découpage de la série. Son plan directeur est conservé comme historique clôturé dans [`plans/007-V0_2_0_SERIES_PLANNING.md`](plans/007-V0_2_0_SERIES_PLANNING.md), avec sa matrice finale [`validation/002-V0_2_0_SERIES_PLANNING.md`](validation/002-V0_2_0_SERIES_PLANNING.md). La release stable `0.2.1 — HTTP Solana foundation` a été ouverte par [`../prompts/006-V0_2_1_START_PROMPT.md`](../prompts/006-V0_2_1_START_PROMPT.md). Son gate de sizing et sa matrice exhaustive sont conservés dans [`plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md`](plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md), avec la validation finale [`validation/003-V0_2_1_ONCHAIN_HTTP.md`](validation/003-V0_2_1_ONCHAIN_HTTP.md), README/USAGE Transport et le smoke Devnet opt-in de composition Config -> Transport. Le prompt [`../prompts/007-V0_2_2_START_PROMPT.md`](../prompts/007-V0_2_2_START_PROMPT.md) a ouvert la release stable `0.2.2 — HTTP Accounts + Tokens + Cluster`. Son plan clôturé [`plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md`](plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md) conserve l'audit et l'implémentation des 22 wrappers typés, tandis que [`validation/004-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER.md`](validation/004-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER.md) enregistre les validations déterministes, les graphes Cargo et les deux smokes Devnet passés avant publication. Le prompt [`../prompts/008-V0_2_3_START_PROMPT.md`](../prompts/008-V0_2_3_START_PROMPT.md) a ouvert la release stable `0.2.3 — HTTP Transactions`. Son plan clôturé [`plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md`](plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md) conserve l'audit et l'implémentation des 11 wrappers ; le réaudit [`validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md`](validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md) confirme la complétude des 37 wrappers HTTP typés et [`validation/006-V0_2_3_HTTP_TRANSACTIONS.md`](validation/006-V0_2_3_HTTP_TRANSACTIONS.md) enregistre les validations finales, graphes Cargo et deux smokes Devnet passés avant publication. Le prompt [`../prompts/009-V0_2_4_START_PROMPT.md`](../prompts/009-V0_2_4_START_PROMPT.md) a ouvert la release stable `0.2.4 — HTTP Blocks + Economics + compliance HTTP finale`. Son plan clôturé [`plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md`](plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md) conserve l’implémentation des 15 wrappers et la compliance `52/52 + 14/14`; la matrice finale [`validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md`](validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md) enregistre le réaudit SIMD/inventaire, les canaries globales et les preuves opérateur avant publication. Le prompt [`../prompts/010-V0_2_5_START_PROMPT.md`](../prompts/010-V0_2_5_START_PROMPT.md), finalisé par `0.2.4-pre.009-fix.001`, ouvre `0.2.5 — Wallet foundation` sur la base stable `v0.2.4`. Son plan historique clôturé [`plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md`](plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md) part du gate `pre.001` (héritage, threat model offline, VIEW/OWNER indépendants et niveau B read-only), puis matérialise la crate en `pre.002`, le wire/transcript en `pre.003`, les primitives Argon2id/XChaCha20-Poly1305 en `pre.004`, les payloads/create/open en `pre.005`, la persistence en `pre.006`, l'administration/signature en `pre.007` et les adapters transfer en `pre.008`. `pre.009` ferme l'audit adversarial/interoperability/compliance dans [`validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md`](validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md) avant la documentation finale `pre.010` ; `pre.010` finalise [`../crates/ksp-wallet-lib/README.md`](../crates/ksp-wallet-lib/README.md), [`../crates/ksp-wallet-lib/USAGE.md`](../crates/ksp-wallet-lib/USAGE.md), la spec, les graphes et la matrice ; `pre.010-fix.001`–`fix.003` ferment ensuite la mise à niveau Dalek et la normalisation Rust/audit structurel. `0.2.5-rel.001` publie la release stable et [`../prompts/011-V0_2_6_START_PROMPT.md`](../prompts/011-V0_2_6_START_PROMPT.md) ouvre `0.2.6 — Wallet Desk`. Le gate `0.2.6-pre.001` est conservé dans [`plans/013-V0_2_6_WALLET_DESK_PLAN.md`](plans/013-V0_2_6_WALLET_DESK_PLAN.md) : il réaudite Config Desk et les APIs finales, retient le gabarit desktop, fixe `std.wallet`, la composition Config/Wallet/HTTP/Logging, les secrets `KSP_SECRET_WALLET_PASS_*`, les frontières VIEW/OWNER et la trajectoire de validation. `pre.002`–`pre.014` matérialisent ensuite le shell Tauri, Config Wallet/composite, inventory, create/open, balance HTTP, import/export, metadata, rotations, révocation VIEW forte, compliance et polish desktop. `pre.015` fige le wire binaire `.kspwallet` V2, `pre.016` matérialise les APIs génériques/versionnées et le runtime V2, puis `pre.017` ajoute la migration explicite OWNER-authentifiée V1 -> V2. `pre.018` ferme le runtime Tauri packagé Config/resources et la documentation candidate ; `pre.018-fix.001` corrige le canari d'ownership Config, après quoi le gate workspace et le build final Linux sont verts. `pre.018-fix.002` renforce uniquement le contrat de reprise `0.2.7`. `0.2.6-rel.001` publie cette surface stable et [`../prompts/012-V0_2_7_START_PROMPT.md`](../prompts/012-V0_2_7_START_PROMPT.md) devient le prochain point d'entrée. Le gate `0.2.7-pre.001` ouvre la release WebSocket standard dans [`plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md`](plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md) ; la matrice normative puis finale est conservée dans [`validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md`](validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md). `0.2.7-pre.014` ferme la candidate technique/documentaire après validation 18/18, smoke WebSocket Devnet et audit du graphe Cargo ; `pre.014-fix.001` renforce uniquement le prompt suivant. `0.2.7-rel.001` publie `0.2.7 — WebSocket Solana standard` stable et [`../prompts/013-V0_2_8_START_PROMPT.md`](../prompts/013-V0_2_8_START_PROMPT.md) ouvre `0.2.8 — Helius LaserStream WebSocket`. Le plan historique clôturé [`plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md`](plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md) et la matrice finale [`validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md`](validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md) conservent la release stable `0.2.8 — Helius LaserStream WebSocket` publiée par `rel.001` : protocol `helius_laserstream`, sept familles standard Helius (`account/logs/program/root/signature/slot/slotsUpdates`), extension `transactionSubscribe`/`transactionUnsubscribe`, `block/vote` absents, heartbeat Ping 60 s, Config/secrets redacted, lifecycle adversarial et graphes Cargo finaux validés. [`../prompts/014-V0_2_9_START_PROMPT.md`](../prompts/014-V0_2_9_START_PROMPT.md) devient le contrat actif pour ouvrir Yellowstone gRPC standard/provider-neutral depuis le tag stable `v0.2.8`. +Le plan historique de la phase fondatrice clôturée est conservé dans [`plans/001-V0_0_3_PLAN.md`](plans/001-V0_0_3_PLAN.md). La séquence active des premières releases fonctionnelles est définie dans [`plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md`](plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md). Le plan détaillé de la release stable `0.1.1` est conservé comme historique clôturé dans [`plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md`](plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.2` est conservé comme historique clôturé dans [`plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md`](plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.3 — Configuration foundation` est conservé comme historique clôturé dans [`plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md`](plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.4 — ksp-app-config-desk` est conservé comme historique clôturé dans [`plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md`](plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md), avec sa matrice finale [`validation/001-V0_1_4_CONFIG_DESKTOP.md`](validation/001-V0_1_4_CONFIG_DESKTOP.md). Son prompt d'ouverture historique reste [`../prompts/004-V0_1_4_START_PROMPT.md`](../prompts/004-V0_1_4_START_PROMPT.md). La release stable `0.2.0` clôt l'audit de bot3 et le découpage de la série. Son plan directeur est conservé comme historique clôturé dans [`plans/007-V0_2_0_SERIES_PLANNING.md`](plans/007-V0_2_0_SERIES_PLANNING.md), avec sa matrice finale [`validation/002-V0_2_0_SERIES_PLANNING.md`](validation/002-V0_2_0_SERIES_PLANNING.md). La release stable `0.2.1 — HTTP Solana foundation` a été ouverte par [`../prompts/006-V0_2_1_START_PROMPT.md`](../prompts/006-V0_2_1_START_PROMPT.md). Son gate de sizing et sa matrice exhaustive sont conservés dans [`plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md`](plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md), avec la validation finale [`validation/003-V0_2_1_ONCHAIN_HTTP.md`](validation/003-V0_2_1_ONCHAIN_HTTP.md), README/USAGE Transport et le smoke Devnet opt-in de composition Config -> Transport. Le prompt [`../prompts/007-V0_2_2_START_PROMPT.md`](../prompts/007-V0_2_2_START_PROMPT.md) a ouvert la release stable `0.2.2 — HTTP Accounts + Tokens + Cluster`. Son plan clôturé [`plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md`](plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md) conserve l'audit et l'implémentation des 22 wrappers typés, tandis que [`validation/004-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER.md`](validation/004-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER.md) enregistre les validations déterministes, les graphes Cargo et les deux smokes Devnet passés avant publication. Le prompt [`../prompts/008-V0_2_3_START_PROMPT.md`](../prompts/008-V0_2_3_START_PROMPT.md) a ouvert la release stable `0.2.3 — HTTP Transactions`. Son plan clôturé [`plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md`](plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md) conserve l'audit et l'implémentation des 11 wrappers ; le réaudit [`validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md`](validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md) confirme la complétude des 37 wrappers HTTP typés et [`validation/006-V0_2_3_HTTP_TRANSACTIONS.md`](validation/006-V0_2_3_HTTP_TRANSACTIONS.md) enregistre les validations finales, graphes Cargo et deux smokes Devnet passés avant publication. Le prompt [`../prompts/009-V0_2_4_START_PROMPT.md`](../prompts/009-V0_2_4_START_PROMPT.md) a ouvert la release stable `0.2.4 — HTTP Blocks + Economics + compliance HTTP finale`. Son plan clôturé [`plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md`](plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md) conserve l’implémentation des 15 wrappers et la compliance `52/52 + 14/14`; la matrice finale [`validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md`](validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md) enregistre le réaudit SIMD/inventaire, les canaries globales et les preuves opérateur avant publication. Le prompt [`../prompts/010-V0_2_5_START_PROMPT.md`](../prompts/010-V0_2_5_START_PROMPT.md), finalisé par `0.2.4-pre.009-fix.001`, ouvre `0.2.5 — Wallet foundation` sur la base stable `v0.2.4`. Son plan historique clôturé [`plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md`](plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md) part du gate `pre.001` (héritage, threat model offline, VIEW/OWNER indépendants et niveau B read-only), puis matérialise la crate en `pre.002`, le wire/transcript en `pre.003`, les primitives Argon2id/XChaCha20-Poly1305 en `pre.004`, les payloads/create/open en `pre.005`, la persistence en `pre.006`, l'administration/signature en `pre.007` et les adapters transfer en `pre.008`. `pre.009` ferme l'audit adversarial/interoperability/compliance dans [`validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md`](validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md) avant la documentation finale `pre.010` ; `pre.010` finalise [`../crates/ksp-wallet-lib/README.md`](../crates/ksp-wallet-lib/README.md), [`../crates/ksp-wallet-lib/USAGE.md`](../crates/ksp-wallet-lib/USAGE.md), la spec, les graphes et la matrice ; `pre.010-fix.001`–`fix.003` ferment ensuite la mise à niveau Dalek et la normalisation Rust/audit structurel. `0.2.5-rel.001` publie la release stable et [`../prompts/011-V0_2_6_START_PROMPT.md`](../prompts/011-V0_2_6_START_PROMPT.md) ouvre `0.2.6 — Wallet Desk`. Le gate `0.2.6-pre.001` est conservé dans [`plans/013-V0_2_6_WALLET_DESK_PLAN.md`](plans/013-V0_2_6_WALLET_DESK_PLAN.md) : il réaudite Config Desk et les APIs finales, retient le gabarit desktop, fixe `std.wallet`, la composition Config/Wallet/HTTP/Logging, les secrets `KSP_SECRET_WALLET_PASS_*`, les frontières VIEW/OWNER et la trajectoire de validation. `pre.002`–`pre.014` matérialisent ensuite le shell Tauri, Config Wallet/composite, inventory, create/open, balance HTTP, import/export, metadata, rotations, révocation VIEW forte, compliance et polish desktop. `pre.015` fige le wire binaire `.kspwallet` V2, `pre.016` matérialise les APIs génériques/versionnées et le runtime V2, puis `pre.017` ajoute la migration explicite OWNER-authentifiée V1 -> V2. `pre.018` ferme le runtime Tauri packagé Config/resources et la documentation candidate ; `pre.018-fix.001` corrige le canari d'ownership Config, après quoi le gate workspace et le build final Linux sont verts. `pre.018-fix.002` renforce uniquement le contrat de reprise `0.2.7`. `0.2.6-rel.001` publie cette surface stable et [`../prompts/012-V0_2_7_START_PROMPT.md`](../prompts/012-V0_2_7_START_PROMPT.md) devient le prochain point d'entrée. Le gate `0.2.7-pre.001` ouvre la release WebSocket standard dans [`plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md`](plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md) ; la matrice normative puis finale est conservée dans [`validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md`](validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md). `0.2.7-pre.014` ferme la candidate technique/documentaire après validation 18/18, smoke WebSocket Devnet et audit du graphe Cargo ; `pre.014-fix.001` renforce uniquement le prompt suivant. `0.2.7-rel.001` publie `0.2.7 — WebSocket Solana standard` stable et [`../prompts/013-V0_2_8_START_PROMPT.md`](../prompts/013-V0_2_8_START_PROMPT.md) ouvre `0.2.8 — Helius LaserStream WebSocket`. Le plan historique clôturé [`plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md`](plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md) et la matrice finale [`validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md`](validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md) conservent la release stable `0.2.8 — Helius LaserStream WebSocket` publiée par `rel.001` : protocol `helius_laserstream`, sept familles standard Helius (`account/logs/program/root/signature/slot/slotsUpdates`), extension `transactionSubscribe`/`transactionUnsubscribe`, `block/vote` absents, heartbeat Ping 60 s, Config/secrets redacted, lifecycle adversarial et graphes Cargo finaux validés. [`../prompts/014-V0_2_9_START_PROMPT.md`](../prompts/014-V0_2_9_START_PROMPT.md) devient le contrat actif pour ouvrir Yellowstone gRPC standard/provider-neutral depuis le tag stable `v0.2.8`. Le gate `0.2.9-pre.001` matérialise désormais [`plans/016-V0_2_9_YELLOWSTONE_GRPC_PLAN.md`](plans/016-V0_2_9_YELLOWSTONE_GRPC_PLAN.md) et [`validation/012-V0_2_9_YELLOWSTONE_GRPC.md`](validation/012-V0_2_9_YELLOWSTONE_GRPC.md) : stratégie proto Apache + client KSP/Tonic, surface standard bornée, Config V3 et smokes gratuits PublicNode puis OrbitFlare. ## Spécifications de formats diff --git a/docs/plans/000-README.md b/docs/plans/000-README.md index 44a6b25..acb7319 100644 --- a/docs/plans/000-README.md +++ b/docs/plans/000-README.md @@ -1,5 +1,5 @@ - + # Plans KSP @@ -24,6 +24,7 @@ Un plan décrit le périmètre, les décisions déjà acquises, les questions ou - [`013-V0_2_6_WALLET_DESK_PLAN.md`](013-V0_2_6_WALLET_DESK_PLAN.md) — plan historique clôturé de la release stable `0.2.6 — Wallet Desk`, ouvert par `pre.001`, étendu en `pre.015`–`pre.017` au wire binaire `.kspwallet` V2, aux APIs multi-version et à la migration V1 -> V2, puis fermé par `pre.018`/`fix.001` avec le runtime Tauri packagé et le build final vert avant publication `rel.001`. - [`014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md`](014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md) — plan historique clôturé de la release stable `0.2.7 — WebSocket Solana standard`, ouvert par `pre.001`, exécuté jusqu’à `pre.014`, corrigé documentairement par `pre.014-fix.001` puis publié par `rel.001`; il conserve l’inventaire officiel 18 méthodes, le modèle session/subscription, le threat model, les preuves de compliance/smoke/dépendances et la préparation de `0.2.8`. - [`015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md`](015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md) — plan historique clôturé de la release stable `0.2.8 — Helius LaserStream WebSocket`, ouvert par `pre.001`, fermé techniquement/documentairement par `pre.011` puis publié par `rel.001`; il conserve la surface finale Helius `7 standard + transaction`, heartbeat/Config/secrets, l’historique des fixes heartbeat, la stratégie live architecture-safe, les graphes Cargo finaux et la préparation du prompt `0.2.9`. +- [`016-V0_2_9_YELLOWSTONE_GRPC_PLAN.md`](016-V0_2_9_YELLOWSTONE_GRPC_PLAN.md) — plan actif de `0.2.9 — Yellowstone gRPC standard/provider-neutral`, ouvert par `pre.001`; il fixe la stratégie `yellowstone-grpc-proto + Tonic KSP`, la surface `Subscribe + 7 unary`, l’exclusion de `SubscribeDeshred`, Config V3, les règles replay/backpressure et les smokes gratuits PublicNode puis OrbitFlare. Le `pre.001` de chaque release fonctionnelle peut introduire son propre plan détaillé lorsque la release s'ouvre. diff --git a/docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md b/docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md index 9129d24..cbd3f07 100644 --- a/docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md +++ b/docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md @@ -1,5 +1,5 @@ - + # Séquence des releases fonctionnelles KSP @@ -473,11 +473,13 @@ Le réaudit final Helius du 23 août 2026 retient `helius_laserstream` comme pro ### `0.2.9` — Yellowstone gRPC standard -Mission : introduire un backend Yellowstone standard/provider-neutral. +Mission active : introduire un backend Yellowstone standard/provider-neutral dans `ksp-onchain-transport-lib`, distinct de HTTP et WebSocket. Le gate `pre.001` est conservé dans [`016-V0_2_9_YELLOWSTONE_GRPC_PLAN.md`](016-V0_2_9_YELLOWSTONE_GRPC_PLAN.md) et sa matrice dans [`../validation/012-V0_2_9_YELLOWSTONE_GRPC.md`](../validation/012-V0_2_9_YELLOWSTONE_GRPC.md). -Le `pre.001` est un gate de sizing : inventorier toute la surface normative cible et scinder la release avant implémentation si sa clôture dans une session paraît incertaine. +Le réaudit du 23 août 2026 corrige le snapshot du prompt : la release GitHub courante observée est `v15.1.2+solana.4.2.0`, tandis que les crates publiées restent `yellowstone-grpc-client 13.3.0` et `yellowstone-grpc-proto 12.6.0`. `0.2.9` retient la stratégie `yellowstone-grpc-proto` Apache-2.0 + client/lifecycle KSP autour de Tonic, et couvre `Subscribe`, les sept RPC unary standard retenus, les filtres Cuckoo/token actuels et les neuf variantes `SubscribeUpdate`. `SubscribeDeshred` reste hors scope comme extension Triton/pré-exécution. -Les profiles/adapters Helius/Triton/ERPC/Chainstack/Shyft sont reportés après les priorités fondatrices. +La Config cible une V3 séparant `grpc_endpoints` de HTTP/WS tout en conservant V1/V2 backward-readable. PublicNode/Allnodes-backed entre dans la release comme premier environnement live standard gratuit Mainnet/Testnet ; OrbitFlare suit comme smoke Devnet gratuit authentifié. Aucun adapter public provider-specific n'est créé pour eux. Tatum reste un fallback opérateur Mainnet à quota lifetime ; les offres gRPC payantes Helius/Shyft/Alchemy/NodeFlare ne deviennent pas des dépendances de validation. + +Forecast recalibré : `pre.002` deps/settings, `pre.003` TLS/metadata+unary, `pre.004` Subscribe commun, `pre.005` accounts/slots, `pre.006` transactions, `pre.007` blocks/meta/entry, `pre.008` lifecycle/backpressure, `pre.009` reconnect/replay, `pre.010` Config V3, `pre.011` live/compliance, `pre.012` clôture candidate/prompt suivant. Chaque tranche reste nominalement 15–20 minutes et peut être scindée si le wire transaction/block, le replay ou le graphe de dépendances l'exige. ### `0.2.10` / `0.2.11` — Off-chain price + app diff --git a/docs/plans/016-V0_2_9_YELLOWSTONE_GRPC_PLAN.md b/docs/plans/016-V0_2_9_YELLOWSTONE_GRPC_PLAN.md new file mode 100644 index 0000000..9cf5ce4 --- /dev/null +++ b/docs/plans/016-V0_2_9_YELLOWSTONE_GRPC_PLAN.md @@ -0,0 +1,1008 @@ + + + +# 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. diff --git a/docs/validation/000-README.md b/docs/validation/000-README.md index 5efefcf..3901e91 100644 --- a/docs/validation/000-README.md +++ b/docs/validation/000-README.md @@ -1,5 +1,5 @@ - + # Validations KSP @@ -20,3 +20,4 @@ Documents : - [`009-V0_2_6_WALLET_DESK_COMPLIANCE.md`](009-V0_2_6_WALLET_DESK_COMPLIANCE.md) — matrice finale validée de la release stable `0.2.6`, couvrant Wallet Desk, les wires V1/V2, la migration explicite, le runtime Tauri packagé, les frontières sécurité/ownership et le gate opérateur `pre.018-fix.001` avec build final Linux vert. - [`010-V0_2_7_ONCHAIN_WEBSOCKET.md`](010-V0_2_7_ONCHAIN_WEBSOCKET.md) — matrice finale validée de la release stable `0.2.7`, ouverte par `pre.001`, fermée techniquement par `pre.014` puis publiée par `rel.001` : inventaire 9 subscribe + 9 unsubscribe, lifecycle borné, statuts unstable, compliance 18/18, non-régression HTTP 52+14, composition Config V2, smoke WebSocket Devnet et audit de dépendances. - [`011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md`](011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md) — matrice finale validée de la release stable `0.2.8`, ouverte par `pre.001`, consolidée jusqu’à `pre.011` puis publiée par `rel.001` : Helius `account/logs/program/root/signature/slot/slotsUpdates + transaction`, `block/vote` absents, heartbeat provider, sécurité/redaction, lifecycle adversarial, non-régressions HTTP/WS, stratégie smoke live et graphes Cargo finaux. +- [`012-V0_2_9_YELLOWSTONE_GRPC.md`](012-V0_2_9_YELLOWSTONE_GRPC.md) — matrice active ouverte par `0.2.9-pre.001` : service Geyser courant, `Subscribe` standard, 7 unary, filtres/updates, dépendances/licence, replay/backpressure, Config V3 et interopérabilité PublicNode/OrbitFlare. diff --git a/docs/validation/012-V0_2_9_YELLOWSTONE_GRPC.md b/docs/validation/012-V0_2_9_YELLOWSTONE_GRPC.md new file mode 100644 index 0000000..3686f98 --- /dev/null +++ b/docs/validation/012-V0_2_9_YELLOWSTONE_GRPC.md @@ -0,0 +1,446 @@ + + + +# Validation `0.2.9` — Yellowstone gRPC standard/provider-neutral + +> **Statut : matrice ouverte par `0.2.9-pre.001`. Les colonnes `DONE` ne seront cochées qu'après preuves réellement exécutées. Le gate d'ouverture a audité le proto/service, les licences, les dépendances et les fournisseurs live gratuits ; il n'a pas ajouté de client gRPC de production.** + +## 1. Autorités du gate + +Base interne : + +```text +v0.2.8 / archive Gitea stable fournie +workspace.package.version initial = 0.2.8 +deltas/0.2.8/rel.001.md +prompts/014-V0_2_9_START_PROMPT.md +``` + +Sources upstream auditées le `2026-08-23` : + +```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/LICENSING.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://docs.rs/crate/yellowstone-grpc-client/latest +https://docs.rs/crate/yellowstone-grpc-proto/latest +``` + +Divergence enregistrée : + +```text +snapshot du prompt : GitHub release v14.2.2+solana.4.1.0 +réaudit courant : GitHub release v15.1.2+solana.4.2.0 (2026-08-18) +crate client : 13.3.0 +crate proto : 12.6.0 +``` + +## 2. Baseline stable + +| Gate | Preuve | État | +| --- | --- | --- | +| `cargo fmt --all` | log opérateur `v0.2.8` | DONE | +| audit Rust workspace | clean | DONE | +| `cargo check --workspace` | log opérateur | DONE | +| `cargo clippy --workspace --all-targets` | log opérateur | DONE | +| `cargo test --workspace` | log opérateur | DONE | +| Transport unit | 335 passed | DONE | +| Transport public API | 41 passed | DONE | +| Transport release completeness | 34 passed | DONE | +| Transport doctests | 4 passed | DONE | +| `cargo tree -p ksp-onchain-transport-lib` | log opérateur | DONE | +| `cargo tree --duplicates` | log opérateur | DONE | + +## 3. Matrice service `Geyser` + +| RPC | Forme | Classification | Scope | Preuve cible | État | +| --- | --- | --- | --- | --- | --- | +| `Subscribe` | bidi | standard | IN | fixture locale + live | TODO | +| `SubscribeDeshred` | bidi | Triton extension/pré-exécution malgré présence proto | OUT | canari d'absence/API | TODO | +| `SubscribeReplayInfo` | unary | standard | IN | fixture unary | TODO | +| `Ping` | unary | standard | IN | fixture unary | TODO | +| `GetLatestBlockhash` | unary | standard | IN | fixture unary | TODO | +| `GetBlockHeight` | unary | standard | IN | fixture unary | TODO | +| `GetSlot` | unary | standard | IN | fixture unary | TODO | +| `IsBlockhashValid` | unary | standard | IN | fixture unary | TODO | +| `GetVersion` | unary | standard | IN | fixture unary | TODO | + +## 4. `SubscribeRequest` — coverage normative + +### 4.1 Top-level + +| Champ | Sémantique | Scope | Preuve | +| --- | --- | --- | --- | +| `accounts` | map filter-name -> account filter | IN | exact wire + bounds | +| `slots` | map -> slot filter | IN | exact wire | +| `transactions` | map -> transaction filter | IN | exact wire + bounds | +| `transactions_status` | map -> transaction filter | IN | exact wire + bounds | +| `blocks` | map -> block filter | IN | exact wire + bounds | +| `blocks_meta` | map -> empty filter | IN | presence/empty semantics | +| `entry` | map -> empty filter | IN | presence/empty semantics | +| `commitment` | optional Processed/Confirmed/Finalized | IN | omitted/value exact | +| `accounts_data_slice` | repeated offset/length | IN | order + bounds | +| `ping` | optional id | IN | Ping/Pong lifecycle | +| `from_slot` | optional u64 | IN | reconnect/replay tests | + +### 4.2 Accounts + +| Capacité | Scope | Preuve | +| --- | --- | --- | +| `account[]` | IN | order/cardinality/address validation | +| `owner[]` | IN | order/cardinality/address validation | +| `filters[]` | IN | AND semantics preserved structurally | +| `nonempty_txn_signature?` | IN | omitted/false/true | +| `cuckoo_accounts_filter?` | IN | exact wire + dimension/data bounds | +| memcmp bytes | IN | exact bytes + bounds | +| memcmp base58 | IN | exact string + validation | +| memcmp base64 | IN | exact string + validation | +| `datasize` | IN | exact u64 | +| `token_account_state` | IN | bool | +| lamports `eq/ne/lt/gt` | IN | oneof exact | + +### 4.3 Slots + +| Capacité | Scope | Preuve | +| --- | --- | --- | +| `filter_by_commitment?` | IN | optional semantics | +| `interslot_updates?` | IN | optional semantics | +| processed/confirmed/finalized | IN | enum decode | +| first_shred_received/completed/created_bank/dead | IN | enum decode + dead_error | + +### 4.4 Transactions / transaction_status + +| Capacité | Scope | Preuve | +| --- | --- | --- | +| `vote?` | IN | optional semantics | +| `failed?` | IN | optional semantics | +| `signature?` | IN | exact/validated | +| `account_include[]` | IN | order/bounds | +| `account_exclude[]` | IN | order/bounds | +| `account_required[]` | IN | order/bounds | +| `cuckoo_account_include?` | IN | exact wire + bounds | +| `token_accounts? = ALL` | IN | optional enum | +| `token_accounts? = BALANCE_CHANGED` | IN | optional enum | + +### 4.5 Blocks + +| Capacité | Scope | Preuve | +| --- | --- | --- | +| `account_include[]` | IN | order/bounds | +| `include_transactions?` | IN | optional semantics | +| `include_accounts?` | IN | optional semantics | +| `include_entries?` | IN | optional semantics | +| `cuckoo_account_include?` | IN | exact wire + bounds | + +## 5. `SubscribeUpdate` — coverage normative + +| Variante | Champs structurants | Scope | Preuve | +| --- | --- | --- | --- | +| `account` | account info, slot, is_startup | IN | exact decode | +| `slot` | slot, parent?, status, dead_error? | IN | exact decode | +| `transaction` | signature, vote, transaction, meta, index, slot | IN | exact decode | +| `transaction_status` | slot, signature, vote, index, err | IN | exact decode | +| `block` | hash/rewards/time/height/parents/counts + tx/accounts/entries | IN | exact decode + bounds | +| `ping` | marker | IN | lifecycle | +| `pong` | id | IN | lifecycle | +| `block_meta` | metadata/counts | IN | exact decode | +| `entry` | slot/index/hash/counts | IN | exact decode | + +Top-level à préserver : + +```text +filters[] +created_at +oneof absent/inconnu -> comportement explicitement testé +``` + +## 6. `solana-storage.proto` — nested wire utile + +Le backend doit préserver les champs nécessaires des structures imbriquées actuelles, sans exposer les types upstream comme contrat public : + +```text +ConfirmedBlock +ConfirmedTransaction +Transaction +Message +MessageHeader +MessageAddressTableLookup +TransactionStatusMeta +TransactionError +InnerInstructions / InnerInstruction +CompiledInstruction +TokenBalance / UiTokenAmount +ReturnData +Reward / Rewards +UnixTimestamp +BlockHeight +NumPartitions +``` + +États optionnels/legacy particulièrement sensibles : + +```text +compute_units_consumed? +cost_units? +inner_instructions_none +log_messages_none +return_data_none +loaded writable/readonly addresses +commission / commission_bps +``` + +Preuve cible : fixtures issues du wire Protobuf + cas old/current + malformed/oversized, sans conversion JSON arbitraire. + +## 7. Unary RPC matrix + +| RPC | Request exact | Response exact | État | +| --- | --- | --- | --- | +| ReplayInfo | empty | `first_available?` | TODO | +| Ping | `count` | `count` | TODO | +| LatestBlockhash | `commitment?` | slot/hash/last_valid_height | TODO | +| BlockHeight | `commitment?` | block_height | TODO | +| Slot | `commitment?` | slot | TODO | +| IsBlockhashValid | blockhash + `commitment?` | slot + bool | TODO | +| Version | empty | version | TODO | + +## 8. Dépendances / licence + +| Gate | Décision `pre.001` | Preuve suivante | +| --- | --- | --- | +| repository default | AGPL-3.0-only | `LICENSING.md` | +| client subtree | Apache-2.0 | `LICENSING.md` | +| proto subtree | Apache-2.0 | `LICENSING.md` | +| strategy A client+proto | rejetée comme default | documenté | +| strategy B proto+Tonic KSP | **retenue** | `pre.002` compile/tree | +| strategy C vendored proto | fallback seulement | aucun vendoring pre.001 | +| system protoc | non attendu avec crate publiée | vérifier build réel | +| raw upstream types public | interdit par défaut | public API canary | +| executable Yellowstone deps | interdit | dependency firewall | + +Versions observées : + +```text +yellowstone-grpc-client 13.3.0 +yellowstone-grpc-proto 12.6.0 +tonic 0.14.x (0.14.6 latest observé) +prost/prost-types 0.14.x (0.14.4 latest observé) +``` + +## 9. Architecture / ownership + +| Invariant | Preuve cible | État | +| --- | --- | --- | +| backend gRPC distinct HTTP/WS | source/API canary | TODO | +| aucun `WsProtocolKind` gRPC | source scan | TODO | +| Transport owns gRPC | dependency graph | TODO | +| Config -> Transport seulement | ownership test | TODO | +| Transport -X-> Config | ownership test | TODO | +| Transport -X-> std::env KSP_* | ownership test | TODO | +| Logging façade KSP only | logging ownership | TODO | +| no raw Tonic client escape hatch | public API canary | TODO | +| no provider-specific public types | public API/completeness | TODO | + +## 10. Settings, bounds et redaction + +À fermer par tests : + +```text +endpoint schemes TLS/non-TLS explicitement validés +connect timeout > 0 +unary timeout > 0 +close timeout > 0 +max inbound/outbound > 0 et plafonnés +request/update queue capacities > 0 et plafonnées +reconnect attempt/backoff bornés +filter-group count +filter-name length/uniqueness +metadata key/value count/size +account/owner/include/exclude/required counts +memcmp/data slice bounds +Cuckoo dimensions/data bounds +``` + +Security canaries : + +```text +endpoint URL Debug redacted +secret metadata Debug/Display absent +Status message/details distants non recopiés aveuglément en context +TLS/connect error sans credential/URI sensible +request/update Debug sans payload arbitraire sensible +snapshot sans endpoint secret ni remote internals inutiles +``` + +## 11. Lifecycle / backpressure / replay + +| Cas | Attendu | État | +| --- | --- | --- | +| stream open | session bornée | TODO | +| request mutation | ordre déterministe | TODO | +| server Ping -> client request ping -> Pong | explicite | TODO | +| server half-close | terminal/reconnect selon policy | TODO | +| client close | cleanup borné | TODO | +| receiver drop | cleanup capacité | TODO | +| slow subscription | pas de queue infinie | TODO | +| inbound oversized | rejet avant allocation excessive | TODO | +| outbound oversized | rejet avant write | TODO | +| reconnect budget | borné | TODO | +| resubscribe order | déterministe | TODO | +| `from_slot` | utilisé sans promesse lossless | TODO | +| ReplayInfo | informatif | TODO | +| duplicates | observables | TODO | +| gaps | observables | TODO | +| divergent node history | couverture documentée | TODO | +| shutdown during reconnect | aucune nouvelle connexion après shutdown | TODO | + +Claims interdits sans nouvelle preuve : + +```text +exactly-once +lossless +historical replay complet +ordre global sans gap +``` + +## 12. Config V3 + +Décision de gate : + +```text +V1 HTTP reste lisible +V2 HTTP+WS reste lisible +V3 ajoute gRPC explicitement +``` + +Shape conceptuelle à matérialiser : + +```text +globals.grpc_defaults +profiles[].grpc_endpoints[] +endpoint.metadata[] # public/non-secret +endpoint.secret_metadata[] # Config-owned secret provenance +``` + +Canaries : + +| Gate | État | +| --- | --- | +| V1 backward readable | TODO | +| V2 backward readable | TODO | +| V3 schema strict | TODO | +| gRPC endpoint mapping | TODO | +| secret provenance enforced | TODO | +| safe projection redacted | TODO | +| no Transport -> Config | TODO | +| `.env.example` inventory if new env vars | TODO | + +## 13. Fournisseurs live gratuits / durables + +| Provider | Cluster gRPC gratuit confirmé | Nature | Priorité `0.2.9` | Verdict | +| --- | --- | --- | --- | --- | +| **PublicNode / Allnodes-backed** | Mainnet + Testnet | endpoint public, pas de plan payant requis observé | 1 | **IN smoke** | +| **OrbitFlare** | Devnet | Free $0, 10 RPS/1 TPS, unlimited credits | 2 | **IN smoke secondaire** | +| Tatum | Mainnet | Free durable mais 100K lifetime credits, 5 subscriptions | 3 | opérateur optionnel | +| Helius | aucun sur Free | Devnet Developer, Mainnet Business | — | OUT free | +| Shyft | aucun sur Free | Free indique No gRPC Access | — | OUT free | +| Alchemy | aucun sur Free | PAYG/Enterprise requis | — | OUT free | +| QuickNode | aucun sur Free | Scale/Business ou add-on payant | — | OUT free | +| Chainstack | aucun sur Free | add-on Yellowstone payant, Growth+ | — | OUT free | +| ERPC | aucun durable | plan Geyser payant, trial 1 jour | — | OUT free | +| NodeFlare | endpoint gRPC présent | plan Yellowstone mensuel payant | — | OUT free | +| Bitquery | pas Yellowstone standard | CoreCast custom, stream gratuit non garanti | — | OUT 0.2.9 | +| Solinfra | **non confirmé** | free tier + Yellowstone annoncés, entitlement gRPC free non explicite | recheck | CANDIDAT | + +Sources provider : + +```text +https://publicnode.com/ +https://solana-yellowstone-grpc.publicnode.com/ +https://orbitflare.com/pricing +https://docs.tatum.io/reference/solana-grpc +https://tatum.io/pricing +https://www.helius.dev/pricing +https://shyft.to/solana-rpc-grpc-pricing +https://www.alchemy.com/docs/reference/yellowstone-grpc-quickstart +https://www.quicknode.com/docs/solana/solana-grpc/overview +https://chainstack.com/pricing/ +https://erpc.global/en/grpc/ +https://nodeflare.app/solana +https://docs.bitquery.io/docs/grpc/solana/introduction/ +https://solinfra.dev/ +``` + +### Smoke PublicNode + +Cible principale officiellement affichée : + +```text +solana-yellowstone-grpc.publicnode.com:443 +``` + +Testnet GRPC est officiellement listé. L'endpoint exact doit être confirmé avant commit d'un profil durable. + +### Smoke OrbitFlare + +Credential : jamais versionné. La clé/header gRPC exacte doit être confirmée depuis la documentation/live au moment du smoke ; le contrat Transport reste generic secret metadata. + +## 14. Non-régressions obligatoires + +| Surface héritée | Attendu final | État | +| --- | --- | --- | +| HTTP current | 52 typed | TODO final | +| HTTP historical | 14 Deprecated/Removed | TODO final | +| Standard WS | 18 opérations / 9 familles | TODO final | +| Helius WS | 7 standard + transaction | TODO final | +| Helius heartbeat | Ping 60 s | TODO final | +| Config V1/V2 | backward read | TODO final | +| Wallet/Wallet Desk | aucune dépendance protocolaire Yellowstone directe | TODO final | + +## 15. Forecast / preuve par tranche + +```text +pre.001 DONE audit + matrices + dependencies/license + providers + sizing +pre.002 TODO deps/settings/errors/facade + cargo tree +pre.003 TODO TLS/metadata + local fixture + 7 unary +pre.004 TODO Subscribe common + Cuckoo/token/from_slot/bounds +pre.005 TODO accounts + slots +pre.006 TODO transactions + transaction_status +pre.007 TODO blocks + block_meta + entry +pre.008 TODO bidi lifecycle/backpressure/half-close/shutdown +pre.009 TODO reconnect/replay/gap/duplicate/equivocation +pre.010 TODO Config V3 +pre.011 TODO live PublicNode/OrbitFlare + compliance + final cargo graphs +pre.012 TODO docs/workspace final/prompt 0.2.10 +rel.001 TODO stable +``` + +## 16. Gate `pre.001` + +| Critère du prompt | Verdict | +| --- | --- | +| base stable `v0.2.8` confirmée | PASS | +| baseline opérateur enregistrée | PASS | +| upstream courant relu | PASS | +| divergence snapshot/latest enregistrée | PASS | +| service/proto exhaustif inventorié | PASS | +| standard vs provider extension classifié | PASS | +| `SubscribeDeshred` classifié | PASS / OUT | +| unary RPCs classifiés | PASS / 7 IN | +| replay/from_slot audités | PASS | +| strategy dependency choisie | PASS / B | +| licence auditée avant ajout | PASS | +| features/MSRV/transitifs audit initial | PASS / materialisation pre.002 | +| architecture distincte WS | PASS | +| metadata/auth neutral | PASS | +| Config shape décidée | PASS / V3 | +| resource/backpressure policy décidée | PASS | +| smoke ownership décidé | PASS | +| providers gratuits audités | PASS | +| release dimensionnée | PASS | +| forecast recalibré | PASS | +| split criteria écrits | PASS | +| aucune implémentation lourde prématurée | PASS | + +**Verdict `pre.001` : gate positif ; `pre.002` peut matérialiser la stratégie B sous validation Cargo.**