# muzick — overnight fix plan

## tasks
1. **fix N+1 queries** in generators.service.ts (#110, prio:4)
2. **fix SSRF guard** in images.routes.ts (#111, prio:3)
3. **clean & re-enrich images** (#124, prio:0 — operational)
4. **ethos UI migration** (#34, prio:5 — dispatched to ethos-ui agent)

## 1. N+1 queries

### comfortGenerator (lines 57-87)
current: loops 20 artists, `SELECT ... WHERE object_id = $1` per artist
fix: single query with `WHERE cf.object_id = ANY($1::uuid[])` + `unnest` to get per-artist rows back

### deepDiveGenerator (lines 248-274)
current: loops 20 albums, `SELECT ... WHERE t.album_id = $1` per album
fix: single query with `WHERE t.album_id = ANY($1::uuid[])` — already batched on artist query

### verification
`comfortGenerator` and `deepDiveGenerator` are tested in `generators.test.ts`

## 2. SSRF guard (images.routes.ts)

current: only checks `url.startsWith('http://') || url.startsWith('https://')` — trivial bypass
fix: add domain allowlist of known image hosts, validate after redirect

allowed domains:
- coverartarchive.org + *.coverartarchive.org
- lastfm.freetls.fastly.net
- i.scdn.co (spotify)
- images.genius.com
- *.musicbrainz.org
- commons.wikimedia.org
- e.snmc.io
