Files
khadhroony-solana-project/docs/plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md
2026-08-17 18:02:18 +02:00

66 KiB
Raw Blame History

0.2.1-pre.001 — plan ksp-onchain-transport-lib HTTP Solana foundation

1. Statut et conclusion exécutive

Ce document ouvre 0.2.1 à partir de la base stable fournie 0.2.0 et exécute le gate de sizing imposé par le prompt 006 avant toute grosse implémentation. Sa version initiale appartient à 0.2.1-pre.001; le split de releases présenté dans cette version du plan est le recalibrage documentaire de 0.2.1-pre.001-fix.001.

Conclusion du gate :

Périmètre monolithique 0.2.1 décrit par le prompt 006 : NON clôturable raisonnablement dans cette session.
0.2.1 réduite après split : OUI, clôturable raisonnablement dans cette session.

Le périmètre initial combinait simultanément : 52 méthodes HTTP courantes typées, 14 méthodes historiques deprecated à classifier, les formes de paramètres legacy encore documentées, la crate foundation, le protocole JSON-RPC, l'ownership des modèles wire, les pools, rôles, priorités, limites, concurrence, retry/backoff, erreurs, logging, Config standard, adapter Config -> Transport, tests, fixtures, smoke tests et documentation. Cette combinaison dépasse la discipline KSP de tranches d'environ 1520 minutes et ne permet pas de garantir la clôture complète de la release dans la même session.

Le split conserve l'inventaire exhaustif : aucune méthode n'est masquée. Les 52 méthodes courantes et les 14 pages deprecated restent verrouillées dans la matrice ci-dessous et sont affectées explicitement à une release de la série HTTP.

2. Sources relues et base stable auditée

2.1 Sources internes KSP

Relues pour cette tranche :

  • ROADMAP.md ;
  • docs/000-README.md ;
  • docs/IDEAS.md ;
  • docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md ;
  • docs/plans/007-V0_2_0_SERIES_PLANNING.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/008-DATA_MATERIALIZATION_AND_STORE.md ;
  • docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md ;
  • docs/rules/RULES_KSP.md ;
  • docs/rules/RULES_DEPENDENCIES.md ;
  • docs/rules/RULES_RUST.md ;
  • docs/rules/PROMPT_STRUCTURE.md ;
  • docs/rules/VERSION_WORKFLOW.md ;
  • docs/rules/FILE_CONTRACTS.md ;
  • contrats publics actuels de ksp-core-lib, ksp-logging-lib et ksp-config-lib.

2.2 Base fournie

L'archive khadhroony-solana-project-v0.2.0.zip contient :

workspace.package.version = "0.2.0"

et exactement les quatre crates déjà stabilisées :

ksp-core-lib
ksp-logging-lib
ksp-config-lib
ksp-app-config-desk

Aucune crate Transport n'existe encore. L'archive ne contient pas .git, donc le tag v0.2.0 ne peut pas être revérifié localement depuis ce zip. Le contenu technique fourni correspond néanmoins à la version stable attendue.

2.3 Contrats KSP qui conditionnent Transport

  • ksp-core-lib possède l'unique Error, ErrorCode et Result<T> KSP. Transport déclarera ses codes dans son domaine mais ne créera pas une hiérarchie d'erreurs concurrente.
  • ksp-logging-lib possède la façade de tracing et les macros KSP ; Transport ne dépendra pas directement de tracing.
  • ksp-config-lib possède déjà registry, documents, profils, interpolation d'environnement, sensibilité/provenance et adapters de runtime. Le nouvel adapter sera donc Config -> settings Transport, jamais l'inverse.
  • Les règles d'architecture interdisent Transport -> Store et Transport -> Program. Les réponses restent wire/transport et préservent l'information nécessaire aux futures couches RAW/CORE.

3. Audit détaillé du transport bot3

Archive de référence :

khadhroony-bot3_v0.5.3-pre.005-fix010.zip
workspace.package.version = "0.5.3-pre.5"

3.1 Dépendances historiques

ks-onchain-transport/Cargo.toml dépend directement de :

futures-util
base64
bs58
ks-config
ks-core
ks-lib
reqwest
serde
serde_json
tokio
tokio-tungstenite
tracing

Décision KSP :

Élément bot3 Décision Motif
reqwest async HTTP adapter besoin HTTP réel, version/features à réauditer
serde / serde_json reprendre contrat JSON-RPC/wire naturel et déjà workspace
tokio reprendre runtime async déjà workspace ; sync devra être ajouté si Semaphore est retenu
base64 / bs58 différer ne les ajouter qu'à la première méthode qui doit réellement encoder/valider ces wires
futures-util abandonner pour HTTP foundation usage surtout live/stream ; pas nécessaire par anticipation
tokio-tungstenite abandonner pour 0.2.1 WebSocket hors périmètre
ks-config abandonner comme dépendance Transport ownership inversé dans KSP
ks-lib abandonner couplage aux modèles canonical/Program contraire à RAW/CORE
tracing direct abandonner ksp-logging-lib est propriétaire

3.2 Inventaire des méthodes bot3

Le registre STANDARD_HTTP_METHODS contient 52 noms uniques, tous avec le contrat TypedAdapter. La comparaison nom par nom avec l'index HTTP officiel audité le 2026-08-17 donne :

current Solana HTTP index : 52
bot3 STANDARD_HTTP_METHODS: 52
missing in bot3           : 0
extra in bot3             : 0

Bot3 constitue donc une bonne preuve historique pour les noms de la surface courante, mais pas une source normative des paramètres, statuts, modèles ni frontières KSP.

3.3 Settings/roles bot3 utiles

Bot3 possède :

  • endpoint : name, enabled, provider, cluster, url, connect_timeout_ms, request_timeout_ms, max_idle_connections_per_host, roles ;
  • rôle : role, enabled, request_kinds, priority, requests_per_second, burst_capacity, max_concurrent_requests, max_subscriptions, pause_after_rate_limit_ms ;
  • wildcard * pour request_kinds ;
  • limiteur token-bucket approximé + Semaphore ;
  • cooldown après rate-limit ;
  • snapshots sans URL afin de limiter la fuite de secrets.

