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,12 +1,12 @@
# file: Cargo.toml # file: Cargo.toml
# version: 268 # version: 269
[workspace] [workspace]
resolver = "3" resolver = "3"
members = ["crates/ksp-app-config-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-logging-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-wallet-lib"] members = ["crates/ksp-app-config-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-logging-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-wallet-lib"]
[workspace.package] [workspace.package]
version = "0.2.10" version = "0.2.11-pre.1"
edition = "2024" edition = "2024"
license = "MIT" license = "MIT"
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"

View File

@@ -1,5 +1,5 @@
<!-- file: ROADMAP.md --> <!-- file: ROADMAP.md -->
<!-- version: 87 --> <!-- version: 88 -->
# Roadmap KSP # Roadmap KSP
@@ -55,8 +55,8 @@ Le roadmap décrit les objectifs à atteindre et les grandes étapes prévues. U
- [X] `0.2.8` — Helius LaserStream WebSocket stable : façade provider dédiée sur lactor WebSocket partagé, sept familles standard réutilisées (`account/logs/program/root/signature/slot/slotsUpdates`) + `transactionSubscribe`/`transactionUnsubscribe`, `block/vote` absents, heartbeat Ping 60 s Helius-only, Config V2/secrets redacted, lifecycle adversarial, compliance HTTP 52+14 / Standard WS 18/18 et graphes Cargo finaux validés ; prompt `0.2.9` prêt. - [X] `0.2.8` — Helius LaserStream WebSocket stable : façade provider dédiée sur lactor WebSocket partagé, sept familles standard réutilisées (`account/logs/program/root/signature/slot/slotsUpdates`) + `transactionSubscribe`/`transactionUnsubscribe`, `block/vote` absents, heartbeat Ping 60 s Helius-only, Config V2/secrets redacted, lifecycle adversarial, compliance HTTP 52+14 / Standard WS 18/18 et graphes Cargo finaux validés ; prompt `0.2.9` prêt.
- [X] `0.2.9` — Yellowstone gRPC standard/provider-neutral stable : moteur Tonic/Protobuf KSP partagé, sept unary standard retenues, `Subscribe` bidi et neuf variantes dupdate, lifecycle/backpressure/reconnect/replay bornés sans promesse lossless, Config Transport V3 backward V1/V2 avec provider/protocol séparés, profils PublicNode Mainnet/Testnet authentifiés par `x-token`, smoke live `Subscribe -> Slot` 2/2 PASS et graphes Cargo finaux inspectés ; `SubscribeDeshred` reste hors scope. - [X] `0.2.9` — Yellowstone gRPC standard/provider-neutral stable : moteur Tonic/Protobuf KSP partagé, sept unary standard retenues, `Subscribe` bidi et neuf variantes dupdate, lifecycle/backpressure/reconnect/replay bornés sans promesse lossless, Config Transport V3 backward V1/V2 avec provider/protocol séparés, profils PublicNode Mainnet/Testnet authentifiés par `x-token`, smoke live `Subscribe -> Slot` 2/2 PASS et graphes Cargo finaux inspectés ; `SubscribeDeshred` reste hors scope.
- [X] `0.2.10` — OrbitFlare Yellowstone gRPC stable : profil Config V3 Devnet, License Key injectée comme metadata secrète `x-token`, smoke live `Subscribe -> Slot + Ping` validé deux fois, sans modification du moteur N1/N2 ni heartbeat provider. - [X] `0.2.10` — OrbitFlare Yellowstone gRPC stable : profil Config V3 Devnet, License Key injectée comme metadata secrète `x-token`, smoke live `Subscribe -> Slot + Ping` validé deux fois, sans modification du moteur N1/N2 ni heartbeat provider.
- [ ] `0.2.11` — Introduire `ksp-offchain-transport-lib` avec un premier lecteur de prix provider-neutral, au minimum SOL/USD et SOL/EUR, après audit actuel des sémantiques provider et de la testabilité live. - [ ] `0.2.11` — Introduire `ksp-offchain-transport-lib` avec SOL/USD multi-provider via HTTP REST `reqwest` sans SDK provider ; la crate possède adapters, capacités/rate limits, disponibilité et refresh génériques, sans consensus/fallback automatique.
- [ ] `0.2.12` — Introduire une petite application desk de visualisation/validation des prix offchain, puis intégrer cette capacité dans `ksp-app-wallet-desk` sans dupliquer la logique de récupération/normalisation possédée par le composant spécialisé. - [ ] `0.2.12` — Introduire `ksp-app-solprices-desk` comme HID provider-agnostic consommant uniquement `ksp-offchain-transport-lib`, avec tableau prix/provider et refresh individuel/multiple ; puis intégrer cette capacité dans `ksp-app-wallet-desk` sans dupliquer la logique de récupération/normalisation.
- [ ] `0.2.13` — Introduire la première surface de `ksp-interface-lib`, comprenant une API wire publique utilisable par les implémentations officielles et externes. - [ ] `0.2.13` — Introduire la première surface de `ksp-interface-lib`, comprenant une API wire publique utilisable par les implémentations officielles et externes.
- [ ] `0.2.14` — Introduire `ksp-program-api` comme premier contrat Program extensible, sans imposer encore `ksp-program-lib` complet. - [ ] `0.2.14` — Introduire `ksp-program-api` comme premier contrat Program extensible, sans imposer encore `ksp-program-lib` complet.

