Skip to content

Commit 76dadce

Browse files
authored
Merge pull request #2 from douglaz/fix/security-and-validation-improvements
Fix security issues and improve input validation
2 parents ca02910 + 127f39f commit 76dadce

File tree

4 files changed

+279
-42
lines changed

4 files changed

+279
-42
lines changed

CONVENTIONS.md

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# Rust Coding Conventions
2+
3+
## String Interpolation
4+
For format!, println!, info!, debug!, and similar macros:
5+
6+
### Correct Usage:
7+
- ALWAYS use direct variable names when they match the placeholder name:
8+
```rust
9+
let name = "John";
10+
println!("Hello {name}"); // GOOD - Direct use of variable name in placeholder
11+
12+
// This also applies to all logging macros
13+
let endpoint = "users";
14+
debug!("Processing request for {endpoint}"); // GOOD
15+
```
16+
17+
- ONLY use named parameters when using a property or method:
18+
```rust
19+
println!("Count: {count}", count = items.len()); // GOOD - Method call needs named parameter
20+
```
21+
22+
- ALWAYS use placeholder names that match the variable names. NEVER create temporary variables just to match placeholder names:
23+
```rust
24+
// GOOD - Placeholder name matches variable name
25+
println!("Checked {files_checked} files");
26+
27+
// GOOD - Named parameter for method call
28+
println!("Found {errors_count} errors", errors_count = errors.len());
29+
30+
// BAD - Don't create temporary variables to match placeholders
31+
let files = files_checked; // DON'T do this
32+
let errors = errors.len(); // DON'T do this
33+
println!("Checked {files} files, found {errors} errors");
34+
```
35+
36+
### Incorrect Usage:
37+
- Don't use positional arguments:
38+
```rust
39+
let name = "John";
40+
println!("Hello {}", name); // BAD - No named placeholder
41+
```
42+
43+
- Don't use redundant named parameters when the variable name matches:
44+
```rust
45+
let name = "John";
46+
println!("Hello {name}", name = name); // BAD - Redundant, just use "{name}"
47+
```
48+
49+
- Don't use different names unnecessarily:
50+
```rust
51+
let name = "John";
52+
println!("Hello {user}", user = name); // BAD - Not property or method, just use "{name}" directly
53+
```
54+
55+
## Error Handling
56+
57+
### Correct Usage:
58+
- ALWAYS use anyhow for error handling, particularly bail! and ensure!:
59+
```rust
60+
// For conditional checks
61+
ensure!(condition, "Error message with {value}");
62+
63+
// For early returns with errors
64+
bail!("Failed with error: {error_message}");
65+
```
66+
67+
- IMPORTANT: When using `.context()` vs `.with_context()` for error handling:
68+
```rust
69+
// For static error messages with no variables:
70+
let result = some_operation.context("Operation failed")?;
71+
72+
// For error messages with variables - ALWAYS use with_context with a closure and format!:
73+
let id = "123";
74+
75+
// GOOD - Direct variable name in placeholder for simple variables
76+
let result = some_operation
77+
.with_context(|| format!("Failed to process item {id}"))?;
78+
79+
// GOOD - Named parameter for property or method calls
80+
let path = std::path::Path::new("file.txt");
81+
let result = std::fs::read_to_string(path)
82+
.with_context(|| format!("Failed to read file: {path}", path = path.display()))?;
83+
84+
// BAD - Don't use positional parameters
85+
// .with_context(|| format!("Failed to read file: {}", path.display()))?
86+
87+
// NEVER use context() with variables directly in the string - this won't work:
88+
// BAD: .context("Failed to process item {id}") // variables won't interpolate!
89+
90+
// NEVER use context() with format!() - this is inneficient!:
91+
// BAD: .context(format!("Failed to process item {id}"))? // use .with_context(|| format!(...))
92+
```
93+
94+
- REMEMBER: All string interpolation rules apply to ALL format strings, including those inside `with_context` closures
95+
96+
### Incorrect Usage:
97+
- NEVER use unwrap() or panic!:
98+
```rust
99+
// BAD - Will crash on None:
100+
let result = optional_value.unwrap();
101+
102+
// BAD - Will crash on Err:
103+
let data = fallible_operation().unwrap();
104+
105+
// BAD - Explicit panic:
106+
panic!("This failed");
107+
```
108+
109+
- Avoid using .ok() or .expect() to silently ignore errors:
110+
```rust
111+
// BAD - Silently ignores errors:
112+
std::fs::remove_file(path).ok();
113+
114+
// BETTER - Log the error but continue:
115+
if let Err(e) = std::fs::remove_file(path) {
116+
debug!("Failed to remove file: {e}");
117+
}
118+
```
119+
120+
## Code Quality Standards
121+
122+
### Always Run After Significant Changes:
123+
1. **Format code** - Ensures consistent code style:
124+
```bash
125+
cargo fmt --all
126+
```
127+
128+
2. **Run clippy** - Catches common mistakes and suggests improvements:
129+
```bash
130+
cargo clippy --locked --offline --workspace --all-targets -- --deny warnings --allow deprecated
131+
```
132+
133+
3. **Run tests** - Ensures no regressions:
134+
```bash
135+
cargo test
136+
```
137+
138+
### When to Run These Commands:
139+
- After implementing a new feature
140+
- After refactoring existing code
141+
- Before creating a pull request
142+
- After resolving merge conflicts
143+
- After any changes that touch multiple files
144+
145+
**Important**: Code must be properly formatted and pass all clippy checks before being committed to the repository.

flake.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
rustToolchain
2828
pkg-config
2929
pkgsStatic.stdenv.cc
30+
gh
3031
];
3132

3233
CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER = "${pkgs.pkgsStatic.stdenv.cc}/bin/${pkgs.pkgsStatic.stdenv.cc.targetPrefix}cc";

0 commit comments

Comments
 (0)