v0.2.8-pre.002-fix.001

This commit is contained in:
2026-08-23 13:22:19 +02:00
parent 0871b85df9
commit c94a54f3e3
5 changed files with 647 additions and 403 deletions

View File

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

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/unit_tests/ws_protocol_session.rs
// version: 1
// version: 2
use futures_util::StreamExt; // rust-rules: trait-import
@@ -30,6 +30,7 @@ async fn accept_until_close(listener: tokio::net::TcpListener) {
return;
}
}
return;
}
#[tokio::test]
@@ -62,11 +63,11 @@ async fn historical_generic_constructor_remains_standard_only_before_network_io(
let error = crate::WsSession::connect(endpoint).await.expect_err("generic historical constructor must reject Helius protocol");
assert_eq!(error.code(), crate::ERROR_CODE_INVALID_SETTINGS);
assert_eq!(
error.context().iter().find(|entry| entry.key() == "expected_protocol").map(|entry| entry.value()),
error.context().iter().find(|entry| return entry.key() == "expected_protocol").map(|entry| return entry.value()),
std::option::Option::Some("solana_standard")
);
assert_eq!(
error.context().iter().find(|entry| entry.key() == "actual_protocol").map(|entry| entry.value()),
error.context().iter().find(|entry| return entry.key() == "actual_protocol").map(|entry| return entry.value()),
std::option::Option::Some("helius_laserstream")
);
}

View File

@@ -0,0 +1,250 @@
<!-- file: deltas/0.2.8/pre.002-fix.001.md -->
<!-- version: 1 -->
# Delta `0.2.8-pre.002-fix.001` — Clippy et normalisation documentaire
## 1. Objet
Ce correctif ferme le défaut Clippy observé après application de `0.2.8-pre.002` et audite l'organisation des documents actifs `0.2.8` afin d'éviter les sections désordonnées ou les fichiers fourre-tout.
La livraison `pre.002.md` reste immutable ; ce fix porte uniquement les corrections nouvelles.
Version workspace :
```text
0.2.8-pre.2.fix.1
```
Livraison / commit attendu :
```text
0.2.8-pre.002-fix.001
v0.2.8-pre.002-fix.001
```
Aucun tag prerelease.
## 2. Clippy : défaut reproduit par l'opérateur
Le checkpoint opérateur de `pre.002` a donné :
```text
cargo fmt --all OK
python3 scripts/audit_rust_workspace_rules.py clean
cargo check --workspace OK
cargo clippy --workspace --all-targets FAIL
cargo test -p ksp-onchain-transport-lib OK
cargo test --workspace OK
```
Le seul blocage est `clippy::implicit_return` dans le nouveau fichier :
```text
crates/ksp-onchain-transport-lib/unit_tests/ws_protocol_session.rs
```
Cinq diagnostics sont concernés :
```text
1 retour explicite manquant après la boucle `while let` de `accept_until_close`
2 predicates `find` sans `return` explicite
2 closures `map` sans `return` explicite
```
Le runtime WebSocket, les façades protocolaires et les tests fonctionnels ne sont pas en échec : le ciblé Transport et le workspace complet passent avant ce fix.
## 3. Correction Rust
Le fix ajoute uniquement les retours explicites exigés par la politique Clippy KSP dans la fixture de test.
Aucun changement n'est apporté à :
```text
WsSession
SolanaStandardWsSession
HeliusLaserStreamWsSession
WsProtocolKind
wire WebSocket
reconnect/backpressure/shutdown
Config
transactionSubscribe
heartbeat
```
Comme le correctif modifie du code de test consommé par le build, Cargo passe conformément à `VERSION_WORKFLOW.md` de :
```text
0.2.8-pre.2
```
à :
```text
0.2.8-pre.2.fix.1
```
## 4. Audit structurel des documents
Références appliquées :
```text
docs/rules/RULES_DOCUMENTATION.md
docs/rules/FILE_CONTRACTS.md
docs/plans/000-README.md
docs/validation/000-README.md
```
Constats :
```text
docs/plans : 000-README puis 001..015, ordre cohérent, aucune collision
docs/validation : 000-README puis 001..011, ordre cohérent, aucune collision
plan 015 : une seule responsabilité, planifier/auditer la release 0.2.8
validation 011 : une seule responsabilité, conserver critères/matrices/preuves 0.2.8
deltas/0.2.8 : journal de livraison séparé, aucun second changelog dans docs/
```
Aucun nouveau répertoire ou fichier documentaire durable n'est nécessaire. Les plans historiques `0.2.5` à `0.2.7` sont de taille comparable ou supérieure ; la taille du plan `015` ne justifie donc pas à elle seule un split.
Deux défauts d'organisation internes sont toutefois corrigés :
1. le plan présentait les décisions de façade dans une première section puis des décisions d'architecture détaillées beaucoup plus loin ; elles sont regroupées dans une seule section `Architecture et frontières de protocole` ;
2. la validation répétait le forecast détaillé alors que `FILE_CONTRACTS.md` attribue cette responsabilité au plan ; cette duplication est supprimée.
L'ordre du plan actif devient :
```text
état courant
forecast souple
sources / baseline
héritage v0.2.7
audit Helius
matrice normative
architecture et frontières
threat model
dépendances
stratégie de validation / smoke
questions reportées
critères de split / clôture
checkpoint courant
```
La validation reste organisée autour de :
```text
références
gate pre.001
matrices provider/façades
contrat transaction à valider
checklists lifecycle/non-régression/sécurité
smoke
preuves pre.002/fix
contrôle structurel docs
```
## 5. État de validation `pre.002` reporté correctement
Les preuves opérateur reçues sont intégrées à `docs/validation/011-*` :
```text
Transport unit tests 313 passed
Transport public API tests 37 passed
release completeness 25 passed
doctor tests compile_fail 2 passed
cargo test -p Transport OK
cargo test --workspace OK
```
Le seul gate restant à revalider après application du fix est la chaîne complète, en particulier Clippy.
## 6. Fichiers de la livraison
Nouveau :
```text
deltas/0.2.8/pre.002-fix.001.md
```
Modifiés :
```text
Cargo.toml
crates/ksp-onchain-transport-lib/unit_tests/ws_protocol_session.rs
docs/plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md
docs/validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md
```
Aucun autre fichier n'est nécessaire.
## 7. Validations exécutées dans le sandbox de préparation
Exécuté après le fix :
```text
python3 scripts/audit_rust_workspace_rules.py
General Rust rule audit: clean
Rust export completeness audit: 0 candidate(s)
KSP workspace Rust rule audit: clean
```
Audit structurel local des documents :
```text
DOC STRUCTURE AUDIT: clean
docs/plans = 000..015 ordonné
docs/validation = 000..011 ordonné
H2/H3 plan actif = cohérent
H2/H3 validation = cohérent
```
Le sandbox ne fournit pas Cargo/rustfmt ; aucune commande Cargo n'est donc déclarée réussie pour le fix lui-même.
## 8. Gate opérateur
Après application :
```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
```
Attendu :
```text
aucun `clippy::implicit_return`
aucun warning Rust
313+ tests Transport hérités/pré.002 verts
37+ public API verts
25+ release completeness verts
2 doctests compile_fail verts
workspace complet vert
```
Si ce checkpoint est vert, `pre.002` + `pre.002-fix.001` sont `DONE` et `pre.003` peut commencer.
## 9. Suite
`pre.003` reste inchangé : ajouter uniquement sur `HeliusLaserStreamWsSession` les six familles standard Helius supportées :
```text
account
logs
program
root
signature
slot
```
avec réutilisation du wire standard et absence durable de :
```text
block
slotsUpdates
vote
```
Config Helius, `transactionSubscribe` et heartbeat restent hors `pre.003` conformément au forecast.

