Files
khadhroony-solana-project/deltas/0.3.14/pre.003.md
2026-09-11 21:54:19 +02:00

334 lines
11 KiB
Markdown

<!-- file: deltas/0.3.14/pre.003.md -->
<!-- version: 1 -->
# Delta `0.3.14-pre.003` — observabilité latest-value de continuité WebSocket
## Base requise
```text
0.3.14-pre.002-fix.002
workspace.package.version = 0.3.14-pre.2.fix.2
deltas/0.3.14/pre.002-fix.002.md présent
```
## Gate de la base
Le gate opérateur de `0.3.14-pre.002-fix.002` est validé avant ouverture de cette tranche :
```text
cargo fmt --all : PASS
cargo fmt --all -- --check : PASS
audit Rust workspace rules : PASS
audit Markdown tables : PASS
cargo check --workspace : PASS
cargo clippy --workspace --all-targets --all-features -- -D warnings : PASS
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features : PASS
```
Le gate Worker comprend notamment :
```text
114 unit tests : PASS
cross_layer_completeness : 8 PASS
dependency_boundary : 19 PASS
hardening : 27 PASS
public_api : 20 PASS
release_completeness : 5 PASS
```
## Objectif
Implémenter strictement la tranche `pre.003` du plan `035` :
```text
ajouter dans Transport une source latest-value sûre pour les snapshots WebSocket typés
la déléguer depuis les façades Standard et Helius existantes
observer les incidents reconnect/overflow dans les sources Standard Logs, Standard Block et Helius du Worker
ancrer un incident sur le dernier slot réellement observé par cette source
borner l'incident avec le premier slot post-incident réellement reçu
conserver une terminalité conservative tant que les tranches de replay/repair ultérieures ne sont pas présentes
ne créer aucun nouveau socket, actor, retry ou repair HTTP
```
Cette tranche ne remplace pas encore un gap WebSocket par une réparation. Elle rend l'incident explicitement observable et bornable en réutilisant exclusivement les snapshots déjà publiés par l'actor Transport existant.
## Transport — source latest-value WebSocket
`WsSession` possède déjà un `tokio::sync::watch::Receiver<WsSessionSnapshot>` interne utilisé pour `snapshot()` et `state()`.
`pre.003` ajoute `WsSessionSnapshotSource`, un observateur cloneable qui encapsule uniquement un clone de ce receiver et expose :
```text
current() -> dernier WsSessionSnapshot sûr
wait_for_change() -> prochaine valeur latest-value, ou None si l'actor disparaît
```
Le type ne contient ni URL, ni credentials, ni socket, ni payload de notification. Son `Debug` reste fondé sur la projection sûre existante.
`WsSession::snapshot_source()` clone le receiver existant. Les façades :
```text
SolanaStandardWsSession
HeliusLaserStreamWsSession
```
délèguent cette méthode au même `WsSession` physique. Aucun second runtime WebSocket n'est créé.
## Worker — ancre d'incident WebSocket
Le Worker introduit un contrat crate-private `RawTransactionIngestWebSocketIncidentAnchor`.
Il conserve uniquement :
```text
start_slot
end_slot optionnel
compteurs de continuity gap / overflow observés au moment de l'incident
motifs reconnect et/ou overflow
```
La borne de début respecte le plan `035` :
```text
start_slot = dernier slot réellement observé par la source avant l'incident
```
Aucun timestamp, frontier dérivé d'une autre source ou `last_slot + 1` n'est utilisé comme preuve de début.
La borne de fin est :
```text
end_slot = premier slot réellement reçu par la même source après l'incident
```
Le range reste inclusif. Les validations réutilisent les bornes run-local introduites en `pre.002` et rejettent notamment inversion, dépassement de plage et compteur régressif.
Si un reconnect/overflow est observé avant qu'un slot source n'ait été vu, le Worker ne fabrique pas d'historique : l'incident est `source.websocket_incident_unbounded`.
## Worker — observation des snapshots
`RawTransactionIngestProcessingFrontierReporter` observe maintenant les `WsSessionSnapshot` Transport et maintient :
```text
continuity gap total WebSocket
notification overflow total
ancre d'incident WebSocket éventuelle
projection de lifecycle source
```
Une source redevenue `Active` reste projetée `Reconnecting` tant qu'un incident ouvert n'a pas reçu sa borne post-incident. Cela évite de publier transitoirement une continuité saine alors que le gap n'est pas encore borné.
Aucune mutation de la politique de reconnect Transport n'est effectuée par le Worker.
## Standard Logs et Helius transaction
Les deux sources réutilisent maintenant `session.snapshot_source()` en parallèle de la réception métier et des tâches d'hydration existantes.
Lorsqu'un incident est détecté :
```text
le premier signal post-incident borne le range de manière inclusive
ce signal est quand même admis dans le coordinator d'hydration existant
aucune nouvelle notification n'est admise après cette borne dans pre.003
les signaux/tâches déjà admis sont drainés
la source termine ensuite par source.continuity_gap_proven
```
Ce séquencement évite de perdre artificiellement le premier événement post-incident tout en restant fail-closed tant que les tranches de repair ne sont pas implémentées.
## Standard Block
La source Standard Block observe le même snapshot latest-value Transport.
Le premier bloc post-incident :
```text
borne l'incident
projette et envoie toutes ses ingresses via l'admission centrale existante
marque ensuite le slot settled
termine enfin par source.continuity_gap_proven
```
Un bloc sans transaction qualifiée peut quand même fermer la borne de slot et est settled avant la terminalité conservative.
## Yellowstone
Le chemin Yellowstone existant reste inchangé fonctionnellement dans cette tranche :
```text
aucune mutation Worker de from_slot
aucun ownership Worker de SubscribeReplayInfo
aucune nouvelle tentative de replay
aucune modification du contrat Transport Yellowstone
```
La preuve de replay native et la distinction `replay_attempt` / couverture effective restent réservées à `pre.004`.
## Tests ajoutés/étendus
Transport couvre :
```text
source latest-value courante
publication d'un changement
fermeture de la source lorsque l'actor publisher disparaît
accessibilité crate-root de WsSessionSnapshotSource
présence des délégations Standard/Helius
réutilisation du watch actor existant sans second runtime
```
Worker couvre :
```text
ancre inclusive et bornée
extension monotone d'un incident reconnect/overflow
rejet d'un incident sans motif
rejet de range inversé ou surdimensionné
incident sans slot précédent -> erreur explicite
compteurs WebSocket régressifs -> erreur explicite
reconnect et overflow successifs -> même ancre la plus ancienne
absence de socket/retry/from_slot possédé par le Worker
```
## Fichiers ajoutés
```text
deltas/0.3.14/pre.003.md
```
## Fichiers modifiés
```text
Cargo.toml
crates/ksp-onchain-transport-lib/src/lib.rs
crates/ksp-onchain-transport-lib/src/ws_protocol_session.rs
crates/ksp-onchain-transport-lib/src/ws_session.rs
crates/ksp-onchain-transport-lib/tests/public_api.rs
crates/ksp-onchain-transport-lib/tests/release_completeness.rs
crates/ksp-onchain-transport-lib/unit_tests/ws_session.rs
crates/ksp-worker-raw-transaction-ingest-lib/src/continuity.rs
crates/ksp-worker-raw-transaction-ingest-lib/src/lib.rs
crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs
crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
crates/ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs
crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/continuity.rs
crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs
```
## Fichiers supprimés
```text
aucun
```
## Version Cargo
Conformément à `VER-ID-009`, cette nouvelle prerelease synchronise la version workspace :
```text
header Cargo.toml : 569 -> 570
workspace.package.version : 0.3.14-pre.2.fix.2 -> 0.3.14-pre.3
```
Versions des fichiers modifiés :
```text
ksp-onchain-transport-lib/src/lib.rs : 47 -> 48
ksp-onchain-transport-lib/src/ws_protocol_session.rs : 6 -> 7
ksp-onchain-transport-lib/src/ws_session.rs : 14 -> 15
ksp-onchain-transport-lib/tests/public_api.rs : 52 -> 53
ksp-onchain-transport-lib/tests/release_completeness.rs : 44 -> 45
ksp-onchain-transport-lib/unit_tests/ws_session.rs : 11 -> 12
ksp-worker-raw-transaction-ingest-lib/src/continuity.rs : 3 -> 4
ksp-worker-raw-transaction-ingest-lib/src/lib.rs : 28 -> 29
ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs : 29 -> 30
ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs : 26 -> 27
ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs : 21 -> 22
ksp-worker-raw-transaction-ingest-lib/unit_tests/continuity.rs : 2 -> 3
ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs : 23 -> 24
```
## Frontières préservées
```text
aucun repair HTTP
aucun nouveau socket WebSocket
aucun second actor WebSocket
aucun retry Worker
aucune nouvelle dépendance
aucune nouvelle feature
aucun changement Config
aucun changement Store
aucun changement Job Backfill
aucun backend Store physique depuis Worker
aucune mutation Worker de Yellowstone from_slot
aucun SubscribeReplayInfo possédé par Worker
aucun élargissement de la façade publique Worker
src/lib.rs Worker reste exempt de ReplayInfo/from_slot/repair/backfill
```
## Validations exécutées
Dans le sandbox de préparation :
```text
python3 scripts/audit_rust_workspace_rules.py
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas
scan exact ReplayInfo/from_slot/repair/backfill dans Worker src/lib.rs
scan de possession WebSocket directe dans Worker
scan set_from_slot dans les sources de production Worker
comparaison exacte 0.3.14-pre.002-fix.002 -> 0.3.14-pre.003
contrôle des versions de fichier modifiées
contrôle du contenu de l'archive delta
unzip -t de l'archive delta
réapplication de l'archive sur la base puis comparaison byte-exacte
```
## Validations non exécutées
Le sandbox de préparation ne fournit pas le toolchain Cargo/Rust. Les gates suivants restent donc explicitement à exécuter côté opérateur :
```text
cargo fmt --all
cargo fmt --all -- --check
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test -p ksp-onchain-transport-lib --all-targets --all-features
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features
```
## Décisions prises
```text
l'observabilité WS réutilise le watch latest-value déjà possédé par Transport
le Worker observe mais ne pilote pas la reconnexion WebSocket
un gap WS commence au dernier slot source réellement observé, inclusivement
le premier slot source post-incident est la borne de fin inclusive
aucune histoire antérieure n'est inventée sans ancre source
le premier événement post-incident est admis avant la terminalité conservative
pre.003 reste fail-closed et ne prétend pas encore réparer le gap
```
## Questions ouvertes
```text
aucune pour pre.003
```
## Tranche suivante
`pre.004` reste dédiée à la preuve de replay natif Yellowstone : qualification de `SubscribeReplayInfo`, preuve de couverture effective et conservation stricte de l'ownership `from_slot` dans Transport.
## Gate opérateur après application
```bash
cargo fmt --all
cargo fmt --all -- --check
python3 scripts/audit_rust_workspace_rules.py
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test -p ksp-onchain-transport-lib --all-targets --all-features
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features
```