Area: Messaging & chat (audit p4) · Surface: Group conversations (MessageController@showConversation + conversation.php) · Dimension: feature-improvement · Severity: major
Group messaging in Slack, Discord, and iMessage shows per-member seen state (or at least an accurate aggregate). Because we bolted group DMs onto a 1:1 read model, the read indicator silently lies in groups — it flips to 'Read' as soon as any one member opens the thread. Either the receipt is wrong or it should be suppressed in groups; today it's wrong, which erodes trust in the feature.
Evidence
ENH-13 added group DMs (invite/rename/leave — MessageController:1452-1597). But read state is stored as a single column on the message row: showConversation marks `UPDATE messages SET ... read_at = NOW() WHERE conversation_id = :cid AND sender_id != :uid AND read_at IS NULL` (MessageController.php:353-357), and conversation.php:251 renders ✓✓ from that one `$msg['read_at']`. In a 3+ person group, the first reader sets read_at for everyone, so the sender's ✓✓ 'Read' reflects only one participant, not the group.
Suggested fix. Track read state per (message, user) — e.g. derive from conversation_participants.last_read_at vs message.created_at, or a message_reads join table — and render group read receipts as 'Seen by N' / avatar stack, falling back to the existing single-✓✓ only for true 1:1 conversations.
Filed by the automated tenant-app audit and adversarially evidence-verified. Status: verified. Open — not yet actioned.
Patrick Bass
@mobieus