# Delta `0.2.11-pre.002` — fondation Off-chain Transport SOL/USD ## 1. Base requise Cette tranche s'applique exclusivement sur : ```text v0.2.10 + 0.2.11-pre.001 + 0.2.11-pre.001-fix.001 ``` La version Cargo d'entrée attendue est : ```text 0.2.11-pre.1 ``` La version Cargo de sortie est : ```text 0.2.11-pre.2 ``` ## 2. Objectif Créer la fondation de `ksp-offchain-transport-lib` sans avancer le client HTTP commun ni aucun adapter provider. La tranche matérialise uniquement : ```text surface publique SOL/USD V1 PriceDecimal exact sans f64 canonique observation/provenance/timestamps provider-neutral identifiant/descripteur provider opaque sémantique de prix explicite auth/rate-limit/quota descriptifs settings communs minimaux availability/state provider-neutral ``` `reqwest`, le limiter actif, les credentials provider et les DTOs wire restent réservés aux prereleases suivantes. ## 3. Décisions matérialisées ### 3.1 Décimal exact `PriceDecimal` possède : ```text coefficient positif u128 scale maximale 18 entrée textuelle maximale 96 octets normalisation des zéros fractionnaires terminaux notation scientifique bornée serialization Serde canonique sous forme de string décimale zéro, négatif, NaN/Inf, overflow et scale excessive rejetés ``` Le type ne passe jamais par `f64` comme vérité canonique. Le zéro étant invalide pour un prix réussi, l'absence de prix ne peut pas être silencieusement transformée en `0`. ### 3.2 Paire et observation V1 La seule paire publique reste : ```text PricePair::SolUsd ``` `SolUsdPriceObservation` conserve : ```text provider_id opaque PriceDecimal PriceSemantics request_started_at received_at provider_timestamp optionnel PriceProvenance sûre et bornée ``` Les timestamps sont projetés en millisecondes UTC depuis Unix epoch via `PriceTimestamp`. Le constructeur rejette une réception antérieure au départ de requête. Aucun timestamp provider n'est obligatoire ou inventé. ### 3.3 Provider-neutral descriptors `PriceProviderId` est un identifiant opaque borné. Il n'expose pas les identifiants wire propriétaires des providers. `PriceProviderDescriptor` conserve uniquement des informations génériques utiles aux consumers : ```text id nom d'affichage PriceSemantics PriceProviderAuthMode PriceProviderRateLimit PriceProviderLongTermQuota optionnel support SOL/USD ``` Les limites fixes exigent un nombre de requêtes et une fenêtre non nuls. Une limite dynamique/server-driven est représentée séparément. Les quotas longs termes sont informatifs : aucun compteur local ne prétend connaître le quota restant réel d'un compte partagé ou consommé par un autre processus. ### 3.4 Settings communs minimaux `PriceProviderCommonSettings` ne contient que : ```text provider_id enabled ``` Il ne contient volontairement ni endpoint, ni API key, ni cadence configurable. Les settings propres à CoinGecko, CoinMarketCap, Jupiter, Birdeye ou DexScreener seront ajoutés uniquement avec leurs adapters afin que chaque configuration corresponde aux capacités réelles du provider. ### 3.5 Availability générique `PriceProviderAvailability` peut représenter : ```text authentication unavailable cooling down + retry_at disabled misconfigured quota unavailable ready temporarily unavailable + retry_at optionnel ``` `PriceProviderState` associe cette projection à un `PriceProviderId` sans demander au consumer de parser une erreur provider. Le registry et les transitions runtime effectives restent prévus en `pre.007`. ## 4. Tests ajoutés La crate contient des tests unitaires physiquement séparés pour : ```text parsing/normalisation/scientific notation PriceDecimal rejets numeric safety round-trip Serde PriceDecimal validation PriceProviderId descriptors auth/rate-limit/quota availability générique observation SOL/USD et ordre des timestamps provenance sûre settings communs sans endpoint/API key/rate-limit ``` Deux tests d'intégration vérifient : ```text surface publique pre.002 au crate-root error codes domaine offchain_transport absence de dépendance Config absence de reqwest/provider SDK dans le manifest pre.002 ``` ## 5. Fichiers ajoutés ```text crates/ksp-offchain-transport-lib/Cargo.toml crates/ksp-offchain-transport-lib/src/decimal.rs crates/ksp-offchain-transport-lib/src/error.rs crates/ksp-offchain-transport-lib/src/lib.rs crates/ksp-offchain-transport-lib/src/observation.rs crates/ksp-offchain-transport-lib/src/provider.rs crates/ksp-offchain-transport-lib/src/settings.rs crates/ksp-offchain-transport-lib/tests/dependency_boundary.rs crates/ksp-offchain-transport-lib/tests/public_api.rs crates/ksp-offchain-transport-lib/unit_tests/decimal.rs crates/ksp-offchain-transport-lib/unit_tests/observation.rs crates/ksp-offchain-transport-lib/unit_tests/provider.rs crates/ksp-offchain-transport-lib/unit_tests/settings.rs deltas/0.2.11/pre.002.md ``` ## 6. Fichiers modifiés ```text Cargo.toml docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md ``` ## 7. Fichiers supprimés ```text aucun ``` ## 8. Fichiers volontairement inchangés ```text CHANGELOG.md ROADMAP.md README.md .env.example config/** crates/ksp-config-lib/** crates/ksp-onchain-transport-lib/** prompts/** ``` `ROADMAP.md` et `CHANGELOG.md` restent hors de cette tranche conformément à leur ownership de release. ## 9. Validations exécutées dans le sandbox ```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 python3 scripts/audit_markdown_tables.py docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md clean / 14 tables / 2 files contrôle lignes Rust > 160 sur la nouvelle crate PASS / aucune inspection manifest nouvelle crate ksp-config-lib absent reqwest absent en pre.002 SDK provider absent ``` ## 10. Validations non exécutées dans le sandbox Le sandbox de génération ne fournit pas `cargo`, `rustc` ou `rustfmt`. Les validations suivantes doivent donc être exécutées par l'opérateur après application du delta : ```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 ``` Les validations Cargo fournies par l'opérateur pour `pre.001` étaient vertes avant cette tranche ; elles constituent une baseline d'entrée mais ne sont pas comptées comme validation du nouveau code `pre.002`. ## 11. Questions ouvertes Aucune question de design ne bloque `pre.003`. Les points volontairement différés restent : ```text HTTP reqwest commun conversion JSON number/string provider vers PriceDecimal classification HTTP/transport Retry-After limiter/cooldown actif credentials provider adapters provider registry runtime effectif ``` ## 12. Suite prévue La tranche suivante reste : ```text 0.2.11-pre.003 — HTTP REST commun et rate limiting ``` Elle pourra ajouter `reqwest` et `ksp-logging-lib` à la nouvelle crate, les bornes HTTP, la redaction, la classification commune des erreurs et le limiter/cooldown générique, sans encore implémenter les adapters provider de `pre.004+`.