Files
khadhroony-solana-project/docs/architecture/011-RAW_TRANSACTION_ACQUISITION.md
2026-09-12 23:07:58 +02:00

1027 lines
62 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- file: docs/architecture/011-RAW_TRANSACTION_ACQUISITION.md -->
<!-- version: 15 -->
# Acquisition et alimentation `RawTransaction`
## 1. Rôle du document
Ce document est l'owner durable de l'architecture d'alimentation des `RawTransaction` de KSP.
Il ne suit pas l'ordre chronologique des audits `pre.004` / `pre.005`. Il synthétise directement le modèle cible :
```text
sources/protocoles/providers
|
| capacités d'acquisition
v
+-----------------------------+ +---------------------------------------+
| ksp-job-backfill-lib | | ksp-worker-raw-transaction-ingest-lib |
| historique paramétré | | acquisition continue start/stop |
+-----------------------------+ +---------------------------------------+
| |
| producteurs indépendants |
+------------------+-------------------+
v
normalisation RAW commune
|
v
Store
|
RawTransaction + observations
```
Le **Store et `RawTransaction` sont le centre**. Le Job Backfill et le Worker Ingest sont deux producteurs indépendants qui convergent vers le même contrat durable. Ils ne se pilotent pas mutuellement, ne se délèguent pas du travail et ne dépendent pas l'un de l'autre.
Les protocoles ne sont pas affectés à un producteur par nature : HTTP, WS, gRPC, archive ou shred peuvent servir au Job, au Worker ou aux deux si leur sémantique correspond au rôle concerné.
Les prix, tiers, quotas et disponibilités provider sont des données d'audit datées. Ils ne deviennent jamais des constantes métier KSP.
## 2. Centre du modèle : Store et `RawTransaction`
### 2.1 Vérité RAW durable
L'identité canonique reste :
```text
RawTransaction identity = (network, signature)
```
Le contenu canonique doit être indépendant de la source d'acquisition :
```text
même identité + même contenu canonique
-> idempotence
même identité + contenu canonique divergent
-> conflit explicite
-> jamais first-provider-wins silencieux
```
La provenance d'acquisition n'est pas l'identité de la transaction. Elle appartient aux observations associées.
### 2.2 Observations et provenance
Une même transaction peut être acquise plusieurs fois :
```text
PublicNode Yellowstone
Helius WSS
HTTP getTransaction
blockSubscribe
archive provider
...
```
Ces acquisitions peuvent converger vers un seul `RawTransaction` et plusieurs `RawTransactionObservation` distinctes lorsque leurs clés d'observation sont différentes et utiles.
La provenance sûre peut conserver notamment :
```text
provider
protocole
méthode
origin logique
endpoint logique
commitment
filter id
capture session id
timestamps
hash/taille du payload source
```
Aucune URL secrète, clé API ou payload sensible ne doit traverser ce contrat durable.
### 2.3 Complétude avant persistence
Une source n'est autorisée à produire directement un `RawTransaction` que si elle permet de reconstruire le payload canonique complet attendu par Store.
Un signal incomplet reste un matériau de discovery/hydration :
```text
signature seule
logs
transaction status
transaction body sans execution meta
shreds
slot/block meta
```
Il doit être complété avant la persistence RAW canonique.
## 3. Deux producteurs indépendants
### 3.1 Job Backfill : historique paramétré et borné
`ksp-job-backfill-lib` a pour rôle de **récupérer un historique demandé**.
Une campagne reçoit des paramètres métier explicites, par exemple :
```text
signature ou liste de signatures
program_id / address / compte ciblé
slot ou plage de slots
borne temporelle
before / after / until
limit / page bounds
commitment
stratégie ou politique de sélection admissible
```
Le Job choisit ensuite, selon Config et les capabilities réellement disponibles, une stratégie en une ou plusieurs étapes :
```text
discovery -> hydration -> normalisation -> Store
stream replay borné -> normalisation -> Store
archive -> extraction -> normalisation -> Store
```
Le Job est :
```text
paramétré
borné
terminable
checkpointable lorsque la stratégie le nécessite
orienté historique / catch-up demandé
```
Il peut utiliser **HTTP, WS, Yellowstone gRPC, replay provider ou archive** si ces capacités permettent de satisfaire la requête historique. Il ne doit pas être modélisé comme « un Worker arrêté après N éléments ».
### 3.2 Worker Raw Transaction Ingest : acquisition continue start/stop
`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 supportent désormais une composition live multi-source bornée de `1` à `32` sources logiques sur un même réseau.
Son contrôle métier V1 est volontairement court :
```text
start
stop
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`.
Deux entrées publiques coexistent : `start` conserve la fondation sans source productive, tandis que `start_with_runtime_resources` lance la collection de ressources live validée. Les cinq familles productives matérialisées sont :
```text
Yellowstone Transaction / TransactionStatus / Block
Standard WS logsSubscribe
Helius transactionSubscribe
-> signaux transactionnels source-neutral
-> registry globale d'hydration bornée (network, signature, commitment)
-> HTTP getTransaction observed
-> Common RAW
Standard WS blockSubscribe Full/Base64 Legacy|V0|V1
HTTP live block polling getSlot -> getBlocksWithLimit -> getBlock observed
-> qualification RAW directe Legacy|V0|V1
-> Common RAW
Toutes les voies
-> admission centrale bornée
-> convergence canonique (network, signature)
-> RawTransaction + observations de provenance distinctes
-> Store
Yellowstone BlockMeta / Slot
-> continuité run-local uniquement
```
La composition est caller-owned : le Worker ne lit pas Config et ne reçoit pas de secret. `RawTransactionIngestRuntimeResources` accepte de `1` à `32` sources logiques d'un même réseau, refuse les identités source dupliquées et supervise toutes les sources simultanément. Une faute source n'autorise la continuation des siblings que lorsque sa plage de perte est sûre, que la coverage passée est réconciliée et que les sources restantes couvrent encore tout le `TargetCoverage` futur. Aucune équivalence n'est déduite du provider ou du protocole.
Il ne lance pas de campagne historique arbitraire.
### 3.3 Continuité Worker ≠ Backfill
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
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
```
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 ouvre ou enrichit alors un gap run-local sans considérer la reconnexion comme une réparation.
La réconciliation reste bornée au run :
```text
gap de continuité borné
-> replay Transport si preuve exploitable
-> coverage redondante structurale si prouvée
-> scan HTTP borné / getBlock / getTransaction selon capability
-> même Common RAW / admission / Store
-> Repaired ou Unresolved explicite
```
Il n'existe toujours aucune délégation automatique vers Backfill. Une demande telle que « récupère les transactions du programme X depuis le slot Y » reste une campagne `ksp-job-backfill-lib`, tandis qu'un gap non bornable ou non réconciliable du run courant fait fault le Worker.
### 3.4 Absence de relation Job ↔ Worker
Le modèle interdit les dépendances fonctionnelles suivantes :
```text
Worker -> Job Backfill
Job Backfill -> Worker
Worker délègue un gap au Job
Job démarre un Worker temporaire
coordination obligatoire entre leurs lifecycles
checkpoint partagé entre Job et Worker
```
Ils peuvent être actifs séparément ou simultanément. S'ils observent la même transaction, **Store et les invariants RAW** fournissent l'idempotence et la détection de conflit ; il ne s'agit pas d'une collaboration entre les deux producteurs.
## 4. Capabilities d'acquisition orthogonales aux producteurs
La configuration et l'architecture ne doivent pas réduire les sources à un enum fermé `HTTP | WS | gRPC`.
Les capabilities utiles sont plutôt :
```text
live_direct_transaction
live_direct_block
live_transaction_discovery
live_early_transaction
transaction_hydration
block_hydration
history_discovery
bounded_replay
continuity_boundary
continuity_repair
archive_history
```
Une source concrète peut fournir plusieurs capabilities. Une capability peut être consommée par le Job, le Worker ou les deux selon l'intention.
## 5. Matrice des méthodes et de leur applicabilité
| Famille / méthode | Contenu obtenu | RAW complet | Usage Worker live | Usage Job Backfill | Remarque |
|-----------------------------------------------------------------|---------------------------------------|------------------------------|------------------------------------------------------------|---------------------------------------------|------------------------------------------------------------|
| HTTP `getTransaction(signature)` | transaction depuis signature connue | oui si disponible | oui, hydration d'un signal live | oui, hydration historique | dépend de la rétention du RPC |
| HTTP `getSignaturesForAddress` + `getTransaction` | discovery adressée puis transaction | oui après hydration | non comme campagne de scan | oui, stratégie historique principale | naturellement paramétré par adresse/programme |
| HTTP `getBlocks` / `getBlocksWithLimit` | slots confirmés | non | oui pour suivre/recoller le frontier courant si nécessaire | oui pour énumérer une plage historique | discovery par slots |
| HTTP `getBlock(slot)` full | bloc et transactions | oui | oui pour live polling ou repair de continuité | oui pour historique par bloc | nécessite provenance observed en pool multi-endpoint |
| HTTP `getSlot` / `getFirstAvailableBlock` / `minimumLedgerSlot` | bornes de ledger | non | oui, continuité | oui, admission d'une campagne | aucune transaction directe |
| WS `logsSubscribe` | signature + logs | non | oui, discovery live + hydration | non pour historique pur | `mentions` standard limité à un pubkey |
| WS `signatureSubscribe` | statut d'une signature connue | non | oui, confirmation ciblée interne | possible pour une requête ciblée en attente | one-shot |
| WS `blockSubscribe` full/base64, Legacy/V0/V1 | bloc + transactions | oui, Legacy/V0/V1 qualifiés | oui, direct pour le sous-ensemble qualifié | non sans mécanisme de replay historique | méthode standard instable ; capability validator-dependent |
| Helius `transactionSubscribe` full/base64 | transaction + meta + signature/index | non sans hydration | oui, signal riche puis hydration HTTP | non comme source historique | absence de blockTime/version dans lenveloppe qualifiée |
| Yellowstone `transactions` | transaction exécutée + meta | oui | oui | oui si replay borné demandé/disponible | filters server-side |
| Yellowstone `blocks` avec transactions | bloc + transactions | oui | oui | oui si replay borné demandé/disponible | utile au live et au backfill |
| Yellowstone `transactions_status` | signature/status/error | non | oui + hydration | oui si replay/filtre borné | discovery/statut uniquement |
| Yellowstone slots / `blocks_meta` | continuité de slots | non | oui | auxiliaire | aucune transaction full |
| Yellowstone `from_slot` / replay | reprise d'un stream depuis slot | dépend du stream | oui uniquement pour continuité du Worker | oui pour campagne historique bornée | profondeur provider-specific |
| API provider historique adressée | historique signatures ou transactions | provider-dependent | non comme campagne historique | oui | exemple Helius `getTransactionsForAddress` |
| RPC archive standard | méthodes HTTP sur ledger ancien | oui selon méthode | non pour recherche historique | oui | provider ou self-host |
| Old Faithful / `yellowstone-faithful` | historique par RPC/index | oui pour données disponibles | non | oui | archive spécialisée |
| transaction body pré-exécution | signature/corps sans meta finale | non | oui, EARLY + hydration | non principal | faible latence |
| shreds / deshred | fragments ou transaction reconstruite | non sans meta d'exécution | oui, EARLY + hydration | non principal | adapter spécialisé |
| Agave RPC auto-hébergé | méthodes standard | selon méthode | oui | oui | mêmes rôles que RPC standard |
| Agave + Yellowstone auto-hébergé | streams Yellowstone | selon stream | oui | oui avec rétention/replay opérateur | capability opérateur |
Cette matrice est intentionnellement **usage-first**. HTTP n'est pas « Backfill » et gRPC n'est pas « Worker » : leur rôle dépend de l'opération effectuée.
## 6. Stratégies Worker live
### 6.1 Acquisition directe
Sources capables de produire directement un matériau transactionnel complet dans l'architecture générale :
```text
Yellowstone transactions/blocks lorsque l'adapter choisi qualifie directement leur wire
WS blockSubscribe full/base64 Legacy/V0/V1 qualifié
HTTP getBlock full/base64 Legacy/V0/V1
provider stream compatible full transaction après parité prouvée
```
Dans le Worker V1 actuel, Yellowstone reste volontairement traité comme signal puis hydraté par HTTP `getTransaction` afin de conserver un seul chemin de canonicalisation productif pour cette famille. Les voies directes effectivement matérialisées dans le Worker sont Standard Block et HTTP Block Polling.
Chemin logique :
```text
source live full
-> adaptation source-neutral
-> canonicalisation RAW
-> Store
-> notification Worker
```
### 6.2 Discovery live + hydration
Sources rapides mais incomplètes :
```text
logsSubscribe
transactions_status
signature/status feed
transaction body pré-exécution
shreds/deshred
```
Chemin logique :
```text
signal live
-> identité/signature
-> getTransaction ou autre hydration admissible
-> canonicalisation RAW
-> Store
```
HTTP est donc une capability normale du Worker lorsqu'il sert l'hydration live.
### 6.3 Suivi live par blocs HTTP
Une implémentation Worker peut aussi suivre le réseau sans subscription push :
```text
getSlot / borne courante
-> nouveaux slots depuis le démarrage
-> getBlock full
-> extraction transaction par transaction
-> Store
```
Cette stratégie est du **live polling** tant qu'elle suit le frontier depuis le démarrage ; elle devient historique si on lui demande une plage ancienne, auquel cas le rôle revient au Job Backfill.
### 6.4 Réparation de continuité
Le Worker doit distinguer reconnexion et continuité :
```text
reconnect réussi != absence de gap
```
Pour un gap survenu pendant son run, il peut utiliser dans cet ordre de préférence selon les capabilities :
```text
1. replay adressable du stream depuis le frontier connu
2. source live redondante ayant couvert la plage
3. HTTP getBlock/getTransaction pour les références/slots manquants
4. reprise live une fois le frontier réconcilié
```
Aucune étape ne reçoit une requête historique arbitraire du caller.
### 6.5 Notifications
Le Worker persiste d'abord la vérité RAW durable puis publie une projection/notification adaptée à son API concrète. Les notifications sont indépendantes de leurs lecteurs :
```text
aucun consumer obligatoire
aucune callback consumer-owned
aucune queue non bornée imposée par ksp-worker-api
```
## 7. Stratégies Job Backfill
### 7.1 Discovery adressée
Vertical slice déjà prouvé :
```text
request avec address/program_id/borne
-> getSignaturesForAddress
-> getTransaction observed
-> canonicalisation
-> Store
```
### 7.2 Signatures explicites
```text
request avec signatures
-> getTransaction observed
-> canonicalisation
-> Store
```
### 7.3 Historique par blocs
```text
request avec plage slot/temps/limite
-> getBlocks/getBlocksWithLimit
-> getBlock observed
-> extraction transaction par transaction
-> Store
```
### 7.4 Replay Yellowstone borné
Si un provider sert réellement `from_slot`/replay :
```text
request historique bornée
-> transactions ou blocks depuis from_slot
-> arrêt lorsque la borne de campagne est atteinte
-> Store
```
Le fait d'utiliser un stream gRPC ne change pas la nature Job : la campagne reste paramétrée, bornée et terminable.
### 7.5 APIs historiques provider
Exemples admis :
```text
Helius getTransactionsForAddress
provider archive via RPC standard
provider persistent history stream
```
Ces stratégies restent des adapters spécialisés et ne remplacent pas les primitives standard.
### 7.6 Archives
Pour les historiques hors fenêtre RPC/replay :
```text
Old Faithful / yellowstone-faithful
archive provider
CAR / Filecoin / S3 / Bigtable ou autre substrat futur
```
Les substrats directs restent une extension plus lointaine ; l'adapter doit toujours converger vers le même matériau source-neutral et le même format RAW canonique.
## 8. Taxonomie de preuve
Le support architectural et la preuve live restent séparés :
```text
possibilité connue = protocole/provider/infrastructure capable en principe
support KSP = adapter/capability implémenté ou planifié
preuve KSP = comportement réellement exercé sur un endpoint accessible
```
Codes :
| Code | Sens |
|---------------|-----------------------------------------------------------------------|
| `ADMIS` | capability à représenter dans le socle KSP |
| `SPÉCIALISÉ` | adapter provider/source autorisé sans contaminer le contrat générique |
| `EARLY` | signal incomplet précoce ; hydration/confirmation obligatoire |
| `SUNSET` | voie historique conservée seulement pour traçabilité/migration |
| `EXISTANT` | surface KSP déjà présente |
| `PLANIFIÉ` | adaptation à implémenter dans la release indiquée |
| `PROUVÉ` | propriété exercée ou directement démontrée pour le périmètre indiqué |
| `TESTABLE` | accès disponible mais smoke KSP encore à produire |
| `NON PROUVÉ` | capability admise sans preuve live actuelle |
| `BLOQUÉ TIER` | branche admise mais accès live indisponible avec les comptes actuels |
| `À REVALIDER` | documentation provider insuffisante ou contradictoire |
Règles :
```text
NON PROUVÉ != REJETÉ
PAYANT/BLOQUÉ != NON SUPPORTÉ
IMPLÉMENTÉ != PROUVÉ LIVE
PROUVÉ CHEZ UN PROVIDER != GARANTI CHEZ TOUS LES PROVIDERS
```
## 9. Matrice providers, réseaux, coût et preuve
Audit externe daté du **4 septembre 2026**.
| Provider / infrastructure | Réseaux utiles documentés | HTTP / WSS standard | Yellowstone / stream full | Historique / replay | Prix / tier utile au 04-09-2026 | Accès KSP actuel | Preuve / décision KSP |
|---------------------------------|-----------------------------------------|-----------------------------|-------------------------------------------|-----------------------------------------------------|-------------------------------------------------------------------------------|--------------------------------|------------------------------------------------------------------------|
| Solana public RPC | Mainnet-beta, Devnet, Testnet | oui | non | ledger public borné | gratuit, fortement rate-limité | oui | standard `PROUVÉ/TESTABLE`, baseline seulement |
| provider RPC standard générique | selon provider | oui si méthodes exposées | éventuel | selon provider | variable | selon compte | `ADMIS` par capabilities, jamais par nom |
| Agave auto-hébergé | Mainnet, Devnet, Testnet, local, custom | oui | Yellowstone si plugin | rétention opérateur | coût infrastructure | non actuellement | `ADMIS`, environnement KSP `NON PROUVÉ` |
| Helius | Mainnet + Devnet | Free+ | Devnet Developer+, Mainnet Business+ | LaserStream 24 h, history API | Free $0, Developer $49, Business $499, Professional $999 | HTTP/WSS gratuit | standard `TESTABLE`, gRPC Mainnet `BLOQUÉ TIER`, replay 24 h documenté |
| PublicNode | Mainnet + Testnet | gratuit | Yellowstone gRPC gratuit | archive sur demande, profondeur replay inconnue | endpoint public gratuit | Mainnet gRPC + RPC disponibles | gRPC Mainnet déjà exercé, profondeur replay `NON PROUVÉE` |
| OrbitFlare | Mainnet + Devnet | oui | Devnet Free/Developer, Mainnet add-on/Pro | archival data, profondeur gRPC inconnue | Free $0, Developer $49, Growth $399, Scale $799, Pro $999, Mainnet gRPC +$500 | Devnet gratuit possible | Devnet `TESTABLE`, Mainnet payant, replay `NON PROUVÉ` |
| QuickNode | Mainnet-beta, Testnet, Devnet | oui | Scale/Business ou add-on | `fromSlot` jusqu'à 3000 slots, archive selon réseau | Scale $499, Business $999 | pas de tier gRPC actuel | `BLOQUÉ TIER`, replay provider documenté |
| Alchemy | Mainnet + Devnet | oui | Yellowstone PAYG/Enterprise | replay documenté mais contradictoire | $75/TB gRPC, PAYG/Enterprise | standard gratuit possible | gRPC `BLOQUÉ/À REVALIDER` |
| Chainstack | Mainnet + Devnet RPC, gRPC Mainnet | Free Developer + payant | add-on Yellowstone Growth+ | archive Growth+, replay gRPC inconnu | Developer $0, Growth $49, gRPC $49/2, $149/7, $449/25 streams | standard gratuit possible | standard `TESTABLE`, gRPC `BLOQUÉ TIER`, replay `NON PROUVÉ` |
| Shyft | Mainnet + Devnet RPC | Free RPC | Build/Grow/Accelerate Yellowstone | replay jusqu'à 150 slots | Free $0, Build $199, Grow $349, Accelerate $649 | RPC gratuit possible | standard `TESTABLE`, gRPC `BLOQUÉ TIER`, 150 slots documentés |
| Triton One | Solana, réseau par endpoint | oui / Whirligig | Dragon's Mouth, Riptide, Fumarole | Fumarole persistant, Old Faithful | dépôt PAYG $125, streaming $0.08/GB, RPC $0.08/GB + $10/M calls | pas de compte actuel | `BLOQUÉ TIER`, architecture `ADMIS` |
| dRPC | Solana, réseau gRPC à qualifier | HTTP/WSS | Yellowstone Premium/Advanced | profondeur replay inconnue | Premium $399, Advanced $599 | standard éventuellement | gRPC `BLOQUÉ TIER`, replay `NON PROUVÉ` |
| Ankr | Mainnet + Devnet | Freemium/Premium HTTP + WSS | Yellowstone Solana non prouvé | ledger rolling, archive générique | $0.00005 par request/subscription/notification Solana | freemium possible | standard `TESTABLE`, ne pas inférer gRPC Solana |
| GetBlock | Mainnet-beta + Devnet | Free+ HTTP/WSS | Yellowstone dedicated/add-on | archive selon plan | Free $0, Starter $49, Advanced $199, Pro $499, Enterprise $999 | standard gratuit possible | standard `TESTABLE`, gRPC payant `NON PROUVÉ` |
| autre Yellowstone-compatible | provider/network-dependent | variable | oui si protocole compatible | provider-dependent | inconnu | non | `ADMIS` via descriptors/capabilities |
### 9.1 Alchemy : replay à revalider
Les pages Alchemy courantes ne sont pas cohérentes entre elles : certaines mentionnent environ **6000 slots**, tandis que la page dédiée Historical Replay annonce `from_slot` dans environ **432 000 slots / ~48 h**.
KSP ne doit donc pas encoder une constante Alchemy. La capability replay doit être qualifiée par documentation courante + test au moment de l'activation.
## 10. Sources ultra-low-latency et pre-execution
Ces voies sont conservées dans le socle de possibilités pour le Worker, mais elles ne deviennent jamais une vérité RAW complète tant que les métadonnées d'exécution nécessaires ne sont pas disponibles.
| Source | Transport | Réseau / accès | Contenu utile | Meta d'exécution | Prix / accès daté | Usage KSP |
|----------------------------------|---------------------|----------------------------|--------------------------------------|------------------|--------------------------------------------|-------------------------------------|
| Helius Shred Delivery | UDP shreds | Mainnet, beta/qualified | shreds bruts | non | Professional+, prix non figé | `EARLY`, deshred + hydration |
| Helius preprocessed transactions | gRPC | Helius Shred Delivery | transaction prétraitée | non | Professional+, 20 crédits/MB | `EARLY`, body/signature + hydration |
| OrbitFlare Jetstream | gRPC basé shreds | provider-dependent | transaction faible latence | non | depuis environ $500/mo selon offre | `EARLY` + hydration |
| Shyft RabbitStream | gRPC depuis shreds | provider-dependent, payant | transactions extraites des shreds | non/à confirmer | Build+ $199+ | `EARLY` + hydration |
| Triton Deshred | extension gRPC | shared/dedicated Triton | transaction reconstruite | non | offre streaming PAYG | `EARLY` + hydration |
| Triton Shred Streaming | shred stream | Triton | shreds | non | $1500/mo/IP/datacenter | phase avancée |
| bloXroute Transaction Streamer | gRPC | Solana | signature + bytes transaction + slot | non | $500/mo | `EARLY`, body + hydration |
| bloXroute Shreds | UDP/gateway | Solana | shreds | non | $500/mo | phase avancée |
| DoubleZero Edge | UDP multicast | feed Solana shreds | shreds bruts | non | $450/$900/$1500 par machine/mo selon metro | deshred + hydration |
| Jito ShredStream | shreds/local decode | Solana | shreds -> transactions | non | sunset | `SUNSET` le 5 septembre 2026 |
| Turbine/shred feed auto-opéré | UDP/local | cluster opéré | shreds bruts | non | coût infrastructure | possibilité générique future |
Jito prévoit l'arrêt complet de ShredStream le **5 septembre 2026** et recommande DoubleZero Edge. La ligne Jito reste uniquement pour exhaustivité historique/migration.
## 11. Réseaux et stratégie de preuve
Le support de stratégie doit rester network-neutral ; les smokes utilisent pragmatiquement les accès disponibles.
| Réseau KSP | Preuves prioritaires disponibles | Branches complémentaires | Règle |
|--------------|-------------------------------------------------------------------------------|-----------------------------------------------------------------------------------|----------------------------------------------------------------|
| `mainnet` | HTTP/WS standard multi-provider, PublicNode Yellowstone gRPC, Helius HTTP/WSS | Helius gRPC payant, QuickNode, Alchemy, Chainstack, Shyft, Triton, dRPC, GetBlock | identité KSP canonique ; `mainnet-beta` = alias legacy/externe |
| `devnet` | Solana public HTTP/WS, Helius standard, OrbitFlare Yellowstone gratuit | Helius LaserStream Developer+, Alchemy, self-host | terrain privilégié pour protocole sans coût Mainnet |
| `testnet` | Solana public HTTP/WS, PublicNode RPC/WS/Yellowstone | self-host et autres providers | ne pas extrapoler disponibilité provider |
| local/custom | fixtures, Agave local, Yellowstone local si nécessaire | serveurs contrôlés | prouver gaps, replay, backpressure et erreurs |
Plan de preuve :
```text
1. tests déterministes pour chaque adapter/capability implémenté
2. smokes live opt-in sur combinaisons gratuites/accessibles
3. smokes live ignored pour branches payantes jusqu'à obtention du tier
```
Une branche peut donc être **implémentée mais non prouvée live**, à condition que la documentation le dise explicitement.
## 12. Inventaire KSP disponible
### 12.1 Transport standard HTTP
KSP possède déjà :
```text
get_signatures_for_address
get_transaction / get_transaction_observed
get_blocks / get_blocks_with_limit
get_block / get_block_observed
get_slot
get_first_available_block
minimum_ledger_slot
```
`get_block_observed` conserve désormais la provenance sûre provider/endpoint du winner réel dun pool HTTP, symétriquement à `get_transaction_observed`. La projection dune transaction full issue dun bloc vers le matériau RAW commun reste volontairement hors de Transport : ladapter productif appartient au producer (Worker/Job) afin de ne créer aucun edge `Transport -> ksp-raw-transaction-lib`.
### 12.2 Transport WebSocket
KSP possède déjà :
```text
logsSubscribe
signatureSubscribe
blockSubscribe
slotSubscribe
slotsUpdatesSubscribe
Helius transactionSubscribe
```
Le runtime WS possède des queues bornées et une logique de reconnect/resubscribe. Un reconnect ne constitue toutefois pas un replay adressable.
La qualification actuelle ferme deux cas distincts : `blockSubscribe` standard en `full/base64` avec `maxSupportedTransactionVersion = 1` qualifie explicitement Legacy/V0/V1 et produit le matériau Common RAW directement ; Helius `transactionSubscribe` full/base64 conserve lidentité, le slot, le transaction wire, la meta et lindex mais ne transporte pas `blockTime` ni `version` dans lenveloppe qualifiée. Helius reste donc un signal live riche à hydrater par HTTP avant persistence RAW.
### 12.3 Yellowstone gRPC
Le moteur KSP expose déjà les familles nécessaires :
```text
transactions
transactions_status
blocks
blocks_meta
slots
from_slot
SubscribeReplayInfo / snapshot de continuité associé
```
Il faut réutiliser ce moteur générique pour les providers compatibles plutôt que créer un client gRPC par provider.
### 12.4 Store
Les primitives de convergence existent déjà autour de :
```text
RawTransactionReference
RawTransaction
RawTransactionObservation
RawAcquisitionProvenance
RawTransactionWrite::persist_raw_transaction_acquisition
RawTransactionObservationWrite::record_raw_transaction_observation
```
Aucun backend physique ne doit entrer dans le Worker ou le Job.
### 12.5 Config
Config reste seul propriétaire :
```text
réseau
endpoints
provider/protocole
secrets
activation des sources
capabilities déclarées
priorités/composition
```
Les prix/tiers d'audit ne doivent pas devenir une politique runtime.
`mainnet` est l'identité réseau durable KSP. `mainnet-beta` reste uniquement un alias de compatibilité/historique ou un libellé externe lorsqu'un provider/API l'emploie. Depuis `0.3.9-pre.006-fix.003`, les profils Config/Store/Transport Mainnet engagés utilisent `mainnet` comme identité logique, et les exemples/tests associés ont été normalisés. Les endpoints publics Solana engagés suivent également la nomenclature Mainnet courante (`https://api.mainnet.solana.com` et `wss://api.mainnet.solana.com`). Aucune migration de données D1 n'est exigée : les données RAW Mainnet encore expérimentales peuvent être droppées/recréées si elles portent l'ancienne identité.
## 13. Normalisation RAW commune sans couplage Job/Worker
La canonicalisation RAW v1 actuellement prouvée dans `ksp-job-backfill-lib::conversion` ne doit ni y rester enfermée ni être copiée dans le Worker.
Le handoff retient la crate source-neutral commune désormais matérialisée :
```text
ksp-raw-transaction-lib
```
Elle n'organise aucune collaboration entre Job et Worker. Elle constitue une dépendance inférieure commune, au même titre qu'un contrat Store partagé.
Responsabilités prévues :
```text
format id/version RAW
matériau source-neutral transaction complète
canonical payload bytes
content hash
construction RawTransaction
construction/projection d'observation depuis métadonnées sûres
validation réseau/signature/slot/meta/version/index
```
Responsabilités interdites :
```text
runtime
HTTP/WS/gRPC
Config
scheduler
Job lifecycle
Worker lifecycle
backend Store physique
```
Graphe matérialisé après la fondation Worker :
```text
ksp-job-backfill-lib --------------------> ksp-raw-transaction-lib ----> ksp-store-api
ksp-worker-raw-transaction-ingest-lib ---> ksp-raw-transaction-lib ----> ksp-store-api
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 ---> ksp-onchain-transport-lib # Yellowstone + HTTP hydration
aucun edge Job <-> Worker
aucun edge Transport <-> ksp-raw-transaction-lib
```
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é.
### 13.1 Transaction wire Legacy/V0/V1
`pre.006` matérialise dans `ksp-raw-transaction-lib` un modèle wire Solana source-neutral, indépendant de Transport et des crates runtime Solana. Il sérialise exactement les formes Legacy, V0 et V1 puis expose aussi la représentation Base64.
Pour V1, le contrat suit SIMD-0385 tel qu'audité le 7 septembre 2026 :
```text
0x81
LegacyHeader
TransactionConfigMask u32 LE
LifetimeSpecifier [32]
NumInstructions u8
NumAddresses u8
Addresses
ConfigValues
InstructionHeaders
InstructionPayloads
Signatures terminales
```
Les limites common verrouillées sont : transaction `<= 4096` octets, `<= 12` signatures, `<= 64` adresses, `<= 64` instructions, indexes bornés, aucune ALT en V1 et aucune donnée après les signatures. La présence de `Message.config` Yellowstone distingue V1 ; `versioned=true` sans config reste V0, et `versioned=false` sans config reste Legacy.
L'extracteur de signature Base64 common reconnaît désormais V1 au premier octet `0x81` et parcourt structurellement le message jusqu'aux signatures terminales au lieu d'appliquer le short-vector signatures-first de Legacy/V0.
Le format V1 est encore documenté upstream comme pre-release/feature-gated ; KSP implémente donc la capacité de lecture/canonicalisation sans déclarer son activation sur un cluster particulier.
### 13.2 Qualification Yellowstone `pre.006`
Un canari cross-layer test-only dans Backfill monte un serveur Geyser local, ouvre le vrai `YellowstoneGrpcChannel::open_standard_subscribe`, reçoit successivement une update `Transaction` V1 et une update `Block` contenant la même transaction, puis projette les DTO Transport vers le modèle wire common uniquement dans le test.
Le gate prouve :
```text
Transaction update -> slot/index + transaction wire V1 exact
Block update -> slot/index + même transaction wire V1 exact + block_time
Transport -> aucun edge production vers ksp-raw-transaction-lib
Backfill -> tonic/yellowstone-grpc-proto strictement dev-only
```
Il ne qualifie pas un RAW-direct complet Yellowstone : une update `Transaction` ne porte pas `block_time`, et la représentation protobuf Yellowstone de la meta n'est pas démontrée byte-identical avec la projection JSON HTTP servant au RAW v1 actuel. La décision `TR-C4` reste donc conservative :
```text
Yellowstone Transaction/Block -> signal structuré + transaction wire fidèle
RAW v1 complet -> hydration HTTP avant persistence
```
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. État du Worker live après `0.3.14`
### 14.0 Verticale matérialisée
La verticale productive possède :
```text
consumer de ksp-worker-api
settings réseau/Worker bornés
start/stop sur runtime Tokio caller-owned
supervision privée de 1..32 sources logiques sur un même réseau
cinq familles live : Yellowstone / Standard Logs / Standard Block / Helius Transaction / HTTP Block Polling
mpsc central borné + backpressure
registry globale d'hydration pour Yellowstone / Standard Logs / Helius
qualification RAW directe pour Standard Block / HTTP Block Polling
coalescence bornée par network/signature/commitment
HTTP getTransaction observed pour hydration
canonicalisation et assembly via ksp-raw-transaction-lib
convergence canonique par (network, signature) + disagreement explicite
persistence atomique via ksp-store-lib en mode Normal + observations supplémentaires idempotentes
quotas pending/in-flight par source et bornes globales exactes
fairness minimale / anti-starvation sous duplicate storm
processing frontier et continuity frontier run-local distinctes
ledger de gaps inclusifs bornés + TargetCoverage conservative
replay Transport / coverage redondante / scan HTTP / block fetch / hydration comme preuves distinctes
observabilité publique source-neutral des gaps, raisons, états, dernière méthode et compteurs checked
projection source-neutral Active/Reconnecting/Closing/Closed/Failed + gauges source_total/active/reconnecting/failed
health Healthy/Degraded/Unhealthy fondée sur gaps, frontiers et coverage présente/future
fairness nominal/repair sur les mêmes admission/hydration/persistence
source loss non terminale uniquement après réconciliation complète et coverage future prouvée
shutdown deadline + abort/join sans tâche orpheline ni late persistence
```
Elle conserve explicitement les frontières suivantes :
```text
aucune lecture Config dans le Worker
aucun backend Store physique
aucune API publique d'enqueue/source registration
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
```
Le replay reconnect est Transport-owned. La processing frontier ne constitue pas une preuve de complétude durable ou blockchain.
### 14.1 Contrat fonctionnel
`ksp-worker-raw-transaction-ingest-lib` doit :
```text
être un consumer de ksp-worker-api
être démarré/arrêté sans requête historique métier
recevoir des ressources déjà composées par la couche supérieure
acquérir à partir du démarrage
normaliser et persister RawTransaction + observations
publier snapshots/notifications concrètes Worker
laisser reconnect/from_slot/replay au Transport
réconcilier uniquement les gaps bornés du run courant avec des preuves de coverage explicites
fault proprement lorsqu'une lacune reste non bornable, non couverte ou unresolved
```
Il ne doit pas :
```text
recevoir signature/program_id/plage/limit de campagne au start
chercher arbitrairement avant son frontier live
instancier ou appeler ksp-job-backfill-lib
attendre un Job pour continuer
hardcoder un provider unique
```
### 14.2 Sources Worker V1 matérialisées et reports
Matérialisé dans `0.3.13` puis durci dans `0.3.14` :
```text
Yellowstone transactions / blocks / status + HTTP hydration
WS logsSubscribe + HTTP getTransaction
WS blockSubscribe Full/Base64 Legacy/V0/V1 direct qualifié
Helius transactionSubscribe Full + HTTP hydration
HTTP live block polling getSlot/getBlocksWithLimit/getBlock observed
HTTP hydration partagée et coalescée cross-source
replay Yellowstone conservé propriétaire de Transport pour continuité du run
gaps run-local bornés et continuity frontier distincte de la processing frontier
coverage exacte/superset conservative avec epochs prouvés
repair borné réutilisant Transport/Common RAW/admission/Store existants
source-loss continuation uniquement sous TargetCoverage prouvée
snapshots gap/repair source-neutral et health gap-aware
```
Reste hors de cette verticale et nécessite une tranche dédiée :
```text
sources EARLY / pre-execution
campagne historique multi-source ou caller-paramétrable
Worker multi-source -> Store live E2E avec environnement complet provisionné
```
### 14.3 Gaps Transport Worker
| ID | Adaptation | Motif |
|--------|---------------------------------------------------------------------------------------|------------------------------------------------------|
| `TR-B` | fermé : `get_block_observed` symétrique de `get_transaction_observed` | provenance exacte en pool HTTP |
| `TR-C` | projection source-neutral des transactions full WS/Yellowstone ; Helius via hydration | éviter plusieurs canonicalizers filaires |
| `TR-D` | métadonnées sûres d'acquisition live au moment de la conversion | observation uniforme |
| `TR-E` | conserver/exploiter `from_slot`, replay info et snapshots de continuité existants | ne pas créer un second moteur Yellowstone |
| `TR-F` | adapters EARLY uniquement quand leur protocole est réellement implémenté | réserver la capability sans tout coder immédiatement |
### 14.4 Config Worker
La composition doit exprimer des routes/capabilities de sources, pas des requêtes métier de campagne :
```text
source id
network
endpoint ref
capabilities
priority
enabled
settings techniques nécessaires
```
Elle peut activer plusieurs providers/endpoints simultanément. Les secrets restent Config-owned, avec réutilisation unique de `KSP_SECRET_HELIUS_API_KEY` pour les surfaces Helius concernées.
## 15. Handoff `0.3.16` : Job Backfill multi-stratégie
Le Job doit conserver son vertical slice existant puis ajouter des stratégies historiques choisies selon requête + capabilities + configuration.
| Stratégie | Entrée de campagne typique | Acquisition | Admission |
|----------------------------------------|-----------------------------------|----------------------------|------------------|
| GSFA + getTransaction | address/program_id + bornes/limit | discovery + hydration HTTP | déjà existante |
| signatures explicites + getTransaction | signatures | hydration HTTP | déjà existante |
| scan blocs | slots/temps/limit | getBlocks + getBlock | oui |
| Yellowstone transactions replay | from slot/plage/filtre | stream full borné | oui |
| Yellowstone blocks replay | plage/filtre | stream bloc borné | oui |
| Helius getTransactionsForAddress | address + filtres provider | history API | oui spécialisé |
| provider archive via RPC | plage historique | RPC standard archive | oui |
| Old Faithful | plage historique | RPC/index archive | oui expérimental |
| substrat archive direct | dataset + plage | adapter spécifique | futur |
Le Job peut donc utiliser gRPC ou WS/replay si cela répond à une campagne historique. Sa nature reste Job parce que l'entrée est paramétrée, la campagne bornée et la terminaison attendue.
## 16. Priorité de réalisation sans réduire le socle
L'exhaustivité de l'architecture ne signifie pas que chaque intégration vendor-specific doit être codée dans la première prerelease.
Ordre conseillé :
```text
0.3.10 P0 : normalisation RAW commune + observed getBlock + preuves cross-source
0.3.11 P0 : Worker foundation/runtime + persistence déterministe
0.3.12 P0 : Yellowstone transactions/blocks/status + hydration + replay continuity
0.3.13 P0 : WS logs + hydration, blockSubscribe, Helius transactionSubscribe, HTTP live polling
0.3.13 P1 : multi-source convergence, dedup, provenance, content conflict, backpressure/fairness
0.3.13 P2 : health source-neutral, shutdown/races, completeness/security et gate live keyless
0.3.14 : trajectoire suivante définie par son prompt dédié ; ne pas réintroduire implicitement un scope reporté
0.3.16 P0 : block scan historique
0.3.16 P0 : replay Yellowstone borné
0.3.16 P1 : provider history/archive
0.3.16 P1 : Old Faithful
plus tard : substrats directs et sources vendor-specific sans accès actuel
```
Une branche `ADMIS` reste dans le modèle même si son smoke live est impossible aujourd'hui.
## 17. Référence fonctionnelle historique kbot3
L'archive kbot3 fournie par l'opérateur a été auditée uniquement comme référence fonctionnelle historique.
Elle confirme notamment les besoins :
```text
discovery adressée
hydration getTransaction
pagination/reprise bornée
frontier/checkpoint pour campagne historique
retries/concurrency bornés
session WS persistante
reconnect/resubscribe
provenance d'acquisition
```
Elle confirme aussi deux limites que KSP ne doit pas reproduire :
```text
retry d'une route choisie != provenance multi-source complète
reconnect WS != replay historique
```
Aucun code, DTO, Config, endpoint, secret, dépendance ou convention de version kbot3 n'est repris.
## 18. Sources externes auditées
Sources consultées le **4 septembre 2026** et revalidées pour Transaction V1 le **7 septembre 2026**. Cette liste consolide les anciens audits A/B dans un seul registre documentaire.
### 18.1 Solana standard
| Sujet | URL |
|-------------------------|-------------------------------------------------------------|
| clusters/public RPC | https://solana.com/docs/references/clusters |
| getSignaturesForAddress | https://solana.com/docs/rpc/http/getsignaturesforaddress |
| getTransaction | https://solana.com/docs/rpc/http/gettransaction |
| getBlocks | https://solana.com/docs/rpc/http/getblocks |
| getBlocksWithLimit | https://solana.com/docs/rpc/http/getblockswithlimit |
| getBlock | https://solana.com/docs/rpc/http/getblock |
| getSlot | https://solana.com/docs/rpc/http/getslot |
| getFirstAvailableBlock | https://solana.com/docs/rpc/http/getfirstavailableblock |
| minimumLedgerSlot | https://solana.com/docs/rpc/http/minimumledgerslot |
| logsSubscribe | https://solana.com/docs/rpc/websocket/logssubscribe |
| signatureSubscribe | https://solana.com/docs/rpc/websocket/signaturesubscribe |
| blockSubscribe | https://solana.com/docs/rpc/websocket/blocksubscribe |
| slotSubscribe | https://solana.com/docs/rpc/websocket/slotsubscribe |
| slotsUpdatesSubscribe | https://solana.com/docs/rpc/websocket/slotsupdatessubscribe |
### 18.2 Yellowstone et providers
| Source | URL |
|----------------------------------|--------------------------------------------------------------------------------------------------------------|
| Yellowstone proto | https://github.com/rpcpool/yellowstone-grpc/blob/master/yellowstone-grpc-proto/proto/geyser.proto |
| Yellowstone storage proto | https://github.com/rpcpool/yellowstone-grpc/blob/master/yellowstone-grpc-proto/proto/solana-storage.proto |
| SIMD-0385 Transaction V1 | https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0385-transaction-v1.md |
| Transaction V1 examples | https://github.com/solana-foundation/transaction-v1-examples |
| Yellowstone README | https://github.com/rpcpool/yellowstone-grpc/blob/master/README.md |
| Yellowstone changelog | https://github.com/rpcpool/yellowstone-grpc/blob/master/CHANGELOG.md |
| Helius data streaming | https://www.helius.dev/docs/data-streaming |
| Helius LaserStream | https://www.helius.dev/blog/introducing-laserstream |
| Helius WebSockets | https://www.helius.dev/blog/laserstream-websockets |
| Helius enhanced WebSockets | https://www.helius.dev/blog/introducing-next-generation-enhanced-websockets |
| Helius getTransactionsForAddress | https://www.helius.dev/blog/introducing-gettransactionsforaddress |
| Helius preprocessed transactions | https://www.helius.dev/docs/shred-delivery/preprocessed-transactions |
| PublicNode Solana | https://solana.publicnode.com/ |
| OrbitFlare Yellowstone | https://docs.orbitflare.com/data-streaming/yellowstone |
| OrbitFlare RPC | https://orbitflare.com/products/rpc-nodes |
| OrbitFlare gRPC | https://orbitflare.com/products/solana-grpc |
| QuickNode Yellowstone | https://www.quicknode.com/guides/solana-development/tooling/solana-grpc/solana-grpc |
| QuickNode gRPC plans | https://www.quicknode.com/blog/solana-grpc-is-now-included-with-scale-and-business-plans |
| Alchemy Solana gRPC | https://www.alchemy.com/solana-grpc |
| Alchemy Yellowstone quickstart | https://www.alchemy.com/docs/reference/yellowstone-grpc-quickstart |
| Alchemy historical replay | https://www.alchemy.com/docs/reference/yellowstone-grpc-historical-replay |
| Alchemy compute/bandwidth | https://www.alchemy.com/docs/reference/compute-unit-costs |
| Chainstack Yellowstone | https://chainstack.com/yellowstone-grpc-more-streams-same-price/ |
| Shyft Yellowstone | https://shyft.to/solana-yellowstone-grpc |
| Shyft pricing | https://shyft.to/solana-rpc-grpc-pricing |
| Shyft RabbitStream | https://shyft.to/solana-shreds-rabbitstream |
| Triton pricing | https://triton.one/pricing |
| Triton Yellowstone | https://blog.triton.one/complete-guide-to-solana-streaming-and-yellowstone-grpc/ |
| Triton Fumarole | https://blog.triton.one/introducing-yellowstone-fumarole/ |
| Triton Deshred | https://blog.triton.one/deshred-transactions-the-fastest-path-to-solana-data/ |
| dRPC Yellowstone | https://drpc.org/docs/solana-yellowstone-geyser-grpc |
| Ankr Solana | https://www.ankr.com/docs/rpc-service/chains/chains-list/s-t/ |
| Ankr pricing | https://www.ankr.com/docs/rpc-service/pricing/ |
| GetBlock pricing | https://getblock.io/pricing-new/ |
| bloXroute pricing | https://bloxroute.com/pricing/ |
| Jito ShredStream | https://docs.jito.wtf/lowlatencytxnfeed/ |
| DoubleZero Edge | https://docs.malbeclabs.com/Edge%20Subscriber%20Connection/ |
| Old Faithful | https://github.com/rpcpool/yellowstone-faithful |
Les URLs sont documentaires. Aucun endpoint runtime, token ou secret de compte n'est ajouté au dépôt par cet audit.
## 19. Décisions fermées après `pre.006`
```text
centre du modèle = Store / RawTransaction
producers = Job Backfill et Worker Ingest indépendants
Job Backfill = historique paramétré, borné, terminable
Worker Ingest = acquisition continue start/stop, sans requête métier historique
protocol ownership = aucun ; HTTP/WS/gRPC/archive sont des capabilities réutilisables
Worker continuity repair = seulement gaps liés à son acquisition live, pas campagne historique
Store convergence = identité (network, signature), idempotence + conflit canonique explicite
observations = plusieurs acquisitions/provenances possibles pour un même RAW
support vs preuve = axes séparés ; NON PROUVÉ n'implique pas REJETÉ
provider model = capabilities/configuration, jamais enum provider fermé
network identity = mainnet canonique ; mainnet-beta alias legacy/externe
RAW canonicalisation = lower-layer commune, sans edge Job <-> Worker
Transaction V1 = wire source-neutral Legacy/V0/V1 dans common ; activation cluster non supposée
Yellowstone pre.006 = transaction wire V1 qualifié ; RAW complet via hydration HTTP
TR-C2 = adapter productif Transport DTO -> common réservé au Worker concret
0.3.10 = common RAW + preuves cross-source
0.3.11 = fondation Worker source-neutral, persistence et observabilité
0.3.12 = première verticale Yellowstone + hydration/replay continuity
0.3.13 = cinq familles live + convergence/fairness/health/shutdown/completeness
0.3.16 = Job Backfill multi-stratégie historique
```
`0.3.9` n'implémente aucune nouvelle stratégie d'acquisition. Il ferme l'architecture et l'inventaire nécessaires aux releases suivantes.