v0.2.2-pre.001

This commit is contained in:
2026-08-18 06:41:41 +02:00
parent 6c3ecf1f18
commit 9059a2dc45
7 changed files with 690 additions and 9 deletions

View File

@@ -1,12 +1,12 @@
# file: Cargo.toml # file: Cargo.toml
# version: 109 # version: 110
[workspace] [workspace]
resolver = "3" resolver = "3"
members = ["crates/ksp-app-config-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-logging-lib", "crates/ksp-onchain-transport-lib"] members = ["crates/ksp-app-config-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-logging-lib", "crates/ksp-onchain-transport-lib"]
[workspace.package] [workspace.package]
version = "0.2.1" version = "0.2.2-pre.1"
edition = "2024" edition = "2024"
license = "MIT" license = "MIT"
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"

View File

@@ -1,5 +1,5 @@
<!-- file: ROADMAP.md --> <!-- file: ROADMAP.md -->
<!-- version: 34 --> <!-- version: 35 -->
# Roadmap KSP # Roadmap KSP
@@ -46,7 +46,7 @@ Le roadmap décrit les objectifs à atteindre et les grandes étapes prévues. U
### Releases fonctionnelles décidées/pressenties ### Releases fonctionnelles décidées/pressenties
- [X] `0.2.1`**HTTP transport foundation réduite par le gate `pre.001`** : crate/settings/JSON-RPC/registry 52 current + 14 deprecated historiques, pool/rôles/limites/retry, Config adapter, documentation et 4 méthodes typées canari (`getBalance`, `getGenesisHash`, `getHealth`, `getVersion`) publiés stables. - [X] `0.2.1`**HTTP transport foundation réduite par le gate `pre.001`** : crate/settings/JSON-RPC/registry 52 current + 14 deprecated historiques, pool/rôles/limites/retry, Config adapter, documentation et 4 méthodes typées canari (`getBalance`, `getGenesisHash`, `getHealth`, `getVersion`) publiés stables.
- [ ] `0.2.2` — Compléter HTTP Accounts + Tokens + Cluster : 5 méthodes Accounts restantes + 5 Tokens + 12 Cluster restantes, soit 22 méthodes. - [/] `0.2.2` — Compléter HTTP Accounts + Tokens + Cluster : 5 méthodes Accounts restantes + 5 Tokens + 12 Cluster restantes, soit 22 méthodes ; `pre.001` confirme le périmètre officiel et un sizing positif.
- [ ] `0.2.3` — Compléter les 11 méthodes HTTP Transactions, y compris write/submission technique avec politique no-resend ambigu. - [ ] `0.2.3` — Compléter les 11 méthodes HTTP Transactions, y compris write/submission technique avec politique no-resend ambigu.
- [ ] `0.2.4` — Compléter les 10 méthodes HTTP Blocks + 5 Economics et exécuter la compliance finale de toute la surface HTTP 52 current + 14 deprecated historiques. - [ ] `0.2.4` — Compléter les 10 méthodes HTTP Blocks + 5 Economics et exécuter la compliance finale de toute la surface HTTP 52 current + 14 deprecated historiques.
- [ ] `0.2.5` — Introduire `ksp-wallet-lib`, le format `.kspwallet`, la gestion sûre des secrets et une architecture d'import/export extensible ; exclure `WalletPolicy`. - [ ] `0.2.5` — Introduire `ksp-wallet-lib`, le format `.kspwallet`, la gestion sûre des secrets et une architecture d'import/export extensible ; exclure `WalletPolicy`.

180
deltas/0.2.2/pre.001.md Normal file
View File

