# 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 ```