3ffa5608d8
Slice 2 of #392 — wires the first producers onto the bus that slice 1 built. After this commit, an SSE subscriber sees real events fire: - track.liked / track.unliked when the user toggles the heart on a track (handleLikeTrack / handleUnlikeTrack). Album + artist like events intentionally deferred — they're symmetric trivial follow-ups but the operator's primary like surface is tracks. - request.status_changed when a Lidarr request is created, cancelled, approved, or rejected. Auto-approve will fire twice (pending then approved) in rapid succession, which is semantically correct; client invalidation handles that fine. Events are user-scoped via row.UserID so admin approve/reject route to the requester, not the admin acting. Helpers live in events_publish.go so the wire shape (kind names, payload keys) stays in one place — future producers in slice 3 reuse the same pattern. events_publish.go is no-op when h.eventbus is nil so tests that construct handlers without a bus continue to pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>