Files
khadhroony-solana-project/docs/rules/RULES_DEPENDENCIES.md
2026-09-08 08:57:07 +02:00

157 lines
21 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/rules/RULES_DEPENDENCIES.md -->
<!-- version: 19 -->
# Règles des dépendances KSP
## Portée
Les règles `DEP-*` définissent quelles dépendances externes et internes peuvent traverser les frontières KSP et quelles couches en sont propriétaires.
Elles complètent les règles Rust générales et le graphe de `docs/architecture/005-DEPENDENCY_GRAPH.md`.
## Firewall des exécutables
- **DEP-EXEC-001** — Les applications, demos, workers et jobs KSP ne dépendent directement d'aucune crate externe relative à Solana ou à un protocole Solana. Ils consomment exclusivement les composants KSP propriétaires de ces contrats.
- **DEP-EXEC-002** — Un exécutable peut dépendre directement de bibliothèques générales non-Solana nécessaires à son interface ou à son runtime, à condition qu'elles ne portent pas une opération métier/protocolaire appartenant à KSP.
- **DEP-EXEC-003** — Si un exécutable a besoin d'un type, d'une fonction ou d'un contrat Solana, le composant KSP propriétaire doit l'exposer ou fournir le wrapper/contrat approprié.
## Direction des dépendances internes
- **DEP-KSP-001** — Une crate `ksp-<domain>-api` ne dépend jamais de l'implémentation officielle `ksp-<domain>-lib`.
- **DEP-KSP-002** — Une bibliothèque basse de transformation/sémantique ne dépend pas d'un worker, job, application ou orchestrateur qui la consomme.
- **DEP-KSP-003** — Les conversions entre modèles de transport, processing et persistence sont réalisées par les composants de composition appropriés plutôt que par des dépendances croisées entre domaines.
- **DEP-KSP-004** — Aucun `ksp-data-api` global n'est introduit uniquement pour éviter des conversions explicites entre modèles appartenant à des responsabilités différentes.
- **DEP-KSP-005** — Une dépendance autorisée par le graphe n'est ajoutée au manifeste que lorsqu'un usage réel la justifie.
## Déclaration Cargo et centralisation workspace
- **DEP-CARGO-001** — Toute dépendance externe utilisée par une crate membre du workspace est déclarée une seule fois dans le `Cargo.toml` racine sous `[workspace.dependencies]`.
- **DEP-CARGO-002** — Une crate membre consomme une dépendance centralisée avec `<dependency>.workspace = true` et ne redéclare pas localement sa version.
- **DEP-CARGO-003** — Les options communes de résolution telles que `default-features` et la contrainte de version sont définies au niveau `[workspace.dependencies]`. Les features d'usage ne sont pas activées dans cette table commune : chaque crate membre active localement uniquement les features nécessaires à son propre code avec `<dependency> = { workspace = true, features = [...] }`.
- **DEP-CARGO-004** — Lorsqu'une génération majeure/mineure compatible est retenue, KSP exprime explicitement l'intention sous forme caret `^M.m` (par exemple `^4.3`) plutôt qu'avec une écriture patch telle que `4.3.0`. Même si Cargo interprète aussi par défaut cette dernière comme une contrainte compatible caret, KSP normalise la syntaxe pour rendre l'intention manifeste. Un pin exact `=M.m.p` ou un bornage différent requiert une justification explicite.
- **DEP-CARGO-005** — Le `Cargo.lock` résout la version patch concrète à l'intérieur de la contrainte du workspace ; cette résolution ne remplace pas la politique de version déclarée dans le manifeste racine.
- **DEP-CARGO-006** — Lorsqu'une feature externe n'est nécessaire qu'aux tests/benchmarks/examples d'une crate, son activation appartient à la section de dépendances de développement correspondante plutôt qu'aux dépendances de production. L'unification des features effectuée par Cargo lors d'un build ne transfère pas cet ownership vers le `Cargo.toml` racine.
- **DEP-CARGO-007** — Les canaries qui inspectent une politique générale du workspace ou plusieurs manifests membres appartiennent à une surface de gouvernance/fondation (actuellement les tests de `ksp-core-lib` tant qu'aucun outil d'audit dédié n'existe). Une crate métier spécialisée conserve uniquement les tests de frontière propres à son domaine et ne devient pas propriétaire d'une règle globale du workspace.
## Codecs wire et cohérence des versions
- **DEP-WIRE-001** — Pour les surfaces wire officielles KSP, les dépendances directes vers `borsh`, `wincode` ou codecs équivalents appartiennent normalement à `ksp-interface-lib`.
- **DEP-WIRE-002** — `ksp-program-lib` ne redécode pas directement une surface possédée par `ksp-interface-lib` avec sa propre dépendance codec.
- **DEP-WIRE-003** — Une crate d'interface externe est retenue seulement si sa source/API et son graphe de dépendances sont suffisamment compatibles avec le stack KSP actuel.
- **DEP-WIRE-004** — Une crate protocolaire externe qui impose une génération ancienne/incompatible d'une dépendance fondamentale peut être remplacée par une réimplémentation KSP bornée aux contrats wire nécessaires.
- **DEP-WIRE-005** — Les doublons de générations de dépendances fondamentales sont audités et les doublons évitables doivent être éliminés ; un doublon inévitable requiert une justification.
- **DEP-WIRE-006** — KSP cherche des versions récentes compatibles et ne fixe pas arbitrairement une ancienne version uniquement pour conserver une crate protocolaire remplaçable.
- **DEP-WIRE-007** — Une extension Program externe peut posséder temporairement son propre wire lorsqu'aucune interface officielle KSP correspondante n'existe encore.
## Logging
- **DEP-LOG-001** — `ksp-logging-lib` est le propriétaire KSP direct de `tracing`, `tracing-appender`, `tracing-subscriber` et de l'initialisation/configuration runtime logging.
- **DEP-LOG-002** — `ksp-logging-lib` peut dépendre de `ksp-core-lib` pour le contrat commun `Error` / `Result`.
- **DEP-LOG-003** — `ksp-core-lib` ne dépend pas de `ksp-logging-lib` dans l'architecture actuelle.
- **DEP-LOG-004** — Les crates KSP comportant du runtime dépendent de `ksp-logging-lib` lorsqu'elles instrumentent leur comportement et n'utilisent pas directement `tracing`, `tracing-subscriber` ou `tracing-appender` pour émettre leurs propres événements/spans.
- **DEP-LOG-005** — Les crates `*-api` purement déclaratives n'ajoutent pas une dépendance logging sans comportement réel à instrumenter.
- **DEP-LOG-006** — Le subscriber KSP rend silencieux par défaut les targets externes ; une information tierce utile est réémise explicitement par la crate KSP propriétaire sous son propre target au lieu de renommer/réécrire l'événement tiers.
- **DEP-LOG-007** — Une application/framework peut exceptionnellement intégrer directement un plugin/dépendance tracing imposé par son framework, notamment Tauri, sans créer une seconde politique de logging parallèle à `ksp-logging-lib`; les événements KSP restent émis via la façade KSP.
- **DEP-LOG-008** — `ksp-logging-lib` possède ses settings runtime et son hot reload ; `ksp-config-lib` peut plus tard construire ces settings et demander une reconfiguration sans créer de dépendance inverse Logging -> Config.
- **DEP-LOG-009** — Tout bridge `tracing` public mais caché de la documentation rendu techniquement nécessaire par lexpansion des macros de `ksp-logging-lib` est un détail dimplémentation réservé à ces macros ; une crate consommatrice ne lutilise jamais directement et reste limitée à la façade KSP documentée.
- **DEP-LOG-010** — Toute crate KSP comportementale qui émet des événements/spans via `ksp-logging-lib` possède un target principal explicite `pub(crate) const TRACING_TARGET: &str` dans `src/constants.rs`, égal au nom Cargo de la crate. Les appels utilisent ce symbole (ou un target spécialisé possédé par le même `constants.rs`) plutôt quun littéral dispersé.
- **DEP-LOG-011** — `env!("CARGO_PKG_NAME")` ne sert pas de target de tracing/logging KSP : le target appartient au contrat dobservabilité et doit rester explicite dans le code. Les metadata Cargo restent autorisées lorsquelles sont réellement la donnée recherchée, par exemple pour un User-Agent ou une information de build.
- **DEP-LOG-012** — Lorsquune seule crate/target KSP nécessite temporairement une verbosité `debug` ou `trace`, le profil Logging général nest pas relevé par défaut : un `target_filter` autorise cette verbosité uniquement pour le target concerné et un sink dédié la route avec son propre `OutputFilter`. Les sinks généraux peuvent ainsi rester à `info`/`warn`. Un relèvement global du profil nest retenu que lorsquun diagnostic transversal le justifie explicitement.
## Program / Execution
- **DEP-PROGRAM-001** — `ksp-program-api` peut dépendre de `ksp-core-lib` et `ksp-interface-lib`.
- **DEP-PROGRAM-002** — `ksp-program-lib` dépend de `ksp-program-api` et peut dépendre de `ksp-interface-lib`/`ksp-core-lib`.
- **DEP-PROGRAM-003** — `ksp-program-api` et `ksp-program-lib` ne dépendent pas du wallet, du transport, du store ou des materializers.
- **DEP-PROGRAM-004** — Une implémentation externe `ksp-program-<name>-lib` peut dépendre directement de `ksp-program-api` sans dépendre de `ksp-program-lib`.
- **DEP-EXECUTION-001** — `ksp-execution-policy-api` dépend du contrat public Program et de Core, pas de `ksp-program-lib`, wallet, transport, store ou UI.
- **DEP-EXECUTION-002** — `ksp-execution-lib` dépend de `ksp-program-api`, `ksp-execution-policy-api`, `ksp-wallet-lib`, `ksp-onchain-transport-lib`, `ksp-logging-lib` et Core ; il ne dépend pas de `ksp-program-lib`.
- **DEP-EXECUTION-003** — Une implémentation de policy reste située dans une crate de scénario/domaine/produit appropriée et ne devient pas une responsabilité de `ksp-program-lib`.
- **DEP-EXECUTION-004** — Une exécution réelle reçoit explicitement une policy ; aucun fallback permissif implicite n'est prévu.
- **DEP-EXECUTION-005** — La policy décide/refuse/contraint mais ne réalise pas la simulation, la signature, le transport réseau ou l'interaction UI.
- **DEP-EXECUTION-006** — Wallet/signers et provider/transport sont fournis/sélectionnés par la composition supérieure ; `ksp-execution-lib` les orchestre sans définir leur policy de sélection.
- **DEP-EXECUTION-007** — Le retry réseau d'un appel identique appartient au transport ; un retry modifiant le lifecycle d'exécution appartient à `ksp-execution-lib`.
- **DEP-EXECUTION-008** — `ksp-execution-lib` ne dépend ni de `ksp-store-api` ni de `ksp-store-lib`; la persistence d'un résultat appartient à une composition supérieure.
## Materializer / Store
- **DEP-MAT-001** — `ksp-materializer-api` peut dépendre de `ksp-program-api` lorsque les contrats de matérialisation consomment des sorties canoniques de processing.
- **DEP-MAT-002** — `ksp-materializer-api` et `ksp-materializer-lib` ne dépendent pas de `ksp-store-api` ou `ksp-store-lib`.
- **DEP-MAT-003** — Une matérialisation générique doit pouvoir produire un output compatible avec le journal D3 sans imposer une table PostgreSQL spécialisée par materializer.
- **DEP-STORE-001** — `ksp-store-api` ne dépend pas de Program, Materializer ou Transport.
- **DEP-STORE-002** — `ksp-store-lib` dépend de `ksp-store-api`, porte la façade/runtime Store commune et peut dépendre optionnellement de crates backend compilées par feature ; il ne dépend pas des implémentations Program/Materializer/Transport.
- **DEP-STORE-003** — Les workers/jobs spécialisés sont propriétaires des conversions entre modèles runtime et DTO persistants.
- **DEP-STORE-004** — Les niveaux durables canoniques sont D1 `RAW`, D2 `STRUCTURAL`, D3 `DECODED` et D4 `DOMAIN` ; le journal générique de matérialisation décodée appartient à D3 et les projections/faits de domaine queryables à D4.
- **DEP-STORE-005** — Les replays D1 -> D2, D2 -> D3 et D3 -> D4 doivent pouvoir être exécutés indépendamment.
- **DEP-STORE-006** — Une notification de donnée persistée ne constitue jamais la source de vérité du backlog ; les queries Store et marqueurs durables d'idempotence/version de processor font autorité.
- **DEP-STORE-007** — Une notification de donnée est publiée seulement après persistence/commit réussis.
- **DEP-STORE-008** — D4 est organisé par faits canoniques quand les invariants le permettent, et non par familles de tables propres aux protocoles.
- **DEP-STORE-009** — `ksp-store-postgres-lib` dépend de `ksp-store-api`, possède seul le driver, le pool, TLS, SQL et les migrations PostgreSQL physiques, et ne dépend jamais de `ksp-store-lib`.
- **DEP-STORE-010** — Les consumers runtime ordinaires — workers, jobs, services et apps — dépendent de `ksp-store-lib` et non directement dune crate backend ; Config/composition traduit la configuration effective vers les settings publics Store sans créer de dépendance Store -> Config.
## Transport
- **DEP-TRANSPORT-001** — `ksp-onchain-transport-lib` ne dépend pas de `ksp-store-api` ou `ksp-store-lib`.
- **DEP-TRANSPORT-002** — Les providers on-chain normalisent leurs réponses dans des modèles KSP homogènes par catégorie de données avant exposition aux consommateurs.
- **DEP-TRANSPORT-003** — Les modèles de transport ne réalisent pas de décodage métier/protocolaire et doivent rester facilement convertibles en DTO raw persistants.
- **DEP-TRANSPORT-004** — Aucun `ksp-onchain-transport-api` ou `ksp-offchain-transport-api` global n'est créé dans l'architecture actuelle.
- **DEP-TRANSPORT-005** — `ksp-onchain-transport-lib` et `ksp-offchain-transport-lib` ne dépendent pas de `ksp-config-lib` : ils possèdent leurs settings/runtime contracts publics, tandis qu'une couche de composition ou un adaptateur appartenant à Config traduit les documents de configuration vers ces contrats.
## Pipelines spécialisés
- **DEP-PIPE-001** — KSP ne crée pas de `ksp-pipeline-lib` monolithique.
- **DEP-PIPE-002** — Les frontières canoniques de processing sont `RAW -> STRUCTURAL -> DECODED -> DOMAIN`. Une crate pipeline dédiée n'est créée que lorsqu'une logique doit réellement être réutilisée entre plusieurs lifecycle hosts (worker/job/app/test) ; aucune liste globale de quatre crates pipeline n'est imposée par symétrie.
- **DEP-PIPE-003** — Un pipeline de processing dépend des APIs nécessaires à sa frontière et non des implémentations officielles correspondantes lorsque l'API permet l'injection/composition.
- **DEP-PIPE-004** — Les pipelines spécialisés ne dépendent pas de `ksp-worker-api` ou `ksp-job-api`; worker et job possèdent le lifecycle.
- **DEP-PIPE-005** — Worker live et job de replay/backfill réutilisent le même pipeline pour une même frontière durable afin d'éviter la duplication de logique.
- **DEP-PIPE-006** — Le pipeline raw ingestion peut dépendre des modèles homogènes de `ksp-onchain-transport-lib` et de `ksp-store-api`, mais pas de `ksp-store-lib`.
- **DEP-PIPE-007** — La transformation `RAW -> STRUCTURAL` est Solana-générique et ne dépend ni de `ksp-program-api`, ni de `ksp-program-lib`, ni de `ksp-materializer-api`; les premiers contrats Program interviennent seulement à partir de `STRUCTURAL -> DECODED`.
- **DEP-PIPE-008** — À partir de `STRUCTURAL -> DECODED`, les pipelines/processors verticaux peuvent dépendre de `ksp-program-api` et de `ksp-materializer-api` selon leur rôle, sans dépendre par défaut des implémentations officielles correspondantes lorsque l'injection/composition suffit. `DECODED -> DOMAIN` utilise de même les contrats de matérialisation/projection nécessaires sans imposer une implémentation globale unique.
## Worker / Job lifecycle
- **DEP-WORKER-001** — `ksp-worker-control-lib` dépend de `ksp-worker-api` et ne dépend pas de `ksp-job-api`.
- **DEP-WORKER-002** — Les workers de processing reconstruisent leur backlog depuis `ksp-store-api`/Store ; une notification ne suffit pas à prouver qu'un input a été traité.
- **DEP-WORKER-003** — La logique réutilisable d'un worker/job dépend en priorité des APIs KSP (`ksp-store-api`, `ksp-program-api`, `ksp-materializer-api`, etc.) et reçoit les implémentations par composition. Le binaire/service mince peut câbler `ksp-store-lib` ou les implémentations officielles nécessaires sans transférer cet ownership à la logique du worker/job.
- **DEP-JOB-001** — `ksp-job-api` ne dépend ni de `ksp-worker-api` ni de `ksp-worker-control-lib`.
- **DEP-JOB-002** — Un orchestrateur futur peut consommer séparément les APIs/contrôles workers et jobs sans introduire un lifecycle parent commun.
- **DEP-JOB-003** — Lorsqu'une même transformation existe en live et en replay, jobs et workers réutilisent la même logique de transformation au lieu de dupliquer `RAW -> STRUCTURAL`, `STRUCTURAL -> DECODED` ou `DECODED -> DOMAIN`.
## Services, applications et control plane
- **DEP-SERVICE-001** — Chaque worker concret doit pouvoir fonctionner comme service/processus indépendant.
- **DEP-SERVICE-002** — La direction de packaging préférée est un package `ksp-worker-<role>` contenant une cible bibliothèque réutilisable et une cible binaire autonome mince.
- **DEP-SERVICE-003** — Un worker concret ne dépend pas d'un autre worker concret ; les données transitent par les niveaux durables Store.
- **DEP-SERVICE-004** — Le binaire worker compose/initialise le service mais ne duplique pas le pipeline ou la logique métier de sa cible bibliothèque.
- **DEP-CONTROL-001** — `ksp-worker-api` définit la sémantique de lifecycle indépendamment du transport local/IPC.
- **DEP-CONTROL-002** — `ksp-worker-control-lib` dépend de `ksp-worker-api` et peut plus tard adapter des handles locaux ou proxies distants.
- **DEP-CONTROL-003** — Le control plane ne transporte pas les payloads D1/D2/D3/D4 entre workers.
- **DEP-CONTROL-004** — Aucun `ksp-ipc-api` générique n'est introduit avant le premier besoin concret de transport de control.
- **DEP-APP-001** — Les applications spécialisées sont privilégiées avant une future application globale.
- **DEP-APP-002** — Une app manager worker pilote le service via les contrats de control et ne modifie pas directement son état interne de processing dans PostgreSQL.
- **DEP-SCENARIO-001** — Une app scenario dépend de `ksp-scenario-<domain>-lib` ; le workflow du scenario ne réside pas dans l'application.
- **DEP-SCENARIO-002** — Une crate scenario ne dépend pas de Tauri et doit pouvoir être appelée depuis d'autres interfaces/tests.
## Propriété des dépendances Solana
- **DEP-SOL-001** — Une dépendance externe relative à Solana doit avoir un composant KSP propriétaire précis.
- **DEP-SOL-002** — Les bibliothèques KSP de haut niveau qui n'ont pas besoin d'un contrat externe bas niveau ne dépendent pas directement de ce contrat.
- **DEP-SOL-003** — Les primitives Solana/Anza suffisamment fondamentales et stables peuvent être utilisées dans les bibliothèques KSP de bas niveau qui en sont propriétaires.
- **DEP-SOL-004** — La liste initialement acceptée de primitives fondamentales comprend `solana-pubkey`, `solana-keypair`, `solana-signer`, `solana-hash` et `solana-nonce`.
- **DEP-SOL-005** — L'ajout d'une autre crate Solana/Anza est décidé à partir d'un besoin concret et de sa stabilité/API.
- **DEP-SOL-006** — Une bibliothèque KSP peut exposer ou réexporter une primitive externe fondamentale lorsque cette primitive fait intentionnellement partie du contrat KSP.
## Crates de protocoles et interfaces wire
- **DEP-PROTO-001** — Les crates d'interface/protocole externes telles que `mpl-token-metadata` ou `spl-elgamal-registry-interface` sont interdites par défaut comme dépendances runtime KSP.
- **DEP-PROTO-002** — KSP préfère posséder ses représentations compatibles nécessaires : Program IDs, discriminants, layouts, enums, structures wire, règles de PDA, sérialisation/désérialisation et autres contrats effectivement requis.
- **DEP-PROTO-003** — Une réimplémentation KSP vise le contrat nécessaire et ne consiste pas à copier mécaniquement l'architecture ou l'intégralité d'une crate externe.
- **DEP-PROTO-004** — La méthode de vérification de compatibilité wire et l'usage éventuel de dépendances externes uniquement en tests de conformité doivent être définis avant la première implémentation concernée.
- **DEP-PROTO-005** — Une dépendance protocolaire externe exceptionnellement nécessaire doit être explicitement justifiée et confinée au composant propriétaire le plus bas possible.
## Versions
- **DEP-VER-001** — KSP privilégie les versions récentes compatibles des dépendances.
- **DEP-VER-002** — Une version volontairement ancienne, bornée ou incompatible avec la politique générale est documentée avec la raison, le propriétaire et la condition permettant de lever la contrainte.
- **DEP-VER-003** — Les lockfiles ne servent pas à figer silencieusement une version de dépendance ; les contraintes nécessaires appartiennent aux manifests et à la documentation.