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

[WIP] MSC2812: Role-based power/permissions #2812

Draft
wants to merge 1 commit into
base: old_master
Choose a base branch
from

Conversation

turt2live
Copy link
Member

@turt2live turt2live added kind:feature MSC for not-core and not-maintenance stuff proposal A matrix spec change proposal labels Oct 8, 2020
which are matched against role IDs (state keys of `m.role` events). All 3 arrays default to empty, implying
that all related actions are denied. Arrays are ordered and are matched as first-allowed wins.

`m.change` denotes which roles a user in the applicable role will be able to modify the properties of.
Copy link

Choose a reason for hiding this comment

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

  1. Is this required to add roles? Ex, in the example m.roles above, would the user granted these permissions be able to create the role org.example.test?
  2. How is role creation abuse handled?

Copy link
Member Author

Choose a reason for hiding this comment

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

  1. Yes.
  2. Like with most things in Matrix, don't give people the power to do things you don't want them to do.

Adding/removing (changing) roles associated with a user is protected by a permission - see the proposed
permissions later in this proposal for more information.

### Default permissions structure
Copy link
Contributor

Choose a reason for hiding this comment

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

How about also adding a default role, maybe if the state key is m.default so that, if present, you can set different default permissions

proposals/2812-role-based-power.md Show resolved Hide resolved
proposals/2812-role-based-power.md Show resolved Hide resolved
are per [BCP47](https://tools.ietf.org/html/bcp47), with `en` being representative of English.

Roles are only required to have an English name. By default, a role has no permissions associated with
it. This can be used to simply categorize members of a role for easy identification rather than granting
Copy link

Choose a reason for hiding this comment

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

  1. IMO, the roles should only be required to have a name, regardless of language
  2. Maybe some state keys, like m.admin could have default names in the spec and could be exempt from having to insert m.name? It just seems awkward to have to add Administrator to the m.name in almost every language, considering that it's a default role...

Copy link
Contributor

Choose a reason for hiding this comment

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

Names reserved in the spec could be admin, default and moderator, just like it is currently with PLs (not sure if the PL thing is in the spec, but clients practically do that)

@@ -0,0 +1,375 @@
# MSC2812: Role-based power structures
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's interest in a tristate. #2812 (comment) needs unpacking.

Copy link
Contributor

Choose a reason for hiding this comment

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

What is tri-state:
Each permission gets three states: allow, deny, nothing
By default every permission has nothing. As it is not allowed, you don't have that permission. If a permission is allowed in one role, you have it, except if it is denied in another role.

Arguments against tri-state:
Additional complexity

Arguments in favour of tri-state:
It allows greater flexibility, for example giving someone a temporary "timeout" role. Example given:
I user is bad and the moderators give them a timeout role for 24h, which denies them to talk. Without tri-state, they would have to manually remove all existing roles and then add the timeout role, only to revert that after 24h.
Depending on how the default role should work (needs clarification, too) that might even be impossible as perhaps the default role would be impossible to un-assign.

Copy link
Member

Choose a reason for hiding this comment

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

IMO it should be implemented by specifying that permissions from roles are applied in some specific order (e.g. in the m.roles array order), and that new values override previous ones. That way it's tri-state of omit/allow/deny

Copy link

@Foxtrek64 Foxtrek64 Nov 22, 2020

Choose a reason for hiding this comment

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

There are two systems to consider here:

  • Ordered overrides, like what @tulir mentions. This would allow the last-most permission to take precedence.
  • Explicit deny wins. This is how Active Directory works, along with many other systems. (e.g. Discord). In this system, roles are cumulative and any m.deny values take precedence.

Pros of ordered overrides:

  1. Easy to bypass permissions

Cons of ordered overrides:

  1. Keeping track of how permissions are ordered becomes important. A mute role, for instance, would need to be manually bumped to the top any time any other roles are added or removed to ensure that they continue to be denied permission to send messages.

Considerations of ordered overrides:

  1. How weighted are overrides? If the send messages permission defaults to m.none or m.omit meaning they cannot send messages, does that override m.allow or does it act as though it's transparent even if it comes after?

Pros of explicit deny wins:

  1. Well-known. Many popular role-based systems use this.
  2. Easy to deny permissions. For example, if you have a muted role, you can place it on a user and guarantee they will not be able to send messages regardless of whatever other roles are added later.
  3. Allows for strong adherence to RBAC principles if this is important to the user.

Cons of explicit deny wins:

  1. You cannot override an explicit deny (though this is by design).

Considerations of explicit deny wins:

  1. m.none should be the default value.
  2. m.none should act as a soft deny when no explicit allow or deny is found. That is, if the send messages permission is m.none, then the user does not have permission to send messages.
  3. m.none should behave transparently (or effectively ignored) when explicit allow or deny permissions are found. That is, m.allow + m.none = m.allow, regardless of order.

Calculating permissions in explicit deny wins:

  1. Throw out all roles where permission has a value of m.none.
    • If no roles are left, result is deny. If roles remain, continue to step 2.
  2. Check for any roles where permission has a value of m.deny.
    • If any are found, result is deny. If none are found, continue to step 3.
  3. All remaining values should be m.allow. Result is allow.

Copy link

@erkinalp erkinalp Dec 23, 2020

Choose a reason for hiding this comment

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

  • Explicit deny wins. This is how Active Directory works, along with many other systems. (e.g. Discord). In this system, roles are cumulative and any m.deny values take precedence.

Correction: on Discord, explicit allow wins, not explicit deny.

Choose a reason for hiding this comment

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

How about having both? Like,
*m.allow immediately followed m.deny=m.none
*m.none immediately followed by m.deny=m.deny
*m.deny or m.none immediately followed by m.allow=m.allow,
*anything followed by m.none returns the preceding power state for the permission in question
collapsed in a left-to-right, left-associative manner.

Choose a reason for hiding this comment

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

How about having both? Like,
*m.allow immediately followed m.deny=m.none
*m.none immediately followed by m.deny=m.deny
*m.deny or m.none immediately followed by m.allow=m.allow,
*anything followed by m.none returns the preceding power state for the permission in question
collapsed in a left-to-right, left-associative manner.

Both is not a good option for this from two perspectives:

  1. It is overly-complex. Whatever option we take should be easily demonstrated by a truth table. This truth table should be simple to understand at a glance. With systems like "explicit deny wins," it's easy to understand the user's effective permissions. If you see a deny anywhere, then it's a deny. If you don't see a deny anywhere, but they have any allows, it's allowed. With a system where both are the case, I would almost need to pull out a permissions calculator or a pencil and paper to figure out a user's effective permissions.
  2. We don't need to reinvent the wheel. Most users who will be managing or administering permissions will come from doing so either in Active Directory or Discord. Among those and some other solutions, explicit deny wins is one of the most prevalent systems and the most widely understood. Explicit allow wins is a variation of that same system, but the fundamentals are mostly the same. We are not the first ones to be having this conversation. It may be prudent to look at not only what the others did, but look into their reasons why, and ultimately decide which of those we use based on what system matches best with our goals.

Also, to keep discussion focused, there are two pieces of a permissions system that we should look at here:

  1. How effective permissions for a single permission node are calculated (explicit deny/allow wins, weighted permissions, etc.)
  2. How permissions combine (additive, most restrictive, etc.).
    a. Additive: A user has two roles. One gives permissions to read a channel. One gives permissions to write in a channel. Effective permissions are Read/Write. Examples: File shares, Discord, Active Directory roles.
    b. Most restrictive: A user has two roles. One gives permissions to read a channel. One gives permissions to write in a channel. Effective permissions are Read. Examples: NTFS.

Personally, I would propose we use explicit deny wins with additive permissions. In this system, the effective permissions would be calculated like this:

  1. Iterate through each permission (e.g. channel.read).
    a. If any role denies the permission, effective permission is deny.
    b. If no explicit denies are found, any explicit allow means effective permission is allow.
    c. If no explicit denies or allows are found, effective permission is no permission (having no permission is treated the same as being denied permission, but is not enforced as a deny and can be overridden).
  2. Accumulate calculated permissions to build a new effective permission role. This role will be the one checked to see if a user has permission to perform a certain action.

Effective permissions would be calculated several times, once for global permissions and once for each channel, per user. Permissions calculations with this system are sufficiently fast, especially when adhering to standard RBAC practices. For instance, only granting the user the minimum permissions required to allow them use the channel.

Copy link

@erkinalp erkinalp Feb 1, 2021

Choose a reason for hiding this comment

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

Whatever option we take should be easily demonstrated by a truth table. With a system where both are the case, I would almost need to pull out a permissions calculator or a pencil and paper to figure out a user's effective permissions.

This is your truth table (non-commutative, non-alternative):

allow·allow = allow
allow·neutral = allow
allow·deny = neutral
neutral·allow = allow
neutral·neutral = neutral
neutral·deny = deny
deny·allow = allow
deny·neutral = deny
deny·deny = deny

It is very easy to combine those, left-to-right. First, you combine 1st and 2nd term, then the result of this with the 3rd term, then with the 4th term and so on. Specificity appendments (not overwrites) would be handled the same way: first, combine the two most generic terms, then the result of this with the 3rd most generic term, and so on.

We don't need to reinvent the wheel. Most users who will be managing or administering permissions will come from doing so either in Active Directory or Discord. Among those and some other solutions, explicit deny wins is one of the most prevalent systems and the most widely understood. Explicit allow wins is a variation of that same system, but the fundamentals are mostly the same. We are not the first ones to be having this conversation. It may be prudent to look at not only what the others did, but look into their reasons why, and ultimately decide which of those we use based on what system matches best with our goals.

My consideration was clients and servers with low memory and primitive processors. The currently proposed system requires an n-operand operation. My proposal, on the other hand, only requires chained two-operand calculations. Moreover, my proposal simplifies power updates, as it allows append-only updates (any permission changes will not overwrite, but append to previous permission declarations of the same level).

Choose a reason for hiding this comment

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

Your suggestion assumes that roles would exist in a hierarchy or somehow be ordered. If that's the case, then that works, but now I have to be careful about how I order my roles and would need to be cognizant of their relationship to each other in this hierarchy.

Also, there is an issue with your truth table that makes things complicated for administrators. Let's say I am a member, so I have a few roles but ultimately my permission to speak is allow. As a punishment for breaking the rules, I get muted. So I get the mute role applied to me, which has speak set to deny. My effective permission is now neutral which depending on context could mean anything. If neutral allows me to speak, then this mute role becomes useless. I'd have to have two mute roles so my permission calculation becomes this:

allow + deny = neutral. Result: can (still) speak.
neutral + deny = deny. Result: cannot speak.

This becomes rather cumbersome to maintain. If I outright deny a permission, then that permission should be outright denied, regardless of whatever other permissions they have. There should be sane defaults here (such as a neutral result/no permissions meaning cannot speak), however if this sane default means that no permissions is equivalent to an allow state, then we run into the same issue above when denying that permission.

Explicit deny win calculations work extremely well for slower/older machines too, since there are only three steps:

  1. If there are any denies, permission is deny.
  2. If there are any allows, permission is allowed.
  3. Otherwise, permission is neutral/no permissions.

These operations can short circuit as well. If there are any denies, then it doesn't need to check if there are any allows. At worst, the speed of this is O(n) where n is the number of roles the user has. It can potentially faster than this though. Here is some sample code I've written in C#:

bool hasAllow = false;

foreach (var role in user.Roles)
{
    if (role.Permission == Permission.Deny)
        return Permission.Deny; // Stop iterating, return deny immediately.

    if (role.Permission == Permission.Allow)
        hasAllow = true;
}

// If allow was found
return hasAllow ? Permission.Allow : Permission.Neutral;

The slowest piece of this code is iterating through the user's role collection. However, any proposal would have us do the same so I don't feel this is a big concession. This might be improved some, performance-wise, but it should be pretty fast as is. Also, this code is hierarchy-agnostic, meaning it'll function regardless of whether the roles exist in a hierarchical structure or are all equivalent (think Discord vs Active Directory).

As an added benefit, this code is very simple, meaning it can be easily understood at a glance and can therefore be easily maintained and diagnosed should something go wrong.

Choose a reason for hiding this comment

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

@Foxtrek64 Thanks for your input. I am now preparing a new MSC with those suggestions applied, as Travis said it diverged from this proposal so much that it should be discussed separately.

@squarepupil
Copy link

As far as I understand it, this proposal for role-based permissions would be similar to the current power level system in that it only defines permissions in a single given room at a time.

I am not savvy enough to answer this question by my own research, but would this proposal be flexible enough in its implementation to be expanded upon to create a multi-room role system? Such a system would allow for unified roles and permissions for a whole community/group (not sure the preferred nomenclature at this point) or homeserver, for example, which I think is an important feature as it mirrors real-life community (peoples' identities and privileges carry over from place to place within a given community). I could see some potential messiness with this approach (for example, if a single room was part of two separate communities), but I think it's an important feature that would be needed if the Discord crowd, among others, is to switch to Matrix.

@turt2live
Copy link
Member Author

@squarepupil that all would be explicitly out of scope of this whole MSC - the communities MSC would have to figure out how roles work, but may very well use this MSC as a base.

@Sorunome Sorunome mentioned this pull request Nov 4, 2020
@erkinalp

This comment has been minimized.

Currently Matrix operates off a power level structure where higher numbers have more power in a
room and lower numbers (with zero being a typical default) have the least power. This structure
can be used to represent a number of systems and can allow for a form of roles (moderator, admin,
etc) to be represented, though can be challenging to bridge to other platforms.
Copy link
Member

Choose a reason for hiding this comment

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

I have yet to ever come up against the need to use roles in native Matrix. To try to gauge how to prioritise the MSC, it'd be really useful to have a real life bridging example - i.e. of a permissions bridge that can't be represented in Matrix today.

Copy link
Member Author

Choose a reason for hiding this comment

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

Discord is the largest example, though this needs to be codified into the MSC properly.

Other examples (which imo are weaker arguments) are familiarity and ease of use - trying to do the mental math for whether or not you're about to give someone the power to destroy the room is often times difficult or requires a notepad (when trying to do non-standard, complex, things).

Copy link
Member

@tulir tulir Nov 10, 2020

Choose a reason for hiding this comment

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

Telegram is a less obvious example, but their permissions are also not linear. There are 6 admin permissions (change group info, delete messages, ban users, add users, pin messages, add new admins) and they can be set completely arbitrarily for each user.

Right now it's impossible to bridge permissions. With this proposal, the permissions could be bridged, although the bridge would need to invent a role name for every combination.

Choose a reason for hiding this comment

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

Discord's permission system is a patchwork, though. Its role hierarchy is bolted-on, the override ordering is only partially intuitive (some orderings are additive, some are hierarchical).

Choose a reason for hiding this comment

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

This could also attract business users - being able to tightly couple roles in Matrix to groups in Active Directory. Not applicable to everyone, but if businesses are looking to replace Teams (because it's a dreadful mess) this may be the feature that convinces them to switch.

Copy link
Contributor

Choose a reason for hiding this comment

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

Soru thinks most real-life examples come when you combine role-based permissions with spaces, so that the same roles gouvern all rooms in that space.

Choose a reason for hiding this comment

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

Soru thinks most real-life examples come when you combine role-based permissions with spaces, so that the same roles gouvern all rooms in that space.

While this is likely the end goal, it's outside of the scope for this specific change. A separate proposal for allowing this was being drafted but I'm not sure the status of that.

Copy link
Member Author

Choose a reason for hiding this comment

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

in random exploration there's a potential use case in virtual worlds where objects need dynamic ownership - power levels could be used for this, but scale might become a concern if too many things are trying to update power levels at once. Equally, granting power levels would mean granting permission to the whole world, which might not be desirable (unless we use objects as rooms? That feels a bit wasteful at first glance though)

* If the user's membership is not `join`, the user does not have any permissions.
* For each role ID defined by the `m.roles` array (default empty, ordered) on the user's membership event:
* If there is no associated `m.role` state event in the room, skip.
* If the `m.role` state event does not have an English name, skip.
Copy link

@erkinalp erkinalp Nov 10, 2020

Choose a reason for hiding this comment

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

Remove this requirement and derive an algorithmic fallback name in the form of "can do this, cannot do that" using permission metadata instead.

Suggested change
* If the `m.role` state event does not have an English name, skip.


For authorizing events themselves:

***TODO - This needs defining***

This comment was marked as resolved.


### Expected server behaviour for profile/membership changes

***TODO - This needs defining***

This comment was marked as resolved.

Comment on lines +43 to +49
which may be interested, such as (in the example) a colour to represent the role. Role names have
translation support, and must at least have an English definition for consistency reasons. Language codes
are per [BCP47](https://tools.ietf.org/html/bcp47), with `en` being representative of English.

Roles are only required to have an English name. By default, a role has no permissions associated with
it. This can be used to simply categorize members of a role for easy identification rather than granting
them any specific power - such examples may be wanting to identify supporters of a project within a room.

This comment was marked as resolved.

Copy link

@erkinalp erkinalp left a comment

Choose a reason for hiding this comment

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

Have an implicit top role T instead of an auto-created role m.admin

Comment on lines +92 to +95
Upon creation of a room, the server creates a default `m.role` state event with state key `m.admin`.
This role consists of all permissions being granted as per each permission's specification. This
role is automatically assigned to the room creator when they join for the first time, and the
authorization rules will be modified to allow this.

This comment was marked as resolved.

Comment on lines +130 to +131
This uses the common permission format and is **disallowed** by default. When the server creates the `m.admin`
role, this would be explicitly set to allowed.

This comment was marked as resolved.

Comment on lines +137 to +138
This uses the common permission format and is **disallowed** by default. When the server creates the `m.admin`
role, this would be explicitly set to allowed.

This comment was marked as resolved.

Comment on lines +144 to +145
This uses the common permission format and is **disallowed** by default. When the server creates the `m.admin`
role, this would be explicitly set to allowed.

This comment was marked as resolved.

Comment on lines +166 to +167
the server creates the `m.admin` role, this would be explicitly set to `["*"]` to denote that anyone
may have their messages redacted by users in the applicable role.

This comment was marked as resolved.

empty, an implicit deny rule of `{"type": "*", "m.allowed": false}` is present. This is to ensure that
announcement-only rooms can be created by simply specifying `"m.room": []`.

When the server creates the default `m.admin` role, the following permission body is to be used:

This comment was marked as resolved.

The key of the object is the notification kind (with `m.room` being the `@room` permission level), and the
value is whether or not the role allows it to be triggered. By default, all notifications are disallowed.

When the server creates the default `m.admin` role, the `m.room` permission must be set as `true`.

This comment was marked as resolved.

to *remove* from a user's `m.roles` array on their membership event. Users are still able to target themselves
here.

When the server is creating the default `m.admin` role, the following permission body is to be used:

This comment was marked as resolved.

Copy link

@erkinalp erkinalp left a comment

Choose a reason for hiding this comment

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

Role and user mentions

Comment on lines +224 to +231
```json
{
"m.room": true
}
```

The key of the object is the notification kind (with `m.room` being the `@room` permission level), and the
value is whether or not the role allows it to be triggered. By default, all notifications are disallowed.

This comment was marked as resolved.

@@ -0,0 +1,375 @@
# MSC2812: Role-based power structures
Copy link
Contributor

Choose a reason for hiding this comment

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

So, soru has been asked to comment on the concept of permission roles and why she personally thinks that
they are a good improvement over the current power level system. Please note that this comment is
about permission roles in general, and does not comment on specific implementations / forms that
this MSC take. Specific comments have already been made in the past.

Now, to start off, permission roles are more flexible. While power levels allow you to finely grain
how high a power you need to send which event, power levels do not allow to give different people
conflicting permissions: So one person should have permission A and not B, and another person should
have permission B and not A. Permission roles allows one to do that. Why that is good will be further
outlined below.

In sorus opinion permission roles only really start to shine when gouverning multiple rooms at once,
which is why she often mentioned them in the context of spaces. For just a single room, power levels
seem sufficient that there aren't really many cases where you need the extra flexibility that permission
roles give you. The idea is basically that you define the same permission roles which are valid across
the entire space, and then add members of the space to these roles, thus them taking affect throughout
rooms of the entire space. This of course does not solve #2962, it might even complicate it.

So, why is the added flexibility so good? It is sadly hard to pinpoint one big thing that just
objectively shows that this is needed. Instead, it seems like many small situations, which, while
they could be solved with a simple bot, adding permission roles would directly bake these mechanics
into matrix itself, removing the need of such a bot. Such scenarios are frequently found in e.g. safe
spaces: You want one group of people to have access to one room of your space, and another, partly
disjoint group of people, access to another room of your space, all while adhering to the same moderation
team, policies, etc. Or perhaps you want to have some people being allowed to invite people to the
space, but some other, partly disjoint, group of people have access to a room (Specific example: LGBTQ+
safespace with a trans room only for trans/enby folks).

There are often such kind of things where the extra flexibility is needed outside of safespaces, too.
@anoadragon453 talked about this permission system being helpful for DnD campaigns, for example:

We run regular DnD sessions. The DM wanted the ability to use Discord's Priority Speaker function,
which allows certain people to temporarily talk while lowering everyone else's mic. It's a pretty
useful function for when everyone's talking over each other in a session.

I just want to give them this exact role, but no other role in the room. At the same time I gave
another person the power to change people's nicks in the room, because it's funny. Because I don't
want to give them the ability to speak over everyone during a game.

#2962 actually already saw the need of something like permission roles: Access to a room is automatically
granted to people who are in a specific room. So.....#2962 kinda introduces permission-roles-as-rooms
already. Abstracting this to be general permission roles seems to make sense here, so that we unify
the two permission systems (power levels and room-access-by-being-in-a-room) into only a single
permission system.

Furthermore, most people want to give people a specific permission to do something. They don't want
to have to think about which power level they have to set which user to etc. So, they can just give
a role the permission "send a sticker" and add that user to the role, instead of setting "send sticker"
to PL 64, give the user that PL, notice that that also means they can now, uuuuuh, kick users from a
voice call, change the PL around again and then make it work. Of course good client UI can simplify
this problem, if the user does not try to configure something for which you need the greater flexibility
of permission roles.

Of course one has to think about how to make permission roles work well across an entire space, what
permissions there should be, if there should be room-level and/or user-level overrides (user-level-at
-room-level overrides?).

For the simple room where there is only really admin, moderator and everyone else needed, a set of
default roles, namely "default", "mod" and "admin" could be introduces, like, that the homeserver sets
those roles along with room creation or something. That way sophisticated admins can still change
everything they want, and "simple" users can still just set people to admin / moderator and then pick
which permissions are valid for them, if they do not like the default.

Copy link

@joepie91 joepie91 Mar 26, 2021

Choose a reason for hiding this comment

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

I'd actually like to bring up another argument for permission-based access control as a concept, that's potentially a much stronger argument for Matrix: permission-based access control is generic over nearly every other form of access control. That is, you can express every common access control mechanism using a sufficiently complete set of permissions.

This is especially important for Matrix due to bridging; it is currently often difficult to 1:1 map between Matrix's access control system and that of the bridged platform, since bridged platforms do not always have a strictly linear access control system. Subtly tweaking the powerlevel system could only solve this issue for specific other access control systems.

Permissions would resolve this by making arbitrary other access control systems representable, at the potential cost of some state event size overhead, as the permission-based representation can get pretty expansive for complex access systems - you'd essentially be 'unpacking' or 'evaluating' the other platform's access control algorithm into a full set of individual permissions.

This of course does not solve #2962, it might even complicate it.

The alternative proposal I'm working on (incomplete draft, MSC in progress), should be able to deal with a permission-based system just fine as far as I can tell.

Copy link
Contributor

Choose a reason for hiding this comment

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

I find the idea of "permission-roles-as-rooms" interesting and came to post that here: In light of #3083, it would be interesting to be able to specify for each permission, one (or more) rooms whose members would inherit the permission.

@JoshuaDietz
Copy link

Maybe it could make sense to just add all permissions of all roles (this would make the order arbitrary and reduce complexity) and then combine it with the Telegram approach of "restrictions" for specific users.

This would mean that roles just give permissions (which makes sense from a human standpoint - why should I have less permissions when I get another role?) and at the end some permissions can be restricted away with a restriction. This restriction can also contain a reason text. I.e. a user can be restricted of sending picture messages and the reason could be "You sent nsfw pictures. See our rules [link to the rules]".

This would also open a whole lot of opportunities. I.e. bots could automatically restrict new users from sending messages and add a reason with a link to the rules. Clicking this link and accepting the rules will then trigger the bot to lift the restrictions. Also then there is another reaction to rule violations then kicking/banning: A bot could restrict a user for a limited time (and maybe for a limited set of features) while also telling the user WHY he was restricted. Then the bot could lift the restiction again after some time. Alternatively the restriction could be given an expiry date.

@turt2live turt2live added the needs-implementation This MSC does not have a qualifying implementation for the SCT to review. The MSC cannot enter FCP. label Jun 8, 2021
@Foxtrek64
Copy link

This restriction can also contain a reason text

I don't think mixing moderation and permissions concepts in a single system is a good idea. This can be done in practice (e.g. if you are being unruly you get a muted role and a warning message from a moderator), but attaching a warning message to the muted role would mean potentially keeping track of every punishment separately. What you're describing would be more suitable for a moderation system which documents the user in question, the moderator, the infraction, and the action taken, where that action could be that they were muted or they were restricted from sending images.

This would mean that roles just give permissions (which makes sense from a human standpoint - why should I have less permissions when I get another role?) and at the end some permissions can be restricted away with a restriction.

I would argue that adding a role means permissions taken away would make sense from a human standpoint much in the same way that you can be given a speeding ticket and now be out something you weren't before.

This is where the tristate we were discussing earlier comes in. It allows you to do what you were proposing - removing permissions through restrictions - through the role system. So my mute role, for instance, could deny permissions to send messages, upload images, and add reactions, which could then be awarded to people (manually or through a bot or separate moderation system) through or as the result of an infraction.

Comment on lines +180 to +183
"m.room": [
{"type": "m.room.message", "m.allowed": true},
{"type": "*", "m.allowed": false}
]
Copy link

@Fox32 Fox32 Sep 28, 2022

Choose a reason for hiding this comment

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

How does this play together we e2ee? The server that is validating these room events would only see the m.room.encrypted, right? Meaning that this rule would deny sending any events, except unencrypted room messages?

Choose a reason for hiding this comment

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

I'm not sure I understand your question. I don't believe the role system would interact with e2ee at all. That is, they would be entirely unaware of each other.

You should only be sent events that are relevant to you. So if you have access to a room but not encrypted contents, you should simply not be sent events for when an encrypted message is sent, modified, or deleted. Likewise, you would not receive events for roles that you are not a member of. This isn't really a function of e2ee, but rather the eventing/messaging bus being efficient with network traffic and limiting unnecessary dispersal of information.

Copy link

Choose a reason for hiding this comment

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

I think my question was a bit confusing, sorry, I try to explain it better. I'm also not sure if I misunderstood something.

So for the whole proposed system, my expectation is that a homeserver is validating the permissions when sending events.

While e2ee is just a transport protocol detail, in this case I think it is relevant. As far as I understand e2ee, the original event (e.g. m.room.message) is wrapped inside a m.room.encrypted event. This means that the homeserver ia not seeing the type of the original event and being unable to enforce the permissions. At least not as a normal user thinks they are working?

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 proposal isn't the one to fix power levels with respect to event types in encrypted rooms - that's more likely to be done by #3842

The example here is for demonstrative (unencrypted) purposes, largely.

Copy link

Choose a reason for hiding this comment

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

Thanks for the pointer 👍

@ghost

This comment was marked as duplicate.

@@ -0,0 +1,375 @@
# MSC2812: Role-based power structures
Copy link
Member Author

Choose a reason for hiding this comment

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

@uranuspucksaxophone says:

I'm going to drop what I think here, ok?

I do like the power level system a lot, so I would like to propose a kind of hybrid model, merging both roles and power levels.

That would turn power levels into roles representations, for example, if we have the moderator role, we list it as power level 50 (the moderator role itself contains all of the actions that a moderator can do like ban, kick...), the same with an Admin (power 100) the only difference is that the Admin would have (by default) all possible actions and tools available.

We obviously would include a "Custom" option which shouldn't have a power level associated to it, just that the user/Admin can choose what actions that custom role can do.

Copy link

Choose a reason for hiding this comment

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

Hi @turt2live thanks for the quick answer. Why convert that into a separate comment?

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's no reply - just moved it to a thread)

Comments on MSCs which aren't in threads are not considered part of the discussion, so when we can we gently move such comments into threads for consideration.

Copy link

Choose a reason for hiding this comment

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

@turt2live Do you think my idea could work? I just came up with it today

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 honestly haven't read it, but it's a threaded comment now so it'll be considered when this MSC ends up back on my list of things to look at :)

Choose a reason for hiding this comment

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

Hybrid system seems unclear/complex.

Copy link
Member Author

@turt2live turt2live Sep 15, 2023

Choose a reason for hiding this comment

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

ftr, the hybrid model actually fixes a security issue, and isn't that complex. It's what Discord does.

Edit: see #4056

@turt2live
Copy link
Member Author

fyi for subscribers: This MSC is effectively replaced by another WIP MSC: #4056

@turt2live turt2live added requires-room-version An idea which will require a bump in room version unassigned-room-version Remove this label when things get versioned. labels Sep 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:feature MSC for not-core and not-maintenance stuff 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.