feat(player): remote stream-client config - #461
Conversation
…names - YouTubeClient gains a StreamProtocol enum (web_cipher_pot / direct) as the single source for useSignatureTimestamp/useWebPoTokens, plus a skipHeadValidation flag replacing the WEB_REMIX name test - clientNeedsNTransform reads the protocol instead of a hardcoded name list - webRemixFailedIds renamed to mainClientFailedIds (it marks the main slot, whoever occupies it) - the main-promotion/disable chain head extracted to the pure StreamClientChain with JVM tests
- YTPlayerUtils resolves each playback against a per-resolution snapshot of the zemer-cipher stream_clients.json table (StreamClientTable), with the compiled constants as the floor when neither bundled asset nor cache loads - a resolution that exhausts every client fires the cooldown-gated table refresh, so a YouTube-side client kill self-heals mid-session without an APK - stream-source toggles become per-family dynamic keys (absent = enabled) with a one-time migration from the six legacy keys; MusicService publishes the disabled set by prefix scan - Stream Sources screen renders rows/groups/order from the same table; known families keep bespoke strings, new ones use the config title - tests/clients.mjs becomes a loader of the same file (WEB stays hand-defined); stream-clients.test.mjs runs the shared parity fixtures; a new validate-stream-clients.mjs gates pushes with schema + whole-song drains - docs regenerated; AGENTS.md gains the remote stream-client rulebook
…VERT BEFORE MERGE
|
Testing setup: the cipher submodule is temporarily pinned to a commit whose REMOTE_URL fetches the FEATURE branch instead of master, so the full remote fetch/apply/update loop is testable on-device pre-merge (push a table tweak to feat/remote-stream-clients and watch devices pick it up). Both TEMPORARY commits (cipher 8a88e7a + this bump) get reverted before merge - do not merge while they are in. |
Cleanup: the cipher submodule pointer moves past the reverted TEMPORARY branch-pinned fetch (REMOTE_URL back to master) - both PRs are back to their shipping state.
|
Both TEMPORARY commits are reverted: the cipher submodule now points past the revert (REMOTE_URL fetches master again) and the branch-pinned test setup is gone. On-device verification completed via the branch channel: remote client removal (VISIONOS benched -> gone from settings/chain, 'applied (5 entries, changed=true, epoch=1)') and restore both confirmed. Also added: the Stream Sources screen now shows the client-table last-sync time under 'Current order'. PR is back to shipping state - merge order still cipher #2 first. |
- the all-clients-failed table refresh now fires only on client-kill shapes: a playability rejection (removed/region-blocked/age-gated), an explicit-rung quality miss, and cipher-side URL failures no longer trigger it, and an in-flight guard stops failing resolutions queueing coroutines behind a refresh that cannot complete on a filtered network - harness scripts read the shared protocol predicate instead of re-deriving the retired client-name list (proven no behavior change across all 18 retired clients), and the whole-song drain defaults to the table's chain instead of a hand-kept copy that would skip newly added clients - new test pins the bundled asset field-for-field against the compiled floor: the asset is what devices actually send, so a one-digit typo there previously shipped fleet-wide with every test green - legacy-key comments now state what the code guarantees (migration source, not a mirror)
client-fulldownload.mjs is a report that always exits 0, so passing its status through meant validate-stream-clients.mjs reported success even when no client could stream. It now reads the per-client verdicts, calls out a failing MAIN client as unpushable, notes that a fallback failure can be video-specific, and exits non-zero.
They were untracked working-tree files that predate this work and got swept in by an over-broad add; they are not part of the stream-client feature.
Summary
The streaming-client chain becomes remote data, on the same model as the cipher player configs: YTPlayerUtils now resolves each playback against a per-resolution snapshot of the zemer-cipher stream_clients.json table (clients, flags, order, main designation), so adding/removing/reordering clients after a YouTube-side change is a config push, not an APK release. Companion PR: ZemerTeam/zemer-cipher#2 (must merge first; this PR bumps the submodule pointer onto it).
Testing