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,202 +1,201 @@
<!-- file: docs/architecture/002-LAYERS_AND_DEPENDENCIES.md -->
<!-- version: 5 -->
<!-- version: 6 -->
# Couches et dépendances KSP
## Rôle des niveaux
## Rôle des niveaux architecturaux
Les niveaux N1 à N4 servent à raisonner sur les responsabilités, la stabilité et le sens des dépendances. Ils ne constituent pas une chaîne d'appels obligatoire.
Les niveaux architecturaux N1N4 décrivent les familles de composants du projet. Ils ne doivent pas être confondus avec les niveaux durables D1D4.
Les niveaux durables de données utilisent une nomenclature distincte **D1 à D4** afin de ne jamais être confondus avec les couches architecturales N1 à N4 : D1 Raw, D2 Core canonique, D3 journal de matérialisation générique et D4 projections spécialisées.
### N1 — Fondations communes
Une couche supérieure peut dépendre directement d'une bibliothèque KSP plus basse lorsque cette bibliothèque est exactement la propriétaire de la capacité recherchée.
- `ksp-core-lib` ;
- `ksp-logging-lib` ;
- `ksp-config-lib` ;
- premières règles/outils transversaux.
## N1Fondations
N1 contient les contrats et services transversaux qui doivent rester bas dans le graphe de dépendances.
Positionnement actuellement retenu :
- `ksp-core-lib` — primitives et contrats fondamentaux réellement transversaux, type d'erreur commun KSP et responsabilité autrefois séparée des identifiants de programmes ;
- `ksp-interface-lib` — façade KSP des interfaces/wire on-chain nécessaires aux autres bibliothèques ;
- `ksp-config-lib` — contrats, chargement/résolution et manipulation autorisée de la configuration et des profils ;
- `ksp-logging-lib` — façade commune de logging/tracing, propriétaire de l'initialisation et des dépendances directes `tracing`, `tracing-appender` et `tracing-subscriber`.
`ksp-logging-lib` peut dépendre de `ksp-core-lib` pour le contrat commun `Error` / `Result`. La relation inverse n'est pas requise : `ksp-core-lib` reste sans dépendance logging tant qu'aucun besoin réel ne la justifie.
Les crates KSP contenant du comportement/runtime peuvent dépendre directement de `ksp-logging-lib` afin de produire des logs structurés aux niveaux `error`, `warn`, `info`, `debug` et `trace`. Les crates `*-api` purement déclaratives n'ajoutent pas cette dépendance sans comportement réel à logger.
Une bibliothèque N1 ne doit pas dépendre d'une fonctionnalité métier située dans une couche supérieure.
## N2 — Capacités Solana
N2 regroupe les capacités réutilisables opérant sur Solana au-dessus des fondations.
Le nom `ksp-program-lib` est retenu pour la bibliothèque propriétaire du traitement des programmes : décodage et préparation technique d'opérations via `ProgramExecutionPreparer`. Elle doit s'appuyer sur `ksp-interface-lib` plutôt que faire porter les contrats wire aux applications.
Les autres responsabilités N2 candidates comprennent notamment :
### N2Capacités Solana réutilisables
- `ksp-onchain-transport-lib` ;
- `ksp-offchain-transport-lib` lorsqu'un premier besoin réel justifiera son implémentation ;
- `ksp-wallet-lib`.
- `ksp-offchain-transport-lib` ;
- `ksp-wallet-lib` ;
- `ksp-interface-lib` ;
- `ksp-program-api` puis implementations Program ;
- `ksp-execution-policy-api` et orchestration d'exécution lorsqu'un vertical slice réel le justifie.
Le transport off-chain est général : il ne se limite pas aux metadata et pourra servir à des ressources telles que metadata externes, prix de référence, services de routage ou autres données hors blockchain.
### N3 — Données, jobs, workers et processing
## N3 — Données et orchestration réutilisable
- `ksp-store-api` / `ksp-store-lib` ;
- `ksp-materializer-api` / implementations lorsque DECODE s'ouvre ;
- `ksp-job-api` et jobs ;
- `ksp-worker-api` et workers ;
- processors/pipelines spécialisés réellement réutilisés.
N3 doit accueillir les responsabilités qui interprètent, persistent ou orchestrent des capacités inférieures, notamment :
### N4 — Exécutables
- matérialisation ;
- stockage ;
- replay/reconstruction ;
- pipelines ;
- scénarios réutilisables ;
- contrôle/orchestration de workers lorsqu'il sera introduit.
- applications desk ;
- services workers ;
- outils/jobs exécutables ;
- demos/scenarios ;
- future orchestration globale.
### W1
## Chaîne durable indépendante des niveaux N1N4
W1 est un worker d'acquisition live/quasi-live uniquement.
Il consomme au minimum les contrats de configuration, transport on-chain et stockage nécessaires pour :
1. écouter les sources configurées ;
2. rapatrier les données ;
3. les persister sous forme raw ;
4. notifier qu'une nouvelle information raw est disponible.
W1 :
- ne décode pas ;
- ne matérialise pas ;
- ne réalise pas de replay ;
- ne décide pas de l'utilisation métier des données collectées ;
- doit pouvoir faire évoluer à chaud ce qu'il écoute, rapatrie ou stocke selon les mécanismes de configuration/commande qui seront définis.
Les notifications W1 servent de wake-up. Les workers/jobs downstream reconstruisent leur backlog depuis le Store et appliquent les pipelines spécialisés correspondant aux frontières D1 -> D2 -> D3 -> D4.
### Workers de processing futurs
Le processing continu n'est plus modélisé comme un unique W2. Il sépare `ksp-worker-core-processor`, `ksp-worker-generic-materializer` et `ksp-worker-domain-projector` afin de respecter les frontières durables D1 Raw -> D2 Core -> D3 journal de matérialisation générique -> D4 projections de domaine. Le lifecycle, backlog, claim/lease et replay sont détaillés dans `009-ACQUISITION_WORKERS_AND_JOBS.md`.
## N4 — Exécutables
N4 contient les applications, demos et workers.
### Dépendances directes autorisées
N4 n'est pas obligé de traverser N3 puis N2 pour atteindre N1.
Exemples valides :
La chaîne de données canonique est :
```text
ksp-app-config-desk
└── ksp-config-lib
ksp-app-store-desk
├── ksp-store-lib
└── ksp-config-lib
D1 RAW
-> D2 CORE
-> D3 DECODE
-> D4 SPECIALIZED
```
Une application de configuration n'a aucune raison de dépendre de couches Solana qui ne participent pas à sa fonction.
Aliases fonctionnels :
Une application de store peut utiliser `ksp-config-lib` pour sélectionner/résoudre un profil et `ksp-store-lib` pour valider, initialiser ou reconstruire le stockage. Elle ne doit pas réimplémenter ces opérations ni appeler directement le backend propriétaire.
```text
RAW -> CORE -> DECODE -> SPECIALIZED
```
## Applications et demos
RAW et CORE sont indépendants du décodage Program.
Une application ou demo :
CORE est une normalisation générique de Solana : structure des blocs, transactions, messages, comptes, instructions/CPI brutes, logs/meta et relations fondamentales.
- recueille et présente les données ;
- effectue les conversions/validations strictement liées à son interface ;
- sélectionne les options, profils et scénarios autorisés ;
- appelle les bibliothèques KSP propriétaires ;
- affiche ou exporte les résultats.
Le premier decoder Program intervient seulement à `CORE -> DECODE`.
Elle ne doit pas réécrire :
## Progression par couche
- le décodage ;
- la logique protocolaire ;
- les PDA et layouts ;
- la construction d'instructions ;
- la matérialisation ;
- les opérations de stockage ;
- les scénarios réutilisables ;
- les autres opérations appartenant à une bibliothèque inférieure.
### RAW et CORE
Lorsqu'une bibliothèque de scénarios possède déjà un workflow de démonstration, l'application demo doit l'appeler.
Ces deux couches sont construites horizontalement.
Les demos/scénarios doivent rester séparés par responsabilité fonctionnelle cohérente. Un regroupement n'est autorisé que lorsque plusieurs interfaces représentent réellement le même domaine fonctionnel.
À la fin de chaque couche, KSP ajoute les composants d'exploitation nécessaires : persistence, replay/backfill, worker/service et application de contrôle lorsque utiles.
Exemples actuellement retenus :
### DECODE et SPECIALIZED
- Memo : demo/scénarios séparés ;
- SPL Token classique : demo/scénarios séparés ;
- Associated Token Account : demo/scénarios séparés ;
- Token-2022 : demo/scénarios séparés ;
- metadata d'assets/tokens : Metaplex Token Metadata et Token-2022 Metadata peuvent partager une même famille de demo/scénarios ;
- Solana Program Metadata (SPM) reste séparé car il n'appartient pas à la même catégorie fonctionnelle.
À partir du décodage, KSP progresse verticalement par groupe fonctionnel :
## Workers
```text
wire
-> decode
-> materialize
-> specialized projection si utile
-> execution preparation
-> policy
-> execute
-> scenarios
```
Les workers sont différents des interfaces utilisateur. Ils peuvent contenir l'orchestration runtime strictement nécessaire à leur responsabilité.
Cela évite de développer tous les decoders avant les matérialisations et toutes les executions.
Un worker doit néanmoins consommer les bibliothèques KSP propriétaires des contrats Solana et ne doit pas dépendre directement de crates Solana/protocoles externes.
## Séparation maximale des dépendances
Les premiers managers de workers sont spécialisés et séparés. Une application globale est un produit futur, tandis qu'un orchestrateur commun reste une abstraction à réévaluer seulement lorsqu'un besoin opérationnel concret le justifie.
Chaque composant possède son contrat et reçoit explicitement les données nécessaires.
Exemples structurants :
```text
ksp-onchain-transport-lib -X-> ksp-config-lib
ksp-onchain-transport-lib -X-> ksp-store-api
ksp-wallet-lib -X-> ksp-onchain-transport-lib
ksp-wallet-lib -X-> execution policy
ksp-interface-lib -X-> ksp-program-api
ksp-execution-lib -X-> ksp-program-lib
```
La composition supérieure relie les composants.
## Configuration
`ksp-config-lib` est l'unique propriétaire des documents Config, `.env` et variables KSP/KSPB.
Un composant ne dépend pas de Config pour être utilisable. Il expose des settings publics.
Config peut fournir un document standard et un adapter vers ces settings lorsque cela devient utile :
```text
ksp-config-lib -> public settings du composant
```
sans dépendance inverse.
## Logging
`ksp-logging-lib` reste l'unique façade KSP de tracing runtime.
Les crates comportant du comportement runtime peuvent en dépendre. Les crates `*-api` purement déclaratives n'ajoutent cette dépendance que si elles ont réellement un comportement à logger.
## Applications
Les applications Tauri restent minces :
- DTOs applicatifs ;
- composition de services KSP ;
- lifecycle fenêtre/UI ;
- instrumentation frontend ;
- aucun déplacement de logique de transport, Wallet, Config, Program, Store ou Materializer dans Tauri.
Des applications spécialisées sont ajoutées au fur et à mesure pour valider les couches : Config Desk, Wallet Desk, Price Desk, backfill/RAW tooling, CORE tooling puis Market Desk.
## Workers et jobs
Un worker est un service continu/autonome ; un job est borné/terminable.
Ils utilisent des APIs lifecycle distinctes et ne s'appellent pas entre eux pour transférer les payloads du data plane.
Le Store reste le point durable de synchronisation entre couches de processing.
## Firewall des dépendances externes
Les exécutables KSP dépendent des bibliothèques KSP pour les capacités Solana.
Les exécutables et couches supérieures n'importent pas directement les crates Solana/protocoles métier lorsqu'une façade KSP existe ou est prévue.
```text
application / demo / worker
bibliothèques KSP
primitives externes explicitement autorisées
Solana
```
Exceptions bas niveau explicitement autorisées restent limitées aux primitives stables décidées par les règles KSP.
Une dépendance externe Solana ou protocolaire doit être possédée par la bibliothèque KSP la plus basse et la plus cohérente avec sa responsabilité.
## Sens des dépendances
Le principe recherché est :
```text
N4 ───────► N3 / N2 / N1
N3 ───────► N2 / N1
N2 ───────► N1
N1 ───────► fondations externes explicitement autorisées
```
Il n'est pas permis d'introduire une dépendance vers une couche supérieure pour résoudre localement un problème. Si cela semble nécessaire, le classement des responsabilités doit être réexaminé.
`ksp-interface-lib` concentre les interfaces/wires officielles ou compatibles afin d'éviter les doublons de générations et les dépendances protocolaires dans les couches supérieures.
## Principe contract-first
Les contrats minimaux entre couches doivent être définis suffisamment tôt pour que les composants futurs puissent se construire contre une frontière KSP stable, même lorsque l'implémentation complète arrive dans une version ultérieure.
Une crate `*-api` est créée uniquement lorsque l'extension externe/backend/lifecycle exige un contrat séparé.
Ce principe s'applique notamment aux futurs :
Cas décidés :
- decoders ;
- `ProgramExecutionPreparer` / constructeurs d'opérations ;
- materializers ;
- store/repositories ;
- transports ;
- scénarios ;
- notifications et contrôle des workers ;
- orchestrateur.
```text
ksp-program-api
ksp-materializer-api
ksp-store-api
ksp-worker-api
ksp-job-api
ksp-execution-policy-api
```
Il ne signifie pas qu'il faut implémenter prématurément toutes les fonctionnalités. Les interfaces/traits peuvent évoluer légèrement lorsque l'expérience révèle un besoin réel, mais une dépendance entre couches ne doit pas être remplacée par un couplage ad hoc sous prétexte que le contrat final n'existe pas encore.
`ksp-interface-lib`, Wallet et transports conservent pour l'instant leurs APIs publiques dans leur bibliothèque d'implémentation.
## Groupes Program prioritaires
Après RAW/CORE :
```text
Solana Core Programs
-> SPL token/trading
-> token metadata
-> Anchor
-> Meteora
-> Raydium
-> Pump
-> Orca
-> Market Desk V1
-> Jupiter/OKX routing
-> Market Desk V2
-> trading-adjacent
-> general decoding
```
Un satellite nécessaire à un protocole reste dans son groupe : Pump fee avec Pump, Meteora vault avec Meteora, etc.
## Questions encore ouvertes
- représentation interne exacte du type d'erreur commun KSP, à traiter dès `0.1.1-pre.001` ;
- types publics précis de `ksp-program-api` et format ouvert/persistable des résultats décodés ;
- méthode de conformité wire contre les projets externes ;
- forme exacte des settings publics Transport ;
- nécessité future d'un pool automatique de sessions WebSocket ;
- split éventuel d'une API Interface séparée uniquement si un vrai besoin apparaît ;
- contrats Rust exacts de Program/Materializer/Store ;
- mécanisme IPC du premier manager de worker autonome ;
- besoins de contexte des futurs `DomainProjector` stateful ;
- nécessité réelle d'un orchestrateur commun lorsque plusieurs services/managers existeront.
- granularité future des workers DECODE/SPECIALIZED par groupe.