View File

@@ -1,263 +1,40 @@
<!-- file: docs/plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md -->
<!-- version: 6 -->
<!-- version: 7 -->
# Plan `0.2.8` — Helius LaserStream WebSocket
> **Statut : `0.2.8-pre.002` matérialise le socle protocolaire décidé par le gate `pre.001`.** Le moteur physique `WsSession` de `0.2.7` reste unique et partagé ; `SolanaStandardWsSession` devient la façade standard explicite et `HeliusLaserStreamWsSession` ouvre le lifecycle Helius LaserStream WebSocket sans encore exposer ses subscriptions. Le constructeur historique `WsSession::connect` reste standard-only et les six wrappers Helius communs restent réservés à `pre.003`.
> **Statut : `0.2.8-pre.002` est appliqué et testé, mais son gate Clippy requiert `pre.002-fix.001`.** Les tests Transport et workspace sont verts ; le fix corrige cinq `clippy::implicit_return` dans la nouvelle fixture protocolaire, passe Cargo à `0.2.8-pre.2.fix.1` et réorganise les documents actifs pour garder une séparation nette entre plan, validation et delta. Le moteur physique `WsSession` reste unique et partagé.
## 1. Objet, base et état du gate
## 1. Objet, base et état courant
`0.2.8` étend le moteur WebSocket publié par `0.2.7` avec la surface Helius LaserStream WebSocket réellement documentée, sans créer un second moteur/session actor et sans confondre WebSocket avec LaserStream gRPC.
Base autoritaire auditée :
Base autoritaire auditée à l'ouverture :
```text
archive fournie : khadhroony-solana-project-v0.2.7-full-from-gitea.zip
workspace.package.version avant ouverture = 0.2.7
delta stable présent = deltas/0.2.7/rel.001.md
prompt actif présent = prompts/013-V0_2_8_START_PROMPT.md
Git metadata dans l'archive = absente ; le tag n'est donc pas revalidable localement avec git
v0.2.7
workspace.package.version initial = 0.2.7
deltas/0.2.7/rel.001.md présent
prompts/013-V0_2_8_START_PROMPT.md présent
```
`0.2.8-pre.001` a ouvert techniquement :
État des livraisons :
```text
workspace.package.version = 0.2.8-pre.1
livraison = 0.2.8-pre.001
```
pre.001 gate audit/sizing Helius
pre.001-fix.001 séparation des façades + fermeture gate Cargo
pre.001-fix.002 forecast compact + namespace LaserStream WS/gRPC
pre.002 socle protocolaire appliqué ; tests verts, Clippy en échec ciblé
pre.002-fix.001 correction Clippy + audit/normalisation structure documentaire
Correctifs documentaires appliqués à `pre.001` :
```text
0.2.8-pre.001-fix.001 séparation des façades protocolaires + fermeture du gate Cargo
0.2.8-pre.001-fix.002 normalisation du forecast + clarification LaserStream WebSocket/gRPC
livraison précédente = 0.2.8-pre.001-fix.002
livraison courante = 0.2.8-pre.002
workspace.package.version = 0.2.8-pre.2
commit attendu = v0.2.8-pre.002
workspace.package.version courant = 0.2.8-pre.2.fix.1
commit attendu = v0.2.8-pre.002-fix.001
aucun tag prerelease
```
Les deux graphes Cargo manquants lors de la préparation initiale ont été fournis par l'opérateur le 2026-08-23 :
Le log opérateur de `pre.002` confirme : `cargo fmt`, audit Rust et `cargo check --workspace` verts ; `cargo test -p ksp-onchain-transport-lib` et `cargo test --workspace` verts ; `cargo clippy --workspace --all-targets` bloque uniquement sur cinq `clippy::implicit_return` dans `unit_tests/ws_protocol_session.rs`. Les résultats détaillés restent dans la matrice de validation et le delta du fix, pas dans le plan.
```text
cargo tree -p ksp-onchain-transport-lib exécuté
cargo tree -p ksp-onchain-transport-lib --duplicates exécuté
```
Constat : aucune dépendance Helius/SDK ajoutée ; les doublons visibles sont transitifs (`syn` 2/3 et `webpki-roots` 0.26/1.0) et ne constituent pas une anomalie bloquante de `pre.001`.
**Verdict courant : gate `pre.001` positif ; socle `pre.002` implémenté dans la présente livraison.** Les validations compilées restent à exécuter par l'opérateur avant commit.
## 2. Décisions structurantes de `pre.001-fix.001` / `fix.002` — séparer les surfaces, qualifier le protocole
La première version du plan prévoyait un unique `WsSession` public exposant toutes les méthodes standard et une matrice de capabilities rejetant à l'exécution les méthodes incompatibles avec Helius.
Cette approche est remplacée par une séparation plus forte : **les méthodes impossibles pour un protocole doivent être absentes de sa façade publique**.
Architecture cible :
```text
moteur physique commun
WsSession
actor/socket/reconnect/queues
pending/remapping/backpressure/close
┌───────────────┴────────────────┐
│ │
▼ ▼
SolanaStandardWsSession HeliusLaserStreamWsSession
façade protocole standard façade protocole Helius
│ │
9 familles standard 6 familles communes
+ transaction
+ policy heartbeat
```
Principe :
```text
ce qui est dupliqué/séparé :
façade publique de protocole
méthodes disponibles
policy/capabilities du protocole
DTOs provider-specific lorsque le wire diverge
heartbeat/provider behavior
ce qui reste partagé :
socket physique
actor unique
command queue / pending JSON-RPC
WsSubscription<T>
local/remote IDs et remapping
reconnect/resubscribe machinery
backpressure
shutdown
snapshots/redaction
DTOs wire réellement identiques
```
Aucun `HeliusWsClient`, aucun second actor et aucune copie du lifecycle physique ne sont autorisés.
### 2.1 Surface `SolanaStandardWsSession`
La façade standard expose exactement les neuf familles acquises en `0.2.7` :
```text
account
block
logs
program
root
signature
slot
slotsUpdates
vote
```
Les 18 opérations standard restent donc présentes et testées : 9 subscribe + 9 unsubscribe.
### 2.2 Surface cible `HeliusLaserStreamWsSession`
À partir de `pre.003`, la façade Helius doit exposer uniquement les familles de subscription suivantes :
```text
account
logs
program
root
signature
slot
transaction
```
Même après `pre.003`, elle **n'expose pas** :
```text
block
slotsUpdates
vote
```
L'objectif est qu'un appel du genre :
```text
helius.block_subscribe(...)
```
soit absent de l'API Helius et donc impossible à écrire contre la façade Helius, plutôt que simplement rejeté après construction d'une requête.
La validation runtime avant I/O reste conservée en défense en profondeur pour les constructeurs, descriptors internes et chemins de compatibilité.
### 2.3 Compatibilité de `WsSession` publié en `0.2.7`
`WsSession` est déjà public et ses wrappers standard sont déjà stabilisés. `0.2.8` ne les supprime pas et ne casse pas les consommateurs existants.
Décision cible :
```text
WsSession
reste le handle/moteur physique partagé
conserve la compatibilité publique standard publiée en 0.2.7
ne devient pas l'entrée publique Helius générique
SolanaStandardWsSession
nouvelle façade explicite/recommandée pour le protocole standard
délègue au même WsSession
HeliusLaserStreamWsSession
nouvelle façade Helius
contient/délègue à un WsSession privé
n'expose aucun getter/into_inner permettant de contourner sa surface en 0.2.8
```
Le chemin public historique `WsSession::connect` doit rester compatible avec `SolanaStandard`. Lors de l'introduction de `HeliusLaserStream`, il ne doit pas permettre d'obtenir un `WsSession` générique Helius puis d'appeler une méthode standard non supportée. Le socle de `pre.002` doit donc extraire/réutiliser un chemin de connexion physique interne partageable, tout en gardant un garde protocolaire sur les constructeurs publics.
### 2.4 DTOs communs versus DTOs Helius
Les six familles communes réutilisent les DTOs standard lorsque le wire et la sémantique sont réellement identiques :
```text
account
logs
program
root
signature
slot
```
Ne pas créer artificiellement `HeliusAccountNotification`, `HeliusLogsNotification`, etc. si ces types seraient des copies strictes des types standard.
Créer des types Helius distincts dès que le contrat diverge ou n'existe pas en standard :
```text
HeliusTransactionSubscribeFilter
HeliusTokenAccountsMode
HeliusTransactionEncoding
HeliusTransactionSubscribeOptions
HeliusTransactionNotification / formes prouvées
```
Une option provider-specific ne doit jamais être injectée dans un DTO Solana standard pour éviter une duplication de façade.
### 2.5 Kind de subscription et registry interne
`WsSubscriptionKind` appartient au lifecycle/snapshot commun et non à la capacité d'invocation publique. Il peut être étendu de manière `#[non_exhaustive]` avec une variante provider-explicite pour `transaction` si cela minimise la rupture du snapshot existant.
Le point obligatoire n'est pas de dupliquer cet enum à tout prix ; le point obligatoire est que :
```text
la façade Helius ne puisse pas invoquer Block/SlotsUpdates/Vote
la façade standard ne puisse pas invoquer HeliusTransaction
le registry/actor interne reste unique et provider-neutral
```
Si `pre.002` montre qu'un descriptor interne distinct rend le snapshot plus propre sans rupture publique, cette forme peut être retenue. Aucun refactor ne doit toutefois remplacer une séparation de façade simple par une hiérarchie générique lourde.
### 2.6 Réalisation de `pre.002`
Le socle concret retient une séparation minimale sans dupliquer les wrappers wire ni l'actor :
```text
WsSession::connect(endpoint)
-> accepte uniquement WsProtocolKind::SolanaStandard
-> compatibilité publique 0.2.7 conservée
SolanaStandardWsSession::connect(endpoint)
-> guard SolanaStandard
-> WsSession::connect_for_protocol(...) interne
-> même connect_physical / même run_ws_session_actor
-> délègue les 9 wrappers standard existants
HeliusLaserStreamWsSession::connect(endpoint)
-> guard HeliusLaserStream
-> WsSession::connect_for_protocol(...) interne
-> même connect_physical / même run_ws_session_actor
-> lifecycle seulement en pre.002
-> aucune subscription Helius exposée avant pre.003
```
`WsProtocolKind` possède désormais :
```text
SolanaStandard -> solana_standard
HeliusLaserStream -> helius_laserstream
```
Les mismatches de constructeur sont rejetés avec `ERROR_CODE_INVALID_SETTINGS` et des contextes sûrs `expected_protocol` / `actual_protocol`, avant toute tentative réseau. Aucune URL ni credential n'entre dans cette erreur.
La façade Helius conserve son `WsSession` interne privé et ne fournit ni `inner()` ni `into_inner()`. Des canaries `compile_fail` verrouillent l'absence de `block_subscribe` et de l'escape hatch à ce stade. Une canary source confirme aussi que le module de façade ne contient ni second `tokio::spawn`, ni `tokio_tungstenite`, ni `WsSessionCommand`.
La façade standard délègue déjà les neuf familles existantes sans recopier leurs encoders/decoders :
```text
account block logs program root signature slot slotsUpdates vote
```
La façade Helius ne recevra les six délégations communes qu'en `pre.003`, afin de garder la tranche actuelle limitée au socle protocolaire et aux guards.
## 3. Forecast souple recalibré
## 2. Forecast souple courant
Le forecast suit le format historique des plans KSP `0.2.5` et `0.2.7` : un bloc compact, directement révisable, qui porte aussi l'état courant des tranches. Les `fix.*` sont rattachés à leur prerelease d'origine au lieu d'être présentés comme des tranches planifiées autonomes.
@@ -266,8 +43,9 @@ pre.001 DONE — audit Helius actuel + matrice + architecture + threat model +
fix.001 DONE — séparation des façades standard/Helius + moteur unique + gate Cargo fermé
fix.002 DONE — forecast normalisé + namespace LaserStream WebSocket/gRPC clarifié
pre.002 PREPARED — socle protocolaire : WsProtocolKind::HeliusLaserStream + façades standard/Helius
pre.002 FIX REQUIRED — socle protocolaire : WsProtocolKind::HeliusLaserStream + façades standard/Helius
+ connexion physique partagée + guards, sans duplication de l'actor
fix.001 PREPARED — correction Clippy `implicit_return` + audit/normalisation structure docs
pre.003 surface Helius standard supportée : account/logs/program/root/signature/slot
+ absence typée de block/slotsUpdates/vote sur Helius + non-régression standard 9/9
pre.004 Config V2 helius_laserstream + schema/fixtures + mapping Config -> Transport
@@ -299,8 +77,9 @@ Règles de lecture et de recalibrage :
Critères de split déjà identifiés : notification decoding multiforme non documenté, refactor générique du lifecycle nécessaire, évolution Helius normative en cours de release, ou stratégie live nécessitant une surface d'intégration séparée.
## 4. Sources internes relues et hiérarchie appliquée
## 3. Sources, baseline et preuves d'ouverture
### 3.1 Sources internes relues
Les sources internes obligatoires du prompt ont été relues depuis la base stable, notamment :
```text
@@ -350,15 +129,13 @@ config/schemas/std.transport.schema.json
Décisions de workflow conservées :
- `pre.001` reste audit + brainstorming + sizing ;
- ce fix corrige uniquement le design prévu par cette tranche ;
- `pre.002-fix.001` corrige la conformité Clippy et normalise lorganisation documentaire sans élargir le scope runtime ;
- une prerelease non-fix synchronise toujours Cargo ;
- un fix documentaire conserve la version Cargo de sa base ;
- un fix qui modifie du code/test consommé par le build synchronise Cargo selon `VERSION_WORKFLOW.md` ;
- `ROADMAP.md` reste global ; les détails vivent dans plan/validation/deltas ;
- `CHANGELOG.md` reste principalement réservé à la publication stable.
## 5. Baseline de démarrage et graphes Cargo
### 5.1 Baseline opérateur sur `v0.2.7`
### 3.2 Baseline opérateur sur `v0.2.7`
Le log opérateur fourni avant ouverture de `0.2.8` enregistre :
@@ -372,7 +149,7 @@ cargo test --workspace OK
Les tests live/bench explicitement opt-in restent ignorés par défaut, conformément à leurs contrats.
### 5.2 Graphes fournis après application de `pre.001`
### 3.3 Graphes fournis après application de `pre.001`
État observé :
@@ -394,9 +171,9 @@ webpki-roots 0.26.11 / 1.0.9
Aucun doublon direct introduit par `0.2.8-pre.001`, aucun SDK Helius et aucune inversion de dépendance KSP ne sont observés.
## 6. État réel hérité de `v0.2.7`
## 4. État hérité de `v0.2.7`
### 6.1 HTTP à ne pas régresser
### 4.1 HTTP à ne pas régresser
```text
52/52 méthodes HTTP courantes typées
@@ -405,7 +182,7 @@ KSP-TRANSPORT-007 appliqué
write submissions sans resend après dispatch ambigu
```
### 6.2 WebSocket standard publié
### 4.2 WebSocket standard publié
Le runtime stable expose neuf familles :
@@ -430,7 +207,7 @@ unstable : Block, SlotsUpdates, Vote
Le moteur possède déjà : actor unique propriétaire du socket, pending JSON-RPC borné, queues bornées, local IDs stables, remote IDs internes/remappables, reconnect fini, resubscribe déterministe, cleanup late ACK, backpressure isolée, `continuity_gap_count`, one-shot Signature et `close().await` borné.
### 6.3 Contrats publics utiles
### 4.3 Contrats publics utiles
`WsProtocolKind` est `#[non_exhaustive]` et ne contient en `v0.2.7` que :
@@ -452,7 +229,7 @@ WsSessionSettings
`WsSession` est un handle `Clone` vers un actor unique et les wrappers standard sont implémentés directement sur ce type. Cette réalité explique la correction de `pre.001-fix.001` : la façade Helius ne doit pas être le même type public surchargé de méthodes incompatibles.
### 6.4 Config V2
### 4.4 Config V2
```text
format_version = 2
@@ -469,9 +246,9 @@ Le schema et l'adapter n'acceptent actuellement que :
solana_standard
```
## 7. Audit Helius officiel du 2026-08-23
## 5. Audit Helius officiel du 2026-08-23
### 7.1 Sources primaires utilisées
### 5.1 Sources primaires utilisées
```text
https://www.helius.dev/docs/rpc/websocket
@@ -490,7 +267,7 @@ https://www.helius.dev/docs/llms.txt
Les documents `llms.txt` servent d'index et de source secondaire. Lorsqu'ils divergent d'une page de référence dédiée ou de la page exhaustive des méthodes, la divergence est enregistrée.
### 7.2 Terminologie et endpoints
### 5.2 Terminologie et endpoints
```text
nom produit courant = LaserStream WebSocket
@@ -502,7 +279,7 @@ Gatekeeper beta = hors 0.2.8
LaserStream gRPC = distinct, hors 0.2.8
```
### 7.3 Inventaire provider retenu
### 5.3 Inventaire provider retenu
```text
standard supporté : account, logs, program, root, signature, slot
@@ -520,7 +297,7 @@ result = true
La référence précise que quelques notifications in-flight peuvent encore arriver après l'unsubscribe.
### 7.4 Divergence `slotsUpdatesSubscribe`
### 5.4 Divergence `slotsUpdatesSubscribe`
Les sources Helius se contredisent :
@@ -536,7 +313,7 @@ HeliusLaserStreamWsSession n'expose pas SlotsUpdates
Une validation interne garde aussi un rejet avant I/O si un descriptor incompatible atteint le moteur par un chemin interne ou de compatibilité.
### 7.5 `transactionSubscribe`
### 5.5 `transactionSubscribe`
Filtre courant :
@@ -570,7 +347,7 @@ method = transactionNotification
La documentation ne détaille pas avec la même précision chacun des quatre modes de `transactionDetails`. KSP ne doit pas inventer ces formes : types précis pour les formes prouvées et fallback borné uniquement si nécessaire.
### 7.6 `accountSubscribe` / `programSubscribe` et `notifyOn`
### 5.6 `accountSubscribe` / `programSubscribe` et `notifyOn`
`notifyOn` est documenté mais marqué :
@@ -584,7 +361,7 @@ Décision : ne pas l'ajouter aux DTOs KSP.
Les pages continuent à employer « enhanced/filtered accountSubscribe » sans publier un wire provider-specific supplémentaire assez précis pour une API typed. Ce point reste reporté explicitement.
## 8. Matrice normative Helius WebSocket
## 6. Matrice normative Helius WebSocket
| Famille | Paire | Classe | Support Helius retenu | Surface publique Helius | Paramètres/options utiles | Notification | Stratégie KSP/test |
|---------------------|-----------------------------------------------------|------------------|-----------------------|-------------------------|------------------------------------|---------------------------|----------------------------------------------------|
@@ -608,9 +385,213 @@ HeliusLaserStreamWsSession : 6 familles standard supportées + 1 famille Helius
La compliance standard KSP reste **18/18** pour `SolanaStandard`.
## 9. Décisions d'architecture détaillées
## 7. Architecture et frontières de protocole
La première version du plan prévoyait un unique `WsSession` public exposant toutes les méthodes standard et une matrice de capabilities rejetant à l'exécution les méthodes incompatibles avec Helius.
### 9.1 Protocol kind et namespace LaserStream
Cette approche est remplacée par une séparation plus forte : **les méthodes impossibles pour un protocole doivent être absentes de sa façade publique**.
Architecture cible :
```text
moteur physique commun
WsSession
actor/socket/reconnect/queues
pending/remapping/backpressure/close
┌───────────────┴────────────────┐
│ │
▼ ▼
SolanaStandardWsSession HeliusLaserStreamWsSession
façade protocole standard façade protocole Helius
│ │
9 familles standard 6 familles communes
+ transaction
+ policy heartbeat
```
Principe :
```text
ce qui est dupliqué/séparé :
façade publique de protocole
méthodes disponibles
policy/capabilities du protocole
DTOs provider-specific lorsque le wire diverge
heartbeat/provider behavior
ce qui reste partagé :
socket physique
actor unique
command queue / pending JSON-RPC
WsSubscription<T>
local/remote IDs et remapping
reconnect/resubscribe machinery
backpressure
shutdown
snapshots/redaction
DTOs wire réellement identiques
```
Aucun `HeliusWsClient`, aucun second actor et aucune copie du lifecycle physique ne sont autorisés.
### 7.1 Surface `SolanaStandardWsSession`
La façade standard expose exactement les neuf familles acquises en `0.2.7` :
```text
account
block
logs
program
root
signature
slot
slotsUpdates
vote
```
Les 18 opérations standard restent donc présentes et testées : 9 subscribe + 9 unsubscribe.
### 7.2 Surface cible `HeliusLaserStreamWsSession`
À partir de `pre.003`, la façade Helius doit exposer uniquement les familles de subscription suivantes :
```text
account
logs
program
root
signature
slot
transaction
```
Même après `pre.003`, elle **n'expose pas** :
```text
block
slotsUpdates
vote
```
L'objectif est qu'un appel du genre :
```text
helius.block_subscribe(...)
```
soit absent de l'API Helius et donc impossible à écrire contre la façade Helius, plutôt que simplement rejeté après construction d'une requête.
La validation runtime avant I/O reste conservée en défense en profondeur pour les constructeurs, descriptors internes et chemins de compatibilité.
### 7.3 Compatibilité de `WsSession` publié en `0.2.7`
`WsSession` est déjà public et ses wrappers standard sont déjà stabilisés. `0.2.8` ne les supprime pas et ne casse pas les consommateurs existants.
Décision cible :
```text
WsSession
reste le handle/moteur physique partagé
conserve la compatibilité publique standard publiée en 0.2.7
ne devient pas l'entrée publique Helius générique
SolanaStandardWsSession
nouvelle façade explicite/recommandée pour le protocole standard
délègue au même WsSession
HeliusLaserStreamWsSession
nouvelle façade Helius
contient/délègue à un WsSession privé
n'expose aucun getter/into_inner permettant de contourner sa surface en 0.2.8
```
Le chemin public historique `WsSession::connect` doit rester compatible avec `SolanaStandard`. Lors de l'introduction de `HeliusLaserStream`, il ne doit pas permettre d'obtenir un `WsSession` générique Helius puis d'appeler une méthode standard non supportée. Le socle de `pre.002` doit donc extraire/réutiliser un chemin de connexion physique interne partageable, tout en gardant un garde protocolaire sur les constructeurs publics.
### 7.4 DTOs communs versus DTOs Helius
Les six familles communes réutilisent les DTOs standard lorsque le wire et la sémantique sont réellement identiques :
```text
account
logs
program
root
signature
slot
```
Ne pas créer artificiellement `HeliusAccountNotification`, `HeliusLogsNotification`, etc. si ces types seraient des copies strictes des types standard.
Créer des types Helius distincts dès que le contrat diverge ou n'existe pas en standard :
```text
HeliusTransactionSubscribeFilter
HeliusTokenAccountsMode
HeliusTransactionEncoding
HeliusTransactionSubscribeOptions
HeliusTransactionNotification / formes prouvées
```
Une option provider-specific ne doit jamais être injectée dans un DTO Solana standard pour éviter une duplication de façade.
### 7.5 Kind de subscription et registry interne
`WsSubscriptionKind` appartient au lifecycle/snapshot commun et non à la capacité d'invocation publique. Il peut être étendu de manière `#[non_exhaustive]` avec une variante provider-explicite pour `transaction` si cela minimise la rupture du snapshot existant.
Le point obligatoire n'est pas de dupliquer cet enum à tout prix ; le point obligatoire est que :
```text
la façade Helius ne puisse pas invoquer Block/SlotsUpdates/Vote
la façade standard ne puisse pas invoquer HeliusTransaction
le registry/actor interne reste unique et provider-neutral
```
Si `pre.002` montre qu'un descriptor interne distinct rend le snapshot plus propre sans rupture publique, cette forme peut être retenue. Aucun refactor ne doit toutefois remplacer une séparation de façade simple par une hiérarchie générique lourde.
### 7.6 Réalisation de `pre.002`
Le socle concret retient une séparation minimale sans dupliquer les wrappers wire ni l'actor :
```text
WsSession::connect(endpoint)
-> accepte uniquement WsProtocolKind::SolanaStandard
-> compatibilité publique 0.2.7 conservée
SolanaStandardWsSession::connect(endpoint)
-> guard SolanaStandard
-> WsSession::connect_for_protocol(...) interne
-> même connect_physical / même run_ws_session_actor
-> délègue les 9 wrappers standard existants
HeliusLaserStreamWsSession::connect(endpoint)
-> guard HeliusLaserStream
-> WsSession::connect_for_protocol(...) interne
-> même connect_physical / même run_ws_session_actor
-> lifecycle seulement en pre.002
-> aucune subscription Helius exposée avant pre.003
```
`WsProtocolKind` possède désormais :
```text
SolanaStandard -> solana_standard
HeliusLaserStream -> helius_laserstream
```
Les mismatches de constructeur sont rejetés avec `ERROR_CODE_INVALID_SETTINGS` et des contextes sûrs `expected_protocol` / `actual_protocol`, avant toute tentative réseau. Aucune URL ni credential n'entre dans cette erreur.
La façade Helius conserve son `WsSession` interne privé et ne fournit ni `inner()` ni `into_inner()`. Des canaries `compile_fail` verrouillent l'absence de `block_subscribe` et de l'escape hatch à ce stade. Une canary source confirme aussi que le module de façade ne contient ni second `tokio::spawn`, ni `tokio_tungstenite`, ni `WsSessionCommand`.
La façade standard délègue déjà les neuf familles existantes sans recopier leurs encoders/decoders :
```text
account block logs program root signature slot slotsUpdates vote
```
La façade Helius ne recevra les six délégations communes qu'en `pre.003`, afin de garder la tranche actuelle limitée au socle protocolaire et aux guards.
### 7.7 Protocol kind et namespace LaserStream
Retenir pour **WebSocket uniquement** :
@@ -628,7 +609,7 @@ Le futur **Helius LaserStream gRPC** reste un backend/provider distinct, hors `0
Cette règle permet de conserver le code court `helius_laserstream` dans son conteneur WS sans créer d'ambiguïté future entre les deux produits portant le nom LaserStream.
### 9.2 Connexion et propriété du moteur
### 7.8 Connexion et propriété du moteur
Cible de `pre.002` :
@@ -648,7 +629,7 @@ pas de second snapshot model
pas de public escape hatch Helius -> raw standard WsSession
```
### 9.3 Capability validation defense-in-depth
### 7.9 Capability validation defense-in-depth
La séparation de façade est la première barrière. Une matrice interne reste utile :
@@ -664,7 +645,7 @@ HeliusLaserStream:
Cette matrice sert aux guards de constructor/descriptor, aux canaries et à la protection interne ; elle ne remplace plus la séparation de l'API publique.
### 9.4 Heartbeat/idle ownership
### 7.10 Heartbeat/idle ownership
Helius annonce un timeout d'inactivité de 10 minutes et recommande des pings périodiques.
@@ -682,7 +663,7 @@ write failure = chemin disconnect/reconnect existant
budget reconnect = fini, inchangé
```
### 9.5 Config V2
### 7.11 Config V2
Évolution :
@@ -694,7 +675,7 @@ profiles[].ws_endpoints[].kind:
Les paramètres de `transactionSubscribe` restent runtime et n'appartiennent pas au profil endpoint Config.
### 9.6 Credentials
### 7.12 Credentials
L'api-key reste uniquement dans l'URL résolue :
@@ -704,15 +685,15 @@ wss://mainnet.helius-rpc.com/?api-key=${KSP_SECRET_HELIUS_API_KEY}
Le nom final du secret est matérialisé avec Config. Transport ne lit jamais `std::env` et reçoit un `WsEndpointUrl` redacted.
## 10. Threat model provider
## 8. Threat model provider
### 10.1 Secret dans query URL
### 8.1 Secret dans query URL
Risque : fuite par `Debug`, handshake error, logs tungstenite ou contexte d'erreur.
Mesures : `WsEndpointUrl` opaque/redacted, mapping vers metadata sûre, canaris avec secret reconnaissable.
### 10.2 Contournement de façade
### 8.2 Contournement de façade
Risque nouveau identifié par le fix : obtenir un handle générique Helius puis appeler une méthode standard non supportée.
@@ -725,23 +706,23 @@ constructeur générique historique gardé standard-only
validation protocolaire interne avant I/O
```
### 10.3 Heartbeat concurrent avec reconnect/close
### 8.3 Heartbeat concurrent avec reconnect/close
Timer détenu par l'actor, actif seulement en `Active`, reset/cancel avec lifecycle, test déterministe par cadence raccourcie interne/test-only.
### 10.4 Late notifications et IDs distants
### 8.4 Late notifications et IDs distants
Après `transactionUnsubscribe`, les messages in-flight sont possibles. L'unsubscribe local gagne ; un remote ID tardif ne réactive pas la subscription.
### 10.5 Payload transaction volumineux
### 8.5 Payload transaction volumineux
Conserver `max_message_size_bytes`, `max_frame_size_bytes`, queue bornée par subscription et absence de payload brut dans les logs/snapshots.
### 10.6 Filtres 50k
### 8.6 Filtres 50k
Valider chaque liste avant I/O, ne pas logguer les valeurs et éviter les clones inutiles.
### 10.7 Continuité
### 8.7 Continuité
```text
reconnect oui
@@ -752,7 +733,7 @@ historical replay non
lossless WebSocket non
```
## 11. Audit dépendances
## 9. Dépendances
Versions observées dans le graphe opérateur :
@@ -767,9 +748,8 @@ Verdict : **aucune nouvelle dépendance**.
Le moteur courant sait déjà gérer TLS WebSocket, Ping/Pong, timers Tokio, futures sink/stream et JSON serde. Un SDK Helius dupliquerait des choix de lifecycle que KSP possède déjà.
## 12. Stratégie de tests
### 12.1 Architecture/façades
## 10. Stratégie de validation et smoke
### 10.1 Architecture/façades
Prévoir :
@@ -786,7 +766,7 @@ constructeur protocolaire invalide rejeté avant I/O
L'absence d'une méthode peut être couverte par compile-fail doctest/canary sans ajouter de dépendance de test si cette forme reste compatible avec les règles Rust KSP.
### 12.2 Helius transaction/lifecycle
### 10.2 Helius transaction/lifecycle
```text
transactionSubscribe serialization exacte
@@ -806,7 +786,7 @@ queue overflow isolé
URL/api-key redaction
```
### 12.3 Non-régressions
### 10.3 Non-régressions
```text
standard WS 18/18 pour SolanaStandard
@@ -819,13 +799,13 @@ Config V2 solana_standard backward readable
no Transport -> Config/Wallet/Store/Program/tracing direct
```
## 13. Smoke live Helius
### 10.4 Smoke live Helius
Le live reste opt-in et secondaire par rapport aux fixtures déterministes.
Stratégie : Config résout le secret et construit l'endpoint Helius ; Transport ne lit jamais l'environnement. Si aucune surface d'intégration sûre n'est disponible, le smoke opérateur peut rester documenté plutôt que d'introduire une dépendance inverse.
## 14. Questions explicitement reportées
## 11. Questions explicitement reportées
```text
wire exact d'un éventuel enhanced/filtered accountSubscribe provider-specific
@@ -841,7 +821,7 @@ refonte générique WsSession<P> : non nécessaire en 0.2.8
Une nouvelle preuve normative peut rouvrir un point et insérer une tranche ; aucun report ne doit disparaître silencieusement.
## 15. Critères de split et de clôture
## 12. Critères de split et de clôture
Créer une tranche/fix supplémentaire si :
@@ -874,37 +854,43 @@ validation finale fermée
prompt 0.2.9 prêt
```
## 16. Verdict après `pre.002`
## 13. Checkpoint `pre.002` / `pre.002-fix.001`
Décisions fermées :
Le socle `pre.002` est matériellement en place :
```text
base stable autoritaire confirmé
surface Helius actuelle auditée
Cargo graph audité, non bloquant
protocol kind HeliusLaserStream / helius_laserstream
namespace WebSocket-owned ; gRPC explicitement distinct/hors 0.2.8
moteur physique WsSession actor unique, partagé
façade standard SolanaStandardWsSession
façade Helius HeliusLaserStreamWsSession
Helius standard exposé Account Logs Program Root Signature Slot
Helius standard absent Block SlotsUpdates Vote
Helius extension Transaction
DTOs communs réutilisés si wire identique
DTOs provider dédiés uniquement si divergence
capability guard defense-in-depth avant I/O
heartbeat actor provider-owned, 60s cible
Config V2 kind addition, même conteneur
credential URL Secret résolue par Config
new dependency aucune
historical/lossless replay aucune promesse
forecast format compact KSP, fixes groupés, pre.001 -> pre.011
pre.002 protocol kind matérialisé : SolanaStandard + HeliusLaserStream
pre.002 standard facade 9 wrappers existants délégués, aucun wire dupliqué
pre.002 Helius facade lifecycle seulement, inner privé
pre.002 generic WsSession constructeur public standard-only
pre.002 physical connection chemin unique partagé, aucun second actor
pre.002 Config/transaction/heartbeat non commencés conformément au forecast
WsProtocolKind::HeliusLaserStream -> helius_laserstream
SolanaStandardWsSession
HeliusLaserStreamWsSession
WsSession::connect historique standard-only
connect_for_protocol / connect_physical partagés
aucun second actor/socket/registry
aucun Config Helius / transactionSubscribe / heartbeat anticipé
```
**`pre.002` est préparé ; après validations opérateur vertes, la prochaine tranche est `0.2.8-pre.003` — six familles standard supportées sur la façade Helius et absence typée durable des trois familles non supportées.**
Preuves opérateur déjà reçues pour `pre.002` :
```text
cargo fmt --all OK
python3 scripts/audit_rust_workspace_rules.py clean
cargo check --workspace OK
cargo clippy --workspace --all-targets FAIL ciblé : 5 implicit_return dans ws_protocol_session.rs
cargo test -p ksp-onchain-transport-lib OK
313 unit tests + 37 public API + 25 release completeness + 2 doctests compile_fail
cargo test --workspace OK
```
`pre.002-fix.001` corrige uniquement ce défaut Clippy dans la fixture, sans modifier le runtime protocolaire. Le fix réorganise aussi les deux documents actifs : le **plan** conserve décisions, audit, forecast et stratégie ; la **validation** conserve matrices, critères et preuves exécutées ; les détails de livraison restent dans les **deltas**.
Après application du fix, le gate opérateur à rejouer est :
```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
```
Si ce checkpoint est vert, `pre.002` + `fix.001` peuvent être considérés `DONE` et `pre.003` ouvre les six familles standard supportées sur `HeliusLaserStreamWsSession`.