À reprendre : identité/provider/cluster, rôles ouverts, priorités, RPS/burst/concurrence, cooldown et snapshots redacted.

À abandonner pour HTTP : max_subscriptions appartient au futur WebSocket et ne sera pas prérempli dans le contrat HTTP.

3.4 Pool bot3 : force et faiblesse

Le pool historique fait un round-robin entre clients pouvant gérer le rôle/la méthode. Le client choisit localement le rôle correspondant de plus faible priorité. Cette architecture ne produit toutefois pas une sélection globale nette « meilleure priorité sur tous les endpoints, puis round-robin dans le tier ».

KSP refond donc la sélection au niveau du pool logique : priorité globale, fairness dans un même tier, fallback sur endpoint indisponible/cooldown/saturé, et deadline commune.

3.5 Retry/rate-limit bot3

Bot3 sait reconnaître HTTP 429, lire Retry-After, appliquer un backoff exponentiel borné et imposer un cooldown. Ces invariants sont utiles mais la politique n'est pas suffisamment liée à la nature de la méthode. En particulier, KSP doit empêcher tout resend ambigu de sendTransaction/requestAirdrop au nom d'un retry « transport » générique.

3.6 Couplages de modèles à supprimer

Bot3 lie certaines méthodes techniques à ks-lib, notamment autour des signatures/transactions et de modèles canoniques. KSP interdit le pattern :

getTransaction -> modèle CORE/DECODE canonique

getTransaction/getBlock devront préserver le wire et les variations d'encoding sans normaliser vers Store/Program.

4. Audit officiel Solana HTTP — 2026-08-17

4.1 Sources normatives

Sources externes utilisées :

La documentation Solana indique JSON-RPC 2.0 sur HTTP POST, Content-Type: application/json, jsonrpc = "2.0", id, method et paramètres ordonnés.

4.2 Surface courante

L'index officiel contient 52 méthodes HTTP courantes :

Accounts     6
Tokens       5
Transactions 11
Blocks       10
Cluster      15
Economics    5
Total        52

Aucune page HTTP courante marquée Unstable Method ou Experimental n'a été trouvée pendant l'audit. Les résultats officiels portant explicitement le marqueur Unstable Method concernent actuellement des méthodes WebSocket/PubSub et restent hors 0.2.1.

4.3 Surface Deprecated séparée

La navigation officielle Deprecated contient 14 méthodes. Les pages indiquent qu'elles étaient attendues supprimées en solana-core v2.0. Le changelog Agave confirme ensuite le retrait des endpoints RPC v1 obsolete/deprecated dans la ligne v2.

Conséquence KSP :

  • elles restent dans le registre/matrice de conformité historique ;
  • leur statut documentaire est Deprecated ;
  • leur statut runtime KSP initial est Removed ;
  • aucune méthode callable ne simulera un succès ;
  • aucune tentative de warning « à l'utilisation » n'est nécessaire tant qu'elles sont réellement non exécutables ;
  • leur disponibilité devra être revérifiée depuis les sources officielles si une release future réouvre ce point.

4.4 Deprecated au niveau d'une forme de requête

Deux méthodes courantes et stables documentent encore une forme de paramètres legacy explicitement deprecated :

  • getTransaction : second paramètre encoding sous forme de string nue ;
  • getBlock : second paramètre encoding sous forme de string nue.

KSP doit donc distinguer :

method documentation status
request-form documentation status
runtime support status

Un simple enum au niveau méthode ne suffit pas à représenter fidèlement la documentation actuelle.

getBlocks possède également un overload backward-compatible où le deuxième paramètre peut être l'objet config, mais la page actuelle ne le marque pas deprecated. Cette forme doit être sérialisée/testée sans warning.

5. Matrice exhaustive — 52 méthodes HTTP courantes

Colonnes : nom, catégorie, paramètres/config à préserver, forme de résultat, statut documentaire, disponibilité runtime, niveau bot3, release KSP assignée, preuve minimale et source normative.

