Status & Changelog
iOS App Store
17.0.0 (80)
LIVE since 2026-04-27
Server
v1.0.47
Self-hosted Docker image
Changelog
v18.0
· Shipped 2026-05-06
#
- Multi-stage
python:3.11-alpine AS generator + nginx:alpine runtime Dockerfile with repo-root build context + default-deny .dockerignore allowlist; MILESTONES.md backfilled with v16.x and v17.0 entries (Phase 162)
- iOS-led hero with App Store badge, "Self-hosted. No signup." brand pivot, all four
https://github.com/your-repo/soundstash placeholders removed, six-card Server features grid, How-it-works iPhone↔server sync SVG diagram, OG/Twitter card meta tags on six pages, build-time-generated 1200×630 og-image.jpg (Phase 163)
- Build-time
pages/status.html generator (Python+Jinja2+Markdown) reading VERSION + MILESTONES.md + ios-status.json with strict regex lint, fail-fast on heading drift (Phase 164)
- Windows installer (
dist/SoundStash-Setup.exe, 29 MB) bundled into nginx image as separate early COPY layer with click-through pages/download.html showing version + size + SHA-256 + SmartScreen caveat; build fails fast if installer missing (Phase 165)
- Full
pages/docs.html rewrite into Server / iOS / Podcasts / Troubleshooting sections current with v14.0–v17.0 features; sticky two-level sidebar ToC with IntersectionObserver scroll-spy; ten zero-footprint anchor-alias spans for SEO carry-forward (Phase 166)
verify_phase167.sh runs 8 automated QA gates (Lighthouse mobile 97/100/100/92, Lychee 0 broken, axe-core 0 WCAG, image 52 MB ≤ 90 MB cap, og-image 26 KB ≤ 300 KB cap, Phase 163 placeholder-grep inheritance, ToS hygiene gate H) (Phase 167)
- Post-ship editorial pivot 2026-05-06: homepage feature section split into "In your pocket" (6 iOS cards) leading + "On your server" (4 server cards) secondary; nav split App / Server
- Post-ship YouTube ToS hygiene pass 2026-05-06: replaced "YouTube downloader" marketing copy with
yt-dlp / "URL" framing across index/docs/changelog; build-time gate H prevents regression; CLAUDE.md "YouTube ToS hygiene (CRITICAL)" policy added
v17.0
· Shipped 2026-04-23
#
- Podcast subscribe / discover / OPML import (Phase 151)
- Episode browse / detail / FTS5 search (Phase 152)
- Core download pipeline + background conditional-GET refresh (Phases 153, 158)
- Server-fallback bulk download + storage management (Phase 154)
- Playback position sync + PC2.0 / PSC chapters (Phases 155, 156)
- Continuous-playback queues (Phase 157)
- Bidirectional sync hardening with absorbing tombstones + per-field LWW (Phase 159)
- App Store ship polish + multi-device test + 2.5.4 background-modes audit (Phase 160)
- Phase 160.1 paywall gating closed the unified 20-download free-tier loophole on podcasts (ship-blocker)
- Phase 161 closed v17.0 doc hygiene with 4 cleanup plans (27 stale REQ-IDs flipped Pending→Satisfied; ROADMAP Progress table refreshed; retrofit
*-VERIFICATION.md scaffolding for Phases 152, 153, 158)
v16.3
· Shipped 2026-04-06
#
getSeriesEpisodeTrackIds() database-driven track discovery (Phase 147)
- Complete cascade deletion with before/after orphan sweep (Phase 148)
- Playback guard via
TrackPlayer.reset() before deletion to prevent dangling playback handles (Phase 149)
- "Delete All Local Data" reset button added under Settings → Storage
- v1.2.3 (build 57) submitted to App Store review
v16.2
· Shipped 2026-04-04
#
LEFT JOIN exclusion queries in offlineDb.ts for standalone-track detection (Phase 143)
- BrowseScreen Tracks section with dual-path loading and TrackRow rendering (Phase 144)
- Tap-to-play via
loadPlaylistForOfflinePlayback with album search (Phase 145)
- Debounced live refresh on download completion / deletion (Phase 146)
- v1.2.2 (build 52) submitted to App Store review
- Expo deprecation warnings fixed (
newArchEnabled, userInterfaceStyle)
v16.1
· Shipped 2026-04-03
#
INSERT OR REPLACE in upsertSeries() silently zeroed episode_count → switched to ON CONFLICT DO UPDATE
- Sync engine previously ignored
delta.series.updated → now processes full series metadata on incremental sync
- Offline completion check loosened from
progressPct === 100 → requires all episodes downloaded AND completed
- Zero-denominator "X of 0 episodes" display replaced with "No episodes" fallback
- Fastlane
release lane added for automated App Store submissions
- App version bumped to 1.2.1; submitted to App Store review
v16.0
· Shipped 2026-04-02
#
- PyInstaller spec includes all new dependencies (
feedparser, listparser, nh3, podcastindex, rapidfuzz, zeroconf) via collect_submodules()
rapidfuzz>=3.9.5 version floor pinned to fix PyInstaller SIMD bundling
- Native extensions (
nh3, rapidfuzz) confirmed bundled as .pyd in the Windows build
- Windows entrypoint switched from
waitress.serve() to socketio.run() so WebSocket transport works on the bundled runtime
- Real-time download progress now delivers WebSocket events on the Windows runtime (was silent before)
- Background podcast-refresh service works under Windows threading mode
- Expanded smoke test covers podcasts, podcast queues, BorrowBox, homepage dashboard, and the WebSocket handshake
- PyInstaller build completes without errors on the Windows host; all expanded smoke tests pass against the Windows-built runtime
- Manual podcast subscribe-download-playback flow verified end-to-end on the Windows runtime
v15.0
· Shipped 2026-03-30
#
- Per-podcast playback order with feed-type defaults, episode list filtering/ordering API, order-aware auto-advance, and PodcastQueue database tables for Phase 132
- Player context discriminator, episode filter segmented control, and play order indicator/settings wired to API endpoints from Plan 01
- Smart playlist rule engine for PodcastEpisode with 7 filterable fields, 5 sort modes including grouped-by-podcast interleaving, and 4 idempotent default queues
- REST API blueprint with 11 endpoints for podcast queue CRUD, episode management with D-09 sort mode application, smart playlist preview, and bootstrap integration creating 4 default queues on startup
- Queue list page with card grid and smart queue rule editor with 7 podcast-specific fields, relative date presets, podcast dropdown, and live preview
- Queue detail page with episode display, drag-to-reorder, inline rename, and +Q flyout on podcast detail for adding episodes to queues
- GET next-episode endpoint resolves queue sort order server-side and returns the adjacent episode for queue-driven auto-advance playback
- Queue-driven playback with auto-advance countdown, session persistence via localStorage, interruption/resume flow, and Now Playing queue context display
- Download worker hardened with 15-min timeout watchdog and persistent queue, plus 4 new bulk download API endpoints with filter presets (all_undownloaded, last_5, last_10, all_unlistened) and count queries
- Download Episodes dropdown with 4 filter presets on podcast detail page and Download New Episodes button on subscriptions page, with batch completion toast via WebSocket tracking
v14.0
· Shipped 2026-03-28
#
- Podcast data foundation with RSS parsing, iTunes namespace, and malformed feed tolerance
- Subscribe, search (iTunes + Podcast Index), and discover with sidebar mode toggle
- Full episode lifecycle: download with WebSocket progress, storage retention, playback with resume and speed control
- Chapter navigation supporting Podcasting 2.0 JSON, PSC, and ID3 CHAP formats
- Background refresh with configurable intervals, auto-download per podcast, conditional HTTP caching
- OPML import/export for subscription migration from Apple Podcasts, Overcast, Pocket Casts
- Episode/season promotion to main library with Track/Series creation and symlink
- Integration hardening via gap closure phase (OPML WebSocket, auto-download toast, refresh service restart, promotion file_path)
v13.0
· Shipped 2026-03-25
#
- Researched podcast RSS ecosystem: feedparser for parsing, iTunes Search API for discovery, python-podcastindex for secondary search, listparser for OPML
- Competitive analysis of Overcast and Amazon Podcasts — SoundStash already has ~60% of podcast infrastructure (player, downloads, series, scheduled tasks)
- Architecture decision: dedicated Podcast/PodcastEpisode models (not reusing Track/Series), sidebar navigation (not mode toggle), shared Player with isPodcast branching
- Identified key pitfalls: GUID fragility, unbounded storage growth, Track model contamination, iTunes namespace requirements, feed HTTP edge cases
- Produced 6-phase implementation recommendation: Foundation → Download/Player → Refresh/Auto-download → Chapters/Queue → Audio Enhancement → Library Migration
v12.0
· Shipped 2026-03-24
#
- Deployed demo server via Cloudflare Quick Tunnel with LibriVox public domain audiobooks for Apple reviewer (Named Tunnel not possible — ihelm.org.uk DNS not on Cloudflare)
- Removed nginx basic auth layer after mobile Safari re-prompted credentials on every page navigation
- Captured screen recording on iPhone 16 Pro and verified IAP sandbox purchase flow end-to-end
- Submitted Resolution Center reply addressing all 5 Apple Guideline 2.1 requirements with recording attached
- Added demo/README.md documenting Quick Tunnel decision and operational caveats
v11.0
· Shipped 2026-03-23
#
- Reverted detection page from v9.1 multi-stage queue to simple candidate cards with accept/modify/reject (5,400-line JS → 1,240 lines)
- Added "Add Track" modal to series detail page with library search, smart episode number guessing from track titles, and insert-and-shift positioning
- Extended accept-candidate endpoint with cover_track_id for user-selected series cover art
- Stripped ~2,100 lines of dead v9.1 gap-fill/queue/completeness UI code while preserving all backend APIs and database tables
- Added .m4b audiobook format support (Libation/Audible imports)
- Extended library search to match file paths (folder names find tracks)
v9.0
· Shipped 2026-03-20
#
v9.1
· Shipped 2026-03-14
#
v8.0
· Shipped 2026-03-07
#
- Route restructuring with homepage at
/, download at /download, BorrowBox at /borrowbox, and grouped sidebar navigation with three sections
- Homepage dashboard with Continue Listening, library stats cards, Recently Added, listening time statistics, Continue Series, Chart.js charts, and Recently Finished
- BorrowBox ZIP import with automatic chapter extraction, ID3 metadata reading, series creation, and duplicate conflict resolution via WebSocket
- BorrowBox account connection with Fernet-encrypted credentials, multi-strategy login, loan browsing with cover art, and one-click audiobook download with chapter-level progress
- BorrowBox loan lifecycle with expiry tracking (active/expiring/expired computed status), visual badges in library and series views, and legal disclaimer acceptance modal
- PlaybackSession delta recording for accurate listening time statistics with time-bucketed aggregation
v7.0
· Shipped 2026-03-06
#
- Web Audio API FFT pipeline with AnalyserNode, 1024-bin-to-64-bar logarithmic processing, and exponential decay smoothing
- Five Canvas2D visualizer modes (Spectrum Bars, Oscilloscope, Circular, Milkdrop-Lite, Frequency Landscape) with full-screen overlay, mode switching, and 5 color palettes
- iOS native Swift FFT module using MTAudioProcessingTap + vDSP with Expo Modules bridge, 30fps CADisplayLink, and KVO-based track re-attachment
- Five View-based iOS visualizer modes with React.memo optimization, dB-scaled FFT data, and full-bleed layout outside SafeAreaView
- Cross-platform parity: identical palette hex values, mode names, FFT processing constants (64 bars, 0.85 decay, log binning), and dB range mapping
- Visual polish: peak hold indicators (500ms hold, 3.0 gravity), per-mode glow effects, album art color extraction (Canvas + react-native-image-colors), and complete v6.5 legacy removal
- All 26 requirements verified including genuine physical device testing on iPhone 16 Pro (TestFlight build 24)
v6.5
· Shipped 2026-03-03
#
- iPhone rotation unlocked app-wide with compact landscape-safe shell, browse, downloads, detail, modal, and settings layouts
- Now Playing redesigned into a deliberate landscape surface with stable scrub state, compact utility sheets, and queue-safe dismissal flow
- Retro visualizer mode added inside Now Playing with a reusable shell, two distinct presets, and track-aware palette treatment
- Visualizer preset persistence, lighter split live/idle animation timing, and failure-aware artwork fallback hardened the visualizer for real playback
- TestFlight build 1.1.0 (7) validated the shipped landscape + visualizer flow, and the upload helper permission issue was fixed for future deploys
v6.4
· Shipped 2026-03-03
#
- Author-aware series auto-detection with RapidFuzz fuzzy matching, author-based grouping, and enhanced online enrichment with persistent caching
- Post-save series editing: drag-to-reorder episodes, add library tracks to existing series, quick-create series from multi-select, and cross-series track moves
- Series merge with two-phase flow (picker + preview), duplicate detection, drag-to-reorder combined episodes, and atomic commit
- Completeness tracking: expected episode count, gap placeholder rendering, file unavailability indicators, library gap-fill search, and URL-based gap-fill with download-then-assign
- Series browse polish: author dropdown filter, author-inclusive search, completeness indicators on cards, and startup author backfill migration
v6.2
· Shipped 2026-03-01
#
- Device-local SQLite database with FTS5 search indexes all downloaded track and collection metadata for offline browsing and filtering
- Two-layer server reachability (NetInfo + health polling) with OfflineError fail-fast on API calls, amber offline banner, and green back-online toast
- Offline-aware browse screens: all three browse views (Browse, PlaylistDetail, SeriesDetail) fall back to cached/local data with dimmed non-downloaded tracks
- Downloaded content filter across Browse, Series, and Playlist screens with two-layer state (user preference + auto-override) and automatic offline activation
- Server auto-discovery: Flask mDNS advertisement via Bonjour + iOS react-native-zeroconf scanning with auto-connect, multi-server list, and manual IP fallback
- Gap closure: full metadata pass-through for playlist/series downloads, one-time repair scan, season-grouped rendering, resetReachability wiring, and server version display
v6.1
· Shipped 2026-02-28
#
- App Store Connect app record and API key (.p8) infrastructure configured on Mac Mini for automated iOS distribution
- Branded SoundStash app icon and dark-themed splash screen generated via reproducible Pillow asset pipeline (generate-assets.py)
- Fastlane automation pipeline (Gemfile, Appfile, Fastfile) with beta/build_only lanes, pre-flight validation, auto build number increment, and Xcode 26.2 altool workaround
- One-command WSL-to-TestFlight deploy script (deploy-testflight.sh) with --sync/--release modes and --notes changelog support
- Build reproducibility hardened: expo-splash-screen pinned in package.json, lock file regenerated, script permissions fixed, error messages corrected
- All documentation and traceability gaps from milestone audit closed (INFRA-02 traceability, CLAUDE.md deps, ROADMAP.md plan status)
v6.0
· Shipped 2026-02-27
#
- Expo SDK 54 + RNTP 4.1.1 iOS build pipeline with WSL-to-Mac Mini SSH deployment and Ad Hoc distribution to physical iPhone
- Full offline audio playback on iPhone with background audio, lock screen/Control Center controls, sleep timer (15/30/45/60/end-of-track), and 0.5x-2.0x speed control
- Flask delta sync API with deletion tombstones, and bidirectional position/listening status sync with offline queue and auto-push on reconnect
- Download manager with concurrent queue, pause/resume, retry on failure, WiFi-only mode, and per-track progress indicators
- Library browsing from server with combined playlist+series list, drill-down detail views, search, and cover art caching via expo-image
- Series browsing with season picker, auto-advance playback (global/per-series toggle), and Continue Listening home section with one-tap resume
- Dark theme matching SoundStash web aesthetic, offline indicator badges, and storage management screen with swipe-to-delete and undo
v5.2
· Shipped 2026-02-25
#
- Backend batch hydration delivers full track metadata (title, artist, duration, cover art) for every candidate via 2 chunked SQL queries
- Rich candidate cards with cover art thumbnails, episode numbers, match reasons, and aggregate summary (duration + format distribution)
- Shared renderRichTrackRow() component used consistently across candidate cards and Modify modal
- Drag-to-reorder episodes in Modify modal with HTML5 Drag API, visual feedback, and Reset Order button
- Edit protection guard deferring background refreshes while Modify modal is open with external change detection
v5.1
· Shipped 2026-02-24
#
- Database migration to soundstash.db with backwards-compatible four-scenario handling and WAL companion file support
- Docker configuration renamed (service, container, project name, compose project) to soundstash
- All 15+ templates branded as SoundStash with consistent "Page | SoundStash — Personal Audio Library" title format
- Backend identifiers updated: health endpoint, Plex headers, MusicBrainz User-Agent, backup filenames, client ID format
- Legal documents revised with multi-source language, Plex privacy sections, and broadened copyright disclaimers
- 45 planning files bulk-updated across milestones, phases, codebase docs, and research docs with historical rename context preserved
v5.0
· Shipped 2026-02-24
#
- 30-second skip forward/back buttons on mini player and Now Playing overlay with keyboard shortcuts and position persistence
- Full-screen Now Playing overlay with responsive layout, large cover art, all playback controls, queue drag-to-reorder, and mobile swipe gestures
- Player tech debt cleanup: fixed default-cover.png references across 9 files, consolidated play button logic, standardized event handlers
- Bulk metadata re-scan pipeline with WebSocket progress, diff preview modal, fill-empty/overwrite modes, and crash recovery checkpointing
- Scheduled background scanning with configurable intervals (startup/daily/weekly/custom), conflict detection, and settings UI toggle
- Series auto-detection engine with four-strategy local pattern matching and opt-in online enrichment via MusicBrainz, OpenLibrary, and Google Books
v4.0
· Shipped 2026-02-22
#
- Three-state listening status (Unplayed/In Progress/Completed) with automatic transitions, manual override, and library-wide filter
- Visual status indicators (dot/ring/checkmark) in grid and list views, smart playlist listening_status rule support
- Series entity with full CRUD: create, edit, delete, cover art auto-populate, seasons, ordered episodes
- Series browse mode as 4th library mode with progress rings, completion badges, and drill-down navigation
- Continue Listening series context and auto-advance playback with countdown overlay and per-series toggle
- Playlist URL detection with preview, batch download, and automatic series creation with episode ordering
- Retroactive data migration for existing tracks (play_count > 0 → Completed)
v3.0
· Shipped 2026-02-21
#
- Docker CLI and Compose installed in container with socket detection and graceful degradation when Docker unavailable
- Host filesystem browsing with WSL drive letter detection, path translation (/host → /mnt), and last-path persistence
- Compose file self-editing via ruamel.yaml round-trip with automatic backups, validation, and atomic writes
- Mount CRUD UI with pending changes queue, protected mount badges, and affected track warnings before removal
- Container self-recreation via fire-and-forget subprocess with WebSocket pre-notification across tabs
- End-to-end restart flow with active download guard, reconnect overlay with health polling, and post-reconnect data auto-refresh
v2.0
· Shipped 2026-02-17
#
- Playback position persistence across sessions with auto-resume via write-through cache, localStorage queue storage, and sendBeacon sync
- Player enhancements: adjustable speed (0.5x-2.0x), sleep timer with timed/end-of-track modes, and Continue Listening section
- Multi-folder library foundation with centralized PathResolver, default folder bootstrap, and folder management UI
- Automated folder scanning with availability checking, offline track indicators, and batch import with deduplication
- Multi-folder download integration with target folder selection in URL/Plex downloads and cross-folder track moves
v1.2
· Shipped 2026-02-13
#
- Codec detection and in-place conversion system with WebSocket progress and library badges for unplayable formats
- Plex download-time codec warnings with one-click conversion format selection for video extraction and music tracks
- Hardened URL source quality analysis with ABR fallback and real-time upsample/downsample format warnings
- File path display in track detail panel with library-relative path stripping
- Hierarchical library browsing with artist/album/folder navigation, breadcrumbs, and full track interactivity
v1.1
· Shipped 2026-02-10
#
- Full metadata editing: inline editing, detail drawer with 9 fields, cover art upload with crop, batch edit
- Smart URL title parsing with regex engine, confidence scoring, and preview-before-apply
- Configurable Artist/Album folder organization with dry-run preview, atomic moves, and auto-organize on download
- Rule-based smart playlists with visual builder, AND/OR logic, sort/limit, preview, and auto-refresh
- Watch folder monitoring with auto-scan, browser drag-drop upload, and cloud placeholder detection
- Database backup with SHA-256 file manifest and merge/replace restore with integrity verification
v1.0
· Shipped 2026-02-08
#
- Database foundation with Fernet-encrypted Plex credential storage
- Dual authentication — OAuth server discovery + manual token fallback
- Full music library browsing hierarchy (Libraries → Artists → Albums → Tracks)
- Music download pipeline with real-time WebSocket progress and metadata preservation
- Two-stage format conversion pipeline with FFmpeg (download → convert → metadata)
- Video audio extraction from movies/TV shows with multi-track selection
- Unified library with source badges and filtering across all configured sources