Files
2026-09-11 22:22:51 +02:00

368 lines
12 KiB
Markdown

<!-- file: deltas/0.3.14/pre.004.md -->
<!-- version: 1 -->
# Delta `0.3.14-pre.004` — preuve conservative de replay natif Yellowstone
## Base requise
```text
0.3.14-pre.003
workspace.package.version = 0.3.14-pre.3
deltas/0.3.14/pre.003.md présent
```
## Gate de la base
Le gate opérateur de `0.3.14-pre.003` 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-onchain-transport-lib --all-targets --all-features : PASS
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features : PASS
```
Le gate Transport comprend notamment :
```text
390 unit tests : PASS
public_api : 53 PASS
release_completeness : 45 PASS
smokes live : ignorés par défaut conformément au contrat existant
```
Le gate Worker comprend notamment :
```text
119 unit tests : PASS
cross_layer_completeness : 8 PASS
dependency_boundary : 19 PASS
hardening : 28 PASS
public_api : 20 PASS
release_completeness : 5 PASS
```
## Objectif
Implémenter strictement la tranche `pre.004` du plan `035` :
```text
conserver l'ownership Yellowstone from_slot / SubscribeReplayInfo dans Transport
distinguer replay attempt de replay delivery
distinguer toute delivery ponctuelle d'une preuve de coverage
conserver first_available comme preuve de limite de rétention uniquement
rendre observable une reprise acceptée dont la couverture reste non prouvée
rester fail-closed côté Worker tant que les tranches de réconciliation ne sont pas présentes
ne créer aucun replay Worker, aucun repair HTTP et aucune nouvelle source
```
## Transport — distinction attempt / delivery / coverage non prouvée
`YellowstoneGrpcSubscribeSnapshot` conserve `replay_attempt_count` et ajoute deux compteurs sûrs :
```text
replay_delivery_count
replay_coverage_unproven_count
```
La sémantique est volontairement conservative.
`replay_delivery_count` n'augmente que lorsqu'une reconnexion replay-bearing redélivre exactement le slot de reprise effectivement demandé par Transport. Cette observation prouve uniquement qu'un matériau slot-bearing a été livré au bord demandé. Elle ne prouve pas que tous les updates correspondant aux filtres ont été rejoués sur l'intervalle.
`replay_coverage_unproven_count` augmente lorsqu'une reconnexion replay-bearing a réussi et que :
```text
le premier update slot-bearing post-reconnect atteint ou dépasse la borne demandée
ou
un nouveau reconnect commence avant tout matériau slot-bearing replayé
```
Même une redélivrance exacte de la borne fait donc progresser `replay_delivery_count` **et** `replay_coverage_unproven_count` : la première prouve une delivery ponctuelle, la seconde conserve explicitement l'absence de preuve de couverture complète.
Cette valeur signifie explicitement **coverage non prouvée**. Elle ne prouve pas qu'un événement filtré existait, qu'il a été perdu, ni que le provider a nécessairement violé son contrat.
Aucun compteur générique `replay_covered` / `replay_coverage_proven` n'est ajouté. Le replay natif Transport ne possède pas aujourd'hui une preuve générique suffisante pour faire cette affirmation.
## Transport — tracker de replay
Le `ContinuityTracker` existant conserve maintenant une seule borne privée :
```text
pending_replay_from_slot
```
Lorsqu'un reconnect physique Yellowstone réussit avec un `effective_from_slot`, Transport ouvre cette preuve pending.
Sur le premier update slot-bearing :
```text
slot == requested -> delivery conservatrice prouvée + coverage globale toujours non prouvée
slot > requested -> aucune delivery de borne prouvée + coverage globale non prouvée
slot < requested -> aucune conclusion positive ; la preuve reste pending
```
Si le stream se coupe de nouveau avant résolution de la borne pending, la coverage de cette tentative est classée non prouvée avant d'ouvrir la tentative suivante.
Les `Ping`/`Pong` ne ferment jamais cette preuve parce qu'ils ne portent aucun slot.
## Transport — rétention `SubscribeReplayInfo`
Le contrat antérieur reste inchangé :
```text
first_available > requested
```
incrémente `continuity_gap_count`, clamp le `from_slot` effectif dans Transport et signifie uniquement que l'endpoint ne peut pas rejouer avant `first_available`.
Le clamp ne devient pas une preuve de perte d'un événement filtré et ne devient pas une preuve de coverage complète.
## Cas replay accepté mais couverture non prouvée
Une fixture dédiée couvre le cas adversarial prévu au plan :
```text
avant coupure : slot 800 observé
reconnect : from_slot = 800 accepté
premier update après reconnect : slot 805
```
Résultat attendu :
```text
reconnect_count = 1
replay_attempt_count = 1
replay_delivery_count = 0
replay_coverage_unproven_count = 1
continuity_gap_count = 0
```
Le résultat ne prétend ni qu'un update manquait réellement entre 800 et 805, ni que le replay est complet. Il démontre seulement que KSP ne possède pas la preuve conservative de delivery requise pour assimiler la reprise à une couverture saine.
La fixture de replay redélivrant `slot 500` conserve au contraire :
```text
replay_attempt_count = 1
replay_delivery_count = 1
replay_coverage_unproven_count = 1
```
Cette delivery ne devient toujours pas un `replay_covered`.
## Worker — consommation des preuves Transport
`RawTransactionIngestProcessingFrontierReporter` observe désormais de manière monotone :
```text
replay_attempt_total
replay_delivery_total
replay_coverage_unproven_total
continuity_gap_total
```
Le Worker ne calcule aucun `from_slot`, n'appelle jamais `SubscribeReplayInfo` et ne construit aucune requête replay.
La phase `replay_attempt` peut être observée avant toute delivery et ne ferme aucune obligation de coverage. Une delivery de borne fait ensuite progresser la preuve de delivery mais conserve simultanément `coverage_unproven`.
Une progression de `replay_coverage_unproven_total` sans gap de rétention produit actuellement :
```text
source.replay_coverage_unproven
```
et conserve la terminalité fail-closed de la source. Cette terminalité est volontairement temporaire jusqu'aux tranches de coverage redondante et de réconciliation du plan `035` ; elle évite qu'un replay accepté mais non prouvé soit assimilé silencieusement à une continuité saine.
Si `continuity_gap_total` augmente simultanément, la preuve de rétention plus forte conserve la priorité et produit le contrat existant :
```text
source.continuity_gap_proven
```
Les nouveaux compteurs privés sont soumis au même rejet de régression que les compteurs reconnect/replay existants.
## Surface publique
Transport étend uniquement le snapshot Yellowstone déjà public avec :
```text
YellowstoneGrpcSubscribeSnapshot::replay_delivery_count()
YellowstoneGrpcSubscribeSnapshot::replay_coverage_unproven_count()
```
Aucun type provider, payload, endpoint, credential ou proto upstream n'est exposé.
La façade publique Worker n'est pas étendue. Les preuves supplémentaires restent privées au runtime Worker dans cette tranche.
## Documentation d'utilisation
`ksp-onchain-transport-lib/USAGE.md` explicite désormais que :
```text
attempt != delivery != coverage
une delivery ponctuelle n'est pas une preuve de replay_covered
coverage_unproven est une absence explicite de preuve, pas une preuve de perte
```
Le document reste version-neutral conformément aux règles workspace.
## Tests ajoutés/étendus
Transport couvre :
```text
replay avec redélivrance exacte de la borne -> delivery = 1
rétention first_available -> gap = 1 tout en conservant delivery distincte
reconnects exhaustés -> attempts sans fausse delivery
replay accepté puis progression au-delà de la borne -> coverage_unproven = 1
absence de compteur générique replay_covered/replay_coverage_proven
accessibilité crate-root des deux getters snapshot
```
Worker couvre :
```text
attempt seul != delivery
delivery de borne != coverage
coverage_unproven devient fail-closed
régression delivery/coverage_unproven rejetée
absence persistante de set_from_slot / SubscribeReplayInfo / YellowstoneReplayInfo dans Worker
```
## Fichiers ajoutés
```text
deltas/0.3.14/pre.004.md
```
## Fichiers modifiés
```text
Cargo.toml
crates/ksp-onchain-transport-lib/USAGE.md
crates/ksp-onchain-transport-lib/src/grpc_stream.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/grpc_stream.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/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 : 570 -> 571
workspace.package.version : 0.3.14-pre.3 -> 0.3.14-pre.4
```
Versions des fichiers modifiés :
```text
ksp-onchain-transport-lib/USAGE.md : 25 -> 26
ksp-onchain-transport-lib/src/grpc_stream.rs : 4 -> 5
ksp-onchain-transport-lib/tests/public_api.rs : 53 -> 54
ksp-onchain-transport-lib/tests/release_completeness.rs : 45 -> 46
ksp-onchain-transport-lib/unit_tests/grpc_stream.rs : 5 -> 6
ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs : 30 -> 31
ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs : 27 -> 28
ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs : 22 -> 23
ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs : 24 -> 25
```
## Frontières préservées
```text
from_slot reste Transport-owned
SubscribeReplayInfo reste Transport-owned
aucun set_from_slot dans Worker
aucun replay loop Worker
aucun retry réseau Worker
aucun repair HTTP
aucune nouvelle source
aucun nouveau provider
aucune nouvelle dépendance
aucune nouvelle feature
aucun changement Config
aucun changement Store
aucun changement Job Backfill
aucun backend Store physique depuis Worker
aucun replay_covered générique inventé par Transport
aucun élargissement de la façade publique Worker
```
## 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 de possession replay dans Worker
scan des nouveaux compteurs attempt/delivery/coverage_unproven
comparaison exacte 0.3.14-pre.003 -> 0.3.14-pre.004
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
replay attempt ne prouve aucune delivery
delivery au slot demandé ne prouve aucune coverage complète
absence de delivery conservative avant progression/reconnect suivant devient coverage_unproven
first_available reste une preuve de rétention et non une preuve d'événement perdu
aucun replay_covered n'est revendiqué par Transport générique
le Worker reste fail-closed sur coverage_unproven jusqu'aux tranches de réconciliation
```
## Questions ouvertes
```text
aucune pour pre.004
```
## Tranche suivante
`pre.005` reste dédiée à la coverage redondante : relations exact/superset conservatrices, epochs/ranges de coverage et refus explicite des équivalences cross-family opportunistes.
## 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
```