Méthode Catégorie Params / config Résultat Statut Runtime Bot3 Release Tests minimaux Source
getAccountInfo Accounts pubkey ; config? {commitment, encoding, dataSlice, minContextSlot} RpcResponse<Account|null> Stable Supporté typed_adapter 0.2.2 params/encoding/dataSlice ; account/null ; RPC error Solana
getBalance Accounts pubkey ; config? {commitment, minContextSlot} RpcResponse Stable Supporté typed_adapter 0.2.1 params/config ; value u64 ; context/error Solana
getLargestAccounts Accounts config? {commitment, filter, sortResults} RpcResponse<[LargestAccount]> Stable Supporté typed_adapter 0.2.2 config/filter/sort ; array Solana
getMinimumBalanceForRentExemption Accounts data_len ; config? {commitment} u64 Stable Supporté typed_adapter 0.2.2 data length/config ; u64 Solana
getMultipleAccounts Accounts pubkeys <= 100 ; config? {commitment, minContextSlot, dataSlice, encoding} RpcResponse<[Account|null]> Stable Supporté typed_adapter 0.2.2 max/params ; mixed account/null ; encoding Solana
getProgramAccounts Accounts program pubkey ; config? {commitment, minContextSlot, withContext, encoding, dataSlice, filters, sortResults} [KeyedAccount] ou RpcResponse<[KeyedAccount]> Stable Supporté typed_adapter 0.2.2 filters/dataSlice ; withContext false/true ; errors Solana
getTokenAccountBalance Tokens token account ; config? {commitment} RpcResponse Stable Supporté typed_adapter 0.2.2 config ; token amount Solana
getTokenAccountsByDelegate Tokens delegate ; filter {mint|programId} ; config? {commitment,minContextSlot,dataSlice,encoding} RpcResponse<[KeyedAccount]> Stable Supporté typed_adapter 0.2.2 mint/programId exclusifs ; config ; array Solana
getTokenAccountsByOwner Tokens owner ; filter {mint|programId} ; config? {commitment,minContextSlot,dataSlice,encoding} RpcResponse<[KeyedAccount]> Stable Supporté typed_adapter 0.2.2 mint/programId exclusifs ; config ; array Solana
getTokenLargestAccounts Tokens mint ; config? {commitment} RpcResponse<[TokenLargestAccount]> Stable Supporté typed_adapter 0.2.2 config ; array Solana
getTokenSupply Tokens mint ; config? {commitment} RpcResponse Stable Supporté typed_adapter 0.2.2 config ; TokenAmount Solana
getFeeForMessage Transactions message base64 ; config? {commitment,minContextSlot} RpcResponse<u64|null> Stable Supporté typed_adapter 0.2.3 message/config ; fee/null ; error Solana
getLatestBlockhash Transactions config? {commitment,minContextSlot} RpcResponse<{blockhash,lastValidBlockHeight}> Stable Supporté typed_adapter 0.2.3 config ; object Solana
getRecentPrioritizationFees Transactions pubkeys? <= 128 [{slot,prioritizationFee}] Stable Supporté typed_adapter 0.2.3 no params / addresses ; max ; array Solana
getSignaturesForAddress Transactions address ; config? {commitment,minContextSlot,limit,before,until} [SignatureInfo] Stable Supporté typed_adapter 0.2.3 pagination/config ; nullable memo/blockTime/status Solana
getSignatureStatuses Transactions signatures <= 256 ; config? {searchTransactionHistory} RpcResponse<[SignatureStatus|null]> Stable Supporté typed_adapter 0.2.3 max ; cache/history ; object/null Solana
getTransaction Transactions signature ; config? {commitment,maxSupportedTransactionVersion,encoding} ; legacy bare encoding deprecated TransactionResponse|null Stable; forme legacy deprecated Supporté typed_adapter 0.2.3 config + legacy warning ; all encodings ; null ; error Solana
getTransactionCount Transactions config? {commitment,minContextSlot} u64 Stable Supporté typed_adapter 0.2.3 config ; u64 Solana
isBlockhashValid Transactions blockhash ; config? {commitment,minContextSlot} RpcResponse Stable Supporté typed_adapter 0.2.3 hash/config ; bool Solana
requestAirdrop Transactions pubkey ; lamports ; config? {commitment,recentBlockhash} signature Stable Supporté typed_adapter 0.2.3 serialization ; signature/error ; no-resend policy Solana
sendTransaction Transactions signed transaction ; config? {encoding,skipPreflight,preflightCommitment,maxRetries,minContextSlot} signature Stable Supporté typed_adapter 0.2.3 all configs ; RPC error ; timeout/no-resend Solana
simulateTransaction Transactions transaction ; config? {commitment,encoding,replaceRecentBlockhash,sigVerify,minContextSlot,innerInstructions,accounts} RpcResponse Stable Supporté typed_adapter 0.2.3 configs compatibles/incompatibles ; logs/accounts/null/error Solana
getBlock Blocks slot ; config? {commitment,encoding,transactionDetails,maxSupportedTransactionVersion,rewards} ; legacy bare encoding deprecated BlockResponse|null Stable; forme legacy deprecated Supporté typed_adapter 0.2.4 config + legacy warning ; transactionDetails variants ; null Solana
getBlockCommitment Blocks slot {commitment:[u64]|null,totalStake:u64} Stable Supporté typed_adapter 0.2.4 slot ; commitment null/array Solana
getBlockHeight Blocks config? {commitment,minContextSlot} u64 Stable Supporté typed_adapter 0.2.4 config ; u64 Solana
getBlockProduction Blocks config? {commitment,identity,range} RpcResponse Stable Supporté typed_adapter 0.2.4 identity/range/config ; map Solana
getBlocks Blocks startSlot ; endSlot? ou config? ; config? {commitment,minContextSlot} [u64] Stable Supporté typed_adapter 0.2.4 overload 1/2/3 params ; max range 500k ; empty Solana
getBlocksWithLimit Blocks startSlot ; limit <= 500000 ; config? {commitment,minContextSlot} [u64] Stable Supporté typed_adapter 0.2.4 limit boundaries ; config ; array Solana
getBlockTime Blocks slot i64 Stable Supporté typed_adapter 0.2.4 success ; unavailable/error variant Solana
getFirstAvailableBlock Blocks aucun u64 Stable Supporté typed_adapter 0.2.4 empty params ; u64 Solana
getRecentPerformanceSamples Blocks limit? <= 720 [PerformanceSample] Stable Supporté typed_adapter 0.2.4 no params/limit ; nullable numNonVoteTransactions Solana
minimumLedgerSlot Blocks aucun u64 Stable Supporté typed_adapter 0.2.4 empty params ; u64 Solana
getClusterNodes Cluster aucun [ClusterNode] Stable Supporté typed_adapter 0.2.2 nullable endpoints/features ; array Solana
getEpochInfo Cluster config? {commitment,minContextSlot} EpochInfo Stable Supporté typed_adapter 0.2.2 config ; transactionCount null Solana
getEpochSchedule Cluster aucun EpochSchedule Stable Supporté typed_adapter 0.2.2 empty params ; object Solana
getGenesisHash Cluster aucun string base58 Stable Supporté typed_adapter 0.2.1 empty params ; hash string ; error Solana
getHealth Cluster aucun "ok" ou RPC unhealthy error Stable Supporté typed_adapter 0.2.1 healthy ; unhealthy RPC error Solana
getHighestSnapshotSlot Cluster aucun {full:u64,incremental:u64|null} Stable Supporté typed_adapter 0.2.2 incremental null ; no snapshot/error Solana
getIdentity Cluster aucun {identity:string} Stable Supporté typed_adapter 0.2.2 empty params ; identity Solana
getLeaderSchedule Cluster slot? | config? | null ; config? {commitment,identity} map identity->[slot_index] | null Stable Supporté typed_adapter 0.2.2 all overloads ; filter ; null Solana
getMaxRetransmitSlot Cluster aucun u64 Stable Supporté typed_adapter 0.2.2 empty params ; u64 Solana
getMaxShredInsertSlot Cluster aucun u64 Stable Supporté typed_adapter 0.2.2 empty params ; u64 Solana
getSlot Cluster config? {commitment,minContextSlot} u64 Stable Supporté typed_adapter 0.2.2 config ; u64 Solana
getSlotLeader Cluster config? {commitment,minContextSlot} string pubkey Stable Supporté typed_adapter 0.2.2 config ; pubkey Solana
getSlotLeaders Cluster startSlot ; limit 1..5000 [string pubkey] Stable Supporté typed_adapter 0.2.2 limit boundaries ; array Solana
getVersion Cluster aucun {solana-core:string,feature-set:u32|null} Stable Supporté typed_adapter 0.2.1 empty params ; feature-set present/null Solana
getVoteAccounts Cluster config? {commitment,votePubkey,keepUnstakedDelinquents,delinquentSlotDistance} {current:[VoteAccount],delinquent:[VoteAccount]} Stable Supporté typed_adapter 0.2.2 filters/config ; both sets Solana
getInflationGovernor Economics config? {commitment} InflationGovernor Stable Supporté typed_adapter 0.2.4 config ; f64 fields Solana
getInflationRate Economics aucun {total,validator,foundation:f64,epoch:u64} Stable Supporté typed_adapter 0.2.4 empty params ; object Solana
getInflationReward Economics addresses ; config? {commitment,epoch,minContextSlot} [InflationReward|null] Stable Supporté typed_adapter 0.2.4 addresses/config ; reward/null ; commission null Solana
getStakeMinimumDelegation Economics config? {commitment,minContextSlot} RpcResponse Stable Supporté typed_adapter 0.2.4 config ; value Solana
getSupply Economics config? {commitment,excludeNonCirculatingAccountsList} RpcResponse Stable Supporté typed_adapter 0.2.4 config true/false ; list semantics Solana

