fix(messaging): self-read receipt at send time so authors don't inflate unread counts

agent_message_reads is the per-viewer source of truth for readAt, but
the send path never recorded the author's own receipt. Every message
the board operator or an agent sent therefore counted as unread to
themselves until they happened to re-open the channel — sidebar badge,
inbox panel, and the channel sidebar all derive from the same join
table. Insert a (message_id, from_agent_id, created_at) row in the
same transaction as the message itself; the receipt becomes an
atomic part of the write rather than a deferred maintenance task.
This commit is contained in:
ZacharyZhang-NY committed 2026-05-14 14:36:10 -04:00
1 parent 2b4b8d987e
commit 0e1710065f
1 file changed
+12 -4
+12 -4
View File
@@ -70,10 +70,13 @@ export function buildMessageMethods(
const body = normalizeMarkdownText(input.body);
const id = randomUUID();
const createdAt = nowIso();
// Single transaction: the row and its mention fan-out must land
// atomically, otherwise a crash between the two writes leaves a
// message visible to its recipient but silently invisible to the
// mentioned agents — which is exactly the old bug we're fixing.
// Single transaction: the row, its self-read receipt, and its
// mention fan-out must land atomically. The self-read receipt
// makes "author has read their own message" an invariant in the
// join table — without it, every message a sender posts inflates
// their own sidebar / inbox / channel unread counts until they
// happen to re-open the channel, because `readAt` is derived from
// `agent_message_reads` per viewer.
deps.transaction(() => {
getDb()
.prepare(
@@ -94,6 +97,11 @@ export function buildMessageMethods(
input.attachmentsJson ?? "[]",
createdAt,
);
getDb()
.prepare(
"insert into agent_message_reads (message_id, agent_id, read_at) values (?, ?, ?)",
)
.run(id, input.fromAgentId, createdAt);
if (input.mentionedAgentIds && input.mentionedAgentIds.length > 0) {
insertMessageMentions(id, input.companyId, input.fromAgentId, input.mentionedAgentIds, createdAt);
}