- Rename milestone from 'Features & Extensibility' to 'Multi-Library Support' - Replace old phases 10-14 (TAG/SMRT/GAP/MB/LAYOUT/PLUG) with 20 multi-library requirements (LIB/LSCAN/VIEW/PLAY/DATA) - Move deferred features to Future Requirements - Update research files with multi-library research (Stack, Features, Architecture, Pitfalls) - Architecture: hybrid model (library_id on audio_files only), libraries in DB, sequential scanning, phantom tracks
2.6 KiB
2.6 KiB
Research Summary: Multi-Library Support
Synthesized: 2026-03-08 Sources: STACK.md, FEATURES.md, ARCHITECTURE.md, PITFALLS.md
Key Findings
Stack
- Zero new packages needed — existing SQLite, sqlc, Wails, Lit stack handles everything
- Migration 6 follows existing PRAGMA user_version pattern (5 precedents)
- sqlc queries: create ByLibrary variants for ~5 key queries
Features
- Desktop player pattern: Merged view by default (foobar2000, Roon), optional filter (Navidrome)
- Table stakes: Multiple folders, unified view, per-folder scan, graceful removal, offline handling
- Anti-features: Separate databases, user access control, auto-dedup
- Cross-library playlists are expected by users (Navidrome, foobar2000)
Architecture
- Hybrid model:
library_idonaudio_filesonly; artists/albums/genres stay global - Migration 6: Create libraries table -> add library_id column -> rebuild playlist_tracks for SET NULL + phantom columns -> recreate track_metadata VIEW
- Scan pipeline:
ScanLibrary(id)replacesScan(), sequential coordination - Orphan cleanup: Reference-counting bottom-up deletes for shared entities
- FTS5: Contentless table works via JOIN filtering; consider contentless_delete migration
Critical Pitfalls
- ALTER TABLE ADD COLUMN requires DEFAULT for NOT NULL — create libraries first
- Table rebuild must audit ALL CASCADE FKs (playlist_tracks AND queue_tracks)
- FTS5 contentless can't DELETE rows — stale entries accumulate after library removal
- Orphan cleanup must not delete shared entities across libraries
- Existing user migration must be seamless (TOML to DB)
- Scan coordination must serialize (single-writer SQLite)
Architecture Decision Record
| Decision | Rationale |
|---|---|
| library_id on audio_files only | Physical files belong to libraries; logical entities (artists, albums) are global |
| Libraries in DB, not TOML | CRUD through UI shouldn't require TOML manipulation; DB is already source of truth |
| SET NULL for playlist_tracks FK | Phantom tracks preserve playlist structure when library removed |
| CASCADE for queue_tracks FK | Queue is ephemeral, not user-curated like playlists |
| Sequential scanning | SQLite single-writer makes parallel scans pointless |
| Backend filtering, not frontend | Don't load 150K tracks when viewing one library |
Build Order
- Schema & Migration — Foundation everything else depends on
- Backend Scan Pipeline — Per-library scanning before exposing in UI
- Backend API — CRUD, filtered queries, events, orphan cleanup
- Frontend — Library manager, filter, store updates, phantom display