Files
khadhroony-solana-project/docs/plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md
2026-08-24 20:48:30 +02:00

81 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.

État 0.2.1-rel.001 : clôturé stable. La foundation HTTP réduite est publiée après validation opérateur complète de pre.007, des graphes Cargo et du smoke Devnet opt-in. 0.2.2 devient la prochaine release active.

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.1.1 Politique client concrétisée par pre.003

Chaque endpoint construit un reqwest::Client partageable qui conserve le pooling de sockets sous-jacent. Le builder KSP applique les connect_timeout, request_timeout et max_idle_connections_per_host déjà possédés par les settings.

Décisions de sécurité/déterminisme :

  • backend HTTPS : feature reqwest/rustls explicite ;
  • redirects automatiques désactivés : une URL provider éventuellement porteuse de credential n'est jamais redirigée implicitement vers une autre destination ;
  • proxies système/environnement implicites désactivés via le builder reqwest; une future prise en charge de proxy devra être un contrat Config/Transport explicite ;
  • User-Agent KSP stable : ksp-onchain-transport-lib/<version> ;
  • URL conservée uniquement dans les settings privés du client logique et absente des snapshots/Debug publics.

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 utilisait reqwest uniquement pour le parsing/validation robuste de HttpEndpointUrl. pre.003 crée réellement les clients HTTP logiques et active donc localement la feature rustls de reqwest 0.13 dans ksp-onchain-transport-lib, tandis que le workspace conserve default-features = false sans feature dusage globale. Aucune feature json n'est nécessaire : KSP possède déjà son encodage JSON-RPC via serde_json. Aucune dépendance Tokio directe n'est ajoutée tant que pre.004 n'utilise pas effectivement ses primitives de concurrence/attente.

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

Ce target est possédé explicitement par src/constants.rs via pub(crate) const TRACING_TARGET: &str = "ksp-onchain-transport-lib"; les appels de logging utilisent crate::TRACING_TARGET conformément à DEP-LOG-010/011. env!("CARGO_PKG_NAME") reste réservé aux usages où lidentité Cargo est réellement la donnée recherchée, par exemple le User-Agent HTTP.

É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.

Pendant le développement actif jusqu'à pre.006, std.logging.json autorisait debug uniquement pour ksp-onchain-transport-lib et routait ces événements vers un fichier dédié. pre.007 applique KSP-APP-031 : le target et le sink dédié reviennent à info, avec le fichier transport/onchain/ksp-onchain-transport.log. La console et file.all.info restent également à info. Un développement/correctif futur peut relever temporairement uniquement ce target/sink via Config Desk conformément à DEP-LOG-012.

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 réalisé : endpoint client + pool logique + rôles/capabilities + priorité/fairness/fallback + snapshots sûrs
pre.004 réalisé : RPS/burst/concurrence/cooldown + deadline commune + retry/backoff + classification retry/no-resend
pre.005 réalisé : exécution HTTP JSON-RPC + getHealth, getVersion, getGenesisHash, getBalance + fixtures déterministes + centralisation des canaries workspace dans Core
pre.006 réalisé : std.transport schema/document/example + registry Config + adapter Config -> Transport + sensibilité/provenance/env tests
pre.007 réalisé et validé : completeness/canaries, smoke opt-in, README/USAGE, docs finales, prompt 0.2.2, validations Cargo et cargo tree

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 annoncés pour pre.003 dans cet état historique sont désormais concrétisés au §22.2 ; rate limiting, concurrence et retry effectif restent reportés.

22.2 État après 0.2.1-pre.003

