* fix hls: require fresh origin window for new playback on retained sessions, count known-length revision bodies as completed
- New playback leases joining a retained shared session no longer start
on
a stale committed window. If the origin window was last confirmed more
than two target durations ago, admission requires a fresh commit
(StaleEntryWindow) using the strict pinned host and no recovery burst.
This prevents the forward jump after fast-start entry.
- RevisionResponseStream tracks bytes sent. A known-length body that is
dropped after its final byte is now recorded as completed and marks
segment completion instead of logging outcome=dropped.
- Add an end-to-end re-entry regression test covering progressive,
first_ready and conservative, plus unit tests for the commit
requirement and revision completion.
* - fix epg: adopt guide channel ID casing on matched live streams
Synchronize the stream's `epg_channel_id` to the exact casing of the
matched XMLTV guide channel. This fixes exact-key B+Tree lookups in short
EPG and client API responses when stream and guide IDs differ in case.
- fix frontend: hide column rail on empty tables
* - fix epg: adopt guide channel ID casing on matched live streams
Synchronize the stream's `epg_channel_id` to the exact casing of the
matched XMLTV guide channel. This fixes exact-key B+Tree lookups in short
EPG and client API responses when stream and guide IDs differ in case.
- fix frontend: hide column rail on empty tables
* fix hls close revision file at reader deadline
Move the progressive revision reader onto its own task and feed the
response stream through a bounded channel. At the deadline the watchdog
aborts the reader, so the file handle and revision pin are released
even if a stalled client never polls the stream again.
Each open revision file now holds its own pin, so GC cannot retire a
revision while a handle is open, including one held by an in-flight
blocking read.
* fix hls close revision file at reader deadline
Move the progressive revision reader onto its own task and feed the
response stream through a bounded channel. At the deadline the watchdog
aborts the reader, so the file handle and revision pin are released
even if a stalled client never polls the stream again.
Each open revision file now holds its own pin, so GC cannot retire a
revision while a handle is open, including one held by an in-flight
blocking read.
---------
Co-authored-by: euzu <euzu@proton.me>
* **New Features**
* Customize table columns by showing, hiding, and reordering them, with keyboard or pointer controls.
* Save layouts per account, restore defaults, and resolve conflicts when preferences change elsewhere. On installations without web authentication, settings are shared.
* CSV tables now support saved layouts for recognized table structures.
* **Bug Fixes**
* Improved pagination bounds and page-size validation.
* Settings requests now return clearer errors for oversized or unreadable request bodies, and recheck access after waiting for settings to become available.
* **Documentation**
* Added guidance for table customization and the settings API.
* fix(frontend): clean up websocket callbacks and reconnect timers on session expiry
* fix(frontend): clean up websocket callbacks and reconnect timers on session expiry
---------
Co-authored-by: euzu <euzu@proton.me>
* fix(m3u): use alias token for Flussonic catch-up archives
Catch-up archive URLs are built from the main account's live URL. On an
alias allocation the M3U URL index only knows live URLs, so the lookup
missed and the archive manifest was fetched with the main stream token.
DVR segments inherited it, and the provider attributed the playback to
the main account.
On an index miss for a Flussonic archive file, resolve the live file in
the same directory through the alias index (one lookup pass for all
candidates) and keep the requested archive file name with the alias
query.
Query-based catch-up templates (append mode) are not covered.
* fix(dvr): retry ffmpeg spawn while executable is busy
Spawning a just-written executable can fail with ETXTBSY when a
concurrently forked process still holds an inherited write descriptor
before its exec. This made run_recording_preempts_fake_ffmpeg_and_
preserves_window_semantics flaky on CI.
Retry the spawn up to five times with a short backoff on
ExecutableFileBusy; other errors fail immediately as before.
* fix(hls): resolve single-variant archive master in shared cache
Archive URLs that return a master playlist with one #EXT-X-STREA
child failed with segment_uri_without_extinf. The variant's media
playlist is now fetched and fed to the cache timeline.
- skip masters with several variants or separate #EXT-X-MEDIA tr
- send entry credentials only to the entry origin
- send master cookies only to the master origin
- merge master and variant session cookies by name
- keep the recovery binding on the entry URL
* **New Features**
* Added an EPG group view with channel counts, programme details, and channel search.
* Added timeline zooming and panning, recording controls for eligible upcoming programmes, and a resizable side panel with keyboard and pointer controls.
* **Improvements**
* EPG group and grid results support JSON or CBOR responses and show up to 1,000 channels per group.
* Channel filters support case-insensitive text and regular expressions; invalid patterns are rejected with an error.
feat(dvr)!: unify live and VOD/series recording into one recoverable DVR
Merge fix/merge_live_and_vod_recording into develop.
- One recording queue for scheduled live captures and VOD/series transfers,
with a shared transition graph, provider-slot scheduling, resumable HTTP
transfers (strong ETag / Last-Modified validation) and ffmpeg live capture.
- Crash-recoverable persistence: B+Tree repository with a journal-first
recovery history; one file can be shared by several library entries.
- Admission checks quota and disk on request, at transfer start (real size)
and before an entry attaches to a finished file; idempotent requests.
- REST is command-only; state reaches clients via owner-filtered WebSocket
snapshots.
- Deleting a recording removes the file once no entry holds it; removing an
entry keeps a finished file and cleans up orphaned partials.
- User ids derive from the configured username (web:/api:); the identity
registry is gone.
- Spanish locale added; ru/ar completed; locale parity test.
BREAKING CHANGE: `video.download` is now `video.recording` (nested
`recording` keys move up, `download_priority`/`recording_priority` become
`priority`); old configs fail to load with a migration hint.
BREAKING CHANGE: `/api/v1/file/download*` and `/file/record` are removed in
favour of `/api/v1/recording/*`.
BREAKING CHANGE: `download.*` and `recording.write` permissions are replaced
by `recording.read|create|manage|delete`; tokens from before the change must
re-authenticate.
BREAKING CHANGE: the old recording queue does not migrate; existing
`identity_registry.json` is ignored.
* fix(hls): return upstream status for HLS resources
- no TS fallback for failed segments, init and keys
- bounded capacity wait on pinned account (manifest 5s, media 2s)
- reject waiting requests after session end or account switch
- per-origin provider cookie jar, read at send time
- opt-in flussonic_hls_audio_tracks input option
* fix(hls): return upstream status for HLS resources
- no TS fallback for failed segments, init and keys
- bounded capacity wait on pinned account (manifest 5s, media 2s)
- reject waiting requests after session end or account switch
- per-origin provider cookie jar, read at send time
- opt-in flussonic_hls_audio_tracks input option
* fix(hls): return upstream status for HLS resources
- no TS fallback for failed segments, init and keys
- bounded capacity wait on pinned account (manifest 5s, media 2s)
- reject waiting requests after session end or account switch
- per-origin provider cookie jar, read at send time
- opt-in flussonic_hls_audio_tracks input option
* fix(hls): keep provider account across client IP changes
Wrap live HLS media playlists in a single-variant master whose variant
URI is a sealed owner token, so playlist refreshes from changing client
IPs keep their owner, lease and provider affinity. Expired sessions are
recreated from the token with the same access and admission checks.
- Classify HLS resources by playlist tag, not by .m3u8 extension
- Answer non-HLS 200 bodies as failed manifests (entry: unavailable,
refresh: 502)
- Pin child manifests and media URIs to the resolving provider account
- Add reverse_proxy.stream.hls_wrap_media_playlist (default true)
- Split AppState into app_state/ containers; move HTTP clients to core
* fix(hls): keep provider account across client IP changes
Wrap live HLS media playlists in a single-variant master whose variant
URI is a sealed owner token, so playlist refreshes from changing client
IPs keep their owner, lease and provider affinity. Expired sessions are
recreated from the token with the same access and admission checks.
- Classify HLS resources by playlist tag, not by .m3u8 extension
- Answer non-HLS 200 bodies as failed manifests (entry: unavailable,
refresh: 502)
- Pin child manifests and media URIs to the resolving provider account
- Add reverse_proxy.stream.hls_wrap_media_playlist (default true)
- Split AppState into app_state/ containers; move HTTP clients to core
* fix(hls): keep provider account across client IP changes
Wrap live HLS media playlists in a single-variant master whose variant
URI is a sealed owner token, so playlist refreshes from changing client
IPs keep their owner, lease and provider affinity. Expired sessions are
recreated from the token with the same access and admission checks.
- Classify HLS resources by playlist tag, not by .m3u8 extension
- Answer non-HLS 200 bodies as failed manifests (entry: unavailable,
refresh: 502)
- Pin child manifests and media URIs to the resolving provider account
- Add reverse_proxy.stream.hls_wrap_media_playlist (default true)
- Split AppState into app_state/ containers; move HTTP clients to core
* fix(hls): keep provider account across client IP changes
Wrap live HLS media playlists in a single-variant master whose variant
URI is a sealed owner token, so playlist refreshes from changing client
IPs keep their owner, lease and provider affinity. Expired sessions are
recreated from the token with the same access and admission checks.
- Classify HLS resources by playlist tag, not by .m3u8 extension
- Answer non-HLS 200 bodies as failed manifests (entry: unavailable,
refresh: 502)
- Pin child manifests and media URIs to the resolving provider account
- Add reverse_proxy.stream.hls_wrap_media_playlist (default true)
- Split AppState into app_state/ containers; move HTTP clients to core
* fix(hls): keep provider account across client IP changes
Wrap live HLS media playlists in a single-variant master whose variant
URI is a sealed owner token, so playlist refreshes from changing client
IPs keep their owner, lease and provider affinity. Expired sessions are
recreated from the token with the same access and admission checks.
- Classify HLS resources by playlist tag, not by .m3u8 extension
- Answer non-HLS 200 bodies as failed manifests (entry: unavailable,
refresh: 502)
- Pin child manifests and media URIs to the resolving provider account
- Add reverse_proxy.stream.hls_wrap_media_playlist (default true)
- Split AppState into app_state/ containers; move HTTP clients to core
---------
Co-authored-by: euzu <euzu@proton.me>
* fix(hls): keep provider affinity after reconnect lease expiry
- Remember the provider that last delivered media for reconnect-capable
playback (HLS, DASH, Catchup, VOD) beyond the lease window. The
preference holds no slot, never forces grace and falls back to the
lineup when the provider is full.
- End it on provider failure, preemption, kick, timeout or admin
terminate; stale cleanups are rejected by binding tag, request ID and
session token. Retry token claims stay bounded.
- Terminate and kick now release the HLS binding they acquired.
- Add reverse_proxy.stream.provider_affinity_ttl_secs (default 120,
max 86400) with Web UI field, docs and translations.
- Testkit: pause_millis steps, TTL overrides and the
m3u-hls-provider-affinity-after-lease-expiry scenario.
* fix(hls): keep provider affinity after reconnect lease expiry
- Remember the provider that last delivered media for reconnect-capable
playback (HLS, DASH, Catchup, VOD) beyond the lease window. The
preference holds no slot, never forces grace and falls back to the
lineup when the provider is full.
- End it on provider failure, preemption, kick, timeout or admin
terminate; stale cleanups are rejected by binding tag, request ID and
session token. Retry token claims stay bounded.
- Terminate and kick now release the HLS binding they acquired.
- Add reverse_proxy.stream.provider_affinity_ttl_secs (default 120,
max 86400) with Web UI field, docs and translations.
- Testkit: pause_millis steps, TTL overrides and the
m3u-hls-provider-affinity-after-lease-expiry scenario.
* fix(hls): keep provider affinity after reconnect lease expiry
- Remember the provider that last delivered media for reconnect-capable
playback (HLS, DASH, Catchup, VOD) beyond the lease window. The
preference holds no slot, never forces grace and falls back to the
lineup when the provider is full.
- End it on provider failure, preemption, kick, timeout or admin
terminate; stale cleanups are rejected by binding tag, request ID and
session token. Retry token claims stay bounded.
- Terminate and kick now release the HLS binding they acquired.
- Add reverse_proxy.stream.provider_affinity_ttl_secs (default 120,
max 86400) with Web UI field, docs and translations.
- Testkit: pause_millis steps, TTL overrides and the
m3u-hls-provider-affinity-after-lease-expiry scenario.
---------
Co-authored-by: euzu <euzu@proton.me>
- Store terminal account states in source.yml/CSV; keep Pending runtime-only
- On 401/403, only flag the account for the throttled expiry worker
- Lift stored bans on panel renewal or credential update
- Persist per file in one batch; back up only when content changes
- Use the first usable alias for playlists when the root is blocked
Co-authored-by: euzu <euzu@proton.me>
* fix(provider): exclude and persist banned/expired accounts
- Store terminal account states in source.yml/CSV; keep Pending runtime-only
- On 401/403, only flag the account for the throttled expiry worker
- Lift stored bans on panel renewal or credential update
- Persist per file in one batch; back up only when content changes
- Use the first usable alias for playlists when the root is blocked
* fix(provider): exclude and persist banned/expired accounts
- Store terminal account states in source.yml/CSV; keep Pending runtime-only
- On 401/403, only flag the account for the throttled expiry worker
- Lift stored bans on panel renewal or credential update
- Persist per file in one batch; back up only when content changes
- Use the first usable alias for playlists when the root is blocked
* fix(hls): reuse stable provider lease owners across playback retries
Keep public HLS tokens unique while sharing provider leases by
client/user/channel fingerprint. Preserve request ID and binding
generation guards and scope socket cleanup to the original session.
Add regression tests for repeated retries, stale cleanup, reused
sockets and M3U alias fallback with an A=2/B=4 provider pool.
* fix(hls): reuse stable provider lease owners across playback retries
- Keep public HLS tokens unique while sharing provider leases by
client/user/channel fingerprint. Preserve request ID and binding
generation guards and scope socket cleanup to the original session.
- Add regression tests for repeated retries, stale cleanup, reused
sockets and M3U alias fallback with an A=2/B=4 provider pool.
fix: proxy external Xtream VOD sources in M3U reverse mode
- Resolve stored VOD URLs using the existing input identity.
- Use canonical movie URLs for alias accounts with the original stream ID.
- Keep redirects internal and stop forwarding upstream Referer headers.
- Add regression tests for CDN URLs, aliases, ranges, and URL leakage
* fix(hls): reuse stable provider lease owners across playback retries
- Keep public HLS tokens unique while sharing provider leases by
client/user/channel fingerprint. Preserve request ID and binding
generation guards and scope socket cleanup to the original session.
- Add regression tests for repeated retries, stale cleanup, reused
sockets and M3U alias fallback with an A=2/B=4 provider pool.
fix: proxy external Xtream VOD sources in M3U reverse mode
- Resolve stored VOD URLs using the existing input identity.
- Use canonical movie URLs for alias accounts with the original stream ID.
- Keep redirects internal and stop forwarding upstream Referer headers.
- Add regression tests for CDN URLs, aliases, ranges, and URL leakage
* **New Features**
* Added a setting to limit Flussonic HLS catch-up archive duration. Valid values range from 1 second to 7 days; the default is 4 hours.
* Bounded archive requests are capped at the configured limit, while shorter valid requests retain their requested duration. Changes apply after a playlist refresh.
* Added a dashboard credits card with app and TMDB attribution.
* **Bug Fixes**
* Open filter dialogs now render in the document body when available, helping them display correctly.
* **Documentation**
* Documented the archive-duration setting and bounded-archive behavior.
* filter input for user form
* added opt-in bounded Flussonic HLS catch-up
- Add flussonic_hls_catchup input option with native default
- Generate bounded archive sources during M3U import
- Preserve live URLs and query tokens
- Expose native and bounded_archive in the WebUI select
* added opt-in bounded Flussonic HLS catch-up
- Add flussonic_hls_catchup input option with native default
- Generate bounded archive sources during M3U import
- Preserve live URLs and query tokens
- Expose native and bounded_archive in the WebUI select
* **New Features**
* Added support for bounded Flussonic HLS catch-up playback when an explicit source is configured, with valid start times and durations of up to seven days.
* Bounded archive playlist resources now inherit missing query parameters from their source while preserving values provided by child resources. Cross-origin URLs remain unchanged.
* **Bug Fixes**
* Rewritten Flussonic catch-up output now uses the rewritten mode without retaining the original catch-up type or provider token.
* **Bug Fixes**
* Playlist publication now continues when optional content curation is unavailable or encounters service, credential, request-limit, or certificate issues.
* In these cases, regular catalog content can still be published to supported outputs and saved to the cache. Curation-specific views are omitted when they cannot be prepared.
* Empty playlists continue to be rejected by the regular publication process.
* **Bug Fixes**
* Playback retries can use another available provider when playback has not started, helping requests proceed if the initially selected provider is unavailable.
* Once playback has started, retries continue using the same eligible provider to preserve playback continuity.
* Provider selection follows the same rules for regular playback and forced reopens, reducing unnecessary provider pinning before media begins.
* Series episode URLs can resolve to the correct account-specific playback address.
* test(curation): cover post-merge admission contracts
Add regression coverage for the merged TMDB/Trakt behavior and correct the stale first-page changelog wording. Keep all existing tests and production code unchanged.
* test(curation): isolate admission fixture from environment proxies
Use the existing no_proxy test-client pattern at the fixture boundary. Preserve the missing TMDB transport, both catalog policies and all assertions; no production transport changes.
---------
Co-authored-by: Juanjo Presa <juanjop@gmail.com>
Co-authored-by: euzu <euzu@proton.me>
* **New Features**
* Stalker playback resolves channel links on request, using available channel commands and falling back to the stored command when needed.
* If a portal rejects a session, playback retries once after reconnecting.
* **Bug Fixes**
* Reading playlists or resolving playback for a different portal identity no longer replaces the published catalog or clears its refresh checkpoint.
* A failed channel playback no longer prevents other published channels from remaining available.
* **Documentation**
* Updated Stalker playback guidance to describe on-demand link resolution and session recovery.
* fixing resource url problem
* fix(resources): classify resource destinations per hop and keep the proxy in the fetch path
A resource URL is classified (public / non-public / local) before it reaches a client, and every
redirect hop is classified and fetched again: non-public hops connect directly, public hops go
through the configured proxy, local hops are refused. Adds the public no-redirect resource client,
a process-wide destination memo, and regression tests for the redirect and Web UI paths.
* fix(resources): classify resource destinations per hop and keep the proxy in the fetch path
A resource URL is classified (public / non-public / local) before it reaches a client, and every
redirect hop is classified and fetched again: non-public hops connect directly, public hops go
through the configured proxy, local hops are refused. Adds the public no-redirect resource client,
a process-wide destination memo, and regression tests for the redirect and Web UI paths.
---------
Co-authored-by: euzu <euzu@proton.me>
* **Bug Fixes**
* Improved live-stream session handling during instant grace periods, including when a session has not yet been created.
* Corrected connection-limit and eviction tracking so active streams remain eligible for eviction even when their session record is unavailable.
* Improved reliability when switching between live channels under connection limits.
* **Improvements**
* Updated staged M3U overlays for Xtream providers: staged groups determine selected categories and channels, while unmatched categories remain available. Provider categories with no usable staged channels are retained.
* **Documentation**
* Clarified how staged Xtream and M3U playlists affect provider categories and channels.
Updated the Stalker input handling. Profile decoding now accepts JSON numbers or numeric strings for status and max_connections, while rejecting malformed values. Bootstrap handling now stops on a decode error or HTTP 429, preserving the useful error instead of cycling through more recipes.
* **Bug Fixes**
* Improved compatibility with provider profiles that represent numeric fields as strings, while rejecting invalid values.
* Handshake requests now stop retrying when rate-limited or when responses cannot be decoded; HTTP 429 responses are reported immediately.
* Rate limits encountered while fetching profiles also stop further retries.
- add target-wide TMDB Trending discovery for movie/TV and day/week, bounded by an optional `limit` (default 100, range 1–500) of unique remote references before local matching
- compose concrete Trakt and TMDB sources under one target curation policy while retaining legacy `output[].trakt` compatibility
- match only positive TMDB IDs of the same media kind and preserve existing catalog identities, series closure, and Xtream alias behavior
- require every active selector to complete before target IDs, writers, caches, or watches can change
- preserve the YAML-owned block through Source Editor operations and add TMDB setup/failure documentation and application Credits attribution
- validate complete decoded pages under independent request, selector, and shared target-batch budgets, using a configured TMDB-only HTTP profile with certificate/hostname verification and no redirects or replays
- Actively drop the hyper connection future (`drop(conn)`) on forced socket close to abort active stream bodies immediately.
- Introduce `SocketCloseState` (Open / Closing) in `ConnectionManager with per-socket oneshot channels to ensure targeted signal delivery and prevent premature provider release on repeated kicks.
- Remove user entries atomically under a single write lock in `ActiveUserManager`.
- Explicitly drop shared stream register locks before async teardown.
- Remove duplicate provider cleanup on serve loop termination.
- Add lifecycle integration tests and unit tests for kick idempotency, dropped receivers, and Closing-state provider retention.
Co-authored-by: euzu <euzu@proton.me>
* **New Features**
* Added a Resource Policy editor for each input, supporting trusted hostnames and private network ranges.
* Resource URLs now retain their source input and use authenticated links where supported.
* Resource caching is scoped to the policy authorizing access.
* **Bug Fixes**
* Invalid or unsupported resource values are safely discarded.
* Redirects and destination addresses are rechecked against the applicable policy.
* **Breaking Changes**
* Private DNS destinations require approved hosts and networks; private IP literals require an approved network.
* Input and alias names must be non-empty and globally unique.
- **New Features**
- Added assertions for verifying which provider account handled the latest request.
- Enabled provider-affine playback to fall back to another available provider when the pinned provider is unavailable.
- **Bug Fixes**
- Improved provider fallback handling, origin request tracking, and session updates.
- Preserved session headers when fallback stream setup fails and refreshed them after successful fallback.
- **Tests**
- Added coverage for provider-pool failover, account reuse, limits, rejection handling, and eviction behavior.
* **New Features**
* Added an opt-in runtime liveness watchdog with diagnostics, health status, and optional automatic restart.
* Added configurable stream cleanup capacity and eviction re-entry protection.
* Expanded configuration and UI access for users with playlist or user permissions, with safer data sanitization.
* Added testkit scenarios and reporting for playback, admission, provider limits, sharing, and VOD behavior.
* Added support for experimental-branch Docker builds.
* **Bug Fixes**
* Improved provider prioritization, shared playback capacity, cleanup, reconnect handling, and concurrent client behavior.
* Fixed playlist parsing for declared media types.
* Release links now use the configured destination.
remove the bundled Trakt Client ID and every fallback to it while keeping the compatible trakt.api.api_key field
trim supplied Client IDs, reject blank/header-invalid values before request construction, and skip only optional Trakt curation with one target-scoped warning
translate Trakt 401/403/404/429 responses explicitly, distinguish list/chart 404s, and preserve partial success across configured sources
disable the checked-in Trakt example until an explicit Client ID is configured and update docs and Source Editor terminology
New Features
Added an option to append a stable, numeric stream index to upstream User-Agent headers.
Stream indexes remain consistent throughout a playback session, including manifests, segments, reconnects, seeks, and provider failover.
Added a configuration checkbox for enabling the feature.
Documentation
Documented the new configuration option, including session behavior and restart handling.
Added English, Arabic, and Russian translations for the setting.
Co-authored-by: euzu <euzu@proton.me>
New Features
Programme icons are now captured when importing XMLTV electronic programme guides.
Programme icons are preserved when combining programme data from multiple sources.
Exported XMLTV guides now include programme icon information when available.
Icon URLs are rewritten consistently when URL rewriting is enabled.
Bug Fixes
Public resource requests now avoid following redirects and validate destinations before fetching.
Resource caching behavior is now correctly applied according to the request type.
Compatibility
Existing guides and legacy programme data remain supported when no icon is provided.
Bug Fixes
Live playback sessions now receive unique session identifiers, preventing parallel playbacks from being conflated.
Improved media segment caching under high write activity to prevent competing operations from interfering with capacity recovery.
Provider reservations now remain independent for different channel variants, preventing one playback from reusing or taking over another’s reservation.
Bug Fixes
Improved provider capacity management and reservation handling for shared connections.
Added support for excluding providers during connection allocation.
Improved grace-period expiration and concurrent access handling.
Preserved reserved capacity during fallback and preemptive allocations.
Chores
Improved unused-dependency checks and command configuration.
Removed unused dependencies across multiple components.
Added exceptions for dependencies used indirectly through macros or renamed packages.
Tests
Added coverage for provider reservations, fallback allocation, grace-period expiry, and concurrent grace access.
New Features
Added target-specific bouquet filtering with whitelist and blacklist modes for Live, VOD, and Series groups.
Added an in-context bouquet editor with search, selection controls, status indicators, reset, and streaming previews.
Targets are managed by name, with saved selections available through the Source Editor.
Improved stream alias resolution and provider failover behavior.
Bug Fixes
Existing playlists are preserved when refreshes produce no usable items.
Empty playlists are no longer published.
Configuration changes now recover more safely from persistence failures.
Documentation
Updated feature and configuration documentation and added translations.
* Fix M3U alias credential rewriting on provider fallback
Rewrite opaque authentication query parameters when stream allocation
switches from the primary M3U provider to an alias.
Support unambiguous cross-key mappings such as token to api_key while
preserving unrelated query parameters and rejecting ambiguous mappings.
Add regression coverage for URL rewriting and provider allocation.
* Fix M3U alias credential rewriting on provider fallback
Rewrite opaque authentication query parameters when stream allocation
switches from the primary M3U provider to an alias.
Support unambiguous cross-key mappings such as token to api_key while
preserving unrelated query parameters and rejecting ambiguous mappings.
Add regression coverage for URL rewriting and provider allocation.
Improvements
Electronic Program Guide (EPG) channels now follow playlist ordering in the web interface and generated XMLTV files.
Channels not included in the playlist appear after referenced channels for more consistent results.
EPG ordering remains consistent across supported playlist formats.
Build and frontend output are more consistent across different development environments.
New Features
Added separate processing and persistence filters, with empty/non-empty checks and expanded filter fields.
Added persistence-stage filter controls in target settings.
Added clear_invalid_epg_ids, preserving playlist entries while clearing unresolved EPG IDs; the legacy setting remains supported.
Added safer, atomic source configuration updates that preserve comments and formatting.
Bug Fixes
Null-like Xtream and Stalker values are now handled correctly.
Duplicate credential warnings provide clearer details.
Bug Fixes
Preserved comments and formatting in sources.yml when saving panel and account-expiration updates.
Kept inline templates intact while applying configuration updates and sanitization.
Improved persistence reliability for updated source configurations.
New Features
Added a target option to require valid EPG programme data for live entries.
Entries without matching EPG data are filtered out when enabled; non-live entries remain unaffected.
Added support for configuring this option in the target editor, with localized labels and explanations.
Documentation
Documented the new setting, including its default behavior and handling when no EPG source is available.