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

MSC4110: Fewer Features #4110

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

cloudrac3r
Copy link

@cloudrac3r cloudrac3r commented Feb 23, 2024

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 cadence@disroot.org

Comment on lines +60 to +63
* `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.
Copy link
Author

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?

Copy link
Contributor

@progval progval Mar 2, 2024

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.

Comment on lines +192 to +199
### 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.
Copy link
Author

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?

Copy link
Author

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.

Copy link
Member

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.

Copy link
Author

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.?

Copy link
Member

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.

@turt2live turt2live added proposal A matrix spec change proposal client-server Client-Server API kind:core MSC which is critical to the protocol's success needs-implementation This MSC does not have a qualifying implementation for the SCT to review. The MSC cannot enter FCP. labels Feb 23, 2024
@jooooscha
Copy link

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.

Copy link
Author

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?

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.

Copy link
Author

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.

Copy link
Contributor

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.

Copy link
Author

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": {
Copy link

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.

Copy link
Author

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.

Copy link
Contributor

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.

Copy link
Member

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.

Copy link
Author

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
Copy link
Contributor

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.

Copy link
Author

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...

Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor

@progval progval Mar 4, 2024

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.

Copy link
Member

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.

Copy link
Author

Choose a reason for hiding this comment

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

Sure, let's give it a try. @progval do you like the approach you took in MSC3969 (and do you want to continue it?) or do you think we should do it differently in Fewer Features?

Copy link
Contributor

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

Comment on lines +165 to +167
#### `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.
Copy link
Member

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
    }
  }
}

Comment on lines +129 to +131
#### `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.
Copy link
Member

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.

Comment on lines +97 to +115
#### `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.
Copy link
Member

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 🤔

Copy link
Author

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.
Copy link
Member

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

Comment on lines +169 to +176
#### `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
Copy link
Member

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.

Copy link
Author

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:

  1. 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
  2. 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
  3. Keep reactions_per_event anyway so that some clients can provide graphical feedback

Do you have a favourite choice?

Copy link
Member

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

Comment on lines +169 to +176
#### `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
Copy link
Member

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.
Copy link
Member

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.

Copy link
Author

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.

Comment on lines +83 to +87
#### `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`.
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
client-server Client-Server API kind:core MSC which is critical to the protocol's success needs-implementation This MSC does not have a qualifying implementation for the SCT to review. The MSC cannot enter FCP. proposal A matrix spec change proposal
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants