Commit Graph
6 Commits
Author SHA1 Message Date
DarkBreakpoint 76acd7be03 fix(dvr): resolve recordings through one owner-independent layout
Playback could not find any recording. Two independent path computations
existed and disagreed:

  writer  RecordingTask::new  -> <root>[/<subdir>]/<filename>
  reader  resolve_for_open    -> <root>/users/<owner>/<filename>

resolve_recording_dir invented a users/<owner>/ or shared/ prefix that
nothing ever wrote, and relative_path stored only the bare filename while
the organised subdirectory lived in file_dir. Nothing covered the round
trip, so the mismatch survived.

recording_path.rs is now the only layout. It is pure, and deliberately
owner-independent: one physical file is shared by every user who requested
it, so keying its directory on an owner is wrong the moment a second user
attaches and would force the file to move when the first detaches.
resolve_recording_dir and its RecordingVisibility are deleted rather than
left as a second answer.

relative_path is now root-relative and carries the full layout, so the
writer's path and the reader's resolution are the same expression. Series
recordings gain the Season NN level they were documented to have but never
produced.

Component sanitisation is one function with a table test: separators,
control characters and the Windows-forbidden set collapse to _, leading and
trailing dots are stripped so a name cannot be hidden or silently aliased,
Windows device names fall back to a placeholder, and components are capped
at 255 bytes on a character boundary so a multi-byte title truncates to
valid UTF-8 rather than to a split character. A property test asserts that
no input the builder accepts can produce a path the containment check
rejects.

Collision suffixes now apply to the file component only, so reserving a
name no longer flattens the directory it belongs to.
2026-09-01 08:24:20 -05:00
DarkBreakpoint 5561ff7690 feat(auth)!: split recording.write into create, manage and delete
A single write permission could not express the policy the DVR needs: a
user who may request a recording is not necessarily one who may cancel
someone else's, and neither implies the right to delete a file. Replace it
with recording.create, recording.manage and recording.delete, and map each
action onto the one it actually needs:

- create private/shared          -> recording.create
- edit, cancel, manage rules     -> recording.manage
- delete, system retention sweep -> recording.delete

The split renumbers every permission bit above recording.read, so
CURRENT_PERMISSION_SCHEMA_VERSION is bumped to 4 and tokens issued earlier
fail closed at the validator instead of having their bits reinterpreted.
The removed recording.write name now decodes to nothing, so a groups file
that still lists it loses the permission rather than silently gaining one
of the three replacements.

Permission bit values are frozen in a test: they are the wire format, and
reordering the enum would reinterpret every issued token.
2026-08-31 15:30:39 -05:00
euzu 486aa955d8 DVR Feature 2026-08-29 11:14:44 +02:00
euzu 3d42c7ab9e DVR Feature 2026-08-28 19:17:39 +02:00
euzu 93a5c5f162 DVR Feature 2026-08-28 09:58:27 +02:00
euzuandGitHub 9ec775b35b Feature/multi crate (#837)
Refactored to multi crate project
2026-08-27 15:36:23 +02:00