- Never use
.unwrap()or.expect()in production code. Use?operator ormatchwith explicit error handling. - Every function returning
Resultmust have a concrete error type, notBox<dyn Error>. Usethiserrorcrate for custom error enums. - Error types must include context: use
#[from]and#[source]attributes. Never create errors with only a string message. - Errors crossing module boundaries must be wrapped in the calling module's error type. Never expose internal error types publicly.
- Every
Resultfrom external crates must be converted to your error type before returning from public functions.
- Never call blocking operations (file I/O, database queries, network calls) directly in async functions. Use
tokio::task::spawn_blocking()or dedicated async libraries. - Every
tokio::spawn()must have.awaiton the join handle or explicitlet _ = handle;comment explaining why it's fire-and-forget. - Channels must specify capacity:
mpsc::channel(100)notmpsc::channel(). Document why that capacity was chosen. - Never use
std::sync::Mutexin async code. Usetokio::sync::Mutexorparking_lot::Mutexwith justification comment.
unsafeblocks are forbidden except insrc/ffi/directory. Everyunsafeblock must have a comment explaining the safety invariant.- Never use
unsafeto suppress Clippy warnings. Fix the underlying issue or disable the warning with#[allow(...)]and document why. - Pointer arithmetic must be bounds-checked before the
unsafeblock, not inside it.
- Never use
astype casts for numeric types. UseTryFromor explicit conversion functions. - Generic functions must have trait bounds on every type parameter. No bare
<T>. - Never use
Stringas a function parameter. Use&strfor owned or borrowed strings, orimpl AsRef<str>for flexibility. - Lifetimes must be explicit in struct definitions. Never rely on elision in public APIs.
- Source files must be in
src/directory. Subdirectories map to module hierarchy:src/api/handlers/user.rsbecomesmod api { mod handlers { mod user } }. - Module files must be named after their primary type or responsibility:
src/models/user.rsexportsUserstruct,src/handlers/auth.rsexports auth handlers. - Test files must be in
tests/directory with path mirroring source:tests/api/handlers/user.rstestssrc/api/handlers/user.rs. - Integration tests must be in
tests/integration/with one file per feature:tests/integration/user_creation.rs. - Unit tests must be in the same file as code, in a
#[cfg(test)] mod testsblock at the end.
- Struct names:
PascalCase. Enum names:PascalCase. Enum variants:PascalCase. - Function names:
snake_case. Private functions: prefix with_only if intentionally hidden from IDE autocomplete. - Constants:
SCREAMING_SNAKE_CASE. Const functions:const fnkeyword required. - Type aliases:
PascalCase. Never create type aliases forResult<T, E>— use explicitResultin signatures. - Variables holding
Result: prefix withresult_oroutcome_. Example:let result_user = fetch_user(id)?;
- Every Clippy warning must be fixed or explicitly allowed with
#[allow(clippy::...)]and a comment explaining why. - Never commit code with
cargo clippy -- -D warningsfailing. #[allow(...)]attributes must be scoped to the smallest possible item (function, not module).
- Every public function must have at least one test. Private functions must have tests if they contain business logic.
- Test function names must describe the scenario:
test_user_creation_with_invalid_email_fails()nottest_user(). - Use
#[tokio::test]for async tests, never#[test]with.block_on(). - Mock external dependencies with
mockallcrate. Never hardcode test data in production code. - Test files must use
assert_eq!()for equality,assert!()for booleans. Never useunwrap()in tests — useexpect()with a message.
- Never hardcode secrets, API keys, or credentials. Use environment variables with
dotenvcrate and validate at startup. - All user input must be validated at the API boundary using
validatorcrate or custom validation functions. - Database queries must use parameterized queries. Never concatenate user input into SQL strings.
- Passwords must be hashed with
argon2crate. Never store plaintext or usebcryptwithout a reason comment. - HTTP responses must set
Content-Typeheader explicitly. Never rely on defaults.
- Dependencies must be pinned to minor version:
tokio = "1.35"nottokio = "1"ortokio = "1.35.*". - Unused imports must be removed. Run
cargo clippyto detect them. - Never import entire modules with
use module::*. Import specific items:use module::{Item1, Item2}. - Re-exports in
lib.rsmust be explicit:pub use crate::models::User;notpub mod models;.
- Every public function must have a doc comment with
///. Include example usage for complex functions. - Doc comments must include
# Errorssection describing whenResult::Erris returned. - Doc comments must include
# Panicssection if the function can panic (it shouldn't in production code). - Struct fields must have doc comments if public.
- Serde
derivemust include#[serde(deny_unknown_fields)]for request DTOs to catch API misuse. - Serde
renamemust be used consistently:#[serde(rename_all = "snake_case")]for all structs in API layer. - Never deserialize directly into domain models. Use separate DTO types in
src/api/dto/and convert withFromorInto. - JSON responses must use
serde_json::json!()macro only in tests. Use typed structs in production.
- Configuration must be loaded once at startup in
main()and passed as dependency, never read from environment in functions. - Configuration struct must derive
DebugandClone. Never useArc<Mutex<Config>>. - Feature flags must be used for optional functionality:
#[cfg(feature = "metrics")]not runtime checks.
Source: Codelibrium — the marketplace for AI behaviour files. Browse multiple rulesets at codelibrium.com or install via CLI:
npx codelibrium-cli install <ruleset-name>