You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
matrix-spec-proposals/proposals/2946-spaces-summary.md

8.0 KiB

MSC2946: Spaces Summary

This MSC depends on MSC1772, which describes why a Space is useful:

Collecting rooms together into groups is useful for a number of purposes. Examples include:

  • Allowing users to discover different rooms related to a particular topic: for example "official matrix.org rooms".
  • Allowing administrators to manage permissions across a number of rooms: for example "a new employee has joined my company and needs access to all of our rooms".
  • Letting users classify their rooms: for example, separating "work" from "personal" rooms.

We refer to such collections of rooms as "spaces".

This MSC attempts to solve how a member of a space discovers rooms in that space. This is useful for quickly exposing a user to many aspects of an entire community, using the examples above, joining the "official matrix.org rooms" space might suggest joining a few rooms:

  • A room to discuss development of the Matrix Spec.
  • An announcements room for news related to matrix.org.
  • An off-topic room for members of the space.

Proposal

A new client-server API (and corresponding server-server API) is added which allows for querying for the rooms and spaces contained within a space. This allows a client to efficiently display a hierarchy of rooms to a user (i.e. without having to walk the full state of the space).

Client-server API

An endpoint is provided to walk the space tree, starting at the provided room ID ("the root room"), and visiting other rooms/spaces found via m.space.child events. It recurses into the children and into their children, etc.

Note that there is no requirement for any of the rooms to be of have a type of m.space, any room with m.space.child events is considered.

This endpoint requires authentication and is not subject to rate-limiting.

Example request:

GET /_matrix/client/r0/rooms/{roomID}/spaces?
    max_rooms_per_space=5&
    suggested_only=true

Example response:

{
    "rooms": [
        {
            "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,
            "creation_ts": 1432735824653,
            "room_type": "m.space"
        },
        { ... }
    ],
    "events": [
        {
            "type": "m.space.child",
            "state_key": "!efgh:example.com",
            "content": {
                "via": ["example.com"],
                "suggested": true
            },
            "room_id": "!ol19s:bleecker.street",
            "sender": "@alice:bleecker.street"
        },
        { ... }
    ]
}

Request params:

  • suggested_only: Optional. If true, return only child events and rooms where the m.space.child event has suggested: true. Defaults to false.

    Must be either true or false, case-sensitive.

  • max_rooms_per_space: Optional: a client-defined limit to the maximum number of children to return per space. Doesn't apply to the root space (ie, the room_id in the request).

    Server implementations may also have an internal limit (recommended as 50) (which does apply to the root room); attempts to exceed this limit are ignored. Must be a non-negative integer.

Response fields:

  • rooms: for each room/space, starting with the root room, a summary of that room. The fields are the same as those returned by /publicRooms (see spec), with the addition of:
    • room_type: the value of the m.type field from the room's m.room.create event, if any.
    • creation_ts: the value of the origin_server_ts field from the room's m.room.create event. This is required for sorting of rooms as specified in MSC1772.
  • events: m.space.child events of the returned rooms. For each event, only the following fields are returned: type, state_key, content, room_id, sender.

Errors:

403 with an error code of M_FORBIDDEN: if the user doesn't have permission to view/peek the root room (including if that room does not exist).

Algorithm

A rough algorithm follows:

  1. Start at the "root" room (the provided room ID).
  2. Generate a summary and add it to rooms.
  3. Add any m.space.child events in the room to events.
  4. Recurse into the targets of the m.space.child events.
    1. If the room is not accessible (or has already been processed), do not process it.
    2. Generate a summary for the room and add it to rooms.
    3. Add any m.space.child events of the room to events.
  5. Recurse into any newly added targets of m.space.child events (i.e. repeat step 4), until either all discovered rooms have been inspected, or the server-side limit on the number of rooms is reached.

Other notes:

  • Any inaccessible children are omitted from the result, but the m.space.child events that point to them are still returned.

  • There could be loops in the returned child events - clients should handle this gracefully.

  • Similarly, note that a child room might appear multiple times (e.g. also be a grandchild). Clients and servers should handle this appropriately.

  • suggested_only applies transitively.

    For example, if a space A has child space B which is not suggested, and space B has suggested child room C, and the client makes a summary request for A with suggested_only=true, neither B nor C will be returned.

    Similarly, if a space A has child space B which is suggested, and space B has suggested child room C which is suggested, and the client makes a summary request for A with suggested_only=true, both B and C will be returned.

  • The current implementation doesn't honour order fields in child events, as suggested in MSC1772.

  • m.space.child with an invalid via (invalid is defined as missing, not an array or an empty array) are ignored.

Server-server API

Much the same interface as the Client-Server API.

Example request:

GET /_matrix/federation/v1/spaces/{roomID}
{
    "exclude_rooms": ["!a:b", "!b:c"],
    "max_rooms_per_space": 5,
    "suggested_only": true
}

The response has the same shape as the Client-Server API.

Request params are the same as the Client-Server API, with the addition of:

  • exclude_rooms: Optional. A list of room IDs that can be omitted from the response.

This is largely the same as the Client-Server API, but differences are:

  • The calling server can specify a list of spaces/rooms to omit from the response (via exclude_rooms).
  • max_rooms_per_space applies to the root room as well as any returned children.
  • If the target server is not a member of any discovered children (so would have to send another request over federation to inspect them), no attempt is made to recurse into them - they are simply omitted from the response.
    • If the target server is not a member of the root room, an empty response is returned.
  • Currently, no consideration is given to room membership: the spaces/rooms must be world-readable (ie, peekable) for them to appear in the results.

Potential issues

To reduce complexity, only a limited number of rooms are returned for a room, no effort is made to paginate the results. Proper pagination is left to a future MSC.

Alternatives

An initial version of this followed both m.space.child and m.space.parent events, but this is unnecessary to provide the expected user experience.

Security considerations

None.

Unstable prefix

During development of this feature it will be available at unstable endpoints.

The client-server API will be: /_matrix/client/unstable/org.matrix.msc2946/rooms/{roomID}/spaces

The server-server API will be: /_matrix/federation/unstable/org.matrix.msc2946/spaces/{roomID}