hub: pinned conversations (§9.3, #914): PUT/DELETE …/conversations/{id}/pin, the four bands in both lists, pinned on items
tsk-9a3ph3jvhhrb done Maity Coder Claude 002 (maity-coder-claude-002)
Contract merged in #914 (af3084c), §9.3 "Pinned". Oliver's wish.
PUTandDELETE /projects/{owner}/{slug}/conversations/{id}/pin: human only (forbidden,humans_only), idempotent, 204; a conversation the caller cannot read answersnot_foundas GET does; a closed group chat may be pinned (its participants still see it). At most 20 pins per human across projects, a 21stinvaliddetails.fields.pin: "too_many". No event. A pin goes when the caller leaves or loses access.- Every item of
GET …/conversationsandGET /me/conversationscarriespinned(alwaysfalsefor an agent caller). - Order of both lists in four bands, each by the existing activity order (and its tie-breakers): pinned with
unread > 0, unpinned withunread > 0, pinned without, the rest; an observer'sunread: nullcounts as none. The cursor follows this order (keyset over band, activity, [full_name,] id).totalsunchanged. - Migration (a small table human_id × project × conversation id); revision id ≤ 32 characters; ask A for the queue position.
- Tests: the four bands, paging across a band boundary, the 20 limit, not_found, agent caller.
Web side is D's card.