18 KiB
Graphe de dépendances KSP
Objet
Ce document constitue la sortie principale de 0.0.3-pre.003.
Il répond à la question : quels composants peuvent dépendre de quels autres composants, et où doivent se produire la composition, l'I/O et les conversions de modèles ?
Convention des graphes :
A -> B
signifie : A peut dépendre de B.
Le graphe exprime une direction architecturale. Une dépendance autorisée n'est pas obligatoire si l'implémentation peut rester plus faible.
Principes structurants
1. APIs sous les implémentations
Une crate ksp-<domain>-api est placée sous les implémentations de son domaine.
implementation -> domain-api
Une API publique ne dépend pas de son implémentation officielle.
2. Transformations séparées de l'I/O
Les bibliothèques de sémantique/transformation comme ksp-program-lib et ksp-materializer-lib ne deviennent pas propriétaires :
- du transport réseau ;
- du wallet ;
- du backend PostgreSQL ;
- du lifecycle d'un worker/job.
Les workers, jobs, scenarios et pipelines spécialisés composent ces capacités lorsqu'ils ont réellement besoin d'I/O.
3. Modèles de domaine distincts des DTO persistants
KSP ne crée pas actuellement un ksp-data-api global.
Chaque frontière possède les modèles nécessaires à sa responsabilité :
- transport : modèles homogènes de transport ;
- program : contrats de décodage/opération préparée ;
- materializer : entrées/sorties de matérialisation ;
- store : modèles persistants et références de données persistées.
La conversion entre ces modèles est explicite dans la couche qui relie les deux responsabilités, principalement les workers/jobs spécialisés.
4. Composition supérieure pour l'exécution
ksp-program-lib ne dépend pas de ksp-wallet-lib ou de ksp-onchain-transport-lib.
Le cycle signature/simulation/envoi/confirmation est composé au-dessus, par ksp-execution-lib.
5. Workers et jobs restent deux familles
ksp-worker-api et ksp-job-api n'ont pas de parent lifecycle commun.
Un orchestrateur futur peut consommer les deux familles séparément sans les fusionner.
Graphe fondations N1
ksp-core-lib
ksp-logging-lib -> ksp-core-lib
ksp-config-lib -> ksp-core-lib
ksp-config-lib -> ksp-logging-lib # lorsque du runtime logging est nécessaire
ksp-interface-lib -> ksp-core-lib
ksp-interface-lib -> ksp-logging-lib # lorsque du runtime logging est nécessaire
ksp-core-lib ne dépend d'aucun composant KSP supérieur.
ksp-interface-lib est propriétaire de la façade wire et peut dépendre des crates externes Solana/interface explicitement autorisées par RULES_DEPENDENCIES.md.
ksp-logging-lib est la façade logging/tracing KSP et peut dépendre de ksp-core-lib pour Error / Result. ksp-core-lib n'a pas de dépendance inverse vers le logging. Les composants comportant du runtime peuvent dépendre directement de ksp-logging-lib; cette permission n'oblige pas les crates purement déclaratives à le faire.
Graphe Logging
ksp-logging-lib
-> ksp-core-lib
-> tracing / tracing-appender / tracing-subscriber
runtime crate
-> ksp-logging-lib
ksp-logging-lib est la seule façade KSP propriétaire de l'initialisation/configuration tracing. Une crate runtime ne dépend normalement pas directement de tracing.
Exception technique possible : une application/framework, notamment Tauri, peut devoir intégrer un plugin tracing. Cette adaptation ne crée pas une seconde politique de logging parallèle.
ksp-core-lib et les crates *-api purement déclaratives n'ont pas de dépendance logging obligatoire.
Propriété des codecs wire
Pour les surfaces wire officielles KSP :
ksp-interface-lib
-> codecs wire nécessaires (borsh/wincode/...)
ksp-program-lib n'ajoute pas directement une autre génération de codec pour les mêmes surfaces.
Une extension Program externe peut temporairement posséder son wire lorsqu'il n'est pas encore officiellement intégré à ksp-interface-lib.
Le critère d'adoption d'une crate d'interface externe inclut la compatibilité de son graphe de dépendances avec le stack KSP actuel.
Graphe Program
ksp-program-api
-> ksp-core-lib
-> ksp-interface-lib
ksp-program-lib
-> ksp-program-api
-> ksp-interface-lib
-> ksp-core-lib
Frontière de ksp-program-api
ksp-program-api doit porter les contrats publics nécessaires à une implémentation externe de decoder/execution preparation.
Il est également le propriétaire candidat du contrat d'opération préparée produit par la sémantique programme et consommé par la couche d'exécution.
Noms exacts à définir en pre.004, par exemple conceptuellement :
PreparedProgramOperation
ProgramExecutionPlan
Le choix du nom/type final n'est pas décidé ici.
Interdictions Program
ksp-program-api -X-> ksp-wallet-lib
ksp-program-api -X-> ksp-onchain-transport-lib
ksp-program-api -X-> ksp-store-api
ksp-program-api -X-> ksp-materializer-api
ksp-program-lib -X-> ksp-wallet-lib
ksp-program-lib -X-> ksp-onchain-transport-lib
ksp-program-lib -X-> ksp-store-api
ksp-program-lib -X-> ksp-store-lib
ksp-program-lib -X-> ksp-materializer-lib
ksp-program-lib -X-> ksp-execution-lib
Le decoder/execution preparation de programme reste donc testable sans réseau, wallet ou base de données.
Implémentations Program externes
Une implémentation externe peut dépendre de :
ksp-program-<name>-lib
-> ksp-program-api
-> ksp-core-lib
-> ksp-interface-lib # lorsque le wire officiel nécessaire existe
Elle ne dépend pas obligatoirement de ksp-program-lib.
Le runtime peut composer registry officiel + registry/implémentations externes derrière ksp-program-api.
Graphe Execution / Policy
ksp-execution-policy-api
-> ksp-program-api
-> ksp-core-lib
ksp-execution-lib
-> ksp-program-api
-> ksp-execution-policy-api
-> ksp-wallet-lib
-> ksp-onchain-transport-lib
-> ksp-logging-lib
-> ksp-core-lib
ksp-execution-lib ne dépend pas de ksp-program-lib et reçoit fondamentalement une opération déjà préparée conforme à ksp-program-api.
Policy obligatoire et multi-checkpoints
Toute exécution réelle reçoit explicitement une implémentation de ksp-execution-policy-api.
La policy peut être consultée à plusieurs checkpoints (préflight, après simulation, avant submission ou autres points réellement justifiés). Le contrat exact ne doit pas imposer plus de callbacks que nécessaire.
La policy peut autoriser/refuser/ajouter des requirements, mais n'appelle ni wallet, ni transport, ni UI.
Composition supérieure
Le caller fournit notamment :
- réseau/provider/transport sélectionné ;
- wallet/signers sélectionnés ;
- options d'exécution.
ksp-execution-lib vérifie/compose ces éléments avec les contraintes techniques de PreparedProgramExecution et les contraintes supplémentaires de policy.
Simulation / signature / submission / confirmation
- primitive simulation/submission/status ->
ksp-onchain-transport-lib; - orchestration de ces étapes ->
ksp-execution-lib; - primitive signature ->
ksp-wallet-lib; - résolution/coordination des signers ->
ksp-execution-lib.
Retry
Retry technique d'un appel réseau identique -> transport.
Retry qui change le lifecycle (nouveau blockhash, reconstruction, resimulation, resignature, resubmission) -> execution, éventuellement limité par policy.
Approbation externe
Une policy peut produire un requirement d'approbation externe. ksp-execution-lib peut retourner un état suspendu/reprenable ; l'UI obtient l'approbation sans être appelée directement par la policy ou l'execution lib.
Store
ksp-execution-policy-api -X-> ksp-store-api
ksp-execution-lib -X-> ksp-store-api
ksp-execution-lib -X-> ksp-store-lib
La persistence d'un ExecutionOutcome est une composition supérieure.
Graphe Wallet
ksp-wallet-lib
-> ksp-core-lib
ksp-wallet-lib peut consommer config/logging si nécessaire à son implémentation, sans que ces dépendances deviennent partie obligatoire du contrat wallet.
Interdictions :
ksp-wallet-lib -X-> ksp-program-lib
ksp-wallet-lib -X-> ksp-execution-lib
ksp-wallet-lib -X-> ksp-store-lib
Le wallet fournit les capacités de clés/signature ; il n'orchestre pas une opération Solana.
Graphe Transport
On-chain
ksp-onchain-transport-lib
-> ksp-core-lib
Il peut consommer config/logging lorsque nécessaire.
Il peut posséder plusieurs familles internes :
HTTP RPC
WS RPC
Helius advanced
Yellowstone
...
sans créer ksp-onchain-transport-api.
Modèles homogènes
Chaque famille provider convertit ses réponses propriétaires vers des modèles KSP homogènes à l'intérieur de la frontière transport.
Exemple conceptuel :
Solana RPC ------\
Helius -----------+--> transport raw model
Yellowstone ------/
Ces modèles :
- sont indépendants du store ;
- conservent le raw et la provenance nécessaire ;
- sont faciles à convertir vers les modèles persistants.
Interdiction ferme :
ksp-onchain-transport-lib -X-> ksp-store-api
ksp-onchain-transport-lib -X-> ksp-store-lib
Off-chain
ksp-offchain-transport-lib
-> ksp-core-lib
Config/logging sont autorisés selon le besoin.
La crate reste volontairement hétérogène. Aucun ksp-offchain-transport-api global n'est introduit.
Graphe Materialization
ksp-materializer-api
-> ksp-core-lib
-> ksp-program-api
ksp-materializer-lib
-> ksp-materializer-api
-> ksp-program-api
-> ksp-core-lib
ksp-interface-lib peut être consommée par ksp-materializer-lib lorsqu'une matérialisation a réellement besoin d'un contrat wire déjà possédé par KSP, mais ne doit pas devenir une dépendance obligatoire de toute matérialisation.
Décision importante
Ni ksp-materializer-api ni ksp-materializer-lib ne dépendent du store.
ksp-materializer-api -X-> ksp-store-api
ksp-materializer-lib -X-> ksp-store-api
ksp-materializer-lib -X-> ksp-store-lib
Une matérialisation transforme des données ; le worker/job/pipeline spécialisé persiste le résultat.
Cette séparation permet également de tester un materializer externe sans PostgreSQL.
Graphe Store
ksp-store-api
-> ksp-core-lib
ksp-store-lib
-> ksp-store-api
-> ksp-core-lib
ksp-store-lib peut dépendre de config/logging et contient PostgreSQL comme implémentation de référence.
Indépendance du store
Le store ne dépend pas des implémentations Program/Materializer/Transport :
ksp-store-api -X-> ksp-program-api
ksp-store-api -X-> ksp-materializer-api
ksp-store-api -X-> ksp-onchain-transport-lib
ksp-store-lib -X-> ksp-program-lib
ksp-store-lib -X-> ksp-materializer-lib
ksp-store-lib -X-> ksp-onchain-transport-lib
ksp-store-api définit les DTO/contrats persistants nécessaires aux niveaux durables sans imposer les modèles runtime des processors.
Notifications de données persistées
ksp-store-api est retenu comme propriétaire du contrat canonique de notification lorsqu'il signifie :
une donnée persistée de telle catégorie est disponible.
Le même contrat est utilisé quelle que soit l'origine :
live worker ----\
backfill job ----+--> persisted data notification
import ----------/
Le mécanisme de diffusion reste hors du contrat :
channel
LISTEN/NOTIFY
IPC
broker
...
Le mode de transport concret sera détaillé en pre.005.
Graphe lifecycle Worker
ksp-worker-api
-> ksp-core-lib
ksp-worker-control-lib
-> ksp-worker-api
-> ksp-core-lib
ksp-worker-control-lib ne dépend pas des workers concrets. Il fournit une gouvernance réutilisable au-dessus de l'API.
Les managers/apps/orchestrateurs composent les implémentations concrètes avec cette bibliothèque.
Interdictions :
ksp-worker-api -X-> ksp-job-api
ksp-worker-control-lib -X-> ksp-job-api
Le contrôle des jobs ne fuit pas dans la gouvernance workers.
Graphe lifecycle Job
ksp-job-api
-> ksp-core-lib
Aucune ksp-job-control-lib n'est prévue actuellement.
Interdictions :
ksp-job-api -X-> ksp-worker-api
ksp-job-api -X-> ksp-worker-control-lib
Un futur orchestrateur peut utiliser workers et jobs séparément sans créer de superclass lifecycle commune.
Graphe des composants concrets d'acquisition/processing
Les dépendances ci-dessous décrivent la composition attendue. Les détails de processus/IPC seront approfondis plus tard.
ksp-worker-raw-retriever
ksp-worker-raw-retriever
-> ksp-worker-api
-> ksp-config-lib
-> ksp-onchain-transport-lib
-> ksp-store-api
-> ksp-store-lib
-> ksp-logging-lib
Responsabilité de conversion :
transport raw model
|
v
store raw persistence model
Cette conversion appartient au worker d'acquisition, pas au transport ni au store.
ksp-job-backfill
ksp-job-backfill
-> ksp-job-api
-> ksp-config-lib
-> ksp-onchain-transport-lib
-> ksp-store-api
-> ksp-store-lib
-> ksp-logging-lib
Il utilise la même famille de DTO raw persistants et la même notification de données persistées que W1.
ksp-worker-core-processor
ksp-worker-core-processor
-> ksp-worker-api
-> ksp-program-api
-> ksp-program-lib
-> ksp-store-api
-> ksp-store-lib
-> ksp-config-lib
-> ksp-logging-lib
Il effectue la conversion explicite :
store raw DTO
|
v
program decode input
|
v
program canonical/decode output
|
v
store Core DTO
ksp-program-lib ne connaît donc pas le store.
ksp-worker-generic-materializer
ksp-worker-generic-materializer
-> ksp-worker-api
-> ksp-materializer-api
-> ksp-materializer-lib
-> ksp-store-api
-> ksp-store-lib
-> ksp-config-lib
-> ksp-logging-lib
La frontière exacte des entrées/sorties génériques sera détaillée en pre.005.
ksp-worker-domain-projector
ksp-worker-domain-projector
-> ksp-worker-api
-> ksp-materializer-api
-> ksp-materializer-lib
-> ksp-store-api
-> ksp-store-lib
-> ksp-config-lib
-> ksp-logging-lib
Son nom reste provisoire.
Il est propriétaire de la composition entre résultats de matérialisation spécialisée et projections persistantes par domaine ; ksp-materializer-lib reste indépendant du backend.
Scenarios et applications demo
Une crate scénario peut composer les capacités nécessaires à son domaine :
ksp-scenario-<domain>-lib
-> ksp-program-api
-> ksp-program-lib
-> ksp-execution-policy-api
-> ksp-execution-lib
-> ksp-wallet-lib
-> ksp-onchain-transport-lib
-> ksp-config-lib
Toutes ces dépendances ne sont pas obligatoires pour chaque scénario.
La crate scénario peut implémenter une policy Devnet adaptée à son besoin.
L'application correspondante reste une interface :
ksp-app-scenario-<domain>-devnet-desk-demo
-> ksp-scenario-<domain>-lib
Elle peut dépendre de bibliothèques KSP d'interface/configuration strictement nécessaires à son UI, mais ne réimplémente ni scénario ni policy métier.
Orchestrateur futur
Le futur orchestrateur est au-dessus des contrôles spécialisés.
Conceptuellement :
orchestrator
-> ksp-worker-control-lib
-> ksp-job-api # séparément, si coordination de jobs nécessaire
-> autres contrôles spécialisés au besoin
Cette dépendance simultanée ne crée pas d'API lifecycle commune.
L'orchestrateur coordonne ; il ne fusionne pas les modèles worker/job.
Dépendances explicitement non retenues
Les composants suivants ne sont pas introduits dans le graphe actuel :
ksp-api-lib
ksp-onchain-transport-api
ksp-offchain-transport-api
ksp-wallet-api
ksp-scenario-api
ksp-job-control-lib
ksp-pipeline-lib
ksp-data-api
Ils pourront être réévalués uniquement si un besoin concret démontre que la frontière actuelle ne suffit plus.
Contrôle des cycles
Le graphe impose notamment :
core
<- interface
<- program-api
<- materializer-api
store-api
<- store-lib
worker-api
<- worker-control
job-api
<- concrete jobs
et interdit toute boucle inverse depuis les couches basses vers leurs consommateurs.
Les conversions entre Program/Materializer/Store ne sont pas résolues par des dépendances croisées mais par des composants de composition explicites.
Questions reportées
pre.004 doit détailler :
- noms/types exacts des entrées/sorties de
ksp-program-api; - forme exacte de l'opération préparée ;
- appel/injection entre program implementation et
ksp-execution-lib; - contrat exact de
ksp-execution-policy-api; - frontière entre préparation, policy, simulation, signature, envoi et confirmation.
pre.005 doit détailler :
- DTO raw/Core/materialization/projection du store ;
- entrées/sorties
ksp-materializer-api; - conversion Core runtime <-> store Core ;
- notifications et transport de notifications ;
- niveaux durables/replay/idempotence/provenance ;
- rôle précis des deux workers de matérialisation.
pre.006 doit détailler :
- managers spécialisés ;
- processus/IPC éventuels ;
- norme des scenarios ;
- apps demo ;
- orchestrateur futur et pipelines spécialisés.