matrix-org / matrix-org/matrix-spec
Threaded receipt EDU shape down /sync makes it impossible to express certain valid receipts
- Dominant language
- HTML
- Stars
- 330
- Forks
- 150
- Avg merge
- 2h 21m
- Merged PRs (30d)
- 3
Description
Threaded read receipts got added in MSC3771 - they look like this down /sync:
```js
{
"content": {
"$thread_reply": {
"m.read": {
"@rikj:jki.re": {
"ts": 1436451550453,
"thread_id": "$thread_root" // or "main" or absent
}
}
}
},
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"type": "m.receipt"
}
```
It is my understanding that receipts form a key-value store, where the key is a 3-uple of `(user_id, room_id, thread_id)`, with the value of the read `(event_id, ts)`. This means a user can have a N+1 receipts in a room, one for each thread ID and one unthreaded receipt (ignoring private receipts). However, the JSON shape restricts the ability to express the following data:
```
room | user | event | thread
-----------------------------
!foo | @bob | $abc | NULL
!foo | @bob | $abc | "some_id"
```
It restricts it because the JSON shape is keyed off the 2-uple (event_id, user_id) - the key is too broad. The net result is that in the sliding sync proxy [and Synapse](https://github.com/matrix-org/complement/pull/709), these receipts are inexpressible and one will be dropped in a undefined manner.
It may be that it's silly for clients to send this particular set of receipts, but given how we want to work with thread-aware and non-thread-aware clients, it's not unrealistic that clients may decide to send 2 receipts for an event: one for "unthreaded" for the benefit of thread unaware clients and one for the `thread_id` for thread-aware clients. If they do this, things break.
Element-Web does exactly this:
> - Click on the button : Mark room as read => unthreaded receipt
> - When you open a room or a thread, interact with the composer etc => threaded receipt
and it's possible to send both for the same event ID:
> the normal RR could be sent for the main/thread timeline, then you send an unthreaded to mark all timelines as read on the same event id if it is the latest in the room
Contributor guide
Research direction
Start by reviewing MSC3771 and the receipt representation under /sync, including the sliding sync proxy and Synapse behavior described in the issue. Determine a protocol shape that preserves both threaded and unthreaded receipts for the same user, room, and event, then update the Matrix specification and verify that neither receipt is dropped.
Written by the indexing model from the issue text.
Assessment
- Domain
- api, documentation
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100