# Changelog All notable changes to Jarri Spooty are documented here. This project follows a practical chronological changelog rather than autogenerated dependency noise. --- # Unreleased ## Added ### Spotify - Added Spotify OAuth login flow - Added `/api/spotify/login` - Added `/api/spotify/callback` - Added `/api/spotify/status` - Added persistent Spotify user token storage - Added authenticated Spotify playlist retrieval - Added OAuth frontend bootstrap flow - Added support for playlists exceeding 300 tracks - Added deterministic playlist pagination handling ### YouTube - Added deterministic YouTube candidate scoring - Added duration-aware YouTube matching - Added failed-candidate rejection memory - Added automatic retry/fallback handling - Added explicit YouTube candidate exclusion support - Added detailed YouTube candidate debug logging - Added explicit yt-dlp CLI execution - Added deterministic yt-dlp stderr capture - Added age-gated video detection - Added invalid-format detection - Added Docker-compatible cookie handling - Added temporary cookie-copy isolation - Added retry-aware queue coordination ### Queue Hardening - Added configurable YouTube search pacing - Added configurable YouTube download pacing - Added sequential queue coordination - Added retry collision prevention - Added deterministic queue replacement handling - Added explicit retry-state transitions - Reduced aggressive request bursts toward YouTube ### Docker - Added persistent SQLite bind-mount recommendations - Added persistent runtime config recommendations - Added yt-dlp installation to runtime container - Improved Docker runtime observability - Improved hardened Docker startup flow - Improved deployment documentation ### Security - Added token-based frontend access mode - Added external secret handling recommendations - Added isolated Spotify credential storage - Added safer cookie handling flow - Improved Docker secret isolation documentation - Removed unused downloader dependencies to reduce transitive attack surface - Hardened download filename sanitization - Hardened remote cover-art fetching with protocol, MIME, timeout, and size checks - Added yt-dlp subprocess timeout and single-settlement handling - Shaped track websocket payloads to avoid leaking internal entity fields - Normalized visible project naming to Jarri Spooty ### Frontend - Added Spotify login integration - Added auth token bootstrap from URL - Improved playlist rendering behavior - Improved large playlist progress tracking ## Improved - Improved YouTube throttling resistance - Improved age-gated video recovery behavior - Improved operational observability - Improved cover-art embedding resilience - Improved queue stability during large playlist imports - Improved deterministic runtime behavior - Improved Docker persistence handling ## Fixed - Fixed Spotify playlist truncation at 100 tracks - Fixed incomplete playlist retrieval behavior - Fixed repeated retry loops against failed YouTube videos - Fixed queue deadlocks during retries - Fixed retry-button queue collisions - Fixed container database loss on restart - Fixed yt-dlp wrapper opacity issues - Fixed hidden yt-dlp stderr failures - Fixed multiple age-gated fallback failure paths - Fixed invalid YouTube candidate reuse - Fixed several Docker persistence edge cases --- # 2.4.2 (Original Spooty Endpoint) ## Fixed - Fixed Spotify playlist pagination using `data.next` - Fixed incomplete playlist retrieval behavior --- # 2.4.1 ## Fixed - Fixed Docker Node.js version compatibility --- # 2.4.0 ## Added - Added configurable audio quality selection ## Fixed - Fixed special character download issues - Fixed EJS runtime issue --- # 2.3.0 ## Added - Added individual track downloads - Added cover art support --- # 2.2.0 ## Added - Added Spotify API integration - Added YouTube cookie support - Added download timeout handling --- # 2.0.0 ## Added - Introduced queue-based backend architecture --- # 1.0.0 ## Added - Initial release