v0.2.11-pre.004
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md -->
|
||||
<!-- version: 7 -->
|
||||
<!-- version: 8 -->
|
||||
|
||||
# Validation `0.2.11` — Off-chain price transport SOL/USD
|
||||
|
||||
@@ -105,24 +105,25 @@ Cette correction reste dans la responsabilité de `pre.002` : elle stabilise la
|
||||
|
||||
## 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 complet sur `pre.003-fix.001` | PENDING | à rejouer par l'opérateur après le correctif |
|
||||
| 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.
|
||||
|
||||
@@ -141,15 +142,43 @@ contrat limiter : burst documenté indépendant de la cadence moyenne et autoris
|
||||
|
||||
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`. Les audits statiques du sandbox sont propres ; le gate Cargo complet doit être rejoué par l'opérateur.
|
||||
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 | à recalculer après finalisation documentaire |
|
||||
| gate Cargo complet `pre.004` | PENDING | opérateur |
|
||||
|
||||
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.
|
||||
|
||||
## 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 | PLANNED | PLANNED | AUDITED |
|
||||
| CoinMarketCap | Oui | Oui | keyless ou Basic key | PLANNED | PLANNED | AUDITED |
|
||||
| CoinPaprika | Oui | Oui | aucune | PLANNED | PLANNED | AUDITED |
|
||||
| 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 | PLANNED | PLANNED | AUDITED |
|
||||
| Coinbase Exchange | Oui | Oui | aucune | PLANNED | PLANNED | AUDITED |
|
||||
| Jupiter Price V3 | Oui | Oui | keyless ou Free key | PLANNED | PLANNED | AUDITED |
|
||||
@@ -185,8 +214,8 @@ Avant la stable, les conditions d'usage et la persistance des offres gratuites d
|
||||
| cadence locale fixe représentable | PASS |
|
||||
| burst documenté supérieur à la cadence moyenne représentable | PASS |
|
||||
| limite dynamique keyless représentable | PASS |
|
||||
| `429` classé | PLANNED |
|
||||
| `Retry-After` honoré lorsqu'exploitable | PLANNED |
|
||||
| `429` classé | PASS |
|
||||
| `Retry-After` honoré lorsqu'exploitable | PASS |
|
||||
| cooldown expose prochain instant admissible | PLANNED |
|
||||
| refresh all ne lance que les providers éligibles | PLANNED |
|
||||
| provider en cooldown ne bloque pas les autres | PLANNED |
|
||||
@@ -197,36 +226,36 @@ Avant la stable, les conditions d'usage et la persistance des offres gratuites d
|
||||
|
||||
## 7. Numeric safety
|
||||
|
||||
| Cas | Statut |
|
||||
|-----------------------------------------------------|---------|
|
||||
| décimal string valide | PASS |
|
||||
| JSON number valide sans passage canonique par `f64` | PLANNED |
|
||||
| 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 |
|
||||
| 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 | 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 |
|
||||
| `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
|
||||
|
||||
Reference in New Issue
Block a user