heimdall-rust-api-disciplinelisted
Install: claude install-skill po4yka/heimdall
# Heimdall Rust API Discipline
## Purpose
Encode API-design discipline from production Rust pitfalls. Apply every rule to every changed public or `pub(crate)` function signature in a diff. Heimdall-specific file references are included where concrete risk exists.
## Borrowed args over owned references
**Severity: WARNING**
Flag `&String`, `&Vec<T>`, and `&PathBuf` in public or crate-public function signatures. The owned-reference shapes force callers to hold an allocation even when they have a slice.
```rust
// BAD
fn scan(path: &PathBuf) {}
fn log(msg: &String) {}
// GOOD
fn scan(path: &std::path::Path) {} // or: impl AsRef<Path>
fn log(msg: &str) {}
```
Risk areas in heimdall (check these paths):
- `src/scanner/` — file-path arguments throughout
- `src/server/` — request/response handler signatures
- `src/oauth/` — token and URL string args
Grep: `rg 'fn .+\(&String|fn .+\(&Vec<|fn .+\(&PathBuf' src/ --type rust -n`
Reference: `crabbook/borrowed_args.md`
## `Fn` callbacks with reference args in async contexts
**Severity: CRITICAL for tokio::spawn closures**
Heimdall uses `tokio::spawn` extensively in `src/server/sse.rs` and `src/scanner/watcher.rs`. Closures passed to `tokio::spawn` must be `'static + Send`. Capturing `&mut State` inside such a closure is a compile error — the reference cannot be `'static`.
Correct patterns:
```rust
// BAD: captures &mut state -- does not compile
tokio::spawn(async move { state.handle(event) });
// GOOD option 1: Arc<Mutex<S