v0.2.11-pre.001

This commit is contained in:
2026-08-25 17:50:08 +02:00
parent afaa9c0239
commit a8e980b225
13 changed files with 1216 additions and 31 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/000-README.md -->
<!-- version: 61 -->
<!-- version: 62 -->
# Plans KSP
@@ -25,7 +25,8 @@ Un plan décrit le périmètre, les décisions déjà acquises, les questions ou
- [`014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md`](014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md) — plan historique clôturé de la release stable `0.2.7 — WebSocket Solana standard`, ouvert par `pre.001`, exécuté jusquà `pre.014`, corrigé documentairement par `pre.014-fix.001` puis publié par `rel.001`; il conserve linventaire officiel 18 méthodes, le modèle session/subscription, le threat model, les preuves de compliance/smoke/dépendances et la préparation de `0.2.8`.
- [`015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md`](015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md) — plan historique clôturé de la release stable `0.2.8 — Helius LaserStream WebSocket`, ouvert par `pre.001`, fermé techniquement/documentairement par `pre.011` puis publié par `rel.001`; il conserve la surface finale Helius `7 standard + transaction`, heartbeat/Config/secrets, lhistorique des fixes heartbeat, la stratégie live architecture-safe, les graphes Cargo finaux et la préparation du prompt `0.2.9`.
- [`016-V0_2_9_YELLOWSTONE_GRPC_PLAN.md`](016-V0_2_9_YELLOWSTONE_GRPC_PLAN.md) — plan historique clôturé de la release stable `0.2.9 — Yellowstone gRPC standard/provider-neutral`, publiée par `rel.001`; il fixe le moteur N1, le standard N2, Config V3, le replay prudent et la validation PublicNode Mainnet/Testnet.
- [`017-V0_2_10_ORBITFLARE_YELLOWSTONE_GRPC_PLAN.md`](017-V0_2_10_ORBITFLARE_YELLOWSTONE_GRPC_PLAN.md) — plan actif de `0.2.10 — OrbitFlare Yellowstone gRPC`, ouvert par `pre.001`; il confirme le Devnet gRPC gratuit, rend N1/N2 immuables pour la release, classe auth/heartbeat/limits et dimensionne un chemin standard prioritaire sans code provider inutile.
- [`017-V0_2_10_ORBITFLARE_YELLOWSTONE_GRPC_PLAN.md`](017-V0_2_10_ORBITFLARE_YELLOWSTONE_GRPC_PLAN.md) — plan historique clôturé de la release stable `0.2.10 — OrbitFlare Yellowstone gRPC`; il conserve le Devnet gRPC gratuit, N1/N2 immuables, la License Key `x-token` et le smoke final `Slot + Ping`.
- [`018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md`](018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md) — plan actif de `0.2.11 — Off-chain price transport`, ouvert par `pre.001`; il fixe SOL/USD V1, huit providers REST gratuits sans SDK, le modèle provider/rate-limit/availability, la Config capability-aware et la frontière HID de `ksp-app-solprices-desk`.
Le `pre.001` de chaque release fonctionnelle peut introduire son propre plan détaillé lorsque la release s'ouvre.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md -->
<!-- version: 89 -->
<!-- version: 90 -->
# Séquence des releases fonctionnelles KSP
@@ -508,13 +508,13 @@ Helius LaserStream gRPC est explicitement reporté : l'audit 2026-08-25 indique
Ces providers ne déplacent pas la séquence active et ne reçoivent ni façade, ni Config profile, ni smoke tant qu'une décision explicite d'implémentation n'est pas prise.
### `0.2.11` / `0.2.12` — Off-chain price + app
### `0.2.11` / `0.2.12` — Off-chain price + SOL Prices Desk
`0.2.11` introduit `ksp-offchain-transport-lib` avec au minimum SOL/USD et SOL/EUR via une abstraction indépendante du premier provider.
`0.2.11` introduit `ksp-offchain-transport-lib` avec une première surface volontairement limitée à SOL/USD. Le gate `pre.001` retient plusieurs providers gratuits accessibles en HTTP REST simple ; leurs adapters utilisent uniquement `reqwest` et des DTOs KSP privés, sans SDK provider. Off-chain Transport possède le registry provider, les capacités/rate limits, les indisponibilités et les refresh individuels/multiples ; aucun consensus ou fallback automatique multi-provider n'est introduit.
`0.2.12` ajoute une petite application desk de visualisation/validation. Après stabilisation de cette application spécialisée, la même release doit intégrer la capacité de prix offchain dans `ksp-app-wallet-desk` sans dupliquer la récupération/normalisation appartenant au composant spécialisé.
`0.2.12` ajoute `ksp-app-solprices-desk`, HID pure qui ne connaît aucun provider et consomme uniquement les descriptors, observations, états et opérations génériques de `ksp-offchain-transport-lib`. Sa première vue liste les providers/prix et permet refresh individuel/multiple en laissant entièrement les limitations au service. Après stabilisation de cette application spécialisée, la même release doit intégrer la capacité de prix offchain dans `ksp-app-wallet-desk` sans dupliquer la récupération/normalisation appartenant au composant spécialisé.
Metadata HTTP/IPFS/Arweave viendra au premier besoin Metadata réel.
Metadata HTTP/IPFS/Arweave viendra au premier besoin Metadata réel. SOL/EUR et les autres quotes restent une extension ultérieure explicite, sans conversion fiat cachée.
### `0.2.13` — Interface foundation

