feat: Phase P reliability (YouTube extractor-args plumbing, signing + smoke-test docs)

- YouTube reliability: Settings.youtubePlayerClient + youtubePoToken ->
  one --extractor-args "youtube:player_client=...;po_token=..." group
  (accessArgs, unit-tested); advanced fields in Settings -> Network.
  Automatic WebView PO-token minting deferred (documented).
- docs/SMOKE-TEST.md: release-gate checklist for all shipped-but-untested
  OS wiring (cookies window, protocol/Send-to, scheduled sync, aria2c, proxy,
  tray/taskbar/pause-resume/terminal) — needs a human to run.
- docs/SIGNING.md: code-signing guide (CSC_LINK/CSC_KEY_PASSWORD, OV/EV,
  CI, HSM hook, verification). Build is signing-ready; needs a cert.
- i18n remains deferred (not faked).

typecheck + test (195) + build all clean. Roadmap: Phase P code shipped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-26 11:25:57 -04:00
parent 20ee913394
commit 24c4c807a3
11 changed files with 238 additions and 21 deletions
@@ -226,6 +226,8 @@ export function SettingsView(): React.JSX.Element {
const proxy = useSettings((s) => s.proxy)
const rateLimit = useSettings((s) => s.rateLimit)
const useAria2c = useSettings((s) => s.useAria2c)
const youtubePlayerClient = useSettings((s) => s.youtubePlayerClient)
const youtubePoToken = useSettings((s) => s.youtubePoToken)
const cookieSource = useSettings((s) => s.cookieSource)
const cookiesBrowser = useSettings((s) => s.cookiesBrowser)
const restrictFilenames = useSettings((s) => s.restrictFilenames)
@@ -675,6 +677,28 @@ export function SettingsView(): React.JSX.Element {
label={useAria2c ? 'On' : 'Off'}
/>
</Field>
<Field
label="YouTube client (advanced)"
hint="Override the YouTube extraction client when downloads start failing the bot check. Try web_safari, tv, or mweb. Leave blank for yt-dlp's default."
>
<Input
value={youtubePlayerClient}
placeholder="web_safari"
onChange={(_, d) => update({ youtubePlayerClient: d.value })}
/>
</Field>
<Field
label="YouTube PO token (advanced)"
hint="A manually-obtained Proof-of-Origin token for YouTube's bot check, sent via --extractor-args. Usually cookies (above) are the easier fix; automatic minting is planned."
>
<Input
value={youtubePoToken}
placeholder="(none)"
onChange={(_, d) => update({ youtubePoToken: d.value })}
/>
</Field>
</Card>
<Card className={styles.card}>
+2
View File
@@ -27,6 +27,8 @@ if (import.meta.env.DEV && !window.api) {
useAria2c: false,
cookieSource: 'none',
cookiesBrowser: 'chrome',
youtubePlayerClient: '',
youtubePoToken: '',
restrictFilenames: false,
downloadArchive: false,
autoUpdateYtdlp: true,
+2
View File
@@ -21,6 +21,8 @@ const FALLBACK: Settings = {
useAria2c: false,
cookieSource: 'none',
cookiesBrowser: 'chrome',
youtubePlayerClient: '',
youtubePoToken: '',
restrictFilenames: false,
downloadArchive: false,
autoUpdateYtdlp: true,