- P3-7: replace gmtime() with thread-safe gmtime_r() in utc_now()
- P3-9: validate columns array elements are strings before as_string()
- P3-10: use sqlite3_close_v2() instead of sqlite3_close() in DbConn dtor
- P3-11: introduce safe_stoi() helper wrapping all 9 std::stoi call sites
with field-name-aware error messages
- P3-12: log _log_internal exceptions to stderr instead of silent swallow
- P3-13: log _do_cleanup COUNT prepare failures to stderr; simplify
finalize to single exit point
- P3-14: reject invalid order_by elements (non-object, missing column)
instead of silently skipping
- P3-15: reject non-string action field instead of defaulting to "select"
- P3-16: validate order_by column is string and desc is boolean
All 22 audit issues now resolved (100%).