-
Notifications
You must be signed in to change notification settings - Fork 385
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
MSC4110: Fewer Features #4110
base: main
Are you sure you want to change the base?
MSC4110: Fewer Features #4110
Conversation
* `0`: Default value, same as it being unset. The bridge understands and will send/convert/substitute the event for the destination platform. | ||
* `-1`: This feature will be worse over the bridge. The client can choose to *Discourage, Substitute, or Disallow* the feature. | ||
* `-2`: This feature will not work over the bridge, and the bridge will fall back to the `body` or `formatted_body` instead. The client can choose to *Substitute or Disallow* the feature. | ||
* `-3`: This feature will not work over the bridge, and fallbacks aren't a good enough substitute. The client must *Disallow* the feature. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking for feedback: Do these make sense? Do they cover all use cases? Does it make sense for them to be ordered like this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In MSC3968 I supported more levels in order to allow expressing "X will be bad over the bridge, but less bad than Y". Not sure that's useful, but at worst clients can ignore the finer levels.
### Extending to future features | ||
|
||
Features added to Matrix in the future will need their own feature declaration keys. There are two ways to add new keys to Fewer Features: | ||
|
||
1. In the MSC or spec for a new feature, the proposal can state what key to use. | ||
2. If any feature in the spec does not have a key, a new MSC can be created to simply propose adding a key for it. | ||
|
||
In addition, any MSCs that are not merged can use their `org.matrix.mscxxxx` number as the feature key. For example, the feature declaration key for [bot indicators][MSC4015] can be `org.matrix.msc4015`. This could be used to inform bots that this bridge will not bridge their bot markers to the external platform. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this helpful, or is it not necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I think this is helpful. One good use for it is things in the flagship client that are very visible to many users (= high likelihood of being sent by users who expect it to work) but which have an unstable prefix and are still going through the spec. Such as the polls feature, which was in Element for a while but only recently MSC merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is helpful (and even necessary) to note that non-spec extensions can be added, but instead of talking about MSCs specifically, it should just define that all feature identifiers must follow the Common Namespaced Identifier Grammar. That spec already defines that identifiers starting with m.
are reserved for specced features, and that custom identifiers following java package naming style are allowed.
There's also no requirement for unstable prefixes in MSCs to use the org.matrix.mscxxxx
format even though it's fairly common, any namespaced identifier is a valid unstable prefix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean I should change the feature keys to all start with m.
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right, they currently don't start with that 🤔
Yeah, I think they should be changed, having m.
on standard keys makes it clearer that custom keys are allowed too.
I would like to see something lile this. But while reading this, I was wondering if this could also be useful for client to client communication. For example, a client could communicate that it does not support threads, or location sharing, or any other client feature. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jooooscha To keep discussions organised and to know when they're each resolved, we tend to keep them on the diff. I'm moving your comment to the diff so I can respond to it:
I would like to see something lile this. But while reading this, I was wondering if this could also be useful for client to client communication. For example, a client could communicate that it does not support threads, or location sharing, or any other client feature.
That's an interesting idea. It might be good for less advanced clients to declare Fewer Features in a 1-1 chat, so the other person can avoid using incompatible features. And the trusted_private_chat preset for 1-1 chats allows both people to set any state event, so anybody could add Fewer Features to the room. But I don't think this would scale to group chats. If a single client could disable rich messaging for everyone in the room, that would be a pretty bad experience for everyone else, so we probably shouldn't allow that.
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree in general. But maybe, the less advanced client could also send Fewer Features to group chats and the more advanced clients decide what to do with it. I am thinking about a more advanced client trying to create a poll, but only one or perhaps none of the other ten group participants can handle polls. It could still be helpful to know that for the creator (client) of the poll.
Not sure if this is in the scope of Fewer Features.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true, it would be cute if when starting a poll in a group chat it could show a notice like "5 of the 10 people in this room can respond to polls". It could be like a larger scale version of a Discouraged feature.
However, I have no idea how to implement this. The Fewer Features proposal relies on state events but regular users can't set state arbitrary state events.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another complicating factor here is that users may use multiple clients with different capabilities. I normally run Element Desktop, Gomuks, and SchildiChat, all of which have different sets of supported features. It's unclear how I would indicate which of these features I as a user support.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, it's not realistic to ask human users to manually configure which events they would like to receive. It also (probably?) can't be done automatically by the clients because we can't distinguish between actively used clients and inactively used clients, unless we did some extreme to-device-messaging, which seems out of scope for Fewer Features.
|
||
```json | ||
{ | ||
"content": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe instead of having the features be an object, it could be a flat hierarchical key~value map, ie.
{
"reply": -1,
"replace": -1,
"formatting.bold": -1,
"formatting.link": -1,
"formatting.link.user": -1,
"formatting.link.event": -1,
"file": -1,
"file.image": -1,
// etc...
}
Then, formatting.link
can be set to discourage any links and formatting.link.event
could be set to discourage event links specifically. This would also be good for backwards compatibility, since new link type would still be disallowed if formatting.link
was set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tezlm As mentioned in "Differences to Poorer Features", I am deliberately limiting entire features rather than individual types, keys, and elements. So I am deliberately not including a way to disable bold formatting.
There is no use case for this because there are no platforms that allow/disallow bold formatting specifically. Even if there was one, the bridge should be able to deal with it, rather than offloading the work onto the client.
If there is a use case then I'm happy to reconsider making it a fine-grained features list like you suggested, but in this proposal I'm currently going with a coarse-grained design because it's the simple option that would be easier for clients to implement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most IRC servers allow channel operators to disallow (or strip) formatting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no use case for this because there are no platforms that allow/disallow bold formatting specifically. Even if there was one, the bridge should be able to deal with it, rather than offloading the work onto the client.
There are lots of platforms with less formatting features than Matrix even if bold is usually supported. For example:
- Most networks don't support inline images, collapsible blocks (
<details>
), tables and font colors - WhatsApp doesn't support spoilers
- Signal doesn't support blockquotes and lists
- Twitter supports user mentions but no other formatting
Bridges can deal with them to some extent, but obviously won't be able to perfectly bridge features that aren't supported. I think there should be a way to tell clients about unsupported features. Some clients may want that info even if other clients won't customize input format based on bridge. I could very well imagine using the goldmark markdown parser in Go and disabling specific features per room.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, seems good! You make good points about both the formatting features on other platforms and how easy it is for clients to implement it. I'll give this a try.
|
||
It is the client's choice whether their Substitution is "suitably close to parity" to be able to use it. This should be considered on a feature-by-feature and client-by-client basis. | ||
|
||
### Feature declarations - sending |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if maximum message length would make sense as a feature? I think right now if messages are too large they get uploaded by the bridge as a text file to the media repo? That has always felt a bit janky though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, we should add this. Though we'd have to consider that messages might become longer after being converted by the bridge. So even if the client complies with the stated length, the bridge might convert it to something longer and then still have to do some extra work to make the transformed message fit within the limit. (For example, this might happen if the bridged platform's format for user mentions is longer than Matrix's format.)
There's also a question of whether we count the length from body
or formatted_body
, and if formatted_body
, whether we count HTML elements as length. This gets even more complicated for extensible events.
Do you have any ideas how to make this work?
All I can think of is saying the maximum length is a "best guess" and bridges should still be able to handle the situation where it goes over the limit? If this stops Matrix users sending textwalls or pasted code blocks to IRC 90% of the time, that would at least be an improvement...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gave this a shot in MSC3969.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So even if the client complies with the stated length, the bridge might convert it to something longer and then still have to do some extra work to make the transformed message fit within the limit.
That's a good point, I don't have a solution for that unfortunately. Maybe it isn't so useful and bridges just need to handle it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What bridges would convert it to something longer? The IRC bridge always makes it shorter, and most other bridges probably just keep the (X)HTML minus disallowed tags.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think guessing based on the length of the user input should be good enough. Bridges will generally handle it by rejecting the message, so it'd be nice if users were told before sending at least for messages that are obviously way too long.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't tried implementing it, so your guess is as good as mine
#### `reaction_list` | ||
|
||
This is a list of all reactions that can be added to a message. This will probably be a list of emojis, but can also include text. (If the key is not specified, Matrix users can react with any text.) The special value `mxc://*` means any MXC URL can be used as a reaction. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if it'd make more sense to have send
values be objects so extra info like reaction limits, file size limits and possibly text length limits could all be in there
{
"send": {
"reaction": {
"desirability": 0,
"list": ["👍️", "👎️"]
},
"file": {
"desirability": 0,
"mimetypes": ["image/png", "image/jpeg"],
"max_size": 102400
},
"text": {
"desirability": 0,
"max_length": 100
},
"sticker": {
"desirability": 0
}
}
}
#### `file` | ||
|
||
This means the external platform doesn't support files. The bridge may be able to send through a hyperlink to the file. If the feature is Disallowed, clients should not upload files. This will also affect the `<img>` HTML element. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably also be more granular. For example, Instagram only allows images, videos and voice messages. WhatsApp allows anything when sending as document, but only specific mimetypes when sending as image/video/audio (https://developers.facebook.com/docs/whatsapp/on-premises/reference/media/). I think being able to set mimetype restrictions per msgtype would allow mapping everything properly.
#### `matrix.to_room` | ||
|
||
This affects the [matrix.to navigation](https://spec.matrix.org/v1.9/appendices/#matrixto-navigation) section of the spec. | ||
|
||
This means the external platform doesn't support links or references to rooms, so the bridge won't be able to convert the `matrix.to` links to a suitable representation. | ||
|
||
If the feature is Substituted, clients might be able to display a room name instead of a link. If the feature is Disallowed, clients shouldn't send `matrix.to` room links. | ||
|
||
#### `matrix.to_user` | ||
|
||
This means the external platform doesn't support links or references to users, so the bridge won't be able to convert it. | ||
|
||
If the feature is Substituted, clients might be able to display a user name instead of a link. If the feature is Disallowed, clients shouldn't send `matrix.to` user links. | ||
|
||
#### `matrix.to_event` | ||
|
||
This means the external platform doesn't support links or references to specific events, so the bridge won't be able to convert it. | ||
|
||
It is unlikely that clients can substitute this feature. If the feature is Disallowed, clients shouldn't send `matrix.to` event links. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should have more generic names rather than referencing matrix.to specifically because matrix:
URIs also exist (and bridges supporting recent versions of the spec should support both). The spec calls them "User and room mentions", although that could be confused with @room
mentions 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough, I don't like the name either. I originally picked it because the spec appendix called it out by name.
If I'm going with the hierarchical values from the suggestion above (formatting.bold
, formatting.link
etc) I'll put them under formatting.link.room
and formatting.link.user
which I think works pretty well. After all, the matrix.to room links really behave like room links and not mentions.
|
||
The Fewer Features proposal aims to make Matrix bridges work better with other platforms. Currently, it is hard for clients and Matrix users to know if what they send in a bridged room will be supported or not. The goal of Fewer Features is to let bridges communicate which Matrix features are supported on the external platform. Then, clients and bots can change how they act based on what the external platform supports. | ||
|
||
In a nutshell, bridges can set a state event that says which Matrix features are discouraged or disallowed in this room. Clients and bots can use this information to disable features, change UI elements, or change the way events are sent. This will give the best possible experience to people on the other side of the bridge. It will also reassure Matrix users that their actions are working properly, because incompatible actions simply cannot be sent. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lines should be wrapped to 120 characters at most
#### `reactions_per_event` | ||
|
||
This is the number of reactions that each Matrix user can add to each event. (If the key is not specified, there is no limit.) | ||
|
||
Once the limit is reached for a user on an event, clients must either: | ||
|
||
* disallow further reactions | ||
* OR automatically remove the existing reaction, then add the newly chosen reaction |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not completely sure if this is a good idea or not. There are several networks that only allow one reaction per message, but my bridges already handle that by automatically redacting the previous reaction. If the client were to do the redaction, then the bridge would bridge that removal over to the remote network first, instead of just making a single API call to replace the reaction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are several networks that only allow one reaction per message, but my bridges already handle that by automatically redacting the previous reaction.
That's a smart idea for handling it, nice!
I'm not completely sure if this is a good idea or not.
As far as I'm aware, our choices are:
- Assume all bridge developers thought of this idea and implemented it in their bridge, and so remove
reactions_per_event
from the proposal because it isn't needed - Assume some bridge developers didn't think of this idea or weren't able to implement it, and keep
reactions_per_event
to be used by bridges that can't handle this situation themselves - Keep
reactions_per_event
anyway so that some clients can provide graphical feedback
Do you have a favourite choice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there was a way to say "limited to X reactions, but the bridge will redact the previous one automatically" it would accurately represent what happens now, but I'm not sure if that's actually useful to clients. I guess clients could have a "local echo" type thing where they hide the previous reaction locally immediately rather than waiting for the redaction? That would provide the best UX in the happy path, but would cause weirdness if the bridge fails to do the redaction for whatever reason.
Other than that, might be fine to keep it around even if it's not used
#### `reactions_per_event` | ||
|
||
This is the number of reactions that each Matrix user can add to each event. (If the key is not specified, there is no limit.) | ||
|
||
Once the limit is reached for a user on an event, clients must either: | ||
|
||
* disallow further reactions | ||
* OR automatically remove the existing reaction, then add the newly chosen reaction |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another thing this reminded me of: Telegram allows 3 reactions for premium users and 1 reaction for normal users. Some platforms also have per-user limits for things like file size and message length. I think it's fine not to solve such cases here, but should probably be noted in potential issues.
|
||
This means the external platform doesn't support redacting events. | ||
|
||
To comply with personal data laws, clients MUST still allow the user to redact the event on Matrix-side, but must inform the user it will still be visible on the external platform. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clients MUST still allow the user to redact the event on Matrix-side
I'm not sure if the spec is allowed to have such strong wording about client UI, SHOULD
would probably be more appropriate. Also, rooms can already prevent users from redacting messages by setting the m.room.redaction
event power level to non-default value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, rooms can already prevent users from redacting messages by setting the
m.room.redaction
event power level to non-default value.
Rooms can prevent users redacting their own events?? I can't believe Matrix allows that. I'll update my proposal to not have that assumption.
#### `replace` | ||
|
||
This affects the [event replacements](https://spec.matrix.org/v1.9/client-server-api/#event-replacements) section of the spec. | ||
|
||
This means the external platform doesn't support edits. It is unlikely that clients can generate a suitable fallback for edits, as the original event will remain unchanged in chat, and it will be difficult for external users to see the difference unless the client's `formatted_body` fallback uses a diffing algorithm between old and new (the spec does not recommend this). If the feature is Substituted, clients might choose to disable it unless they have really good `formatted_body`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just remembered another type of limit that many other networks have: maximum number of edits and maximum time after sending that message can be edited. Similarly, redactions also have a time limit on some networks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Beeper is planning on using a different format, which is documented at https://github.com/mautrix/go/blob/main/event/capabilities.d.ts
Notable differences:
- Each file message type is handled separately, with allowed mime types listed
- Formatted text is split into features to allow signaling exactly what's supported
- Levels range from -2 to 2 instead of -3 to 0
Rendered
This is hopefully a progression from Poorer Features. Please let me know if I'm on the right track here or if I'm barking up the wrong tree.
Signed-off-by: Cadence Ember [email protected]