Internet-Draft | MIMI Policy Envelope | September 2023 |
Ralston & Hodgson | Expires 26 March 2024 | [Page] |
The MIMI Policy Envelope describes a policy control protocol and participation control protocol for use in a room, applied at the user participation level, as described by [I-D.barnes-mimi-arch].¶
This note is to be removed before publishing as an RFC.¶
The latest revision of this draft can be found at https://turt2live.github.io/ietf-mimi-policy/draft-ralston-mimi-policy.html. Status information for this document may be found at https://datatracker.ietf.org/doc/draft-ralston-mimi-policy/.¶
Discussion of this document takes place on the More Instant Messaging Interoperability Working Group mailing list (mailto:mimi@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/mimi/. Subscribe at https://www.ietf.org/mailman/listinfo/mimi/.¶
Source for this draft and an issue tracker can be found at https://github.com/turt2live/ietf-mimi-policy.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 26 March 2024.¶
Copyright (c) 2023 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
The primary objective for the More Instant Messaging Interoperability (MIMI) working group is to specify the needed protocols to achieve interoperability among modern messaging providers. The protocols which make up the "MIMI stack" are described by [I-D.barnes-mimi-arch].¶
In the stack are a policy control protocol and a participation control protocol. These two control protocols are described by this document, supported by TODO(TR): Link to I-D.ralston-mimi-signaling.¶
Policy control is handled through permissions, while participation is managed
primarily through the rules governing m.room.user
. Together, these control
protocols create this policy document.¶
When an action is impossible for a server to enforce, such as when a client operated by a user sends an encrypted instant message, the receiving clients are responsible for enforcing the remainder of the policy. This may mean, for example, decrypting a message but not rendering it due to a policy violation.¶
The concepts of permissions and participation state for a user are deliberately separated in this policy document. A user's participation state might affect which permissions they can use, but a user's permissions do not change their participation in a room.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
Terms from [I-D.barnes-mimi-arch] and [I-D.ralston-mimi-terminology] are used throughout this document. [I-D.barnes-mimi-arch] takes precedence where there's conflict.¶
Terms from TODO(TR): Link to I-D.ralston-mimi-signaling are used throughout this document.¶
Other terms include:¶
Rejected: The action being performed ceases to continue through the remainder of the send/rendering steps. For a hub server, this means the event being sent is not added to the room and is not sent to any other server. For a client, this equates to not rendering or respecting the action.¶
Allowed: The opposite of Rejected. The action is expressly permitted to occur.¶
"Engaging with the room": The user is able to take some actions and send messages in the room, provided the remainder of the policy allows them to do that. The encryption/security layer MAY further restrict a user's ability to take action. For example, the user might need 1 or more clients to be able to successfully send a message.¶
Action: Something a user does in the context of a room. For example, invite another user or send a message to the room.¶
Permission: A flag which allows (or rejects) execution of an action.¶
Role: A user-defined set of permissions. Users are added to roles to gain the included permissions.¶
Target: The user affected by a participation state.¶
Sender: The user affecting a target user with a participation state.¶
Invited: The target is given the choice to accept the invite (join the room) or decline (leave the room).¶
Joined: The target is capable of engaging with the room.¶
Left: The target has either voluntarily chosen to leave the room, or has been removed with a kick.¶
Banned: The target is kicked and cannot be invited, joined, or knock on the room until unbanned.¶
Knocking: The sender is requesting an invite into the room. They can either be welcomed in (invited) or declined (kicked).¶
Kicked: Involuntary leave. The target and sender are not the same user.¶
TODO(TR): Do we want to send as not-users? (GH issue)¶
Currently this document only supports sender
being a user ID.¶
Rooms are capable of defining their own roles for grouping permissions to apply to users. These roles do not currently have aesthetic characteristics, such as a display name, badge color, or avatar.¶
Roles are described by an m.room.role
state event. The state key for the event
is the "role ID", and is not intended to be human readable.¶
The content for the event has the following structure in TLS presentation language format (Section 3 of [RFC8446]):¶
enum { // Iterated later in the document. } Permission; struct { select (Permission) { // cases defined later in the document. } permission; } PermissionValue; struct { PermissionValue permissions[]; } MRoomRoleEventContent;¶
Users are assigned to roles using an m.room.role_map
state event, with empty
string for a state key. The content being as follows:¶
struct { // The role's ID. opaque roleId; // The user IDs who are assigned this role. opaque userIds[]; // The power level for the role. This is used in cases of tiebreak and to // override permissions from another role. uint32 order; } RoleConfig; struct { RoleConfig roles[]; } MRoomRoleMapEventContent;¶
Each role ID MUST only appear once in MRoomRoleMapEventContent.roles
. Each
RoleConfig.order
MUST be distinct from all other entries. If either of these
checks fail when a server receives the event, the event is rejected.¶
A user's permissions is the sum of the permissions described by their assigned
roles. When two roles define the same permission (but with different values),
the higher order
role takes precedence.¶
For example, if given the following role structure...¶
... and a user assigned all three roles, the user's resolved set of permissions would be:¶
These permissions are then used to define whether a user can "send" the event.¶
In some cases it is required to know the "power level" for a user to solve
tiebreaks. The power level of a user is the highest order
role they are
assigned with the desired permission set, regardless of value for that
permission.¶
Using the example from Section 5.1, a user with all three roles would have the following effective power levels for each permission in question:¶
The full definitions for Permission
and PermissionValue
in
Section 5 is:¶
enum { // Whether other users can be invited to the room by the role. // Default: false. invite(1), // Whether other users can be kicked from the room by the role. // Default: false. kick(2), // Whether other users can be banned from the room by the role. // Default: false. ban(3), // Whether another user's events can be redacted by the role. // Senders can always redact their own events regardless of this permission. // Default: false. redact(4), // TODO(TR): Do we need this one? // The event types the role is able to send. // Default: None. events(5), // The actions this role can take against roles. For example, adding or // removing permissions. // Default: None. roles(6), } Permission; struct { select (Permission) { case invite: BooleanPermission; case kick: BooleanPermission; case ban: BooleanPermission; case redact: BooleanPermission; case events: EventTypePermission; case roles: RolePermission; } permission; } PermissionValue; struct { // When false, the permission is explicitly not granted. byte granted; } BooleanPermission; struct { // The event type being gated by a permission. opaque eventType; // When false, the permission to send the event is explicitly not granted. byte granted; } EventTypePermissionRecord; struct { // The event type restrictions. If there are duplicates, the lastmost entry // takes priority. EventTypePermissionRecord eventTypes[]; } EventTypePermission; struct { // The role IDs that can be affected by this role. This includes adding, // removing, and changing permissions. // TODO(TR): We might want something more comprehensive. opaque affectRoleId[]; } RolePermission;¶
The sender
for an event MUST have permission (Section 5.1) to
send that event type, unless the event type is m.room.user
. User participation
events are handled specifically in Section 6.¶
The sender
MUST also be in the joined state to send such events.¶
TODO(TR): I believe we need words to describe how to use the role permissions described above. Probably something using effective power levels and talking about what "add", "remove", and "change" actually mean.¶
TODO(TR): We also need to specify that the creator has superuser permissions until a role is defined/assigned.¶
User participation is tracked as m.room.user
state events. The content
for
such an event has the following structure in TLS presentation language format
(Section 3 of [RFC8446]):¶
enum { invite, // "Invited" state. join, // "Joined" state. leave, // "Left" state (including Kicked). ban, // "Banned" state. knock // "Knocking" state. } ParticipationState; struct { ParticipationState participation; opaque reason; // optional reason for the participation state } MRoomUserEventContent;¶
A user is considered to be "joined" to a room if they have a participation state
of join
. All servers with users in the joined state are considered to be "in"
the room.¶
Servers which are in the room can send events for their users directly. The signaling protocol is able to assist servers (and therefore users) in sending the appropriate participation events until they are able complete the join process.¶
The target user for an invite MUST:¶
The sender for an invite MUST:¶
Otherwise, reject.¶
The target and sender of a join MUST be the same.¶
Whether a user can join without invite is dependent on the join rules (Section 6.7).¶
If the join rule is invite
or knock
, the user MUST already be in the joined
or invite state.¶
If the join rule is public
, the user MUST NOT already be in the banned state.¶
Otherwise, reject.¶
The target and sender of a knock MUST be the same.¶
If the current join rule (Section 6.7) for the room is knock
, the
user MUST NOT already be in the banned or joined state.¶
Otherwise, reject.¶
The sender for a ban MUST:¶
Otherwise, reject.¶
Note that a ban implies kick.¶
Leaves in a room come in two varieties: voluntary and kicks. Voluntary leaves are when the user no longer wishes to be an active participant in the room. A kick is done to remove a user forcefully.¶
When the target and sender of a leave is the same, it is a voluntary leave.¶
The target user for a kick MUST:¶
The sender for a kick MUST:¶
If the target user is in the banned state, the sender requires permission to ban users instead (as to ban means to unban as well). This additionally extends to the effective power level check.¶
Otherwise, reject.¶
m.room.join_rules
State key: Empty string.¶
Content:¶
enum { invite, knock, public, } JoinRule; struct { // The current join rule for the room. Defaults to `invite` if no join rules // event is in the room. JoinRule rule; } MRoomJoinRulesEventContent;¶
Redaction considerations: rule
under content
is protected from
redaction.¶
Unless otherwise specified by the event type, non-state events MUST NOT be sent to a user's client if the history visibility rules prohibit it. State events are always visible to clients.¶
When a server is fetching events it is missing to build history, the returned events are redacted unless the server has at least one user which is able to see the event under the history visibility rules. The server must then further filter the events before sending them to clients.¶
History visibility rules are defined by m.room.history_visibility
(Section 7.1), and can only affect future events. Events sent before
the history visibility rule change are not retroactively affected.¶
Taking into consideration the m.room.history_visibility
event that is current
at the time an event was sent, a user's visibility of a that event is described
as:¶
world
, show.¶
shared
and the user was in the joined state at
any point after the event was sent, show.¶
invited
,
show.¶
m.room.history_visibility
State key: Empty string.¶
Content:¶
enum { invited, joined, shared, world, } Visibility; struct { // The current join rule for the room. Defaults to `shared` if no history // visibility event is present in the room. Visibility visibility; } MRoomHistoryVisibilityEventContent;¶
Redaction considerations: visibility
under content
is protected from
redaction.¶
This document as a whole makes up the m.0
policy ID, as per
TODO(TR): Link to I-D.ralston-mimi-signaling.¶
This document's descriptions for the following event types are registered to the event types registry in TODO(TR): Link to I-D.ralston-mimi-signaling:¶
m.room.role
(Section 5)¶
m.room.role_map
(Section 5)¶
m.room.join_rules
(Section 6.7)¶
m.room.history_visibility
(Section 7.1)¶