View File

@@ -0,0 +1,642 @@
<!-- file: docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md -->
<!-- version: 1 -->
# Plan `0.2.11` — Off-chain price transport SOL/USD multi-provider
**Statut courant : `0.2.11-pre.001` ouvre la release par le gate obligatoire de lecture, réaudit externe, comparaison des sémantiques de prix, threat model, sizing et planification. Aucun client provider n'est encore implémenté. Le scope V1 est volontairement limité à SOL/USD via HTTP REST `reqwest`, sans SDK provider, avec huit providers gratuits retenus pour implémentation progressive.**
## 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
```
## 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.
Direction retenue pour `pre.002` : type décimal KSP borné, sérialisable sans perte, construit depuis la représentation textuelle du provider.
Forme de travail :
```text
coefficient positif u128
scale bornée
normalisation des zéros terminaux
parsing décimal et notation scientifique bornés
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.
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
```
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
```
L'état runtime peut représenter au minimum :
```text
ready
cooling down avec prochain instant admissible
temporarily unavailable
authentication unavailable
quota unavailable
misconfigured
disabled
```
Les noms Rust finaux sont à fixer avec le code, mais 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, hors build lent ou attente provider. Le découpage pourra être réorganisé par delta si la réalité l'exige.
| Prerelease | Objectif principal |
|------------|----------------------------------------------------------------------------------------------------------------|
| `pre.001` | audit externe, sémantiques, scope SOL/USD, architecture HID, threat model, numeric design, sizing et plan |
| `pre.002` | création crate, modèle SOL/USD, décimal KSP, descriptors/settings/états provider-neutral |
| `pre.003` | client HTTP REST commun, classification d'erreurs, body/timeouts/redaction, limiter/cooldown générique |
| `pre.004` | adapters CoinGecko, CoinMarketCap et CoinPaprika avec tests wire |
| `pre.005` | adapters Kraken et Coinbase Exchange avec sémantique exchange et tests |
| `pre.006` | adapters Jupiter et DexScreener, pair SOL/USD DexScreener explicite et validée |
| `pre.007` | adapter Birdeye, auth provider, registry complet et états d'indisponibilité |
| `pre.008` | service refresh single/multiple, orchestration rate-limit-aware et tests cross-provider |
| `pre.009` | document Config `std.offchain_transport`, schema/examples/env secrets et adapter Config -> Off-chain Transport |
| `pre.010` | hardening public API, tests adversariaux/completeness, README/USAGE draft technique sans réconciliation finale |
| `pre.011` | gate technique/live final, smokes gratuits possibles, graphes Cargo et caractérisation finale des providers |
| `pre.012` | réconciliation documentaire finale plan/validation/README/USAGE/architecture et références durables |
| `pre.013` | préparation publication minimale : prompt `0.2.12`, CHANGELOG, ROADMAP et version mécanique |
| `rel.001` | publication stable `v0.2.11` |
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.