|
| 1 | +# MSC3266: Room Summary API |
| 2 | + |
| 3 | +Quite a few clients and tools have a need preview a room: |
| 4 | + |
| 5 | +- A client may want to show the room in the roomlist, when showing a space. |
| 6 | +- matrix.to may want to show avatar and name of a room. |
| 7 | +- Nextcloud may want to list the names and avatars of your `/joined_rooms` when |
| 8 | + asking where to share the media. |
| 9 | +- A client may want to preview a room, when hovering a room alias, id or after |
| 10 | + clicking on it. |
| 11 | +- A client may want to preview a room, when the user is trying to knock on it or |
| 12 | + to show pending knocks. |
| 13 | +- A traveller bot may use that to show a room summary on demand without actually |
| 14 | + keeping the whole room state around and having to subscribe to /sync (or |
| 15 | + using the appservice API). |
| 16 | + |
| 17 | +There are a few ways to request a room summary, but they only support some of |
| 18 | +the use cases. The spaces summary API |
| 19 | +([MSC2946](https://github.com/matrix-org/matrix-doc/pull/2946)) only provides |
| 20 | +limited control over what rooms to summarize and only works for rooms in spaces. |
| 21 | +`{roomid}/initialSync` and `{roomid}/state/{event_type}` don't work over |
| 22 | +federation and are much heavier than necessary or need a lot of http calls for |
| 23 | +each room. |
| 24 | + |
| 25 | +## Proposal |
| 26 | + |
| 27 | +A new client-server API, which allows you to fetch a summary of a room by id or |
| 28 | +alias and a corresponding server-server API, to fetch a summary over federation. |
| 29 | + |
| 30 | +### Client-Server API |
| 31 | + |
| 32 | +The API returns the summary of the specified room, if the room could be found |
| 33 | +and the client should be able to view its contents according to the join_rules, |
| 34 | +history visibility, space membership and similar rules outlined in |
| 35 | +[MSC3173](https://github.com/matrix-org/matrix-doc/pull/3173) as well as if the |
| 36 | +user is already a member of that room. |
| 37 | + |
| 38 | +A request could look like this: |
| 39 | + |
| 40 | +``` |
| 41 | +GET /_matrix/client/r0/rooms/{roomidOrAlias}/summary? |
| 42 | + via=matrix.org& |
| 43 | + via=neko.dev |
| 44 | +``` |
| 45 | + |
| 46 | +- `roomidOrAlias` can be the roomid or an alias to a room. |
| 47 | +- `via` are servers, that should be tried to request a summary from, if it can't |
| 48 | + be generated locally. These can be from a matrix URI, matrix.to link or a |
| 49 | + `m.space.child` event for example. |
| 50 | + |
| 51 | +A response includes the stripped state in the following format: |
| 52 | + |
| 53 | +```json5 |
| 54 | +{ |
| 55 | + room_id: "!ol19s:bleecker.street", |
| 56 | + avatar_url: "mxc://bleecker.street/CHEDDARandBRIE", |
| 57 | + guest_can_join: false, |
| 58 | + name: "CHEESE", |
| 59 | + num_joined_members: 37, |
| 60 | + topic: "Tasty tasty cheese", |
| 61 | + world_readable: true, |
| 62 | + join_rules: "public", |
| 63 | + room_type: "m.space", |
| 64 | + is_direct: true, |
| 65 | + membership: "invite", |
| 66 | + is_encrypted: true, |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +These are the same fields as those returned by `/publicRooms`, with a few |
| 71 | +additions: `room_type`, `is_direct`, `membership` and `is_encrypted`. |
| 72 | + |
| 73 | +All those fields are already accessible as the stripped state according to |
| 74 | +[MSC3173](https://github.com/matrix-org/matrix-doc/pull/3173), with the |
| 75 | +exception of `membership` and potentially `is_direct`. |
| 76 | + |
| 77 | +#### Rationale and description of reponse fields |
| 78 | + |
| 79 | +| fieldname | description | rationale | |
| 80 | +| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | |
| 81 | +| room_id | Id of the room | Useful, when the API is called with an alias or to disambiguate multiple responses clientside. | |
| 82 | +| avatar_url | Avatar of the room | Copied from `publicRooms`. | |
| 83 | +| guest_can_join | If guests can join the room. | Copied from `publicRooms`. | |
| 84 | +| name | Name of the room | Copied from `publicRooms`. | |
| 85 | +| num_joined_members | Member count of the room | Copied from `publicRooms`. | |
| 86 | +| topic | Topic of the room | Copied from `publicRooms`. | |
| 87 | +| world_readable | If the room history can be read without joining. | Copied from `publicRooms`. | |
| 88 | +| join_rules | Join rules of the room | Copied from `publicRooms`. | |
| 89 | +| room_type | Optional. Type of the room, if any, i.e. `m.space` | Used to distinguish rooms from spaces. | |
| 90 | +| is_direct | Optional. If this is a direct chat. The server should use the usual rules to figure out, if this is a direct chat, not just look in the create event. | May be used in previews to distinguish normal rooms from DMs. | |
| 91 | +| membership | The current membership of this user in the room. Usually `leave` if the room is fetched over federation. | Useful to distinguish invites and knocks from joined rooms. | |
| 92 | +| is_encrypted | Optional. If the room is encrypted. This is already accessible as stripped state. Currently a bool, but maybe the algorithm makes more sense? | Some users may only want to join encrypted rooms or clients may want to filter out encrypted rooms, if they don't support encryption. | |
| 93 | + |
| 94 | +It should be possible to call this API without authentication, but servers may |
| 95 | +rate limit how often they fetch information over federation more heavily, if the |
| 96 | +user is unauthenticated. Also the fields `membership` and `is_direct` will be |
| 97 | +missing. |
| 98 | + |
| 99 | +### Server-Server API |
| 100 | + |
| 101 | +The Server-Server API mirrors the Client-Server API, with a few exceptions. The |
| 102 | +`membership` and `is_direct` fields are never present. No `via` field is |
| 103 | +necessary on the request, since servers should not forward the request to other |
| 104 | +servers. |
| 105 | + |
| 106 | +The server can't know, which user is requesting the summary. As such it should |
| 107 | +apply visibility rules to check if any user on the requesting server would have |
| 108 | +access to the summary. |
| 109 | + |
| 110 | +A request would be made as follows: |
| 111 | + |
| 112 | +``` |
| 113 | +GET /_matrix/federation/v1/summary/{roomidOrAlias} |
| 114 | +``` |
| 115 | + |
| 116 | +The requesting server should cache the response to this request. |
| 117 | + |
| 118 | +## Potential issues |
| 119 | + |
| 120 | +### Perfomance |
| 121 | + |
| 122 | +Clients may start calling this API very often instead of using the batched |
| 123 | +summary API (MSC2946) for spaces or caching the state received via `/sync`. |
| 124 | +Looking up all the state events required for this API may cause performance |
| 125 | +issues in that case. |
| 126 | + |
| 127 | +To mitigate that, servers are recommended to cache the response for this API and |
| 128 | +apply rate limiting if necessary. |
| 129 | + |
| 130 | +## Alternatives |
| 131 | + |
| 132 | +- The spaces summary API could be used, but it doesn't work for arbitrary rooms |
| 133 | + and you always need to pass the parent space, without any control over the |
| 134 | + rooms being returned. |
| 135 | +- The `/state` API could be used, but the response is much bigger than needed, |
| 136 | + can't be cached as easily and may need more requests. This also doesn't work |
| 137 | + over federation (yet). |
| 138 | +- Peeking could solve this too, but with additional overhead and |
| 139 | + [MSC2753](https://github.com/matrix-org/matrix-doc/pull/2753) is much more |
| 140 | + complex. |
| 141 | + |
| 142 | +## Security considerations |
| 143 | + |
| 144 | +This API may leak data, if implemented incorrectly or malicious servers could |
| 145 | +return wrong results for a summary. |
| 146 | + |
| 147 | +Those are the same concerns as on [MSC2946](https://github.com/matrix-org/matrix-doc/pull/2946) |
| 148 | +or [MSC3173](https://github.com/matrix-org/matrix-doc/pull/3173). |
| 149 | + |
| 150 | +This API could also used for denial of service type attacks. Appropriate |
| 151 | +ratelimiting and caching should be able to mitigate that. |
| 152 | + |
| 153 | +## Unstable prefix |
| 154 | + |
| 155 | +This uses the `im.nheko.summary` unstable prefix instead of the `summary` key in |
| 156 | +the request paths during the MSC phase. As a result: |
| 157 | + |
| 158 | +- the client API will be |
| 159 | + `/_matrix/client/unstable/rooms/{roomidOrAlias}/im.nheko.summary` |
| 160 | +- the federation API will be |
| 161 | + `/_matrix/federation/unstable/im.nheko.summary/{roomidOrAlias}` |
0 commit comments