@@ -0,0 +1,180 @@
<!-- file: deltas/0.2.2/pre.001.md -->
<!-- version: 1 -->
# Delta `0.2.2-pre.001` — réaudit HTTP Accounts/Tokens/Cluster, DTOs et sizing
## Base requise
Release stable attendue :
```text
v0.2.1
```
L'archive KSP fournie porte `workspace.package.version = "0.2.1"`. Elle ne contient pas `.git`; le tag `v0.2.1` n'est donc pas revérifiable
localement depuis le zip.
## Objectif
Exécuter la première tranche obligatoire de `0.2.2` sans implémentation fonctionnelle lourde : relire les contrats KSP, réauditer la surface
HTTP Solana officielle actuelle, confirmer la matrice des 22 méthodes Accounts/Tokens/Cluster, cadrer les DTOs wire, évaluer les dépendances et
trancher le gate de sizing.
## Version Cargo
Conformément à `VER-ID-009`, la prerelease non-fix synchronise le signal technique :
```text
0.2.1 -> 0.2.2-pre.1
```
Aucune source Rust, dépendance Cargo ou configuration runtime n'est modifiée dans cette tranche.
## Résultats principaux
- index HTTP Solana courant réaudité : **52 méthodes** ;
- navigation Deprecated officielle : **14 méthodes historiques**, inchangées ;
- familles de la release : Accounts `6 = 1 acquis + 5 ciblés`, Tokens `5 = 5 ciblés`, Cluster `15 = 3 acquis + 12 ciblés` ;
- aucune méthode ajoutée/supprimée/déplacée détectée depuis l'audit `0.2.1` du 2026-08-17 ;
- les 22 méthodes ciblées restent des méthodes courantes non marquées Deprecated/Unstable et les descriptors KSP restent `Read + RetrySafe` ;
- `getMultipleAccounts` conserve la limite documentée de 100 adresses ;
- `getSlotLeaders` conserve la limite documentée `1..=5000` ;
- `getLargestAccounts` et `getProgramAccounts` documentent toujours `sortResults` ;
- `getProgramAccounts` conserve sa réponse bare par défaut et contextualisée avec `withContext=true` ;
- la source primaire Agave confirme trois filtres Program Accounts (`dataSize`, `memcmp`, `tokenAccountState`), 4 filtres max et 128 octets décodés max pour `memcmp` ;
- le wire Account requiert une union pour `data`, y compris le fallback `jsonParsed -> [base64]`, et `space` reste nullable ;
- `TokenAmount.uiAmount` reste nullable ;
- `getHighestSnapshotSlot` conserve `incremental: null` et la source officielle Agave confirme une erreur `NoSnapshot` en absence de snapshot ;
- `getLeaderSchedule` conserve son overload slot/config particulier ;
- `getVoteAccounts` conserve `current/delinquent` et les epoch credits triples; la source Agave courante borne cet historique RPC à 5 entrées par validator.
## Gate de sizing
Question obligatoire :
```text
Les 22 wrappers typés + DTOs partagés + tests + documentation peuvent-ils être clôturés proprement dans cette session ?
```
Réponse :
```text
OUI.
```
Aucun split de release n'est nécessaire. Le plan conserve `0.2.2` à 22 méthodes et répartit le travail sur DTOs communs, Accounts, Tokens,
Cluster simple, Cluster schedule/slot/vote puis clôture. Si une tranche réelle dépasse le budget KSP, elle sera scindée par une prerelease
supplémentaire sans déplacer de méthode hors `0.2.2`.
## Décisions prises
- conserver exactement la partition `4 / 22 / 11 / 15` de `0.2.1``0.2.4` ;
- ne pas reconstruire un transport par famille ; tous les wrappers passent par descriptor + `execute_standard_rpc` ;
- mutualiser `SolanaCommitment` et `SolanaRpcContext` sans casser les réexports `0.2.1` ;
- représenter Account data comme une forme wire discriminée, sans décodage Program/SPL ;
- conserver `jsonParsed.parsed` comme `serde_json::Value` dans Transport ;
- utiliser `ksp_core_lib::Pubkey` dans les DTOs publics, avec wire structs privés puis conversion explicite ;
- représenter le selector Token comme une union exclusive `mint` / `programId` ;
- représenter le résultat `getProgramAccounts` comme bare ou contextualisé selon `withContext` ;
- conserver les endpoints de `getClusterNodes` comme chaînes wire optionnelles au contrat public ;
- conserver les `null` documentés (`Account`, `space`, `uiAmount`, `transactionCount`, snapshot incremental, leader schedule) ;
- ne pas modifier Config : le contrat `std.transport` existant suffit ;
- ne pas ajouter `base64`, `bs58`, SPL, `solana-client` ou SDK RPC haut niveau à `pre.001`; les formes encodées `memcmp` peuvent rester des chaînes wire tant quaucun décodage local nest requis.
## Prévision de travail
```text
pre.001 audit officiel + matrice + DTOs + dépendances + sizing
pre.002 primitives/configs/results partagés + fixtures de base
pre.003 5 Accounts + tests
pre.004 5 Tokens + tests
pre.005 Cluster simple (7 méthodes) + tests
pre.006 Cluster schedule/slot/vote (5 méthodes) + tests
pre.007 canaries + smoke opt-in si utile + docs + prompt 0.2.3 + préparation stable
```
Une prerelease supplémentaire reste autorisée si le budget réel d'une tranche l'exige.
## Fichiers ajoutés
```text
docs/plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md
deltas/0.2.2/pre.001.md
```
## Fichiers modifiés
```text
Cargo.toml
ROADMAP.md
docs/000-README.md
docs/plans/000-README.md
docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md
```
## Fichiers supprimés
Aucun.
## Fichiers volontairement inchangés
```text
CHANGELOG.md
docs/plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md
docs/validation/003-V0_2_1_ONCHAIN_HTTP.md
crates/ksp-onchain-transport-lib/src/**
crates/ksp-onchain-transport-lib/unit_tests/**
crates/ksp-onchain-transport-lib/tests/**
crates/ksp-config-lib/src/transport.rs
config/std.transport.json
config/schemas/std.transport.schema.json
```
Les deltas `0.2.1` restent historiques et ne sont pas réécrits.
## Validations exécutées
- relecture des sources KSP obligatoires du prompt `0.2.2` ;
- inspection de l'archive stable KSP fournie et de la foundation Transport `0.2.1` ;
- confirmation locale que le registry assigne déjà exactement les 22 méthodes ciblées à `HttpRpcCoverageRelease::V0_2_2` ;
- confirmation locale que ces 22 descriptors sont `Stable / Supported / Stable`, `Read`, `RetrySafe` ;
- consultation de l'index HTTP Solana officiel courant et des 22 pages de méthodes ciblées ;
- consultation de la navigation Deprecated officielle courante ;
- consultation de `Solana RPC JSON Structures` pour Account data et TokenAmount ;
- consultation des sources Agave `v3.1.8` liées par les pages officielles pour les ambiguïtés Account, filters/memcmp, cardinalités RPC, largest accounts, snapshot, leader schedule,
cluster node et vote accounts ;
- contrôle documentaire de la matrice `52 current / 14 historical / 4+22+11+15` ;
- contrôle de l'absence de nouvelle dépendance ou de besoin Config dans le design de `pre.001`.
## Validations non exécutées
Le sandbox courant ne fournit pas le binaire `cargo` (`command -v cargo` ne retourne aucun chemin). Les validations Cargo suivantes n'ont donc pas
été exécutées ici et doivent être rejouées sur le checkout de développement avant commit :
```bash
cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-onchain-transport-lib
```
Aucun `cargo tree` n'est nécessaire dans cette tranche car aucune dépendance ni feature n'a changé. Les quatre vues `cargo tree` du prompt restent
obligatoires dès qu'une prerelease change une dépendance/feature et à la clôture.
L'archive KSP fournie ne contient pas `.git`; le commit attendu après application et validations suit `VER-GIT-001` :
```text
v0.2.2-pre.001
```
## Questions ouvertes
Aucune question bloquante pour `pre.002`.
Les détails exacts de nommage Rust des DTOs restent ajustables pendant leur implémentation, mais les invariants wire et frontières fixés par le
plan `009` ne doivent pas être relâchés pour simplifier artificiellement les wrappers.
## Suite
`0.2.2-pre.002` : introduire les primitives/configs/results partagés, mutualiser Context/Commitment, fixer les conversions wire et installer les
fixtures déterministes communes avant les wrappers Accounts.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/000-README.md --> <!-- file: docs/000-README.md -->
<!-- version: 24 --> <!-- version: 25 -->
# Documentation KSP # Documentation KSP
@@ -40,7 +40,8 @@ docs/
│ ├── 005-V0_1_3_CONFIG_FOUNDATION_PLAN.md │ ├── 005-V0_1_3_CONFIG_FOUNDATION_PLAN.md
│ ├── 006-V0_1_4_CONFIG_DESKTOP_PLAN.md │ ├── 006-V0_1_4_CONFIG_DESKTOP_PLAN.md
│ ├── 007-V0_2_0_SERIES_PLANNING.md │ ├── 007-V0_2_0_SERIES_PLANNING.md
── 008-V0_2_1_ONCHAIN_HTTP_PLAN.md ── 008-V0_2_1_ONCHAIN_HTTP_PLAN.md
│ └── 009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md
├── validation/ ├── validation/
│ ├── 000-README.md │ ├── 000-README.md
│ ├── 001-V0_1_4_CONFIG_DESKTOP.md │ ├── 001-V0_1_4_CONFIG_DESKTOP.md
@@ -62,7 +63,7 @@ D'autres sous-répertoires seront ajoutés uniquement lorsque leur rôle aura é
## Documents de planification ## Documents de planification
Le plan historique de la phase fondatrice clôturée est conservé dans [`plans/001-V0_0_3_PLAN.md`](plans/001-V0_0_3_PLAN.md). La séquence active des premières releases fonctionnelles est définie dans [`plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md`](plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md). Le plan détaillé de la release stable `0.1.1` est conservé comme historique clôturé dans [`plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md`](plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.2` est conservé comme historique clôturé dans [`plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md`](plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.3 — Configuration foundation` est conservé comme historique clôturé dans [`plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md`](plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.4 — ksp-app-config-desk` est conservé comme historique clôturé dans [`plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md`](plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md), avec sa matrice finale [`validation/001-V0_1_4_CONFIG_DESKTOP.md`](validation/001-V0_1_4_CONFIG_DESKTOP.md). Son prompt d'ouverture historique reste [`../prompts/004-V0_1_4_START_PROMPT.md`](../prompts/004-V0_1_4_START_PROMPT.md). La release stable `0.2.0` clôt l'audit de bot3 et le découpage de la série. Son plan directeur est conservé comme historique clôturé dans [`plans/007-V0_2_0_SERIES_PLANNING.md`](plans/007-V0_2_0_SERIES_PLANNING.md), avec sa matrice finale [`validation/002-V0_2_0_SERIES_PLANNING.md`](validation/002-V0_2_0_SERIES_PLANNING.md). La release stable `0.2.1 — HTTP Solana foundation` a été ouverte par [`../prompts/006-V0_2_1_START_PROMPT.md`](../prompts/006-V0_2_1_START_PROMPT.md). Son gate de sizing et sa matrice exhaustive sont conservés dans [`plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md`](plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md), avec la validation finale [`validation/003-V0_2_1_ONCHAIN_HTTP.md`](validation/003-V0_2_1_ONCHAIN_HTTP.md), README/USAGE Transport et le smoke Devnet opt-in de composition Config -> Transport. Le prompt [`../prompts/007-V0_2_2_START_PROMPT.md`](../prompts/007-V0_2_2_START_PROMPT.md) devient le point d'entrée de `0.2.2`. Le plan historique de la phase fondatrice clôturée est conservé dans [`plans/001-V0_0_3_PLAN.md`](plans/001-V0_0_3_PLAN.md). La séquence active des premières releases fonctionnelles est définie dans [`plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md`](plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md). Le plan détaillé de la release stable `0.1.1` est conservé comme historique clôturé dans [`plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md`](plans/003-V0_1_1_CORE_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.2` est conservé comme historique clôturé dans [`plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md`](plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.3 — Configuration foundation` est conservé comme historique clôturé dans [`plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md`](plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md). Le plan détaillé de la release stable `0.1.4 — ksp-app-config-desk` est conservé comme historique clôturé dans [`plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md`](plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md), avec sa matrice finale [`validation/001-V0_1_4_CONFIG_DESKTOP.md`](validation/001-V0_1_4_CONFIG_DESKTOP.md). Son prompt d'ouverture historique reste [`../prompts/004-V0_1_4_START_PROMPT.md`](../prompts/004-V0_1_4_START_PROMPT.md). La release stable `0.2.0` clôt l'audit de bot3 et le découpage de la série. Son plan directeur est conservé comme historique clôturé dans [`plans/007-V0_2_0_SERIES_PLANNING.md`](plans/007-V0_2_0_SERIES_PLANNING.md), avec sa matrice finale [`validation/002-V0_2_0_SERIES_PLANNING.md`](validation/002-V0_2_0_SERIES_PLANNING.md). La release stable `0.2.1 — HTTP Solana foundation` a été ouverte par [`../prompts/006-V0_2_1_START_PROMPT.md`](../prompts/006-V0_2_1_START_PROMPT.md). Son gate de sizing et sa matrice exhaustive sont conservés dans [`plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md`](plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md), avec la validation finale [`validation/003-V0_2_1_ONCHAIN_HTTP.md`](validation/003-V0_2_1_ONCHAIN_HTTP.md), README/USAGE Transport et le smoke Devnet opt-in de composition Config -> Transport. Le prompt [`../prompts/007-V0_2_2_START_PROMPT.md`](../prompts/007-V0_2_2_START_PROMPT.md) devient le point d'entrée de `0.2.2`. Son `pre.001` ouvre le plan actif [`plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md`](plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md), qui confirme après réaudit officiel le périmètre de 22 wrappers typés et son découpage de travail.
`IDEAS.md` conserve les pistes et questions qui ne sont pas encore des engagements du roadmap ni des décisions architecturales. `IDEAS.md` conserve les pistes et questions qui ne sont pas encore des engagements du roadmap ni des décisions architecturales.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/000-README.md --> <!-- file: docs/plans/000-README.md -->
<!-- version: 31 --> <!-- version: 32 -->
# Plans KSP # Plans KSP
@@ -17,6 +17,7 @@ Un plan décrit le périmètre, les décisions déjà acquises, les questions ou
- [`006-V0_1_4_CONFIG_DESKTOP_PLAN.md`](006-V0_1_4_CONFIG_DESKTOP_PLAN.md) — plan historique clôturé de la release stable `0.1.4 — ksp-app-config-desk`, établi par `0.1.4-pre.001` puis consolidé jusqu'à `0.1.4-rel.001`. - [`006-V0_1_4_CONFIG_DESKTOP_PLAN.md`](006-V0_1_4_CONFIG_DESKTOP_PLAN.md) — plan historique clôturé de la release stable `0.1.4 — ksp-app-config-desk`, établi par `0.1.4-pre.001` puis consolidé jusqu'à `0.1.4-rel.001`.
- [`007-V0_2_0_SERIES_PLANNING.md`](007-V0_2_0_SERIES_PLANNING.md) — plan historique clôturé de la release stable `0.2.0`, ouvert par `pre.001`, consolidé par `pre.002`, audité par `pre.003` puis publié par `rel.001`; il fixe l'ordre `0.2.1+`, la stratégie RAW/CORE/DECODE/SPECIALIZED, les vertical slices Program et le prompt `0.2.1`. - [`007-V0_2_0_SERIES_PLANNING.md`](007-V0_2_0_SERIES_PLANNING.md) — plan historique clôturé de la release stable `0.2.0`, ouvert par `pre.001`, consolidé par `pre.002`, audité par `pre.003` puis publié par `rel.001`; il fixe l'ordre `0.2.1+`, la stratégie RAW/CORE/DECODE/SPECIALIZED, les vertical slices Program et le prompt `0.2.1`.
- [`008-V0_2_1_ONCHAIN_HTTP_PLAN.md`](008-V0_2_1_ONCHAIN_HTTP_PLAN.md) — plan de `0.2.1`, établi par `0.2.1-pre.001`, recalibré par `pre.001-fix.001` et amené en clôture candidate par `pre.007`; il conserve l'inventaire 52 méthodes HTTP courantes + 14 Deprecated historiques, le design Transport/Config et le split de couverture typée sur `0.2.1``0.2.4`. - [`008-V0_2_1_ONCHAIN_HTTP_PLAN.md`](008-V0_2_1_ONCHAIN_HTTP_PLAN.md) — plan de `0.2.1`, établi par `0.2.1-pre.001`, recalibré par `pre.001-fix.001` et amené en clôture candidate par `pre.007`; il conserve l'inventaire 52 méthodes HTTP courantes + 14 Deprecated historiques, le design Transport/Config et le split de couverture typée sur `0.2.1``0.2.4`.
- [`009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md`](009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md) — plan actif de `0.2.2`, établi par `0.2.2-pre.001` après réaudit officiel ; il confirme les 22 méthodes Accounts/Tokens/Cluster, leurs formes wire communes et le sizing de la release.
Le `pre.001` de chaque release fonctionnelle peut introduire son propre plan détaillé lorsque la release s'ouvre. Le `pre.001` de chaque release fonctionnelle peut introduire son propre plan détaillé lorsque la release s'ouvre.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md --> <!-- file: docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md -->
<!-- version: 33 --> <!-- version: 34 -->
# Séquence des releases fonctionnelles KSP # Séquence des releases fonctionnelles KSP
@@ -390,6 +390,8 @@ Ces trois releases constituent le découpage nominal, pas une obligation de troi
Chaque `pre.001` réaudite la documentation officielle actuelle. Les méthodes Deprecated réellement retirées restent tracées comme historiques/runtime removed au lieu d'être simulées. Chaque `pre.001` réaudite la documentation officielle actuelle. Les méthodes Deprecated réellement retirées restent tracées comme historiques/runtime removed au lieu d'être simulées.
`0.2.2-pre.001` a effectué ce réaudit : la partition reste 22 méthodes (5 Accounts + 5 Tokens + 12 Cluster) et le gate de sizing est positif. Le plan d'exécution actif est `docs/plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md`.
## `0.2.5` — Wallet foundation ## `0.2.5` — Wallet foundation
Mission : créer `ksp-wallet-lib` et le format `.kspwallet`. Mission : créer `ksp-wallet-lib` et le format `.kspwallet`.

View File

@@ -0,0 +1,497 @@
<!-- file: docs/plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md -->
<!-- version: 2 -->
# Plan `0.2.2` — HTTP Accounts + Tokens + Cluster
## Statut
Ce plan ouvre `0.2.2-pre.001` sur la base stable `v0.2.1`.
`0.2.1` a déjà stabilisé la foundation HTTP commune : settings, endpoints/pool/rôles, admission et limites, retry, JSON-RPC 2.0,
registry des méthodes, exécution HTTP générique, adapter Config -> Transport et quatre wrappers typés canari.
Cette release ne reconstruit aucun transport par famille. Elle complète uniquement la surface typée des 22 méthodes déjà attribuées à
`HttpRpcCoverageRelease::V0_2_2`.
## Sources normatives réauditées le 2026-08-17
Source documentaire principale :
```text
https://solana.com/docs/rpc/http
```
Références complémentaires officielles utilisées pour les formes wire communes :
```text
https://solana.com/docs/rpc/json-structures
https://github.com/anza-xyz/agave/blob/v3.1.8/rpc/src/rpc.rs
https://github.com/anza-xyz/agave/blob/v3.1.8/rpc-client-types/src/config.rs
https://github.com/anza-xyz/agave/blob/v3.1.8/rpc-client-types/src/filter.rs
https://github.com/anza-xyz/agave/blob/v3.1.8/rpc-client-types/src/request.rs
https://github.com/anza-xyz/agave/blob/v3.1.8/rpc-client-types/src/response.rs
```
Les liens `Source` des pages RPC Solana consultées pointent actuellement vers Agave `v3.1.8`. KSP ne prend pas de dépendance sur ces crates :
leur source sert seulement à lever les ambiguïtés de la documentation HTTP lorsque nécessaire.
## Résultat de l'audit global
L'index HTTP officiel courant contient toujours **52 méthodes**. Pour les familles concernées par cette release :
```text
Accounts : 6 current = 1 acquis en 0.2.1 + 5 ciblés en 0.2.2
Tokens : 5 current = 5 ciblés en 0.2.2
Cluster : 15 current = 3 acquis en 0.2.1 + 12 ciblés en 0.2.2
```
La navigation officielle Deprecated contient toujours exactement les **14 méthodes historiques** déjà enregistrées dans KSP :
```text
confirmTransaction
getConfirmedBlock
getConfirmedBlocks
getConfirmedBlocksWithLimit
getConfirmedSignaturesForAddress2
getConfirmedTransaction
getFeeCalculatorForBlockhash
getFeeRateGovernor
getFees
getRecentBlockhash
getSignatureConfirmation
getSignatureStatus
getSnapshotSlot
getStakeActivation
```
Aucune méthode ajoutée, supprimée ou déplacée n'a été détectée par rapport à l'audit `0.2.1` du 2026-08-17. Les 22 méthodes de cette release
restent donc la partition exacte prévue. Les pages courantes ciblées ne portent pas de marqueur Deprecated ou Unstable ; les descriptors KSP
restent `Stable / Supported / Stable`, `Read`, `RetrySafe`.
## Gate de sizing obligatoire
Question :
```text
Les 22 wrappers typés + DTOs partagés + tests + documentation peuvent-ils être clôturés proprement dans cette session ?
```
Réponse :
```text
OUI.
```
Le périmètre ne nécessite ni nouvelle foundation de transport, ni nouvelle crate, ni nouvelle dépendance externe identifiée à `pre.001`.
Les difficultés sont concentrées dans quelques contrats wire, principalement les données de compte, `getProgramAccounts`, `getLeaderSchedule`
et `getVoteAccounts`. Elles peuvent être isolées dans les prereleases prévues sans compresser les tests.
Le sizing reste conditionnel à la règle KSP habituelle : si une tranche dépasse réellement le budget de 1520 minutes, une prerelease
supplémentaire est ajoutée dans `0.2.2`; la release n'est pas artificiellement comprimée et aucune méthode n'est déplacée silencieusement.
## Matrice exacte — Accounts
| Méthode | Paramètres/config confirmés | Résultat typé à préserver | Limites / points significatifs |
|-------------------------------------|-----------------------------------------------------------------|-------------------------------------|---------------------------------------------------------------------------------------------------------|
| `getAccountInfo` | `Pubkey`, config `commitment/encoding/dataSlice/minContextSlot` | `RpcResponse<Option<Account>>` | compte absent = `null`; erreur min-context distincte |
| `getLargestAccounts` | config `commitment/filter/sortResults` | `RpcResponse<Vec<AccountBalance>>` | 20 résultats; filtre `circulating/nonCirculating`; cache provider possible |
| `getMinimumBalanceForRentExemption` | longueur de données, `commitment?` | `u64` lamports | aucune valeur sentinelle inventée |
| `getMultipleAccounts` | `Vec<Pubkey>`, config Account | `RpcResponse<Vec<Option<Account>>>` | maximum documenté 100; ordre des résultats = ordre demandé |
| `getProgramAccounts` | `Pubkey`, config Account + `filters/withContext/sortResults` | résultat bare ou contextualisé | HTTP documente `dataSize`/`memcmp`; Agave accepte aussi `tokenAccountState`; 4 filtres max côté serveur |
### Wire Account commun
Le type `Account` KSP doit rester un DTO de transport, sans décodage Program. Les formes documentées imposent de conserver :
```text
lamports u64
owner Pubkey
executable bool
rentEpoch u64
space Option<u64>
data forme wire discriminée
```
`data` n'est pas modélisable correctement par un simple `String`. Les formes à conserver sont :
- chaîne legacy `binary` lorsque le serveur l'émet ;
- couple `[data, encoding]` pour `base58`, `base64` et `base64+zstd` ;
- objet `jsonParsed` lorsque le parser RPC existe ;
- fallback `[data, "base64"]` même lorsqu'un appel demande `jsonParsed` mais qu'aucun parser n'est disponible.
La valeur `jsonParsed.parsed` reste un `serde_json::Value` au niveau Transport. Aucun modèle SPL/Program n'est introduit ici.
`dataSlice` est un petit DTO `{ offset, length }`. Il n'impose aucun décodage local des données et ne justifie donc pas l'ajout de `base64`
ou `bs58` dans cette release.
### `getProgramAccounts`
Le résultat dépend de `withContext` :
```text
false/absent -> Vec<KeyedAccount>
true -> RpcResponse<Vec<KeyedAccount>>
```
Le contrat public doit refléter cette union au lieu de supprimer le contexte ou d'inventer un contexte lorsque le serveur n'en renvoie pas.
Les filtres KSP doivent distinguer les trois variantes acceptées par la source primaire Agave actuelle :
```text
DataSize(u64)
Memcmp { offset, bytes, encoding }
TokenAccountState
```
Pour `Memcmp`, `base58` est l'encodage implicite lorsque `encoding` est absent; `base58`, `base64` et les octets bruts sont acceptés par le wire
courant, tandis que l'ancien libellé `binary` n'est plus accepté. La donnée comparée est limitée à 128 octets après décodage. Agave expose en
outre `MAX_GET_PROGRAM_ACCOUNT_FILTERS = 4`, même si la page HTTP actuelle ne publie pas cette cardinalité. Le plan retient donc **4 filtres max
comme limite runtime/source primaire à préserver**, en la distinguant explicitement d'une limite publiée sur la page HTTP.
Cette connaissance n'impose pas l'ajout immédiat de `base64` ou `bs58` à KSP : le DTO peut préserver les chaînes encodées sans les décoder.
Une validation locale de la taille décodée ne sera ajoutée que si elle apporte une valeur claire et justifie la dépendance; le wrapper doit en
revanche empêcher plus de quatre filtres, car cette requête serait refusée par le serveur actuel.
## Matrice exacte — Tokens
| Méthode | Paramètres/config confirmés | Résultat typé à préserver | Limites / points significatifs |
|------------------------------|-----------------------------------------------------------------------|-----------------------------------------|-------------------------------------------------------------------|
| `getTokenAccountBalance` | token account `Pubkey`, `commitment?` | `RpcResponse<TokenAmount>` | erreur RPC si le compte n'est pas exploitable comme token account |
| `getTokenAccountsByDelegate` | delegate `Pubkey`, selector `{mint}` ou `{programId}`, config Account | `RpcResponse<Vec<KeyedAccount>>` | selector exclusif par construction |
| `getTokenAccountsByOwner` | owner `Pubkey`, selector `{mint}` ou `{programId}`, config Account | `RpcResponse<Vec<KeyedAccount>>` | selector exclusif par construction |
| `getTokenLargestAccounts` | mint `Pubkey`, `commitment?` | `RpcResponse<Vec<TokenAccountBalance>>` | 20 plus gros comptes du mint |
| `getTokenSupply` | mint `Pubkey`, `commitment?` | `RpcResponse<TokenAmount>` | aucune conversion métier SPL |
Le selector commun doit rendre impossible la production accidentelle d'un objet contenant simultanément `mint` et `programId`, par exemple avec
un enum KSP `Mint(Pubkey) | ProgramId(Pubkey)` sérialisé vers la forme RPC attendue.
Le `TokenAmount` wire commun conserve :
```text
amount String
decimals u8
uiAmount Option<f64>
uiAmountString String
```
`uiAmount` est nullable dans les structures JSON officielles ; KSP ne doit pas le remplacer par `0.0`.
Les deux méthodes de liste réutilisent le DTO Account générique. `jsonParsed` peut contenir des structures SPL, mais Transport les conserve en
JSON sans les convertir en modèle Token métier.
## Matrice exacte — Cluster
| Méthode | Paramètres/config confirmés | Résultat typé à préserver | Limites / points significatifs |
|--------------------------|------------------------------------|---------------------------|---------------------------------------------------------------------------------------------|
| `getClusterNodes` | aucun | `Vec<ClusterNode>` | nombreux endpoints/champs optionnels |
| `getEpochInfo` | config `commitment/minContextSlot` | `EpochInfo` | `transactionCount` nullable |
| `getEpochSchedule` | aucun | `EpochSchedule` | structure fixe d'epoch schedule |
| `getHighestSnapshotSlot` | aucun | `SnapshotSlotInfo` | `incremental` nullable; absence de snapshot = erreur RPC |
| `getIdentity` | aucun | identity `Pubkey` | objet `{identity}` sur le wire |
| `getLeaderSchedule` | slot/config overload | `Option<LeaderSchedule>` | forme des paramètres particulière; résultat nullable |
| `getMaxRetransmitSlot` | aucun | `u64` | lecture simple |
| `getMaxShredInsertSlot` | aucun | `u64` | lecture simple |
| `getSlot` | config `commitment/minContextSlot` | `u64` | erreur min-context possible |
| `getSlotLeader` | config `commitment/minContextSlot` | leader `Pubkey` | erreur min-context possible |
| `getSlotLeaders` | `startSlot`, `limit` | `Vec<Pubkey>` | limite documentée `1..=5000`; ordre par slot |
| `getVoteAccounts` | config vote accounts | `VoteAccountStatus` | `current` + `delinquent`; Agave borne actuellement `epochCredits` à 5 entrées par validator |
### `ClusterNode`
La surface courante documente les champs suivants :
```text
pubkey Pubkey
featureSet Option<u32>
gossip Option<String>
pubsub Option<String>
rpc Option<String>
serveRepair Option<String>
shredVersion Option<u16>
tpu Option<String>
tpuForwards Option<String>
tpuForwardsQuic Option<String>
tpuQuic Option<String>
tpuVote Option<String>
tvu Option<String>
version Option<String>
```
Même si Agave utilise actuellement `SocketAddr` en interne pour plusieurs endpoints, le DTO public Transport ne doit pas imposer davantage que
le contrat JSON. Les adresses réseau restent donc des chaînes wire optionnelles à moins qu'un invariant officiel plus strict soit nécessaire.
### `EpochInfo` et `EpochSchedule`
`EpochInfo` conserve :
```text
absoluteSlot u64
blockHeight u64
epoch u64
slotIndex u64
slotsInEpoch u64
transactionCount Option<u64>
```
`EpochSchedule` conserve :
```text
firstNormalEpoch u64
firstNormalSlot u64
leaderScheduleSlotOffset u64
slotsPerEpoch u64
warmup bool
```
### `getHighestSnapshotSlot`
La page officielle possède les états « Snapshot / No Snapshot ». La source Agave reliée par cette page confirme qu'un noeud sans configuration
snapshot ou sans full snapshot renvoie `RpcCustomError::NoSnapshot`. KSP conserve cette situation comme erreur JSON-RPC applicative ; il ne la
convertit pas en `{ full: 0, incremental: null }`.
### `getLeaderSchedule`
La forme actuelle doit être respectée exactement :
```text
paramètre 1 optionnel : slot u64 | config object | null
paramètre 2 optionnel : config object lorsque le premier paramètre est slot/null
config : commitment + identity
résultat : map identity -> indices de slots relatifs au début de l'epoch, ou null
```
Une API Rust typée doit empêcher les combinaisons incohérentes plutôt que demander à l'appelant de construire manuellement ce tableau JSON.
### `getVoteAccounts`
La config actuelle contient :
```text
commitment
votePubkey
keepUnstakedDelinquents
delinquentSlotDistance
```
Chaque record conserve au minimum :
```text
votePubkey Pubkey
nodePubkey Pubkey
activatedStake u64
commission u8
epochVoteAccount bool
epochCredits Vec<(epoch u64, credits u64, previousCredits u64)>
lastVote u64
rootSlot u64
```
Un petit DTO nommé pour une entrée `epochCredits` est préférable à exposer un tuple public opaque, tout en conservant la forme tableau du wire
au décodage. La source Agave courante limite la réponse à cinq entrées d'historique `epochCredits` par validator; KSP ne doit pas supposer que
l'historique complet d'un vote account est exposé par cette méthode RPC.
## DTOs communs et organisation prévue
`pre.002` doit introduire des types partagés ciblés, pas un « mega DTO ». Le découpage prévu est conceptuellement :
```text
RPC context / commitment
account encoding + data slice + account wire
keyed account
program-account filters
token selector + token amount
cluster epoch/schedule/node/snapshot/leader/vote structures
```
`SolanaCommitment` et `SolanaRpcContext`, actuellement nés avec les canaris `0.2.1`, doivent être mutualisés sans casser leur réexport public.
Les wrappers continueront à utiliser des structs wire privés `serde` puis une conversion explicite vers les DTOs publics KSP, notamment pour
valider et convertir les chaînes de pubkey vers `ksp_core_lib::Pubkey`.
Aucune activation anticipée d'une feature `serde` sur `solana-pubkey` n'est nécessaire : la foundation actuelle sait déjà sérialiser une Pubkey
par sa représentation texte, et les réponses peuvent être décodées par wire structs privés avant conversion.
## Architecture d'exécution imposée
Tous les wrappers suivent :
```text
wrapper typé
-> descriptor central
-> execute_standard_rpc
-> pool/admission
-> reqwest HTTP
-> validation JSON-RPC
-> decode typé
```
Sont explicitement interdits :
- client HTTP parallèle par famille ;
- appel `reqwest` direct dans un wrapper ;
- bypass deadline/admission/retry ;
- dépendance Transport -> Config/Store/Program ;
- import direct de `tracing` ;
- conversion des accounts en modèles Program/SPL métier.
## Erreurs, retry et sécurité
Les 22 descriptors sont réaudités comme lectures et restent `RetrySafe`. Aucun `WriteSubmission` n'entre dans `0.2.2`.
Les règles `0.2.1` sont inchangées :
- erreur JSON-RPC applicative distincte des erreurs transport ;
- `reqwest::Error::without_url()` avant exposition comme source ;
- aucune URL/provider credential/body complet dans diagnostics ou logs ordinaires ;
- retry central uniquement selon descriptor/policy ;
- unique hiérarchie d'erreur via `ksp_core_lib::Error`.
Les validations de paramètres KSP sont ajoutées seulement lorsqu'elles sont normatives et utiles avant I/O, notamment :
```text
getMultipleAccounts : <= 100 pubkeys
getProgramAccounts : <= 4 filtres (limite runtime Agave courante)
getSlotLeaders : 1..=5000
Token selector : exactement mint OU programId
```
`minContextSlot` peut produire l'erreur RPC dédiée `MinContextSlotNotReached`; le wrapper ne doit pas la transformer en absence de données.
## Logging
Aucun événement par méthode n'est ajouté par défaut. Les événements génériques de Transport restent la source d'observabilité : méthode,
rôle, endpoint logique, tentative et statut technique, avec metadata sûre.
Toute instrumentation temporaire `debug` ajoutée pendant les prereleases d'implémentation doit revenir à la baseline `info`/`warn` lors de la
tranche finale.
## Config
L'audit de `std.transport.json`, de son schema et de `ksp-config-lib/src/transport.rs` ne révèle aucune capacité manquante nécessaire aux 22
wrappers. Aucun changement Config n'est prévu dans `pre.001`.
La direction reste strictement :
```text
ksp-config-lib -> ksp-onchain-transport-lib
```
Transport ne lit ni `.env`, ni `std::env`.
## Dépendances
Aucune nouvelle dépendance externe n'est requise par le design retenu à `pre.001`.
En particulier, `base64` et `bs58` ne sont pas nécessaires pour représenter les chaînes encodées du wire. Elles ne seront ajoutées que si une
capacité publique réelle de décodage/validation binaire est décidée ultérieurement, ce qui n'est pas un objectif de `0.2.2`.
Aucune crate SPL, `solana-client`, SDK RPC haut niveau ou `ksp-interface-lib` n'est introduit pour cette surface.
## Stratégie de tests
Chaque wrapper doit disposer de fixtures déterministes et d'un serveur HTTP local couvrant au minimum :
- sérialisation exacte de la request ;
- réponse success typée ;
- `null`/option pertinent ;
- config/overload pertinent ;
- erreur JSON-RPC significative ;
- cardinalité/selector lorsqu'un invariant est documenté.
Cas transversaux prioritaires :
- toutes les variantes Account data réellement supportées ;
- fallback `jsonParsed -> base64` ;
- `space: null` ;
- `getAccountInfo` et `getMultipleAccounts` avec comptes absents ;
- `getProgramAccounts` bare vs `withContext` ;
- `TokenAmount.uiAmount: null` ;
- fields optionnels de `getClusterNodes` ;
- `EpochInfo.transactionCount: null` ;
- `SnapshotSlotInfo.incremental: null` et erreur NoSnapshot ;
- `getLeaderSchedule: null` + overloads ;
- `getVoteAccounts` current/delinquent et epoch credits ;
- limites 100, 4 filtres Program Accounts et 5000; variantes/encodages `memcmp`.
Les canaries de release doivent maintenir :
```text
current methods == 52 exactes
historical methods == 14 exactes
coverage partition == 4 / 22 / 11 / 15
0.2.1 typed canaries == getBalance/getGenesisHash/getHealth/getVersion, inchangés
0.2.2 exact set == les 22 méthodes de ce plan
0.2.3/0.2.4 != typed-complete prématurément
```
Un smoke Devnet opt-in pourra couvrir un sous-ensemble représentatif, sans jamais remplacer les fixtures locales.
## Prévision souple des prereleases
| Tranche | Objectif |
|-----------|--------------------------------------------------------------------------------------------------------------------|
| `pre.001` | audit officiel actuel, matrice exacte, architecture DTO, dépendances et sizing |
| `pre.002` | primitives/configs/results communs Account/Token/Cluster + fixtures de base; mutualiser Context/Commitment |
| `pre.003` | 5 wrappers Accounts + tests déterministes |
| `pre.004` | 5 wrappers Tokens + tests déterministes |
| `pre.005` | Cluster simple : nodes, epoch info/schedule, snapshot, identity, max retransmit, max shred + tests |
| `pre.006` | Cluster schedule/slot/vote : leader schedule, slot, slot leader(s), vote accounts + tests |
| `pre.007` | canaries de complétude, smoke opt-in si utile, README/USAGE, validation finale, prompt `0.2.3`, préparation stable |
Le découpage est volontairement asymétrique : `pre.006` contient moins de méthodes mais les formes les plus complexes. Toute tranche qui dépasse
le budget est scindée en une prerelease supplémentaire plutôt que compressée.
## Hors périmètre
Sont exclus de `0.2.2` :
- les 11 méthodes Transactions de `0.2.3` ;
- les 15 méthodes Blocks + Economics de `0.2.4` ;
- WebSocket, Yellowstone, provider-specific streams ;
- décodage SPL/Program ;
- Store/materialization ;
- `ksp-interface-lib` anticipé ;
- modification de Config sans besoin concret ;
- ajout de dépendances de décodage pour simple représentation wire.
## Validations prévues
Pendant le développement :
```bash
cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-onchain-transport-lib
```
À la clôture :
```bash
cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-onchain-transport-lib
cargo test -p ksp-config-lib
cargo test -p ksp-core-lib
cargo test --workspace
cargo tree -p ksp-onchain-transport-lib
cargo tree -p ksp-onchain-transport-lib -d
cargo tree -p ksp-onchain-transport-lib -e features
cargo tree -p ksp-onchain-transport-lib -e normal
```
## Critères de clôture `0.2.2`
`0.2.2` ne devient stable que lorsque :
- la matrice officielle est réauditée une dernière fois ;
- les 22 méthodes de ce plan ont chacune un wrapper public typé et leurs tests ;
- les quatre canaris `0.2.1` restent inchangés ;
- la partition globale ne perd aucune méthode future ;
- les DTOs conservent les `null`/options documentés ;
- les frontières de dépendances, redaction, retry et logging restent conformes ;
- README/USAGE et validation durable sont synchronisés ;
- les commandes Cargo finales réellement exécutables passent ;
- le prompt `0.2.3 — HTTP Transactions` est prêt ;
- `rel.001` ne contient plus de développement fonctionnel nouveau.