soulsync/core/discovery
Broque Thomas d9529fc801 Token leak round 2: artist endpoint + playlist sync + URL-encoded redaction
The first token-leak fix scrubbed the artwork URL fixer's own log
calls. This catches three more sites that ALSO leaked tokens, plus
one upstream gap that let URL-encoded tokens slip through the
redactor.

Three sites in `web_server.py` (artist endpoint at line 8765-8773):

- "Artist image before fix: '...'" -- logged the raw image_url with
  the auth token in plain form.
- "Artist image after fix: '...'" -- logged the URL-encoded form
  after it had been wrapped in the image proxy
  (`/api/image-proxy?url=<percent-encoded-token>`).
- "Final artist data being sent: {...}" -- dumped the entire
  artist_info dict on every render, including the image_url field.

All three were dev-time debug noise. Removed entirely. The "No
artist image URL found" warning at line 8770 stays (no URL, just
the artist name).

One site in `core/discovery/sync.py:402`:

- "[PLAYLIST IMAGE] image_url=..." -- logged the playlist poster URL
  during sync. Same auth-token leak risk for Plex / Jellyfin
  playlists. Changed to log only `has_image=True/False`.

Upstream gap in `_redact_url_secrets`:

- The original regex only matched plain query params (`?key=value`).
  When an auth-bearing URL gets wrapped inside another URL's query
  string (our `/api/image-proxy?url=<encoded>` flow) the auth params
  end up percent-encoded -- `%3FX-Plex-Token%3D...` -- and slipped
  through.
- New second pattern catches the URL-encoded form. Both passes run
  on every redact call; idempotent.

Verified manually:
  /api/image-proxy?url=...%3FX-Plex-Token%3DABC...
  -> /api/image-proxy?url=...%3FX-Plex-Token%3D***REDACTED***

6 artwork tests pass.
2026-05-15 09:33:15 -07:00
..
__init__.py PR5a: lift _run_sync_task to core/discovery/sync.py 2026-04-28 11:20:47 -07:00
beatport.py PR5f: lift _run_beatport_discovery_worker to core/discovery/beatport.py 2026-04-28 15:36:15 -07:00
deezer.py PR5d: lift _run_deezer_discovery_worker to core/discovery/deezer.py 2026-04-28 12:45:18 -07:00
hero.py Lift get_discover_hero to core/discovery/hero.py 2026-04-30 09:47:06 -07:00
listenbrainz.py PR5g: lift _run_listenbrainz_discovery_worker to core/discovery/listenbrainz.py 2026-04-28 16:09:02 -07:00
playlist.py Surface silent exceptions in watchlist + discovery + reorganize — 18 sites 2026-05-07 09:52:20 -07:00
quality_scanner.py Surface silent exceptions across remaining modules — ~70 sites 2026-05-07 10:28:58 -07:00
scoring.py Lift discovery scoring + tidal-track search to core/discovery/scoring.py 2026-04-30 09:08:47 -07:00
spotify_public.py PR5e: lift _run_spotify_public_discovery_worker to core/discovery/spotify_public.py 2026-04-28 13:13:41 -07:00
sync.py Token leak round 2: artist endpoint + playlist sync + URL-encoded redaction 2026-05-15 09:33:15 -07:00
tidal.py Lift _run_tidal_discovery_worker to core/discovery/tidal.py 2026-04-28 23:02:24 -07:00
youtube.py fix: cast duration_ms to int before :02d format in discovery workers 2026-04-28 12:07:54 -07:00