37 KiB
Plan 0.2.11 — Off-chain price transport SOL/USD multi-provider
Statut courant : 0.2.11-pre.004-fix.001 corrige le gate statique/Clippy et la fixture CoinMarketCap V2 de pre.004; pre.004 active les primitives http_* en production et implémente les trois premiers adapters market_price_* — CoinGecko, CoinMarketCap et CoinPaprika — en SOL/USD uniquement, sans SDK provider. Le staging cfg(test) de pre.003-fix.001 disparaît donc structurellement avec leurs premiers consumers de production. CoinMarketCap utilise la surface Simple Price V2 actuelle ; la surface V1 deprecated n'est pas introduite.
1. Base et autorité
Base stable autoritaire :
v0.2.10
État vérifié dans l'archive Gitea fournie :
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 :
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 :
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.
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 :
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 :
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 :
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
<future_capability>_* 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 même frontière s'applique à la façade publique. À partir de pre.002-fix.003, tout symbole public spécifique à cette famille porte un nom explicitement MarketPrice* ou MARKET_PRICE_* : MarketPriceDecimal, MarketPriceObservation, MarketPriceProviderId, MarketPriceProviderDescriptor, MarketPriceProviderRateLimit, etc. Aucun alias public Price* n'est conservé pendant cette prerelease, car il figerait précisément l'ambiguïté que le correctif supprime. Une future famille swap_quote_* devra employer son propre préfixe public SwapQuote*; une abstraction sans préfixe de famille ne pourra être créée que lorsqu'un invariant réellement partagé aura été démontré.
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 :
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 :
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 :
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 :
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 :
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 :
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/documentation/pro-api-reference/cryptocurrency/simple-price-v2
https://coinmarketcap.com/api/documentation/pro-api-reference/cryptocurrency/simple-price-v1
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.
Réaudit pre.004 : CoinMarketCap Simple Price est implémenté sur la surface V2 actuelle. La surface Simple Price V1 est documentée comme deprecated et n'est pas utilisée par KSP. Les deux modes V1 retenus restent distincts : endpoint public keyless V2 sans credential, ou endpoint Pro V2 Basic avec X-CMC_PRO_API_KEY.
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 :
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 :
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 :
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 :
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 :
SOL/USD
Les identifiants propriétaires restent privés aux adapters ou aux settings provider :
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 :
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 :
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 : MarketPriceDecimal est le type décimal KSP borné, sérialisable sans perte et construit depuis la représentation textuelle du provider.
Contrat V1 exact :
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.
MarketPriceDecimal 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 :
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 MarketPriceObservation, MarketPriceTimestamp (millisecondes UTC depuis Unix epoch) et MarketPriceProvenance 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 :
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 :
capabilities statiques auditées
état runtime courant
Le descriptor statique peut exposer :
provider id opaque
nom d'affichage
sémantique
mode d'auth générique
limitation générique
support SOL/USD
pre.002 fixe MarketPriceProviderId, MarketPriceProviderDescriptor, MarketPriceProviderAuthMode, MarketPriceProviderRateLimit, MarketPriceProviderLongTermQuota 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 :
ready
cooling down avec prochain instant admissible
temporarily unavailable
authentication unavailable
quota unavailable
misconfigured
disabled
MarketPriceProviderAvailability et MarketPriceProviderState 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 :
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) :
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 :
é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 :
reqwest uniquement
HTTPS officiel fixe dans les adapters V1
redirect désactivé
Referer automatique désactivé
proxy système/implicite désactivé
retries implicites reqwest désactivés
connect timeout borné : défaut 5 s, hard max 30 s
request timeout borné : défaut 10 s, hard max 120 s
GET uniquement pour les prix V1
body réponse borné avant désérialisation : défaut 1 MiB, hard max 4 MiB
JSON syntaxiquement validé avant remise à l'adapter typed
429 classé explicitement
Retry-After delta-seconds honoré et borné à 1 h lorsqu'il est exploitable
408 et 5xx classés transitoires
401/403 classés 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.
Les primitives http_* sont crate-private : elles ne créent pas un client HTTP générique public contournant les capacités métier. Les adapters market_price_*, puis de futures familles telles que swap_quote_*, les consomment derrière leur propre contrat.
Le limiter pre.003 est non bloquant. Une cadence fixe est matérialisée par un token bucket lissé ; lorsqu'aucun burst n'est documenté, la capacité locale initiale reste volontairement 1. Lorsqu'un burst est documenté, sa capacité est indépendante du nombre moyen de requêtes de la fenêtre et peut donc lui être supérieure. Une limite dynamique n'invente aucune cadence locale et apprend seulement des réponses provider, notamment 429. Un Retry-After serveur peut prolonger le cooldown mais ne peut pas dépasser une borne défensive d'une heure. Aucune primitive HTTP commune ne dort en attendant la disponibilité : elle expose un délai de defer que l'orchestrateur pre.008 pourra projeter provider par provider.
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 :
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 :
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 :
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 :
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
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 : MarketPriceDecimal, 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.002-fix.003 — Nommage public MarketPrice*
Statut : réalisé.
Préfixage de toute la surface publique spécifique à la famille market_price en MarketPrice* / MARKET_PRICE_*, y compris observation, décimal, timestamps, provenance, provider settings/descriptors/limits/availability et codes d'erreur. Aucun alias Price* n'est conservé : le correctif évite de devoir renommer ces API lorsque d'autres familles telles que swap_quote_* seront ajoutées. La version technique workspace devient 0.2.11-pre.2.fix.3.
pre.003 — HTTP REST commun et rate limiting
Statut : réalisé avec correctif.
Client HTTP REST commun crate-private, classification d'erreurs HTTP/reqwest, bornes de body et timeouts, redaction, désactivation explicite des redirects/proxy/retries implicites, JSON syntaxiquement validé, limiter token-bucket générique non bloquant et cooldown provider-driven borné. Aucun adapter provider n'est avancé.
pre.003-fix.001 — Façade crate-root, staging et burst documenté
Statut : réalisé ; gate Cargo/Clippy/tests PASS, RUST-FMT-108 structurel repris par pre.004.
Correction de l'ordre alphabétique des constantes d'erreur, utilisation systématique de la façade crate-root pour les items http_* partagés (impl crate::... et signatures crate-wide), suppression des #[allow(dead_code)] préparatoires au profit de #[cfg(test)] conformément à RUST-API-008, et correction du contrat de burst : un burst documenté peut dépasser la cadence moyenne de la fenêtre, comme le cas Coinbase 10 req/s, burst 15. La version technique workspace devient 0.2.11-pre.3.fix.1.
pre.004 — CoinGecko, CoinMarketCap et CoinPaprika
Statut : réalisé, gate Cargo opérateur à exécuter.
Activation en production du socle http_* et implémentation des trois adapters d'agrégateurs avec DTOs wire privés, parsing décimal exact via RawValue, timestamps provider lorsque fournis, endpoints officiels fixes, auth correspondant aux capacités réelles et limites provider décrites dans leurs descriptors. CoinGecko supporte keyless ou Demo key, CoinMarketCap keyless ou Basic key sur Simple Price V2, CoinPaprika reste keyless. Aucun registry global, Config ou smoke live n'est avancé.
pre.004-fix.001 — Ordre des constantes, Clippy et fixture CoinMarketCap V2
Statut : réalisé, gate Cargo opérateur à rejouer.
Correctif strict de pre.004 : tri alphabétique complet des constantes d'erreur, suppression des deux warnings clippy::collapsible_if dans les builders CoinGecko/CoinMarketCap, et correction de la fixture CoinMarketCap V2 dont le JSON concaténé omettait le guillemet ouvrant de last_updated. Aucun contrat provider, endpoint, parsing runtime, rate limit ou scope de release n'est modifié. La version technique workspace devient 0.2.11-pre.4.fix.1.
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 :
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 :
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.