- audit_log table with action, resource, resourceId, description, ip, countryCode, meta
- AuditEventsService (EventEmitter), AuditRepository, AuditService, AuditInterceptor
- @Auditable decorator wired on all mutating endpoints across every controller
- auth events (login, logout, register, password change, failed login) emitted directly in AuthService with IP capture
- geoip-lite for offline IP-to-country resolution
- nightly retention cleanup via cron with configurable audit_retention_days setting
- superuser-only GET /audit-log endpoint with userId, action, resource, date range filters
- AuditLogPage.vue with table, filters, pagination, and failed-auth row highlighting
- regenerated baseline migration to include audit_log in 0000_baseline.sql
- detect HTTP 429 via fetchWithThrottle utility and throw ProviderThrottleError
- track per-provider cooldown windows with exponential backoff in ProviderThrottleTracker
- Google Books uses a conservative schedule (10m/30m/1h/2h/4h); others use default (2m/5m/10m/30m/1h)
- pipeline filters throttled providers before each book fetch
- orchestrator extends inter-book delay to 10-20s when any provider is throttled
- add displayOrder column to lenses and collections schema
- add POST /api/v1/{lenses,collections}/reorder endpoints (user-scoped)
- move Lens type to @projectx/types; add displayOrder to Collection type
- add useDraggableOrder composable with optimistic updates, debounce, rollback, and unmount cleanup
- wire VueDraggable into AppSidebar with per-section edit-mode toggle
- replace section header add/reorder buttons with a single kebab dropdown
- set metadata fetch preferences defaults (goodreads-first provider order, saveProviderIds, genre merge)
- set appearance defaults: dark theme, vinyl pattern, brightness 50, updated card overlays
- set cover size 140px, grid gap 20px, new indicator threshold 7 days
- replace rating dots with colored star badge (per-rating color scale)
- set convert-to-kepub default to false
- add CODEOWNERS assigning .github/ to @neonsolstice
- configure automated updates for npm, docker, and github-actions ecosystems
- replace custom change-detection bash script with dorny/paths-filter@v4
- consolidate lint, typecheck, and test into a single checks matrix job
- gate per-package change detection via has-changes step (matrix unavailable in job-level if)
- fix duplicate actions/setup-node call in setup-node-pnpm composite action
- scope pnpm store cache key by pnpm version to prevent stale cross-version cache hits
- pin all action references to commit SHAs
- fix container-image concurrency group to use commit SHA across all trigger types
- add timeout-minutes to all jobs
- document fail-fast: false rationale and checks: write trade-off
- add useRefreshingBooks composable for shared per-book spinner state
- show refresh spinner on BookCoverCard during any bulk operation
- bulk-refresh-metadata and bulk-re-extract-cover endpoints now stream SSE
- client reads SSE stream and updates each card cover+spinner one-by-one
- wire all missing SelectionActionBar events in LensView and CollectionView
- fix nested group ALL/ANY toggle visibility and empty-rules group handling
- add FilterSummary component with color-coded field/operator/value display
- add collapsible filter preview in LensView with header toggle
- raise MAX_DEPTH to 5 to match backend validation
- add ruleToParts helper for structured rule rendering
- update filter chip styling: emerald fields, muted operators, primary values
- style ALL/ANY badges with sky-blue and amber respectively
- add segmented sort chip with rose accent and icon
- rebuild @projectx/types package to include tag and collection in RuleField