6.9 KiB
Contrat de tracing par crate et composant
Objectif
Chaque événement est émis par la crate qui prend réellement la décision. kb_app_demo journalise les frontières Tauri, les actions utilisateur, l’état des fenêtres et les résumés d’orchestration ; il ne recopie pas les décisions internes du RPC, du pipeline, du store, d’un décodeur, d’un matérialiseur ou d’un exécuteur.
Classification des crates
Une crate est opérationnelle lorsqu’elle réalise au moins une des actions suivantes :
- I/O réseau ou base de données ;
- orchestration concurrente, retry, pacing ou annulation ;
- décodage ou matérialisation ;
- construction ou simulation d’un plan d’exécution ;
- décision runtime mutable ayant un effet observable.
Une crate passive contient uniquement des types, contrats, DTO, traits sans implémentation, registres ou constantes. Elle ne dépend pas de tracing. kb_config reste une exception de bootstrap : son chargement et sa validation précèdent l’installation du subscriber.
Cible canonique
Toute crate opérationnelle hors kb-lib qui déclare tracing.workspace = true doit :
- posséder
src/constants.rs; - définir exactement une constante
pub(crate) const TRACING_TARGET; - utiliser comme valeur le nom exact du package Cargo ;
- réexporter la constante depuis sa façade puis appeler les macros avec
target: crate::TRACING_TARGET; - déplacer la granularité interne dans des champs structurés.
kb-lib constitue une exception architecturale volontaire : chaque décodeur, matérialiseur ou exécuteur opérationnel possède son propre constants.rs et un target hiérarchique kb-lib.<famille>.<surface>. La façade de kb-lib réexporte chaque target sous un alias interne préfixé afin que plusieurs composants puissent coexister sans collision.
Exemple :
tracing::error!(
target: crate::SOLANA_CORE_TRACING_TARGET,
action = "decoder_outcome_failure",
campaign_id = %campaign_id,
signature = %input.signature,
instruction_path = %input.instruction_path,
program_id = %input.program_id,
processor_name = %identity.name,
processor_version = %identity.version,
status = ?result.status,
diagnostics = ?result.diagnostics,
"contextual instruction was not decoded successfully"
);
Les targets khbot.* et les targets de fenêtre ne sont plus utilisés par les composants opérationnels migrés. Les identifiants frontend historiques restent acceptés comme valeurs du champ frontend_target, mais l’événement Rust est émis sous le target canonique de l’application.
Crates actuellement routées
Les targets déjà migrés vers les noms canoniques bot3 sont :
kb-lib.decoder.solana.core
kb-lib.decoder.spl.memo
kb-logging
kb-store
L’audit audit_khadhroony_workspace_rules.py vérifie les targets de crates et les targets hiérarchiques de kb-lib. Il interdit également les faux usages let _target et impose que chaque macro de kb-lib utilise un alias réexporté par la façade.
Les routes sont filtrées au niveau de leur writer plutôt que par un Filtered layer distinct. Un seul filtre d’admission agrégé empêche en amont le formatage des événements refusés par toutes les routes. Cette architecture préserve toutes les sorties globales et par crate au-delà de la limite interne de 64 identifiants de filtres de tracing-subscriber. Le test more_than_64_routes_compose_without_filtered_layer_ids protège explicitement ce contrat.
Granularité et corrélation
Le target identifie la crate. Les champs décrivent l’action et le contexte :
action
stage
window
campaign_id
capture_session_id
signature
slot
instruction_path
program_id
processor_name
processor_version
materializer_name
materializer_version
input_key
input_hash
status
decision
error_code
Les spans de campagne et d’input utilisent eux aussi le target canonique kb_pipeline. Les événements des autres crates conservent leur propre target et reprennent les identifiants de corrélation utiles dans leurs champs.
Politique des erreurs de décodage et de matérialisation
Un événement error est obligatoire pour :
- un input sélectionné sans décodeur compatible ;
- un résultat de décodeur
failed; - un résultat de décodeur
unsupportedaprès dispatch vers une surface déclarée compatible ; - un résultat de décodeur invalide au regard du contrat API ;
- un résultat de matérialiseur
failed; - une erreur de persistance decode, couverture, ledger ou matérialisation ;
- une campagne qui termine avec
unmatched > 0oufailed_inputs > 0.
L’événement doit permettre de retrouver rapidement l’input et la cause. Il conserve, lorsque disponibles, la campagne, la signature, le slot, le chemin d’instruction, le program ID, l’identité et la version du processor, la clé/hash d’input, le statut et les diagnostics structurés.
Les cas suivants ne sont pas des erreurs logicielles :
- transaction Solana échouée mais payload correctement décodé ;
- observation non commitée conformément au statut on-chain ;
- matérialisation
refusedpar la politique de transaction ; - entrée volontairement
ignoredavec justification ; - annulation coopérative demandée par l’opérateur.
Ils sont journalisés en debug, info ou warn selon leur impact.
Responsabilité
kb-rpc: sélection d’endpoint, requêtes, réponses bornées, retry, rate limit et transport.- composants
kb-lib.executor: assemblage du message, contrôle du contrat de signataires, liaison de simulation et signature transactionnelle. kb-store: transactions SQL, commit/rollback, compteurs et erreurs de persistance.kb-pipeline: sélection, dispatch, concurrence, annulation, backfill et agrégation.- décodeur : reconnaissance, validation du format, décision et diagnostic borné.
- matérialiseur : applicabilité exacte, politique de transaction et sorties produites.
- exécuteur : support, construction, simulation et garde-fous.
- application : invocation Tauri, fenêtre, progression utilisateur et résumé final.
Données interdites
Ne jamais journaliser :
- clé privée, seed phrase ou transaction à signer ;
- DSN ou URL contenant un secret non masqué ;
- payload brut complet ou réponse RPC volumineuse ;
- donnée dynamique non bornée.
Conserver à la place la taille, un préfixe borné et un SHA-256 lorsque l’audit du payload est nécessaire.
Évolution
L’ajout ou la suppression de tracing.workspace = true impose dans le même delta :
- la constante canonique ou sa suppression ;
- les événements réels de la crate ;
- la mise à jour de
config/example.config.json; - la mise à jour des tests de contrat ;
- la mise à jour de la liste ci-dessus.
Pour un composant de kb-lib, les mêmes obligations s’appliquent au target hiérarchique, à son alias de façade et à ses routes dédiées.