# Règles spécifiques à KSP ## Nomenclature - **KSP-NAME-001** — Une bibliothèque Rust d'implémentation réutilisable se nomme `ksp--lib`, sauf famille explicitement définie par une règle plus spécifique. - **KSP-NAME-002** — Une crate publique de contrats extensibles se nomme `ksp--api`. Elle est techniquement une bibliothèque Rust mais ne porte volontairement pas le suffixe `-lib`. - **KSP-NAME-003** — Une crate `ksp--api` expose principalement les types/traits/contrats nécessaires aux implémentations ; elle n'est pas une implémentation fonctionnelle directement destinée aux exécutables. - **KSP-NAME-004** — Une application se nomme `ksp-app--` lorsque l'interface doit être indiquée. - **KSP-NAME-005** — Un worker continu se nomme `ksp-worker-`. - **KSP-NAME-006** — Un job ponctuel/historique/terminable se nomme `ksp-job-`. - **KSP-NAME-007** — Une démonstration se termine par `-demo`. - **KSP-NAME-008** — Les crates Rust sont placées directement sous `crates/`. - **KSP-NAME-009** — Une application desktop de scénario spécialisée suit la forme `ksp-app-scenario---desk-demo` lorsque l'environnement est imposé. - **KSP-NAME-010** — Un pipeline spécialisé réutilisable se nomme `ksp-pipeline--lib`; aucun `ksp-pipeline-lib` générique n'est créé. ## Architecture et APIs - **KSP-API-001** — Un domaine extensible peut séparer `ksp--api` et `ksp--lib`. - **KSP-API-002** — Les premiers couples retenus sont `ksp-program-api` / `ksp-program-lib`, `ksp-materializer-api` / `ksp-materializer-lib` et `ksp-store-api` / `ksp-store-lib`. - **KSP-API-003** — KSP ne crée pas de `ksp-api-lib` monolithique regroupant les contrats de domaines indépendants. - **KSP-API-004** — Un contrat public extensible doit pouvoir être implémenté depuis une crate séparée du workspace principal lorsque cela est techniquement pertinent. - **KSP-API-005** — Les signatures des contrats publics utilisent en priorité des types publics KSP et les primitives externes explicitement admises ; elles ne doivent pas imposer des détails internes instables. - **KSP-API-006** — `ksp-store-lib` contient PostgreSQL comme implémentation officielle de référence derrière `ksp-store-api`. - **KSP-API-007** — Une crate `*-api` n'est créée que lorsqu'un vrai besoin d'extension, backend ou lifecycle le justifie ; la symétrie de nommage n'est jamais une justification suffisante. ## Programmes et exécution - **KSP-PROGRAM-001** — Les contrats de décodage et de préparation d'exécution appartiennent à `ksp-program-api`; les implémentations officielles intégrées appartiennent à `ksp-program-lib`. - **KSP-PROGRAM-002** — Le decoder vise toute surface techniquement décodable dont la définition est connue, y compris les formats anciens, obsolètes ou expérimentaux encore distinguables. - **KSP-PROGRAM-003** — Le statut `deprecated` concerne la capacité d'exécution, pas la capacité de décodage. - **KSP-PROGRAM-004** — Lorsqu'une définition wire a été réellement écrasée/remplacée sous la même identité et que l'ancienne définition n'est plus distinguable de manière fiable, le decoder utilise la définition la plus récente applicable. - **KSP-PROGRAM-005** — Une opération devenue obsolète mais toujours identifiable/exécutable peut rester implémentée dans l'executor et être marquée `deprecated`. - **KSP-PROGRAM-006** — `ksp-program-lib` ne contient pas la politique de sécurité de production. - **KSP-EXEC-001** — `ksp-execution-policy-api` est l'API publique de décision/safety d'exécution ; chaque contexte fournit sa propre implémentation. - **KSP-EXEC-002** — Toute exécution réelle via `ksp-execution-lib` reçoit explicitement une policy ; aucun fallback implicite permissif n'est prévu. - **KSP-EXEC-003** — Une policy peut être évaluée à plusieurs checkpoints et peut autoriser, refuser ou imposer des requirements ; elle ne signe pas, n'appelle pas le réseau et n'interagit pas directement avec l'UI. - **KSP-EXEC-004** — `ksp-execution-lib` consomme fondamentalement `PreparedProgramExecution`, dépend de `ksp-program-api` et non de `ksp-program-lib`. - **KSP-EXEC-005** — `ksp-execution-lib` orchestre simulation, signature, submission, confirmation et retry de lifecycle à partir de primitives possédées par transport/wallet. - **KSP-EXEC-006** — Wallet/signers et transport/provider sont sélectionnés/fournis par la composition supérieure ; l'execution lib ne choisit pas arbitrairement ces ressources. - **KSP-EXEC-007** — Une approbation externe peut produire un état suspendu/reprenable sans dépendance de la policy/execution vers Tauri ou une UI. - **KSP-EXEC-008** — `ksp-execution-lib` ne persiste pas automatiquement son résultat et ne dépend pas du store. ## Transports - **KSP-TRANSPORT-001** — KSP ne crée pas de `ksp-onchain-transport-api` séparée dans l'architecture actuelle. - **KSP-TRANSPORT-002** — `ksp-onchain-transport-lib` ne dépend pas de `ksp-store-api`. - **KSP-TRANSPORT-003** — Les providers on-chain normalisent leurs sorties dans des modèles de transport homogènes par catégorie de données avant exposition aux consommateurs. - **KSP-TRANSPORT-004** — Les modèles de transport restent sans décodage métier/protocolaire et doivent être explicitement/facilement convertibles vers les modèles raw persistants de `ksp-store-api` par la couche d'acquisition. - **KSP-TRANSPORT-005** — KSP ne crée pas de `ksp-offchain-transport-api` globale ni de trait universel artificiel pour des domaines off-chain hétérogènes. ## Wallet - **KSP-WALLET-001** — KSP ne crée pas de `ksp-wallet-api` dans l'architecture actuelle ; `ksp-wallet-lib` possède le format wallet KSP et ses capacités de lecture/protection/import/export/pubkey/secret/signature. - **KSP-PROGRAM-007** — Le contrat de préparation d'exécution est nommé conceptuellement `ProgramExecutionPreparer`; il ne signe, ne simule, n'envoie et ne confirme pas une transaction. - **KSP-PROGRAM-008** — `ksp-program-api` reste ouvert : aucun enum central fermé ne doit imposer une modification de l'API pour ajouter un Program ID externe. - **KSP-PROGRAM-009** — Le résultat décodé doit pouvoir être auto-identifié et devenir persistable ; `Any` ne constitue pas à lui seul un contrat de résultat acceptable. - **KSP-PROGRAM-010** — Une extension de programme est une implémentation `ksp-program--lib`, pas une nouvelle crate `*-api`. - **KSP-PROGRAM-011** — `ksp-program-lib` est organisé selon `domain -> program/protocol -> capability`; les dossiers globaux regroupant tous les decoders de tous les protocoles sont évités. - **KSP-PROGRAM-012** — Le statut legacy/deprecated d'une opération est machine-readable et indépendant du décodage historique. - **KSP-PROGRAM-013** — `#[deprecated]` n'est pas imposé pour les opérations historiques ; un warning runtime et la policy supérieure peuvent porter la décision d'usage. - **KSP-WIRE-001** — `ksp-interface-lib` est le propriétaire normal des codecs wire pour les interfaces officielles KSP. - **KSP-WIRE-002** — Les interfaces externes sont sélectionnées aussi selon la modernité/cohérence de leur graphe de dépendances, pas uniquement selon la commodité de leur API. - **KSP-WIRE-003** — Les contrats wire d'une crate protocolaire rejetée sont réimplémentés de manière bornée dans `ksp-interface-lib` lorsque KSP en a besoin. ## Niveaux durables et Store - **KSP-DURABLE-001** — Les niveaux persistants utilisent la nomenclature D1 à D4, distincte des couches architecturales N1 à N4. - **KSP-DURABLE-002** — D1 est Raw, D2 Core canonique, D3 le journal générique de matérialisation et D4 les projections spécialisées/queryables. - **KSP-DURABLE-003** — D1/D2/D3 sont destinés à devenir fortement stables après stabilisation de la première série Store ; D4 reste plus évolutif. - **KSP-DURABLE-004** — Le journal D3 est durable et obligatoire ; il ne peut pas être supprimé au profit de projections D4 directes. - **KSP-DURABLE-005** — Les replays D1 -> D2, D2 -> D3 et D3 -> D4 sont indépendants. - **KSP-DURABLE-006** — Les instructions top-level et CPI restent des faits Core distincts lorsque leurs invariants/requêtes diffèrent. - **KSP-DURABLE-007** — D4 modélise des faits canoniques plutôt que des familles de tables par protocole lorsque les invariants sont normalisables. - **KSP-DURABLE-008** — Les temporalités blockchain et locales restent distinctes ; un `block_time` absent n'est jamais remplacé par une date locale inventée. ## Materialization - **KSP-MAT-001** — `ksp-materializer-api` est l'unique API publique de matérialisation actuellement prévue et peut exposer des capacités distinctes D2 -> D3 et D3 -> D4. - **KSP-MAT-002** — `ksp-materializer-lib` transforme mais ne persiste pas directement et ne dépend pas du Store. - **KSP-MAT-003** — Une extension externe de materializer doit pouvoir produire du D3 générique sans migration PostgreSQL spécialisée. - **KSP-MAT-004** — Une nouvelle projection relationnelle D4 exige explicitement un contrat Store/migration/backend correspondant ; cette responsabilité n'est pas cachée dans `ksp-materializer-api`. ## Backlog, claims et reprise - **KSP-PROC-001** — Le backlog est défini relativement à l'identité/version/capability du processor et non par simple absence d'une row de sortie. - **KSP-PROC-002** — Une nouvelle version de processor peut rendre de nouveau candidat un input déjà terminal pour une version précédente. - **KSP-PROC-003** — Un input peut avoir plusieurs outcomes indépendants lorsqu'il est candidat pour plusieurs materializers/projectors. - **KSP-PROC-004** — Les claims sont temporaires ; une lease expirée après crash rend le candidat de nouveau traitable. - **KSP-PROC-005** — Les erreurs transitoires utilisent retry/backoff borné ; les failures déterministes doivent pouvoir devenir un état durable afin d'éviter une boucle infinie. - **KSP-PROC-006** — Unsupported/NotApplicable ne sont pas nécessairement des erreurs et constituent des outcomes terminaux pour la version/capability concernée. - **KSP-PROC-007** — Les consumers combinent wake-up par notification et polling périodique du backlog. - **KSP-PROC-008** — Un backlog downstream croissant n'entraîne pas automatiquement le ralentissement du raw retriever ; une éventuelle backpressure globale appartient à une policy/configuration/orchestration supérieure. ## Notifications de données persistées - **KSP-NOTIFY-001** — `ksp-store-api` possède le format canonique d'une notification signalant qu'une donnée persistée est disponible. - **KSP-NOTIFY-002** — Le format est indépendant de l'origine de la donnée : worker live, backfill, import, replay ou autre source. - **KSP-NOTIFY-003** — Une notification est un signal de réveil et n'est jamais la source de vérité du backlog. - **KSP-NOTIFY-004** — La persistence et le commit réussissent avant publication d'une notification. - **KSP-NOTIFY-005** — Le payload de notification privilégie une référence durable compacte plutôt que la duplication du payload persistant. - **KSP-NOTIFY-006** — Le contrat de notification reste indépendant du mécanisme de diffusion concret. ## Workers - **KSP-WORKER-001** — Un worker représente un service continu/live ; il est distinct d'un job. - **KSP-WORKER-002** — Les contrats communs des workers appartiennent à `ksp-worker-api` et ne contiennent aucun contrat propre aux jobs. - **KSP-WORKER-003** — `ksp-worker-api` est principalement une lifecycle API de services continus : identité, état, health, démarrage/arrêt et événements communs ; les capacités optionnelles ne deviennent universelles que si plusieurs workers les partagent réellement. - **KSP-WORKER-004** — `ksp-worker-control-lib` est une implémentation commune de gouvernance/contrôle réutilisable d'abord par les apps manager spécialisées, puis éventuellement par un futur orchestrateur/application globale ; les apps ne réimplémentent pas cette gouvernance. - **KSP-WORKER-005** — `ksp-worker-raw-retriever` est le worker d'acquisition raw live/quasi-live. Il ne décode pas, ne matérialise pas et ne réalise pas de replay/backfill historique. - **KSP-WORKER-006** — `ksp-worker-raw-retriever` persiste les données raw puis notifie leur disponibilité selon les contrats de données normalisés. - **KSP-WORKER-007** — `ksp-worker-raw-retriever` doit pouvoir faire évoluer à chaud les listeners et la sélection des données qu'il rapatrie/stocke. - **KSP-WORKER-008** — Les workers de processing actuellement retenus sont `ksp-worker-core-processor`, `ksp-worker-generic-materializer` et `ksp-worker-domain-projector`; le dernier nom reste provisoire. - **KSP-WORKER-009** — Les workers de processing utilisent notification comme wake-up mais reconstruisent leur backlog depuis le Store. - **KSP-WORKER-010** — `ksp-worker-raw-retriever` distingue une configuration desired et une configuration effective lors des reconfigurations à chaud. - **KSP-WORKER-011** — Un cursor de scan est une optimisation ; les processing outcomes durables constituent la preuve qu'un input a été traité pour un processor/version/capability. - **KSP-WORKER-012** — La concurrence de processing utilise une sémantique de claim/lease récupérable après expiration/crash. - **KSP-WORKER-013** — Chaque worker doit pouvoir fonctionner comme service/processus indépendant afin d'être arrêté/redémarré/mis à jour sans imposer l'arrêt volontaire des autres workers. - **KSP-WORKER-014** — La direction de packaging préférée est un package worker avec cible bibliothèque réutilisable et binaire autonome mince. - **KSP-WORKER-015** — Les workers ne dépendent pas directement les uns des autres ; D1–D4 constituent leur data plane partagé. - **KSP-WORKER-016** — Aucun ordre global strict de démarrage des workers n'est figé actuellement. ## Jobs - **KSP-JOB-001** — Un job représente un travail déclenché à la demande, suivable et terminable ; il est distinct d'un worker continu. - **KSP-JOB-002** — Les contrats communs des jobs appartiennent à `ksp-job-api` et ne contiennent aucun contrat propre aux workers. - **KSP-JOB-003** — `ksp-job-api` est principalement une lifecycle API de travaux terminables : identité, état, progression, annulation, résultat et capacités de reprise lorsqu'elles sont pertinentes. - **KSP-JOB-004** — Les implémentations concrètes utilisent le préfixe `ksp-job-`. - **KSP-JOB-005** — `ksp-job-backfill` est retenu pour le backfill historique ; il ne doit pas être implémenté comme un mode du worker raw. - **KSP-JOB-006** — D'autres jobs peuvent être introduits pour metadata, quotes ou autres travaux ponctuels lorsqu'un besoin réel le justifie. - **KSP-JOB-007** — Aucune `ksp-job-control-lib` commune n'est prévue actuellement ; elle ne sera créée que si une duplication concrète entre plusieurs jobs le justifie. - **KSP-JOB-008** — Le contrôle/gouvernance des jobs reste séparé du contrôle des workers. - **KSP-JOB-009** — Les jobs de replay retenus sont `ksp-job-replay-core`, `ksp-job-replay-generic-materialization` et `ksp-job-replay-domain-projection`. - **KSP-JOB-010** — Les jobs de replay réutilisent exactement le pipeline spécialisé de la frontière correspondante. - **KSP-JOB-011** — Le backfill conserve un checkpoint de progression dans la source historique en plus des outcomes de persistence D1. - **KSP-JOB-012** — Replay normal/reprise et force replay sont deux intentions distinctes ; un force replay conserve provenance/historique et ne supprime pas silencieusement le résultat courant. ## Matérialisation et persistence - **KSP-MAT-001** — `ksp-materializer-api` peut dépendre de `ksp-program-api` ; `ksp-materializer-lib` dépend de son API mais ne dépend pas du store. - **KSP-MAT-002** — `ksp-materializer-api` / `ksp-materializer-lib` ne réalisent pas eux-mêmes la persistance ; les workers/jobs/pipelines spécialisés composent matérialisation et store. - **KSP-STORE-001** — `ksp-store-api` reste indépendant des APIs Program/Materializer/Transport et possède les contrats persistants. - **KSP-STORE-002** — Les conversions entre modèles runtime et DTO persistants sont explicites aux frontières de composition ; aucun `ksp-data-api` global n'est introduit actuellement. ## Notifications de données - **KSP-DATA-001** — Une notification de donnée décrit la donnée disponible et non le worker/job qui l'a produite. - **KSP-DATA-002** — Le même type de donnée utilise le même contrat de notification quelle que soit son origine : worker, job, import ou autre source. - **KSP-DATA-003** — `ksp-store-api` est le propriétaire retenu des références/notifications canoniques lorsqu'elles signifient qu'une donnée persistée est disponible. - **KSP-DATA-004** — Le contrat de notification est séparé de son mécanisme de transport concret. ## Pipelines et scénarios - **KSP-PIPE-001** — KSP ne crée pas de `ksp-pipeline-lib` monolithique. - **KSP-PIPE-002** — Les quatre pipelines spécialisés retenus pour les frontières durables sont raw ingestion, Core processing, generic materialization et domain projection. - **KSP-PIPE-003** — Un pipeline spécialisé contient la logique réutilisable d'une frontière mais aucun lifecycle worker/job. - **KSP-PIPE-004** — Les pipelines utilisent les APIs Program/Materializer/Store lorsque ces frontières doivent être injectables ; les implémentations officielles sont composées par workers/jobs. - **KSP-PIPE-005** — Le traitement est at-least-once avec persistence idempotente et outcomes durables, plutôt qu'une promesse exactly-once distribuée. - **KSP-PIPE-006** — Un traitement valide produisant zéro output possède malgré tout un outcome terminal explicite tel que NoOutput/NotApplicable/Unsupported selon la sémantique finale. - **KSP-PIPE-007** — Outputs obligatoires et processing outcome d'une unité logique sont atomiques du point de vue durable. - **KSP-SCENARIO-001** — Il n'existe pas de crate monolithique `ksp-scenarios-lib`. - **KSP-SCENARIO-002** — Les scénarios sont séparés en crates `ksp-scenario--lib` par responsabilité fonctionnelle cohérente. - **KSP-SCENARIO-003** — `ksp-scenario-api` n'est pas retenu actuellement ; KSP privilégie d'abord une norme documentaire/structurelle commune qui ne limite pas les contrats spécifiques des scénarios. - **KSP-SCENARIO-004** — Memo, SPL Token classique, ATA et Token-2022 restent dans des crates/scénarios séparés. - **KSP-SCENARIO-005** — Une famille metadata d'assets/tokens peut regrouper Metaplex Token Metadata et Token-2022 Metadata ; Solana Program Metadata reste séparé. - **KSP-SCENARIO-006** — Lorsqu'un scénario réutilisable existe dans KSP, l'application demo le consomme et ne réimplémente pas le workflow. - **KSP-SCENARIO-007** — La logique fonctionnelle d'un scenario s'exécute dans `ksp-scenario--lib` et reste appelable hors desktop. - **KSP-SCENARIO-008** — Les scenarios suivent `docs/rules/SCENARIO_CONVENTION.md` tant qu'aucun contrat Rust commun suffisamment utile ne justifie `ksp-scenario-api`. ## Applications - **KSP-APP-001** — Une application KSP est une interface et une couche de composition. Elle ne réimplémente pas une opération appartenant conceptuellement à un composant KSP réutilisable inférieur. - **KSP-APP-002** — Les applications/demos ne dépendent pas directement de crates Solana/protocoles externes. - **KSP-APP-003** — Les applications/demos peuvent réaliser les opérations strictement liées à l'interface, mais pas la logique métier/protocolaire réutilisable. - **KSP-APP-004** — Une demo scenario desktop consomme la crate `ksp-scenario--lib` correspondante ; elle suit la convention `ksp-app-scenario---desk-demo` lorsque l'environnement est imposé. - **KSP-APP-005** — Les applications spécialisées précèdent toute future application globale ; aucune app globale n'est un livrable actuel. - **KSP-APP-006** — Une app manager worker utilise le control plane et ne modifie pas directement l'état interne de processing du worker en base. - **KSP-APP-007** — Une future application globale est conservée comme idée produit et sera cadrée seulement après validation suffisante des apps spécialisées/demos. ## Data plane / control plane - **KSP-CONTROL-001** — Le data plane des workers passe par transport + D1/D2/D3/D4 et notifications de données persistées. - **KSP-CONTROL-002** — Le control plane porte lifecycle, status, health et reconfiguration ; il ne transporte pas les payloads de processing entre workers. - **KSP-CONTROL-003** — La sémantique de `ksp-worker-api` doit rester utilisable avec un handle local ou un futur proxy IPC. - **KSP-CONTROL-004** — Aucun `ksp-ipc-api` générique n'est prévu actuellement ; le premier manager/service concret doit d'abord démontrer le transport nécessaire. - **KSP-CONTROL-005** — `ksp-orchestrator-lib` est seulement un concept futur et n'est pas une crate retenue dans le plan actuel. ## Releases fonctionnelles - **KSP-REL-001** — Une série `X.Y.x` est une famille fonctionnelle ; chaque release concrète `X.Y.Z` est dimensionnée séparément. - **KSP-REL-002** — À partir de `0.1.x`, chaque delta/prerelease/fix est commité afin de préserver l'historique réel du développement. - **KSP-REL-003** — Une erreur intermédiaire est corrigée par un delta/commit suivant ; l'historique n'est pas réécrit pour supprimer artificiellement l'étape erronée. - **KSP-REL-004** — Seul le commit d'une release stable reçoit le tag `vX.Y.Z`. - **KSP-REL-005** — Le premier `pre.001` d'une release fonctionnelle commence par brainstorming, audit, vérification des dépendances actuelles lorsque concernées, plan détaillé et dimensionnement. - **KSP-REL-006** — Une release ou prerelease trop grosse est scindée plutôt que compressée pour respecter un numéro prévu. - **KSP-REL-007** — La dernière prerelease d'une release fonctionnelle réalise par défaut validations finales, documentation, nettoyage/archivage, changelog et prompt de la release suivante. - **KSP-REL-008** — La première release fonctionnelle sélectionnée est `0.1.1`, dédiée à la stabilisation de `ksp-core-lib`.