0.3.15-pre.015

This commit is contained in:
2026-09-18 21:06:58 +02:00
parent b266019ea8
commit 582a286baa
9 changed files with 323 additions and 54 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/036-V0_3_15_RAW_TRANSACTION_INGEST_DESK_PLAN.md -->
<!-- version: 23 -->
<!-- version: 24 -->
# Plan v0.3.15 — Raw Transaction Ingest Desk
@@ -342,7 +342,7 @@ La documentation Helius actuelle indique que `blockSubscribe` n'est pas support
| Store open / network / partage `Arc<Store>` | aucun gap | Store + app | `ksp-store-lib` suffit |
| Lifecycle / stop / snapshots Worker | aucun gap | Worker + app | handles publics existants |
| Backfill / historical repair | hors scope | Job Backfill | aucune orchestration automatique |
| Taille release | pas de split de release | plan | forecast étendu jusquà `pre.017` |
| Taille release | pas de split de release | plan | forecast étendu jusquà `pre.018` |
La release n'est pas rescindée. Le gap WS est petit, clairement propriétaire et testable. En revanche, le forecast doit être étendu pour ne pas fusionner Transport, Config, Worker et scaffold UI dans une même tranche.
@@ -668,7 +668,7 @@ Le build Tauri final reste un gate tardif et ne remplace pas les tests runtime.
## 20. Forecast recalibré — prereleases souples
Le forecast initial `pre.002 -> pre.013` est désormais étendu jusqu'à `pre.017`. La cause n'est pas une inflation UI : c'est la découverte d'un contrat WS capability manquant qui doit être fermé proprement dans Transport, Config puis Worker avant consommation par la Desk.
Le forecast initial `pre.002 -> pre.013` est désormais étendu jusqu'à `pre.018`. La cause n'est pas une inflation UI : c'est la découverte d'un contrat WS capability manquant qui doit être fermé proprement dans Transport, Config puis Worker avant consommation par la Desk.
Le forecast reste volontairement souple. Chaque prerelease possède une sous-section directement éditable ; lorsqu'un correctif est nécessaire, il est ajouté sous la prerelease concernée avec un titre `#### pre.NNN-fix.MMM`. Les responsabilités de clôture `gate technique/live -> réconciliation documentaire -> préparation de publication` restent séparées.
@@ -849,15 +849,15 @@ Budget cible : une tranche hardening.
### `pre.013` — Yellowstone Block hydration backpressure
**État : implémenté, gate opérateur requis.** Le live de `pre.012-fix.004` a reproduit deux `grpc_backpressure_overflow` Mainnet environ 79 s puis 81 s après démarrage Yellowstone. Les WARN Transport précèdent les Stop opérateur de plusieurs secondes : la cause est donc le couplage historique `Block update -> getBlock HTTP -> admission de toutes les transactions -> lecture de l'update suivante`, et non la sémantique Stop. Conformément à `VER-LIFECYCLE-010`, ce défaut du couloir acquisition antérieur ouvre une nouvelle prerelease dédiée au lieu d'un `pre.012-fix.005`.
**État : implémenté ; amélioration confirmée, saturation prolongée rouverte en `pre.015`.** Le live de `pre.012-fix.004` a reproduit deux `grpc_backpressure_overflow` Mainnet environ 79 s puis 81 s après démarrage Yellowstone. Les WARN Transport précèdent les Stop opérateur de plusieurs secondes : la cause initiale est donc le couplage historique `Block update -> getBlock HTTP -> admission de toutes les transactions -> lecture de l'update suivante`, et non la sémantique Stop. Conformément à `VER-LIFECYCLE-010`, ce défaut du couloir acquisition antérieur a ouvert une prerelease dédiée au lieu d'un `pre.012-fix.005`.
Le mode Yellowstone Block reçoit désormais une partition déterministe des budgets d'hydration déjà possédés par le Worker. Les slots gRPC sont placés dans un coordinateur privé borné ; plusieurs `getBlock` peuvent progresser concurremment jusqu'au quota `in-flight`, et chaque tâche porte aussi l'admission complète de son bloc avant settlement du slot. La boucle source continue de consommer `session.next_update()` tant qu'une capacité pending existe. Aucun changement de capacité Transport, aucune queue non bornée et aucun drop silencieux ne masquent une surcharge durable.
Le mode Yellowstone Block reçoit désormais une partition déterministe des budgets d'hydration déjà possédés par le Worker. Les slots gRPC sont placés dans un coordinateur privé borné ; plusieurs `getBlock` peuvent progresser concurremment jusqu'au quota `in-flight`, et chaque tâche porte aussi l'admission complète de son bloc avant settlement du slot. La boucle source continue de consommer `session.next_update()` tant qu'une capacité pending existe. Cette correction supprime le couplage strictement séquentiel, mais un live plus long a ensuite prouvé qu'une saturation durable des bornes Worker puis Transport restait possible ; cette seconde responsabilité est isolée en `pre.015`.
Budget cible : une tranche corrective acquisition/throughput, suivie d'un live Mainnet prolongé.
Budget cible : une tranche corrective acquisition/throughput, suivie du complément Transport de `pre.015`.
### `pre.014` — convergence inter-provider + completeness/security cross-layer
**État : implémenté, gate/live opérateur requis.** Le gate de `pre.013` compile et teste proprement le workspace et le live ne reproduit plus `grpc_backpressure_overflow`. Un unique `content_conflict` Mainnet apparaît toutefois entre HTTP Block Polling (`solana_mainnet_public`) et Yellowstone hydraté par HTTP (`publicnode_solana_mainnet_rpc`), tous deux en `confirmed`. Le diagnostic `pre.012-fix.004` prouve que `slot`, `block_time`, transaction wire, version et `transactionIndex` sont identiques ; seule la valeur `meta.logMessages` diverge.
**État : implémenté et gate opérateur PASS après `pre.014-fix.003`.** Le premier live après `pre.013` n'a pas reproduit immédiatement `grpc_backpressure_overflow`, mais un unique `content_conflict` Mainnet est apparu entre HTTP Block Polling (`solana_mainnet_public`) et Yellowstone hydraté par HTTP (`publicnode_solana_mainnet_rpc`), tous deux en `confirmed`. Le diagnostic `pre.012-fix.004` a prouvé que `slot`, `block_time`, transaction wire, version et `transactionIndex` étaient identiques ; seule la valeur `meta.logMessages` divergeait.
La tranche ne normalise ni n'ignore `logMessages`. Elle ajoute un diagnostic de convergence sûr permettant de distinguer un fork `confirmed` d'une divergence de représentation/provider : chaque `getBlock` réussi des deux routes journalise le slot et un fingerprint SHA-256 irréversible de l'identité de bloc (`blockhash`, `previousBlockhash`, `parentSlot`, `blockHeight`) sans exposer les blockhash. En cas de conflit RAW, Store journalise désormais les slots exacts et une forme bornée de la divergence `logMessages` : état absent/null/array, cardinalités, premier index divergent, type statique de la première ligne divergente, longueur, relation de préfixe et présence d'un marqueur de troncature. Aucun texte de log distant n'est copié.
@@ -867,19 +867,29 @@ Les canaris de clôture continuent de vérifier dependency firewalls, API publiq
Budget cible : une tranche de convergence/completeness cross-layer, sans modification de la politique fail-closed.
### `pre.015` — gate technique/live final
### `pre.015` — Yellowstone sustained gRPC backpressure
**État : en cours.** Le live prolongé de `pre.014-fix.001` a reproduit `Yellowstone subscribe update queue overflowed` à `22:09:54`, alors que le Stop opérateur n'est demandé qu'à `22:12:03`. `pre.013` a donc amélioré le débit sans fermer le défaut durable : lorsque les `256` slots pending Worker sont pleins, le Worker suspend `next_update()` ; la queue Transport bornée de `256` updates finit ensuite par se remplir et son ancien `try_send` transforme cette pression locale en faute terminale `grpc_backpressure_overflow`.
La correction conserve toutes les bornes et n'augmente aucune queue. L'acteur Yellowstone Transport remplace uniquement l'envoi non bloquant de l'update décodée par un `send().await` sélectionné avec le signal de shutdown prioritaire. Une queue pleine suspend ainsi le polling du stream Tonic et propage la backpressure au flux gRPC/HTTP/2 ; lorsque le consumer libère une place, la livraison reprend. Aucun update n'est dropé et aucune allocation non bornée n'est introduite. `grpc_backpressure_overflow` reste un code public valide pour les queues de mutations de requête synchrones/fail-fast et les bornes de message ; seule la saturation de la queue d'updates reçues cesse d'être un terminal local.
Le gate live doit dépasser la durée de reproduction précédente : Yellowstone Mainnet seul puis Yellowstone + HTTP Block Polling doivent chacun rester actifs au moins 10 minutes, sans WARN `Yellowstone subscribe update queue overflowed`, sans `grpc_backpressure_overflow` et avec Stop ciblé terminant `Stopped`. Une vraie rupture distante reste traitée par le reconnect/replay borné existant.
Budget cible : une tranche corrective Transport/acquisition, sans croissance d'API publique.
### `pre.016` — gate technique/live final
Exécuter le workspace complet, Clippy strict, suites ciblées, graphes/duplicates, smokes réellement accessibles et build frontend/Tauri final. Aucun nouveau scope métier.
Budget cible : une tranche technique.
### `pre.016` — réconciliation documentaire finale
### `pre.017` — réconciliation documentaire finale
Réconcilier plan, validation, README/USAGE et documents durables réellement affectés. Ne pas modifier CHANGELOG, ROADMAP ni le prompt suivant.
Budget cible : une tranche documentaire.
### `pre.017` — préparation de publication
### `pre.018` — préparation de publication
Préparer le prompt suivant, CHANGELOG, ROADMAP et la mécanique minimale de version/delta. Aucun rattrapage fonctionnel ou documentaire durable.
@@ -922,7 +932,7 @@ aucun gap Store / HTTP / lifecycle Worker essentiel
capability WS fine = gap lower-layer réel à fermer avant UI
Helius standard WS != Helius transactionSubscribe
aucune route rendue disponible à partir d'un exemple Config ou du provider name
forecast recalibré jusqu'à pre.017
forecast recalibré jusqu'à pre.018
```
`pre.002` doit donc commencer par le contrat Transport de capabilities WS, et non par le scaffold Tauri.