v0.2.7-pre.013
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
# file: Cargo.toml
|
||||
# version: 213
|
||||
# version: 214
|
||||
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
members = ["crates/ksp-app-config-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-logging-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-wallet-lib"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.2.7-pre.12.fix.1"
|
||||
version = "0.2.7-pre.13"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-core-lib/tests/workspace_dependencies.rs
|
||||
// version: 3
|
||||
// version: 4
|
||||
|
||||
//! Workspace-level dependency policy canaries owned by the foundational KSP test surface.
|
||||
|
||||
@@ -68,3 +68,57 @@ fn transport_manifest_preserves_ksp_dependency_firewall() {
|
||||
assert!(manifest.contains("[dev-dependencies]"));
|
||||
assert!(manifest.contains("tokio = { workspace = true, features = [\"net\", \"rt\"] }"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transport_manifest_runtime_and_dev_dependency_names_are_exact() {
|
||||
let manifest_path = workspace_root().join("crates/ksp-onchain-transport-lib/Cargo.toml");
|
||||
let manifest = std::fs::read_to_string(manifest_path).expect("transport manifest must be readable during workspace integration tests");
|
||||
let dependencies_tail = manifest.split("[dependencies]").nth(1);
|
||||
assert!(dependencies_tail.is_some(), "transport dependencies section must exist");
|
||||
let dependencies_tail = match dependencies_tail {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
let dependencies = match dependencies_tail.split("[dev-dependencies]").next() {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
let dependency_names = manifest_dependency_names(dependencies);
|
||||
assert_eq!(
|
||||
dependency_names,
|
||||
std::vec!["futures-util", "ksp-core-lib", "ksp-logging-lib", "reqwest", "serde", "serde_json", "tokio", "tokio-tungstenite"]
|
||||
);
|
||||
let dev_dependencies_tail = manifest.split("[dev-dependencies]").nth(1);
|
||||
assert!(dev_dependencies_tail.is_some(), "transport dev-dependencies section must exist");
|
||||
let dev_dependencies_tail = match dev_dependencies_tail {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
let dev_dependencies = match dev_dependencies_tail.split("[lints]").next() {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
assert_eq!(manifest_dependency_names(dev_dependencies), std::vec!["tokio"]);
|
||||
}
|
||||
|
||||
fn manifest_dependency_names(section: &str) -> std::vec::Vec<&str> {
|
||||
let mut names = std::vec::Vec::new();
|
||||
for line in section.lines() {
|
||||
let content = match line.split('#').next() {
|
||||
std::option::Option::Some(value) => value.trim(),
|
||||
std::option::Option::None => continue,
|
||||
};
|
||||
if content.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let name = match content.split('=').next() {
|
||||
std::option::Option::Some(value) => value.trim().trim_end_matches(".workspace"),
|
||||
std::option::Option::None => continue,
|
||||
};
|
||||
if !name.is_empty() {
|
||||
names.push(name);
|
||||
}
|
||||
}
|
||||
names.sort_unstable();
|
||||
return names;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: crates/ksp-onchain-transport-lib/README.md -->
|
||||
<!-- version: 17 -->
|
||||
<!-- version: 18 -->
|
||||
|
||||
# `ksp-onchain-transport-lib`
|
||||
|
||||
@@ -234,22 +234,30 @@ La configuration Logging de référence conserve un fichier dédié Transport à
|
||||
|
||||
Les tests par défaut sont déterministes et n'exigent pas Internet : fixtures JSON et serveur HTTP local couvrent requêtes, réponses, retry, 429, timeout, redaction et routing.
|
||||
|
||||
Deux smokes Devnet opt-in sont séparés par responsabilité :
|
||||
Trois smokes Devnet opt-in sont séparés par responsabilité :
|
||||
|
||||
```text
|
||||
Transport pur : settings programmatiques -> HttpTransportPool
|
||||
-> Accounts/Tokens/Cluster représentatifs
|
||||
-> trois reads Transactions
|
||||
-> getBlockHeight
|
||||
-> getInflationRate/getStakeMinimumDelegation
|
||||
Transport HTTP pur : settings programmatiques -> HttpTransportPool
|
||||
-> Accounts/Tokens/Cluster représentatifs
|
||||
-> trois reads Transactions
|
||||
-> getBlockHeight
|
||||
-> getInflationRate/getStakeMinimumDelegation
|
||||
|
||||
Transport WebSocket pur : settings programmatiques -> WsSession
|
||||
-> slotSubscribe
|
||||
-> une slotNotification sous timeout
|
||||
-> slotUnsubscribe
|
||||
-> close
|
||||
|
||||
Composition historique : Config -> std.transport/devnet_public -> HttpTransportPool
|
||||
-> getHealth/getGenesisHash/getVersion/getBalance
|
||||
```
|
||||
|
||||
Le smoke Transport utilise pour sa branche Token la forme Devnet documentée `getTokenAccountsByOwner(owner, { programId }, { commitment: finalized, encoding: jsonParsed })`. L'owner est une Pubkey ordinaire de l'exemple officiel ; aucune présence de token account n'est exigée, donc une liste vide reste valide.
|
||||
Le smoke HTTP Transport utilise pour sa branche Token la forme Devnet documentée `getTokenAccountsByOwner(owner, { programId }, { commitment: finalized, encoding: jsonParsed })`. L'owner est une Pubkey ordinaire de l'exemple officiel ; aucune présence de token account n'est exigée, donc une liste vide reste valide.
|
||||
|
||||
Les deux sont `ignored` par défaut. Le smoke Transport appartient durablement à cette crate ; le smoke cross-crates hébergé dans Config reste transitoire jusqu'à l'existence d'une surface KSP d'intégration/orchestration appropriée.
|
||||
Le smoke WebSocket Transport cible uniquement la famille stable `slotSubscribe` sur l'endpoint public Devnet `wss://api.devnet.solana.com`. Il borne connexion, attente de notification, unsubscribe et fermeture ; il ne transforme aucune famille unstable en gate live.
|
||||
|
||||
Les trois tests sont `ignored` par défaut. Les deux smokes Transport appartiennent durablement à cette crate ; le smoke cross-crates hébergé dans Config reste transitoire jusqu'à l'existence d'une surface KSP d'intégration/orchestration appropriée. Un rate-limit, refus externe ou incident Devnet n'est pas assimilé automatiquement à une régression locale.
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: crates/ksp-onchain-transport-lib/USAGE.md -->
|
||||
<!-- version: 17 -->
|
||||
<!-- version: 18 -->
|
||||
|
||||
# Utilisation de `ksp-onchain-transport-lib`
|
||||
|
||||
@@ -334,7 +334,7 @@ La configuration standard route les événements `info` de Transport vers un fic
|
||||
|
||||
## 10. Smokes Devnet opt-in
|
||||
|
||||
Le smoke **Transport pur** construit ses settings programmatiquement et exerce un sous-ensemble représentatif d'Accounts/Tokens/Cluster, trois reads Transactions, puis des reads Blocks/Economics de la release stable `0.2.4` :
|
||||
Le smoke **Transport HTTP pur** construit ses settings programmatiquement et exerce un sous-ensemble représentatif d'Accounts/Tokens/Cluster, trois reads Transactions, puis des reads Blocks/Economics de la release stable `0.2.4` :
|
||||
|
||||
```bash
|
||||
cargo test -p ksp-onchain-transport-lib --test transport_devnet_smoke -- --ignored --nocapture
|
||||
@@ -342,6 +342,14 @@ cargo test -p ksp-onchain-transport-lib --test transport_devnet_smoke -- --ignor
|
||||
|
||||
Il appelle `getAccountInfo`, `getTokenAccountsByOwner`, `getEpochInfo`, `getVoteAccounts`, puis `getLatestBlockhash`, `isBlockhashValid`, `getTransactionCount`, `getBlockHeight`, `getInflationRate` et `getStakeMinimumDelegation`. La branche Token suit la forme Devnet documentée : owner Pubkey ordinaire de l'exemple officiel, selector `programId` avec l'ID canonique du programme SPL Token, puis config explicite `commitment: finalized` + `encoding: jsonParsed`. Une réponse vide reste acceptable. La branche Transaction reste read-only : elle ne déclenche ni airdrop ni soumission de transaction et ne remplace pas les fixtures déterministes couvrant les 11 wrappers.
|
||||
|
||||
Le smoke **Transport WebSocket pur** utilise l'endpoint public Devnet standard avec des settings programmatiques, ouvre une session physique, crée une subscription stable `slotSubscribe`, attend une notification bornée, vérifie une valeur de slot non nulle, annule la subscription avec son handle puis ferme explicitement la session :
|
||||
|
||||
```bash
|
||||
cargo test -p ksp-onchain-transport-lib --test websocket_devnet_smoke -- --ignored --nocapture
|
||||
```
|
||||
|
||||
Il n'utilise ni `blockSubscribe`, ni `slotsUpdatesSubscribe`, ni `voteSubscribe` : ces familles restent unstable et leur disponibilité dépend des capabilities du validator. Le smoke live n'est donc pas un gate de disponibilité de ces extensions.
|
||||
|
||||
Le smoke historique de **composition Config -> Transport** reste également disponible :
|
||||
|
||||
```bash
|
||||
@@ -350,4 +358,14 @@ cargo test -p ksp-config-lib --test transport_devnet_smoke -- --ignored --nocapt
|
||||
|
||||
Il valide le profil committé `devnet_public` et les quatre canaris foundation. Il reste transitoirement hébergé dans Config : les futurs smokes cross-crates ne doivent pas faire de Config leur destination générale et devront migrer vers une surface d'intégration/orchestration dédiée lorsqu'elle existera.
|
||||
|
||||
Les endpoints publics Solana sont rate-limités et non destinés à la production. Un échec réseau externe n'est pas assimilé automatiquement à une régression locale ; les fixtures HTTP locales restent les gates reproductibles.
|
||||
Les endpoints publics Solana sont rate-limités et non destinés à la production. Un échec réseau externe n'est pas assimilé automatiquement à une régression locale ; les fixtures HTTP et WebSocket locales restent les gates reproductibles.
|
||||
|
||||
Pour l'audit final de dépendances de `0.2.7`, inspecter également le graphe effectif après résolution Cargo :
|
||||
|
||||
```bash
|
||||
cargo tree -p ksp-onchain-transport-lib
|
||||
cargo tree -p ksp-onchain-transport-lib --duplicates
|
||||
cargo tree --duplicates
|
||||
```
|
||||
|
||||
Le premier graphe doit conserver la frontière `Transport -> Core + Logging + crates techniques`; il ne doit introduire aucune dépendance Config, Wallet, Store, Program ou `tracing` directe. Les sorties `--duplicates` sont un diagnostic de résolution transitive : une duplication n'est pas supprimée aveuglément si elle est imposée par des dépendances upstream incompatibles.
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// file: crates/ksp-onchain-transport-lib/tests/websocket_devnet_smoke.rs
|
||||
// version: 1
|
||||
|
||||
//! Opt-in live Devnet smoke for one stable standard Solana WebSocket subscription.
|
||||
|
||||
fn devnet_websocket_endpoint() -> ksp_core_lib::Result<ksp_onchain_transport_lib::WsEndpointSettings> {
|
||||
let url_result = ksp_onchain_transport_lib::WsEndpointUrl::parse("wss://api.devnet.solana.com");
|
||||
let url = match url_result {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let session = ksp_onchain_transport_lib::WsSessionSettings::new(
|
||||
std::time::Duration::from_secs(10),
|
||||
std::time::Duration::from_secs(5),
|
||||
ksp_onchain_transport_lib::WsReconnectSettings::new(0, std::time::Duration::from_millis(250), std::time::Duration::from_secs(2)),
|
||||
ksp_onchain_transport_lib::WsResubscribePolicy::ActiveSubscriptions,
|
||||
16,
|
||||
16,
|
||||
8,
|
||||
8,
|
||||
4 * 1024 * 1024,
|
||||
4 * 1024 * 1024,
|
||||
256 * 1024,
|
||||
);
|
||||
return std::result::Result::Ok(ksp_onchain_transport_lib::WsEndpointSettings::new(
|
||||
"solana_devnet_public_ws",
|
||||
true,
|
||||
ksp_onchain_transport_lib::WsProviderName::new("solana-public"),
|
||||
ksp_onchain_transport_lib::WsClusterName::new("devnet"),
|
||||
ksp_onchain_transport_lib::WsProtocolKind::SolanaStandard,
|
||||
url,
|
||||
session,
|
||||
));
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
#[ignore = "opt-in live Solana Devnet WebSocket smoke; performs an external network connection"]
|
||||
async fn programmatic_devnet_websocket_reaches_slot_notification_then_unsubscribes_and_closes() {
|
||||
let endpoint = devnet_websocket_endpoint().expect("programmatic Devnet WebSocket settings must construct an endpoint");
|
||||
let session = ksp_onchain_transport_lib::WsSession::connect(endpoint).await.expect("Devnet WebSocket handshake must succeed");
|
||||
assert_eq!(session.snapshot().state(), ksp_onchain_transport_lib::WsSessionState::Active);
|
||||
let mut subscription = session.slot_subscribe().await.expect("Devnet slotSubscribe must succeed");
|
||||
assert_eq!(subscription.kind(), ksp_onchain_transport_lib::WsSubscriptionKind::Slot);
|
||||
assert_eq!(subscription.state(), ksp_onchain_transport_lib::WsSubscriptionState::Active);
|
||||
let notification_wait = tokio::time::timeout(std::time::Duration::from_secs(20), subscription.recv()).await;
|
||||
let notification = match notification_wait {
|
||||
std::result::Result::Ok(std::option::Option::Some(std::result::Result::Ok(value))) => value,
|
||||
std::result::Result::Ok(std::option::Option::Some(std::result::Result::Err(error))) => panic!("Devnet slot notification decoding failed: {error}"),
|
||||
std::result::Result::Ok(std::option::Option::None) => panic!("Devnet slot subscription closed before one notification arrived"),
|
||||
std::result::Result::Err(_) => panic!("Devnet slot notification did not arrive within the smoke timeout"),
|
||||
};
|
||||
assert!(notification.slot() > 0);
|
||||
let unsubscribed = subscription.unsubscribe().await.expect("Devnet slotUnsubscribe must succeed");
|
||||
assert!(unsubscribed);
|
||||
session.close().await.expect("Devnet WebSocket session must close cleanly");
|
||||
assert_eq!(session.snapshot().state(), ksp_onchain_transport_lib::WsSessionState::Closed);
|
||||
}
|
||||
99
deltas/0.2.7/pre.013.md
Normal file
99
deltas/0.2.7/pre.013.md
Normal file
@@ -0,0 +1,99 @@
|
||||
<!-- file: deltas/0.2.7/pre.013.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta `0.2.7-pre.013` — smoke WebSocket live et audit final des dépendances
|
||||
|
||||
## Base
|
||||
|
||||
Base directe validée par l'opérateur :
|
||||
|
||||
```text
|
||||
0.2.7-pre.012-fix.001
|
||||
Cargo 0.2.7-pre.12.fix.1
|
||||
```
|
||||
|
||||
Les gates `fmt`, audit Python, `check`, `clippy`, les 309 tests unitaires Transport, 36 tests d'API publique, 24 tests de release completeness, 109 tests unitaires Config et le workspace complet sont verts.
|
||||
|
||||
## Signal technique
|
||||
|
||||
```text
|
||||
livraison = 0.2.7-pre.013
|
||||
workspace.package.version = 0.2.7-pre.13
|
||||
commit = v0.2.7-pre.013
|
||||
tag = aucun
|
||||
```
|
||||
|
||||
## Smoke WebSocket Devnet opt-in
|
||||
|
||||
Un nouveau smoke Transport pur `websocket_devnet_smoke.rs` couvre le chemin live stable minimal :
|
||||
|
||||
```text
|
||||
settings programmatiques
|
||||
-> wss://api.devnet.solana.com
|
||||
-> WsSession::connect
|
||||
-> slotSubscribe
|
||||
-> une slotNotification sous timeout 20 s
|
||||
-> slotUnsubscribe via WsSubscription
|
||||
-> WsSession::close
|
||||
```
|
||||
|
||||
Le test est `#[ignore]` par défaut. Il ne lit ni Config ni environnement et n'utilise aucune famille unstable. Les fixtures WebSocket locales restent les gates déterministes du lifecycle, des DTOs et des familles `block`, `slotsUpdates` et `vote`.
|
||||
|
||||
Un échec lié au réseau, au rate-limit ou à l'indisponibilité Devnet ne constitue pas automatiquement une régression KSP.
|
||||
|
||||
## Audit de dépendances
|
||||
|
||||
Le canari workspace de `ksp-core-lib` verrouille désormais les noms directs de dépendances de Transport :
|
||||
|
||||
```text
|
||||
runtime : futures-util, ksp-core-lib, ksp-logging-lib, reqwest, serde, serde_json, tokio, tokio-tungstenite
|
||||
dev : tokio
|
||||
```
|
||||
|
||||
Il complète le firewall existant contre Config, Store, Program et `tracing` direct.
|
||||
|
||||
L'inspection du graphe résolu doit être faite côté opérateur :
|
||||
|
||||
```bash
|
||||
cargo tree -p ksp-onchain-transport-lib
|
||||
cargo tree -p ksp-onchain-transport-lib --duplicates
|
||||
cargo tree --duplicates
|
||||
```
|
||||
|
||||
Les doublons transitifs sont à analyser, pas à supprimer mécaniquement lorsqu'ils résultent de contraintes upstream différentes.
|
||||
|
||||
## Documentation
|
||||
|
||||
`README.md` et `USAGE.md` distinguent désormais les smokes HTTP Transport, WebSocket Transport et le smoke historique Config -> Transport. Le plan et la matrice enregistrent le checkpoint `pre.013`.
|
||||
|
||||
`ROADMAP.md` et `CHANGELOG.md` restent inchangés pendant cette prerelease.
|
||||
|
||||
## Comptages attendus
|
||||
|
||||
```text
|
||||
Transport unit tests = 309
|
||||
Transport public API tests = 36
|
||||
Transport release completeness = 24
|
||||
Transport WebSocket live smoke = 1 ignored par défaut
|
||||
Config unit tests = 109
|
||||
Core workspace dependency tests = 3
|
||||
```
|
||||
|
||||
## Validation opérateur
|
||||
|
||||
```bash
|
||||
cargo fmt --all
|
||||
python3 scripts/audit_rust_workspace_rules.py
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets
|
||||
cargo test -p ksp-onchain-transport-lib
|
||||
cargo test --workspace
|
||||
cargo tree -p ksp-onchain-transport-lib
|
||||
cargo tree -p ksp-onchain-transport-lib --duplicates
|
||||
cargo tree --duplicates
|
||||
cargo test -p ksp-onchain-transport-lib --test websocket_devnet_smoke -- --ignored --nocapture
|
||||
```
|
||||
|
||||
Le smoke live peut être qualifié séparément si Devnet est indisponible ; les autres gates restent déterministes.
|
||||
|
||||
Le sandbox de préparation ne possède pas Cargo/rustc ; les gates Cargo et le smoke live restent à exécuter côté opérateur.
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md -->
|
||||
<!-- version: 14 -->
|
||||
<!-- version: 15 -->
|
||||
|
||||
# Plan `0.2.7` — WebSocket Solana standard
|
||||
|
||||
@@ -947,6 +947,34 @@ Les noms JSON-RPC exacts restent verrouillés par le canari interne `websocket_s
|
||||
|
||||
La preuve Config -> session est volontairement déterministe : le future de connexion est construit à partir d'un `WsEndpointSettings` issu du document V2 committed sans polling. Aucun réseau réel n'est donc nécessaire ; le smoke live reste dans `pre.013`.
|
||||
|
||||
## 21.2 Checkpoint smoke live et dépendances `pre.013`
|
||||
|
||||
`pre.013` ne modifie pas le runtime WebSocket. Il ajoute le smoke live Transport pur retenu par le plan et ferme la documentation d'utilisation avant la validation workspace finale.
|
||||
|
||||
Le smoke est volontairement stable et minimal :
|
||||
|
||||
```text
|
||||
wss://api.devnet.solana.com
|
||||
-> WsSession::connect
|
||||
-> slotSubscribe
|
||||
-> une slotNotification sous timeout
|
||||
-> WsSubscription::unsubscribe
|
||||
-> WsSession::close
|
||||
```
|
||||
|
||||
Il est `#[ignore]` par défaut, utilise des settings programmatiques et n'accède ni à Config ni à l'environnement. Les trois familles unstable ne participent pas au smoke : leur activation dépend des capabilities du validator et un refus externe ne doit pas devenir une régression locale.
|
||||
|
||||
Le gate de dépendances est renforcé de deux façons :
|
||||
|
||||
```text
|
||||
source canary -> noms exacts des dépendances runtime/dev de ksp-onchain-transport-lib
|
||||
opérateur -> cargo tree Transport + cargo tree --duplicates local et workspace
|
||||
```
|
||||
|
||||
Le canari source interdit qu'une dépendance nouvelle se glisse silencieusement dans Transport. `cargo tree --duplicates` reste un diagnostic de résolution transitive : le gate demande inspection et justification, pas la suppression mécanique de doublons imposés par upstream.
|
||||
|
||||
README/USAGE documentent désormais les smokes HTTP/WS séparés, les limites du smoke live et les commandes d'audit du graphe Cargo.
|
||||
|
||||
## 22. Forecast recalibré
|
||||
|
||||
L'inventaire officiel n'impose que 9 familles de subscriptions, mais le lifecycle concurrent est plus coûteux que le forecast initial. Le gate reste **positif sans split de release**, à condition de granulariser les tranches au lieu de compresser le moteur et les wrappers.
|
||||
@@ -964,7 +992,7 @@ pre.009 DONE — wrappers stable lot A : account + program + logs, DTOs/options
|
||||
pre.010 DONE — wrappers stable lot B : signature + slot + root, terminaison signature/KSP-TRANSPORT-007
|
||||
pre.011 DONE — unstable : block + slotsUpdates + vote, warnings + fallbacks wire/KSP-TRANSPORT-007
|
||||
pre.012 DONE — compliance 18/18 + canaries public API + composition Config + régressions HTTP
|
||||
pre.013 smoke live opt-in + README/USAGE + cargo tree/duplicates + dependency audit final
|
||||
pre.013 DONE — smoke live opt-in + README/USAGE + source dependency canary + cargo tree/duplicates opérateur
|
||||
pre.014 validation workspace finale + docs/compliance + prompt 0.2.8
|
||||
rel.001 publication stable stricte
|
||||
```
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<!-- file: docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md -->
|
||||
<!-- version: 14 -->
|
||||
<!-- version: 15 -->
|
||||
|
||||
# Validation `0.2.7` — WebSocket Solana standard
|
||||
|
||||
> **Statut : matrice active, `0.2.7-pre.012`.** Les 9 familles standard et leurs 9 opérations unsubscribe sont matérialisées. `pre.012` consolide la compliance 18/18, la surface publique, la composition Config V2 -> Transport et la non-régression HTTP avant le smoke/audit de dépendances final.
|
||||
> **Statut : matrice active, `0.2.7-pre.013`.** La compliance 18/18 est acquise. `pre.013` ajoute le smoke WebSocket Devnet opt-in, synchronise README/USAGE et renforce le gate de dépendances avant la validation workspace finale.
|
||||
|
||||
## 1. Baseline normative
|
||||
|
||||
@@ -206,33 +206,35 @@ Les votes observés sont gossip/pre-consensus ; aucune garantie d'entrée dans l
|
||||
|
||||
## 7. Threat/security compliance initiale
|
||||
|
||||
| Invariant | Preuve attendue | Statut |
|
||||
|---------------------------------------------------|----------------------------------------------|------------------------------------------|
|
||||
| URL/credentials absents de `Debug` | unit tests URL wrapper | **Done `pre.002`** |
|
||||
| URL/credentials absents des erreurs | validation URL + connection errors safe | **Done through `pre.004`** |
|
||||
| URL/credentials absents des logs | actor logs only safe endpoint metadata | Partial `pre.004`, capture finale future |
|
||||
| snapshots sans URL/raw payload | unit shape + public contract | **Done `pre.002`** |
|
||||
| frame/message finis | settings bornés + `WebSocketConfig` raccordé | **Done `pre.005`** |
|
||||
| JSON borné indirectement par message | oversized + malformed fixture | **Done `pre.005`** |
|
||||
| queues notifications bornées | queue typed bornée + overflow isolé | **Done `pre.008`** |
|
||||
| pending RPC borné + timeout | map actor bornée + timeout request | **Done `pre.004`** |
|
||||
| reconnect loop bornée | repeated disconnect fixture | Done `pre.007` |
|
||||
| unsubscribe pendant reconnect ne resubscribe pas | race fixture | Done `pre.007` |
|
||||
| signature terminale ne resubscribe pas | terminal fixture | Planned |
|
||||
| shutdown ne bloque pas | peer hostile/no close ack fixture | **Done `pre.005`** |
|
||||
| no Store/Program/Wallet/Config dep dans Transport | cargo tree + source canary | Planned |
|
||||
| no direct `tracing` dans Transport | workspace audit + source audit | **Done `pre.002`** |
|
||||
| Invariant | Preuve attendue | Statut |
|
||||
|---------------------------------------------------|----------------------------------------------|--------------------------------------------------------|
|
||||
| URL/credentials absents de `Debug` | unit tests URL wrapper | **Done `pre.002`** |
|
||||
| URL/credentials absents des erreurs | validation URL + connection errors safe | **Done through `pre.004`** |
|
||||
| URL/credentials absents des logs | actor logs only safe endpoint metadata | **Done through `pre.011`, source audit `pre.013`** |
|
||||
| snapshots sans URL/raw payload | unit shape + public contract | **Done `pre.002`** |
|
||||
| frame/message finis | settings bornés + `WebSocketConfig` raccordé | **Done `pre.005`** |
|
||||
| JSON borné indirectement par message | oversized + malformed fixture | **Done `pre.005`** |
|
||||
| queues notifications bornées | queue typed bornée + overflow isolé | **Done `pre.008`** |
|
||||
| pending RPC borné + timeout | map actor bornée + timeout request | **Done `pre.004`** |
|
||||
| reconnect loop bornée | repeated disconnect fixture | Done `pre.007` |
|
||||
| unsubscribe pendant reconnect ne resubscribe pas | race fixture | Done `pre.007` |
|
||||
| signature terminale ne resubscribe pas | terminal fixture | **Done `pre.010`** |
|
||||
| shutdown ne bloque pas | peer hostile/no close ack fixture | **Done `pre.005`** |
|
||||
| no Store/Program/Wallet/Config dep dans Transport | cargo tree + source canary | **Source gate `pre.013`, cargo tree opérateur requis** |
|
||||
| no direct `tracing` dans Transport | workspace audit + source audit | **Done `pre.002`** |
|
||||
|
||||
## 8. Dependency compliance initiale
|
||||
|
||||
Candidate retenue au gate :
|
||||
Candidates auditées à l'ouverture de release :
|
||||
|
||||
```text
|
||||
tokio-tungstenite 0.30.0
|
||||
futures-util 0.3.34
|
||||
tokio-tungstenite 0.30.x
|
||||
futures-util 0.3.x
|
||||
```
|
||||
|
||||
Features prévues :
|
||||
Le workspace conserve des contraintes caret `^0.30` et `^0.3` sans lockfile versionné. La version transitive effectivement résolue n'est donc pas figée dans cette matrice ; `pre.013` exige l'inspection du `cargo tree` opérateur correspondant au checkout validé.
|
||||
|
||||
Features retenues :
|
||||
|
||||
```text
|
||||
tokio-tungstenite: default-features=false + connect + rustls-tls-webpki-roots
|
||||
@@ -642,6 +644,50 @@ Transport release completeness = 24
|
||||
Config unit tests = 109
|
||||
```
|
||||
|
||||
## 9.11 Checkpoint smoke live et audit de dépendances `pre.013`
|
||||
|
||||
Le smoke WebSocket live retenu est un test Transport pur `#[ignore]` qui ne lit ni Config ni environnement :
|
||||
|
||||
```text
|
||||
endpoint programmatique wss://api.devnet.solana.com
|
||||
WsSession::connect
|
||||
slotSubscribe stable
|
||||
attente bornée d'une slotNotification
|
||||
slot > 0
|
||||
slotUnsubscribe via handle
|
||||
close explicite de la session
|
||||
```
|
||||
|
||||
Les familles `block`, `slotsUpdates` et `vote` ne sont pas utilisées dans ce smoke car leur disponibilité dépend de capabilities validator unstable. Les fixtures locales restent les preuves reproductibles de ces familles et du lifecycle.
|
||||
|
||||
Le canari workspace de dépendances verrouille désormais les noms directs de Transport :
|
||||
|
||||
```text
|
||||
runtime : futures-util, ksp-core-lib, ksp-logging-lib, reqwest, serde, serde_json, tokio, tokio-tungstenite
|
||||
dev : tokio
|
||||
```
|
||||
|
||||
Il complète le firewall existant contre Config/Store/Program/tracing direct. L'inspection du graphe résolu reste une preuve opérateur avec :
|
||||
|
||||
```bash
|
||||
cargo tree -p ksp-onchain-transport-lib
|
||||
cargo tree -p ksp-onchain-transport-lib --duplicates
|
||||
cargo tree --duplicates
|
||||
```
|
||||
|
||||
Une duplication transitive n'est pas considérée automatiquement comme un défaut : elle doit être comprise et n'est supprimée que si KSP peut la résoudre sans downgrade, pin artificiel ou violation des responsabilités upstream.
|
||||
|
||||
Comptages déterministes attendus inchangés côté Transport, plus un smoke live ignoré et un canari workspace supplémentaire dans Core :
|
||||
|
||||
```text
|
||||
Transport unit tests = 309
|
||||
Transport public API tests = 36
|
||||
Transport release completeness = 24
|
||||
Transport WebSocket live smoke = 1 ignored par défaut
|
||||
Config unit tests = 109
|
||||
Core workspace dependency tests = 3
|
||||
```
|
||||
|
||||
## 10. Validation du gate `pre.001`
|
||||
|
||||
Exécuté dans le sandbox :
|
||||
@@ -689,9 +735,9 @@ reconnect/resubscribe/backpressure/shutdown gates verts
|
||||
unstable warnings centralisés
|
||||
HTTP 52+14 non régressé (**Done `pre.012`**)
|
||||
Config V1 backward + V2 WS validés (**Done `pre.003`**, compilation opérateur requise)
|
||||
smoke live opt-in documenté
|
||||
cargo tree inspecté
|
||||
smoke live opt-in documenté (**Done `pre.013`**)
|
||||
cargo tree inspecté (**preuve opérateur `pre.013` requise**)
|
||||
cargo test --workspace vert
|
||||
README/USAGE synchronisés
|
||||
README/USAGE synchronisés (**Done `pre.013`**)
|
||||
prompt 0.2.8 préparé
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user