fix(playback): carry portal headers into collection playback

Codex round-3 P1: Stalker channels opened from Favorites/Recently Viewed
resolved through StreamResolverService.resolveStalker(), which returned no
portal headers — the video path handed the header owner an empty set and
collection radio bypassed it entirely, so auth-gated streams still 403'd
from collections.

- resolveStalker() now builds the same profile as the live layout via the
  shared classifier: portal-owned streams get mac cookie/Bearer token/MAG
  UA/portal Origin+Referer, foreign hosts keep the credential-free KSPlayer
  profile (both create_link results and direct radio URLs).
- UnifiedLiveTabComponent applies the scoped override for radio before the
  audio element gets its URL (ownership claimed before awaiting the IPC,
  round-2 lesson), and clears it on close and destroy.
- Regression tests: resolver header profiles for portal-host and foreign
  streams; unified tab radio apply-then-clear.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Fable 5 committed 2026-08-02 09:26:33 +02:00
1 parent 4c0be3fde5
commit 02969dca26
6 files changed
+221 -22

No files matched your search

+6 -5
View File
@@ -137,12 +137,13 @@ owner of the scoped override slot: it extracts the full header set from the
resolved playback (including the Stalker mac cookie and Bearer token), and
its `clear()` releases the slot only while the caller's stream still owns it,
so a consumer being destroyed cannot wipe an override a newer consumer just
configured. Two surfaces apply it: `WebPlayerViewComponent` for every
configured. Three surfaces apply it: `WebPlayerViewComponent` for every
built-in video player (configuring the override **before** handing the
source over, clearing on destroy), and the Stalker live layout for the
dedicated radio audio player, which never mounts a `WebPlayerViewComponent`.
Individual player components must not call the bridge themselves — a
narrower call would overwrite the credentialed override.
source over, clearing on destroy), and — for the dedicated radio audio
player, which never mounts a `WebPlayerViewComponent` — the Stalker live
layout and the unified collection tab (global/portal Favorites and Recently
Viewed). Individual player components must not call the bridge themselves —
a narrower call would overwrite the credentialed override.
Rules:
+4
View File
@@ -189,6 +189,10 @@ Every playback kind — ITV, VOD, series episodes, and radio — resolves its
stream and attaches the same portal header set through
`buildStalkerExternalPlaybackHeaders()`
(`libs/portal/stalker/data-access/src/lib/stalker-live-playback.utils.ts`).
The collection routes (Favorites/Recently Viewed) share the contract:
`StreamResolverService.resolveStalker()` builds the identical profile for the
streams it resolves, so a channel opened from a collection carries the same
credentials as one opened from the portal.
The resolved `ResolvedPortalPlayback.headers` feed both the external players
(MPV/VLC/Embedded MPV via the launch IPC) and the built-in players via the
scoped Electron request-header override (`ElectronStreamHeadersService`,