# Plan `0.2.11` — Off-chain price transport SOL/USD multi-provider **Statut courant : `0.2.11-pre.002-fix.002` ferme le dernier écart Clippy de la fondation avant `pre.003`. Les rustdocs, la façade Logging KSP et la taxonomie interne `market_price_*` restent acquises ; le contrat V1 reste limité à SOL/USD et aucun client HTTP/provider n'est encore ajouté.** ## 1. Base et autorité Base stable autoritaire : ```text v0.2.10 ``` État vérifié dans l'archive Gitea fournie : ```text workspace.package.version = 0.2.10 deltas/0.2.10/rel.001.md présent prompts/016-V0_2_11_START_PROMPT.md présent ksp-offchain-transport-lib absente metadata .git absente de l'archive Gitea ``` Cette tranche ouvre : ```text workspace.package.version = 0.2.11-pre.1 commit attendu = v0.2.11-pre.001 aucun tag prerelease ``` Ordre d'autorité pendant `0.2.11` : ```text règles normatives KSP archive stable v0.2.10 et code réellement livré décisions opérateur consignées dans le présent plan validation 014 et deltas immuables de 0.2.11 prompt 016 pour les contraintes non supersédées sources provider officielles actuelles pour les faits externes ``` ## 2. Supersessions explicites du prompt d'ouverture Le brainstorming opérateur du 2026-08-25 remplace plusieurs hypothèses préparatoires du prompt `016`. ```text minimum V1 SOL/USD uniquement nombre de providers un ou plusieurs, sans limite artificielle à un provider initial providers ciblés tous les candidats gratuits retenus par le gate pre.001 transport provider HTTP REST avec reqwest uniquement SDK provider interdit dans 0.2.11 SOL/EUR hors scope de cette première release fallback automatique hors scope consensus/agrégation KSP hors scope future application ksp-app-solprices-desk en 0.2.12 rôle de l'application HID pure, aucune connaissance d'un provider DexScreener V1 un client SOL/USD sur une paire configurée et validée ``` Le retrait de SOL/EUR n'interdit pas son ajout ultérieur. Il évite de forcer dès V1 une conversion fiat externe ou de privilégier artificiellement les providers multi-fiat. ## 3. Mission opérationnelle `0.2.11` doit créer `ksp-offchain-transport-lib` comme propriétaire de la récupération de prix off-chain SOL/USD et des différences opérationnelles entre providers. La surface commune doit permettre à un consumer de : ```text lister les providers de prix connus du service observer leur description et leur sémantique générique observer leur disponibilité runtime observer leur capacité de refresh et le prochain instant admissible rafraîchir un provider par identifiant opaque rafraîchir plusieurs providers sans violer leurs limites respectives obtenir une observation SOL/USD typée et sa provenance obtenir une absence/erreur/cooldown sans connaissance du fournisseur ``` La crate possède les exceptions provider. Un consumer ne doit pas coder : ```text URL provider header d'auth provider ID CoinGecko ou CoinMarketCap mint Jupiter/Birdeye paire Kraken/Coinbase pair address DexScreener rate limit provider forme JSON wire provider mapping de status HTTP provider ``` ### 3.1 Taxonomie interne durable de `ksp-offchain-transport-lib` `ksp-offchain-transport-lib` est une crate de transport **off-chain hétérogène**. `0.2.11` n'en définit que la première famille fonctionnelle ; la crate elle-même ne doit pas être structurée comme si toutes ses responsabilités futures étaient des prix. La convention retenue à partir de `pre.002-fix.001` est : ```text constants.rs préoccupations partagées à toute la crate error.rs erreurs partagées / codes crate-wide http_* mécanique HTTP réutilisable entre familles lorsqu'elle sera matérialisée market_price_* prix de marché / spot et observations normalisées swap_quote_* réservé aux futures quotes montant/route, uniquement lorsqu'elles seront réellement implémentées _* nouvelle famille uniquement lorsqu'un scope réel l'exige ``` Les fichiers génériques `decimal.rs`, `observation.rs`, `provider.rs` et `settings.rs` introduits initialement par `pre.002` sont donc corrigés avant toute extension runtime : la fonctionnalité actuelle est préfixée `market_price_*`. Les futurs domaines ne doivent pas être ajoutés dans ces modules uniquement parce qu'ils utilisent eux aussi un provider HTTP. La règle est **responsabilité avant taille** : un module commun n'est promu au niveau crate-wide que lorsqu'au moins deux familles réelles partagent le même invariant. Ainsi, le HTTP, le scheduling ou une identité provider pourront être factorisés plus tard si leur partage est effectivement démontré ; aucune abstraction générique n'est créée aujourd'hui uniquement pour anticiper Jupiter Quotes. ### 3.2 Lecture, écriture et verbes HTTP La capacité `market_price` de `0.2.11` est strictement read-only. La crate n'est toutefois pas déclarée architecturalement read-only pour toutes ses versions futures. L'ownership dépend de la sémantique métier, pas du verbe HTTP : ```text GET/POST qui récupère ou calcule une donnée off-chain peut appartenir à Off-chain Transport quote de swap dépendante d'un montant et d'une route future famille swap_quote, pas market_price construction distante d'un payload sans soumission à auditer selon le contrat futur soumission/signature d'une transaction Solana reste hors d'Off-chain Transport écriture distante ayant un effet métier externe nécessite un scope/contrat explicite avant ajout ``` Un futur endpoint Jupiter utilisant `POST` ne devient donc pas automatiquement une « écriture » KSP. Inversement, aucune opération mutante distante n'est autorisée implicitement sous prétexte qu'elle passe par `reqwest`. ## 4. Frontière avec la future `ksp-app-solprices-desk` La release suivante doit créer : ```text ksp-app-solprices-desk ``` Son rôle est **purement HID**. Elle dépend de la façade publique de `ksp-offchain-transport-lib` et ne connaît aucun provider individuellement. Son premier tableau pourra afficher génériquement : ```text nom d'affichage provider prix SOL/USD fraîcheur disponible état runtime prochain refresh possible bouton refresh ``` Un bouton de refresh multiple/all appelle une opération générique du service. L'application ne fait aucun `sleep`, aucun token bucket, aucun retry provider et aucun dispatch par nom de provider. La composition Rust de l'application peut utiliser Config pour obtenir les settings puis construire le service Off-chain Transport, mais elle ne matche pas les variantes provider pour exécuter une requête. ## 5. Baseline technique interne L'inventaire de `v0.2.10` confirme que les primitives génériques nécessaires existent déjà au workspace : ```text reqwest ^0.13 serde ^1.0 serde_json ^1.0 tokio ^1.53 http ^1.5 chrono ^0.4 si parsing timestamp réellement nécessaire ``` Décision de dépendances V1 : ```text aucun SDK CoinGecko aucun SDK CoinMarketCap aucun SDK CoinPaprika aucun SDK Kraken aucun SDK Coinbase aucun SDK Jupiter aucun SDK Birdeye aucun SDK DexScreener aucune bibliothèque decimal provider/externe ajoutée par facilité ``` Les adapters utilisent `reqwest` et des DTOs wire privés KSP. `0.2.11-pre.001` n'ajoute encore aucune crate ni dépendance. ## 6. Audit provider actuel du 2026-08-25 Les huit providers ci-dessous satisfont le critère fonctionnel retenu : accès gratuit actuel, HTTP REST simple et possibilité de produire SOL/USD sans SDK provider. | Provider | Accès gratuit V1 | Auth V1 | Limite ou quota à modéliser | Sémantique SOL/USD | Verdict | |-------------------|-----------------------|-----------------------|----------------------------------------------------|--------------------------------------------|---------| | CoinGecko | keyless ou Demo | aucune ou Demo key | keyless dynamique IP, Demo 100 par min et 10k mois | agrégateur marché CoinGecko | IN | | CoinMarketCap | keyless ou Basic | aucune ou API key | keyless dynamique IP, Basic 50 par min et 15k mois | agrégateur marché CoinMarketCap | IN | | CoinPaprika | Free | aucune | 10 par sec IP et 20k mois, refresh moyen 5 min | agrégateur marché CoinPaprika | IN | | Kraken | public Spot REST | aucune | cadence sûre documentée à 1 par sec ou moins | dernier trade du marché Kraken SOL/USD | IN | | Coinbase Exchange | public Exchange REST | aucune | 10 par sec IP, burst 15 | dernier trade du produit Coinbase SOL-USD | IN | | Jupiter Price V3 | keyless ou Free | aucune ou API key | keyless 0.5 RPS, Free 1 RPS | heuristique de prix USD orientée Solana | IN | | Birdeye | Standard | X-API-KEY obligatoire | 1 RPS compte, 30k CU, Price Single 3 CU | spot USD token Solana Birdeye | IN | | DexScreener | API publique gratuite | aucune | 300 par min pour pairs/tokens | priceUsd de la paire DEX Solana configurée | IN | Sources officielles principales auditées : ```text https://docs.coingecko.com/docs/keyless-public-api https://docs.coingecko.com/reference/simple-price https://www.coingecko.com/en/api/pricing https://coinmarketcap.com/api/documentation/pro-api-reference/keyless-public-api https://coinmarketcap.com/api/documentation/pro-api-reference/cryptocurrency https://coinmarketcap.com/api/pricing https://docs.coinpaprika.com/api-reference/rest-api/introduction https://docs.coinpaprika.com/api-reference/tickers/get-ticker-for-a-specific-coin https://docs.coinpaprika.com/api-plans https://support.kraken.com/articles/206548367-what-are-the-api-rate-limits- https://support.kraken.com/hc/articles/360000919986-public-endpoint-examples-you-can-try-them-directly-in-a-web-browser- https://docs.kraken.com/api/docs/rest-api/get-ticker-information https://docs.cdp.coinbase.com/exchange/rest-api/rate-limits https://docs.cdp.coinbase.com/api-reference/exchange-api/rest-api/products/get-product-ticker https://docs.cdp.coinbase.com/api-reference/exchange-api/rest-api/products/get-single-product https://developers.jup.ag/docs/portal/migration https://developers.jup.ag/pricing https://developers.jup.ag/docs/price https://docs.birdeye.so/docs/pricing https://docs.birdeye.so/docs/rate-limiting https://docs.birdeye.so/reference/get-defi-price https://docs.birdeye.so/docs/compute-unit-cost https://docs.dexscreener.com/api/reference https://docs.dexscreener.com/ ``` Les chiffres externes sont une photographie d'audit, pas une constante éternelle. Les adapters doivent rester capables de classer `429` et les informations serveur sans supposer que la documentation ne changera jamais. ### 6.1 Gratuité technique et conditions d'usage Le verdict `IN` signifie ici qu'un accès HTTP gratuit permet techniquement de développer et live-tester le provider dans `0.2.11`. Il ne constitue pas une affirmation de gratuité commerciale permanente. L'audit du 2026-08-25 relève notamment : ```text CoinGecko keyless est présenté pour faible volume, expérimentation/prototypage et usages assimilés ; le plan Demo porte ses propres conditions et attribution CoinMarketCap keyless est présenté pour évaluation/prototypage ; un plan authentifié reste la voie documentée pour un usage avec allowance dédiée CoinPaprika Free est annoncé pour usage personnel ; l'usage commercial relève des offres payantes actuelles ``` Conséquence KSP : ```text les adapters gratuits restent implémentables en V1 aucune documentation stable KSP ne promet une gratuité commerciale durable les conditions d'usage et plans gratuits sont réaudités au gate live final avant publication stable un changement de plan/licence peut rendre un provider administrativement indisponible sans casser le contrat provider-neutral ``` ## 7. Providers écartés de V1 ### Pyth Hermes Pyth reste intéressant comme oracle mais la transition Pyth Core annoncée pour le 2026-08-26 rend son modèle d'accès immédiatement mouvant et ne garantit pas un accès gratuit durable après la période d'essai. Décision : ```text Pyth = OUT de 0.2.11 V1 ``` Un audit ultérieur pourra l'ajouter comme sémantique oracle distincte. ### Binance Aucune assimilation implicite de SOL/USDT à SOL/USD n'est admise. Décision : ```text Binance = OUT tant qu'un produit SOL/USD direct et pertinent n'est pas retenu explicitement ``` ## 8. Identité et sémantique de la paire V1 Le contrat public V1 ne devient pas un moteur générique de symboles. La seule paire fonctionnelle exposée est : ```text SOL/USD ``` Les identifiants propriétaires restent privés aux adapters ou aux settings provider : ```text CoinGecko coin id solana CoinMarketCap asset id 5426 CoinPaprika coin id sol-solana Kraken pair SOLUSD Coinbase product SOL-USD Jupiter mint SOL canonique attendu par Price V3 Birdeye mint SOL canonique attendu par Price Single DexScreener pair address configurée, base SOL vérifiée ``` Le résultat commun ne prétend pas que les prix sont équivalents. Le descriptor générique expose une classe de sémantique, par exemple : ```text AggregatedMarket ExchangeLastTrade SolanaHeuristic SolanaSpot DexPairUsd ``` Le nom final des variantes appartient à `pre.002`, mais la distinction sémantique est obligatoire. ## 9. Cas DexScreener V1 Décision opérateur : `0.2.11` implémente bien DexScreener, mais uniquement comme client SOL/USD. Le client V1 : ```text utilise un pair address Solana configuré appelle l'endpoint pair direct vérifie chainId = solana vérifie que la paire correspond au SOL attendu lit uniquement priceUsd pour le contrat commun conserve la pair address comme provenance provider sûre ne recherche pas automatiquement la meilleure pool ne sélectionne pas par liquidité ne construit aucun consensus entre pools ``` Le choix d'une paire explicite évite d'introduire silencieusement une politique de sélection DEX. Une future version pourra remplacer cette stratégie sans modifier le contrat HID de `ksp-app-solprices-desk`. ## 10. Représentation numérique Le gate rejette `f64` comme représentation canonique publique du prix. Décision matérialisée en `pre.002` : `PriceDecimal` est le type décimal KSP borné, sérialisable sans perte et construit depuis la représentation textuelle du provider. Contrat V1 exact : ```text coefficient positif u128 scale bornée à 18 décimales entrée textuelle bornée à 96 octets normalisation des zéros terminaux parsing décimal et notation scientifique bornés sans passage par f64 aucun NaN aucun Inf overflow rejeté zéro/négatif rejetés pour un prix réussi serialization canonique décimale en chaîne ``` Le wire d'un provider peut être JSON number ou string. L'adapter le convertit vers le type KSP sans utiliser `as_f64()` comme vérité canonique. `PriceDecimal` sérialise toujours sa valeur canonique sous forme de chaîne décimale non scientifique. Le zéro est invalide pour ce type puisqu'il représente exclusivement un prix réussi ; l'absence de prix reste donc hors de la valeur numérique elle-même. Cette solution évite d'ajouter une crate decimal uniquement pour V1 et prépare le passage frontend sans perte IEEE-754. ## 11. Observation commune et fraîcheur Une observation SOL/USD commune doit distinguer : ```text provider_id opaque prix décimal KSP sémantique de prix instant de départ requête KSP instant de réception KSP instant provider optionnel lorsqu'il existe réellement provenance provider sûre et bornée ``` `pre.002` matérialise ce contrat avec `SolUsdPriceObservation`, `PriceTimestamp` (millisecondes UTC depuis Unix epoch) et `PriceProvenance` bornée à 256 octets sans caractères de contrôle. Le constructeur d'observation rejette un instant de réception antérieur au départ de requête. Règles : ```text ne jamais inventer un timestamp provider ne jamais interpréter un timestamp de création token comme timestamp de prix ne jamais transformer block id, pair creation time ou autre champ en faux update time absence de prix != prix zéro stale != transport indisponible ``` ## 12. Registry et état runtime `ksp-offchain-transport-lib` possède un registry runtime des providers de prix activés/configurés. Deux surfaces génériques doivent rester distinctes : ```text capabilities statiques auditées état runtime courant ``` Le descriptor statique peut exposer : ```text provider id opaque nom d'affichage sémantique mode d'auth générique limitation générique support SOL/USD ``` `pre.002` fixe `PriceProviderId`, `PriceProviderDescriptor`, `PriceProviderAuthMode`, `PriceProviderRateLimit`, `PriceProviderLongTermQuota` et leurs enums de scope/période/unité. Les limites fixes exigent un budget et une fenêtre non nuls ; les limites dynamiques restent explicitement distinctes. Les quotas longs termes sont descriptifs et ne deviennent jamais un compteur local de quota restant. L'état runtime peut représenter au minimum : ```text ready cooling down avec prochain instant admissible temporarily unavailable authentication unavailable quota unavailable misconfigured disabled ``` `PriceProviderAvailability` et `PriceProviderState` matérialisent cette projection générique dès `pre.002`; le registry et les transitions runtime effectives restent prévus en `pre.007`. Les noms Rust de cette fondation sont désormais matérialisés ; aucun consumer ne doit parser des strings d'erreur pour connaître cet état. ## 13. Rate limiting et refresh multiple Le rate limiting appartient entièrement à `ksp-offchain-transport-lib`. Le modèle doit savoir représenter : ```text cadence fixe burst si documenté fenêtre par seconde ou minute quota long terme informatif limite dynamique/server-driven scope IP, compte ou organisation lorsque pertinent ``` Les quotas mensuels provider ne sont pas décrémentés comme une vérité authoritative locale : un autre processus peut consommer le même compte. Ils sont exposés comme capacités documentées ; les réponses provider restent la vérité runtime. ### Refresh individuel Un `refresh(provider_id)` : ```text vérifie l'éligibilité locale exécute si autorisé met à jour observation et état classe 429 et Retry-After ne contourne jamais le cooldown ``` ### Refresh multiple/all Un refresh multiple : ```text évalue chaque provider indépendamment lance concurremment les providers éligibles ne bloque pas Coinbase parce que Jupiter est en cooldown ne dort pas pour attendre tous les providers non éligibles retourne un résultat générique par provider expose le prochain instant admissible pour les providers différés ``` La future UI peut donc désactiver/annoter un bouton à partir de l'état retourné sans connaître la règle provider. ## 14. HTTP commun et résilience Les adapters REST réutilisent les patterns sûrs déjà éprouvés dans KSP sans dépendre de `ksp-onchain-transport-lib`. Décisions V1 : ```text reqwest uniquement HTTPS officiel fixe lorsque le provider le supporte redirect désactivé proxy implicite désactivé selon le pattern KSP retenu connect timeout borné request timeout borné GET uniquement pour les prix V1 body réponse borné JSON attendu et validé 429 classé explicitement Retry-After honoré lorsqu'il est exploitable 5xx classé transitoire 401/403 classé auth/access URL retirée des erreurs reqwest avant contexte KSP aucun body remote brut dans KspError ``` Il n'existe pas d'URL provider arbitraire dans la Config V1. Cela évite SSRF, redirection de credential et confusion de provenance. ## 15. Config provider-capability-aware Config reste l'unique propriétaire des documents/env/secrets. Off-chain Transport expose ses settings publics ; Config adapte un futur document standard dédié, pressenti : ```text file_id = std.offchain_transport ``` Les branches de configuration correspondent aux capacités réelles de chaque provider. | Provider | Champs spécifiques V1 attendus | |-------------------|------------------------------------------------------------| | CoinGecko | enabled, access_mode keyless ou demo, api_key optionnelle | | CoinMarketCap | enabled, access_mode keyless ou basic, api_key optionnelle | | CoinPaprika | enabled | | Kraken | enabled | | Coinbase Exchange | enabled | | Jupiter | enabled, access_mode keyless ou free, api_key optionnelle | | Birdeye | enabled, api_key requise si activé | | DexScreener | enabled, sol_usd_pair_address requise si activé | Le schema final doit conditionner la présence des credentials au mode choisi. Aucun secret n'est versionné. Toute variable d'environnement ajoutée respecte `KSP_SECRET_*` et est inventoriée dans `.env.example`. Les limites provider ne deviennent pas des valeurs libres permettant à Config/UI d'augmenter la cadence. Une future policy pourra permettre un throttle **plus strict** si un besoin réel apparaît. ## 16. Ownership des erreurs et indisponibilités Une panne d'un provider ne doit pas rendre tous les autres inexploitables. Le service classe par provider : ```text configuration manquante/invalide DNS/connect/timeout TLS HTTP 4xx HTTP 429 HTTP 5xx JSON invalide ou schema drift asset/pair mismatch prix absent prix numérique invalide staleness provider si mesurable ``` Un refresh multiple retourne donc des outcomes partiels. Le service peut conserver un provider dans l'inventaire avec un état indisponible, au lieu de forcer l'application à connaître pourquoi Birdeye ou un autre provider manque. ## 17. Threat model V1 | Risque | Contrôle prévu | |------------------------------------------|-----------------------------------------------------------------| | fuite API key | Config propriétaire, header privé, redaction logs/debug/erreurs | | SSRF ou exfiltration vers URL configurée | origines provider fixes en V1, aucun endpoint arbitraire | | redirect credential | redirects HTTP désactivés | | proxy environnement implicite | policy no-proxy cohérente avec les clients KSP sensibles | | réponse JSON énorme | limite de taille avant désérialisation | | prix NaN, Inf, négatif ou overflow | parser décimal KSP borné | | faux asset par collision de symbole | IDs provider fixes et validations d'identité | | mauvaise paire DexScreener | pair address explicite et identité SOL vérifiée | | 429 répétés | limiter local, Retry-After, cooldown provider | | provider down | état provider séparé, autres providers continuent | | stale data | timestamps réels conservés, aucune fraîcheur inventée | | schema drift | DTOs wire privés stricts et erreur provider classée | | quota partagé hors processus | quota local non présenté comme authoritative | | différences de prix | sémantique/provenance visible, aucun consensus KSP V1 | | log d'une réponse sensible | aucun payload remote brut dans les erreurs/logs | ## 18. Tests et smokes attendus ### Tests déterministes Prévoir : ```text parsing décimal string/JSON number/scientifique limites et overflow mapping de chaque wire provider asset/pair mismatch prix null/absent HTTP status classification 429 et Retry-After rate limiter par policy cooldown états unavailable/auth/quota refresh single refresh all partiel un provider en échec n'empêche pas les autres redaction credential Config branches provider public API sans type wire provider ``` ### Smokes live opt-in Une tranche technique dédiée en fin de release doit tester les adapters réellement retenus avec un accès gratuit courant. Le smoke : ```text ne hardcode aucun secret n'affiche aucun secret interroge uniquement SOL/USD vérifie prix positif et parseable vérifie provider et identité attendue respecte chaque cadence ne compare pas à un prix exact figé n'échoue pas tout le batch parce qu'un provider externe est indisponible ``` Les providers keyed gratuits peuvent nécessiter des credentials opérateur via Config. Les smokes keyless restent séparables pour ne pas obliger à posséder toutes les clés au même instant. ## 19. Hors périmètre `0.2.11` ```text SOL/EUR autres fiat prix d'autres assets ou SPL tokens publics Price Desk Tauri modification Wallet Desk provider SDK WebSocket/SSE price streaming OHLCV/candles historique/backfill prix order books quotes/routing/swap metadata token/IPFS/Arweave consensus multi-provider moyenne/médiane KSP fallback automatique choix automatique de pool DexScreener cache durable nouvelle abstraction réseau universelle Pyth Binance sans SOL/USD direct retenu ``` Le fait que Jupiter/Birdeye/DexScreener soient capables de couvrir d'autres tokens ne les met pas dans la surface publique V1. ## 20. Forecast souple des prereleases Chaque tranche technique vise **environ 15 à 20 minutes de travail effectif** lorsque le sujet s'y prête. Cette durée est une cible de granularité et **pas une durée maximale** : un build lent, un live test, un diagnostic ou une difficulté réelle peut légitimement prolonger une tranche. Le forecast reste volontairement souple. Une tranche peut être scindée, fusionnée ou réordonnée par delta si la réalité technique l'exige, à condition de préserver les responsabilités de clôture. Le nombre de prereleases prévu n'impose ni une session de conversation par tranche, ni une scission de session : plusieurs prereleases peuvent être réalisées dans une même session de travail. Chaque entrée porte désormais un statut directement modifiable. Lorsqu'un fix d'une tranche est nécessaire, il peut être ajouté sous la prerelease concernée avec un titre `####`, sans transformer le forecast en tableau ni casser sa lisibilité. ### `pre.001` — Audit, sizing et cadrage multi-provider **Statut : réalisé.** Audit externe des providers, comparaison des sémantiques, réduction du scope V1 à SOL/USD, architecture HID de la future application, threat model, numeric design, sizing et planification. #### `pre.001-fix.001` — Forecast souple éditable **Statut : réalisé.** Remplacement du forecast tabulaire par des sous-sections éditables, clarification de la cible de 15 à 20 minutes et de l'absence de relation obligatoire entre prerelease et session de conversation. Aucun changement du scope technique de `0.2.11`. ### `pre.002` — Fondation de `ksp-offchain-transport-lib` **Statut : réalisé.** Création de la crate et de sa façade publique initiale : `PriceDecimal`, paire SOL/USD, observation/provenance/timestamps, identifiants/descriptors provider, capacités auth/rate-limit/quota, settings communs minimaux et états d'availability provider-neutral. Aucun HTTP, limiter actif, credential provider ou adapter wire n'est avancé depuis `pre.003+`. #### `pre.002-fix.001` — Rustdoc, Logging et taxonomie Off-chain **Statut : réalisé.** Correction des deux warnings `missing_docs` des tests d'intégration, ajout de `ksp-logging-lib` avec `src/constants.rs` et `TRACING_TARGET = "ksp-offchain-transport-lib"`, instrumentation KSP des validations/constructions comportementales, et renommage des modules actuels en `market_price_*` pour préparer les futures familles hétérogènes telles que `swap_quote_*` sans transformer la crate entière en module de prix. #### `pre.002-fix.002` — Conformité Clippy `implicit_return` **Statut : réalisé.** Correction du canari `dependency_boundary` pour respecter `-D clippy::implicit-return`, sans changement de contrat ni de comportement runtime. La version technique workspace devient `0.2.11-pre.2.fix.2`. ### `pre.003` — HTTP REST commun et rate limiting **Statut : planifié.** Client HTTP REST commun, classification d'erreurs, bornes de body et timeouts, redaction, limiter et cooldown génériques. ### `pre.004` — CoinGecko, CoinMarketCap et CoinPaprika **Statut : planifié.** Implémentation des trois adapters d'agrégateurs avec leurs DTOs wire privés et tests dédiés. ### `pre.005` — Kraken et Coinbase Exchange **Statut : planifié.** Implémentation des deux adapters exchange, conservation de leur sémantique de marché propre et tests dédiés. ### `pre.006` — Jupiter et DexScreener **Statut : planifié.** Implémentation des adapters Jupiter et DexScreener. DexScreener reste limité en V1 à la paire SOL/USD explicite configurée et validée. ### `pre.007` — Birdeye, registry et availability **Statut : planifié.** Implémentation de Birdeye avec son auth provider, finalisation du registry multi-provider et des états génériques d'indisponibilité. ### `pre.008` — Refresh individuel et multiple **Statut : planifié.** Service de refresh single/multiple, orchestration rate-limit-aware et tests cross-provider sans scheduling provider dans les consumers. ### `pre.009` — Config Off-chain Transport **Statut : planifié.** Document standard `std.offchain_transport`, schema, exemples, secrets d'environnement nécessaires et adapter Config -> Off-chain Transport conforme aux capacités de chaque provider. ### `pre.010` — Hardening et complétude technique **Statut : planifié.** Hardening de l'API publique, tests adversariaux/completeness et brouillons techniques README/USAGE sans réconciliation documentaire finale. ### `pre.011` — Gate technique et live final **Statut : planifié.** Smokes gratuits possibles, graphes Cargo, validations techniques finales et caractérisation actuelle des providers. ### `pre.012` — Réconciliation documentaire finale **Statut : planifié.** Réconciliation finale du plan, de la validation, des README/USAGE, de l'architecture et des références durables après les gates techniques. ### `pre.013` — Préparation minimale de publication **Statut : planifié.** Prompt `0.2.12`, `CHANGELOG.md`, `ROADMAP.md` et mécanique de version uniquement, sans reprendre les responsabilités techniques ou documentaires des deux tranches précédentes. ### `rel.001` — Publication stable `v0.2.11` **Statut : planifié.** Publication stable après validation de la dernière prerelease et vérification de la cohérence de release. Les responsabilités de clôture restent strictement séparées : ```text pre.011 = technique/live pre.012 = documentation finale pre.013 = prompt suivant + CHANGELOG + ROADMAP seulement ``` ## 21. Gate de sizing `pre.001` Verdict : **GO sans split de release**. Justification : ```text huit adapters REST sont petits et indépendants aucun SDK provider n'est nécessaire les primitives HTTP/serde/tokio sont déjà au workspace la seule paire publique est SOL/USD le contrat commun reste volontairement petit la complexité réelle est isolée dans registry/rate limiting/availability les adapters peuvent être livrés par groupes de prereleases courtes ``` `0.2.11` reste toutefois une release multi-provider et ne doit pas compresser artificiellement les gates de sécurité/live.