# Delta `0.2.11-pre.009` — Config Off-chain Transport ## 1. Base requise Cette tranche s'applique exclusivement après `0.2.11-pre.008-fix.001` validé. Version Cargo attendue à l'entrée : ```text 0.2.11-pre.8.fix.1 ``` Version Cargo de sortie : ```text 0.2.11-pre.9 ``` Le gate opérateur de la base est intégralement PASS : audits Rust/Markdown, `cargo check --workspace`, `cargo clippy --workspace --all-targets`, tests ciblés Off-chain puis `cargo test --workspace`. ## 2. Scope réalisé `pre.009` matérialise la frontière Config -> Off-chain Transport sans modifier les contrats réseau des huit providers V1. La tranche ajoute : ```text cfg.std.offchain_transport schema.std.offchain_transport std.offchain_transport.json format_version 1 std.offchain_transport.schema.json exemple et fixture Config ResolvedOffchainTransportConfig adapter Config -> MarketPriceService variables d'environnement documentées pour les credentials/pair DexScreener ressources desktop nécessaires au packaged runtime ``` Elle n'ajoute pas : ```text nouveau provider nouvel endpoint provider SDK provider URL provider configurable rate limit librement configurable scheduler périodique fallback / consensus / agrégation smoke live ``` ## 3. Structure durable du document Le document Off-chain Transport reste générique et place la capacité actuelle sous : ```text market_price ``` Deux profils versionnés sont fournis : ```text public_keyless all_free ``` `public_keyless` active uniquement les modes réellement utilisables sans secret. Birdeye et DexScreener y restent désactivés. `all_free` active les modes gratuits nécessitant une clé et DexScreener avec une paire SOL/USD explicite. Les huit branches `market_price` sont obligatoires dans le schema afin que l'inventaire V1 reste explicite et déterministe. ## 4. Capabilities provider et secrets Le schema conditionne les credentials selon les capacités : ```text CoinGecko keyless -> api_key interdite CoinGecko demo activé -> api_key requise CoinMarketCap keyless -> api_key interdite CoinMarketCap basic activé -> api_key requise Jupiter keyless -> api_key interdite Jupiter free activé -> api_key requise Birdeye activé -> api_key requise DexScreener activé -> sol_usd_pair_address requise ``` L'adapter effectif ajoute une contrainte de provenance que le JSON Schema ne peut pas exprimer : toute API key provider doit provenir d'une variable classée Secret par Config. Un littéral credential ou une variable d'environnement non secret sont rejetés sans recopier la valeur dans l'erreur. Variables versionnées dans `.env.example` : ```text KSP_SECRET_BIRDEYE_API_KEY KSP_SECRET_COINGECKO_DEMO_API_KEY KSP_SECRET_COINMARKETCAP_API_KEY KSP_SECRET_JUPITER_API_KEY KSP_PUBLIC_DEXSCREENER_SOL_USD_PAIR_ADDRESS ``` La paire DexScreener est publique. Lorsqu'elle provient de l'environnement, l'adapter exige une provenance `Public` ; un namespace Secret/Internal est rejeté. ## 5. Adapter Config -> runtime `ResolvedOffchainTransportConfig` conserve : ```text file_id logique profile_id selection_source source_path ResolvedConfigJson effectif et safe MarketPriceService construit ``` `ConfigDocumentEngine` expose : ```text load_resolved_offchain_transport_config resolve_offchain_transport_config_profile ``` Le mapping utilise les settings publics des huit adapters et construit `MarketPriceProviderSetup`, puis `MarketPriceService`. Après cette composition, le consumer runtime reste provider-agnostic. `ksp-offchain-transport-lib` ne dépend jamais de `ksp-config-lib` et ne lit pas directement l'environnement. ## 6. Réconciliation DexScreener capability-aware Le contrat de plan exigeait `sol_usd_pair_address` uniquement si DexScreener est activé. La construction runtime demandait encore une paire même lorsque le provider était désactivé. `MarketPriceDexScreenerSettings` est donc réconcilié : ```text enabled = true + pair absente -> erreur pair présente mais invalide -> erreur enabled = false + pair absente -> valide ``` Cette évolution évite de fabriquer une fausse adresse de paire uniquement pour conserver DexScreener dans le registry générique. Elle ne change ni l'endpoint, ni les validations chain/pair/WSOL, ni le parsing `priceUsd` lorsque le provider est actif. ## 7. Registry Config et packaged runtime Le registry Config enregistre désormais dix descriptors et ajoute le document/schema Off-chain Transport avec leurs file ids durables. Les deux applications desktop existantes embarquent également : ```text config/std.offchain_transport.json config/schemas/std.offchain_transport.schema.json ``` Cette inclusion est nécessaire parce que `prepare_packaged_runtime` synchronise l'intégralité du registry Config, même si Wallet Desk et Config Desk ne consomment pas directement le service de prix dans cette release. ## 8. Tests et canaries ajoutés Les nouveaux tests couvrent notamment : ```text registry document/schema Off-chain Transport profil public_keyless -> huit providers, Birdeye/Dex disabled profil all_free -> huit providers Ready avec environnement complet redaction des quatre credential canaries rejet d'un credential provider littéral rejet d'une paire DexScreener provenant d'un namespace Secret DexScreener disabled sans paire façade Config publique depuis crate root ownership Off-chain -> Config interdit inventaire .env.example ressources packaged desktop mises à jour ``` ## 9. Fichiers ajoutés ```text config/examples/std.offchain_transport.example.json config/schemas/std.offchain_transport.schema.json config/std.offchain_transport.json crates/ksp-config-lib/src/offchain_transport.rs crates/ksp-config-lib/unit_tests/fixtures/std.offchain_transport.json crates/ksp-config-lib/unit_tests/offchain_transport.rs deltas/0.2.11/pre.009.md ``` ## 10. Fichiers modifiés ```text .env.example Cargo.toml crates/ksp-app-config-desk/tauri.conf.json crates/ksp-app-config-desk/tests/desktop_contract.rs crates/ksp-app-wallet-desk/tauri.conf.json crates/ksp-app-wallet-desk/tests/desktop_contract.rs crates/ksp-app-wallet-desk/tests/release_compliance.rs crates/ksp-config-lib/Cargo.toml crates/ksp-config-lib/src/lib.rs crates/ksp-config-lib/src/registry.rs crates/ksp-config-lib/tests/ownership.rs crates/ksp-config-lib/tests/public_api.rs crates/ksp-config-lib/unit_tests/registry.rs crates/ksp-offchain-transport-lib/src/market_price_dexscreener.rs crates/ksp-offchain-transport-lib/tests/public_api.rs crates/ksp-offchain-transport-lib/unit_tests/market_price_dexscreener.rs crates/ksp-offchain-transport-lib/unit_tests/market_price_registry.rs crates/ksp-offchain-transport-lib/unit_tests/market_price_service.rs docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md ``` ## 11. Audits sandbox Contrôles disponibles à la construction de la tranche : ```text General Rust rule audit: clean Rust export completeness audit: 0 candidate(s) KSP workspace Rust rule audit: clean Markdown table audit: clean (123 tables / 115 files) JSON syntax: document, exemple, schema, fixture et Tauri configs PASS JSON Schema Draft 2020-12: document, exemple et fixture PASS schema conditionals: keyless credential interdit, keyed credential requis si activé, Birdeye key requis si activé, Dex pair requis si activé PASS ``` Cargo n'est pas disponible dans cet environnement ; les validations compilation/Clippy/tests restent donc opérateur. ## 12. Gate opérateur requis ```bash cargo fmt --all 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.2.11 cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-config-lib cargo test -p ksp-offchain-transport-lib cargo test --workspace ``` `pre.010` ne doit commencer qu'après ce gate propre ou un delta fix explicite.