v0.2.7-pre.012

This commit is contained in:
2026-08-23 09:40:44 +02:00
parent 66deaf8245
commit 628b4f12f2
7 changed files with 229 additions and 15 deletions

View File

@@ -1,12 +1,12 @@
# file: Cargo.toml
# version: 211
# version: 212
[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.11.fix.1"
version = "0.2.7-pre.12"
edition = "2024"
license = "MIT"
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-config-lib/unit_tests/transport.rs
// version: 3
// version: 4
#[test]
fn fixture_transport_profile_maps_complete_runtime_contract() {
@@ -122,6 +122,30 @@ fn committed_transport_document_maps_default_and_explicit_profiles() {
}
}
#[test]
fn committed_v2_websocket_endpoint_composes_with_public_session_constructor_without_polling() {
let engine = committed_engine();
let engine = match engine {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let environment = crate::ConfigEnvironment::from_maps(std::collections::BTreeMap::new(), std::collections::BTreeMap::new());
let resolved = engine.load_resolved_transport_config(std::option::Option::Some("devnet_public"), &environment);
assert!(resolved.is_ok(), "committed V2 Transport profile should map: {resolved:?}");
if let std::result::Result::Ok(resolved) = resolved {
let (http, ws) = resolved.into_transport_settings();
assert_eq!(http.endpoints().len(), 1);
assert!(ws.is_some(), "committed V2 Transport profile should expose WebSocket settings");
if let std::option::Option::Some(ws) = ws {
assert!(ws.validate().is_ok(), "Config-produced WebSocket settings should satisfy Transport validation");
assert_eq!(ws.endpoints().len(), 1);
let endpoint = ws.endpoints()[0].clone();
assert_eq!(endpoint.protocol(), ksp_onchain_transport_lib::WsProtocolKind::SolanaStandard);
let _connect_future = ksp_onchain_transport_lib::WsSession::connect(endpoint);
}
}
}
#[test]
fn transport_profile_preserves_global_and_profile_origin() {
let engine = committed_engine();

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/tests/public_api.rs
// version: 32
// version: 33
//! Integration tests for the public `ksp-onchain-transport-lib` consumer contract.
@@ -650,3 +650,29 @@ fn public_v0_2_7_pre_011_unstable_websocket_wrappers_and_dtos_are_available_from
let _slot_update_stats = std::any::type_name::<ksp_onchain_transport_lib::SolanaSlotUpdateStats>();
let _vote_notification = std::any::type_name::<ksp_onchain_transport_lib::SolanaVoteNotification>();
}
#[test]
fn public_v0_2_7_pre_012_complete_standard_websocket_surface_is_available_from_crate_root() {
let _account = ksp_onchain_transport_lib::WsSession::account_subscribe;
let _block = ksp_onchain_transport_lib::WsSession::block_subscribe;
let _logs = ksp_onchain_transport_lib::WsSession::logs_subscribe;
let _program = ksp_onchain_transport_lib::WsSession::program_subscribe;
let _root = ksp_onchain_transport_lib::WsSession::root_subscribe;
let _signature = ksp_onchain_transport_lib::WsSession::signature_subscribe;
let _slot = ksp_onchain_transport_lib::WsSession::slot_subscribe;
let _slots_updates = ksp_onchain_transport_lib::WsSession::slots_updates_subscribe;
let _vote = ksp_onchain_transport_lib::WsSession::vote_subscribe;
let _unsubscribe = ksp_onchain_transport_lib::WsSubscription::<serde_json::Value>::unsubscribe;
let kinds = [
ksp_onchain_transport_lib::WsSubscriptionKind::Account,
ksp_onchain_transport_lib::WsSubscriptionKind::Block,
ksp_onchain_transport_lib::WsSubscriptionKind::Logs,
ksp_onchain_transport_lib::WsSubscriptionKind::Program,
ksp_onchain_transport_lib::WsSubscriptionKind::Root,
ksp_onchain_transport_lib::WsSubscriptionKind::Signature,
ksp_onchain_transport_lib::WsSubscriptionKind::Slot,
ksp_onchain_transport_lib::WsSubscriptionKind::SlotsUpdates,
ksp_onchain_transport_lib::WsSubscriptionKind::Vote,
];
assert_eq!(kinds.len(), 9);
}

View File

@@ -1,7 +1,7 @@
// file: crates/ksp-onchain-transport-lib/tests/release_completeness.rs
// version: 22
// version: 23
//! Release-level completeness canaries for the staged HTTP wrapper sequence.
//! Release-level completeness canaries for staged HTTP and WebSocket Transport coverage.
#[test]
fn release_registry_partition_matches_the_audited_http_plan() {
@@ -730,3 +730,42 @@ fn release_v0_2_4_pre_009_final_http_inventory_and_coverage_partition_are_exact(
assert_eq!((v0_2_1, v0_2_2, v0_2_3, v0_2_4), (4, 22, 11, 15));
assert_eq!(historical_current, 0);
}
#[test]
fn release_v0_2_7_pre_012_websocket_surface_accounts_for_all_nine_standard_pairs() {
let kinds = [
ksp_onchain_transport_lib::WsSubscriptionKind::Account,
ksp_onchain_transport_lib::WsSubscriptionKind::Block,
ksp_onchain_transport_lib::WsSubscriptionKind::Logs,
ksp_onchain_transport_lib::WsSubscriptionKind::Program,
ksp_onchain_transport_lib::WsSubscriptionKind::Root,
ksp_onchain_transport_lib::WsSubscriptionKind::Signature,
ksp_onchain_transport_lib::WsSubscriptionKind::Slot,
ksp_onchain_transport_lib::WsSubscriptionKind::SlotsUpdates,
ksp_onchain_transport_lib::WsSubscriptionKind::Vote,
];
let expected_names = ["account", "block", "logs", "program", "root", "signature", "slot", "slots_updates", "vote"];
let actual_names = kinds.map(ksp_onchain_transport_lib::WsSubscriptionKind::as_str);
assert_eq!(actual_names, expected_names);
assert_eq!(kinds.len() * 2, 18);
let _account = ksp_onchain_transport_lib::WsSession::account_subscribe;
let _block = ksp_onchain_transport_lib::WsSession::block_subscribe;
let _logs = ksp_onchain_transport_lib::WsSession::logs_subscribe;
let _program = ksp_onchain_transport_lib::WsSession::program_subscribe;
let _root = ksp_onchain_transport_lib::WsSession::root_subscribe;
let _signature = ksp_onchain_transport_lib::WsSession::signature_subscribe;
let _slot = ksp_onchain_transport_lib::WsSession::slot_subscribe;
let _slots_updates = ksp_onchain_transport_lib::WsSession::slots_updates_subscribe;
let _vote = ksp_onchain_transport_lib::WsSession::vote_subscribe;
let _unsubscribe = ksp_onchain_transport_lib::WsSubscription::<serde_json::Value>::unsubscribe;
}
#[test]
fn release_v0_2_7_pre_012_http_inventory_remains_52_current_plus_14_historical() {
let current = ksp_onchain_transport_lib::current_http_rpc_methods();
let historical = ksp_onchain_transport_lib::historical_http_rpc_methods();
assert_eq!(current.len(), 52);
assert_eq!(historical.len(), 14);
assert!(current.iter().all(|descriptor| descriptor.runtime_status() == ksp_onchain_transport_lib::RpcRuntimeStatus::Supported));
assert!(historical.iter().all(|descriptor| descriptor.runtime_status() == ksp_onchain_transport_lib::RpcRuntimeStatus::Removed));
}

77
deltas/0.2.7/pre.012.md Normal file
View File

@@ -0,0 +1,77 @@
<!-- file: deltas/0.2.7/pre.012.md -->
<!-- version: 1 -->
# Delta `0.2.7-pre.012` — compliance WebSocket 18/18
## Signal technique
```text
delivery = 0.2.7-pre.012
workspace.package.version = 0.2.7-pre.12
commit = v0.2.7-pre.012
tag = aucun
```
## Objet
Cette tranche ne crée aucune nouvelle famille WebSocket et ne modifie pas le runtime actor. Elle consolide les acquis `pre.002` à `pre.011` en gates de release explicites avant le smoke live et l'audit de dépendances final de `pre.013`.
## Compliance WebSocket
Le gate de release couvre désormais explicitement :
```text
9 familles standard WsSubscriptionKind
9 wrappers subscribe publics
9 opérations unsubscribe via WsSubscription<T>::unsubscribe
18 opérations subscribe/unsubscribe standard comptabilisées
triplets JSON-RPC exacts déjà verrouillés par ws_lifecycle
3 familles unstable exactes : block, slotsUpdates, vote
```
Aucune primitive publique `subscribe(method, raw_params)` n'est ajoutée.
## Composition Config -> Transport
Un canari déterministe Config charge le profil V2 committed `devnet_public`, récupère les settings HTTP + WebSocket, valide `WsTransportSettings`, clone le `WsEndpointSettings` produit par Config puis construit le future `WsSession::connect(endpoint)`.
Le future reste volontairement non pollé : le test vérifie la compatibilité réelle des contrats Config -> Transport sans effectuer de connexion réseau. Le smoke live reste réservé à `pre.013`.
## Régression HTTP
Un gate de release supplémentaire confirme :
```text
52 méthodes HTTP courantes -> Supported
14 méthodes HTTP historiques -> Removed
```
Le canari exhaustif `0.2.4-pre.009` reste également présent et continue de verrouiller les noms exacts, statuts, partitions de release et classes de retry HTTP.
## Documentation
`docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md` enregistre le checkpoint `pre.012` et les comptages attendus.
`docs/plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md` marque `pre.012` comme réalisé dans le forecast. `ROADMAP.md` et `CHANGELOG.md` restent volontairement inchangés pendant cette prerelease.
## Comptages attendus
```text
Transport unit tests = 309
Transport public API tests = 36
Transport release completeness = 24
Config public API tests = 16
```
## 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
```
Le sandbox de préparation ne possède pas Cargo/rustc ; les gates Cargo restent donc à exécuter côté opérateur.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md -->
<!-- version: 13 -->
<!-- version: 14 -->
# Plan `0.2.7` — WebSocket Solana standard
@@ -932,6 +932,21 @@ public raw provider-extension API -> gate 0.2.8
application heartbeat/ping périodique -> différé sans besoin démontré
```
## 21.1 Checkpoint compliance `pre.012`
La tranche `pre.012` ne crée pas de dixième famille et ne modifie pas le runtime actor. Elle consolide la release autour de quatre preuves :
```text
WebSocket inventory -> 9 familles publiques x subscribe/unsubscribe = 18 opérations standard
public API -> 9 wrappers subscribe + handle unsubscribe accessibles depuis la crate root
Config composition -> V2 -> WsTransportSettings -> WsEndpointSettings accepté par WsSession::connect
HTTP regression -> 52 current Supported + 14 historical Removed inchangés
```
Les noms JSON-RPC exacts restent verrouillés par le canari interne `websocket_subscription_kinds_map_exact_standard_method_triplets`; la partition unstable reste verrouillée séparément à `block`, `slotsUpdates`, `vote`. `pre.012` ajoute un canari de release qui compte les neuf paires et un canari public qui adresse les neuf wrappers sans exposer de primitive raw arbitraire.
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`.
## 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.
@@ -948,7 +963,7 @@ pre.008 DONE — backpressure per-sub + overflow/limits + causes terminales sû
pre.009 DONE — wrappers stable lot A : account + program + logs, DTOs/options/KSP-TRANSPORT-007
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 compliance 18/18 + canaries public API + composition Config + régressions HTTP
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.014 validation workspace finale + docs/compliance + prompt 0.2.8
rel.001 publication stable stricte

View File

@@ -1,9 +1,9 @@
<!-- file: docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md -->
<!-- version: 13 -->
<!-- version: 14 -->
# Validation `0.2.7` — WebSocket Solana standard
> **Statut : matrice active, `0.2.7-pre.010`.** Settings/lifecycle `pre.002`, Config V2 `pre.003`, session physique `pre.004`, durcissement `pre.005`, registry `pre.006`, reconnect/resubscribe `pre.007`, backpressure `pre.008` et les six familles stables des lots `pre.009``pre.010` sont matérialisés. Les trois familles unstable restent ouvertes pour `pre.011`.
> **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.
## 1. Baseline normative
@@ -410,7 +410,6 @@ snapshot -> local IDs + remote_bound uniquement
Le registry est détenu par le même actor que le socket et la pending map JSON-RPC. Aucun caller ne manipule le socket ni le remote ID. Les wrappers publics `accountSubscribe`, `programSubscribe`, etc. restent volontairement différés aux lots `pre.009+` afin de ne pas exposer une API raw provider-extension intermédiaire.
## 9.5 Checkpoint reconnect/resubscribe `pre.007`
Surface matérialisée :
@@ -609,6 +608,40 @@ Transport public API tests = 35
release completeness = 22
```
## 9.10 Checkpoint compliance consolidée `pre.012`
`pre.012` n'ajoute aucune nouvelle famille WebSocket. Il transforme les preuves acquises de `pre.002` à `pre.011` en gates de release explicites et vérifie simultanément que la surface HTTP héritée reste intacte.
Le réaudit de l'index public Solana effectué le **23 août 2026** confirme que la surface courante reste inchangée à 9 subscribe + 9 unsubscribe.
Gates ajoutés ou consolidés :
```text
9 WsSubscriptionKind publics exactement couverts
9 wrappers subscribe publics disponibles depuis la crate root
1 handle WsSubscription<T>::unsubscribe commun aux 9 familles
9 paires subscribe/unsubscribe = 18 opérations standard comptabilisées
triplets exacts subscribe/unsubscribe/notification toujours verrouillés par le canari ws_lifecycle
partition unstable exacte toujours verrouillée : block + slotsUpdates + vote
Config V2 committed -> ResolvedTransportConfig -> WsTransportSettings validé
WsEndpointSettings produit par Config -> type accepté directement par WsSession::connect
Config V1 -> HTTP-only reste couvert par le checkpoint pre.003
HTTP courant -> 52 méthodes Supported
HTTP historique -> 14 méthodes Removed
surface API publique WebSocket complète -> canari crate-root dédié
```
La composition Config est testée sans réseau : l'async future `WsSession::connect` est construite à partir de l'endpoint produit par Config et laissée non pollée jusqu'à sa destruction en fin de portée. Le gate vérifie donc la compatibilité de types et de contrats entre Config et Transport sans transformer `pre.012` en smoke live ; le vrai smoke reste réservé à `pre.013`.
Comptages attendus après compilation :
```text
Transport unit tests = 309
Transport public API tests = 36
Transport release completeness = 24
Config unit tests = 109
```
## 10. Validation du gate `pre.001`
Exécuté dans le sandbox :
@@ -645,16 +678,16 @@ La matrice ne considère donc pas `pre.001` techniquement validé par Cargo tant
Avant `rel.001`, cette matrice doit obtenir :
```text
18/18 méthodes official-index accounted
9/9 subscribe wrappers public typed
9/9 unsubscribe couverts par handles/registry
18/18 méthodes official-index accounted (**Done `pre.012`**)
9/9 subscribe wrappers public typed (**Done `pre.012`**)
9/9 unsubscribe couverts par handles/registry (**Done `pre.012`**)
0 option officielle perdue
0 fuite URL/credential
N sessions same URL prouvé
N subscriptions same session prouvé
reconnect/resubscribe/backpressure/shutdown gates verts
unstable warnings centralisés
HTTP 52+14 non régressé
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é