265 lines
44 KiB
Markdown
265 lines
44 KiB
Markdown
<!-- file: docs/rules/RULES_KSP.md -->
|
||
<!-- version: 37 -->
|
||
|
||
# Règles spécifiques à KSP
|
||
|
||
## Nomenclature
|
||
|
||
- **KSP-NAME-001** — Une bibliothèque Rust d'implémentation réutilisable se nomme `ksp-<role>-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-<domain>-api`. Elle est techniquement une bibliothèque Rust mais ne porte volontairement pas le suffixe `-lib`.
|
||
- **KSP-NAME-003** — Une crate `ksp-<domain>-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-<role>-<interface>` lorsque l'interface doit être indiquée.
|
||
- **KSP-NAME-005** — Un worker continu se nomme `ksp-worker-<role>`.
|
||
- **KSP-NAME-006** — Un job ponctuel/historique/terminable se nomme `ksp-job-<role>`.
|
||
- **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-<domain>-<environment>-desk-demo` lorsque l'environnement est imposé.
|
||
- **KSP-NAME-010** — Un pipeline spécialisé réutilisable se nomme `ksp-pipeline-<role>-lib`; aucun `ksp-pipeline-lib` générique n'est créé.
|
||
|
||
## Architecture et APIs
|
||
|
||
- **KSP-API-001** — Un domaine extensible peut séparer `ksp-<domain>-api` et `ksp-<domain>-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.
|
||
|
||
## Configuration et environnement
|
||
|
||
- **KSP-CONFIG-001** — `ksp-config-lib` est l'unique propriétaire KSP de la lecture des documents Config, du `.env`, des variables applicatives `KSP_*` / `KSPB_*` et de leur résolution ; les autres crates ne lisent pas directement ces sources.
|
||
- **KSP-CONFIG-002** — Les namespaces d'environnement sont `KSP_*`, `KSP_PUBLIC_*`, `KSP_SECRET_*` pour les composants génériques et `KSPB_*`, `KSPB_PUBLIC_*`, `KSPB_SECRET_*` pour la branche bot ; les anciens préfixes KS/KB ne sont pas utilisés dans KSP.
|
||
- **KSP-CONFIG-003** — La priorité d'une variable est environnement du processus > `./.env` > fallback déclaré au point d'usage. Une chaîne vide explicitement définie est une valeur présente et n'active pas le fallback.
|
||
- **KSP-CONFIG-004** — Le `.env` runtime est local, non versionné et non échangé. Config le lit sans prétendre modifier l'environnement du shell/systemd/parent qui a lancé le processus.
|
||
- **KSP-CONFIG-005** — `.env.example` est versionné à la racine et inventorie toutes les variables d'environnement runtime KSP/KSPB utilisées par les fichiers Config ou le code ; toute nouvelle variable y est ajoutée dans le même delta que sa première utilisation.
|
||
- **KSP-CONFIG-006** — Chaque entrée de `.env.example` est précédée d'un commentaire décrivant son usage/utilité. Sa valeur peut être un défaut sûr, une valeur générique non secrète ou une entrée commentée ; aucun vrai secret n'y est enregistré.
|
||
- **KSP-CONFIG-007** — Les placeholders Config utilisent `${NAME}` ou `${NAME:-fallback}`. Le fallback s'applique uniquement si la variable est absente ; l'interpolation appartient à `ksp-config-lib` et non aux consumers.
|
||
- **KSP-CONFIG-008** — La sensibilité d'une variable est dérivée de son nom : `KSP_SECRET_*`/`KSPB_SECRET_*` -> `Secret`, `KSP_PUBLIC_*`/`KSPB_PUBLIC_*` -> `Public`, les autres variables KSP/KSPB -> `Internal`, avec l'ordre `Secret > Internal > Public`.
|
||
- **KSP-CONFIG-009** — Toute valeur Config contenant un segment `Secret` conserve une valeur réelle pour le runtime légitime et une représentation sûre où chaque segment secret est remplacé par `********`; les `Debug` génériques ne révèlent jamais la valeur réelle secrète.
|
||
- **KSP-CONFIG-010** — La sensibilité d'une chaîne composée est la plus forte des placeholders utilisés. Un fallback d'une variable `Secret` reste `Secret` et doit être redacted même si la valeur provient du fallback.
|
||
- **KSP-CONFIG-011** — La provenance de résolution n'embarque jamais la valeur d'environnement elle-même ; elle distingue document literal, process, `.env` et fallback avec le nom de variable concerné.
|
||
- **KSP-CONFIG-012** — Pour `std.logging`, `logs_directory` peut être absolu ou relatif ; un chemin relatif est ancré sur le current working directory du processus lors de la construction des settings. Le fallback du placeholder ne s'applique que si la variable est absente ; une valeur explicitement présente mais invalide provoque une erreur de configuration effective.
|
||
- **KSP-CONFIG-013** — Le document standard Logging ne consomme pas de variable classée `Secret`. L'adapter Config -> Logging rejette une configuration effective `Secret` afin qu'aucune valeur secrète ne soit transmise aux diagnostics runtime/filesystem de Logging.
|
||
- **KSP-CONFIG-014** — La persistence Config n'expose pas de primitive publique d'écriture vers un chemin arbitraire. Un document connu est muté via son contrat source typé, validé complètement puis remplacé atomiquement dans le path résolu par son `file_id`; un échec avant commit conserve l'ancien fichier.
|
||
- **KSP-CONFIG-015** — L'environnement du processus reste read-only. La surface management peut créer/modifier/supprimer uniquement des entrées KSP/KSPB du `.env`; chaque mutation rapporte séparément changement de source persistée, changement effectif courant, shadowing par le process et besoin de reload.
|
||
- **KSP-CONFIG-016** — Les rapports management ordinaires n'exposent que des valeurs sûres/redacted. L'accès en clair à une valeur d'environnement passe par un appel `reveal_*` explicite; l'authentification/autorisation de l'utilisateur final appartient à l'application et cette révélation n'autorise jamais le secret dans les logs/`Debug`/diagnostics génériques.
|
||
- **KSP-CONFIG-017** — Les frontières d'ownership Config sont vérifiées par des audits exécutables du workspace : Core/Logging ne dépendent pas de Config, les crates hors `ksp-config-lib` ne lisent pas directement les variables KSP/KSPB via `std::env::var*`/énumération de l'environnement et ne codent pas en dur les noms physiques des fichiers gérés lorsqu'un contrat Config existe.
|
||
- **KSP-CONFIG-018** — L'inventaire `.env.example` est vérifié automatiquement contre les variables KSP/KSPB concrètes utilisées par les JSON sous `config/` et le code Rust production. Toute clé runtime détectée doit posséder une entrée d'inventaire précédée d'un commentaire explicatif.
|
||
|
||
## 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 réellement deprecated mais toujours identifiable et techniquement préparabile peut rester supportée par son `ProgramExecutionPreparer`, avec statut/warning machine-readable et décision finale laissée à la policy supérieure.
|
||
- **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-WALLET-002** — `.kspwallet` V1 est autonome : le fichier et le password de la capability concernée suffisent au parsing, à la vérification et au déverrouillage ; aucun Config, environnement, pepper global, keychain, réseau, OTP ou ancre de confiance externe n'est requis par le format.
|
||
- **KSP-WALLET-003** — VIEW et OWNER sont des capabilities cryptographiquement indépendantes. VIEW peut lire Pubkey/alias/notes et tourner uniquement son propre password ; il ne peut ni signer, ni exporter le secret, ni administrer les metadata ou l'état OWNER-controlled.
|
||
- **KSP-WALLET-004** — La keypair Solana d'un wallet V1 est immuable après création/import et reste encapsulée dans `ksp-wallet-lib`. La surface publique expose la `Pubkey` via `ksp-core-lib` et une opération OWNER de signature, pas la `solana_keypair::Keypair` brute.
|
||
- **KSP-WALLET-005** — Toute création ou import natif est no-clobber. Un import crée un nouveau `.kspwallet` et ne remplace jamais un wallet natif existant ; les replacements sont réservés aux mutations capability-bound explicitement autorisées.
|
||
- **KSP-WALLET-006** — `ksp-wallet-lib` ne possède aucun répertoire Wallet par défaut et ne lit ni Config ni environnement pour choisir un chemin ; le caller fournit explicitement les chemins de persistence/import/export.
|
||
- **KSP-WALLET-007** — L'état OWNER-controlled V1 est authentifié par une autorité Ed25519 distincte de la keypair Solana. V1 ne prétend pas détecter un remplacement intégral par un autre wallet autonome valide ni un rollback intégral vers une ancienne copie valide ; ces garanties exigeraient une ancre externe hors du format V1.
|
||
|
||
- **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-<name>-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 ne sont pas figés à l'avance sous une chaîne globale `core -> generic materializer -> domain projector`. RAW et CORE peuvent disposer de workers horizontaux propres à leur couche ; à partir de DECODE, les workers/processors sont introduits au besoin avec chaque groupe fonctionnel vertical afin que décodage, matérialisation, projection spécialisée et validation d'exécution évoluent ensemble.
|
||
- **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** — Aucun inventaire global de jobs de replay DECODE/SPECIALIZED n'est figé à l'avance. `RAW -> CORE` peut introduire un job de replay Core lorsque la couche CORE est ouverte ; à partir de DECODE, les jobs de replay sont introduits avec les groupes/capacités verticaux qui en ont réellement besoin, sans imposer des jobs génériques `generic-materialization` / `domain-projection` pour tout Solana.
|
||
- **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.
|
||
|
||
## Persistence
|
||
|
||
- **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 frontières canoniques de données/processing sont `RAW -> CORE -> DECODE -> SPECIALIZED`. Les pipelines RAW et CORE peuvent être développés horizontalement jusqu'à leur acquisition/persistence/replay/worker/app ; à partir de DECODE, KSP progresse par groupes fonctionnels verticaux et ne pré-déclare pas une chaîne globale de crates pipeline pour tous les protocoles.
|
||
- **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-<domain>-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-<domain>-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-<domain>-lib` correspondante ; elle suit la convention `ksp-app-scenario-<domain>-<environment>-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.
|
||
- **KSP-APP-008** — `ksp-app-config-desk` est l'application desktop de référence destinée à établir le gabarit des futures applications Tauri KSP. Les applications suivantes réutilisent ce gabarit sauf justification explicite documentée.
|
||
- **KSP-APP-009** — Le gabarit desktop KSP réutilise/refond les éléments éprouvés de khadhroony-bot3 : organisation SASS/SCSS, dépendances frontend utiles, gabarit visuel initial, icône de base et fichiers de build TypeScript/Vite similaires. Cette référence est auditée et adaptée ; elle n'est pas copiée aveuglément.
|
||
- **KSP-APP-010** — Une application Tauri KSP est un package Rust mixte avec cible bibliothèque et cible binaire de noms distincts. Le binaire reste un launcher mince.
|
||
- **KSP-APP-011** — `main.rs` d'une application Tauri appelle essentiellement la fonction publique `run` de la bibliothèque applicative ; il porte uniquement le bootstrap strictement exécutable, notamment le verrou single-instance et les arguments CLI lorsqu'ils sont nécessaires.
|
||
- **KSP-APP-012** — `lib.rs` d'une application Tauri reste un point de déclaration de modules et de réexport des fonctions/contrats nécessaires ; la logique des fenêtres et opérations n'y est pas accumulée.
|
||
- **KSP-APP-013** — `tauri.rs` possède la fonction `run`, les wrappers `#[tauri::command]` vers les fonctions déclarées dans leurs modules, ainsi que les helpers Tauri/démarrage communs lorsqu'ils sont réellement partagés (`init_rustls`, `open_or_focus_window`, etc.). Les annotations `#[tauri::command]` ne sont pas dispersées dans les modules métier/fenêtre.
|
||
- **KSP-APP-014** — Les modules propres à une fenêtre Tauri utilisent le préfixe `tw_` (`Tauri window`) sauf convention équivalente explicitement décidée avant implémentation. Les helpers réutilisables entre fenêtres sont regroupés dans des modules communs au lieu d'être dupliqués.
|
||
- **KSP-APP-015** — Toutes les applications Tauri KSP réutilisent un splashscreen commun et son lifecycle de démarrage. Les paramètres de temporisation du splashscreen sont configurables via Config/.env, jamais codés en dur dans chaque application.
|
||
- **KSP-APP-016** — Toute variable d'environnement introduite pour le splashscreen ou une autre capacité desktop respecte les namespaces KSP/KSPB et est ajoutée à `.env.example`, avec commentaire, dans le même delta que sa première utilisation runtime conformément à `KSP-CONFIG-005/006`.
|
||
- **KSP-APP-017** — Le `README.md` d'une application Tauri documente le package et ne sert jamais de source Markdown chargée dans une fenêtre de présentation. Lorsqu'une application affiche une présentation embarquée, le contenu UI appartient à un fichier dédié `PRESENTATION.md`; `markdown-it` est la référence de rendu issue de khadhroony-bot3 lorsque ce besoin existe et sa version est auditée avant ajout.
|
||
- **KSP-APP-018** — `PRESENTATION.md` est optionnel : une application monofenêtre qui ne possède aucune vue de présentation n'en crée pas. Lorsqu'il existe, il contient du contenu Markdown statique destiné à l'UI et aucun lien navigable Markdown ou HTML (`[texte](...)`, `<a ...>`, URL brute destinée à la navigation) susceptible de détourner ou casser le comportement des fenêtres Tauri.
|
||
- **KSP-APP-019** — Les applications Tauri KSP utilisent l'écosystème `tracing` à leur frontière desktop via le plugin Tauri de tracing retenu (`tauri-plugin-tracing` ou successeur explicitement validé) et des adapters similaires au modèle éprouvé de khadhroony-bot3. Elles n'utilisent pas `tauri-plugin-log` ni la façade `log`, sauf décision architecturale future explicite qui remplacerait cette règle. L'application ne configure pas directement `tracing-subscriber`/`tracing-appender` : `ksp-logging-lib` reste propriétaire du runtime Logging, le plugin Tauri servant d'adapter d'intégration desktop.
|
||
- **KSP-APP-020** — La première version de `ksp-app-config-desk` n'est clôturable que si l'UI permet de créer, modifier, sauvegarder et sélectionner plusieurs profils Logging, dont au minimum un profil mono-fichier et un profil multi-fichiers avec sorties séparées plus sortie logiciel/console, puis de recharger à chaud la configuration Logging et de constater effectivement le nouveau routage sans redémarrage de l'application.
|
||
- **KSP-APP-021** — `ksp-app-config-desk` est conçu comme un gestionnaire Config extensible : la première version peut fournir un éditeur Logging typé, mais son architecture/navigation/état ne doit pas figer l'application sur `std.logging.json`. De futurs `file_id`, schemas et éditeurs spécialisés doivent pouvoir être ajoutés sans déplacer la propriété des documents, de leur validation ou de leur persistence hors de `ksp-config-lib`.
|
||
- **KSP-APP-022** — La construction d'un `tauri::Builder` KSP reste progressive et lisible : une variable builder est configurée/réassignée par étapes courtes ou helpers ciblés plutôt qu'au moyen d'une longue chaîne monolithique, afin qu'un plugin, state, setup ou groupe de commandes puisse être désactivé sans restructurer l'ensemble du runtime.
|
||
- **KSP-APP-023** — Le gabarit Tauri KSP place les sources web sous `frontend/`, les modules TypeScript sous `frontend/ts/`, les styles SCSS sous `frontend/sass/` et les bindings TS-RS générés sous `frontend/ts/bindings/`. Les bindings et artefacts générés ne sont pas versionnés ; les DTO Rust applicatifs restent la source des contrats TS-RS.
|
||
- **KSP-APP-024** — Chaque application desk Tauri KSP possède un couple de ports Vite/HMR exclusif. L'allocation commence à `1430/1431` pour `ksp-app-config-desk` puis progresse par paires (`1432/1433`, `1434/1435`, etc.). Le port Vite est strict afin qu'une collision échoue explicitement au lieu de sélectionner silencieusement un autre port.
|
||
- **KSP-APP-025** — Dans `package.json`, les bibliothèques consommées par le bundle applicatif appartiennent à `dependencies`; les outils de build/développement et paquets `@types/*` appartiennent à `devDependencies`. npm est utilisé directement uniquement pour installer ou mettre à jour ces dépendances. Le cycle normal de développement/build passe par Tauri, qui déclenche les scripts npm configurés via `beforeDevCommand`/`beforeBuildCommand`; les lockfiles frontend restent non versionnés.
|
||
- **KSP-APP-026** — Dans un workspace Rust multi-app, `-c/--config` de Tauri est un overlay de configuration et ne sélectionne pas la crate applicative. Les commandes Tauri sont donc exécutées depuis le répertoire de la crate ciblée : `(cd crates/<app> && cargo tauri dev)` ou `(cd crates/<app> && cargo tauri build)`. Le lancement depuis la racine avec `-c crates/<app>/tauri.conf.json` est interdit comme sélecteur d’application.
|
||
- **KSP-APP-027** — Les applications Tauri KSP instrumentent systématiquement le comportement frontend via le bridge Logging commun : actions utilisateur et transitions d’état significatives en `debug`, événements techniques fins, rendu/remplacement de sections et étapes fréquentes en `trace`. Les chargements/rafraîchissements de données sont tracés au début et à la fin sans journaliser les payloads sensibles. Cette instrumentation doit permettre de reconstruire le déroulement frontend sans dépendre uniquement de l’état visuel.
|
||
- **KSP-APP-028** — Le header d’une application desk ne répète pas inutilement l’identité déjà portée par son logo : il affiche le nom ou l’abréviation fonctionnelle de l’application, puis un tiret cadratin `—` et le titre de la vue active. Les commandes principales peu nombreuses peuvent utiliser des tabs/pills alignées à droite ; lorsque leur nombre nuit à la lisibilité ou à l’espace disponible, un dropdown est préféré.
|
||
- **KSP-APP-029** — En développement workspace, Tauri est lancé depuis `crates/<app>` conformément à `KSP-APP-026`. Le processus Rust peut ensuite normaliser son current working directory vers la racine du workspace avant le bootstrap Config lorsque les chemins de développement KSP y sont enracinés. Cette adaptation ne lit ni ne parse directement `config/`, `.env` ou les variables `KSP_*`/`KSPB_*` : `ksp-config-lib` reste seul propriétaire de ces ressources. Le runtime distribué ne doit pas dépendre d’un checkout source.
|
||
- **KSP-APP-030** — Lorsqu’une application KSP persiste des logs applicatifs, chaque lancement doit disposer d’un fichier propre et non partagé avec un lancement précédent. Le nom encode au minimum l’identité applicative et un horodatage de démarrage, par exemple `app-name.YYYYMMDD-HHMMSS.log` / `.json` / `.jsonl` selon le format du sink ; une rotation quotidienne ne doit pas fusionner plusieurs exécutions applicatives dans le même fichier.
|
||
- **KSP-APP-031** — Le niveau de logging spécifique à une application/crate peut être élevé temporairement à `debug` ou `trace` pendant une phase de développement ou correction. Avant la clôture/release de cette application/crate, son niveau de référence est ramené à `info` ou `warn` selon le besoin opératoire ; il n’est remonté que lorsqu’un développement/correctif est explicitement rouvert.
|
||
- **KSP-APP-032** — Les interfaces desk KSP n’utilisent pas les dialogues bloquants natifs du navigateur (`window.alert`, `window.confirm`, `window.prompt`) pour les interactions applicatives normales. Les confirmations destructives ou privilégiées utilisent un modal Bootstrap intégré à l’UI, instrumenté par le bridge Logging ; toute exception doit être explicitement justifiée et documentée.
|
||
- **KSP-APP-033** — Un test d’une application ou d’un manager qui peut modifier un document Config du workspace ne traite jamais les valeurs courantes de ce document comme une fixture immuable. Les tests de valeurs exactes utilisent une fixture isolée ; les tests qui lisent la Config workspace vérifient uniquement des invariants, la validité et la cohérence source → résolution → runtime afin de rester valides après une édition légitime par Config Desk.
|
||
- **KSP-APP-034** — Pour une application Tauri KSP, npm n’est jamais invoqué directement pour lancer les scripts applicatifs de développement, contrôle ou build. Les seules commandes npm directes servent à installer ou mettre à jour les dépendances déclarées. Le cycle applicatif est crate-local : `(cd crates/<app> && cargo tauri dev)` et `(cd crates/<app> && cargo tauri build)` ; Tauri déclenche lui-même les hooks `beforeDevCommand` / `beforeBuildCommand`, dont le `cwd` reste explicitement la crate. Dans une validation finale, le `cargo tauri build` crate-local est exécuté **en toute dernière opération**, après fmt/audit/check/clippy, tests et parcours fonctionnel.
|
||
|
||
## 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`.
|
||
- **KSP-REL-009** — Après toute modification d'un fichier Rust, la tranche concernée exécute avant livraison au minimum `cargo fmt --all`, `python3 scripts/audit_rust_workspace_rules.py`, `cargo check --workspace` et `cargo clippy --workspace --all-targets`, dans cet ordre. L'audit structurel complète rustfmt/Clippy et ne peut être ignoré parce que la compilation est verte. Une commande non exécutée n'est jamais déclarée réussie.
|
||
- **KSP-REL-010** — Pendant le développement courant d'une crate, les tests Rust privilégient la portée ciblée `cargo test -p <crate>` et, si utile, ses tests d'intégration nommés. `cargo test --workspace` est conservé pour l'ouverture ou la fermeture d'une session/version et pour les validations globales explicitement justifiées.
|
||
- **KSP-REL-011** — Les validations d'une crate incluent les audits `cargo tree` pertinents pour son graphe réel : arbre normal, doublons et features lorsque ces vues apportent une information utile. Les crates fondamentales/complétées conservent leurs canaries de dépendances.
|
||
- **KSP-REL-012** — Toute crate ou composant KSP considéré comme complété possède un `README.md` descriptif durable avant clôture de sa release.
|
||
- **KSP-REL-013** — Toute bibliothèque KSP considérée comme complétée possède un `USAGE.md` durable, sans notes de version, présentant sa surface publique et un exemple d'utilisation pour chaque API publique destinée à être consommée directement ; plusieurs APIs étroitement liées peuvent partager un même exemple lorsque leur usage réel est composé. Les changements de release appartiennent au changelog/delta, pas au guide d'utilisation.
|
||
- **KSP-REL-014** — Toute application/binaire Tauri KSP considéré comme complété possède un `USAGE.md` durable décrivant ses fenêtres, leurs objectifs, leurs flux principaux et leur utilisation opérateur.
|
||
- **KSP-REL-015** — Une application Tauri complétée ne crée `PRESENTATION.md` que si elle possède réellement une vue de présentation embarquée ; dans ce cas le fichier est finalisé comme contenu UI sans liens navigables et reste distinct du `README.md` et du `USAGE.md`.
|
||
- **KSP-REL-016** — Une prerelease vise environ 15 à 20 minutes de travail effectif. Le `pre.001` dimensionne aussi la release concrète entière : une release doit pouvoir être ouverte, développée, validée et clôturée dans une seule session de chat. Si cette clôture paraît incertaine, la release est scindée avant l'implémentation fonctionnelle lourde ; une version volontairement répartie sur plusieurs sessions est interdite.
|
||
- **KSP-TRANSPORT-006** — Pour une surface de transport explicitement ciblée, KSP inventorie et implémente toutes les méthodes/opérations exposées par la documentation normative retenue, sauf impossibilité technique explicitement documentée. L'inventaire couvre aussi les sections officielles séparées `deprecated`/`obsolete` et `unstable`/`experimental` lorsqu'elles existent. Les opérations deprecated/obsolete encore réellement fonctionnelles et unstable/experimental restent utilisables mais émettent un `warn` via `ksp-logging-lib` à chaque utilisation concernée ; leur statut est décrit par une metadata centralisée et non par des warnings dispersés.
|
||
- **KSP-TRANSPORT-007** — La complétude d'un wrapper de transport standard couvre toute la surface sémantique de requête auditée : paramètres, options de configuration, variantes/overloads courants, formes legacy encore supportées et contraintes déterministes connues. Les formes de réponse pertinentes sont conservées losslessly, y compris les variantes, `null` et omissions significatives. KSP peut canonicaliser des syntaxes strictement équivalentes et conserver des sous-arbres wire riches via `serde_json::Value` tant qu'aucune information n'est perdue ; toute limitation volontaire d'une possibilité normative/runtime supportée doit être explicitement justifiée et documentée.
|
||
- **KSP-FLOW-001** — La progression durable canonique est `RAW -> CORE -> DECODE -> SPECIALIZED`. RAW et CORE ne nécessitent aucun decoder Program ; le passage RAW -> CORE reste une normalisation générique de la blockchain Solana. À partir de DECODE, KSP progresse verticalement par groupe fonctionnel à travers wire, décodage, matérialisation, projection spécialisée si utile, préparation d'exécution, policy, exécution et scénarios de validation.
|
||
- **KSP-FLOW-002** — Un programme ou composant satellite nécessaire à la compréhension, la matérialisation ou l'exécution correcte d'un protocole appartient au groupe de ce protocole. Il n'est pas reporté artificiellement dans une catégorie `trading-adjacent`.
|