6. Matrice exhaustive — 14 méthodes Deprecated historiques

Méthode Statut doc Runtime actuel Remplacement / direction Bot3 HTTP Contrat KSP Source
confirmTransaction Deprecated Removed (Agave v2+) getSignatureStatuses absent du registre HTTP bot3 descripteur historique en 0.2.1, aucune exécution simulée Solana
getConfirmedBlock Deprecated Removed (Agave v2+) getBlock absent du registre HTTP bot3 descripteur historique en 0.2.1, aucune exécution simulée Solana
getConfirmedBlocks Deprecated Removed (Agave v2+) getBlocks absent du registre HTTP bot3 descripteur historique en 0.2.1, aucune exécution simulée Solana
getConfirmedBlocksWithLimit Deprecated Removed (Agave v2+) getBlocksWithLimit absent du registre HTTP bot3 descripteur historique en 0.2.1, aucune exécution simulée Solana
getConfirmedSignaturesForAddress2 Deprecated Removed (Agave v2+) getSignaturesForAddress absent du registre HTTP bot3 descripteur historique en 0.2.1, aucune exécution simulée Solana
getConfirmedTransaction Deprecated Removed (Agave v2+) getTransaction absent du registre HTTP bot3 descripteur historique en 0.2.1, aucune exécution simulée Solana
getFeeCalculatorForBlockhash Deprecated Removed (Agave v2+) isBlockhashValid / getFeeForMessage absent du registre HTTP bot3 descripteur historique en 0.2.1, aucune exécution simulée Solana
getFeeRateGovernor Deprecated Removed (Agave v2+) getFeeForMessage absent du registre HTTP bot3 descripteur historique en 0.2.1, aucune exécution simulée Solana
getFees Deprecated Removed (Agave v2+) getFeeForMessage absent du registre HTTP bot3 descripteur historique en 0.2.1, aucune exécution simulée Solana
getRecentBlockhash Deprecated Removed (Agave v2+) getLatestBlockhash absent du registre HTTP bot3 descripteur historique en 0.2.1, aucune exécution simulée Solana
getSignatureConfirmation Deprecated Removed (Agave v2+) getSignatureStatuses absent du registre HTTP bot3 descripteur historique en 0.2.1, aucune exécution simulée Solana
getSignatureStatus Deprecated Removed (Agave v2+) getSignatureStatuses absent du registre HTTP bot3 descripteur historique en 0.2.1, aucune exécution simulée Solana
getSnapshotSlot Deprecated Removed (Agave v2+) getHighestSnapshotSlot absent du registre HTTP bot3 descripteur historique en 0.2.1, aucune exécution simulée Solana
getStakeActivation Deprecated Removed (Agave v2+) approche alternative documentée absent du registre HTTP bot3 descripteur historique en 0.2.1, aucune exécution simulée Solana

6.1 Écart bot3 / documentation actuelle

La décision runtime = Removed repose ici sur le changelog officiel Agave v2+, qui documente la suppression des endpoints RPC v1 obsolètes/dépréciés. Aucun POST JSON-RPC live vers un provider public ou privé na été exécuté pendant pre.001; une divergence propre à un provider devra donc être documentée comme extension/comportement provider, sans réintroduire ces méthodes dans le contrat standard KSP.

Résumé nom par nom :

  • les 52 courantes sont toutes présentes dans bot3 et toutes marquées TypedAdapter ;
  • les 14 Deprecated de la navigation officielle sont absentes du registre HTTP standard bot3 ;
  • elles ne doivent pas être recopiées comme wrappers callables aujourd'hui puisque le runtime Agave v2 les a retirées ;
  • le nouvel inventaire KSP sera donc plus complet que bot3 sur la metadata documentaire, tout en exposant moins de faux support runtime.

7. Split obligatoire de la série HTTP

Le split retenu est :

Release Mission Surface courante assignée
0.2.1 HTTP transport foundation 4 canaris : getBalance, getGenesisHash, getHealth, getVersion + registre 52/14 + infrastructure complète foundation
0.2.2 HTTP Accounts + Tokens + Cluster 5 Accounts restants + 5 Tokens + 12 Cluster restants = 22
0.2.3 HTTP Transactions 11
0.2.4 HTTP Blocks + Economics + compliance finale 10 Blocks + 5 Economics = 15 + gate exhaustif 52 courantes / 14 historiques

La présence d'un appel JSON-RPC raw/générique dans 0.2.1 ne comptera pas comme couverture typée des méthodes affectées à 0.2.20.2.4.

Ces trois releases HTTP complémentaires représentent trois sessions nominales au maximum, pas trois chats obligatoires. Si une release est entièrement clôturée plus vite que prévu, la même session peut ouvrir puis clôturer la suivante après un nouveau gate de sizing positif. Les frontières restent strictement séparées : numéro de release, prereleases, version, delta, validations et clôture stable.

