docs: document SQLite config and HTTP middleware stack in CLAUDE.md

This commit is contained in:
Jon Seager 2026-02-06 18:05:21 +00:00
parent 5c75c39883
commit 5bcd01d358
No known key found for this signature in database

View file

@ -109,7 +109,7 @@ Only reset state on `finished` or `error`, never unconditionally.
**7. Use token-based text classes, never hardcoded `text-stone-*`.** Always use `text-text`, `text-text-secondary`, `text-text-muted` which adapt between light and dark themes.
**8. Static assets need explicit routes.** All assets are embedded at compile time via `include_str!()`/`include_bytes!()` with explicit routes in `application/routes/mod.rs`. There is no `tower-http` static file serving.
**8. Static assets need explicit routes and cache headers.** All assets are embedded at compile time via `include_str!()`/`include_bytes!()` with explicit routes in `application/routes/app/mod.rs`. There is no `tower-http` static file serving. Every static asset handler must return a `cache-control: public, max-age=604800` header alongside `content-type`.
**9. CSP must be updated when adding external resources.** The `Content-Security-Policy` header is set in `application/routes/mod.rs`. If you add a new external script, stylesheet, font, or image source, update the corresponding CSP directive (`script-src`, `style-src`, `font-src`, `img-src`) or the browser will block it silently. Datastar requires `'unsafe-inline'` and `'unsafe-eval'` in `script-src`.
@ -121,6 +121,25 @@ Only reset state on `finished` or `error`, never unconditionally.
## Backend Patterns
### SQLite Configuration
`infrastructure/database.rs` configures SQLite pragmas at connection time:
| Pragma | Value | Purpose |
|--------|-------|---------|
| `foreign_keys` | `ON` | Enforce FK constraints |
| `journal_mode` | `WAL` | Concurrent reads during writes |
| `synchronous` | `NORMAL` | Faster writes (safe with WAL) |
| `cache_size` | `-8000` | 8 MB page cache |
| `temp_store` | `MEMORY` | Temp tables in RAM |
| `busy_timeout` | `5000` | Wait up to 5s on lock contention |
When adding new pragmas, add them after the existing ones in `Database::connect()`. Connection pool is capped at 5 — appropriate for SQLite's single-writer model.
### HTTP Middleware Stack
The middleware stack in `application/routes/mod.rs` applies layers in this order (outermost first): request tracing, cookie parsing, body size limit, security headers (`X-Content-Type-Options`, `X-Frame-Options`, `Referrer-Policy`, `CSP`, `HSTS`), and gzip compression. When adding new middleware, place it in the `ServiceBuilder` chain at the appropriate position.
### Repository Pattern
All data access goes through trait-based repositories defined in `domain/repositories.rs`. SQL implementations live in `infrastructure/repositories/`, each using a private `Record` struct with a `to_domain()` method to convert database rows to domain entities. Use typed ID wrappers from `domain/ids.rs` (e.g., `RoastId`, `BagId`) — never raw `i64`.