diff --git a/Cargo.toml b/Cargo.toml index b72702a..a252323 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ # file: Cargo.toml -# version: 386 +# version: 387 [workspace] resolver = "3" members = ["crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib"] [workspace.package] -version = "0.3.5-pre.3" +version = "0.3.5-pre.4" edition = "2024" license = "MIT" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" diff --git a/crates/ksp-interface-lib/tests/dependency_boundary.rs b/crates/ksp-interface-lib/tests/dependency_boundary.rs index 1b569af..7a60ed8 100644 --- a/crates/ksp-interface-lib/tests/dependency_boundary.rs +++ b/crates/ksp-interface-lib/tests/dependency_boundary.rs @@ -1,5 +1,5 @@ // file: crates/ksp-interface-lib/tests/dependency_boundary.rs -// version: 5 +// version: 6 //! Dependency and passive-surface canaries for the Interface foundation. @@ -91,6 +91,8 @@ fn pre_005_all_production_sources_preserve_the_dependency_firewall() { include_str!("../src/lib.rs"), include_str!("../src/program_account_meta.rs"), include_str!("../src/program_instruction.rs"), + include_str!("../src/slot_lifecycle.rs"), + include_str!("../src/transaction_execution.rs"), ]; for source in production_sources { for forbidden in [ @@ -129,3 +131,31 @@ fn pre_005_instruction_source_has_no_narrowing_cast_or_hidden_codec_entry_point( } return; } + +#[test] +fn v0_3_5_pre_004_acquisition_sources_remain_provider_neutral_and_runtime_free() { + let acquisition_sources = [include_str!("../src/slot_lifecycle.rs"), include_str!("../src/transaction_execution.rs")]; + for source in acquisition_sources { + for forbidden in [ + "borsh::", + "bincode::", + "ksp_config_lib::", + "ksp_logging_lib::", + "ksp_onchain_transport_lib::", + "ksp_store_api::", + "ksp_store_lib::", + "reqwest::", + "serde::", + "serde_json::", + "solana_instruction::", + "tauri::", + "tokio::", + "tonic::", + concat!("tracing", "::"), + "wincode::", + ] { + assert!(!source.contains(forbidden), "forbidden acquisition dependency path detected: {forbidden}"); + } + } + return; +} diff --git a/crates/ksp-interface-lib/tests/external_consumer.rs b/crates/ksp-interface-lib/tests/external_consumer.rs index eed317c..2d109d2 100644 --- a/crates/ksp-interface-lib/tests/external_consumer.rs +++ b/crates/ksp-interface-lib/tests/external_consumer.rs @@ -1,12 +1,22 @@ // file: crates/ksp-interface-lib/tests/external_consumer.rs -// version: 1 +// version: 2 -//! Downstream-style consumer canary for the public Interface facade. +//! Downstream-style consumer canaries for the public Interface facade. fn consume_instruction(instruction: ksp_interface_lib::ProgramInstruction) -> (ksp_interface_lib::Pubkey, usize, usize) { return (*instruction.program_id(), instruction.accounts().len(), instruction.data().len()); } +fn consume_slot_lifecycle(event: ksp_interface_lib::SlotLifecycleEvent) -> (u64, ksp_interface_lib::SlotLifecycleStage) { + return (event.slot(), event.stage()); +} + +fn consume_transaction_execution( + event: ksp_interface_lib::TransactionExecutionEvent, +) -> (u64, ksp_interface_lib::TransactionSignature, ksp_interface_lib::TransactionExecutionOutcome) { + return (event.slot(), event.signature(), event.outcome()); +} + #[test] fn pre_005_external_consumer_uses_only_the_crate_root_facade() { let program_id = ksp_interface_lib::Pubkey::new_from_array([0xA1_u8; 32]); @@ -25,3 +35,13 @@ fn pre_005_external_consumer_uses_only_the_crate_root_facade() { assert_eq!(ksp_interface_lib::ERROR_CODE_PROGRAM_INSTRUCTION_LIMIT_EXCEEDED.domain(), "interface"); return; } + +#[test] +fn v0_3_5_pre_004_external_consumer_uses_only_crate_root_for_both_acquisition_families() { + let lifecycle = ksp_interface_lib::SlotLifecycleEvent::new(u64::MAX, ksp_interface_lib::SlotLifecycleStage::OptimisticallyConfirmed); + assert_eq!(consume_slot_lifecycle(lifecycle), (u64::MAX, ksp_interface_lib::SlotLifecycleStage::OptimisticallyConfirmed)); + let signature = ksp_interface_lib::TransactionSignature::new([0xA3_u8; 64]); + let execution = ksp_interface_lib::TransactionExecutionEvent::new(u64::MAX - 1, signature, ksp_interface_lib::TransactionExecutionOutcome::Failed); + assert_eq!(consume_transaction_execution(execution), (u64::MAX - 1, signature, ksp_interface_lib::TransactionExecutionOutcome::Failed)); + return; +} diff --git a/crates/ksp-interface-lib/tests/release_completeness.rs b/crates/ksp-interface-lib/tests/release_completeness.rs index 5760af8..6a39579 100644 --- a/crates/ksp-interface-lib/tests/release_completeness.rs +++ b/crates/ksp-interface-lib/tests/release_completeness.rs @@ -1,5 +1,5 @@ // file: crates/ksp-interface-lib/tests/release_completeness.rs -// version: 4 +// version: 5 //! Release-completeness canaries for the public `ksp-interface-lib` surface. @@ -9,15 +9,11 @@ fn crate_root_source() -> std::result::Result std::result::Result<(), std::io::Error> { +fn v0_3_5_pre_004_exact_crate_root_export_inventory_is_stable() -> std::result::Result<(), std::io::Error> { let source = match crate_root_source() { Ok(source) => source, Err(error) => return Err(error), @@ -51,7 +48,7 @@ fn v0_3_5_pre_003_exact_crate_root_export_inventory_includes_both_acquisition_fa } #[test] -fn v0_3_5_pre_003_production_module_inventory_adds_only_transaction_execution() -> std::result::Result<(), std::io::Error> { +fn v0_3_5_pre_004_production_module_inventory_is_exact() -> std::result::Result<(), std::io::Error> { let source = match crate_root_source() { Ok(source) => source, Err(error) => return Err(error), @@ -67,3 +64,12 @@ fn v0_3_5_pre_003_production_module_inventory_adds_only_transaction_execution() assert!(!source.contains("ksp_store")); return Ok(()); } + +#[test] +fn v0_3_5_pre_004_evolutive_acquisition_enums_remain_non_exhaustive() { + let lifecycle_source = include_str!("../src/slot_lifecycle.rs"); + let execution_source = include_str!("../src/transaction_execution.rs"); + assert!(lifecycle_source.contains("#[non_exhaustive]\npub enum SlotLifecycleStage")); + assert!(execution_source.contains("#[non_exhaustive]\npub enum TransactionExecutionOutcome")); + return; +} diff --git a/deltas/0.3.5/pre.004.md b/deltas/0.3.5/pre.004.md new file mode 100644 index 0000000..62b25f0 --- /dev/null +++ b/deltas/0.3.5/pre.004.md @@ -0,0 +1,153 @@ + + + +# Delta `0.3.5-pre.004` — canaris externes et complétude API + +## Base requise + +```text +0.3.5-pre.3 +``` + +Le gate opérateur de `pre.003` est entièrement propre : audits Rust/Markdown, `cargo check --workspace`, Clippy, tests `ksp-interface-lib` et `ksp-program-api` passent. + +## Version + +La tranche modifie des sources Rust de test/canari. La version workspace devient : + +```text +0.3.5-pre.4 +``` + +## Mission + +Verrouiller la surface des deux familles passives admises sans ajouter de comportement ni de type de production : + +```text +SlotLifecycleEvent / SlotLifecycleStage +TransactionExecutionEvent / TransactionExecutionOutcome / TransactionSignature +``` + +## Consumer externe + +`tests/external_consumer.rs` consomme maintenant les deux familles acquisition uniquement depuis le crate-root public. + +Le canari prouve notamment qu'un consumer downstream peut récupérer : + +```text +slot + stage +slot + signature + outcome +``` + +sans accès aux modules privés, à Transport ou à Store. + +Le canari Program historique reste conservé. + +## Inventaire exact + +`tests/release_completeness.rs` fige : + +```text +5 modules privés de production +11 reexports crate-root +2 familles passives d'acquisition exactement +``` + +Aucun nouveau module ni export de production n'est ajouté par `pre.004`. + +## Evolutivité + +Les deux enums publics évolutifs restent explicitement `#[non_exhaustive]` : + +```text +SlotLifecycleStage +TransactionExecutionOutcome +``` + +Les canaris publics downstream de `pre.002` et `pre.003` restent inchangés et continuent d'utiliser un fallback `_`. + +## Firewalls négatifs + +Le scan de production inclut désormais les deux modules acquisition. + +Un canari spécifique interdit dans `slot_lifecycle.rs` et `transaction_execution.rs` les paths de : + +```text +Config +Logging +Transport +Store +reqwest +serde +Solana instruction +Tauri +Tokio +Tonic +tracing +borsh/bincode/wincode +``` + +Le manifeste `ksp-interface-lib` reste Core-only et inchangé. + +## Hors scope + +Toujours interdits/reportés : + +```text +converters Transport -> Interface +provider DTOs +Store RAW +serde/codecs +runtime/channels +logging +TransactionLogEvent +TransactionCommitmentEvent +``` + +## Fichiers + +Modifiés : + +```text +Cargo.toml +crates/ksp-interface-lib/tests/dependency_boundary.rs +crates/ksp-interface-lib/tests/external_consumer.rs +crates/ksp-interface-lib/tests/release_completeness.rs +docs/validation/022-V0_3_5_INTERFACE_ACQUISITION_EVENTS.md +``` + +Ajouté : + +```text +deltas/0.3.5/pre.004.md +``` + +Explicitement inchangés : + +```text +crates/ksp-interface-lib/Cargo.toml +crates/ksp-interface-lib/src/** +crates/ksp-interface-lib/unit_tests/** +crates/ksp-onchain-transport-lib/** +crates/ksp-store-api/** +crates/ksp-store-lib/** +crates/ksp-store-postgres-lib/** +crates/ksp-program-api/** +README.md +ROADMAP.md +CHANGELOG.md +``` + +## Gate opérateur + +```text +cargo fmt --all +python3 scripts/audit_rust_workspace_rules.py +python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.5 +cargo check --workspace +cargo clippy --workspace --all-targets +cargo test -p ksp-interface-lib +cargo test -p ksp-program-api +``` + +Les gates Cargo restent à exécuter par l'opérateur. diff --git a/docs/validation/022-V0_3_5_INTERFACE_ACQUISITION_EVENTS.md b/docs/validation/022-V0_3_5_INTERFACE_ACQUISITION_EVENTS.md index 6a47774..c5972be 100644 --- a/docs/validation/022-V0_3_5_INTERFACE_ACQUISITION_EVENTS.md +++ b/docs/validation/022-V0_3_5_INTERFACE_ACQUISITION_EVENTS.md @@ -1,11 +1,11 @@ - + # Validation `0.3.5` — Interface passive acquisition events ## 1. Portée -Ce document est ouvert par `0.3.5-pre.001`, corrigé par `0.3.5-pre.001-fix.001`, enrichi par `0.3.5-pre.002` puis par `0.3.5-pre.003`. `pre.002` matérialise `SlotLifecycleEvent`; `pre.003` ferme le gate `TransactionExecutionEvent` et admet la seconde famille passive minimale. +Ce document est ouvert par `0.3.5-pre.001`, corrigé par `0.3.5-pre.001-fix.001`, enrichi par `0.3.5-pre.002`, `pre.003` puis `pre.004`. `pre.002` matérialise `SlotLifecycleEvent`; `pre.003` ferme le gate `TransactionExecutionEvent` et admet la seconde famille passive minimale ; `pre.004` verrouille les canaris externes et la complétude de cette surface sans ajouter de contrat de production. Base : @@ -573,3 +573,67 @@ cargo test -p ksp-program-api Les gates Cargo de `pre.003` restent à exécuter par l'opérateur dans le repository réel. +## 25. Gate opérateur `pre.003` + +Le gate opérateur du `2026-08-31` est intégralement propre : + +```text +General Rust rule audit: clean +Rust export completeness audit: 0 candidate(s) +KSP workspace Rust rule audit: clean +Markdown table audit: clean (240 table(s), 141 file(s)) +cargo check --workspace: PASS +cargo clippy --workspace --all-targets: PASS +cargo test -p ksp-interface-lib: PASS +cargo test -p ksp-program-api: PASS +``` + +`ksp-interface-lib` exécute alors seize tests unitaires, dont les trois canaris `transaction_execution`, et les deux tests publics `transaction_execution_public_api` passent. `ksp-program-api` reste vert avec ses frontières historiques inchangées. + +## 26. Complétude API et canaris externes — `pre.004` + +`pre.004` n'ajoute aucun contrat de production. La version workspace évolue vers `0.3.5-pre.4` parce que la tranche modifie des sources Rust de test/canari. + +Les canaris figent désormais explicitement : + +```text +2 familles passives d'acquisition exactement +5 modules privés de production exactement +11 reexports crate-root exactement +SlotLifecycleStage #[non_exhaustive] +TransactionExecutionOutcome #[non_exhaustive] +consumer externe crate-root pour SlotLifecycleEvent +consumer externe crate-root pour TransactionExecutionEvent +aucune dependency/path Transport, Store, runtime, serde ou logging dans les sources acquisition +``` + +Le consumer externe ne dépend d'aucun module privé et consomme les deux contrats uniquement via `ksp_interface_lib::*`. Le firewall de dépendances balaie maintenant également `slot_lifecycle.rs` et `transaction_execution.rs`. + +Restent hors de la surface : + +```text +converters Transport -> Interface +DTOs provider +Store RAW +serde/codecs +logging/tracing +runtime/channels +TransactionLogEvent +TransactionCommitmentEvent +``` + +Aucun changement n'est apporté à `crates/ksp-interface-lib/Cargo.toml`, aux sources de production Interface, à Transport, Store, Program API, README, ROADMAP ou CHANGELOG. + +## 27. Gate opérateur demandé pour `pre.004` + +```text +cargo fmt --all +python3 scripts/audit_rust_workspace_rules.py +python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.5 +cargo check --workspace +cargo clippy --workspace --all-targets +cargo test -p ksp-interface-lib +cargo test -p ksp-program-api +``` + +Les gates Cargo de `pre.004` restent à exécuter par l'opérateur dans le repository réel.