Wallet est décalé à 0.2.5 et Wallet Desk à 0.2.6. Le premier getBalance reste volontairement dans 0.2.1, donc ce split ne retire pas la capacité réseau minimale dont Wallet Desk aura besoin.

8. Périmètre exact de la 0.2.1 réduite

0.2.1 doit clôturer :

  1. création de ksp-onchain-transport-lib ;
  2. settings publics Transport et validation ;
  3. JSON-RPC 2.0 request/result/error envelopes ;
  4. registre exhaustif des 52 courantes + 14 historiques deprecated ;
  5. metadata méthode + forme de requête + runtime + retry class ;
  6. endpoint client HTTP async ;
  7. pool logique, rôles ouverts, capabilities/request kinds, priorité et fallback ;
  8. RPS/burst/concurrence/cooldown ;
  9. timeout et retry transport borné ;
  10. mapping vers ksp_core_lib::Error ;
  11. observabilité via ksp-logging-lib ;
  12. 4 méthodes typées canari ;
  13. std.transport + schema + exemple + adapter Config -> settings Transport ;
  14. tests/fixtures/canaries/smoke opt-in ;
  15. README.md / USAGE.md ;
  16. preuve que les familles restantes sont explicitement reportées, sans perdre l'inventaire.

9. Contrats publics Transport décidés

Les noms pourront être ajustés seulement si une contrainte Rust concrète apparaît, mais l'ownership et la sémantique sont fixés.

9.1 Settings principaux

pub struct HttpTransportSettings {
    pub endpoints: Vec<HttpEndpointSettings>,
    pub retry: HttpRetrySettings,
}

pub struct HttpEndpointSettings {
    pub name: String,
    pub enabled: bool,
    pub provider: String,
    pub cluster: String,
    pub url: HttpEndpointUrl,
    pub connect_timeout: Duration,
    pub request_timeout: Duration,
    pub max_idle_connections_per_host: Option<usize>,
    pub roles: Vec<HttpEndpointRoleSettings>,
}

pub struct HttpEndpointRoleSettings {
    pub role: HttpRoleName,
    pub enabled: bool,
    pub request_kinds: Vec<HttpRequestKind>,
    pub priority: u32,
    pub limits: HttpRoleLimits,
}

pub struct HttpRoleLimits {
    pub requests_per_second: Option<NonZeroU32>,
    pub burst_capacity: Option<NonZeroU32>,
    pub max_concurrent_requests: Option<NonZeroU32>,
    pub pause_after_rate_limit: Option<Duration>,
}

pub struct HttpRetrySettings {
    pub max_retries: u32,
    pub initial_backoff: Duration,
    pub max_backoff: Duration,
}

Décisions :

  • Transport utilise Duration; Config traduit ses scalaires *_ms vers ce contrat runtime ;
  • provider, cluster, role et request_kind restent des descriptors ouverts/newtypes validés, pas des enums fermées ;
  • * reste un wildcard valide pour request_kinds ;
  • URL est encapsulée dans un type KSP avec Debug redacted ; reqwest::Url n'est pas un type public du contrat ;
  • aucune lecture directe de l'environnement dans Transport ;
  • aucun champ WS/gRPC anticipé.

9.2 Validation minimale

Refuser au minimum :

  • nom endpoint vide/dupliqué ;
  • URL non HTTP(S) ou invalide ;
  • aucun endpoint activé ;
  • rôle vide/dupliqué sur un endpoint ;
  • request kind vide ;
  • limites incohérentes (burst sans RPS, zéro lorsque la valeur est présente, backoff max < initial, etc.) ;
  • timeout nul lorsque la sémantique exige une deadline positive.

Un endpoint enabled = false reste valide dans le document/snapshot mais n'est jamais candidat à la sélection.

10. Descriptor central des méthodes

Contrat conceptuel :

pub struct HttpRpcMethodDescriptor {
    pub method: &'static str,
    pub category: HttpRpcCategory,
    pub request_kind: &'static str,
    pub documentation_status: RpcDocumentationStatus,
    pub runtime_status: RpcRuntimeStatus,
    pub operation_kind: RpcOperationKind,
    pub transport_retry_class: TransportRetryClass,
    pub replacement: Option<&'static str>,
}

pub enum RpcDocumentationStatus {
    Stable,
    Deprecated,
    Unstable,
}

pub enum RpcRuntimeStatus {
    Supported,
    Removed,
}

pub enum RpcRequestFormStatus {
    Stable,
    Deprecated,
}

pub enum RpcOperationKind {
    Read,
    Simulation,
    WriteSubmission,
}

Le descripteur est la source unique pour :

  • nom JSON-RPC ;
  • routing/request kind ;
  • statut documentaire ;
  • statut runtime ;
  • warning deprecated/unstable ;
  • remplacement historique ;
  • politique de retry transport ;
  • canary de complétude.

Les warnings ne sont pas dispersés dans 52 méthodes.

11. JSON-RPC et API raw/générique

0.2.1 fournit les envelopes JSON-RPC 2.0 KSP :

request : jsonrpc, id, method, params
success : jsonrpc, id, result
failure : jsonrpc, id, error { code, message, data? }

Invariants :

  • jsonrpc doit être exactement 2.0 ;
  • l'id de réponse doit correspondre à la requête ;
  • result et error sont mutuellement exclusifs ;
  • une réponse invalide devient invalid_response/json_rpc_protocol, jamais un faux résultat ;
  • le data d'une erreur RPC peut être préservé comme serde_json::Value, mais n'est pas loggué massivement par défaut.

Une API raw/générique peut exister pour l'extensibilité/provider interop. Elle ne remplace pas la surface typée normative et n'est pas une preuve de couverture des releases 0.2.20.2.4.

Pour la surface standard connue, l'exécuteur consulte le registry. Une méthode runtime = Removed est refusée comme méthode standard au lieu d'être envoyée en prétendant qu'elle est supportée.

12. Pool, rôles, capabilities et sélection

12.1 Unité de pool

