v0.3.13-pre.001
This commit is contained in:
860
docs/plans/034-V0_3_13_MULTI_SOURCE_LIVE_CONVERGENCE_PLAN.md
Normal file
860
docs/plans/034-V0_3_13_MULTI_SOURCE_LIVE_CONVERGENCE_PLAN.md
Normal file
@@ -0,0 +1,860 @@
|
||||
<!-- file: docs/plans/034-V0_3_13_MULTI_SOURCE_LIVE_CONVERGENCE_PLAN.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Plan v0.3.13 — WS standard / Helius / HTTP live + convergence multi-source RawTransaction
|
||||
|
||||
## 1. But de la version
|
||||
|
||||
`0.3.13` étend la verticale live stable de `0.3.12` sans remplacer Yellowstone, sans recréer Transport et sans transformer le Worker en Job historique.
|
||||
|
||||
Pipeline durable :
|
||||
|
||||
```text
|
||||
source live caller-composed
|
||||
-> signal ou matériau Worker privé
|
||||
-> convergence/coalescence bornée Worker
|
||||
-> hydration HTTP observed si le matériau n'est pas complet
|
||||
-> Common RAW ksp-raw-transaction-lib
|
||||
-> admission Worker centrale existante
|
||||
-> persistence ksp-store-lib
|
||||
```
|
||||
|
||||
Sources P0 retenues :
|
||||
|
||||
```text
|
||||
Yellowstone existant
|
||||
WS standard logsSubscribe + getTransaction observed
|
||||
WS standard blockSubscribe full/base64
|
||||
Helius transactionSubscribe full/base64 + getTransaction observed
|
||||
HTTP live getSlot + getBlocksWithLimit + getBlock observed
|
||||
```
|
||||
|
||||
`0.3.13` ferme la convergence live et les observations multiples. Le gap repair multi-source, les campagnes historiques et les sources EARLY restent `0.3.14+` / `0.3.16+` selon la roadmap.
|
||||
|
||||
## 2. Base autoritaire auditée en pre.001
|
||||
|
||||
```text
|
||||
archive : khadhroony-solana-project-v0.3.12.zip
|
||||
SHA-256 : 85c41eb9f8575ee58edd9863445cbc37b79ef59c4a7cf882679ff24dc8991bf5
|
||||
ZIP bytes : 8260528
|
||||
ZIP entries : 1981
|
||||
ZIP files : 1788
|
||||
workspace members : 21
|
||||
workspace.package.version : 0.3.12
|
||||
stable delta : deltas/0.3.12/rel.001.md
|
||||
prompt : prompts/032-V0_3_13_START_PROMPT.md
|
||||
```
|
||||
|
||||
Contrôles archive :
|
||||
|
||||
```text
|
||||
unzip -t : PASS
|
||||
entrée absolue : 0
|
||||
path traversal : 0
|
||||
doublon d'entrée ZIP : 0
|
||||
symlink ZIP : 0
|
||||
Cargo.lock : 0
|
||||
rust-toolchain.toml : 0
|
||||
package-lock/pnpm-lock/yarn.lock : 0
|
||||
.env : 0
|
||||
crate manifests : 21
|
||||
workspace members sans crate : 0
|
||||
crates hors workspace : 0
|
||||
```
|
||||
|
||||
La stable contient bien la verticale productive `Worker -> Transport -> Common RAW -> Store` de `0.3.12`, sans edge Worker vers Config, Job Backfill ou backend Store physique.
|
||||
|
||||
## 3. Audit des règles actives
|
||||
|
||||
Les documents normatifs ont été relus depuis `RULES.md` et `docs/rules/`.
|
||||
|
||||
Contraintes bloquantes :
|
||||
|
||||
```text
|
||||
Rust 2024
|
||||
unsafe interdit
|
||||
unwrap / expect / panic interdits en production
|
||||
? interdit en production
|
||||
retours explicites
|
||||
pas de pub mod
|
||||
pub/pub(crate) partagés réexportés au crate-root
|
||||
accès intra-crate partagé via crate::Item
|
||||
unit_tests/ pour les tests privés, tests/ pour l'API publique
|
||||
Config possède fichiers/profils/endpoints/secrets
|
||||
Transport ne dépend ni de Config ni de Store
|
||||
Worker ne dépend ni de Job Backfill ni d'un backend Store physique
|
||||
Worker persiste via ksp-store-lib seulement
|
||||
aucun acteur/socket/client Transport réimplémenté dans Worker
|
||||
une prerelease non-fix synchronise workspace.package.version
|
||||
archive d'échange = delta minimal
|
||||
commande non exécutée != PASS
|
||||
```
|
||||
|
||||
### 3.1 Collision normative trouvée
|
||||
|
||||
L'audit supplémentaire d'unicité des identifiants de règles a trouvé deux règles distinctes nommées `KSP-CONFIG-018` dans `docs/rules/RULES_KSP.md`.
|
||||
|
||||
Le delta historique `0.1.3-pre.014` prouve que la règle d'inventaire `.env.example` est l'identité `KSP-CONFIG-018` d'origine. La règle desktop ajoutée ultérieurement doit donc devenir `KSP-CONFIG-019` sans changement de contenu normatif.
|
||||
|
||||
Cette correction documentaire est intégrée à `pre.001` parce qu'elle ferme une ambiguïté normative découverte pendant le gate de règles demandé par le prompt.
|
||||
|
||||
## 4. État stable à préserver
|
||||
|
||||
`0.3.12` possède déjà :
|
||||
|
||||
```text
|
||||
start/stop/supervisor Worker
|
||||
mpsc d'admission centrale bornée
|
||||
persistence Store atomique/idempotente
|
||||
Common RAW Legacy/V0/V1
|
||||
une source Yellowstone caller-composed
|
||||
Transaction/TransactionStatus/Block -> hydration HTTP observed
|
||||
BlockMeta/Slot -> continuité seulement
|
||||
coalescence hydration (network, signature, commitment)
|
||||
processing frontier run-local
|
||||
reconnect/replay/gap source-neutral
|
||||
fault sur retention gap prouvé
|
||||
shutdown borné avec abort/join
|
||||
snapshot latest-value redacted
|
||||
canaris dependency/security cross-layer
|
||||
```
|
||||
|
||||
La migration multi-source doit réutiliser ces contrats plutôt que créer un second pipeline.
|
||||
|
||||
## 5. Audit Transport interne actuel
|
||||
|
||||
### 5.1 WebSocket standard
|
||||
|
||||
`ksp-onchain-transport-lib` possède déjà `SolanaStandardWsSession`, façade typée au-dessus du même `WsSession` physique.
|
||||
|
||||
Elle expose notamment :
|
||||
|
||||
```text
|
||||
logs_subscribe
|
||||
block_subscribe
|
||||
signature_subscribe
|
||||
slot/root/cluster wrappers existants
|
||||
snapshot/state/close
|
||||
```
|
||||
|
||||
Le reconnect, le resubscribe, les IDs distants, les queues de notifications et le backpressure WebSocket sont Transport-owned.
|
||||
|
||||
### 5.2 Helius WebSocket
|
||||
|
||||
`HeliusLaserStreamWsSession` réutilise le même acteur physique Transport et expose `transaction_subscribe` sans escape hatch vers le `WsSession` générique.
|
||||
|
||||
Le type `HeliusFullTransactionNotification` fournit le matériau transactionnel riche, la signature, le slot et l'index, mais l'enveloppe full qualifiée ne contient pas directement tous les champs Common RAW déjà garantis par `getTransaction observed`.
|
||||
|
||||
### 5.3 HTTP
|
||||
|
||||
Le pool HTTP expose déjà les primitives nécessaires :
|
||||
|
||||
```text
|
||||
get_transaction_observed
|
||||
get_block_observed
|
||||
get_slot
|
||||
get_blocks
|
||||
get_blocks_with_limit
|
||||
```
|
||||
|
||||
Le winner provider/endpoint est projeté sous forme sûre ; URL, credential et erreur distante arbitraire restent cachés.
|
||||
|
||||
Retry, rate limit, timeout et sélection d'endpoint restent Transport-owned.
|
||||
|
||||
## 6. Audit externe courant du 10 septembre 2026
|
||||
|
||||
### 6.1 Solana logsSubscribe
|
||||
|
||||
La documentation Solana courante confirme :
|
||||
|
||||
```text
|
||||
all
|
||||
allWithVotes
|
||||
mentions avec exactement un pubkey par abonnement
|
||||
notification = context.slot + signature + err + logs
|
||||
```
|
||||
|
||||
Cette source ne transporte pas un RAW complet ; `getTransaction observed` reste requis.
|
||||
|
||||
### 6.2 Solana blockSubscribe
|
||||
|
||||
La documentation courante maintient `blockSubscribe` comme méthode instable, disponible seulement sur les validators qui activent explicitement la subscription de blocs. Commitment admis : `confirmed` ou `finalized`.
|
||||
|
||||
Pour KSP P0 :
|
||||
|
||||
```text
|
||||
encoding = base64
|
||||
transactionDetails = full
|
||||
showRewards = false
|
||||
maxSupportedTransactionVersion = 1
|
||||
```
|
||||
|
||||
Le guide Solana Transaction V1 courant précise qu'un client version-aware doit utiliser `maxSupportedTransactionVersion = 1` pour `getTransaction`, `getBlock` et la consommation de blocs ; sinon une transaction V1 peut faire échouer HTTP ou produire `block: null` côté `blockSubscribe`.
|
||||
|
||||
Le format V1 n'est pas encore actif sur les clusters publics au 10 septembre 2026, mais KSP doit être prêt avant activation.
|
||||
|
||||
### 6.3 Helius transactionSubscribe
|
||||
|
||||
La documentation/pricing Helius courant confirme :
|
||||
|
||||
```text
|
||||
transactionSubscribe disponible à partir du tier Developer
|
||||
standard WSS disponible sur Free+
|
||||
blockSubscribe classé unstable et non supporté sur LaserStream WSS
|
||||
maxSupportedTransactionVersion doit être préparé à 1 pour Legacy/V0/V1
|
||||
```
|
||||
|
||||
Conclusion :
|
||||
|
||||
```text
|
||||
Helius transactionSubscribe reste une source dédiée Helius
|
||||
blockSubscribe reste une source WS standard, jamais HeliusLaserStreamWsSession
|
||||
aucun tier/prix n'entre dans une constante métier KSP
|
||||
smoke Helius live conditionnel au credential/tier opérateur
|
||||
```
|
||||
|
||||
### 6.4 Sources externes normatives
|
||||
|
||||
```text
|
||||
https://solana.com/docs/rpc/websocket/logssubscribe
|
||||
https://solana.com/docs/rpc/websocket/blocksubscribe
|
||||
https://solana.com/docs/rpc/http/getslot
|
||||
https://solana.com/docs/rpc/http/getblocks
|
||||
https://solana.com/docs/rpc/http/getblockswithlimit
|
||||
https://solana.com/docs/rpc/http/getblock
|
||||
https://solana.com/docs/rpc/http/gettransaction
|
||||
https://solana.com/docs/core/transactions/versioned-transactions
|
||||
https://www.helius.dev/docs/api-reference/rpc/websocket-methods
|
||||
https://www.helius.dev/pricing
|
||||
https://www.helius.dev/blog/laserstream-websockets
|
||||
```
|
||||
|
||||
## 7. Décision de maintien de la release
|
||||
|
||||
Décision : **maintenir `0.3.13` telle que prévue**, sans rescission fonctionnelle avant codage.
|
||||
|
||||
Motifs :
|
||||
|
||||
```text
|
||||
les quatre nouvelles familles de Transport existent déjà
|
||||
aucune nouvelle dépendance externe n'est nécessaire
|
||||
Common RAW et Store n'ont pas besoin d'être redessinés
|
||||
le Worker a déjà une admission centrale bornée et des observations déterministes
|
||||
le principal refactor est local au Worker : source inventory + convergence globale
|
||||
la prévision pre.002..pre.012 sépare correctement les risques
|
||||
pre.013/pre.014/pre.015 réservent gate, documentation et publication
|
||||
```
|
||||
|
||||
Le scope serait rescindé uniquement si `pre.002` démontre qu'une collection multi-source sûre exige une rupture de Common RAW/Store/Transport, ce que l'audit `pre.001` ne montre pas.
|
||||
|
||||
## 8. Modèle de source multi-source retenu
|
||||
|
||||
### 8.1 Source logique
|
||||
|
||||
Le Worker introduira une source live interne discriminée par **capability**, pas par provider :
|
||||
|
||||
```text
|
||||
Yellowstone
|
||||
StandardLogs
|
||||
StandardBlock
|
||||
HeliusTransaction
|
||||
HttpBlockPolling
|
||||
```
|
||||
|
||||
Le provider/endpoint reste une donnée de route/provenance Transport, pas un enum Worker.
|
||||
|
||||
### 8.2 Identité de source
|
||||
|
||||
Chaque source reçoit une `source_key` stable de 32 octets dérivée par SHA-256 d'un domaine KSP et des seules données sûres nécessaires :
|
||||
|
||||
```text
|
||||
network
|
||||
source family
|
||||
safe provider/endpoint identity ou profile-safe identity
|
||||
commitment
|
||||
filter fingerprint / request fingerprint
|
||||
```
|
||||
|
||||
Aucune URL, API key, header, transaction, log ou erreur distante ne participe en clair à la clé ou à Debug.
|
||||
|
||||
Deux sources configurées avec exactement la même identité logique sont rejetées à la construction des runtime resources afin d'éviter une duplication accidentelle invisible.
|
||||
|
||||
### 8.3 Collection bornée
|
||||
|
||||
Décision P0 :
|
||||
|
||||
```text
|
||||
MAX_RAW_TRANSACTION_INGEST_LIVE_SOURCES = 32
|
||||
minimum = 1 source pour start_with_runtime_resources
|
||||
maximum = 32 sources logiques par Worker
|
||||
```
|
||||
|
||||
Cette borne concerne les **sources runtime**, pas la cardinalité des filtres provider, laquelle reste possédée et bornée par Transport.
|
||||
|
||||
La collection est validée entièrement avant tout spawn réseau.
|
||||
|
||||
### 8.4 Simultanéité
|
||||
|
||||
Toutes les sources retenues dans `RawTransactionIngestRuntimeResources` sont démarrées simultanément.
|
||||
|
||||
Il n'existe pas en `0.3.13` de politique implicite :
|
||||
|
||||
```text
|
||||
first-provider-wins
|
||||
priority/fallback caché
|
||||
source primaire + standby
|
||||
arrêt des autres sources après première observation
|
||||
```
|
||||
|
||||
Les priorités Config éventuelles restent hors Worker tant qu'une sémantique de coverage/failover n'est pas définie en `0.3.14`.
|
||||
|
||||
## 9. Convergence globale retenue
|
||||
|
||||
### 9.1 Deux classes d'entrée
|
||||
|
||||
Une source Worker produit l'une des formes privées suivantes :
|
||||
|
||||
```text
|
||||
ReferenceSignal
|
||||
network + signature + slot + commitment + source observation seed
|
||||
|
||||
CompleteMaterial
|
||||
RawTransactionMaterial + source observation seed
|
||||
```
|
||||
|
||||
`ReferenceSignal` doit être hydraté. `CompleteMaterial` peut entrer directement dans Common RAW si sa qualification de version est prouvée.
|
||||
|
||||
### 9.2 Coordinator Worker global
|
||||
|
||||
Le coordinator d'hydration actuellement privé à la source Yellowstone devient une ressource Worker **globale aux sources**.
|
||||
|
||||
Clé de coalescence :
|
||||
|
||||
```text
|
||||
(network, signature, hydration commitment)
|
||||
```
|
||||
|
||||
Un seul `getTransaction observed` est ouvert pour plusieurs signaux simultanés portant la même clé. Les observation seeds restent distincts et sont conservés dans un vecteur borné par le nombre total de signaux admis.
|
||||
|
||||
### 9.3 Bornes globales
|
||||
|
||||
Décision P0 :
|
||||
|
||||
```text
|
||||
source signal queue capacity = settings.admission_queue_capacity()
|
||||
global pending signal count <= settings.admission_queue_capacity()
|
||||
hydration tasks in flight <= settings.persistence_concurrency()
|
||||
source count <= 32
|
||||
pas de queue provider privée dans Worker
|
||||
pas de Vec/Map pending non bornée
|
||||
```
|
||||
|
||||
Les limites existantes restent :
|
||||
|
||||
```text
|
||||
admission queue : 1 .. 65536
|
||||
persistence concurrency : 1 .. 64
|
||||
shutdown timeout : bornes 0.3.12 conservées
|
||||
```
|
||||
|
||||
Le coordinator doit utiliser la capacité effective configurée plutôt que la constante maximale comme borne opérationnelle de pending.
|
||||
|
||||
### 9.4 Fairness minimale
|
||||
|
||||
Aucune source ne reçoit une queue Worker non bornée. Tous les producteurs attendent sur le même canal borné et subissent le même backpressure.
|
||||
|
||||
`pre.009` doit prouver qu'un duplicate storm d'une source ne peut ni faire croître la mémoire sans borne, ni créer un fanout d'hydration, ni empêcher définitivement une autre source déjà prête d'être consommée.
|
||||
|
||||
Aucune promesse de scheduler pondéré complexe n'est introduite en `0.3.13`.
|
||||
|
||||
## 10. Observations multiples sans identité RawTransaction dupliquée
|
||||
|
||||
Identité canonique durable :
|
||||
|
||||
```text
|
||||
(RawNetworkId, TransactionSignature)
|
||||
```
|
||||
|
||||
Elle ne contient jamais la source.
|
||||
|
||||
Pour une même transaction observée par plusieurs sources :
|
||||
|
||||
```text
|
||||
canonicalisation Common RAW une fois par matériau convergé
|
||||
première observation -> persist_raw_transaction_acquisition atomique
|
||||
observations supplémentaires du même lot -> record_raw_transaction_observation
|
||||
```
|
||||
|
||||
Cette stratégie réutilise la capability Store existante conçue pour enregistrer une observation supplémentaire sans resoumettre le payload RAW potentiellement volumineux.
|
||||
|
||||
Les clés d'observation restent producteur-owned et déterministes. Deux sources distinctes doivent produire deux observation keys distinctes ; une rediffusion idempotente de la même source doit retrouver la même key.
|
||||
|
||||
Si la persistence atomique initiale échoue, aucune observation additionnelle n'est écrite. Si une observation additionnelle échoue, le Worker conserve la politique de faute Store sûre de `0.3.12` ; aucun succès silencieux n'est déclaré.
|
||||
|
||||
## 11. Content conflict et disagreement cross-source
|
||||
|
||||
Politique conservatrice :
|
||||
|
||||
```text
|
||||
même identité + même canonical payload/hash = idempotence
|
||||
même identité + payload/hash divergent = content conflict explicite
|
||||
```
|
||||
|
||||
Aucune majorité de providers, préférence de tier ou overwrite n'est autorisé.
|
||||
|
||||
Le Store reste l'autorité durable finale du conflit. Le coordinator peut détecter plus tôt une divergence lorsque plusieurs matériaux complets de même identité coexistent dans le même lot, mais cette optimisation ne remplace jamais le guard Store.
|
||||
|
||||
Un content conflict reste terminal pour le Worker en `0.3.13`.
|
||||
|
||||
## 12. Contrat source Yellowstone existant
|
||||
|
||||
Entrée :
|
||||
|
||||
```text
|
||||
YellowstoneGrpcChannel
|
||||
YellowstoneSubscribeRequest
|
||||
HttpTransportPool
|
||||
HttpRoleName hydration
|
||||
network dérivé et validé
|
||||
```
|
||||
|
||||
Sortie : `ReferenceSignal` pour les familles Transaction/TransactionStatus/Block qualifiées, continuité seule pour BlockMeta/Slot.
|
||||
|
||||
Bornes : Transport + queue globale Worker ; aucune nouvelle queue par source.
|
||||
|
||||
Retry/reconnect : Transport Yellowstone et HTTP.
|
||||
|
||||
Preuve : suites `0.3.12` non régressées + canaris multi-source avec Yellowstone en parallèle d'une seconde source factice/déterministe.
|
||||
|
||||
## 13. Contrat source WS standard logsSubscribe
|
||||
|
||||
Entrée caller-composed :
|
||||
|
||||
```text
|
||||
WsEndpointSettings kind solana_standard
|
||||
SolanaLogsSubscribeFilter
|
||||
commitment Confirmed ou Finalized
|
||||
HttpTransportPool
|
||||
HttpRoleName hydration
|
||||
```
|
||||
|
||||
Le Worker ouvre `SolanaStandardWsSession::connect` via Transport puis `logs_subscribe`.
|
||||
|
||||
Sortie :
|
||||
|
||||
```text
|
||||
context.slot
|
||||
signature
|
||||
source observation seed
|
||||
```
|
||||
|
||||
Les logs et l'erreur distante ne sont jamais recopiés dans snapshot/tracing ; ils ne sont pas nécessaires à Common RAW.
|
||||
|
||||
Hydration : `get_transaction_observed` avec Base64 et `maxSupportedTransactionVersion = 1`.
|
||||
|
||||
Retry/reconnect/resubscribe : Transport WS.
|
||||
|
||||
Hydration retry/rate limit : Transport HTTP.
|
||||
|
||||
Preuve : fixture logs notification -> une seule hydration -> exact Common RAW golden ; mentions/all/allWithVotes ; stop/reconnect/backpressure ; redaction des logs.
|
||||
|
||||
## 14. Contrat source WS standard blockSubscribe
|
||||
|
||||
Entrée caller-composed :
|
||||
|
||||
```text
|
||||
WsEndpointSettings kind solana_standard
|
||||
SolanaBlockSubscribeFilter
|
||||
commitment Confirmed ou Finalized
|
||||
encoding Base64
|
||||
transactionDetails Full
|
||||
maxSupportedTransactionVersion = 1
|
||||
showRewards = false
|
||||
```
|
||||
|
||||
Sortie : transactions du bloc sous forme `CompleteMaterial` lorsque la version est qualifiée ; fallback/fault explicite ailleurs.
|
||||
|
||||
Qualification P0 :
|
||||
|
||||
```text
|
||||
Legacy : RAW-direct déjà prouvé par 0.3.10, à rejouer
|
||||
V0 : RAW-direct déjà prouvé par 0.3.10, à rejouer
|
||||
V1 : doit être prouvé en pre.004 sur fixture locale v1 avant RAW-direct
|
||||
```
|
||||
|
||||
Tant que le golden V1 n'est pas vert, une transaction V1 n'est pas déclarée direct-qualified. Le chemin autorisé est hydration `getTransaction observed` si l'identité peut être obtenue, sinon faute explicite sûre.
|
||||
|
||||
`block: null` avec erreur de version/support n'est jamais interprété comme bloc vide ni comme progression de frontier.
|
||||
|
||||
Retry/reconnect/resubscribe : Transport WS.
|
||||
|
||||
Preuve : parité bytes/hash entre notification blockSubscribe et `getBlock`/fixture Common RAW pour Legacy/V0 puis V1 ; canari `block:null` ; unsupported validator explicite.
|
||||
|
||||
## 15. Contrat source Helius transactionSubscribe
|
||||
|
||||
Entrée caller-composed :
|
||||
|
||||
```text
|
||||
WsEndpointSettings kind helius_laserstream
|
||||
HeliusTransactionSubscribeRequest
|
||||
commitment Confirmed ou Finalized
|
||||
encoding Base64
|
||||
transactionDetails Full
|
||||
maxSupportedTransactionVersion = 1
|
||||
HttpTransportPool
|
||||
HttpRoleName hydration
|
||||
```
|
||||
|
||||
Sortie : `ReferenceSignal` riche mais hydraté avant Common RAW P0.
|
||||
|
||||
Motif : conserver une seule source de vérité de complétude `getTransaction observed` pour `blockTime`, version et wire exact, même si Helius enrichit son enveloppe à l'avenir.
|
||||
|
||||
Retry/reconnect/resubscribe : Transport WS.
|
||||
|
||||
Hydration retry/rate limit : Transport HTTP.
|
||||
|
||||
Config : réutiliser uniquement `KSP_SECRET_HELIUS_API_KEY`. Aucun secret Helius supplémentaire et aucun SDK provider.
|
||||
|
||||
Live smoke : conditionnel à un credential/tier Developer+ disponible. L'absence de ressource reste `NON EXÉCUTÉ`.
|
||||
|
||||
## 16. Contrat source HTTP live block polling
|
||||
|
||||
### 16.1 Borne de run
|
||||
|
||||
Au démarrage de la source :
|
||||
|
||||
```text
|
||||
start_slot = getSlot(commitment)
|
||||
next_scan_slot = start_slot
|
||||
```
|
||||
|
||||
Aucun slot inférieur à `start_slot` n'est recherché par cette source. Elle reste donc live/run-local et ne devient pas un Backfill.
|
||||
|
||||
### 16.2 Discovery
|
||||
|
||||
À chaque cycle :
|
||||
|
||||
```text
|
||||
current_tip = getSlot(commitment)
|
||||
getBlocksWithLimit(next_scan_slot, bounded_limit, commitment)
|
||||
getBlock observed pour les slots réellement listés
|
||||
```
|
||||
|
||||
Les skipped slots sont exclus naturellement par `getBlocksWithLimit`; aucun faux gap n'est créé simplement parce qu'un slot n'a pas de bloc confirmé.
|
||||
|
||||
### 16.3 Bornes P0
|
||||
|
||||
Le contrat Worker de polling introduira :
|
||||
|
||||
```text
|
||||
poll interval default = 1 s
|
||||
poll interval min = 100 ms
|
||||
poll interval max = 30 s
|
||||
max discovered blocks per cycle default = 128
|
||||
max discovered blocks per cycle min = 1
|
||||
max discovered blocks per cycle max = 1024
|
||||
```
|
||||
|
||||
Le rate limit physique reste Transport-owned et peut ralentir l'exécution réelle.
|
||||
|
||||
Une réponse `getBlock = null` pour un slot précédemment listé ne fait pas avancer silencieusement `next_scan_slot`; le slot reste la tête de travail du cycle suivant ou devient une faute sûre selon le résultat déterministe défini en `pre.006`.
|
||||
|
||||
Timer/cadence : Worker source task.
|
||||
|
||||
Retry HTTP : Transport.
|
||||
|
||||
Preuve : faux pool/fixtures déterministes avec skipped slots, tip qui avance, null transitoire, stop pendant timer/getBlock, rate-limit lent et absence de scan antérieur au start slot.
|
||||
|
||||
## 17. Source lifecycle et health
|
||||
|
||||
Le lifecycle physique détaillé reste privé/source-neutral.
|
||||
|
||||
États existants à préserver :
|
||||
|
||||
```text
|
||||
Active
|
||||
Reconnecting
|
||||
Closing
|
||||
Closed
|
||||
Failed
|
||||
```
|
||||
|
||||
Sous multi-source, le Worker maintient un inventaire privé `source_key -> latest state` borné à 32 entrées.
|
||||
|
||||
Projection publique P0 :
|
||||
|
||||
```text
|
||||
source_total
|
||||
source_active
|
||||
source_reconnecting
|
||||
source_failed
|
||||
source_state agrégé compatible
|
||||
source_failure_total agrégé existant
|
||||
backpressure_total agrégé existant
|
||||
```
|
||||
|
||||
Aucun provider, endpoint, filtre, URL ou credential n'est exposé.
|
||||
|
||||
Politique conservatrice de terminalité : une source configurée qui atteint `Failed` reste terminale pour le Worker en `0.3.13`. KSP ne peut pas supposer que les autres sources couvrent le même univers de filtres. La relaxation vers degraded/failover exige une preuve de coverage et appartient à `0.3.14`.
|
||||
|
||||
Un reconnect transitoire peut projeter `Degraded` sans terminalité. Un retention gap prouvé reste terminal comme en `0.3.12`.
|
||||
|
||||
## 18. Processing frontier et continuité
|
||||
|
||||
La processing frontier reste run-local et ne devient ni checkpoint durable ni preuve de blockchain completeness.
|
||||
|
||||
Sous multi-source :
|
||||
|
||||
```text
|
||||
chaque signal/material observe son slot
|
||||
un pending coalescé reste pending tant que sa persistence/observation requise n'est pas réglée
|
||||
la frontier globale n'avance jamais à travers un pending de n'importe quelle source
|
||||
reconnect != replay != repair
|
||||
source redondante != preuve automatique de couverture
|
||||
```
|
||||
|
||||
Le gap repair reste explicitement `0.3.14`.
|
||||
|
||||
## 19. Threat model 0.3.13
|
||||
|
||||
### 19.1 Duplicate storm
|
||||
|
||||
Risque : une même signature arrive par plusieurs subscriptions/providers.
|
||||
|
||||
Réponse : coalescence globale, signal count borné, observation keys idempotentes, aucune hydration fanout.
|
||||
|
||||
### 19.2 Source skew
|
||||
|
||||
Risque : une source fournit un slot/index différent d'une autre.
|
||||
|
||||
Réponse : identity/material guards et conflit explicite ; aucune préférence silencieuse.
|
||||
|
||||
### 19.3 Provider disagreement
|
||||
|
||||
Risque : contenu divergent pour la même signature.
|
||||
|
||||
Réponse : hash canonique + Store content conflict terminal.
|
||||
|
||||
### 19.4 Reconnect storms
|
||||
|
||||
Risque : resubscribe simultané et duplicates.
|
||||
|
||||
Réponse : reconnect Transport-owned, logical subscription stable, coordinator idempotent/borné.
|
||||
|
||||
### 19.5 Hydration fanout
|
||||
|
||||
Risque : N sources déclenchent N getTransaction identiques.
|
||||
|
||||
Réponse : une hydration globale par `(network, signature, commitment)`.
|
||||
|
||||
### 19.6 Polling drift
|
||||
|
||||
Risque : timer plus rapide que capacité HTTP/Store.
|
||||
|
||||
Réponse : pas de spawn par tick, cycle séquentiel/borné, backpressure et rate limit Transport.
|
||||
|
||||
### 19.7 Slow Store
|
||||
|
||||
Risque : accumulation signal/hydration.
|
||||
|
||||
Réponse : admission et convergence bornées ; producteurs attendent ; aucun drop silencieux.
|
||||
|
||||
### 19.8 Stop/fault concurrent
|
||||
|
||||
Risque : connect/resubscribe/timer/hydration/persistence actifs au terminal.
|
||||
|
||||
Réponse : ownership supervisor, stop préemptif là où sûr, drain Store borné, abort/join de toutes tasks owned.
|
||||
|
||||
### 19.9 Secrets/remote material
|
||||
|
||||
Interdit dans Debug/error/snapshot/tracing :
|
||||
|
||||
```text
|
||||
URL
|
||||
API key/token/header
|
||||
transaction bytes
|
||||
raw signature text dans logs
|
||||
provider logs
|
||||
Helius filter values
|
||||
remote error text arbitraire
|
||||
```
|
||||
|
||||
## 20. Graphe Cargo cible
|
||||
|
||||
Aucune nouvelle dépendance externe n'est nécessaire.
|
||||
|
||||
```text
|
||||
ksp-worker-raw-transaction-ingest-lib
|
||||
-> ksp-core-lib
|
||||
-> ksp-logging-lib
|
||||
-> ksp-onchain-transport-lib
|
||||
-> ksp-raw-transaction-lib
|
||||
-> ksp-store-lib default-features=false
|
||||
-> ksp-worker-api
|
||||
-> sha2
|
||||
-> tokio macros,rt,sync,time
|
||||
```
|
||||
|
||||
Toujours interdit :
|
||||
|
||||
```text
|
||||
Worker -> ksp-config-lib
|
||||
Worker -> ksp-job-backfill-lib
|
||||
Worker -> ksp-store-postgres-lib
|
||||
Worker -> reqwest direct
|
||||
Worker -> tonic direct
|
||||
Worker -> yellowstone-grpc-proto direct
|
||||
Worker -> provider SDK
|
||||
Transport -> Common RAW
|
||||
Transport -> Store
|
||||
```
|
||||
|
||||
## 21. Config et secrets
|
||||
|
||||
L'archive stable contient des profils standard Solana committed et des exemples Helius LaserStream. `KSP_SECRET_HELIUS_API_KEY` est déjà l'identité de secret documentée.
|
||||
|
||||
Décision : `pre.001` n'ajoute aucun profil Config. `pre.005` ne modifiera Config que si un profil runtime committed est réellement nécessaire à un consumer/smoke de cette release. Le Worker reste incapable de lire Config.
|
||||
|
||||
Aucune nouvelle clé `.env` n'est anticipée.
|
||||
|
||||
## 22. Preuves déterministes obligatoires
|
||||
|
||||
Avant clôture technique :
|
||||
|
||||
```text
|
||||
resource collection 1..32 + duplicate source identity reject
|
||||
Yellowstone non-régression
|
||||
logs -> one hydration -> RAW exact
|
||||
blockSubscribe Legacy/V0 direct exact
|
||||
blockSubscribe V1 qualification ou fallback/fault exact
|
||||
block:null non assimilé à vide
|
||||
Helius full -> hydration -> RAW exact
|
||||
HTTP polling never scans before run start
|
||||
skipped slots handled without false transaction/gap
|
||||
cross-source same identity/same content -> one entity + N observations
|
||||
cross-source same identity/divergent content -> content conflict
|
||||
one hydration for duplicate cross-source references
|
||||
pending queues bounded under storm
|
||||
fair progress for a second ready source
|
||||
source failure/reconnect aggregate projection redacted
|
||||
stop/fault joins WS/poll/hydration/persistence tasks
|
||||
no Config/Job/backend/provider dependency leak
|
||||
Legacy/V0/V1 canaries cross-layer
|
||||
```
|
||||
|
||||
## 23. Smokes live et qualification
|
||||
|
||||
Disponibles sans secret selon l'environnement opérateur :
|
||||
|
||||
```text
|
||||
Solana HTTP Devnet
|
||||
Solana WS Devnet logsSubscribe
|
||||
Solana WS Devnet blockSubscribe seulement si endpoint/validator l'expose
|
||||
HTTP polling Devnet
|
||||
```
|
||||
|
||||
Conditionnels :
|
||||
|
||||
```text
|
||||
Helius transactionSubscribe : credential/tier Developer+
|
||||
Yellowstone : credential/provider selon stable 0.3.12
|
||||
```
|
||||
|
||||
Chaque smoke indisponible est `NON EXÉCUTÉ`, jamais PASS.
|
||||
|
||||
## 24. Sizing recalibré
|
||||
|
||||
### pre.001 — audit / règles / sizing / plan
|
||||
|
||||
Archive, règles, collision `KSP-CONFIG-018`, audit interne/externe, contrats sources, convergence, threat model, graphes, validation.
|
||||
|
||||
### pre.002 — runtime resources multi-source
|
||||
|
||||
Collection bornée 1..32, source key, discriminants capability-owned, validation globale, sans branchement productif des nouvelles sources.
|
||||
|
||||
### pre.003 — WS standard logsSubscribe + hydration
|
||||
|
||||
Source logs, signal privé, intégration coordinator global et hydration observed.
|
||||
|
||||
### pre.004 — WS standard blockSubscribe
|
||||
|
||||
Source block, projection full/base64, qualification Legacy/V0/V1, `block:null` et fallback/fault.
|
||||
|
||||
### pre.005 — Helius transactionSubscribe
|
||||
|
||||
Source Helius, max version 1, hydration, Config uniquement si réellement requis, tests redaction/tier non codé.
|
||||
|
||||
### pre.006 — HTTP live block polling
|
||||
|
||||
Borne de run, timer, getSlot/getBlocksWithLimit/getBlock observed, skipped slots/null/stop.
|
||||
|
||||
### pre.007 — supervisor/source inventory
|
||||
|
||||
Démarrage simultané, source lifecycle privé, stop/fault/joins et processing frontier multi-source.
|
||||
|
||||
### pre.008 — convergence + observations multiples
|
||||
|
||||
Coalescence cross-source, canonicalisation de lot, persistence entity + observations supplémentaires, idempotence.
|
||||
|
||||
### pre.009 — conflits/backpressure/fairness
|
||||
|
||||
Disagreement, content conflict, duplicate storms, global bounds, starvation canaries.
|
||||
|
||||
### pre.010 — snapshots/health multi-source
|
||||
|
||||
Counts source-neutral, agrégation health/activity, redaction publique.
|
||||
|
||||
### pre.011 — races/shutdown hardening
|
||||
|
||||
Stop/fault pendant connect/reconnect/hydration/polling/Store, no orphan et counter exhaustion.
|
||||
|
||||
### pre.012 — completeness/security cross-layer
|
||||
|
||||
Canaris API/dependencies/Legacy-V0-V1/Transport-Worker-CommonRAW-Store et non-régression Yellowstone.
|
||||
|
||||
### pre.013 — gate technique/live
|
||||
|
||||
Workspace complet, Clippy strict, tests, graphes/duplicates et smokes accessibles. Aucun nouveau scope.
|
||||
|
||||
### pre.014 — réconciliation documentaire
|
||||
|
||||
README/USAGE, plan, validation et architectures réellement affectées. Pas de CHANGELOG/ROADMAP/prompt suivant.
|
||||
|
||||
### pre.015 — préparation publication
|
||||
|
||||
Prompt `0.3.14`, CHANGELOG, ROADMAP et mécanique autorisée par les règles.
|
||||
|
||||
### rel.001
|
||||
|
||||
Publication stable mécanique après dernier gate validé.
|
||||
|
||||
## 25. Critère de sortie pre.001
|
||||
|
||||
Fermé avant `pre.002` :
|
||||
|
||||
```text
|
||||
release maintenue
|
||||
sources P0 identifiées
|
||||
entrée/sortie de chaque source définie
|
||||
retry/reconnect owner défini
|
||||
bornes multi-source définies
|
||||
coalescence cross-source définie
|
||||
stratégie observations multiples définie
|
||||
content conflict défini
|
||||
HTTP run bound/cadence définis
|
||||
health publique conservative définie
|
||||
smokes qualifiés
|
||||
aucune dépendance externe nouvelle
|
||||
collision normative corrigée
|
||||
```
|
||||
|
||||
Questions volontairement reportées :
|
||||
|
||||
```text
|
||||
preuve de coverage entre sources
|
||||
failover non-terminal d'une source
|
||||
repair multi-source
|
||||
historical replay/backfill
|
||||
EARLY feeds
|
||||
consumer Desk 0.3.15
|
||||
```
|
||||
Reference in New Issue
Block a user