# Convention canonique des identités runtime et des codes d’opération ## 1. Objet Ce document définit les chaînes stables utilisées par `khadhroony-bot3` dans le code, les plans d’exécution, les événements décodés, les sorties matérialisées, les journaux et PostgreSQL. Ces chaînes sont des contrats de données. Elles ne doivent pas être renommées localement, improvisées dans un test ou dérivées du nom d’une ancienne crate. Toute nouvelle surface doit être ajoutée à la matrice `test-fixtures/contract-matrices/OPERATION_NAMING_MATRIX.json` avant son premier remplissage persistant. ## 2. Principe général Les valeurs persistées utilisent une hiérarchie en segments séparés par un point : ```text .[.][.] ``` Chaque segment utilise `snake_case`. Un underscore reste autorisé à l’intérieur d’un concept indivisible, par exemple `token_2022`, `compute_budget` ou `associated_token_account`. Il ne doit pas remplacer un séparateur hiérarchique. Correct : ```text solana.core.system.transfer spl.memo.v4.add_memo spl.token_2022.transfer_checked spl.associated_token_account.create_idempotent metadata.metaplex_token_metadata.create_metadata_account_v3 ``` Interdit : ```text solana_core.system.transfer spl_memo_v4.add_memo spl_token_2022.transfer_checked spl_associated_token_account.create_idempotent metadata_metaplex_token_metadata.create_metadata_account_v3 ``` ## 2.1 Frontière avec les codes de registre La notation par points s’applique aux identités runtime, processeurs, surfaces, opérations et événements persistés. Elle ne s’applique pas aux codes techniques du registre `kb-program-ids`, qui restent des identifiants Rust/registre en `lower_snake_case` afin de préserver leur ordre lexical, leur compatibilité et leur rôle de clé interne. Exemples de codes de registre : ```text metadata_metaplex_token_metadata spl_memo_v4 spl_token spl_token_2022 ``` Le même programme peut donc avoir : ```text registry code : spl_token_2022 processor_name : spl.token_2022 surface_code : spl.token_2022 ``` ## 3. Catégories de noms ### 3.1 Identité runtime d’un composant Format : ```text kb-lib...[.] ``` Exemples : ```text kb-lib.decoder.solana.core kb-lib.executor.solana.core kb-lib.decoder.spl.memo kb-lib.executor.spl.token_2022 kb-lib.materializer.transaction.annotations ``` Cette identité désigne le composant logiciel, pas une opération on-chain. ### 3.2 `processor_name` Format : ```text .[.] ``` Exemples : ```text solana.core spl.memo spl.token spl.token_2022 spl.associated_token_account spl.elgamal_registry metadata.metaplex_token_metadata materializer.transaction.annotations materializer.token.accounts materializer.risk ``` `processor_name` doit rester stable entre les campagnes et ne doit pas inclure une version. La version est stockée séparément dans `processor_version`. ### 3.3 `surface_code` Format : ```text .[.] ``` La surface représente la frontière on-chain effectivement observée. Exemples : ```text solana.core.system solana.core.compute_budget solana.core.loader_v4 spl.memo.v1 spl.memo.v3 spl.memo.v4 spl.token spl.token_2022 spl.token_2022.confidential_transfer spl.associated_token_account metadata.metaplex_token_metadata ``` Une génération est ajoutée seulement lorsqu’elle change l’identité du programme ou le contrat observé. ### 3.4 `operation_code` Format : ```text . ``` `operation_code` décrit une intention constructible par un exécuteur. Il peut être plus générique que l’événement observé lorsque l’exécuteur cible une seule génération actuelle. Exemples : ```text solana.core.system.transfer spl.memo.add_memo spl.token.transfer_checked spl.token_2022.close_account spl.associated_token_account.create ``` Pour Memo, l’exécuteur ne construit que Memo v4, mais l’intention reste `spl.memo.add_memo`. Le Program ID du plan fixe la génération réellement construite. ### 3.5 `event_code` Format : ```text . ``` `event_code` décrit ce qui a été observé et conserve la génération lorsque celle-ci est significative. Exemples : ```text spl.memo.v1.add_memo spl.memo.v3.add_memo spl.memo.v4.add_memo spl.token.transfer_checked spl.token_2022.close_account solana.core.system.transfer ``` ### 3.6 `protocol_code` `protocol_code` identifie le protocole fonctionnel sans opération : ```text solana.core spl.memo spl.token spl.token_2022 spl.associated_token_account spl.elgamal_registry metadata.metaplex_token_metadata ``` Il ne doit pas réintroduire les anciennes formes `solana_native`, `spl_token` ou `spl_memo`. ## 4. Correspondance entre Rust et les valeurs persistées Les symboles Rust suivent les règles Rust habituelles, tandis que leurs valeurs suivent cette convention : ```rust pub const EX_SPL_TOKEN_2022_TRANSFER_CHECKED_OPERATION: &str = "spl.token_2022.transfer_checked"; ``` - symbole Rust : `SCREAMING_SNAKE_CASE` ; - module Rust : `snake_case` ; - valeur persistée : segments hiérarchiques séparés par `.` ; - type Rust : `PascalCase`, par exemple `Token2022`. ## 5. Stabilité et migrations Ces valeurs peuvent participer à : - des clés de ledger ; - des contraintes d’unicité ; - des clés d’idempotence ; - des événements Decode ; - des observations de couverture ; - des sorties matérialisées ; - des filtres SQL et frontend ; - des preuves de scénarios Devnet. Un renommage après remplissage d’une base est donc une migration de données. Avant production, toute modification exige : 1. une mise à jour coordonnée du code, des matrices et des règles ; 2. une décision explicite entre migration SQL et reconstruction des tables dérivées ; 3. une validation de l’idempotence ; 4. une vérification des filtres et APIs ; 5. une nouvelle preuve runtime. Pendant la phase actuelle de développement, les bases Devnet et recherche peuvent être recréées depuis les raws. ## 6. Matrice normative La source machine-readable est : ```text test-fixtures/contract-matrices/OPERATION_NAMING_MATRIX.json ``` Chaque entrée documente au minimum : - `programId` ; - `processorName` ; - `surfaceCode` ; - `operationCode` ; - `eventCode` ; - `decoderName` ; - `executorName` ; - `status` ; - `source`. Une surface `decode_only` peut avoir `operationCode` et `executorName` à `null`. ## 7. Règles d’ajout d’une nouvelle opération Avant de fusionner une nouvelle opération : 1. choisir son domaine et sa famille ; 2. identifier le Program ID canonique dans `kb-program-ids` ; 3. définir `processor_name` et `surface_code` ; 4. définir séparément `operation_code` et `event_code` ; 5. ajouter les constantes Rust ; 6. ajouter ou mettre à jour la matrice normative ; 7. ajouter les tests de cohérence entre constantes et matrice ; 8. vérifier l’impact PostgreSQL avant tout backfill ou replay durable.