Menu
AkurAI-Build
publicLatest change 2a1193541cf008c406be9f347e44150a58a66130 - docs: preserve the architecture review, backlog, and schema policy by Olafur Bui
# ARCHITECT REVIEW 2/10 — Dependency & Framework Choices (bunfork)
Note: `plan.md` / `progress.md` do not exist in the repo; review is based on Cargo.toml, Cargo.lock, README.md, and src/*.rs.
## Overall assessment
The dependency tree is lean (132 lockfile packages) and every declared dependency is actually used and used well: `subtle::ConstantTimeEq` for secret comparison (src/db.rs:18, src/server.rs:25), `Zeroizing` for keys, `getrandom::fill` for keygen (src/db.rs:455), rusqlite `limits` feature exercised (src/db.rs:645-653) with extensive `DbConfig` hardening, `DefaultBodyLimit::max(1 MiB)` (src/server.rs:240), and graceful SIGTERM shutdown (src/server.rs:251). Versions are current in the lockfile (axum 0.8.9, tower-http 0.7.0, tokio 1.52.3, minijinja 2.21.0, hyper 1.10.1, tracing-subscriber 0.3.23). No bloat deps (no reqwest, no chrono, no regex). Framework choices (axum + minijinja + rusqlite/SQLCipher) fit the stated "small, secure Rust-first" goal.
## Prioritized suggestions
**P1 — Add automated advisory monitoring for the vendored OpenSSL stack.** `bundled-sqlcipher-vendored-openssl` statically links openssl-src `300.6.1+3.6.3` (Cargo.lock:669-671). Distro OpenSSL patches will never reach this binary; a libcrypto CVE requires a `cargo update -p openssl-src` + rebuild + redeploy. Vendoring is a defensible choice for reproducibility, but there is no `deny.toml`, no `.github/` CI, and no documented update cadence. Add `cargo audit`/`cargo deny` in CI and document the rebuild-on-advisory procedure.
**P1 — The `=0.40.1` rusqlite pin gives false full-stack pinning.** The exact pin blocks semver-compatible rusqlite patch fixes, yet does *not* pin what actually matters for security: libsqlite3-sys 0.38.1 (→ SQLCipher C code) and openssl-src are caret-ranged transitive deps, so a bare `cargo update` still bumps them. Real determinism comes from Cargo.lock + `--locked` (which the README build already uses). Either drop the `=` and rely on `--locked`, or document the pin rationale and pin `libsqlite3-sys` explicitly too. Current state is the worst of both.
**P1 — Drop unmaintained `fs2`; use std file locking.** fs2 0.4.3 last released ~2018. `File::{lock, lock_shared, try_lock, unlock}` are stable since Rust 1.89 and the toolchain here is 1.97 stable (`rust-toolchain.toml` = stable channel). All three call sites (src/db.rs:81,94,499; src/main.rs:633,810) map directly to std. Removes one unmaintained crate from a security-focused tree.
**P1 — Missing request/header timeouts on a LAN-visible listener.** `axum::serve` on `0.0.0.0:3100` has no read/header timeout — slow-loris can pin connections. Add tower-http's `timeout` feature (`TimeoutLayer`) or hyper-util server builder timeouts. This is the one genuinely *missing* dependency capability.
**P2 — Drop the unused tower-http `fs` feature.** No `ServeDir`/`ServeFile` anywhere; static and public assets are preloaded into memory by design (README: "without request-time filesystem reads"). Only `compression-gzip` and `trace` are used (src/server.rs:26). Removing `fs` cuts code and compile surface.
**P2 — Tracing default filter silences per-request logs.** Default `EnvFilter` is `bunfork=info,tower_http=info` (src/main.rs:1029), but `TraceLayer::new_for_http()` emits spans/events at DEBUG by default — so HTTP request logging is effectively failure-only unless `RUST_LOG` is set. Either configure `DefaultMakeSpan`/`DefaultOnResponse` at `Level::INFO`, or set `tower_http=debug` in the default filter, whichever matches intent.
**P2 — Trim axum default features.** Only `Json`, `extract::Path/OriginalUri/State`, and `serve` are used. `default-features = false` plus `http1, json, tokio, query, original-uri, matched-path` (as needed) modestly shrinks the tree; low value, low risk.
**P2 — Consider whether full OpenSSL is proportionate.** SQLCipher only needs libcrypto primitives (AES, HMAC, PBKDF2), yet the vendored feature builds all of OpenSSL. rusqlite's feature set offers no smaller backend today, so this is a watch item, not an action — but it strengthens the P1 case for CI advisory scanning.
## Verdict
Healthy, deliberate dependency set. No P0s. The two structural gaps are operational (no CVE-response automation for the vendored C stack) and the misleading exact-pin strategy; both are cheap to fix.