v0.3.11-pre.010
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
# file: Cargo.toml
|
||||
# version: 512
|
||||
# version: 513
|
||||
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
members = ["crates/ksp-app-backfill-desk", "crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-store-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-job-api", "crates/ksp-job-backfill-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-raw-transaction-lib", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib", "crates/ksp-worker-api", "crates/ksp-worker-raw-transaction-ingest-lib"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.3.11-pre.9.fix.3"
|
||||
version = "0.3.11-pre.10"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"
|
||||
|
||||
277
crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
Normal file
277
crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
Normal file
@@ -0,0 +1,277 @@
|
||||
// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
|
||||
// version: 1
|
||||
|
||||
//! External public, security, redaction and release-boundary hardening canaries for `pre.010`.
|
||||
|
||||
fn network(value: &'static str) -> std::option::Option<ksp_store_lib::RawNetworkId> {
|
||||
let result = ksp_store_lib::RawNetworkId::new(value);
|
||||
return match result {
|
||||
std::result::Result::Ok(value) => std::option::Option::Some(value),
|
||||
std::result::Result::Err(error) => {
|
||||
assert_eq!(error.code(), ksp_store_lib::ERROR_CODE_RAW_MODEL_INVALID);
|
||||
std::option::Option::None
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn worker_id(value: &'static str) -> std::option::Option<ksp_worker_api::WorkerId> {
|
||||
let result = ksp_worker_api::WorkerId::new(value);
|
||||
return match result {
|
||||
std::result::Result::Ok(value) => std::option::Option::Some(value),
|
||||
std::result::Result::Err(error) => {
|
||||
assert_eq!(error.code(), ksp_worker_api::ERROR_CODE_WORKER_ID_INVALID);
|
||||
std::option::Option::None
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_010_external_error_codes_are_stable_unique_and_domain_scoped() {
|
||||
let codes = [
|
||||
(ksp_worker_raw_transaction_ingest_lib::ERROR_CODE_RAW_TRANSACTION_INGEST_CONTENT_CONFLICT, "content_conflict"),
|
||||
(ksp_worker_raw_transaction_ingest_lib::ERROR_CODE_RAW_TRANSACTION_INGEST_COUNTER_EXHAUSTED, "counter_exhausted"),
|
||||
(ksp_worker_raw_transaction_ingest_lib::ERROR_CODE_RAW_TRANSACTION_INGEST_DRAIN_TIMEOUT, "drain_timeout"),
|
||||
(ksp_worker_raw_transaction_ingest_lib::ERROR_CODE_RAW_TRANSACTION_INGEST_RUNTIME_INVALID, "runtime_invalid"),
|
||||
(ksp_worker_raw_transaction_ingest_lib::ERROR_CODE_RAW_TRANSACTION_INGEST_SETTINGS_INVALID, "settings_invalid"),
|
||||
(ksp_worker_raw_transaction_ingest_lib::ERROR_CODE_RAW_TRANSACTION_INGEST_SOURCE_FAILED, "source_failed"),
|
||||
(ksp_worker_raw_transaction_ingest_lib::ERROR_CODE_RAW_TRANSACTION_INGEST_STORE_FAILED, "store_failed"),
|
||||
];
|
||||
for (index, (code, expected)) in codes.iter().enumerate() {
|
||||
assert_eq!(code.domain(), "worker_raw_transaction_ingest");
|
||||
assert_eq!(code.code(), *expected);
|
||||
for (other_index, (other, _)) in codes.iter().enumerate() {
|
||||
if index != other_index {
|
||||
assert_ne!(code, other);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_010_debug_and_settings_errors_redact_worker_identity_and_invalid_values() {
|
||||
let raw_worker_id = "raw-ingest-secret-marker-001";
|
||||
let network = match network("mainnet") {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
let worker_id = match worker_id(raw_worker_id) {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
assert_eq!(std::format!("{worker_id:?}"), "WorkerId(..)");
|
||||
let settings =
|
||||
match ksp_worker_raw_transaction_ingest_lib::RawTransactionIngestSettings::new(network.clone(), worker_id, 1, 1, std::time::Duration::from_millis(100))
|
||||
{
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let settings_debug = std::format!("{settings:?}");
|
||||
assert!(!settings_debug.contains(raw_worker_id));
|
||||
assert!(settings_debug.contains("WorkerId(..)"));
|
||||
let invalid_worker_id = match worker_id("raw-ingest-secret-marker-002") {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
let invalid =
|
||||
ksp_worker_raw_transaction_ingest_lib::RawTransactionIngestSettings::new(network, invalid_worker_id, 65_537, 1, std::time::Duration::from_millis(100));
|
||||
let error = match invalid {
|
||||
std::result::Result::Ok(_) => return,
|
||||
std::result::Result::Err(error) => error,
|
||||
};
|
||||
let error_debug = std::format!("{error:?}");
|
||||
assert_eq!(error.code(), ksp_worker_raw_transaction_ingest_lib::ERROR_CODE_RAW_TRANSACTION_INGEST_SETTINGS_INVALID);
|
||||
assert!(!error_debug.contains("raw-ingest-secret-marker-002"));
|
||||
assert!(!error_debug.contains("65537"));
|
||||
assert!(error.context().iter().any(|context| return context.key() == "field" && context.value() == "admission_queue_capacity"));
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_010_manifest_dependency_surface_remains_exact_source_neutral_and_backend_neutral() {
|
||||
let manifest = include_str!("../Cargo.toml");
|
||||
let mut section = "";
|
||||
let mut normal = std::collections::BTreeSet::new();
|
||||
let mut dev = std::collections::BTreeSet::new();
|
||||
let mut build = std::collections::BTreeSet::new();
|
||||
for line in manifest.lines() {
|
||||
let trimmed = line.trim();
|
||||
if trimmed.starts_with('[') && trimmed.ends_with(']') {
|
||||
section = trimmed;
|
||||
continue;
|
||||
}
|
||||
if trimmed.is_empty() || trimmed.starts_with('#') {
|
||||
continue;
|
||||
}
|
||||
let name = match trimmed.split_once('=') {
|
||||
std::option::Option::Some((name, _)) => name.trim(),
|
||||
std::option::Option::None => continue,
|
||||
};
|
||||
if section == "[dependencies]" {
|
||||
normal.insert(name);
|
||||
} else if section == "[dev-dependencies]" {
|
||||
dev.insert(name);
|
||||
} else if section == "[build-dependencies]" {
|
||||
build.insert(name);
|
||||
}
|
||||
}
|
||||
assert_eq!(
|
||||
normal,
|
||||
std::collections::BTreeSet::from(["ksp-core-lib", "ksp-logging-lib", "ksp-raw-transaction-lib", "ksp-store-lib", "ksp-worker-api", "sha2", "tokio",])
|
||||
);
|
||||
assert!(dev.is_empty());
|
||||
assert!(build.is_empty());
|
||||
assert!(manifest.contains("ksp-store-lib = { path = \"../ksp-store-lib\", default-features = false }"));
|
||||
assert!(manifest.contains("tokio = { workspace = true, features = [\"macros\", \"rt\", \"sync\", \"time\"] }"));
|
||||
for forbidden in [
|
||||
"ksp-config-lib",
|
||||
"ksp-job-api",
|
||||
"ksp-job-backfill-lib",
|
||||
"ksp-onchain-transport-lib",
|
||||
"ksp-store-api",
|
||||
"ksp-store-postgres-lib",
|
||||
"reqwest",
|
||||
"tokio-tungstenite",
|
||||
"tonic",
|
||||
"yellowstone-grpc-proto",
|
||||
] {
|
||||
assert!(!manifest.contains(forbidden), "forbidden Worker manifest dependency present: {forbidden}");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_010_source_visibility_contract_uses_crate_root_for_shared_items() {
|
||||
let source_contracts: [(&str, &[&str]); 4] = [
|
||||
(include_str!("../src/settings.rs"), &["RawTransactionIngestSettings"]),
|
||||
(include_str!("../src/runtime.rs"), &["RawTransactionIngestHandle", "RawTransactionIngestWorker"]),
|
||||
(include_str!("../src/snapshot.rs"), &["RawTransactionIngestSnapshot", "RawTransactionIngestSnapshotSource"]),
|
||||
(include_str!("../src/persistence.rs"), &["RawTransactionIngestPersistenceOutcome", "RawTransactionIngestPersistencePort"]),
|
||||
];
|
||||
for (source, symbols) in source_contracts {
|
||||
for symbol in symbols {
|
||||
let required = std::format!("impl crate::{symbol}");
|
||||
assert!(source.contains(required.as_str()), "shared item must use crate-root impl path: {symbol}");
|
||||
let forbidden = std::format!("impl {symbol}");
|
||||
assert!(!source.contains(forbidden.as_str()), "shared item must not use bare impl path: {symbol}");
|
||||
}
|
||||
}
|
||||
for (module, source) in [
|
||||
("admission", include_str!("../src/admission.rs")),
|
||||
("error", include_str!("../src/error.rs")),
|
||||
("identity", include_str!("../src/identity.rs")),
|
||||
("persistence", include_str!("../src/persistence.rs")),
|
||||
("runtime", include_str!("../src/runtime.rs")),
|
||||
("settings", include_str!("../src/settings.rs")),
|
||||
("snapshot", include_str!("../src/snapshot.rs")),
|
||||
] {
|
||||
let forbidden = std::format!("crate::{module}::");
|
||||
assert!(!source.contains(forbidden.as_str()), "internal module path bypasses crate-root façade: {forbidden}");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_010_production_surface_has_no_historical_backfill_or_retriever_contract() {
|
||||
let sources = [
|
||||
include_str!("../src/admission.rs"),
|
||||
include_str!("../src/error.rs"),
|
||||
include_str!("../src/identity.rs"),
|
||||
include_str!("../src/lib.rs"),
|
||||
include_str!("../src/persistence.rs"),
|
||||
include_str!("../src/runtime.rs"),
|
||||
include_str!("../src/settings.rs"),
|
||||
include_str!("../src/snapshot.rs"),
|
||||
];
|
||||
for source in sources {
|
||||
for forbidden in [
|
||||
"ksp-worker-raw-retriever",
|
||||
"raw_transaction_retriever",
|
||||
"RawTransactionRetriever",
|
||||
"Backfill",
|
||||
"backfill",
|
||||
"Checkpoint",
|
||||
"checkpoint",
|
||||
"Discovery",
|
||||
"discovery",
|
||||
"Hydration",
|
||||
"hydration",
|
||||
"historical",
|
||||
] {
|
||||
assert!(!source.contains(forbidden), "historical/retriever surface leaked into Worker production source: {forbidden}");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_010_production_sources_scan_clean_for_config_secrets_backend_and_transport() {
|
||||
let sources = [
|
||||
include_str!("../src/admission.rs"),
|
||||
include_str!("../src/error.rs"),
|
||||
include_str!("../src/identity.rs"),
|
||||
include_str!("../src/lib.rs"),
|
||||
include_str!("../src/persistence.rs"),
|
||||
include_str!("../src/runtime.rs"),
|
||||
include_str!("../src/settings.rs"),
|
||||
include_str!("../src/snapshot.rs"),
|
||||
];
|
||||
for source in sources {
|
||||
let lower = source.to_ascii_lowercase();
|
||||
for forbidden in ["api_key", "api-key", "authorization", "bearer ", "password", "credential", "secret"] {
|
||||
assert!(!lower.contains(forbidden), "secret-like material leaked into Worker production source: {forbidden}");
|
||||
}
|
||||
for forbidden in [
|
||||
"ksp_config_lib::",
|
||||
"ksp_store_postgres_lib::",
|
||||
"ksp_onchain_transport_lib::",
|
||||
"ksp_offchain_transport_lib::",
|
||||
"reqwest::",
|
||||
"tokio_tungstenite::",
|
||||
"tonic::",
|
||||
"yellowstone_grpc_proto::",
|
||||
"postgresql://",
|
||||
"postgres://",
|
||||
] {
|
||||
assert!(!source.contains(forbidden), "Config/backend/Transport implementation leaked into Worker production source: {forbidden}");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_010_lower_layers_have_no_dependency_return_to_concrete_worker() {
|
||||
for manifest in [
|
||||
include_str!("../../ksp-core-lib/Cargo.toml"),
|
||||
include_str!("../../ksp-logging-lib/Cargo.toml"),
|
||||
include_str!("../../ksp-raw-transaction-lib/Cargo.toml"),
|
||||
include_str!("../../ksp-store-api/Cargo.toml"),
|
||||
include_str!("../../ksp-store-lib/Cargo.toml"),
|
||||
include_str!("../../ksp-store-postgres-lib/Cargo.toml"),
|
||||
include_str!("../../ksp-worker-api/Cargo.toml"),
|
||||
] {
|
||||
assert!(!manifest.contains("ksp-worker-raw-transaction-ingest-lib"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_010_public_root_exposes_no_runtime_backend_or_live_source_implementation_types() {
|
||||
let root = include_str!("../src/lib.rs");
|
||||
for forbidden in [
|
||||
"pub mod ",
|
||||
"tokio::",
|
||||
"JoinSet",
|
||||
"watch::Receiver",
|
||||
"watch::Sender",
|
||||
"mpsc::Sender",
|
||||
"ksp_store_postgres_lib::",
|
||||
"ksp_onchain_transport_lib::",
|
||||
"ksp_config_lib::",
|
||||
"reqwest::",
|
||||
"tonic::",
|
||||
] {
|
||||
assert!(!root.contains(forbidden), "implementation/backend/live-source detail leaked into public root: {forbidden}");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs
|
||||
// version: 1
|
||||
|
||||
//! Release-completeness canaries through the `pre.010` public/release/security hardening tranche.
|
||||
|
||||
#[test]
|
||||
fn pre_010_production_module_inventory_is_exact() -> std::io::Result<()> {
|
||||
let source_root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src");
|
||||
let entries = match std::fs::read_dir(source_root) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let mut names = std::vec::Vec::new();
|
||||
for entry in entries {
|
||||
let entry = match entry {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let file_type = match entry.file_type() {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
if !file_type.is_file() {
|
||||
continue;
|
||||
}
|
||||
let name = match entry.file_name().into_string() {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => continue,
|
||||
};
|
||||
if name.ends_with(".rs") {
|
||||
names.push(name);
|
||||
}
|
||||
}
|
||||
names.sort_unstable();
|
||||
assert_eq!(names, std::vec!["admission.rs", "error.rs", "identity.rs", "lib.rs", "persistence.rs", "runtime.rs", "settings.rs", "snapshot.rs",]);
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_010_public_root_export_inventory_is_exact() {
|
||||
let root = include_str!("../src/lib.rs");
|
||||
let mut exports = std::vec::Vec::new();
|
||||
for line in root.lines() {
|
||||
let line = line.trim();
|
||||
if !line.starts_with("pub use ") {
|
||||
continue;
|
||||
}
|
||||
let path = line.trim_start_matches("pub use ").trim_end_matches(';');
|
||||
let name = match path.rsplit("::").next() {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => continue,
|
||||
};
|
||||
exports.push(name);
|
||||
}
|
||||
exports.sort_unstable();
|
||||
assert_eq!(
|
||||
exports,
|
||||
std::vec![
|
||||
"DEFAULT_RAW_TRANSACTION_INGEST_ADMISSION_QUEUE_CAPACITY",
|
||||
"DEFAULT_RAW_TRANSACTION_INGEST_PERSISTENCE_CONCURRENCY",
|
||||
"DEFAULT_RAW_TRANSACTION_INGEST_SHUTDOWN_DRAIN_TIMEOUT",
|
||||
"ERROR_CODE_RAW_TRANSACTION_INGEST_CONTENT_CONFLICT",
|
||||
"ERROR_CODE_RAW_TRANSACTION_INGEST_COUNTER_EXHAUSTED",
|
||||
"ERROR_CODE_RAW_TRANSACTION_INGEST_DRAIN_TIMEOUT",
|
||||
"ERROR_CODE_RAW_TRANSACTION_INGEST_RUNTIME_INVALID",
|
||||
"ERROR_CODE_RAW_TRANSACTION_INGEST_SETTINGS_INVALID",
|
||||
"ERROR_CODE_RAW_TRANSACTION_INGEST_SOURCE_FAILED",
|
||||
"ERROR_CODE_RAW_TRANSACTION_INGEST_STORE_FAILED",
|
||||
"MAX_RAW_TRANSACTION_INGEST_ADMISSION_QUEUE_CAPACITY",
|
||||
"MAX_RAW_TRANSACTION_INGEST_PERSISTENCE_CONCURRENCY",
|
||||
"MAX_RAW_TRANSACTION_INGEST_SHUTDOWN_DRAIN_TIMEOUT",
|
||||
"MIN_RAW_TRANSACTION_INGEST_ADMISSION_QUEUE_CAPACITY",
|
||||
"MIN_RAW_TRANSACTION_INGEST_PERSISTENCE_CONCURRENCY",
|
||||
"MIN_RAW_TRANSACTION_INGEST_SHUTDOWN_DRAIN_TIMEOUT",
|
||||
"RAW_TRANSACTION_INGEST_WORKER_KIND_CODE",
|
||||
"RawTransactionIngestHandle",
|
||||
"RawTransactionIngestSettings",
|
||||
"RawTransactionIngestSnapshot",
|
||||
"RawTransactionIngestSnapshotFuture",
|
||||
"RawTransactionIngestSnapshotSource",
|
||||
"RawTransactionIngestTerminalFuture",
|
||||
"RawTransactionIngestWorker",
|
||||
]
|
||||
);
|
||||
assert!(!root.contains("pub mod "));
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_010_external_hardening_suite_is_present_and_scoped() {
|
||||
let hardening = include_str!("hardening.rs");
|
||||
for required in [
|
||||
"pre_010_external_error_codes_are_stable_unique_and_domain_scoped",
|
||||
"pre_010_debug_and_settings_errors_redact_worker_identity_and_invalid_values",
|
||||
"pre_010_manifest_dependency_surface_remains_exact_source_neutral_and_backend_neutral",
|
||||
"pre_010_source_visibility_contract_uses_crate_root_for_shared_items",
|
||||
"pre_010_production_surface_has_no_historical_backfill_or_retriever_contract",
|
||||
"pre_010_production_sources_scan_clean_for_config_secrets_backend_and_transport",
|
||||
"pre_010_lower_layers_have_no_dependency_return_to_concrete_worker",
|
||||
"pre_010_public_root_exposes_no_runtime_backend_or_live_source_implementation_types",
|
||||
] {
|
||||
assert!(hardening.contains(required), "required pre.010 hardening canary missing: {required}");
|
||||
}
|
||||
let dependency_boundary = include_str!("dependency_boundary.rs");
|
||||
assert!(dependency_boundary.contains("pre_002_manifest_dependency_surface_is_exact"));
|
||||
assert!(dependency_boundary.contains("pre_009_source_surface_hardens_shutdown_and_faults_without_backend_or_live_source"));
|
||||
let public_api = include_str!("public_api.rs");
|
||||
assert!(public_api.contains("pre_003_kind_code_and_settings_are_consumable_from_crate_root"));
|
||||
assert!(public_api.contains("pre_004_start_handle_and_terminal_future_are_consumable_without_public_join_handle"));
|
||||
assert!(public_api.contains("pre_008_snapshot_surface_and_common_projection_are_public_and_stable"));
|
||||
assert!(public_api.contains("pre_009_source_and_drain_timeout_error_codes_are_public_and_stable"));
|
||||
return;
|
||||
}
|
||||
126
deltas/0.3.11/pre.010.md
Normal file
126
deltas/0.3.11/pre.010.md
Normal file
@@ -0,0 +1,126 @@
|
||||
<!-- file: deltas/0.3.11/pre.010.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta `0.3.11-pre.010` — hardening public, release et sécurité
|
||||
|
||||
## Base requise
|
||||
|
||||
```text
|
||||
0.3.11-pre.009-fix.003
|
||||
workspace.package.version = 0.3.11-pre.9.fix.3
|
||||
```
|
||||
|
||||
Le gate opérateur du 8 septembre 2026 est vert sur `fmt`, audits Rust/Markdown, `cargo check --workspace`, Clippy strict, 45 tests de la crate Worker et les doc-tests. Aucune dépendance/feature n'ayant changé, aucun `cargo tree` intermédiaire n'était requis.
|
||||
|
||||
## Objectif
|
||||
|
||||
Fermer uniquement le hardening externe `pre.010` du plan `032` : surface publique crate-root exacte, dépendances exactes, absence de surface historique, redaction, codes d'erreur, inventaire des modules et scans Config/secret/backend/Transport. Aucun comportement runtime n'est ajouté.
|
||||
|
||||
## Version
|
||||
|
||||
```text
|
||||
identifiant de livraison : 0.3.11-pre.010
|
||||
workspace.package.version : 0.3.11-pre.10
|
||||
```
|
||||
|
||||
## Hardening externe
|
||||
|
||||
Nouvelle suite `tests/hardening.rs` :
|
||||
|
||||
```text
|
||||
7 ErrorCode publics uniques et domain-scoped
|
||||
WorkerId redacted dans Debug
|
||||
settings invalides sans echo de valeur ni WorkerId
|
||||
manifest productif exact
|
||||
aucun dev/build dependency
|
||||
crate::Item pour les impl partagées
|
||||
aucune surface Backfill/historical/checkpoint/discovery/hydration/retriever
|
||||
aucun Config productif
|
||||
aucun secret-like material productif
|
||||
aucun backend Store direct
|
||||
aucun Transport productif
|
||||
aucune dépendance retour depuis les couches basses
|
||||
aucun type runtime/backend/live-source exposé par la crate-root
|
||||
```
|
||||
|
||||
## Release completeness
|
||||
|
||||
Nouvelle suite `tests/release_completeness.rs` :
|
||||
|
||||
```text
|
||||
8 modules de production exacts
|
||||
24 exports publics crate-root exacts
|
||||
aucun pub mod
|
||||
présence des canaries dependency/public/hardening requises
|
||||
```
|
||||
|
||||
Le corpus attendu après cette tranche est :
|
||||
|
||||
```text
|
||||
35 unit tests
|
||||
3 dependency-boundary tests
|
||||
7 public API tests
|
||||
8 hardening tests
|
||||
3 release-completeness tests
|
||||
56 tests Worker au total
|
||||
```
|
||||
|
||||
## Fichiers ajoutés
|
||||
|
||||
```text
|
||||
crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
|
||||
crates/ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs
|
||||
deltas/0.3.11/pre.010.md
|
||||
```
|
||||
|
||||
## Fichiers modifiés
|
||||
|
||||
```text
|
||||
Cargo.toml
|
||||
docs/plans/032-V0_3_11_RAW_TRANSACTION_INGEST_WORKER_FOUNDATION_PLAN.md
|
||||
docs/validation/028-V0_3_11_RAW_TRANSACTION_INGEST_WORKER_FOUNDATION.md
|
||||
```
|
||||
|
||||
## Fichiers supprimés
|
||||
|
||||
Aucun.
|
||||
|
||||
## Code de production
|
||||
|
||||
Aucun fichier `crates/ksp-worker-raw-transaction-ingest-lib/src/*.rs` n'est modifié.
|
||||
|
||||
## Dépendances
|
||||
|
||||
Aucune dépendance ni feature n'est ajoutée, supprimée ou modifiée. Le `Cargo.toml` de la crate Worker reste identique à la base.
|
||||
|
||||
## Validations exécutées dans l'environnement d'assemblage
|
||||
|
||||
```text
|
||||
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
|
||||
scans statiques API/dependency/historical/Config/secret/backend/Transport
|
||||
comparaison byte-for-byte des sources productives et du manifest Worker
|
||||
```
|
||||
|
||||
L'environnement d'assemblage ne fournit ni `cargo`, ni `rustc`, ni `rustfmt`. Aucun gate Cargo de `pre.010` n'est déclaré PASS localement.
|
||||
|
||||
## Gate opérateur demandé
|
||||
|
||||
Aucune dépendance ni feature n'ayant changé, aucun `cargo tree` intermédiaire n'est requis :
|
||||
|
||||
```bash
|
||||
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
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
cargo test -p ksp-worker-raw-transaction-ingest-lib
|
||||
```
|
||||
|
||||
## Décision
|
||||
|
||||
`pre.011` reste bloquée jusqu'à validation opérateur verte des canaries public/release/security.
|
||||
|
||||
## Questions ouvertes
|
||||
|
||||
Aucune nouvelle question architecturale. Les sources live restent hors scope de `0.3.11`.
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/plans/032-V0_3_11_RAW_TRANSACTION_INGEST_WORKER_FOUNDATION_PLAN.md -->
|
||||
<!-- version: 9 -->
|
||||
<!-- version: 10 -->
|
||||
|
||||
# Plan v0.3.11 — fondation runtime du Worker RawTransaction ingest
|
||||
|
||||
@@ -744,12 +744,14 @@ Budget cible : **15–20 min**. `watch` latest-value, compteurs checked, common
|
||||
|
||||
Budget cible : **15–20 min**. Drain deadline, stop/fault ordering, saturation, source failure, Store slow/failure, abort+join au timeout, no orphan tasks. Scinder immédiatement si le gate réel dépasse le budget.
|
||||
|
||||
État après matérialisation : **implémenté, gate opérateur requis**. Les tâches source privées retournent désormais `ksp_core_lib::Result<()>` dans le `JoinSet` du supervisor ; une erreur source ou un `JoinError` devient `worker_raw_transaction_ingest.source_failed` et incrémente `source_failure_total` sans exposer de texte provider. Le shutdown possède une deadline stricte `shutdown_drain_timeout` ; au timeout, admission, persistences et sources sont fermées/abortées puis toutes rejointes avant `Faulted(worker_raw_transaction_ingest.drain_timeout)`. Le stop reste prioritaire dans le `select!`, mais un Store fault découvert pendant le drain n'est pas masqué par un stop antérieur ; un fault terminal déjà décidé n'est pas remplacé par un stop tardif. La saturation est instrumentée de façon source-neutral au dequeue d'une queue `mpsc` pleine via `backpressure_wait_total`, sans drop ni queue non bornée. Les tests déterministes couvrent source failure, stop/Store fault, saturation et timeout avec absence de tâches orphelines. Aucune source live, aucun Transport, aucun backend direct et aucune nouvelle dépendance/feature ne sont introduits.
|
||||
État après matérialisation : **implémenté et gate opérateur validé après `pre.009-fix.003`**. Les tâches source privées retournent désormais `ksp_core_lib::Result<()>` dans le `JoinSet` du supervisor ; une erreur source ou un `JoinError` devient `worker_raw_transaction_ingest.source_failed` et incrémente `source_failure_total` sans exposer de texte provider. Le shutdown possède une deadline stricte `shutdown_drain_timeout` ; au timeout, admission, persistences et sources sont fermées/abortées puis toutes rejointes avant `Faulted(worker_raw_transaction_ingest.drain_timeout)`. Le stop reste prioritaire dans le `select!`, mais un Store fault découvert pendant le drain n'est pas masqué par un stop antérieur ; un fault terminal déjà décidé n'est pas remplacé par un stop tardif. La saturation est instrumentée de façon source-neutral au dequeue d'une queue `mpsc` pleine via `backpressure_wait_total`, sans drop ni queue non bornée. Les correctifs `pre.009-fix.001` à `.003` ont uniquement réparé les nouveaux tests (signature de `receive`, annotation du `JoinSet`, `store_guard` et `implicit_return`) sans modifier le code de production ni les dépendances. Le gate communiqué le 8 septembre 2026 est vert sur `fmt`, audits, `check`, Clippy strict, 45 tests de crate et doc-tests. Aucun arbre Cargo n'a été requis car aucune dépendance/feature n'avait changé.
|
||||
|
||||
### `pre.010` — hardening public/release/security
|
||||
|
||||
Budget cible : **10–15 min**. Tests externes exacts : API root, dependencies, historical-surface absence, redaction, error codes, module inventory et scans Config/secret/backend.
|
||||
|
||||
État après matérialisation : **implémenté, gate opérateur requis**. Deux suites externes nouvelles ferment la tranche sans modifier le runtime : `hardening.rs` vérifie les sept codes d'erreur publics, la redaction du `WorkerId` et des valeurs invalides, la surface de dépendances exacte, l'usage `crate::Item`, l'absence de surface historique/Backfill/retriever, les scans Config/secret/backend/Transport et l'absence de dépendance retour depuis les couches basses ; `release_completeness.rs` verrouille l'inventaire exact des huit modules de production, les vingt-quatre exports publics crate-root et la présence des canaries externes attendues. Aucun fichier `src/`, aucune dépendance et aucune feature ne changent.
|
||||
|
||||
### `pre.011` — gate technique final
|
||||
|
||||
Budget cible : **10–15 min**. Workspace tests/all-features, Clippy strict, suites ciblées, arbres normal/features, duplicate tree. Aucun nouveau scope fonctionnel.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/validation/028-V0_3_11_RAW_TRANSACTION_INGEST_WORKER_FOUNDATION.md -->
|
||||
<!-- version: 12 -->
|
||||
<!-- version: 13 -->
|
||||
|
||||
# Validation v0.3.11 — fondation runtime du Worker RawTransaction ingest
|
||||
|
||||
@@ -1404,3 +1404,114 @@ cargo test -p ksp-worker-raw-transaction-ingest-lib
|
||||
```
|
||||
|
||||
Critère de passage : races stop/fault déterministes, timeout borné sans tâche orpheline, saturation observable sans drop et frontières de dépendances inchangées.
|
||||
|
||||
## 21. `pre.010` — hardening public/release/security
|
||||
|
||||
### 21.1 Clôture opérateur de `pre.009-fix.003`
|
||||
|
||||
Le gate communiqué le 8 septembre 2026 est vert :
|
||||
|
||||
```text
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
KSP workspace Rust rule audit: clean
|
||||
Markdown table audit: clean (340 table(s), 789 file(s))
|
||||
cargo check --workspace: PASS
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings: PASS
|
||||
35 unit tests: PASS
|
||||
3 dependency-boundary tests: PASS
|
||||
7 public API tests: PASS
|
||||
doc-tests: PASS
|
||||
```
|
||||
|
||||
Les trois fixes `pre.009-fix.001` à `.003` ont uniquement corrigé les nouveaux tests ; aucun code de production, edge de dépendance ou feature n'a changé. Aucun `cargo tree` intermédiaire n'était requis.
|
||||
|
||||
### 21.2 Surface publique exacte
|
||||
|
||||
`pre.010` n'ajoute aucun symbole productif. La suite `release_completeness.rs` verrouille exactement les vingt-quatre exports publics crate-root déjà ouverts par `pre.003` à `pre.009` et interdit `pub mod`.
|
||||
|
||||
Inventaire productif exact verrouillé :
|
||||
|
||||
```text
|
||||
admission.rs
|
||||
error.rs
|
||||
identity.rs
|
||||
lib.rs
|
||||
persistence.rs
|
||||
runtime.rs
|
||||
settings.rs
|
||||
snapshot.rs
|
||||
```
|
||||
|
||||
Aucun nouveau module de production n'est introduit.
|
||||
|
||||
### 21.3 Hardening externe et redaction
|
||||
|
||||
La suite `hardening.rs` ajoute des preuves externes pour :
|
||||
|
||||
```text
|
||||
7 ErrorCode publics uniques et domain-scoped
|
||||
WorkerId redacted dans Debug
|
||||
settings invalides sans echo de valeur ni WorkerId
|
||||
manifest exact et backend-neutral
|
||||
crate::Item pour les impl partagées
|
||||
aucune surface historical/Backfill/checkpoint/discovery/hydration/retriever
|
||||
aucun Config productif
|
||||
aucun secret-like material productif
|
||||
aucun backend Store direct
|
||||
aucun Transport productif
|
||||
aucune dépendance retour depuis les couches basses vers le Worker concret
|
||||
aucun type Tokio/backend/live-source exposé par la crate-root
|
||||
```
|
||||
|
||||
Les scans secret ciblent uniquement des marqueurs à valeur de credential (`api_key`, `authorization`, `bearer`, `password`, `credential`, `secret`) et ne confondent pas les tokens de contrôle runtime avec des secrets.
|
||||
|
||||
### 21.4 Dépendances
|
||||
|
||||
Le manifest productif reste exactement :
|
||||
|
||||
```text
|
||||
ksp-core-lib
|
||||
ksp-logging-lib
|
||||
ksp-raw-transaction-lib
|
||||
ksp-store-lib (default-features = false)
|
||||
ksp-worker-api
|
||||
sha2
|
||||
tokio (macros, rt, sync, time)
|
||||
```
|
||||
|
||||
Aucun `[dev-dependencies]` ni `[build-dependencies]` n'est ajouté. Aucun arbre Cargo intermédiaire n'est requis puisque le manifest de la crate Worker est inchangé.
|
||||
|
||||
### 21.5 Frontière volontaire de `pre.010`
|
||||
|
||||
La tranche reste purement tests/release/security et n'introduit aucun :
|
||||
|
||||
```text
|
||||
source live
|
||||
Transport
|
||||
Config
|
||||
backend Store direct
|
||||
nouvelle API publique
|
||||
nouveau runtime behavior
|
||||
nouvelle dépendance/feature
|
||||
réconciliation README/USAGE
|
||||
publication metadata
|
||||
```
|
||||
|
||||
`pre.011` reste propriétaire du gate technique final workspace et des arbres Cargo.
|
||||
|
||||
### 21.6 Gate opérateur demandé pour `pre.010`
|
||||
|
||||
Aucune dépendance ni feature n'est modifiée ; le gate ciblé reste :
|
||||
|
||||
```bash
|
||||
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
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
cargo test -p ksp-worker-raw-transaction-ingest-lib
|
||||
```
|
||||
|
||||
Critère de passage : toutes les canaries public/release/security sont vertes sans modification de la surface productive.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user