v0.2.8-pre.001
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/plans/000-README.md -->
|
||||
<!-- version: 56 -->
|
||||
<!-- version: 57 -->
|
||||
|
||||
# Plans KSP
|
||||
|
||||
@@ -23,6 +23,7 @@ Un plan décrit le périmètre, les décisions déjà acquises, les questions ou
|
||||
- [`012-V0_2_5_WALLET_FOUNDATION_PLAN.md`](012-V0_2_5_WALLET_FOUNDATION_PLAN.md) — plan historique clôturé de la release stable `0.2.5 — Wallet foundation`, ouvert par `pre.001`, livré jusqu’à `pre.010`, renforcé par `pre.010-fix.001`–`fix.003` pour Dalek 3 et la normalisation Rust/audit structurel, puis publié par `rel.001`; il couvre `.kspwallet` V1, VIEW/OWNER, crypto, persistence, administration, transfer et compliance.
|
||||
- [`013-V0_2_6_WALLET_DESK_PLAN.md`](013-V0_2_6_WALLET_DESK_PLAN.md) — plan historique clôturé de la release stable `0.2.6 — Wallet Desk`, ouvert par `pre.001`, étendu en `pre.015`–`pre.017` au wire binaire `.kspwallet` V2, aux APIs multi-version et à la migration V1 -> V2, puis fermé par `pre.018`/`fix.001` avec le runtime Tauri packagé et le build final vert avant publication `rel.001`.
|
||||
- [`014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md`](014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md) — plan historique clôturé de la release stable `0.2.7 — WebSocket Solana standard`, ouvert par `pre.001`, exécuté jusqu’à `pre.014`, corrigé documentairement par `pre.014-fix.001` puis publié par `rel.001`; il conserve l’inventaire officiel 18 méthodes, le modèle session/subscription, le threat model, les preuves de compliance/smoke/dépendances et la préparation de `0.2.8`.
|
||||
- [`015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md`](015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md) — plan actif de `0.2.8 — Helius LaserStream WebSocket`, ouvert par `pre.001`; il conserve l’audit Helius du 23 août 2026, la matrice provider, le choix `HeliusLaserStream`, la stratégie transaction/heartbeat/Config/secrets et le forecast souple recalibré.
|
||||
|
||||
Le `pre.001` de chaque release fonctionnelle peut introduire son propre plan détaillé lorsque la release s'ouvre.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md -->
|
||||
<!-- version: 82 -->
|
||||
<!-- version: 83 -->
|
||||
|
||||
# Séquence des releases fonctionnelles KSP
|
||||
|
||||
@@ -465,7 +465,11 @@ La candidate atteint `pre.014` après matérialisation des 9 familles standard,
|
||||
|
||||
### `0.2.8` — Helius LaserStream WebSocket
|
||||
|
||||
Mission : étendre le moteur WebSocket standard avec les opérations/filtres/capabilities Helius ciblés sans copier le client.
|
||||
Mission active : étendre le moteur WebSocket standard avec la surface Helius LaserStream WebSocket actuelle sans copier le client/session actor. Le gate `pre.001` est conservé dans [`015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md`](015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md) et la matrice active dans [`../validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md`](../validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md).
|
||||
|
||||
L'audit Helius du 23 août 2026 retient `helius_laserstream` comme nouveau protocol kind : les six familles standard `account/logs/program/root/signature/slot` réutilisent les wrappers publiés, tandis que `block/slotsUpdates/vote` sont rejetées avant I/O sur Helius selon l'index provider exhaustif. `transactionSubscribe`/`transactionUnsubscribe` et `tokenAccounts` constituent la nouvelle surface typed principale. `notifyOn`, désormais deprecated et no-op depuis Agave 4.2, n'est pas exposé. Un heartbeat Helius-only est planifié dans l'actor existant pour le timeout d'inactivité provider.
|
||||
|
||||
Le forecast souple est recalibré jusqu'à `pre.010` avant `rel.001`; le numéro final reste non contractuel. Aucun SDK Helius, aucune dépendance gRPC et aucun replay historique WebSocket ne sont introduits.
|
||||
|
||||
### `0.2.9` — Yellowstone gRPC standard
|
||||
|
||||
|
||||
739
docs/plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md
Normal file
739
docs/plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md
Normal file
@@ -0,0 +1,739 @@
|
||||
<!-- file: docs/plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Plan `0.2.8` — Helius LaserStream WebSocket
|
||||
|
||||
> **Statut : gate `0.2.8-pre.001` préparé, publication conditionnée aux graphes Cargo opérateur.** L'audit normatif Helius du 23 août 2026, l'inventaire du runtime `v0.2.7`, le threat model provider et le sizing sont fermés. Aucun runtime Helius, aucun changement Config provider et aucune nouvelle dépendance ne sont introduits dans `pre.001`.
|
||||
|
||||
## 1. Objet et base vérifiée
|
||||
|
||||
`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 client/session actor et sans confondre WebSocket avec LaserStream gRPC.
|
||||
|
||||
Base autoritaire auditée :
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
La combinaison archive stable fournie + version Cargo stable + delta `rel.001` + prompt actif satisfait la base documentaire exigée par le prompt. Les souvenirs, prereleases et anciennes copies ne sont pas utilisés comme autorité.
|
||||
|
||||
`0.2.8-pre.001` ouvre techniquement :
|
||||
|
||||
```text
|
||||
workspace.package.version = 0.2.8-pre.1
|
||||
livraison = 0.2.8-pre.001
|
||||
commit attendu = v0.2.8-pre.001
|
||||
aucun tag prerelease
|
||||
```
|
||||
|
||||
## 2. Sources internes relues et hiérarchie appliquée
|
||||
|
||||
Les sources internes obligatoires du prompt ont été relues depuis la base stable, notamment :
|
||||
|
||||
```text
|
||||
RULES.md
|
||||
docs/000-README.md
|
||||
docs/rules/RULES_GENERAL.md
|
||||
docs/rules/RULES_KSP.md
|
||||
docs/rules/RULES_RUST.md
|
||||
docs/rules/RULES_DEPENDENCIES.md
|
||||
docs/rules/RULES_DOCUMENTATION.md
|
||||
docs/rules/FILE_CONTRACTS.md
|
||||
docs/rules/VERSION_WORKFLOW.md
|
||||
docs/rules/PROMPT_STRUCTURE.md
|
||||
|
||||
docs/architecture/000-README.md
|
||||
docs/architecture/002-LAYERS_AND_DEPENDENCIES.md
|
||||
docs/architecture/003-COMPONENT_CONTRACTS.md
|
||||
docs/architecture/004-COMPONENT_INVENTORY.md
|
||||
docs/architecture/005-DEPENDENCY_GRAPH.md
|
||||
docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md
|
||||
docs/architecture/010-APPS_SERVICES_SCENARIOS_AND_CONTROL.md
|
||||
|
||||
docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md
|
||||
docs/plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md
|
||||
docs/plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md
|
||||
docs/validation/003-V0_2_1_ONCHAIN_HTTP.md
|
||||
docs/validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md
|
||||
docs/validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md
|
||||
docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md
|
||||
|
||||
deltas/0.2.7/rel.001.md
|
||||
docs/IDEAS.md
|
||||
|
||||
crates/ksp-onchain-transport-lib/Cargo.toml
|
||||
crates/ksp-onchain-transport-lib/README.md
|
||||
crates/ksp-onchain-transport-lib/USAGE.md
|
||||
crates/ksp-onchain-transport-lib/src/**
|
||||
crates/ksp-onchain-transport-lib/tests/**
|
||||
crates/ksp-config-lib/Cargo.toml
|
||||
crates/ksp-config-lib/src/transport.rs
|
||||
crates/ksp-config-lib/unit_tests/transport.rs
|
||||
config/std.transport.json
|
||||
config/schemas/std.transport.schema.json
|
||||
.env.example
|
||||
```
|
||||
|
||||
Décisions de workflow conservées :
|
||||
|
||||
- `pre.001` est audit + brainstorming + sizing ;
|
||||
- une prerelease non-fix synchronise toujours Cargo ;
|
||||
- une tranche vise nominalement environ 15–20 minutes de travail effectif ;
|
||||
- le forecast est souple et doit être recalibré, jamais traité comme une deadline ;
|
||||
- `ROADMAP.md` reste global ; les détails des prereleases vivent dans le plan, la validation et les deltas ;
|
||||
- `CHANGELOG.md` reste réservé principalement à la publication stable.
|
||||
|
||||
## 3. Baseline de démarrage
|
||||
|
||||
### 3.1 Preuve opérateur fournie sur `v0.2.7`
|
||||
|
||||
Le log opérateur joint à la session enregistre, avant ouverture de `0.2.8` :
|
||||
|
||||
```text
|
||||
cargo fmt --all OK
|
||||
python3 scripts/audit_rust_workspace_rules.py OK
|
||||
General Rust rule audit clean
|
||||
Rust export completeness audit 0 candidate(s)
|
||||
KSP workspace Rust rule audit clean
|
||||
cargo check --workspace OK
|
||||
cargo clippy --workspace --all-targets OK
|
||||
cargo test --workspace OK
|
||||
```
|
||||
|
||||
Les tests live/bench explicitement opt-in restent ignorés par défaut, conformément à leurs contrats.
|
||||
|
||||
### 3.2 Baseline du sandbox de préparation
|
||||
|
||||
Le sandbox de préparation ne fournit pas `cargo`. Avant modification :
|
||||
|
||||
```text
|
||||
python3 scripts/audit_rust_workspace_rules.py OK
|
||||
cargo fmt/check/clippy/tree IMPOSSIBLE : cargo absent
|
||||
```
|
||||
|
||||
L'archive ne contient pas `.git`; `git status`/validation du tag n'est donc pas disponible dans ce sandbox.
|
||||
|
||||
Aucun `cargo tree` de `v0.2.7` n'a été fourni dans le log opérateur de cette session. Les deux graphes imposés par le prompt restent donc un **gate opérateur avant commit** de `pre.001` :
|
||||
|
||||
```bash
|
||||
cargo tree -p ksp-onchain-transport-lib
|
||||
cargo tree -p ksp-onchain-transport-lib --duplicates
|
||||
```
|
||||
|
||||
## 4. État réel hérité de `v0.2.7`
|
||||
|
||||
### 4.1 HTTP à ne pas régresser
|
||||
|
||||
Le contrat stable reste :
|
||||
|
||||
```text
|
||||
52/52 méthodes HTTP courantes typées
|
||||
14/14 méthodes historiques Deprecated/Removed conservées
|
||||
KSP-TRANSPORT-007 appliqué
|
||||
write submissions sans resend après dispatch ambigu
|
||||
```
|
||||
|
||||
### 4.2 WebSocket standard publié
|
||||
|
||||
Le runtime stable expose neuf familles :
|
||||
|
||||
```text
|
||||
Account
|
||||
Block
|
||||
Logs
|
||||
Program
|
||||
Root
|
||||
Signature
|
||||
Slot
|
||||
SlotsUpdates
|
||||
Vote
|
||||
```
|
||||
|
||||
avec les paires exactes subscribe/unsubscribe et la partition :
|
||||
|
||||
```text
|
||||
stable : Account, Logs, Program, Root, Signature, Slot
|
||||
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é.
|
||||
|
||||
### 4.3 Contrats publics utiles
|
||||
|
||||
`WsProtocolKind` est `#[non_exhaustive]` mais ne contient que :
|
||||
|
||||
```text
|
||||
SolanaStandard -> "solana_standard"
|
||||
```
|
||||
|
||||
`WsEndpointSettings` possède déjà le conteneur commun nécessaire :
|
||||
|
||||
```text
|
||||
name
|
||||
enabled
|
||||
provider
|
||||
cluster
|
||||
protocol kind
|
||||
WsEndpointUrl redacted
|
||||
WsSessionSettings
|
||||
```
|
||||
|
||||
`WsSubscriptionKind` est lui aussi non exhaustif et centralise pour les neuf familles les triplets :
|
||||
|
||||
```text
|
||||
subscribe method
|
||||
unsubscribe method
|
||||
notification method
|
||||
```
|
||||
|
||||
`WsSession::subscribe_typed` est interne à la crate et constitue le point naturel de contrôle de capability avant émission JSON-RPC.
|
||||
|
||||
### 4.4 Config V2
|
||||
|
||||
Le document stable conserve :
|
||||
|
||||
```text
|
||||
format_version = 2
|
||||
retry
|
||||
ws_defaults
|
||||
default_profile
|
||||
profiles[].endpoints[]
|
||||
profiles[].ws_endpoints[].kind
|
||||
```
|
||||
|
||||
Le schema et l'adapter n'acceptent aujourd'hui que :
|
||||
|
||||
```text
|
||||
solana_standard
|
||||
```
|
||||
|
||||
La structure a été volontairement rendue extensible en `0.2.7`; il n'est pas nécessaire de créer un nouveau conteneur provider.
|
||||
|
||||
## 5. Audit Helius officiel du 2026-08-23
|
||||
|
||||
### 5.1 Sources primaires utilisées
|
||||
|
||||
Sources Helius relues :
|
||||
|
||||
```text
|
||||
https://www.helius.dev/docs/rpc/websocket
|
||||
https://www.helius.dev/docs/api-reference/rpc/websocket-methods
|
||||
https://www.helius.dev/docs/api-reference/rpc/websocket/transactionsubscribe
|
||||
https://www.helius.dev/docs/rpc/websocket/transaction-subscribe
|
||||
https://www.helius.dev/docs/rpc/websocket/token-account-filtering
|
||||
https://www.helius.dev/docs/api-reference/rpc/websocket/accountsubscribe
|
||||
https://www.helius.dev/docs/rpc/websocket/account-subscribe
|
||||
https://www.helius.dev/docs/api-reference/rpc/websocket/programsubscribe
|
||||
https://www.helius.dev/docs/api-reference/rpc/websocket/slotsupdatessubscribe
|
||||
https://www.helius.dev/docs/faqs/websockets
|
||||
https://www.helius.dev/docs/api-reference/rpc/websocket/llms.txt
|
||||
https://www.helius.dev/docs/llms.txt
|
||||
```
|
||||
|
||||
Les documents `llms.txt` servent d'index et de source secondaire de rapprochement. 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 au lieu d'être résolue silencieusement.
|
||||
|
||||
### 5.2 Terminologie et endpoints
|
||||
|
||||
Décisions normatives :
|
||||
|
||||
```text
|
||||
nom produit courant = LaserStream WebSocket
|
||||
ancien nom = Enhanced WebSockets, désormais intégré à LaserStream WebSocket
|
||||
mainnet = wss://mainnet.helius-rpc.com/?api-key=...
|
||||
devnet = wss://devnet.helius-rpc.com/?api-key=...
|
||||
credential = api-key en query URL, Secret
|
||||
Gatekeeper beta = hors 0.2.8
|
||||
LaserStream gRPC = distinct, hors 0.2.8
|
||||
```
|
||||
|
||||
La FAQ Helius confirme que les anciens chemins Enhanced WebSockets redirigent vers la famille LaserStream WebSocket et que les méthodes standard/Helius passent par les mêmes endpoints par réseau.
|
||||
|
||||
### 5.3 Inventaire provider retenu
|
||||
|
||||
La page exhaustive **LaserStream WebSocket Methods** distingue :
|
||||
|
||||
```text
|
||||
standard supporté : account, logs, program, root, signature, slot
|
||||
Helius extension : transactionSubscribe
|
||||
non supporté : block, slotsUpdates, vote
|
||||
```
|
||||
|
||||
`transactionUnsubscribe` n'est pas listé comme entrée séparée dans l'index des méthodes, mais la référence `transactionSubscribe` le documente explicitement avec :
|
||||
|
||||
```text
|
||||
method = transactionUnsubscribe
|
||||
params = [remoteSubscriptionId]
|
||||
result = true
|
||||
```
|
||||
|
||||
et précise que quelques notifications in-flight peuvent encore arriver après l'unsubscribe.
|
||||
|
||||
### 5.4 Divergence `slotsUpdatesSubscribe`
|
||||
|
||||
Les sources Helius se contredisent :
|
||||
|
||||
- la page exhaustive `websocket-methods` classe explicitement `slotsUpdatesSubscribe`/`slotsUpdatesUnsubscribe` dans **Unstable Methods (Not Supported)** ;
|
||||
- la page individuelle dit que la méthode est unstable et « may not always be supported » ;
|
||||
- le fichier `websocket/llms.txt` la place paradoxalement dans une section « Stable, Helius-supported » avant d'introduire une section de méthodes unstable non supportées.
|
||||
|
||||
Décision KSP du gate :
|
||||
|
||||
```text
|
||||
HeliusLaserStream + SlotsUpdates -> capability Unsupported, rejet avant I/O
|
||||
```
|
||||
|
||||
Raison : la page exhaustive courante énonce le support provider le plus explicitement. Un futur réaudit peut changer cette décision si Helius harmonise sa documentation ou si une preuve live sûre l'infirme.
|
||||
|
||||
### 5.5 `transactionSubscribe`
|
||||
|
||||
Filtre documenté courant :
|
||||
|
||||
```text
|
||||
vote Option<bool>
|
||||
failed Option<bool>
|
||||
signature Option<string>
|
||||
accountInclude Option<string[]> max 50_000
|
||||
accountExclude Option<string[]> max 50_000
|
||||
accountRequired Option<string[]> max 50_000
|
||||
tokenAccounts none | balanceChanged | all
|
||||
```
|
||||
|
||||
`tokenAccounts` étend la correspondance owner/ATA pour les adresses d'`accountInclude`; `none` équivaut à l'absence. Une valeur invalide reçoit actuellement `-32602` côté provider. KSP doit rendre les trois valeurs représentables par type et ne pas exposer une string arbitraire.
|
||||
|
||||
Options documentées :
|
||||
|
||||
```text
|
||||
commitment processed | confirmed | finalized
|
||||
encoding base58 | base64 | jsonParsed
|
||||
transactionDetails full | signatures | accounts | none
|
||||
showRewards bool
|
||||
maxSupportedTransactionVersion integer
|
||||
```
|
||||
|
||||
La référence impose `maxSupportedTransactionVersion` lorsque `transactionDetails` vaut `accounts` ou `full`.
|
||||
|
||||
Notification :
|
||||
|
||||
```text
|
||||
method = transactionNotification
|
||||
```
|
||||
|
||||
La forme `full` illustrée contient :
|
||||
|
||||
```text
|
||||
transaction.transaction
|
||||
transaction.meta
|
||||
signature
|
||||
slot
|
||||
transactionIndex
|
||||
```
|
||||
|
||||
La documentation officielle ne détaille pas avec la même précision la forme de résultat de chacun des quatre modes `transactionDetails`. **KSP ne doit pas inventer ces formes.** Le plan retient un contrat typé capable de représenter les formes prouvées et un fallback `Unknown` borné pour les formes/futures variantes non suffisamment documentées, sur le modèle déjà utilisé pour les variantes standard évolutives.
|
||||
|
||||
### 5.6 `accountSubscribe` / `programSubscribe` et `notifyOn`
|
||||
|
||||
Les références courantes de `accountSubscribe` et `programSubscribe` documentent `notifyOn` mais le marquent :
|
||||
|
||||
```text
|
||||
deprecated
|
||||
no-op depuis Agave 4.2
|
||||
suppression future annoncée
|
||||
```
|
||||
|
||||
Décision : **ne pas ajouter `notifyOn` aux DTOs KSP**.
|
||||
|
||||
La FAQ et les indexes continuent d'employer l'expression « enhanced/filtered accountSubscribe », mais la page API courante et le guide `accountSubscribe` ne publient pas de wire provider-specific supplémentaire précis au-delà du contrat standard et du champ `notifyOn` devenu no-op.
|
||||
|
||||
Décision :
|
||||
|
||||
```text
|
||||
Account/Program sur HeliusLaserStream -> wrappers standard KSP réutilisés tels quels
|
||||
nouveau DTO provider account/program -> non
|
||||
notifyOn -> non exposé
|
||||
extension account provider non spécifiée exactement -> reportée explicitement
|
||||
```
|
||||
|
||||
Le report n'est pas un oubli : une surface provider ne sera ajoutée que lorsqu'une référence courante fournit un contrat wire exact et testable.
|
||||
|
||||
## 6. Matrice normative Helius WebSocket
|
||||
|
||||
| Famille | Paire | Classe | Support Helius retenu | Paramètres/options utiles | Notification | Idle/credential | Stratégie KSP/test |
|
||||
|---------------------|-----------------------------------------------------|------------------|------------------------------------------------|----------------------------------------------------------|--------------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|
|
||||
| `account` | `accountSubscribe` / `accountUnsubscribe` | Solana standard | Oui | contrat standard ; `notifyOn` deprecated/no-op donc omis | `accountNotification` | ping provider ; api-key query | wrapper 0.2.7 inchangé + fixture capability |
|
||||
| `block` | `blockSubscribe` / `blockUnsubscribe` | Solana unstable | **Non** | aucune émission provider | `blockNotification` théorique | api-key query | rejet capability avant I/O |
|
||||
| `logs` | `logsSubscribe` / `logsUnsubscribe` | Solana standard | Oui | contrat standard | `logsNotification` | ping provider ; api-key query | wrapper 0.2.7 inchangé |
|
||||
| `program` | `programSubscribe` / `programUnsubscribe` | Solana standard | Oui | contrat standard ; `notifyOn` deprecated/no-op donc omis | `programNotification` | ping provider ; api-key query | wrapper 0.2.7 inchangé + filtres existants |
|
||||
| `root` | `rootSubscribe` / `rootUnsubscribe` | Solana standard | Oui | aucun paramètre | `rootNotification` | ping provider ; api-key query | wrapper 0.2.7 inchangé |
|
||||
| `signature` | `signatureSubscribe` / `signatureUnsubscribe` | Solana standard | Oui | contrat standard ; one-shot conservé | `signatureNotification` | ping provider ; api-key query | wrapper 0.2.7 + fermeture terminale inchangée |
|
||||
| `slot` | `slotSubscribe` / `slotUnsubscribe` | Solana standard | Oui | aucun paramètre | `slotNotification` | ping provider ; api-key query | wrapper 0.2.7 inchangé |
|
||||
| `slotsUpdates` | `slotsUpdatesSubscribe` / `slotsUpdatesUnsubscribe` | Solana unstable | **Non** par page exhaustive ; docs divergentes | aucune émission provider | `slotsUpdatesNotification` théorique | api-key query | rejet avant I/O + canari divergence |
|
||||
| `vote` | `voteSubscribe` / `voteUnsubscribe` | Solana unstable | **Non** | aucune émission provider | `voteNotification` théorique | api-key query | rejet capability avant I/O |
|
||||
| `heliusTransaction` | `transactionSubscribe` / `transactionUnsubscribe` | Helius extension | Oui | filtres + `tokenAccounts`; options complètes ci-dessus | `transactionNotification` | ping provider ; api-key query ; extension Developer+ d'après index | nouveaux DTOs typed + fixtures exactes + actor existant |
|
||||
|
||||
Statut provider de la surface standard :
|
||||
|
||||
```text
|
||||
6 paires standard supportées
|
||||
3 paires standard explicitement non supportées
|
||||
1 paire Helius transaction ajoutée
|
||||
```
|
||||
|
||||
La compliance standard globale KSP reste toutefois **18/18** : les 18 opérations continuent d'exister et de fonctionner pour `WsProtocolKind::SolanaStandard`; le protocol Helius applique une capability matrix différente.
|
||||
|
||||
## 7. Décisions d'architecture du gate
|
||||
|
||||
### 7.1 Nouveau protocol kind
|
||||
|
||||
Retenir :
|
||||
|
||||
```text
|
||||
WsProtocolKind::HeliusLaserStream
|
||||
as_str() = "helius_laserstream"
|
||||
provider metadata attendu = "helius"
|
||||
```
|
||||
|
||||
Pourquoi ne pas utiliser `SolanaStandard + provider=helius` : les capabilities et le heartbeat provider changent le comportement de session et l'ensemble de méthodes admissibles. Le discriminateur de protocole est précisément le contrat extensible préparé par `0.2.7`.
|
||||
|
||||
`provider` reste une metadata ouverte et sûre ; il ne devient pas un second discriminateur implicite.
|
||||
|
||||
### 7.2 Pas de nouveau moteur
|
||||
|
||||
Le chemin reste :
|
||||
|
||||
```text
|
||||
WsEndpointSettings
|
||||
-> WsSession::connect
|
||||
-> actor existant
|
||||
-> subscribe_typed / registry
|
||||
-> local WsSubscriptionId
|
||||
-> remote id interne/remappable
|
||||
```
|
||||
|
||||
Aucun `HeliusWsClient`, aucun second actor et aucun SDK Helius ne sont prévus.
|
||||
|
||||
### 7.3 Extension du registry de subscription
|
||||
|
||||
Retenir une nouvelle famille logique provider :
|
||||
|
||||
```text
|
||||
WsSubscriptionKind::HeliusTransaction
|
||||
subscribe = transactionSubscribe
|
||||
unsubscribe = transactionUnsubscribe
|
||||
notification = transactionNotification
|
||||
```
|
||||
|
||||
Le nom public exact pourra rester provider-explicite pour ne pas faire passer `transactionSubscribe` pour une méthode Solana standard.
|
||||
|
||||
### 7.4 Capability validation avant I/O
|
||||
|
||||
Ajouter une matrice déterministe `protocol kind x subscription kind` avant construction/envoi du RPC :
|
||||
|
||||
```text
|
||||
SolanaStandard:
|
||||
Account Block Logs Program Root Signature Slot SlotsUpdates Vote -> allowed
|
||||
HeliusTransaction -> rejected
|
||||
|
||||
HeliusLaserStream:
|
||||
Account Logs Program Root Signature Slot HeliusTransaction -> allowed
|
||||
Block SlotsUpdates Vote -> rejected
|
||||
```
|
||||
|
||||
Le rejet doit produire un code d'erreur sûr et stable sans URL/api-key/payload. Une erreur RPC provider reste possible pour des paramètres/quotas/plan runtime non déterministes et ne doit pas tuer la session physique sans raison.
|
||||
|
||||
### 7.5 DTOs transaction provider-specific
|
||||
|
||||
Créer des types dédiés, sans polluer les DTOs standard :
|
||||
|
||||
```text
|
||||
HeliusTransactionSubscribeFilter
|
||||
HeliusTokenAccountsMode
|
||||
HeliusTransactionEncoding
|
||||
HeliusTransactionSubscribeOptions
|
||||
HeliusTransactionNotification / variantes prouvées
|
||||
```
|
||||
|
||||
Réutilisations possibles après vérification d'égalité sémantique :
|
||||
|
||||
```text
|
||||
SolanaCommitment
|
||||
SolanaTransactionDetails
|
||||
SolanaEncodedTransaction / types transaction wire communs compatibles
|
||||
SolanaWireField<T>
|
||||
```
|
||||
|
||||
`HeliusTransactionEncoding` doit rester restreint aux valeurs documentées Helius (`base58`, `base64`, `jsonParsed`) plutôt que de réexporter automatiquement toutes les valeurs d'un enum HTTP plus large.
|
||||
|
||||
Validation locale prouvable :
|
||||
|
||||
```text
|
||||
accountInclude.len() <= 50_000
|
||||
accountExclude.len() <= 50_000
|
||||
accountRequired.len() <= 50_000
|
||||
accounts/full -> maxSupportedTransactionVersion requis
|
||||
```
|
||||
|
||||
Ne pas inventer de limite agrégée, de minimum ou d'interaction non documentée.
|
||||
|
||||
### 7.6 Heartbeat/idle ownership
|
||||
|
||||
Helius annonce un timeout d'inactivité de 10 minutes et recommande des pings périodiques, généralement toutes les 30–60 secondes / chaque minute.
|
||||
|
||||
Décision : **heartbeat provider-owned dans l'actor existant**, activé automatiquement pour `HeliusLaserStream`, sans devenir un champ public générique de `WsSessionSettings` dans cette release.
|
||||
|
||||
Politique cible :
|
||||
|
||||
```text
|
||||
intervalle nominal = 60 s
|
||||
frame = WebSocket Ping control frame
|
||||
actif uniquement quand la session est Active
|
||||
annulé pendant close / terminal failure
|
||||
réarmé après reconnect réussi
|
||||
échec d'écriture -> chemin disconnect/reconnect existant
|
||||
aucune boucle de reconnect infinie : budget 0.2.7 conservé
|
||||
aucun secret/payload dans logs
|
||||
```
|
||||
|
||||
Raison du choix : ce heartbeat est une exigence opérationnelle provider, pas une politique générique démontrée pour tous les protocoles. Une cadence configurable ne sera ajoutée que si un besoin réel apparaît.
|
||||
|
||||
Les réponses automatiques aux Ping entrants déjà acquises en `0.2.7` restent distinctes de ce Ping sortant périodique.
|
||||
|
||||
### 7.7 Config V2
|
||||
|
||||
Évolution retenue :
|
||||
|
||||
```text
|
||||
profiles[].ws_endpoints[].kind:
|
||||
solana_standard
|
||||
helius_laserstream
|
||||
```
|
||||
|
||||
Aucun nouveau conteneur Config et aucun champ heartbeat n'est requis au gate.
|
||||
|
||||
Les filtres/options de `transactionSubscribe` sont des paramètres de subscription runtime ; ils n'appartiennent pas au profil endpoint Config.
|
||||
|
||||
### 7.8 Credentials
|
||||
|
||||
L'api-key Helius reste uniquement contenue dans l'URL résolue :
|
||||
|
||||
```text
|
||||
wss://mainnet.helius-rpc.com/?api-key=${KSP_SECRET_HELIUS_API_KEY}
|
||||
```
|
||||
|
||||
Le nom exact de secret sera matérialisé en `pre.003`, sous le namespace secret KSP et avec `.env.example` sans vraie valeur. Transport ne lit jamais `std::env`; il reçoit seulement `WsEndpointUrl`, déjà redacted dans `Debug` et erreurs.
|
||||
|
||||
Aucun champ `api_key` n'est ajouté à `WsEndpointSettings`.
|
||||
|
||||
## 8. Threat model provider
|
||||
|
||||
### 8.1 Secret dans query URL
|
||||
|
||||
Risque : URL complète copiée dans `Debug`, erreur de handshake, logs tungstenite ou contexte `KspError`.
|
||||
|
||||
Mesures : conserver `WsEndpointUrl` opaque/redacted, erreurs mappées vers metadata sûre, canaris avec valeur secret reconnaissable et interdiction de l'observer dans `Debug`/Display/log context.
|
||||
|
||||
### 8.2 Heartbeat concurrent avec reconnect/close
|
||||
|
||||
Risque : timer continue après close, écrit sur ancien socket, déclenche reconnect parasite ou bloque l'actor.
|
||||
|
||||
Mesures : timer détenu par l'actor, sélectionné dans la boucle Active, reset/cancel avec le lifecycle, test temps raccourci déterministe par hook interne/test-only.
|
||||
|
||||
### 8.3 Late notifications et IDs distants
|
||||
|
||||
Helius documente des messages in-flight après `transactionUnsubscribe`. Le contrat KSP 0.2.7 est compatible : local unsubscribe gagne, remote id devient non routable et une notification tardive ne réactive pas la subscription.
|
||||
|
||||
### 8.4 Payload transaction volumineux
|
||||
|
||||
`transactionDetails=full`, rewards et metadata transaction peuvent produire des notifications nettement plus grosses que les familles standard légères.
|
||||
|
||||
Mesures : conserver `max_message_size_bytes`/`max_frame_size_bytes`, reject/reconnect borné sur frame oversized, notification queue par subscription et overflow isolé. Aucun payload brut dans snapshots/logs.
|
||||
|
||||
### 8.5 Filtres 50k
|
||||
|
||||
Trois listes indépendantes peuvent contenir jusqu'à 50 000 adresses chacune. Risques : mémoire de construction, clone inutile, sérialisation lourde et logs accidentels.
|
||||
|
||||
Mesures : validation de cardinalité avant I/O, pas de Debug affichant les listes, éviter les copies superflues et ne jamais projeter les adresses comme metadata de session.
|
||||
|
||||
### 8.6 Capability mismatch
|
||||
|
||||
Risque : envoyer `block/slotsUpdates/vote` à Helius puis interpréter `Method not found` comme panne session.
|
||||
|
||||
Mesure : capability validation locale déterministe. Les erreurs provider dynamiques restent des erreurs de subscription/request, pas une faillite du socket par défaut.
|
||||
|
||||
### 8.7 Continuité
|
||||
|
||||
LaserStream WebSocket ne reçoit aucune promesse KSP de replay historique. Après reconnect :
|
||||
|
||||
```text
|
||||
resubscribe oui
|
||||
continuity_gap_count oui
|
||||
backfill non
|
||||
historical replay non
|
||||
lossless non
|
||||
```
|
||||
|
||||
Les capacités de replay de LaserStream gRPC sont hors scope.
|
||||
|
||||
## 9. Audit dépendances
|
||||
|
||||
Dépendances directes déjà présentes et versions stables observées au 2026-08-23 :
|
||||
|
||||
```text
|
||||
futures-util 0.3.34
|
||||
tokio 1.53.1
|
||||
tokio-tungstenite 0.30.0
|
||||
reqwest 0.13.4
|
||||
```
|
||||
|
||||
Les contraintes workspace (`^0.3`, `^1.53`, `^0.30`, `^0.13`) restent compatibles avec ces versions. Aucun changement de manifest n'est justifié dans `pre.001`.
|
||||
|
||||
Verdict : **aucune nouvelle dépendance**.
|
||||
|
||||
Le moteur actuel sait déjà : WebSocket TLS, control Ping/Pong, timers Tokio, futures sink/stream, JSON serde. Un SDK Helius dupliquerait le moteur, introduirait des choix de lifecycle non KSP et n'est pas requis pour modéliser le wire.
|
||||
|
||||
Le graphe résolu/doublons doit encore être observé par les commandes opérateur `cargo tree` avant commit de cette prerelease.
|
||||
|
||||
## 10. Stratégie de tests
|
||||
|
||||
### 10.1 Gate principal : déterministe local
|
||||
|
||||
Prévoir des fixtures/local peers couvrant :
|
||||
|
||||
```text
|
||||
protocol capability matrix
|
||||
transactionSubscribe serialization exacte
|
||||
transactionUnsubscribe exact
|
||||
transactionNotification method exact
|
||||
ack/error RPC
|
||||
50k/50k/50k bounds
|
||||
maxSupportedTransactionVersion requirement
|
||||
tokenAccounts exact enum
|
||||
late notifications après unsubscribe
|
||||
remote id remapping reconnect/resubscribe
|
||||
provider RPC error sans session failure
|
||||
heartbeat timer + cancellation
|
||||
shutdown pendant heartbeat/reconnect
|
||||
oversized frame/message
|
||||
queue overflow isolé
|
||||
URL/api-key redaction
|
||||
public API canaries
|
||||
Config -> Transport mapping
|
||||
standard WS 18/18 non régressé
|
||||
HTTP 52 + 14 non régressé
|
||||
```
|
||||
|
||||
### 10.2 Smoke live Helius
|
||||
|
||||
Le live est opt-in et ne constitue pas la preuve principale de wire.
|
||||
|
||||
Stratégie retenue : composition Config -> Transport avec secret résolu par Config. Transport ne doit jamais faire `std::env` pour récupérer l'api-key.
|
||||
|
||||
Le smoke ne sera matérialisé qu'après le contrat Config de `pre.003`. En absence de credential opérateur sûr, la release peut rester déterministiquement conforme et documenter le smoke opérateur plutôt que de violer les frontières.
|
||||
|
||||
## 11. Questions explicitement reportées
|
||||
|
||||
```text
|
||||
forme provider-specific exacte de « enhanced/filtered accountSubscribe » non publiée clairement
|
||||
modes transactionNotification non suffisamment documentés pour inventer leurs DTOs
|
||||
Gatekeeper beta
|
||||
provider metering/billing
|
||||
LaserStream gRPC / replay
|
||||
Yellowstone gRPC
|
||||
pool/scheduler automatique de sessions
|
||||
configuration publique arbitraire du heartbeat
|
||||
```
|
||||
|
||||
Le premier point doit être réaudité à la compliance finale. Si Helius publie un wire exact pendant `0.2.8`, le forecast peut ajouter une tranche dédiée ; il ne doit pas être injecté silencieusement dans un DTO standard.
|
||||
|
||||
## 12. Sizing et forecast recalibré
|
||||
|
||||
L'audit réduit le scope par rapport au forecast initial : `notifyOn` ne doit pas être implémenté et aucune extension account/program exacte supplémentaire n'est actuellement spécifiable. La difficulté se concentre sur `transactionSubscribe`, capability validation et heartbeat provider.
|
||||
|
||||
Prévision souple recalibrée :
|
||||
|
||||
```text
|
||||
pre.001 audit actuel + matrice + architecture + threat model + dependencies + sizing
|
||||
preuves : ce plan + validation/011 + delta ; graphes Cargo opérateur requis ; aucun runtime Helius
|
||||
|
||||
pre.002 WsProtocolKind::HeliusLaserStream + WsSubscriptionKind::HeliusTransaction
|
||||
+ capability matrix + erreurs/redaction/public canaries
|
||||
preuves : aucun second client ; 6 standard Helius admis, 3 standard Helius rejetés avant I/O
|
||||
|
||||
pre.003 Config V2 helius_laserstream + schema/fixtures + mapping Config -> Transport
|
||||
+ stratégie de secret Helius
|
||||
preuves : V1/V2 backward, unknown kind rejeté, URL secret redacted, aucune dépendance inverse
|
||||
|
||||
pre.004 transactionSubscribe request typed + filters/options/tokenAccounts + transactionUnsubscribe
|
||||
preuves : wire exact, bounds 50k, max version conditionnel, ack/error fixtures, aucune string raw publique
|
||||
|
||||
pre.005 transactionNotification typed + actor integration + reconnect/resubscribe/unsubscribe races
|
||||
preuves : formes officielles prouvées, fallback borné, remote/local remap, late notification ignorée
|
||||
|
||||
pre.006 heartbeat Helius 60s + interaction control frames/reconnect/shutdown
|
||||
preuves : tests temporels locaux déterministes, cancellation bornée, échec Ping -> lifecycle existant
|
||||
|
||||
pre.007 provider adversarial lifecycle + payload/backpressure + security
|
||||
preuves : provider RPC error isolée, oversized, queue overflow, secret canaries, mismatch capability
|
||||
|
||||
pre.008 compliance Helius + non-régression standard 18/18 + HTTP 52/14 + Config/API canaries
|
||||
preuves : matrice rapprochée source par source, account/program standard inchangés, aucun scope silencieux
|
||||
|
||||
pre.009 smoke Helius opt-in si credential/config sûrs + README/USAGE + audit dependencies/duplicates
|
||||
preuves : smoke sans secret versionné si réalisable ; cargo tree direct + duplicates ; docs version-neutral
|
||||
|
||||
pre.010 validation workspace finale + fermeture plan/matrice/indexes + prompt 0.2.9
|
||||
preuves : workspace complet vert, docs cohérentes, dépendances finales auditées, prompt suivant autonome
|
||||
|
||||
rel.001 publication stable stricte
|
||||
```
|
||||
|
||||
Budget nominal : chaque tranche vise environ **15–20 minutes** de travail effectif.
|
||||
|
||||
Critères de split/addition :
|
||||
|
||||
- une tranche dépasse réellement ~20 minutes parce que notification decoding ou lifecycle cache plusieurs problèmes indépendants ;
|
||||
- Helius publie une nouvelle surface provider WebSocket normative avant le gate final ;
|
||||
- la forme exacte de plusieurs modes `transactionDetails` nécessite une investigation distincte ;
|
||||
- la stratégie live impose une surface d'intégration qui n'existe pas encore ;
|
||||
- un défaut du moteur standard doit être corrigé séparément plutôt que masqué dans une tranche provider.
|
||||
|
||||
`pre.010` n'est pas une deadline. Des `pre.011+` ou fixes seront ajoutés si nécessaire.
|
||||
|
||||
## 13. Verdict du gate `pre.001`
|
||||
|
||||
### Décisions fermées
|
||||
|
||||
```text
|
||||
base stable autoritaire confirmé
|
||||
surface officielle Helius actuelle auditée
|
||||
terminologie LaserStream WebSocket clarifiée
|
||||
protocol kind HeliusLaserStream / helius_laserstream
|
||||
moteur WsSession actor existant réutilisé
|
||||
standard Helius 6 paires supportées / 3 rejetées
|
||||
transaction pair transactionSubscribe / transactionUnsubscribe
|
||||
transaction notification transactionNotification
|
||||
transaction filters/options inventoriés, tokenAccounts inclus
|
||||
notifyOn deprecated no-op, non exposé
|
||||
account/program provider extras report explicite faute de wire exact courant
|
||||
capability validation avant I/O
|
||||
heartbeat actor provider-owned, 60s cible
|
||||
Config V2 kind addition, pas de nouveau conteneur
|
||||
credential URL Secret résolue par Config, jamais env direct Transport
|
||||
new dependency aucune
|
||||
historical/lossless replay aucune promesse
|
||||
forecast recalibré pre.001 -> pre.010
|
||||
```
|
||||
|
||||
### Point restant avant commit
|
||||
|
||||
Le gate n'est **pas déclaré entièrement positif dans ce sandbox** tant que les deux graphes Cargo obligatoires n'ont pas été exécutés par l'opérateur :
|
||||
|
||||
```bash
|
||||
cargo tree -p ksp-onchain-transport-lib
|
||||
cargo tree -p ksp-onchain-transport-lib --duplicates
|
||||
```
|
||||
|
||||
Aucun code provider ne doit commencer avant cette preuve. Si les graphes ne révèlent pas de dérive incompatible, `pre.001` peut être validé/commité et `pre.002` ouvrir le runtime provider.
|
||||
Reference in New Issue
Block a user