Postline can already publish to Bluesky (connect via app password, publish, link previews, timeline), but the flow needs hardening before we rely on it day-to-day.
Tasks
- Session/token lifecycle: refresh expired Bluesky sessions instead of failing the publish
- Surface richer per-provider errors in
BlueskyPublishAction/CrosspostPublishAction(rate limits, auth expiry, network) instead of generic failures - Image/media upload support for Bluesky posts (composer currently only supports an image URL for Instagram)
- Rich text facets: mentions, hashtags, and links should be proper facets, not plain text
- Wire real scheduling:
Post/PostTargetmodels already havestatus+scheduled_at(with an index), but nothing publishes scheduled posts — add a job/scheduler pass - Replace the Queue page mock data with real
Postrecords (see UI polish issue) - Tests for the publish path (driver-level with mocked ATProto responses)
Context
- Driver:
app/Services/Social/Drivers/BlueskyDriver.ts, service:app/Services/Social/BlueskyService.ts - Actions:
app/Actions/Postline/Bluesky*.ts - Fan-out:
app/Services/Social/CrosspostService.ts