311
deltas/0.2.11/pre.001.md Normal file
View File

@@ -0,0 +1,311 @@
<!-- file: deltas/0.2.11/pre.001.md -->
<!-- version: 1 -->
# Delta `0.2.11-pre.001` — audit/sizing Off-chain price SOL/USD multi-provider
## 1. Base requise et vérifiée
Archive autoritaire fournie :
```text
khadhroony-solana-project-v0.2.10-full-from-gitea.zip
```
État vérifié :
```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 livraison ouvre :
```text
workspace.package.version = 0.2.11-pre.1
commit attendu = v0.2.11-pre.001
aucun tag prerelease
```
## 2. Objet
`pre.001` exécute exclusivement le gate de cadrage obligatoire :
```text
lecture base/règles/architecture
inventaire primitives HTTP existantes
réaudit actuel des providers de prix
comparaison des sémantiques
scope SOL/USD
choix multi-provider gratuit
absence de SDK provider
numeric safety
provider registry et availability
rate limiting et refresh multiple
Config provider-capability-aware
cas DexScreener SOL/USD
frontière future ksp-app-solprices-desk
threat model
sizing et forecast
```
Aucun client provider, crate Off-chain Transport, Config runtime ou secret n'est ajouté dans cette tranche.
## 3. Décisions opérateur supersédant le prompt préparatoire
Le prompt `016` préparait SOL/USD + SOL/EUR et laissait le provider initial ouvert. Le brainstorming d'ouverture fixe désormais :
```text
V1 = SOL/USD uniquement
0.2.11 peut et doit implémenter plusieurs providers gratuits
HTTP REST via reqwest uniquement
aucun SDK provider
SOL/EUR reporté
aucun consensus/fallback automatique
future app = ksp-app-solprices-desk
future app = HID pure sans connaissance provider
Off-chain Transport possède limits/exceptions/availability
DexScreener V1 = paire SOL/USD explicite uniquement
```
Ces décisions sont répercutées dans le plan, la validation, l'architecture durable, la séquence fonctionnelle et le ROADMAP global d'ouverture.
## 4. Providers retenus
Audit officiel du 2026-08-25 :
| Provider | Gratuit V1 | Auth possible V1 | Contrainte principale | Verdict |
|-------------------|------------|----------------------|---------------------------------------------|---------|
| CoinGecko | Oui | keyless ou Demo key | dynamic IP ou Demo 100/min et 10k/mois | IN |
| CoinMarketCap | Oui | keyless ou Basic key | dynamic IP ou Basic 50/min et 15k/mois | IN |
| CoinPaprika | Oui | aucune | 10/s IP, 20k/mois, refresh Free moyen 5 min | IN |
| Kraken | Oui | aucune | 1/s ou moins recommandé sur public REST | IN |
| Coinbase Exchange | Oui | aucune | 10/s IP, burst 15 | IN |
| Jupiter Price V3 | Oui | keyless ou Free key | 0.5 RPS keyless, 1 RPS Free | IN |
| Birdeye | Oui | API key | Standard 1 RPS, 30k CU, Price Single 3 CU | IN |
| DexScreener | Oui | aucune | 300/min endpoints pair/token | IN |
Pyth est écarté de V1 à cause de la transition d'accès imminente et de l'absence de gratuité durable confirmée après trial. Binance est écarté tant que KSP n'a pas retenu un vrai marché SOL/USD ; SOL/USDT n'est pas assimilé à SOL/USD.
## 5. Sémantique et numérique
Décisions :
```text
une observation conserve provider + sémantique + timestamps KSP
provider update timestamp reste optionnel
aucune fraîcheur provider inventée
f64 n'est pas le canon public
prix canonique = décimal KSP borné sans nouvelle crate decimal
wire JSON number/string -> parser textuel sûr
zéro/négatif/overflow/forme invalide rejetés
```
Les classes de sémantique distingueront notamment agrégateur, exchange last trade, heuristique Solana, spot Solana et paire DEX.
## 6. Registry, availability et refresh
`ksp-offchain-transport-lib` sera propriétaire de :
```text
inventory/registry provider
descriptors/capabilities
adapters/wires privés
rate limits/cooldowns
classification 401/403/429/5xx/transport/schema
état provider ready/unavailable/misconfigured/quota/auth
refresh provider générique
refresh multiple/all générique
```
Un refresh multiple lance les providers actuellement éligibles sans attendre ceux en cooldown et retourne un outcome par provider. La future UI ne contient aucune logique de scheduling.
## 7. DexScreener V1
Décision :
```text
pair address Solana configurée
endpoint pair direct
chain et identité SOL validées
lecture de priceUsd uniquement pour le contrat commun
aucune découverte/selection automatique de pool
aucun tri liquidité
aucun consensus entre pools
```
Cette policy pourra être changée dans une release ultérieure sans exposer DexScreener à l'application.
## 8. Config et sécurité
Config reste propriétaire des fichiers/env/secrets et adaptera un document standard Off-chain Transport futur.
Les branches seront provider-capability-aware :
```text
providers keyless sans faux credential obligatoire
modes keyless/keyed représentés quand les deux existent
Birdeye credential obligatoire si activé
DexScreener pair address obligatoire si activé
origines HTTP provider fixes en V1
aucun base_url arbitraire
aucune limite provider librement augmentable par Config/UI
```
Le threat model couvre credential exfiltration, SSRF, redirects, proxy implicite, body non borné, numeric abuse, wrong pair, stale data, rate limit, provider outage et schema drift.
## 9. Future `ksp-app-solprices-desk`
Architecture fixée pour `0.2.12` :
```text
HID pure
aucune connaissance provider
aucune requête HTTP provider
aucun rate limit provider côté UI
liste issue du registry générique
prix/état/cooldown issus du service générique
refresh row générique
refresh multiple générique
```
`0.2.11` ne crée pas l'application.
## 10. Forecast
Chemin souple retenu :
```text
pre.001 audit/sizing
pre.002 crate + contrats + décimal
pre.003 HTTP commun + errors + rate limiter
pre.004 CoinGecko + CMC + CoinPaprika
pre.005 Kraken + Coinbase
pre.006 Jupiter + DexScreener
pre.007 Birdeye + registry availability
pre.008 refresh single/multiple cross-provider
pre.009 Config std.offchain_transport
pre.010 hardening/API/tests + docs techniques draft
pre.011 gate technique/live final
pre.012 réconciliation documentaire finale
pre.013 publication minimale prompt 0.2.12 + CHANGELOG + ROADMAP
rel.001 stable
```
## 11. Fichiers ajoutés
```text
docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md
docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md
deltas/0.2.11/pre.001.md
```
## 12. Fichiers modifiés
```text
Cargo.toml
ROADMAP.md
docs/000-README.md
docs/architecture/002-LAYERS_AND_DEPENDENCIES.md
docs/architecture/003-COMPONENT_CONTRACTS.md
docs/architecture/004-COMPONENT_INVENTORY.md
docs/architecture/005-DEPENDENCY_GRAPH.md
docs/plans/000-README.md
docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md
docs/validation/000-README.md
```
## 13. Fichiers supprimés
```text
aucun
```
## 14. Fichiers volontairement inchangés
```text
CHANGELOG.md
prompts/016-V0_2_11_START_PROMPT.md
.env.example
config/**
crates/**
README/USAGE de crates existantes
```
Le prompt d'ouverture reste historique ; les supersessions sont portées par le plan/delta de la release active.
## 15. Sources externes réauditées
```text
CoinGecko keyless/simple-price/pricing
CoinMarketCap keyless/simple-price/pricing
CoinPaprika REST/ticker/plans
Kraken public market REST/rate limits
Coinbase Exchange ticker/rate limits
Jupiter Developer Platform/Price V3
Birdeye pricing/rate limiting/Price Single
DexScreener API reference
Pyth Core transition pour décision OUT V1
```
Les URLs détaillées sont conservées dans le plan 018.
Le gate distingue désormais explicitement accès gratuit technique et conditions d'usage : CoinGecko/CMC keyless sont orientés évaluation/prototypage selon leurs documents actuels et CoinPaprika Free est annoncé pour usage personnel. Ces points n'empêchent pas l'implémentation V1 mais seront réaudités avant la stable ; KSP ne promet aucune gratuité commerciale durable.
## 16. Validations exécutées dans le sandbox
```text
inspection archive/version/rel/prompt PASS
inspection absence metadata .git PASS
inspection absence ksp-offchain-transport-lib PASS
inventaire workspace dependencies PASS
python3 scripts/audit_rust_workspace_rules.py PASS / clean / 0 candidate export
audit Markdown ciblé des 12 fichiers touchés PASS / 16 tables
audit Markdown scope session complet PASS / 115 tables / 100 files
```
Le sandbox ne fournit ni `cargo` ni `rustc`. Aucun `cargo fmt/check/clippy/test` n'est donc déclaré exécuté localement. Aucun smoke provider live KSP n'est déclaré PASS dans `pre.001` puisque la crate n'existe pas encore.
## 17. Validations non exécutées dans `pre.001`
```text
cargo fmt --all non exécuté, Cargo absent du sandbox
cargo check --workspace non exécuté, Cargo absent du sandbox
cargo clippy --workspace --all-targets non exécuté, Cargo absent du sandbox
cargo test --workspace non exécuté, Cargo absent du sandbox
aucun test adapter provider code absent
aucun smoke live provider KSP code absent
aucun test Config Off-chain document absent
aucun build ksp-app-solprices-desk application hors scope
```
## 18. Validation opérateur attendue avant commit
```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 --workspace
```
Aucun smoke réseau provider n'est attendu pour cette tranche documentaire de cadrage.
## 19. Questions ouvertes
Les questions fonctionnelles majeures sont closes pour démarrer l'implémentation. Restent à fixer au niveau du code dans les prereleases prévues :
```text
noms Rust exacts des descriptors/outcomes/status
bornes exactes coefficient/scale du décimal KSP
body limit et timeouts par défaut
forme exacte du rate limiter générique
noms des variables KSP_SECRET provider keyed
pair address DexScreener opérateur à configurer et live-valider
endpoint/version CMC exact à figer après canari live courant
```
Ces points ne remettent pas en cause le gate de sizing.

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/002-LAYERS_AND_DEPENDENCIES.md --> <!-- file: docs/architecture/002-LAYERS_AND_DEPENDENCIES.md -->
<!-- version: 6 --> <!-- version: 7 -->
# Couches et dépendances KSP # Couches et dépendances KSP
@@ -134,7 +134,7 @@ Les applications Tauri restent minces :
- instrumentation frontend ; - instrumentation frontend ;
- aucun déplacement de logique de transport, Wallet, Config, Program, Store ou Materializer dans Tauri. - aucun déplacement de logique de transport, Wallet, Config, Program, Store ou Materializer dans Tauri.
Des applications spécialisées sont ajoutées au fur et à mesure pour valider les couches : Config Desk, Wallet Desk, Price Desk, backfill/RAW tooling, CORE tooling puis Market Desk. Des applications spécialisées sont ajoutées au fur et à mesure pour valider les couches : Config Desk, Wallet Desk, `ksp-app-solprices-desk`, backfill/RAW tooling, CORE tooling puis Market Desk. `ksp-app-solprices-desk` reste une HID mince : elle consomme linventaire, les observations, les états et les opérations génériques de `ksp-offchain-transport-lib` sans connaître les providers, leurs endpoints, leurs credentials ni leurs limites.
## Workers et jobs ## Workers et jobs

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/003-COMPONENT_CONTRACTS.md --> <!-- file: docs/architecture/003-COMPONENT_CONTRACTS.md -->
<!-- version: 7 --> <!-- version: 8 -->
# Contrats initiaux des composants KSP # Contrats initiaux des composants KSP
@@ -72,7 +72,13 @@ La complétude vaut aussi à l'intérieur de chaque opération : paramètres, op
Aucune `ksp-offchain-transport-api` commune n'est prévue. Aucune `ksp-offchain-transport-api` commune n'est prévue.
`ksp-offchain-transport-lib` peut contenir plusieurs modules/APIs distincts : prix, metadata HTTP/IPFS/Arweave, quotes et autres accès externes. La première surface engagée est le prix SOL/USD et SOL/EUR. `ksp-offchain-transport-lib` peut contenir plusieurs modules/APIs distincts : prix, metadata HTTP/IPFS/Arweave, quotes et autres accès externes. La première surface engagée par `0.2.11` est exclusivement le prix SOL/USD.
Pour cette surface, Off-chain Transport possède le registry runtime des providers, leurs adapters/wires privés, leurs capacités et contraintes de refresh, la classification des indisponibilités et l'orchestration de refresh individuel/multiple. Plusieurs providers peuvent produire la même paire sans que KSP invente un consensus, une moyenne ou un fallback automatique.
Les adapters provider V1 utilisent uniquement `reqwest` et les primitives génériques du workspace ; aucun SDK provider n'est introduit. Config peut adapter ses documents vers les settings publics provider-capability-aware, mais Off-chain Transport ne lit jamais directement l'environnement ou les fichiers Config.
La future `ksp-app-solprices-desk` est une HID provider-agnostic : elle liste et déclenche uniquement les surfaces génériques de la crate. Toute connaissance de CoinGecko, CoinMarketCap, CoinPaprika, Kraken, Coinbase, Jupiter, Birdeye ou DexScreener reste sous Off-chain Transport/Config.
## Wallet ## Wallet

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/004-COMPONENT_INVENTORY.md --> <!-- file: docs/architecture/004-COMPONENT_INVENTORY.md -->
<!-- version: 21 --> <!-- version: 22 -->
# Inventaire initial des composants KSP # Inventaire initial des composants KSP
@@ -29,11 +29,11 @@ Ce document maintient l'inventaire synthétique des composants retenus ou presse
| Wallet V2 | `ksp-wallet-lib` | lib | Stable | `0.2.6` | wire/runtime V2 + API default/versionnée + migration explicite | | Wallet V2 | `ksp-wallet-lib` | lib | Stable | `0.2.6` | wire/runtime V2 + API default/versionnée + migration explicite |
| Standard WS | `ksp-onchain-transport-lib` | lib | Stable | `0.2.7` | WebSocket Solana 18/18, sessions/subscriptions bornées | | Standard WS | `ksp-onchain-transport-lib` | lib | Stable | `0.2.7` | WebSocket Solana 18/18, sessions/subscriptions bornées |
| Helius WS | `ksp-onchain-transport-lib` | lib | Stable | `0.2.8` | LaserStream WS : 7 standard + transaction, actor partagé | | Helius WS | `ksp-onchain-transport-lib` | lib | Stable | `0.2.8` | LaserStream WS : 7 standard + transaction, actor partagé |
| Yellowstone | `ksp-onchain-transport-lib` | lib | Pressenti | `0.2.9` | client gRPC standard/provider-neutral | | Yellowstone | `ksp-onchain-transport-lib` | lib | Stable | `0.2.9` | client gRPC standard/provider-neutral |
| Off-chain price | `ksp-offchain-transport-lib` | lib | Retenu | `0.2.10` | première abstraction/provider de prix SOL/USD, SOL/EUR | | Off-chain price | `ksp-offchain-transport-lib` | lib | Actif | `0.2.11` | prix SOL/USD multi-provider, limits et availability |
| Price Desk | nom à fixer | app | Retenu | `0.2.11` | visualisation/validation des prix + intégration Wallet Desk | | SOL Prices Desk | `ksp-app-solprices-desk` | app | Retenu | `0.2.12` | HID provider-agnostic pour visualisation/refresh prix |
| Wire | `ksp-interface-lib` | lib | Retenu | `0.2.12` | façade wire officielle + API publique wire | | Wire | `ksp-interface-lib` | lib | Retenu | `0.2.13` | façade wire officielle + API publique wire |
| Program API | `ksp-program-api` | API | Retenu | `0.2.13` | contrats extensibles Program | | Program API | `ksp-program-api` | API | Retenu | `0.2.14` | contrats extensibles Program |
| Program impl. | `ksp-program-lib` | lib | Retenu | vertical slices ultérieurs | implementations Program officielles | | Program impl. | `ksp-program-lib` | lib | Retenu | vertical slices ultérieurs | implementations Program officielles |
| Program extension | `ksp-program-<name>-lib` | lib externe | À la demande | dès besoin | implementation externe de `ksp-program-api` | | Program extension | `ksp-program-<name>-lib` | lib externe | À la demande | dès besoin | implementation externe de `ksp-program-api` |
| Store API | `ksp-store-api` | API | Retenu | `0.3.1` | contrats persistence backend-agnostic, RAW d'abord | | Store API | `ksp-store-api` | API | Retenu | `0.3.1` | contrats persistence backend-agnostic, RAW d'abord |
@@ -87,6 +87,8 @@ Les WebSockets supportent plusieurs sessions pour un même endpoint URL, mais un
Les providers Yellowstone spécifiques restent des extensions futures ; le contrat standard est provider-neutral. Les providers Yellowstone spécifiques restent des extensions futures ; le contrat standard est provider-neutral.
`ksp-offchain-transport-lib` ouvre en `0.2.11` une première surface SOL/USD multi-provider. La crate possède les adapters `reqwest`, les capacités/rate limits, létat runtime et le refresh individuel/multiple. Elle ne dépend pas de Config et nexpose aucun wire provider comme contrat de lapplication. `ksp-app-solprices-desk`, prévu en `0.2.12`, consomme exclusivement cette surface générique et reste une HID sans connaissance provider.
## Wallet ## Wallet
Le format natif est `.kspwallet`. Le format natif est `.kspwallet`.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/005-DEPENDENCY_GRAPH.md --> <!-- file: docs/architecture/005-DEPENDENCY_GRAPH.md -->
<!-- version: 13 --> <!-- version: 14 -->
# Graphe de dépendances KSP # Graphe de dépendances KSP
@@ -120,12 +120,22 @@ Yellowstone gRPC est un backend standard/provider-neutral. Les adapters/capabili
ksp-offchain-transport-lib ksp-offchain-transport-lib
-> ksp-core-lib -> ksp-core-lib
-> ksp-logging-lib -> ksp-logging-lib
-> external HTTP/client crates nécessaires -> reqwest
-> serde / serde_json
-> tokio
``` ```
Aucune `ksp-offchain-transport-api` globale n'est prévue. Aucune `ksp-offchain-transport-api` globale n'est prévue.
La première surface est un reader de prix ; metadata HTTP/IPFS/Arweave et autres besoins sont ajoutés lorsqu'ils deviennent concrets. La première surface `0.2.11` est SOL/USD uniquement et peut être servie par plusieurs adapters REST. Aucun SDK provider n'est ajouté : les DTOs wire restent privés et les origines provider V1 sont fixes. La crate possède le registry, les capacités/rate limits, les cooldowns, l'état d'indisponibilité et les refresh individuel/multiple.
```text
ksp-offchain-transport-lib -X-> ksp-config-lib
ksp-offchain-transport-lib -X-> ksp-onchain-transport-lib
ksp-offchain-transport-lib -X-> provider SDKs
```
Config peut dépendre d'Off-chain Transport pour adapter un document standard vers ses settings publics. Metadata HTTP/IPFS/Arweave et autres besoins sont ajoutés lorsqu'ils deviennent concrets.
## Wallet ## Wallet
@@ -390,15 +400,17 @@ ksp-app-wallet-desk
L'app compose ; elle ne déplace pas Config/Wallet/Transport dans Tauri. Les handles `WalletView`/`WalletOwner` restent côté Rust, et le frontend ne reçoit que des DTOs sûrs. Config fournit la racine/profil Wallet et le profil Transport. Les passwords Wallet ne deviennent jamais des champs des documents JSON Config ; ils peuvent être saisis éphémèrement frontend -> Rust ou provenir plus tard de secrets process/`.env` `KSP_SECRET_WALLET_PASS_*` possédés exclusivement par Config. Le secret Solana ne devient jamais une valeur Config ni un DTO frontend. L'app compose ; elle ne déplace pas Config/Wallet/Transport dans Tauri. Les handles `WalletView`/`WalletOwner` restent côté Rust, et le frontend ne reçoit que des DTOs sûrs. Config fournit la racine/profil Wallet et le profil Transport. Les passwords Wallet ne deviennent jamais des champs des documents JSON Config ; ils peuvent être saisis éphémèrement frontend -> Rust ou provenir plus tard de secrets process/`.env` `KSP_SECRET_WALLET_PASS_*` possédés exclusivement par Config. Le secret Solana ne devient jamais une valeur Config ni un DTO frontend.
### Price Desk ### SOL Prices Desk
```text ```text
price desk ksp-app-solprices-desk
-> ksp-config-lib -> ksp-config-lib
-> ksp-offchain-transport-lib -> ksp-offchain-transport-lib
-> ksp-logging-lib -> ksp-logging-lib
``` ```
L'application est une HID pure. Elle ne dépend d'aucun SDK provider, ne construit aucune requête HTTP provider et ne connaît ni endpoint, ni credential, ni limite provider. Les rows et actions de refresh sont alimentées par les descriptors/états/opérations génériques de `ksp-offchain-transport-lib`.
### Backfill app ### Backfill app
```text ```text

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/000-README.md --> <!-- file: docs/plans/000-README.md -->
<!-- version: 61 --> <!-- version: 62 -->
# Plans KSP # 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`. - [`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`. - [`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. - [`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. 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 --> <!-- file: docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md -->
<!-- version: 89 --> <!-- version: 90 -->
# Séquence des releases fonctionnelles KSP # 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. 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 ### `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.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/000-README.md --> <!-- file: docs/validation/000-README.md -->
<!-- version: 25 --> <!-- version: 26 -->
# Validations KSP # Validations KSP
@@ -21,4 +21,5 @@ Documents :
- [`010-V0_2_7_ONCHAIN_WEBSOCKET.md`](010-V0_2_7_ONCHAIN_WEBSOCKET.md) — matrice finale validée de la release stable `0.2.7`, ouverte par `pre.001`, fermée techniquement par `pre.014` puis publiée par `rel.001` : inventaire 9 subscribe + 9 unsubscribe, lifecycle borné, statuts unstable, compliance 18/18, non-régression HTTP 52+14, composition Config V2, smoke WebSocket Devnet et audit de dépendances. - [`010-V0_2_7_ONCHAIN_WEBSOCKET.md`](010-V0_2_7_ONCHAIN_WEBSOCKET.md) — matrice finale validée de la release stable `0.2.7`, ouverte par `pre.001`, fermée techniquement par `pre.014` puis publiée par `rel.001` : inventaire 9 subscribe + 9 unsubscribe, lifecycle borné, statuts unstable, compliance 18/18, non-régression HTTP 52+14, composition Config V2, smoke WebSocket Devnet et audit de dépendances.
- [`011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md`](011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md) — matrice finale validée de la release stable `0.2.8`, ouverte par `pre.001`, consolidée jusquà `pre.011` puis publiée par `rel.001` : Helius `account/logs/program/root/signature/slot/slotsUpdates + transaction`, `block/vote` absents, heartbeat provider, sécurité/redaction, lifecycle adversarial, non-régressions HTTP/WS, stratégie smoke live et graphes Cargo finaux. - [`011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md`](011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md) — matrice finale validée de la release stable `0.2.8`, ouverte par `pre.001`, consolidée jusquà `pre.011` puis publiée par `rel.001` : Helius `account/logs/program/root/signature/slot/slotsUpdates + transaction`, `block/vote` absents, heartbeat provider, sécurité/redaction, lifecycle adversarial, non-régressions HTTP/WS, stratégie smoke live et graphes Cargo finaux.
- [`012-V0_2_9_YELLOWSTONE_GRPC.md`](012-V0_2_9_YELLOWSTONE_GRPC.md) — matrice finale de la release stable `0.2.9` : service Geyser courant, `Subscribe` standard, 7 unary, filtres/updates, dépendances/licence, replay/backpressure, Config V3 et smoke PublicNode Mainnet/Testnet. - [`012-V0_2_9_YELLOWSTONE_GRPC.md`](012-V0_2_9_YELLOWSTONE_GRPC.md) — matrice finale de la release stable `0.2.9` : service Geyser courant, `Subscribe` standard, 7 unary, filtres/updates, dépendances/licence, replay/backpressure, Config V3 et smoke PublicNode Mainnet/Testnet.
- [`013-V0_2_10_ORBITFLARE_YELLOWSTONE_GRPC.md`](013-V0_2_10_ORBITFLARE_YELLOWSTONE_GRPC.md) — matrice active ouverte par `0.2.10-pre.001` : Free Devnet, auth provider, endpoint security, heartbeat standard, capabilities, Config V3, smoke live et invariant N1/N2 immuable. - [`013-V0_2_10_ORBITFLARE_YELLOWSTONE_GRPC.md`](013-V0_2_10_ORBITFLARE_YELLOWSTONE_GRPC.md) — matrice finale de la release stable `0.2.10` : Free Devnet, auth `x-token`, endpoint security, heartbeat standard, Config V3, smoke live `Slot + Ping` et invariant N1/N2 immuable.
- [`014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md`](014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md) — matrice active ouverte par `0.2.11-pre.001` : SOL/USD multi-provider, `reqwest` sans SDK provider, numeric safety, rate limiting/availability, Config capability-aware, DexScreener pair explicite et frontière HID future.

View File

@@ -0,0 +1,210 @@
<!-- file: docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md -->
<!-- version: 1 -->
# Validation `0.2.11` — Off-chain price transport SOL/USD
## 1. Objet
Cette matrice suit la release `0.2.11 — Off-chain price transport` ouverte par `pre.001`.
Le contrat fonctionnel V1 est :
```text
SOL/USD uniquement
plusieurs providers gratuits admis
HTTP REST reqwest uniquement
aucun SDK provider
provider/rate-limit/availability possédés par ksp-offchain-transport-lib
Config -> Off-chain Transport sans dépendance inverse
future ksp-app-solprices-desk purement HID et provider-agnostic
```
Les statuts `PLANNED` restent non validés tant que la tranche correspondante n'est pas exécutée.
## 2. Gate `0.2.11-pre.001`
| Critère | Statut | Preuve |
|---------------------------------------------------------------|--------|-----------------------------------------------------------------------------------------|
| archive stable `v0.2.10` utilisée | PASS | archive Gitea fournie par l'opérateur |
| `workspace.package.version = 0.2.10` à l'entrée | PASS | inspection `Cargo.toml` |
| `deltas/0.2.10/rel.001.md` présent | PASS | inspection archive |
| `prompts/016-V0_2_11_START_PROMPT.md` présent | PASS | inspection archive |
| `.git` absent de l'archive | PASS | inspection filesystem |
| `ksp-offchain-transport-lib` absent à l'entrée | PASS | inventaire workspace |
| primitives reqwest/serde/serde_json/tokio/http déjà présentes | PASS | inventaire `[workspace.dependencies]` |
| audit providers gratuit/live actuel | PASS | sources officielles CoinGecko, CMC, CoinPaprika, Kraken, Coinbase, Jupiter, Birdeye, DS |
| conditions d'usage gratuites distinguées du transport | PASS | plan 018, gratuité technique distincte de licence commerciale durable |
| SOL/USD retenu comme seule paire V1 | PASS | décision opérateur + plan 018 |
| aucun SDK provider retenu | PASS | décision opérateur + plan 018 |
| huit providers retenus pour implémentation | PASS | plan 018 section provider |
| DexScreener V1 limité à une paire SOL/USD configurée | PASS | décision opérateur + plan 018 |
| future `ksp-app-solprices-desk` purement HID | PASS | décision opérateur + architecture |
| ownership rate limits/availability dans Off-chain Transport | PASS | décision opérateur + plan 018 |
| threat model V1 établi | PASS | plan 018 |
| forecast prereleases établi | PASS | plan 018 |
| code runtime provider ajouté en `pre.001` | N/A | interdit par le gate, aucune crate créée |
## 3. Matrice provider prévue
| Provider | SOL/USD V1 | Gratuit V1 | Mode auth prévu | Test déterministe | Smoke live | Statut courant |
|-------------------|------------|------------|----------------------|-------------------|------------|----------------|
| CoinGecko | Oui | Oui | keyless ou Demo key | PLANNED | PLANNED | AUDITED |
| CoinMarketCap | Oui | Oui | keyless ou Basic key | PLANNED | PLANNED | AUDITED |
| CoinPaprika | Oui | Oui | aucune | PLANNED | PLANNED | AUDITED |
| Kraken | Oui | Oui | aucune | PLANNED | PLANNED | AUDITED |
| Coinbase Exchange | Oui | Oui | aucune | PLANNED | PLANNED | AUDITED |
| Jupiter Price V3 | Oui | Oui | keyless ou Free key | PLANNED | PLANNED | AUDITED |
| Birdeye | Oui | Oui | API key Standard | PLANNED | PLANNED | AUDITED |
| DexScreener | Oui | Oui | aucune | PLANNED | PLANNED | AUDITED |
`AUDITED` signifie uniquement que la documentation officielle actuelle satisfait le gate d'entrée. Ce statut ne vaut pas preuve d'un smoke réseau KSP.
Avant la stable, les conditions d'usage et la persistance des offres gratuites doivent être réauditées ; un provider peut rester techniquement supporté tout en nécessitant un plan différent pour certains usages.
## 4. Contrat public prévu
| Invariant | Statut |
|------------------------------------------------------------------------|---------|
| surface publique limitée à SOL/USD dans V1 | PLANNED |
| identifiants provider opaques pour les consumers | PLANNED |
| provenance provider toujours observable | PLANNED |
| sémantique de prix observable sans prétendre à une équivalence | PLANNED |
| timestamp requête/réception KSP présents | PLANNED |
| timestamp provider optionnel seulement lorsqu'il est réellement fourni | PLANNED |
| absence de prix distincte de zéro | PLANNED |
| `f64` non utilisé comme canon public | PLANNED |
| aucune structure wire provider exportée | PLANNED |
| aucune URL/header/asset id provider requis côté app | PLANNED |
| registry provider et état runtime possédés par Off-chain Transport | PLANNED |
| refresh provider par identifiant générique | PLANNED |
| refresh multiple sans connaissance provider côté consumer | PLANNED |
## 5. Rate limiting et availability
| Cas | Statut |
|---------------------------------------------------------------|---------|
| cadence locale fixe représentable | PLANNED |
| burst documenté représentable | PLANNED |
| limite dynamique keyless représentable | PLANNED |
| `429` classé | PLANNED |
| `Retry-After` honoré lorsqu'exploitable | PLANNED |
| cooldown expose prochain instant admissible | PLANNED |
| refresh all ne lance que les providers éligibles | PLANNED |
| provider en cooldown ne bloque pas les autres | PLANNED |
| provider down ne rend pas le service global inutilisable | PLANNED |
| auth manquante distinguée d'un transport down | PLANNED |
| quota indisponible distingué d'un transport down | PLANNED |
| quota mensuel local non présenté comme compteur authoritative | PLANNED |
## 6. Numeric safety
| Cas | Statut |
|-----------------------------------------------------|---------|
| décimal string valide | PLANNED |
| JSON number valide sans passage canonique par `f64` | PLANNED |
| notation scientifique bornée | PLANNED |
| coefficient/scale overflow rejeté | PLANNED |
| valeur négative rejetée | PLANNED |
| zéro rejeté pour une observation réussie | PLANNED |
| NaN/Inf impossibles dans le type canonique | PLANNED |
| serialization canonique sans perte | PLANNED |
| round-trip public déterministe | PLANNED |
## 7. HTTP et sécurité
| Invariant | Statut |
|------------------------------------------------|---------|
| `reqwest` seul client provider | PLANNED |
| aucun SDK provider | PLANNED |
| endpoint provider officiel fixe en V1 | PLANNED |
| redirects désactivés | PLANNED |
| proxy implicite désactivé selon policy KSP | PLANNED |
| connect timeout borné | PLANNED |
| request timeout borné | PLANNED |
| body réponse borné avant parsing | PLANNED |
| URL retirée des erreurs reqwest | PLANNED |
| réponse remote brute absente des KspError/logs | PLANNED |
| API key absente de Debug/log/error | PLANNED |
| 401/403 classés auth/access | PLANNED |
| 429 classé rate limit | PLANNED |
| 5xx classé transient | PLANNED |
| schema drift classé provider protocol | PLANNED |
## 8. DexScreener V1
| Invariant | Statut |
|----------------------------------------------|---------|
| pair address SOL/USD explicite dans settings | PLANNED |
| `chainId = solana` vérifié | PLANNED |
| identité SOL de la paire vérifiée | PLANNED |
| `priceUsd` utilisé comme prix commun | PLANNED |
| aucune recherche automatique de pool | PLANNED |
| aucun tri automatique par liquidité | PLANNED |
| aucune moyenne/consensus entre pools | PLANNED |
## 9. Config -> Off-chain Transport
| Invariant | Statut |
|------------------------------------------------------------------|---------|
| Off-chain Transport ne dépend pas de Config | PLANNED |
| document standard offchain dédié | PLANNED |
| branches provider conditionnelles dans schema | PLANNED |
| CoinGecko keyless/Demo représentés | PLANNED |
| CoinMarketCap keyless/Basic représentés | PLANNED |
| Jupiter keyless/Free représentés | PLANNED |
| Birdeye exige credential lorsqu'activé | PLANNED |
| DexScreener exige pair address lorsqu'activé | PLANNED |
| providers sans auth n'exposent pas de faux champ API key | PLANNED |
| secrets via Config uniquement | PLANNED |
| `.env.example` synchronisé pour les secrets réellement ajoutés | PLANNED |
| aucune cadence provider configurable au-dessus de la limite sûre | PLANNED |
## 10. Frontière future `ksp-app-solprices-desk`
| Invariant | Statut |
|--------------------------------------------------------------------|---------|
| nom de l'application fixé à `ksp-app-solprices-desk` | DECIDED |
| rôle HID uniquement | DECIDED |
| aucun enum/provider spécifique requis dans l'UI | PLANNED |
| aucun endpoint/header/provider id propriétaire dans l'app | PLANNED |
| table construite depuis l'inventaire générique Off-chain Transport | PLANNED |
| refresh row appelle une opération générique | PLANNED |
| refresh multiple appelle une opération générique | PLANNED |
| cooldown/availability affichables depuis état générique | PLANNED |
| aucune logique de rate limiting dans Tauri/frontend | PLANNED |
Cette section valide l'architecture préparée par `0.2.11`; l'application elle-même reste hors scope et sera testée en `0.2.12`.
## 11. Non-régression et gates finaux prévus
| Gate | Statut |
|-------------------------------------------------|---------|
| `cargo fmt --all` | PLANNED |
| audit Rust workspace | PLANNED |
| audit Markdown tables | PLANNED |
| `cargo check --workspace` | PLANNED |
| `cargo clippy --workspace --all-targets` | PLANNED |
| `cargo test --workspace` | PLANNED |
| tests `ksp-offchain-transport-lib` | PLANNED |
| tests Config | PLANNED |
| cargo tree Off-chain Transport | PLANNED |
| absence de dépendances provider SDK | PLANNED |
| smokes keyless gratuits | PLANNED |
| smokes keyed gratuits disponibles à l'opérateur | PLANNED |
| réconciliation README/USAGE/plan/validation | PLANNED |
## 12. Hors scope validé
```text
SOL/EUR et autres quotes
SPL token price générique
OHLCV/historique
streaming price
fallback automatique
consensus/moyenne/médiane
pool discovery DexScreener
Price Desk dans 0.2.11
Wallet Desk dans 0.2.11
Pyth V1
Binance SOL/USDT assimilé à SOL/USD
```