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

MSC3761: State event change control #3761

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

turt2live
Copy link
Member

Rendered

Draft because of TODOs, but general concept should be there.

@turt2live turt2live changed the title MSC: State event change control MSC3761: State event change control Mar 31, 2022
@turt2live turt2live added requires-room-version An idea which will require a bump in room version proposal A matrix spec change proposal unassigned-room-version Remove this label when things get versioned. 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 Mar 31, 2022
Copy link
Member Author

@turt2live turt2live left a comment

Choose a reason for hiding this comment

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

documenting comments from internal review (anonymized/summarized where context is sensitive)

Additionally, anyone who can normally redact a (state) event can *always* redact the ACL'd state event and the ACL
event itself.

Only events which are **not** included in `auth_events` can be ACL'd. This means that ACL events cannot be ACL'd,
Copy link
Member Author

Choose a reason for hiding this comment

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

I don't quite understand what this line is trying to say. Which event are we talking about when we reference auth_events here?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's trying to say that you can't apply ACLs to membership events, power level events, etc: the things that are required for inclusion in auth_events on any event.

All other state, like topic changes, beacons, and other custom stuff would be ACL-able.

Copy link
Member

@dkasak dkasak Apr 1, 2022

Choose a reason for hiding this comment

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

(Gah, I accidentally deleted my own review comment due to Github's sucky UX, so reposting.)

Suggested wording:

ACLs can be set on all state events **except** [authorization
events](https://spec.matrix.org/v1.2/rooms/v9/#authorization-rules).

Copy link
Member Author

Choose a reason for hiding this comment

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

The m.event.acl event is included in authorization events though, so should already be covered.

(also, why v2?)

Copy link
Member

Choose a reason for hiding this comment

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

Ah, good point. And the v2 was just an accident, edited accordingly.

target state event, the event cannot be sent. Similarly, if the ACL event ID is not able to be located, the event
cannot be sent.

***TODO: Should the state event be rejected if the ACL event ID cannot be resolved, or just treat it as an ACL of "no one"?***
Copy link
Member Author

Choose a reason for hiding this comment

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

This may splitbrain the room if another homeserver does end up resolving the event ID?

Copy link
Member Author

Choose a reason for hiding this comment

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

it'd be similar to the server missing the power level event during auth, I think.


To apply this ACL to a state event, the sender would include an `?acl=$event_id_of_acl` query parameter to
[`PUT /state/:type/:key`](https://spec.matrix.org/v1.2/client-server-api/#put_matrixclientv3roomsroomidstateeventtypestatekey)
which denotes the ACL event to apply to the to-be-sent state event. If the sender fails the existing ACL on the
Copy link
Member Author

Choose a reason for hiding this comment

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

There was discussion around race conditions and someone being able to apply ACLs before you get a chance to. Particularly if someone maliciously wants to take over the event type + state key tuple they could send their event at the same time or earlier than you, making the ACL questionable and potentially not apply.

I think this would be fixed by state resolution which will pick a "correct" event in the case of conflict, and if someone is racing to claim a state key before you then it's a bit of a social/room moderation problem moreso than tech. If someone were to be maliciously trying to claim location beacons (for example) then that might not be a room you want to be a member of.

That said, we should consider a case where a state event can be sent by PL0 people and thus lead to further (social) conflict.


## Proposal

We introduce a new state event called `m.event.acl` with a `content` which looks as follows:
Copy link
Contributor

Choose a reason for hiding this comment

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

To me, the way that this event is defined as a state event (as opposed to a regular event) is "weird".

Down below the state event is specifically mentioned by ID, as opposed to relied on when defining the event. That's understandable, considering that you'd essentially "pick the rules" when posting an event like this.

However, via this method, one would spew a bunch of nonsensical m.event.acl events as state in a room, while they may not be useful as a state event in that room thereafter.

This to me looks a lot more reasonable as a normal event. However, I can imagine why it wasn't chosen as thus, due to retention policies potentially evicting and removing this event, as it is no state event.

This way, this detail just strikes me as "weird", though not "wrong". I'd like to know if my suspicions and musings regarding this are correct.

Copy link
Contributor

@ShadowJonathan ShadowJonathan Mar 31, 2022

Choose a reason for hiding this comment

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

Reading the other comments, I get the feeling that my initial assessment of "picking and choosing" ACLs wasn't initially correct, though to me it doesn't make much sense to have it any other way; If i were to have 3 different events, and all three of them would have different ACL rules, why would they all adhere to one specific ACL event?

Copy link
Member Author

Choose a reason for hiding this comment

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

It was picked as a state event so the server is reasonably assured to get it as part of event authorization: authorizing an event against a non-state event means taking a harder path to locate the event.

Plus, with it being a state event we inherit the permissions structure of most rooms where regular members can't send them, preventing spam. A notable exception is in the MSC where someone can specify their own ACL event, but this is a future-proof optimization for if/when we want to apply ACLs to non-state too. Worst case is you end up with double the state events (1 for each member, 1 for each member's personal ACL).

Comment on lines +75 to +76
Additionally, anyone who can normally redact a (state) event can *always* redact the ACL'd state event and the ACL
event itself.
Copy link
Member

Choose a reason for hiding this comment

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

What is the intended effect of such a redaction?

Copy link
Member Author

Choose a reason for hiding this comment

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

Moderation and anti-spam.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, I just realized I'm only talking about part of that sentence and was not explicit enough.

I'm only asking about the redaction of the ACL event itself. The intent is not that the redaction should neutralize the ACL's rules, right?

Copy link
Member Author

Choose a reason for hiding this comment

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

potentially. It's not really been worked out what will be protected from redaction and what won't.

Copy link
Member

Choose a reason for hiding this comment

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

It sounds like redactions should not have the ability to neutralize the ACL. Otherwise the example for with_power_for is useless since that power is always available to people who can redact things given they could always just redact (and therefore neutralize) the ACL.

Comment on lines +50 to +73
To apply this ACL to a state event, the sender would include an `?acl=$event_id_of_acl` query parameter to
[`PUT /state/:type/:key`](https://spec.matrix.org/v1.2/client-server-api/#put_matrixclientv3roomsroomidstateeventtypestatekey)
which denotes the ACL event to apply to the to-be-sent state event. If the sender fails the existing ACL on the
target state event, the event cannot be sent. Similarly, if the ACL event ID is not able to be located, the event
cannot be sent.

***TODO: Should the state event be rejected if the ACL event ID cannot be resolved, or just treat it as an ACL of "no one"?***

The ACL event ID is then appended to the top level of the state event as `acl`:

```json5
{
"type": "org.example.event",
"state_key": "whatever",
"acl": "$abcdef",
"content": {
// event-specific detail
},
// etc
}
```

Changes to that state event, including the removal of the ACL event ID from the event (by not sending an `?acl` on
subsequent `PUT`s), must include the ACL event which allows the change in its `auth_events`.
Copy link
Member

Choose a reason for hiding this comment

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

The mechanism of use and rules relating to this new event are quite convoluted. I may be missing something, but why does this need to be a separate event at all, as opposed to embedding the ACL content directly under the acl key of the actual ACL-ed state event?

I guess the primary problem is that we have no nice way of passing an additional JSON object to the current API, besides the content. Still, all of this feels very race condition-y to me and I would encourage us to try finding a way of embedding the ACL content directly when sending a state event instead of making it a separate state event.

Copy link
Member Author

Choose a reason for hiding this comment

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

We lose the ability to have reusable ACLs though, which leads to data duplication :(

Copy link
Member

Choose a reason for hiding this comment

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

That's a valid concern, though the finickiness (and potential for unforeseen problems) with the current approach seem worse. It should be noted that state events are relatively rare compared to non-state events and we're already faring quite a bit worse there with respect to redundancy.

I'm also having trouble imagining how this ACL reuse would work from a client's POV. Let's say I decide to place an ACL on a new event and I have previously already sent an equivalent ACL to the room. How would I learn that this ACL is already available in the state?

I guess I would have to fetch all of my m.event.acl events in the room, then iterate through them in search for an equivalent one to the one I'm planning on setting right now. That seems rather error-prone.

Copy link

@gleachkr gleachkr Apr 3, 2022

Choose a reason for hiding this comment

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

It would be nice, as a client author, to be able to do something like m.peer_unwritable or something under acl to handle a common usecase - basically have a few basic ACLS baked in.

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 with @dkasak here. This seems finnicky, and having to add new stuff to auth_events is really scary.

@@ -0,0 +1,97 @@
# MSC3761: State event change control
Copy link
Contributor

@MTRNord MTRNord Apr 2, 2022

Choose a reason for hiding this comment

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

This comment exists to point out an additional usecase where this would help (as I assume not many will be aware of this?):

Matrix-Art could highly benefit from this.

The usecase is that MatrixArt is using a Folder structure based upon MSC3089 for the user directory per instance.

The thing is that any user needs to be able to add the child spaces to it to reflect their own profiles. However, as of today, there is no way to protect against User A removing the room from User B from that space. This MSC most likely will be able to protect against this. Explicitly, I would need it to restrict the event edits to their own Rooms instead of modifying the space child states of every user.

@@ -0,0 +1,97 @@
# MSC3761: State event change control

Copy link
Member

Choose a reason for hiding this comment

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

I don't really like this proposal. It feels like this functionality should exist in the power levels event, and the fact that it doesn't complicates things. Any kind of server-enforced check means modification to auth rules. This can't live in the PL event currently because this MSC is allowing random users to assign arbitrary ACLs to random sets of state events, which seem to just be given on a first-come first-serve basis. This also has problems.

Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

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

generally this feels like it is going to be tricky to get right, and I'm yet to be convinced it solves the problems at hand.

Comment on lines +45 to +48
The ability to send this ACL event would still be subject to power levels, except in the special case where the
sender uses a `state_key` of their own user ID: this bypasses the `events["m.event.acl"]` power level check,
allowing the user to define a single ACL for their state events. If they want multiple ACLs, they will need
permission to do so.
Copy link
Member

Choose a reason for hiding this comment

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

this "exception" (allowing @alice:example.com to send an event withstate_key: @alice:example.com) would be specific to events of type: m.event.acl, correct?

Copy link
Member

Choose a reason for hiding this comment

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

it would be good to clarify how this interacts with events_default and state_default, but note that this implies there is no way to stop people sending such events in a room, even if that room is supposedly locked down with a high events_default.

Comment on lines +50 to +73
To apply this ACL to a state event, the sender would include an `?acl=$event_id_of_acl` query parameter to
[`PUT /state/:type/:key`](https://spec.matrix.org/v1.2/client-server-api/#put_matrixclientv3roomsroomidstateeventtypestatekey)
which denotes the ACL event to apply to the to-be-sent state event. If the sender fails the existing ACL on the
target state event, the event cannot be sent. Similarly, if the ACL event ID is not able to be located, the event
cannot be sent.

***TODO: Should the state event be rejected if the ACL event ID cannot be resolved, or just treat it as an ACL of "no one"?***

The ACL event ID is then appended to the top level of the state event as `acl`:

```json5
{
"type": "org.example.event",
"state_key": "whatever",
"acl": "$abcdef",
"content": {
// event-specific detail
},
// etc
}
```

Changes to that state event, including the removal of the ACL event ID from the event (by not sending an `?acl` on
subsequent `PUT`s), must include the ACL event which allows the change in its `auth_events`.
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 with @dkasak here. This seems finnicky, and having to add new stuff to auth_events is really scary.

{
"type": "org.example.event",
"state_key": "whatever",
"acl": "$abcdef",
Copy link
Member

Choose a reason for hiding this comment

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

to be explicit: is this key redacted when the event is redacted? If so, I think that leaves us with an event that may not be valid (because there is no longer an acl allowing its change)?

Comment on lines +72 to +73
Changes to that state event, including the removal of the ACL event ID from the event (by not sending an `?acl` on
subsequent `PUT`s), must include the ACL event which allows the change in its `auth_events`.
Copy link
Member

Choose a reason for hiding this comment

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

to be clear: the original event doesn't need an m.event.acl in its auth_events (just a reference to it in the event body), but subsequent changes do require it in the auth events?

er, why?

@turt2live
Copy link
Member Author

This MSC and any updates to it are blocked on MSC3672 defining the actual problems in more detail - this MSC appears to be premature for what was intended.

@turt2live turt2live added the blocked Something needs to be done before action can be taken on this PR/issue. label Apr 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked Something needs to be done before action can be taken on this PR/issue. 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 requires-room-version An idea which will require a bump in room version unassigned-room-version Remove this label when things get versioned.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants