From f79503a045513b5463044087dbeab055fde7dec8 Mon Sep 17 00:00:00 2001 From: Alfonso Grillo Date: Wed, 10 May 2023 11:21:42 +0200 Subject: [PATCH 1/7] Add poll history cache md --- proposals/4013-poll-history-cache.md | 176 +++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 proposals/4013-poll-history-cache.md diff --git a/proposals/4013-poll-history-cache.md b/proposals/4013-poll-history-cache.md new file mode 100644 index 00000000000..50cc13818ed --- /dev/null +++ b/proposals/4013-poll-history-cache.md @@ -0,0 +1,176 @@ +# MSC4013: Poll History cache + +The purpose of this MSC is to allow clients to quickly fetch all the polls in a given room (aka “Poll History”). + +## Problem + +Clients sometimes may want to access quickly to all the polls sent in a given room (similarly to how they may want to access all the media being sent in a room). +Today clients don’t have an efficient way to make such an operation. Clients that want to implement this feature for encrypted rooms on the status quo may need to backward paginate on the room’s timeline until all the polls are found or they reach the beginning of the timeline. +For unencrypted rooms the problem doesn't exist since clients can call the [messages API](https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv3roomsroomidmessages) filtering by event type (e.g. by `m.poll.start`). + +## Proposal + +Introduce a new state event `m.room.poll_history`. This state event is supposed to be referenced by any `m.poll.start` that will be sent next in the room. The new state event must have an empty string as `state_key`. +More information on polls can be found on the [MSC3381](https://github.com/matrix-org/matrix-spec-proposals/blob/travis/msc/polls/proposals/3381-polls.md). + +This is how the new state event would look like: + +```json +{ + // irrelevant fields not shown + "content": {}, + "state_key": "", + "type": "m.room.poll_history", + "event_id": "poll_history_id" +} + +``` + +## Client behaviour +First of all a room creator sends the new `m.room.poll_history` state event in the `initial_state` when calling the [createRoom API](https://spec.matrix.org/v1.6/client-server-api/#post_matrixclientv3createroom). + +For example the body when creating a new encrypted room would look like this: + +```json +{ + "preset": "private_chat", + "name": "Some room", + "is_direct": false, + "initial_state": [ + // ... other state events + { + "stateKey": "", + "type": "m.room.encryption", + "content": { + "algorithm": "m.megolm.v1.aes-sha2" + } + }, + { + "stateKey": "", + "type": "m.room.poll_history", + "content": {} + } + ] +} +``` + + +Any time a client starts a new poll, it also includes a reference to the above state event id like this: + +```json +{ + "type": "m.poll.start", + // irrelevant fields not shown + "content": { + "m.poll.start": { + "kind": "m.poll.disclosed", + "answers": [ + {"id": "id_a", "m.text": "Yes"}, + {"id": "id_b", "m.text": "No"} + ], + "question": { "m.text": "Do you like polls?" }, + "max_selections": 1, + }, + // reference to the state event of type "m.room.poll_history" + "m.relates_to": { + "event_id": "poll_history_id", + "rel_type": "m.reference" + } + } +} +``` + +Clients can now use the event relationship to fetch the history of polls in the room: + +1. They call the [relations API](https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv1roomsroomidrelationseventid) with the new state event’s event identifier (`poll_history_id` in the example). Since the API takes a timeline direction and a pagination token, clients still have the flexibility to decide how many polls they want to fetch in a given room and in which direction. + + The request would look like this: + + `/_matrix/client/v1/rooms/{Room ID}/relations/poll_history_id/m.reference?from=from_token&dir=b&limit=100` + + The [response](https://spec.matrix.org/v1.6/client-server-api/#server-side-aggregation-of-mreference) will contain an array of related event identifiers. In encrypted rooms these events have likely the type `m.room.encrypted`. After the decryption clients should keep just decrypted events of type `m.poll.start`. +4. For each event `id_some` kept from the previous step, clients need to make the poll aggregation either by fetching data from a local database (if available) or by calling again the relations API again with the `id_some` event id. At this point clients have all the information they need to build the full poll history. + +## Potential issues + +### History on already existing rooms +It’s desirable to have the new `m.room.poll_history` state as a part of the `initial_state` of a room, but sometimes people may want to have a similar behaviour on already existing rooms. In this case a user with enough power level can just publish a `m.room.poll_history` event in the room. It is worth noticing that in this cases `m.poll.start` events sent before wouldn't have any relationship with the state event. + +### Rooms with both old and new clients +Clients understanding the new `m.room.poll_history` state event should still not fetch the poll history as described above if the `m.room.poll_history` is missing in a room. It's still possible however to have old and new clients in a room supporting the poll history. In this case new clients wouldn't see new polls opened by old clients in the poll history. This problem doesn't affect the room's timeline. + +### Privacy +Even in encrypted rooms references to other events (key `m.relates_to`) are clear text. With this proposal, starting a poll in an encrypted room means sending an event of type `m.room.encrypted` having a reference to the state event id of type `m.room.poll_history`. Since state events are also clear text, people may infer that the actual content of the encrypted message is actually a started poll (although its content is still encrypted). + +## Power levels considerations +The new `m.room.poll_history` event isn’t supposed to change over time. For this reason the power level required to change the `m.room.poll_history` event should be as high as the the one required for changing the state event `m.room.power_levels` (or similar). + +## Possible extensions + +The problem this MSC is trying to fix here is to build an index for events of a given type (`m.poll.start` in this case). In theory this approach can be useful to group other events together (e.g. images) with the purpose to show them together on clients. To fix this problem we can think of a more generic state event type `m.room.history` and use the `state_key` to differentiate several types of events. + +For polls the state event would look like this: + +```json +{ + // irrelevant fields not shown + "content": {}, + "state_key": "m.poll.start", + "type": "m.room.history", + "event_id": "poll_history_id" +} + +``` + +## Alternatives considered + +### State event for each poll + +An alternative can be to have multiple instances of the same state event `m.room.poll_history` but with different `state_key`s. In this case the client opening a poll is also required to send a state event with the `state_key` equal to `@sender:somewhere.org_XYZ`. The string `XYZ` should be a unique token for the poll. The perfect candidate is the event id of the `m.poll.start` event. +The poll history can later be built by fetching all the state events with type `m.room.poll_history` by calling the [state API](https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv3roomsroomidstateeventtypestatekey). This is possible since here the state event also contains the event id of the `m.poll.start` event: + +```json +{ + // irrelevant fields not shown + "content": { + // the id of the `m.poll.start` event + "poll_id": "poll started event id" + }, + // Potentially XYZ == the id of the `m.poll.start` event + "state_key": "@someone:somewhere.org_XYZ", + "type": "m.room.poll_history", + "event_id": "poll_history_id" +} + +``` + +Potential problems with this approach however are: +- Users opening a poll need enough power level to send a state event (`m.room.poll_history`) +- This approach has an additional dependency: [MSC3757](https://github.com/matrix-org/matrix-spec-proposals/blob/andybalaam/owner-state-events/proposals/3757-restricting-who-can-overwrite-a-state-event.md) + +### State event containing an array of poll started events + +The idea here is to introduce new state event as the main proposal. The only difference is that here clients are supposed to update the state event every time they open a new poll. The new state event's purpose is to contain all the ids for `m.poll.start` events. + +The new state event would look like this: +```json +{ + // irrelevant fields not shown + "content": { + "polls": [ + "poll_started_a_id", + "poll_started_b_id", + + ] + }, + "state_key": "", + "type": "m.room.poll_history", + "event_id": "poll_history_id" +} + +``` + +Potential problems with this approach are: +- Users opening a poll need enough power level to send a state event (`m.room.poll_history`) +- Conflicts may arise when two users attempt to change the state event at the same time +- A malicious user or a bug in a client may accidentally erase the history sending a wrong payload From 3735515a239ec98382380235701c002e7d2d2fcd Mon Sep 17 00:00:00 2001 From: Alfonso Grillo Date: Wed, 10 May 2023 11:33:53 +0200 Subject: [PATCH 2/7] Fix code block annotations --- proposals/4013-poll-history-cache.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/proposals/4013-poll-history-cache.md b/proposals/4013-poll-history-cache.md index 50cc13818ed..657fbfad2ad 100644 --- a/proposals/4013-poll-history-cache.md +++ b/proposals/4013-poll-history-cache.md @@ -15,7 +15,7 @@ More information on polls can be found on the [MSC3381](https://github.com/matri This is how the new state event would look like: -```json +```json5 { // irrelevant fields not shown "content": {}, @@ -31,7 +31,7 @@ First of all a room creator sends the new `m.room.poll_history` state event in t For example the body when creating a new encrypted room would look like this: -```json +```json5 { "preset": "private_chat", "name": "Some room", @@ -57,7 +57,7 @@ For example the body when creating a new encrypted room would look like this: Any time a client starts a new poll, it also includes a reference to the above state event id like this: -```json +```json5 { "type": "m.poll.start", // irrelevant fields not shown @@ -111,7 +111,7 @@ The problem this MSC is trying to fix here is to build an index for events of a For polls the state event would look like this: -```json +```json5 { // irrelevant fields not shown "content": {}, @@ -129,7 +129,7 @@ For polls the state event would look like this: An alternative can be to have multiple instances of the same state event `m.room.poll_history` but with different `state_key`s. In this case the client opening a poll is also required to send a state event with the `state_key` equal to `@sender:somewhere.org_XYZ`. The string `XYZ` should be a unique token for the poll. The perfect candidate is the event id of the `m.poll.start` event. The poll history can later be built by fetching all the state events with type `m.room.poll_history` by calling the [state API](https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv3roomsroomidstateeventtypestatekey). This is possible since here the state event also contains the event id of the `m.poll.start` event: -```json +```json5 { // irrelevant fields not shown "content": { @@ -153,7 +153,7 @@ Potential problems with this approach however are: The idea here is to introduce new state event as the main proposal. The only difference is that here clients are supposed to update the state event every time they open a new poll. The new state event's purpose is to contain all the ids for `m.poll.start` events. The new state event would look like this: -```json +```json5 { // irrelevant fields not shown "content": { From 135220e3d3f37b90b00b85c6de1807655f3da055 Mon Sep 17 00:00:00 2001 From: Alfonso Grillo Date: Wed, 10 May 2023 11:54:20 +0200 Subject: [PATCH 3/7] Add unstable prefix section --- proposals/4013-poll-history-cache.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proposals/4013-poll-history-cache.md b/proposals/4013-poll-history-cache.md index 657fbfad2ad..195be23732e 100644 --- a/proposals/4013-poll-history-cache.md +++ b/proposals/4013-poll-history-cache.md @@ -174,3 +174,7 @@ Potential problems with this approach are: - Users opening a poll need enough power level to send a state event (`m.room.poll_history`) - Conflicts may arise when two users attempt to change the state event at the same time - A malicious user or a bug in a client may accidentally erase the history sending a wrong payload + +# Unstable prefix + +While this MSC is not considered stable, implementations should use `org.matrix.msc4013.*` as a prefix in place of `m.*` for the new state event type. From 347445273ba409f0cb1df90eaaab5d6634af817c Mon Sep 17 00:00:00 2001 From: Alfonso Grillo Date: Wed, 10 May 2023 11:57:53 +0200 Subject: [PATCH 4/7] Update MSC title --- proposals/4013-poll-history-cache.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/4013-poll-history-cache.md b/proposals/4013-poll-history-cache.md index 195be23732e..289f6890269 100644 --- a/proposals/4013-poll-history-cache.md +++ b/proposals/4013-poll-history-cache.md @@ -1,6 +1,6 @@ -# MSC4013: Poll History cache +# MSC4013: Poll history cache -The purpose of this MSC is to allow clients to quickly fetch all the polls in a given room (aka “Poll History”). +The purpose of this MSC is to allow clients to quickly fetch all the polls in a given room (aka “Poll history”). ## Problem From 1585d9741ab495370f0e37cf9b3e5a4e9384b241 Mon Sep 17 00:00:00 2001 From: Alfonso Grillo Date: Thu, 11 May 2023 10:16:20 +0200 Subject: [PATCH 5/7] Update proposals/4013-poll-history-cache.md Co-authored-by: Travis Ralston --- proposals/4013-poll-history-cache.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/4013-poll-history-cache.md b/proposals/4013-poll-history-cache.md index 289f6890269..3794a4b5a9e 100644 --- a/proposals/4013-poll-history-cache.md +++ b/proposals/4013-poll-history-cache.md @@ -11,7 +11,7 @@ For unencrypted rooms the problem doesn't exist since clients can call the [mess ## Proposal Introduce a new state event `m.room.poll_history`. This state event is supposed to be referenced by any `m.poll.start` that will be sent next in the room. The new state event must have an empty string as `state_key`. -More information on polls can be found on the [MSC3381](https://github.com/matrix-org/matrix-spec-proposals/blob/travis/msc/polls/proposals/3381-polls.md). +More information on polls can be found on the [MSC3381](https://github.com/matrix-org/matrix-spec-proposals/pull/3381). This is how the new state event would look like: From a5f7d0e70c4e5fda8707cf57100b6b26246385b9 Mon Sep 17 00:00:00 2001 From: Alfonso Grillo Date: Thu, 11 May 2023 10:21:24 +0200 Subject: [PATCH 6/7] Add MSC dependencies --- proposals/4013-poll-history-cache.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/proposals/4013-poll-history-cache.md b/proposals/4013-poll-history-cache.md index 3794a4b5a9e..ff7df0be28e 100644 --- a/proposals/4013-poll-history-cache.md +++ b/proposals/4013-poll-history-cache.md @@ -26,6 +26,9 @@ This is how the new state event would look like: ``` +### Dependencies +- [MSC3381](https://github.com/matrix-org/matrix-spec-proposals/pull/338) + ## Client behaviour First of all a room creator sends the new `m.room.poll_history` state event in the `initial_state` when calling the [createRoom API](https://spec.matrix.org/v1.6/client-server-api/#post_matrixclientv3createroom). From 2d2fa1c2fd0c75264ab7829ddf201f05e4d2516b Mon Sep 17 00:00:00 2001 From: Alfonso Grillo Date: Mon, 29 May 2023 17:15:25 +0200 Subject: [PATCH 7/7] Wrap lines to 120 chars --- proposals/4013-poll-history-cache.md | 72 +++++++++++++++++++++------- 1 file changed, 54 insertions(+), 18 deletions(-) diff --git a/proposals/4013-poll-history-cache.md b/proposals/4013-poll-history-cache.md index ff7df0be28e..11683594682 100644 --- a/proposals/4013-poll-history-cache.md +++ b/proposals/4013-poll-history-cache.md @@ -4,13 +4,18 @@ The purpose of this MSC is to allow clients to quickly fetch all the polls in a ## Problem -Clients sometimes may want to access quickly to all the polls sent in a given room (similarly to how they may want to access all the media being sent in a room). -Today clients don’t have an efficient way to make such an operation. Clients that want to implement this feature for encrypted rooms on the status quo may need to backward paginate on the room’s timeline until all the polls are found or they reach the beginning of the timeline. -For unencrypted rooms the problem doesn't exist since clients can call the [messages API](https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv3roomsroomidmessages) filtering by event type (e.g. by `m.poll.start`). +Clients sometimes may want to access quickly to all the polls sent in a given room (similarly to how they may want to +access all the media being sent in a room).Today clients don’t have an efficient way to make such an operation. +Clients that want to implement this feature for encrypted rooms on the status quo may need to backward paginate on the +room’s timeline until all the polls are found or they reach the beginning of the timeline. For unencrypted rooms the +problem doesn't exist since clients can call the +[messages API](https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv3roomsroomidmessages) +filtering by event type (e.g. by `m.poll.start`). ## Proposal -Introduce a new state event `m.room.poll_history`. This state event is supposed to be referenced by any `m.poll.start` that will be sent next in the room. The new state event must have an empty string as `state_key`. +Introduce a new state event `m.room.poll_history`. This state event is supposed to be referenced by any `m.poll.start` +that will be sent next in the room. The new state event must have an empty string as `state_key`. More information on polls can be found on the [MSC3381](https://github.com/matrix-org/matrix-spec-proposals/pull/3381). This is how the new state event would look like: @@ -30,7 +35,8 @@ This is how the new state event would look like: - [MSC3381](https://github.com/matrix-org/matrix-spec-proposals/pull/338) ## Client behaviour -First of all a room creator sends the new `m.room.poll_history` state event in the `initial_state` when calling the [createRoom API](https://spec.matrix.org/v1.6/client-server-api/#post_matrixclientv3createroom). +First of all a room creator sends the new `m.room.poll_history` state event in the `initial_state` when calling the +[createRoom API](https://spec.matrix.org/v1.6/client-server-api/#post_matrixclientv3createroom). For example the body when creating a new encrypted room would look like this: @@ -85,32 +91,53 @@ Any time a client starts a new poll, it also includes a reference to the above s Clients can now use the event relationship to fetch the history of polls in the room: -1. They call the [relations API](https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv1roomsroomidrelationseventid) with the new state event’s event identifier (`poll_history_id` in the example). Since the API takes a timeline direction and a pagination token, clients still have the flexibility to decide how many polls they want to fetch in a given room and in which direction. +1. They call the [relations API](https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv1roomsroomidrelationseventid) +with the new state event’s event identifier (`poll_history_id` in the example). Since the API takes a timeline direction +and a pagination token, clients still have the flexibility to decide how many polls they want to fetch in a given room +and in which direction. The request would look like this: `/_matrix/client/v1/rooms/{Room ID}/relations/poll_history_id/m.reference?from=from_token&dir=b&limit=100` - The [response](https://spec.matrix.org/v1.6/client-server-api/#server-side-aggregation-of-mreference) will contain an array of related event identifiers. In encrypted rooms these events have likely the type `m.room.encrypted`. After the decryption clients should keep just decrypted events of type `m.poll.start`. -4. For each event `id_some` kept from the previous step, clients need to make the poll aggregation either by fetching data from a local database (if available) or by calling again the relations API again with the `id_some` event id. At this point clients have all the information they need to build the full poll history. + The [response](https://spec.matrix.org/v1.6/client-server-api/#server-side-aggregation-of-mreference) will contain + an array of related event identifiers. In encrypted rooms these events have likely the type `m.room.encrypted`. + After the decryption clients should keep just decrypted events of type `m.poll.start`. +4. For each event `id_some` kept from the previous step, clients need to make the poll aggregation either by fetching +data from a local database (if available) or by calling again the relations API again with the `id_some` event id. +At this point clients have all the information they need to build the full poll history. ## Potential issues ### History on already existing rooms -It’s desirable to have the new `m.room.poll_history` state as a part of the `initial_state` of a room, but sometimes people may want to have a similar behaviour on already existing rooms. In this case a user with enough power level can just publish a `m.room.poll_history` event in the room. It is worth noticing that in this cases `m.poll.start` events sent before wouldn't have any relationship with the state event. +It’s desirable to have the new `m.room.poll_history` state as a part of the `initial_state` of a room, but sometimes +people may want to have a similar behaviour on already existing rooms. In this case a user with enough power level can +just publish a `m.room.poll_history` event in the room. It is worth noticing that in this cases `m.poll.start` events +sent before wouldn't have any relationship with the state event. ### Rooms with both old and new clients -Clients understanding the new `m.room.poll_history` state event should still not fetch the poll history as described above if the `m.room.poll_history` is missing in a room. It's still possible however to have old and new clients in a room supporting the poll history. In this case new clients wouldn't see new polls opened by old clients in the poll history. This problem doesn't affect the room's timeline. +Clients understanding the new `m.room.poll_history` state event should still not fetch the poll history as described +above if the `m.room.poll_history` is missing in a room. It's still possible however to have old and new clients in a +room supporting the poll history. In this case new clients wouldn't see new polls opened by old clients in the poll +history. This problem doesn't affect the room's timeline. ### Privacy -Even in encrypted rooms references to other events (key `m.relates_to`) are clear text. With this proposal, starting a poll in an encrypted room means sending an event of type `m.room.encrypted` having a reference to the state event id of type `m.room.poll_history`. Since state events are also clear text, people may infer that the actual content of the encrypted message is actually a started poll (although its content is still encrypted). +Even in encrypted rooms references to other events (key `m.relates_to`) are clear text. With this proposal, starting a +poll in an encrypted room means sending an event of type `m.room.encrypted` having a reference to the state event id of +type `m.room.poll_history`. Since state events are also clear text, people may infer that the actual content of the +encrypted message is actually a started poll (although its content is still encrypted). ## Power levels considerations -The new `m.room.poll_history` event isn’t supposed to change over time. For this reason the power level required to change the `m.room.poll_history` event should be as high as the the one required for changing the state event `m.room.power_levels` (or similar). +The new `m.room.poll_history` event isn’t supposed to change over time. For this reason the power level required to +change the `m.room.poll_history` event should be as high as the the one required for changing the state event +`m.room.power_levels` (or similar). ## Possible extensions -The problem this MSC is trying to fix here is to build an index for events of a given type (`m.poll.start` in this case). In theory this approach can be useful to group other events together (e.g. images) with the purpose to show them together on clients. To fix this problem we can think of a more generic state event type `m.room.history` and use the `state_key` to differentiate several types of events. +The problem this MSC is trying to fix here is to build an index for events of a given type (`m.poll.start` in this case). +In theory this approach can be useful to group other events together (e.g. images) with the purpose to show them +together on clients. To fix this problem we can think of a more generic state event type `m.room.history` and use the +`state_key` to differentiate several types of events. For polls the state event would look like this: @@ -129,8 +156,13 @@ For polls the state event would look like this: ### State event for each poll -An alternative can be to have multiple instances of the same state event `m.room.poll_history` but with different `state_key`s. In this case the client opening a poll is also required to send a state event with the `state_key` equal to `@sender:somewhere.org_XYZ`. The string `XYZ` should be a unique token for the poll. The perfect candidate is the event id of the `m.poll.start` event. -The poll history can later be built by fetching all the state events with type `m.room.poll_history` by calling the [state API](https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv3roomsroomidstateeventtypestatekey). This is possible since here the state event also contains the event id of the `m.poll.start` event: +An alternative can be to have multiple instances of the same state event `m.room.poll_history` but with different +`state_key`s. In this case the client opening a poll is also required to send a state event with the `state_key` equal +to `@sender:somewhere.org_XYZ`. The string `XYZ` should be a unique token for the poll. The perfect candidate is the +event id of the `m.poll.start` event. +The poll history can later be built by fetching all the state events with type `m.room.poll_history` by calling the +[state API](https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv3roomsroomidstateeventtypestatekey). +This is possible since here the state event also contains the event id of the `m.poll.start` event: ```json5 { @@ -149,11 +181,14 @@ The poll history can later be built by fetching all the state events with type ` Potential problems with this approach however are: - Users opening a poll need enough power level to send a state event (`m.room.poll_history`) -- This approach has an additional dependency: [MSC3757](https://github.com/matrix-org/matrix-spec-proposals/blob/andybalaam/owner-state-events/proposals/3757-restricting-who-can-overwrite-a-state-event.md) +- This approach has an additional dependency: +[MSC3757](https://github.com/matrix-org/matrix-spec-proposals/blob/andybalaam/owner-state-events/proposals/3757-restricting-who-can-overwrite-a-state-event.md) ### State event containing an array of poll started events -The idea here is to introduce new state event as the main proposal. The only difference is that here clients are supposed to update the state event every time they open a new poll. The new state event's purpose is to contain all the ids for `m.poll.start` events. +The idea here is to introduce new state event as the main proposal. The only difference is that here clients are +supposed to update the state event every time they open a new poll. The new state event's purpose is to contain all the +ids for `m.poll.start` events. The new state event would look like this: ```json5 @@ -180,4 +215,5 @@ Potential problems with this approach are: # Unstable prefix -While this MSC is not considered stable, implementations should use `org.matrix.msc4013.*` as a prefix in place of `m.*` for the new state event type. +While this MSC is not considered stable, implementations should use `org.matrix.msc4013.*` as a prefix in place of +`m.*` for the new state event type.