Test RecordConfig directly instead of FrigateConfig to avoid dependencies
on Docker-only paths (/labelmap.txt, /config) and detector runtimes.
Added enum value and serialization roundtrip tests.
- C3: Make retain_policy global-only by hiding from per-camera settings
UI and removing from CameraConfig TypeScript type
- C4: Add missing units field to StorageBreakdown TypeScript type to
match API response
- I3: Add 24-hour grace period for deleted camera recordings in rollover
mode to prevent data loss if camera is temporarily removed from config
- I6: Deduplicate model_validator warning by using module-level flag to
prevent N+1 duplicate warnings during config propagation
- S5: Add debug log when skipping time-based expiry in rollover mode and
clean up redundant if/not-if to if/else
- C1: Rewrite breakdown endpoint with JOIN queries (eliminates N+1)
- C2: Use getUnitSize() for consistent MiB/GiB display
- C3: Add retain_policy to global FrigateConfig TypeScript type
- I1: Only fetch breakdown data when rollover mode is active
- I2: Handle NULL end_time for in-progress events/reviews
- I5: Add model_validator warning when rollover + days are both set
- S4: Hide breakdown when total is 0
New GET /recordings/storage/breakdown endpoint returns storage usage
broken into three categories: overwritable (continuous recordings),
event_retention (active alerts/detections), and protected (indefinite).
In rollover mode, RecordingCleanup no longer deletes recordings based
on continuous.days / motion.days. Instead, StorageMaintainer handles
overflow by deleting oldest recordings when disk fills up. Deleted
cameras have their recordings removed immediately rather than waiting
for time-based expiry. Review segment expiry still runs normally.
Introduce a new RetainPolicyEnum with 'time' (default, existing behavior)
and 'continuous_rollover' (fill disk, overwrite oldest) options. Add the
retain_policy field to RecordConfig and include unit tests for config
validation.