Le pool sélectionne un endpoint/client HTTP logique. Le pooling de sockets/keep-alive reste la responsabilité du client reqwest sous-jacent.

12.2 Algorithme de sélection

Pour une requête :

  1. déterminer le request_kind depuis le descriptor standard ou le caller raw ;
  2. filtrer endpoints disabled ;
  3. filtrer rôles disabled ;
  4. filtrer rôle exact + capability (request_kind ou *) ;
  5. exclure temporairement les candidats en cooldown/rate-limit ;
  6. ordonner par priority croissante ;
  7. round-robin équitable entre candidats du meilleur tier ;
  8. si capacité/concurrence indisponible, essayer les pairs puis le tier de priorité suivant ;
  9. si tous les candidats sont temporairement bloqués, attendre jusqu'au premier candidat admissible sans dépasser la deadline de requête ;
  10. si aucun endpoint ne peut satisfaire le rôle/méthode, retourner une erreur endpoint_selection structurée.

12.3 Concurrence et rate limit

Chaque couple endpoint/rôle possède son état runtime :

  • token bucket RPS/burst si configuré ;
  • semaphore de concurrence si configuré ;
  • cooldown après 429 ;
  • deadline commune de requête.

Aucune boucle active de health-check n'est ajoutée en 0.2.1. Le health est passif : succès/échecs récents, cooldown et état Enabled/Disabled/Available/Degraded/RateLimited dans des snapshots sûrs.

12.4 Thread-safety

Les clients/pools sont partageables entre tâches : Arc sur état commun, primitives Tokio pour concurrence asynchrone, atomics lorsque suffisants. Aucune mutex synchrone ne doit couvrir un await réseau.

13. Retry, backoff et timeout

13.1 Retry transport autorisé

Retry uniquement quand l'opération est classée retry-safe et qu'aucun résultat exploitable n'a été obtenu :

  • erreur de connexion clairement retryable ;
  • certaines erreurs HTTP provider temporaires ;
  • 429 avec cooldown/Retry-After ;
  • timeout pour les opérations read/simulation retry-safe.

Backoff exponentiel borné :

initial_backoff <= computed_backoff <= max_backoff
attempts <= max_retries

Retry-After peut allonger la pause dans la borne décidée par le transport ; aucune attente non bornée.

13.2 Write/submission

sendTransaction et requestAirdrop sont classés WriteSubmission / NeverAfterDispatch.

Le transport KSP ne renvoie pas automatiquement une transaction sur timeout ou erreur ambiguë après dispatch. Le paramètre Solana sendTransaction.maxRetries appartient au comportement du nœud RPC et ne devient pas la politique de retry HTTP KSP.

simulateTransaction reste une simulation et peut être retry-safe au niveau transport.

13.3 Retry métier interdit

Aucune décision du type « RPC application error => refaire l'opération métier » n'est introduite dans Transport.

14. Stratégie d'erreurs

Les erreurs utilisent ksp_core_lib::Error et des constantes ErrorCode::new("onchain_transport", ...) dans la crate Transport.

Codes candidats à stabiliser dans pre.002 :

invalid_settings
endpoint_selection_failed
http_connection_failed
http_request_failed
timeout
rate_limited
json_encode_failed
json_decode_failed
json_rpc_protocol_invalid
rpc_application_error
method_removed
invalid_response

Chaque erreur ajoute uniquement du contexte sûr : endpoint name/provider/cluster, méthode, rôle, attempt, code HTTP/RPC. L'URL complète et tout secret sont exclus des contextes/logs.

15. Ownership des modèles de réponse

15.1 Principe

Transport représente le wire nécessaire à l'appel et à sa future persistence RAW. Il ne produit pas CORE, DECODE ou SPECIALIZED.

15.2 Primitives communes

Introduire des types transport seulement lorsqu'ils ajoutent un invariant wire utile. Les champs dynamiques/évolutifs peuvent rester serde_json::Value aux frontières appropriées plutôt que de forcer une dépendance SDK massive.

Décisions :

  • RpcResponse<T> pour les réponses contextuelles ;
  • RpcContext avec slot/API version lorsque documenté ;
  • TokenAmount conservant amount: String, decimals, uiAmount: Option<f64>, uiAmountString ;
  • Account transport préservant encoding/data sans décodage Program ;
  • signatures/hash/identités comme wire string/newtype KSP, sauf bénéfice clair à utiliser une primitive ksp-core-lib déjà autorisée ;
  • getTransaction/getBlock : top-level typé + payloads encoding-dependent lossless/flexibles ;
  • distinction stricte JSON null vs champ absent lorsque le contrat le nécessite.

15.3 Dépendances SDK

Ne pas introduire solana-client ni un SDK client haut niveau pour obtenir des DTOs. Une dépendance Solana additionnelle devra répondre à un besoin wire précis et respecter le firewall KSP.

16. Config standard Transport et adapter

16.1 Identifiants retenus

Selon les conventions de ksp-config-lib :

FILE_ID_STD_TRANSPORT              = "cfg.std.transport"
FILE_ID_SCHEMA_STD_TRANSPORT       = "schema.std.transport"
DEFAULT_STD_TRANSPORT_FILENAME     = "std.transport.json"
DEFAULT_STD_TRANSPORT_SCHEMA_FILENAME = "std.transport.schema.json"

Fichiers :

config/std.transport.json
config/schemas/std.transport.schema.json
config/examples/std.transport.example.json

16.2 Forme candidate du document

{
  "format_version": 1,
  "default_profile": "devnet_public",
  "retry": {
    "max_retries": 2,
    "initial_backoff_ms": 100,
    "max_backoff_ms": 2000
  },
  "profiles": [
    {
      "profile_id": "devnet_public",
      "http_endpoints": [
        {
          "name": "solana_devnet_public",
          "enabled": true,
          "provider": "solana-public",
          "cluster": "devnet",
          "url": "https://api.devnet.solana.com",
          "connect_timeout_ms": 5000,
          "request_timeout_ms": 15000,
          "max_idle_connections_per_host": 8,
          "roles": [
            {
              "role": "default",
              "enabled": true,
              "request_kinds": ["*"],
              "priority": 100,
              "limits": {
                "requests_per_second": null,
                "burst_capacity": null,
                "max_concurrent_requests": 8,
                "pause_after_rate_limit_ms": 1000
              }
            }
          ]
        }
      ]
    }
  ]
}

