From d6bd91c305c6460f3e8a37718542c1c3af309149 Mon Sep 17 00:00:00 2001 From: SinuS Von SifriduS Date: Fri, 31 Jul 2026 15:44:46 +0200 Subject: [PATCH] v0.1.0-pre.070 --- docs/rules/CRATE_DOCUMENTATION_RULES.md | 1 + docs/templates/CRATE_USAGE_TEMPLATE.md | 5 +- kb-config/CHANGELOG.md | 6 +- kb-config/USAGE.md | 45 +++++- kb-lib/CHANGELOG.md | 6 +- kb-lib/USAGE.md | 122 +++++++++++++++- kb-logging/CHANGELOG.md | 6 +- kb-logging/USAGE.md | 87 +++++++++++- kb-onchain-transport/CHANGELOG.md | 19 +++ kb-onchain-transport/README.md | 37 +++++ kb-onchain-transport/TODO.md | 11 ++ kb-onchain-transport/USAGE.md | 147 +++++++++++++++++++ kb-pipeline-demo-scenarios/CHANGELOG.md | 20 +++ kb-pipeline-demo-scenarios/README.md | 35 +++-- kb-pipeline-demo-scenarios/TODO.md | 13 ++ kb-pipeline-demo-scenarios/USAGE.md | 181 ++++++++++++++++++++++++ kb-pipeline/CHANGELOG.md | 20 +++ kb-pipeline/README.md | 36 +++++ kb-pipeline/TODO.md | 12 ++ kb-pipeline/USAGE.md | 180 +++++++++++++++++++++++ kb-store/CHANGELOG.md | 6 +- kb-store/USAGE.md | 95 +++++++++++-- 22 files changed, 1055 insertions(+), 35 deletions(-) create mode 100644 kb-onchain-transport/CHANGELOG.md create mode 100644 kb-onchain-transport/README.md create mode 100644 kb-onchain-transport/TODO.md create mode 100644 kb-onchain-transport/USAGE.md create mode 100644 kb-pipeline-demo-scenarios/CHANGELOG.md create mode 100644 kb-pipeline-demo-scenarios/TODO.md create mode 100644 kb-pipeline-demo-scenarios/USAGE.md create mode 100644 kb-pipeline/CHANGELOG.md create mode 100644 kb-pipeline/README.md create mode 100644 kb-pipeline/TODO.md create mode 100644 kb-pipeline/USAGE.md diff --git a/docs/rules/CRATE_DOCUMENTATION_RULES.md b/docs/rules/CRATE_DOCUMENTATION_RULES.md index 5a10f0f..f9fe43d 100644 --- a/docs/rules/CRATE_DOCUMENTATION_RULES.md +++ b/docs/rules/CRATE_DOCUMENTATION_RULES.md @@ -117,6 +117,7 @@ Les travaux planifiés pour supprimer une limite temporaire appartiennent au TOD Les exemples Rust doivent respecter les règles du workspace, y compris les conventions de propagation d’erreurs. Chaque API publique significative doit disposer d’au moins un exemple ou être couverte par un exemple de scénario explicitement identifié. Les APIs triviales ou regroupées peuvent partager un exemple lorsqu’il démontre réellement leur usage. +Un `USAGE.md` doit fournir plusieurs exemples lorsque la crate expose plusieurs familles d’API ou plusieurs étapes d’un parcours public. Un unique exemple global n’est suffisant que pour une surface publique réellement minimale. Les exemples doivent couvrir en priorité la construction des requêtes, leur validation, l’exécution principale, l’interprétation du résultat et les invariants opérateur pertinents. ### 4.4 Crates sans API bibliothèque publique diff --git a/docs/templates/CRATE_USAGE_TEMPLATE.md b/docs/templates/CRATE_USAGE_TEMPLATE.md index 1aedabd..46e6ce4 100644 --- a/docs/templates/CRATE_USAGE_TEMPLATE.md +++ b/docs/templates/CRATE_USAGE_TEMPLATE.md @@ -27,7 +27,10 @@ Pour chaque API ou groupe cohérent : - valeur retournée ; - erreurs ; - invariants ; -- exemple. +- exemple de construction ou configuration ; +- exemple de validation ; +- exemple d’exécution ou d’appel principal ; +- exemple d’interprétation du résultat lorsque pertinent. ## Types publics importants diff --git a/kb-config/CHANGELOG.md b/kb-config/CHANGELOG.md index e2b4d0a..1ca3de0 100644 --- a/kb-config/CHANGELOG.md +++ b/kb-config/CHANGELOG.md @@ -1,8 +1,12 @@ - + # CHANGELOG — kb-config +## 0.1.0-pre.070 + +- enrichissement de `USAGE.md` avec plusieurs exemples couvrant les familles d’API publiques significatives. + ## 0.1.0-pre.069 ### Documentation diff --git a/kb-config/USAGE.md b/kb-config/USAGE.md index 08a407b..a0fb7ae 100644 --- a/kb-config/USAGE.md +++ b/kb-config/USAGE.md @@ -1,5 +1,5 @@ - + # Utilisation de kb-config @@ -29,10 +29,25 @@ let report = match kb_config::load_workspace_environment(std::path::Path::new(". Ok(value) => value, Err(error) => return Err(error), }; + +for path in report.loaded_files { + println!("environment file: {}", path.display()); +} ``` `EnvironmentLoadReport` indique les fichiers chargés. Les placeholders non résolus sans fallback restent visibles afin que la validation ou le consommateur puisse les signaler explicitement. +## Résolution explicite des placeholders + +```rust +let raw = r#"{"databaseUrl":"${KB_DATABASE_URL:-postgres://localhost/kb}"}"#; +let resolved = kb_config::resolve_environment_placeholders(raw); + +assert!(resolved.contains("databaseUrl")); +``` + +Cette API est utile pour un outil de diagnostic qui veut afficher le JSON résolu avant parsing. + ## Validation et parsing ```rust @@ -61,6 +76,14 @@ let pretty = match kb_config::serialize_config_json_pretty(&config) { Ok(value) => value, Err(error) => return Err(error), }; + +let write_result = std::fs::write("config/generated.config.json", pretty); +if let Err(error) = write_result { + return Err(kb_core::Error::new( + "config_write_failed", + format!("cannot write generated configuration: {error}"), + )); +} ``` La configuration est validée avant sérialisation. @@ -73,10 +96,30 @@ let schema_value = match kb_config::config_json_schema_value() { Ok(value) => value, Err(error) => return Err(error), }; + +let property_count = schema_value + .get("properties") + .and_then(serde_json::Value::as_object) + .map_or(0, serde_json::Map::len); + +println!("embedded schema bytes={}, properties={property_count}", schema_text.len()); ``` Le schéma actif est aussi disponible sous [`../config/schema.config.json`](../config/schema.config.json). Le fichier [`../config/example.config.json`](../config/example.config.json) fournit un exemple utilisateur complet. +## Sélection du profil actif + +```rust +let profile = match kb_config::active_profile(&config) { + Ok(value) => value, + Err(error) => return Err(error), +}; + +println!("active profile: {}", profile.name); +println!("http endpoints: {}", profile.solana.http_endpoints.len()); +println!("websocket endpoints: {}", profile.solana.ws_endpoints.len()); +``` + ## Types publics importants - `AppConfig`, `ProfileConfig`, `AppSectionConfig` ; diff --git a/kb-lib/CHANGELOG.md b/kb-lib/CHANGELOG.md index 0bc6a2c..6a1282c 100644 --- a/kb-lib/CHANGELOG.md +++ b/kb-lib/CHANGELOG.md @@ -1,8 +1,12 @@ - + # CHANGELOG — kb-lib +## 0.1.0-pre.070 + +- enrichissement de `USAGE.md` avec plusieurs exemples couvrant les familles d’API publiques significatives. + ## 0.1.0-pre.069 ### Documentation diff --git a/kb-lib/USAGE.md b/kb-lib/USAGE.md index 400256e..fe291fa 100644 --- a/kb-lib/USAGE.md +++ b/kb-lib/USAGE.md @@ -1,5 +1,5 @@ - + # Utilisation de kb-lib @@ -30,6 +30,19 @@ let result = DcApiInstructionDecoder::decode(&decoder, &input); Le consommateur doit vérifier le résultat typé et ses diagnostics. Une transaction échouée peut produire une intention structurée, mais pas une mutation committée. +```rust +let execution = DcApiInstructionDecoder::decode(&decoder, &input); + +match execution { + Ok(result) => { + println!("status={:?}", result.status); + println!("observations={}", result.observations.len()); + println!("diagnostics={}", result.diagnostics.len()); + }, + Err(error) => return Err(error), +} +``` + Décodeurs fonctionnels principaux : - `DcSolanaCoreDecoder` ; @@ -45,13 +58,26 @@ Les types réservés `Dc*Decoder` ne doivent pas être interprétés comme des d ## Lecture d’états Token-2022 et ElGamal ```rust -let state = kb_lib::decoder_spl_token_2022_parse_token_2022_state( - &program_id, +let state = match kb_lib::decoder_spl_token_2022_parse_token_2022_state( + kb_lib::DcToken2022StateKind::Account, &account_data, -); -let registry = kb_lib::decoder_spl_elgamal_registry_parse_elgamal_registry_state( +) { + Ok(value) => value, + Err(error) => return Err(error), +}; + +println!("parsed token-2022 state: {state:#?}"); +``` + +```rust +let registry = match kb_lib::decoder_spl_elgamal_registry_parse_elgamal_registry_state( &account_data, -); +) { + Ok(value) => value, + Err(error) => return Err(error), +}; + +println!("parsed registry state: {registry:#?}"); ``` Les parseurs vérifient les bornes et formats qu’ils annoncent. Ils ne reconstruisent pas un état historique depuis un RPC courant. @@ -60,6 +86,37 @@ Les parseurs vérifient les bornes et formats qu’ils annoncent. Ils ne reconst Les fonctions `decoder_metadata_metaplex_token_metadata_decode_*_account` décodent les familles de comptes publiques prises en charge. Le consommateur doit fournir les données et le contexte attendus par la signature exacte de la fonction concernée. Les parseurs conservent les variantes historiques et refusent les longueurs, propriétaires ou suffixes incompatibles. +```rust +let metadata = match kb_lib::decoder_metadata_metaplex_token_metadata_decode_metadata_account( + metadata_account.as_str(), + metadata_owner.as_str(), + &account_data, +) { + Ok(value) => value, + Err(error) => return Err(error), +}; + +println!("metadata mint={}", metadata.mint); +println!("metadata name={}", metadata.name); +``` + +```rust +let edition = match kb_lib::decoder_metadata_metaplex_token_metadata_decode_edition_account( + edition_account.as_str(), + metadata_owner.as_str(), + mint.as_str(), + &account_data, +) { + Ok(value) => value, + Err(error) => return Err(error), +}; + +println!("edition kind={:?}", edition.kind); +println!("edition parent={:?}", edition.parent); +``` + +Les signatures exactes doivent être vérifiées lors de l’utilisation : certaines familles exigent un contexte ou une identité canonique supplémentaire. + ## Exécution typée `ExApiTypedInstructionExecutor` produit un `ExApiPreparedExecutionPlan` à partir d’une intention et d’une politique explicites. Les exécuteurs concrets incluent notamment : @@ -84,16 +141,58 @@ let plan = ExApiTypedInstructionExecutor::build_prepared_plan( Le plan ne signe et n’envoie rien. La simulation, la confirmation opérateur, la soumission et la confirmation réseau appartiennent aux couches d’orchestration et de transport. +```rust +let plan = match ExApiTypedInstructionExecutor::build_prepared_plan( + &executor, + &intent, +) { + Ok(value) => value, + Err(error) => return Err(error), +}; + +println!("instructions={}", plan.instructions.len()); +println!("required_signers={}", plan.required_signers.len()); +``` + Memo v1 et v3 restent non exécutables. Memo v4 est la seule génération exécutable. ## Sécurité Les types `ExSafetyChecker`, `ExSafetyDecision`, `ExSafetyEvaluation` et `ExSafetyViolation` permettent d’évaluer un plan avant son utilisation. Une décision conservatrice doit être respectée par le consommateur ; elle ne doit pas être contournée par l’application. +```rust +let evaluation = match checker.evaluate_prepared_plan(&plan) { + Ok(value) => value, + Err(error) => return Err(error), +}; + +match evaluation.decision { + kb_lib::ExSafetyDecision::Allow => { + println!("execution plan accepted"); + }, + kb_lib::ExSafetyDecision::Deny => { + for violation in evaluation.violations { + eprintln!("safety violation: {violation:#?}"); + } + }, +} +``` + ## Matérialisation `MtApiEventMaterializer` définit le contrat public de matérialisation. Les résultats `MtApiMaterializerExecutionResult` contiennent les sorties et diagnostics sans dépendre d’un backend de stockage. +```rust +let result = kb_lib::MtApiEventMaterializer::materialize( + &materializer, + &decoded_observation, +); + +println!("status={:?}", result.status); +println!("outputs={}", result.outputs.len()); +println!("diagnostics={}", result.diagnostics.len()); +``` + Les fonctions stateful publiques comprennent notamment : - `materializer_admin_materialize_token_2022_state_snapshots` ; @@ -107,6 +206,17 @@ Les fonctions stateful publiques comprennent notamment : `MdCoreInstructionReplayInput` représente une instruction extraite avec son contexte transactionnel. Il constitue la frontière entre l’extraction Core, le pipeline de replay et les décodeurs. +```rust +let recognition = DcApiInstructionDecoder::recognize(&decoder, &replay_input); + +if recognition.compatible { + let decoded = DcApiInstructionDecoder::decode(&decoder, &replay_input); + if let Err(error) = decoded { + return Err(error); + } +} +``` + ## Tests et matrices utiles Les tests unitaires du décodeur Metaplex et du décodeur Solana Core chargent directement certaines matrices de [`../test-fixtures/contract-matrices/`](../test-fixtures/contract-matrices/). Ils vérifient notamment l’égalité entre les entrées compilées et les contrats JSON, les discriminants, les bornes et les comportements historiques. diff --git a/kb-logging/CHANGELOG.md b/kb-logging/CHANGELOG.md index af3488a..5bd404c 100644 --- a/kb-logging/CHANGELOG.md +++ b/kb-logging/CHANGELOG.md @@ -1,8 +1,12 @@ - + # CHANGELOG — kb-logging +## 0.1.0-pre.070 + +- enrichissement de `USAGE.md` avec plusieurs exemples couvrant les familles d’API publiques significatives. + ## 0.1.0-pre.069 ### Documentation diff --git a/kb-logging/USAGE.md b/kb-logging/USAGE.md index 1e22019..dc5a7f0 100644 --- a/kb-logging/USAGE.md +++ b/kb-logging/USAGE.md @@ -1,5 +1,5 @@ - + # Utilisation de kb-logging @@ -37,14 +37,97 @@ assert_eq!(guard.guard_count(), 1); assert_eq!(guard.route_names(), &["console".to_string()]); ``` -## Routes fichier +## Route fichier JSON + +```rust +let file_route = kb_logging::LogTargetConfig { + name: "operations-json".to_string(), + enabled: true, + sink: "file".to_string(), + level: "debug".to_string(), + path: "logs/operations.jsonl".to_string(), + rotation: "daily".to_string(), + format: "json".to_string(), + ansi: false, + targets: vec![ + "kb-pipeline*".to_string(), + "kb-onchain-transport*".to_string(), + ], +}; + +let config = kb_logging::LoggingConfig { + default_level: "info".to_string(), + targets: vec![file_route], + target_filters: Vec::new(), +}; + +let guard = match kb_logging::init_logging(&config) { + Ok(value) => value, + Err(error) => return Err(error), +}; +``` Pour une route `file`, `path` doit désigner le fichier cible et `rotation` doit être une valeur supportée (`none`, `never`, `daily` ou `hourly`). Les formats supportés sont `human`, `compact`, `pretty` et `json`. ## Filtres de targets +```rust +let config = kb_logging::LoggingConfig { + default_level: "warn".to_string(), + targets: vec![kb_logging::LogTargetConfig { + name: "console".to_string(), + enabled: true, + sink: "console".to_string(), + level: "info".to_string(), + path: String::new(), + rotation: "none".to_string(), + format: "compact".to_string(), + ansi: true, + targets: vec!["kb-*".to_string()], + }], + target_filters: vec![ + kb_logging::LogTargetFilterConfig { + target: "kb-pipeline".to_string(), + level: "debug".to_string(), + }, + kb_logging::LogTargetFilterConfig { + target: "kb-store".to_string(), + level: "info".to_string(), + }, + ], +}; +``` + Les routes acceptent des targets exactes et des préfixes wildcard. Les `target_filters` ajoutent des niveaux spécifiques aux routes wildcard. Une route d’erreur conserve la sémantique stricte prévue par l’implémentation. +## Émission d’événements après initialisation + +```rust +tracing::info!( + target: kb_logging::tracing_target(), + action = "startup", + "logging runtime initialized" +); + +tracing::debug!( + target: "kb-pipeline.demo", + scenario = "token_2022", + "scenario preparation started" +); +``` + +Les targets doivent suivre la nomenclature canonique du workspace pour que les routes et filtres restent prévisibles. + +## Inspection des routes actives + +```rust +for route_name in guard.route_names() { + println!("active logging route: {route_name}"); +} + +assert_eq!(guard.route_count(), guard.route_names().len()); +``` + ## Erreurs Les erreurs utilisent `kb_core::Error`. Les cas principaux sont : diff --git a/kb-onchain-transport/CHANGELOG.md b/kb-onchain-transport/CHANGELOG.md new file mode 100644 index 0000000..6d0fcf1 --- /dev/null +++ b/kb-onchain-transport/CHANGELOG.md @@ -0,0 +1,19 @@ + + + +# CHANGELOG — kb-onchain-transport + +## 0.1.0-pre.070 + +- enrichissement du `USAGE.md` avec plusieurs exemples couvrant les principales familles d’API publiques ; +- ajout du contrat documentaire de la crate ; +- description des APIs publiques HTTP, WebSocket, JSON-RPC et exécution ; +- clarification de la séparation entre transport, pipeline, décodage et stockage ; +- classement des travaux futurs de streaming et résilience dans le TODO. + +## 0.1.0-pre.062 + +- migration et consolidation des anciennes crates RPC de bot2 ; +- renommage en `kb-onchain-transport` ; +- conservation des transports HTTP, WebSocket, acquisition canonique, simulation, soumission et confirmation ; +- adaptation aux normes Rust 2024 et Khadhroony bot3. diff --git a/kb-onchain-transport/README.md b/kb-onchain-transport/README.md new file mode 100644 index 0000000..51fa8aa --- /dev/null +++ b/kb-onchain-transport/README.md @@ -0,0 +1,37 @@ + + + +# kb-onchain-transport + +`kb-onchain-transport` fournit les transports Solana on-chain de `khadhroony-bot3`. + +## Responsabilités + +- requêtes JSON-RPC HTTP standard ; +- sessions et pools WebSocket ; +- routage par rôle d’endpoint ; +- adaptation des réponses RPC vers les contrats canoniques ; +- simulation, soumission et confirmation de transactions ; +- acquisition de signatures et transactions pour le backfill ; +- validation bornée des paramètres et réponses réseau. + +La crate ne décode pas les programmes Solana et ne persiste pas directement les données. Elle alimente `kb-pipeline`, qui orchestre l’acquisition, l’extraction et le replay, et utilise les contrats de `kb-core` et `kb-lib`. + +## Surfaces publiques principales + +- `HttpClient`, `HttpEndpointPool` ; +- `SolanaRpcClient`, `RpcEndpoint` ; +- contrats JSON-RPC ; +- méthodes HTTP standard et leurs types de configuration ; +- `WsClient`, `WsEndpointPool`, sessions et abonnements WebSocket ; +- adaptateurs `getTransaction`, `getSignaturesForAddress` et méthodes d’exécution RPC. + +Voir [USAGE.md](USAGE.md) pour les APIs publiques et les exemples. + +## Documentation + +- [USAGE.md](USAGE.md) +- [TODO.md](TODO.md) +- [CHANGELOG.md](CHANGELOG.md) +- [Architecture du pipeline](../docs/architecture/PIPELINE_ARCHITECTURE.md) +- [Carte des crates](../docs/architecture/CRATE_MAP.md) diff --git a/kb-onchain-transport/TODO.md b/kb-onchain-transport/TODO.md new file mode 100644 index 0000000..ed843bd --- /dev/null +++ b/kb-onchain-transport/TODO.md @@ -0,0 +1,11 @@ + + + +# TODO — kb-onchain-transport + +- [ ] Transport temps réel - étendre le support WebSocket Helius selon les contrats retenus pour `0.13.x`. +- [ ] Transport temps réel - auditer l’état réel de LaserStream et définir les compléments nécessaires. +- [ ] Transport temps réel - concevoir l’intégration Yellowstone gRPC sans coupler le pipeline à un fournisseur. +- [ ] Résilience - formaliser les politiques de reprise, continuité, reconnexion, backpressure et métriques des transports streaming. +- [ ] Documentation - créer le guide transversal RPC, backfill et streaming à partir des APIs bot3 actuelles. +- [ ] Tests - compléter les tests d’intégration opt-in pour les rôles d’endpoints et les scénarios de reconnexion. diff --git a/kb-onchain-transport/USAGE.md b/kb-onchain-transport/USAGE.md new file mode 100644 index 0000000..34a440d --- /dev/null +++ b/kb-onchain-transport/USAGE.md @@ -0,0 +1,147 @@ + + + +# Utilisation de kb-onchain-transport + +## Objectif + +La crate expose les contrats publics nécessaires aux communications RPC HTTP et WebSocket avec Solana. + +## Prérequis + +- une configuration `kb-config` contenant au moins un endpoint compatible ; +- un runtime Tokio pour les opérations asynchrones ; +- des limites et engagements adaptés à l’opération demandée. + +## Construire un client HTTP + +```rust +fn build_http_client( + endpoint: kb_config::HttpEndpointConfig, +) -> kb_core::Result { + let result = kb_onchain_transport::HttpClient::new(endpoint); + + match result { + Ok(client) => Ok(client), + Err(error) => Err(error), + } +} +``` + +## Construire et interroger un pool HTTP + +```rust +fn select_query_client( + profile: &kb_config::ProfileConfig, +) -> kb_core::Result { + let pool_result = kb_onchain_transport::HttpEndpointPool::from_profile(profile); + let pool = match pool_result { + Ok(pool) => pool, + Err(error) => return Err(error), + }; + + pool.select_client_for_role_and_method("http_queries", "getBalance") +} +``` + +`HttpEndpointPool::snapshot` fournit un état sérialisable des endpoints actifs et de leurs rôles. + +## Classer une méthode RPC + +```rust +fn classify_method(method: &str) -> String { + kb_onchain_transport::request_kind_from_method(method) +} + +assert_eq!(classify_method("getTransaction"), "transaction_read"); +``` + +La valeur retournée sert au routage par rôle. Elle ne remplace pas le nom RPC exact utilisé sur le wire. + +## Parser une réponse JSON-RPC + +```rust +fn parse_response( + text: &str, +) -> kb_core::Result { + let result = kb_onchain_transport::parse_json_rpc_text(text); + + match result { + Ok(response) => Ok(response), + Err(error) => Err(error), + } +} +``` + +Le parseur distingue les réponses de succès, les erreurs JSON-RPC et les notifications. + +## Charger un solde + +```rust +async fn load_balance( + client: &kb_onchain_transport::HttpClient, + address: &str, +) -> kb_core::Result { + let result = client + .get_balance( + address, + kb_onchain_transport::GetBalanceConfig::default(), + ) + .await; + + match result { + Ok(balance) => Ok(balance.value), + Err(error) => Err(error), + } +} +``` + +## Adapter une transaction canonique + +`GetTransactionAdapter` et `CanonicalTransactionAdapter` convertissent une réponse RPC standard en acquisition canonique sans imposer au pipeline le format brut du fournisseur. + +```rust +fn adapt_transaction( + raw: serde_json::Value, + config: &kb_onchain_transport::GetTransactionConfig, +) -> kb_core::Result { + let result = kb_onchain_transport::adapt_get_transaction_result(raw, config); + + match result { + Ok(acquisition) => Ok(acquisition), + Err(error) => Err(error), + } +} +``` + +## Exécution RPC + +Les types suivants couvrent les opérations d’exécution : + +- `SimulateTransactionConfig` et `SimulateTransactionResult` ; +- `SendTransactionConfig` et `SendTransactionResult` ; +- `ConfirmTransactionConfig` ; +- `GetLatestBlockhashConfig` ; +- `GetSignatureStatusesConfig`. + +La soumission ne remplace pas les contrôles de sécurité, préflights et confirmations opérateur réalisés par les couches supérieures. + +## Erreurs et invariants + +- les réponses sont validées et adaptées avant exposition aux couches supérieures ; +- les tailles, encodages et listes sont bornés par les contrats de la crate ; +- une erreur RPC distante reste distincte d’une erreur de transport ou d’adaptation ; +- les endpoints ne doivent pas être supposés interchangeables lorsqu’ils ont des rôles différents. + +## Tests de référence + +- tests d’équivalence des fixtures `getTransaction` ; +- tests legacy, v0, ALT, CPI et Token-2022 dans `tests/fixtures/` ; +- tests de `standard_methods.rs` vérifiant la matrice contractuelle RPC ; +- tests des pools HTTP/WebSocket et du routage par rôle. + +## Limites durables + +- la crate traite les transports on-chain ; elle ne gère pas les métadonnées HTTP, IPFS ou Arweave ; +- elle ne décode pas les instructions de programmes ; +- elle ne décide pas seule de l’autorisation d’envoyer une transaction. diff --git a/kb-pipeline-demo-scenarios/CHANGELOG.md b/kb-pipeline-demo-scenarios/CHANGELOG.md new file mode 100644 index 0000000..49b5e88 --- /dev/null +++ b/kb-pipeline-demo-scenarios/CHANGELOG.md @@ -0,0 +1,20 @@ + + + +# CHANGELOG — kb-pipeline-demo-scenarios + +## 0.1.0-pre.070 + +- enrichissement du `USAGE.md` avec plusieurs exemples couvrant les principales familles d’API publiques ; +- ajout du contrat documentaire de la crate mixte ; +- inventaire des scénarios publics et du binaire CLI ; +- documentation des tests Devnet comme références d’exécution réelle ; +- classement des travaux d’autonomie CLI, fixtures et Metaplex dans le TODO. + +## 0.1.0-pre.062 + +- extraction des scénarios de démonstration hors du desktop ; +- conservation du nom de bibliothèque `kb_pipeline_demo_scenarios` ; +- création du binaire explicite `kb-pipeline-demo-scenarios-cli` avec `autobins = false` ; +- migration des scénarios System Transfer, Memo v4, ATA, SPL Token et Token-2022 ; +- validation connue de 39 tests de bibliothèque et 1 test de binaire. diff --git a/kb-pipeline-demo-scenarios/README.md b/kb-pipeline-demo-scenarios/README.md index fd43ae8..22d0a24 100644 --- a/kb-pipeline-demo-scenarios/README.md +++ b/kb-pipeline-demo-scenarios/README.md @@ -1,16 +1,29 @@ + + -## Environnement des scénarios +# kb-pipeline-demo-scenarios -Les exécutables et tests opt-in peuvent appeler `initialize_demo_scenario_environment(workspace_root)` avant de lire leurs variables. Cette fonction délègue à `kb-config` et applique la même priorité que l'application desktop. La crate ne dépend pas directement de `dotenvy`. +`kb-pipeline-demo-scenarios` fournit des scénarios opérateur et Devnet réutilisables au-dessus de `kb-pipeline`. -## Préparation de la fixture Token-2022 +La crate est mixte : -```bash -cargo run -p kb-pipeline-demo-scenarios --bin kb-pipeline-demo-scenarios-cli -- prepare-token-2022-fixture \ - --rpc-url https://api.devnet.solana.com \ - --wallet wallets/temporary/local_devnet/local-devnet-operator.json \ - --wallet-dir wallets/temporary/local_devnet \ - --decimals 9 -``` +- bibliothèque Rust `kb_pipeline_demo_scenarios` ; +- binaire `kb-pipeline-demo-scenarios-cli`. -La commande crée ou réutilise un mint avec freeze authority, trois comptes Token-2022 distincts et un delegate, puis écrit `spl_token_2022_validation/fixture.env`. Les keypairs sont générés avec `solana-keygen --silent` et ne sont jamais inclus dans la sortie JSON. +## Responsabilités + +- préparation de l’environnement et du profil Devnet ; +- scénarios System Program, Memo v4, ATA, SPL Token et Token-2022 ; +- simulation ou soumission explicitement autorisée ; +- préparation de fixtures publiques ; +- validation des matrices et rapports Token-2022 ; +- progression observable et annulation coopérative. + +Elle ne remplace ni le pipeline générique ni l’application desktop. + +## Documentation + +- [USAGE.md](USAGE.md) +- [TODO.md](TODO.md) +- [CHANGELOG.md](CHANGELOG.md) +- [Architecture du pipeline](../docs/architecture/PIPELINE_ARCHITECTURE.md) diff --git a/kb-pipeline-demo-scenarios/TODO.md b/kb-pipeline-demo-scenarios/TODO.md new file mode 100644 index 0000000..ff52e53 --- /dev/null +++ b/kb-pipeline-demo-scenarios/TODO.md @@ -0,0 +1,13 @@ + + + +# TODO — kb-pipeline-demo-scenarios + +- [ ] CLI - rendre chaque scénario public exécutable hors `kb-app-demo-desktop`. +- [ ] CLI - compléter les arguments, sorties structurées et diagnostics du binaire. +- [ ] Fixtures - améliorer la création, réutilisation et validation des fixtures publiques. +- [ ] Metaplex Token Metadata - ajouter les scénarios de démonstration requis pour la future `0.4.7`. +- [ ] Registre ElGamal - ne créer un scénario exécutable qu’après confirmation du déploiement et disponibilité des preuves requises. +- [ ] Tests Devnet - conserver les tests réseau en opt-in et documenter précisément leurs prérequis. +- [ ] Tests Devnet - compléter les validations de bout en bout manquantes sans dépendre de l’interface desktop. +- [ ] Documentation - ajouter un guide opérateur des scénarios et de leurs effets réseau. diff --git a/kb-pipeline-demo-scenarios/USAGE.md b/kb-pipeline-demo-scenarios/USAGE.md new file mode 100644 index 0000000..819d12e --- /dev/null +++ b/kb-pipeline-demo-scenarios/USAGE.md @@ -0,0 +1,181 @@ + + + +# Utilisation de kb-pipeline-demo-scenarios + +## Objectif + +La bibliothèque expose des scénarios Devnet contrôlés. Le binaire permet leur exécution hors de l’application desktop lorsque la commande correspondante est disponible. + +## Initialiser l’environnement + +```rust +fn initialize_environment() -> kb_core::Result<()> { + kb_pipeline_demo_scenarios::initialize_demo_scenario_environment() +} +``` + +`resolve_demo_devnet_profile` sélectionne un profil Devnet configuré et `prepare_demo_devnet_profile_store` vérifie ou initialise son stockage PostgreSQL. + +## Observer une exécution + +`NoopSolanaExecutionObserver` convient aux appels sans progression personnalisée. + +```rust +fn observer() -> kb_pipeline_demo_scenarios::NoopSolanaExecutionObserver { + kb_pipeline_demo_scenarios::NoopSolanaExecutionObserver +} +``` + +Une application peut implémenter `SolanaExecutionObserver` pour recevoir les événements et demander une annulation coopérative. + +## Préparer une simulation System Program + +```rust +fn system_transfer_request( + recipient: kb_lib::MdPubkey, +) -> kb_pipeline_demo_scenarios::DevnetSystemTransferRequest { + kb_pipeline_demo_scenarios::DevnetSystemTransferRequest::new( + "system-transfer-001", + recipient, + 1_000, + ) +} +``` + +Le constructeur crée une requête conservative : `submit` et `operator_confirmed` restent à `false`. + +## Préparer et exécuter un Memo v4 + +```rust +fn memo_request() -> kb_pipeline_demo_scenarios::DevnetMemoExecutionRequest { + kb_pipeline_demo_scenarios::DevnetMemoExecutionRequest::new( + "memo-001", + "khadhroony-bot3 Devnet validation", + ) +} +``` + +```rust +async fn run_memo( + store: &S, + observer: &O, + request: kb_pipeline_demo_scenarios::DevnetMemoExecutionRequest, +) -> kb_core::Result +where + S: kb_store::Store + Sync, + O: kb_pipeline_demo_scenarios::SolanaExecutionObserver, +{ + let result = kb_pipeline_demo_scenarios::execute_devnet_memo( + store, + observer, + request, + ) + .await; + + match result { + Ok(summary) => Ok(summary), + Err(error) => Err(error), + } +} +``` + +## Simuler Token-2022 + +```rust +async fn simulate_token_2022( + request: kb_pipeline_demo_scenarios::DevnetSplToken2022ExecutionRequest, + observer: &O, +) -> kb_core::Result +where + O: kb_pipeline_demo_scenarios::SolanaExecutionObserver, +{ + let result = + kb_pipeline_demo_scenarios::simulate_devnet_spl_token_2022(request, observer).await; + + match result { + Ok(summary) => Ok(summary), + Err(error) => Err(error), + } +} +``` + +## Charger la matrice de validation Token-2022 + +```rust +fn load_validation_matrix( +) -> kb_core::Result { + let result = kb_pipeline_demo_scenarios::load_token_2022_validation_matrix(); + + match result { + Ok(matrix) => Ok(matrix), + Err(error) => Err(error), + } +} +``` + +La matrice provient de `test-fixtures/contract-matrices/SPL_TOKEN_2022_VALIDATION_MATRIX.json` et est validée avant d’être retournée. + +## Parcourir les scénarios publics + +```rust +fn scenario_ids() -> Vec { + kb_pipeline_demo_scenarios::devnet_spl_validation_scenarios() + .iter() + .map(|scenario| scenario.id.clone()) + .collect() +} +``` + +Cette liste permet au CLI ou au desktop de présenter l’inventaire sans dupliquer les identifiants. + +## Préparer une fixture Token-2022 + +```rust +async fn prepare_fixture( + wallet_path: std::path::PathBuf, + wallet_dir: std::path::PathBuf, +) -> kb_core::Result { + let options = kb_pipeline_demo_scenarios::Token2022FixturePreparationOptions { + rpc_url: "https://api.devnet.solana.com".to_string(), + wallet_path, + wallet_dir, + decimals: 9, + }; + let result = kb_pipeline_demo_scenarios::prepare_token_2022_fixture(&options).await; + + match result { + Ok(summary) => Ok(summary), + Err(error) => Err(error), + } +} +``` + +La préparation peut créer des comptes et exécuter des commandes Solana CLI. Elle doit rester explicitement déclenchée par l’opérateur. + +## Tests de référence + +Les tests de cette crate sont particulièrement utiles pour comprendre l’orchestration réelle : + +- validation de la matrice Token-2022 ; +- préparation et réutilisation des fixtures ; +- simulation et exécution des scénarios ; +- hydratation canonique, extraction Core, replay et matérialisation ; +- idempotence et confirmation des états finaux ; +- test du binaire `kb-pipeline-demo-scenarios-cli`. + +Les tests Devnet restent opt-in et peuvent produire des transactions réelles lorsque la soumission est explicitement activée. + +## Erreurs et invariants + +- aucun envoi ne doit résulter d’une simple demande de simulation ; +- le profil doit cibler Devnet pour les scénarios Devnet ; +- les secrets restent gérés par `kb-wallet` ; +- les résumés ne doivent pas déclarer une validation non observée ; +- ElGamal ne doit pas être présenté comme validé sur réseau. + +## Limites durables + +- cette crate est destinée aux démonstrations, validations et outils opérateur, pas au moteur de production autonome ; +- les scénarios réseau exigent un endpoint, un wallet et des fonds compatibles ; +- la bibliothèque ne fournit pas d’interface graphique. diff --git a/kb-pipeline/CHANGELOG.md b/kb-pipeline/CHANGELOG.md new file mode 100644 index 0000000..be653bf --- /dev/null +++ b/kb-pipeline/CHANGELOG.md @@ -0,0 +1,20 @@ + + + +# CHANGELOG — kb-pipeline + +## 0.1.0-pre.070 + +- enrichissement du `USAGE.md` avec plusieurs exemples couvrant les principales familles d’API publiques ; +- ajout du contrat documentaire de la crate ; +- classement des APIs publiques par campagnes, replay et inspections stateful ; +- clarification des invariants de déterminisme, bornage et matérialisation ; +- inscription des travaux Metaplex et ElGamal restants dans le TODO. + +## 0.1.0-pre.062 + +- migration du pipeline bot2 dans l’architecture consolidée bot3 ; +- reprise du backfill, de l’extraction Core, du decode replay et des matérialisations ; +- migration des préflights, corrélations et orchestrations Token-2022 ; +- migration des contrats stateful SPL Token, ATA et registre ElGamal ; +- adaptation aux normes Rust 2024 et Khadhroony bot3. diff --git a/kb-pipeline/README.md b/kb-pipeline/README.md new file mode 100644 index 0000000..3059bcd --- /dev/null +++ b/kb-pipeline/README.md @@ -0,0 +1,36 @@ + + + +# kb-pipeline + +`kb-pipeline` orchestre les traitements on-chain de `khadhroony-bot3`. + +## Responsabilités + +- backfill HTTP borné ; +- extraction des transactions canoniques vers le modèle Core ; +- replay contextualisé des décodeurs ; +- matérialisation optionnelle et idempotente ; +- préflights et inspections stateful ; +- orchestration Token-2022, preuves et postconditions ; +- corrélation entre instructions observées et états finaux. + +La crate coordonne `kb-onchain-transport`, `kb-store`, `kb-lib`, `kb-core` et `kb-program-ids`. Elle ne contient pas l’interface desktop ni les scénarios opérateur de démonstration. + +## Familles publiques + +- backfill ; +- extraction Core ; +- decode replay ; +- inspections stateful Solana Core, SPL Token, ATA, Token-2022 et registre ElGamal ; +- préflight cryptographique et orchestration d’exécution Token-2022. + +Voir [USAGE.md](USAGE.md) pour les contrats publics. + +## Documentation + +- [USAGE.md](USAGE.md) +- [TODO.md](TODO.md) +- [CHANGELOG.md](CHANGELOG.md) +- [Architecture du pipeline](../docs/architecture/PIPELINE_ARCHITECTURE.md) +- [Architecture du stockage](../docs/architecture/STORAGE_ARCHITECTURE.md) diff --git a/kb-pipeline/TODO.md b/kb-pipeline/TODO.md new file mode 100644 index 0000000..159d4ab --- /dev/null +++ b/kb-pipeline/TODO.md @@ -0,0 +1,12 @@ + + + +# TODO — kb-pipeline + +- [ ] Metaplex Token Metadata - intégrer la matérialisation migrée et les étapes restantes au replay bot3. +- [ ] Metaplex Token Metadata - ajouter l’orchestration nécessaire à l’exécuteur et aux validations de la future `0.4.7`. +- [ ] Registre ElGamal - confirmer l’existence et le déploiement du programme avant toute campagne réseau. +- [ ] Registre ElGamal - compléter uniquement les couches pipeline justifiées par un scénario réellement exécutable. +- [ ] Tests - ajouter les tests ciblés correspondant aux écarts identifiés par l’audit d’alignement `0.4.6`. +- [ ] Documentation - compléter le guide de replay, extraction Core et matérialisation à partir des contrats bot3. +- [ ] Dette technique - vérifier les duplications résiduelles entre les orchestrations SPL Token classique et Token-2022. diff --git a/kb-pipeline/USAGE.md b/kb-pipeline/USAGE.md new file mode 100644 index 0000000..3abefff --- /dev/null +++ b/kb-pipeline/USAGE.md @@ -0,0 +1,180 @@ + + + +# Utilisation de kb-pipeline + +## Objectif + +La crate expose les campagnes bornées d’acquisition, d’extraction, de replay et les inspections stateful nécessaires aux applications et scénarios. + +## Valider une requête d’extraction Core + +```rust +fn validate_pending_extraction() -> kb_core::Result<()> { + let request = kb_pipeline::CoreExtractionRequest { + source: kb_pipeline::CoreExtractionSource::Pending, + limit: 1_000, + max_concurrent_extractions: 4, + force_replay: false, + }; + + request.validate() +} +``` + +Une extraction ciblée peut utiliser `CoreExtractionSource::Signatures`, `SlotRange` ou `ProgramId`. + +## Exécuter une campagne d’extraction Core + +```rust +async fn run_core_extraction( + store: &S, + observer: &O, + request: kb_pipeline::CoreExtractionRequest, +) -> kb_core::Result +where + S: kb_store::CanonicalTransactionStore + + kb_store::CoreExtractionStore + + Sync, + O: kb_pipeline::CoreExtractionObserver, +{ + let result = kb_pipeline::execute_core_extraction(store, observer, request).await; + + match result { + Ok(summary) => Ok(summary), + Err(error) => Err(error), + } +} +``` + +## Préparer une requête de decode replay + +```rust +fn validate_decode_request( + selection: kb_store::DecodeSelectionFilter, +) -> kb_core::Result<()> { + let request = kb_pipeline::DecodeReplayRequest { + campaign_id: "manual-replay-001".to_string(), + selection, + decoder_names: Vec::new(), + dispatch_policy: kb_pipeline::DecodeDispatchPolicy::HighestPriority, + max_concurrent_inputs: 4, + force_replay: false, + force_replay_all_matching: false, + materialize_after_decode: true, + }; + + request.validate() +} +``` + +Une liste vide dans `decoder_names` signifie que tous les décodeurs fournis à l’orchestrateur restent éligibles. + +## Exécuter un decode replay + +```rust +async fn run_decode_replay( + store: &S, + observer: &O, + request: kb_pipeline::DecodeReplayRequest, + decoders: &[&dyn kb_lib::MdApiInstructionDecoder], + materializers: &[&dyn kb_lib::MdApiEventMaterializer], +) -> kb_core::Result +where + S: kb_store::DecodeReplayStore + Sync, + O: kb_pipeline::DecodeReplayObserver, +{ + let result = kb_pipeline::execute_decode_replay( + store, + observer, + request, + decoders, + materializers, + ) + .await; + + match result { + Ok(summary) => Ok(summary), + Err(error) => Err(error), + } +} +``` + +## Backfill HTTP + +La surface principale utilise `BackfillRequest`, `BackfillObserver`, `execute_http_backfill` et `BackfillSummary`. + +```rust +async fn run_backfill( + store: &S, + observer: &O, + request: kb_pipeline::BackfillRequest, +) -> kb_core::Result +where + S: kb_store::CanonicalTransactionStore + Sync, + O: kb_pipeline::BackfillObserver, +{ + let result = kb_pipeline::execute_http_backfill(store, observer, request).await; + + match result { + Ok(summary) => Ok(summary), + Err(error) => Err(error), + } +} +``` + +## Inspections stateful + +Les familles publiques comprennent : + +- `inspect_solana_core_stateful_readiness` ; +- inspections SPL Token et ATA ; +- inspections et corrélations Token-2022 ; +- préflight cryptographique Token-2022 ; +- lecture et matérialisation stateful du registre ElGamal. + +```rust +async fn inspect_classic_token( + store: &S, + request: kb_pipeline::SplTokenStatefulReadinessRequest, +) -> kb_core::Result +where + S: kb_store::CanonicalTransactionStore + Sync, +{ + let result = kb_pipeline::inspect_spl_token_stateful_readiness(store, request).await; + + match result { + Ok(report) => Ok(report), + Err(error) => Err(error), + } +} +``` + +Les rapports stateful ne constituent jamais une autorisation implicite d’exécution. + +## Observateurs + +Les campagnes longues exposent des traits d’observation distincts pour le backfill, l’extraction Core et le replay. L’observateur peut publier la progression et participer à l’annulation coopérative selon le contrat concerné. + +## Erreurs et invariants + +- toutes les campagnes sont bornées ; +- la progression persistée ne doit avancer qu’après traitement cohérent ; +- le replay doit rester déterministe pour une même entrée et une même version de pipeline ; +- une matérialisation ne doit pas inventer un état confirmé ; +- les erreurs de transport, stockage, décodage et préflight restent distinguées. + +## Tests de référence + +- tests de frontière contiguë et reprise du backfill ; +- tests d’extraction Core et d’idempotence ; +- tests de decode replay, dispatch et matérialisation ; +- tests stateful SPL Token, ATA et Token-2022 ; +- tests de preuves, préflight cryptographique et postconditions ; +- tests du registre ElGamal fail-closed. + +## Limites durables + +- la crate orchestre les traitements mais ne fournit pas d’interface opérateur ; +- elle ne conserve pas de secret de wallet ; +- elle ne remplace pas les scénarios Devnet et validations explicites de `kb-pipeline-demo-scenarios`. diff --git a/kb-store/CHANGELOG.md b/kb-store/CHANGELOG.md index c0a3548..aa940f7 100644 --- a/kb-store/CHANGELOG.md +++ b/kb-store/CHANGELOG.md @@ -1,8 +1,12 @@ - + # CHANGELOG — kb-store +## 0.1.0-pre.070 + +- enrichissement de `USAGE.md` avec plusieurs exemples couvrant les familles d’API publiques significatives. + ## 0.1.0-pre.069 ### Documentation diff --git a/kb-store/USAGE.md b/kb-store/USAGE.md index e805ce8..8e57295 100644 --- a/kb-store/USAGE.md +++ b/kb-store/USAGE.md @@ -1,5 +1,5 @@ - + # Utilisation de kb-store @@ -8,23 +8,23 @@ ```rust let options = match kb_store::PostgresStoreOptions::new( database_url, - "public".to_string(), 10, - std::time::Duration::from_secs(10), + 10_000, + true, ) { Ok(value) => value, Err(error) => return Err(error), }; + +println!("postgres endpoint: {}", options.masked_dsn()); + let store = match kb_store::PostgresStore::connect(options).await { Ok(value) => value, Err(error) => return Err(error), }; -if let Err(error) = store.initialize_store_schema().await { - return Err(error); -} ``` -`PostgresStoreOptions::new` valide le DSN, le schéma, le nombre de connexions et le timeout. Utiliser `masked_dsn` ou `mask_postgres_dsn` dans les logs ; ne jamais journaliser le DSN brut. +`PostgresStoreOptions::new` valide le DSN, le nombre de connexions et le timeout. Lorsque `auto_initialize_schema` vaut `true`, la connexion applique les schémas idempotents. Utiliser `masked_dsn` ou `mask_postgres_dsn` dans les logs ; ne jamais journaliser le DSN brut. ## Diagnostics @@ -32,10 +32,44 @@ if let Err(error) = store.initialize_store_schema().await { let health = store.health_snapshot().await; let migrations = store.migration_snapshot().await; let backend = store.backend_diagnostics().await; + +println!("health={:?}", health.status); +println!("migration={:?}", migrations.status); +println!("backend={:?}", backend.descriptor.backend); ``` Les diagnostics de tables raw, Core et decode/materialization sont également disponibles par les méthodes `*_table_diagnostics`. +```rust +let raw_tables = match store.raw_table_diagnostics().await { + Ok(value) => value, + Err(error) => return Err(error), +}; + +for table in raw_tables { + println!( + "table={} domain={} exists={}", + table.table_name, + table.domain, + table.exists + ); +} +``` + +## Pagination bornée + +```rust +let first_page = kb_store::PageRequest::first_page(); + +let next_page = match kb_store::PageRequest::new(250, 250) { + Ok(value) => value, + Err(error) => return Err(error), +}; + +assert_eq!(first_page.limit, kb_store::DEFAULT_PAGE_SIZE); +assert!(next_page.limit <= kb_store::MAX_PAGE_SIZE); +``` + ## Contrats de repositories Les traits publics principaux sont : @@ -55,9 +89,32 @@ Ils permettent au pipeline de dépendre d’un contrat async plutôt que d’une ## Replay et requêtes bornées ```rust -let candidates = store.replay_transaction_candidates(filter).await; -let programs = store.replay_program_summaries(program_filter).await; -let entities = store.replay_entity_summaries(entity_filter).await; +let candidates = match store.replay_transaction_candidates(filter).await { + Ok(value) => value, + Err(error) => return Err(error), +}; + +for candidate in candidates { + println!( + "signature={} slot={}", + candidate.signature, + candidate.slot + ); +} +``` + +```rust +let programs = match store.replay_program_summaries(program_filter).await { + Ok(value) => value, + Err(error) => return Err(error), +}; + +let entities = match store.replay_entity_summaries(entity_filter).await { + Ok(value) => value, + Err(error) => return Err(error), +}; + +println!("programs={}, entities={}", programs.len(), entities.len()); ``` Les filtres refusent les limites nulles ou supérieures aux bornes publiques. `PageRequest` impose également `DEFAULT_PAGE_SIZE` et `MAX_PAGE_SIZE`. @@ -66,6 +123,24 @@ Les filtres refusent les limites nulles ou supérieures aux bornes publiques. `P Les bundles `CoreExtractionBundle`, `DecodePersistenceBundle` et `MaterializationPersistenceBundle` regroupent les écritures qui doivent réussir ou être annulées ensemble. Les consommateurs ne doivent pas reproduire manuellement ces transactions avec des écritures isolées. +## Validation des noms de tables + +```rust +if let Err(error) = kb_store::validate_raw_store_table_names() { + return Err(error); +} +if let Err(error) = kb_store::validate_core_store_table_names() { + return Err(error); +} +if let Err(error) = kb_store::validate_decode_store_table_names() { + return Err(error); +} + +assert!(kb_store::is_valid_solana_table_name( + kb_store::CORE_TRANSACTIONS_TABLE_NAME +)); +``` + ## Schéma et tables Les constantes `RAW_STORE_TABLE_NAMES`, `CORE_STORE_TABLE_NAMES` et `DECODE_STORE_TABLE_NAMES` exposent les noms canoniques. Les fonctions `validate_*_table_names` et `is_valid_solana_table_name` servent aux audits et outils d’administration.