Skip to content
Open
Changes from 13 commits
Commits
Show all changes
178 commits
Select commit Hold shift + click to select a range
9cbe448
draft
toger5 May 10, 2024
b2b4e5e
lowercase filename
toger5 May 13, 2024
8c1340a
add note about this relying on MSC3757
toger5 May 14, 2024
8c800a6
remove the m.prefix from fields.
toger5 May 17, 2024
1dcbfce
update
toger5 Jun 5, 2024
813a21a
add foci_preferred well known section
toger5 Jun 6, 2024
d65e42e
update to reference to msc [MSC4158](https://github.com/matrix-org/ma…
toger5 Jun 20, 2024
4ab679a
add a "Reliability requirements for the room state" section
toger5 Jul 2, 2024
6d84256
use current state key format
toger5 Sep 11, 2024
d68e942
add `expires_after`
toger5 Sep 11, 2024
3b19b49
add section about send order (delayed leave event -> join event)
toger5 Sep 11, 2024
a278ff8
language fixes
ara4n Nov 25, 2024
f97e4e6
clarify that non-empty delayed membership events are invalid
ara4n Nov 25, 2024
b626d51
Latest
hughns Dec 17, 2024
ec9fa8b
json5 for legibility
hughns Dec 17, 2024
50db42a
be more specific on `member.id`
toger5 Jul 30, 2025
9bc444c
add id to session
toger5 Jul 31, 2025
33231dc
calrify that the state key cannot be used as the source of truth for …
toger5 Jul 31, 2025
cea4cdd
Update proposals/4143-matrix-rtc.md
toger5 Aug 8, 2025
d61969a
clarify what is part of this MSC and what can be found in other MSC's
toger5 Aug 26, 2025
4ad3961
major rewrite addressing a lot of feedback from offline discussions.
fkwp Oct 14, 2025
1fbd843
json5 code block formats
toger5 Oct 14, 2025
60e23d9
add unstable m.rtc.slot prefix.
toger5 Oct 14, 2025
680ef7d
fix grammar & link the MSC
ara4n Oct 14, 2025
b62f75b
more informatino on the purpose of `member.id`
fkwp Dec 12, 2025
50f8331
markdown cleanup
fkwp Dec 12, 2025
d53175b
Remove stray . from slot ID
robintown Jan 23, 2026
dc605bf
cleanup field description for to-device message
fkwp Jan 23, 2026
7907635
minor changes to the m.rtc.encryption_key to-device format
fkwp Jan 23, 2026
c032f03
Update transport type to match latest MSC4195 revision
robintown Mar 11, 2026
866ca09
Require authentication for MatrixRTC transport discovery endpoint
fkwp Apr 15, 2026
3855617
Fix [!NOTE] syntax
Johennes Jun 5, 2026
be629da
Use "power level" rather than "`power_level`" to avoid ambiguity
Johennes Jun 5, 2026
9c17cc6
Avoid using MUST with respect to creating MSCs per application
Johennes Jun 8, 2026
29a3f30
Remove recommendation to provide widget implementations for applicati…
Johennes Jun 8, 2026
e3083de
Clarify that RTC member refers to m.rtc.member events
Johennes Jun 8, 2026
f928273
Fix number of states
Johennes Jun 8, 2026
730296f
Downgrade UX description to examples
Johennes Jun 8, 2026
c7fcea0
Remove duplicate paragraph
Johennes Jun 8, 2026
72f3c4c
Linkify
Johennes Jun 8, 2026
6dd4f50
Fix property name
Johennes Jun 8, 2026
73efe93
Fix bullets
Johennes Jun 8, 2026
d840122
Relocate slot ID grammar
Johennes Jun 8, 2026
535138a
Avoid "slot name" term
Johennes Jun 9, 2026
118c9db
Clarify common namespaced identifier requirements
Johennes Jun 15, 2026
9852003
Clarify why we require stickyness to consider a member connected
Johennes Jun 15, 2026
3ccd90b
Remove vulnerable hashing example
Johennes Jun 15, 2026
8587297
Fix spelling
Johennes Jun 16, 2026
d597297
Clarify origin of disconnect_reason design and remove examples as the…
Johennes Jun 16, 2026
37ded3e
Fix typo
Johennes Jun 16, 2026
e5e135a
Clarify that we're using unpadded base64
Johennes Jun 16, 2026
8235365
Clarify delegation requirements
Johennes Jun 16, 2026
6bc4ff0
Add unstable version flag
Johennes Jun 16, 2026
6bf733f
Cross-link MSC4075
Johennes Jun 16, 2026
eac1005
Add .well-known alternative
Johennes Jun 17, 2026
57c8cbe
Explain why we use the claimed_ prefixes
Johennes Jun 17, 2026
5bcd4f0
Some clarifications around encryption
Johennes Jun 17, 2026
0229f89
Move future ratcheting extension to potential issues
Johennes Jun 17, 2026
0a78a66
Merge content 'Scope and Responsibilities of MatrixRTC Applications' …
Johennes Jun 18, 2026
a5bef33
Remove relations
Johennes Jul 6, 2026
98bd92d
Blend part of the beginning of the proposal into the introduction to …
Johennes Jul 6, 2026
01abcd6
Update slot description and include encryption setting
Johennes Jul 7, 2026
b63210a
Update membership section
Johennes Jul 9, 2026
9e07f16
Fix typos
Johennes Jul 9, 2026
9409b17
Clarify SHOULD'ness of disconnect_reason
Johennes Jul 9, 2026
48645d4
Update sessions section
Johennes Jul 9, 2026
234a4b1
Update transports section
Johennes Jul 9, 2026
3c98456
Remove shared key encryption
Johennes Jul 9, 2026
82f5e57
Remove delegation of delayed event management
Johennes Jul 10, 2026
af4c337
Update encryption section
Johennes Jul 10, 2026
e4f3693
Highlight that member events must be encrypted
Johennes Jul 14, 2026
cbab20d
Update potential issues section
Johennes Jul 15, 2026
396c61b
Slightly adapt wording in key traffic discussion now that per-partici…
Johennes Jul 15, 2026
164f804
Update alternatives section
Johennes Jul 15, 2026
79db42b
Update security considerations and the rest
Johennes Jul 15, 2026
2231bad
Fix typo
Johennes Jul 15, 2026
807199f
Fix links and styling
Johennes Jul 15, 2026
f23d415
Add decline MSC reference
Johennes Jul 15, 2026
720aeee
Shorten slot/member consideration
Johennes Jul 15, 2026
98c59df
Add space
Johennes Jul 15, 2026
27854d4
Remove duplicate footnote
Johennes Jul 15, 2026
9bd7142
Fix typos
Johennes Jul 15, 2026
d1363e3
Shorten link
Johennes Jul 15, 2026
ae98f71
Add CNIG restriction
Johennes Jul 15, 2026
a58efb9
Only remove app obj
Johennes Jul 15, 2026
ecb695a
Remove claimed useer ID
Johennes Jul 15, 2026
98aa57a
Improve wording
Johennes Jul 15, 2026
ff3810b
Avoid SFU ref
Johennes Jul 15, 2026
a7e7e35
Fix typos
Johennes Jul 15, 2026
b304723
Improve wording
Johennes Jul 15, 2026
55d36f8
Improve wording
Johennes Jul 15, 2026
8685d8d
Improve wording
Johennes Jul 15, 2026
d5a758c
Improve wording
Johennes Jul 15, 2026
903ae32
Improve wording
Johennes Jul 15, 2026
a6be849
Improve wording
Johennes Jul 15, 2026
ebf0ee2
Improve wording
Johennes Jul 15, 2026
0bc3a1d
Improve wording
Johennes Jul 15, 2026
dcc1e1e
Improve wording
Johennes Jul 15, 2026
6786235
Improve wording
Johennes Jul 15, 2026
20265cb
Improve wording
Johennes Jul 15, 2026
b7f8568
Add missing prefix
Johennes Jul 15, 2026
de35d8b
Fix typo
Johennes Jul 15, 2026
8fafc5b
reason/description -> code/reason
Johennes Jul 15, 2026
0a158a0
Switch to 32 bytes
Johennes Jul 15, 2026
adba11b
version -> format
Johennes Jul 15, 2026
c87b1ee
Improve wording
Johennes Jul 15, 2026
b98cb2f
Improve wording
Johennes Jul 15, 2026
8297dcc
Add encryption requirement
Johennes Jul 15, 2026
04ee51b
Small clarity and style fixes to MSC4143 (#4510)
robintown Jul 16, 2026
0e7bd82
Clarify that slot participation might also require higher power levels
Johennes Jul 16, 2026
272cc47
Introduce slot status and consider encryption downgrade security impact
Johennes Jul 16, 2026
9d621d4
Clarify can_subscribe
Johennes Jul 16, 2026
3cddce3
Shorten explanation of why membership is bounded by stickiness
Johennes Jul 16, 2026
25a4a61
m.per_participant -> m.per_member
Johennes Jul 16, 2026
7f1185d
Remove interoperation potential issue as it should be covered by can_…
Johennes Jul 16, 2026
eb8f21f
Clarify key traffic issue
Johennes Jul 16, 2026
cd6c615
Use uniform language for members, joining, leaving, rename disconnect…
Johennes Jul 16, 2026
55bebd6
Remove note about canonical member id
Johennes Jul 16, 2026
79fefa5
Fix typo
Johennes Jul 16, 2026
0c5f187
Specify generic leave codes
Johennes Jul 16, 2026
dab1eeb
Clarify slot<>room relationship
Johennes Jul 22, 2026
492e69f
Improve line wrapping
Johennes Jul 22, 2026
6d5f4ea
Spell out that the `encryption` object en-/disables encryption
Johennes Jul 22, 2026
d45bf23
Make the required relation between application.type and state_key exp…
Johennes Jul 22, 2026
e127b34
Spell out that application is required for open slots
Johennes Jul 22, 2026
4602646
member.id is only unique for the same user
Johennes Jul 22, 2026
3e3df5a
Tighten join requirements
Johennes Jul 22, 2026
2c1ed9e
Tighten leave requirements
Johennes Jul 22, 2026
ecd40da
Fix position of leave marker in chart
Johennes Jul 22, 2026
3e265cf
Clarify that the JSON is an OlmPlaintext
Johennes Jul 22, 2026
5b13400
Also mention the former name OlmPayload
Johennes Jul 22, 2026
d5366ab
Tighten wording around open and closed slots
Johennes Jul 22, 2026
cedd4a9
Add shadow sessions consideration
Johennes Jul 22, 2026
0eb3656
Adapt MatrixRTC encryption to latest agreements (#4516)
Johennes Jul 24, 2026
4b8c6ea
Move transport types out of MSC4143 and into MSC4519
turt2live Jul 28, 2026
694b4e4
Provide an application example
robintown Jul 30, 2026
e830685
Describe slots more concisely
robintown Jul 30, 2026
00c0b07
Provide a transport example
robintown Jul 30, 2026
aa2d746
Clarify why we proscribe a deterministic slot ID grammar
robintown Jul 30, 2026
3236b00
Merge branch 'toger5/matrixRTC' into travis/msc4143/rtc-registry
robintown Jul 30, 2026
595ef84
Fix typo
Johennes Aug 17, 2026
2a45b77
Link to MSC4531 for deprecating legacy VoIP
Johennes Aug 18, 2026
adb8fa5
Remove transport provisioning alternatives now that transport discove…
Johennes Aug 18, 2026
cea5014
Clarify that m.per_member is defined in the text following
Johennes Aug 18, 2026
5495f4b
Clarify that cross-signing refers to the owner
Johennes Aug 18, 2026
a67a217
Fix to-device message snippet
Johennes Aug 18, 2026
44caf05
Move format inside of media_key object
Johennes Aug 18, 2026
e2a64eb
Clarify what cryptographically secure means
Johennes Aug 18, 2026
98e5783
Clarify why encryption in unencrypted rooms is disallowed
Johennes Aug 18, 2026
39c144d
Clarify that slots MUST be considered closed
Johennes Aug 18, 2026
6b414dd
format=0 -> format=m.base64
Johennes Aug 19, 2026
6c054fb
Fix typo
Johennes Aug 19, 2026
95f8be6
Clarify coalescing key rotations on leaves
Johennes Aug 25, 2026
3e3d084
Stress that the member ID must be unique across devices
Johennes Aug 26, 2026
1e41430
Clients should store keys even if the membership event is not yet known
Johennes Aug 26, 2026
59c3f98
Recommend one hour of stickyness
Johennes Aug 27, 2026
0e473cb
Membership events can be redacted to kick members
Johennes Aug 27, 2026
d6133e4
Agreeing on transports is out of scope
Johennes Aug 27, 2026
c3d05cf
PRNG -> RNG + notes on why we use a transport agnostic key agreement …
Johennes Aug 28, 2026
51c8dfe
livekit -> m.livekit
Johennes Aug 31, 2026
af59d73
Ignore unencrypted streams in encrypted slots; call out unmappable st…
Johennes Sep 1, 2026
db289df
Fix typo
Johennes Sep 1, 2026
99bb791
m.call#ROOM -> m.call#room
Johennes Sep 1, 2026
c194030
Eliminate dependency on MSC4519 and move transport discovery back int…
Johennes Sep 2, 2026
d544107
Clarify that member IDs must be unique across rooms and slots as well
Johennes Sep 2, 2026
8f8601f
Member IDs must be non-deterministic
Johennes Sep 2, 2026
fda56fc
Replicate slots on room upgrades
Johennes Sep 3, 2026
5b86183
Changing room encrypting can invalidate existing slots
Johennes Sep 7, 2026
469940f
Fix typo
Johennes Sep 9, 2026
148fe38
Fix typo
Johennes Sep 9, 2026
1163ae1
Clarify ordering in /transports
Johennes Sep 9, 2026
540849b
Add missing application.type requirement
Johennes Sep 9, 2026
bdd63a5
Clarify why member_id is sufficient for disambiguating slots
Johennes Sep 9, 2026
eefcc38
Remove format
Johennes Sep 9, 2026
a741a25
Clarify handling of unencrypted rooms
Johennes Sep 9, 2026
9a6f8d4
Clarify how to obtain device IDs from encrypted messages and link to …
Johennes Sep 9, 2026
82b790e
Make transports responsible for the key length
Johennes Sep 9, 2026
d5fe303
Fix typo
Johennes Sep 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
278 changes: 278 additions & 0 deletions proposals/4143-matrix-rtc.md

@Johennes Johennes Jul 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Implementation requirements:

  • Client
  • Server

@Johennes Johennes Jul 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This proposal and its implementations have an extensive history that went through multiple iterations. Current implementations are linked below using pull requests wherever possible. In some cases though, direct links into the source code were more practical and have been used instead.

To test MatrixRTC with the currently implemented versions of #4196 and #4195, you need a homeserver that has implemented and enabled #4140 and #4354. The server also needs to have https://github.com/element-hq/lk-jwt-service and a LiveKit SFU configured and advertised. Within the developer options of Element Call you can then force the Matrix 2.0 mode.

Slots

Membership

Note

The JS SDK still uses the properties user_id and device_id in the member object of m.rtc.member events. These have been eliminated in the MSC as they can be deduced by other / more secure means.

Similarly, the SDK still includes the versions property and m.reference relations when sending m.rtc.member events. These have been removed from the MSC as they were unneeded.

The member.membership property of m.rtc.member events is not implement. Instead the JS SDK treats the absence of the application object as implicitly left.

Equally, the leave_reason code slot_closed has not yet been implemented. It blocks on the combination of matrix-org/matrix-js-sdk#5445 and matrix-org/matrix-js-sdk#5437.

Transport discovery

Note

The endpoint uses rtc_transports rather than transports as the property name in its response.

When ran in widget mode, Element Call cannot yet use the /transports endpoint because the widget API doesn't expose access to it. This is covered by #4515.

End-to-end encryption

Note

The JS SDK still relies on the (claimed) device_id property in m.rtc.member events while the MSC has eliminated claimed_device_id and instead infers the device ID from authenticated properties obtained in the decryption process of m.rtc.member events.

Instead of m.rtc.encryption_key, the JS SDK uses the legacy event type io.element.call.encryption_keys with a slightly different but equivalent schema.

Additionally, the JS SDK generates 16-byte instead 32-byte keys.

Discarding unencrypted to-device key messages and verifying the to-device message sender and device ID against the m.rtc.member event are not yet implemented in the JS SDK. These block on changes to the widget API (https://github.com/element-hq/voip-internal/issues/651 / https://github.com/element-hq/voip-internal/issues/655).

Finally the format property used in the implementation was removed from the MSC.

Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
# MSC4143: MatrixRTC
Comment thread
Johennes marked this conversation as resolved.
Outdated

This MSC defines the modules with which the MatrixRTC (Matrix Real Time Communication) signalling system is built.

The MatrixRTC specification is separated into different modules.

- The MatrixRTC room state that defines the state of the real time application.\
It is the source of truth for:
- Who is part of a session
- Who is connected via what technology/backend
- Metadata per device used by other participants to decide whether the streams
from this source are of interest / need to be subscribed.
- The RTC backend.
- It defines how to connect the participating peers.
- Livekit is the standard for this as of writing.
- Defines how to connect to a server/other peers, how to update the connection,
how to subscribe to different streams...
- Another planned backend is a full mesh implementation based on MSC3401.
- The RTCSession types (application) have their own per application spec.
- Calls can be done with an application of type `m.call` see (TODO: link call msc)
- The application defines all the details of the RTC experience:
- How to interpret the metadata of the member events.
- What streams to connect to.
- What data in which format to sent over the RTC channels.

This MSC will focus on the Matrix room state, which can be seen as the most high
level signalling of a call:

## Proposal

Each RTC session is made out of a collection of `m.rtc.member` state events.
Each `m.rtc.member` event defines the application type: `application`
and a `call_id`.
The first element of the state key is the `userId` and the second the `deviceId`.
(see [this proposal for state keys](https://github.com/matrix-org/matrix-spec-proposals/pull/3757#issuecomment-2099010555)
for context about second/first state key.)

### The MatrixRTC room state

Everything required for working MatrixRTC
(current session, sessions history, join/leave events, ...) only
require one event type.

A complete `m.rtc.member` state event looks like this:

```json5
// event type: "m.rtc.member"
// event key: "@user:matrix.domain_DEVICEID"
{
"application": "m.my_session_type",
"call_id": "",
"device_id": "DEVICEID",
"created_ts": Time | undefined,
"expires_after": Duration,
"focus_active": {...FOCUS_A},
"foci_preferred": [
{...FOCUS_1},
{...FOCUS_2}
]
}
```

> [!NOTE]
> This relies on [MSC3757](https://github.com/matrix-org/matrix-spec-proposals/pull/3757).
Comment thread
toger5 marked this conversation as resolved.
Outdated
> We need to have one state event per device, hence multiple "non-overwritable" state
> events per user.

This gives us the information, that user: `@user:matrix.domain` with device `DEVICEID`
is part of an RTCSession of type `m.call` in the scope/sub-session `""` (empty
string as call id) connected over `FOCUS_A`. This is all information that is needed
for another room member to detect the running session and join it.

We include the device_id in the member content to not rely on the exact format of the state key.
In case [MSC3757](https://github.com/matrix-org/matrix-spec-proposals/pull/3757) is used it would not
be the second element of the state key array.

`created_ts` is an optional property that caches the time of creation. It is not required
for an event that, has not yet been updated, there the `origin_server_ts` is used.

> [!NOTE]
> We introduce `created_ts()` as the notation for `created_ts ?? origin_server_ts`

Once the event gets updated, the origin_server_ts needs to be copied into the `created_ts` field.
An existing `created_ts` field implies that this is a state event updating the current session
and a missing `created_ts` field implies that it is a join state event.
All membership events that belong to one member session can be grouped with the index
`created_ts()`+`device_id`. This is why the `m.rtc.member` events deliberately do NOT include a `membership_id`.

Other then the membership sessions, there is **no event** to represent a rtc session (containing all members).
Such an event would include shared information, and deciding who has authority over that is not trivial.
Comment thread
Johennes marked this conversation as resolved.
Outdated
Instead the session is a computed value based on `m.rtc.member` events.
The list of events with the same `application` and `m.call_id` represent one session.
This array allows to compute fields such as participant count, start time, etc.

Sending an empty `m.rtc.member` event represents a leave action.
Sending a well formatted `m.rtc.member` represents a join action.

Based on the value of `application`, the event might include additional parameters
required to provide additional session parameters.

> A [thirdroom](https://thirdroom.io)-like experience could include the information of an approximate position
> on the map, so that clients can omit connecting to participants that are not in their
> area of interest.

#### Reliability requirements for the room state

Room state is a very well suited place to store the data for a MatrixRTC session, as
it allows:

- The client to determine current ongoing sessions without loading history for every room,
or doing additional work other than the sync loop that needs to run anyway.
- The client can compute/access data of past sessions without any additional redundant data.
- Sessions (start/end/participant count) are federated and there is not redundant data storage that
could result in conflicts, or can get out of sync. The room state events are part of the dag and this
is solved like any other PDU in matrix.

A challenge with using the room state to represent a session is disconnection behaviour.
If the client disconnects from a call because of a network issue,
an application crash, or a user forcefully quitting the client - then the room state cannot be updated any more.
The client is required to leave by sending a new empty state which cannot happen once connection is lost.

If the state is not updated correctly we end up with incorrect session end timestamps, and a room state that is not
correctly representing the current RTC session state. Historic and current MatrixRTC session data would be broken.

For an acceptable solution, the following requirements need to be taken into consideration:

- Room state is set to empty if the client loses connection. (A heardbeat like system is desired)
- The best source of truth for a call participation is a working connection to the SFU.
It is desired that the disconnect of the SFU is connected to the room state.
- It should be possible to update the room state without the client being online.
- All of this should still work when Matrix uses cryptographic identities (e.g.
[MSC4080](https://github.com/matrix-org/matrix-spec-proposals/pull/4080)).

[MSC4140](https://github.com/matrix-org/matrix-spec-proposals/pull/4140) proposes a concept to
delay the leave events until one of the leave conditions (heartbeat or SFU disconnect) occur
and fulfil all of the these requirements.

A MatrixRTC client has to first send/schedule the following delayed leave event:

```json5
// event type: "m.rtc.member"
// event key: "@user:matrix.domain_DEVICEID"
{
"leave_reason": "CONNECTION_LOST"
Comment thread
Johennes marked this conversation as resolved.
Outdated
}
Comment thread
Johennes marked this conversation as resolved.
```
Comment thread
BillCarsonFr marked this conversation as resolved.

Subsequently, the actual state event can be sent, so that we guarantee that the state will be empty eventually.
The `leave_reason` is added so clients can be more verbal about why a user disconnected from a call.

Receiving clients will be able to detect if the delayed event request was recognised by the presence of the `has_delayed_overwrite: true`
unsigned property. If the property is missing the event is invalid.

This also ensures that delayed leave events that are incorrectly sent with a non-empty membership content are invalidated,
as they will not contain the `has_delayed_overwrite: true` unsigned property.

#### Historic sessions

Since there is no single entry for a historic session (because of the ownership ambiguity),
historic sessions need to be computed on the client.

Each state event can either mark a join or leave:

- join: `prev_state.application != current_state.application` &&
`prev_state.m.call_id != current_state.m.call_id` &&
`current_state.application != undefined`
(where an empty `m.rtc.member` event would imply `state.application == undefined`)
- leave: `prev_state.application != current_state.application` &&
`prev_state.m.call_id != current_state.m.call_id` &&
`current_state.application == undefined`

Based on this one can find user sessions. The range between a join and a leave
event gives the specific times and duration of the session.
The collection of all overlapping user sessions with the same `call_id` and
`application` define one MatrixRTC history event.

### The RTC backend

`foci_active` and `foci_preferred` are used to communicate:

- how a user is connected to the session (`foci_active`)
- what connection method this user knows about would like to connect with.

The only enforced parameter of a `foci_preferred` or `foci_active` is `type`.
Based on the focus type a different amount of parameters might be needed to,
communicate how to connect to other users.
`foci_preferred` and `foci_active` can have different parameters so that it is,
possible to use a combination of the two to figure our that everyone is connected
with each other.

Only users with the same type can connect in one session. If a frontend does
not support the used type they cannot connect.

Each focus type will get its own MSC, describing how to get from the foci
information to establishing WebRTC connections for all participants.

- [`livekit`](www.example.com) TODO: create `livekit` focus MSC and add link here.
- [`full_mesh`](https://github.com/matrix-org/matrix-spec-proposals/pull/3401)
TODO: create `full-mesh` focus MSC based on[MSC3401](https://github.com/matrix-org/matrix-spec-proposals/pull/3401)
and add link here.

#### Sourcing `foci_preferred`

At some point participants have to decide/propose which focus they use.
Based on the focus type and use case choosing a `foci_preferred` can be different.
If possible these guidelines should be obeyed:

- If there is a relation between the `focus_active` and a preferred focus (`type: livekit` is an example for this)
it is recommended to copy _the preferred focus that relates to the current `focus_active`_ of other participants to
the start of the `foci_preferred` array of the member event.
(The exact definition of: _the preferred focus that relates to the current `focus_active`_ is part of the
specification for each focus type. For `full_mesh` for example there is no such thing as: _the preferred focus that
relates to the current `focus_active`_ )
- Homeservers can proposes `preferred_foci` via the well known. An array of preferred foci is provided behind the well
known key `m.rtc_foci`. This is defined in [MSC4158](https://github.com/matrix-org/matrix-spec-proposals/pull/4158).
They are related and it is recommended to also read
[MSC4158](https://github.com/matrix-org/matrix-spec-proposals/pull/4158) with this MSC.
Those proposals from **your own** homeserver should come next in the `foci_preferred` list of the member event.
- Clients also have the option to configure a preferred foci even though this is not recommended (see below).
Those come last in the list.

The rationale for these guidelines are:

- It is always desired to have as few focus switches as possible.
That is why the highest priority is to prefer the focus that is already in use.
- MatrixRTC is designed around the same architecture as the rest of Matrix, with
conversations being powered by many homeservers from across the network.
MatrixRTC has the same goal. To achieve a stable and healthy ecosystem
RTC infrastructure should be thought of as a part of a homeserver. It is very similar
to a turn server: mostly traffic and little cpu load.
To not end up in a world where each user is only using one central SFU but where the traffic
is split over multiple SFU's it is important that we leverage the SFU distribution similarly to the
distribution of homeservers.
For this reason the second guideline is to lookup the preferred foci from the homeserver's well_known.
- Looking up the preferred foci from a client is toxic to a federated system. If the majority of users
decide to use the same client all of the users will use one focus. This destroys the passive security mechanism that
each instance is not an interesting attack vector since it is only a fraction of the network.
Additionally it will result in poor performance if every user on Matrix would use the same focus.
There are cases where this is acceptable:
- Transitioning to MatrixRTC. Here it might be beneficial to have a client that has a fallback focus
so calls also work with homeservers not supporting it.
- For testing purposes where a different focus should be tested but one does not want to touch the .well_known
- For custom deployments that benefit from having the Focus configuration on a per client basis instead of per homeserver.

### The RTC Session types (application)

Each session type can have its own specification in how the different streams
are interpreted and even what focus type to use. This makes this proposal extremely
flexible. For instance, a Jitsi conference could be added by introducing a new `application`
and a new focus type and would be MatrixRTC compatible. It would not be compatible
with applications that do not use the Jitsi focus but clients would know that there
is an ongoing session of unknown type and unknown focus and could display/represent
this in the user interface.

To make it easy for clients to support different RTC session types, the recommended
approach is to provide a Matrix widget for each session type, so that client developers
can use the widget as the first implementation if they want to support this RTC
session type.

Each application should get its own MSC in which the all the additional
fields are explained and how the communication with the possible foci is
defined:

- [`m.call`](www.example.com) TODO: create `m.call` MSC and add link here.
Comment thread
Johennes marked this conversation as resolved.
Outdated

## Potential issues
Comment thread
Johennes marked this conversation as resolved.

## Alternatives

## Security considerations
Comment thread
Johennes marked this conversation as resolved.

## Unstable prefix
Comment thread
Johennes marked this conversation as resolved.

The state events and the well_known key introduced in this MSC use the unstable prefix
`org.matrix.msc4143.` instead of `m.` as used in the text.
Comment thread
Johennes marked this conversation as resolved.
Outdated

Possible values inside the `m.rtc.member` event (like `m.call`) will use a prefix defined in the
related PR (TODO create and link `m.call` application type PR)