View File

@@ -1,9 +1,9 @@
<!-- file: docs/validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md -->
<!-- version: 6 -->
<!-- version: 7 -->
# Validation `0.2.8` — Helius LaserStream WebSocket
> **Statut : `0.2.8-pre.002` implémente le socle des deux façades protocolaires sur le moteur `WsSession` unique.** Le protocol kind Helius LaserStream WebSocket, les guards de constructeur, la compatibilité standard historique et l'absence d'escape hatch Helius sont matérialisés. Les six subscriptions standard supportées par Helius restent volontairement ouvertes pour `pre.003`.
> **Statut : `pre.002` testé avec succès sauf Clippy ; `pre.002-fix.001` préparé.** La matrice conserve les critères et preuves exécutées ; le forecast détaillé reste exclusivement dans le plan actif afin que ce fichier ne devienne pas un second plan.
## 1. Références
@@ -14,6 +14,8 @@ base stable v0.2.7 / deltas/0.2.7/rel.001.md
pre.001 deltas/0.2.8/pre.001.md
fix architecture deltas/0.2.8/pre.001-fix.001.md
fix forecast/nomenclature deltas/0.2.8/pre.001-fix.002.md
pre.002 deltas/0.2.8/pre.002.md
pre.002 Clippy/docs fix deltas/0.2.8/pre.002-fix.001.md
validation standard WS docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md
HTTP compliance docs/validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md
KSP-TRANSPORT-007 docs/validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md
@@ -21,8 +23,7 @@ KSP-TRANSPORT-007 docs/validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AU
Audit Helius initial : **2026-08-23**.
## 2. Gate `pre.001` et dependency graph
## 2. Gate `pre.001` fermé
Baseline opérateur acquise :
```text
@@ -58,6 +59,35 @@ webpki-roots 0.26.11 / 1.0.9
Verdict : doublons transitifs, aucune nouvelle dépendance Helius, aucune anomalie bloquante du gate.
### 2.1 Checklist de fermeture `pre.001`
```text
[x] base stable inspectée
[x] baseline opérateur disponible
[x] sources Helius courantes relues
[x] terminologie/endpoints/auth clarifiés
[x] surface standard supportée/non supportée inventoriée
[x] transactionSubscribe/unsubscribe inventoriés
[x] tokenAccounts inventorié
[x] notifyOn classé deprecated/no-op
[x] divergence slotsUpdates enregistrée et arbitrée explicitement
[x] architecture corrigée : surfaces protocolaires séparées
[x] moteur WsSession/actor unique préservé
[x] stratégie de compatibilité WsSession 0.2.7 définie
[x] heartbeat ownership décidé
[x] Config shape décidée
[x] credential strategy décidée
[x] aucune nouvelle dépendance justifiée
[x] forecast recalibré au format compact historique et fixes groupés sous `pre.001`
[x] namespace `helius_laserstream` explicitement WebSocket-owned
[x] futur LaserStream gRPC maintenu distinct et hors contrat WS
[x] cargo tree direct exécuté par opérateur
[x] cargo tree duplicates exécuté par opérateur
[x] doublons ciblés analysés comme transitifs/non bloquants
```
Verdict : **gate `0.2.8-pre.001` positif ; `pre.002` testé par lopérateur avec un unique échec Clippy ciblé, corrigé par `pre.002-fix.001`.**
## 3. Matrice provider normative
| Capability | Standard KSP | Helius doc actuelle | Décision `0.2.8` | Surface Helius attendue | Preuve finale attendue |
@@ -116,7 +146,7 @@ Verdict : doublons transitifs, aucune nouvelle dépendance Helius, aucune anomal
| secret | query URL derrière `WsEndpointUrl` | redaction canaries | décidé |
| new Rust dependency | aucune | manifest/tree audit | décidé |
## 5. `transactionSubscribe` à couvrir
## 5. Contrat `transactionSubscribe` à valider
### 5.1 Filter
@@ -156,12 +186,12 @@ fallback borné si une forme officielle reste insuffisamment explicitée
aucun payload brut dans logs/snapshots
```
## 6. Validation lifecycle/provider à construire
## 6. Validation lifecycle/provider
```text
[x] un seul actor/socket implementation path dans le code `pre.002`
[ ] SolanaStandardWsSession public et constructible — canary ajoutée, exécution opérateur requise
[ ] HeliusLaserStreamWsSession public et constructible — canary ajoutée, exécution opérateur requise
[x] SolanaStandardWsSession public et constructible — test Transport opérateur vert
[x] HeliusLaserStreamWsSession public et constructible — test Transport opérateur vert
[x] `helius_laserstream` reste possédé par le namespace WebSocket
[x] aucune API/Config gRPC n'est anticipée ou aliasée sur le contrat WS
[x] WsSession historique reste public et son constructeur devient explicitement standard-only
@@ -170,7 +200,7 @@ aucun payload brut dans logs/snapshots
[x] Helius facade n'expose pas voteSubscribe en `pre.002`
[x] SolanaStandard facade n'expose pas transactionSubscribe
[x] Helius facade n'expose aucun escape hatch vers le handle générique
[ ] protocol mismatch rejeté avant I/O — fixtures ajoutées, exécution opérateur requise
[x] protocol mismatch rejeté avant I/O — fixture opérateur verte
[ ] 6 familles standard Helius utilisent le wire standard exact — `pre.003`
[ ] transaction subscribe/ack exact
[ ] transaction unsubscribe/result exact
@@ -190,24 +220,24 @@ aucun payload brut dans logs/snapshots
[ ] payload/filters/api-key absents de Debug/snapshots sûrs
```
## 7. Non-régressions obligatoires
## 7. Non-régressions
```text
[ ] standard WebSocket 18/18 toujours comptabilisé pour SolanaStandard
[ ] partition standard unstable 3/9 inchangée
[ ] signature one-shot inchangée
[ ] HTTP current 52/52 inchangé
[ ] HTTP historical 14/14 inchangé
[ ] KSP-TRANSPORT-007 inchangé
[ ] Config V1 HTTP-only backward readable
[ ] Config V2 solana_standard backward readable
[ ] no Transport -> Config/Wallet/Store/Program/tracing direct
[x] standard WebSocket 18/18 toujours comptabilisé pour SolanaStandard — release completeness vert
[x] partition standard unstable 3/9 inchangée — tests hérités verts
[x] signature one-shot inchangée — tests hérités verts
[x] HTTP current 52/52 inchangé — workspace/release completeness verts
[x] HTTP historical 14/14 inchangé — workspace/release completeness verts
[x] KSP-TRANSPORT-007 inchangé — tests Transport/workspace verts
[x] Config V1 HTTP-only backward readable — tests Config workspace verts
[x] Config V2 solana_standard backward readable — tests Config workspace verts
[x] no Transport -> Config/Wallet/Store/Program/tracing direct — audits/tests ownership verts
```
## 8. Security/redaction
## 8. Sécurité/redaction
```text
[ ] api-key absente de Debug WsEndpointUrl
[x] api-key absente de Debug WsEndpointUrl — canaries héritées + pre.002 vert
[ ] api-key absente de Debug settings/session/subscription
[ ] api-key absente des KspError safe contexts
[ ] URL complète absente des snapshots
@@ -215,7 +245,7 @@ aucun payload brut dans logs/snapshots
[ ] raw transaction payload absent des logs/snapshots
[ ] large filter addresses non loggées
[ ] provider error payload arbitraire non copié dans context
[ ] façade Helius ne permet pas de contourner les capabilities par exposition du inner
[x] façade Helius ne permet pas de contourner les capabilities par exposition du inner — source + doctest compile_fail verts
```
## 9. Smoke live
@@ -224,59 +254,7 @@ Statut initial : **non exécuté**.
Contrat cible : opt-in, Config résout l'api-key, Transport ne lit pas l'environnement. Aucun secret n'est versionné ou affiché. Un échec lié au plan/credential provider doit rester distinguable d'une panne du moteur.
## 10. Forecast courant
Le plan est la source normative du forecast. La validation reprend la même forme compacte et groupe les fixes sous leur prerelease :
```text
pre.001 DONE — audit/sizing/matrice/dependencies
fix.001 DONE — façades séparées + gate Cargo fermé
fix.002 DONE — forecast compact + namespace LaserStream WS/gRPC
pre.002 PREPARED — socle protocolaire/façades/connect partagé
pre.003 6 familles Helius communes + absence 3 unsupported
pre.004 Config V2 + secrets
pre.005 transaction request/unsubscribe
pre.006 transaction notification + lifecycle
pre.007 heartbeat Helius WebSocket
pre.008 adversarial/security/backpressure
pre.009 compliance/non-regression
pre.010 live smoke/docs/dependency graph
pre.011 final workspace/prompt 0.2.9
rel.001 stable
```
Le forecast reste souple ; les fixes ne sont pas comptés comme des prereleases planifiées supplémentaires et le numéro final n'est jamais un critère de clôture.
## 11. Gate initial après `pre.001-fix.002`
```text
[x] base stable inspectée
[x] baseline opérateur disponible
[x] sources Helius courantes relues
[x] terminologie/endpoints/auth clarifiés
[x] surface standard supportée/non supportée inventoriée
[x] transactionSubscribe/unsubscribe inventoriés
[x] tokenAccounts inventorié
[x] notifyOn classé deprecated/no-op
[x] divergence slotsUpdates enregistrée et arbitrée explicitement
[x] architecture corrigée : surfaces protocolaires séparées
[x] moteur WsSession/actor unique préservé
[x] stratégie de compatibilité WsSession 0.2.7 définie
[x] heartbeat ownership décidé
[x] Config shape décidée
[x] credential strategy décidée
[x] aucune nouvelle dépendance justifiée
[x] forecast recalibré au format compact historique et fixes groupés sous `pre.001`
[x] namespace `helius_laserstream` explicitement WebSocket-owned
[x] futur LaserStream gRPC maintenu distinct et hors contrat WS
[x] cargo tree direct exécuté par opérateur
[x] cargo tree duplicates exécuté par opérateur
[x] doublons ciblés analysés comme transitifs/non bloquants
```
Verdict : **gate `0.2.8-pre.001` positif ; socle `pre.002` matérialisé, validations compilées opérateur encore requises avant commit.**
## 12. Preuve spécifique `pre.002`
## 10. Preuve `pre.002` et fix Clippy
Surface introduite :
@@ -296,20 +274,49 @@ Canaries ajoutées/prévues dans la livraison :
[x] façade Helius publique + lifecycle partagé
[x] generic WsSession::connect rejette Helius avant I/O
[x] chaque façade rejette le mauvais protocol kind avant I/O
[ ] les deux façades ouvrent/ferment une connexion contre un peer local via le même actor — test ajouté
[ ] Debug Helius ne projette pas une query api-key canary — test ajouté
[x] les deux façades ouvrent/ferment une connexion contre un peer local via le même actor — test opérateur vert
[x] Debug Helius ne projette pas une query api-key canary — test opérateur vert
[x] source de façade sans second spawn/socket/command actor
[ ] compile-fail Helius blockSubscribe — doctest ajouté
[ ] compile-fail Helius into_inner — doctest ajouté
[x] compile-fail Helius blockSubscribe — doctest opérateur vert
[x] compile-fail Helius into_inner — doctest opérateur vert
[ ] six wrappers standard Helius — `pre.003`
```
Validation du sandbox de préparation :
Validation opérateur reçue pour `pre.002` :
```text
python3 scripts/audit_rust_workspace_rules.py = clean
cargo fmt/check/clippy/test = non exécutables dans le sandbox de préparation
cargo fmt --all OK
python3 scripts/audit_rust_workspace_rules.py clean
cargo check --workspace OK
cargo clippy --workspace --all-targets FAIL : 5 `implicit_return` dans unit_tests/ws_protocol_session.rs
cargo test -p ksp-onchain-transport-lib OK
cargo test --workspace OK
```
Les gates compilés opérateur de `pre.002` restent requis avant commit.
`pre.002-fix.001` ajoute les retours explicites exigés par la politique Clippy KSP et ne change aucun contrat runtime. Le fix doit être revalidé par le même checkpoint avant passage à `pre.003`.
## 11. Audit structurel des documents actifs
Contrats appliqués :
```text
docs/plans/*.md = planification, décisions, audit de scope, forecast, stratégie de validation
docs/validation/*.md = matrices, critères, états et preuves réellement exécutées
deltas/0.2.8/*.md = journal immuable de chaque livraison
```
Constats `pre.002-fix.001` :
```text
[x] docs/plans est ordonné : 000-README puis 001..015 sans collision
[x] docs/validation est ordonné : 000-README puis 001..011 sans collision
[x] aucun nouveau répertoire documentaire n'est nécessaire pour Helius WebSocket
[x] le plan 015 garde une seule responsabilité : organiser la release 0.2.8
[x] la validation 011 garde une seule responsabilité : rapprocher critères et preuves 0.2.8
[x] le delta du fix reste le seul journal détaillé de la livraison
[x] le forecast détaillé n'est plus dupliqué dans la validation
[x] les sections architecture auparavant séparées sont regroupées dans le plan
[x] l'ordre du plan suit désormais : état/forecast -> sources/baseline -> héritage -> audit -> matrice -> architecture -> risques -> validation -> clôture
```
Aucun split en fichiers supplémentaires n'est retenu : les plans historiques `0.2.5``0.2.7` sont de taille comparable ou supérieure, et le contenu du plan `015` reste entièrement centré sur une seule release. Le problème identifié était **l'ordre interne et la duplication de responsabilités**, pas la nécessité d'un nouveau type de document.