feat(subscriptions): surface DM-delivery health
three pieces that work together so the user knows when DMs won't land:
1. bot-follow banner — on login, check app.bsky.graph.getRelationships
against @pub-search.waow.tech. if the user doesn't follow the bot,
show a warning with a direct link. quiet on the happy path.
2. last_error persistence — new columns on the subscriptions table;
populated by the delivery worker on failure (and cleared on success).
surfaced in /api/subscriptions and rendered under each toggle.
3. bsky error extraction — bsky_bot now plucks the `error` field from
non-2xx chat responses (e.g. ActorNotMessageable) and exposes the
snippet via lastErrorSnippet(). notifications.deliver combines the
zig error name with this snippet into the persisted last_error.
Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>