feat(notifications): scalable SSE notification system + real XRPC shout/like mutations
Backend
- notifications table (recipient, actor, type, shout/subject refs, read) + migration 0018
- notifications.service: create/list/getUnreadCount/markSeen; publishes to a
per-user NATS subject (rocksky.notification.<userId>) so SSE fan-out scales
horizontally without websockets; never throws so it can't break a mutation
- emit notifications from the shared service layer so BOTH the legacy Hono REST
routes and the XRPC handlers trigger them: like song/scrobble, follow,
comment on scrobble, comment on profile, reply, react on comment
- app.rocksky.notification.{listNotifications,getUnreadCount,updateSeen} lexicons
+ generated types + XRPC handlers
- SSE endpoint GET /notifications/stream (token via query param, heartbeat,
initial unread count) subscribed to the user's NATS subject
- implement the previously-stubbed XRPC mutations (likeShout, likeSong,
dislikeShout, dislikeSong, createShout, replyShout, reportShout, removeShout)
by delegating to the same services the Hono app uses
Web
- NotificationBell (bell + red unread badge, popover inbox) in the navbar,
visible only to authenticated users; live via EventSource
Web-mobile
- replace the "For You" bottom-nav tab with a notifications bell tab (red badge),
move Recommendations into the profile menu; notifications screen + live badge