283 lines
9.2 KiB
Markdown
283 lines
9.2 KiB
Markdown
<!-- file: deltas/0.2.1/pre.005.md -->
|
|
<!-- version: 1 -->
|
|
|
|
# Delta `v0.2.1-pre.005`
|
|
|
|
## Base
|
|
|
|
Base attendue :
|
|
|
|
```text
|
|
v0.2.1-pre.004-fix.002
|
|
```
|
|
|
|
Cette base a été validée localement par le user avec `cargo fmt --all`, `cargo check --workspace`, `cargo clippy --workspace --all-targets`, `cargo test -p ksp-onchain-transport-lib` et `cargo test --workspace`.
|
|
|
|
Version Cargo cible :
|
|
|
|
```text
|
|
0.2.1-pre.5
|
|
```
|
|
|
|
## Objectif
|
|
|
|
Matérialiser la première exécution réseau HTTP complète de `ksp-onchain-transport-lib` et les quatre méthodes typées canari assignées à `0.2.1` :
|
|
|
|
```text
|
|
getHealth
|
|
getVersion
|
|
getGenesisHash
|
|
getBalance
|
|
```
|
|
|
|
La tranche doit également corriger l'ownership des canaries de dépendances générales : les contrôles portant sur le workspace entier ne restent pas dans la crate métier Transport et sont centralisés dans la surface de tests de `ksp-core-lib` tant qu'aucun outil d'audit dédié n'existe.
|
|
|
|
## Vérification de la surface Solana
|
|
|
|
La documentation Solana HTTP officielle a été revérifiée le 17 août 2026 pour les quatre canaris :
|
|
|
|
- `getHealth` : aucun paramètre, résultat stable `"ok"` lorsque le node est sain ;
|
|
- `getGenesisHash` : aucun paramètre, résultat string base58 ;
|
|
- `getVersion` : aucun paramètre, objet contenant `solana-core` et `feature-set` optionnel/null ;
|
|
- `getBalance` : pubkey base58 obligatoire, configuration optionnelle `commitment` / `minContextSlot`, réponse `{ context, value }` où `value` est le solde en lamports.
|
|
|
|
## Exécuteur HTTP JSON-RPC
|
|
|
|
Nouvelle surface publique :
|
|
|
|
```text
|
|
HttpTransportPool::execute_standard_rpc(...)
|
|
```
|
|
|
|
L'exécuteur :
|
|
|
|
1. vérifie le descriptor RPC audité et son support runtime ;
|
|
2. alloue un identifiant JSON-RPC numérique KSP ;
|
|
3. construit et sérialise `JsonRpcRequest` sans exposer les params dans `Debug` ;
|
|
4. dérive le request-kind depuis le registre ;
|
|
5. fixe une deadline commune à partir du plus petit `request_timeout` des endpoints compatibles ;
|
|
6. acquiert un `HttpRequestPermit`, donc respecte rôles/capabilities/priorité/fairness/RPS/burst/concurrence/cooldown ;
|
|
7. exécute un POST `application/json` via le `reqwest::Client` privé de l'endpoint ;
|
|
8. mappe connexion, timeout, HTTP status, JSON invalide, protocole JSON-RPC et RPC application error vers les codes KSP existants ;
|
|
9. met à jour la santé passive du rôle ;
|
|
10. applique le retry/backoff centralisé sans dépasser la deadline commune.
|
|
|
|
Les retries libèrent le permit précédent puis réacquièrent explicitement capacité RPS/concurrence : ils ne contournent donc pas les limites runtime du pool.
|
|
|
|
## HTTP status, `Retry-After` et retry
|
|
|
|
Le raccordement réseau de la résilience est désormais effectif :
|
|
|
|
- `429` -> `record_rate_limited`, cooldown de rôle et `HttpRetryCause::RateLimited` ;
|
|
- `Retry-After` sous forme HTTP delta-seconds -> `Duration`, puis borne défensive déjà possédée par la résilience ;
|
|
- `408`, `500`, `502`, `503`, `504` -> `HttpRetryCause::TemporaryHttp` ;
|
|
- erreur de connexion reqwest -> `HttpRetryCause::Connection` + `NotDispatched` ;
|
|
- timeout reqwest -> `HttpRetryCause::Timeout` + `DispatchedAmbiguous` ;
|
|
- autres erreurs request -> non retryables automatiquement ;
|
|
- RPC application error et réponse invalide restent hors retry transport.
|
|
|
|
Le parsing d'une forme HTTP-date de `Retry-After` n'est pas introduit dans cette tranche : si le header n'est pas un delta-seconds valide, le cooldown local configuré/fallback reste utilisé.
|
|
|
|
La règle `NeverAfterDispatch` reste centralisée dans `evaluate_transport_retry()` ; l'exécuteur générique ne la contourne pas et prépare donc correctement les futurs appels write/submission de `0.2.3`.
|
|
|
|
## Quatre canaris typés
|
|
|
|
### `getHealth`
|
|
|
|
Nouvelle méthode :
|
|
|
|
```text
|
|
HttpTransportPool::get_health(...)
|
|
```
|
|
|
|
Résultat public :
|
|
|
|
```text
|
|
SolanaNodeHealth::Healthy
|
|
```
|
|
|
|
Toute autre forme qu'un résultat string exact `"ok"` est classée `invalid_response`.
|
|
|
|
### `getGenesisHash`
|
|
|
|
Nouvelle méthode :
|
|
|
|
```text
|
|
HttpTransportPool::get_genesis_hash(...)
|
|
```
|
|
|
|
Résultat public :
|
|
|
|
```text
|
|
SolanaGenesisHash
|
|
```
|
|
|
|
Le wrapper exige un string non vide et trimé et n'utilise pas abusivement `Pubkey` pour représenter sémantiquement un hash de genesis.
|
|
|
|
### `getVersion`
|
|
|
|
Nouvelle méthode :
|
|
|
|
```text
|
|
HttpTransportPool::get_version(...)
|
|
```
|
|
|
|
Résultat public :
|
|
|
|
```text
|
|
SolanaNodeVersion
|
|
solana_core: String
|
|
feature_set: Option<u32>
|
|
```
|
|
|
|
### `getBalance`
|
|
|
|
Nouvelle méthode :
|
|
|
|
```text
|
|
HttpTransportPool::get_balance(...)
|
|
```
|
|
|
|
L'adresse est reçue sous forme `ksp_core_lib::Pubkey`, conformément à l'ownership Core du type Solana bas niveau.
|
|
|
|
Nouveaux contrats :
|
|
|
|
```text
|
|
SolanaCommitment
|
|
GetBalanceConfig
|
|
SolanaRpcContext
|
|
GetBalanceResult
|
|
```
|
|
|
|
`GetBalanceConfig` encode uniquement les champs présents ; un config vide n'ajoute pas un second paramètre inutile.
|
|
|
|
## Fixtures déterministes
|
|
|
|
Nouvelles fixtures :
|
|
|
|
```text
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_health.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_genesis_hash.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_version.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_balance.success.json
|
|
```
|
|
|
|
Les tests utilisent un serveur TCP local déterministe pour exercer réellement le POST HTTP sans dépendre de Devnet ou d'Internet.
|
|
|
|
Ils vérifient notamment :
|
|
|
|
- les quatre réponses typées ;
|
|
- le nom de méthode envoyé ;
|
|
- les params `getBalance`, dont `commitment` et `minContextSlot` ;
|
|
- un cycle `429 + Retry-After: 0 -> retry -> succès` ;
|
|
- le mapping d'un timeout reqwest vers `ERROR_CODE_TIMEOUT`.
|
|
|
|
Le smoke réseau réel reste opt-in et appartient toujours à `pre.007`.
|
|
|
|
## Centralisation des canaries de dépendances
|
|
|
|
Le fichier suivant est supprimé :
|
|
|
|
```text
|
|
crates/ksp-onchain-transport-lib/tests/dependency_boundary.rs
|
|
```
|
|
|
|
Les deux contrôles qu'il contenait sont transférés vers :
|
|
|
|
```text
|
|
crates/ksp-core-lib/tests/workspace_dependencies.rs
|
|
```
|
|
|
|
Ils continuent de vérifier :
|
|
|
|
- absence d'activation `features = [...]` sous `[workspace.dependencies]` ;
|
|
- maintien de `default-features` au root ;
|
|
- firewall direct Transport -> pas de Config/Store/Program/`tracing` ;
|
|
- feature-set direct attendu de `reqwest` et `tokio` dans le manifest Transport.
|
|
|
|
Nouvelle règle `DEP-CARGO-007` : les canaries qui inspectent une politique générale du workspace ou plusieurs manifests appartiennent à une surface de gouvernance/fondation, actuellement `ksp-core-lib`, et non à une crate métier spécialisée.
|
|
|
|
## ROADMAP et plan
|
|
|
|
`ROADMAP.md` reçoit uniquement la mise à jour synthétique normale de la release : exécution HTTP et quatre canaris deviennent acquis ; Config standard et clôture restent à venir.
|
|
|
|
Le plan `008` marque `pre.005` réalisé et ajoute son état détaillé. L'historique technique reste dans `deltas/`.
|
|
|
|
## Tests
|
|
|
|
Après déplacement des deux canaries workspace hors de Transport et ajout des nouveaux tests :
|
|
|
|
```text
|
|
ksp-onchain-transport-lib : 78 tests Rust déclarés
|
|
ksp-core-lib : +2 tests d'intégration workspace_dependencies
|
|
```
|
|
|
|
La suite Transport reste propriétaire uniquement des tests fonctionnels/API de son domaine ; les canaries workspace générales sont exécutées via Core lors du `cargo test --workspace`.
|
|
|
|
## Dépendances
|
|
|
|
Aucune nouvelle dépendance externe et aucune nouvelle feature externe ne sont introduites.
|
|
|
|
La politique de `pre.004-fix.001/.002` reste inchangée : versions/default-features au root, features d'usage dans chaque crate consommatrice.
|
|
|
|
## Fichiers ajoutés
|
|
|
|
```text
|
|
crates/ksp-core-lib/tests/workspace_dependencies.rs
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_balance.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_genesis_hash.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_health.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_version.success.json
|
|
crates/ksp-onchain-transport-lib/src/executor.rs
|
|
crates/ksp-onchain-transport-lib/src/rpc_canary.rs
|
|
crates/ksp-onchain-transport-lib/unit_tests/executor.rs
|
|
crates/ksp-onchain-transport-lib/unit_tests/rpc_canary.rs
|
|
deltas/0.2.1/pre.005.md
|
|
```
|
|
|
|
## Fichiers modifiés
|
|
|
|
```text
|
|
Cargo.toml
|
|
ROADMAP.md
|
|
crates/ksp-onchain-transport-lib/src/client.rs
|
|
crates/ksp-onchain-transport-lib/src/lib.rs
|
|
crates/ksp-onchain-transport-lib/src/pool.rs
|
|
crates/ksp-onchain-transport-lib/tests/public_api.rs
|
|
docs/plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md
|
|
docs/rules/RULES_DEPENDENCIES.md
|
|
```
|
|
|
|
## Fichiers supprimés
|
|
|
|
```text
|
|
crates/ksp-onchain-transport-lib/tests/dependency_boundary.rs
|
|
```
|
|
|
|
## Validation
|
|
|
|
Non exécutée dans le sandbox de génération : `cargo` et `rustc` n'y sont pas installés.
|
|
|
|
Après application :
|
|
|
|
```bash
|
|
cargo fmt --all
|
|
cargo check --workspace
|
|
cargo clippy --workspace --all-targets
|
|
cargo test -p ksp-onchain-transport-lib
|
|
cargo test -p ksp-core-lib
|
|
cargo test --workspace
|
|
```
|
|
|
|
Aucune dépendance/feature n'ayant changé, un `cargo tree` complet n'est pas requis pour cette tranche. Il peut néanmoins être rejoué au checkpoint final `pre.007` comme prévu.
|
|
|
|
## Suite
|
|
|
|
Tranche suivante prévue :
|
|
|
|
```text
|
|
0.2.1-pre.006
|
|
```
|
|
|
|
Périmètre : document/schema/exemple Config standard `std.transport`, enregistrement dans Config, adapter Config -> Transport et tests de sensibilité/provenance/env sans créer de dépendance inverse Transport -> Config.
|