docs/architecture/global-state-crate-split-plan.md
This document records the late global-state cleanup plan after the AppContext foundation, storage API contracts, ECStore layout, runtime lifecycle, and cluster control-plane boundaries are stable.
As of the Phase 7 closeout, runtime resolver fallbacks have been pushed out of the root facade and into explicit owner-local boundaries. Future work should therefore treat broad fallback removal as complete and use this document for the remaining ECStore-owned bootstrap state and crate-split decisions.
The issue #730 global-state baseline and runtime migration target inventory are
recorded in global-state-inventory.md.
| Owner | Current role | Migration stance |
|---|---|---|
rustfs/src/app/context.rs | AppContext-first resolver facade. | Resolver helpers stay context-first and do not construct concrete no-AppContext defaults. |
rustfs/src/app/context/runtime_sources.rs | Default adapters for KMS, IAM, object store, endpoints, config, metrics, and notification state used by AppContext construction. | This is an allowed adapter boundary, not a business logic owner. |
rustfs/src/*/runtime_sources.rs | Root, admin, app, server, startup, and storage owner-local runtime-source boundaries. | Business modules use these boundaries instead of calling global state directly; owner facades own any remaining no-AppContext compatibility defaults. |
rustfs/src/*/storage_api.rs | Root, admin, app, and storage owner-local storage contract/facade boundaries. | Storage helper and ECStore facade access remains visible at local owner boundaries. |
crates/*/storage_api.rs | External crate-local storage facade boundaries for IAM, scanner, heal, notify, observability, Swift, and S3 Select. | External runtime crates consume ECStore runtime state through rustfs_ecstore::api::runtime instead of the direct global facade. |
crates/ecstore/src/runtime/global.rs | ECStore bootstrap/runtime state owner. | Keep internal until ECStore has explicit owner handles for all remaining bootstrap state. |
crates/ecstore/src/runtime/sources.rs | ECStore runtime-source adapter over global state. | Preferred ECStore-internal access path while shrinking direct runtime::global reads. |
Runtime-source modules are the allowed compatibility layer between migrated consumers and process-global state. They must keep these properties:
AppContext handle exists;The architecture guard snapshots the files currently allowed to reference
rustfs_ecstore::api::global directly:
rustfs/src/storage/storage_api.rsThat boundary now keeps only bootstrap writes and lifecycle controls in the
global facade. Read-only runtime getters must be exported through
rustfs_ecstore::api::runtime and consumed through the local storage facade.
New direct uses must either move behind an existing owner-local boundary or
update this plan and the guard in the same reviewed migration PR.
AppContext or ECStore globals directly when
an owner-local runtime-source boundary exists.GLOB-007 is complete when these invariants hold:
rustfs/src/runtime_sources.rs is an AppContext/root facade entrypoint
and no longer composes concrete fallback defaults with unwrap_or,
unwrap_or_else, direct init_global, or direct new_global calls;rustfs_ecstore::api::global
boundary list explicit.Allowed remaining fallbacks are owner compatibility decisions, not resolver fallback families. They are kept so embedded startup, tests, and no-context callers preserve the previous behavior while higher layers continue migrating to explicit AppContext ownership.
ecstore-erasure and storage-cluster remain proposal-only until dependency
cycles and hot-path risks are proven safe. The Phase 7 evaluation is complete
for now: neither split is ready for code movement in this migration round.
The follow-up ECStore module split plan is recorded in
ecstore-module-split-plan.md, including the
remaining SetDisks, lifecycle, replication, and facade-shrink boundaries.
ecstore-erasureCurrent coupling:
rustfs_ecstore::api::erasure.Decision: do not split in code yet. The erasure boundary is a candidate only after the shard-source, disk-error, bitrot, and metrics contracts are explicit enough to avoid a dependency cycle back into ECStore.
Required evidence before proposing the split:
cargo tree -p rustfs-ecstore -e normal --depth 2 snapshot for dependency
impact;rustfs_ecstore::api::erasure and test harnesses;storage-clusterCurrent coupling:
Decision: do not split in code yet. The storage-cluster boundary is a candidate only after remote disk, peer health, lock/quorum, runtime metrics, and endpoint layout contracts are explicit enough to stand below ECStore without circular dependencies.
Required evidence before proposing the split:
rustfs-storage-api, runtime
source owners, or cluster control-plane owners;rustfs_ecstore::api::cluster, api::rpc, and test
fixtures that build local disks or endpoint pools;bucket-lifecycleDecision: do not split in code yet. Lifecycle remains coupled to ECStore object
operations, bucket metadata, SetDisks stale multipart cleanup, tier config,
runtime lifecycle state, scanner metrics, notification/audit side effects, and
replication delete scheduling.
Required evidence before proposing the split:
rustfs_ecstore::api::bucket::lifecycle consumers;bucket-replicationDecision: do not split in code yet. Replication remains coupled to ECStore object APIs, bucket target clients, metadata systems, file metadata replication state, ECStore-owned runtime replication pool/stat handles, bucket monitor state, scanner repair classification, lifecycle-originated deletes, and notification events. RustFS-facing runtime consumers should use storage-owner wrapper handles while that state remains in ECStore.
Required evidence before proposing the split:
rustfs_ecstore::api::bucket::replication consumers;