A live smoke test of buildArgs' argv against the bundled yt-dlp + ffmpeg found
that ffprobe.exe was never bundled (resources/bin/ shipped only ffmpeg.exe).
yt-dlp resolves both from --ffmpeg-location, so duration-aware post-processing
failed at runtime for every user with "ffprobe not found": --sponsorblock-remove,
--force-keyframes-at-cuts, and --split-chapters (CODE-AUDIT C1).
- Bundle ffprobe.exe (matching n8.1.2 LGPL build, sha256-verified against the
already-bundled ffmpeg.exe) and document it in resources/bin/README.md as a
required binary; correct the stale "not committed to git" note.
- Guard startDownload against a missing ffmpeg.exe/ffprobe.exe up front so the
failure is a clear AeroFetch error, not a cryptic yt-dlp postprocessing one
(new getFfprobePath() in binaries.ts).
- Expand test/real-download.integration.test.ts from 2 to 8 live cases: crop,
sponsorblock-remove, audio opus re-encode, mkv+vp9 merge, subtitle+chapter
embed, restrict-filenames, download-archive skip, and Phase C extra-args.
All 8 pass against live yt-dlp + ffmpeg.
- ROADMAP: mark the Phase A/B/C smoke-test caveats done. CODE-AUDIT: add C1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Security:
- S1 (backup.ts): require explicit confirmation before enabling custom-command
templates from a backup file; import templates in a disabled state if declined
- S2 (cookies.ts): deny non-http/https popups in cookie login window, matching
the main window's setWindowOpenHandler defence
- S3 (download.ts): main-process concurrency cap — startDownload now rejects
spawns when active.size >= maxConcurrent (defence-in-depth; renderer already
enforces this but should not be the only gate)
- S4 (settings.ts, validation.ts): reject filenameTemplate values containing
path traversal (.. segments or absolute paths); validate outputDir is absolute
- S5 (history.ts, errorlog.ts, templates.ts, validation.ts): per-field
validation on JSON reads — invalid entries dropped rather than blindly trusted
Performance:
- P1 (settings.ts): getSettings() now only writes to disk when sanitization
actually changed a value; removes synchronous file I/O on every hot-path read
- P2 (ipc.ts, download.ts, downloads.ts): renderer forwards its pre-probed
metadata (title/channel/duration) via StartDownloadOptions.meta; main uses
it directly instead of spawning a redundant second yt-dlp probe
Maintainability:
- M1 (log.ts, download.ts, probe.ts): extract duplicated cleanError() to
src/main/log.ts; both callers import from the shared module
- M2 (buildArgs.ts): document parseExtraArgs escape-sequence limitations
- M3 (electron-builder.yml): clarify icon TODO as a pre-release action
- P3 (downloads.ts): document that lowering maxConcurrent mid-flight does
not pause active downloads (intended behaviour, now written down)
Tests:
- Add test/validation.test.ts covering isSafeFilenameTemplate, isSafeOutputDir,
isValidHistoryEntry, isValidErrorLogEntry, isTemplateLike (76 tests pass)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>