--- name: rust-engineering description: > Apply pragmatic Rust engineering conventions when implementing, modifying, reviewing, or refactoring Rust code. Use for Rust CLI tools, system utilities, daemons, filesystem operations, network integrations, and security-sensitive code. Based on the official Rust guidelines and selected Google Rust Style Guide practices. --- # Rust Engineering ## Instruction precedence 1. Follow explicit user requirements. 2. Read repository-specific AGENTS.md and project instructions. 3. Respect established APIs, architecture, and compatibility. 4. Apply this skill to new or modified code. 5. Consult Google's Rust guide when a design choice is unclear. Do not mechanically refactor unrelated code. Treat Google-specific Chrome, Android, and Fuchsia rules as optional. ## 1. Readability and scope - Prefer straightforward, explicit, idiomatic Rust. - Optimize for maintainability over brevity. - Keep functions cohesive and responsibilities clear. - Prefer loops or matches over obscure iterator chains. - Avoid speculative abstractions, traits, and generics. - Preserve existing module and crate boundaries unless changes are justified by the task. - Never introduce stylistic churn unrelated to the task. ## 2. Ownership and borrowing - Prefer &str over &String for read-only string inputs. - Prefer &Path over &PathBuf for read-only path inputs. - Prefer &[T] over &Vec for read-only sequence inputs. - Avoid clone() and to_owned() without an ownership reason. - Move values when ownership transfer is intended. - Use Arc, Rc, Mutex, and RwLock only when justified. - Avoid holding locks across .await. - Minimize lifetime and duplication of sensitive data. - Never optimize ownership at the expense of correctness. ## 3. Types and APIs - Prefer enums over bool parameters when expressing policies. - Use newtypes for easily confused values and critical invariants. - Prefer named fields over positional tuples for domain data. - Implement standard traits where semantically appropriate. - Implement Default for options/configuration structs when a meaningful default exists. - Introduce traits only for genuine behavioral abstractions. - Avoid unnecessary public APIs. - Consider #[must_use] for easily ignored important results. - Consider #[non_exhaustive] for externally consumed APIs. ## 4. Errors and panics - Return Result for recoverable failures. - Use ? to propagate errors. - Add actionable context at meaningful boundaries. - Prefer match, if let, and ok_or_else over unwrap(). - Never panic on untrusted input or expected runtime failures. - Use expect() only for clearly documented invariants. - Do not silently discard errors. - Never expose credentials, tokens, private keys, or sensitive payloads in errors or logs. ## 5. Naming, imports, and formatting - Run rustfmt; do not manually fight its output. - Respect repository-specific rustfmt.toml. - Use descriptive Rust-standard identifiers. - Avoid ambiguous abbreviations. - Avoid glob imports in production code. - Prefer explicit, comprehensible imports. - Use module-qualified calls when they improve clarity. - Follow existing naming conventions unless misleading. ## 6. Documentation - Document public APIs and non-obvious behavior. - Explain safety, ownership, and concurrency invariants. - Document assumptions that affect correctness. - Prefer comments explaining why rather than what. - Keep examples and documentation synchronized with behavior. - Avoid redundant comments and documentation churn. ## 7. Concurrency and security - Use the project's existing sync/async architecture. - Do not add new runtimes or synchronization mechanisms without justification. - Define lock poisoning and failure behavior deliberately. - Avoid broad critical sections and unnecessary contention. - Avoid logging secrets or raw sensitive request data. - Validate external data before using it for sensitive operations. - Preserve authentication and authorization boundaries. - Treat unsafe code as exceptional; document invariants and test the affected behavior. ## 8. Testing - Add focused tests for new behavior and bug fixes. - Cover success, failure, and relevant edge cases. - Test invariants instead of implementation details. - Use mocks/fakes at existing external integration boundaries. - Prefer deterministic tests without live credentials. - Test filesystem operations with isolated temporary directories. - Do not weaken tests to make code changes pass. - Preserve integration and cross-platform behavior. ## 9. Compatibility - Follow the Rust edition declared in the project's `Cargo.toml`; do not assume the latest edition. Keep syntax and edition-sensitive behavior compatible with that declaration. - Preserve CLI flags, output contracts, and exit behavior. - Preserve public APIs and documented configuration formats. - Avoid adding dependencies without concrete value. - Do not change persistent data formats without migration review. - Treat security-relevant behavioral changes as high risk. - Explicitly disclose possible breaking changes. ## 10. Project-specific rules ### poof - Preserve user-space installation behavior. - Keep command dispatch separate from core domain operations. - Maintain GitHub release and asset-selection semantics. - Validate paths, archive entries, and extracted destinations. - Avoid unintended filesystem writes and deletions. - Maintain platform-specific behavior and installation layouts. - Preserve release, update, and uninstall invariants. ### vault-conductor - Never write private keys to disk. - Avoid unnecessary cloning of private-key material. - Keep sensitive values out of logs and errors. - Preserve SSH-agent protocol behavior. - Preserve Bitwarden fetching and cache semantics. - Maintain appropriate synchronization around key caches. - Handle missing, invalid, and inaccessible keys safely. - Preserve SecretFetcher or equivalent test boundaries. - Never require real production credentials in unit tests. ## 11. Execution workflow Before changing code: 1. Read AGENTS.md, Cargo.toml, rustfmt.toml, clippy.toml, rust-toolchain.toml, and relevant modules when present. 2. Check git status and identify existing user changes. 3. Inspect related call sites and existing tests. 4. Make the smallest change that fulfills the request. After changing code: 5. Run cargo fmt --all -- --check. 6. Run cargo clippy --all-targets -- -D warnings, or the repository's configured equivalent. 7. Run cargo test, or the repository's relevant test command. 8. Run relevant just recipes and additional checks when available. 9. Review git diff for unrelated changes and sensitive output. 10. Report results and any skipped or failed checks. Never claim tests passed unless actually executed. Do not commit, push, tag, or publish without authorization. ## 12. Review output contract Report: - Changes made and their purpose. - Relevant Google Rust guideline(s). - Ownership, error, security, or compatibility implications. - Tests and checks executed, with pass/fail status. - Remaining risks or unverified assumptions. Classify review findings as: - BLOCKER: Security vulnerability, data loss, correctness failure. - HIGH: Panic, broken error handling, compatibility regression. - MEDIUM: Ownership inefficiency, unclear API, missing tests. - LOW: Nonessential readability or naming improvement. Prioritize correctness and safety over stylistic preferences. ## References - https://google.github.io/styleguide/rustguide.html - https://doc.rust-lang.org/style-guide/ - https://rust-lang.github.io/api-guidelines/ - https://doc.rust-lang.org/clippy/