Room Activity Log can misclassify membership transitions for back-paginated (older) events #82

Closed
opened 2026-09-12 01:51:32 -04:00 by jared · 0 comments
Owner

Severity: low · Type: bug · Confidence: medium

Location: src/app/features/room-settings/RoomActivityLog.tsx:51-170, 333-349

Problem

describeEvent relies on ev.getPrevContent() to distinguish "joined" vs. "profile update", "kicked" vs. "invite withdrawn", and "banned"/"unbanned" transitions. prev_content for m.room.member events is reliably populated by the SDK for live, forward-synced events, but is not guaranteed to be present on events fetched via mx.paginateEventTimeline(..., { backwards: true }) (the mechanism handleLoadMore uses to backfill this log), since the homeserver's /messages response does not always include unsigned.prev_content for historical state events. When prevContent comes back empty for a paginated (i.e. essentially all, since state events are rare in the initial sync window per the code's own comment) event, describeEvent's membership === 'join' branch treats prevMembership === undefined the same as a fresh invite/knock-based join, and a leave with no prior context falls through to the generic "was kicked by" case — potentially mislabeling e.g. a voluntary-leave-then-rejoin or a rescinded-then-reissued invite as a kick.

How to trigger

Load older mod-log history (click "Load more") in a room where the historical /messages response for m.room.member events lacks unsigned.prev_content (varies by homeserver implementation) — some join/leave entries can show the wrong description.

Suggested fix

When prevContent is empty/undefined for a paginated event, fall back to a neutral phrasing ("membership changed to ") rather than assuming the same defaults used for live events, or fetch the member's actual prior state via /state at that point in the timeline if precision matters.


Filed from the September 2026 client audit (branch lotus @ 4bea4895).

**Severity:** low · **Type:** bug · **Confidence:** medium **Location:** `src/app/features/room-settings/RoomActivityLog.tsx:51-170, 333-349` ### Problem `describeEvent` relies on `ev.getPrevContent()` to distinguish "joined" vs. "profile update", "kicked" vs. "invite withdrawn", and "banned"/"unbanned" transitions. `prev_content` for `m.room.member` events is reliably populated by the SDK for live, forward-synced events, but is not guaranteed to be present on events fetched via `mx.paginateEventTimeline(..., { backwards: true })` (the mechanism `handleLoadMore` uses to backfill this log), since the homeserver's `/messages` response does not always include `unsigned.prev_content` for historical state events. When `prevContent` comes back empty for a paginated (i.e. essentially all, since state events are rare in the initial sync window per the code's own comment) event, `describeEvent`'s `membership === 'join'` branch treats `prevMembership === undefined` the same as a fresh invite/knock-based join, and a `leave` with no prior context falls through to the generic "was kicked by" case — potentially mislabeling e.g. a voluntary-leave-then-rejoin or a rescinded-then-reissued invite as a kick. ### How to trigger Load older mod-log history (click "Load more") in a room where the historical `/messages` response for `m.room.member` events lacks `unsigned.prev_content` (varies by homeserver implementation) — some join/leave entries can show the wrong description. ### Suggested fix When `prevContent` is empty/undefined for a paginated event, fall back to a neutral phrasing ("membership changed to <X>") rather than assuming the same defaults used for live events, or fetch the member's actual prior state via `/state` at that point in the timeline if precision matters. --- --- _Filed from the September 2026 client audit (branch `lotus` @ 4bea4895)._
jared added this to the Audit 2026-09 · Medium & Low milestone 2026-09-12 01:51:32 -04:00
jared added the bugpriority: lowarea: moderation labels 2026-09-12 01:51:32 -04:00
jared self-assigned this 2026-09-12 01:51:32 -04:00
jared closed this issue 2026-09-12 20:29:10 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny#82