From aafbb1a85db51da6a85d7034708de95ae3582e41 Mon Sep 17 00:00:00 2001 From: Logan Devine Date: Thu, 25 Jun 2026 13:56:32 -0700 Subject: [PATCH 01/12] MSCXXXX: Selective Presence Co-authored-by: Tyler J. Russell Co-authored-by: Henry-Hiles Co-authored-by: timedout Co-authored-by: stratself <126093083+stratself@users.noreply.github.com> Co-authored-by: 31a05b9c Co-authored-by: 7w1 Signed-off-by: Logan Devine --- proposals/xxxx-selective-presence.md | 428 +++++++++++++++++++++++++++ 1 file changed, 428 insertions(+) create mode 100644 proposals/xxxx-selective-presence.md diff --git a/proposals/xxxx-selective-presence.md b/proposals/xxxx-selective-presence.md new file mode 100644 index 00000000000..fefc9ac952c --- /dev/null +++ b/proposals/xxxx-selective-presence.md @@ -0,0 +1,428 @@ +# MSCXXXX: Selective Presence + +Presence is widely known to be one of the most expensive features in the Matrix specification. Even with continued +efforts to improve server implementations[^1][^2], large public deployments still disable outbound federated +presence, citing its substantial performance impact. Presence, as it stands, is fundamentally flawed: users receive +presence EDUs for every user they share a room with, even if the users have never interacted or have no interest in +each other's presence; server operators often have no choice but to disable presence altogether to limit the +excessive federation load; and users who do _not_ want to share potentially trackable information with public, +federated rooms \- a limitation [acknowledged by the current specification][presence-v1-privacy] \- the only option +they typically have is to, again, disable presence outright. + +This proposal introduces "Selective Presence," a system for users to decide precisely _who_ their +presence is shared with. The benefits of this are twofold: +1. the overall load on homeservers implementing presence is reduced substantially, as users only share their + presence with interested parties, and +2. users benefit from improved privacy by only sharing such sensitive information with those they want to have + access to it. + +## Prior Art + +Prior to [MSC1819], a mechanism known as "presence lists" allowed users to subscribe to others' presence. In +theory, it also offered a mechanism for other users to request your presence. However, Synapse historically +[accepted all presence requests automatically][#4417], ultimately resulting in the feature's removal prior to r0. + +[MSC4325: Presence privacy][MSC4325] attempts to solve this problem by reintroducing a concept similar to Selective +Presence. However, MSC4325 lacks some features integral to this proposal's goal of keeping UX similar to the +current approach; room hints, for example, allow rooms to recommend that clients prompt users about whether they +would like to share their presence, or forbid sharing presence altogether. This keeps presence usable for small +communities, private rooms, and DMs, while reducing the load from federating presence in large public rooms. + +## Proposal + +### User Presence Sharing Preferences + +A new [`account_data`] entry, `m.presence.sharing`, is stored for modification by clients and use by homeservers. + +This event contains four fields: +* The boolean `share_locally` enables sharing presence with all users with mutual rooms on the local homeserver + (default `false`) +* Three **presence sharing map** objects, mapping one of several entity types to presence sharing behaviour: + 1. `users` mapping [User IDs][mxid-format] (default `{}`) + 2. `rooms` mapping [Room IDs][roomid-format] (default `{}`) + 3. `servers` mapping [Server Names][servername-format] (default `{}`) + +While homeservers SHOULD follow these defaults, operators and implementations MAY override them where appropriate. +For example, an operator may default `share_locally` to `true` in an organisation environment. + +No glob resolution is supported for any key in a presence sharing map. + +The string values of these presence sharing maps may be any of the following: +* `"deny"`: Explicitly forbid sending presence to the entity + The `"deny"` state MUST NOT be specified for room IDs under the `"rooms"` object. +* `"allow"`: Permit sharing presence with the entity + The `"allow"` state MUST NOT be specified for entire homeservers under the `"servers"` object. + +Servers MUST treat users without `m.presence.sharing` in their `account_data` as though the default values were +specified. + +Sample `m.presence.sharing` account data event: +```json +{ + "share_locally": true, + "users": { + "@alice:example.com": "allow", + "@mallory:example.com": "deny", + }, + "rooms": { "!family-group-chat": "allow" }, + "servers": { "matrix.org": "deny" } +} +``` + +### Room Presence Sharing Hints + +A new room state event is introduced, `m.room.presence_sharing`. This state event contains one field, +`presence_sharing`, which is a string with two possible values: `"suggest"` and `"forbid"`. If the event is not +present, the room is treated as though its value is `"forbid"` by default. + +Servers MUST NOT include rooms with a `presence_sharing` value of `"forbid"` when they calculate a user's recipient +user set, even if the user `"allow"`s presence to be shared with the room. + +#### Presence Sharing Prompts + +A new [`account_data`] entry, `m.presence.prompted`, is introduced to improve the user experience for clients with +presence sharing prompts. To allow users to dismiss a prompt on one client and have this register across all of +their clients, so that they do not have to answer the prompt several times, the following standard fields are +used: +* `users`: An array of [User IDs][mxid-format] (default `[]`) +* `rooms`: An array of [Room IDs][roomid-format] (default `[]`) + +Sample `m.presence.prompted` account data event: +```json +{ + "users": [ + "@joey:example.com", + "@chandler:example.com", + ], + "rooms": ["!apartment-group-chat"] +} +``` + +Clients implementing presence sharing prompts SHOULD show a prompt resembling "Would you like to share your +presence with this room?" for a relevant entity, which is the user in an `m.direct` room with **exactly one** other +joined user or the room itself otherwise, in the following circumstances: +* The room's `presence_sharing` is set to `"suggest"` +* The relevant entity is not in the user's corresponding `m.presence.prompted` array or `m.presence.sharing` map + +Clients MAY wish to check room predecessor chains to avoid showing previously dismissed prompts in upgraded rooms. +They MUST NOT prompt the user to share presence in a room with a `presence_sharing` value of `"forbid"`. + +#### Room Defaults + +[`POST /_matrix/client/v3/create_room`][cs-createroom] SHOULD use the `preset` parameter to set the +`m.room.presence_sharing` state event in created rooms to the following template values: + +| room creation `preset` | `m.room.presence_sharing` | +| ---------------------- | ----------------------------------- | +| `private_chat` | `{ "presence_sharing": "suggest" }` | +| `trusted_private_chat` | `{ "presence_sharing": "suggest" }` | +| `public_chat` | `{ "presence_sharing": "forbid" }` | + +### Modifications to the [`m.presence` EDU] + +The federation [User Presence Update] type is modified to include: +* An optional map, `recipients`, containing two populated arrays of [User IDs][mxid-format] belonging to the + destination server, `add` and `del`. +* A pair of integer identifiers, `stream_id` and `prev_id`, which are unique per `user_id`. These values do not need to + be sequential or in any particular order, only unique. + +`stream_id` and `prev_id` form a sequence representing the state of the user's recipient user set, similar to the +behaviour of the [Device List Update] type. `recipients` may only be present if `prev_id` is present. If a user's +`stream_id` is incremented but no changes are relevant to the receiving homeserver, the sending server uses empty `add` +and `del` lists. + +A server MUST NOT send updates lacking `add` to a destination homeserver after their last user is updated out of the +recipient set. + +`m.presence` EDU (as received by `example.com`): +```json +{ + "content": { + "push": [ + { + "currently_active": true, + "last_active_ago": 5000, + "presence": "online", + "status_msg": "Making cupcakes", + "user_id": "@john:matrix.org", + "recipients": { + "add": ["@alice:example.com"], + "del": ["@geoff:example.com"], + }, + "stream_id": 1, + "prev_id": 0, + } + ] + }, + "edu_type": "m.presence" +} +``` + +#### Dispatch Algorithm + +The **recipient user set** of a user's presence transition is determined as follows: +1. Include all members of rooms both **listed as `"allow"`** in the user's `m.presence.sharing` configuration and + with an `m.room.presence_sharing` state event with `presence_sharing` set to `"suggest"`. Servers MUST NOT + include rooms that do not satisfy this criteria. +2. Exclude any user IDs with a server name corresponding to **any server listed as `"deny"`** in the user's + `m.presence.sharing` configuration. +3. Include all local users if the user's `m.presence.sharing` configuration has `share_locally` set to `true`. + Servers SHOULD only include local users that the sender shares at least one room with. +4. Include all **users listed as `"allow"`** in the user's `m.presence.sharing` configuration. Servers SHOULD only + include users from this list that the sender shares at least one room with. +5. Exclude any **users listed as `"deny"`** in the user's `m.presence.sharing` configuration. + +Determine the delta from the previous recipient user set. If there is no previous state, the entire set is an addition. +If the recipient user set is left unchanged, emit a presence EDU using only the prior `stream_id` \- no `recipients`, +no `prev_id`. Otherwise, generate a `stream_id` for the new state. For each server name represented in these updates, +emit a presence EDU with `prev_id` set to the last `stream_id` sent to that destination if applicable, `stream_id` set +according to the new state, and `recipients` populated with the updates. + +#### Inbound Processing + +When a server receives a `m.presence` EDU over federation, servers follow these rules for distributing the presence +change over both `/sync` and `/_matrix/client/v3/presence/{userId}/status`: +* **`stream_id` missing:** Servers SHOULD distribute the presence transition to every local user that shares a room + with the `user_id` of the EDU, following current presence behaviour. +* **`recipients` missing, `prev_id` missing:** If `stream_id` matches the server's latest known ID, it MUST reuse + its current view of the recipient user set to distribute the presence change to users in the set. +* **`recipients` present, `prev_id` missing:** Servers MUST initialise this as a new set using `recipients` if they + have no existing state for the user, and only distribute the presence change to users added by `recipients`. +* **`recipients` present, `prev_id` present:** Servers MUST apply the delta to the set corresponding to `prev_id` + and only distribute the presence change to users in the resulting set, superseding `prev_id` in the process. + +For cases where `prev_id` is present but is not the previous `stream_id`, or `stream_id` is present on its own but +unrecognised, servers SHOULD query the `GET /_matrix/federation/v1/query/presence_recipients` endpoint on the origin +server. + +### Server-Server Endpoint `GET /_matrix/federation/v1/query/presence_recipients` + +Servers that do not recognise a `stream_id` or `prev_id` in an incoming `m.presence` EDU need a way to ask the +origin server for the user's latest `stream_id` and a snapshot of its recipient user set. This proposal introduces +a new federation endpoint to address this need. If a server is unable to determine the proper recipient user set +(for example, if this endpoint returns an error), servers SHOULD treat it as the empty set, `[]` until it is able +to fetch the full list. + + + + + + + + + + + + +
Rate limited:No
Requires authentication:Yes
+ +#### Request + +##### Request parameters + +| Name | Type | Description | +|-----------|----------|----------------------------------------------------------------------------| +| `user_id` | `string` | **Required:** The user ID to query. Must be local to the queried server. | + +#### Responses + +| Status | Description | +|--------|--------------------------------------------------------------------------------------------| +| `200` | The corresponding user's latest `stream_id` and recipient user set for the sending server. | +| `404` | The user does not have a recipient set available for the sending server. | + +The 404 response uses the same format as in the existing query endpoints. + +##### 200 response + +| Name | Type | Description | +|--------------|-----------------------------|----------------------------------------------------------------------------------| +| `stream_id` | `integer` | **Required:** A unique identifier for the user's current recipient user set. | +| `recipients` | `[`[`User`][mxid-format]`]` | **Required:** An array of local recipients the user intends to push presence to. | + +```json +{ + "stream_id": 1, + "recipients": [ + "@jesse:example.com", + "@jane:example.com" + ] +} +``` + +## Potential issues + +### Presence Access + +Selective Presence *disables presence by default*. This may complicate future proposals that require publicly +accessible presence information, and may change the way users interact with presence features. However, as +previously mentioned, presence should not be public by default. A future proposal may address public, fetchable +presence (see [Alternatives](#Alternatives)). + +### Presence Data "Leaks" + +* Presence information may be exposed to unintended or undesirable users by bad-acting servers if any of their + users are included in the recipient user set. This proposal is a best-effort approach and cannot combat this. +* Presence information may be exposed to unintended or undesirable users by the user's own homeserver, for instance + if the administrator modifies their account data to trick them. +* Remote homeservers may deduce parts of users' exclusion lists probabilistically. The scope of this is limited by + only sending relevant data to each homeserver. +* The introduced account data for exclusion lists is sensitive and not encryptable (as in [MSC4483]), but this is + information the server would likely know by other means (e.g. [`m.ignored_user_list`]) + +### Lack of Presence Requests + +Prior to [MSC1819], Presence Lists provided for a "presence request" feature. This may be desirable in the future, +but it is considered out of scope for this proposal. + +### Performance + +Homeserver operators and implementers may wish to limit the performance impacts of presence, particularly as the +goal of Selective Presence is to make presence viable for popular use. Potential options for doing so may include: +* Limiting the ability of users to share presence with rooms above a certain number of members +* Limiting the number of entities (or total recipient users) users can have in their presence sharing maps + +### Presence EDU Batch Sizes + +Homeserver implementations or the specification may, in future, limit EDU sizes in the same way PDU sizes are limited. +This proposal does not specify a strict limit on batch sizes because it is currently unclear what the size limit of EDUs +may be, so a batch size will need to be specified if this happens. If the limit turns out to be 64KiB, as it is for +PDUs, and assuming the `status_msg` stays within 255 bytes, you cannot fit more than 250 full 255 byte entities into a +presence EDU with a single state transition. + +## Alternatives + +### Pull-based Presence + +A pull-based system leads to unnecessary requests over federation on polling intervals when no presence updates are +available, creating inefficiencies that may be intolerable for mainstream use and still requiring access control to +achieve any privacy benefits. An auxiliary fetchable presence system is considered complementary follow-up work to +allow users to make their presence public. + +### Receiver Resolution + +Instead of sending a finalised list of recipient users to remote servers, the user's preferences (allowed rooms and +users, denied users) could be sent over federation. This proposal uses sender-side user resolution to avoid sending +a "block list" to third parties, and to keep resolution consistent with the sending homeserver's state. + +### Entity Selection Affordances + +Servers could be permitted in the inclusion list, and rooms could be permitted in the exclusion list. The authors +of this proposal found no reason for doing so. In organisation environments where it may be desired to share +presence with an entire homeserver, users are almost certainly on the same local homeserver, where `share_locally` +applies, or share a room with everyone in the organisation, which the users can set as `"allow"`. Excluding a room +has no practical benefits as users can simply not include it in the configuration. + +### Entity Resolution Ordering + +The inclusion and exclusion lists could be applied in different orders; for example, if a user of a homeserver is set to +`"allow"`, and the homeserver is set to `"deny"`, should the user become an exception, or should the whole homeserver be +prevented from receiving the presence? It was decided that users should always be the overriding rule, otherwise a user +wouldn't explicitly `"allow"` them, and only allowing one other entity type for either option prevents conflicts. + +### Per-Room Hint Following + +In this proposal, the `"allow"` state means "follow the room's hint state." Instead, the user's configuration could +be decoupled from room hints, meaning users could broadcast their presence to all users of a room regardless of +whether the room administrators have enabled the hint. This can create issues in large rooms and conflicts with the +recommendation purpose of the hints system. + +Allowing room administrators to suggest that their members share presence means users can still see presence for +members of small rooms (assuming they opt in to this behaviour) without explicitly creating user lists. These are +the rooms where presence matters most: small groups of friends, organisation environments, etc. + +Only allowing users to follow hints via `"allow"` means a `"forbid"` hint state explicitly forbids presence sharing +for all users of a room. This allows room administrators to retroactively *disable* presence sharing for rooms as +they grow; for example, if a previously private room grows to be public and contain many members, a room +administrator may wish to disable presence sharing in the room. + +### `m.room.presence_sharing` states + +There are multiple potential states for room hints, and just as many potential defaults. It was ultimately +determined that this proposal should only specify the actual states of `"suggest"` or `"forbid"`, leaving the +decision of when to ask users if they would like to enable presence up to the clients. + +### Room Account Data + +It was proposed that a user's `m.presence.sharing` `"rooms"` configuration could live in room account data, but +this proposal opted against doing so to avoid fragmenting the configuration between different sources. + +### Fallback Behaviours + +#### Client-Server Sync + +If a server were to receive an EDU with no `stream_id`, it could either ignore the EDU, or sync it to clients of its +local users that share a room with the `user_id` in the EDU, as is the current behaviour. To preserve backwards +compatibility for older servers unaware of the `recipients` system, this proposal specifies that the current behaviour +should be invoked for these EDUs. The authors of this proposal intend for this fallback behaviour to be removed when a +sufficient proportion of the network has updated to use Selective Presence, which will entirely remove the excess +traffic of publicly broadcasted presence and allow implementers to simplify processing on receiving homeservers. + +#### Server-Server Dispatch + +If a user's `account_data` were missing `m.presence.sharing` configuration, the sending server could either invoke the +current behaviour by sending a presence EDU with no `stream_id`, or avoid sending presence for the user entirely. While +backwards compatibility is important where it is possible, allowing *clients* to induce this behaviour intentionally +would create a user-controlled bypass for Selective Presence altogether, defeating its purpose. Therefore, this proposal +opts to forbid sending presence for users that have not set an `m.presence.sharing` configuration. + +## Security considerations + +This proposal does not introduce any new security considerations as far as its authors are aware. + +## Future work + +The following complementary proposals are planned: +* Increasing presence TTLs and improving batching behaviour +* Fetchable presence, possibly involving [MSC4133]'s profile key-value fields +* Sliding Sync extension for presence +* Presence Requests + +## Unstable prefix + +| Stable identifier | Purpose | Unstable identifier | +| ------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------ | +| `recipients` | Recipient users to add and delete in federation presence EDU | `org.continuwuity.presence_v2.mscXXXX.recipients` | +| `stream_id` | Current recipient user set identifier federation presence EDU | `org.continuwuity.presence_v2.mscXXXX.stream_id` | +| `prev_id` | Previous recipient user set identifier in federation presence EDU | `org.continuwuity.presence_v2.mscXXXX.prev_id` | +| `m.presence.sharing` | `account_data` entry for presence sharing config | `org.continuwuity.presence_v2.mscXXXX.presence.sharing` | +| `m.presence.prompted` | `account_data` entry for persisting presence hint prompt responses | `org.continuwuity.presence_v2.mscXXXX.presence.prompted` | +| `m.room.presence_sharing` | Room state event for presence sharing hint | `org.continuwuity.presence_v2.mscXXXX.room.presence_sharing` | + +Servers may advertise support for Selective Presence by listing `org.continuwuity.presence_v2.mscXXXX` in the +`unstable_features` section of the response to [`GET /_matrix/client/versions`][cs-versions]. + +The stable endpoint `/_matrix/federation/v1/query/presence_recipients` will use the unstable identifier +`/_matrix/federation/unstable/org.continuwuity.presence_v2.mscXXXX/query/presence_recipients`. + +Once this proposal completes FCP, servers may advertise support for the stable identifiers by listing +`org.continuwuity.presence_v2.mscXXXX.stable` in `unstable_features`; clients may use this while they +are waiting for the server to adopt a version of the spec that includes it. + +## Dependencies + +None. + +[^1]: Synapse has had a meta-issue open about improving presence performance for 5 years: [#9478] +[^2]: Since 2018, homeserver operators have had performance concerns related to presence, and even raised them + as bugs in Synapse. [#3971] [#9339] + +[#3971]: https://github.com/matrix-org/synapse/issues/3971 +[#4417]: https://github.com/matrix-org/synapse/issues/4417 +[#9339]: https://github.com/matrix-org/synapse/issues/9339 +[#9478]: https://github.com/matrix-org/synapse/issues/9478 +[MSC1819]: https://github.com/matrix-org/matrix-spec-proposals/pull/1819 +[MSC4133]: https://github.com/matrix-org/matrix-spec-proposals/pull/4133 +[MSC4325]: https://github.com/matrix-org/matrix-spec-proposals/pull/4325 +[MSC4483]: https://github.com/matrix-org/matrix-spec-proposals/pull/4483 +[presence-v1-privacy]: https://spec.matrix.org/v1.17/client-server-api/#security-considerations-4 +[`m.presence` EDU]: https://spec.matrix.org/v1.18/server-server-api/#definition-mpresence +[User Presence Update]: https://spec.matrix.org/v1.18/server-server-api/#definition-mpresence_user-presence-update +[Device List Update]: https://spec.matrix.org/v1.18/server-server-api/#definition-mdevice_list_update_device-list-update +[mxid-format]: https://spec.matrix.org/v1.18/appendices/#user-identifiers +[roomid-format]: https://spec.matrix.org/v1.18/appendices/#room-ids +[servername-format]: https://spec.matrix.org/v1.18/appendices/#server-name +[`account_data`]: https://spec.matrix.org/v1.18/client-server-api/#client-config +[cs-versions]: https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientversions +[cs-createroom]: https://spec.matrix.org/v1.18/client-server-api/#post_matrixclientv3createroom +[`m.ignored_user_list`]: https://spec.matrix.org/v1.18/client-server-api/#mignored_user_list From 5db32672fa4f1a1f044b864160d3a65b21a351ef Mon Sep 17 00:00:00 2001 From: Logan Devine Date: Thu, 25 Jun 2026 14:20:20 -0700 Subject: [PATCH 02/12] Become MSC4495 Signed-off-by: Logan Devine --- ...presence.md => 4495-selective-presence.md} | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) rename proposals/{xxxx-selective-presence.md => 4495-selective-presence.md} (98%) diff --git a/proposals/xxxx-selective-presence.md b/proposals/4495-selective-presence.md similarity index 98% rename from proposals/xxxx-selective-presence.md rename to proposals/4495-selective-presence.md index fefc9ac952c..d2a45338c5e 100644 --- a/proposals/xxxx-selective-presence.md +++ b/proposals/4495-selective-presence.md @@ -1,4 +1,4 @@ -# MSCXXXX: Selective Presence +# MSC4495: Selective Presence Presence is widely known to be one of the most expensive features in the Matrix specification. Even with continued efforts to improve server implementations[^1][^2], large public deployments still disable outbound federated @@ -382,21 +382,21 @@ The following complementary proposals are planned: | Stable identifier | Purpose | Unstable identifier | | ------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------ | -| `recipients` | Recipient users to add and delete in federation presence EDU | `org.continuwuity.presence_v2.mscXXXX.recipients` | -| `stream_id` | Current recipient user set identifier federation presence EDU | `org.continuwuity.presence_v2.mscXXXX.stream_id` | -| `prev_id` | Previous recipient user set identifier in federation presence EDU | `org.continuwuity.presence_v2.mscXXXX.prev_id` | -| `m.presence.sharing` | `account_data` entry for presence sharing config | `org.continuwuity.presence_v2.mscXXXX.presence.sharing` | -| `m.presence.prompted` | `account_data` entry for persisting presence hint prompt responses | `org.continuwuity.presence_v2.mscXXXX.presence.prompted` | -| `m.room.presence_sharing` | Room state event for presence sharing hint | `org.continuwuity.presence_v2.mscXXXX.room.presence_sharing` | - -Servers may advertise support for Selective Presence by listing `org.continuwuity.presence_v2.mscXXXX` in the +| `recipients` | Recipient users to add and delete in federation presence EDU | `org.continuwuity.presence_v2.msc4495.recipients` | +| `stream_id` | Current recipient user set identifier federation presence EDU | `org.continuwuity.presence_v2.msc4495.stream_id` | +| `prev_id` | Previous recipient user set identifier in federation presence EDU | `org.continuwuity.presence_v2.msc4495.prev_id` | +| `m.presence.sharing` | `account_data` entry for presence sharing config | `org.continuwuity.presence_v2.msc4495.presence.sharing` | +| `m.presence.prompted` | `account_data` entry for persisting presence hint prompt responses | `org.continuwuity.presence_v2.msc4495.presence.prompted` | +| `m.room.presence_sharing` | Room state event for presence sharing hint | `org.continuwuity.presence_v2.msc4495.room.presence_sharing` | + +Servers may advertise support for Selective Presence by listing `org.continuwuity.presence_v2.msc4495` in the `unstable_features` section of the response to [`GET /_matrix/client/versions`][cs-versions]. The stable endpoint `/_matrix/federation/v1/query/presence_recipients` will use the unstable identifier -`/_matrix/federation/unstable/org.continuwuity.presence_v2.mscXXXX/query/presence_recipients`. +`/_matrix/federation/unstable/org.continuwuity.presence_v2.msc4495/query/presence_recipients`. Once this proposal completes FCP, servers may advertise support for the stable identifiers by listing -`org.continuwuity.presence_v2.mscXXXX.stable` in `unstable_features`; clients may use this while they +`org.continuwuity.presence_v2.msc4495.stable` in `unstable_features`; clients may use this while they are waiting for the server to adopt a version of the spec that includes it. ## Dependencies From 4534876654918cca792d495f5b1958cc988bb76d Mon Sep 17 00:00:00 2001 From: lveneris Date: Thu, 25 Jun 2026 23:31:43 +0100 Subject: [PATCH 03/12] Polish language for federation sections This also fixes a rogue "populated" in the EDU updates, which conflicted with the case where there are updates but not for a particular remote. Signed-off-by: L Veneris --- proposals/4495-selective-presence.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/proposals/4495-selective-presence.md b/proposals/4495-selective-presence.md index d2a45338c5e..e3b489fc1b0 100644 --- a/proposals/4495-selective-presence.md +++ b/proposals/4495-selective-presence.md @@ -121,18 +121,18 @@ They MUST NOT prompt the user to share presence in a room with a `presence_shari ### Modifications to the [`m.presence` EDU] The federation [User Presence Update] type is modified to include: -* An optional map, `recipients`, containing two populated arrays of [User IDs][mxid-format] belonging to the - destination server, `add` and `del`. +* An optional map, `recipients`, containing two arrays of [User IDs][mxid-format] belonging to the destination + server, `add` and `del`. * A pair of integer identifiers, `stream_id` and `prev_id`, which are unique per `user_id`. These values do not need to be sequential or in any particular order, only unique. `stream_id` and `prev_id` form a sequence representing the state of the user's recipient user set, similar to the behaviour of the [Device List Update] type. `recipients` may only be present if `prev_id` is present. If a user's -`stream_id` is incremented but no changes are relevant to the receiving homeserver, the sending server uses empty `add` +`stream_id` is replaced but no changes are relevant to the receiving homeserver, the sending server uses empty `add` and `del` lists. -A server MUST NOT send updates lacking `add` to a destination homeserver after their last user is updated out of the -recipient set. +A server MUST NOT send updates lacking a populated `add` to a destination homeserver after their last user is +updated out of the recipient set. `m.presence` EDU (as received by `example.com`): ```json @@ -191,17 +191,17 @@ change over both `/sync` and `/_matrix/client/v3/presence/{userId}/status`: * **`recipients` present, `prev_id` present:** Servers MUST apply the delta to the set corresponding to `prev_id` and only distribute the presence change to users in the resulting set, superseding `prev_id` in the process. -For cases where `prev_id` is present but is not the previous `stream_id`, or `stream_id` is present on its own but -unrecognised, servers SHOULD query the `GET /_matrix/federation/v1/query/presence_recipients` endpoint on the origin -server. +If `prev_id` is present but differs from the previous `stream_id`, or `stream_id` is present on its own but +unrecognised, servers SHOULD query the `GET /_matrix/federation/v1/query/presence_recipients` endpoint on the +origin server. ### Server-Server Endpoint `GET /_matrix/federation/v1/query/presence_recipients` Servers that do not recognise a `stream_id` or `prev_id` in an incoming `m.presence` EDU need a way to ask the origin server for the user's latest `stream_id` and a snapshot of its recipient user set. This proposal introduces -a new federation endpoint to address this need. If a server is unable to determine the proper recipient user set -(for example, if this endpoint returns an error), servers SHOULD treat it as the empty set, `[]` until it is able -to fetch the full list. +a new federation endpoint to address this need. If a server cannot determine the proper recipient user set \- for +example, if this endpoint returns an error \- it SHOULD be assumed to be empty (`[]`) until the server can fetch +the full set. From bee426874d85da06689c5d292b305af9a3595eb7 Mon Sep 17 00:00:00 2001 From: lveneris Date: Mon, 29 Jun 2026 15:51:18 +0100 Subject: [PATCH 04/12] Address phrasing feedback from @HarHarLinks Signed-off-by: L Veneris --- proposals/4495-selective-presence.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/proposals/4495-selective-presence.md b/proposals/4495-selective-presence.md index e3b489fc1b0..c8b7167f2c4 100644 --- a/proposals/4495-selective-presence.md +++ b/proposals/4495-selective-presence.md @@ -34,7 +34,7 @@ communities, private rooms, and DMs, while reducing the load from federating pre A new [`account_data`] entry, `m.presence.sharing`, is stored for modification by clients and use by homeservers. -This event contains four fields: +This event contains four properties: * The boolean `share_locally` enables sharing presence with all users with mutual rooms on the local homeserver (default `false`) * Three **presence sharing map** objects, mapping one of several entity types to presence sharing behaviour: @@ -82,7 +82,7 @@ user set, even if the user `"allow"`s presence to be shared with the room. A new [`account_data`] entry, `m.presence.prompted`, is introduced to improve the user experience for clients with presence sharing prompts. To allow users to dismiss a prompt on one client and have this register across all of -their clients, so that they do not have to answer the prompt several times, the following standard fields are +their clients, so that they do not have to answer the prompt several times, the following standard properties are used: * `users`: An array of [User IDs][mxid-format] (default `[]`) * `rooms`: An array of [Room IDs][roomid-format] (default `[]`) @@ -105,7 +105,8 @@ joined user or the room itself otherwise, in the following circumstances: * The relevant entity is not in the user's corresponding `m.presence.prompted` array or `m.presence.sharing` map Clients MAY wish to check room predecessor chains to avoid showing previously dismissed prompts in upgraded rooms. -They MUST NOT prompt the user to share presence in a room with a `presence_sharing` value of `"forbid"`. +They SHOULD carry settings over when starting and following a room upgrade. They MUST NOT prompt the user to share +presence in a room with a `presence_sharing` value of `"forbid"`. #### Room Defaults @@ -126,14 +127,15 @@ The federation [User Presence Update] type is modified to include: * A pair of integer identifiers, `stream_id` and `prev_id`, which are unique per `user_id`. These values do not need to be sequential or in any particular order, only unique. +The `add` and `del` arrays of `recipients` represent an incremental update to a user's recipient user set, adding +and removing users respectively. A server MUST NOT send updates lacking a populated `add` to a destination +homeserver after their last user is updated out of the recipient set. + `stream_id` and `prev_id` form a sequence representing the state of the user's recipient user set, similar to the behaviour of the [Device List Update] type. `recipients` may only be present if `prev_id` is present. If a user's `stream_id` is replaced but no changes are relevant to the receiving homeserver, the sending server uses empty `add` and `del` lists. -A server MUST NOT send updates lacking a populated `add` to a destination homeserver after their last user is -updated out of the recipient set. - `m.presence` EDU (as received by `example.com`): ```json { @@ -173,10 +175,10 @@ The **recipient user set** of a user's presence transition is determined as foll 5. Exclude any **users listed as `"deny"`** in the user's `m.presence.sharing` configuration. Determine the delta from the previous recipient user set. If there is no previous state, the entire set is an addition. -If the recipient user set is left unchanged, emit a presence EDU using only the prior `stream_id` \- no `recipients`, -no `prev_id`. Otherwise, generate a `stream_id` for the new state. For each server name represented in these updates, -emit a presence EDU with `prev_id` set to the last `stream_id` sent to that destination if applicable, `stream_id` set -according to the new state, and `recipients` populated with the updates. +If the recipient user set is left unchanged, emit a presence EDU using only the prior `stream_id` \- no `recipients`, no +`prev_id`. Otherwise, generate a `stream_id` for the new state. Emit a presence EDU for each destination of the +recipients in these updates, with `prev_id` set to the last `stream_id` sent to the destination if applicable, +`stream_id` set according to the new state, and `recipients` populated with the updates for the destination. #### Inbound Processing From 10aca0a2aeaa911ec26b592ebdf85ca3fc8b4a29 Mon Sep 17 00:00:00 2001 From: lveneris Date: Tue, 30 Jun 2026 19:06:34 +0100 Subject: [PATCH 05/12] Rename del -> delete --- proposals/4495-selective-presence.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/4495-selective-presence.md b/proposals/4495-selective-presence.md index c8b7167f2c4..e8cb4fba6ea 100644 --- a/proposals/4495-selective-presence.md +++ b/proposals/4495-selective-presence.md @@ -123,18 +123,18 @@ presence in a room with a `presence_sharing` value of `"forbid"`. The federation [User Presence Update] type is modified to include: * An optional map, `recipients`, containing two arrays of [User IDs][mxid-format] belonging to the destination - server, `add` and `del`. + server, `add` and `delete`. * A pair of integer identifiers, `stream_id` and `prev_id`, which are unique per `user_id`. These values do not need to be sequential or in any particular order, only unique. -The `add` and `del` arrays of `recipients` represent an incremental update to a user's recipient user set, adding -and removing users respectively. A server MUST NOT send updates lacking a populated `add` to a destination +The `add` and `delete` arrays of `recipients` represent an incremental update to a user's recipient user set, +adding and removing users respectively. A server MUST NOT send updates lacking a populated `add` to a destination homeserver after their last user is updated out of the recipient set. `stream_id` and `prev_id` form a sequence representing the state of the user's recipient user set, similar to the behaviour of the [Device List Update] type. `recipients` may only be present if `prev_id` is present. If a user's `stream_id` is replaced but no changes are relevant to the receiving homeserver, the sending server uses empty `add` -and `del` lists. +and `delete` lists. `m.presence` EDU (as received by `example.com`): ```json From 0d415c1d47633e7ad02bc3569bd374c7748cf45e Mon Sep 17 00:00:00 2001 From: lveneris Date: Tue, 30 Jun 2026 19:09:41 +0100 Subject: [PATCH 06/12] Add rationale for prohibiting globs --- proposals/4495-selective-presence.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proposals/4495-selective-presence.md b/proposals/4495-selective-presence.md index e8cb4fba6ea..9880ce84599 100644 --- a/proposals/4495-selective-presence.md +++ b/proposals/4495-selective-presence.md @@ -315,6 +315,10 @@ presence with an entire homeserver, users are almost certainly on the same local applies, or share a room with everyone in the organisation, which the users can set as `"allow"`. Excluding a room has no practical benefits as users can simply not include it in the configuration. +Globs were prohibited in presence sharing maps to avoid introducing security issues for servers running glob parsing on +arbitrary user-provided strings, and because users are not typically namespaced beyond servers in a way that would be +suitable for glob selection. + ### Entity Resolution Ordering The inclusion and exclusion lists could be applied in different orders; for example, if a user of a homeserver is set to From 098d72b902d480dafbb184e96e61591616e794e6 Mon Sep 17 00:00:00 2001 From: lveneris Date: Tue, 30 Jun 2026 19:13:38 +0100 Subject: [PATCH 07/12] Add note on servers respecting users' exclusion lists --- proposals/4495-selective-presence.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/proposals/4495-selective-presence.md b/proposals/4495-selective-presence.md index 9880ce84599..649024b1e61 100644 --- a/proposals/4495-selective-presence.md +++ b/proposals/4495-selective-presence.md @@ -42,8 +42,9 @@ This event contains four properties: 2. `rooms` mapping [Room IDs][roomid-format] (default `{}`) 3. `servers` mapping [Server Names][servername-format] (default `{}`) -While homeservers SHOULD follow these defaults, operators and implementations MAY override them where appropriate. -For example, an operator may default `share_locally` to `true` in an organisation environment. +While homeservers SHOULD follow these defaults, operators and implementations MAY override them where appropriate; +however, they MUST NOT overrule a user's wishes to deny presence sharing. For example, an operator may default +`share_locally` to `true` in an organisation environment. No glob resolution is supported for any key in a presence sharing map. From 295063569cace17af55a5a8cd612973281888eb9 Mon Sep 17 00:00:00 2001 From: lveneris Date: Tue, 30 Jun 2026 19:17:39 +0100 Subject: [PATCH 08/12] Update example m.presence EDU for del -> delete --- proposals/4495-selective-presence.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/4495-selective-presence.md b/proposals/4495-selective-presence.md index 649024b1e61..2dda350e06a 100644 --- a/proposals/4495-selective-presence.md +++ b/proposals/4495-selective-presence.md @@ -150,7 +150,7 @@ and `delete` lists. "user_id": "@john:matrix.org", "recipients": { "add": ["@alice:example.com"], - "del": ["@geoff:example.com"], + "delete": ["@geoff:example.com"], }, "stream_id": 1, "prev_id": 0, From 671d2562774c771df475eb368e2cc3d0ed140d4b Mon Sep 17 00:00:00 2001 From: Logan Devine Date: Tue, 30 Jun 2026 11:55:05 -0700 Subject: [PATCH 09/12] Recommend `m.room.presence_sharing` as a transferable state event in room upgrades Signed-off-by: Logan Devine --- proposals/4495-selective-presence.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/proposals/4495-selective-presence.md b/proposals/4495-selective-presence.md index 2dda350e06a..211b8d56531 100644 --- a/proposals/4495-selective-presence.md +++ b/proposals/4495-selective-presence.md @@ -79,6 +79,8 @@ present, the room is treated as though its value is `"forbid"` by default. Servers MUST NOT include rooms with a `presence_sharing` value of `"forbid"` when they calculate a user's recipient user set, even if the user `"allow"`s presence to be shared with the room. +The `m.room.presence_sharing` hint SHOULD be [transferred upon room upgrade][room-upgrades]. + #### Presence Sharing Prompts A new [`account_data`] entry, `m.presence.prompted`, is introduced to improve the user experience for clients with @@ -433,3 +435,4 @@ None. [cs-versions]: https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientversions [cs-createroom]: https://spec.matrix.org/v1.18/client-server-api/#post_matrixclientv3createroom [`m.ignored_user_list`]: https://spec.matrix.org/v1.18/client-server-api/#mignored_user_list +[room-upgrades]: https://spec.matrix.org/v1.18/client-server-api/#server-behaviour-21 From 7cad1a509edf8d8b4bb593984216851b25c2ed7d Mon Sep 17 00:00:00 2001 From: lveneris Date: Tue, 30 Jun 2026 20:02:24 +0100 Subject: [PATCH 10/12] Add m.selective_presence Client-Server capability --- proposals/4495-selective-presence.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/proposals/4495-selective-presence.md b/proposals/4495-selective-presence.md index 211b8d56531..08356c4042d 100644 --- a/proposals/4495-selective-presence.md +++ b/proposals/4495-selective-presence.md @@ -255,6 +255,12 @@ The 404 response uses the same format as in the existing query endpoints. } ``` +### Client-Server Capability + +Servers implementing Selective Presence MUST include the capability `m.selective_presence` in their response to the `GET +/_matrix/client/v3/capabilities` endpoint. This allows clients to identify servers using Selective Presence so they MAY +avoid showing inapplicable UI on servers without it, or inform users when their servers are upgraded to use it. + ## Potential issues ### Presence Access @@ -397,6 +403,7 @@ The following complementary proposals are planned: | `m.presence.sharing` | `account_data` entry for presence sharing config | `org.continuwuity.presence_v2.msc4495.presence.sharing` | | `m.presence.prompted` | `account_data` entry for persisting presence hint prompt responses | `org.continuwuity.presence_v2.msc4495.presence.prompted` | | `m.room.presence_sharing` | Room state event for presence sharing hint | `org.continuwuity.presence_v2.msc4495.room.presence_sharing` | +| `m.selective_presence` | Capability to announce Selective Presence behaviour to clients | `org.continuwuity.presence_v2.msc4495.selective_presence` | Servers may advertise support for Selective Presence by listing `org.continuwuity.presence_v2.msc4495` in the `unstable_features` section of the response to [`GET /_matrix/client/versions`][cs-versions]. From d1ef8dd23fc13127b1b409083e6539683e431282 Mon Sep 17 00:00:00 2001 From: lveneris Date: Wed, 1 Jul 2026 18:39:28 +0100 Subject: [PATCH 11/12] Revert 'Add m.selective_presence Client-Server Capability' Signed-off-by: L Veneris --- proposals/4495-selective-presence.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/proposals/4495-selective-presence.md b/proposals/4495-selective-presence.md index 08356c4042d..211b8d56531 100644 --- a/proposals/4495-selective-presence.md +++ b/proposals/4495-selective-presence.md @@ -255,12 +255,6 @@ The 404 response uses the same format as in the existing query endpoints. } ``` -### Client-Server Capability - -Servers implementing Selective Presence MUST include the capability `m.selective_presence` in their response to the `GET -/_matrix/client/v3/capabilities` endpoint. This allows clients to identify servers using Selective Presence so they MAY -avoid showing inapplicable UI on servers without it, or inform users when their servers are upgraded to use it. - ## Potential issues ### Presence Access @@ -403,7 +397,6 @@ The following complementary proposals are planned: | `m.presence.sharing` | `account_data` entry for presence sharing config | `org.continuwuity.presence_v2.msc4495.presence.sharing` | | `m.presence.prompted` | `account_data` entry for persisting presence hint prompt responses | `org.continuwuity.presence_v2.msc4495.presence.prompted` | | `m.room.presence_sharing` | Room state event for presence sharing hint | `org.continuwuity.presence_v2.msc4495.room.presence_sharing` | -| `m.selective_presence` | Capability to announce Selective Presence behaviour to clients | `org.continuwuity.presence_v2.msc4495.selective_presence` | Servers may advertise support for Selective Presence by listing `org.continuwuity.presence_v2.msc4495` in the `unstable_features` section of the response to [`GET /_matrix/client/versions`][cs-versions]. From 181df09d593b2a7cebb0302bedc1e7b025db274e Mon Sep 17 00:00:00 2001 From: lveneris Date: Fri, 3 Jul 2026 11:12:29 +0100 Subject: [PATCH 12/12] Clarify defaults behaviour for m.presence.sharing Signed-off-by: L Veneris --- proposals/4495-selective-presence.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/proposals/4495-selective-presence.md b/proposals/4495-selective-presence.md index 211b8d56531..2477057b27f 100644 --- a/proposals/4495-selective-presence.md +++ b/proposals/4495-selective-presence.md @@ -42,9 +42,10 @@ This event contains four properties: 2. `rooms` mapping [Room IDs][roomid-format] (default `{}`) 3. `servers` mapping [Server Names][servername-format] (default `{}`) -While homeservers SHOULD follow these defaults, operators and implementations MAY override them where appropriate; -however, they MUST NOT overrule a user's wishes to deny presence sharing. For example, an operator may default -`share_locally` to `true` in an organisation environment. +If the homeserver requires different defaults, for example setting `share_locally` to true in an organisation +environment, the server MAY create a pre-populated `m.presence.sharing` event for a user when the user is created +or if the user exists already but does not have an `m.presence.sharing` event. Otherwise, a missing property MUST +be assumed to use its above default. No glob resolution is supported for any key in a presence sharing map. @@ -54,9 +55,6 @@ The string values of these presence sharing maps may be any of the following: * `"allow"`: Permit sharing presence with the entity The `"allow"` state MUST NOT be specified for entire homeservers under the `"servers"` object. -Servers MUST treat users without `m.presence.sharing` in their `account_data` as though the default values were -specified. - Sample `m.presence.sharing` account data event: ```json {