diff --git a/proposals/3266-room-summary.md b/proposals/3266-room-summary.md new file mode 100644 index 00000000000..58e3cbf1386 --- /dev/null +++ b/proposals/3266-room-summary.md @@ -0,0 +1,161 @@ +# MSC3266: Room Summary API + +Quite a few clients and tools have a need preview a room: + +- A client may want to show the room in the roomlist, when showing a space. +- matrix.to may want to show avatar and name of a room. +- Nextcloud may want to list the names and avatars of your `/joined_rooms` when + asking where to share the media. +- A client may want to preview a room, when hovering a room alias, id or after + clicking on it. +- A client may want to preview a room, when the user is trying to knock on it or + to show pending knocks. +- A traveller bot may use that to show a room summary on demand without actually + keeping the whole room state around and having to subscribe to /sync (or + using the appservice API). + +There are a few ways to request a room summary, but they only support some of +the use cases. The spaces summary API +([MSC2946](https://github.com/matrix-org/matrix-doc/pull/2946)) only provides +limited control over what rooms to summarize and only works for rooms in spaces. +`{roomid}/initialSync` and `{roomid}/state/{event_type}` don't work over +federation and are much heavier than necessary or need a lot of http calls for +each room. + +## Proposal + +A new client-server API, which allows you to fetch a summary of a room by id or +alias and a corresponding server-server API, to fetch a summary over federation. + +### Client-Server API + +The API returns the summary of the specified room, if the room could be found +and the client should be able to view its contents according to the join_rules, +history visibility, space membership and similar rules outlined in +[MSC3173](https://github.com/matrix-org/matrix-doc/pull/3173) as well as if the +user is already a member of that room. + +A request could look like this: + +``` +GET /_matrix/client/r0/rooms/{roomidOrAlias}/summary? + via=matrix.org& + via=neko.dev +``` + +- `roomidOrAlias` can be the roomid or an alias to a room. +- `via` are servers, that should be tried to request a summary from, if it can't + be generated locally. These can be from a matrix URI, matrix.to link or a + `m.space.child` event for example. + +A response includes the stripped state in the following format: + +```json5 +{ + room_id: "!ol19s:bleecker.street", + avatar_url: "mxc://bleecker.street/CHEDDARandBRIE", + guest_can_join: false, + name: "CHEESE", + num_joined_members: 37, + topic: "Tasty tasty cheese", + world_readable: true, + join_rules: "public", + room_type: "m.space", + is_direct: true, + membership: "invite", + is_encrypted: true, +} +``` + +These are the same fields as those returned by `/publicRooms`, with a few +additions: `room_type`, `is_direct`, `membership` and `is_encrypted`. + +All those fields are already accessible as the stripped state according to +[MSC3173](https://github.com/matrix-org/matrix-doc/pull/3173), with the +exception of `membership` and potentially `is_direct`. + +#### Rationale and description of reponse fields + +| fieldname | description | rationale | +| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| room_id | Id of the room | Useful, when the API is called with an alias or to disambiguate multiple responses clientside. | +| avatar_url | Avatar of the room | Copied from `publicRooms`. | +| guest_can_join | If guests can join the room. | Copied from `publicRooms`. | +| name | Name of the room | Copied from `publicRooms`. | +| num_joined_members | Member count of the room | Copied from `publicRooms`. | +| topic | Topic of the room | Copied from `publicRooms`. | +| world_readable | If the room history can be read without joining. | Copied from `publicRooms`. | +| join_rules | Join rules of the room | Copied from `publicRooms`. | +| room_type | Optional. Type of the room, if any, i.e. `m.space` | Used to distinguish rooms from spaces. | +| 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. | +| 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. | +| 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. | + +It should be possible to call this API without authentication, but servers may +rate limit how often they fetch information over federation more heavily, if the +user is unauthenticated. Also the fields `membership` and `is_direct` will be +missing. + +### Server-Server API + +The Server-Server API mirrors the Client-Server API, with a few exceptions. The +`membership` and `is_direct` fields are never present. No `via` field is +necessary on the request, since servers should not forward the request to other +servers. + +The server can't know, which user is requesting the summary. As such it should +apply visibility rules to check if any user on the requesting server would have +access to the summary. + +A request would be made as follows: + +``` +GET /_matrix/federation/v1/summary/{roomidOrAlias} +``` + +The requesting server should cache the response to this request. + +## Potential issues + +### Perfomance + +Clients may start calling this API very often instead of using the batched +summary API (MSC2946) for spaces or caching the state received via `/sync`. +Looking up all the state events required for this API may cause performance +issues in that case. + +To mitigate that, servers are recommended to cache the response for this API and +apply rate limiting if necessary. + +## Alternatives + +- The spaces summary API could be used, but it doesn't work for arbitrary rooms + and you always need to pass the parent space, without any control over the + rooms being returned. +- The `/state` API could be used, but the response is much bigger than needed, + can't be cached as easily and may need more requests. This also doesn't work + over federation (yet). +- Peeking could solve this too, but with additional overhead and + [MSC2753](https://github.com/matrix-org/matrix-doc/pull/2753) is much more + complex. + +## Security considerations + +This API may leak data, if implemented incorrectly or malicious servers could +return wrong results for a summary. + +Those are the same concerns as on [MSC2946](https://github.com/matrix-org/matrix-doc/pull/2946) +or [MSC3173](https://github.com/matrix-org/matrix-doc/pull/3173). + +This API could also used for denial of service type attacks. Appropriate +ratelimiting and caching should be able to mitigate that. + +## Unstable prefix + +This uses the `im.nheko.summary` unstable prefix instead of the `summary` key in +the request paths during the MSC phase. As a result: + +- the client API will be + `/_matrix/client/unstable/rooms/{roomidOrAlias}/im.nheko.summary` +- the federation API will be + `/_matrix/federation/unstable/im.nheko.summary/{roomidOrAlias}`