Le moteur Config existant résout profil + environnement. L'adapter transforme ensuite ce document effectif vers HttpTransportSettings et convertit les millisecondes en Duration.

16.3 Secrets/env

Transport ne lit jamais l'environnement.

Le schema autorise une URL résolue par le mécanisme de placeholders Config existant. La sensibilité KSP_SECRET_* doit être propagée/redacted dans l'adapter et les snapshots.

Aucune nouvelle variable .env.example n'est nécessaire en pre.001. Le profil standard peut utiliser l'URL publique Devnet sans secret. Une variable provider réellement consommée sera ajoutée dans la même tranche que son usage réel, pas par anticipation.

16.4 Config Desk

Aucune UI Transport dédiée. Le document reste éditable via le moteur générique Config Desk existant.

17. Dépendances externes candidates

Audit du 2026-08-17 :

  • reqwest courant observé : 0.13.4 ;
  • tokio courant observé : 1.53.1, tandis que le workspace utilise déjà ^1.53 ;
  • serde / serde_json sont déjà des dépendances workspace ^1.0 ;
  • bot3 utilisait également base64 et bs58, à différer jusqu'au premier besoin d'encoding explicite.

Décision concrétisée par pre.002 :

reqwest = ^0.13, default-features = false au workspace
serde.workspace = true
serde_json.workspace = true
ksp-core-lib path/workspace
ksp-logging-lib path/workspace

pre.002 utilise reqwest uniquement pour le parsing/validation robuste de HttpEndpointUrl; aucune requête réseau n'est encore créée. Conformément à RUST-DEP-001 / RUST-DEP-003, aucune feature TLS/JSON/client ni dépendance Tokio locale n'est activée par anticipation. Les features réellement nécessaires au client async sont décidées et ajoutées dans pre.003, lorsque le chemin de compilation HTTP existe. Le même principe reporte tokio à la première tranche qui utilise effectivement ses primitives runtime/sync.

Ne pas ajouter :

solana-client
tokio-tungstenite
gRPC stack
futures-util uniquement pour anticipation live
base64/bs58 avant besoin concret
tracing direct

Les commandes cargo tree sont obligatoires dans la tranche qui ajoute effectivement reqwest.

18. Logging et observabilité

Target KSP :

ksp-onchain-transport-lib

Événements :

  • création client/pool ;
  • sélection endpoint/rôle ;
  • début/fin requête en debug/trace ;
  • retry/attempt ;
  • timeout ;
  • 429/cooldown/backoff ;
  • endpoint degraded/unavailable ;
  • RPC application error ;
  • forme deprecated/unstable utilisée ;
  • snapshots de santé importants.

Interdits par défaut :

  • URL complète si elle peut porter un token ;
  • API key/provider token ;
  • body massif ;
  • transaction complète ;
  • réponse complète.

Les erreurs reqwest utiles sont remappées/réémises via ksp-logging-lib; aucun target externe n'est activé globalement par Transport.

19. Architecture de tests

19.1 Unit tests

Sous unit_tests/ miroir de src/ :

  • settings validation ;
  • URL redaction ;
  • endpoint/role/request-kind matching ;
  • priority/fairness/fallback ;
  • limiter RPS/burst ;
  • max concurrent ;
  • cooldown ;
  • retry/backoff borné ;
  • timeout ;
  • JSON-RPC request/success/error/id mismatch ;
  • RPC error mapping ;
  • method/request-form status ;
  • warning path deprecated/unstable ;
  • aucune fuite de secret dans Debug/snapshot.

19.2 Tests par méthode

Chaque méthode de la matrice obtient dans sa release assignée au minimum :

  • sérialisation de request ;
  • désérialisation du succès ;
  • optional/null significatifs ;
  • erreur significative ;
  • configs/overloads pertinents.

Fixtures JSON déterministes, pas d'Internet pour les tests par défaut.

19.3 Smoke réseau opt-in

0.2.1 peut valider sur Devnet, de manière ignorée/opt-in :

getHealth
getVersion
getGenesisHash
getBalance

Le test obtient son endpoint depuis les mécanismes Config/fixtures de test ; Transport ne lit pas directement l'env.

19.4 Canaries architecturales

Automatiser autant que possible :

Transport -X-> Config
Transport -X-> Store
Transport -X-> Program
Transport -X-> tracing direct
registre current == 52 noms audités
registre deprecated historique == 14 noms audités
4 méthodes typed de 0.2.1 présentes
aucune méthode reportée déclarée typed-complete avant sa release

La canary de méthode utilise un inventaire statique versionné/audité ; elle ne scrape pas Internet pendant cargo test.

20. Hors périmètre confirmé de la 0.2.1 réduite

Explicitement reportés :

  • les 48 méthodes courantes non canari selon la matrice 0.2.20.2.4 ;
  • WebSocket Solana ;
  • LaserStream ;
  • Yellowstone gRPC ;
  • Wallet et Wallet Desk ;
  • Store/RAW persistence ;
  • Program/decoders/materializers ;
  • execution policy et orchestration métier ;
  • workers/jobs ;
  • Tauri Transport dédiée ;
  • off-chain/trading/ML.

Le report des 48 méthodes n'est pas une suppression de l'obligation exhaustive : elles restent listées nom par nom dans ce plan et réservées à des releases déjà numérotées.

21. Critères de clôture de la 0.2.1 réduite

La release peut devenir stable seulement si :

  • crate ksp-onchain-transport-lib propre ;
  • aucune dépendance vers Config/Store/Program/tracing direct ;
  • settings publics et validation documentés ;
  • JSON-RPC 2.0 et error mapping testés ;
  • registry 52 current + 14 historical exact ;
  • statuts centralisés et request-form deprecated supporté pour la foundation du mécanisme ;
  • pool/priority/fallback/limites/concurrence/timeout/retry testés ;
  • write retry policy inscrite dans les descriptors même si les méthodes write arrivent en 0.2.3 ;
  • snapshots/Debug ne révèlent pas les secrets ;
  • getBalance, getGenesisHash, getHealth, getVersion sont typés et testés ;
  • Config standard + schema + example + adapter fonctionnent dans le bon sens ;
  • README/USAGE expliquent API raw vs typed et limites de couverture de 0.2.1 ;
  • tests ciblés/workspace et cargo tree passent sur le poste de développement ;
  • prompt 0.2.2 — HTTP Accounts + Tokens + Cluster prêt dans la dernière prerelease ;
  • aucune méthode de la matrice n'est perdue du planning HTTP global.

