## Full Audit Report

**Scope**: All `src/` files (~17K LOC)
**Subsystems Audited**: write-path, read-path, memtable, WAL, SST, iterator, compaction, manifest, cache, types & encoding
**Total Findings**: 16 (2 critical, 8 high, 1 medium, 5 low)

## Findings

### [CRITICAL] write-path: WAL write failure does not set background error

**Where**: `src/db.rs:1680` (approximate, `write_batch_group`)
**What**: If `wal.add_record` or `wal.flush` fails, the error is returned to the user, but `bg_error` is not set. Earlier batches in a group commit might have already been inserted into the MemTable and become visible to readers, while the durable WAL is now inconsistent or truncated.
**Why**: Violates `Failure Path Analysis` (Review Core 3.3). Partial failure leaves the DB in an inconsistent state. Subsequent writes will continue to append to a potentially corrupted WAL stream.
**Fix**: Call `self.set_bg_error()` before returning from a WAL write failure.

### [CRITICAL] compaction: Background compaction stall due to holding db_mutex during I/O

**Where**: `src/compaction/leveled.rs:653` and `src/db.rs`
**What**: Compaction I/O (reading/writing SSTs) is performed while holding the main `db_mutex`. 
**Why**: Violates `INV-CC4: Background Thread Safety`. Holding the global lock during slow disk I/O stalls all other database operations, including the write path and MemTable flushes, leading to unbounded L0 accumulation and eventual write stops.
**Fix**: Release `db_mutex` before performing compaction I/O, then re-acquire it only to apply the `VersionEdit`.

---

### [HIGH] write-path: Synchronous MemTable flush blocks all writers

**Where**: `src/db.rs:1722`
**What**: When a MemTable reaches its size limit, the group commit leader performs the SST flush synchronously.
**Why**: Performance regression (Review Core 4.2). The architecture mandates background flushes so writers can immediately switch to a new active MemTable. Synchronous I/O in the write path severely limits throughput.
**Fix**: Freeze the MemTable and signal a background flush thread instead of performing I/O inline.

### [HIGH] read-path: O(N) range tombstone scan across all L1+ files

**Where**: `src/db.rs:805` (`get`) and `src/db.rs:1078` (iterator)
**What**: Read paths iterate over ALL files in L1+ that have range deletions to accumulate tombstones, ignoring key ranges.
**Why**: Changes algorithmic complexity from O(log N) to O(N) in the number of SST files.
**Fix**: Only query range tombstones from files whose `[smallest, largest]` bounds overlap the query key or iterator range.

### [HIGH] WAL: Missing boundary check for record length

**Where**: `src/wal/reader.rs:130-143`
**What**: `WalReader` reads the `length` field and attempts to read that many bytes without verifying it fits in the current block.
**Why**: Corrupted headers can cause arithmetic underflow panics or silent truncation (data loss) if the read hits EOF unexpectedly. (Technical Pattern 2.3).
**Fix**: Validate `length` against remaining block space before reading the payload.

### [HIGH] compaction: Incorrect bottommost level calculation

**Where**: `src/compaction/leveled.rs:695`
**What**: `is_bottommost` only checks if the `target_level` is the statically defined last level.
**Why**: Violates `INV-C2` (Tombstone Retention). If levels below the target are empty, tombstones should be dropped. This bug causes tombstones to be retained indefinitely, degrading read performance.
**Fix**: Check if any files actually exist in levels deeper than the target level that overlap the compaction range.

### [HIGH] manifest & cache: Fsync executed while holding VersionSet lock

**Where**: `src/manifest/version_set.rs:244`
**What**: `log_and_apply` calls `writer.sync()` while holding the mutable `VersionSet` lock.
**Why**: Violates `INV-CC1`. Holding a lock during `fsync` causes priority inversion and stalls all threads requiring `VersionSet` access.
**Fix**: Perform the `fsync` outside the critical section.

### [HIGH] types & encoding: RateLimiter allows concurrent bursts to exceed rate

**Where**: `src/rate_limiter.rs:57-61`
**What**: The limiter ignores accumulated debt for concurrent callers via `.max(0.0)`.
**Why**: Under heavy concurrent load (e.g., multiple compaction threads), the effective rate exceeds the configured limit by a factor of the number of threads.
**Fix**: Remove the `.max(0.0)` cap so deficit includes total queued debt.

### [HIGH] types & encoding: InternalKey methods panic on malformed keys

**Where**: `src/types.rs:113-132`
**What**: Methods assume `encoded.len() >= 8` and perform direct indexing.
**Why**: Contradicts the defensive design in `compare_internal_key`. Corrupted SSTs will cause process crashes rather than return errors.
**Fix**: Safe length checks in `user_key()`, `sequence()`, etc.

---

### [MEDIUM] manifest & cache: Cache stampede on misses

**Where**: `src/cache/table_cache.rs:43`
**What**: Check-then-act pattern on cache misses allows multiple threads to redundantly load the same SST/block from disk.
**Why**: Inefficient resource usage under high concurrency.
**Fix**: Use `moka`'s `get_with` to atomize loading.

---

### [LOW] Code Style: Inline paths and grouped imports

**Where**: Project-wide (`src/db.rs`, `src/memtable/`, `src/wal/`, `src/sst/`, `src/manifest/`)
**What**: Extensive use of inline paths (e.g., `crate::types::LazyValue`) and separate `use` lines for common prefixes.
**Why**: Violates Task 4 Code Style Enforcement rules.
**Fix**: Move to top-level grouped imports.
