soulsync/database
BoulderBadgeDad 60b9fe10e9 Profiles: per-profile Tidal self-auth (playlists) — with a safe token-save redirect
Second service. Each profile connects its own Tidal; its playlist reads use that
account, everything else stays global. The gotcha vs Spotify: TidalClient loads
AND saves tokens to one global slot (tidal_tokens), so a naive per-profile client
would clobber the admin's tokens on refresh.

- get_tidal_client_for_profile builds a dedicated TidalClient seeded with the
  profile's tokens, refreshed via the shared/global app creds, and OVERRIDES its
  _save_tokens to persist to the PROFILE row — never the global slot. Admin
  (profile 1) + unconnected profiles use the global client unchanged. Cached per
  profile + evicted on (dis)connect.
- DB: set_profile_tidal_tokens / get_profile_tidal (encrypted); the OAuth callback
  now uses them + evicts the cached client.
- Wired the Tidal playlist reads (list + tracks) to the per-profile client; the
  module import line left intact.
- My Accounts: Tidal row (Connect via /auth/tidal?profile_id=, status, Disconnect).
  Connections API extended; disconnect made generic (/<service>/disconnect).
  Admin sees "managed in Settings" for every service.

Tests: per-profile token refresh writes to the profile and leaves the global
tidal_tokens untouched (the safety guarantee); connect status + disconnect;
admin/unconnected → global client. 22 endpoint tests pass.
2026-06-10 13:11:59 -07:00
..
__init__.py basic db structure 2025-08-05 22:43:04 -07:00
music_database.py Profiles: per-profile Tidal self-auth (playlists) — with a safe token-save redirect 2026-06-10 13:11:59 -07:00
personalized_schema.py Personalized pipeline: auto-refresh stale snapshots after watchlist scan 2026-05-15 20:53:03 -07:00