getInfo returns cached JSON (download-video.ts:127) before the info.webpage_url ||= url normalization (line 133) runs, and the cache file stores the pre-mutation infoStr. If yt-dlp omits webpage_url, the first call works but every cache hit returns info without it, and downloadVideo's info.webpage_url! (line ~276) feeds undefined into filenamify.
Related: all disk JSON is trusted (as VideoInfo cast at line 132, cache reads, pending-downloads reads) — no validation at any construction boundary.
Fix direction: one parse/normalize function on both fresh and cached paths; consider RawVideoInfo vs validated VideoInfo split (see type-design notes in baseline review).
getInfo returns cached JSON (download-video.ts:127) before the
info.webpage_url ||= urlnormalization (line 133) runs, and the cache file stores the pre-mutation infoStr. If yt-dlp omits webpage_url, the first call works but every cache hit returns info without it, and downloadVideo'sinfo.webpage_url!(line ~276) feeds undefined into filenamify.Related: all disk JSON is trusted (
as VideoInfocast at line 132, cache reads, pending-downloads reads) — no validation at any construction boundary.Fix direction: one parse/normalize function on both fresh and cached paths; consider RawVideoInfo vs validated VideoInfo split (see type-design notes in baseline review).