# Agent Configuration

**IMPORTANT:** `xxx | keep | zzz` must be as performant as possible in all situations.

## Build/Test Commands

**IMPORTANT**: Do not run the application, start the web server, or the trunk server.
**IMPORTANT:** Cargo commands cannot be run in parallel. Prefix all commands with `TERM=dumb`.

```bash
TERM=dumb cargo check              # Fast compile check
TERM=dumb cargo build              # Build project
TERM=dumb cargo test               # Run all tests
TERM=dumb cargo test test_name     # Run specific test by name substring
TERM=dumb cargo test -- --nocapture  # Verbose test output
TERM=dumb cargo fmt --check        # Check formatting
TERM=dumb cargo fmt                # Apply formatting
TERM=dumb cargo clippy -- -D warnings  # Lint (warnings are errors)
TERM=dumb cargo build --release    # Release build
TERM=dumb cargo build --features server  # With server feature
```

## Code Conventions

- `anyhow::Result` for error handling; `thiserror` for custom error types (`src/services/error.rs`)
- Plugin traits: `CompressionEngine`, `FilterPlugin`, `MetaPlugin`
- Dynamic trait objects use `clone_box()` for `Clone` on `Box<dyn Trait>`
- Plugin registration uses `ctor` constructors at module load time
- Filter plugins must implement `filter()`, `clone_box()`, and `options()`
- Meta plugins extend `BaseMetaPlugin` for boilerplate reduction
- Enum string representations: `#[strum(serialize_all = "snake_case")]`
- Lint rules: `deny(clippy::all)`, `deny(unsafe_code)` (except `libc::umask` in main.rs)
- Feature flags: `default = ["magic", "lz4", "gzip"]`; optional: `server`, `swagger`

## Testing

- Tests in `src/tests/` mirroring `src/` structure; shared helpers in `src/tests/common/test_helpers.rs`
- Key helpers: `create_temp_dir()`, `create_temp_db()`, `test_compression_engine()`
- Test naming: `test_<feature>_<scenario>`

## Streaming Constraint

**At no point should the whole file be in memory at once.** All I/O must use fixed-size buffers:

- `PIPESIZE` = 8192 bytes (`src/common/mod.rs:10`)
- Server POST body streams through `save_item_raw_streaming` via `MpscReader`
- Server GET content streams via streaming reader (not `read_to_end`)
- When `max_body_size` is exceeded, return `413` but keep the partial item (nonfatal by design)
- Filter/meta plugins use `PIPESIZE`-sized buffers

## HTML Rendering

- Use `html_escape` crate for all user-controlled data in HTML pages
- `esc()` for text content, `esc_attr()` for HTML attributes
- Security headers middleware: `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`, `Referrer-Policy: strict-origin-when-cross-origin`
