v0.2.0-pre.002

This commit is contained in:
2026-08-17 13:33:37 +02:00
parent 7d40de3249
commit 259bff6707
23 changed files with 2999 additions and 3301 deletions

View File

@@ -1,614 +1,344 @@
<!-- file: docs/architecture/008-DATA_MATERIALIZATION_AND_STORE.md -->
<!-- version: 2 -->
<!-- version: 3 -->
# Data, Materialization et Store
## Objet
Ce document constitue la sortie principale de `0.0.3-pre.006`.
Ce document définit la chaîne durable KSP, la responsabilité du Store et les frontières de replay.
Il définit les frontières durables de données KSP et précise :
- les niveaux D1 à D4 ;
- la séparation `ksp-materializer-api` / `ksp-materializer-lib` / Store ;
- le rôle backend-agnostic de `ksp-store-api` ;
- PostgreSQL comme implémentation de référence de `ksp-store-lib` ;
- provenance et temporalités ;
- idempotence et versionnement des processors ;
- replay indépendant par frontière ;
- sémantique des notifications de données persistées ;
- stabilité différente entre niveaux structurants et projections spécialisées.
Le lifecycle complet, batching, concurrence, backlog et reprise des workers/jobs sont détaillés dans `009-ACQUISITION_WORKERS_AND_JOBS.md`.
## Nomenclature des niveaux durables
Les niveaux de données ne réutilisent pas N1 à N4, déjà réservés aux couches architecturales KSP.
La nomenclature durable retenue est :
La nomenclature canonique est désormais :
```text
D1 — Raw
D2 — Core canonique
D3 — Journal de matérialisation générique
D4 — Projections spécialisées/queryables par domaine
RAW -> CORE -> DECODE -> SPECIALIZED
```
Flux général :
Les aliases D1D4 restent utilisés pour les niveaux persistés :
```text
source on-chain
|
v
ksp-worker-raw-retriever
|
v
D1 Raw
|
v
ksp-worker-core-processor
|
v
D2 Core canonique
|
v
ksp-worker-generic-materializer
|
v
D3 journal générique
|
v
ksp-worker-domain-projector
|
v
D4 projections de domaine
D1 = RAW
D2 = CORE
D3 = DECODE / matérialisation générique décodée
D4 = SPECIALIZED
```
Le nom `ksp-worker-domain-projector` reste révisable ; la frontière D3 -> D4 est, elle, retenue.
Cette clarification remplace l'ancienne interprétation où D1 -> D2 pouvait déjà dépendre de `ksp-program-api`. **RAW et CORE sont indépendants de tout decoder Program.**
# D1 — Raw
## Principes structurants
- le Store persiste des contrats de données ; il ne possède ni transport, ni decoder, ni materializer ;
- chaque frontière durable peut être rejouée indépendamment ;
- les données de provenance/versioning permettent de savoir quel processor a produit quel output ;
- les couches dérivées ne rendent jamais obligatoire une nouvelle acquisition réseau lorsque l'input durable nécessaire existe déjà ;
- D4 privilégie les faits métier génériques lorsqu'une normalisation inter-protocoles est pertinente.
# D1 — RAW
## Mission
D1 conserve l'acquisition suffisamment fidèlement pour permettre un nouveau processing sans redemander la donnée à la blockchain lorsque l'information nécessaire a déjà été capturée.
RAW conserve l'acquisition suffisamment fidèlement pour reconstruire CORE sans redemander la donnée au provider lorsqu'elle a déjà été capturée.
`raw` ne signifie pas nécessairement « enveloppe propriétaire du provider conservée sans aucune normalisation ». Le transport peut normaliser ses différentes sources vers des modèles KSP homogènes.
Le transport peut normaliser plusieurs providers vers un modèle KSP homogène, mais D1 doit rester lossless pour les besoins de replay couverts.
La persistance D1 doit toutefois rester **lossless pour les besoins de replay couverts** : toute information nécessaire à la reconstruction du Core doit être conservée, y compris le contenu brut et la provenance utile.
D1 ne décode aucun programme Solana/SPL/Metaplex/DEX.
## Frontière transport -> D1
## Frontière Transport -> RAW
```text
Solana RPC ------\
Helius -----------+--> modèle homogène ksp-onchain-transport-lib
Yellowstone ------/
|
v
conversion explicite
|
v
DTO D1 de ksp-store-api
HTTP / WS / gRPC / provider
|
v
ksp-onchain-transport-lib
|
v
conversion explicite
|
v
ksp-store-api RAW DTO
|
v
ksp-store-lib
```
`ksp-onchain-transport-lib` ne dépend ni de `ksp-store-api` ni de `ksp-store-lib`.
La conversion appartient au composant de composition, principalement `ksp-worker-raw-retriever` ou `ksp-job-backfill`.
## Provenance RAW
## Provenance D1
Selon la catégorie, D1 doit pouvoir conserver notamment :
Selon la catégorie de donnée, D1 doit pouvoir conserver notamment :
- réseau ;
- identité blockchain : slot, signature, pubkey ou autre identifiant applicable ;
- contenu raw/replayable ;
- cluster/network ;
- slot/signature/pubkey/identité blockchain applicable ;
- payload replayable ;
- provider ;
- transport/source ;
- rôle d'acquisition : live, backfill, import ou autre ;
- instant d'observation/acquisition ;
- endpoint/source/transport ;
- rôle d'acquisition : live, backfill, import ;
- instant d'observation ;
- instant de persistence ;
- hash/identité d'idempotence ;
- informations de pagination/capture nécessaires à la reprise lorsque pertinentes.
- identité/hash d'idempotence ;
- cursor/page/range/checkpoint lorsque pertinent.
`block_time` reste optionnel et n'est jamais inventé lorsqu'il n'est pas fourni ou reconstructible de manière fiable.
# D2 — Core canonique
# D2 — CORE
## Mission
D2 contient les faits canoniques Solana produits à partir de D1.
CORE est une **normalisation canonique générique de la blockchain Solana**.
Le Core doit être suffisamment durable et général pour être rejoué vers les matérialisations futures sans repasser par l'acquisition ou le décodage raw.
Cette couche doit fonctionner même si `ksp-program-api` et `ksp-program-lib` ne sont pas encore capables de décoder le moindre programme métier.
Conceptuellement, D2 peut accueillir notamment :
Exemples de faits CORE candidats :
- transactions canoniques ;
- instructions top-level ;
- instructions CPI ;
- comptes/états canoniques ;
- résultats de décodage Program ouverts ;
- événements/return data lorsqu'ils sont supportés ;
- autres faits génériques Solana qui appartiennent réellement au Core.
- slots ;
- blocks et block metadata ;
- signatures ;
- transactions ;
- messages legacy/versioned ;
- account keys et address lookups ;
- comptes et états bruts structurés génériquement ;
- instructions top-level brutes ;
- instructions CPI brutes ;
- logs ;
- transaction meta ;
- balances/fees/rewards lorsqu'ils appartiennent au contrat blockchain générique ;
- return data brute ;
- relations structurelles transaction/message/instruction/account.
## Top-level / CPI
Un fait CORE peut contenir un `program_id`, des bytes et des indexes sans savoir que l'instruction représente un `Transfer`, un `Swap` ou une mutation Metadata.
Les instructions top-level et CPI restent des faits distincts.
Leur modèle peut partager des champs, mais KSP ne doit pas les fusionner artificiellement lorsque leurs invariants ou requêtes diffèrent.
La séparation physique exacte sera décidée dans la première release Store.
## Frontière D1 -> D2
## Frontière RAW -> CORE
```text
DTO D1 store
|
v
ksp-worker-core-processor
|
+--> conversion vers entrée ksp-program-api
|
+--> ksp-program-lib / extension compatible
|
+--> sortie Core ouverte
|
v
conversion vers DTO D2 store
D1 RAW
|
v
normalisation Solana générique
|
v
D2 CORE
```
`ksp-program-api` / `ksp-program-lib` restent indépendants du Store.
Interdictions :
## Provenance D2
```text
RAW -> CORE -X-> ksp-program-api
RAW -> CORE -X-> ksp-program-lib
RAW -> CORE -X-> ksp-materializer-api
```
D2 doit pouvoir relier un résultat à :
Les codecs/wires génériques nécessaires à la structure Solana peuvent provenir de `ksp-interface-lib` lorsqu'ils appartiennent à la façade wire officielle, sans transformer cette étape en décodage Program.
## Provenance CORE
D2 doit pouvoir relier chaque résultat à :
- son input D1 ;
- l'identité/version du processor ;
- l'identité/version de l'implémentation Program/decoder lorsque pertinente ;
- la capacité de décodage utilisée ;
- un hash de l'input logique ;
- l'identité/version du normalizer CORE ;
- un hash logique d'input ;
- l'instant de processing/persistence ;
- l'état de processing lorsqu'un lifecycle durable est nécessaire.
- son état de processing durable lorsque nécessaire.
# D3 — Journal de matérialisation générique
# D3 — DECODE / matérialisation générique
## Mission
D3 est un **journal durable**, pas une étape volatile.
DECODE commence lorsque KSP interprète un `program_id`, un layout d'instruction, un compte ou un événement selon un contrat Program/protocole.
Il conserve l'équivalent conceptuel obligatoire de l'ancien journal `k_sol_mat_outputs` de `ks-store`, sans figer encore le nom exact de la table KSP.
Il doit permettre de répondre à des questions telles que :
La progression logique d'un groupe est :
```text
quel input D2 ?
CORE
|
v
decoder Program
|
v
decoded facts
|
v
materialisation générique / journal durable
|
v
D3 DECODE
```
D3 conserve l'équivalent conceptuel obligatoire du journal générique de matérialisation de bot3 (`k_sol_mat_outputs`), sans imposer son ancien schéma ou son nom physique.
Le journal doit pouvoir répondre au minimum :
```text
quel input CORE ?
quel program/decoder ?
quelle version ?
quel materializer ?
quelle version ?
quel output logique ?
quel type/domaine ?
quel hash ?
quel instant ?
quel état courant/superseded/failed/replay ?
quel état/superseded/failed/replay ?
```
D3 permet notamment de reconstruire D4 après évolution d'un projector sans refaire D1 -> D2 ou D2 -> D3.
Les types exacts de decoded facts et du journal sont décidés lorsque les premiers vertical slices Program existent.
## Frontière D2 -> D3
## Frontière CORE -> DECODE
```text
D2 Core
D2 CORE
|
v
ksp-worker-generic-materializer
|
+--> conversion vers ksp-materializer-api
|
+--> GenericMaterializer
ksp-program-api implementation
|
v
generic materialization output
decoded output
|
v
conversion vers DTO D3 store
ksp-materializer-api implementation
|
v
D3 journal / decoded materialization
```
Les noms Rust exacts ne sont pas figés.
Les implémentations officielles pourront provenir de `ksp-program-lib` et `ksp-materializer-lib`; des implémentations externes compatibles restent possibles.
## Extensibilité externe
Program et Materializer ne dépendent pas du backend Store.
Une implémentation externe de materializer doit pouvoir produire un output générique compatible avec D3 sans exiger une nouvelle table PostgreSQL spécialisée.
Cela rend possible :
```text
external materializer
|
v
ksp-materializer-api
|
v
D3 journal générique
```
avant une éventuelle intégration officielle complète en D4.
# D4 — Projections spécialisées de domaine
# D4 — SPECIALIZED
## Mission
D4 contient les représentations optimisées pour les requêtes métier, analytiques et produit.
Exemples futurs :
- assets/tokens ;
- metadata d'assets/tokens ;
- Solana Program Metadata ;
- liquidity pools ;
- order books ;
- swaps/trades ;
- prices/volumes ;
- positions ;
- autres projections de domaine.
## Faits canoniques, pas familles par protocole
D4 reste organisé par **fait canonique**, pas par Program ID/protocole.
Éviter par défaut :
```text
meteora_pools
raydium_pools
orca_pools
```
au profit d'une projection canonique telle que :
```text
liquidity_pools
```
avec provenance/identité du protocole lorsque nécessaire.
La même règle s'applique aux swaps, order books et autres faits pouvant être normalisés.
## Metadata
Les metadata d'assets/tokens constituent une famille canonique commune pouvant recevoir des données provenant notamment :
- Metaplex Token Metadata ;
- Token-2022 Metadata.
Solana Program Metadata reste une projection distincte car le domaine fonctionnel est différent.
## Nouvelle projection externe
Une nouvelle projection D4 relationnelle implique nécessairement un contrat de persistence et une implémentation backend.
KSP ne masque pas cette réalité derrière une API de matérialisation « magique ».
Une extension externe peut fonctionner jusqu'à D3 sans migration Store spécialisée. Pour obtenir une nouvelle projection D4 officielle, il faut intégrer :
- le contrat DTO/repository approprié dans `ksp-store-api` ;
- la migration/repository PostgreSQL dans `ksp-store-lib` ;
- la conversion/projector appropriée dans le composant de processing.
Un mécanisme de backend/projection entièrement externe pourra être étudié seulement si un besoin concret apparaît.
# Stabilité des niveaux durables
La direction retenue est :
```text
D1 — fortement stable
D2 — fortement stable
D3 — fortement stable
D4 — volontairement plus évolutif
```
Après stabilisation de la première série Store réelle, les contrats D1/D2/D3 doivent changer seulement en cas :
- d'erreur structurelle ;
- d'omission majeure ;
- de nécessité de compatibilité impossible à résoudre additivement.
D4 peut évoluer plus librement lorsque de nouveaux décodeurs, materializers ou produits révèlent des besoins queryables supplémentaires.
# `ksp-materializer-api`
## Rôle
Une seule crate publique est retenue :
```text
ksp-materializer-api
```
Elle expose les contrats de matérialisation réutilisables sans dépendre du Store.
Deux capacités conceptuelles doivent pouvoir être distinguées :
```text
GenericMaterializer
DomainProjector
```
Les noms exacts restent à valider.
### GenericMaterializer
Transforme une représentation Core/runtime en output générique persistable en D3.
### DomainProjector
Transforme un ou plusieurs inputs génériques/canoniques en représentation spécialisée de domaine destinée à D4.
Le second contrat peut évoluer en fonction des premiers cas réels. La séparation des responsabilités est plus importante que le nom du trait.
## Dépendances
```text
ksp-materializer-api
-> ksp-core-lib
-> ksp-program-api
```
Pas de dépendance vers Store.
# `ksp-materializer-lib`
`ksp-materializer-lib` contient les implémentations officielles KSP de `ksp-materializer-api`.
Organisation conceptuelle possible :
```text
generic/
...
domain/
metadata/
token/
dex/
...
```
La structure finale suivra les règles de domaine établies avec les premières implémentations.
Interdictions :
```text
ksp-materializer-lib -X-> ksp-store-api
ksp-materializer-lib -X-> ksp-store-lib
```
Un materializer transforme ; il ne persiste pas directement.
Le worker/job/pipeline spécialisé relie la transformation à la persistence.
# `ksp-store-api`
## Rôle
`ksp-store-api` expose la frontière backend-agnostic de persistence KSP.
Il possède les contrats persistants correspondant aux niveaux durables :
```text
raw
core
materialization
domain
```
La structure exacte des modules Rust sera définie avec la première implémentation.
`ksp-store-api` ne dépend pas de Program, Materializer ou Transport.
## Contrats génériques et contrats de domaine
D1/D2/D3 doivent rester génériques et fortement structurants.
D4 peut croître progressivement avec les domaines officiellement supportés.
Cette différence est volontaire : l'API Store doit pouvoir ajouter de nouvelles projections queryables sans déstabiliser les contrats de replay historiques.
# `ksp-store-lib`
`ksp-store-lib` est l'implémentation officielle de référence de `ksp-store-api`.
PostgreSQL est le backend de référence prévu.
La crate possède notamment :
- configuration backend/connexion ;
- pool/transactions backend ;
- migrations ;
- repositories ;
- queries ;
- persistence D1/D2/D3/D4 ;
- primitives de backlog/replay nécessaires au backend ;
- mécanismes PostgreSQL de notification lorsqu'ils sont retenus.
Les autres crates KSP ne contournent pas `ksp-store-lib` pour exécuter directement leurs propres opérations PostgreSQL.
Un second backend n'est pas créé abstraitement ; il devra justifier l'évolution de l'architecture lorsqu'un besoin réel apparaît.
# Temporalités
Les temporalités blockchain et locales sont distinctes.
Exemples blockchain :
```text
slot
block_time: Option<...>
```
Exemples locaux :
```text
observed_at
acquired_at
persisted_at
processed_at
materialized_at
projected_at
```
Toutes ne doivent pas nécessairement être présentes dans chaque DTO/table. Leur sémantique doit cependant être explicite lorsqu'elles existent.
Aucune date locale ne remplace silencieusement un `block_time` absent.
# Provenance
Un niveau dérivé doit permettre de remonter à son input durable et au processor qui l'a produit.
## D1
Provenance d'acquisition :
- network ;
- provider/source ;
- transport ;
- rôle d'acquisition ;
- identité blockchain ;
- temporalités d'observation/persistence.
## D2
En plus :
- input D1 ;
- processor/decoder identity ;
- processor/decoder version ;
- input hash ;
- processing time/state.
## D3
En plus :
- input D2 ;
- materializer identity/version ;
- output identity/type/domain ;
- output/input hash ;
- materialization time/state.
## D4
En plus :
- input(s) D3 ou références canoniques explicitement définies ;
- projector identity/version ;
- projection time/state.
La représentation exacte de la provenance sera conçue pour éviter de répéter inutilement de gros payloads.
# Idempotence et versionnement
Chaque frontière dérivée doit pouvoir rejouer le même input sans créer de doublons logiquement distincts.
Principe conceptuel :
```text
same logical input
+ same processor identity
+ same processor version
+ same logical output identity
= same durable result
```
Une nouvelle version du processor doit pouvoir coexister avec ou superséder le résultat précédent selon la politique du niveau.
Le système doit pouvoir représenter selon besoin des états tels que :
```text
current
superseded
pending
failed
replay
```
Les noms, colonnes et contraintes SQL exacts seront décidés avec la première implémentation.
L'idempotence ne doit pas reposer uniquement sur l'espoir qu'une notification soit livrée une seule fois.
# Replay
Les replays sont séparés par frontière durable :
```text
D1 -> D2
D2 -> D3
D3 -> D4
```
Ils doivent pouvoir être exécutés indépendamment.
SPECIALIZED expose des projections queryables utiles aux applications, analyses et futurs modèles ML.
Exemples :
- nouveau decoder/Core processor : rejouer D1 -> D2 ;
- nouveau materializer générique : rejouer D2 -> D3 ;
- nouvelle version d'un projector : rejouer D3 -> D4.
- token/asset state ;
- metadata canonique d'asset ;
- pools/markets ;
- reserves/liquidity ;
- positions ;
- swaps/trades ;
- fees ;
- observations de prix ;
- OHLC/candles ;
- routes et legs ;
- faits trading-adjacent ;
- projections d'autres domaines futurs.
Il ne doit pas être nécessaire de refaire toute la chaîne lorsqu'un niveau inférieur inchangé contient déjà l'information requise.
## Faits métier génériques
Les replays sont des **jobs bornés**, pas des modes cachés des workers live.
Les projections de trading ne sont pas séparées automatiquement par protocole.
Les jobs de replay retenus sont `ksp-job-replay-core`, `ksp-job-replay-generic-materialization` et `ksp-job-replay-domain-projection`.
# Notifications de données persistées
## Contrat
`ksp-store-api` est le propriétaire du contrat canonique lorsqu'une notification signifie :
> une donnée durable de telle catégorie/référence est disponible.
Le même type de donnée utilise le même format de notification quelle que soit son origine :
Préférer lorsque possible :
```text
worker live
backfill job
import
replay
autre source
liquidity_pools
trades
positions
price_observations
ohlc
routes
route_legs
```
## Notification != source de vérité
Une notification est un **signal de réveil/accélération**, jamais la source de vérité du backlog.
Elle peut être :
- perdue ;
- dupliquée ;
- retardée ;
- reçue après un restart.
Le consumer doit toujours pouvoir reconstruire son travail depuis le Store.
Exemple conceptuel :
plutôt que :
```text
notification RawAvailable
|
v
wake-up core worker
|
v
store query:
"quels inputs D1 ne sont pas encore traités
par CoreProcessor version X ?"
meteora_trades
raydium_trades
orca_trades
pump_trades
```
Le Store, l'idempotence et les checkpoints durables constituent la vérité.
Les champs réellement protocol-specific peuvent être conservés dans une extension ou une projection dédiée uniquement lorsqu'un besoin de requête/invariant le justifie.
Cette règle évite d'exiger immédiatement un broker exactly-once.
## Metadata
## Ordre de publication
La direction reste :
Une donnée n'est annoncée disponible qu'après persistence réussie :
- projection canonique commune pour metadata d'assets/tokens alimentée par Metaplex Token Metadata et Token-2022 Metadata ;
- SPM reste distinct et sera redéveloppé plus tard avec le décodage généraliste.
## OHLC
Les candles sont des projections SPECIALIZED calculées à partir des trades/price observations persistés.
Une application marché lit les OHLC matérialisés ; elle ne reparcourt pas toutes les transactions pour reconstruire les candles à chaque affichage.
# Vertical slices Program
RAW et CORE sont développés horizontalement.
À partir de DECODE, la progression est verticale par groupe :
```text
wire
-> decode
-> generic materialization / D3
-> specialized projection / D4 si utile
-> execution preparation
-> execution policy
-> execution
-> Devnet scenarios / validation
```
Un groupe doit atteindre une cohérence verticale suffisante avant que le groupe suivant devienne prioritaire.
Les composants satellites nécessaires à un protocole appartiennent à son groupe : Pump fees avec Pump, Meteora vaults avec Meteora, etc.
# `ksp-store-api`
`ksp-store-api` est backend-agnostic et porte les contrats nécessaires aux consommateurs.
La première implementation `0.3.1` est volontairement **RAW-only** : elle ne crée pas prématurément les contrats physiques D2/D3/D4.
Les surfaces CORE/DECODE/SPECIALIZED sont ajoutées quand leurs couches sont réellement ouvertes.
# `ksp-store-lib`
`ksp-store-lib` fournit PostgreSQL comme backend officiel de référence derrière `ksp-store-api`.
Il possède :
- migrations ;
- SQL ;
- transactions ;
- mapping backend ;
- pagination ;
- claim/lease lorsque nécessaire ;
- notifications backend si retenues.
Il ne possède pas :
- transport réseau ;
- decoder Program ;
- materializer ;
- orchestration de worker/job.
# `ksp-materializer-api` et `ksp-materializer-lib`
Ils sont introduits seulement lorsque le premier groupe DECODE démontre le contrat réel.
`ksp-materializer-api` porte les contrats extensibles ; `ksp-materializer-lib` contient les implementations officielles communes.
Une projection très locale/spécifique peut rester dans son groupe si la création d'une implémentation commune séparée n'apporte pas de réutilisation réelle.
# Replay
Les frontières durables restent replayables indépendamment :
```text
RAW -> CORE
CORE -> DECODE
DECODE -> SPECIALIZED
```
Un replay d'une couche dérivée ne doit pas refaire arbitrairement les couches précédentes.
# Notifications persistées
Le Store reste source de vérité du backlog.
Les notifications ne sont qu'un wake-up : elles peuvent être perdues ou dupliquées.
Ordre :
```text
persist
@@ -616,118 +346,35 @@ commit
notify
```
et non :
```text
notify
persist
```
## Payload
La notification privilégie une référence durable compacte plutôt que la duplication de tout le payload :
- catégorie/type ;
- réseau ;
- identifiant/range/cursor durable ;
- autres informations minimales nécessaires au consumer.
Les noms de DTO exacts restent à définir.
## Mécanisme de diffusion
Le contrat est indépendant du mécanisme.
Candidats :
```text
channel in-process
PostgreSQL LISTEN/NOTIFY
IPC
broker externe
```
`ksp-store-lib` peut fournir PostgreSQL LISTEN/NOTIFY comme mécanisme de référence si cela répond au premier besoin.
Le mécanisme initial de référence et la reprise opérationnelle sont détaillés dans `009-ACQUISITION_WORKERS_AND_JOBS.md`.
Le consumer reconstruit toujours son backlog depuis le Store avec les versions de processor et les marqueurs d'idempotence.
# Acquisition live et backfill
`ksp-worker-raw-retriever` et `ksp-job-backfill` diffèrent par leur lifecycle/orchestration mais produisent le **même contrat D1** pour la même catégorie de donnée.
Live et backfill alimentent la même frontière RAW :
```text
live source ----------\
+--> D1 Raw
historical backfill --/
live worker ----\
+--> RAW persistence
backfill job ----/
```
Cela garantit que le processing downstream ne dépend pas de la manière dont la donnée a été acquise.
Ils ne dupliquent pas le contrat durable.
Le backfill n'est pas un mode historique du worker live.
# Stabilité
# Workers de processing
La stabilité cible est différente selon la couche :
Les frontières de responsabilité sont désormais :
```text
ksp-worker-raw-retriever
transport -> D1
ksp-worker-core-processor
D1 -> D2
ksp-worker-generic-materializer
D2 -> D3
ksp-worker-domain-projector
D3 -> D4
```
Chaque worker :
- peut utiliser les notifications pour réduire la latence ;
- doit pouvoir reconstruire son backlog depuis le Store ;
- écrit seulement le niveau durable dont il est propriétaire ;
- ne transforme pas silencieusement plusieurs frontières en une étape monolithique.
Le lifecycle, la concurrence, les cursors/checkpoints et la hot reconfiguration sont détaillés dans `009-ACQUISITION_WORKERS_AND_JOBS.md`.
# Projections de trading et autres domaines
Le trading reste une priorité produit mais ne détermine pas la structure D1/D2/D3.
D4 doit accueillir progressivement des faits canoniques de nombreux domaines :
- token ;
- metadata ;
- staking ;
- programmes ;
- trading/DEX ;
- autres domaines futurs.
Pour le trading, les materializers/projectors doivent normaliser les noms et structures propres aux protocoles vers des faits communs lorsque les invariants le permettent.
- RAW : fortement stable après mise en production ;
- CORE : fortement stable après validation de la normalisation Solana générique ;
- DECODE : extensible par nouveaux Program/versions ;
- SPECIALIZED : plus évolutif selon les besoins de query, trading et analytics.
# Questions laissées ouvertes
La première implémentation Store devra encore fixer :
- schémas SQL et noms exacts des tables ;
- clés/idempotence exactes ;
- représentation des hashes ;
- états de processing exacts ;
- temporalités obligatoires/optionnelles par table ;
- format exact des DTO D1/D2/D3 ;
- structure des repositories/transactions backend ;
- pagination/cursors ;
- conversion u64/slot/PostgreSQL ;
- stratégie des migrations initiales.
Les sujets opérationnels worker/job ont été précisés dans `009-ACQUISITION_WORKERS_AND_JOBS.md`.
Restent à définir à l'implémentation :
- schémas SQL et contraintes exactes ;
- format concret des DTO D1/D2/D3/D4 ;
- claim/lease PostgreSQL ;
- contexte des projectors stateful ;
- mécanisme IPC des managers de services autonomes.
- schémas SQL exacts RAW puis CORE ;
- représentation persistable exacte d'un decoded output ;
- contrat exact du journal D3 ;
- granularité des projectors SPECIALIZED ;
- politique de supersession/versioning des outputs ;
- fenêtres OHLC initiales ;
- mécanisme de contexte pour les projections stateful.