feat(ack): message acknowledgement / required-read tracking (LC-490) #481
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/LC-490-message-acknowledgements"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements LC-490: mark a message "needs acknowledgement" and track who has clicked Acknowledge, surfaced as a roster on the message. Mirrors the existing reaction (per-user roster + sub-region OOB) and pin (author/mod boolean toggle + full-bubble OOB) precedents. Stack unchanged (Askama + HTMX + Tailwind).
Behavior
Acknowledgedevent that re-renders the#ack-{id}sub-region per viewer; toggling the requirement fans outAckRequiredChangedthat re-renders the whole bubble per viewer (so the bar + menu item appear/disappear for everyone).Data model
0073_acknowledgements.sql:message_ack_required(pin-shaped flag) +message_acks(reaction-shaped(message_id, user_id)roster); bothON DELETE CASCADE. Clearing the requirement drops the roster.db::acks: set/clear required,is_required,required_ids_for_room(bulk page path),acknowledge(idempotent),rollup(count / acked_by_me / acker_ids).Rendering correctness
MessageViewgainsack: Option<AckState>(Some= required). The clobber risk (a full-bubble re-render from an edit/pin/bookmark wiping a required message's bar) is handled by computing ack centrally inload_message_view_for_viewer(covers the pin/bookmark/edit/ack WS single-message renders) and at the two inline edit sites (render_edited_message,patch_message); the room-list path bulk-gates onrequired_idsso the rollup only runs for flagged messages; DMs and brand-new messages areNone.Routes
POST /messages/{id}/ack- acknowledge (any room member; 400 if not required).POST/DELETE /messages/{id}/ack-required- flag / clear (author or room moderator; 403 otherwise).Tests
New
routes_acksintegration test: RBAC (non-author 403), 400 on acking a non-required message, require -> acknowledge -> roster count, idempotent ack, clear drops the roster. Added theackfield to the two hand-builtMessageViewtest constructors and regenerated the LC-77 render fixtures (only an empty#ackregion added).just check,just test,just test-saas(incl. en/es i18n parity),just build-cssall pass.AckState on MessageView; partials/ack_bar.html (initial) + ws/ack_update.html (live OOB on #ack-{id}); message.html renders the id-keyed region and the author/mod-gated Require/Clear acknowledgement menu item. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>POST /messages/{id}/ack (any member) + POST/DELETE /ack-required (author/mod); Acknowledged (sub-region) + AckRequiredChanged (full-bubble) events rendered per-recipient. build_ack_view computed centrally in load_message_view_for_viewer and at every full-bubble site so edits never wipe the bar; list path bulk-gates on required_ids. en+es strings. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>