v0.3.14-pre.001

This commit is contained in:
2026-09-11 19:37:36 +02:00
parent 9785cda39d
commit 2ca56dbaf4
4 changed files with 1874 additions and 2 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,594 @@
<!-- file: docs/validation/031-V0_3_14_MULTI_SOURCE_GAP_REPAIR_HARDENING.md -->
<!-- version: 4 -->
# Validation v0.3.14 — gap repair / hardening multi-source RawTransaction
## 1. Rôle
Ce document enregistre les preuves réellement exécutées, les non-claims et les décisions de validation de `0.3.14`.
`pre.001` est uniquement le gate d'audit/brainstorming/sizing/planification demandé par `prompts/033-V0_3_14_START_PROMPT.md`. Aucun moteur de repair, aucune policy failover/degraded, aucune modification Transport/Config et aucun adapter EARLY n'est implémenté dans cette tranche.
## 2. Archive stable contrôlée
```text
archive : khadhroony-solana-project-v0.3.13.zip
SHA-256 : 253fa7ef5e0a6b2721da66fc3ea8dc7695d991d3a00bcc7d34396d9a32b65245
bytes : 8431253
entries : 2012
files : 1818
absolute entries : 0
parent traversal entries : 0
duplicate entries : 0
symlink entries : 0
workspace members : 21
crate manifests : 21
workspace.package.version : 0.3.13
edition : 2024
stable delta : deltas/0.3.13/rel.001.md
```
Artefacts interdits recherchés :
```text
Cargo.lock : absent
package-lock.json : absent
pnpm-lock.yaml : absent
yarn.lock : absent
rust-toolchain.toml : absent
.env : absent
target/ : absent
node_modules/ : absent
dist/ : absent
.git/ : absent
```
Résultat archive : PASS.
L'absence de `.git` empêche de vérifier localement l'objet du tag `v0.3.13`. L'identité stable interne et le delta `rel.001` sont présents et cohérents ; aucune équivalence cryptographique au tag n'est revendiquée.
## 3. Preuve opérateur stable fournie
Le journal opérateur fourni avec la base exécute sur `0.3.13` :
```text
cargo clean
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 --workspace --all-targets --all-features
cargo tree -p ksp-worker-raw-transaction-ingest-lib --edges normal
cargo tree -p ksp-worker-raw-transaction-ingest-lib -e features
cargo tree --duplicates
```
Les sorties fournies contiennent :
```text
General Rust rule audit: clean
Rust export completeness audit: 0 candidate(s)
KSP workspace Rust rule audit: clean
Markdown table audit: clean (340 table(s), 855 file(s))
```
Agrégation des `130` lignes `test result` du journal :
```text
1 850 passed
0 failed
15 ignored
```
Ce gate qualifie la stable d'entrée. Les tests ignored restent ignored ; aucune preuve provider-gated n'est inventée.
## 4. Audits locaux de la base avant modification
Exécuté localement :
```bash
python3 scripts/audit_rust_workspace_rules.py
```
Résultat :
```text
General Rust rule audit: clean
Rust export completeness audit: 0 candidate(s)
KSP workspace Rust rule audit: clean
```
Exécuté localement :
```bash
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas
```
Résultat :
```text
Markdown table audit: clean (340 table(s), 855 file(s))
```
`cargo`/`rustfmt` ne sont pas disponibles dans l'environnement d'assemblage courant. Aucune commande Cargo locale n'est déclarée PASS.
## 5. Audit des règles
Documents normatifs relus :
```text
RULES.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
```
Scan supplémentaire des définitions normatives :
```text
489 définitions
489 identifiants uniques
0 doublon
```
Un scan générique de tous les textes trouve des headers absents dans quelques deltas historiques et un fichier de font/documentation, ainsi qu'une fin de ligne absente dans un JSON de capability. Ces constats ne sont pas assimilés à une violation nouvelle de la stable :
```text
les deltas historiques publiés sont immuables
JSON ne supporte pas les headers de commentaire
audit Rust officiel : clean
audit Markdown officiel : clean
```
Aucun ancien delta n'est réécrit par `pre.001`.
## 6. Frontières de dépendances contrôlées
Le manifest Worker stable contient exactement comme dépendances directes :
```text
ksp-core-lib
ksp-logging-lib
ksp-onchain-transport-lib
ksp-raw-transaction-lib
ksp-store-lib
ksp-worker-api
sha2
tokio
```
Absences confirmées :
```text
ksp-config-lib
ksp-job-backfill-lib
ksp-store-postgres-lib
reqwest
tokio-tungstenite
tonic
yellowstone-grpc-proto direct Worker
provider SDK
```
La séparation Worker/Job/Transport/Store est donc cohérente avec les règles à l'ouverture.
## 7. État de continuité interne audité
### 7.1 Yellowstone Transport
`YellowstoneGrpcSubscribeSnapshot` expose les compteurs de reconnect/replay et les slots sûrs. Sa documentation précise que `continuity_gap_count` est une preuve de rétention insuffisante lorsque `first_available` dépasse le replay demandé, pas une preuve qu'un événement filtré a réellement été perdu.
Résultat : conforme au besoin de distinction `replay_attempt != repair`.
### 7.2 Worker stable
`RawTransactionIngestProcessingFrontierReporter::observe_source_continuity` :
```text
rejette les régressions de compteurs
met à jour reconnect/replay/gap
rend source.continuity_gap_proven dès que continuity_gap_total augmente
```
Résultat : la terminalité conservative `0.3.13` est bien encore en place ; aucun repair non terminal caché n'existe.
### 7.3 WebSocket
L'acteur Transport incrémente le compteur de continuity gap lors d'une reconnexion physique. Il resubscribe les abonnements mais n'a pas de replay standard.
Les façades typées exposent `snapshot()` mais pas de `snapshot_source()` watch public, et les sources Worker Standard Logs/Standard Block/Helius ne consomment actuellement pas la snapshot WS. Une évolution Transport latest-value additive est donc planifiée avant le repair afin de ne pas dépendre d'une notification métier ultérieure pour voir le gap.
Résultat : reconnect WebSocket doit être traité comme détection de discontinuité potentielle, jamais comme preuve de couverture.
### 7.4 HTTP
Transport possède déjà :
```text
getSlot
getBlocks
getBlocksWithLimit
getBlock observed
getTransaction observed
```
Mais les ressources Worker ne garantissent pas toutes ces méthodes de la même manière :
```text
Yellowstone / Standard Logs / Helius Transaction : constructeur => getTransaction seulement
HTTP Block Polling : constructeur => getSlot + getBlocksWithLimit + getBlock
Standard Block : aucun pool HTTP attaché
fixtures hydration : rôles volontairement limités à get_transaction présents
```
Résultat : aucune nouvelle dépendance HTTP Worker n'est nécessaire pour le plan nominal, mais `pool HTTP présent` ne signifie jamais `repair HTTP disponible`. La capability de scan doit être détectée explicitement sur le rôle same-network réellement fourni.
## 8. Audit externe — Solana RPC/WebSocket
Références consultées le 11 septembre 2026 :
```text
https://solana.com/docs/rpc/http/getslot
https://solana.com/docs/rpc/http/getblocks
https://solana.com/docs/rpc/http/getblockswithlimit
https://solana.com/docs/rpc/http/getblock
https://solana.com/docs/rpc/http/gettransaction
https://solana.com/docs/rpc/websocket/logssubscribe
https://solana.com/docs/rpc/websocket/blocksubscribe
```
Constats :
```text
getBlocks/getBlocksWithLimit énumèrent des slots de blocs confirmés
plage maximale RPC documentée : 500 000 slots
getBlock peut retourner null
getTransaction peut retourner null
logsSubscribe transporte une référence/signature et non Common RAW
blockSubscribe reste instable et validator-gated
aucun replay historique WebSocket standard n'est documenté
```
Non-claim : les limites RPC ne sont pas reprises comme bornes Worker.
Point à requalifier en smoke : les pages localisées Solana affichent encore `maxSupportedTransactionVersion = 0` alors que la stable KSP porte Legacy/V0/V1. `pre.001` ne change pas le contrat stable sur cette divergence documentaire ; il conserve ce point comme gate provider/live distinct.
## 9. Audit externe — Yellowstone upstream
Références consultées :
```text
https://docs.rs/crate/yellowstone-grpc-proto/12.7.0
https://github.com/rpcpool/yellowstone-grpc/blob/master/yellowstone-grpc-proto/proto/geyser.proto
https://github.com/rpcpool/yellowstone-grpc/blob/master/CHANGELOG.md
```
Constats :
```text
KSP ^12.7 résout la version courante 12.7.0 publiée le 29 août 2026
SubscribeRequest possède from_slot
Geyser possède SubscribeReplayInfo
SubscribeReplayInfoResponse possède first_available
```
Risque upstream prouvé : le changelog du 22 juillet 2026 décrit un bug corrigé où un replay de filtre `blocks` acceptait `from_slot` mais ne livrait aucun `Message::Block` replayé, puis reprenait au live head avec un state gap.
Décision : une acceptation protocolaire de replay ne sera jamais suffisante comme critère `repaired`.
## 10. Audit providers courants
### 10.1 PublicNode
Référence :
```text
https://solana.publicnode.com/
```
Prouvé publiquement :
```text
Solana Mainnet RPC/WS/Yellowstone gRPC
Solana Testnet RPC/WS/Yellowstone gRPC
archive data available
```
Non prouvé dans une source primaire suffisamment précise :
```text
profondeur Yellowstone replay
first_available effectif
rétention du stream
auth exacte du profil KSP actuel
```
Statut replay `pre.001` : NON PROUVÉ / smoke requis.
### 10.2 OrbitFlare
Références :
```text
https://docs.orbitflare.com/data-streaming/yellowstone
https://orbitflare.com/products/solana-grpc
https://orbitflare.com/pricing
https://orbitflare.com/blog/developers/build-grpc-indexer
```
Prouvé publiquement :
```text
Yellowstone full-data streaming
Devnet gRPC sur les tiers Free/Developer courants
gRPC complet/shared payant pour les usages plus larges
exemple récent d'utilisation de from_slot pour reprendre depuis MAX(slot)
```
Non prouvé :
```text
profondeur exacte de replay du serveur KSP
SubscribeReplayInfo/first_available réellement activé sur le tier utilisé
équivalence du credential opérateur stable avec la documentation actuelle
```
Statut : candidat smoke Devnet, NON EXÉCUTÉ en `pre.001`.
### 10.3 Helius
Références :
```text
https://www.helius.dev/pricing
https://www.helius.dev/blog/laserstream-websockets
https://www.helius.dev/laserstream
```
Prouvé publiquement :
```text
transactionSubscribe WSS : Developer+
LaserStream gRPC Devnet : Developer+
LaserStream gRPC Mainnet : Business+
replay LaserStream annoncé jusqu'à 24 h
```
Décision : ne pas attribuer ce replay gRPC à `transactionSubscribe` WSS et ne pas ajouter LaserStream gRPC comme nouvelle source `0.3.14`.
### 10.4 QuickNode
Référence comparative :
```text
https://www.quicknode.com/guides/solana-development/tooling/solana-grpc/solana-grpc
```
La documentation du 3 septembre 2026 annonce `fromSlot` jusqu'à `3000` slots récents. QuickNode n'est pas configuré dans KSP ; aucune modification Config n'en découle.
## 11. Matrice de capabilities validée pour le plan
### Yellowstone
```text
gap detect : oui
native replay : oui si provider l'adresse
replay coverage proof : non par attempt seul
reference hydration : oui
block material : oui selon filtre
HTTP repair : conditionnel ; pool présent mais constructeur garantit seulement getTransaction
```
### Standard Logs
```text
gap detect : oui
native replay : non
coverage proof seule : non
reference hydration : oui
HTTP repair : conditionnel ; getTransaction seul est garanti par construction
```
### Standard Block
```text
gap detect : oui
native replay : non
block material : oui
coverage proof intervalle : pas sans preuve complémentaire
HTTP repair attaché : non ; capability run-wide possible via une autre ressource compatible
```
### Helius Transaction WSS
```text
gap detect : oui
native replay WSS : non prouvé
coverage proof seule : non
reference hydration : oui
HTTP repair : conditionnel ; getTransaction seul est garanti par construction
```
### HTTP Block Polling
```text
gap detect : oui
slot enumeration : oui
skipped proof : oui uniquement dans une fenêtre de discovery prouvée complète
block material : oui
HTTP repair : oui
```
Interprétation de coverage retenue : `HTTP Block Polling` et `Standard Block(All)` sont les deux scopes `FullLedgerTransactions` immédiatement prouvables par l'état stable. Les autres filtres restent des `ExactSourceScope` privés. Une source full-ledger continue peut couvrir canoniquement un scope plus étroit sans fabriquer l'observation manquante de la source perdue. À l'inverse, un scan full-block n'est pas autorisé à élargir un run composé uniquement de scopes filtrés.
## 12. Décisions pre.001
Décisions fermées :
```text
1. gap = intervalle de continuité run-local, pas liste présumée de transactions manquantes ;
2. gap privé lié à source/network/commitment/range/coverage requirement ;
3. reconnect, replay_attempt, replay_covered, repaired et unresolved sont distincts ;
4. replay accepté n'est jamais une preuve de repair ;
5. transaction-only source peut fournir du matériau mais pas prouver l'absence d'autres transactions ;
6. le repair vise la coverage des entités RawTransaction autorisées, pas la fabrication des observations provider manquantes ;
7. FullLedgerTransactions est un superset explicite ; un scope filtré reste exact/opaque tant qu'une relation plus forte n'est pas prouvée ;
8. aucune équivalence cross-family n'est déduite d'un provider, d'un hash ou de deux sockets Active ;
9. KnownReferences/getTransaction peut compléter du matériau connu mais ne ferme pas les références inconnues ;
10. un pool/role d'hydration garantit getTransaction seulement ; les méthodes de scan doivent être détectées séparément ;
11. preuve finale de range = fenêtre slot/block explicitement complète ou capability équivalente qualifiée ;
12. getBlocksWithLimit réussi ne ferme pas à lui seul une queue arbitraire car sa limite compte des blocs ;
13. skipped slot seulement dans une fenêtre discovery prouvée complète, jamais depuis silence de stream ;
14. getBlock null sur slot produit = unresolved tant qu'aucune autre preuve ne le ferme ;
15. getTransaction null = missing/unresolved pour la référence connue, avec fallback possible vers le bloc du slot ;
16. un scan full-block ne broadit pas silencieusement un scope filtré ;
17. tout matériau admis repasse par Common RAW, admission centrale et ksp-store-lib ;
18. aucun retry réseau parallèle dans Worker ;
19. toutes les sources restent attendues ; redundant est une relation de coverage dynamique, pas un flag provider statique ;
20. Healthy exige aucune lacune et toutes les sources attendues actives ;
21. Degraded est permis uniquement si coverage canonique reste prouvée malgré reconnect/perte ;
22. Unhealthy signifie coverage temporairement non prouvée pendant repair borné ; unresolved non récupérable fait Faulted ;
23. processing frontier et continuity frontier restent distincts ; les ranges sont inclusifs pour couvrir les pertes intra-slot ;
24. un gap WS sans borne slot sûre n'est pas inventé depuis un timestamp ; il reste unresolved/terminal si aucune autre capability ne le borne ;
25. la snapshot WS doit devenir observable latest-value sans attendre une notification métier, via une petite surface Transport additive ;
26. TargetCoverage est la réunion conservative des scopes configurés au même network/commitment ; aucune relation Confirmed/Finalized implicite ;
27. une source Transport terminale n'est jamais respawnée par le Worker ; Degraded durable exige que les sources restantes couvrent TargetCoverage pour la suite du run ;
28. EARLY est hors scope 0.3.14 ; aucune nouvelle dépendance n'est nécessaire ; Config reste inchangé en pre.001 et ne sera ouvert qu'en cas de besoin prouvé ;
29. 0.3.14 est maintenue sans rescission, mais le forecast est allongé jusqu'à pre.016 pour respecter le budget par tranche.
```
## 13. Bornes cibles à tester
```text
MAX_OPEN_REPAIR_GAPS = 64
MAX_REPAIR_RANGE_SLOTS = 4096
MAX_REPAIR_DISCOVERY_WINDOW_SLOTS = 512
MAX_REPAIR_BLOCK_FETCH_IN_FLIGHT = 4
MAX_REPAIR_ACTIVE_GAPS = 1
```
Ces valeurs doivent être matérialisées par `pre.002+` avec tests exacts aux limites. Elles ne sont pas encore du runtime en `pre.001`.
## 14. Threat model enregistré
À couvrir :
```text
reconnect storms
overlapping/adjacent gaps
stale redundant source
filter non-equivalence
replay truncation
replay accepted but empty
HTTP holes
skipped slots
getBlock null after produced-slot discovery
getTransaction null
duplicate repair/live
content disagreement
slow Store
admission backpressure
hydration fanout/coalescence
stop/fault pendant replay/scan/hydration/persistence
counter exhaustion
late snapshot publication
secret/provider/filter/signature leakage
```
## 15. Smokes accessibles / non accessibles en pre.001
```text
Solana HTTP Devnet : accessible en principe, non exécuté dans cette tranche de planification
Solana WebSocket Devnet : déjà qualifié sur stable ; non rejoué en pre.001
OrbitFlare Yellowstone Devnet replay : credential requis, NON EXÉCUTÉ
PublicNode Yellowstone Mainnet/Testnet replay : auth/replay à qualifier, NON EXÉCUTÉ
Helius transactionSubscribe : tier/API key requis, NON EXÉCUTÉ
Worker repair -> Store end-to-end : moteur non implémenté, NON EXÉCUTÉ
```
Aucun smoke n'est présenté comme PASS sans exécution réelle.
## 16. Sizing
Mesuré sur la stable :
```text
Worker src : 9 fichiers / 6 317 lignes
Worker tests : 5 fichiers / 2 725 lignes
Worker unit_tests : 6 fichiers / 5 523 lignes
Transport src : 33 fichiers / 22 764 lignes
```
Décision : scope maintenu dans `0.3.14`, mais le forecast initial est allongé de `pre.014` à `pre.016`. L'audit a isolé deux responsabilités qui ne doivent pas être mélangées : observabilité WS latest-value avant repair, puis replay natif et coverage redondante en tranches séparées. Les cinq familles et les primitives Transport restent la base ; les extensions suivantes rendraient le scope trop large et sont interdites dans cette release :
```text
EARLY/Jetstream/shreds
nouveau provider Config
provider SDK
nouveau client Transport parallèle
campagne historique caller-driven
checkpoint durable Worker/Job
```
## 17. Modifications de pre.001
```text
Cargo.toml
header 565 -> 566
workspace.package.version 0.3.13 -> 0.3.14-pre.1
docs/plans/035-V0_3_14_MULTI_SOURCE_GAP_REPAIR_HARDENING_PLAN.md
ajouté
docs/validation/031-V0_3_14_MULTI_SOURCE_GAP_REPAIR_HARDENING.md
ajouté
deltas/0.3.14/pre.001.md
ajouté
```
Aucun code Rust, Config, test, dépendance, feature, README/USAGE, architecture, CHANGELOG, ROADMAP ou prompt n'est modifié.
## 18. Gate local post-modification
Exécuté après application effective de `pre.001` :
```text
General Rust rule audit : clean
Rust export completeness audit : 0 candidate(s)
KSP workspace Rust rule audit : clean
Markdown table audit : clean (340 tables / 858 files)
rule definitions : 489 définitions / 489 IDs uniques / 0 doublon
comparaison archive stable -> worktree : 3 ajouts / 1 modification / 0 suppression
artefacts générés après audit : scripts/__pycache__ supprimé avant packaging
Cargo fmt/check : NON EXÉCUTÉ LOCAL — cargo absent du sandbox
```
La comparaison avec le ZIP stable confirme que les seuls fichiers de livraison sont :
```text
Cargo.toml
docs/plans/035-V0_3_14_MULTI_SOURCE_GAP_REPAIR_HARDENING_PLAN.md
docs/validation/031-V0_3_14_MULTI_SOURCE_GAP_REPAIR_HARDENING.md
deltas/0.3.14/pre.001.md
```
Le statut Cargo post-bump reste volontairement non revendiqué. Le journal opérateur fourni qualifie la stable `0.3.13`, pas `0.3.14-pre.1`.
## 19. Gate opérateur requis avant pre.002
```bash
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/0.3.14
cargo check --workspace
```
`pre.001` ne modifie pas de Rust ; un Clippy/test workspace exhaustif n'est pas nécessaire pour prouver le contenu de cette tranche de planification, mais le gate stable complet fourni reste la baseline. Si le gate post-bump révèle un défaut, ouvrir un fix rattaché à `pre.001` avant `pre.002`.