Files
khadhroony-solana-project/deltas/0.2.12/pre.004.md
2026-08-27 10:02:46 +02:00

286 lines
9.0 KiB
Markdown

<!-- file: deltas/0.2.12/pre.004.md -->
<!-- version: 1 -->
# Delta `0.2.12-pre.004` — runtime prix, registry rows et DTOs
## 1. Base requise
Cette tranche s'applique exclusivement après :
```text
v0.2.11
+ 0.2.12-pre.001
+ 0.2.12-pre.001-fix.001
+ 0.2.12-pre.002
+ 0.2.12-pre.002-fix.001
+ 0.2.12-pre.003
+ 0.2.12-pre.003-fix.001
```
Le retour opérateur du `27 août 2026` clôt `pre.003-fix.001` pour la progression de release : `cargo fmt`, audits Rust/Markdown, `cargo check --workspace`, Clippy workspace, `cargo test -p ksp-app-solprices-desk` et `cargo tauri dev` passent. Le runtime Tauri journalise le bootstrap Logging, le profil composite `public_keyless`, le profil Off-chain `public_keyless` et `provider_count=8`. `cargo test --workspace` n'est pas présent dans ce retour précis et n'est donc pas revendiqué comme exécuté.
La version workspace passe à :
```text
0.2.12-pre.4
```
Les versions `package.json` et `tauri.conf.json` de SOL Prices Desk sont synchronisées sur la même prerelease.
## 2. Responsabilité de la tranche
`pre.004` matérialise uniquement la couche applicative provider-neutral entre le `MarketPriceService` déjà construit par Config et la future UX de refresh :
```text
MarketPriceRuntime backend
état de présentation courant en mémoire uniquement
projection du registry en lignes stables
MarketPriceRuntimeStatusDto
MarketPriceProviderRowDto
commande list_market_prices
états frontend loading / empty / table
projection initiale sans observation ni prix
```
La tranche n'appelle ni `MarketPriceService::refresh`, ni `refresh_many`, ni `refresh_all`. Aucun bouton de refresh ou scheduler n'est introduit avant les tranches prévues.
## 3. Ownership du runtime prix
`AppState` possède désormais un `MarketPriceRuntime`. Celui-ci retient :
```text
OffchainTransportStartup
-> ResolvedOffchainTransportConfig
-> MarketPriceService
presentation: Mutex<...>
-> une entrée par provider_id opaque
-> loading bool
-> dernière observation optionnelle
```
La présentation n'est persistée ni dans Config, ni dans Store, ni sur le filesystem frontend, ni dans `localStorage`/`sessionStorage`.
L'inventaire initial est dérivé du `MarketPriceService::registry()` détaché. Chaque ligne commence avec :
```text
loading = false
observation = None
price = None
refreshed = false
```
L'availability initiale reste celle possédée par Off-chain Transport (`Ready`, `Disabled`, etc.).
## 4. DTOs provider-neutral
`MarketPriceRuntimeStatusDto` remplace le nom bootstrap générique précédent et expose uniquement :
```text
application/config/composite/logging/offchain metadata sûrs
provider_count
ready_provider_count
unavailable_provider_count
startup_diagnostic sûr
```
`MarketPriceProviderRowDto` expose uniquement la projection générique décidée par le plan :
```text
provider_id opaque
display_name
pair = SOL/USD
semantics générique
auth_mode générique
availability générique
loading
refreshed
price optionnel
provider_timestamp optionnel
received_at optionnel
retry_at optionnel
```
Le prix exact traverse l'IPC sous forme de `Option<String>` issue de `MarketPriceDecimal::to_canonical_string()`. Les timestamps traversent eux aussi sous forme de chaînes de millisecondes Unix afin de ne pas introduire de perte d'entier JavaScript. Aucun `f64` n'est une vérité IPC.
Les enums Off-chain `#[non_exhaustive]` sont projetés en codes génériques bornés avec fallback `unknown`; aucune enum provider-specific n'est exposée au frontend.
## 5. Commande d'inventaire
La nouvelle commande Tauri centralisée est :
```text
list_market_prices
```
Elle n'accepte aucun argument et retourne :
```text
Vec<MarketPriceProviderRowDto>
```
Elle ne déclenche aucun réseau. L'ordre des lignes suit l'ordre stable du registry Off-chain.
La surface command reste donc à cette tranche :
```text
emit_frontend_log
get_runtime_status
list_market_prices
splash_frontend_ready
```
Les commandes `refresh_market_price`, `refresh_market_prices` et `refresh_all_market_prices` restent absentes par contrat.
## 6. Frontend initial
La vue `Prices` remplace le placeholder de `pre.003` par trois états explicites :
```text
loading
empty
table provider-neutral
```
La table initiale affiche les capacités et l'availability du registry. Comme aucun refresh n'a encore eu lieu, les prix et timestamps d'observation s'affichent comme absents.
La tranche n'ajoute aucun bouton Refresh. La finalisation responsive/interactions/DataTable reste propriétaire de `pre.007`.
Diagnostics ajoute les comptes total/ready/unavailable sans exposer endpoint, credential, header ou payload provider.
## 7. Logging frontend/backend
`KSP-APP-027` reste appliqué :
```text
navigation/clic utilisateur debug
requête IPC debug via invokeKsp
fin IPC trace
chargement registry start/end trace
rendu des lignes trace avec row_count uniquement
erreur de projection/chargement warn/error sûr
```
Aucun log ne sérialise le prix, la row DTO complète, une API key, un header ou une réponse provider.
## 8. Dépendances et boundaries
SOL Prices Desk ajoute une dépendance directe à `ksp-offchain-transport-lib` parce que la couche application consomme désormais ses types publics génériques de registry/observation.
Cette dépendance ne donne lieu à aucune connaissance provider-specific :
```text
aucun SDK provider
aucun reqwest direct app
aucun fetch frontend
aucune URL/header/API key dans IPC
aucune branche CoinGecko/Kraken/etc.
aucun limiter/retry/sleep provider dans app
```
Config reste propriétaire de la construction du service et des secrets.
## 9. Tests et canaris
Les tests ajoutés/étendus couvrent :
```text
codes génériques auth/availability/semantics
projection initiale sans observation
projection exacte d'un decimal 123.4500 -> "123.45"
provider_timestamp / received_at / retry_at distincts
MarketPriceRuntime présent à partir de pre.004
commande list_market_prices centralisée dans tauri.rs
absence des trois commandes de refresh
états frontend loading/empty/table
aucune conversion parseFloat/Number du prix
aucun reqwest direct dans la crate app
logging registry sans sérialisation métier
```
Les bindings TS-RS restent générés par les tests et ne sont pas versionnés.
## 10. Fichiers ajoutés
```text
crates/ksp-app-solprices-desk/src/market_price_runtime.rs
crates/ksp-app-solprices-desk/unit_tests/market_price_runtime.rs
deltas/0.2.12/pre.004.md
```
## 11. Fichiers modifiés
```text
Cargo.toml
crates/ksp-app-solprices-desk/Cargo.toml
crates/ksp-app-solprices-desk/package.json
crates/ksp-app-solprices-desk/tauri.conf.json
crates/ksp-app-solprices-desk/frontend/main.html
crates/ksp-app-solprices-desk/frontend/ts/main.ts
crates/ksp-app-solprices-desk/src/app_state.rs
crates/ksp-app-solprices-desk/src/dto_common.rs
crates/ksp-app-solprices-desk/src/lib.rs
crates/ksp-app-solprices-desk/src/tauri.rs
crates/ksp-app-solprices-desk/tests/desktop_contract.rs
crates/ksp-app-solprices-desk/tests/desktop_security.rs
docs/plans/019-V0_2_12_SOL_PRICES_DESK_PLAN.md
docs/validation/015-V0_2_12_SOL_PRICES_DESK.md
```
## 12. Fichiers volontairement inchangés
```text
crates/ksp-offchain-transport-lib/**
crates/ksp-config-lib/**
crates/ksp-app-wallet-desk/**
crates/ksp-app-config-desk/**
README.md
ROADMAP.md
CHANGELOG.md
prompts/017-V0_2_12_START_PROMPT.md
```
Aucun provider, wire REST, rate limit ou Config document n'est modifié.
## 13. Validations exécutées dans le sandbox
Après matérialisation du code avant écriture du delta :
```text
python3 scripts/audit_rust_workspace_rules.py
General Rust rule audit: clean
Rust export completeness audit: 0 candidate(s)
KSP workspace Rust rule audit: clean
```
Après écriture du présent delta :
```text
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.2.12
Markdown table audit: clean (143 table(s), 113 file(s))
validation JSON package.json / tauri.conf.json
JSON validation: clean
```
Le sandbox ne possède pas `cargo`; aucune commande Cargo n'est déclarée PASS localement.
## 14. Gate opérateur attendu
```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.12
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-app-solprices-desk
cargo test --workspace
(cd crates/ksp-app-solprices-desk && cargo tauri dev)
```
Le parcours Tauri attendu doit afficher huit lignes provider-neutral pour le profil `public_keyless`, avec availability initiale mais sans prix ni timestamp d'observation, et sans effectuer de refresh réseau. Diagnostics doit afficher `provider_count=8` avec les comptes ready/unavailable cohérents.
## 15. Questions ouvertes
Aucune. Si le gate devient propre, `pre.005` peut brancher exclusivement le refresh individuel sur ce runtime sans modifier le format Config ni les adapters providers.