diff --git a/crates/ecstore/benches/comparison_benchmark.rs b/crates/ecstore/benches/comparison_benchmark.rs index 641e24e19..e8bef847c 100644 --- a/crates/ecstore/benches/comparison_benchmark.rs +++ b/crates/ecstore/benches/comparison_benchmark.rs @@ -33,7 +33,7 @@ //! ``` use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main}; -use rustfs_ecstore::erasure_coding::Erasure; +use rustfs_ecstore::api::erasure::Erasure; use std::hint::black_box; use std::time::Duration; diff --git a/crates/ecstore/benches/erasure_benchmark.rs b/crates/ecstore/benches/erasure_benchmark.rs index 4bb6bde65..0790524fd 100644 --- a/crates/ecstore/benches/erasure_benchmark.rs +++ b/crates/ecstore/benches/erasure_benchmark.rs @@ -44,7 +44,7 @@ //! - SIMD optimization for different shard sizes use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main}; -use rustfs_ecstore::erasure_coding::{BitrotReader, BitrotWriter, Erasure, calc_shard_size}; +use rustfs_ecstore::api::erasure::{BitrotReader, BitrotWriter, Erasure, calc_shard_size}; use rustfs_utils::HashAlgorithm; use std::hint::black_box; use std::io::Cursor; diff --git a/crates/ecstore/benches/single_block_non_inline_benchmark.rs b/crates/ecstore/benches/single_block_non_inline_benchmark.rs index 627bdbdbf..3647ce968 100644 --- a/crates/ecstore/benches/single_block_non_inline_benchmark.rs +++ b/crates/ecstore/benches/single_block_non_inline_benchmark.rs @@ -13,7 +13,7 @@ // limitations under the License. use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main}; -use rustfs_ecstore::erasure_coding::{BitrotWriterWrapper, CustomWriter, Erasure}; +use rustfs_ecstore::api::erasure::{BitrotWriterWrapper, CustomWriter, Erasure}; use rustfs_utils::HashAlgorithm; use std::io::Cursor; use std::sync::Arc; diff --git a/crates/ecstore/src/api/mod.rs b/crates/ecstore/src/api/mod.rs index 1b306d312..d4465ccd0 100644 --- a/crates/ecstore/src/api/mod.rs +++ b/crates/ecstore/src/api/mod.rs @@ -18,6 +18,10 @@ pub mod admin { pub use crate::admin_server_info::{get_local_server_property, get_server_info}; } +pub mod bitrot { + pub use crate::bitrot::{create_bitrot_reader, create_bitrot_writer}; +} + pub mod bucket { pub use crate::bucket::{ bandwidth, bucket_target_sys, lifecycle, metadata, metadata_sys, migration, object_lock, policy_sys, quota, replication, @@ -78,7 +82,15 @@ pub mod error { }; } +pub mod erasure { + pub use crate::erasure_coding::{ + BitrotReader, BitrotWriter, BitrotWriterWrapper, CustomWriter, Erasure, ReedSolomonEncoder, calc_shard_size, + calc_shard_size_legacy, + }; +} + pub mod event { + pub use crate::event::name::EventName; pub use crate::event_notification::{EventArgs, register_event_dispatch_hook}; } @@ -107,6 +119,13 @@ pub mod notification { }; } +pub mod object { + pub use crate::object_api::{ + BLOCK_SIZE_V2, ERASURE_ALGORITHM, GetObjectReader, ObjectInfo, ObjectOptions, PutObjReader, RangedDecompressReader, + StreamConsumer, + }; +} + pub mod rebalance { pub use crate::rebalance::{ DiskStat, RebalSaveOpt, RebalStatus, RebalanceCleanupWarnings, RebalanceInfo, RebalanceMeta, RebalanceStats, @@ -132,6 +151,10 @@ pub mod set_disk { pub use crate::set_disk::{DEFAULT_READ_BUFFER_SIZE, SetDisks, get_lock_acquire_timeout, is_valid_storage_class}; } +pub mod store_list { + pub use crate::store_list_objects::{ListPathOptions, max_keys_plus_one}; +} + pub mod storage { pub use crate::store::{ ECStore, all_local_disk, all_local_disk_path, find_local_disk_by_ref, init_local_disks, init_lock_clients, diff --git a/crates/ecstore/src/erasure_coding/erasure.rs b/crates/ecstore/src/erasure_coding/erasure.rs index 21cd5131a..4317c2082 100644 --- a/crates/ecstore/src/erasure_coding/erasure.rs +++ b/crates/ecstore/src/erasure_coding/erasure.rs @@ -368,7 +368,7 @@ fn recover_empty_payload_data_shards( /// /// # Example /// ```ignore -/// use rustfs_ecstore::erasure_coding::Erasure; +/// use rustfs_ecstore::api::erasure::Erasure; /// let erasure = Erasure::new(4, 2, 8); /// let data = b"hello world"; /// let shards = erasure.encode_data(data).unwrap(); diff --git a/crates/ecstore/src/event/name.rs b/crates/ecstore/src/event/name.rs index 82781925f..697ceb06e 100644 --- a/crates/ecstore/src/event/name.rs +++ b/crates/ecstore/src/event/name.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Compatibility re-export for the legacy `rustfs_ecstore::event::name::EventName` path. +//! Compatibility re-export for the ECStore event facade. //! The canonical event definition now lives in `rustfs_s3_types::EventName`. pub use rustfs_s3_types::EventName; diff --git a/crates/ecstore/src/lib.rs b/crates/ecstore/src/lib.rs index 7d25b1932..2a3954214 100644 --- a/crates/ecstore/src/lib.rs +++ b/crates/ecstore/src/lib.rs @@ -17,8 +17,8 @@ extern crate core; mod admin_server_info; pub mod api; -pub mod batch_processor; -pub mod bitrot; +mod batch_processor; +mod bitrot; mod bucket; mod cache_value; mod compress; @@ -28,13 +28,13 @@ mod data_usage; mod disk; mod disks_layout; mod endpoints; -pub mod erasure_coding; +mod erasure_coding; mod error; mod global; pub(crate) mod layout; mod metrics_realtime; mod notification_sys; -pub mod object_api; +mod object_api; mod pools; mod rebalance; mod rio; @@ -44,12 +44,12 @@ mod sets; mod storage_api_contracts; mod store; mod store_init; -pub mod store_list_objects; +mod store_list_objects; mod store_utils; // pub mod checksum; mod client; -pub mod event; +mod event; mod event_notification; #[cfg(test)] mod pools_test; diff --git a/crates/ecstore/tests/ecstore_contract_compat_test.rs b/crates/ecstore/tests/ecstore_contract_compat_test.rs index 04f70fa36..44153c323 100644 --- a/crates/ecstore/tests/ecstore_contract_compat_test.rs +++ b/crates/ecstore/tests/ecstore_contract_compat_test.rs @@ -13,8 +13,8 @@ // limitations under the License. use rustfs_common::heal_channel::HealOpts; +use rustfs_ecstore::api::object::{GetObjectReader, ObjectInfo, ObjectOptions, PutObjReader}; use rustfs_ecstore::api::{disk::DiskStore, error::Error, storage::ECStore}; -use rustfs_ecstore::object_api::{GetObjectReader, ObjectInfo, ObjectOptions, PutObjReader}; use rustfs_filemeta::FileInfo; use rustfs_lock::NamespaceLockWrapper; use rustfs_madmin::heal_commands::HealResultItem; diff --git a/crates/ecstore/tests/legacy_bitrot_read_test.rs b/crates/ecstore/tests/legacy_bitrot_read_test.rs index a9a17d81f..46fd9d08f 100644 --- a/crates/ecstore/tests/legacy_bitrot_read_test.rs +++ b/crates/ecstore/tests/legacy_bitrot_read_test.rs @@ -27,9 +27,9 @@ //! //! For MinIO data: RUSTFS_LEGACY_TEST_ROOT=/path/to/minio (disk "test" and .minio.sys auto-detected). +use rustfs_ecstore::api::bitrot::create_bitrot_reader; use rustfs_ecstore::api::disk::endpoint::Endpoint; use rustfs_ecstore::api::disk::{DiskOption, STORAGE_FORMAT_FILE, new_disk}; -use rustfs_ecstore::bitrot::create_bitrot_reader; use rustfs_filemeta::{FileInfoOpts, get_file_info}; use rustfs_utils::HashAlgorithm; use std::path::PathBuf; diff --git a/crates/ecstore/tests/minio_generated_read_test.rs b/crates/ecstore/tests/minio_generated_read_test.rs index feb816562..75233f338 100644 --- a/crates/ecstore/tests/minio_generated_read_test.rs +++ b/crates/ecstore/tests/minio_generated_read_test.rs @@ -4,11 +4,11 @@ use std::fs; use std::io::Cursor; use std::path::{Path, PathBuf}; +use rustfs_ecstore::api::bitrot::create_bitrot_reader; use rustfs_ecstore::api::disk::endpoint::Endpoint; use rustfs_ecstore::api::disk::{DiskAPI as _, DiskOption, new_disk}; -use rustfs_ecstore::bitrot::create_bitrot_reader; -use rustfs_ecstore::erasure_coding::Erasure; -use rustfs_ecstore::object_api::{GetObjectReader, ObjectInfo, ObjectOptions}; +use rustfs_ecstore::api::erasure::Erasure; +use rustfs_ecstore::api::object::{GetObjectReader, ObjectInfo, ObjectOptions}; use rustfs_filemeta::{FileInfo, FileInfoOpts, get_file_info}; use serde::Deserialize; use sha2::{Digest, Sha256}; diff --git a/docs/architecture/crate-boundaries.md b/docs/architecture/crate-boundaries.md index a2332edb8..4522677f3 100644 --- a/docs/architecture/crate-boundaries.md +++ b/docs/architecture/crate-boundaries.md @@ -137,12 +137,16 @@ must remain crate-private; public layout access goes through `rustfs_ecstore::api::layout`. Facade-covered ECStore root modules must remain crate-private after this boundary is established; outer crates should use `rustfs_ecstore::api::*` -instead of legacy root module paths. +instead of legacy root module paths. This includes storage/layout surfaces as +well as remaining bitrot, erasure coding, object DTO/reader, event, list, and +batch processor root modules once their facade groups exist. RustFS startup internals must stay crate-private after the startup owner split. Only `startup_entrypoint` remains a public startup module for the binary entrypoint; IAM bootstrap, optional runtime, and profiling startup shims must -not be re-exported as public library modules. +not be re-exported as public library modules. Items inside crate-private +startup modules must also use crate visibility rather than bare public +visibility. ECStore internal consumers must use `rustfs-storage-api` lifecycle helper DTOs directly for `ExpirationOptions` and `TransitionedObject`; ECStore keeps the diff --git a/docs/architecture/migration-progress.md b/docs/architecture/migration-progress.md index a967391a3..94af2ab03 100644 --- a/docs/architecture/migration-progress.md +++ b/docs/architecture/migration-progress.md @@ -467,6 +467,22 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block layer guards, formatting, diff hygiene, Rust risk scan, branch freshness check, pre-commit quality gate, and three-expert review. +- [x] `API-077` Prune remaining ECStore root compatibility modules. + - Completed slice: add explicit `rustfs_ecstore::api` facade groups for + bitrot, erasure coding, object DTO/reader, event name, and store-list + helper surfaces, then migrate ECStore tests and benches away from the + legacy root module paths. + - Acceptance: `batch_processor`, `bitrot`, `erasure_coding`, `event`, + `object_api`, and `store_list_objects` are no longer public ECStore root + modules, and the migration guard rejects restoring them as public modules. + - Must preserve: ECStore internal module access, public facade access for + compatibility tests/benches, bitrot reader/writer behavior, erasure coding + constructors/helpers, object reader/DTO wire shape, and list option + semantics. + - Verification: migration guard, ECStore compatibility tests/benches compile + coverage, formatting, diff hygiene, Rust risk scan, branch freshness check, + pre-commit quality gate, and three-expert review. + - [x] `TEST-PRTYPE-001` Check PR type enum consistency. - Acceptance: `./scripts/check_architecture_migration_rules.sh` parses the allowed PR types from [`crate-boundaries.md`](crate-boundaries.md) and fails @@ -2733,6 +2749,20 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block migration/layer guards, formatting, diff hygiene, Rust risk scan, branch freshness check, pre-commit quality gate, and three-expert review. +- [x] `R-069` Narrow startup owner item visibility. + - Do: make internal items in crate-private startup modules use crate + visibility, and extend the migration guard so only `startup_entrypoint` + can remain a public startup module. + - Acceptance: startup owner modules expose no bare public items outside the + public binary entrypoint module, and migration rules reject restoring public + startup modules or public items inside crate-private startup files. + - Must preserve: binary startup entrypoint access, embedded public API, + startup ordering, IAM readiness bootstrap, optional runtime shutdown, + profiling hooks, TLS material initialization, and all log fields. + - Verification: RustFS lib and bin check, focused startup tests, + migration/layer/unsafe guards, formatting, diff hygiene, Rust risk scan, + pre-commit quality gate, and three-expert review. + - [x] `E-001/E-SET-001` Add ECStore layout skeleton and set-layout boundary. - Do: create the ECStore internal layout ownership buckets and pin static set layout versus runtime `Sets`/`SetDisks` orchestration boundaries before any @@ -2975,20 +3005,44 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block ## Next PRs -1. `pure-move`: continue pruning startup public surface and owner boundaries. +1. `pure-move`: continue pruning remaining facade compatibility and owner boundaries. ## Pre-Push Review Log | Expert | Status | Notes | |---|---|---| -| Quality/architecture | passed | API-076 removes facade-covered legacy ECStore root modules from the public module surface while keeping the explicit `rustfs_ecstore::api` boundary as the supported compatibility path. | -| Migration preservation | passed | ECStore internal call sites, storage contract tests, object API, bitrot, erasure coding, and outer compatibility imports keep their behavior and names through retained facade paths. | -| Testing/verification | passed | ECStore/outer compile checks, bench compile, migration/layer/unsafe guards, formatting, diff hygiene, Rust risk scan, and pre-commit gate passed. | +| Quality/architecture | passed | R-069 narrows startup owner item visibility and API-077 removes remaining facade-covered ECStore root modules without runtime logic changes. | +| Migration preservation | passed | `startup_entrypoint` remains the only public startup module; ECStore bitrot, erasure, object, event, list, and batch surfaces now route through `rustfs_ecstore::api`. | +| Testing/verification | passed | ECStore all-target compile, migration/layer/unsafe guards, formatting, diff hygiene, added-line risk scan, and pre-commit gate passed. | ## Verification Notes Passed before push: +- Issue #660 R-069 current slice: + - `cargo check -p rustfs --lib`: passed. + - `cargo check -p rustfs --bins`: passed. + - `cargo test -p rustfs --lib startup_ -- --nocapture`: passed; 53 tests. + - `cargo fmt --all`: applied formatting. + - `cargo fmt --all --check`: passed. + - `git diff --check`: passed. + - `bash -n scripts/check_architecture_migration_rules.sh`: passed. + - `./scripts/check_architecture_migration_rules.sh`: passed. + - `./scripts/check_layer_dependencies.sh`: passed. + - `./scripts/check_unsafe_code_allowances.sh`: passed. + - Startup public owner scan: passed; only `startup_entrypoint::run_process` + remains public. + - Rust added-line risk scan on changed Rust files and guard script: passed. + - `make pre-commit`: passed. + +- Issue #660 API-077 current slice: + - `cargo check -p rustfs-ecstore --all-targets`: passed. + - `cargo fmt --all --check`: passed. + - `git diff --check`: passed. + - `./scripts/check_architecture_migration_rules.sh`: passed. + - Rust added-line risk scan on changed Rust files: passed. + - `make pre-commit`: passed; nextest ran 6340 tests with 6340 passed, 111 skipped, and doctests passed. + - Issue #660 API-076 current slice: - `cargo check --tests -p rustfs-ecstore -p rustfs -p rustfs-scanner -p rustfs-heal -p rustfs-iam -p rustfs-notify -p rustfs-obs -p rustfs-protocols -p rustfs-s3select-api -p e2e_test`: passed. - `cargo check --benches -p rustfs-ecstore`: passed. diff --git a/rustfs/src/startup_embedded.rs b/rustfs/src/startup_embedded.rs index cae6bf5e4..20bac96c6 100644 --- a/rustfs/src/startup_embedded.rs +++ b/rustfs/src/startup_embedded.rs @@ -73,13 +73,13 @@ impl EmbeddedStartupArgs { } pub(crate) struct EmbeddedStartedServer { - pub bound_addr: SocketAddr, - pub access_key: String, - pub secret_key: String, - pub region: String, - pub shutdown_handle: ShutdownHandle, - pub cancel_token: CancellationToken, - pub temp_dir: Option, + pub(crate) bound_addr: SocketAddr, + pub(crate) access_key: String, + pub(crate) secret_key: String, + pub(crate) region: String, + pub(crate) shutdown_handle: ShutdownHandle, + pub(crate) cancel_token: CancellationToken, + pub(crate) temp_dir: Option, } #[derive(Debug)] diff --git a/rustfs/src/startup_fs_guard.rs b/rustfs/src/startup_fs_guard.rs index 287ef6f6a..5ff2f7295 100644 --- a/rustfs/src/startup_fs_guard.rs +++ b/rustfs/src/startup_fs_guard.rs @@ -72,7 +72,7 @@ fn collect_local_paths(endpoint_pools: &EndpointServerPools) -> Vec { local_paths.into_iter().collect() } -pub fn enforce_unsupported_fs_policy(endpoint_pools: &EndpointServerPools) -> Result<()> { +pub(crate) fn enforce_unsupported_fs_policy(endpoint_pools: &EndpointServerPools) -> Result<()> { let local_paths = collect_local_paths(endpoint_pools); if local_paths.is_empty() { return Ok(()); diff --git a/rustfs/src/startup_iam.rs b/rustfs/src/startup_iam.rs index e86282f02..fe32143a3 100644 --- a/rustfs/src/startup_iam.rs +++ b/rustfs/src/startup_iam.rs @@ -39,12 +39,12 @@ const IAM_RETRY_MAX_INTERVAL: Duration = Duration::from_secs(30); const IAM_RETRY_ESCALATION_THRESHOLD: u64 = 12; #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum IamBootstrapDisposition { +pub(crate) enum IamBootstrapDisposition { ReadyInline, Deferred, } -pub async fn publish_ready_for_iam_bootstrap( +pub(crate) async fn publish_ready_for_iam_bootstrap( disposition: IamBootstrapDisposition, readiness: &GlobalReadiness, state_manager: Option<&ServiceStateManager>, @@ -307,7 +307,7 @@ async fn attempt_init_iam_sys(store: Arc) -> std::result::Result<(), st /// Returns `Ok(ReadyInline)` if IAM initialized immediately, `Ok(Deferred)` if /// recovery is happening in the background, or `Err` if IAM succeeded but /// app context initialization failed (unexpected, indicates a bug). -pub async fn bootstrap_or_defer_iam_init( +pub(crate) async fn bootstrap_or_defer_iam_init( store: Arc, kms_interface: Arc, readiness: Arc, @@ -349,7 +349,7 @@ pub async fn bootstrap_or_defer_iam_init( Ok(IamBootstrapDisposition::Deferred) } -pub async fn bootstrap_or_defer_iam_init_with_startup_kms( +pub(crate) async fn bootstrap_or_defer_iam_init_with_startup_kms( store: Arc, readiness: Arc, state_manager: Option>, diff --git a/rustfs/src/startup_lifecycle.rs b/rustfs/src/startup_lifecycle.rs index dbd0e5600..e3dca2ac7 100644 --- a/rustfs/src/startup_lifecycle.rs +++ b/rustfs/src/startup_lifecycle.rs @@ -82,18 +82,18 @@ fn mark_embedded_global_init_started( Ok(()) } -pub struct StartupRuntimeLifecycle { - pub server_address: String, - pub state_manager: Arc, - pub s3_shutdown_tx: Option, - pub console_shutdown_tx: Option, - pub service_runtime: StartupServiceRuntime, - pub store: Arc, - pub shutdown_token: CancellationToken, - pub readiness: Arc, +pub(crate) struct StartupRuntimeLifecycle { + pub(crate) server_address: String, + pub(crate) state_manager: Arc, + pub(crate) s3_shutdown_tx: Option, + pub(crate) console_shutdown_tx: Option, + pub(crate) service_runtime: StartupServiceRuntime, + pub(crate) store: Arc, + pub(crate) shutdown_token: CancellationToken, + pub(crate) readiness: Arc, } -pub async fn run_startup_runtime_lifecycle(lifecycle: StartupRuntimeLifecycle) -> Result<()> { +pub(crate) async fn run_startup_runtime_lifecycle(lifecycle: StartupRuntimeLifecycle) -> Result<()> { let StartupRuntimeLifecycle { server_address, state_manager, @@ -151,7 +151,10 @@ pub async fn run_startup_runtime_lifecycle(lifecycle: StartupRuntimeLifecycle) - Ok(()) } -pub async fn publish_embedded_startup_ready(iam_bootstrap: IamBootstrapDisposition, readiness: &GlobalReadiness) -> Result<()> { +pub(crate) async fn publish_embedded_startup_ready( + iam_bootstrap: IamBootstrapDisposition, + readiness: &GlobalReadiness, +) -> Result<()> { publish_ready_for_iam_bootstrap(iam_bootstrap, readiness, None).await?; rustfs_common::set_global_init_time_now().await; Ok(()) @@ -168,7 +171,7 @@ pub(crate) fn embedded_endpoint_address(address: SocketAddr) -> SocketAddr { SocketAddr::new(ip, address.port()) } -pub fn log_embedded_server_ready(endpoint_address: SocketAddr) { +pub(crate) fn log_embedded_server_ready(endpoint_address: SocketAddr) { info!( target: "rustfs::embedded", component = LOG_COMPONENT_EMBEDDED, diff --git a/rustfs/src/startup_optional_runtime_sidecars.rs b/rustfs/src/startup_optional_runtime_sidecars.rs index b6284035a..aaeadfc89 100644 --- a/rustfs/src/startup_optional_runtime_sidecars.rs +++ b/rustfs/src/startup_optional_runtime_sidecars.rs @@ -24,17 +24,17 @@ const LOG_COMPONENT_MAIN: &str = "main"; const LOG_SUBSYSTEM_STARTUP: &str = "startup"; const EVENT_PROTOCOL_SYSTEM_STATE: &str = "protocol_system_state"; -pub struct OptionalRuntimeServices { - pub protocols: ProtocolShutdownSenders, +pub(crate) struct OptionalRuntimeServices { + pub(crate) protocols: ProtocolShutdownSenders, } impl OptionalRuntimeServices { - pub fn new(protocols: ProtocolShutdownSenders) -> Self { + pub(crate) fn new(protocols: ProtocolShutdownSenders) -> Self { Self { protocols } } } -pub async fn init_optional_runtime_services() -> Result { +pub(crate) async fn init_optional_runtime_services() -> Result { let protocols = init_protocol_shutdown_senders().await?; Ok(OptionalRuntimeServices::new(protocols)) } @@ -76,7 +76,7 @@ fn optional_runtime_shutdown_steps(protocols: &ProtocolShutdownSenders) -> Vec Vec { +pub(crate) fn prepare_optional_runtime_shutdowns(optional_runtimes: OptionalRuntimeServices) -> Vec { let ProtocolShutdownSenders { ftp, ftps, webdav, sftp } = optional_runtimes.protocols; let mut protocol_shutdowns = Vec::new(); @@ -100,7 +100,7 @@ pub fn prepare_optional_runtime_shutdowns(optional_runtimes: OptionalRuntimeServ protocol_shutdowns } -pub async fn shutdown_optional_runtime_services(protocol_shutdowns: Vec) { +pub(crate) async fn shutdown_optional_runtime_services(protocol_shutdowns: Vec) { join_all(protocol_shutdowns.into_iter().map(ShutdownHandle::shutdown)).await; } diff --git a/rustfs/src/startup_preflight.rs b/rustfs/src/startup_preflight.rs index 506dc3b3f..fd58160e0 100644 --- a/rustfs/src/startup_preflight.rs +++ b/rustfs/src/startup_preflight.rs @@ -29,7 +29,7 @@ const EVENT_OBSERVABILITY_GUARD_SET: &str = "observability_guard_set"; const EVENT_OBSERVABILITY_GUARD_SET_FAILED: &str = "observability_guard_set_failed"; #[derive(Debug)] -pub enum StartupServerPreflightError { +pub(crate) enum StartupServerPreflightError { ObservabilityInit(Error), Other(Error), } @@ -54,12 +54,12 @@ impl std::error::Error for StartupServerPreflightError { } } -pub fn bootstrap_external_prefix_compat() -> Result { +pub(crate) fn bootstrap_external_prefix_compat() -> Result { let env_compat_report = apply_external_env_compat(); Ok(env_compat_report) } -pub async fn init_startup_server_preflight( +pub(crate) async fn init_startup_server_preflight( config: &Config, env_compat_report: &ExternalEnvCompatReport, ) -> std::result::Result<(), StartupServerPreflightError> { diff --git a/rustfs/src/startup_protocols.rs b/rustfs/src/startup_protocols.rs index 00d5cb984..dadd6b122 100644 --- a/rustfs/src/startup_protocols.rs +++ b/rustfs/src/startup_protocols.rs @@ -31,14 +31,14 @@ type ProtocolInitResult = std::result::Result, Box, - pub ftps: Option, - pub webdav: Option, - pub sftp: Option, +pub(crate) struct ProtocolShutdownSenders { + pub(crate) ftp: Option, + pub(crate) ftps: Option, + pub(crate) webdav: Option, + pub(crate) sftp: Option, } -pub async fn init_protocol_shutdown_senders() -> Result { +pub(crate) async fn init_protocol_shutdown_senders() -> Result { Ok(ProtocolShutdownSenders { ftp: init_ftp_protocol().await?, ftps: init_ftps_protocol().await?, diff --git a/rustfs/src/startup_runtime.rs b/rustfs/src/startup_runtime.rs index 75fe974c7..d0e6ad1d3 100644 --- a/rustfs/src/startup_runtime.rs +++ b/rustfs/src/startup_runtime.rs @@ -19,7 +19,7 @@ use crate::{ }; use std::io::Result; -pub async fn init_startup_runtime_foundation(config: &Config) -> Result<()> { +pub(crate) async fn init_startup_runtime_foundation(config: &Config) -> Result<()> { log_startup_runtime_diagnostics(); init_profiling_runtime().await; rustfs_trusted_proxies::init(); diff --git a/rustfs/src/startup_runtime_hooks.rs b/rustfs/src/startup_runtime_hooks.rs index 5dc427946..a95fec1cf 100644 --- a/rustfs/src/startup_runtime_hooks.rs +++ b/rustfs/src/startup_runtime_hooks.rs @@ -27,7 +27,7 @@ const EVENT_CRYPTO_PROVIDER_STATE: &str = "crypto_provider_state"; const EVENT_DIAL9_RUNTIME_STATUS: &str = "dial9_runtime_status"; const EVENT_RUNTIME_LICENSE_STATUS: &str = "runtime_license_status"; -pub fn log_startup_runtime_diagnostics() { +pub(crate) fn log_startup_runtime_diagnostics() { log_dial9_runtime_status(); log_runtime_license_status(); debug!("{}", crate::server::LOGO); @@ -66,7 +66,7 @@ fn log_runtime_license_status() { ); } -pub async fn init_profiling_runtime() { +pub(crate) async fn init_profiling_runtime() { init_profiling_runtime_with(crate::profiling::init_from_env).await; } @@ -78,7 +78,7 @@ where init().await; } -pub fn shutdown_profiling_runtime() { +pub(crate) fn shutdown_profiling_runtime() { shutdown_profiling_runtime_with(crate::profiling::shutdown_profiling); } @@ -89,7 +89,7 @@ where shutdown(); } -pub fn install_default_crypto_provider() { +pub(crate) fn install_default_crypto_provider() { if default_provider().install_default().is_err() { debug!( target: "rustfs::main", @@ -103,7 +103,7 @@ pub fn install_default_crypto_provider() { } } -pub async fn init_embedded_runtime_hooks(obs_endpoint: String) -> Result<()> { +pub(crate) async fn init_embedded_runtime_hooks(obs_endpoint: String) -> Result<()> { let guard = rustfs_obs::init_obs(Some(obs_endpoint)) .await .map_err(|err| Error::other(format!("init_obs: {err}")))?; diff --git a/rustfs/src/startup_server.rs b/rustfs/src/startup_server.rs index 53d1ca86e..f5bac7961 100644 --- a/rustfs/src/startup_server.rs +++ b/rustfs/src/startup_server.rs @@ -40,42 +40,42 @@ const EVENT_ACTION_CREDENTIALS_INITIALIZED: &str = "action_credentials_initializ const EVENT_ACTION_CREDENTIALS_INITIALIZATION_FAILED: &str = "action_credentials_initialization_failed"; const DEFAULT_CREDENTIALS_WARNING_MESSAGE: &str = "Detected default root credentials; set RUSTFS_ACCESS_KEY and RUSTFS_SECRET_KEY to non-default values for production deployments"; -pub struct StartupListenContext { - pub readiness: Arc, - pub server_addr: SocketAddr, - pub server_address: String, +pub(crate) struct StartupListenContext { + pub(crate) readiness: Arc, + pub(crate) server_addr: SocketAddr, + pub(crate) server_address: String, } -pub struct EmbeddedStartupListenContext { - pub readiness: Arc, - pub server_addr: SocketAddr, - pub server_address: String, +pub(crate) struct EmbeddedStartupListenContext { + pub(crate) readiness: Arc, + pub(crate) server_addr: SocketAddr, + pub(crate) server_address: String, } pub(crate) struct EmbeddedStartupConfig { - pub config: Config, - pub identity: EmbeddedServerIdentity, + pub(crate) config: Config, + pub(crate) identity: EmbeddedServerIdentity, pub(crate) temp_dir_guard: Option, } pub(crate) struct EmbeddedServerIdentity { - pub access_key: String, - pub secret_key: String, - pub region: String, + pub(crate) access_key: String, + pub(crate) secret_key: String, + pub(crate) region: String, } pub(crate) struct EmbeddedHttpServer { - pub shutdown_handle: ShutdownHandle, - pub bound_addr: SocketAddr, + pub(crate) shutdown_handle: ShutdownHandle, + pub(crate) bound_addr: SocketAddr, } -pub struct StartupHttpServers { - pub state_manager: Arc, - pub s3_shutdown_tx: Option, - pub console_shutdown_tx: Option, +pub(crate) struct StartupHttpServers { + pub(crate) state_manager: Arc, + pub(crate) s3_shutdown_tx: Option, + pub(crate) console_shutdown_tx: Option, } -pub async fn init_startup_listen_context(config: &Config) -> Result { +pub(crate) async fn init_startup_listen_context(config: &Config) -> Result { log_sanitized_server_config(config); let readiness = Arc::new(GlobalReadiness::new()); @@ -171,7 +171,7 @@ pub(crate) fn find_embedded_available_port() -> Result { Ok(port) } -pub async fn init_embedded_startup_listen_context(config: &Config) -> Result { +pub(crate) async fn init_embedded_startup_listen_context(config: &Config) -> Result { let readiness = Arc::new(GlobalReadiness::new()); let server_addr = @@ -214,7 +214,7 @@ pub(crate) async fn start_embedded_http_server(config: &Config, readiness: Arc) -> Result { +pub(crate) async fn init_startup_http_servers(config: &Config, readiness: Arc) -> Result { init_capacity_management().await; let state_manager = Arc::new(ServiceStateManager::new()); state_manager.update(ServiceState::Starting); diff --git a/rustfs/src/startup_services.rs b/rustfs/src/startup_services.rs index a42cf5aec..8389b4061 100644 --- a/rustfs/src/startup_services.rs +++ b/rustfs/src/startup_services.rs @@ -32,17 +32,17 @@ use rustfs_common::GlobalReadiness; use std::{io::Result, sync::Arc}; use tokio_util::sync::CancellationToken; -pub struct StartupServiceRuntime { - pub optional_runtimes: OptionalRuntimeServices, - pub iam_bootstrap: IamBootstrapDisposition, - pub enable_scanner: bool, +pub(crate) struct StartupServiceRuntime { + pub(crate) optional_runtimes: OptionalRuntimeServices, + pub(crate) iam_bootstrap: IamBootstrapDisposition, + pub(crate) enable_scanner: bool, } -pub struct EmbeddedStartupServiceRuntime { - pub iam_bootstrap: IamBootstrapDisposition, +pub(crate) struct EmbeddedStartupServiceRuntime { + pub(crate) iam_bootstrap: IamBootstrapDisposition, } -pub async fn init_embedded_startup_runtime_services( +pub(crate) async fn init_embedded_startup_runtime_services( config: &Config, endpoint_pools: EndpointServerPools, store: Arc, @@ -59,7 +59,7 @@ pub async fn init_embedded_startup_runtime_services( Ok(EmbeddedStartupServiceRuntime { iam_bootstrap }) } -pub async fn init_startup_runtime_services( +pub(crate) async fn init_startup_runtime_services( config: &Config, endpoint_pools: EndpointServerPools, store: Arc, diff --git a/rustfs/src/startup_shutdown.rs b/rustfs/src/startup_shutdown.rs index 84cd93e89..eb9415dc7 100644 --- a/rustfs/src/startup_shutdown.rs +++ b/rustfs/src/startup_shutdown.rs @@ -59,7 +59,7 @@ fn background_shutdown_steps(enable_scanner: bool, enable_heal: bool) -> Vec, @@ -201,7 +201,7 @@ pub async fn run_startup_shutdown_sequence( ); } -pub async fn run_embedded_shutdown_cleanup() { +pub(crate) async fn run_embedded_shutdown_cleanup() { shutdown_event_notifier().await; if let Err(err) = stop_audit_system().await { @@ -235,7 +235,7 @@ pub(crate) fn run_embedded_server_drop_cleanup( } } -pub async fn run_embedded_server_shutdown( +pub(crate) async fn run_embedded_server_shutdown( ctx: &CancellationToken, shutdown_handle: &mut Option, temp_dir: Option<&Path>, diff --git a/rustfs/src/startup_storage.rs b/rustfs/src/startup_storage.rs index 7739c8719..f922c97b4 100644 --- a/rustfs/src/startup_storage.rs +++ b/rustfs/src/startup_storage.rs @@ -39,12 +39,12 @@ const EVENT_STORAGE_POOL_HOST_RISK: &str = "storage_pool_host_risk"; const EVENT_EMBEDDED_STORAGE_INIT_FAILED: &str = "embedded_storage_init_failed"; const EVENT_EMBEDDED_STORAGE_INIT_RETRY: &str = "embedded_storage_init_retry"; -pub struct StartupStorageRuntime { - pub store: Arc, - pub shutdown_token: CancellationToken, +pub(crate) struct StartupStorageRuntime { + pub(crate) store: Arc, + pub(crate) shutdown_token: CancellationToken, } -pub async fn init_startup_storage_foundation(server_address: &str, volumes: &[String]) -> Result { +pub(crate) async fn init_startup_storage_foundation(server_address: &str, volumes: &[String]) -> Result { info!( target: "rustfs::main::run", event = EVENT_ENDPOINT_PARSING_STARTED, @@ -106,7 +106,10 @@ pub async fn init_startup_storage_foundation(server_address: &str, volumes: &[St Ok(endpoint_pools) } -pub async fn init_embedded_startup_storage_foundation(server_address: &str, volumes: &[String]) -> Result { +pub(crate) async fn init_embedded_startup_storage_foundation( + server_address: &str, + volumes: &[String], +) -> Result { let (endpoint_pools, setup_type) = EndpointServerPools::from_volumes(server_address, volumes.to_vec()) .await .map_err(|err| Error::other(format!("endpoints: {err}")))?; @@ -123,7 +126,7 @@ pub async fn init_embedded_startup_storage_foundation(server_address: &str, volu Ok(endpoint_pools) } -pub async fn init_startup_storage_runtime( +pub(crate) async fn init_startup_storage_runtime( server_addr: SocketAddr, endpoint_pools: &EndpointServerPools, readiness: Arc, @@ -164,7 +167,7 @@ pub async fn init_startup_storage_runtime( }) } -pub async fn init_embedded_startup_storage_runtime( +pub(crate) async fn init_embedded_startup_storage_runtime( server_addr: SocketAddr, endpoint_pools: &EndpointServerPools, readiness: Arc, diff --git a/scripts/check_architecture_migration_rules.sh b/scripts/check_architecture_migration_rules.sh index 25dc8dd1a..1c88cd6a7 100755 --- a/scripts/check_architecture_migration_rules.sh +++ b/scripts/check_architecture_migration_rules.sh @@ -83,6 +83,7 @@ BROAD_STORE_API_COMPAT_REEXPORT_HITS_FILE="${TMP_DIR}/broad_store_api_compat_ree NESTED_STORE_API_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/nested_store_api_compat_module_hits.txt" UNAPPROVED_STORE_API_COMPAT_ALIAS_HITS_FILE="${TMP_DIR}/unapproved_store_api_compat_alias_hits.txt" PUBLIC_STORE_API_MODULE_HITS_FILE="${TMP_DIR}/public_store_api_module_hits.txt" +ECSTORE_PUBLIC_ROOT_MODULE_HITS_FILE="${TMP_DIR}/ecstore_public_root_module_hits.txt" STORE_API_MODULE_PATH_HITS_FILE="${TMP_DIR}/store_api_module_path_hits.txt" ECSTORE_COMPAT_PASSTHROUGH_EXPECTED_FILE="${TMP_DIR}/ecstore_compat_passthrough_expected.txt" ECSTORE_COMPAT_PASSTHROUGH_ACTUAL_FILE="${TMP_DIR}/ecstore_compat_passthrough_actual.txt" @@ -610,11 +611,23 @@ fi ( cd "$ROOT_DIR" - rg -n --no-heading '^pub mod startup_(iam|optional_runtimes|profiling);' rustfs/src/lib.rs || true + { + perl -ne ' + if (/^\s*pub\s+mod\s+(startup_[A-Za-z0-9_]+);/ && $1 ne "startup_entrypoint") { + print "$ARGV:$.:$_"; + } + ' rustfs/src/lib.rs + find rustfs/src -maxdepth 1 -type f -name 'startup_*.rs' ! -name 'startup_entrypoint.rs' -print0 | + xargs -0 perl -ne ' + if (/^\s*pub\s+(?!\()/) { + print "$ARGV:$.:$_"; + } + ' + } || true ) >"$STARTUP_PUBLIC_SHIM_HITS_FILE" if [[ -s "$STARTUP_PUBLIC_SHIM_HITS_FILE" ]]; then - report_failure "startup compatibility shims must not be public library modules: $(paste -sd '; ' "$STARTUP_PUBLIC_SHIM_HITS_FILE")" + report_failure "startup owner boundaries must stay crate-private except startup_entrypoint: $(paste -sd '; ' "$STARTUP_PUBLIC_SHIM_HITS_FILE")" fi ( @@ -784,6 +797,10 @@ if rg -n --no-heading '^\s*pub\s+mod\s+store_api\s*;' "$ROOT_DIR/crates/ecstore/ report_failure "ECStore store_api must remain private; expose ECStore-owned object DTO and reader aliases through rustfs_ecstore::object_api" fi +if rg -n --no-heading '^\s*pub\s+mod\s+(batch_processor|bitrot|erasure_coding|event|object_api|store_list_objects)\s*;' "$ROOT_DIR/crates/ecstore/src/lib.rs" >"$ECSTORE_PUBLIC_ROOT_MODULE_HITS_FILE"; then + report_failure "facade-covered ECStore root modules must remain private; expose compatibility through rustfs_ecstore::api: $(paste -sd '; ' "$ECSTORE_PUBLIC_ROOT_MODULE_HITS_FILE")" +fi + ( cd "$ROOT_DIR" {