matrix-org / matrix-org/matrix-spec

Threaded receipt EDU shape down /sync makes it impossible to express certain valid receipts

Open
#1,727 9 comments 0 reactions 0 assignees View on GitHub
A-Client-Server clarification
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.