v0.2.12-pre.007

This commit is contained in:
2026-08-27 14:35:18 +02:00
parent 7d0fe8ac5f
commit 2042482592
13 changed files with 764 additions and 95 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/019-V0_2_12_SOL_PRICES_DESK_PLAN.md -->
<!-- version: 12 -->
<!-- version: 13 -->
# Plan `0.2.12` — SOL Prices Desk + intégration prix Wallet Desk
@@ -526,15 +526,15 @@ Le gate de `pre.005` confirme que le refresh individuel fonctionne et que le run
### `pre.006` — Refresh multiple et global
**Statut : implémenté ; gate opérateur à confirmer.**
**Statut : réalisé ; gate opérateur Cargo/workspace et parcours manuel multi-refresh intégralement PASS.**
Ajout de `refresh_market_prices` et `refresh_all_market_prices` sur les APIs génériques `MarketPriceService::refresh_many`/`refresh_all`. La sélection frontend est reconstruite dans l'ordre courant des rows, le backend valide atomiquement doublons/IDs inconnus/conflits `in_flight`, marque toutes les lignes concernées `loading`, relâche le mutex de présentation pendant l'`await`, puis applique les outcomes dans leur ordre déterministe. `MarketPriceRefreshManyRequestDto` transporte uniquement les IDs opaques et `MarketPriceRefreshResultDto` retourne les rows affectées avec `requested_count`/`refreshed_count`. Les cooldown/retry deadlines restent les projections Off-chain existantes ; aucun polling, sleep consommateur, fallback automatique ou consensus provider n'est introduit.
### `pre.007` — UX et instrumentation SOL Prices Desk
**Statut : planifié.**
**Statut : implémenté ; gate opérateur à confirmer.**
Finalisation de la table responsive, interactions utilisateur, états visuels, instrumentation frontend/backend et polish du Desk. La tranche reste manuelle : aucun auto-refresh ni persistance navigateur n'est ajouté.
Finalisation de la table responsive sans changer le contrat de dispatch : résumé providers/ready/observed/attention/refreshing, header sticky, colonnes secondaires adaptatives, badges génériques d'auth/semantics/availability, prix exact conservé en String et timestamps présentés à la fois sous forme humaine et en millisecondes exactes. `provider_timestamp = None` est rendu explicitement comme `Not supplied`, sans substitution par `received_at`. La sélection gagne un contrôle global et `Clear selection`, uniquement frontend. Chaque nouveau contrôle est journalisé en `debug`; les rendus et comptes sûrs restent en `trace`. Les wrappers Tauri journalisent les échecs avec seulement `command`, `error_domain` et `error_code`. Aucun prix, timestamp, payload provider, URL, header ou credential n'entre dans les logs. La tranche reste manuelle : aucune nouvelle commande métier, aucun auto-refresh, scheduler ou persistance navigateur n'est ajouté.
### `pre.008` — Hardening SOL Prices Desk
@@ -590,7 +590,7 @@ Préparation du prompt de la release suivante, de `CHANGELOG.md` et de `ROADMAP.
Mécanique de publication stable uniquement, après validation de la dernière prerelease et vérification de la cohérence de release. Aucun défaut fonctionnel ou documentaire ne doit être absorbé par `rel.001`.
Le point de packaging transversal de `pre.003` est désormais fermé. Le prochain risque fonctionnel est borné aux refresh `pre.005`/`pre.006`, sans remettre en cause le découpage souple ni les responsabilités documentaires de clôture.
Le packaging transversal et les refresh manuels du Price Desk sont désormais fermés par les gates opérateur jusquà `pre.006`. Après le polish `pre.007`, le prochain risque fonctionnel est borné au hardening `pre.008` avant louverture du couloir Wallet Desk `pre.009+`, sans remettre en cause le découpage souple ni les responsabilités documentaires de clôture.
## 20. Critères de sortie `pre.001`

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/015-V0_2_12_SOL_PRICES_DESK.md -->
<!-- version: 11 -->
<!-- version: 12 -->
# Validation `0.2.12` — SOL Prices Desk + intégration Wallet Desk
@@ -51,11 +51,12 @@ NOT RUN commande non exécutée dans le contexte indiqué
| splash Price Desk | lifecycle KSP commun | PASS |
| main shell Price Desk | header/navigation KSP | PASS |
| table providers | registry provider-neutral, ordre stable | PASS |
| table responsive UX | sticky/badges/timestamps distincts | PASS |
| prix exact | String issue de `MarketPriceDecimal` | PASS |
| availability/fraîcheur | état générique + timestamps réels | PASS |
| refresh row | `MarketPriceService::refresh` | PASS |
| refresh selected/many | `MarketPriceService::refresh_many` | PENDING |
| refresh all | `MarketPriceService::refresh_all` | PENDING |
| refresh selected/many | `MarketPriceService::refresh_many` | PASS |
| refresh all | `MarketPriceService::refresh_all` | PASS |
| Diagnostics | profils/counts sûrs seulement | PASS |
| Wallet price panel | Dashboard compact provider-neutral | PENDING |
| auto-refresh | aucun scheduler/polling | OUT |
@@ -63,17 +64,17 @@ NOT RUN commande non exécutée dans le contexte indiqué
## 4. DTO/command matrix
| Contrat | Entrée/sortie sûre | Statut |
|----------------------------------------|--------------------------------------------------------------------|---------|
| `MarketPriceRuntimeStatusDto` | profiles/counts sans secret | PASS |
| `MarketPriceProviderRowDto` | ID/display/pair/semantics/auth/availability/price/timestamps/retry | PASS |
| single refresh direct | provider_id opaque seulement | PASS |
| `MarketPriceRefreshManyRequestDto` | liste bornée dIDs opaques | PENDING |
| `MarketPriceRefreshResultDto` | rows/outcome classifiés | PENDING |
| runtime/list/refresh/many/all commands | aucun URL/header/API key/body | PENDING |
| TS-RS exports | bindings générés non versionnés | PASS |
| provider-specific type dans IPC | interdit | OUT |
| prix `f64` comme vérité IPC | interdit | OUT |
| Contrat | Entrée/sortie sûre | Statut |
|----------------------------------------|--------------------------------------------------------------------|--------|
| `MarketPriceRuntimeStatusDto` | profiles/counts sans secret | PASS |
| `MarketPriceProviderRowDto` | ID/display/pair/semantics/auth/availability/price/timestamps/retry | PASS |
| single refresh direct | provider_id opaque seulement | PASS |
| `MarketPriceRefreshManyRequestDto` | liste dIDs opaques ; borne hostile à durcir en `pre.008` | PASS |
| `MarketPriceRefreshResultDto` | rows/outcome classifiés | PASS |
| runtime/list/refresh/many/all commands | aucun URL/header/API key/body | PASS |
| TS-RS exports | bindings générés non versionnés | PASS |
| provider-specific type dans IPC | interdit | OUT |
| prix `f64` comme vérité IPC | interdit | OUT |
## 5. Config/composite matrix
@@ -94,35 +95,36 @@ NOT RUN commande non exécutée dans le contexte indiqué
## 6. Provider-agnostic boundary matrix
| Canari | Attendu | Statut |
|--------------------------------------------|------------------|---------|
| app dépend du service/registry générique | oui | PASS |
| branche `coingecko`/`kraken`/etc. dans app | aucune | PASS |
| SDK provider dans app | aucun | PASS |
| reqwest/provider fetch frontend | aucun | PASS |
| endpoint/header/API key dans DTO | aucun | PASS |
| rate limiter/sleep/retry provider dans app | aucun | PASS |
| refresh many ordre service | préservé | PENDING |
| semantics provider-neutral visibles | oui, sans fusion | PASS |
| prix canonique/fallback/moyenne | aucun | OUT |
| Canari | Attendu | Statut |
|--------------------------------------------|------------------|--------|
| app dépend du service/registry générique | oui | PASS |
| branche `coingecko`/`kraken`/etc. dans app | aucune | PASS |
| SDK provider dans app | aucun | PASS |
| reqwest/provider fetch frontend | aucun | PASS |
| endpoint/header/API key dans DTO | aucun | PASS |
| rate limiter/sleep/retry provider dans app | aucun | PASS |
| refresh many ordre service | préservé | PASS |
| semantics provider-neutral visibles | oui, sans fusion | PASS |
| prix canonique/fallback/moyenne | aucun | OUT |
## 7. Security matrix
| Risque/canari | Attendu | Statut |
|--------------------------------|----------------------------------------------|---------|
| URL arbitraire depuis frontend | impossible par contrat command | PASS |
| extraction API key/header | aucune projection/log | PASS |
| provider_id inconnu | erreur KSP sûre | PASS |
| batch duplicate/oversized | rejet avant dispatch | PENDING |
| refresh spam | limites/cooldown Off-chain toujours actifs | PASS |
| stale observation | timestamps/état distingués | PASS |
| double-click race | in-flight/order contrôlés | PENDING |
| close pendant refresh | aucune persistance/sûreté frontend requise | PENDING |
| CWD/resource confusion | canaris propres à chaque app | PENDING |
| Price Desk capabilities | `core:default`, `tracing:default` uniquement | PASS |
| plugin dialog Price Desk | absent | PASS |
| frontend sensitive logging | action/ID/count/code seulement | PASS |
| Wallet VIEW/OWNER/secrets | non-régression | PENDING |
| Risque/canari | Attendu | Statut |
|--------------------------------|-------------------------------------------------|---------|
| URL arbitraire depuis frontend | impossible par contrat command | PASS |
| extraction API key/header | aucune projection/log | PASS |
| provider_id inconnu | erreur KSP sûre | PASS |
| batch duplicate | rejet avant dispatch | PASS |
| batch oversized | borne hostile applicative à durcir en `pre.008` | PENDING |
| refresh spam | limites/cooldown Off-chain toujours actifs | PASS |
| stale observation | timestamps/état distingués | PASS |
| double-click race | in-flight/order contrôlés | PASS |
| close pendant refresh | aucune persistance/sûreté frontend requise | PENDING |
| CWD/resource confusion | canaris propres à chaque app | PENDING |
| Price Desk capabilities | `core:default`, `tracing:default` uniquement | PASS |
| plugin dialog Price Desk | absent | PASS |
| frontend sensitive logging | action/ID/count/code seulement | PASS |
| Wallet VIEW/OWNER/secrets | non-régression | PENDING |
## 8. Wallet integration matrix
@@ -529,4 +531,37 @@ python3 scripts/audit_markdown_tables.py README.md ... deltas PASS
cargo fmt/check/clippy/test NOT RUN — cargo indisponible dans le sandbox
```
Les lignes `refresh selected/many`, `refresh all`, `MarketPriceRefreshManyRequestDto`, `MarketPriceRefreshResultDto`, ordre many, batch duplicate/oversized et double-click race de la matrice générale restent `PENDING` jusqu'au gate opérateur de cette tranche.
Le gate opérateur de `pre.006` fourni le 2026-08-27 ferme ensuite cette tranche : audits, `cargo check`, Clippy, test ciblé et `cargo test --workspace` passent, `cargo tauri dev` démarre correctement et le parcours manuel confirme que le multi-refresh fonctionne. Les lignes `refresh selected/many`, `refresh all`, les deux DTOs batch, l'ordre many, le rejet des doublons et le conflit `in_flight` passent donc à `PASS`. La borne hostile d'une requête batch artificiellement surdimensionnée reste volontairement `PENDING` pour le hardening `pre.008`.
## 23. Gate `0.2.12-pre.007`
La tranche finalise l'UX et l'instrumentation sans modifier le moteur Off-chain ni ajouter de nouvelle commande métier :
```text
résumé Providers / Ready / Observed / Attention / Refreshing implémenté
header table sticky + scroll horizontal borné implémenté
Semantics/Auth secondaires adaptatifs implémenté
availability générique par badge implémenté
prix exact String inchangée, aucune coercition float
timestamp provider absent Not supplied, jamais remplacé par received_at
timestamps présents local/ISO + millisecondes exactes visibles
select all / clear selection frontend uniquement
clics select-all / clear / row / selected / all / navigation debug
rendu table + comptes sûrs trace
échec command backend command + error_domain + error_code seulement
nouvelle command IPC aucune
prix/timestamp/payload/URL/header/API key dans les logs aucun
auto-refresh / setInterval / setTimeout / requestAnimationFrame absent
localStorage / sessionStorage / fetch / XMLHttpRequest absent
```
Canaris statiques ajoutés : table responsive et états génériques, absence de coercition du prix, instrumentation de tous les contrôles, projection sûre des erreurs backend et maintien du fonctionnement exclusivement manuel.
Validations sandbox après matérialisation :
```text
python3 scripts/audit_rust_workspace_rules.py PASS
python3 scripts/audit_markdown_tables.py README.md ... deltas PASS
TypeScript syntax transpile main.ts PASS
cargo fmt/check/clippy/test NOT RUN — cargo indisponible dans le sandbox
```