# 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. ## Nomenclature interne des modules Les modules privés sont organisés par domaine : - `metadata_metaplex_token_metadata_*` ; - `metadata_solana_program_*` ; - `spl_ata_stateful` et `spl_elgamal_registry_stateful` ; - `spl_token_stateful` et `spl_token_2022_*` ; - `solana_stateful` uniquement pour les primitives Solana Core partagées. Cette réorganisation ne renomme pas les fonctions et structures publiques existantes. ## Valider historiquement Solana Program Metadata La validation historique reste un enchaînement de surfaces généralistes, pas un scénario Devnet : 1. `demo_backfill` hydrate un échantillon borné de signatures confirmées ; 2. l’extraction Core résout les instructions et comptes ; 3. `demo_decode_replay` sélectionne le Program ID `ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S` et le décodeur `metadata.solana_program_metadata` ; 4. `materializeAfterDecode` active `materializer.metadata.solana_program_metadata` ; 5. la requête bornée des événements matérialisés permet de vérifier les faits produits. Le registre générique du desktop fournit désormais ce décodeur et ce matérialiseur. `kb-pipeline-demo-scenarios` n’intervient pas dans ce parcours historique. ## Lire et prévalider Solana Program Metadata ```rust async fn read_program_metadata( pool: &kb_onchain_transport::HttpEndpointPool, account: kb_lib::MdPubkey, ) -> kb_core::Result { let request = kb_pipeline::SolanaProgramMetadataStatefulReadRequest { query_role: "rpc".to_string(), account, expected_state: kb_pipeline::SolanaProgramMetadataExpectedAccountState::Any, min_context_slot: std::option::Option::None, max_data_bytes: kb_pipeline::MAX_SOLANA_PROGRAM_METADATA_STATEFUL_ACCOUNT_BYTES, }; let result = kb_pipeline::read_solana_program_metadata_stateful_snapshot(pool, &request).await; return match result { std::result::Result::Ok(value) => std::result::Result::Ok(value), std::result::Result::Err(error) => std::result::Result::Err(error), }; } ``` Le préflight reçoit l’intent typé, le plan produit par `ExMetadataSolanaProgramMetadataExecutor`, les snapshots confirmés et, pour les opérations qui allouent ou agrandissent un compte, une observation explicite du minimum de rent. Il refuse un plan `Deny`, mais les opérations dangereuses restent exécutables lorsqu’elles sont explicitement approuvées et que l’enveloppe commune de sécurité est satisfaite. Après simulation du message exact, `validate_solana_program_metadata_execution_readiness` vérifie les signers et l’autorisation de soumission. Après confirmation, `inspect_solana_program_metadata_post_execution` compare les lectures avant/après pour les neuf opérations. ## 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`. ## Lire un compte Metaplex Token Metadata La lecture stateful exige un endpoint HTTP, une catégorie de compte explicite et une borne stricte sur les données décodées. ```rust async fn read_metaplex_metadata( pool: &kb_onchain_transport::HttpEndpointPool, metadata: kb_lib::MdPubkey, ) -> kb_core::Result { let request = kb_pipeline::MetaplexTokenMetadataStatefulReadRequest { query_role: "rpc".to_string(), account: metadata, kind: kb_pipeline::MetaplexTokenMetadataAccountKind::Metadata, min_context_slot: std::option::Option::None, max_data_bytes: kb_pipeline::MAX_METAPLEX_TOKEN_METADATA_ACCOUNT_BYTES, }; let result = kb_pipeline::read_metaplex_token_metadata_stateful_snapshot( pool, &request, ) .await; match result { Ok(snapshot) => Ok(snapshot), Err(error) => Err(error), } } ``` Pour une edition, fournir le mint dans `MetaplexTokenMetadataAccountKind::Edition`. Pour un token record programmable, fournir le mint et le token account dans `TokenRecord`. ## Inspecter le préflight Metaplex Le préflight lie un plan préparé par `kb-lib` à des snapshots confirmés et applique la politique des opérations dépréciées. ```rust fn inspect_metaplex_preflight( plan: kb_lib::ExApiPreparedExecutionPlan, snapshots: Vec, allow_deprecated_operation: bool, ) -> kb_core::Result { let request = kb_pipeline::MetaplexTokenMetadataPreflightRequest { plan, snapshots, allow_deprecated_operation, }; kb_pipeline::inspect_metaplex_token_metadata_preflight(&request) } ``` Une opération marquée dépréciée par `kb-lib` est refusée lorsque `allow_deprecated_operation` vaut `false`. ### Exigences stateful par famille Le pipeline ne doit pas considérer un intent sérialisé comme prêt à exécuter sans snapshots adaptés : - création : lire le mint et vérifier owner, décimales, supply, mint authority et freeze authority avant la construction finale ; les PDA metadata et edition doivent être absents ou compatibles selon la variante ; - mutation : lire metadata et, lorsque requis, edition, token account, token record, delegate record, collection metadata et rule set ; - vérification : prouver la relation d’autorité visée avant l’instruction et relire le bit ou l’enregistrement modifié après confirmation ; - délégation, verrouillage, transfert et burn : corréler le mint, le token account, le token record programmable et les autorités exactes ; - escrow, print, use, collect, migrate et resize : fournir les comptes spécialisés de la variante et définir une postcondition observable. Une campagne sans modèle préparé doit rester bloquée. Elle ne doit jamais réutiliser l’intent de l’opération précédemment sélectionnée. ## Valider l’enveloppe d’exécution Metaplex L’orchestration refuse la signature ou la soumission tant que la simulation exacte du message, les signers et la confirmation opérateur ne sont pas cohérents. ```rust fn validate_metaplex_execution( plan: kb_lib::ExApiPreparedExecutionPlan, preflight: kb_pipeline::MetaplexTokenMetadataPreflightReport, message_hash: String, resolved_signers: Vec, ) -> kb_core::Result { let request = kb_pipeline::MetaplexTokenMetadataExecutionReadinessRequest { plan, preflight, message_hash: message_hash.clone(), simulated_message_hash: message_hash, simulated: true, simulation_succeeded: true, resolved_signers, submit: false, operator_confirmed: false, }; kb_pipeline::validate_metaplex_token_metadata_execution_readiness(&request) } ``` Pour une soumission réelle, `submit` et `operator_confirmed` doivent être vrais et le plan ne doit plus être en `dry_run`. ## Agréger les postconditions Metaplex ```rust fn summarize_metaplex_postconditions( statuses: &[kb_pipeline::MetaplexTokenMetadataPostconditionStatus], ) -> kb_pipeline::MetaplexTokenMetadataPostconditionStatus { kb_pipeline::summarize_metaplex_token_metadata_postconditions(statuses) } ``` `Contradicted` est prioritaire sur `Confirmed`, et l’absence de postcondition applicable reste `NotApplicable`. ## Orchestration des scénarios Metaplex `kb-pipeline-demo-scenarios` expose des parcours déclaratifs plutôt que cent combinaisons forcées. Chaque parcours déclare : - la famille d’asset ; - la fixture requise ; - l’état initial ; - les opérations ordonnées ; - l’état terminal attendu ; - les comptes et projections nécessaires aux postconditions. Lorsque `materialize_after_confirmation` est activé, une soumission exige au moins une lecture de postcondition. Après confirmation, les snapshots bornés sont décodés et projetés. Lorsque l’option est désactivée, le runner conserve la simulation, la soumission, la confirmation et les postconditions demandées, mais n’émet pas les projections de matérialisation.