Address the completion review findings on top of the upstream review
fixes:
- Store runs on the engine's checkpoint goroutine without the task
lock and serializes the returned value afterwards: take the fetcher
mutex and return a deep copy instead of the live state pointer,
matching the HTTP protocol's Store pattern
- Load the journal and per-run base counters before publishing the run
as active, so Stats/Progress never observe half-initialized fields
- Bind the journal fingerprint to the key IV as well: a rotated IV on
an otherwise identical plan would silently decrypt to garbage
- Keep every EXT-X-MEDIA member per group instead of only the first
one, so a group with a URI on a later member is still detected
- After a merge that raced with a pause, keep the staged segments and
exit silently instead of cleaning them up; drop a dead context
check and an unused helper, and make the MAP identity and merge
part-file names unambiguous
New hls protocol in internal/protocol/hls (registered ahead of http):
- master playlist variant picking (highest bandwidth), RFC3986 segment
URL resolution, fMP4 init segments, EXT-X-BYTERANGE, EXT-X-GAP skip
- AES-128 decryption with mid-playlist key rotation and sequence-derived
IVs; explicit errors for live streams, SAMPLE-AES and multi-period fMP4
- concurrent segment downloads with retry, journal-based resume across
pause/app restarts, automatic in-order merge into a single .ts/.mp4
- best-effort Content-Length probing for determinate progress
- anti-hotlink Referer/Cookie/UA via task extra headers (Go transport
does not filter them)
Core: fix SchemeFilter extension match for URLs with query strings
(also benefits .torrent links); Flutter: Protocol.hls enum, hls protocol
config model (prevents config round-trip wipe) and HLS settings block
with localized labels in all 22 locales.
Tests: parser/crypto unit tests, httptest e2e (Referer-enforced CDN,
encrypted streams, byterange, pause/resume, store/restore) and an
opt-in live-site acceptance gate (HLS_LIVE_URL).