Three gaps allowed an unverified binary to reach a trusted location:
- The ffmpeg ZIP fallback logged a warning on checksum mismatch and
installed anyway (the 7z path already aborted). Abort instead.
- The yt-dlp auto-update path downloaded and renamed the binary over
the verified one with no checksum at all. Verify against the official
SHA2-256SUMS like the first-install path, and use atomic os.replace.
- The yt-dlp first install streamed the download directly to the
trusted path and only verified afterwards; a crash in between left an
unverified executable to be run on next launch. Download to .part and
os.replace only after verification.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Unpacking getOpenFileName() into a variable named _ made _ local to
select_ytdlp_path(), so the i18n _() calls earlier in the function
raised UnboundLocalError before the file dialog could open, breaking
manual binary selection entirely.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Introduce check_ytdlp_deno_integration() in ytsage_yt_dlp.py to detect Deno integration by running `yt-dlp --verbose` and scanning debug output for JS runtimes containing "deno" (with timeout and logging/fallback).
Add SystemInfoThread (QThread) in ytsage_dialogs_base.py to collect yt-dlp, ffmpeg and deno presence, versions, paths, cache timestamps and integration status in the background, emitting the gathered info via info_ready. AboutDialog now starts the thread in update_system_info() and populates the UI asynchronously via _populate_system_info(), showing a small "+ yt-dlp" integration indicator next to the Deno status when detected. Refactors usage of version/cache lookups to use the thread-provided info dictionary.
Renamed 'src/core' to 'ytsage/core' and updated all internal imports to use relative paths. This improves package structure and ensures correct module resolution after the directory move.