Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSC1840: Typed rooms #1840

Closed
85 changes: 85 additions & 0 deletions proposals/1840-room-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
- **Author**: Jonathan Frederickson
- **Created**: 2019-02-03

# Room Types

## Problem

The Matrix protocol currently has no mechanism to differentiate rooms
from each other based on their intended use case. There have been
proposals such as
[MSC1769](https://github.com/matrix-org/matrix-doc/pull/1769) and
[MSC1772](https://github.com/matrix-org/matrix-doc/pull/1772) that use
rooms for purposes other than the traditional messaging
use-case. Without a mechanism to differentiate them from messaging
rooms, clients will display them as they do any other room unless they
work around this limitation on a case-by-case basis.

## Solution

The proposal is to add a new state event, `m.room.type`, to define the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realise this may bloat the proposal, but I feel like we should define a few common types in the spec and how clients should react to them, at least at a high level. I.e. m.room_type.messaging should present users with a chat-room like interface, wheras m.room_type.iot.* may just show a simplified view.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a type like m.room_type.nsfw could be used to filter out explicit content. In that case, would it make sense to allow public directory filtering by room type?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marking something as nsfw is more like a tag than a type IMO, because you can have nsfw content in different types of room. I think nsfw tagging (or content notices/warnings to be more generic) are a separate topic.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Counter-examples are useful too. It's worth included a counter-example like this in the spec to illustrate one of the boundaries of applicability.

Copy link
Author

@jfrederickson jfrederickson Oct 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a few examples.

For what it's worth... nsfw might still be a useful type to have if it's possible to have multiple types associated with a room? In other words, rather than:

"content": {
    "type": "m.messaging"
}

Use an array:

"content": {
    "types": ["m.messaging", "m.nsfw"]
}

...though regardless of the types in particular, I'd like to consider the option of a types array. @jcgruenhage brought this up outside of a thread, and I think I agree with it:

What do people think about having multi purpose rooms? For example if a room is used for hosting a git project in matrix, using the same room for discussion about that project would be desirable, because it allows us to use the same alias there.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allowing multiple types at once would cause massive confusion especially in clients which denormalize data. Imagine a room marked as IoT, Messaging, a Matrix Space and a User Profile room, how do you store anything and what do you even render?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was suggested in #matrix-spec:matrix.org that I use org.matrix.msc1840 as an unstable state event type until this PR is merged. Should this be noted somewhere in this document?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please, typically in an Unstable Prefix section.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a client developer, I would strongly argue to make room types immutable after room creation (e.g. putting it in /createRoom / m.room.create). Needing to anticipate that a community or profile room can be turned into a conversation room is just going to be a source for a lot of complexity. I also can't see any use case for this, we even want the DM-status of a conversation to be immutable in their new incarnation. And if we would want some type in the future that is mutable, we can always use a separate sub_type state event then.

The way to implement communities and profiles on Hydrogen for example would be to have a specialized storage model for those room types, which can't be turned back into a conversation room without resyncing that one room. I would argue that the spec should not exclude clients from making these kinds of optimizations, or at least burdening them with an unreasonable amount of complexity with no good use-case.

Copy link
Contributor

@Sorunome Sorunome Oct 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also can't see any use case for this, we even want the DM-status of a conversation to be immutable in their new incarnation.

Soru has had multiple usecases already where she invited people into a DM making it a "normal" room and vice versa. The usecase for that does exist and it makes it way harder now that element removed the UI for it :(

Needing to anticipate that a community or profile room can be turned into a conversation room is just going to be a source for a lot of complexity.

How so? With fluffychat at least it just builds up all the views of the current state, and does not tag anything permanently. The only exception here is not allowing to disable e2ee

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Soru has had multiple usecases already where she invited people into a DM making it a "normal" room and vice versa. The usecase for that does exist and it makes it way harder now that element removed the UI for it :(

As mentioned, if the DM-flag needs to be mutable, maybe there is a case for an immutable type as well as a mutable (sub)type.

Needing to anticipate that a community or profile room can be turned into a conversation room is just going to be a source for a lot of complexity.

How so? With fluffychat at least it just builds up all the views of the current state, and does not tag anything permanently. The only exception here is not allowing to disable e2ee

Hydrogen for example persists things in a denormalized state, and for a community room likely won't be storing the timeline. Apart from that, it seems nonsensical to allow a community room to be converted into a conversation room. Even if it would be easy to implement, it is something that will not be well tested (and therefore handled) and might not be expected by some clients.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from that, it seems nonsensical to allow a community room to be converted into a conversation room.

converting DMs to general rooms and back again is something we have today. Designing it out of the protocol feels like a big decision to me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from that, it seems nonsensical to allow a community room to be converted into a conversation room. Even

But maybe the other way round :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

room version upgrade is a bad example as that is a non-linear structure. One "low-level" room can have multiple parents. Which is exactly why UX is hard

Copy link
Contributor

@bwindels bwindels Nov 18, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from that, it seems nonsensical to allow a community room to be converted into a conversation room.

converting DMs to general rooms and back again is something we have today. Designing it out of the protocol feels like a big decision to me.

Agreed, so I'd say we need two kinds of types: a immutable one and a mutable one, e.g. "type": "m.messaging" with "sub_type": "m.dm", or "type": "m.space" for a #1772 space.

This may feel less elegant, but this really feels like madness otherwise, turning a space into conversation being akin to taking a sqlite file created by one application and trying to load it into another.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fwiw, there's no reason why a DM room needs to be its own type. Canonical DMs and associated MSCs can figure out how to represent it differently (like using m.kind in the current proposal).

Copy link
Contributor

@bwindels bwindels Nov 18, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fwiw, there's no reason why a DM room needs to be its own type. Canonical DMs and associated MSCs can figure out how to represent it differently (like using m.kind in the current proposal).

Right, but we might want to adjust the naming to make clear that the (mutable) kind is scoped within the (immutable) type? Having a type and a kind on a room might be confusing if their relationship is not clear. In any case, the main point being there is a place for both an immutable and mutable flag, so we should have both.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea, kind is badly named regardless of this MSC or not - the Canonical DMs MSC might be the one to figure out what mutable looks like. This MSC shouldn't be mutable imo.

intended usage of the room.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to say how this "defines the intended usage of the room". What values does it take? What kind of values does it take? The "examples" section contains some examples but we need to be explicit here.

For a start we need to say whether the list of values is fixed in the spec or user-extensible; the grammar (suggestion: from MSC2773, "The m.kind value grammar follows MSC2758's proposal"); and the syntax of values like whether they can contain arbitrary sub-type components ("messaging", "messaging.user_profile", "messaging.user_profile.user_status", etc.).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to mention the grammar explicitly conforming to MSC2758.

Regarding whether or not sub-types should be supported (or whether or not sub-types should be treated as such in the spec, I guess)... not sure, anyone have strong opinions on this? I'm inclined to leave that open to client developers who define their own types and to not explicitly specify them as subtypes. (IOW: if you're a client developer and want your client to consider a com.example.iot.graphs room to be a subset of com.example.iot, you can implement it that way, but they're otherwise not considered related.)


This by itself could be used by a client to properly display rooms
based on their intended usage. However, to optimize the use of
bandwidth for an account used for varying purposes, the filter API
could then be extended to allow for filtering the rooms that are
returned from a sync based on room type. (A client meant for receiving
IoT device data, for example, has no need to receive messages destined
for that account, nor to be aware at all that messaging rooms exist.)

N.B. There's an opportunity here to additionally scope access tokens
to specific room types, but that feels like it's beyond the scope of
this proposal at this point.

## Examples
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the type is omitted, would we consider m.room_type.messaging to be the default type given Matrix's history.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be wrong for this part of the spec to state a default value unconditionally. Concretely, it would be wrong for a general purpose library or SDK to report an unconditionally specified default value when the type is omitted.

A typical IM client, working with typical existing IM rooms, will presumably by default (when the type is unspecified) assume it's an IM messaging room; whereas the default assumption in an IoT client will be something else; and there could be deployment scenarios where all rooms have an explicit room type and no default is needed and the client software developed for that scenario reports an error or ignores the room if no type is provided.

A default value is in the eye of the beholder, not absolute.


### m.room.type

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MSC should give examples of non-messaging room types; either hypothetical or real ones will do.

The current single example of "messaging" is not really useful except to demonstrate syntax, because in the current ecosystem there's hardly anything else so it's hard to deduce anything about the scope and boundaries of applicability of this type.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a few examples - does that sufficiently answer this?


```json
{
"content": {
"type": "m.room_type.messaging"
jfrederickson marked this conversation as resolved.
Show resolved Hide resolved
jfrederickson marked this conversation as resolved.
Show resolved Hide resolved
},
"event_id": "$143273582443PhrSn:domain.com",
"origin_server_ts": 1432735824653,
"room_id": "!jEsUZKDJdhlrceRyVU:domain.com",
"sender": "@example:domain.com",
"state_key": "",
"type": "m.room.type",
"unsigned": {
"age": 1234
}
}
```

### Filter API Changes

```
POST /_matrix/client/r0/user/%40alice%3Aexample.com/filter HTTP/1.1
Content-Type: application/json

{
"room": {
"state": {
"types": [
"m.room.*"
],
"not_rooms": [
"!726s6s6q:example.com"
],
"room_types": [
"m.room_type.messaging"
],
"not_room_types": [
"m.room_type.iot.*"
],
},
"event_format": "client",
"event_fields": [
"type",
"content",
"sender"
]
}
```