Skip to content

Latest commit

 

History

History
98 lines (71 loc) · 6.35 KB

File metadata and controls

98 lines (71 loc) · 6.35 KB

Error Handling

  • Never use .unwrap() or .expect() in production code. Use ? operator or match with explicit error handling.
  • Every function returning Result must have a concrete error type, not Box<dyn Error>. Use thiserror crate 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 Result from external crates must be converted to your error type before returning from public functions.

Async and Concurrency

  • 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 .await on the join handle or explicit let _ = handle; comment explaining why it's fire-and-forget.
  • Channels must specify capacity: mpsc::channel(100) not mpsc::channel(). Document why that capacity was chosen.
  • Never use std::sync::Mutex in async code. Use tokio::sync::Mutex or parking_lot::Mutex with justification comment.

Unsafe Code

  • unsafe blocks are forbidden except in src/ffi/ directory. Every unsafe block must have a comment explaining the safety invariant.
  • Never use unsafe to suppress Clippy warnings. Fix the underlying issue or disable the warning with #[allow(...)] and document why.
  • Pointer arithmetic must be bounds-checked before the unsafe block, not inside it.

Type System and Generics

  • Never use as type casts for numeric types. Use TryFrom or explicit conversion functions.
  • Generic functions must have trait bounds on every type parameter. No bare <T>.
  • Never use String as a function parameter. Use &str for owned or borrowed strings, or impl AsRef<str> for flexibility.
  • Lifetimes must be explicit in struct definitions. Never rely on elision in public APIs.

File Structure and Naming

  • Source files must be in src/ directory. Subdirectories map to module hierarchy: src/api/handlers/user.rs becomes mod api { mod handlers { mod user } }.
  • Module files must be named after their primary type or responsibility: src/models/user.rs exports User struct, src/handlers/auth.rs exports auth handlers.
  • Test files must be in tests/ directory with path mirroring source: tests/api/handlers/user.rs tests src/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 tests block at the end.

Naming Conventions

  • 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 fn keyword required.
  • Type aliases: PascalCase. Never create type aliases for Result<T, E> — use explicit Result in signatures.
  • Variables holding Result: prefix with result_ or outcome_. Example: let result_user = fetch_user(id)?;

Clippy and Linting

  • Every Clippy warning must be fixed or explicitly allowed with #[allow(clippy::...)] and a comment explaining why.
  • Never commit code with cargo clippy -- -D warnings failing.
  • #[allow(...)] attributes must be scoped to the smallest possible item (function, not module).

Testing

  • 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() not test_user().
  • Use #[tokio::test] for async tests, never #[test] with .block_on().
  • Mock external dependencies with mockall crate. Never hardcode test data in production code.
  • Test files must use assert_eq!() for equality, assert!() for booleans. Never use unwrap() in tests — use expect() with a message.

Security

  • Never hardcode secrets, API keys, or credentials. Use environment variables with dotenv crate and validate at startup.
  • All user input must be validated at the API boundary using validator crate or custom validation functions.
  • Database queries must use parameterized queries. Never concatenate user input into SQL strings.
  • Passwords must be hashed with argon2 crate. Never store plaintext or use bcrypt without a reason comment.
  • HTTP responses must set Content-Type header explicitly. Never rely on defaults.

Dependencies and Imports

  • Dependencies must be pinned to minor version: tokio = "1.35" not tokio = "1" or tokio = "1.35.*".
  • Unused imports must be removed. Run cargo clippy to detect them.
  • Never import entire modules with use module::*. Import specific items: use module::{Item1, Item2}.
  • Re-exports in lib.rs must be explicit: pub use crate::models::User; not pub mod models;.

Documentation

  • Every public function must have a doc comment with ///. Include example usage for complex functions.
  • Doc comments must include # Errors section describing when Result::Err is returned.
  • Doc comments must include # Panics section if the function can panic (it shouldn't in production code).
  • Struct fields must have doc comments if public.

Serialization and Validation

  • Serde derive must include #[serde(deny_unknown_fields)] for request DTOs to catch API misuse.
  • Serde rename must 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 with From or Into.
  • JSON responses must use serde_json::json!() macro only in tests. Use typed structs in production.

Configuration

  • Configuration must be loaded once at startup in main() and passed as dependency, never read from environment in functions.
  • Configuration struct must derive Debug and Clone. Never use Arc<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>