MSC: Sending events as a server or room

travis/msc/send-as-server-or-room
Travis Ralston 9 months ago
parent 2a73041f06
commit 65066444f1

@ -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.
Loading…
Cancel
Save