v0.3.12-pre.012

This commit is contained in:
2026-09-09 23:24:20 +02:00
parent 474b894d1c
commit 79e278064d
10 changed files with 493 additions and 193 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/004-COMPONENT_INVENTORY.md -->
<!-- version: 38 -->
<!-- version: 39 -->
# Inventaire initial des composants KSP
@@ -46,7 +46,7 @@ Ce document maintient l'inventaire synthétique des composants retenus ou presse
| Store Desk | `ksp-app-store-desk` | app | Implémenté | `0.3.8` | inspection RAW read-only Transaction/Account/Observation via façade Store |
| RAW transaction common | `ksp-raw-transaction-lib` | lib | Implémenté | `0.3.10` | canonicalisation/wire RAW Transaction v1 source-neutral partagé entre producteurs |
| Worker lifecycle | `ksp-worker-api` | API | Implémenté | `0.3.9` | lifecycle/health/progression génériques des services continus |
| RAW transaction worker | `ksp-worker-raw-transaction-ingest-lib` | worker/lib | Implémenté | `0.3.11`, extensions `0.3.12+` | fondation source-neutral, puis sources live multi-source/recovery |
| RAW transaction worker | `ksp-worker-raw-transaction-ingest-lib` | worker/lib | Implémenté | `0.3.11`, live `0.3.12` | fondation + Yellowstone productif, hydration HTTP, frontier/reconnect run-local |
| RAW ingest Desk | `ksp-app-raw-transaction-ingest-desk` | app | Retenu | `0.3.15` | choix/supervision dune ou plusieurs sources/méthodes sans réimplémenter le worker |
| STRUCTURAL job | nom à fixer | job/lib | Retenu | couche STRUCTURAL | normalisation Solana générique RAW -> STRUCTURAL bornée/rejouable |
| STRUCTURAL worker | nom à fixer | worker/lib | Retenu | fin couche STRUCTURAL | backlog RAW -> STRUCTURAL continu |

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/005-DEPENDENCY_GRAPH.md -->
<!-- version: 27 -->
<!-- version: 28 -->
# Graphe de dépendances KSP
@@ -419,9 +419,10 @@ Il remplit RAW et ne décode aucun programme. Il ne dépend pas de Config : la c
ksp-worker-api
-> ksp-core-lib
ksp-worker-raw-transaction-ingest-lib # fondation source-neutral matérialisée
ksp-worker-raw-transaction-ingest-lib # fondation + première source live matérialisées
-> ksp-core-lib
-> ksp-logging-lib
-> ksp-onchain-transport-lib # Yellowstone subscribe + HTTP getTransaction observed
-> ksp-raw-transaction-lib
-> ksp-store-lib # default-features = false ; aucun backend imposé
-> ksp-worker-api
@@ -432,9 +433,9 @@ ksp-worker-control-lib # composant retenu, non matérialis
-> ksp-core-lib
```
`ksp-worker-api` est ouvert en `0.3.9` comme contrat générique de services continus et ne connaît ni Solana, ni Transport, ni Store, ni Tauri. `ksp-worker-raw-transaction-ingest-lib` est son premier consumer concret : sa fondation `0.3.11` est source-neutral, possède admission/persistence/snapshots/shutdown, et ne dépend pas encore de Transport. Les adapters live sont ajoutés ensuite sans déplacer Config ni backend physique dans le Worker.
`ksp-worker-api` est ouvert en `0.3.9` comme contrat générique de services continus et ne connaît ni Solana, ni Transport, ni Store, ni Tauri. `ksp-worker-raw-transaction-ingest-lib` est son premier consumer concret : sa fondation `0.3.11` possède admission/persistence/snapshots/shutdown ; l'extension live `0.3.12` ouvre l'edge direct vers `ksp-onchain-transport-lib` pour une source Yellowstone standard et l'hydration HTTP `getTransaction`. Config et le backend physique restent hors du Worker.
La cible live n'est pas « un worker WebSocket » ou « un worker gRPC ». Les tranches de sources peuvent ajouter `ksp-onchain-transport-lib` lorsque l'adapter productif le nécessite et composer des stratégies alternatives, complémentaires (discovery + hydration), redondantes entre providers ou spécialisées live/catch-up/gap-repair. La transaction canonique reste identifiée indépendamment de la source et chaque acquisition utile conserve sa propre observation/provenance Store.
La verticale actuelle n'est ni « un worker WebSocket » ni un moteur historique : `RawTransactionIngestRuntimeResources` contient exactement une source Yellowstone validée, les signaux transactionnels sont hydratés par HTTP avant Common RAW, et `BlockMeta`/`Slot` restent continuity-only. Reconnect, `from_slot` et `SubscribeReplayInfo` restent propriétaires de Transport ; le Worker observe leur projection sûre et fault sur un gap de rétention prouvé sans appeler le Job Backfill. Les extensions multi-source restent ultérieures.
RAW worker puis STRUCTURAL worker sont introduits à la fin de leur couche respective, lorsque persistence/backlog sont disponibles. Le traitement RAW -> STRUCTURAL borné est porté par un STRUCTURAL job distinct du service continu. Les workers DECODED/DOMAIN sont introduits avec les groupes Program concernés plutôt que tous anticipés en bloc.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md -->
<!-- version: 18 -->
<!-- version: 19 -->
# Acquisition, workers, jobs et pipelines spécialisés
@@ -102,7 +102,7 @@ ksp-worker-raw-transaction-ingest-lib
Sa responsabilité est l'acquisition **continue** de `RawTransaction` puis la persistance via `ksp-store-lib`. Il ne décode pas de Program, ne possède aucun SQL/backend physique et ne fait pas de la source réseau une partie de l'identité canonique de transaction.
La fondation matérialisée possède déjà le lifecycle continu, les settings techniques bornés, la queue d'admission privée bornée, la canonicalisation Common RAW, la persistance atomique backend-neutral, les snapshots latest-value et le shutdown borné. Elle ne possède encore aucune source réseau productive et n'a donc aucun edge Transport ; les adapters live/catch-up complètent ensuite ce même Worker sans ouvrir de second runtime parallèle.
Le Worker matérialisé possède le lifecycle continu, les settings techniques bornés, la queue d'admission privée, la canonicalisation Common RAW, la persistance atomique backend-neutral, les snapshots latest-value et le shutdown borné. Sa première source productive est désormais Yellowstone standard + hydration HTTP `getTransaction`, injectée par `RawTransactionIngestRuntimeResources` sans lecture Config interne. `Transaction`, `TransactionStatus` et les transactions de `Block` deviennent des signaux coalescés puis hydratés ; `BlockMeta` et `Slot` restent continuity-only. Le Worker n'ouvre pas un second runtime parallèle et n'expose toujours aucune API publique d'enqueue.
Le modèle cible n'est pas :
@@ -131,18 +131,13 @@ normalisation RawTransaction commune
ksp-store-lib
```
Une stratégie peut donc être :
Le modèle général autorise des stratégies alternatives, complémentaires ou redondantes, mais la verticale productive actuelle est volontairement plus étroite : **une** source Yellowstone + **une** voie HTTP d'hydration. Ce choix n'inscrit pas le provider ou le protocole dans l'identité RAW et ne ferme pas l'architecture future multi-source.
- **alternative** : une source choisie à la place d'une autre ;
- **complémentaire** : une source découvre une signature/slot et une autre hydrate la transaction complète ;
- **redondante** : plusieurs providers/transports observent la même transaction et produisent des observations distinctes ;
- **spécialisée** : une source live, une voie d'hydration et une voie de continuité/gap repair du run peuvent coexister avec des responsabilités différentes.
Le worker ne doit pas être réduit à un enum superficiel `Http | WebSocket | Grpc`. La configuration/runtime doit exprimer les **capacités et rôles d'acquisition réellement nécessaires** : discovery, hydration, direct full transaction, live, replay/catch-up, gap repair, filtre, finality/commitment, reprise et limites.
Le reconnect/replay du stream est une capacité Transport. Le Worker conserve une processing frontier run-local sur le travail réellement observé, projette `Active/Reconnecting/Closing/Closed/Failed` et des compteurs reconnect/replay/gap, mais ne possède ni checkpoint durable ni campagne de gap repair. Un gap de rétention prouvé par Transport devient un fault `source_failed` ; une récupération historique éventuelle reste une responsabilité séparée du Job Backfill.
#### Résultat de l'audit `0.3.9`
L'audit exhaustif est synthétisé dans [`011-RAW_TRANSACTION_ACQUISITION.md`](011-RAW_TRANSACTION_ACQUISITION.md). Il confirme qu'un besoin d'acquisition Solana/provider ne remonte pas dans `ksp-worker-api` : le contrat générique reste fermé et le Worker concret porte ses propres capabilities de sources, sans les ouvrir dans sa fondation source-neutral.
L'audit exhaustif est synthétisé dans [`011-RAW_TRANSACTION_ACQUISITION.md`](011-RAW_TRANSACTION_ACQUISITION.md). Il confirme qu'un besoin d'acquisition Solana/provider ne remonte pas dans `ksp-worker-api` : le contrat générique reste fermé et le Worker concret porte ses capabilities de source dans sa propre implémentation/runtime resources.
Les familles admises par la synthèse couvrent notamment :

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/011-RAW_TRANSACTION_ACQUISITION.md -->
<!-- version: 12 -->
<!-- version: 13 -->
# Acquisition et alimentation `RawTransaction`
@@ -149,7 +149,7 @@ Il peut utiliser **HTTP, WS, Yellowstone gRPC, replay provider ou archive** si c
### 3.2 Worker Raw Transaction Ingest : acquisition continue start/stop
`ksp-worker-raw-transaction-ingest-lib` a pour rôle cible de **remplir continuellement Store à partir du moment où il est démarré**. Sa fondation source-neutral matérialise déjà le runtime, l'admission, la canonicalisation Common RAW, la persistence et les snapshots, mais aucune source réseau productive n'est encore branchée.
`ksp-worker-raw-transaction-ingest-lib` a pour rôle de **remplir continuellement Store à partir du moment où il est démarré**. Sa fondation runtime, l'admission, la canonicalisation Common RAW, la persistence et les snapshots sont complétés par une première source productive Yellowstone standard + hydration HTTP `getTransaction`.
Son contrôle métier V1 est volontairement court :
@@ -161,43 +161,49 @@ snapshot / notifications
Le caller ne lui fournit pas une signature, un `program_id`, une plage historique, une limite de campagne ou une requête de backfill. Les endpoints, réseaux, sources activées, capabilities et secrets proviennent de Config/composition, pas d'un payload métier de `start`.
La fondation actuelle, lorsqu'elle démarre sans adapter source productif, publie son lifecycle/snapshot puis reste contrôlable jusqu'au stop. Dès qu'une source interne est matérialisée, le pipeline cible devient :
Deux entrées publiques coexistent : `start` conserve la fondation sans source productive, tandis que `start_with_runtime_resources` lance une source Yellowstone supervisée. Le pipeline productif actuel est :
```text
acquiert les nouvelles transactions disponibles
hydrate les signaux live incomplets si nécessaire
normalise puis persiste RawTransaction + observations
publie ses snapshots latest-value indépendamment de leurs lecteurs
continue jusqu'à stop ou fault
Yellowstone Transaction / TransactionStatus / Block
-> signaux transactionnels source-neutral
-> coalescence bornée (network, signature, commitment)
-> HTTP getTransaction observed
-> Common RAW
-> admission centrale
-> Store
Yellowstone BlockMeta / Slot
-> continuité run-local uniquement
```
Le Worker peut ensuite utiliser **WS, Yellowstone gRPC, HTTP, block polling, provider streams ou sources EARLY** si ces capacités servent l'acquisition live. Ces sources restent internes au Worker ; le caller ne pousse pas directement des ingress dans sa queue privée.
La source est caller-composed : le Worker ne lit pas Config et ne reçoit pas de secret. `RawTransactionIngestRuntimeResources` contient actuellement exactement une source Yellowstone validée, pas encore une collection multi-source.
Il ne lance pas de campagne historique arbitraire.
### 3.3 Continuité Worker ≠ Backfill
Le Worker peut utiliser un replay ou HTTP pour **réparer une perte de continuité apparue pendant son acquisition active** :
La continuité du Worker reste limitée au run courant. Le moteur Yellowstone de Transport possède le reconnect et peut réémettre une demande `from_slot` à partir de son high-watermark observé ; le Worker ne choisit pas lui-même ce slot et ne traite pas directement `SubscribeReplayInfo`.
Les notions restent séparées :
```text
stream actif
-> gap détecté
-> replay from_slot / HTTP hydration / block recovery
-> frontier live restauré
-> reprise du flux
Transport last_observed_slot = high-watermark du stream observé
Worker processing_frontier_slot = travail source observé et non bloqué par un pending plus ancien
Store durable = persistence des acquisitions admises
blockchain completeness = non prouvée par les métriques ci-dessus
```
Cette réparation reste liée au frontier du Worker et ne transforme pas le Worker en moteur historique.
Une tentative de replay ne prouve ni succès ni continuité parfaite. Si Transport prouve qu'un slot demandé est antérieur à `first_available`, son compteur de continuity gap augmente ; le Worker projette ce gap puis termine avec un fault `source_failed`.
Inversement :
Il n'existe pas de délégation automatique vers Backfill :
```text
« récupère les transactions du programme X depuis le slot Y »
« récupère les 100 000 dernières signatures de cette adresse »
« rejoue cette plage d'archive »
gap de rétention prouvé
-> Worker fault/stop
-> aucun lancement de campagne historique
```
sont des campagnes Job Backfill.
Inversement, une demande telle que « récupère les transactions du programme X depuis le slot Y » reste une campagne `ksp-job-backfill-lib`.
### 3.4 Absence de relation Job ↔ Worker
@@ -657,13 +663,13 @@ ksp-worker-raw-transaction-ingest-lib ---> ksp-raw-transaction-lib ----> ksp-sto
ksp-job-backfill-lib --------------------> ksp-store-lib
ksp-worker-raw-transaction-ingest-lib ---> ksp-store-lib
ksp-job-backfill-lib --------------------> ksp-onchain-transport-lib
ksp-worker-raw-transaction-ingest-lib -X-> ksp-onchain-transport-lib # aucun adapter live productif encore
ksp-worker-raw-transaction-ingest-lib ---> ksp-onchain-transport-lib # Yellowstone + HTTP hydration
aucun edge Job <-> Worker
aucun edge Transport <-> ksp-raw-transaction-lib
```
Les tranches live suivantes peuvent matérialiser l'edge Worker -> Transport lorsqu'un adapter source productif le nécessite ; cet edge n'appartient pas à la fondation source-neutral.
L'edge Worker -> Transport est désormais productif, mais reste strictement contenu dans le Worker concret. `ksp-worker-api`, Common RAW et Store API ne gagnent aucune connaissance Transport/provider.
La migration doit préserver exactement les golden bytes/hash RAW v1 déjà prouvés. Aucun RAW v2 n'est justifié.
@@ -713,13 +719,13 @@ Yellowstone Transaction/Block -> signal structuré + transaction wire fidèle
RAW v1 complet -> hydration HTTP avant persistence
```
Aucun adapter productif n'est ajouté par la qualification cross-source. Conformément à `TR-C2`, l'adapter `Transport DTO -> common` demeure réservé au Worker concret. La fondation `0.3.11` est désormais matérialisée sans Transport ; le premier adapter productif reste donc une responsabilité des tranches live suivantes.
Cette qualification cross-source a préparé le contrat sans créer d'edge Common RAW -> Transport. L'extension Worker live utilise désormais cette décision conservative : Yellowstone produit des signaux structurés dans le Worker concret, puis HTTP `getTransaction` fournit le matériau RAW complet avant canonicalisation. Common RAW reste entièrement Transport-neutral.
## 14. Handoff fondation Worker `0.3.11` vers live `0.3.12` à `0.3.14`
## 14. État du Worker live après `0.3.12`
### 14.0 État fermé par la fondation source-neutral
### 14.0 Verticale matérialisée
La fondation du Worker est matérialisée avec :
La verticale productive possède :
```text
consumer de ksp-worker-api
@@ -727,26 +733,33 @@ settings réseau/Worker bornés
start/stop sur runtime Tokio caller-owned
supervision privée des tâches
mpsc central borné + backpressure
une source Yellowstone standard caller-composed
Transaction / TransactionStatus / Block -> signaux transactionnels
BlockMeta / Slot -> continuity-only
coalescence bornée par network/signature/commitment
HTTP getTransaction observed pour hydration
canonicalisation et assembly via ksp-raw-transaction-lib
observation key déterministe
persistence atomique via ksp-store-lib en mode Normal
concurrence Store bornée
snapshots concrete + projection WorkerSnapshotSource
faults Store/content/source/counter classifiés
processing frontier run-local bornée
projection source Active/Reconnecting/Closing/Closed/Failed
observation des compteurs reconnect/replay/gap Transport
fault sur gap de rétention prouvé
shutdown deadline + abort/join sans tâche orpheline
```
Elle ne possède encore :
Elle conserve explicitement les frontières suivantes :
```text
aucun adapter HTTP/WS/Yellowstone productif
aucun edge ksp-onchain-transport-lib
aucune lecture Config
aucune lecture Config dans le Worker
aucun backend Store physique
aucune API publique d'enqueue/source registration
aucun replay/gap-repair live
aucun checkpoint persistant de processing frontier
aucun appel Worker -> ksp-job-backfill-lib
aucune campagne historique automatique sur continuity gap
aucun client reqwest/tonic/proto direct hors façade Transport
```
Cette frontière est volontaire : les tranches live ajoutent des sources au supervisor existant au lieu d'introduire un second runtime ou une API d'admission publique.
Le replay reconnect est Transport-owned. La processing frontier ne constitue pas une preuve de complétude durable ou blockchain.
### 14.1 Contrat fonctionnel
@@ -755,12 +768,12 @@ Cette frontière est volontaire : les tranches live ajoutent des sources au supe
```text
être un consumer de ksp-worker-api
être démarré/arrêté sans requête historique métier
ouvrir les sources activées par Config
recevoir des ressources déjà composées par la couche supérieure
acquérir à partir du démarrage
supporter plusieurs sources simultanées
normaliser et persister RawTransaction + observations
publier snapshots/notifications concrètes Worker
réparer seulement ses propres pertes de continuité live
laisser reconnect/from_slot/replay au Transport
fault proprement lorsqu'un gap de rétention est prouvé
```
Il ne doit pas :