pre.003 matérialise la première couche de routing HTTP sans encore exécuter de JSON-RPC :

  • workspace.package.version = 0.2.1-pre.3 ;
  • reqwest reste default-features = false et active uniquement rustls pour rendre les endpoints HTTPS réellement constructibles ;
  • HttpEndpointClient encapsule un reqwest::Client, applique connect/request timeout et limite idle-per-host, désactive redirect et proxy système implicites, et n'expose jamais l'URL dans Debug/snapshot ;
  • HttpEndpointSnapshot, HttpEndpointRoleSnapshot et HttpTransportPoolSnapshot exposent uniquement identité/provider/cluster/routing/status sûrs ;
  • HttpTransportPool valide les settings puis construit un client logique par endpoint ;
  • sélection exacte rôle + capability, wildcard *, priorité globale croissante et round-robin par rôle/request-kind dans le meilleur tier ;
  • endpoint ou rôle disabled exclus ; un tier inférieur devient donc fallback lorsqu'aucun candidat du tier supérieur n'est sélectionnable ;
  • select_for_method dérive la capability depuis le registre RPC central et refuse une méthode historique Removed avant routing ;
  • aucune mutex synchrone ne couvre un await réseau : le seul verrou actuel protège brièvement les curseurs de fairness, avant toute I/O ;
  • le contrat d'availability réserve Disabled, Available, Degraded, RateLimited; pre.003 ne produit que les deux premiers, les transitions runtime appartenant à pre.004.
  • la suite Transport compte désormais 53 tests déclarés, dont les nouvelles preuves de redaction client/pool, priorité, fairness, fallback, capability et contrat public du pool.

Restent volontairement à pre.004 : token bucket RPS/burst, semaphore de concurrence, cooldown/429, deadline effective, retry/backoff et mutations passives Degraded/RateLimited.

22.3 État après 0.2.1-pre.004

pre.004 matérialise la résilience runtime du pool sans encore exécuter les quatre méthodes JSON-RPC canari :

  • workspace.package.version = 0.2.1-pre.4 ;
  • limiteur token-bucket par couple endpoint/rôle avec RPS et burst ; lorsque RPS est configuré sans burst explicite, la capacité initiale dérive d'une seconde de RPS ;
  • semaphore Tokio par rôle pour max_concurrent_requests, avec permit détenu pendant la durée de l'admission/exécution et notification des waiters à la libération ;
  • cooldown par rôle après rate-limit provider, utilisant la valeur configurée ou un fallback runtime borné ; un Retry-After déjà résolu en durée peut prolonger ce cooldown dans une borne défensive ;
  • sélection runtime par priorité puis round-robin, avec tentative des pairs et tiers inférieurs lorsqu'un candidat est temporairement bloqué par RPS, cooldown ou concurrence ;
  • si tous les candidats sont temporairement bloqués, attente du premier signal/candidat admissible sans dépasser une deadline commune ; par défaut, cette deadline utilise le plus petit request_timeout des endpoints structurellement compatibles ;
  • snapshots sûrs enrichis avec availability de rôle, limites, requêtes en vol, cooldown restant et compteurs success/failure/rate-limit, sans URL ni secret ;
  • transitions passives Available -> Degraded/RateLimited sur observations runtime et retour Degraded -> Available après succès ;
  • policy centralisée evaluate_transport_retry() : backoff exponentiel borné, budget max_retries, causes transport explicitement retryables, RPC application errors hors retry, et respect strict de TransportRetryClass::NeverAfterDispatch pour empêcher un resend automatique après dispatch ambigu ;
  • après pre.004-fix.001/.002, les features dusage sont activées localement par crate : Transport porte reqwest/rustls, serde/derive, tokio/macros+sync+time et tokio/rt seulement en dev ; le root conserve version/default-features sans activation de features dusage ;
  • la suite Transport compte désormais 72 tests déclarés, avec preuves supplémentaires sur limiter, concurrence, cooldown, deadline, fallback runtime, santé passive, policy de retry et consommation publique de l'admission async.

La tranche ne parse pas encore elle-même le header HTTP Retry-After et n'exécute pas de POST JSON-RPC : ces signaux seront raccordés à l'exécuteur HTTP avec les méthodes canari de pre.005.

