-
Notifications
You must be signed in to change notification settings - Fork 399
MSC4049: Sending events as a server or room #4049
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
Draft
turt2live
wants to merge
1
commit into
main
Choose a base branch
from
travis/msc/send-as-server-or-room
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
# MSC4049: Sending events as a server or room | ||
|
||
Matrix rooms operate off a principle where only users can send events, and thus only users can change | ||
settings (state events) or send messages as themselves. When a server wants to make changes in a room | ||
on behalf of users, that server needs to "impersonate" or otherwise puppet a user account it controls | ||
in the room. While technically feasible, the approach is often disagreeable from (at minimum) a privacy | ||
perspective. | ||
|
||
A server might want to send an event without associated user when a user is not semantically responsible | ||
for the event. For example: | ||
|
||
* Keeping the `via` list for an [`m.space.child`](https://spec.matrix.org/v1.7/client-server-api/#mspacechild) | ||
event updated. | ||
* Replacing the functionality of a [system alerts](https://spec.matrix.org/v1.7/client-server-api/#server-notices) | ||
room. ie: not occupying a [phishy user ID](https://github.com/vector-im/element-meta/issues/1759). | ||
* Populating a [policy room](https://spec.matrix.org/v1.7/client-server-api/#moderation-policy-lists) | ||
with rules as the entity, avoiding occupying/puppeting a user ID. ie: when matrix.org publishes changes | ||
to its code of conduct or terms of service policy rooms, it intends to do so as matrix.org, but due to | ||
limitations with how events work it sends as `@abuse:matrix.org` instead. | ||
* Other abuse-related notifications, such as a message to a room that they are potentially breaking | ||
the terms of service. | ||
|
||
Sending as a server might be relatively rare, but a more common feature would be to send events as | ||
a room or space. For example, in announcement rooms where the sender might not want to take personal | ||
credit for the message, as they might be sending it on behalf of a company or community. Doing so | ||
protects the identity of the sender, preventing bombardment of DMs/questions being sent to an individual. | ||
|
||
Being able to send as a room is popular in announcement-only channels/rooms on other messaging platforms | ||
such as Telegram. In Matrix, we can already have read-only rooms, but cannot hide the sender's identity. | ||
A related feature is being able to hide the membership list of the room from other users - this is | ||
specifically out of scope for this MSC, though possible with MSCs like [MSC4047](https://github.com/matrix-org/matrix-spec-proposals/pull/4047). | ||
|
||
This proposal adapts the `sender` field of an event through a future room version, permitting non-user | ||
ID values to be used, provided that entity has appropriate permissions. | ||
|
||
Dependencies: | ||
* [MSC4047](https://github.com/matrix-org/matrix-spec-proposals/pull/4047) | ||
* Depends on [MSC4046](https://github.com/matrix-org/matrix-spec-proposals/pull/4046) | ||
|
||
## Proposal | ||
|
||
*This MSC is done entirely in context of a future room version, due to event format, event auth, | ||
and redaction algorithm changes.* | ||
|
||
There are two conditions which describe a legal `sender` for an event: | ||
|
||
1. Membership in the room. | ||
2. Power level in the room. | ||
|
||
For user-based senders this should hopefully be very familiar. A user which is joined to the room and | ||
has enough power level can typically send events. With this MSC we extend `sender` to additionally be | ||
a server name or room ID though, making these conditions slightly harder to reason about. | ||
|
||
### Membership | ||
|
||
Servers already have a notion of "participation" within a room: if they have at least 1 user which is | ||
joined to the room, the server is participating in that room. We use this same definition to satisfy | ||
the membership condition for servers-as-`sender`. | ||
|
||
Rooms being members of a room is difficult to think about, but luckily we have a parent/child relationship | ||
structure we can base our work off of: [spaces](https://spec.matrix.org/v1.7/client-server-api/#spaces). | ||
In essence, spaces allow for rooms to be listed as children (read: members) of a room. Such a structure | ||
is ideal when the message is intended to be visually sent by a parent space. For example, the "AliceChat" | ||
space contains an "AliceChat Desktop News" announcement room - not only will users want to send as the | ||
Desktop News room, but they'll want to send as the parent AliceChat space from time to time too. | ||
|
||
Using the `m.space.child` relationship doesn't work as a way to determine "membership" for rooms though. | ||
Event authorization operates exclusively within the target room, meaning it can't easily branch out to | ||
another room (the parent space) to see if the room is listed as a child. That also assumes the server | ||
evaluating the event even has visibility on the parent space room to begin with. Instead, we require | ||
the largely-unused [`m.space.parent`](https://spec.matrix.org/v1.7/client-server-api/#mspaceparent) state | ||
event to be specified within the target room. When a legal space parent is specified, the referenced room | ||
ID is considered "joined" to the room for purposes of the membership condition on `sender`. We also declare | ||
that a room is always "joined" to itself, allowing events to be sent as that room. | ||
|
||
To ban a server from sending further events, all of its users can be removed or it can be | ||
[ACL'd](https://spec.matrix.org/v1.8/server-server-api/#server-access-control-lists-acls) out of the room. | ||
|
||
To ban a room from sending further events, it's `m.space.parent` event is removed/made invalid in the room. | ||
Banning sending using the current room ID is done by revoking the "send key" (discussed later in this proposal). | ||
|
||
### Power levels | ||
|
||
#### Sending as server power levels | ||
|
||
With membership solved, the remaining condition is power levels. The protocol already supports a `users` | ||
and `users_default` structure in [`m.room.power_levels`](https://spec.matrix.org/v1.7/client-server-api/#mroompower_levels) | ||
for user ID senders, but `m.room.power_levels` obviously doesn't consider servers (or rooms) as senders. | ||
|
||
Sending as a server can be replicated by using the same `users` and `users_default` structure: | ||
|
||
* `servers` are the power levels for specific servers. It is an object keyed by server name with value | ||
of power level for that server. | ||
* `servers_default` is the default power level for any server not listed in `servers`, defaulting to | ||
zero itself. Unlike `users_default`, the room creator does *not* get any special treatment on this | ||
field. | ||
|
||
Both fields use the same integer requirements as the other power level fields, and are protected from | ||
redaction. See the "Security Considerations" section for why we don't inherit a server's permissions | ||
from its users' power levels. | ||
|
||
#### Sending as room power levels | ||
|
||
Sending as a room is more complicated, at least for power levels. We can't simply copy the structure | ||
we use for servers because that would allow anyone (literally anyone) to send an event as the room. | ||
Narrowing it down to using the origin server's power level doesn't work for 2 reasons: first, the | ||
protocol doesn't have a way to identify an origin when the `sender` is a room ID (a problem this MSC | ||
needs to solve anyways, and does later on), and second it doesn't actually prevent much. For example, | ||
if an announcement room for matrix.org were to be set up, it would be natural to allow matrix.org to | ||
post as its own room. However, seeing as how matrix.org is also a large public server, any random user | ||
could create official-looking news in the room. | ||
|
||
We can keep trying to narrow it down by saying there's a `sender_user_id` field next to `sender`, but | ||
then we're violating one of the principles covered in this MSC's introduction: we deliberately do not | ||
want to know which user sent an event when it is sent as another entity. | ||
|
||
*Author's note: this area of the MSC in particular could do with input/ideas. It's more WIP than proposal.* | ||
|
||
##### Option 1: Send keys | ||
|
||
To solve the issue of not being able to find a sender we can authenticate against, we use a simple | ||
public/private key pair, as described by [MSC4047](https://github.com/matrix-org/matrix-spec-proposals/pull/4047). | ||
|
||
We can then mirror `servers` and `servers_default` for send keys as `send_keys` and `send_keys_default` | ||
in `m.room.power_levels`. Events which have a room ID as their `sender` must use a send key, and the | ||
power levels associated with that send key determine what events it can send. The highest privileged | ||
send key is used for auth rules, if multiple send keys were used to send the event. | ||
|
||
##### Option 2: ??? | ||
|
||
*This is where more ideas are welcome.* | ||
|
||
### `/send` API changes | ||
|
||
The remaining ability is for an entity, usually a client, to send an event with a server or room ID | ||
`sender`. This proposal expects that servers-as-senders will be more common with internal tooling and | ||
so expects that vendor-specific APIs will be used in that case. For sending as a room though, the client | ||
or entity with the send key can use [MSC4047](https://github.com/matrix-org/matrix-spec-proposals/pull/4047)'s | ||
`/send_pdu` client-server API endpoint to modify the `sender`. | ||
|
||
### Full diff: Event authorization | ||
|
||
**TODO**: This section. Need a rule to describe how the power level semantics work, and `m.space.parent` becomes | ||
an auth event. | ||
|
||
### Full diff: Redaction algorithm | ||
|
||
**TODO**: This section. Ensure new power level properties are not redacted. `m.space.parent` might also need | ||
protecting in some way as it becomes an auth event. | ||
|
||
### Examples and test vectors | ||
|
||
**TODO**: This section. | ||
|
||
## Potential issues | ||
|
||
**TODO**: This section. Cover whether `m.room.member` can have non-user ID senders/state keys. Cover that only | ||
PDUs are affected by this proposal (not to-device messages or other ephemeral events). | ||
|
||
## Alternatives | ||
|
||
Alternatives are described inline where relevant. Structural alternatives are not currently identified. | ||
|
||
## Security considerations | ||
|
||
**TODO** This section. Primary questions to answer: | ||
|
||
1. Why not use the existing `users` power levels to determine a server name's power level? => Power escalation. | ||
2. Why not provide a CS API endpoint for sending as a server? => Power level defaults to zero, is easily abused. | ||
|
||
## Unstable prefix | ||
|
||
While this proposal is not incorporated into a stable room version, implementations should use `org.matrix.msc4049` | ||
as an unstable room version, using [MSC4047](https://github.com/matrix-org/matrix-spec-proposals/pull/4047) as a | ||
base. `sender` is not prefixed in this room version. | ||
|
||
## Dependencies | ||
|
||
As of writing, this MSC is being evaluated as a potential feature for use in the MIMI working group at the IETF | ||
through the Spec Core Team's efforts. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
seemingly I forgot to mention
m.room.create
: it needs to be sent by a user ID, not a server (or room, not that it can...) because it implies that servers create rooms when it's actually users who do. I don't think anything overly breaks if we were to allow it, but the semantic reasons justify banning (imo).