// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/dependency_boundary.rs // version: 10 //! Dependency firewall canaries for the RAW transaction ingest Worker foundation. #[test] fn pre_002_manifest_dependency_surface_is_exact() { let manifest = include_str!("../Cargo.toml"); let dependencies = dependency_section(manifest); let names = manifest_dependency_names(dependencies); assert_eq!( names, vec![ "ksp-core-lib", "ksp-logging-lib", "ksp-onchain-transport-lib", "ksp-raw-transaction-lib", "ksp-store-lib", "ksp-worker-api", "sha2", "tokio", ], ); for required in [ "ksp-core-lib = { path = \"../ksp-core-lib\" }", "ksp-logging-lib = { path = \"../ksp-logging-lib\" }", "ksp-onchain-transport-lib = { path = \"../ksp-onchain-transport-lib\" }", "ksp-raw-transaction-lib = { path = \"../ksp-raw-transaction-lib\" }", "ksp-store-lib = { path = \"../ksp-store-lib\", default-features = false }", "ksp-worker-api = { path = \"../ksp-worker-api\" }", "sha2 = { workspace = true }", "tokio = { workspace = true, features = [\"macros\", \"rt\", \"sync\", \"time\"] }", ] { assert!(dependencies.contains(required), "required Worker dependency missing: {required}"); } return; } #[test] fn v0_3_12_pre_002_manifest_opens_only_the_onchain_transport_live_source_edge() { let manifest = include_str!("../Cargo.toml"); let dependencies = dependency_section(manifest); for forbidden in [ "futures-util", "ksp-config-lib", "ksp-interface-lib", "ksp-job-api", "ksp-job-backfill-lib", "ksp-program-api", "ksp-store-api", "ksp-store-postgres-lib", "ksp-wallet-lib", "reqwest", "solana-", "tokio-tungstenite", "tonic", "yellowstone-grpc-proto", ] { assert!(!dependencies.contains(forbidden), "forbidden Worker dependency present: {forbidden}"); } assert!(!manifest.contains("[dev-dependencies]"), "foundation requires no test-only dependency"); assert!(!manifest.contains("[build-dependencies]"), "foundation requires no build dependency"); return; } #[test] fn v0_3_12_pre_003_transaction_and_status_adapters_are_private_offline_and_transport_facade_only() { let root = include_str!("../src/lib.rs"); let resources = include_str!("../src/runtime_resources.rs"); for required in [ "RawTransactionIngestYellowstoneSignalView for ksp_onchain_transport_lib::YellowstoneTransactionUpdate", "RawTransactionIngestYellowstoneSignalView for ksp_onchain_transport_lib::YellowstoneTransactionStatusUpdate", "YellowstoneTransactionUpdate::transaction(self).signature()", "YellowstoneTransactionUpdate::transaction(self).index()", "YellowstoneTransactionStatusUpdate::signature(self)", "YellowstoneTransactionStatusUpdate::index(self)", "RawTransactionSignature::new", "matched_filter_fingerprint", "yellowstone_provider_unrepresentable", "yellowstone_endpoint_unrepresentable", ] { assert!(resources.contains(required), "required pre.003 signal-adapter contract missing: {required}"); } for forbidden in [ "pub struct RawTransactionIngestSourceSignal", "pub(crate) struct RawTransactionIngestSourceSignal", "pub use self::runtime_resources::RawTransactionIngestSourceSignal", "open_standard_subscribe", "next_update", "get_transaction_observed", "get_block_observed", "ksp_store_postgres_lib::", "reqwest::", "tonic::", "yellowstone_grpc_proto::", ] { assert!(!resources.contains(forbidden) && !root.contains(forbidden), "pre.003 crossed a private/offline boundary: {forbidden}"); } let status_impl = match resources.split_once("impl RawTransactionIngestYellowstoneSignalView for ksp_onchain_transport_lib::YellowstoneTransactionStatusUpdate") { std::option::Option::Some((_, tail)) => match tail.split_once("impl std::convert::From<") { std::option::Option::Some((value, _)) => value, std::option::Option::None => tail, }, std::option::Option::None => "", }; assert!(!status_impl.contains("::error(self)"), "TransactionStatus remote error material must not enter the private signal"); return; } #[test] fn v0_3_12_pre_002_source_surface_hardens_shutdown_and_faults_without_backend_or_premature_live_io() { let root = include_str!("../src/lib.rs"); let runtime = include_str!("../src/runtime.rs"); let admission = include_str!("../src/admission.rs"); let persistence = include_str!("../src/persistence.rs"); let snapshot = include_str!("../src/snapshot.rs"); let runtime_resources = include_str!("../src/runtime_resources.rs"); for required in [ "tokio::sync::mpsc::channel", "canonicalize_raw_transaction", "assemble_raw_transaction_acquisition", "RawTransactionIngestPersistencePort", "RawTransactionAcquisitionMode::Normal", "RawTransactionIngestSnapshot", "RawTransactionIngestSnapshotSource", "WorkerSnapshotSource", "tokio::sync::watch::channel", "ERROR_CODE_RAW_TRANSACTION_INGEST_COUNTER_EXHAUSTED", "ERROR_CODE_RAW_TRANSACTION_INGEST_DRAIN_TIMEOUT", "ERROR_CODE_RAW_TRANSACTION_INGEST_SOURCE_FAILED", "record_source_failure", "tokio::time::timeout", "abort_all", "backpressure_wait_total", ] { assert!( root.contains(required) || runtime.contains(required) || admission.contains(required) || persistence.contains(required) || snapshot.contains(required) || runtime_resources.contains(required), "required pre.009 hardening contract missing: {required}" ); } for forbidden in [ "pub use self::admission::RawTransactionAdmission", "pub use self::admission::RawTransactionIngress", "pub use self::persistence::RawTransactionIngestPersistencePort", "unbounded_channel", "ksp_store_postgres_lib::", "ForceRehydrate", "ksp_config_lib::", "reqwest::", ] { assert!( !root.contains(forbidden) && !runtime.contains(forbidden) && !admission.contains(forbidden) && !persistence.contains(forbidden) && !snapshot.contains(forbidden) && !runtime_resources.contains(forbidden), "pre.009 crossed a forbidden runtime boundary: {forbidden}" ); } assert_eq!(runtime.matches("tokio::sync::watch::channel").count(), 2, "runtime retains only the external-control and private-source stop watches"); assert_eq!(snapshot.matches("tokio::sync::watch::channel").count(), 1, "exactly one shared concrete snapshot watch is allowed"); return; } fn dependency_section(manifest: &str) -> &str { let after_header = match manifest.split_once("[dependencies]") { std::option::Option::Some((_, section)) => section, std::option::Option::None => { return ""; }, }; let end = match after_header.find("\n[") { std::option::Option::Some(index) => index, std::option::Option::None => after_header.len(), }; return &after_header[..end]; } fn manifest_dependency_names(section: &str) -> std::vec::Vec<&str> { let mut names = std::vec::Vec::new(); for line in section.lines() { let content = match line.split('#').next() { std::option::Option::Some(value) => value.trim(), std::option::Option::None => continue, }; if content.is_empty() { continue; } let name = match content.split('=').next() { std::option::Option::Some(value) => value.trim().trim_end_matches(".workspace"), std::option::Option::None => continue, }; if !name.is_empty() { names.push(name); } } names.sort_unstable(); return names; }