Restent à pre.005 : exécution HTTP JSON-RPC réelle et wrappers typés getHealth, getVersion, getGenesisHash, getBalance, avec fixtures déterministes et raccordement des erreurs HTTP/429/timeout à la résilience maintenant disponible.

22.4 État après 0.2.1-pre.005

pre.005 matérialise la première exécution réseau HTTP complète et les quatre canaris typés de la release :

  • workspace.package.version = 0.2.1-pre.5 ;
  • exécuteur générique execute_standard_rpc : allocation d'id JSON-RPC KSP, admission via pool, POST application/json, deadline commune, mapping connexion/timeout/status HTTP, parsing JSON-RPC et mise à jour de santé passive ;
  • HTTP 429 raccordé au cooldown de rôle et à la policy de retry avec parsing défensif de Retry-After sous forme delta-seconds ; statuts temporaires 408/500/502/503/504 raccordés au retry borné ;
  • les retries réacquièrent capacité RPS/concurrence et restent bornés par la même deadline ; la classification NeverAfterDispatch reste centralisée pour empêcher les futurs write/submission de se resoumettre après ambiguïté ;
  • wrappers typés getHealth, getGenesisHash, getVersion, getBalance, avec ksp_core_lib::Pubkey, commitment/minContextSlot optionnels, DTO de contexte/balance/version et validation de forme ;
  • fixtures JSON déterministes et serveur HTTP local de tests : les canaris prouvent le POST réel et les formes request/response ; tests supplémentaires sur récupération après 429 et timeout reqwest ;
  • les deux canaries de dépendances générales quittent ksp-onchain-transport-lib/tests/dependency_boundary.rs et sont centralisées sous ksp-core-lib/tests/workspace_dependencies.rs, conformément à DEP-CARGO-007 ;
  • Transport compte désormais 78 tests déclarés ; Core porte 2 canaries workspace supplémentaires dans sa surface d'intégration.

pre.005-fix.001 normalise ensuite le contrat de target KSP : Transport et Config possèdent désormais leur TRACING_TARGET principal dans src/constants.rs, les targets comportementaux ne dépendent plus de env!("CARGO_PKG_NAME") ni de littéraux dispersés, et une canarie workspace Core protège cette convention. Lusage Cargo de CARGO_PKG_NAME pour le User-Agent Transport reste volontaire et autorisé.

Restent à pre.006 : document/schema/exemple std.transport, enregistrement Config, adapter Config -> Transport et tests de sensibilité/provenance/env.

22.5 État après 0.2.1-pre.006

pre.006 matérialise la frontière de configuration standard du Transport sans créer de dépendance inverse :

  • workspace.package.version = 0.2.1-pre.6 ;
  • config/std.transport.json et config/schemas/std.transport.schema.json deviennent des ressources Config gérées, avec cfg.std.transport / schema.std.transport dans le registry ;
  • le document standard possède retry en global et des endpoints par profil ; devnet_public est le profil autonome par défaut et mainnet_public reste sélectionnable explicitement ;
  • config/examples/std.transport.example.json illustre un pool mixte public/privé, y compris une URL complète provenant dun KSP_SECRET_* ;
  • .env.example inventorie les deux overrides publics standard et loverride secret dexemple sans committer de credential réel ;
  • ksp-config-lib dépend désormais de ksp-onchain-transport-lib dans la direction autorisée Config -> Transport, tandis que le firewall Transport -> Config reste inchangé ;
  • ConfigDocumentEngine::load_resolved_transport_config sélectionne le profil, résout lenvironnement, convertit les scalaires *_ms en Duration, construit les rôles/limites/endpoints puis délègue la validation finale à HttpTransportSettings::validate() ;
  • ResolvedTransportConfig conserve le profil, la provenance détaillée et la projection safe, et expose les settings runtime réels ; son Debug nexpose pas les URLs secrètes ;
  • les tests couvrent le document committé, les origines global/profile, la precedence process > .env, la provenance JSON Pointer, la redaction KSP_SECRET_* et léchec dune URL secrète invalide sans fuite de canary ;
  • DEP-TRANSPORT-005 explicite maintenant que Config peut dépendre des crates Transport pour posséder les adapters, jamais linverse.

