mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 08:18:18 +00:00
b5e565c0ce
* docs: update security advisory lessons * chore(agents): add Rust code quality rules and skill Add rules derived from full-project code review (48 findings across 7 dimensions) to prevent recurring issues in agent-generated code. AGENTS.md changes: - crates/AGENTS.md: error type design, concurrency, recursion safety, type casting, test quality rules - root AGENTS.md: serde safety, naming conventions - crates/ecstore/AGENTS.md: allocation discipline, lock ordering, recursion safety, dead code policy - crates/notify/AGENTS.md: lock ordering for runtime_view/facade Skill changes: - code-change-verification: add Rust-specific checks (unwrap, as cast, clone, lock order, recursion, error types, test assertions) - security-advisory-lessons: add serde deserialization safety pattern - NEW rust-code-quality: automated scan + manual review checklist
3.1 KiB
3.1 KiB
Crates Instructions
Applies to all paths under crates/.
Library Design
- Treat crate code as reusable library code by default.
- Prefer
thiserrorfor library-facing error types. - Do not use
unwrap(),expect(), or panic-driven control flow outside tests.
Testing
- Keep unit tests close to the module they test.
- Keep integration tests under each crate's
tests/directory. - Add regression tests for bug fixes and behavior changes.
Error Type Design
- Public API functions must return a typed error enum (preferably
thiserror-derived), neverResult<_, String>. - Do not use
Box<dyn Error>orBox<dyn Error + Send + Sync>in public trait methods or struct methods. Define a concrete error type with specific variants. - When implementing
std::error::Error, always overridefn source()if you store an inner error. Breaking the error chain makes debugging impossible. - Internal helpers that return
Result<_, String>and are immediately wrapped via.map_err(Error::other)should return the actual error type directly.
Concurrency
- Document lock acquisition order when a module uses multiple locks. Never acquire the same set of locks in different orders across code paths.
- Never hold a
tokio::sync::RwLock/Mutexwrite guard across.awaitpoints unless the critical section is unavoidably async and the hold time is bounded. - Prefer
compare_exchangeloops over load-then-store for concurrent counters (peak values, adaptive heuristics). - When resetting multi-field atomic statistics, use a version/sequence counter or accept that concurrent readers may see partial snapshots; document the tradeoff.
std::sync::Mutexis acceptable in async context only when held for a brief, non-await-containing critical section. If in doubt, usetokio::sync::Mutex.
Recursion Safety
- Recursive tree/graph traversals must have a depth limit (e.g.,
max_depthcounter) or use an iterative approach with an explicitVecstack. - This applies to cache trees, directory walks, and any user-influenced hierarchy.
- A corrupted or malicious input must not be able to overflow the thread stack.
Type Casting
- Never use
asfor numeric conversions that may truncate or overflow. Usetry_into()with explicit error handling, or clamp withvalue.max(0) as usizewhen the domain is bounded. f64 as usizesaturates but is fragile; clamp to[0, usize::MAX as f64]first.- Treat every
ascast in a PR review as a potential bug; require justification.
Testing
- Keep unit tests close to the module they test.
- Keep integration tests under each crate's
tests/directory. - Add regression tests for bug fixes and behavior changes.
- Every test function must contain at least one
assert!/assert_eq!/assert_matches!. A test that only calls code without asserting is not a test. - In tests, prefer
.expect("context: what was being tested")over bare.unwrap(). A test failure should tell you which operation failed and with what input.
Async and Performance
- Keep async paths non-blocking.
- Move CPU-heavy operations out of async hot paths with
tokio::task::spawn_blockingwhen appropriate.