Agent-instruction and architecture docs had drifted from the code: - CLAUDE.md: slim to commands + pointers; fix wrong claim that `make pre-commit` is the full pre-PR gate (that is `make pre-pr`); drop stale pre-#3929 file paths and merged bug narratives - AGENTS.md: drop dead `rust-refactor-helper` skill rule and the hand-maintained (already stale) scoped-AGENTS index; link architecture docs from Sources of Truth - .github/AGENTS.md: replace the outdated copied CI command matrix with a pointer to ci.yml - crates/AGENTS.md: merge duplicated Testing sections - ARCHITECTURE.md: resolve the utils->config contradiction (edges are removed), mark volatile counts as snapshots, fix a bad path - docs/architecture: add README router; move one-shot plans/trackers (rebalance-decommission phases, migration-progress ledger, PR template) to docs/superpowers/plans with archive headers; fix stale source paths in kept inventories (core/sets.rs, core/pools.rs, store/mod.rs, startup_* split from #3671) - docs/operations/tier-ilm-debugging.md: extracted tier debugging playbook with corrected paths - scripts/check_doc_paths.sh: new guard failing pre-commit/pre-pr when instruction/architecture docs reference nonexistent file paths - .claude/skills: add tier-debug and arch-checks repo skills; .gitignore now keeps .claude/skills and docs/operations committable Verification: ./scripts/check_doc_paths.sh, ./scripts/check_architecture_migration_rules.sh (both pass) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
12 KiB
Archived implementation plan/tracker — moved from
docs/architecture/(2026-07). Kept for history; not maintained. File paths inside may reflect the pre-#3929 module layout (e.g.crates/ecstore/src/rebalance.rsis nowcrates/ecstore/src/store/rebalance.rs;set_disk.rsis nowset_disk/).
Rebalance and Decommission Phase 3 Hardening Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Improve operator visibility, auditability, metadata robustness, and documented compatibility after the Phase 1 and Phase 2 safety fixes.
Architecture: Phase 3 should not change core data movement semantics unless a hardening test exposes a safety bug. It adds bounded status data, structured logs, metadata validation tests, and an explicit decision around rebalance completion tolerance.
Tech Stack: Rust, tracing structured logs, admin status DTOs, serde/rmp metadata decoding, existing guardrail scripts, crate-local unit tests.
Scope
This plan covers:
- F11: improve rebalance cleanup failure reporting.
- F12: add structured audit fields for rebalance/decommission operations.
- F13: harden persisted rebalance and pool metadata decoding.
- F14: decide and document rebalance completion threshold behavior.
This plan assumes the safety semantics from Phase 1 and the data movement behavior from Phase 2 are stable.
Shared Principles
- Hardening must not hide safety failures.
- Status fields should be bounded to avoid unbounded metadata growth.
- Logs must be structured, searchable, and free of secrets.
- Metadata compatibility must be explicit: strict where possible, legacy-compatible where necessary.
F11: Rebalance Cleanup Failure Reporting
Decision
Rebalance cleanup failures should not be invisible completion details. Admin status should expose whether completion had cleanup warnings and provide bounded object-level detail.
Files
- Modify:
crates/ecstore/src/rebalance.rs - Modify:
rustfs/src/admin/handlers/rebalance.rs - Possibly modify: admin response DTOs in the same module or related madmin types
- Test: rebalance status and metadata tests
Design
-
Extend cleanup warning metadata.
- Keep existing count.
- Add a bounded list of recent cleanup failures, for example last 10 entries.
- Each entry should include bucket, object, message, and timestamp.
-
Keep metadata bounded.
- Do not store every cleanup failure unboundedly in
rebalance.bin. - Use a ring-buffer style helper or truncate older entries.
- Do not store every cleanup failure unboundedly in
-
Make terminal state visible.
- If rebalance completes with cleanup warnings, status should show warning count and details.
- Avoid reporting a clean completion when source cleanup failed.
Implementation Tasks
- Add a cleanup warning entry struct with bounded retention.
- Add metadata compatibility defaults for older
rebalance.binwithout the new list. - Update
record_rebalance_cleanup_warning_in_metato append bounded entries and update count/last fields. - Update admin status serialization to expose warning count and entries.
- Add tests for one warning, multiple warnings, and bounded truncation.
- Add legacy metadata decode test.
Focused Test Commands
cargo test -p rustfs-ecstore cleanup_warning --lib
cargo test -p rustfs-ecstore rebalance_meta --lib
cargo test -p rustfs rebalance --lib
Acceptance Criteria
- Multiple cleanup failures are visible through count and bounded details.
- Legacy rebalance metadata still decodes.
- Status distinguishes clean completion from completion with cleanup warnings.
Risks
- Adding status fields may affect clients if response schemas are strict. Prefer additive fields with defaults.
F12: Structured Audit Fields
Decision
Rebalance and decommission admin operations should have consistent structured logs for success, rejection, propagation failure, and partial/degraded state.
Files
- Modify:
rustfs/src/admin/handlers/rebalance.rs - Modify:
rustfs/src/admin/handlers/pools.rs - Modify:
crates/ecstore/src/notification_sys.rs - Modify:
crates/ecstore/src/rpc/peer_rest_client.rs - Possibly modify:
scripts/check_logging_guardrails.shor related guardrails if logging rules require updates
Design
-
Define standard fields.
eventcomponentsubsystemactionresultrequest_idwhen availableactoror masked access key when availableremote_addrwhen availablepool_indicesorrebalance_idpeererror
-
Apply to admin handlers.
- Start, stop, cancel, status-affecting operations.
- Authorization failures should remain handled by existing auth paths but should have enough context if already logged.
-
Apply to peer propagation.
- Peer success and failure should use stable event names.
- Partial failure must be warn/error, not info-only.
-
Avoid secret leakage.
- Never log raw credentials, signatures, tokens, or full auth headers.
Implementation Tasks
- Inventory existing rebalance/decommission log events and field names.
- Define a small local helper or convention for masked actor/request fields if one already exists.
- Update rebalance admin start/stop/status logs.
- Update decommission start/cancel/status logs.
- Update notification peer propagation failure logs.
- Add log-capture tests for success, partial failure, and rejected operation where feasible.
- Run logging guardrail script if the repository has one.
Focused Test Commands
cargo test -p rustfs rebalance --lib
cargo test -p rustfs pools --lib
cargo test -p rustfs-ecstore notification --lib
scripts/check_logging_guardrails.sh
Acceptance Criteria
- Operators can answer who requested an operation, what resource it targeted, and which peers failed.
- Partial failures are searchable through stable structured fields.
- Logs contain no secrets.
Risks
- Logging changes can be noisy. Keep high-volume per-object logs out of admin audit events.
F13: Persisted Metadata Decode Hardening
Decision
Persisted rebalance and pool metadata should reject or surface unknown/corrupt fields where compatibility allows. Legacy compatibility must be tested explicitly.
Files
- Modify:
crates/ecstore/src/rebalance.rs - Modify:
crates/ecstore/src/pools.rs - Possibly add fixtures under an existing test fixture directory if one exists
- Test: metadata decode tests in
rebalance.rsandpools.rs
Design
-
Identify persisted structs.
- Rebalance metadata and stats structs.
- Pool metadata and decommission info structs.
-
Choose strictness per struct.
- Use strict unknown-field rejection where metadata is not expected to carry forward-compatible fields.
- For legacy-compatible structs, keep decode lenient but log or validate unknown/unsupported state where possible.
-
Add state validation.
- Reject conflicting terminal states such as complete plus canceled plus running.
- Reject impossible counters or invalid pool indices where existing validation can catch them.
-
Preserve legacy fixtures.
- Existing old metadata must still decode if compatibility is required.
Implementation Tasks
- List all rebalance and pool metadata structs currently deserialized from persisted bytes.
- Add fixture tests for unknown fields, missing critical fields, and conflicting terminal states.
- Add strict serde attributes only where fixtures show compatibility is safe.
- Add post-decode validation helpers for state conflicts.
- Update load paths to surface validation errors with actionable messages.
Focused Test Commands
cargo test -p rustfs-ecstore rebalance_meta --lib
cargo test -p rustfs-ecstore pool_meta --lib
cargo test -p rustfs-ecstore metadata --lib
Acceptance Criteria
- Unknown/corrupt metadata does not silently become an apparently valid operation state.
- Legacy metadata fixtures continue to decode through documented paths.
- Conflicting terminal state is rejected or quarantined.
Risks
- Strict decode can block startup if old metadata contains benign extra fields. Start with tests and post-decode validation before broad strict attributes.
F14: Rebalance Completion Threshold Decision
Decision
RustFS must explicitly choose whether to match MinIO's tolerance-based rebalance completion or keep strict completion. The recommended default is to match MinIO unless RustFS has a documented reason to move more data.
Files
- Modify:
crates/ecstore/src/rebalance.rs - Possibly modify: admin docs if present
- Test: rebalance goal/completion tests in
rebalance.rs
Design Options
-
Match MinIO tolerance.
- Complete when pool free-space ratio is within the MinIO-like tolerance of the goal.
- Reduces movement and operational time.
- Best for compatibility.
-
Keep strict behavior and document it.
- No code behavior change.
- Add tests proving strict behavior is intentional.
- Status/docs should avoid implying MinIO-compatible tolerance.
-
Configurable tolerance.
- Most flexible but not recommended unless operators need it.
- Adds configuration and support burden.
Recommended Plan
Start with option 1 if compatibility is the goal. If maintainers prefer strictness, implement option 2 with explicit tests and documentation.
Implementation Tasks
- Add tests that capture current strict behavior around the completion goal.
- Add tests for MinIO-like tolerance behavior.
- Confirm maintainers choose MinIO-compatible or strict behavior.
- Implement the selected threshold behavior.
- Update status/docs comments so completion semantics are clear.
Focused Test Commands
cargo test -p rustfs-ecstore rebalance_goal --lib
cargo test -p rustfs-ecstore check_if_rebalance_done --lib
cargo test -p rustfs-ecstore rebalance --lib
Acceptance Criteria
- Completion threshold behavior is covered by deterministic tests.
- Operators can understand whether RustFS matches MinIO tolerance.
- Empty-queue completion path remains valid.
Risks
- Changing threshold may alter operational expectations for existing users. Document the change if behavior changes.
Phase 3 Test Matrix
Run after individual fix tests pass:
cargo test -p rustfs-ecstore rebalance_meta --lib
cargo test -p rustfs-ecstore pool_meta --lib
cargo test -p rustfs-ecstore rebalance --lib
cargo test -p rustfs rebalance --lib
cargo test -p rustfs pools --lib
cargo fmt --all --check
If logging guardrails are relevant:
scripts/check_logging_guardrails.sh
Before PR:
cargo fmt --all
cargo fmt --all --check
make pre-commit
Clean generated build artifacts after build-based verification.
Suggested PR Split
- PR 1: F11 cleanup warning status.
- PR 2: F12 structured audit fields.
- PR 3: F13 metadata decode hardening.
- PR 4: F14 completion threshold decision and tests.
F11 may depend on Phase 2 cleanup semantics if F10 changes retry behavior. F12 can be done anytime after Phase 1 defines distributed failure semantics.
Open Questions Before Coding
- What is the maximum number of cleanup warning entries to keep in persisted rebalance metadata?
- Which actor identity is safe and useful to log for admin requests?
- Should metadata unknown fields fail startup, warn and continue, or quarantine only the affected operation?
- Should RustFS match MinIO's rebalance completion tolerance by default?