- Add authlib for OAuth/OIDC support
- Implement OIDC login/callback routes with group-based admin sync
- Support OIDC_ONLY mode to disable password authentication
- Add logged_out page for post-logout flow
- Show OIDC/Local auth type badge in user management
- Add user edit modal with OIDC sync warning
- Fix script.js null guards for non-main pages
- Hide password change section for OIDC users in profile
- Add ProxyFix middleware for reverse proxy deployments
### Added
- Persistent artist request model and migration for tracking user requests.
- Admin interface for reviewing, approving, and rejecting pending requests.
- Socket endpoint for users to submit artist requests from the UI.
- Client-side request button and user-info emission so the UI can show request vs add actions.
- Server-side handler to create requests, emit toast notifications, and update the UI.
### Changed
- Button behavior now shows "Request" for non-admins and preserves add-to-service action for admins.
- Session state includes an admin flag and is sent to clients on connection.
- Approving a request now triggers adding the artist to the external content service and marks the request approved.
### Changed
- Rely on public Last.fm usernames for personal recommendations; the recommendation API endpoint was deprecated long ago
- Remove UI and client-side logic that showed or managed a "linked" session key; data handling no longer reads or exposes a linked session-key state.
### Deprecated
- Preserve migration chain with an explicit no-op migration after removing the session-key column from the schema.
### Removed
- Database column and model field for Last.fm session key.
- Server endpoints and UI flows for linking/authorizing via session tokens and session-based storage of link tokens.
### Fixed
- Prevents errors and unnecessary auth flows when fetching personal recommendations without user credentials.
### Added
- Persistent per-user Last.fm session key column.
- Link and completion endpoints plus UI controls to authorize and unlink accounts.
- A user-focused Last.fm service that supports authenticated requests and richer recommendation aggregation.
- Frontend indicators to show linked status and guide the linking flow.
### Changed
- Use stored session key when fetching personal recommendations and expose a linked flag to the UI.
- Prefer direct user recommendations when available, otherwise aggregate similar artists from top artists.
- Ensure the user's remote library cache is populated synchronously so owned artists are filtered reliably.
- Emit an acknowledgment and update sidebar state when personal discovery yields no seeds.
- Clear stored session key when a user unlinks their account.
### Removed
- Legacy simple recommendation implementation replaced by the new user-centric integration.
### Fixed
- Prevent spinner from hanging when there are no seeds by sending an ACK and stopping the run.
- Surface link token state and completion control in the profile flow so users can finish linking.
### Added
- Personal discovery support for Last.fm and ListenBrainz to fetch user-specific top/recommended artists.
- Profile fields for Last.fm username, ListenBrainz username and user token, with UI controls to add or remove the token.
- Sidebar controls, spinners and socket events to initiate and stream personal recommendations.
- Database migration adding user columns for listening service integration.
### Changed
- Recommendation flow now streams seed artists, deduplicates against the user's library, and presents missing/skip feedback.
- Session and socket logic extended to emit per-user service availability and detailed error/ack responses.
- Service initialization wires up Last.fm and ListenBrainz clients and broadcasts availability state to connected sessions.
### Fixed
- Ensures personal discovery state and UI refresh after profile updates and when opening the sidebar so availability is accurate.
### Security
- ListenBrainz token handling added with an option to clear the stored token; token input is treated as a secret in the UI.