tidaldb/.sdlc/features/p1-quality-diversity-baseline/audit.md

55 lines
3.6 KiB
Markdown

# Audit: Quality & Diversity Baseline
## Scope
Security, correctness, and operational audit of the `brief` ranking profile and associated pipeline fixes.
## Findings
### 1. Security
| # | Check | Status | Notes |
|---|-------|--------|-------|
| S1 | No user input in profile definition | PASS | Profile is code-defined with hardcoded constants. No injection surface. |
| S2 | No new network or I/O surface | PASS | Pure in-process ranking. No external calls. |
| S3 | No credential or secret handling | PASS | Not applicable. |
| S4 | No unsafe code | PASS | All changes are safe Rust. |
### 2. Correctness
| # | Check | Status | Notes |
|---|-------|--------|-------|
| C1 | Gate thresholds are >= (not >) | PASS | `passes_gates()` uses `>=` comparison. Items at exactly the threshold are included. |
| C2 | Exploration disabled for gate safety | PASS | `BRIEF_EXPLORATION = 0.0`. `inject_exploration()` bypasses gates; disabling it preserves the quality floor invariant. |
| C3 | Format enrichment populates correctly | PASS | Format populated from `meta.get("format")` only when `candidate.format.is_none()`. No double-write risk. |
| C4 | Metadata loading trigger complete | PASS | `needs_metadata_for_creator_grouping` now checks `max_per_creator || format_mix_max_fraction || notification_caps`. All three diversity-related conditions covered. |
| C5 | Gate signal names match schema | PASS | Gates reference "view" and "completion". If schema lacks these, `read_agg` returns 0.0, failing the gate. All items excluded — safe degradation (no garbage surfaced). |
| C6 | No integer overflow risk | PASS | Gate thresholds are `f64`. Windowed counts are `u64` cast to `f64` internally. No overflow at the quantities involved. |
### 3. Performance
| # | Check | Status | Notes |
|---|-------|--------|-------|
| P1 | Gate evaluation cost | PASS | Two additional `read_agg` calls per candidate. `read_agg` is O(1) DashMap lookup + constant-time BucketedCounter read. Negligible overhead. |
| P2 | Metadata loading for format | PASS | Metadata was already being loaded when `max_per_creator` was set. The format enrichment adds one `HashMap::get` per candidate per iteration — negligible. |
| P3 | Integration test speed | PASS | All 6 tests complete in 0.01s. No sleeps, no I/O. |
### 4. Operational
| # | Check | Status | Notes |
|---|-------|--------|-------|
| O1 | Profile is registered at startup | PASS | Added to `register_builtins()`. Available immediately on `TidalDb::open()`. |
| O2 | No migration required | PASS | No schema changes, no storage changes, no WAL format changes. |
| O3 | Backward compatible | PASS | New profile is additive. Existing profiles unaffected. Format enrichment fix is backward compatible (format was always `None` before, so format-based diversity was a no-op). |
### 5. Known Limitations
| # | Limitation | Severity | Notes |
|---|-----------|----------|-------|
| L1 | DiversitySelector operates on full scored set | Low | Diversity is applied to the full scored set, then pagination takes a slice. At the page level, creator distribution depends on scoring order. Tests account for this. Not a bug — it's the architectural design. |
| L2 | Exploration permanently disabled | Low | Cannot be re-enabled without also adding gate re-evaluation to `inject_exploration()`. This is a deliberate trade-off for this profile. |
## Verdict
**PASS.** No security, correctness, or performance concerns. The implementation is clean, well-documented, and all changes are backward compatible. The two pipeline fixes (format enrichment and metadata loading trigger) are improvements that benefit the entire ranking system, not just the `brief` profile.