docs(12-01): complete library CRUD backend plan
- SUMMARY.md with 2 task commits, 6 files, 6 requirements completed - STATE.md advanced to Phase 12 Plan 1/2, added Phase 12 decisions - ROADMAP.md marked 12-01 complete (1/2 plans) - REQUIREMENTS.md marked LIB-01, LIB-02, LIB-03, DATA-02, DATA-03, PLAY-04 complete
This commit is contained in:
+14
-14
@@ -23,9 +23,9 @@ Requirements for v1.1 Multi-Library Support milestone. Each maps to roadmap phas
|
|||||||
|
|
||||||
### Library Management
|
### Library Management
|
||||||
|
|
||||||
- [ ] **LIB-01**: User can add a new library directory via a folder picker dialog
|
- [x] **LIB-01**: User can add a new library directory via a folder picker dialog
|
||||||
- [ ] **LIB-02**: User can rename a library (display name)
|
- [x] **LIB-02**: User can rename a library (display name)
|
||||||
- [ ] **LIB-03**: User can remove a library — tracks are deleted from DB, shared entities (artists, albums, genres) are cleaned up only if no other library references them
|
- [x] **LIB-03**: User can remove a library — tracks are deleted from DB, shared entities (artists, albums, genres) are cleaned up only if no other library references them
|
||||||
- [x] **LIB-04**: Libraries are stored in SQLite (not TOML config) with CRUD through the UI
|
- [x] **LIB-04**: Libraries are stored in SQLite (not TOML config) with CRUD through the UI
|
||||||
- [x] **LIB-05**: Existing single-directory config is migrated seamlessly to the libraries table on first run after upgrade
|
- [x] **LIB-05**: Existing single-directory config is migrated seamlessly to the libraries table on first run after upgrade
|
||||||
- [ ] **LIB-06**: Library list is displayed in a management UI (settings or sidebar section)
|
- [ ] **LIB-06**: Library list is displayed in a management UI (settings or sidebar section)
|
||||||
@@ -50,13 +50,13 @@ Requirements for v1.1 Multi-Library Support milestone. Each maps to roadmap phas
|
|||||||
- [ ] **PLAY-01**: Playlists can contain tracks from multiple libraries (cross-library playlists)
|
- [ ] **PLAY-01**: Playlists can contain tracks from multiple libraries (cross-library playlists)
|
||||||
- [ ] **PLAY-02**: When a library is removed, playlist entries for that library's tracks become phantom tracks (preserved with cached metadata, not cascade-deleted)
|
- [ ] **PLAY-02**: When a library is removed, playlist entries for that library's tracks become phantom tracks (preserved with cached metadata, not cascade-deleted)
|
||||||
- [ ] **PLAY-03**: Phantom tracks are visually distinguished in playlist views (e.g., greyed out, icon indicator)
|
- [ ] **PLAY-03**: Phantom tracks are visually distinguished in playlist views (e.g., greyed out, icon indicator)
|
||||||
- [ ] **PLAY-04**: Queue tracks from a removed library are cascade-deleted (queue is ephemeral)
|
- [x] **PLAY-04**: Queue tracks from a removed library are cascade-deleted (queue is ephemeral)
|
||||||
|
|
||||||
### Data Integrity
|
### Data Integrity
|
||||||
|
|
||||||
- [x] **DATA-01**: Schema migration adds `libraries` table and `library_id` FK on `audio_files`
|
- [x] **DATA-01**: Schema migration adds `libraries` table and `library_id` FK on `audio_files`
|
||||||
- [ ] **DATA-02**: Orphan cleanup after library removal: reference-counting bottom-up deletes for artists, albums, genres only referenced by removed library's tracks
|
- [x] **DATA-02**: Orphan cleanup after library removal: reference-counting bottom-up deletes for artists, albums, genres only referenced by removed library's tracks
|
||||||
- [ ] **DATA-03**: FTS5 index entries for removed tracks are cleaned up (handling contentless table limitations)
|
- [x] **DATA-03**: FTS5 index entries for removed tracks are cleaned up (handling contentless table limitations)
|
||||||
- [x] **DATA-04**: All library operations are transactional — no partial state on failure
|
- [x] **DATA-04**: All library operations are transactional — no partial state on failure
|
||||||
|
|
||||||
## Future Requirements
|
## Future Requirements
|
||||||
@@ -180,9 +180,9 @@ Which phases cover which requirements. Updated during roadmap creation.
|
|||||||
| KEY-03 | Phase 9 | Complete |
|
| KEY-03 | Phase 9 | Complete |
|
||||||
| KEY-04 | Phase 9 | Complete |
|
| KEY-04 | Phase 9 | Complete |
|
||||||
| KEY-05 | Phase 9 | Complete |
|
| KEY-05 | Phase 9 | Complete |
|
||||||
| LIB-01 | Phase 12 | Pending |
|
| LIB-01 | Phase 12 | Complete |
|
||||||
| LIB-02 | Phase 12 | Pending |
|
| LIB-02 | Phase 12 | Complete |
|
||||||
| LIB-03 | Phase 12 | Pending |
|
| LIB-03 | Phase 12 | Complete |
|
||||||
| LIB-04 | Phase 10 | Complete |
|
| LIB-04 | Phase 10 | Complete |
|
||||||
| LIB-05 | Phase 10 | Complete |
|
| LIB-05 | Phase 10 | Complete |
|
||||||
| LIB-06 | Phase 12 | Pending |
|
| LIB-06 | Phase 12 | Pending |
|
||||||
@@ -198,15 +198,15 @@ Which phases cover which requirements. Updated during roadmap creation.
|
|||||||
| PLAY-01 | Phase 13 | Pending |
|
| PLAY-01 | Phase 13 | Pending |
|
||||||
| PLAY-02 | Phase 13 | Pending |
|
| PLAY-02 | Phase 13 | Pending |
|
||||||
| PLAY-03 | Phase 13 | Pending |
|
| PLAY-03 | Phase 13 | Pending |
|
||||||
| PLAY-04 | Phase 12 | Pending |
|
| PLAY-04 | Phase 12 | Complete |
|
||||||
| DATA-01 | Phase 10 | Complete |
|
| DATA-01 | Phase 10 | Complete |
|
||||||
| DATA-02 | Phase 12 | Pending |
|
| DATA-02 | Phase 12 | Complete |
|
||||||
| DATA-03 | Phase 12 | Pending |
|
| DATA-03 | Phase 12 | Complete |
|
||||||
| DATA-04 | Phase 10 | Complete |
|
| DATA-04 | Phase 10 | Complete |
|
||||||
|
|
||||||
**Coverage:**
|
**Coverage:**
|
||||||
- v1.1 requirements: 31 total (8 complete + 23 pending)
|
- v1.1 requirements: 31 total (19 complete + 12 pending)
|
||||||
- Mapped to phases: 31/31 ✓ (Phase 9: 8 complete, Phases 10-13: 23 pending)
|
- Mapped to phases: 31/31 ✓ (Phase 9: 8, Phase 10: 5, Phase 11: 4, Phase 12: 6 of 7 — 12 pending in Phase 12-13)
|
||||||
- No orphaned requirements
|
- No orphaned requirements
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ Plans:
|
|||||||
5. Queue tracks from a removed library are cascade-deleted; the queue continues playing from the next valid track
|
5. Queue tracks from a removed library are cascade-deleted; the queue continues playing from the next valid track
|
||||||
**Plans:** 2 plans
|
**Plans:** 2 plans
|
||||||
Plans:
|
Plans:
|
||||||
- [ ] 12-01-PLAN.md — Backend CRUD API + orphan cleanup + queue compaction + events
|
- [x] 12-01-PLAN.md — Backend CRUD API + orphan cleanup + queue compaction + events
|
||||||
- [ ] 12-02-PLAN.md — Frontend library management UI in settings + sidebar cleanup
|
- [ ] 12-02-PLAN.md — Frontend library management UI in settings + sidebar cleanup
|
||||||
|
|
||||||
### Phase 13: Library Views & Phantom Tracks
|
### Phase 13: Library Views & Phantom Tracks
|
||||||
@@ -124,7 +124,7 @@ Plans:
|
|||||||
| 9. Scan Cancellation & Keyboard Shortcuts | v1.1 | 5/5 | Complete | 2026-03-07 |
|
| 9. Scan Cancellation & Keyboard Shortcuts | v1.1 | 5/5 | Complete | 2026-03-07 |
|
||||||
| 10. Schema & Migration | 2/2 | Complete | 2026-03-09 | - |
|
| 10. Schema & Migration | 2/2 | Complete | 2026-03-09 | - |
|
||||||
| 11. Per-Library Scan Pipeline | 3/3 | Complete | 2026-03-09 | - |
|
| 11. Per-Library Scan Pipeline | 3/3 | Complete | 2026-03-09 | - |
|
||||||
| 12. Library CRUD & Data Integrity | v1.1 | 0/2 | Planned | - |
|
| 12. Library CRUD & Data Integrity | v1.1 | 1/2 | In Progress | - |
|
||||||
| 13. Library Views & Phantom Tracks | v1.1 | 0/? | Not started | - |
|
| 13. Library Views & Phantom Tracks | v1.1 | 0/? | Not started | - |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
+22
-11
@@ -22,11 +22,11 @@ See: .planning/PROJECT.md (updated 2026-03-08)
|
|||||||
|
|
||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
Phase: 11 — Per-Library Scan Pipeline
|
Phase: 12 — Library CRUD & Data Integrity
|
||||||
Plan: 3 of 3 in Phase (Plan 03 complete)
|
Plan: 1 of 2 in Phase (Plan 01 complete)
|
||||||
Status: Phase 11 complete — all plans done
|
Status: Plan 12-01 complete — backend CRUD API implemented
|
||||||
Progress: ████████████████░░░░ 3/5 phases complete (Phase 11 complete)
|
Progress: ████████████████░░░░ 3/5 phases complete (Phase 12 in progress)
|
||||||
Last activity: 2026-03-09 — Completed 11-03 wire auto-scan and legacy cleanup
|
Last activity: 2026-03-12 — Completed 12-01 library CRUD backend API
|
||||||
|
|
||||||
### Phase Overview
|
### Phase Overview
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ Last activity: 2026-03-09 — Completed 11-03 wire auto-scan and legacy cleanup
|
|||||||
| 9. Scan Cancellation & Keyboard Shortcuts | Complete (5/5 plans) ✅ |
|
| 9. Scan Cancellation & Keyboard Shortcuts | Complete (5/5 plans) ✅ |
|
||||||
| 10. Schema & Migration | Complete (2/2 plans) ✅ |
|
| 10. Schema & Migration | Complete (2/2 plans) ✅ |
|
||||||
| 11. Per-Library Scan Pipeline | Complete (3/3 plans) ✅ |
|
| 11. Per-Library Scan Pipeline | Complete (3/3 plans) ✅ |
|
||||||
| 12. Library CRUD & Data Integrity | Not started |
|
| 12. Library CRUD & Data Integrity | In progress (1/2 plans) |
|
||||||
| 13. Library Views & Phantom Tracks | Not started |
|
| 13. Library Views & Phantom Tracks | Not started |
|
||||||
|
|
||||||
## Performance Metrics
|
## Performance Metrics
|
||||||
@@ -55,6 +55,7 @@ Last activity: 2026-03-09 — Completed 11-03 wire auto-scan and legacy cleanup
|
|||||||
| Phase 11-01 P01 | 7 min | 2 tasks | 11 files |
|
| Phase 11-01 P01 | 7 min | 2 tasks | 11 files |
|
||||||
| Phase 11-03 P03 | 10 min | 1 task | 3 files |
|
| Phase 11-03 P03 | 10 min | 1 task | 3 files |
|
||||||
| Phase 11-02 P02 | 4 min | 2 tasks | 2 files |
|
| Phase 11-02 P02 | 4 min | 2 tasks | 2 files |
|
||||||
|
| Phase 12-01 P01 | 6 min | 2 tasks | 6 files |
|
||||||
|
|
||||||
## Accumulated Context
|
## Accumulated Context
|
||||||
|
|
||||||
@@ -108,6 +109,16 @@ Decisions from v1.0 are archived in PROJECT.md Key Decisions table. Key patterns
|
|||||||
| LibraryConfigChanged handler removed entirely | Multi-library model uses CRUD API (Phase 12), not event-driven config updates |
|
| LibraryConfigChanged handler removed entirely | Multi-library model uses CRUD API (Phase 12), not event-driven config updates |
|
||||||
| Scan() wrapper deleted | Only callers were handleConfigUpdate (deleted) and FullRescan (updated to scanInternal) |
|
| Scan() wrapper deleted | Only callers were handleConfigUpdate (deleted) and FullRescan (updated to scanInternal) |
|
||||||
|
|
||||||
|
### Phase 12 Decisions
|
||||||
|
|
||||||
|
| Decision | Rationale |
|
||||||
|
|----------|-----------|
|
||||||
|
| Application-level name uniqueness check (iterate GetAllLibraries) | Avoids migration 7; rename is infrequent, check is simple |
|
||||||
|
| RemovalHooks callback struct (StopPlayback + CompactQueue) | Mirrors RescanHooks pattern; breaks circular dependency between library, player, queue packages |
|
||||||
|
| querySingleInt64 helper for hand-crafted SQL aggregates | DB type has QueryContext (returns *sql.Rows) but no QueryRowContext; helper wraps scan-close cycle |
|
||||||
|
| Sentinel errors for all validation per err113 | errLibraryNameEmpty, errLibraryNameTooLong, errLibraryNameDuplicate, errLibraryPathNotExist |
|
||||||
|
| Pre-populate phantom metadata BEFORE cascade delete | Avoids lost join data — playlist_tracks need track metadata after audio_files rows are gone |
|
||||||
|
|
||||||
### Warnings (carry forward)
|
### Warnings (carry forward)
|
||||||
|
|
||||||
- Player lock ordering (`p.mu` before `speaker.Lock()`, goroutine dispatch in beep callback) — carry forward
|
- Player lock ordering (`p.mu` before `speaker.Lock()`, goroutine dispatch in beep callback) — carry forward
|
||||||
@@ -129,10 +140,10 @@ Decisions from v1.0 are archived in PROJECT.md Key Decisions table. Key patterns
|
|||||||
|
|
||||||
### Last Session
|
### Last Session
|
||||||
|
|
||||||
**Date:** 2026-03-09
|
**Date:** 2026-03-12
|
||||||
**What happened:** Executed Phase 11, Plan 03 — wired auto-scan on app launch via ScanAllLibraries goroutine in OnDomReady, removed legacy LibraryConfigChanged handler, handleConfigUpdate, and deprecated Scan() wrapper. Updated FullRescan to resolve library from DB via GetAllLibraries.
|
**What happened:** Executed Phase 12, Plan 01 — implemented backend Library CRUD API (AddLibrary, RenameLibrary, RemoveLibrary, GetRemovalImpact) with full orphan cleanup pipeline, phantom track preservation, FTS5 rebuild, queue compaction via CompactAfterLibraryRemoval, and RemovalHooks wiring in app.go.
|
||||||
**Where we stopped:** Completed 11-03-PLAN.md — Phase 11 complete
|
**Where we stopped:** Completed 12-01-PLAN.md — Plan 01 of Phase 12 complete
|
||||||
**Next action:** Plan Phase 12 (Library CRUD & Data Integrity)
|
**Next action:** Execute Phase 12 Plan 02 (Frontend library management UI)
|
||||||
|
|
||||||
---
|
---
|
||||||
*State initialized: 2026-02-27*
|
*State initialized: 2026-02-27*
|
||||||
@@ -145,4 +156,4 @@ Decisions from v1.0 are archived in PROJECT.md Key Decisions table. Key patterns
|
|||||||
| 18 | add multi-column metadata display to playlist-details | 2026-03-08 | ce23177 | [18-add-multi-column-metadata-display-to-pla](./quick/18-add-multi-column-metadata-display-to-pla/) |
|
| 18 | add multi-column metadata display to playlist-details | 2026-03-08 | ce23177 | [18-add-multi-column-metadata-display-to-pla](./quick/18-add-multi-column-metadata-display-to-pla/) |
|
||||||
|
|
||||||
Last activity: 2026-03-08 - Completed quick task 18: add multi-column metadata display to playlist-details
|
Last activity: 2026-03-08 - Completed quick task 18: add multi-column metadata display to playlist-details
|
||||||
*Last updated: 2026-03-09 — Completed 11-03-PLAN.md (Phase 11 complete)*
|
*Last updated: 2026-03-12 — Completed 12-01-PLAN.md (Phase 12 Plan 01 complete)*
|
||||||
|
|||||||
@@ -0,0 +1,146 @@
|
|||||||
|
---
|
||||||
|
phase: 12-library-crud-data-integrity
|
||||||
|
plan: 01
|
||||||
|
subsystem: library
|
||||||
|
tags: [crud, orphan-cleanup, data-integrity, queue-compaction, phantom-tracks, events]
|
||||||
|
|
||||||
|
# Dependency graph
|
||||||
|
requires:
|
||||||
|
- phase: 11-per-library-scan-pipeline
|
||||||
|
provides: ScanLibrary, ScanAllLibraries, scan queue coordinator
|
||||||
|
- phase: 10-schema-migration
|
||||||
|
provides: libraries table, library_id FK, phantom columns on playlist_tracks
|
||||||
|
provides:
|
||||||
|
- AddLibrary, RenameLibrary, RemoveLibrary, GetRemovalImpact backend API
|
||||||
|
- Orphan cleanup pipeline (recordings → genres → release_groups → artist_credits → artists → cover_art)
|
||||||
|
- Queue CompactAfterLibraryRemoval method
|
||||||
|
- Phantom metadata population before cascade delete
|
||||||
|
- LibraryAdded, LibraryRenamed, LibraryRemoved events
|
||||||
|
affects: [12-02-frontend-library-ui, 13-library-views-phantom-tracks]
|
||||||
|
|
||||||
|
# Tech tracking
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- "RemovalHooks callback struct — breaks circular dependency between library, player, and queue packages"
|
||||||
|
- "Bottom-up orphan cleanup in single transaction — reference-counting DELETE WHERE NOT IN subqueries"
|
||||||
|
- "Pre-populate phantom metadata BEFORE cascade delete — avoids lost join data"
|
||||||
|
- "querySingleInt64 helper for hand-crafted SQL returning single aggregate values"
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- backend/library/crud.go
|
||||||
|
modified:
|
||||||
|
- backend/library/library.go
|
||||||
|
- backend/events/events.go
|
||||||
|
- frontend/src/events.ts
|
||||||
|
- backend/queue/queue.go
|
||||||
|
- backend/app.go
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "Application-level name uniqueness check (iterate GetAllLibraries) rather than DB UNIQUE constraint — avoids migration 7"
|
||||||
|
- "RemovalHooks struct pattern (StopPlayback + CompactQueue callbacks) wired in app.go — mirrors existing RescanHooks pattern"
|
||||||
|
- "querySingleInt64 helper wraps DB.QueryContext returning *sql.Rows since DB has no QueryRowContext method"
|
||||||
|
- "Sentinel errors for all validation (errLibraryNameEmpty, errLibraryNameTooLong, errLibraryNameDuplicate, errLibraryPathNotExist) per err113 linter rule"
|
||||||
|
- "Context parameter placed first in querySingleInt64 per revive context-as-argument rule"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "RemovalHooks callback struct for cross-package lifecycle coordination"
|
||||||
|
- "querySingleInt64 for hand-crafted aggregate SQL queries"
|
||||||
|
|
||||||
|
requirements-completed: [LIB-01, LIB-02, LIB-03, DATA-02, DATA-03, PLAY-04]
|
||||||
|
|
||||||
|
# Metrics
|
||||||
|
duration: 6min
|
||||||
|
completed: 2026-03-12
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 12 Plan 01: Library CRUD Backend API Summary
|
||||||
|
|
||||||
|
**Backend CRUD API with AddLibrary/RenameLibrary/RemoveLibrary, full orphan cleanup pipeline, phantom track preservation, FTS5 rebuild, queue compaction, and event emission**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** 6 min
|
||||||
|
- **Started:** 2026-03-12T23:32:27Z
|
||||||
|
- **Completed:** 2026-03-12T23:38:30Z
|
||||||
|
- **Tasks:** 2
|
||||||
|
- **Files created:** 1
|
||||||
|
- **Files modified:** 5
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- **AddLibrary(path)** — validates path exists, auto-names from folder base, creates DB row via sqlc, emits LibraryAdded, starts async ScanLibrary
|
||||||
|
- **RenameLibrary(id, newName)** — validates 1-50 char length, checks name uniqueness across all libraries (application-level), updates via sqlc, emits LibraryRenamed
|
||||||
|
- **GetRemovalImpact(libraryID)** — read-only queries returning track count, affected playlists count, queue items count for confirmation dialog
|
||||||
|
- **RemoveLibrary(id)** — the critical 23-step method:
|
||||||
|
1. Cancel active scan for library
|
||||||
|
2. Stop playback if current track belongs to library
|
||||||
|
3. Pre-count metrics for summary
|
||||||
|
4. Begin transaction
|
||||||
|
5. Populate phantom metadata on playlist_tracks (BEFORE cascade delete)
|
||||||
|
6. DELETE audio_files WHERE library_id (CASCADE on queue_tracks, SET NULL on playlist_tracks)
|
||||||
|
7. Bottom-up orphan cleanup: recordings → recording_genres → release_group_recordings → release_groups → artist_credits (dual FK check) → artist_credit_artists → artists → genres → cover_art
|
||||||
|
8. DELETE library row
|
||||||
|
9. Commit transaction
|
||||||
|
10. Post-commit: RebuildSearchIndex (FTS5), delete cover art files, CompactQueue, emit events
|
||||||
|
- **CompactAfterLibraryRemoval()** on Queue — reloads surviving tracks from DB, detects if current track survived, resets index, unloads player if needed, clears shuffle order, emits QueueChanged
|
||||||
|
- **RemovalHooks** wired in app.go: StopPlayback → player.UnloadTrack(), CompactQueue → queue.CompactAfterLibraryRemoval()
|
||||||
|
- Three new event constants: LibraryAdded, LibraryRenamed, LibraryRemoved — auto-generated to frontend events.ts
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
Each task was committed atomically:
|
||||||
|
|
||||||
|
1. **Task 1: Implement Library CRUD methods and orphan cleanup pipeline** — `bd44f83` (feat)
|
||||||
|
- Created backend/library/crud.go (525 lines) with all CRUD methods
|
||||||
|
- Added 3 event constants to backend/events/events.go
|
||||||
|
- Added removalHooks field to Library struct
|
||||||
|
- Regenerated frontend/src/events.ts
|
||||||
|
2. **Task 2: Add queue compaction method and wire removal hooks in app.go** — `5995dfd` (feat)
|
||||||
|
- Added CompactAfterLibraryRemoval() to backend/queue/queue.go (80 lines)
|
||||||
|
- Wired RemovalHooks in backend/app.go OnStartup
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `backend/library/crud.go` (NEW) — AddLibrary, RenameLibrary, RemoveLibrary, GetRemovalImpact, cancelLibraryScan, currentTrackBelongsToLibrary, querySingleInt64, RemovalHooks type, sentinel errors
|
||||||
|
- `backend/library/library.go` — Added removalHooks RemovalHooks field to Library struct
|
||||||
|
- `backend/events/events.go` — Added LibraryAdded, LibraryRenamed, LibraryRemoved constants
|
||||||
|
- `frontend/src/events.ts` — Regenerated with new library CRUD event constants
|
||||||
|
- `backend/queue/queue.go` — Added CompactAfterLibraryRemoval method
|
||||||
|
- `backend/app.go` — Wired RemovalHooks in OnStartup (StopPlayback + CompactQueue callbacks)
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- **Application-level name uniqueness:** Iterate GetAllLibraries to check for duplicate names rather than adding a UNIQUE constraint to the libraries table. Avoids needing migration 7; the check is only done during rename which is infrequent.
|
||||||
|
- **RemovalHooks callback struct:** Follows the existing RescanHooks pattern to break circular dependencies between library → player and library → queue packages. Wired in app.go where all subsystems are accessible.
|
||||||
|
- **querySingleInt64 helper:** The project's `database.DB` type exposes `QueryContext` returning `*sql.Rows` but no `QueryRowContext`. The helper wraps the full scan-close cycle for single-value aggregate queries.
|
||||||
|
- **Sentinel errors per err113:** Defined `errLibraryNameEmpty`, `errLibraryNameTooLong`, `errLibraryNameDuplicate`, `errLibraryPathNotExist` as package-level vars to satisfy the golangci-lint err113 rule.
|
||||||
|
- **Context-first parameter order:** `querySingleInt64(ctx, db, query, args...)` follows `revive` linter's context-as-argument rule.
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
None — plan executed exactly as written.
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
## User Setup Required
|
||||||
|
|
||||||
|
None — no external service configuration required.
|
||||||
|
|
||||||
|
## Next Plan Readiness
|
||||||
|
|
||||||
|
- Plan 12-01 complete — backend CRUD API fully implemented
|
||||||
|
- Ready for Plan 12-02: Frontend library management UI in settings + sidebar cleanup
|
||||||
|
- All Wails-bindable methods (AddLibrary, RenameLibrary, RemoveLibrary, GetRemovalImpact) are available for frontend consumption
|
||||||
|
- Events (LibraryAdded, LibraryRenamed, LibraryRemoved) are defined for frontend reactive updates
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
All files verified present, all commits verified in git log.
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 12-library-crud-data-integrity*
|
||||||
|
*Completed: 2026-03-12*
|
||||||
Reference in New Issue
Block a user