Add Spaces to the spec (#3610)
* First iteration of specifying Spaces MSCs: * https://github.com/matrix-org/matrix-doc/pull/3288 * https://github.com/matrix-org/matrix-doc/pull/2946 * https://github.com/matrix-org/matrix-doc/pull/1772 Note that this makes modifications to the underlying MSCs as well. These are intended to be minor edits to aid clarity/accuracy of the MSCs, as per the proposal process. Functionally, clients and servers might need to change their behaviour slightly as is expected of implementing this stuff early. Synapse has these changes (alongside backwards compatibility) here: https://github.com/matrix-org/synapse/pull/11667 * add changelogs * Accuracy per review * Apply suggestions from code review Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> * fully prefix new endpoints * Fully prefix endpoint in 3616 too * Fix ordering example Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>pull/977/head
parent
21882b6006
commit
9af83dfd41
@ -0,0 +1 @@
|
|||||||
|
Add Spaces and room types as per [MSC1772](https://github.com/matrix-org/matrix-doc/pull/1772) and [MSC2946](https://github.com/matrix-org/matrix-doc/pull/2946).
|
@ -0,0 +1 @@
|
|||||||
|
Add the Space Hierarchy API (`GET /_matrix/client/v1/rooms/{roomId}/hierarchy`) as per [MSC2946](https://github.com/matrix-org/matrix-doc/pull/2946).
|
@ -1 +1 @@
|
|||||||
Add `/register/m.login.registration_token/validity` as per [MSC3231](https://github.com/matrix-org/matrix-doc/pull/3231).
|
Add `/_matrix/client/v1/register/m.login.registration_token/validity` as per [MSC3231](https://github.com/matrix-org/matrix-doc/pull/3231).
|
@ -0,0 +1 @@
|
|||||||
|
Add the `room_type` to stored invites as per [MSC3288](https://github.com/matrix-org/matrix-doc/pull/3288).
|
@ -0,0 +1 @@
|
|||||||
|
Add the Space Hierarchy API (`GET /_matrix/federation/v1/hierarchy/{roomId}`) as per [MSC2946](https://github.com/matrix-org/matrix-doc/pull/2946).
|
@ -0,0 +1,254 @@
|
|||||||
|
---
|
||||||
|
type: module
|
||||||
|
weight: 340
|
||||||
|
---
|
||||||
|
|
||||||
|
### Spaces
|
||||||
|
|
||||||
|
{{% added-in v="1.2" %}}
|
||||||
|
|
||||||
|
Often used to group rooms of similar subject matter (such as a public "Official
|
||||||
|
matrix.org rooms" space or personal "Work stuff" space), spaces are a way to
|
||||||
|
organise rooms while being represented as rooms themselves.
|
||||||
|
|
||||||
|
A space is defined by the [`m.space` room type](#types), making it known as a
|
||||||
|
"space-room". The space's name, topic, avatar, aliases, etc are all defined through
|
||||||
|
the existing relevant state events within the space-room.
|
||||||
|
|
||||||
|
Sending normal [`m.room.message`](#mroommessage) events within the space-room is
|
||||||
|
discouraged - clients are not generally expected to have a way to render the timeline
|
||||||
|
of the room. As such, space-rooms should be created with [`m.room.power_levels`](#mroompower_levels)
|
||||||
|
which prohibit normal events by setting `events_default` to a suitably high number.
|
||||||
|
In the default power level structure, this would be `100`. Clients might wish to
|
||||||
|
go a step further and explicitly ignore notification counts on space-rooms.
|
||||||
|
|
||||||
|
Membership of a space is defined and controlled by the existing mechanisms which
|
||||||
|
govern a room: [`m.room.member`](#mroommember), [`m.room.history_visibility`](#mroomhistory_visibility),
|
||||||
|
and [`m.room.join_rules`](#mroomjoin_rules). Public spaces are encouraged to have
|
||||||
|
a similar setup to public rooms: `world_readable` history visibility, published
|
||||||
|
canonical alias, and suitably public `join_rule`. Invites, including third-party
|
||||||
|
invites, still work just as they do in normal rooms as well.
|
||||||
|
|
||||||
|
All other aspects of regular rooms are additionally carried over, such as the
|
||||||
|
ability to set arbitrary state events, hold room account data, etc. Spaces are
|
||||||
|
just rooms with extra functionality on top.
|
||||||
|
|
||||||
|
#### Managing rooms/spaces included in a space
|
||||||
|
|
||||||
|
Spaces form a hierarchy of rooms which clients can use to structure their room
|
||||||
|
list into a tree-like view. The parent/child relationship can be defined in two
|
||||||
|
ways: with [`m.space.child`](#mspacechild) state events in the space-room, or with
|
||||||
|
[`m.space.parent`](#mspaceparent) state events in the child room.
|
||||||
|
|
||||||
|
In most cases, both the child and parent relationship should be defined to aid
|
||||||
|
discovery of the space and its rooms. When only a `m.space.child` is used, the space
|
||||||
|
is effectively a curated list of rooms which the rooms themselves might not be aware
|
||||||
|
of. When only a `m.space.parent` is used, the rooms are "secretly" added to spaces
|
||||||
|
with the effect of not being advertised directly by the space.
|
||||||
|
|
||||||
|
{{% boxes/warning %}}
|
||||||
|
Considering spaces are rooms themselves, it is possible to nest spaces within spaces,
|
||||||
|
and it is possible to create a loop. Though the creation of loops is explicitly disallowed,
|
||||||
|
implementations might still encounter them and must be careful not to loop infinitely when
|
||||||
|
this happens.
|
||||||
|
|
||||||
|
Clients and servers should additionally be aware of excessively long trees which may
|
||||||
|
cause performance issues.
|
||||||
|
{{% /boxes/warning %}}
|
||||||
|
|
||||||
|
##### `m.space.child` relationship
|
||||||
|
|
||||||
|
When using this approach, the state events get sent into the space-room which is the
|
||||||
|
parent to the room. The `state_key` for the event is the child room's ID.
|
||||||
|
|
||||||
|
For example, to achieve the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
#space:example.org
|
||||||
|
#general:example.org (!abcdefg:example.org)
|
||||||
|
!private:example.org
|
||||||
|
```
|
||||||
|
|
||||||
|
the state of `#space:example.org` would consist of:
|
||||||
|
|
||||||
|
*Unimportant fields trimmed for brevity.*
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "m.space.child",
|
||||||
|
"state_key": "!abcdefg:example.org",
|
||||||
|
"content": {
|
||||||
|
"via": ["example.org"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "m.space.child",
|
||||||
|
"state_key": "!private:example.org",
|
||||||
|
"content": {
|
||||||
|
"via": ["example.org"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
No state events in the child rooms themselves would be required (though they
|
||||||
|
can also be present). This allows for users
|
||||||
|
to define personal/private spaces to organise their own rooms without needing explicit
|
||||||
|
permission from the room moderators/admins.
|
||||||
|
|
||||||
|
Child rooms can be removed from a space by omitting the `via` key of `content` on the
|
||||||
|
relevant state event, such as through redaction or otherwise clearing the `content`.
|
||||||
|
|
||||||
|
{{% event event="m.space.child" %}}
|
||||||
|
|
||||||
|
###### Ordering
|
||||||
|
|
||||||
|
When the client is displaying the children of a space, the children should be ordered
|
||||||
|
using the algorithm below. In some cases, like a traditional left side room list, the
|
||||||
|
client may override the ordering to provide better user experience. A theoretical
|
||||||
|
space summary view would however show the children ordered.
|
||||||
|
|
||||||
|
Taking the set of space children, first order the children with a valid `order` key
|
||||||
|
lexicographically by Unicode code-points such that `\x20` (space) is sorted before
|
||||||
|
`\x7E` (`~`). Then, take the remaining children and order them by the `origin_server_ts`
|
||||||
|
of their `m.space.child` event in ascending numeric order, placing them after the
|
||||||
|
children with a valid `order` key in the resulting set.
|
||||||
|
|
||||||
|
In cases where the `order` values are the same, the children are ordered by their
|
||||||
|
timestamps. If the timestamps are the same, the children are ordered lexicographically
|
||||||
|
by their room IDs (state keys) in ascending order.
|
||||||
|
|
||||||
|
Noting the careful use of ASCII spaces here, the following demonstrates a set of space
|
||||||
|
children being ordered appropriately:
|
||||||
|
|
||||||
|
*Unimportant fields trimmed for brevity.*
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"type": "m.space.child",
|
||||||
|
"state_key": "!b:example.org",
|
||||||
|
"origin_server_ts": 1640341000000,
|
||||||
|
"content": {
|
||||||
|
"order": " ",
|
||||||
|
"via": ["example.org"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "m.space.child",
|
||||||
|
"state_key": "!a:example.org",
|
||||||
|
"origin_server_ts": 1640141000000,
|
||||||
|
"content": {
|
||||||
|
"order": "aaaa",
|
||||||
|
"via": ["example.org"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "m.space.child",
|
||||||
|
"state_key": "!c:example.org",
|
||||||
|
"origin_server_ts": 1640841000000,
|
||||||
|
"content": {
|
||||||
|
"order": "first",
|
||||||
|
"via": ["example.org"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "m.space.child",
|
||||||
|
"state_key": "!e:example.org",
|
||||||
|
"origin_server_ts": 1640641000000,
|
||||||
|
"content": {
|
||||||
|
"via": ["example.org"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "m.space.child",
|
||||||
|
"state_key": "!d:example.org",
|
||||||
|
"origin_server_ts": 1640741000000,
|
||||||
|
"content": {
|
||||||
|
"via": ["example.org"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
1. `!b:example.org` is first because `\x20` is before `aaaa` lexically.
|
||||||
|
2. `!a:example.org` is next because `aaaa` is before `first` lexically.
|
||||||
|
3. `!c:example.org` is next because `first` is the last `order` value.
|
||||||
|
4. `!e:example.org` is next because the event timestamp is smallest.
|
||||||
|
5. `!d:example.org` is last because the event timestamp is largest.
|
||||||
|
|
||||||
|
##### `m.space.parent` relationships
|
||||||
|
|
||||||
|
Rooms can additionally claim to be part of a space by populating their own state
|
||||||
|
with a parent event. Similar to child events within spaces, the parent event's
|
||||||
|
`state_key` is the room ID of the parent space, and they have a similar `via` list
|
||||||
|
within their `content` to denote both whether or not the link is valid and which
|
||||||
|
servers might be possible to join through.
|
||||||
|
|
||||||
|
To avoid situations where a room falsely claims it is part of a given space,
|
||||||
|
`m.space.parent` events should be ignored unless one of the following is true:
|
||||||
|
|
||||||
|
* A corresponding `m.space.child` event can be found in the supposed parent space.
|
||||||
|
* The sender of the `m.space.parent` event has sufficient power level in the
|
||||||
|
supposed parent space to send `m.space.child` state events (there doesn't need
|
||||||
|
to be a matching child event).
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
Clients might need to peek into a parent space to inspect the room state if they
|
||||||
|
aren't already joined. If the client is unable to peek the state, the link should
|
||||||
|
be assumed to be invalid.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
A consequence of the second condition is that a room admin being demoted in the
|
||||||
|
parent space, leaving the parent space, or otherwise being removed from the parent
|
||||||
|
space can mean that a previously valid `m.space.parent` event becomes invalid.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
`m.space.parent` events can additionally include a `canonical` boolean key in their
|
||||||
|
`content` to denote that the parent space is the main/primary space for the room.
|
||||||
|
This can be used to, for example, have the client find other rooms by peeking into
|
||||||
|
that space and suggesting them to the user. Only one canonical parent should exist,
|
||||||
|
though this is not enforced. To tiebreak, use the lowest room ID sorted lexicographically
|
||||||
|
by Unicode code-points.
|
||||||
|
|
||||||
|
{{% event event="m.space.parent" %}}
|
||||||
|
|
||||||
|
#### Discovering rooms within spaces
|
||||||
|
|
||||||
|
Often the client will want to assist the user in exploring what rooms/spaces are part
|
||||||
|
of a space. This can be done with crawling [`m.space.child`](#mspacechild) state events
|
||||||
|
in the client and peeking into the rooms to get information like the room name, though
|
||||||
|
this is impractical for most cases.
|
||||||
|
|
||||||
|
Instead, a hierarchy API is provided to walk the space tree and discover the rooms with
|
||||||
|
their aesthetic details.
|
||||||
|
|
||||||
|
The [`GET /hierarchy`](#get_matrixclientv1roomsroomidhierarchy) API works in a depth-first
|
||||||
|
manner: when it encounters another space as a child it recurses into that space before
|
||||||
|
returning non-space children.
|
||||||
|
|
||||||
|
{{% boxes/warning %}}
|
||||||
|
Though prohibited, it is still possible for loops to occur. Servers should gracefully
|
||||||
|
break loops.
|
||||||
|
|
||||||
|
Additionally, a given child room might appear multiple times in the response as a
|
||||||
|
grandchild (for example).
|
||||||
|
{{% /boxes/warning %}}
|
||||||
|
|
||||||
|
{{% http-api spec="client-server" api="space_hierarchy" %}}
|
||||||
|
|
||||||
|
##### Server behaviour
|
||||||
|
|
||||||
|
In the case where the server does not have access to the state of a child room, it can
|
||||||
|
request the information over federation with the
|
||||||
|
[`GET /hierarchy`](/server-server-api/#get_matrixfederationv1hierarchyroomid) API. The
|
||||||
|
response to this endpoint should be cached for a period of time. The response might
|
||||||
|
additionally contain information about rooms the requesting user is already a member
|
||||||
|
of, or that the server is aware of - the local data should be used instead of the remote
|
||||||
|
server's data.
|
||||||
|
|
||||||
|
Note that the response to the client endpoint is contextual based on the user. Servers are
|
||||||
|
encouraged to cache the data for a period of time, though permission checks may need to
|
||||||
|
be performed to ensure the response is accurate for that user.
|
@ -0,0 +1,70 @@
|
|||||||
|
# Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
type: object
|
||||||
|
title: "PublicRoomsChunk"
|
||||||
|
properties:
|
||||||
|
aliases:
|
||||||
|
type: array
|
||||||
|
description: Aliases of the room. May be empty.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
example: ["#general:example.org"]
|
||||||
|
canonical_alias:
|
||||||
|
type: string
|
||||||
|
description: The canonical alias of the room, if any.
|
||||||
|
example: "#general:example.org"
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: The name of the room, if any.
|
||||||
|
example: "General Chat"
|
||||||
|
num_joined_members:
|
||||||
|
type: integer
|
||||||
|
description: The number of members joined to the room.
|
||||||
|
example: 42
|
||||||
|
room_id:
|
||||||
|
type: string
|
||||||
|
description: The ID of the room.
|
||||||
|
example: "!abcdefg:example.org"
|
||||||
|
topic:
|
||||||
|
type: string
|
||||||
|
description: The topic of the room, if any.
|
||||||
|
example: "All things general"
|
||||||
|
world_readable:
|
||||||
|
type: boolean
|
||||||
|
description: Whether the room may be viewed by guest users without joining.
|
||||||
|
example: false
|
||||||
|
guest_can_join:
|
||||||
|
type: boolean
|
||||||
|
description: |-
|
||||||
|
Whether guest users may join the room and participate in it.
|
||||||
|
If they can, they will be subject to ordinary power level
|
||||||
|
rules like any other user.
|
||||||
|
example: true
|
||||||
|
avatar_url:
|
||||||
|
type: string
|
||||||
|
format: uri
|
||||||
|
description: The URL for the room's avatar, if one is set.
|
||||||
|
example: "mxc://example.org/abcdef"
|
||||||
|
join_rule:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The room's join rule. When not present, the room is assumed to
|
||||||
|
be `public`.
|
||||||
|
example: "public"
|
||||||
|
required:
|
||||||
|
- room_id
|
||||||
|
- num_joined_members
|
||||||
|
- world_readable
|
||||||
|
- guest_can_join
|
@ -0,0 +1,194 @@
|
|||||||
|
# Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
swagger: '2.0'
|
||||||
|
info:
|
||||||
|
title: "Matrix Client-Server Space Hierarchy API"
|
||||||
|
version: "1.0.0"
|
||||||
|
host: localhost:8008
|
||||||
|
schemes:
|
||||||
|
- https
|
||||||
|
- http
|
||||||
|
basePath: /_matrix/client/v1
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
securityDefinitions:
|
||||||
|
$ref: definitions/security.yaml
|
||||||
|
paths:
|
||||||
|
"/rooms/{roomId}/hierarchy":
|
||||||
|
get:
|
||||||
|
x-addedInMatrixVersion: "1.2"
|
||||||
|
summary: Retrieve a portion of a space tree.
|
||||||
|
description: |-
|
||||||
|
Paginates over the space tree in a depth-first manner to locate child rooms of a given space.
|
||||||
|
|
||||||
|
Where a child room is unknown to the local server, federation is used to fill in the details.
|
||||||
|
The servers listed in the `via` array should be contacted to attempt to fill in missing rooms.
|
||||||
|
|
||||||
|
Only [`m.space.child`](#mspacechild) state events of the room are considered. Invalid child
|
||||||
|
rooms and parent events are not covered by this endpoint.
|
||||||
|
operationId: getSpaceHierarchy
|
||||||
|
security:
|
||||||
|
- accessToken: []
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
type: string
|
||||||
|
name: roomId
|
||||||
|
description: The room ID of the space to get a hierarchy for.
|
||||||
|
required: true
|
||||||
|
x-example: "!space:example.org"
|
||||||
|
- in: query
|
||||||
|
type: boolean
|
||||||
|
name: suggested_only
|
||||||
|
description: |-
|
||||||
|
Optional (default `false`) flag to indicate whether or not the server should only consider
|
||||||
|
suggested rooms. Suggested rooms are annotated in their [`m.space.child`](#mspacechild) event
|
||||||
|
contents.
|
||||||
|
x-example: true
|
||||||
|
- in: query
|
||||||
|
type: number
|
||||||
|
name: limit
|
||||||
|
description: |-
|
||||||
|
Optional limit for the maximum number of rooms to include per response. Must be an integer
|
||||||
|
greater than zero.
|
||||||
|
|
||||||
|
Servers should apply a default value, and impose a maximum value to avoid resource exhaustion.
|
||||||
|
x-example: 20
|
||||||
|
- in: query
|
||||||
|
type: number
|
||||||
|
name: max_depth
|
||||||
|
description: |-
|
||||||
|
Optional limit for how far to go into the space. Must be a non-negative integer.
|
||||||
|
|
||||||
|
When reached, no further child rooms will be returned.
|
||||||
|
|
||||||
|
Servers should apply a default value, and impose a maximum value to avoid resource exhaustion.
|
||||||
|
x-example: 5
|
||||||
|
- in: query
|
||||||
|
type: string
|
||||||
|
name: from
|
||||||
|
description: |-
|
||||||
|
A pagination token from a previous result. If specified, `max_depth` and `suggested_only` cannot
|
||||||
|
be changed from the first request.
|
||||||
|
x-example: "next_batch_token"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: |-
|
||||||
|
A portion of the space tree, starting at the provided room ID.
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"rooms": [
|
||||||
|
{
|
||||||
|
"room_id": "!space:example.org",
|
||||||
|
"avatar_url": "mxc://example.org/abcdef",
|
||||||
|
"guest_can_join": false,
|
||||||
|
"name": "The First Space",
|
||||||
|
"topic": "No other spaces were created first, ever",
|
||||||
|
"world_readable": true,
|
||||||
|
"join_rule": "public",
|
||||||
|
"room_type": "m.space",
|
||||||
|
"num_joined_members": 42,
|
||||||
|
"aliases": ["#general:example.org"],
|
||||||
|
"canonical_alias": "#general:example.org",
|
||||||
|
"children_state": [
|
||||||
|
{
|
||||||
|
"type": "m.space.child",
|
||||||
|
"state_key": "!a:example.org",
|
||||||
|
"content": {
|
||||||
|
"via": ["example.org"]
|
||||||
|
},
|
||||||
|
"sender": "@alice:example.org",
|
||||||
|
"origin_server_ts": 1629413349153
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"next_batch": "next_batch_token"
|
||||||
|
}
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
rooms:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
The rooms for the current page, with the current filters.
|
||||||
|
items:
|
||||||
|
allOf:
|
||||||
|
- $ref: "definitions/public_rooms_chunk.yaml"
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
room_type:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The `type` of room (from [`m.room.create`](/client-server-api/#mroomcreate)), if any.
|
||||||
|
children_state:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
The [`m.space.child`](#mspacechild) events of the space-room, represented
|
||||||
|
as [Stripped State Events](#stripped-state) with an added `origin_server_ts` key.
|
||||||
|
|
||||||
|
If the room is not a space-room, this should be empty.
|
||||||
|
items:
|
||||||
|
allOf:
|
||||||
|
- $ref: "../../event-schemas/schema/core-event-schema/stripped_state.yaml"
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
origin_server_ts:
|
||||||
|
type: number
|
||||||
|
format: int64
|
||||||
|
description: The `origin_server_ts` for the event.
|
||||||
|
required: [origin_server_ts]
|
||||||
|
required: [room_type, children_state]
|
||||||
|
next_batch:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
A token to supply to `from` to keep paginating the responses. Not present when there are
|
||||||
|
no further results.
|
||||||
|
required: [rooms]
|
||||||
|
403:
|
||||||
|
description: |-
|
||||||
|
The user cannot view or peek on the room. A meaningful `errcode`
|
||||||
|
and description error text will be returned. Example reasons for rejection are:
|
||||||
|
|
||||||
|
- The room is not set up for peeking.
|
||||||
|
- The user has been banned from the room.
|
||||||
|
- The room does not exist.
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"errcode": "M_FORBIDDEN",
|
||||||
|
"error": "You are not allowed to view this room."
|
||||||
|
}
|
||||||
|
schema:
|
||||||
|
"$ref": "definitions/errors/error.yaml"
|
||||||
|
400:
|
||||||
|
description: |-
|
||||||
|
The request was invalid in some way. A meaningful `errcode`
|
||||||
|
and description error text will be returned. Example reasons for rejection are:
|
||||||
|
|
||||||
|
- The `from` token is unknown to the server.
|
||||||
|
- `suggested_only` or `max_depth` changed during pagination.
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"errcode": "M_INVALID_PARAM",
|
||||||
|
"error": "suggested_only and max_depth cannot change on paginated requests"
|
||||||
|
}
|
||||||
|
schema:
|
||||||
|
"$ref": "definitions/errors/error.yaml"
|
||||||
|
429:
|
||||||
|
description: This request was rate-limited.
|
||||||
|
schema:
|
||||||
|
"$ref": "definitions/errors/rate_limited.yaml"
|
||||||
|
tags:
|
||||||
|
- Spaces
|
@ -0,0 +1,207 @@
|
|||||||
|
# Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
swagger: '2.0'
|
||||||
|
info:
|
||||||
|
title: "Matrix Federation Space Hierarchy API"
|
||||||
|
version: "1.0.0"
|
||||||
|
host: localhost:8448
|
||||||
|
schemes:
|
||||||
|
- https
|
||||||
|
basePath: /_matrix/federation/v1
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
securityDefinitions:
|
||||||
|
$ref: definitions/security.yaml
|
||||||
|
paths:
|
||||||
|
"/hierarchy/{roomId}":
|
||||||
|
get:
|
||||||
|
x-addedInMatrixVersion: "1.2"
|
||||||
|
summary: Retrieve a portion of a space tree.
|
||||||
|
description: |-
|
||||||
|
Federation version of the Client-Server [`GET /hierarchy`](/client-server-api/#get_matrixclientv1roomsroomidhierarchy)
|
||||||
|
endpoint. Unlike the Client-Server API version, this endpoint does not paginate. Instead, all
|
||||||
|
the space-room's children the requesting server could feasibly peek/join are returned. The
|
||||||
|
requesting server is responsible for filtering the results further down for the user's request.
|
||||||
|
|
||||||
|
Only [`m.space.child`](#mspacechild) state events of the room are considered. Invalid child
|
||||||
|
rooms and parent events are not covered by this endpoint.
|
||||||
|
|
||||||
|
Responses to this endpoint should be cached for a period of time.
|
||||||
|
operationId: getSpaceHierarchy
|
||||||
|
security:
|
||||||
|
- signedRequest: []
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
type: string
|
||||||
|
name: roomId
|
||||||
|
description: The room ID of the space to get a hierarchy for.
|
||||||
|
required: true
|
||||||
|
x-example: "!space:example.org"
|
||||||
|
- in: query
|
||||||
|
type: boolean
|
||||||
|
name: suggested_only
|
||||||
|
description: |-
|
||||||
|
Optional (default `false`) flag to indicate whether or not the server should only consider
|
||||||
|
suggested rooms. Suggested rooms are annotated in their [`m.space.child`](#mspacechild) event
|
||||||
|
contents.
|
||||||
|
x-example: true
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: |-
|
||||||
|
The space room and its children.
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"room": {
|
||||||
|
"room_id": "!space:example.org",
|
||||||
|
"avatar_url": "mxc://example.org/abcdef",
|
||||||
|
"guest_can_join": false,
|
||||||
|
"name": "The First Space",
|
||||||
|
"topic": "No other spaces were created first, ever",
|
||||||
|
"world_readable": true,
|
||||||
|
"join_rule": "public",
|
||||||
|
"room_type": "m.space",
|
||||||
|
"num_joined_members": 42,
|
||||||
|
"aliases": ["#general:example.org"],
|
||||||
|
"canonical_alias": "#general:example.org",
|
||||||
|
"allowed_room_ids": [],
|
||||||
|
"children_state": [
|
||||||
|
{
|
||||||
|
"type": "m.space.child",
|
||||||
|
"state_key": "!a:example.org",
|
||||||
|
"content": {
|
||||||
|
"via": ["remote.example.org"]
|
||||||
|
},
|
||||||
|
"sender": "@alice:example.org",
|
||||||
|
"origin_server_ts": 1629413349153
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"inaccessible_children": [
|
||||||
|
"!secret:example.org"
|
||||||
|
],
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"room_id": "!second_room:example.org",
|
||||||
|
"avatar_url": "mxc://example.org/abcdef2",
|
||||||
|
"guest_can_join": false,
|
||||||
|
"name": "The ~~First~~ Second Space",
|
||||||
|
"topic": "Hello world",
|
||||||
|
"world_readable": true,
|
||||||
|
"join_rule": "restricted",
|
||||||
|
"room_type": "m.space",
|
||||||
|
"num_joined_members": 42,
|
||||||
|
"aliases": ["#general:example.org"],
|
||||||
|
"canonical_alias": "#general:example.org",
|
||||||
|
"allowed_room_ids": [
|
||||||
|
"!upstream:example.org"
|
||||||
|
],
|
||||||
|
"children_state": [
|
||||||
|
{
|
||||||
|
"type": "m.space.child",
|
||||||
|
"state_key": "!b:example.org",
|
||||||
|
"content": {
|
||||||
|
"via": ["remote.example.org"]
|
||||||
|
},
|
||||||
|
"sender": "@alice:example.org",
|
||||||
|
"origin_server_ts": 1629422222222
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
room:
|
||||||
|
description: A summary of the room requested.
|
||||||
|
allOf:
|
||||||
|
- $ref: "../client-server/definitions/public_rooms_chunk.yaml"
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
room_type:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The `type` of room (from [`m.room.create`](/client-server-api/#mroomcreate)), if any.
|
||||||
|
allowed_room_ids:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
If the room is a [restricted room](#restricted-rooms), these are the room IDs which
|
||||||
|
are specified by the join rules. Empty or omitted otherwise.
|
||||||
|
children_state:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
The [`m.space.child`](/client-server-api/#mspacechild) events of the space-room, represented
|
||||||
|
as [Stripped State Events](/client-server-api/#stripped-state) with an added
|
||||||
|
`origin_server_ts` key.
|
||||||
|
|
||||||
|
If the room is not a space-room, this should be empty.
|
||||||
|
items:
|
||||||
|
allOf:
|
||||||
|
- $ref: "../../event-schemas/schema/core-event-schema/stripped_state.yaml"
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
origin_server_ts:
|
||||||
|
type: number
|
||||||
|
format: int64
|
||||||
|
description: The `origin_server_ts` for the event.
|
||||||
|
required: [origin_server_ts]
|
||||||
|
required: [room_type, allowed_room_ids, children_state]
|
||||||
|
children:
|
||||||
|
description: |-
|
||||||
|
A summary of the space's children. Rooms which the requesting server cannot peek/join will
|
||||||
|
be excluded.
|
||||||
|
allOf:
|
||||||
|
- $ref: "../client-server/definitions/public_rooms_chunk.yaml"
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
room_type:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The `type` of room (from [`m.room.create`](/client-server-api/#mroomcreate)), if any.
|
||||||
|
allowed_room_ids:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
If the room is a [restricted room](#restricted-rooms), these are the room IDs which
|
||||||
|
are specified by the join rules. Empty or omitted otherwise.
|
||||||
|
required: [room_type, allowed_room_ids, children_state]
|
||||||
|
inaccessible_children:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The list of room IDs the requesting server doesn't have a viable way to peek/join. Rooms which
|
||||||
|
the responding server cannot provide details on will be outright excluded from the response instead.
|
||||||
|
|
||||||
|
Assuming both the requesting and responding server are well behaved, the requesting server should
|
||||||
|
consider these room IDs as not accessible from anywhere. They should not be re-requested.
|
||||||
|
required: [room, children, inaccessible_children]
|
||||||
|
404:
|
||||||
|
description: |-
|
||||||
|
The room is not known to the server or the requesting server is unable to peek/join
|
||||||
|
it (if it were to attempt this).
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"errcode": "M_NOT_FOUND",
|
||||||
|
"error": "Room does not exist."
|
||||||
|
}
|
||||||
|
schema:
|
||||||
|
"$ref": "../client-server/definitions/errors/error.yaml"
|
||||||
|
tags:
|
||||||
|
- Spaces
|
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"$ref": "core/state_event.json",
|
||||||
|
"type": "m.space.child",
|
||||||
|
"state_key": "!roomid:example.org",
|
||||||
|
"content": {
|
||||||
|
"suggested": true,
|
||||||
|
"via": ["example.org", "other.example.org"],
|
||||||
|
"order": "lexicographically_compare_me"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"$ref": "core/state_event.json",
|
||||||
|
"type": "m.space.parent",
|
||||||
|
"state_key": "!parent_roomid:example.org",
|
||||||
|
"content": {
|
||||||
|
"canonical": true,
|
||||||
|
"via": ["example.org", "other.example.org"]
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
allOf:
|
||||||
|
- $ref: core-event-schema/state_event.yaml
|
||||||
|
description: Defines the relationship of a child room to a space-room. Has no effect in rooms which are not [spaces](#spaces).
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
properties:
|
||||||
|
via:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
A list of servers to try and join through. See also: [Routing](/appendices/#routing).
|
||||||
|
|
||||||
|
When not present or invalid, the child room is not considered to be part of the space.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
order:
|
||||||
|
type: string
|
||||||
|
maxLength: 50
|
||||||
|
pattern: '^[\x20-\x7E]+$'
|
||||||
|
description: |-
|
||||||
|
Optional string to define ordering among space children. These are lexicographically
|
||||||
|
compared against other children's `order`, if present.
|
||||||
|
|
||||||
|
Must consist of ASCII characters within the range `\x20` (space) and `\x7E` (`~`),
|
||||||
|
inclusive. Must not exceed 50 characters.
|
||||||
|
|
||||||
|
`order` values with the wrong type, or otherwise invalid contents, are to be treated
|
||||||
|
as though the `order` key was not provided.
|
||||||
|
|
||||||
|
See [Ordering](/client-server-api/#ordering-1) for information on how the ordering works.
|
||||||
|
suggested:
|
||||||
|
type: boolean
|
||||||
|
description: |-
|
||||||
|
Optional (default `false`) flag to denote whether the child is "suggested" or of interest
|
||||||
|
to members of the space. This is primarily intended as a rendering hint for clients to
|
||||||
|
display the room differently, such as eagerly rendering them in the room list.
|
||||||
|
type: object
|
||||||
|
state_key:
|
||||||
|
description: The child room ID being described.
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
enum:
|
||||||
|
- m.space.child
|
||||||
|
type: string
|
||||||
|
title: Space child room
|
||||||
|
type: object
|
@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
allOf:
|
||||||
|
- $ref: core-event-schema/state_event.yaml
|
||||||
|
description: Defines the relationship of a room to a parent space-room.
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
properties:
|
||||||
|
via:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
A list of servers to try and join through. See also: [Routing](/appendices/#routing).
|
||||||
|
|
||||||
|
When not present or invalid, the room is not considered to be part of the parent space.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
canonical:
|
||||||
|
type: boolean
|
||||||
|
description: |-
|
||||||
|
Optional (default `false`) flag to denote this parent is the primary parent for the room.
|
||||||
|
|
||||||
|
When multiple `canonical` parents are found, the lowest parent when ordering by room ID
|
||||||
|
lexicographically by Unicode code-points should be used.
|
||||||
|
type: object
|
||||||
|
state_key:
|
||||||
|
description: The parent room ID.
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
enum:
|
||||||
|
- m.space.parent
|
||||||
|
type: string
|
||||||
|
title: Room space parent
|
||||||
|
type: object
|
Loading…
Reference in New Issue