pre.006-fix.002, déclenché par laudit complet du workspace avant clôture, corrige une fuite diagnostique potentielle : les reqwest::Error attachées à ksp_core_lib::Error sont désormais neutralisées par without_url() avant with_source, avec une canarie timeout portant un secret dans la query de lendpoint. Le même audit remet aussi en conformité les fins de ligne des fichiers courants concernés par GEN-FILE-005 et corrige le rustdoc Transport devenu obsolète après lintroduction de ladapter Config -> Transport. Les écarts purement documentaires sans impact code/config restent volontairement réservés à pre.007.

22.6 État candidat après 0.2.1-pre.007

pre.007 ferme le périmètre de développement de la foundation sans ajouter de méthode HTTP typed au-delà des quatre canaris :

  • workspace.package.version = 0.2.1-pre.7 ;
  • revérification officielle du 2026-08-17 : lindex Solana HTTP courant expose toujours 52 méthodes et la navigation Deprecated conserve les 14 noms historiques audités ;
  • deux canaries dintégration publiques figent la partition 52 current / 14 historical / 4-22-11-15 et le set exact des quatre canaris 0.2.1 ;
  • la candidate déclare 80 tests Transport et 114 tests Config, dont un unique smoke Devnet Config ignored ;
  • un smoke Devnet ignored sous ksp-config-lib valide de manière opt-in la chaîne Config -> devnet_public -> Transport -> getHealth/getGenesisHash/getVersion/getBalance, sans lecture denvironnement dans Transport ; ce placement est une exception transitoire et non un modèle pour les futurs smokes Config + autre crate ;
  • ksp-onchain-transport-lib/README.md et USAGE.md documentent frontières, API raw vs typed, résilience, sécurité, Config et utilisation ;
  • docs/validation/003-V0_2_1_ONCHAIN_HTTP.md devient la matrice durable de clôture ;
  • le niveau de référence du sink Transport dédié revient de debug à info avant stable ;
  • les écarts documentaires résiduels issus de laudit complet sont normalisés : convention bindings/gen, README Config et inventaire composant HTTP ;
  • prompts/007-V0_2_2_START_PROMPT.md prépare 0.2.2 — HTTP Accounts + Tokens + Cluster avec un nouvel audit officiel et gate de sizing ;
  • CHANGELOG.md est mis à jour dans rel.001 avec la synthèse stable 0.2.1.

Les validations Cargo, cargo tree et le smoke Devnet opt-in de cette candidate ont été exécutés avec succès sur le dépôt canonique. rel.001 reste strictement publicationnel : version stable, statuts ROADMAP/plan/validation, entrée CHANGELOG et delta de release. Le commit v0.2.1-rel.001 doit être validé avant création du tag stable v0.2.1.

22.7 Clôture stable 0.2.1-rel.001

La publication stable est autorisée par les preuves opérateur du 2026-08-17 : cargo fmt --all, cargo check --workspace, cargo clippy --workspace --all-targets, tests ciblés Transport/Config/Core/Config Desk, cargo test --workspace, graphes cargo tree Transport et Config, puis smoke Devnet explicite. Le smoke live a atteint les quatre canaris avec le profil devnet_public.

TODO architectural conservé pour la suite : ksp-config-lib ne doit jamais devenir la destination générale des smoke tests cross-crates. Le test actuel Config -> Transport -> Devnet reste temporairement sous Config uniquement parce qu'aucune crate/surface d'intégration ou d'orchestration n'existe encore ; il devra migrer dès qu'une telle surface sera disponible, et les futurs smokes Config + autre crate devront viser cette surface dédiée.

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.