# Delta `0.2.2-pre.005` — sept wrappers HTTP Cluster simples typés ## Base requise Livraison précédente validée localement par l'opérateur : ```text 0.2.2-pre.004 workspace.package.version = "0.2.2-pre.4" ``` La validation opérateur du 2026-08-18 a confirmé : ```text cargo fmt --all OK cargo check --workspace OK cargo clippy --workspace --all-targets OK cargo test -p ksp-onchain-transport-lib OK ``` Résultats Transport de cette base : ```text 106 unit tests 11 public API tests 4 release completeness tests 0 warning signalé par check/clippy ``` Le plan canonique reste `docs/plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md` version 3. ## Contrôle documentaire avant nouvelle tranche Le contrôle de cohérence demandé entre prereleases confirme : - `ROADMAP.md` conserve correctement `0.2.2` en cours `[/]` ; - le plan `009` attribue exactement à `pre.005` les sept méthodes Cluster simples implémentées ici ; - `pre.006` conserve exactement cinq méthodes différées : `getLeaderSchedule`, `getSlot`, `getSlotLeader`, `getSlotLeaders`, `getVoteAccounts` ; - les index `docs/000-README.md`, `docs/plans/000-README.md` et `docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md` restent cohérents et ne nécessitent aucune modification. ## Objectif Implémenter les sept wrappers publics typés Cluster simples prévus par le plan : ```text getClusterNodes getEpochInfo getEpochSchedule getHighestSnapshotSlot getIdentity getMaxRetransmitSlot getMaxShredInsertSlot ``` Tous passent par la foundation HTTP commune : ```text wrapper typé -> descriptor audité -> execute_standard_rpc -> pool/admission/retry/deadline -> reqwest HTTP -> JSON-RPC validation -> décodage DTO KSP ``` Aucun wrapper Cluster ne contacte `reqwest` directement. ## Version Cargo Conformément au cycle prerelease KSP : ```text 0.2.2-pre.4 -> 0.2.2-pre.5 ``` Aucune dépendance ni feature Cargo n'est ajoutée ou retirée. ## Réaudit ciblé du contrat courant Les pages RPC Solana courantes ont été revérifiées le 2026-08-18 : ```text https://solana.com/docs/rpc/http/getclusternodes https://solana.com/docs/rpc/http/getepochinfo https://solana.com/docs/rpc/http/getepochschedule https://solana.com/docs/rpc/http/gethighestsnapshotslot https://solana.com/docs/rpc/http/getidentity https://solana.com/docs/rpc/http/getmaxretransmitslot https://solana.com/docs/rpc/http/getmaxshredinsertslot ``` Le contrat reste cohérent avec le plan `009` : - `getClusterNodes` ne prend aucun paramètre et renvoie une liste de contacts de noeuds ; - `getEpochInfo` accepte uniquement la config commune `commitment/minContextSlot` et conserve `transactionCount` nullable ; - `getEpochSchedule` ne prend aucun paramètre et renvoie la structure fixe d'epoch schedule ; - `getHighestSnapshotSlot` ne prend aucun paramètre, conserve `incremental` nullable et laisse l'absence de snapshot comme erreur JSON-RPC distante ; - `getIdentity` ne prend aucun paramètre et renvoie l'objet `{ identity }`, converti en `Pubkey` KSP ; - `getMaxRetransmitSlot` et `getMaxShredInsertSlot` ne prennent aucun paramètre et renvoient chacun un `u64`. Le champ Agave `v4.2.1` `clientId: Option` identifié par `pre.001-fix.001` reste conservé par `SolanaClusterNode`, sans devenir obligatoire. ## Surface typée Cluster simple ### `getClusterNodes` ```text role -> Vec ``` Chaque `pubkey` est validée et convertie en `ksp_core_lib::Pubkey`. Les endpoints réseau restent des chaînes optionnelles. Les champs optionnels absents, y compris `clientId`, restent `None`. ### `getEpochInfo` ```text role + Option -> SolanaEpochInfo ``` Un config explicitement vide est omis de `params`. `transactionCount: null` reste `None`. ### `getEpochSchedule` ```text role -> SolanaEpochSchedule ``` Aucune transformation métier n'est introduite. ### `getHighestSnapshotSlot` ```text role -> SolanaSnapshotSlotInfo ``` `incremental` reste optionnel. Une erreur RPC « no snapshot » n'est pas convertie en valeur sentinelle. ### `getIdentity` ```text role -> Pubkey ``` Le wrapper valide la chaîne `identity` avant de l'exposer comme `Pubkey`, sans recopier une valeur wire invalide dans le diagnostic. ### `getMaxRetransmitSlot` / `getMaxShredInsertSlot` ```text role -> u64 ``` Les deux wrappers partagent un chemin privé simple de décodage `u64` et ne créent aucun DTO artificiel. ## Activation ciblée des helpers préparés en `pre.002` Les helpers Cluster nécessaires à cette tranche deviennent production-live uniquement maintenant qu'ils ont des consommateurs runtime : - `SolanaClusterNode::decode_wire` + `WireClusterNode` ; - `SolanaEpochInfo::decode_wire` + `WireEpochInfo` ; - `SolanaEpochSchedule::decode_wire` + `WireEpochSchedule` ; - `SolanaSnapshotSlotInfo::decode_wire` + `WireSnapshotSlotInfo`. Les helpers spécifiques à `getLeaderSchedule` et `getVoteAccounts` restent sous `#[cfg(test)]` jusqu'à `pre.006`. Aucun `#[allow(dead_code)]` n'est ajouté. ## Fixtures HTTP déterministes ajoutées ```text crates/ksp-onchain-transport-lib/fixtures/http/get_cluster_nodes.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_cluster_nodes.invalid_pubkey.json crates/ksp-onchain-transport-lib/fixtures/http/get_epoch_info.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_epoch_schedule.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_highest_snapshot_slot.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_highest_snapshot_slot.error.json crates/ksp-onchain-transport-lib/fixtures/http/get_identity.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_identity.invalid_pubkey.json crates/ksp-onchain-transport-lib/fixtures/http/get_max_retransmit_slot.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_max_shred_insert_slot.success.json ``` Les tests utilisent uniquement un serveur HTTP loopback local. ## Couverture de tests ajoutée Les tests couvrent notamment : - requête sans paramètres pour les six méthodes sans config ; - sérialisation exacte `commitment + minContextSlot` pour `getEpochInfo` ; - omission d'un `SolanaContextConfig` explicitement vide ; - `transactionCount: null` ; - champs ClusterNode optionnels présents et absents ; - conservation de `clientId` Agave `v4.2.1` ; - rejet d'une `pubkey` de noeud invalide ; - `incremental: null` ; - propagation d'une erreur RPC « no snapshot » ; - validation de l'identity `Pubkey` ; - décodage des deux slots max comme `u64`. Le test public compile explicitement les sept nouvelles méthodes depuis `HttpTransportPool`. Un canari release fige le sous-ensemble `pre.005` exact et vérifie `Read + RetrySafe` pour les sept descriptors, tout en laissant les cinq méthodes Cluster de `pre.006` enregistrées mais différées. Après application, la cible Transport attendue devient : ```text 116 unit tests 12 public API tests 5 release completeness tests ``` ## Fichiers ajoutés ```text crates/ksp-onchain-transport-lib/fixtures/http/get_cluster_nodes.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_cluster_nodes.invalid_pubkey.json crates/ksp-onchain-transport-lib/fixtures/http/get_epoch_info.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_epoch_schedule.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_highest_snapshot_slot.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_highest_snapshot_slot.error.json crates/ksp-onchain-transport-lib/fixtures/http/get_identity.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_identity.invalid_pubkey.json crates/ksp-onchain-transport-lib/fixtures/http/get_max_retransmit_slot.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_max_shred_insert_slot.success.json deltas/0.2.2/pre.005.md ``` ## Fichiers modifiés ```text Cargo.toml crates/ksp-onchain-transport-lib/src/rpc_cluster.rs crates/ksp-onchain-transport-lib/unit_tests/rpc_cluster.rs crates/ksp-onchain-transport-lib/tests/public_api.rs crates/ksp-onchain-transport-lib/tests/release_completeness.rs ``` ## Fichiers supprimés Aucun. ## Documentation durable Aucune modification de ROADMAP/plan/index n'est requise par cette tranche après le contrôle documentaire : les documents existants décrivent déjà exactement ce découpage. `CHANGELOG.md` reste réservé à la clôture stable. ## Validation à exécuter sur le checkout opérateur ```bash cargo fmt --all cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-onchain-transport-lib ``` La livraison n'affirme pas que ces commandes ont été exécutées dans l'environnement de génération. ## Critères de validation de `pre.005` `pre.005` est validable lorsque : - les quatre commandes ci-dessus passent sans warning nouveau ; - les 116 unit tests passent ; - les 12 tests public API passent ; - les 5 tests release completeness passent ; - aucun helper Cluster simple production-live n'est `dead_code` ; - les cinq wrappers complexes de `pre.006` restent hors de cette tranche.