Third step of ADR-008. Two routes inside the item family: the playlist starts
the session lazily and serves what ffmpeg has written so far, so playback can
begin while the rest still encodes; the segment route serves one .ts.
Segment names are validated against the exact shape ffmpeg writes before being
used as a path. Verified red-green: removing the check serves a file from
outside the session directory with a 200.
Two corrections made in review.
1. The manager was being built inside NewHandlers, which meant nothing could
ever shut it down. Its reaper would run for the process lifetime and a
running ffmpeg would outlive the server that started it. It is now created
in main.go beside the job queue and deferred, and passed in - the same
ownership the queue already has.
2. A playlist request could 404 before ffmpeg wrote the file, which a native
HLS player treats as fatal rather than retrying. The playlist handler now
waits up to four seconds for the first write. Segments are never waited for.
Verified end-to-end against a running server with real hardware: a 30-second
file produced a valid EVENT playlist in about a second (the wait doing its
job - no 404), a 658 KB segment with Content-Type video/mp2t, a 404 for a
traversal attempt, and a 401 unauthenticated.
Also confirmed at boot: all four metadata providers report their disabled
state and name their env var, including the new adult one.