# Delta `0.2.11-pre.005` — Kraken + Coinbase Exchange ## 1. Base requise Cette tranche s'applique exclusivement après `0.2.11-pre.004-fix.001` validé par l'opérateur. Version Cargo attendue à l'entrée : ```text 0.2.11-pre.4.fix.1 ``` Version Cargo de sortie : ```text 0.2.11-pre.5 ``` Le gate d'entrée du `2026-08-25` est intégralement PASS : audit Rust clean, audit Markdown clean, `cargo check --workspace`, `cargo clippy --workspace --all-targets`, `cargo test -p ksp-offchain-transport-lib` et `cargo test --workspace`. ## 2. Objet strict de la tranche `pre.005` ajoute uniquement les deux providers exchange prévus par le forecast : ```text Kraken Spot Coinbase Exchange ``` Le contrat reste : ```text SOL/USD uniquement HTTP REST direct via reqwest aucun SDK provider aucun credential provider pour Kraken/Coinbase Exchange MarketPriceSemantics::ExchangeLastTrade pas de registry global pas de Config pas de refresh multiple pas de smoke live revendiqué ``` ## 3. Kraken Spot Ajout de : ```text market_price_kraken.rs unit_tests/market_price_kraken.rs MarketPriceKrakenSettings MarketPriceKrakenProvider ``` Le provider est keyless et utilise l'endpoint public fixe : ```text https://api.kraken.com/0/public/Ticker?pair=SOLUSD ``` Le dernier trade est lu dans `c[0]` et normalisé par `MarketPriceDecimal::parse_json_raw` sans passage par `f64`. Le ticker public Kraken ne porte pas de timestamp du dernier trade dans cette forme. KSP conserve donc : ```text provider_timestamp = None ``` et n'invente aucune heure provider à partir de l'heure de réception locale. La sémantique reste : ```text MarketPriceSemantics::ExchangeLastTrade ``` La documentation Kraken indique qu'une cadence de `1 req/s` ou moins reste dans les limites des endpoints REST publics. Le descriptor V1 retient donc une limite locale conservatrice : ```text 1 req/s scope IP burst non documenté ``` ## 4. Coinbase Exchange Ajout de : ```text market_price_coinbase_exchange.rs unit_tests/market_price_coinbase_exchange.rs MarketPriceCoinbaseExchangeSettings MarketPriceCoinbaseExchangeProvider ``` Le provider est keyless et utilise l'endpoint public fixe : ```text https://api.exchange.coinbase.com/products/SOL-USD/ticker ``` KSP conserve : ```text price provider timestamp RFC3339 time ``` Le prix est parsé exactement via `RawValue` et le timestamp est converti dans le contrat millisecondes UTC existant. Le descriptor conserve le token bucket public documenté par Coinbase Exchange : ```text 10 req/s par IP burst 15 ``` La sémantique reste : ```text MarketPriceSemantics::ExchangeLastTrade ``` ## 5. Façade publique La taxonomie publique reste capability-scoped : ```text MarketPriceKraken* MarketPriceCoinbaseExchange* ``` Le nom `CoinbaseExchange` est volontairement explicite afin de ne pas confondre cette surface avec Advanced Trade ou d'autres APIs Coinbase futures. Aucun type wire provider n'est exporté. Les primitives `http_*` restent crate-private. ## 6. Tests déterministes ajoutés Les nouveaux canaries couvrent : ```text Kraken exact last trade decimal Kraken provider_timestamp absent Kraken descriptor keyless + 1 req/s IP Kraken provider error rejetée Kraken résultat d'une autre paire rejeté Coinbase exact last trade decimal Coinbase timestamp RFC3339 conservé Coinbase descriptor keyless + 10 req/s IP + burst 15 Coinbase timestamp invalide rejeté façade publique des deux adapters endpoints fixes et absence de std::env ``` ## 7. Documentation réconciliée Mise à jour de : ```text docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md ``` Le plan marque `pre.004-fix.001` comme gate opérateur complet PASS et `pre.005` comme réalisé en attente de son gate Cargo. ## 8. Fichiers ajoutés ```text crates/ksp-offchain-transport-lib/src/market_price_coinbase_exchange.rs crates/ksp-offchain-transport-lib/src/market_price_kraken.rs crates/ksp-offchain-transport-lib/unit_tests/market_price_coinbase_exchange.rs crates/ksp-offchain-transport-lib/unit_tests/market_price_kraken.rs deltas/0.2.11/pre.005.md ``` ## 9. Fichiers modifiés ```text Cargo.toml crates/ksp-offchain-transport-lib/src/lib.rs crates/ksp-offchain-transport-lib/tests/dependency_boundary.rs crates/ksp-offchain-transport-lib/tests/public_api.rs docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md ``` ## 10. Validation attendue ```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-offchain-transport-lib cargo test --workspace ``` `pre.006` ne doit commencer qu'après un gate propre de `pre.005` ou un delta fix explicite.