v0.2.7-pre.009

This commit is contained in:
2026-08-22 23:08:47 +02:00
parent 93199d1856
commit d17161234a
15 changed files with 1093 additions and 35 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md -->
<!-- version: 10 -->
<!-- version: 11 -->
# Plan `0.2.7` — WebSocket Solana standard
@@ -780,6 +780,36 @@ Définir des DTOs WS dédiés pour : enveloppes notification, lifecycle, subscri
Pour unstable/évolutif, préférer des enums avec fallback `Unknown { type_name, raw }` borné plutôt qu'un rejet session-wide d'un variant upstream nouveau.
### 16.1 Checkpoint wrappers stables lot A `pre.009`
Le premier lot public conserve exactement les options retenues par l'audit :
```text
accountSubscribe
pubkey
encoding = binary | base58 | base64 | jsonParsed | base64+zstd
dataSlice
commitment
minContextSlot non exposé : champ upstream partagé mais ignoré par le handler PubSub v4.2.1
programSubscribe
program pubkey
mêmes encoding/dataSlice/commitment account
filters = dataSize | memcmp | tokenAccountState
withContext omitted/false/true
sortResults non exposé : option HTTP non consommée par le handler PubSub audité
notification = keyed account bare OU RpcResponse<KeyedAccount>
logsSubscribe
filter = all | allWithVotes | mentions exactement une pubkey
commitment
notification = RpcResponse<{ signature, err nullable, logs ordonnés }>
```
Les wrappers publics sont `WsSession::account_subscribe`, `WsSession::program_subscribe` et `WsSession::logs_subscribe`. Ils retournent tous `WsSubscription<T>` et réutilisent donc sans duplication le registry local, le remapping remote/local, le reconnect/resubscribe, le backpressure et l'unsubscribe par handle. Le constructeur générique `subscribe_typed` reste `pub(crate)` et aucune méthode provider-extension arbitraire n'entre dans l'API publique.
La forme `Mentions(Pubkey)` rend la cardinalité `mentions == 1` vraie par construction. Les contraintes déterministes déjà retenues pour les filtres programme sont conservées côté WS : maximum quatre filtres et maximum 128 octets pour la variante raw `Bytes` de `memcmp`; les formes encodées restent laissées au runtime upstream comme sur la surface HTTP existante.
## 17. API générique provider-specific
Le moteur interne doit encoder une spec générique `subscribe_method + unsubscribe_method + params + decoder`, afin qu'une release provider-specific puisse réutiliser la session.
@@ -887,7 +917,7 @@ pre.005 DONE — limites frame/message/request + control frames + cancellation/
pre.006 DONE — registry subscriptions + IDs locaux + generic subscribe/unsubscribe engine + channels typed bounded
pre.007 DONE — reconnect borné + resubscribe déterministe + continuity gap + races unsubscribe/reconnect
pre.008 DONE — backpressure per-sub + overflow/limits + causes terminales sûres + leak/lifecycle adversarial tests
pre.009 wrappers stable lot A : account + program + logs, DTOs/options/KSP-TRANSPORT-007
pre.009 DONE — wrappers stable lot A : account + program + logs, DTOs/options/KSP-TRANSPORT-007
pre.010 wrappers stable lot B : signature + slot + root, terminaison signature/KSP-TRANSPORT-007
pre.011 unstable : block + slotsUpdates + vote, warnings + fallbacks wire/KSP-TRANSPORT-007
pre.012 compliance 18/18 + canaries public API + composition Config + régressions HTTP

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md -->
<!-- version: 10 -->
<!-- version: 11 -->
# Validation `0.2.7` — WebSocket Solana standard
@@ -481,6 +481,45 @@ resubscribe RPC application error -> rpc_application_error terminal sur le handl
`overflow_count` et `continuity_gap_count` sont deux signaux distincts : le premier mesure les saturations locales de consumers, le second les ruptures de continuité physique. Aucun des deux ne déclenche de replay ou de backfill automatique. Les causes terminales n'exposent qu'un `ErrorCode` KSP, jamais le payload distant, le remote subscription ID ou l'URL.
## 9.7 Checkpoint wrappers stables lot A `pre.009`
Surface publique ajoutée :
```text
WsSession::account_subscribe
SolanaAccountSubscribeConfig
WsSubscription<SolanaRpcResponse<SolanaAccount>>
WsSession::program_subscribe
SolanaProgramSubscribeConfig
SolanaProgramNotification = bare keyed account | contextual keyed account
WsSession::logs_subscribe
SolanaLogsSubscribeFilter = All | AllWithVotes | Mentions(Pubkey)
SolanaLogsNotification = signature + err nullable + logs ordonnés
```
Gates déterministes ajoutés :
```text
accountSubscribe -> params exacts pubkey + encoding/dataSlice/commitment
accountSubscribe -> aucun minContextSlot promis ou sérialisable par le config WS
accountNotification -> SolanaRpcContext + SolanaAccount partagé
account handle unsubscribe -> accountUnsubscribe avec remote ID interne
programSubscribe -> filters + withContext préservés, sortResults absent
program filters -> >4 et raw memcmp >128 rejetés avant émission subscribe
programNotification -> forme bare acceptée
programNotification -> forme contextualisée acceptée
program handle unsubscribe -> programUnsubscribe exact
logs filter -> all/allWithVotes/mentions exactement une pubkey
logsNotification -> context + signature + err null/object + ordre logs préservés
logsNotification sans champ err requis -> invalid_response typed, session non concernée
logs handle unsubscribe -> logsUnsubscribe exact
API publique -> aucun subscribe(method, raw params) exposé
```
Les trois wrappers passent par le même moteur actor/registry acquis en `pre.006``pre.008`; les remote IDs ne deviennent donc pas publics et les paramètres typés initiaux restent les specs rejouées lors d'un resubscribe `ActiveSubscriptions`. Le lot B (`signature`, `slot`, `root`) reste explicitement différé à `pre.010`.
## 10. Validation du gate `pre.001`
Exécuté dans le sandbox :