22. Prévision souple des prereleases de la 0.2.1 réduite

Tranche Objectif
pre.001 audit KSP + bot3 + docs officielles, matrice 52+14, architecture, split et sizing
pre.002 réalisé : crate/workspace, codes erreur, settings/validation, JSON-RPC, descriptors/status, base Logging
pre.003 endpoint client + pool logique + rôles/capabilities + priorité/fairness/fallback + snapshots sûrs
pre.004 RPS/burst/concurrence/cooldown + timeout + retry/backoff + classification retry/no-resend
pre.005 méthodes canari getHealth, getVersion, getGenesisHash, getBalance + fixtures déterministes
pre.006 std.transport schema/document/example + registry Config + adapter Config -> Transport + sensibilité/env tests
pre.007 completeness/canaries, smoke opt-in, cargo tree, README/USAGE, docs finales, prompt 0.2.2, préparation rel.001

Ce découpage est révisable si une tranche dépasse le budget ; la release réduite, contrairement au scope initial, reste raisonnablement clôturable dans la session.

22.1 État après 0.2.1-pre.002

pre.002 matérialise la fondation sans ouvrir le client/pool de pre.003 :

  • nouvelle crate ksp-onchain-transport-lib, membre du workspace, workspace.package.version = 0.2.1-pre.2 ;
  • dépendances directes : ksp-core-lib, ksp-logging-lib, serde, serde_json, reqwest sans features par défaut ; aucune dépendance Config/Store/Program/tracing directe ;
  • settings runtime publics : URL redacted, provider/cluster/role/request-kind ouverts, endpoints/rôles/limites/retry et validation structurelle ;
  • douze codes d'erreur onchain_transport réservés/stabilisés selon la stratégie du §14 ;
  • JSON-RPC HTTP KSP : request numérique KSP, sérialisation, parse success/error, validation jsonrpc = 2.0, id exact et exclusivité result/error, avec null résultat préservé ;
  • Debug des requests/réponses n'expose pas les params, résultats ou payloads d'erreur distants par défaut ;
  • registre central exact de 52 méthodes current + 14 historiques, avec catégorie, request kind, statut documentaire/runtime, forme legacy, operation kind, retry class, remplacement et release de couverture ;
  • getTransaction et getBlock portent explicitement StableWithDeprecatedLegacy; sendTransaction et requestAirdrop portent WriteSubmission / NeverAfterDispatch;
  • contrôle central ensure_runtime_supported() : warning KSP pour surfaces non stables supportées, warning + method_removed pour les historiques supprimées ;
  • 40 tests Rust ajoutés (unitaires + intégration), dont redaction, invariants JSON-RPC, matrice 4/22/11/15 et canary de firewall du manifest.

Les éléments suivants restent volontairement à pre.003+ : construction reqwest::Client, clients logiques, pool, sélection/rôles/fallback, Tokio runtime/sync, TLS, rate limiting, concurrence et retry effectif.

23. Séquence 0.2.x recalibrée

0.2.1  HTTP transport foundation + 4 canaris
0.2.2  HTTP Accounts + Tokens + Cluster
0.2.3  HTTP Transactions
0.2.4  HTTP Blocks + Economics + compliance HTTP finale
0.2.5  wallet foundation (.kspwallet)
0.2.6  Wallet Desk
0.2.7  standard Solana WebSocket
0.2.8  Helius LaserStream WebSocket
0.2.9  Yellowstone gRPC standard foundation
0.2.10 off-chain price transport
0.2.11 price visualization desk
0.2.12 interface/wire foundation
0.2.13 program-api foundation

Le découpage 0.2.20.2.4 est un maximum nominal de trois sessions. Une session peut clôturer plusieurs releases successives si, après la clôture complète de chacune, le sizing de la suivante reste positif. Cette optimisation de session ne fusionne jamais les releases elles-mêmes.

Chaque release HTTP 0.2.20.2.4 commence par une revérification officielle temporelle de sa famille et de l'index global. Si Solana ajoute/supprime/change une méthode entre-temps, la matrice est mise à jour explicitement plutôt que de conserver aveuglément l'état du 2026-08-17.

24. Gate de sizing — réponse obligatoire

Question :

La release 0.2.1 peut-elle raisonnablement être entièrement clôturée dans cette session de chat
avec des prereleases de ~1520 minutes ?

Réponse pour le périmètre du prompt 006 :

NON.

Motif : 52 méthodes typed + 14 deprecated historiques + toute la foundation/résilience/Config/tests/docs constituent plusieurs releases cohérentes et non une seule release de session.

Réponse après split, pour la 0.2.1 réduite définie par ce plan :

OUI, raisonnablement.

La grosse implémentation ne doit commencer qu'à pre.002, sur ce périmètre réduit.

25. Validations de pre.001

Exécutées dans le sandbox :

  • lecture des sources internes obligatoires ;
  • inspection des manifests et contrats publics KSP ;
  • audit ciblé de l'archive bot3 et de ks-onchain-transport/Config historique ;
  • comparaison locale automatisée des 52 noms bot3 avec les 52 noms de l'index officiel audité : aucun manque/extra ;
  • consultation des sources officielles Solana/JSON-RPC/Agave ;
  • audit des versions candidates reqwest/tokio depuis leurs registres officiels ;
  • vérification de l'absence de .git dans l'archive KSP.

Non exécutées :

cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test --workspace
cargo tree ...

Le binaire cargo n'est pas disponible dans ce sandbox (cargo: command not found). Aucune réussite Cargo n'est donc déclarée. Aucune dépendance ni source Rust n'étant ajoutée dans pre.001, les cargo tree seront particulièrement utiles à pre.002, après ajout réel de reqwest.