# Validation v0.3.13 — WS standard / Helius / HTTP live + convergence multi-source ## 1. Rôle Ce document enregistre les preuves réellement exécutées et les non-claims de `0.3.13`. `pre.001` ferme l'audit/planification, `pre.002` matérialise la composition runtime multi-source, `pre.003` ajoute Standard Solana `logsSubscribe` + hydration HTTP observée, `pre.004` ajoute Standard Solana `blockSubscribe` RAW-direct qualifié Legacy/V0/V1, `pre.005` ajoute Helius `transactionSubscribe` + hydration commune et `pre.006` ajoute le live HTTP block polling run-local, sans activer encore la supervision simultanée. ## 2. Archive stable contrôlée ```text archive : khadhroony-solana-project-v0.3.12.zip SHA-256 : 85c41eb9f8575ee58edd9863445cbc37b79ef59c4a7cf882679ff24dc8991bf5 bytes : 8260528 entries : 1981 files : 1788 directories : 193 absolute entries : 0 parent traversal entries : 0 duplicate entries : 0 symlink entries : 0 workspace members : 21 crate manifests : 21 workspace.package.version : 0.3.12 edition : 2024 stable delta : deltas/0.3.12/rel.001.md ``` Résultat structurel : PASS. Artefacts interdits recherchés : ```text Cargo.lock : absent rust-toolchain.toml : absent rust-toolchain : absent package-lock.json : absent pnpm-lock.yaml : absent yarn.lock : absent .env : absent ``` Résultat : PASS. ## 3. Baseline statique locale avant modification Exécuté dans l'archive extraite : ```text python3 scripts/audit_rust_workspace_rules.py General Rust rule audit: clean Rust export completeness audit: 0 candidate(s) KSP workspace Rust rule audit: clean ``` Résultat : PASS. Exécuté : ```text python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.12 Markdown table audit: clean (306 table(s), 199 file(s)) ``` Résultat : PASS. ## 4. Preuve opérateur stable fournie Le journal opérateur fourni avec l'ouverture `0.3.13` montre sur `0.3.12` : ```text cargo fmt --all -- --check : terminé sans erreur visible audit Rust : clean, export completeness 0 audit Markdown ciblé stable : clean (306 tables, 199 fichiers) cargo check --workspace : terminé avec succès cargo clippy --workspace --all-targets --all-features -- -D warnings : terminé avec succès cargo test -p ksp-worker-raw-transaction-ingest-lib : vert cargo tree Worker --edges normal : produit cargo tree Worker -e features : produit ``` Suites Worker affichées : ```text unit : 66 pass cross_layer_completeness : 4 pass dependency_boundary : 9 pass hardening : 16 pass public_api : 9 pass release_completeness : 4 pass doc-tests : 0 ``` Cette preuve concerne la stable d'entrée. Elle n'est pas présentée comme une exécution locale post-modification de `pre.001`. ## 5. Cargo local dans l'environnement d'assemblage `cargo` et `rustfmt` ne sont pas installés dans l'environnement d'assemblage courant. Non exécuté localement avant ou après modification : ```text cargo fmt --all -- --check cargo check --workspace cargo clippy --workspace --all-targets --all-features -- -D warnings cargo test -p ksp-worker-raw-transaction-ingest-lib 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 ``` Aucune de ces commandes n'est déclarée PASS localement. ## 6. Audit des règles Documents normatifs audités : ```text RULES.md docs/rules/RULES_GENERAL.md docs/rules/RULES_RUST.md docs/rules/RULES_KSP.md docs/rules/RULES_DEPENDENCIES.md docs/rules/RULES_DOCUMENTATION.md docs/rules/PROMPT_STRUCTURE.md docs/rules/FILE_CONTRACTS.md docs/rules/VERSION_WORKFLOW.md docs/rules/SCENARIO_CONVENTION.md ``` Scan supplémentaire des identifiants normatifs : ```text fichiers de règles : 10 rule ids détectés : 489 rule ids uniques : 488 collision : KSP-CONFIG-018 x2 ``` Le dépôt stable ne contenait pas de contradiction de contenu entre ces deux règles, mais l'identifiant normatif n'était pas unique. Preuve historique : `deltas/0.1.3/pre.014.md` définit explicitement l'inventaire `.env.example` comme `KSP-CONFIG-018`. La règle desktop est donc renumérotée `KSP-CONFIG-019` dans `pre.001` ; aucun texte de règle n'est affaibli ni supprimé. ## 7. Audit dépendances et frontières Contrôlé statiquement : ```text 21 crates = 21 workspace members aucune version package explicite hors workspace inheritance aucune edition crate divergente ksp-worker-raw-transaction-ingest-lib dépend de ksp-onchain-transport-lib Worker ne dépend pas de ksp-config-lib Worker ne dépend pas de ksp-job-backfill-lib Worker ne dépend pas de ksp-store-postgres-lib Worker ne dépend pas directement de reqwest/tonic/yellowstone-grpc-proto Store physique absent du Worker ``` La primitive `solana-keypair` présente dans `ksp-wallet-lib` est autorisée explicitement par `DEP-SOL-004` et n'est pas une violation. Résultat : aucune violation de dépendance stable identifiée par cet audit. ## 8. Handoff 0.3.12 vérifié Sources lues : ```text docs/plans/033-V0_3_12_YELLOWSTONE_HYDRATION_CONTINUITY_PLAN.md docs/validation/029-V0_3_12_YELLOWSTONE_HYDRATION_CONTINUITY.md crates/ksp-worker-raw-transaction-ingest-lib/Cargo.toml crates/ksp-worker-raw-transaction-ingest-lib/README.md crates/ksp-worker-raw-transaction-ingest-lib/USAGE.md crates/ksp-worker-raw-transaction-ingest-lib/src/ crates/ksp-worker-raw-transaction-ingest-lib/tests/ crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/ ``` Contrats stables confirmés : ```text une source Yellowstone caller-composed hydratation getTransaction observed coalescence network/signature/commitment source_key opaque 32 bytes observation key = domain + network + signature + source_key admission centrale bounded mpsc canonicalisation Common RAW avant Store persistence atomique transaction + observation processing frontier run-local reconnect/replay/gap sans repair ``` ## 9. Common RAW et Store vérifiés `ksp-raw-transaction-lib` expose : ```text RawTransactionMaterial canonicalize_raw_transaction assemble_raw_transaction_acquisition wire Legacy/V0/V1 ``` `ksp-store-api` / `ksp-store-lib` exposent déjà deux capabilities distinctes utiles à la convergence : ```text persist_raw_transaction_acquisition(transaction, observation, Normal) record_raw_transaction_observation(observation) ``` La seconde est explicitement conçue pour une observation supplémentaire d'une transaction déjà persistée sans resoumettre le payload canonique. Conclusion : aucun changement Store API n'est requis par le design `pre.001`. ## 10. Transport WS/HTTP vérifié Surface standard : ```text SolanaStandardWsSession::connect logs_subscribe block_subscribe shared WsSession actor reconnect/resubscribe Transport-owned ``` Surface Helius : ```text HeliusLaserStreamWsSession::connect transaction_subscribe shared WsSession actor pas d'escape hatch générique blockSubscribe volontairement non exposé sur Helius facade ``` Surface HTTP : ```text get_transaction_observed get_block_observed get_slot get_blocks get_blocks_with_limit ``` Conclusion : aucun nouveau client HTTP/WS ni nouvelle dépendance réseau n'est requis dans Worker. ## 11. Config/secrets vérifiés `config/std.transport.json` contient les profils committed standard/public actuels. `config/examples/std.transport.example.json` démontre déjà les formes Helius LaserStream Mainnet/Devnet. `KSP_SECRET_HELIUS_API_KEY` existe déjà dans l'inventaire `.env.example` et dans les contrats Config/tests concernés. Conclusion pre.001 : ```text aucune nouvelle variable secret aucun profil Config ajouté dans cette tranche Config reste hors Worker pre.005 décidera un profil committed seulement si un consumer/smoke concret le justifie ``` ## 12. Audit externe courant Consulté le 10 septembre 2026. ### 12.1 logsSubscribe Solana confirme `all`, `allWithVotes` et `mentions` avec un seul pubkey par appel. La notification contient contexte/slot, signature, erreur et logs mais pas le RAW complet. Décision : hydration obligatoire. ### 12.2 blockSubscribe Solana maintient la méthode comme instable et conditionnée à l'activation validator. Commitment `confirmed`/`finalized` seulement. Le guide Transaction V1 courant impose la préparation `maxSupportedTransactionVersion = 1`; sinon V1 peut provoquer `-32015` en HTTP et `block:null`/stagnation côté blockSubscribe. Décision : toutes les nouvelles requêtes transaction/block de `0.3.13` utilisent `1` lorsque la surface le permet. La qualification RAW-direct V1 reste test-gated en `pre.004`. ### 12.3 Helius La référence Helius courante liste `transactionSubscribe` comme extension supportée et `blockSubscribe` parmi les méthodes instables non supportées sur LaserStream WSS. Le pricing courant place `transactionSubscribe` à partir de Developer, pas sur Free. Décision : aucun tier n'est codé ; smoke live conditionnel. Sources : ```text https://solana.com/docs/rpc/websocket/logssubscribe https://solana.com/docs/rpc/websocket/blocksubscribe https://solana.com/docs/core/transactions/versioned-transactions https://www.helius.dev/docs/api-reference/rpc/websocket-methods https://www.helius.dev/pricing ``` ## 13. Contrats de source fermés par pre.001 ### 13.1 Yellowstone ```text input : channel/request + HTTP pool/role output : reference signal + continuity bound : Transport + global Worker queue retry/reconnect : Transport proof : non-regression 0.3.12 ``` ### 13.2 Standard logs ```text input : standard WS endpoint/filter/confirmed-or-finalized + HTTP pool/role output : signature/slot reference signal bound : WS notification queue + global Worker queue retry/reconnect : Transport WS hydration retry : Transport HTTP proof : deterministic notification -> one observed getTransaction -> RAW golden ``` ### 13.3 Standard block ```text input : standard WS + full/base64 + confirmed/finalized + maxVersion=1 output : complete material for qualified versions bound : WS queue + global Worker queue retry/reconnect : Transport WS proof : RAW parity Legacy/V0, V1 dedicated fixture, block:null canary ``` ### 13.4 Helius transaction ```text input : Helius WS + full/base64 + maxVersion=1 + HTTP pool/role output : reference signal then hydration bound : Transport Helius filters/queue + global Worker queue retry/reconnect : Transport WS hydration retry : Transport HTTP proof : deterministic Helius notification -> RAW golden; live conditional ``` ### 13.5 HTTP live polling ```text input : HTTP pool/roles + confirmed/finalized + polling settings run bound : getSlot at source start; never scan lower slot output : getBlock observed transactions source timer owner : Worker HTTP retry/rate-limit : Transport proof : deterministic tip/skipped/null/stop tests ``` ## 14. Bornes fermées ```text live sources : 1..32 source signal queue : settings.admission_queue_capacity() pending signals global : <= settings.admission_queue_capacity() hydration in-flight : <= settings.persistence_concurrency() no provider-private unbounded Worker queue HTTP poll interval : 100 ms .. 30 s, default 1 s HTTP poll max blocks/cycle : 1 .. 1024, default 128 ``` Ces bornes sont des décisions de plan à matérialiser/tester dans les prereleases techniques correspondantes ; elles ne sont pas encore une API de `pre.001`. ## 15. Convergence et observations Décision : coalescence avant hydration par `(network, signature, commitment)` pour toutes les sources reference-only. Une hydration peut servir plusieurs observation seeds. Après canonicalisation : ```text première observation : persistence atomique entity + observation suivantes : record_raw_transaction_observation ``` Même identité/content identique : idempotent. Même identité/content divergent : content conflict explicite et terminal. ## 16. Health/terminalité L'inventaire de sources reste interne et borné. La projection publique future est source-neutral et agrège des counts d'états sans provider material. Décision conservative : un `Failed` terminal d'une source configurée reste terminal pour le Worker en `0.3.13`, car aucune preuve de coverage équivalent n'existe encore. Failover/degraded non-terminal appartient au gap-repair/coverage `0.3.14`. ## 17. Sizing Release maintenue avec : ```text pre.002 resources multi-source pre.003 logs + hydration pre.004 blockSubscribe pre.005 Helius pre.006 HTTP polling pre.007 supervisor/inventory pre.008 convergence/observations pre.009 conflict/backpressure/fairness pre.010 snapshot/health pre.011 races/shutdown pre.012 completeness/security pre.013 gate technique/live pre.014 documentation pre.015 publication prep rel.001 stable ``` Aucune responsabilité de fermeture n'est fusionnée. ## 18. Non-claims pre.001 `pre.001` ne prétend pas : ```text avoir ajouté une source productive avoir modifié le runtime Worker multi-source avoir exécuté un smoke Helius avoir prouvé blockSubscribe V1 en live avoir exécuté cargo dans l'environnement d'assemblage avoir implémenté gap repair/failover avoir ajouté un profil Config Helius committed ``` ## 19. Validation post-modification pre.001 Exécuté : ```text python3 scripts/audit_rust_workspace_rules.py General Rust rule audit: clean Rust export completeness audit: 0 candidate(s) KSP workspace Rust rule audit: clean ``` Résultat : PASS. Exécuté : ```text python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas Markdown table audit: clean (340 table(s), 828 file(s)) ``` Résultat : PASS. Exécuté : ```text supplemental normative rule-id scan 489 ids, 489 uniques, 0 duplicate ``` Résultat : PASS. Comparaison exhaustive du working tree avec l'archive stable après suppression du cache Python généré par l'audit : ```text added : 3 deltas/0.3.13/pre.001.md docs/plans/034-V0_3_13_MULTI_SOURCE_LIVE_CONVERGENCE_PLAN.md docs/validation/030-V0_3_13_MULTI_SOURCE_LIVE_CONVERGENCE.md modified : 2 Cargo.toml docs/rules/RULES_KSP.md deleted : 0 extra/unexpected : 0 ``` Résultat : PASS. Cargo post-modification reste `NON EXÉCUTÉ LOCAL` parce que le toolchain n'est pas disponible. ## 20. Gate opérateur requis avant pre.002 Après application du delta : ```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 cargo check --workspace cargo clippy --workspace --all-targets --all-features -- -D warnings cargo test -p ksp-worker-raw-transaction-ingest-lib cargo tree -p ksp-worker-raw-transaction-ingest-lib --edges normal cargo tree -p ksp-worker-raw-transaction-ingest-lib -e features ``` `pre.002` ne doit pas commencer si cette livraison révèle une anomalie de règles/version/archive non corrigée. ## 21. Gate opérateur pre.001 reçu avant pre.002 Le journal opérateur du 10 septembre 2026 sur `0.3.13-pre.1` montre : ```text cargo fmt --all -- --check : PASS General Rust rule audit : clean Rust export completeness audit : 0 candidate KSP workspace Rust rule audit : clean Markdown table audit : clean (340 tables, 828 files) cargo check --workspace : PASS cargo clippy --workspace --all-targets --all-features -- -D warnings : PASS cargo test -p ksp-worker-raw-transaction-ingest-lib : PASS cargo tree Worker --edges normal : produit cargo tree Worker -e features : produit cargo tree --duplicates : produit ``` Suites Worker affichées : ```text unit : 66 pass cross_layer_completeness : 4 pass dependency_boundary : 9 pass hardening : 16 pass public_api : 9 pass release_completeness : 4 pass doc-tests : 0 ``` Le gate `pre.001 -> pre.002` est donc satisfait. ## 22. Implémentation pre.002 `pre.002` ajoute dans le Worker : ```text MAX_RAW_TRANSACTION_INGEST_LIVE_SOURCES = 32 collection privée Vec discriminant privé capability-owned : Yellowstone source_count public source-neutral try_push_yellowstone_source transactionnel validation réseau globale rejet duplicate logical source identity rejet > 32 rejet cross-network ``` L'identité Yellowstone est calculée sans URL/credential/payload distant : ```text KSP source-key domain source family = yellowstone network safe provider identity safe endpoint identity commitment opaque deterministic Yellowstone Subscribe request identity SHA-256 -> [u8; 32] ``` Le rôle/pool HTTP d'hydration n'entre volontairement pas dans cette identité : il qualifie la stratégie d'enrichissement d'un signal, pas l'identité de la source live Yellowstone. Deux subscriptions Yellowstone identiques ne peuvent donc pas contourner le rejet de doublon en changeant uniquement de rôle HTTP. Transport fournit l'identité de requête sous `YellowstoneSubscribeRequestIdentity` : les sept familles de filtres sont encodées séparément dans l'ordre canonique des noms de `BTreeMap`, avec leur protobuf exact, puis les options communes sont encodées avec les maps vidées. Les bytes restent privés ; `Debug` n'expose que leur longueur et l'API ne fournit aucun getter des bytes. Aucune nouvelle dépendance n'est ajoutée : Transport réutilise le `prost` réexporté par `yellowstone-grpc-proto` déjà présent. ## 23. Gate d'activation multi-source pre.002 Le modèle final `0.3.13` exige le démarrage simultané de toutes les sources configurées, mais le supervisor/source inventory appartient explicitement à `pre.007`. Décision de sûreté pour `pre.002` : ```text 1 source Yellowstone : voie productive 0.3.12 conservée 2..32 sources validées : composition acceptée start avec 2..32 sources : erreur stable avant spawn aucun démarrage silencieux d'un sous-ensemble aucune nouvelle famille de source productive ``` Condition d'erreur interne : ```text runtime_resources.multi_source_activation_pending ``` Cette barrière sera retirée uniquement lorsque `pre.007` possédera le supervisor simultané et ses preuves de stop/fault/join. ## 24. Preuves déterministes ajoutées pre.002 Transport : ```text request identity stable malgré ordre d'insertion des filtres request identity change si le contenu logique du filtre change Debug de l'identité ne révèle pas les noms de filtres surface publique identité disponible via crate root absence de bytes/as_bytes escape hatch ``` Worker : ```text source_key stable pour même source logique source_key change si request fingerprint ou endpoint-safe identity change exactement 32 sources acceptées 33e source rejetée transactionnellement duplicate logical identity rejeté cross-network source rejetée Debug runtime resources = source_count seulement multi-source start fail-closed avant supervisor tranche surface publique = bound + count + push capability-specific, sans source_key public ``` ## 25. Validations locales post-modification pre.002 Le toolchain Cargo/Rustfmt reste indisponible dans l'environnement d'assemblage. Les validations Cargo ci-dessous devront donc être exécutées par l'opérateur avant `pre.003` et ne sont pas déclarées PASS localement. Résultat après toutes les modifications de la tranche : ```text General Rust rule audit : clean Rust export completeness audit : 0 candidate KSP workspace Rust rule audit : clean Markdown table audit : clean (340 tables, 829 files) normative rule definitions : 489 / 489 uniques / 0 duplicate definition id ``` ## 26. Non-claims pre.002 `pre.002` ne prétend pas : ```text avoir ajouté logsSubscribe productif avoir ajouté blockSubscribe productif avoir ajouté Helius transactionSubscribe productif avoir ajouté HTTP block polling productif avoir démarré plusieurs sources simultanément avoir déplacé le coordinator Yellowstone vers le niveau Worker global avoir implémenté observation fanout multi-source avoir modifié Common RAW ou Store API avoir ajouté une dépendance externe avoir exécuté Cargo localement ``` ## 27. Gate opérateur requis avant pre.003 Après application du delta : ```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 cargo check --workspace cargo clippy --workspace --all-targets --all-features -- -D warnings cargo test -p ksp-onchain-transport-lib cargo test -p ksp-worker-raw-transaction-ingest-lib 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 ``` `pre.003` ne doit pas commencer si cette livraison révèle une anomalie de règles, API, version, archive ou dépendance non corrigée. ## 28. Gate opérateur pre.002-fix.001 reçu avant pre.003 Le correctif de format `0.3.13-pre.002-fix.001` a été validé par l’opérateur après `cargo clean` : ```text cargo fmt --all : PASS cargo fmt --all -- --check : PASS, silencieux General Rust rule audit : clean Rust export completeness audit : 0 candidate KSP workspace Rust rule audit : clean Markdown table audit : clean (340 tables, 830 files) cargo check --workspace : PASS clippy workspace/all-targets/all-features -D warnings : PASS ksp-onchain-transport-lib unit tests : 389 pass transport public_api : 52 pass transport release_completeness : 44 pass transport doc-tests : 4 pass live transport smokes : ignored opt-in, comme prévu ksp-worker-raw-transaction-ingest-lib unit tests : 70 pass cross_layer_completeness : 4 pass dependency_boundary : 9 pass hardening : 16 pass public_api : 10 pass release_completeness : 4 pass worker doc-tests : 0 ``` Le gate `pre.002-fix.001 -> pre.003` est satisfait. ## 29. Implémentation pre.003 — Standard Logs + hydration `pre.003` ajoute `RawTransactionIngestStandardLogsSource`, construite exclusivement à partir de surfaces Transport déjà publiques : ```text WsEndpointSettings kind solana_standard SolanaLogsSubscribeFilter SolanaCommitment Confirmed ou Finalized HttpTransportPool HttpRoleName hydration ``` La construction reste sans I/O et valide avant spawn : endpoint/protocole, commitment, réseau, provenance sûre et existence d’une route `getTransaction` compatible sur le même cluster. Aucun endpoint URL, filtre brut, credential ou client inférieur n’est exposé par l’API Worker. Au runtime : ```text SolanaStandardWsSession::connect -> logs_subscribe -> context.slot + signature seulement -> coordinator d’hydration Worker source-neutral -> get_transaction_observed encoding = base64 maxSupportedTransactionVersion = 1 -> Common RAW -> admission centrale existante -> Store ``` `logs` et `err` ne sont jamais copiés dans le signal Worker. Le reconnect, le resubscribe et le backpressure de la subscription restent possédés par le même acteur WebSocket Transport. Retry/reroutage/rate-limit HTTP restent possédés par Transport. La voie Yellowstone réutilise le même contrat d’hydration source-neutral et passe elle aussi à `maxSupportedTransactionVersion = 1`; aucune nouvelle queue, aucun second client HTTP et aucun acteur WebSocket Worker ne sont introduits. ## 30. Identité et bornes pre.003 L’identité logique Standard Logs est déterministe et opaque : ```text domain KSP live source key family = standard_logs network safe provider identity safe endpoint identity commitment private filter fingerprint SHA-256 -> [u8; 32] ``` Le rôle/pool HTTP d’hydration est volontairement exclu de l’identité live. Les trois variantes `All`, `AllWithVotes`, `Mentions(pubkey)` produisent des empreintes distinctes ; la valeur d’un pubkey `Mentions` n’apparaît pas dans `Debug`. Les bornes du coordinator sont maintenant alignées sur les settings effectifs : ```text in-flight hydration <= persistence_concurrency pending source signals <= admission_queue_capacity ``` Une activation mono-source Yellowstone ou Standard Logs est autorisée. Une composition `2..32` reste validable mais son démarrage demeure `runtime_resources.multi_source_activation_pending` avant spawn jusqu’à `pre.007`. ## 31. Preuves déterministes ajoutées pre.003 Worker unit tests ajoutés : ```text validation protocole/commitment/route HTTP Standard Logs source_key filter-sensitive et hydration-role-neutral redaction Mentions/URL/source-key bytes projection reference-only slot/signature fixture logs -> une hydration HTTP -> exact matériau Common RAW requête getTransaction = base64 + maxSupportedTransactionVersion 1 rejet duplicate Standard Logs identity ``` Canaris externes ajoutés/étendus : ```text public_api : construction et composition Standard Logs depuis crate root dependency_boundary : Transport facade only, sans Config/Job/backend/direct network crate hardening : aucune copie logs/err/payload/url, Debug borné release_completeness : nouvelle surface et nouveaux canaris obligatoires ``` Les preuves de reconnect/resubscribe/backpressure restent celles de `ksp-onchain-transport-lib`, car le Worker délègue ces mécanismes au `SolanaStandardWsSession` existant plutôt que de les réimplémenter. ## 32. Validations locales post-modification pre.003 Le toolchain Cargo/Rustfmt n’est pas disponible dans l’environnement d’assemblage. Les commandes Cargo post-`pre.003` sont donc `NON EXÉCUTÉ LOCAL` et devront être confirmées par l’opérateur. Les audits statiques réellement exécutés sont consignés dans `deltas/0.3.13/pre.003.md`. ## 33. Non-claims pre.003 `pre.003` ne prétend pas : ```text avoir ajouté blockSubscribe productif avoir ajouté Helius transactionSubscribe productif avoir ajouté HTTP live polling avoir activé plusieurs sources simultanément avoir implémenté le fanout d’observations Store multi-source avoir rendu le coordinator partagé entre plusieurs tâches source simultanées avoir ajouté du gap repair ou du backfill avoir ajouté une dépendance réseau directe au Worker avoir exécuté Cargo localement après modification ``` ## 34. Gate opérateur requis avant pre.004 Après application du delta : ```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 cargo check --workspace cargo clippy --workspace --all-targets --all-features -- -D warnings cargo test -p ksp-onchain-transport-lib cargo test -p ksp-worker-raw-transaction-ingest-lib 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 ``` `pre.004` ne doit pas commencer si une anomalie de format, règle, compilation, API, dépendance ou test apparaît. ## 35. Gate opérateur pre.003-fix.003 reçu avant pre.004 Le gate fourni par l'opérateur sur `0.3.13-pre.3.fix.3` est vert pour toutes les commandes exécutées : ```text cargo fmt --all : PASS cargo fmt --all -- --check : PASS, silencieux General Rust rule audit : clean Rust export completeness audit : 0 candidate KSP workspace Rust rule audit : clean Markdown table audit : clean (340 tables, 834 files) cargo check --workspace : PASS clippy workspace/all-targets/all-features -D warnings : PASS ksp-worker-raw-transaction-ingest-lib unit tests : 75 pass cross_layer_completeness : 4 pass dependency_boundary : 10 pass hardening : 17 pass public_api : 11 pass release_completeness : 4 pass worker doc-tests : 0 ``` Cette exécution ne contenait pas `cargo test -p ksp-onchain-transport-lib` ni les commandes `cargo tree`; aucune nouvelle affirmation n'est ajoutée pour ces commandes. Le gate Worker demandé après `pre.003-fix.003` est satisfait. ## 36. Implémentation pre.004 — Standard Block RAW-direct `pre.004` ajoute `RawTransactionIngestStandardBlockSource` à l'agrégat runtime existant. La construction reste sans I/O et exige : ```text WsEndpointSettings kind solana_standard SolanaBlockSubscribeFilter SolanaCommitment Confirmed ou Finalized ``` Au runtime, la source réutilise `SolanaStandardWsSession::connect` et `block_subscribe` avec : ```text encoding = Base64 transactionDetails = Full maxSupportedTransactionVersion = 1 showRewards = false ``` Aucun `HttpTransportPool`, aucun `getBlock` HTTP et aucun second acteur WebSocket ne sont ajoutés à cette source. ## 37. Qualification RAW-direct et sûreté block:null La projection accepte uniquement des versions explicitement qualifiées : ```text Legacy -> RawTransactionVersion::Legacy 0 -> RawTransactionVersion::Number(0) 1 -> RawTransactionVersion::Number(1) >1 -> source.standard_block_transaction_version_unsupported omise/null -> source.standard_block_transaction_version_unqualified ``` Le matériau Common RAW direct est construit à partir du wire Base64 de chaque transaction avec signature embarquée, slot, `blockTime`, `meta`, version et index de transaction. La fixture V1 locale sérialise un vrai `RawSolanaTransactionMessage::V1` par les types publics de `ksp-raw-transaction-lib` avant projection ; la tranche ne déduit donc pas V1 d'une simple étiquette. Les gardes suivantes sont fail-closed avant progression de frontier : ```text context.slot != notification.slot notification.err != null block == null transactions omitted/null transaction non Base64 version omise/null/>1 signature embarquée invalide index usize non représentable en u32 ``` `block: null` n'est jamais traité comme bloc vide ou slot settled. Pour un bloc non vide, le slot n'est enregistré settled qu'après l'admission réussie de toutes ses transactions. La voie directe ne détourne pas `hydration_pending`; un arrêt ou une faute au milieu du bloc ne produit aucune progression transitoire. ## 38. Identité, redaction et composition pre.004 La clé logique Standard Block est dérivée de : ```text domain KSP live source key family = standard_block network safe provider identity safe endpoint identity commitment private block-filter fingerprint SHA-256 -> [u8; 32] ``` `Debug` n'expose que des identités sûres, le type de filtre et les longueurs d'empreinte/clé. Un pubkey de `MentionsAccountOrProgram` n'est pas recopié. L'agrégat public gagne `from_standard_block_source` et `try_push_standard_block_source` avec les mêmes bornes `1..32`, invariant réseau unique et rejet transactionnel des doublons. Une seule source reste productivement activable. Une collection `2..32` demeure `runtime_resources.multi_source_activation_pending` avant spawn jusqu'à `pre.007`. ## 39. Preuves déterministes ajoutées pre.004 Worker unit tests ajoutés couvrent : ```text validation protocol/commitment Standard Block source_key stable, filter-sensitive et redacted qualification exacte Legacy/V0/V1 rejet version omise/null/>1 fixture V1 wire -> matériau Common RAW direct exact rejet duplicate Standard Block identity ``` Canaris externes ajoutés/étendus : ```text public_api : construction et composition Standard Block depuis crate root dependency_boundary : façade Transport uniquement, sans getBlock HTTP/direct network crate hardening : block:null/version/encoding/redaction explicites release_completeness : export et canaris pre.004 obligatoires ``` ## 40. Validations locales post-modification pre.004 Le toolchain Cargo/Rustfmt reste indisponible dans l'environnement d'assemblage. Les commandes Cargo post-`pre.004` sont donc `NON EXÉCUTÉ LOCAL`; seuls les audits statiques effectivement lancés sont déclarés PASS dans le delta de livraison. ## 41. Non-claims pre.004 `pre.004` ne prétend pas : ```text avoir ajouté Helius transactionSubscribe productif avoir ajouté HTTP live polling avoir activé plusieurs sources simultanément avoir implémenté le fanout d'observations Store multi-source avoir ajouté un fallback HTTP getBlock/getTransaction à Standard Block avoir étendu le RAW-direct à une version >1 ou ambiguë avoir transformé block:null en progression avoir ajouté une dépendance réseau directe au Worker avoir exécuté Cargo localement après modification ``` ## 42. Gate opérateur requis avant pre.005 Après application du delta : ```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 cargo check --workspace cargo clippy --workspace --all-targets --all-features -- -D warnings cargo test -p ksp-onchain-transport-lib cargo test -p ksp-worker-raw-transaction-ingest-lib 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 ``` `pre.005` ne doit pas commencer si une anomalie de format, règle, compilation, API, dépendance ou test apparaît. ## 43. Gate opérateur pre.004-fix.001 Preuve reçue le 10 septembre 2026 : ```text fmt : PASS audits Rust : clean / export completeness 0 Markdown : clean, 340 tables / 836 files cargo check --workspace : PASS clippy workspace all-targets all-features -D warnings : PASS worker unit : 79/79 PASS cross-layer : 4/4 PASS dependency boundary : 11/11 PASS hardening : 18/18 PASS public API : 12/12 PASS release completeness : 4/4 PASS ``` ## 44. Surface pre.005 matérialisée ```text RawTransactionIngestHeliusTransactionSource RawTransactionIngestRuntimeResources::from_helius_transaction_source RawTransactionIngestRuntimeResources::try_push_helius_transaction_source HeliusLaserStreamWsSession::connect HeliusLaserStreamWsSession::transaction_subscribe HeliusTransactionSubscribeOptions Full/Base64/maxV1/showRewards=false project_helius_transaction_signal hydration source-neutral get_transaction_observed ``` Aucun changement Config/Transport/manifeste de crate n'est requis. ## 45. Contrats Helius vérifiés statiquement La tranche exige : ```text protocol = helius_laserstream commitment = confirmed | finalized HTTP hydration route = get_transaction sur même réseau notification productive = Full uniquement signal Worker = signature + slot + transactionIndex + route/filter safe identity nested transaction payload = non copié protocol de provenance convergée = helius_ws_http acquisition method = transaction_get_transaction ``` La source key inclut le filtre complet sous empreinte SHA-256 privée, avec normalisation de l'ordre des listes de pubkeys. Le rôle d'hydration n'entre pas dans l'identité live. ## 46. Config, secret et tier Les profils Helius LaserStream Mainnet/Devnet et `KSP_SECRET_HELIUS_API_KEY` existaient avant `pre.005`. Le Worker reçoit seulement `WsEndpointSettings` déjà résolu et ne dépend jamais de Config. Aucun tier provider, prix, quota ou entitlement n'est codé ; l'éligibilité réelle d'un compte Helius reste une propriété externe/live. ## 47. Preuves unitaires et externes attendues ```text unit : request fixed Full/Base64/maxV1/showRewards=false unit : protocol/commitment/cross-network hydration rejection unit : source key stable/filter-sensitive/order-normalized/redacted unit : Full reference projection signature/slot/index only unit : reference -> HTTP getTransaction -> Common RAW exact unit : duplicate Helius source rejected transactionally public_api : root constructor/from/push typed boundary : facade Helius + one common getTransaction only hardening : nested payload/secret/tier absent release : export inventory + canaries pre.005 ``` ## 48. Validation locale d'assemblage pre.005 Le toolchain Cargo/Rustfmt n'est pas disponible dans l'environnement d'assemblage. Les commandes Cargo post-modification restent `NON EXÉCUTÉ LOCAL`; seuls les audits statiques effectivement exécutés peuvent être déclarés PASS dans le delta. ## 49. Non-claims pre.005 ```text pas de multi-source simultané avant pre.007 pas de HTTP live polling avant pre.006 pas de RAW-direct depuis le nested payload Helius pas de SDK Helius pas de secret/Config dans le Worker pas de tier/quota provider codé pas de nouveau profil Config pas de changement Transport ``` ## 50. Gate opérateur requis avant pre.006 ```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 cargo test -p ksp-worker-raw-transaction-ingest-lib 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 ``` ## 51. Gate opérateur pre.005-fix.001 reçu Preuve communiquée le 10 septembre 2026 : ```text fmt : PASS audits Rust : clean / export completeness 0 Markdown : clean, 340 tables / 838 files cargo check --workspace : PASS clippy workspace all-targets all-features -D warnings : PASS worker unit : 84/84 PASS cross-layer : 4/4 PASS dependency boundary : 12/12 PASS hardening : 19/19 PASS public API : 13/13 PASS release completeness : 4/4 PASS ``` ## 52. Surface pre.006 matérialisée ```text RawTransactionIngestHttpBlockPollingSource RawTransactionIngestRuntimeResources::from_http_block_polling_source RawTransactionIngestRuntimeResources::try_push_http_block_polling_source getSlot(commitment) au démarrage et à chaque cycle getBlocksWithLimit(next_scan_slot, bounded_limit, commitment) getBlock observed sur les slots listés Full/Base64/maxV1/rewards=false RAW-direct Legacy/V0/V1 timer Worker stop-preemptible ``` Aucun manifeste de crate ni aucune dépendance Transport/Config supplémentaire n'est requis. ## 53. Invariants statiques vérifiés pre.006 La tranche encode explicitement : ```text start_slot = premier getSlot du run next_scan_slot initial = start_slot aucune découverte avant next_scan_slot découverte strictement croissante getBlock=null sur slot listé => next_scan_slot reste ce slot skipped slot non listé => pas de faux gap slot settled seulement après admission de tout le bloc aucun hydration_pending pour la voie RAW-direct version Legacy/V0/V1 qualifiée, ambiguë/>1 rejetée provenance endpoint/provider réellement observé sur getBlock source_key indépendant du poll interval et du batch size ``` Les anciens canaris de `0.3.12` qui interdisaient globalement `get_block_observed`/`tokio::time::sleep` ont été resserrés plutôt que supprimés : le coordinator d'hydration continue de ne posséder ni polling ni retry, tandis que ces primitives sont explicitement permises et bornées dans la seule source HTTP polling. ## 54. Validation locale d'assemblage pre.006 Le toolchain Cargo/Rustfmt n'est pas disponible dans l'environnement d'assemblage. Les commandes Cargo post-modification restent donc `NON EXÉCUTÉ LOCAL`. Les audits statiques exécutés sur l'état final sont consignés dans le delta `pre.006`. ## 55. Non-claims pre.006 ```text pas de scan historique avant le start_slot du run pas de checkpoint durable de polling pas de Backfill implicite pas de multi-source simultané avant pre.007 pas de retry/backoff HTTP implémenté dans le Worker pas de client reqwest direct pas de Config lu dans le Worker pas de version transaction >1 ou ambiguë acceptée pas de getBlock=null assimilé à un slot vide ``` ## 56. Gate opérateur requis avant pre.007 ```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 cargo test -p ksp-worker-raw-transaction-ingest-lib 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 ``` ## 57. Gate opérateur pre.006-fix.001 reçu Preuve communiquée le 10 septembre 2026 sur les commandes exécutées : ```text fmt : PASS audits Rust : clean / export completeness 0 Markdown : clean, 340 tables / 840 files cargo check --workspace : PASS clippy workspace all-targets all-features -D warnings : PASS worker unit : 88/88 PASS cross-layer : 4/4 PASS dependency boundary : 13/13 PASS hardening : 20/20 PASS public API : 14/14 PASS release completeness : 4/4 PASS ``` Les sorties Transport ciblées et `cargo tree` demandées dans le gate complet ne figurent pas dans le log reçu et ne sont donc pas déclarées PASS. ## 58. Surface pre.007 matérialisée ```text RawTransactionIngestRuntimeResources::run_live_sources RawTransactionIngestSourceInventory privé RawTransactionIngestSourceInventoryPublisher privé JoinSet privé 1..32 sources stop fanout privé drain/join de toutes les sources projection processing frontier agrégée suppression de multi_source_activation_pending ``` Aucune nouvelle API publique n'est nécessaire : les méthodes `from_*`, `try_push_*`, `source_count` et `start_with_runtime_resources` existantes suffisent à composer puis lancer plusieurs sources. ## 59. Invariants supervisor/source inventory vérifiés statiquement La tranche exige : ```text 1..32 sources validées avant run toutes les sources présentes sont spawnees aucun sous-ensemble silencieux aucune politique primary/standby/fallback une source fautive arrête les autres et le supervisor les join une fermeture source avant stop est terminale source_key reste privée inventaire borné initialisé depuis les source_key validées frontier globale conservatrice = minimum seulement si toutes les sources ont une frontier oldest pending global = minimum état source agrégé sans provider material ``` Les tests déterministes ajoutés utilisent des tasks factices pour prouver le join de trois sources au stop et le stop/join d'une sœur après faute, sans I/O réseau. ## 60. Validation locale d'assemblage pre.007 Le toolchain Cargo/Rustfmt n'est pas disponible dans l'environnement d'assemblage. Les commandes Cargo post-modification restent `NON EXÉCUTÉ LOCAL`; seuls les audits statiques effectivement exécutés sont déclarés PASS dans le delta. ## 61. Non-claims pre.007 ```text pas de coalescence cross-source complète avant pre.008 pas d'unique hydration globale cross-source garantie avant pre.008 pas d'observations Store multiples convergées avant pre.008 pas de fairness duplicate-storm fermée avant pre.009 pas de nouveaux compteurs/health publics multi-source avant pre.010 pas de failover/degraded non-terminal d'une source pas de preuve de coverage entre sources ``` ## 62. Gate opérateur requis avant pre.008 ```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 cargo test -p ksp-worker-raw-transaction-ingest-lib 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 ``` ## 63. Gate opérateur pre.007 reçu Preuve communiquée le 10 septembre 2026 : fmt PASS, audits Rust clean/export completeness 0, Markdown clean `340/841`, `cargo check --workspace` PASS, Clippy strict PASS, Worker `90/90` unit, `4/4` cross-layer, `14/14` dependency-boundary, `21/21` hardening, `15/15` public-api, `4/4` release-completeness et `0` doc-test. Le log fourni ne contient pas les sorties Transport ciblées ni les trois `cargo tree`. ## 64. Surface pre.008 matérialisée ```text RawTransactionIngestGlobalHydrationRegistry privé coalescence globale (network, signature, commitment) leader unique getTransaction observed résultat partagé par watch borné/retiré RawTransactionIngestPersistenceConvergence privé clé canonique (network, signature) hash canonique conflict-checked première persistence atomique entity + observation observations suivantes via record_raw_transaction_observation RawObservationKey source-distincte et idempotente ``` ## 65. Invariants pre.008 ```text aucun fanout HTTP pour une même clé d'hydration simultanée aucune fusion des identités de source dans l'API publique une identité RAW canonique n'est pas dupliquée par source hash divergent pour même network/signature => content conflict terminal observation source différente => observation durable supplémentaire replay même observation => AlreadyPresent sans réécriture RAW registre hydration <= admission_queue_capacity cache persistence runtime <= max(admission_queue_capacity, persistence_concurrency) aucun backend Store physique ni client HTTP direct dans Worker ``` ## 66. Validation locale d'assemblage pre.008 Le toolchain Cargo/Rustfmt n'est pas disponible dans l'environnement d'assemblage. Les commandes Cargo post-modification restent `NON EXÉCUTÉ LOCAL`; les audits statiques et contrôles de packaging sont consignés dans le delta `pre.008`. ## 67. Non-claims pre.008 ```text pas encore de fairness adversariale complète avant pre.009 pas encore de canari starvation/duplicate storm cross-source complet avant pre.009 pas de failover provider implicite pas de préférence silencieuse entre sources divergentes pas de nouveaux compteurs/health publics multi-source avant pre.010 ``` ## 68. Gate complet pre.008-fix.002 reçu Le 10 septembre 2026, le gate Worker puis son complément Transport/graphe ont été fournis et sont verts pour toutes les commandes exécutées : ```text fmt : PASS audits Rust : clean / export completeness 0 Markdown : clean, 340 tables / 844 files cargo check --workspace : PASS clippy strict : PASS Worker : 94 unit + 4 cross-layer + 15 dependency-boundary + 22 hardening + 16 public-api + 4 release-completeness, 0 échec Transport : 389 unit + 52 public-api + 44 release-completeness + 4 doc-tests, 0 échec smokes Transport live opt-in : 5 ignored comme prévu cargo tree worker normal/features : exécutés sans erreur cargo tree --duplicates : exécuté sans erreur et liste les doublons existants du workspace ``` Aucun smoke live ignoré n'est requalifié en preuve réseau réelle. ## 69. Surface pre.009 matérialisée ```text validate_hydration_fairness_capacity privé hydration_pending_limit privé hydration_in_flight_limit privé quotas statiques par source reference-bearing RawTransactionIngestGlobalHydrationRegistry max_pending exact sémaphore global hydration RawTransactionIngestHydrationLeaderGuard privé RawTransactionIngestCanonicalState privé comparaison slot/block_time/format/hash avant observation additionnelle ``` Aucune API publique ni dépendance supplémentaire n'est requise. ## 70. Invariants globaux pre.009 Pour une composition productive valide : ```text hydration_source_count <= admission_queue_capacity hydration_source_count <= persistence_concurrency somme quotas pending = admission_queue_capacity somme quotas hydration tasks = persistence_concurrency quota de chaque source reference-bearing >= 1 global registry distinct keys <= admission_queue_capacity HTTP leader effectivement ouvert <= persistence_concurrency source count <= 32 ``` Une composition sous-provisionnée échoue avant spawn. Il n'existe aucune extension silencieuse des bornes configurées, aucune queue provider privée et aucune `unbounded_channel`. ## 71. Duplicate storm, fairness et cleanup Les tests déterministes ajoutés vérifient : ```text 32 subscriptions identiques -> une seule entrée/leader global clés distinctes au-delà de max_pending -> runtime_invalid sûr sémaphore capacité 1 -> seconde acquisition simultanée refusée leader guard droppé -> follower reçoit Failed et la clé peut redevenir leader queue admission capacité 1 -> une seconde source déjà prête n'est pas affamée par la répétition d'une storm ``` Le test de fairness ne revendique ni priorité métier ni scheduler pondéré. Il vérifie le comportement minimal attendu du canal borné commun et les quotas réservent une capacité aux autres sources reference-bearing. ## 72. Disagreement/content conflict pre.009 Pour une même identité `(network, signature)`, le cache run-local compare maintenant : ```text slot block_time format_id format_version content_hash ``` Les cas slot divergent, block time divergent et contenu/hash divergent sont testés comme content conflicts terminaux avant `record_raw_transaction_observation`. Le Store reste l'autorité durable finale et aucune politique de majority vote, provider priority, preferred provider ou overwrite conflict n'est admise. ## 73. Canaris externes pre.009 Les suites externes sont étendues pour verrouiller : ```text dependency-boundary : bornes/fairness restent dans Worker + façades existantes hardening : quotas, sémaphore, cleanup, disagreement et absence de provider preference public-api : registry, leader guard, quotas et canonical state restent privés release-completeness : présence obligatoire des trois nouveaux canaris ``` ## 74. Validation locale d'assemblage pre.009 Le toolchain Cargo/Rustfmt n'est pas disponible dans l'environnement d'assemblage. Les commandes Cargo post-modification restent `NON EXÉCUTÉ LOCAL`; seules les validations statiques effectivement exécutées et les contrôles de packaging pourront être déclarés PASS dans le delta. ## 75. Non-claims pre.009 ```text pas de nouveaux compteurs/health publics avant pre.010 pas de QoS/scheduler pondéré pas de failover provider implicite pas de source primary/standby pas de majority vote pas de préférence provider/tier pas de overwrite d'un conflit canonique pas de preuve live réseau nouvelle ``` ## 76. Gate opérateur requis avant pre.010 ```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 cargo test -p ksp-worker-raw-transaction-ingest-lib 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 ```