Desktop: Inbox renders relay system events as raw JSON messages
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
## Summary
The Home Inbox conversation pane renders relay system events (kind 40099) as normal message bubbles with raw JSON bodies. The main channel timeline handles the same events (`SystemMessageRow.tsx`), so an event that is hidden or pretty-printed in a channel shows as raw JSON in the Inbox.
## Steps to reproduce
1. Create a DM. The relay writes a `dm_created` system event into the DM channel and fans it out (`crates/buzz-relay/src/handlers/side_effects.rs`, `emit_system_message`):
```json
{"actor":"","participants":["",""],"type":"dm_created"}
```
2. Open the conversation from Home > Inbox (header: "DM with ").
3. The event shows as a message from the relay's signing key: body = raw JSON, author label = truncated event pubkey, avatar = initials derived from that truncated hex.
4. Open the same conversation in the main channel view: the event does not render at all.
## Root cause
- `desktop/src/features/home/ui/InboxDetailPane.tsx` feeds every timeline event to `InboxMessageRow`. Nothing in `desktop/src/features/home/` references `KIND_SYSTEM_MESSAGE` (40099).
- `InboxMessageRow.tsx` has no system-event branch. It renders `message.content` as Markdown and uses the event `pubkey` as the author. Relay-signed events have no kind 0 profile, so the label falls back to a truncated hex pubkey and `getInitials` derives the avatar initials from it.
- `dm_created` has no case in `describeSystemEvent` (`desktop/src/features/messages/ui/SystemMessageRow.tsx`); the `default` branch returns null. Unknown 40099 types are invisible in the channel timeline and raw JSON in the Inbox.
## Impact
- The full internal payload of a private DM, including both participant pubkeys, displays verbatim to users.
- System rows from the relay key look like messages from an unknown user (truncated hex name, meaningless avatar initials). Users cannot tell they are system rows.
- Every 40099 type leaks this way in the Inbox, including types the channel timeline renders correctly (`member_joined`, `member_left`, `member_removed`, `message_deleted`, `topic_changed`, `purpose_changed`).
## Suggested fix
Route kind 40099 events in the Inbox pane to the system-row renderer (reuse the `describeSystemEvent` semantics), and resolve the displayed actor from the payload `actor` field, not the event `pubkey`. Add a `dm_created` case ("started a direct message") so DM creation renders cleanly in both paths.
## Environment
- Desktop source at `master` as of 2026-09-02; the Inbox path has no system-event handling at this commit.
- Seen on a self-hosted relay. The fault is client-side rendering of relay data, not the stored events.
Contributor guide
Research direction
Start with desktop/src/features/home/ui/InboxDetailPane.tsx and InboxMessageRow.tsx, then compare their event handling with desktop/src/features/messages/ui/SystemMessageRow.tsx. Read the relay event shape in crates/buzz-relay/src/handlers/side_effects.rs, especially emit_system_message. Done means kind 40099 events render as system rows in Inbox, dm_created is described consistently, and private payloads no longer appear as raw JSON.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, typescript
- Domain
- desktop, frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100