41 KiB
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 :
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. Gate 0.2.11-pre.002
| Critère | Statut | Preuve |
|---|---|---|
crate ksp-offchain-transport-lib créée |
PASS | membre workspace + package dédié |
version workspace synchronisée sur 0.2.11-pre.2 |
PASS | Cargo.toml racine |
| dépendance inverse vers Config absente | PASS | manifest crate |
reqwest et SDK providers absents de la fondation |
PASS | manifest crate |
MarketPriceDecimal exact sans canon f64 |
PASS | coefficient u128, scale 18, sérialisation string |
| SOL/USD seule paire publique V1 | PASS | MarketPricePair::SolUsd + MarketPriceObservation |
| identifiant/descripteur provider opaques | PASS | MarketPriceProviderId + MarketPriceProviderDescriptor |
| auth/rate-limit/quota représentables génériquement | PASS | types provider-neutral dédiés |
| settings communs sans faux endpoint/API key | PASS | MarketPriceProviderCommonSettings |
| availability provider-neutral représentable | PASS | MarketPriceProviderAvailability + MarketPriceProviderState |
| HTTP actif ou adapter provider ajouté | N/A | explicitement réservé à pre.003+ |
3.1 Taxonomie Off-chain et observabilité
| Invariant | Statut |
|---|---|
crate ksp-offchain-transport-lib non assimilée à une crate price-only |
PASS |
capacité V1 classée sous modules privés market_price_* |
PASS |
modules partagés constants.rs et error.rs restent crate-wide |
PASS |
futures quotes prévues sous famille distincte swap_quote_* |
PASS |
| aucune abstraction future créée sans responsabilité réellement partagée | PASS |
market_price V1 strictement read-only |
PASS |
| verbe HTTP distinct de la sémantique métier read/write | PASS |
| soumission/signature Solana reste hors d'Off-chain Transport | PASS |
ksp-logging-lib utilisé pour les événements KSP de la crate |
PASS |
src/constants.rs possède TRACING_TARGET = ksp-offchain-transport-lib |
PASS |
aucune dépendance directe à tracing |
PASS |
| crate-rustdocs présentes dans les tests d'intégration | PASS |
3.2 Correctif 0.2.11-pre.002-fix.002
Le gate cargo clippy --workspace --all-targets de pre.002-fix.001 a détecté un unique écart clippy::implicit-return dans le canari tests/dependency_boundary.rs. Le correctif ajoute le return explicite attendu dans la closure de Iterator::any et synchronise workspace.package.version sur 0.2.11-pre.2.fix.2. Aucun contrat public, comportement runtime ou scope provider n'est modifié.
Les validations opérateur du 2026-08-25 sur pre.002-fix.002 sont : cargo fmt --all PASS, audit Rust PASS, audit Markdown PASS, cargo check --workspace PASS, cargo test -p ksp-offchain-transport-lib PASS avec 13 tests exécutés, et cargo clippy --workspace --all-targets PASS. cargo test --workspace n'a pas été rejoué après ce fix et n'est donc pas déclaré PASS pour cet état exact.
3.3 Correctif 0.2.11-pre.002-fix.003
Le nommage public initial Price* restait trop générique alors que les modules qui possèdent ces contrats sont explicitement la famille market_price_*. Le correctif synchronise workspace.package.version sur 0.2.11-pre.2.fix.3 et renomme sans alias de compatibilité toute la surface publique spécifique à cette famille en MarketPrice* / MARKET_PRICE_*.
Le contrat attendu après application est :
MarketPriceDecimal
MarketPriceObservation
MarketPriceTimestamp
MarketPriceProvenance
MarketPricePair
MarketPriceSemantics
MarketPriceProvider*
MARKET_PRICE_*
ERROR_CODE_MARKET_PRICE_*
Cette correction reste dans la responsabilité de pre.002 : elle stabilise la fondation et sa façade avant l'introduction du HTTP runtime en pre.003.
3.4 Gate 0.2.11-pre.003
| Critère | Statut | Preuve |
|---|---|---|
version workspace 0.2.11-pre.3 |
PASS | Cargo.toml racine |
reqwest utilisé directement, sans SDK provider |
PASS | manifest ksp-offchain-transport-lib |
primitives HTTP communes sous modules http_* crate-private |
PASS | http_client, http_settings, http_admission |
| client HTTP générique non exporté aux consumers | PASS | façade lib.rs |
| redirects, Referer, proxy système et retries reqwest désactivés | PASS | construction HttpRestClient |
| connect/request timeouts bornés | PASS | HttpClientSettings |
| body borné pendant lecture chunked avant désérialisation | PASS | HttpRestClient::get_json |
| JSON syntaxiquement validé sans normalisation numérique intermédiaire | PASS | serde::de::IgnoredAny sur bytes bruts |
| 401/403, 429, 408/5xx et autres statuts distingués | PASS | codes d'erreur HTTP dédiés |
| URL reqwest supprimée des sources d'erreur | PASS | reqwest::Error::without_url |
| body remote non recopié dans les erreurs | PASS | erreurs construites uniquement depuis metadata safe |
| limiter fixe lissé et burst absent traité conservativement | PASS | HttpAdmissionController |
| limite dynamique n'invente pas de cadence locale | PASS | HttpAdmissionPolicy::Dynamic |
cooldown Retry-After borné et admission non bloquante |
PASS | record_rate_limited + try_admit |
| adapters CoinGecko/Jupiter/etc. ajoutés | N/A | explicitement réservés à pre.004+ |
gate Cargo check/clippy/tests Off-chain sur pre.003-fix.001 |
PASS | résultats opérateur du 2026-08-25 |
audit Rust final de pre.003-fix.001 |
CARRY | seul RUST-FMT-108, cause supprimée en pre.004 |
Les tests déterministes de pre.003 couvrent en particulier le body chunked dépassant la limite, le refus des redirects, un 429 avec Retry-After, la non-propagation d'un body distant canari, le JSON invalide et le refill/cooldown du limiter.
3.5 Correctif 0.2.11-pre.003-fix.001
Le gate opérateur de pre.003 a révélé quatre classes d'écarts avant poursuite vers pre.004 : six violations RUST-FMT-104 dans src/error.rs, six réexports pub(crate) HTTP inutilisés dans le build normal, un test de burst rejeté par la validation burst > requests, et la non-utilisation de la façade crate-root dans les impl des items HTTP partagés. cargo check et cargo clippy terminaient avec les warnings de réexports, tandis que cargo test -p ksp-offchain-transport-lib échouait sur documented_burst_is_consumed_atomically_before_refill.
Le correctif applique les règles suivantes :
RUST-FMT-005 / RUST-FMT-104 : constantes homogènes triées alphabétiquement
RUST-IMPORT-009 / RUST-API-004 : items HTTP partagés consommés via crate::Item, y compris dans leurs impl
RUST-API-008 : helpers préparatoires sans consumer production sous #[cfg(test)], aucun #[allow(dead_code)] compensatoire
contrat limiter : burst documenté indépendant de la cadence moyenne et autorisé à la dépasser
Le cas 1 req/s avec burst 2 devient un canari déterministe ; il protège notamment la représentabilité du cas Coinbase documenté dans le plan à 10 req/s, burst 15. Les modules http_* restent donc testés et prêts en pre.003, mais leur compilation normale sera activée en pre.004 lorsque les premiers adapters de production les consommeront réellement.
La version Cargo du correctif est 0.2.11-pre.3.fix.1. Le gate opérateur du 2026-08-25 confirme cargo check --workspace PASS, cargo clippy --workspace --all-targets PASS et cargo test -p ksp-offchain-transport-lib PASS avec 22 unitaires, 2 boundary et 2 public API. L'audit Rust signale uniquement RUST-FMT-108 dans src/lib.rs, conséquence directe du staging #[cfg(test)] des modules http_*. L'opérateur a explicitement décidé de ne pas publier un fix artificiel pour ce point puisque pre.004 retire ce staging avec les premiers consumers de production.
3.6 Gate 0.2.11-pre.004
| Critère | Statut | Preuve |
|---|---|---|
version workspace 0.2.11-pre.4 |
PASS | Cargo.toml racine |
modules http_* actifs en production, sans staging crate-root test |
PASS | src/lib.rs |
cause RUST-FMT-108 de pre.003-fix.001 supprimée |
PASS | modules production avant tests |
| CoinGecko SOL/USD adapter public | PASS | market_price_coingecko.rs |
| CoinGecko keyless et Demo key distingués | PASS | settings + descriptor + header sensible |
| CoinMarketCap SOL/USD adapter public | PASS | market_price_coinmarketcap.rs |
| CoinMarketCap Simple Price V2 utilisé, V1 deprecated absent du runtime | PASS | endpoints V2 fixes + canari dependency boundary |
| CoinMarketCap keyless et Basic key distingués | PASS | settings + descriptor + header sensible |
| CoinPaprika SOL/USD adapter public | PASS | market_price_coinpaprika.rs |
| CoinPaprika sans faux credential | PASS | settings keyless uniquement |
prix JSON provider parsé exactement sans passage par f64 |
PASS | RawValue -> MarketPriceDecimal::parse_json_raw |
| timestamps provider conservés lorsqu'ils existent | PASS | Unix seconds CoinGecko, RFC3339 CoinMarketCap/CoinPaprika |
| DTOs wire provider privés | PASS | structs privées dans chaque module provider |
| endpoints provider fixes et HTTPS | PASS | constantes privées + HttpGetRequest::new_https |
API keys absentes de Debug et diagnostics |
PASS | MarketPriceApiKey redacted + tests settings |
429 alimente le cooldown local partagé |
PASS | get_json -> record_rate_limited |
| aucun SDK provider | PASS | manifest + boundary tests |
| Config, registry global et refresh multiple non avancés | PASS | scopes réservés à pre.007+ / pre.009 |
| audit Rust sandbox | PASS | clean, 0 candidate export |
| audit Markdown sandbox | PASS | clean, 119 tables / 110 fichiers |
gate Cargo complet pre.004 |
FAIL | audit Rust : 1 x RUST-FMT-104 ; Clippy : 2 warnings ; 1 fixture CMC KO |
Les tests déterministes de pre.004 couvrent les modes d'auth, les headers sans fuite de credential, les URLs/query fixes, le parsing des réponses SOL/USD, le rejet d'identités ou schémas incohérents et le parsing exact des nombres JSON. Aucun smoke réseau n'est revendiqué dans cette tranche.
3.7 Correctif 0.2.11-pre.004-fix.001
Le gate opérateur du 2026-08-25 sur pre.004 a confirmé cargo check --workspace PASS, mais a détecté trois écarts avant pre.005 : une violation RUST-FMT-104 dans le bloc de constantes de src/error.rs, deux warnings clippy::collapsible_if dans les builders CoinGecko/CoinMarketCap et un échec du test coinmarketcap_v2_fixture_normalizes_string_status_and_exact_price.
L'échec CoinMarketCap provenait uniquement de la fixture : la concaténation produisait ...,151.987654321012345678,last_updated... au lieu de ...,151.987654321012345678,"last_updated".... Le parser runtime n'est pas modifié. Le correctif remet le bloc de constantes dans l'ordre alphabétique complet, utilise des let-chains pour les deux insertions de headers optionnels et corrige le JSON déterministe de la fixture.
La version Cargo du correctif est 0.2.11-pre.4.fix.1. Aucun endpoint, mode d'auth, descriptor, limite provider ou contrat public n'est modifié.
Le gate opérateur rejoué le 2026-08-25 est intégralement PASS : audit Rust clean avec 0 candidate export, audit Markdown clean à 118 tables / 109 fichiers, cargo check --workspace PASS, cargo clippy --workspace --all-targets PASS, cargo test -p ksp-offchain-transport-lib PASS avec 31 unitaires + 3 boundary + 3 public API, puis cargo test --workspace PASS avec uniquement les smokes/timing explicitement ignorés.
3.8 Gate 0.2.11-pre.005
| Critère | Statut | Preuve |
|---|---|---|
version workspace 0.2.11-pre.5 |
PASS | Cargo.toml racine |
| Kraken Spot SOL/USD adapter public | PASS | market_price_kraken.rs |
| Kraken public keyless sans faux credential | PASS | settings + descriptor |
| Kraken dernier trade conservé avec sémantique exchange | PASS | ticker SOLUSD -> c[0] -> ExchangeLastTrade |
| Kraken ne fabrique aucun timestamp provider absent | PASS | provider_timestamp = None |
| Kraken cadence locale conservatrice 1 req/s IP | PASS | descriptor + canari unitaire |
| Coinbase Exchange SOL/USD adapter public | PASS | market_price_coinbase_exchange.rs |
| Coinbase Exchange public keyless sans faux credential | PASS | settings + descriptor |
| Coinbase dernier trade et timestamp provider conservés | PASS | price + time -> ExchangeLastTrade |
| Coinbase token bucket public 10 req/s IP, burst 15 | PASS | descriptor + canari unitaire |
| DTOs wire Kraken/Coinbase privés | PASS | structs privées dans les modules providers |
| endpoints provider fixes et HTTPS | PASS | constantes privées + boundary canary |
prix exchange parsés exactement sans passage par f64 |
PASS | RawValue -> MarketPriceDecimal::parse_json_raw |
| aucun SDK provider, Config ou registry global avancé | PASS | manifest + dependency boundary |
| audit Rust sandbox | PASS | clean, 0 candidate export |
| audit Markdown sandbox | PASS | clean, 119 tables / 110 fichiers |
cargo check / Clippy / tests Off-chain |
PASS | résultats opérateur du 2026-08-25 |
cargo test --workspace sur état exact pre.005 |
N/R | non rejoué avant passage explicite à pre.006 |
Les tests déterministes de pre.005 couvrent les descriptors exchange, la précision décimale, le timestamp Coinbase, l'absence de timestamp Kraken, le rejet d'une erreur/identité Kraken incohérente et le rejet d'un timestamp Coinbase invalide. Le gate opérateur ciblé du 2026-08-25 est PASS : audit Rust clean, audit Markdown clean à 119 tables / 110 fichiers, cargo check --workspace PASS, cargo clippy --workspace --all-targets PASS et cargo test -p ksp-offchain-transport-lib PASS avec 37 unitaires + 3 boundary + 4 public API. cargo test --workspace n'a pas été rejoué sur cet état exact.
3.9 Gate 0.2.11-pre.006
| Critère | Statut | Preuve |
|---|---|---|
version workspace 0.2.11-pre.6 |
PASS | Cargo.toml racine |
| Jupiter Price V3 adapter public | PASS | market_price_jupiter.rs |
| Jupiter keyless et Free key distingués | PASS | settings + descriptor + header sensible |
| Jupiter keyless 0,5 RPS et Free 1 RPS représentés | PASS | descriptors + canaries unitaires |
| Jupiter utilise uniquement le mint WSOL | PASS | query ids fixe |
usdPrice Jupiter parsé exactement sans f64 canonique |
PASS | RawValue -> MarketPriceDecimal |
blockId Jupiter conservé en provenance sans faux timestamp |
PASS | provenance bornée + provider_timestamp = None |
| DexScreener adapter public avec pair address explicite | PASS | MarketPriceDexScreenerSettings |
| DexScreener endpoint direct pair uniquement | PASS | /latest/dex/pairs/solana/{pairId} |
DexScreener vérifie chainId, pair address et identité WSOL |
PASS | parser provider |
DexScreener utilise uniquement priceUsd |
PASS | DTO wire privé + parsing exact |
| DexScreener 300 req/min représenté | PASS | descriptor provider |
| aucune découverte/selection/ranking automatique de pool | PASS | dependency boundary + absence search/token-pairs/tokens |
| aucun SDK provider, Config, registry ou refresh multiple avancé | PASS | manifest + scope des modules |
| audit Rust sandbox | PASS | clean, 0 candidate export |
| audit Markdown sandbox | PASS | clean, 120 tables / 111 fichiers |
cargo check / Clippy / tests Off-chain |
PASS | résultats opérateur du 2026-08-25 |
cargo test --workspace sur état exact pre.006 |
N/R | non rejoué avant passage explicite à pre.007 |
Les fixtures de pre.006 couvrent Jupiter keyless/Free, redaction de la clé, prix exact, identité WSOL, blockId, absence volontaire de faux timestamp, ainsi que DexScreener avec pair Solana explicite, priceUsd, rejet de chain/pair/base invalides, réponse multiple et prix absent. Le gate opérateur ciblé du 2026-08-25 est PASS : audit Rust clean, audit Markdown clean à 120 tables / 111 fichiers, cargo check --workspace PASS, cargo clippy --workspace --all-targets PASS et cargo test -p ksp-offchain-transport-lib PASS avec 43 unitaires + 4 boundary + 5 public API. cargo test --workspace n'a pas été rejoué sur cet état exact.
3.10 Gate 0.2.11-pre.007
| Critère | Statut | Preuve |
|---|---|---|
version workspace 0.2.11-pre.7 |
PASS | Cargo.toml racine |
| Birdeye Standard SOL/USD adapter public | PASS | market_price_birdeye.rs |
Birdeye exige X-API-KEY lorsqu'activé |
PASS | settings + header sensible |
Birdeye fixe x-chain = solana et le mint WSOL |
PASS | request builder |
Birdeye Price Single value parsé exactement |
PASS | RawValue -> MarketPriceDecimal |
Birdeye updateUnixTime conservé comme timestamp provider |
PASS | parser provider |
| Birdeye Standard 1 RPS compte modélisé | PASS | descriptor provider |
| quota Birdeye 30 000 compute units informatif | PASS | MarketPriceProviderLongTermQuota |
| coût Price Single 3 compute units informatif | PASS | MarketPriceProviderRequestCost |
| registry provider-neutral matérialisé | PASS | MarketPriceProviderRegistry |
| huit providers V1 présents dans le canari de complétude registry | PASS | test market_price_registry |
| registry trié par provider id et doublons rejetés | PASS | constructeur public générique + tests |
| entry publique limitée à descriptor + état générique | PASS | MarketPriceProviderRegistryEntry |
availability expose éligibilité et retry_at génériques |
PASS | MarketPriceProviderAvailability |
| registry sans mutation ou dispatch réseau | PASS | projection générique publique |
| registry ne contient aucun dispatch/name provider | PASS | dependency boundary |
| refresh single/multiple, Config et smoke live non avancés | PASS | scope réservé à pre.008+ |
| audit Rust sandbox | PASS | clean, 0 candidate export |
| audit Markdown sandbox | PASS | clean, 121 tables / 112 fichiers |
| gate Cargo | PASS | gate opérateur complet du 2026-08-26 |
Les tests déterministes de pre.007 couvrent l'auth Birdeye et sa redaction, le descriptor 1 RPS / 30 000 CU / 3 CU, le parsing exact du prix et du timestamp, les réponses invalides, ainsi que le registry complet des huit providers, son ordre déterministe, le rejet de doublons et les projections d'availability. Le gate opérateur du 2026-08-26 est intégralement PASS : audits Rust/Markdown, cargo check --workspace, cargo clippy --workspace --all-targets, tests ciblés Off-chain et cargo test --workspace. Aucun smoke live provider n'est revendiqué.
3.11 Gate 0.2.11-pre.008
| Critère | Statut | Preuve |
|---|---|---|
version workspace 0.2.11-pre.8 |
PASS | Cargo.toml racine |
MarketPriceService provider-agnostic public |
PASS | market_price_service.rs |
| setup provider-specific limité à la composition | PASS | MarketPriceProviderSetup |
| registry détachable sans dispatch provider | PASS | MarketPriceService::registry |
refresh individuel par MarketPriceProviderId |
PASS | MarketPriceService::refresh |
| refresh multiple par liste d'identifiants opaques | PASS | MarketPriceService::refresh_many |
| refresh all en ordre provider déterministe | PASS | MarketPriceService::refresh_all |
| doublons / provider inconnu rejetés avant dispatch | PASS | tests market_price_service |
| provider non éligible projeté sans requête réseau | PASS | eligibility + test huit providers disabled |
429 / defer local projetés en CoolingDown |
PASS | classification générique |
401/403 keyed projetés en AuthenticationUnavailable |
PASS | classification auth-aware |
| transport temporaire projeté sans rendre le service global inutilisable | PASS | outcome provider-neutral |
| aucune attente/sleep de rate limit dans le service | PASS | dependency boundary |
| aucun fallback, consensus ou agrégation multi-provider | PASS | scope + dependency boundary |
| Config, scheduling périodique et smoke live non avancés | PASS | scope réservé à pre.009+ |
| audit Rust sandbox | PASS | clean, 0 candidate export |
| audit Markdown sandbox | PASS | clean, 122 tables / 113 fichiers |
| gate Cargo | PLANNED | à exécuter par l'opérateur |
Les tests déterministes de pre.008 vérifient le registry de service sur les huit setups V1, refresh_all sans réseau lorsque tous les providers sont désactivés, le rejet pré-dispatch des doublons/providers inconnus, les classes auth/rate-limit/temporaire/local misconfiguration et l'éligibilité temporelle des cooldowns. Les méthodes multiples restent séquentielles et déterministes dans V1 ; elles ne dorment jamais pour attendre un provider et ne font aucun fallback/consensus.
4. 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 | PASS | PLANNED | IMPLEMENTED |
| CoinMarketCap | Oui | Oui | keyless ou Basic key | PASS | PLANNED | IMPLEMENTED |
| CoinPaprika | Oui | Oui | aucune | PASS | PLANNED | IMPLEMENTED |
| Kraken | Oui | Oui | aucune | PASS | PLANNED | IMPLEMENTED |
| Coinbase Exchange | Oui | Oui | aucune | PASS | PLANNED | IMPLEMENTED |
| Jupiter Price V3 | Oui | Oui | keyless ou Free key | PASS | PLANNED | IMPLEMENTED |
| Birdeye | Oui | Oui | API key Standard | PASS | PLANNED | IMPLEMENTED |
| DexScreener | Oui | Oui | aucune | PASS | PLANNED | IMPLEMENTED |
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.
5. Contrat public prévu
| Invariant | Statut |
|---|---|
| surface publique limitée à SOL/USD dans V1 | PASS |
| identifiants provider opaques pour les consumers | PASS |
| provenance provider toujours observable | PASS |
| sémantique de prix observable sans prétendre à une équivalence | PASS |
| timestamp requête/réception KSP présents | PASS |
| timestamp provider optionnel seulement lorsqu'il est réellement fourni | PASS |
| absence de prix distincte de zéro | PASS |
f64 non utilisé comme canon public |
PASS |
| aucune structure wire provider exportée | PASS |
| aucune URL/header/asset id provider requis côté app | PASS |
| registry provider et état runtime possédés par Off-chain Transport | PASS |
| refresh provider par identifiant générique | PASS |
| refresh multiple sans connaissance provider côté consumer | PASS |
6. Rate limiting et availability
| Cas | Statut |
|---|---|
| cadence locale fixe représentable | PASS |
| burst documenté supérieur à la cadence moyenne représentable | PASS |
| limite dynamique keyless représentable | PASS |
429 classé |
PASS |
Retry-After honoré lorsqu'exploitable |
PASS |
| cooldown expose prochain instant admissible | PASS |
| refresh all ne lance que les providers éligibles | PASS |
| provider en cooldown ne bloque pas les autres | PASS |
| provider down ne rend pas le service global inutilisable | PASS |
| auth rejetée distinguée d'un transport down | PASS |
| quota indisponible distingué d'un transport down | PLANNED |
| quota mensuel local non présenté comme compteur authoritative | PASS |
7. Numeric safety
| Cas | Statut |
|---|---|
| décimal string valide | PASS |
JSON number valide sans passage canonique par f64 |
PASS |
| notation scientifique bornée | PASS |
| coefficient/scale overflow rejeté | PASS |
| valeur négative rejetée | PASS |
| zéro rejeté pour une observation réussie | PASS |
| NaN/Inf impossibles dans le type canonique | PASS |
| serialization canonique sans perte | PASS |
| round-trip public déterministe | PASS |
8. HTTP et sécurité
| Invariant | Statut |
|---|---|
reqwest seul client provider |
PASS |
| aucun SDK provider | PASS |
| endpoint provider officiel fixe en V1 | PASS |
| redirects désactivés | PASS |
| proxy implicite désactivé selon policy KSP | PASS |
| connect timeout borné | PASS |
| request timeout borné | PASS |
| body réponse borné avant parsing | PASS |
| URL retirée des erreurs reqwest | PASS |
| réponse remote brute absente des KspError/logs | PASS |
| API key absente de Debug/log/error | PASS |
| 401/403 classés auth/access | PASS |
| 429 classé rate limit | PASS |
| 5xx classé transient | PASS |
| schema drift classé provider protocol | PLANNED |
9. DexScreener V1
| Invariant | Statut |
|---|---|
| pair address SOL/USD explicite dans settings | PASS |
chainId = solana vérifié |
PASS |
| identité SOL de la paire vérifiée | PASS |
priceUsd utilisé comme prix commun |
PASS |
| aucune recherche automatique de pool | PASS |
| aucun tri automatique par liquidité | PASS |
| aucune moyenne/consensus entre pools | PASS |
10. 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 |
11. 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.
12. 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 |
13. Hors scope validé
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