Closes #21 — the second MVP gap. The queue could publish-now or delete, but not edit, so fixing a typo in a scheduled post meant delete-and-recompose. Standard schedulers edit in place.
What's added
QueueService.get(id)— a queued post's editable state (text, title, providers, schedule, link, image kind)QueueService.update(id, …)— edits text/title/providers/schedule/link/image in place; rebuilds the placeholderpost_targetsto the new provider set; image is tri-state (keep / replace / remove). Only draft/scheduled/failed are editable.- Routes —
GET /postline/queue/item,POST /postline/queue/update(auth) - UI — the queue gains an Edit action that opens the composer at
/?edit=<id>, prefilled: an "Editing a queued post" banner + Cancel, the post's text/title/providers/schedule/link, and a "current image (kept)" chip (attaching replaces it, clearing removes it). The publish button becomes Update post / Update schedule and saves in place, then returns to the queue.
Verification (end-to-end on the vendored tree)
- API: save → get → update (text, title,
blog→blog,bluesky, new schedule) → verified persisted - Guard: updating a
publishedpost → 422 "Only draft, scheduled, or failed posts can be changed" - Browser: Edit button → composer prefilled (text, title, providers, "Update schedule" label, schedule datetime in local time) → edit → update → back to
/queue, 0 console errors tscexit 0,pickierclean
Note
Editing drops providers that are no longer connected (they can't be a valid target). Acceptable for MVP; could surface a "dropped X (disconnected)" notice later.