Merge branch 'main' into travis/msc/fix-x-matrix-auth
commit
b148a23d9a
@ -0,0 +1,7 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
max_line_length = 120
|
@ -1,2 +1,11 @@
|
||||
[default]
|
||||
check-filename = true
|
||||
|
||||
[default.extend-identifiers]
|
||||
OTK = "OTK"
|
||||
OTKs = "OTKs"
|
||||
|
||||
[default.extend-words]
|
||||
OTK = "OTK"
|
||||
OTKs = "OTKs"
|
||||
Iy = "Iy"
|
||||
|
@ -0,0 +1,92 @@
|
||||
# MSC1692: Terms of service at registration
|
||||
|
||||
At registration, homeservers may wish to require the user to accept a given set of policy documents,
|
||||
such as a terms of service and privacy policy. There may be many different types of documents, all of
|
||||
which are versioned and presented in (potentially) multiple languages.
|
||||
|
||||
This proposal covers requiring users to accept the list of documents during registration. Future
|
||||
improvements could include informing the user *after* registration that a document has changed, which
|
||||
has been spun out to [MSC3012](https://github.com/matrix-org/matrix-spec-proposals/pull/3012).
|
||||
|
||||
## Proposal
|
||||
|
||||
The [User-Interactive Authentication](https://spec.matrix.org/v1.9/client-server-api/#user-interactive-authentication-api)
|
||||
API (UIA) is currently used during registration to create a new account. In future, it is expected
|
||||
that OIDC will be used instead, which can include support for this MSC's principles without needing
|
||||
to change the Matrix specification itself. As a measure until OIDC is here though, this MSC exists
|
||||
to fill the need.
|
||||
|
||||
A new `m.login.terms` authentication type is introduced, allowing servers to include it in registration
|
||||
flows if it desires. Servers which do not require policy acceptance at registration are not required
|
||||
to support this flow.
|
||||
|
||||
The parameters for the new authentication type look like the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"policies": {
|
||||
"terms_of_service": {
|
||||
"version": "1.2",
|
||||
"en": {
|
||||
"name": "Terms of Service",
|
||||
"url": "https://example.org/somewhere/terms-1.2-en.html"
|
||||
},
|
||||
"fr": {
|
||||
"name": "Conditions d'utilisation",
|
||||
"url": "https://example.org/somewhere/terms-1.2-fr.html"
|
||||
}
|
||||
},
|
||||
"privacy_policy": {
|
||||
"version": "1.2",
|
||||
"en": {
|
||||
"name": "Privacy Policy",
|
||||
"url": "https://example.org/somewhere/privacy-1.2-en.html"
|
||||
},
|
||||
"fr": {
|
||||
"name": "Politique de confidentialité",
|
||||
"url": "https://example.org/somewhere/privacy-1.2-fr.html"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Each key under `policies` is a "Policy ID", and defined by the server. They are an opaque identifier
|
||||
(described later in this proposal). Each policy object associated with the policy ID has a required
|
||||
`version` as a convenience to the client, and is another opaque identifier. All other keys are language
|
||||
codes to represent the same document. The client picks the language which best suits the user.
|
||||
|
||||
Language codes *should* be formatted as per [Section 2.2 of RFC 5646](https://datatracker.ietf.org/doc/html/rfc5646#section-2.2),
|
||||
noting that some implementation *may* use an underscore instead of dash. For example, `en_US` instead
|
||||
of `en-US`. This recommendation is to ensure maximum compatibility with existing conventions around
|
||||
language choices in (Matrix) clients.
|
||||
|
||||
`name` and `url` for each policy document are required, and are arbitrary strings with no maximum
|
||||
length. `url` *must* be a valid URI with scheme `https://` or `http://`. Insecure HTTP is discouraged.
|
||||
|
||||
If a client encounters an invalid parameter, registration should stop with an error presented to the
|
||||
user.
|
||||
|
||||
To complete the stage, accepting *all* of the listed documents, the client submits an empty `auth`
|
||||
dict. The client *should* present the user with a checkbox to accept each policy, including a link
|
||||
to the provided `url`, or otherwise rely on [fallback auth](https://spec.matrix.org/v1.9/client-server-api/#fallback).
|
||||
|
||||
The server is expected to track which document versions it presented to the user during registration,
|
||||
if applicable.
|
||||
|
||||
### Opaque identifier
|
||||
|
||||
This definition is inherited from [MSC1597](https://github.com/matrix-org/matrix-spec-proposals/pull/1597).
|
||||
|
||||
> Opaque IDs must be strings consisting entirely of the characters
|
||||
> `[0-9a-zA-Z._~-]`. Their length must not exceed 255 characters and they must
|
||||
> not be empty.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
Regrettably, this MSC was implemented with *stable* identifiers before an unstable identifiers process
|
||||
was established. Implementation has existed in some capacity since 2018: https://github.com/matrix-org/synapse/pull/4004
|
||||
|
||||
Noting that the modern MSC process forbids such behaviour, new implementations should use the stable
|
||||
`m.login.terms` identifier regardless of MSC status. If the MSC changes in a breaking way, a new
|
||||
identifier *must* be chosen, and *must* include a proper unstable prefix.
|
@ -0,0 +1,71 @@
|
||||
# MSC1929 Homeserver Admin Contact and Support page
|
||||
|
||||
Currently, contacting a homeserver admin is difficult because you need to have insider knowledge
|
||||
of who the admin actually is. This proposal aims to fix that by specifying a way to add contact details
|
||||
of admins, as well as a link to a support page for users who are having issues with the service.
|
||||
|
||||
This proposal aims to fix https://github.com/matrix-org/matrix-doc/issues/484
|
||||
|
||||
## Proposal
|
||||
|
||||
The proposal suggests adding a new endpoint: `https://{hostname}/.well-known/matrix/support`,
|
||||
where `hostname` is the server name, without the port number. This is the same as what is used
|
||||
when performing server discovery.
|
||||
|
||||
The response format should be:
|
||||
|
||||
```json5
|
||||
{
|
||||
"contacts": [
|
||||
{
|
||||
"matrix_id": "@admin:domain.tld",
|
||||
"email_address": "admin@domain.tld",
|
||||
"role": "m.role.admin"
|
||||
},
|
||||
{
|
||||
"email_address": "security@domain.tld",
|
||||
"role": "m.role.security"
|
||||
}
|
||||
],
|
||||
"support_page": "https://domain.tld/support.html"
|
||||
}
|
||||
```
|
||||
|
||||
The `contacts` array is optional, but recommended.
|
||||
|
||||
The `matrix_id` and `email_address` do NOT need to have the same domain as the homeserver. It is expected that
|
||||
an admin will have a "backup" contact address if the server is down, like an email or alternative mxid on a different homeserver.
|
||||
|
||||
Entries may have a `matrix_id` OR an `email_address`, but at least one MUST be specified.
|
||||
|
||||
`role` is an informal description of what the address(es) are used for. The only two specified in this
|
||||
proposal are `m.role.admin` and `m.role.security`.
|
||||
|
||||
- `m.role.admin` is a catch-all user for any queries.
|
||||
- `m.role.security` is intended for sensitive requests
|
||||
|
||||
A value for `role` MUST be specified. Custom values are permitted using the
|
||||
[common namespaced identifier format](https://spec.matrix.org/v1.8/appendices/#common-namespaced-identifier-grammar).
|
||||
|
||||
`support_page` is an optional property to specify an affiliated page of the homeserver to give users help
|
||||
specific to the homeserver, like extra login/registration steps.
|
||||
|
||||
At least one valid key should be provided. This means `contacts` should have at least one entry, or the `support_page` should be defined. An empty object is not considered valid, however both `contacts `and `support_page` may be specified together.
|
||||
|
||||
## Alternative solutions
|
||||
|
||||
Hardcode a given user localpart that should be used as an admin address.
|
||||
- The account would need to either internally redirect messages intended for @admin:domain.tld to another account(s)
|
||||
- OR require an admin to regularly sign into this special account to check for messages. Neither of which is useful.
|
||||
|
||||
Specify the same content inside a homeserver endpoint, rather than use `.well-known`.
|
||||
- This requires the homeserver to be up or responsive, which might be not very useful if trying to report issues with
|
||||
connectivity.
|
||||
|
||||
Use vCards.
|
||||
- vCards would add bloat, as the vast majority of a vcards contents is not useful for contacting an admin.
|
||||
|
||||
## Security considerations
|
||||
|
||||
If the host is compromised, any information could be specified in the well known file which may direct users to send
|
||||
sensitive information to a malicious user.
|
@ -0,0 +1,138 @@
|
||||
# MSC2191: Markup for mathematical messages
|
||||
|
||||
Some people write using an odd language that has strange symbols. No, I'm not
|
||||
talking about computer programmers; I'm talking about mathematicians. In order
|
||||
to aid these people in communicating, Matrix should define a standard way of
|
||||
including mathematical notation in messages.
|
||||
|
||||
This proposal presents a format using LaTeX, in contrast with a [previous
|
||||
proposal](https://github.com/matrix-org/matrix-doc/pull/1722/) that used
|
||||
MathML.
|
||||
|
||||
See also:
|
||||
|
||||
- https://github.com/vector-im/riot-web/issues/1945
|
||||
|
||||
|
||||
## Proposal
|
||||
|
||||
A new attribute `data-mx-maths` will be added for use in `<span>` or `<div>`
|
||||
elements. Its value will be mathematical notation in LaTeX format. `<span>`
|
||||
is used for inline math, and `<div>` for display math. The contents of the
|
||||
`<span>` or `<div>` will be a fallback representation or the desired notation
|
||||
for clients that do not support mathematical display, or that are unable to
|
||||
render the entire `data-mx-maths` attribute. The fallback representation is
|
||||
left up to the sending client and could be, for example, an image, or an HTML
|
||||
approximation, or the raw LaTeX source. When using an image as a fallback, the
|
||||
sending client should be aware of issues that may arise from the receiving
|
||||
client using a different background colour.
|
||||
|
||||
Example (with line breaks and indentation added to `formatted_body` for clarity):
|
||||
|
||||
```json
|
||||
{
|
||||
"content": {
|
||||
"body": "This is an equation: sin(x)=a/b",
|
||||
"format": "org.matrix.custom.html",
|
||||
"formatted_body": "This is an equation:
|
||||
<span data-mx-maths=\"\\sin(x)=\\frac{a}{b}\">
|
||||
sin(<i>x</i>)=<sup><i>a</i></sup>/<sub><i>b</i></sub>
|
||||
</span>",
|
||||
"msgtype": "m.text"
|
||||
},
|
||||
"event_id": "$eventid:example.com",
|
||||
"origin_server_ts": 1234567890,
|
||||
"sender": "@alice:example.com",
|
||||
"type": "m.room.message",
|
||||
"room_id": "!soomeroom:example.com"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Other solutions
|
||||
|
||||
[MSC1722](https://github.com/matrix-org/matrix-doc/pull/1722/) proposes using
|
||||
MathML as the format of transporting mathematical notation. It also summarizes
|
||||
some other solutions in its "Other Solutions" section.
|
||||
|
||||
In comparison with MathML, LaTeX has several advantages and disadvantages.
|
||||
|
||||
The first advantage, which is quite obvious, is that LaTeX is much less verbose
|
||||
and more readable than MathML. In many cases, the LaTeX code is a suitable
|
||||
fallback for the rendered notation.
|
||||
|
||||
LaTeX is a suitable input method for many people, and so converting from a
|
||||
user's input to the message format would be a no-op.
|
||||
|
||||
However, balanced against these advantages, LaTeX has several disadvantages as
|
||||
a message format. Some of these are covered in the "Potential issues" and
|
||||
"Security considerations".
|
||||
|
||||
|
||||
## Potential issues
|
||||
|
||||
### "LaTeX" as a format is poorly defined
|
||||
|
||||
There are several extensions to LaTeX that are commonly used, such as
|
||||
AMS-LaTeX. It is unclear which extensions should be supported, and which
|
||||
should not be supported. Different LaTeX-rendering libraries support different
|
||||
sets of commands.
|
||||
|
||||
This proposal suggests that the receiving client should render the LaTeX
|
||||
version if possible, but if it contains unsupported commands, then it should
|
||||
display the fallback. Thus, it is up to the receiving client to decide what
|
||||
commands it will support, rather than dictating what commands must be
|
||||
supported. This comes at a cost of possible inconsistency between clients, but
|
||||
is somewhat mitigated by the use of a fallback. Clients should, however, aim
|
||||
to support, at minimum, the basic LaTeX2e maths commands and the TeX maths
|
||||
commands, with the possible exception of commands that could be security risks
|
||||
(see below).
|
||||
|
||||
To improve compatibility, the sender's client may warn the sender if they are
|
||||
using a command that comes from another package, such as AMS-LaTeX.
|
||||
|
||||
### Lack of libraries for displaying mathematics
|
||||
|
||||
see the corresponding section in [MSC1722](https://github.com/matrix-org/matrix-spec-proposals/pull/1722/files#diff-4a271297299040dbfa622bfc6d2aab02f9bc82be0b28b2a92ce30b14c5621f94R148-R164)
|
||||
|
||||
|
||||
## Security considerations
|
||||
|
||||
LaTeX is a [Turing complete programming
|
||||
language](https://web.archive.org/web/20160110102145/http://en.literateprograms.org/Turing_machine_simulator_%28LaTeX%29);
|
||||
it is possible to write a LaTeX document that contains an infinite loop, or
|
||||
that will require large amounts of memory. While it may be fun to write a
|
||||
[LaTeX file that can control a Mars
|
||||
Rover](https://wiki.haskell.org/wikiupload/8/85/TMR-Issue13.pdf#chapter.2), it
|
||||
is not desirable for a mathematical formula embedded in a Matrix message to
|
||||
control a Mars Rover. Clients should take precautions when rendering LaTeX.
|
||||
Clients that use a rendering library should only use one that can process the
|
||||
LaTeX safely.
|
||||
|
||||
Clients should not render mathematics by calling the `latex` executable without
|
||||
proper sandboxing, as the `latex` executable was not written to handle
|
||||
untrusted input. (see, for example, <https://hovav.net/ucsd/dist/texhack.pdf>,
|
||||
<https://0day.work/hacking-with-latex/>, and
|
||||
<https://hovav.net/ucsd/dist/tex-login.pdf>.) Some LaTeX rendering libraries
|
||||
are better suited for processing untrusted input.
|
||||
|
||||
Certain commands, such as [those that can create
|
||||
macros](https://katex.org/docs/supported#macros), are potentially dangerous;
|
||||
clients should either decline to process those commands, or should take care to
|
||||
ensure that they are handled in safe ways (such as by limiting recursion). In
|
||||
general, LaTeX commands should be filtered by allowing known-good commands
|
||||
rather than forbidding known-bad commands. Some LaTeX libraries may have
|
||||
options for doing this.
|
||||
|
||||
In general, LaTeX places a heavy burden on client authors to ensure that it is
|
||||
processed safely. Some LaTeX rendering libraries provide security advice, for
|
||||
example, <https://github.com/KaTeX/KaTeX/blob/main/docs/security.md>.
|
||||
|
||||
|
||||
## Conclusion
|
||||
|
||||
Math(s) is hard, but LaTeX makes it easier to write mathematical notation.
|
||||
However, using LaTeX as a format for including mathematics in Matrix messages
|
||||
has some serious downsides. Nevertheless, if clients handle the LaTeX
|
||||
carefully, or rely on the fallback representation, the concerns can be
|
||||
addressed.
|
@ -0,0 +1,59 @@
|
||||
# MSC2701: Media and the `Content-Type` relationship
|
||||
|
||||
The specification currently does not outline in great detail how `Content-Type` should be handled
|
||||
with respect to media, particularly around uploads. The [`POST /upload`](https://spec.matrix.org/v1.9/client-server-api/#post_matrixmediav3upload)
|
||||
and [`PUT /upload/:serverName/:mediaId`](https://spec.matrix.org/v1.9/client-server-api/#put_matrixmediav3uploadservernamemediaid)
|
||||
endpoints mention that `Content-Type` is a header that can be set, but does not list it as required,
|
||||
for example. Similarly, the `Content-Type` seems to entirely disappear when talking about
|
||||
[downloads](https://spec.matrix.org/v1.9/client-server-api/#get_matrixmediav3downloadservernamemediaid).
|
||||
|
||||
This proposal clarifies how the `Content-Type` header is used on upload and download, in line with
|
||||
current best practices among server implementations.
|
||||
|
||||
## Proposal
|
||||
|
||||
For `POST` and `PUT` `/upload`, the `Content-Type` header becomes explicitly *optional*, defaulting
|
||||
to `application/octet-stream`. [Synapse](https://github.com/element-hq/synapse/blob/742bae3761b7b2c638975f853ab6161527629240/synapse/rest/media/upload_resource.py#L91)
|
||||
and [MMR](https://github.com/turt2live/matrix-media-repo/blob/fdb434dfd8b7ef7d93401d7b86791610fed72cb6/api/r0/upload_sync.go#L33)
|
||||
both implement this behaviour. Clients SHOULD always supply a `Content-Type` header though, as this
|
||||
may change in future iterations of the endpoints.
|
||||
|
||||
**Note**: Synapse's behaviour was changed in October 2021 with [PR #11200](https://github.com/matrix-org/synapse/pull/11200).
|
||||
Previously, Synapse required the header.
|
||||
|
||||
For `GET /download`, the server MUST return a `Content-Type` which is either exactly the same as the
|
||||
original upload, or reasonably close. The bounds of "reasonable" are:
|
||||
|
||||
* Adding a `charset` to `text/*` content types.
|
||||
* Detecting HTML and using `text/html` instead of `text/plain`.
|
||||
* Using `application/octet-stream` when the server determines the content type is obviously wrong. For
|
||||
example, an encrypted file being claimed as `image/png`.
|
||||
* Returning `application/octet-stream` when the media has an unknown/unprovided `Content-Type`. For
|
||||
example, being uploaded before the server tracked content types or when the remote server is non-compliantly
|
||||
omitting the header entirely.
|
||||
|
||||
Actions not in the spirit of the above are not considered "reasonable". Existing server implementations
|
||||
are encouraged to downgrade their behaviour to be in line with this guidance. [Synapse](https://github.com/element-hq/synapse/blob/742bae3761b7b2c638975f853ab6161527629240/synapse/media/_base.py#L154)
|
||||
already does very minimal post-processing while [MMR](https://github.com/turt2live/matrix-media-repo/blob/fdb434dfd8b7ef7d93401d7b86791610fed72cb6/api/_routers/98-use-rcontext.go#L110-L139)
|
||||
actively ignores the uploaded `Content-Type` (the incorrect thing to do under this MSC).
|
||||
|
||||
## Potential issues
|
||||
|
||||
Some media may have already been uploaded to a server without a content type. Such media items are
|
||||
returned as `application/octet-stream` under this proposal.
|
||||
|
||||
## Alternatives
|
||||
|
||||
No significant alternatives.
|
||||
|
||||
## Security considerations
|
||||
|
||||
No relevant security considerations, though server authors are encouraged to consider the impact of
|
||||
[MSC2702](https://github.com/matrix-org/matrix-spec-proposals/pull/2702) in their threat model.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
This MSC is backwards compatible with existing specification and requires no particular unstable
|
||||
prefix. Servers are already able to implement this proposal's behaviour legally.
|
||||
|
||||
Additionally, cited in the proposal are examples of the behaviour being used in production today.
|
@ -0,0 +1,128 @@
|
||||
# MSC2702: `Content-Disposition` usage in the media repo
|
||||
|
||||
The current specification does not clarify how to treat `Content-Disposition` on responses to
|
||||
[`/download`](https://spec.matrix.org/v1.8/client-server-api/#get_matrixmediav3downloadservernamemediaid)
|
||||
and [`/thumbnail`](https://spec.matrix.org/v1.8/client-server-api/#get_matrixmediav3thumbnailservernamemediaid)
|
||||
requests. This has led to clients (and most notably, IRC bridges) relying on implementation-specific
|
||||
behaviour for how their uploads will be represented. This reliance has caused issues in the past where
|
||||
a security decision was made to use an `attachment` disposition on the download endpoint, however this
|
||||
caused an IRC bridge's use of the media repo to break when trying to send large messages: users on the
|
||||
IRC side were forced to download and open a text file instead of seeing it in their browser. Similar
|
||||
problems have occurred in the past with respect to clients using the download endpoint as an "open in
|
||||
browser" button.
|
||||
|
||||
This proposal clarifies the exact behaviour and introduces a set of suggestions for servers to follow
|
||||
with respect to `Content-Disposition`.
|
||||
|
||||
## Context
|
||||
|
||||
Headers:
|
||||
* [`Content-Disposition`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition)
|
||||
|
||||
Endpoints affected:
|
||||
|
||||
* [`/download`](https://spec.matrix.org/v1.8/client-server-api/#get_matrixmediav3downloadservernamemediaid)
|
||||
* [`/thumbnail`](https://spec.matrix.org/v1.8/client-server-api/#get_matrixmediav3thumbnailservernamemediaid)
|
||||
|
||||
Upload endpoints:
|
||||
* [`POST /upload`](https://spec.matrix.org/v1.8/client-server-api/#post_matrixmediav3upload)
|
||||
* [`PUT /upload`](https://spec.matrix.org/v1.8/client-server-api/#put_matrixmediav3uploadservernamemediaid)
|
||||
|
||||
## Proposal
|
||||
|
||||
For `/download`:
|
||||
|
||||
* `Content-Disposition` MUST be returned, and MUST be one of `inline` or `attachment`.
|
||||
|
||||
* `inline` *should* be used when one of the "safe" content types listed below is being served.
|
||||
|
||||
* When uploads are made with a `filename`, the `Content-Disposition` header MUST contain the same
|
||||
`filename`. Otherwise, `filename` is excluded from the header.
|
||||
|
||||
* If the media being downloaded is remote, the remote server's `filename` in the `Content-Disposition`
|
||||
header is used as the `filename` instead. When the header is not supplied, or does not supply a
|
||||
`filename`, the local download response does not include a `filename` (though does still contain
|
||||
a generated `Content-Disposition`).
|
||||
|
||||
For `/thumbnail`:
|
||||
|
||||
* `Content-Disposition` MUST be returned, and MUST be `inline` (see below).
|
||||
* `Content-Disposition` SHOULD include a server-generated `filename`. For example, `thumbnail.png`.
|
||||
|
||||
Note that in both endpoints `Content-Disposition` becomes required, though the legal set of parameters is
|
||||
intentionally different. Specifically, because `/thumbnail` returns server-generated content, that content
|
||||
is safe to serve inline relative to a given user upload and therefore can be inline. It is however atypical
|
||||
for a client to link to `/thumbnail` directly, but in the event they do we provide a safe default.
|
||||
|
||||
The following content types are considered "safe" for `inline` usage. For `/download`, servers SHOULD
|
||||
use `attachment` if the returned `Content-Type` is not on the list. For `/thumbnail`, servers SHOULD
|
||||
only generate thumbnails with a `Content-Type` listed below.
|
||||
|
||||
* `text/css`
|
||||
* `text/plain`
|
||||
* `text/csv`
|
||||
* `application/json`
|
||||
* `application/ld+json`
|
||||
* `image/jpeg`
|
||||
* `image/gif`
|
||||
* `image/png`
|
||||
* `image/apng`
|
||||
* `image/webp`
|
||||
* `image/avif`
|
||||
* `video/mp4`
|
||||
* `video/webm`
|
||||
* `video/ogg`
|
||||
* `video/quicktime`
|
||||
* `audio/mp4`
|
||||
* `audio/webm`
|
||||
* `audio/aac`
|
||||
* `audio/mpeg`
|
||||
* `audio/ogg`
|
||||
* `audio/wave`
|
||||
* `audio/wav`
|
||||
* `audio/x-wav`
|
||||
* `audio/x-pn-wav`
|
||||
* `audio/flac`
|
||||
* `audio/x-flac`
|
||||
|
||||
`Content-Type` additionally becomes a required header on responses to both `/download` and `/thumbnail`, as `Content-Disposition`
|
||||
without `Content-Type` is effectively useless in HTTP. The `Content-Type` header is the `Content-Type` supplied by
|
||||
the client during `/upload`. If no `Content-Type` was supplied during upload, `application/octet-stream` is used.
|
||||
|
||||
Clients SHOULD NOT rely on servers returning `inline` rather than `attachment` on `/download`. Server
|
||||
implementations might decide out of an abundance of caution that all downloads are responded to with
|
||||
`attachment`, regardless of content type - clients should not be surprised by this behaviour.
|
||||
|
||||
## Potential issues
|
||||
|
||||
This proposal does not require the usage of `inline` on `/download`, making it harder for IRC and similar
|
||||
bridges to rely on "pastebin" behaviour. For example, when a large message is posted on the Matrix side of
|
||||
the bridge, the IRC bridge might upload it as a text file due to limits on the IRC side. Ideally, that text
|
||||
file would be rendered inline by the server. Bridges are encouraged to use "proxy APIs" to serve the text
|
||||
file instead, where they can better control the user experience.
|
||||
|
||||
## Alternatives
|
||||
|
||||
No major alternatives identified.
|
||||
|
||||
## Security considerations
|
||||
|
||||
This MSC fixes a possible Cross-Site Scripting issue in environments with insecure configurations.
|
||||
For example, if a Matrix web client is also hosted on the same domain as the media download URL. This
|
||||
is mitigated by only suggesting `inline` as a disposition on content types which are not likely to
|
||||
execute code within the browser upon being viewed. A browser may still have further bugs which reveal
|
||||
information, though those issues quickly become impractical for the Matrix specification to mitigate.
|
||||
|
||||
No new security issues are identified, and careful consideration was put into `inline` to ensure an
|
||||
extremely limited set of possible media types.
|
||||
|
||||
The allowable content types for `inline` were inspired by [the react-sdk](https://github.com/matrix-org/matrix-react-sdk/blob/a70fcfd0bcf7f8c85986da18001ea11597989a7c/src/utils/blobs.ts#L51),
|
||||
and extended to include what is present in [a related Synapse PR](https://github.com/matrix-org/synapse/pull/15988).
|
||||
The react-sdk list of types has been known to be safe for several years now, and the added types in the Synapse
|
||||
PR are not subject to XSS or similar attacks. Note that `image/svg`, `text/javascript`, and `text/html` are
|
||||
explicitly not allowed.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
This MSC has no particular unstable prefix requirements. Servers are already able to return arbitrary
|
||||
`Content-Disposition` headers on the affected endpoints.
|
@ -0,0 +1,52 @@
|
||||
# MSC2705: Animated thumbnails
|
||||
|
||||
Users may already upload animated media to the media repository, such as gifs, webp images, and videos.
|
||||
When this media is used in an event or avatar, many clients are stuck with a static thumbnail until
|
||||
the user clicks on it to get the full, unedited, file. Some clients however would prefer to show an
|
||||
animated thumbnail in certain conditions, like when the user is hovering over the message or avatar.
|
||||
|
||||
This proposal introduces a new query parameter to the [`GET /_matrix/media/v3/thumbnail`](https://spec.matrix.org/v1.9/client-server-api/#get_matrixmediav3thumbnailservernamemediaid)
|
||||
endpoint, allowing clients to specifically request an animated thumbnail.
|
||||
|
||||
## Proposal
|
||||
|
||||
A new query parameter, `animated`, is added to the `/thumbnail` endpoint. It has the following behaviour:
|
||||
|
||||
* When `true`: the server SHOULD return an animated thumbnail if possible/supported.
|
||||
* When `false`: the server MUST NOT return an animated thumbnail.
|
||||
* When not provided: the server SHOULD NOT return an animated thumbnail.
|
||||
|
||||
The default case is a relaxed version of the `false` behaviour to allow server owners to customize the
|
||||
default behaviour when their users' clients do not support requesting animated thumbnails.
|
||||
|
||||
Clients SHOULD respect a user's preference to [reduce motion](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion)
|
||||
and request non-animated thumbnails in these cases.
|
||||
|
||||
The content types which are able to be animated is left as an implementation detail. The following
|
||||
SHOULD be supported at a minimum, however:
|
||||
|
||||
* `image/gif`
|
||||
* `image/png` or `image/apng` ("APNG" format)
|
||||
* `image/webp`
|
||||
|
||||
The returned content type for an animated thumbnail is additionally left as an implementation detail,
|
||||
though servers SHOULD use `image/webp` whenever possible.
|
||||
|
||||
When media cannot be animated, such as a PDF or JPEG, the server should return a thumbnail as though
|
||||
`animated` was `false`.
|
||||
|
||||
## Alternatives
|
||||
|
||||
No significant alternatives.
|
||||
|
||||
## Security considerations
|
||||
|
||||
Server load could increase when the server tries to thumbnail a large file. Servers are expected to
|
||||
mitigate this on their own by providing an option to disable the feature or limiting how/when
|
||||
they will animate the media.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
While this proposal is not considered stable, `animated` is specified as `org.matrix.msc2705.animated`
|
||||
on requests. No unstable endpoints are required due to backwards compatibility being built-in to the
|
||||
proposal.
|
@ -0,0 +1,66 @@
|
||||
# MSC2870: Protect server ACLs from redaction
|
||||
|
||||
[Server ACLs](https://matrix.org/docs/spec/client_server/r0.6.1#server-access-control-lists-acls-for-rooms)
|
||||
are a way to prevent malicious/untrusted homeservers from participating in a given room. These ACLs
|
||||
are represented by a state event which is easily capable of demolishing all useful functionality of
|
||||
a federated room. Typically this sort of design flaw would be worked out during the MSC process, and
|
||||
in this particular case it was acknowledged as a potential source of accidental mistake, however the
|
||||
impact of making a mistake appears to be larger than anticipated.
|
||||
|
||||
Specifically, the ACLs do not default to allowing all servers when they are set but missing an `allow`
|
||||
field. When an `allow` rule is missing, it means that all servers can no longer participate in the
|
||||
room. The natural reaction to such a disaster is to try sending a new ACL event, however all the
|
||||
receiving servers rightly refuse the event because the specification says so and it's not yet
|
||||
possible to tell if a trusted server is publishing the new ACLs (due to the social nature of the
|
||||
problem space rather than the technical side). Redacting a server ACL event causes the event content
|
||||
to become `{}`, which means no `allow` rule is present.
|
||||
|
||||
## Proposal
|
||||
|
||||
In a future room version, the `allow`, `deny`, and `allow_ip_literals` fields of the `m.room.server_acl`
|
||||
state event are protected from redaction. Typically this measure is only taken when a field is critical
|
||||
to the operation of the protocol, such as in the case of protecting power levels from redactions. ACLs
|
||||
are not as critical to the protocol as most of the other protected event fields, however the consequences
|
||||
of accidentally redacting a server ACL event are disproportionately large.
|
||||
|
||||
## Potential issues
|
||||
|
||||
None foreseen - this MSC should remedy a problem encountered in the wild.
|
||||
|
||||
## Alternatives
|
||||
|
||||
We could instead dictate that a lack of `allow` rule implicitly means `allow: ["*"]`, however this is
|
||||
a behavioural change which is easily missed between room versions. We could also define that `{}` means
|
||||
applying the same mechanics of ACLs when the state event isn't set, however again this is subject to
|
||||
being missed as a behavioural change. Behavioural changes are hard to represent in the specification as
|
||||
room versions are not meant to contain information about how a room might react in the eyes of a room
|
||||
administrator or client implementation, where possible. They are more intended to change server-side
|
||||
algorithms, like the redaction algorithm, to change the functionality under the hood without impacting
|
||||
the room administrator's understanding of their room's function.
|
||||
|
||||
Another possible approach is to have servers prevent sending faulty ACL events by preventing their
|
||||
local clients from doing so, such as by rejecting redaction requests. This doesn't solve the issue
|
||||
over federation, but can reduce the likelihood of such events making it to the federation layer. This
|
||||
is what Synapse currently does to help mitigate the issue. This is only effective if the server (or
|
||||
client, locally) implements it - it's common for both clients and servers to forget to add these checks
|
||||
during development, leading to occasional room breakage. This MSC instead tries to resolve the issue
|
||||
more completely for future room versions, pending replacement of ACLs entirely.
|
||||
|
||||
Meanwhile, [MSC4124](https://github.com/matrix-org/matrix-spec-proposals/pull/4124) exists as a possible
|
||||
permanent replacement for ACLs.
|
||||
|
||||
## Security considerations
|
||||
|
||||
It may be desirable to redact server ACLs due to abusive server names needing to be banned. Clients
|
||||
are encouraged to *not* display the differences to the ACLs without the user opting in to seeing the
|
||||
changes (such as by clicking a 'show details' link).
|
||||
|
||||
Of particular note is that redacted events may be provided to future users/servers, regardless of the
|
||||
history visibility settings. If fields are protected from redaction, this means they will be visible
|
||||
to those future joiners. This may be undesirable in some circumstances. This MSC does not attempt to
|
||||
address this concern.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
Implementations looking to test this MSC before it lands in a released room version can use `org.matrix.msc2870`
|
||||
as the room version, using [room version 11](https://spec.matrix.org/v1.9/rooms/v11/) as a base.
|
@ -0,0 +1,152 @@
|
||||
# MSC3061: Sharing room keys for past messages
|
||||
|
||||
In Matrix, rooms can be configured via the `m.room.history_visibility` state
|
||||
event such that historical messages can be visible to all Matrix users
|
||||
(`world_readable`), all room members (`shared`), room members from the time
|
||||
that they are invited to a room (`invited`), or room members from the time that
|
||||
they join a room (`joined`). However, currently in encrypted rooms, rooms with
|
||||
the history visibility set to `world_readable` or `shared` are effectively
|
||||
set to `invited` since other members generally do not send new members the keys
|
||||
to decrypt messages sent before they were invited or joined a room.
|
||||
|
||||
We define a "shared-history" flag that identifies keys for messages that were
|
||||
sent when the room's visibility setting was set to `world_readable` or
|
||||
`shared`. This allows clients to know which keys are "safe" to share with new
|
||||
members so that they can decrypt historical messages. We also give examples of
|
||||
ways in which this flag can be used.
|
||||
|
||||
|
||||
## Proposal
|
||||
|
||||
A room key (such as a megolm session) is flagged as having been used for shared
|
||||
history when it was used to encrypt a message while the room's history
|
||||
visibility setting was set to `world_readable` or `shared`.
|
||||
|
||||
If the client does not have an `m.room.history_visibility` state event for the
|
||||
room, or its value is not understood, the client should treat it as if its
|
||||
value is `joined` for the purposes of determining whether the key is used for
|
||||
shared history. This is in contrast with the normal processing of
|
||||
`m.room.history_visibility` which defaults to `world_readable` when there is no
|
||||
`m.room.history_visibility` state event or its value is not understood. This
|
||||
is done so that, in the event of a bug that causes the client to fail to obtain
|
||||
the state event, the client will fail in a secure manner.
|
||||
|
||||
Internally, a client may use any mechanism it wants to keep track of this flag.
|
||||
When a room key is marked as having been used for shared history:
|
||||
|
||||
- `m.room_key` and `m.forwarded_room_key` messages used to share this key have
|
||||
a `shared_history` property set to `true` e.g.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "m.room_key",
|
||||
"content": {
|
||||
"algorithm": "m.megolm.v1.aes-sha2",
|
||||
"room_id": "!room_id",
|
||||
"session_id": "session_id",
|
||||
"session_key": "session_key",
|
||||
"shared_history": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- the [`SessionData` type](https://spec.matrix.org/unstable/client-server-api/#definition-sessiondata)
|
||||
in key backups (that is, the plaintext object that gets encrypted into the
|
||||
`session_data` field) of this key has a `shared_history` property set to
|
||||
`true` in the decrypted JSON structure e.g.
|
||||
|
||||
```json
|
||||
{
|
||||
"algorithm": "m.megolm.v1.aes-sha2",
|
||||
"forwarding_curve25519_key_chain": [
|
||||
"hPQNcabIABgGnx3/ACv/jmMmiQHoeFfuLB17tzWp6Hw"
|
||||
],
|
||||
"sender_claimed_keys": {
|
||||
"ed25519": "aj40p+aw64yPIdsxoog8jhPu9i7l7NcFRecuOQblE3Y"
|
||||
},
|
||||
"sender_key": "RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU",
|
||||
"session_key": "AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8Llf...",
|
||||
"shared_history": true
|
||||
}
|
||||
```
|
||||
|
||||
and,
|
||||
- the [`SessionData` type](https://spec.matrix.org/unstable/client-server-api/#key-export-format)
|
||||
used in key exports has a `shared_history` property that is set to `true` for
|
||||
this key e.g.
|
||||
|
||||
```json
|
||||
{
|
||||
"algorithm": "m.megolm.v1.aes-sha2",
|
||||
"forwarding_curve25519_key_chain": [
|
||||
"hPQNcabIABgGnx3/ACv/jmMmiQHoeFfuLB17tzWp6Hw"
|
||||
],
|
||||
"sender_claimed_keys": {
|
||||
"ed25519": "aj40p+aw64yPIdsxoog8jhPu9i7l7NcFRecuOQblE3Y"
|
||||
},
|
||||
"sender_key": "RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU",
|
||||
"session_key": "AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8Llf...",
|
||||
"shared_history": true
|
||||
}
|
||||
```
|
||||
|
||||
When a client obtains a key that has the `shared_history` property set to
|
||||
`true`, then it flags the key internally as having been used for shared
|
||||
history. Otherwise, the key should not be flagged as such.
|
||||
|
||||
When the room's history visibility setting changes to `world_readable` or
|
||||
`shared` from `invited` or `joined`, or changes to `invited` or `joined` from
|
||||
`world_readable` or `shared`, senders that support this flag must rotate their
|
||||
megolm sessions.
|
||||
|
||||
Clients may use this flag to modify their behaviour with respect to sharing
|
||||
keys. For example, when the user invites someone to the room, they may
|
||||
preemptively share keys that have this flag with the invited user. Other
|
||||
behaviours may be possible, but must be careful not to guard against malicious
|
||||
homeservers. See the "Security Considerations" section.
|
||||
|
||||
## Potential issues
|
||||
|
||||
Room keys from clients that do not support this proposal will not be eligible
|
||||
for the modified client behaviour.
|
||||
|
||||
The suggested behaviour in this MSC is to only share additional keys when
|
||||
inviting another user. This does not allow users who join the room but were
|
||||
not invited (for example, if membership is restricted to another space, or if
|
||||
the room is publicly joinable) to receive the keys. Also, if the inviter does
|
||||
not have all the keys available for whatever reason, the invitee has no way of
|
||||
receiving the keys. This may be solved in the future when we have a mechanism
|
||||
for verifying room membership.
|
||||
|
||||
## Alternatives
|
||||
|
||||
Rather than having the sender flagging keys, a client can paginate through the
|
||||
room's history to determine the room's history visibility settings when the
|
||||
room key was used. This would not require any changes, but has performance
|
||||
problems. In addition, the server could lie about the room history while the
|
||||
user is paginating through the history. By having the sender flag keys, this
|
||||
ensures that the key is treated in a manner consistent with the sender's view
|
||||
of the room.
|
||||
|
||||
Rather than using a boolean flag, we could include the history visibility
|
||||
setting as-is. For example, a `history_visibility` field could be added, which
|
||||
is set to the history visibility setting (e.g. `world_readable`). This
|
||||
produces an equivalent effect, but it pushes the processing of the history
|
||||
visibility setting to the receiver rather than the sender. For consistency, it
|
||||
is better for as much of the decision-making done by the sender, rather than
|
||||
the receiver.
|
||||
|
||||
## Security considerations
|
||||
|
||||
Clients should still ensure that keys are only shared with authorized users and
|
||||
devices, as a malicious homeserver could inject fake room membership events.
|
||||
One way to ensure that keys are only shared with authorized users is to only
|
||||
share keys with users when the client invites them, as the client is then
|
||||
certain that the user is allowed to be in the room. Another way is to have a
|
||||
mechanism of verifying membership, such as the method proposed in
|
||||
[MSC3917](https://github.com/matrix-org/matrix-spec-proposals/pull/3917).
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
Until this feature lands in the spec, the property name to be used is
|
||||
`org.matrix.msc3061.shared_history` rather than `shared_history`.
|
@ -0,0 +1,111 @@
|
||||
# MSC3077: Support for multi-stream VoIP
|
||||
|
||||
This MSC proposes a method for differentiating WebRTC streams from each other.
|
||||
|
||||
[MSC2746](https://github.com/matrix-org/matrix-doc/pull/2746) has improved VoIP
|
||||
immeasurably. Yet, there is still no clear way to handle things such as
|
||||
screen-sharing.
|
||||
|
||||
Simple VoIP calls only ever feature one stream, though often clients will want
|
||||
to send multiple - usermedia, screensharing and possibly more. In a situation
|
||||
with more streams, it can be very helpful to provide the other side with
|
||||
metadata about the content of the streams.
|
||||
|
||||
## Proposal
|
||||
|
||||
This MSC proposes adding an `sdp_stream_metadata` field to the events containing
|
||||
a session description i.e.:
|
||||
|
||||
+ [`m.call.invite`](https://spec.matrix.org/v1.7/client-server-api/#mcallinvite)
|
||||
+ [`m.call.answer`](https://spec.matrix.org/v1.7/client-server-api/#mcallanswer)
|
||||
+ [`m.call.negotiate`](https://spec.matrix.org/v1.7/client-server-api/#mcallnegotiate)
|
||||
|
||||
The `sdp_stream_metadata` field is an object in which each key is one stream
|
||||
`id` in the session description. The values are objects with the
|
||||
following fields:
|
||||
|
||||
+ `purpose` - a string indicating the purpose of the stream. For compatibility
|
||||
between client the following values are defined:
|
||||
+ `m.usermedia` - stream that contains the webcam and/or microphone tracks
|
||||
+ `m.screenshare` - stream with the screen-sharing tracks
|
||||
|
||||
### Example
|
||||
|
||||
```JSON
|
||||
{
|
||||
"type": "m.call.invite",
|
||||
"room_id": "!roomId",
|
||||
"content": {
|
||||
"call_id": "1414213562373095",
|
||||
"invitee": "@bob:matrix.org",
|
||||
"party_id": "1732050807568877",
|
||||
"lifetime": "60000",
|
||||
"capabilities": {
|
||||
"m.call.transferee": true,
|
||||
},
|
||||
"offer": {
|
||||
"sdp": "...",
|
||||
"type": "offer",
|
||||
},
|
||||
"sdp_stream_metadata": {
|
||||
"271828182845": {
|
||||
"purpose": "m.screenshare",
|
||||
},
|
||||
"314159265358": {
|
||||
"purpose": "m.usermedia",
|
||||
},
|
||||
},
|
||||
"version": "1",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Edge cases
|
||||
|
||||
+ If an incoming stream is not described in `sdp_stream_metadata` and
|
||||
`sdp_stream_metadata` is present, the stream should be ignored.
|
||||
+ If a stream has a `purpose` of an unknown type (i.e. not `m.usermedia` or
|
||||
`m.screenshare`), it should be ignored.
|
||||
|
||||
### Backwards compatibility
|
||||
|
||||
During the initial invite and answer exchange clients find out if the field
|
||||
`sdp_stream_metadata` is missing. If it is not present in the event sent by the
|
||||
opponent, the client should ignore any new incoming streams (i.e. it should use
|
||||
the first one) and it shouldn't send more than one stream (i.e. clients cannot send a video feed and a screenshare at the same time, as is the case in current clients).
|
||||
|
||||
## Alternatives
|
||||
|
||||
Setting the stream `id`s to custom values had been considered. Though this is
|
||||
possible on some platforms, it is not in browsers. That is because the `id`
|
||||
property of `MediaStream` is _read-only_ as the [MDN Documentation
|
||||
states](https://developer.mozilla.org/en-US/docs/Web/API/MediaStream/id).
|
||||
Similar is true for SDP attributes.
|
||||
|
||||
This proposal is also more practical for cases where more complex metadata is
|
||||
needed. For conferencing, a `user_id` field could be added to
|
||||
the objects in `sdp_stream_metadata`; for differentiating between the front and rear camera of a
|
||||
phone, a `camera_type` field could be added.
|
||||
|
||||
Previously, it has been thought that the `purpose` field has to be unique (or
|
||||
another unique field has to be added), though this could only ever be important
|
||||
if we wanted to replace a stream with another one in-place. It was deemed as a
|
||||
rather uncommon thing for which there doesn't seem to be any use-case, so
|
||||
uniqueness is not required.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
During development, the following fields should be used:
|
||||
|
||||
|Release |Development |
|
||||
|----------------------------|-----------------------------------------------|
|
||||
|`sdp_stream_metadata` |`org.matrix.msc3077.sdp_stream_metadata` |
|
||||
|`m.call.sdp_stream_metadata`|`org.matrix.msc3077.call.sdp_stream_metadata` |
|
||||
|
||||
## Potential issues
|
||||
|
||||
None that I can think of.
|
||||
|
||||
## Security considerations
|
||||
|
||||
None that I can think of.
|
@ -0,0 +1,130 @@
|
||||
# MSC3291: Muting in VoIP calls
|
||||
|
||||
During VoIP calls, it is common for a user to mute their microphone/camera.
|
||||
Ideally, the other side should be able to see that the opponent's camera is
|
||||
muted, so that it could reflect this in the UI (e.g. show the user's avatar
|
||||
instead of their camera feed). We would also want the changes in the mutes state
|
||||
to be quick.
|
||||
|
||||
Using pure WebRTC there are two ways to do muting and both have their issues:
|
||||
|
||||
+ Disabling the corresponding track
|
||||
+ Setting the corresponding track as `recvonly`/`inactive`
|
||||
|
||||
The Alternatives section describes the issues with using these alone.
|
||||
|
||||
## Proposal
|
||||
|
||||
This MSC proposes extending the `sdp_stream_metadata` object (see
|
||||
[MSC3077](https://github.com/matrix-org/matrix-doc/pull/3077)) to allow
|
||||
indicating the mute state to the other side using the following fields:
|
||||
|
||||
+ `audio_muted` - a boolean indicating the current audio mute state
|
||||
+ `video_muted` - a boolean indicating the current video mute state
|
||||
|
||||
This MSC also adds a new call event `m.call.sdp_stream_metadata_changed`, which
|
||||
has the common VoIP fields as specified in
|
||||
[MSC2746](https://github.com/matrix-org/matrix-doc/pull/2746) (`version`,
|
||||
`call_id`, `party_id`) and a `sdp_stream_metadata` object which is the same
|
||||
thing as `sdp_stream_metadata` in `m.call.negotiate`, `m.call.invite` and
|
||||
`m.call.answer`. The client sends this event when the `sdp_stream_metadata` has
|
||||
changed but no negotiation is required (e.g. the user mutes their
|
||||
camera/microphone).
|
||||
|
||||
All tracks should be assumed unmuted unless specified otherwise.
|
||||
|
||||
Clients are recommended to not mute the audio of WebRTC tracks locally when a
|
||||
incoming stream has the `audio_muted` field set to `true`. This is because when the
|
||||
other user unmutes themselves, there may be a slight delay between their client
|
||||
sending audio and the `m.call.sdp_stream_metadata_changed` event arriving. If
|
||||
`enabled` is set to `false`, then any audio sent in between those two events
|
||||
will not be heard. The other user will still stop transmitting audio once they
|
||||
mute on their side, so no audio is sent without the user's knowledge.
|
||||
|
||||
The same suggestion does not apply to `video_muted` - there clients _should_
|
||||
mute video locally, so that the receiving side doesn't see black video.
|
||||
|
||||
### Example
|
||||
|
||||
```JSON
|
||||
{
|
||||
"type": "m.call.sdp_stream_metadata_changed",
|
||||
"room_id": "!roomId",
|
||||
"content": {
|
||||
"version": "1",
|
||||
"call_id": "1414213562373095",
|
||||
"party_id": "1732050807568877",
|
||||
"sdp_stream_metadata": {
|
||||
"2311546231": {
|
||||
"purpose": "m.usermedia",
|
||||
"audio_muted:": true,
|
||||
"video_muted": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This event indicates that both audio and video are muted. It is suggested the
|
||||
video track of stream `2311546231` should be hidden in the UI (probably replaced
|
||||
by an avatar). It also suggests the UI should show an indication that the audio
|
||||
track is muted but the client should not mute the audio on the receiving side.
|
||||
|
||||
## Potential issues
|
||||
|
||||
When the user mutes their camera, some browsers may keep sending meaningless data
|
||||
which will waste bandwidth.
|
||||
|
||||
## Alternatives
|
||||
|
||||
### Only disabling the corresponding track
|
||||
|
||||
This is the solution that some clients (e.g. Element Android) use at the moment.
|
||||
While this is almost instantaneous, it doesn't allow the other side to know the
|
||||
opponent's mute state. This leads to the opponent showing a black screen for a
|
||||
muted video track and not doing anything for a muted audio track which is bad
|
||||
for UX.
|
||||
|
||||
### Setting the corresponding track as `recvonly`/`inactive`
|
||||
|
||||
While this would be beneficial for low bandwidth connections, it takes time. The
|
||||
delay might be acceptable for video but isn't for audio (with which you would
|
||||
assume an instantaneous mute state change). This is also problematic since there
|
||||
could be a confusion with holding (as defined in
|
||||
[MSC2746](https://github.com/matrix-org/matrix-doc/pull/2746)).
|
||||
|
||||
### Using a separate event for muting
|
||||
|
||||
While this might feel clearer initially, it doesn't have much real benefit. The
|
||||
mute state is in fact a meta information about the stream and using
|
||||
`sdp_stream_metadata` is also more flexible for cases where the user joins a
|
||||
call already muted. It is also more flexible in general and would be useful if
|
||||
we ever decided to do what is described in the next section.
|
||||
|
||||
### A combination of disabling tracks, `sdp_stream_metadata` and SDP
|
||||
|
||||
An option would be using the current method in combination with setting the
|
||||
corresponding track as `recvonly`/`inactive`. Along with this clients would need
|
||||
to set the mute state in `sdp_stream_metadata` to avoid conflicts with holding
|
||||
(as defined in [MSC2746](https://github.com/matrix-org/matrix-doc/pull/2746)).
|
||||
While this solution might be the most flexible solution as it would allow
|
||||
clients to choose between bandwidth and a mute state change delay for each
|
||||
track, it would be harder to implement and feels generally disjointed.
|
||||
|
||||
## Security considerations
|
||||
|
||||
None that I can think of.
|
||||
|
||||
## Dependencies
|
||||
|
||||
+ [MSC3077](https://github.com/matrix-org/matrix-doc/pull/3077)
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
|Release |Development |
|
||||
|------------------------------------|---------------------------------------------|
|
||||
|`m.call.sdp_stream_metadata_changed`|`org.matrix.call.sdp_stream_metadata_changed`|
|
||||
|`sdp_stream_metadata` |`org.matrix.msc3077.sdp_stream_metadata` |
|
||||
|
||||
We use an unstable prefix for `sdp_stream_metadata` to match
|
||||
[MSC3077](https://github.com/matrix-org/matrix-doc/pull/3077).
|
@ -0,0 +1,467 @@
|
||||
# MSC3381: Chat Polls
|
||||
|
||||
Polls are additive functionality in a room, allowing someone to pose a question and others to answer
|
||||
until the poll is closed. In chat, these are typically used for quick questionnaires such as what to
|
||||
have for lunch or when the next office party should be, not elections or anything needing truly
|
||||
secret ballot.
|
||||
|
||||
[MSC2192](https://github.com/matrix-org/matrix-doc/pull/2192) does introduce a different way of doing
|
||||
polls (originally related to inline widgets, but diverged into `m.room.message`-based design). That
|
||||
MSC's approach is discussed at length in the alternatives section for why it is inferior.
|
||||
|
||||
## Proposal
|
||||
|
||||
Polls are intended to be handled completely client-side and encrypted when possible in a given room.
|
||||
They are started by sending an event, responded to using events, and closed using more events - all
|
||||
without involving the server (beyond being the natural vessel for sending the events). Other MSCs
|
||||
related to polls might require changes from servers, however this MSC is intentionally scoped so that
|
||||
it does not need server-side involvement.
|
||||
|
||||
The events in this MSC make use of the following functionality:
|
||||
|
||||
* [MSC1767](https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/1767-extensible-events.md) (extensible events & `m.text`)
|
||||
* [Event relationships](https://spec.matrix.org/v1.6/client-server-api/#forming-relationships-between-events)
|
||||
* [Reference relations](https://spec.matrix.org/v1.6/client-server-api/#reference-relations)
|
||||
|
||||
To start a poll, a user sends an `m.poll.start` event into the room. An example being:
|
||||
|
||||
```json5
|
||||
{
|
||||
"type": "m.poll.start",
|
||||
"sender": "@alice:example.org",
|
||||
"content": {
|
||||
"m.text": [
|
||||
// Simple text is used as a fallback for text-only clients which don't understand polls. Specific formatting is
|
||||
// not specified, however something like the following is likely best.
|
||||
{
|
||||
"mimetype": "text/plain",
|
||||
"body": "What should we order for the party?\n1. Pizza 🍕\n2. Poutine 🍟\n3. Italian 🍝\n4. Wings 🔥"
|
||||
}
|
||||
],
|
||||
"m.poll": {
|
||||
"kind": "m.disclosed",
|
||||
"max_selections": 1,
|
||||
"question": {
|
||||
"m.text": [{"body": "What should we order for the party?"}]
|
||||
},
|
||||
"answers": [
|
||||
{"m.id": "pizza", "m.text": [{"body": "Pizza 🍕"}]},
|
||||
{"m.id": "poutine", "m.text": [{"body": "Poutine 🍟"}]},
|
||||
{"m.id": "italian", "m.text": [{"body": "Italian 🍝"}]},
|
||||
{"m.id": "wings", "m.text": [{"body": "Wings 🔥"}]},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
With consideration for extensible events, a new `m.poll` content block is defined:
|
||||
|
||||
* `kind` - An optional namespaced string to represent a poll's general approach. Currently specified
|
||||
values being `m.disclosed` and `m.undisclosed`. Clients which don't understand the `kind` should
|
||||
assume `m.undisclosed` for maximum compatibility. The definitions for these values are specified
|
||||
later in this proposal.
|
||||
* `max_selections` - An optional integer to represent how many answers the user is allowed to select
|
||||
from the poll. Must be greater than or equal to `1`, and defaults to `1`.
|
||||
* `question` - A required object to represent the question being posed by the poll. Takes an `m.text`
|
||||
content block within. More blocks might be added in the future. Clients should treat this similar
|
||||
to how they would an `m.message` event.
|
||||
* `answers` - Array of options users can select. Each entry is an object with an `m.text` content
|
||||
block, similar to `question`, and an opaque string field `m.id` for use in response events. More
|
||||
blocks might be added in the future. Clients should treat each entry similar to how they would an
|
||||
`m.message` event. The array is truncated to 20 maximum options.
|
||||
|
||||
Note that arrays are inherently ordered. Clients *should* render options in the order presented in
|
||||
the array - a future MSC may add a flag to permit rendering in a different or random order.
|
||||
|
||||
Together with content blocks from other proposals, an `m.poll.start` is described as:
|
||||
|
||||
* **Required** - An `m.text` block to act as a fallback for clients which can't process polls.
|
||||
* **Required** - An `m.poll` block to describe the poll itself. Clients use this to show the poll.
|
||||
|
||||
The above describes the minimum requirements for sending an `m.poll.start` event. Senders can add additional
|
||||
blocks, however as per the extensible events system, receivers which understand poll events should not
|
||||
honour them.
|
||||
|
||||
If a client does not support rendering polls inline, the client would instead typically represent
|
||||
the event as a plain text message. This would allow users of such clients to participate in the poll,
|
||||
even if they can not vote properly on it (ie: by using text messages or reactions).
|
||||
|
||||
To respond or vote in a poll, a user sends an `m.poll.response` event into the room. An example being:
|
||||
|
||||
```json5
|
||||
{
|
||||
"type": "m.poll.response",
|
||||
"sender": "@bob:example.org",
|
||||
"content": {
|
||||
// Reference relationship formed per spec
|
||||
// https://spec.matrix.org/v1.6/client-server-api/#reference-relations
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.reference",
|
||||
"event_id": "$poll_start_event_id"
|
||||
},
|
||||
"m.selections": ["poutine"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
With consideration for extensible events, a new `m.selections` content block is defined:
|
||||
|
||||
* An array of string identifiers to denote a user's selection. Can be empty to denote "no selection".
|
||||
Identifiers are determined by the surrounding event type context, if available.
|
||||
|
||||
Together with content blocks from other proposals, an `m.poll.response` is described as:
|
||||
|
||||
* **Required** - An `m.relates_to` block to form a reference relationship to the poll start event.
|
||||
* **Required** - An `m.selections` block to list the user's preferred selections in the poll. Clients
|
||||
must truncate this array to `max_selections` during processing. Each entry is the `m.id` of a poll
|
||||
answer option from the poll start event. If *any* of the supplied answers is unknown, the sender's
|
||||
vote is spoiled (as if they didn't make a selection). If an entry is repeated after truncation, only
|
||||
one of those entries counts as the sender's vote (each sender gets 1 vote).
|
||||
|
||||
The above describes the minimum requirements for sending an `m.poll.response` event. Senders can add
|
||||
additional blocks, however as per the extensible events system, receivers which understand poll events
|
||||
should not honour them.
|
||||
|
||||
There is deliberately no textual or renderable fallback on poll responses: the intention is that clients
|
||||
which don't understand how to process these events will hide/ignore them. This is to mirror what a
|
||||
client which *does* support polls would do: they wouldn't render each vote as a new message, but would
|
||||
aggregate them into a single result at the end of the poll. By not having a text fallback, the vote
|
||||
is only revealed when the poll ends, which does have a text fallback.
|
||||
|
||||
Only a user's most recent vote (by `origin_server_ts`) is accepted, even if that event is invalid.
|
||||
Votes with timestamps after the poll has closed are ignored, as if they never happened. Note
|
||||
that redaction currently removes the `m.relates_to` information from the event, causing the vote to be
|
||||
detached from the poll. In this scenario, the user's vote is *reverted* to its previous state rather
|
||||
than explicitly spoiled. To "unvote" or otherwise override the previous vote state, clients should send
|
||||
a response with an empty `m.selections` array.
|
||||
|
||||
To close a poll, a user sends an `m.poll.end` event into the room. An example being:
|
||||
|
||||
```json5
|
||||
{
|
||||
"type": "m.poll.end",
|
||||
"sender": "@alice:example.org",
|
||||
"content": {
|
||||
// Reference relationship formed per spec
|
||||
// https://spec.matrix.org/v1.6/client-server-api/#reference-relations
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.reference",
|
||||
"event_id": "$poll_start_event_id"
|
||||
},
|
||||
"m.text": [{
|
||||
// Simple text is used as a fallback for text-only clients which don't understand polls. Specific formatting is
|
||||
// not specified, however something like the following is likely best.
|
||||
"body": "The poll has closed. Top answer: Poutine 🍟"
|
||||
}],
|
||||
"m.poll.results": { // optional
|
||||
"pizza": 5,
|
||||
"poutine": 8,
|
||||
"italian": 7,
|
||||
"wings": 6
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
With consideration for extensible events, a new `m.poll.results` content block is defined:
|
||||
|
||||
* A dictionary object keyed by answer ID (`m.id` from the poll start event) and value being the integer
|
||||
number of votes for that option as seen by the sender's client. Note that these values might not be
|
||||
accurate, however other clients can easily validate the counts by retrieving all relations from the
|
||||
server.
|
||||
* User IDs which voted for each option are deliberately not included for brevity: clients requiring
|
||||
more information about the poll are required to gather the relations themselves.
|
||||
|
||||
Together with content blocks from other proposals, an `m.poll.end` is described as:
|
||||
|
||||
* **Required** - An `m.relates_to` block to form a reference relationship to the poll start event.
|
||||
* **Required** - An `m.text` block to act as a fallback for clients which can't process polls.
|
||||
* **Optional** - An `m.poll.results` block to show the sender's perspective of the vote results. This
|
||||
should not be used as a trusted block, but rather as a placeholder while the client's local results
|
||||
are tabulated.
|
||||
|
||||
The above describes the minimum requirements for sending an `m.poll.end` event. Senders can add additional
|
||||
blocks, however as per the extensible events system, receivers which understand poll events should not
|
||||
honour them.
|
||||
|
||||
If a client does not support rendering polls (generally speaking), the client would instead typically
|
||||
represent the poll start event as text (per above), and thus would likely do the same for the closure
|
||||
event, keeping users in the loop with what is going on.
|
||||
|
||||
If a `m.poll.end` event is received from someone other than the poll creator or user with permission to
|
||||
redact other's messages in the room, the event must be ignored by clients due to being invalid. The
|
||||
redaction power level is chosen to support moderation: while moderators can just remove the poll from the
|
||||
timeline entirely, they may also wish to simply close it to keep context visible.
|
||||
|
||||
**Rationale**: Although clock drift is possible, as is clock manipulation, it is not anticipated that
|
||||
polls will be closed while they are still receiving high traffic. There are some cases where clients might
|
||||
apply local timers to auto-close polls, though these are typically used in extremely high traffic cases
|
||||
such as Twitch-style audience polls - rejecting even 100 responses is unlikely to significantly affect
|
||||
the results. Further, if a server were to manipulate its clock so that poll responses are sent after the
|
||||
poll was closed, but timestamped for when it was open, the server is violating a social contract and likely
|
||||
will be facing a ban from the room. This MSC does not propose a mitigation strategy beyond telling people
|
||||
not to ruin the fun. Also, don't use polls for things that are important.
|
||||
|
||||
The `m.poll.end`'s `origin_server_ts` determines when the poll closes exactly: if no valid end event
|
||||
is received, the poll is still open. If the poll is closed, only votes sent on or before that timestamp
|
||||
are considered, even if those votes are from before the start event. This is to handle clock drift over
|
||||
federation as gracefully as possible.
|
||||
|
||||
Repeated end events are ignored - only the first (valid) closure event by `origin_server_ts` is counted.
|
||||
Clients should disable voting interactions with polls once they are closed.
|
||||
|
||||
### Poll kinds
|
||||
|
||||
This proposal defines an `m.poll` content block with a `kind` field accepting namespaced strings, with
|
||||
`m.disclosed` and `m.undisclosed` being mentioned (`m.undisclosed` being the default), however it does
|
||||
not describe what these values represent.
|
||||
|
||||
In short, `m.disclosed` means the votes for poll are shown to users while the poll is still open. An
|
||||
`m.undisclosed` poll would only show results when the poll is closed.
|
||||
|
||||
**Note**: because poll responses are sent into the room, non-compliant clients or curious users could
|
||||
tally up results regardless of the poll being explicitly disclosed or not. This proposal acknowledges
|
||||
the issue, but does not fix it.
|
||||
|
||||
Custom poll kinds are possible using the [standardized namespace grammar](https://spec.matrix.org/v1.4/appendices/#common-namespaced-identifier-grammar),
|
||||
and clients which do not recognize the kind are to assume `m.undisclosed` for maximum compatibility
|
||||
with other poll kinds.
|
||||
|
||||
#### Disclosed versus undisclosed polls
|
||||
|
||||
Disclosed polls are most similar to what is seen on Twitch and often Twitter: members of the room are able
|
||||
to see the results and vote accordingly. Clients are welcome to hide the poll results until after the user
|
||||
has voted to avoid biasing the user.
|
||||
|
||||
Undisclosed polls do track who voted for what, though don't reveal the results until the poll has been
|
||||
closed, even after a user has voted themselves. This is enforced visually and not by the protocol given
|
||||
the votes are sent to the room for local tallying - this is considered more of a social trust issue than
|
||||
a technical one. This MSC expects that rooms (and clients) won't spoil the results of an undisclosed poll
|
||||
before it is closed.
|
||||
|
||||
In either case, once the poll ends the results are shown regardless of kind. Clients might wish to avoid
|
||||
disclosing who voted for what in an undisclosed poll, though this MSC leaves that at just a suggestion.
|
||||
|
||||
### Client implementation notes
|
||||
|
||||
Clients can rely on the [`/relations`](https://spec.matrix.org/v1.4/client-server-api/#get_matrixclientv1roomsroomidrelationseventidreltype)
|
||||
API to find votes which might have been received during limited ("gappy") syncs, or whenever they become
|
||||
descynchronized and need to recalculate events. Ranged approaches, such as [MSC3523](https://github.com/matrix-org/matrix-spec-proposals/pull/3523),
|
||||
are not suitable for this particular case because the gap between syncs might contain events which are not
|
||||
revealed by the range. For example, if a remote server took an extra hour to send events and the receiving
|
||||
client had a gappy sync over a span of 15 minutes: the client might not know that it needs to go back potentially
|
||||
hours to see the missing event.
|
||||
|
||||
This MSC does not describe an aggregation approach for poll events, hence the need for the client to retrieve
|
||||
all referenced events rather than simply relying on bundles.
|
||||
|
||||
## Potential issues
|
||||
|
||||
As mentioned, poll responses are sent to the room regardless of the kind of poll. For open polls this
|
||||
isn't a huge deal, but it can be considered an issue with undisclosed polls. This MSC strongly considers
|
||||
the problem a social one: users who are looking to "cheat" at the results are unlikely to engage with the
|
||||
poll in a productive way in the first place. And, of course, polls should never be used for something
|
||||
important like electing a new leader for a country.
|
||||
|
||||
Poll responses are also de-anonymized by nature of having the sender attached to a response. Clients
|
||||
are strongly encouraged to demonstrate anonymization by not showing who voted for what, but should consider
|
||||
warning the user that their vote is not anonymous. For example, saying "22 total responses, including
|
||||
from TravisR, Matthew, and Alice" before the user casts their own vote.
|
||||
|
||||
Limiting polls to client-side enforcement could be problematic if the MSC was interested in reliable
|
||||
or provable votes, however as a chat feature this should reasonably be able to achieve user expectations.
|
||||
Bolt-on support for signing, verification, validity, etc can be accomplished as well in the future.
|
||||
|
||||
Due to the reference relationship between responses and the poll start event, it's possible that a
|
||||
client facing an "unable to decrypt" error on the response won't know if it's a poll response specifically
|
||||
or some other reference relationship. Clients are encouraged to tell users when there's a possibility
|
||||
that not all responses are known, potentially impacting the results, such as where related events are
|
||||
undecryptable.
|
||||
|
||||
## Alternatives
|
||||
|
||||
The primary competition to this MSC is the author's own [MSC2192](https://github.com/matrix-org/matrix-doc/pull/2192)
|
||||
which describes not only polls but also inline widgets. The poll implementation in MSC2192 is primarily
|
||||
based around `m.room.message` events, using `msgtype` to differentiate between the different states. As
|
||||
[a thread](https://github.com/matrix-org/matrix-doc/pull/2192/files#r514497274) notes on the MSC, this
|
||||
is an awful experience on clients which do not support polls properly, leaving an irritating amount of
|
||||
contextless messages in the timeline. Though not directly mentioned on that thread, polls also cannot be
|
||||
closed under that MSC which leads to people picking options hours or even days after the poll has "ended".
|
||||
This MSC instead proposes to only supply fallback on the start and end of a poll, leading to enough context
|
||||
for unsupporting clients without flooding the room with messages.
|
||||
|
||||
Originally, MSC2192 was intended to propose polls as a sort of widget with access to timeline events
|
||||
and other important information, however the widget infrastructure is just not ready for this sort of
|
||||
thing to exist. First, we'd need to be able to send events to the widget which reference itself (for
|
||||
counting votes), and allow the widget to self-close if needed. This is surprisingly difficult when widgets
|
||||
can be "popped out" or have a link clicked in lieu of rendering (for desktop clients): there's no
|
||||
communication channel back to the client to get the information back and forth. Some of this can be solved
|
||||
with scoped access tokens for widgets, though at the time of writing those are a long ways out. In the
|
||||
end, it's simply more effective to use Extensible Events and Matrix directly rather than building out
|
||||
the widgets infrastructure to cope - MSC2192 is a demonstration of this, considering it ended up taking
|
||||
out all the widget aspects and replacing them with fields in the content.
|
||||
|
||||
Finally, MSC2192 is simply inferior due to not being able to restrict who can post a poll. Responses
|
||||
and closures can also be limited arbitrarily by room admins, so clients might want to check to make
|
||||
sure that the sender has a good chance of being able to close the poll they're about to create just
|
||||
to avoid future issues.
|
||||
|
||||
### Aggregations instead of references?
|
||||
|
||||
A brief moment in this MSC's history described an approach which used aggregations (annotations/reactions)
|
||||
instead of the proposed reference relationships, though this had immediate concerns of being too
|
||||
complicated for practical use.
|
||||
|
||||
While it is beneficial for votes to be quickly tallied by the server, the client still needs to do
|
||||
post-processing on the data from the server in order to accurately represent the valid votes. The
|
||||
server should not be made aware of the poll rules as it can lead to over-dependence on the server,
|
||||
potentially causing excessive network requests from clients.
|
||||
|
||||
As such, the reference relationship is maintained by this proposal in order to remain consistent with
|
||||
how the poll close event is sent: instead of clients having to process two paginated requests they can
|
||||
use a single request to get the same information, but in a more valuable form.
|
||||
|
||||
For completeness, the approach of aggregations-based responses is summarized as:
|
||||
|
||||
* `m.annotation` `rel_type`
|
||||
* `key` is an answer ID
|
||||
* Multiple response events for multi-select polls. Only the most recent duplicate is considered valid.
|
||||
* Unvoting is done through redaction.
|
||||
|
||||
Additional concerns are how the client needs to ensure that the answer IDs won't collide with a reaction
|
||||
or other annotation, adding additional complexity in the form of magic strings.
|
||||
|
||||
## Security considerations
|
||||
|
||||
As mentioned a multitude of times throughout this proposal, this MSC's approach is prone to disclosure
|
||||
of votes and has a couple abuse vectors which make it not suitable for important or truly secret votes.
|
||||
Do not use this functionality to vote for presidents.
|
||||
|
||||
Clients should apply a large amount of validation to each field when interacting with polls. Event
|
||||
bodies are already declared as completely untrusted, though not all clients apply a layer of validation.
|
||||
In general, this MSC aims to try and show something of use to users so they can at least figure out
|
||||
what the sender intended, though clients are also welcome to just hide invalid events/responses (with
|
||||
the exception of spoiled votes: those are treated as "unvoting" or choosing nothing). Clients are
|
||||
encouraged to try and fall back to something sensible, even if just an error message saying the poll
|
||||
is invalid.
|
||||
|
||||
Users should be wary of polls changing their question after they have voted. Considering polls can be
|
||||
edited, responses might no longer be relevant. For example, if a poll was opened for "do you like
|
||||
cupcakes?" and you select "yes", the question may very well become "should we outlaw cupcakes?" where
|
||||
your "yes" no longer applies. This MSC considers this problem more of a social issue than a technical
|
||||
one, and reminds the reader that polls should not be used for anything important/serious at the moment.
|
||||
|
||||
## Future considerations
|
||||
|
||||
Some aspects of polls are explicitly not covered by this MSC, and are intended for another future MSC
|
||||
to solve:
|
||||
|
||||
* Allowing voters/room members to add their own freeform options. The edits system doesn't prevent other
|
||||
members from editing messages, though clients tend to reject edits which are not made by the original
|
||||
author. Altering this rule to allow it on some polls could be useful in a future MSC.
|
||||
|
||||
* Verifiable or cryptographically secret polls. There is interest in a truly enforceable undisclosed poll
|
||||
where even if the client wanted to it could not reveal the results before the poll is closed. Approaches
|
||||
like [MSC3184](https://github.com/matrix-org/matrix-doc/pull/3184) or Public Key Infrastructure (PKI)
|
||||
might be worthwhile to investigate in a future MSC.
|
||||
|
||||
## Other notes
|
||||
|
||||
If a client/user wishes to make a poll statically visible, they should check out
|
||||
[pinned messages](https://spec.matrix.org/v1.4/client-server-api/#mroompinned_events).
|
||||
|
||||
Notifications support for polls have been moved to [MSC3930](https://github.com/matrix-org/matrix-spec-proposals/pull/3930).
|
||||
|
||||
Normally extensible events would only be permitted in a specific room version, however as a known-lossy chat
|
||||
feature, this proposal's events are permitted in any room version. The stable event types should only be sent
|
||||
in a room version which supports extensible events, however.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
While this MSC is not considered stable, implementations should use `org.matrix.msc3381.*` as a namespace
|
||||
instead of `m.*` throughout this proposal, with the added considerations below. Note that extensible events
|
||||
and content blocks might have their own prefixing requirements.
|
||||
|
||||
Unstable implementations should note that a previous draft is responsible for defining the event format/schema
|
||||
for the unstable prefix. The differences are rooted in a change in MSC1767 (Extensible Events) where the approach
|
||||
and naming of fields changed. The differences are:
|
||||
|
||||
* For `m.poll.start` / `org.matrix.msc3381.poll.start`:
|
||||
* `m.text` throughout becomes a single string, represented as `org.matrix.msc1767.text`
|
||||
* `m.poll` becomes `org.matrix.msc3381.poll.start`, retaining all other fields as described. Note the `m.text`
|
||||
under `question` and `answers`, and the `org.matrix.msc3381.poll` prefix for `kind` enum values. `m.id` under
|
||||
`answers` additionally becomes `id`, without prefix.
|
||||
* For `m.poll.response` / `org.matrix.msc3381.poll.response`:
|
||||
* `m.selections` becomes an `org.matrix.msc3381.poll.response` object with a single key `answers` being the
|
||||
array of selections.
|
||||
* `m.relates_to` is unchanged.
|
||||
* For `m.poll.end` / `org.matrix.msc3381.poll.end`:
|
||||
* `m.text` has the same change as `m.poll.start`.
|
||||
* `m.poll.results` is removed.
|
||||
* `org.matrix.msc3381.poll.end` is added as an empty object, and is required.
|
||||
|
||||
Examples of unstable events are:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "org.matrix.msc3381.poll.start",
|
||||
"content": {
|
||||
"org.matrix.msc1767.text": "What should we order for the party?\n1. Pizza 🍕\n2. Poutine 🍟\n3. Italian 🍝\n4. Wings 🔥",
|
||||
"org.matrix.msc3381.poll.start": {
|
||||
"kind": "org.matrix.msc3381.poll.disclosed",
|
||||
"max_selections": 1,
|
||||
"question": {
|
||||
"org.matrix.msc1767.text": "What should we order for the party?",
|
||||
},
|
||||
"answers": [
|
||||
{"id": "pizza", "org.matrix.msc1767.text": "Pizza 🍕"},
|
||||
{"id": "poutine", "org.matrix.msc1767.text": "Poutine 🍟"},
|
||||
{"id": "italian", "org.matrix.msc1767.text": "Italian 🍝"},
|
||||
{"id": "wings", "org.matrix.msc1767.text": "Wings 🔥"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "org.matrix.msc3381.poll.response",
|
||||
"content": {
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.reference",
|
||||
"event_id": "$fw8dod4VdLCkakmKiD6XiVj7-RrFir9Jwc9RW6llJhU"
|
||||
},
|
||||
"org.matrix.msc3381.poll.response": {
|
||||
"answers": ["pizza"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "org.matrix.msc3381.poll.end",
|
||||
"content": {
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.reference",
|
||||
"event_id": "$fw8dod4VdLCkakmKiD6XiVj7-RrFir9Jwc9RW6llJhU"
|
||||
},
|
||||
"org.matrix.msc1767.text": "The poll has ended. Top answer: Italian 🍝",
|
||||
"org.matrix.msc3381.poll.end": {},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Implementation considerations
|
||||
|
||||
Client authors should note that as a feature using the Extensible Events system,
|
||||
usage of the *stable* event types in regular room versions is not permitted. As
|
||||
of writing (December 2023), Extensible Events does not have a *stable* room version
|
||||
which supports such events, therefore meaning that clients will have to use the
|
||||
*unstable* event types if they intend to support polls in existing room versions.
|
||||
|
||||
When Extensible Events as a system is released in a dedicated room version, clients
|
||||
will be able to use the stable event types there. The unstable event types should
|
||||
not be used in that dedicated room version.
|
@ -0,0 +1,28 @@
|
||||
# MSC3604: Room Version 11
|
||||
|
||||
A new room version, `11`, is proposed using [room version 10](https://spec.matrix.org/v1.7/rooms/v10/) as a base
|
||||
and incorporating the following MSCs:
|
||||
|
||||
* [MSC2174](https://github.com/matrix-org/matrix-spec-proposals/pull/2174) - Move `redacts` to sane place
|
||||
* [MSC2175](https://github.com/matrix-org/matrix-spec-proposals/pull/2175) - Remove `creator` field from `m.room.create` events
|
||||
* [MSC2176](https://github.com/matrix-org/matrix-spec-proposals/pull/2176) - Updates to redaction rules
|
||||
* [MSC3989](https://github.com/matrix-org/matrix-spec-proposals/pull/3989) - Redact `origin` on events
|
||||
* [MSC3821](https://github.com/matrix-org/matrix-spec-proposals/pull/3821) - More updates to redaction rules
|
||||
|
||||
Though other MSCs are capable of being included in this version, they do not have sufficient implementation to be
|
||||
considered stable enough for v11 rooms. A future room version may still include them. Such examples of ineligible MSCs
|
||||
are:
|
||||
|
||||
* [MSC2244](https://github.com/matrix-org/matrix-spec-proposals/pull/2244) - Mass redactions
|
||||
* A number of MSCs which have not yet been accepted (they are not iterated here).
|
||||
|
||||
Room version 11 upon being added to the specification shall be considered stable. No other room versions are affected
|
||||
by this MSC.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
Implementations looking to test v11 before written into the specification should use `org.matrix.msc3820.opt2`
|
||||
as the room version, treating it as unstable.
|
||||
|
||||
Note: `org.matrix.msc3820.opt1` is from a prior draft of this proposal, consisting of different MSCs than the
|
||||
current iteration. Implementations should not treat opt1 the same as other unstable-for-MSC3820 versions.
|
@ -0,0 +1,37 @@
|
||||
# MSC3821: Update redaction rules, again
|
||||
|
||||
[MSC2176](https://github.com/matrix-org/matrix-spec-proposals/pull/2176) aimed to fix inconsistencies
|
||||
with the [redaction algorithm](https://spec.matrix.org/v1.6/rooms/v10/#redactions) where server-side
|
||||
event auth required properties to exist that were being removed. While MSC2176 fixed a number of cases,
|
||||
one was unfortunately missed.
|
||||
|
||||
This MSC aims to fix that missing case, originally identified long ago by [synapse#1831](https://github.com/matrix-org/synapse/issues/1831).
|
||||
|
||||
## Proposal
|
||||
|
||||
*Note*: It is recommended to read [MSC2176](https://github.com/matrix-org/matrix-spec-proposals/pull/2176)
|
||||
before this proposal as MSC2176 contains a lot of backing context.
|
||||
|
||||
In a future room version, the following changes are made to the [redaction algorithm](https://spec.matrix.org/v1.6/rooms/v10/#redactions).
|
||||
Note that this requires a new room version because changing the redaction algorithm changes how
|
||||
[event IDs](https://spec.matrix.org/v1.6/rooms/v10/#event-ids) are calculated, as they are
|
||||
[reference hashes](https://spec.matrix.org/v1.6/server-server-api/#calculating-the-reference-hash-for-an-event)
|
||||
which redact the event during calculation.
|
||||
|
||||
* [`m.room.member`](https://spec.matrix.org/v1.6/client-server-api/#mroommember) events preserve a portion
|
||||
of `third_party_invite` under `content`, if present. Those properties being:
|
||||
|
||||
* `signed`: the block is required for the server to validate the event, however excess adjacent properties
|
||||
such as `display_name` are not important.
|
||||
|
||||
Clients should note that because `display_name` is *not* preserved during redaction they might need to change
|
||||
how that event is rendered/presented to users. For example, when rendering such a redacted event the client
|
||||
might show it as "Bob accepted a third party invite".
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
Implementations looking to test these changes before adopted into a stable room version should use
|
||||
`org.matrix.msc3821.opt1` as the room version, using **v9** as a base and treating it as unstable.
|
||||
|
||||
**History**: This MSC was originally written before room version 10 existed. Implementations wishing to use
|
||||
v10 as a base instead of v9 should use `org.matrix.msc3821.opt1.v10` as the room version instead.
|
@ -0,0 +1,142 @@
|
||||
# MSC3930: Polls push rules/notifications
|
||||
|
||||
[MSC3381](https://github.com/matrix-org/matrix-spec-proposals/pull/3381) describes how chat polls can work,
|
||||
though deliberately leaves out details on how push rules or notifications could work for such a feature.
|
||||
This proposal aims to address that specific feature gap.
|
||||
|
||||
Readers should review MSC3381 to better understand how polls are intended to operate in a room.
|
||||
|
||||
Push rules are currently defined [here](https://spec.matrix.org/v1.7/client-server-api/#push-rules) in
|
||||
specification.
|
||||
|
||||
## Proposal
|
||||
|
||||
Polls should behave similar to message events. To achieve this effect, we define the following underride
|
||||
push rules which mimic their `m.room.message` partners.
|
||||
|
||||
Note that [order matters](https://github.com/matrix-org/matrix-spec/issues/1406) for push rules - these
|
||||
underride rules are to be inserted immediately after the `.m.rule.encrypted` underride push rule, in the
|
||||
order presented by this MSC.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"rule_id": ".m.rule.poll_start_one_to_one",
|
||||
"default": true,
|
||||
"enabled": true,
|
||||
"conditions": [
|
||||
{"kind": "room_member_count", "is": "2"},
|
||||
|
||||
// Note: `.` is escaped once, but for valid JSON we need to escape the escape.
|
||||
{"kind": "event_property_is", "key": "type", "value": "m\\.poll\\.start"}
|
||||
],
|
||||
"actions": [
|
||||
"notify",
|
||||
{"set_tweak": "sound", "value": "default"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"rule_id": ".m.rule.poll_start",
|
||||
"default": true,
|
||||
"enabled": true,
|
||||
"conditions": [
|
||||
// Note: `.` is escaped once, but for valid JSON we need to escape the escape.
|
||||
{"kind": "event_property_is", "key": "type", "value": "m\\.poll\\.start"}
|
||||
],
|
||||
"actions": [
|
||||
"notify"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"rule_id": ".m.rule.poll_end_one_to_one",
|
||||
"default": true,
|
||||
"enabled": true,
|
||||
"conditions": [
|
||||
{"kind": "room_member_count", "is": "2"},
|
||||
|
||||
// Note: `.` is escaped once, but for valid JSON we need to escape the escape.
|
||||
{"kind": "event_property_is", "key": "type", "value": "m\\.poll\\.end"}
|
||||
],
|
||||
"actions": [
|
||||
"notify",
|
||||
{"set_tweak": "sound", "value": "default"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"rule_id": ".m.rule.poll_end",
|
||||
"default": true,
|
||||
"enabled": true,
|
||||
"conditions": [
|
||||
// Note: `.` is escaped once, but for valid JSON we need to escape the escape.
|
||||
{"kind": "event_property_is", "key": "type", "value": "m\\.poll\\.end"}
|
||||
],
|
||||
"actions": [
|
||||
"notify"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Additionally, a new override rule is defined to suppress poll responses by default, inserted immediately
|
||||
after the `.m.rule.room.server_acl` override rule.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"rule_id": ".m.rule.poll_response",
|
||||
"default": true,
|
||||
"enabled": true,
|
||||
"conditions": [
|
||||
// Note: `.` is escaped once, but for valid JSON we need to escape the escape.
|
||||
{"kind": "event_property_is", "key": "type", "value": "m\\.poll\\.response"}
|
||||
],
|
||||
"actions": []
|
||||
}
|
||||
```
|
||||
|
||||
*Note*: Lack of `actions` means "don't do anything with matching events", or "don't notify".
|
||||
|
||||
Typically these rules would be kept in sync with the `m.room.message` rules they are based upon,
|
||||
however there is no requirement to do so. A client's approach might be to only keep them in sync
|
||||
while setting the values, rather than monitoring for changes to push rules.
|
||||
|
||||
Clients might find [MSC3934](https://github.com/matrix-org/matrix-spec-proposals/pull/3934) of value
|
||||
for keeping the rules in sync, though this MSC does not require MSC3934.
|
||||
|
||||
For the purposes of [MSC3932](https://github.com/matrix-org/matrix-spec-proposals/pull/3932), the
|
||||
push rules defined in this proposal are *not* affected by the room version limitations. This is due
|
||||
to polls not inherently being room version-specific, unlike other extensible event structures. For
|
||||
clarity, this means the push rules described here are treated the same as `.m.rule.master` (for
|
||||
example) - they always apply, regardless of room version.
|
||||
|
||||
## Potential issues
|
||||
|
||||
The push rules for this feature are complex and not ideal. The author believes that it solves a short
|
||||
term need while other MSCs work on improving the notifications system. Most importantly, the author
|
||||
believes future MSCs which aim to fix notifications for extensible events in general will be a more
|
||||
preferred approach over this MSC's (hopefully) short-term solution.
|
||||
|
||||
## General considerations
|
||||
|
||||
While the order within the MSC is deliberate for the new rules, the positioning relative to other rules
|
||||
already in the spec is fairly arbitrary. The new rules are placed at the end of each list (underride and
|
||||
override) for simplicity, but could realistically go anywhere in the list.
|
||||
|
||||
See ["Dot-separated property paths"](https://spec.matrix.org/v1.7/appendices/#dot-separated-property-paths)
|
||||
for more information on why we escape the `event_property_is` condition values.
|
||||
|
||||
## Security considerations
|
||||
|
||||
None applicable - no new considerations need to be made with this proposal.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
While this MSC is not considered stable, implementations should use `org.matrix.msc3930.*` as a prefix
|
||||
in place of `m.*` for the push rule IDs. The event types for those associated push rules are described
|
||||
by the [Unstable Prefix section of MSC3381](https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/3381-polls.md#unstable-prefix).
|
@ -0,0 +1,142 @@
|
||||
# MSC3958: Suppress notifications from message edits
|
||||
|
||||
[Event replacement](https://spec.matrix.org/v1.7/client-server-api/#event-replacements)
|
||||
(more commonly known as message edits) signals that a message is intended to
|
||||
be replaced with new content.
|
||||
|
||||
This works well for fixing typos or other minor correction, but can cause
|
||||
spurious notifications if the event mentions a user's display name / localpart or
|
||||
if it includes `@room` (which is particularly bad in large rooms as every user
|
||||
is re-notified). This contributes to notification fatigue as the additional
|
||||
notifications contain no new information.
|
||||
|
||||
Additionally for users which have a room set to "all messages" then every event
|
||||
edit results in an additional notification.[^1]
|
||||
|
||||
## Proposal
|
||||
|
||||
A new default push rule is added to suppress notifications due to [edits](https://spec.matrix.org/v1.7/client-server-api/#event-replacements).
|
||||
|
||||
```json
|
||||
{
|
||||
"rule_id": ".m.rule.suppress_edits",
|
||||
"default": true,
|
||||
"enabled": true,
|
||||
"conditions": [
|
||||
{
|
||||
"kind": "event_property_is",
|
||||
"key": "content.m\\.relates_to.rel_type",
|
||||
"value": "m.replace"
|
||||
}
|
||||
],
|
||||
"actions": []
|
||||
}
|
||||
```
|
||||
|
||||
This rule should be placed after the [`.m.rule.room.server_acl` rule](https://spec.matrix.org/v1.7/client-server-api/#default-override-rules)
|
||||
as the last override rule.
|
||||
|
||||
It would match events such as those given in [event replacements](https://spec.matrix.org/v1.7/client-server-api/#event-replacements)
|
||||
portion of the spec:
|
||||
|
||||
```json5
|
||||
{
|
||||
"type": "m.room.message",
|
||||
"content": {
|
||||
"body": "* Hello! My name is bar",
|
||||
"msgtype": "m.text",
|
||||
"m.new_content": {
|
||||
"body": "Hello! My name is bar",
|
||||
"msgtype": "m.text"
|
||||
},
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.replace",
|
||||
"event_id": "$some_event_id"
|
||||
}
|
||||
},
|
||||
// ... other fields required by events
|
||||
}
|
||||
```
|
||||
|
||||
With the [updated mentions behavior in Matrix 1.7](https://spec.matrix.org/v1.7/client-server-api/#user-and-room-mentions),
|
||||
this would allow the [`.m.rule.is_user_mention`](https://spec.matrix.org/v1.7/client-server-api/#_m_rule_is_user_mention)
|
||||
and the [`.m.rule.is_room_mention`](https://spec.matrix.org/v1.7/client-server-api/#_m_rule_is_room_mention)
|
||||
rules to continue matching, even for edited events, while suppressing notifications
|
||||
from other edits.
|
||||
|
||||
Some users may be depending on notifications of edits. If a user would like to
|
||||
revert to the old behavior they can disable the `.m.rule.suppress_edits` push rule.
|
||||
|
||||
## Potential issues
|
||||
|
||||
### Edits of invites and tombstones
|
||||
|
||||
The [`.m.rule.invite_for_me` and `.m.rule.tombstone`](https://spec.matrix.org/v1.7/client-server-api/#default-override-rules)
|
||||
rules may still cause spurious notifications if events which match those rules
|
||||
are edited. Both of those are state events and
|
||||
[not subject to valid edits](https://spec.matrix.org/v1.7/client-server-api/#validity-of-replacement-events).
|
||||
|
||||
### Keeping notifications up-to-date
|
||||
|
||||
Mobile clients currently depend on the push notifications of edited events to update the
|
||||
text of on-screen notifications. The proposed push rule would result in mobile clients no
|
||||
longer receiving these edits; but showing slightly outdated text on a notification screen. That
|
||||
is only a minor impact and it would be better to separate when (& why) we send pushes vs.
|
||||
when we generate notifications.
|
||||
|
||||
### Suppression of notifications to a new keyword
|
||||
|
||||
If an event is edited and the new event (but not the original event) matches a keyword
|
||||
then the notification would erroneously be suppressed.
|
||||
|
||||
## Alternatives
|
||||
|
||||
An alternative solution would be to add a push rule with no actions and a condition to
|
||||
check whether a notification was generated for the original message.
|
||||
|
||||
This would be placed as an override rule before the `.m.rule.contains_display_name`
|
||||
and the `.m.rule.roomnotif` [push rules](https://spec.matrix.org/v1.7/client-server-api/#push-rules).
|
||||
|
||||
This would suppress duplicate notifications, while still allow for new notifications due
|
||||
to new mentions or keywords changing.
|
||||
|
||||
## Security considerations
|
||||
|
||||
None forseen.
|
||||
|
||||
## Future extensions
|
||||
|
||||
If message edits by other senders were allowed than it would be useful to
|
||||
know when your own message was edited, but this
|
||||
[is not currently allowed](https://spec.matrix.org/v1.7/client-server-api/#validity-of-replacement-events).
|
||||
A future MSC to define this behavior should take into account notifying
|
||||
users in this situation.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
The unstable prefix of `.org.matrix.msc3958.suppress_edits` should be used in place of
|
||||
`.m.rule.suppress_edits`.
|
||||
|
||||
A previous version of this MSC used `.com.beeper.suppress_edits` with a different condition
|
||||
(which should match the same events), but different rule placement.
|
||||
|
||||
## Dependencies
|
||||
|
||||
N/A
|
||||
|
||||
<!-- Footnotes below -->
|
||||
|
||||
[^1]: A room can be configured to be notify for "all messages" by creating a [room-specific push rule](https://spec.matrix.org/v1.7/client-server-api/#push-rules)
|
||||
with an `rule_id` of the room ID & has `actions` set to "notify" , e.g.:
|
||||
|
||||
```json
|
||||
{
|
||||
"rule_id" : "!abcdef:example.com",
|
||||
"default" : false,
|
||||
"enabled" : true,
|
||||
"actions" : ["notify"]
|
||||
}
|
||||
```
|
||||
|
||||
See the [Element Web](https://github.com/matrix-org/matrix-react-sdk/blob/da7aa4055e04f291be9b5141b704bd12aec03d0c/src/RoomNotifs.ts#L162-L170)
|
||||
implementation.
|
@ -0,0 +1,165 @@
|
||||
# MSC3981: `/relations` recursion
|
||||
|
||||
The [`/relations`] API allows clients to retrieve events which directly relate
|
||||
to a given event.
|
||||
|
||||
This API has been used as basis of many other features and MSCs since then,
|
||||
including threads.
|
||||
|
||||
Threads was one of the first usages of this API that allowed nested relations -
|
||||
an event may have an [`m.reaction`] or [`m.replace`] relation to another event,
|
||||
which in turn may have an `m.thread` relation to the thread root.
|
||||
|
||||
This forms a tree of relations. A client wanting to display a thread will want
|
||||
to display reactions and edits to messages in the thread, and will therefore need
|
||||
the second-order related events in addition to just the events with a direct thread
|
||||
relation to the root.
|
||||
|
||||
Clients can recursively perform the /relations queries on each event but this is
|
||||
very slow and does not give the client any information on how the events are ordered
|
||||
for the purpose of sending read receipts.
|
||||
|
||||
## Proposal
|
||||
|
||||
It is proposed to add the `recurse` parameter to the `/relations` API, defined
|
||||
as follows:
|
||||
|
||||
> Whether to additionally include events which only relate indirectly to the
|
||||
> given event,
|
||||
> ie. events related to the root events via one or more direct relationships.
|
||||
>
|
||||
> If set to false, only events which have direct a relation with the given
|
||||
> event will be included.
|
||||
>
|
||||
> If set to true, all events which relate to the given event, or relate to
|
||||
> events that relate to the given event, will be included.
|
||||
>
|
||||
> It is recommended that at least 3 levels of relationships are traversed.
|
||||
> Implementations may perform more but should be careful to not infinitely recurse.
|
||||
>
|
||||
> One of: `[true false]`.
|
||||
|
||||
In order to be backwards compatible the `recurse` parameter must be
|
||||
optional (defaulting to `false`).
|
||||
|
||||
Regardless of the value of the `recurse` parameter, events will always be
|
||||
returned in topological ordering, ie. the same order in which the `/messages` API
|
||||
would return them (given the same `dir` parameter).
|
||||
|
||||
It is also proposed to add a response parameter, `recursion_depth` to the response
|
||||
which gives the actual depth limit the server used in its recursion. This key is mandatory if
|
||||
the `recurse` parameter was passed and is absent otherwise. eg:
|
||||
|
||||
```json
|
||||
{
|
||||
"chunk": [...],
|
||||
"recursion_depth": 3
|
||||
}
|
||||
```
|
||||
|
||||
Note that there no way in this MSC for a client to affect how much the server recurses.
|
||||
If the client decides that the server's recursion level is insufficient, it could, for example,
|
||||
perform the recursion manually, or disable whatever feature requires more recursion.
|
||||
|
||||
Filters specified via `event_type` or `rel_type` will be applied to all events
|
||||
returned, whether direct or indirect relations. Events that would match the filter,
|
||||
but whose only relation to the original given event is through a non-matching
|
||||
intermediate event, will not be included. This means that supplying a `rel_type`
|
||||
parameter of `m.thread` is not appropriate for fetching all events in a thread since
|
||||
relations to the threaded events would be filtered out. For this purpose, clients should
|
||||
omit the `rel_type` parameter and perform any necessary filtering on the client side.
|
||||
|
||||
## Potential issues
|
||||
|
||||
Naive implementations might be tempted to provide support for this parameter
|
||||
through a thin shim which is functionally identical to the client doing
|
||||
separate recursive `/relations` requests itself. However this would allow a
|
||||
client to craft a set of events that would cause unreasonable load.
|
||||
|
||||
## Alternatives
|
||||
|
||||
1. Clients could fetch all relations recursively client-side, which would
|
||||
increase network traffic and server load significantly.
|
||||
2. A new, specialised endpoint could be created for threads, specifically
|
||||
designed to present separate timelines that, in all other ways, would
|
||||
behave identically to `/messages`.
|
||||
3. Twitter-style threads (see [MSC2836]).
|
||||
4. Alternatively a `depth` parameter could have been specified, as in [MSC2836].
|
||||
We believe that a customizable depth would add unnecessary constraints to
|
||||
server implementers, as different server implementations may have different
|
||||
performance considerations and may choose different limits. Additionally,
|
||||
the maximum currently achievable depth is still low enough to avoid this
|
||||
becoming an issue.
|
||||
|
||||
## Security considerations
|
||||
|
||||
Security considerations are discussed inline throughout this proposal. To summarise:
|
||||
* Allowing a client to control recursion depth could allow a client to cause outsize
|
||||
load on the server if the server doesn't check the recursion depth.
|
||||
* Naive server implementations could allow a client to craft a set of events that would
|
||||
cause high load.
|
||||
|
||||
## Examples
|
||||
|
||||
Given the following graph:
|
||||
|
||||
```mermaid
|
||||
flowchart RL
|
||||
subgraph Thread
|
||||
G
|
||||
E-->D
|
||||
B-->A
|
||||
end
|
||||
B-.->|m.thread|A
|
||||
G-.->|m.thread|A
|
||||
E-.->|m.annotation|B
|
||||
D-.->|m.edit|A
|
||||
G-->F-->E
|
||||
D-->C-->B
|
||||
```
|
||||
|
||||
`/messages` with `dir=f` would
|
||||
return `[A, B, C, D, E, F, G]`.
|
||||
|
||||
`/relations` on event `A` with `rel_type=m.thread` and `dir=f` would
|
||||
return `[B, G]`.
|
||||
|
||||
`/relations` on event `A` with `recurse=true` and `dir=f` would
|
||||
return `[B, D, E, G]`.
|
||||
|
||||
`/relations` on event `A` with `recurse=true`, `dir=b` and `limit=2` would
|
||||
return `[G, E]`.
|
||||
|
||||
`/relations` on event `A` with `rel_type=m.annotation`,
|
||||
`event_type=m.reaction` and `recurse=true` would return `[G, E]`.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
### While the MSC is not yet part of a spec version
|
||||
|
||||
During this period, to detect server support, clients should check for the
|
||||
presence of the `org.matrix.msc3981` flag in the `unstable_features` map
|
||||
on [`/versions`](https://spec.matrix.org/v1.7/client-server-api/#get_matrixclientversions).
|
||||
|
||||
Clients are also required to use `org.matrix.msc3981.recurse` in place
|
||||
of `recurse` at this time.
|
||||
|
||||
`recursion_depth` is always used un-namespaced (it would only ever be sent
|
||||
if the client had already sent the recurse parameter).
|
||||
|
||||
### Once the MSC is in a spec version
|
||||
|
||||
Once this MSC becomes a part of a spec version, clients should rely on the
|
||||
presence of the spec version that supports this MSC in the `/version` response
|
||||
to determine support.
|
||||
|
||||
Servers are encouraged to keep the `org.matrix.msc3827` flag around for a
|
||||
reasonable amount of time to help smooth over the transition for clients.
|
||||
"Reasonable" is intentionally left as an implementation detail, however the MSC
|
||||
process currently recommends at most 2 months from the date of spec release.
|
||||
|
||||
[MSC2836]: https://github.com/matrix-org/matrix-spec-proposals/pull/2836
|
||||
[MSC3771]: https://github.com/matrix-org/matrix-spec-proposals/pull/3771
|
||||
[`/relations`]: https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv1roomsroomidrelationseventid
|
||||
[`m.reaction`]: https://github.com/matrix-org/matrix-spec-proposals/pull/2677
|
||||
[`m.replace`]: https://spec.matrix.org/v1.6/client-server-api/#event-replacements
|
@ -0,0 +1,61 @@
|
||||
# MSC3989: Redact `origin` property on events
|
||||
|
||||
The [current redaction algorithm](https://spec.matrix.org/v1.6/rooms/v10/#redactions) *keeps* the
|
||||
top-level `origin` property on events during redaction, however, as of this writing, the only use within the
|
||||
spec of `origin` as a top-level event property is a malformed example of event format. The property has no
|
||||
significant meaning in modern room versions.
|
||||
|
||||
Within the ecosystem, it's clear that we'd [prefer the property to disappear](https://github.com/matrix-org/matrix-spec/issues/374),
|
||||
and have [tried to do so](https://github.com/matrix-org/matrix-spec/pull/998) in the past. The
|
||||
malformed examples are even [known to us](https://github.com/matrix-org/matrix-spec/issues/1480).
|
||||
|
||||
What's not clear, and mentioned in [a comment](https://github.com/matrix-org/matrix-spec/issues/1480#issuecomment-1495183789),
|
||||
is whether the `origin` property is *actually* used. There do not appear to be any auth rules or similar
|
||||
which would use the property, however it'd hardly be the first time that the spec was wrong about an
|
||||
ancient room version like v1. What is clear is that Synapse, where this question would be asked,
|
||||
wants to [drop support](https://github.com/matrix-org/synapse/issues/3816) for the property and has
|
||||
taken [steps](https://github.com/matrix-org/synapse/pull/8324) towards that mission by fixing bugs
|
||||
in the area. In a [quick audit](https://github.com/matrix-org/matrix-spec-proposals/pull/3989#issuecomment-1497659507)
|
||||
of the Synapse codebase during implementation of this MSC, the `origin` property appears unused.
|
||||
|
||||
Given the above context, this proposal removes the `origin` property from the [redaction algorithm](https://spec.matrix.org/v1.7/rooms/v10/#redactions)
|
||||
in a future room version, leaving it as-is for existing versions (not that an MSC can change the behaviour
|
||||
of an already-stable room version anyways).
|
||||
|
||||
Some other properties are additionally useless in modern room versions, however they are already adapted
|
||||
by [MSC2176](https://github.com/matrix-org/matrix-spec-proposals/pull/2176).
|
||||
|
||||
## Proposal
|
||||
|
||||
In a future room version, the `origin` property is *removed* from the list of *event* keys which are
|
||||
kept during redaction. Note that this requires a new room version because changing the redaction
|
||||
algorithm changes how [event IDs](https://spec.matrix.org/v1.6/rooms/v10/#event-ids) are calculated,
|
||||
as they are [reference hashes](https://spec.matrix.org/v1.6/server-server-api/#calculating-the-reference-hash-for-an-event)
|
||||
which redact the event during calculation.
|
||||
|
||||
## Potential issues
|
||||
|
||||
No major concerns.
|
||||
|
||||
## Alternatives
|
||||
|
||||
No significant alternatives.
|
||||
|
||||
## Security considerations
|
||||
|
||||
No major concerns.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
While this MSC is not considered stable, implementations should use `org.matrix.msc3989` as the room
|
||||
version identifier, using v10 as a base.
|
||||
|
||||
## Dependencies
|
||||
|
||||
No blocking dependencies.
|
||||
|
||||
This MSC would partner well with the following MSCs, however:
|
||||
* [MSC2176](https://github.com/matrix-org/matrix-spec-proposals/pull/2176)
|
||||
* [MSC2175](https://github.com/matrix-org/matrix-spec-proposals/pull/2175)
|
||||
* [MSC2174](https://github.com/matrix-org/matrix-spec-proposals/pull/2174)
|
||||
* [MSC3821](https://github.com/matrix-org/matrix-spec-proposals/pull/3821)
|
@ -0,0 +1,103 @@
|
||||
# MSC4009: Expanding the Matrix ID grammar to enable E.164 IDs
|
||||
|
||||
[E.164](https://www.itu.int/rec/T-REC-E.164) is a set of international standards
|
||||
for telephone numbering. This defines a phone number as a `+` followed by a country
|
||||
code (e.g. `1` for the US, `44` for the UK) followed by a local phone number.
|
||||
For example, a E.164 phone number would look like: `+15558675309`.
|
||||
|
||||
It is somewhat common[^1] for social networks or messaging applications to use phone
|
||||
numbers as identifiers instead of relying on users remembering separate usernames
|
||||
(and needing to tell other users how to find them).
|
||||
|
||||
[Matrix user identifiers](https://spec.matrix.org/v1.6/appendices/#user-identifiers)
|
||||
are *almost* compatible with E.164:
|
||||
|
||||
> The `localpart` of a user ID is an opaque identifier for that user. It MUST NOT
|
||||
> be empty, and MUST contain only the characters `a-z`, `0-9`, `.`, `_`, `=`, `-`,
|
||||
> and `/`.
|
||||
|
||||
## Proposal
|
||||
|
||||
Add `+` to the list of allowed characters in a Matrix user identifier. This would
|
||||
allow a full E.164 phone number as a user's username on a server, which is common
|
||||
practice for many applications. This should hopefully ease bridging of those
|
||||
services to Matrix or help them natively speak Matrix in the future. Users would
|
||||
not need to learn a new Matrix ID, but can continue using their phone number, as
|
||||
today.
|
||||
|
||||
Although E.164 IDs are meant to be globally unique they are still namespaced under
|
||||
a domain under this proposal, e.g. `@+15558675309:example.com`, as the same user may
|
||||
already be registered on multiple service providers.
|
||||
|
||||
## Potential issues
|
||||
|
||||
Homeservers and clients must already be
|
||||
[more tolerant of Matrix user IDs](https://spec.matrix.org/v1.6/appendices/#historical-user-ids):
|
||||
|
||||
> Older versions of this specification were more tolerant of the characters
|
||||
> permitted in user ID localparts. [...] clients and servers MUST accept user IDs
|
||||
> with localparts from the expanded character set:
|
||||
>
|
||||
> `extended_user_id_char = %x21-39 / %x3B-7E ; all ASCII printing chars except :`
|
||||
|
||||
Thus, it is expected to not cause any issues, although clients will need to identify
|
||||
that the `+` character is valid for a homeserver. This could be from the supported
|
||||
Matrix versions which the homeserver advertises.
|
||||
|
||||
----
|
||||
|
||||
A user having two accounts with the same identifier on different services is not
|
||||
ideal, but is not different than today where a user may log into both WhatsApp
|
||||
and Signal with their phone number. This MSC does *not* attempt to help with mapping
|
||||
of an E.164 identifier to an actual Matrix ID, that's best left to the current
|
||||
[identity service `/lookup` endpoint](https://spec.matrix.org/v1.6/identity-service-api/#post_matrixidentityv2lookup)
|
||||
or future discovery services.
|
||||
|
||||
----
|
||||
|
||||
If a service uses E.164 identifiers as Matrix IDs then it must be careful to avoid
|
||||
leaking history when reassigning IDs to new users. This is related to [#234](https://github.com/matrix-org/matrix-spec/issues/234),
|
||||
but only applies to the localpart of the Matrix ID, not the entire domain. The
|
||||
solution remains the same: using portable identifiers ([MSC1228](https://github.com/matrix-org/matrix-spec-proposals/pull/1228)
|
||||
or [MSC4014](https://github.com/matrix-org/matrix-spec-proposals/pull/4014)).
|
||||
|
||||
## Alternatives
|
||||
|
||||
The `+` could continue to be disallowed and left off the beginning of the Matrix
|
||||
IDs. Note that Synapse reserves digit-only usernames for guest users, although this
|
||||
seems to be an implementation detail and not mandated by the specification.
|
||||
|
||||
Another option would be to [map from other character sets](https://spec.matrix.org/v1.6/appendices/#mapping-from-other-character-sets)
|
||||
or prefix the Matrix ID with something (e.g. `msisdn`).
|
||||
This would generate a Matrix ID like `@=2b15558675309:example.com` or
|
||||
`@msisdn_5558675309:example.com`, which would dramatically impact usability
|
||||
for the users on homeservers which use phone numbers as identifiers.
|
||||
|
||||
----
|
||||
|
||||
Although E.164 limits the `+` character to the initial character there seems to
|
||||
be no reason to limit that for Matrix identifiers.
|
||||
|
||||
## Security considerations
|
||||
|
||||
E.164 IDs are globally unique, but the proposed change only enforces per-homeserver
|
||||
uniqueness. If a homeserver does not diligently check that the phone number belongs
|
||||
to a user then this may allow additional spoofing attacks. The author does not consider
|
||||
this to be much worse than today's situation:
|
||||
|
||||
1. Many current applications need to verify that a phone number truly is owned
|
||||
by an account. Any current best practices should be followed by a service
|
||||
taking advantage of this MSC.
|
||||
2. It is already quite easy today to spoof a user's ID by registering the same
|
||||
user localpart on a different homeserver. The same issue occurs with email or
|
||||
other distributed system (Mastodon, etc.).
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
N/A
|
||||
|
||||
## Dependencies
|
||||
|
||||
N/A
|
||||
|
||||
[^1]: E.g. Signal, WhatsApp, etc.
|
@ -0,0 +1,80 @@
|
||||
# MSC4010: Push rules and account data
|
||||
|
||||
Push rules have a [bespoke API](https://spec.matrix.org/v1.6/client-server-api/#push-rules-api)
|
||||
which clients use to retrieve, add, modify, and remove push rules. Any modifications
|
||||
made using this API are sent to all clients via a `m.push_rules` event in the
|
||||
`account_data` section in the
|
||||
[the next `/sync` response](https://spec.matrix.org/v1.6/client-server-api/#push-rules-events).
|
||||
|
||||
The client-server API does not have any special behavior around using the
|
||||
[account data APIs](https://spec.matrix.org/v1.6/client-server-api/#client-behaviour-17)
|
||||
with the `m.push_rules` type leading to different behavior on different homeservers:
|
||||
|
||||
* Synapse will accept the data and shadow the real push rules in `/sync`, but
|
||||
*won't use the data when evaluating push rules*.
|
||||
* Dendrite will return an HTTP 403 if you attempt to set `m.push_rules` via
|
||||
`/account_data`.
|
||||
* Conduit has no protections for special account data. It will accept `m.push_rules` via
|
||||
`/account_data` *and* use those when evaluating push rules.
|
||||
|
||||
The [fully read marker](https://spec.matrix.org/v1.6/client-server-api/#fully-read-markers)
|
||||
operates in a similar way and
|
||||
[servers must reject updating `m.fully_read` via `/account_data`](https://spec.matrix.org/v1.6/client-server-api/#server-behaviour-10).
|
||||
|
||||
Note that when attempting to set `m.fully_read` via `/account_data` the following
|
||||
behavior is observed:
|
||||
|
||||
* Synapse will reject it with a 405 error (only for room account data).
|
||||
* Dendrite will reject it with an HTTP 403 error.
|
||||
|
||||
## Proposal
|
||||
|
||||
To make push rules data consistent with fully read markers, the following
|
||||
clarifications are offered:
|
||||
|
||||
* The `m.push_rules` account data type becomes protected and cannot be set using
|
||||
the `/account_data` API, similarly to `m.fully_read`.
|
||||
* "Rejected" means to use the 405 error response as
|
||||
[documented](https://spec.matrix.org/v1.6/client-server-api/#put_matrixclientv3useruseridaccount_datatype):
|
||||
|
||||
> This `type` of account data is controlled by the server; it cannot be modified
|
||||
> by clients. Errcode: `M_BAD_JSON`.
|
||||
* `m.push_rules` and `m.fully_read` should be rejected for both global and room
|
||||
account data.
|
||||
* Reading `m.push_rules` and `m.fully_read` should be allowed (although note that
|
||||
currently `m.push_rules` only makes sense for global account data and `m.fully_read`
|
||||
only makes sense for room account data). The format should match what is currently
|
||||
[returned via `/sync`](https://spec.matrix.org/v1.6/client-server-api/#push-rules-events).
|
||||
|
||||
The above rules shall also apply when deleting account data if [MSC3391](https://github.com/matrix-org/matrix-spec-proposals/pull/3391)
|
||||
is merged before this MSC.
|
||||
|
||||
## Potential issues
|
||||
|
||||
It is possible that a client is currently storing data in the `m.push_rules`
|
||||
(or global `m.fully_read`) account data. After this change it could no longer
|
||||
be updated, deleted, or retrieved. It seems unlikely that the data stored here
|
||||
is done purposefully (and is likely the result of undefined behavior that this
|
||||
MSC is attempting to fix).
|
||||
|
||||
## Alternatives
|
||||
|
||||
An alternative would be to remove the current push rules API and have clients
|
||||
store all push rules in bulk. This would be subject to race conditions between
|
||||
clients.
|
||||
|
||||
A slight variation of the above would be to *additionally* define the `/account_data/m.push_rules`
|
||||
endpoint as bulk modifying the push rules data. This could be seen as an alternative
|
||||
to [MSC3934](https://github.com/matrix-org/matrix-spec-proposals/pull/3934).
|
||||
|
||||
## Security considerations
|
||||
|
||||
None foreseen.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
This is mostly clarifications and does not add any event types or new endpoints.
|
||||
|
||||
## Dependencies
|
||||
|
||||
N/A
|
@ -0,0 +1,83 @@
|
||||
# MSC4025: Local user erasure requests
|
||||
|
||||
Long ago a need arose for having a user specify that they'd like to not just deactivate their account,
|
||||
but also *erase* as much of their content as possible for largely GDPR purposes. This got implemented
|
||||
in the matrix-js-sdk as [PR #649](https://github.com/matrix-org/matrix-js-sdk/pull/649), but never
|
||||
quite made it to the spec.
|
||||
|
||||
Back in 2018 the proposal process was very different (technically didn't actually exist at the time
|
||||
the js-sdk PR was written). A [spec omission issue](https://github.com/matrix-org/matrix-spec/issues/297)
|
||||
was opened to track the missing property, however [an attempt](https://github.com/matrix-org/matrix-spec-proposals/pull/1290)[^1]
|
||||
to do the documentation got blocked on having a larger GDPR-centric proposal.
|
||||
|
||||
Eventually, [MSC2438](https://github.com/matrix-org/matrix-spec-proposals/pull/2438) was drafted,
|
||||
presumably to be that GDPR/erasure-specific MSC the prior spec PR was waiting for. Unfortunately, it
|
||||
appears to have gotten stuck in various stages of drafting.
|
||||
|
||||
It's highly regrettable that yet another spec change from 2018 has managed to go unspecified for so
|
||||
long. Theoretically, the change could go through as a spec PR (much like the one linked above) rather
|
||||
than as a proposal, however there is significant interest in giving the feature a formal chance to be
|
||||
*rejected* as a solution under the modern spec proposal process.
|
||||
|
||||
This MSC serves as that opportunity. While a more comprehensive system could be designed, such as in
|
||||
MSC2438, this MSC has a very narrow and specific scope of what was implemented back in 2018. For the
|
||||
spec process, this translates to accepting the feature as-is, or rejecting it and flagging the client
|
||||
behaviour non-compliant.
|
||||
|
||||
## Proposal
|
||||
|
||||
A new optional boolean is added to the request body of [`POST /deactivate`](https://spec.matrix.org/v1.7/client-server-api/#post_matrixclientv3accountdeactivate):
|
||||
`erase`. It defaults to `false` and signifies whether the user would like their content to be erased
|
||||
as much as possible.
|
||||
|
||||
Erasure does *not* mean issuing redactions for all of the user's sent events, but does mean that any
|
||||
users (or servers) which join the room after the erasure request are served redacted copies of those
|
||||
events. Users which had visibility on the event prior to the erasure are able to see unredacted copies.
|
||||
|
||||
The server should additionally erase any non-event data associated with the user, such as account
|
||||
data and [contact 3PIDs](https://spec.matrix.org/v1.7/client-server-api/#adding-account-administrative-contact-information).
|
||||
|
||||
This is in line with what Synapse does, as referenced [here](https://github.com/matrix-org/synapse/issues/8185).
|
||||
|
||||
This is also what is described by the [matrix.org blog post](https://matrix.org/blog/2018/05/08/gdpr-compliance-in-matrix)
|
||||
on GDPR compliance.
|
||||
|
||||
## Potential issues
|
||||
|
||||
Erasure requests are not sent over federation in this model, meaning servers which already have an
|
||||
unredacted copy of the event will continue to serve that to their users after the erasure happened.
|
||||
Servers are expected to be informed out of band of erasure requests that affect them, if they affect
|
||||
them.
|
||||
|
||||
## Alternatives
|
||||
|
||||
[MSC2438](https://github.com/matrix-org/matrix-spec-proposals/pull/2438) is the leading alternative,
|
||||
however as specified in the introduction for this proposal, the desired outcomes of this MSC are either
|
||||
acceptance as-written or rejection. Ideally, if rejected, another MSC or idea is marked as the suitable
|
||||
alternative.
|
||||
|
||||
Redactions could be sent for all the user's events, however this has obvious performance impact on
|
||||
servers and rooms. The [matrix.org blog](https://matrix.org/blog/2018/05/08/gdpr-compliance-in-matrix)
|
||||
discusses how redactions and GDPR Right to Erasure interact (or rather, how they aren't the same).
|
||||
|
||||
## Security considerations
|
||||
|
||||
This feature was originally introduced primarily in response to the GDPR Right to Erasure requirement
|
||||
within the European Union. The privacy benefits apply to all users of the ecosystem and there's no clear
|
||||
reason to region-lock or otherwise leave this as an implementation detail for EU-operated homeservers.
|
||||
|
||||
There are however consequences of GDPR erasure that are not covered by this proposal, such as the
|
||||
deletion of server logs, forwarding the request, etc. Server operators are encouraged to seek legal
|
||||
advice on how to handle this form of erasure request (and whether it qualifies under GDPR's Right to
|
||||
Erasure requirements). The general recommendation is to enforce the erasure request as much as possible
|
||||
on the local homeserver, including redacting/purging server logs, appservice data, etc.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
Even more regrettably than having unspecified behaviour, this feature was implemented before unstable
|
||||
namespaces existed. Implementations can use `erase` without prefix.
|
||||
|
||||
<!-- Footnotes below here (github draws this as a real line in the rendered view) -->
|
||||
|
||||
[^1]: Readers should note that the spec-proposals repo used to contain both the spec itself and proposals
|
||||
to change the spec. This was later split into dedicated repos, but closed PRs and issues were not migrated.
|
@ -0,0 +1,39 @@
|
||||
# MSC4026: Allow /versions to optionally accept authentication
|
||||
|
||||
## Introduction
|
||||
|
||||
Synapse is implementing the ability to turn some unstable features on per-user. Once this is
|
||||
implemented, certain experimental features will be available to be enabled per-user via the [Admin API](https://matrix-org.github.io/synapse/latest/usage/administration/admin_api/index.html).
|
||||
The intention is to allow certain users to test the experimental feature without making it available to
|
||||
all users before it is stable.
|
||||
This is in addition to the current ability to toggle on/off those features system-wide in the configuration.
|
||||
|
||||
However, this poses a problem when considering how to advertise that those features are enabled to clients.
|
||||
Traditionally, to determine what unstable features were available from a server clients checked the [`/_matrix/client/versions`](https://spec.matrix.org/v1.7/client-server-api/#get_matrixclientversions)
|
||||
endpoint, which in turn checked the Synapse configuration to determine what experimental features were enabled. With the
|
||||
changes being implemented this is no longer possible, as some experimental features may be enabled per-user. As the
|
||||
`/_matrix/client/versions` endpoint does not require authentication there is no way to know which experimental features
|
||||
are enabled - there is no access token that we can extract user info from to determine which unstable features are
|
||||
currently enabled (as they may only be enabled for some users) - and thus there is no way to correctly communicate to
|
||||
clients which experimental features are enabled.
|
||||
|
||||
## Proposal
|
||||
|
||||
The proposal to remedy this is to make `/_matrix/client/versions` optionally accept authentication, and ask clients
|
||||
to use the authenticated version when determining which experimental features are enabled.
|
||||
|
||||
## Potential issues
|
||||
|
||||
This does raise the question of what the non-authenticated version of `/_matrix/client/versions` should return with
|
||||
regard to unstable features if the proposal is accepted.
|
||||
|
||||
## Alternatives
|
||||
|
||||
An alternative to the proposal would be to move advertising the unstable features to the [`/_matrix/client/v3/capabilities`](https://spec.matrix.org/v1.7/client-server-api/#get_matrixclientv3capabilities)
|
||||
endpoint, which does require authentication. However, the spec is clear that `/_matrix/client/v3/capabilities` "should
|
||||
not be used to advertise unstable or experimental features - this is better done by the `/versions` endpoint." Thus,
|
||||
this seems like a less desirable option than the proposed solution.
|
||||
|
||||
## Security considerations
|
||||
|
||||
None that I am currently aware of.
|
@ -0,0 +1,119 @@
|
||||
# MSC4040: Update SRV service name to IANA registration
|
||||
|
||||
The Internet Assigned Numbers Authority (IANA) holds a registry of all service names and ports in use
|
||||
by Internet applications. Unfortunately, the service name `matrix` was registered an eternity ago for
|
||||
use in an unrelated project, which makes our usage of it improper at best. On August 4, 2023 our
|
||||
registration of port 8448 was accepted, with an included service name of `matrix-fed`. This MSC
|
||||
proposes a backwards-compatible change to use this newly registered service name.
|
||||
|
||||
The registrations with keyword "matrix" can be found [here](https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=matrix).
|
||||
|
||||
This fixes https://github.com/matrix-org/matrix-spec/issues/400
|
||||
|
||||
See also https://github.com/matrix-org/matrix-spec/issues/1576
|
||||
|
||||
## Proposal
|
||||
|
||||
The [current specification](https://spec.matrix.org/v1.7/server-server-api/#resolving-server-names) for
|
||||
resolving server names requires an implementation to look up `_matrix._tcp` SRV records in some steps.
|
||||
Those steps become *deprecated* and new steps which use `_matrix-fed._tcp` are added immediately before
|
||||
each existing step.
|
||||
|
||||
Deprecation in context of this MSC is to discourage continued use, and to queue the affected steps for eventual
|
||||
removal from the specification under the [deprecation policy](https://spec.matrix.org/v1.7/#deprecation-policy).
|
||||
|
||||
The new steps thus become:
|
||||
|
||||
1. (unchanged) If the hostname is an IP literal, then that IP address should be used, together with the
|
||||
given port number, or 8448 if no port is given. The target server must present a valid certificate for
|
||||
the IP address. The `Host` header in the request should be set to the server name, including the port if
|
||||
the server name included one.
|
||||
|
||||
2. (unchanged) If the hostname is not an IP literal, and the server name includes an explicit port, resolve
|
||||
the hostname to an IP address using CNAME, AAAA or A records. Requests are made to the resolved IP address
|
||||
and given port with a `Host` header of the original server name (with port). The target server must present
|
||||
a valid certificate for the hostname.
|
||||
|
||||
3. (steps added/deprecated) If the hostname is not an IP literal, a regular HTTPS request is made to `https://<hostname>/.well-known/matrix/server`,
|
||||
expecting the schema defined later in this section. 30x redirects should be followed, however redirection
|
||||
loops should be avoided. Responses (successful or otherwise) to the `/.well-known` endpoint should be
|
||||
cached by the requesting server. Servers should respect the cache control headers present on the response,
|
||||
or use a sensible default when headers are not present. The recommended sensible default is 24 hours. Servers
|
||||
should additionally impose a maximum cache time for responses: 48 hours is recommended. Errors are recommended
|
||||
to be cached for up to an hour, and servers are encouraged to exponentially back off for repeated failures.
|
||||
The schema of the `/.well-known` request is later in this section. If the response is invalid (bad JSON,
|
||||
missing properties, non-200 response, etc), skip to step 4. If the response is valid, the `m.server`
|
||||
property is parsed as `<delegated_hostname>[:<delegated_port>]` and processed as follows:
|
||||
|
||||
1. (unchanged) If `<delegated_hostname>` is an IP literal, then that IP address should be used together
|
||||
with the `<delegated_port>` or 8448 if no port is provided. The target server must present a valid TLS
|
||||
certificate for the IP address. Requests must be made with a `Host` header containing the IP address,
|
||||
including the port if one was provided.
|
||||
|
||||
2. (unchanged) If `<delegated_hostname>` is not an IP literal, and `<delegated_port>` is present, an IP
|
||||
address is discovered by looking up CNAME, AAAA or A records for `<delegated_hostname>`. The resulting IP
|
||||
address is used, alongside the `<delegated_port>`. Requests must be made with a `Host` header of
|
||||
`<delegated_hostname>:<delegated_port>`. The target server must present a valid certificate for `<delegated_hostname>`.
|
||||
|
||||
3. **(ADDED)** If `<delegated_hostname>` is not an IP literal and no `<delegated_port>` is present, an
|
||||
SRV record is looked up for `_matrix-fed._tcp.<delegated_hostname>`. This may result in another hostname
|
||||
(to be resolved using AAAA or A records) and port. Requests should be made to the resolved IP address and
|
||||
port with a `Host` header containing the `<delegated_hostname>`. The target server must present a valid
|
||||
certificate for `<delegated_hostname>`.
|
||||
|
||||
4. **(DEPRECATED)** If `<delegated_hostname>` is not an IP literal and no `<delegated_port>` is present, an
|
||||
SRV record is looked up for `_matrix._tcp.<delegated_hostname>`. This may result in another hostname (to
|
||||
be resolved using AAAA or A records) and port. Requests should be made to the resolved IP address and port
|
||||
with a `Host` header containing the `<delegated_hostname>`. The target server must present a valid certificate
|
||||
for `<delegated_hostname>`.
|
||||
|
||||
5. (unchanged) If no SRV record is found, an IP address is resolved using CNAME, AAAA or A records. Requests
|
||||
are then made to the resolve IP address and a port of 8448, using a `Host` header of `<delegated_hostname>`.
|
||||
The target server must present a valid certificate for `<delegated_hostname>`.
|
||||
|
||||
4. **(ADDED)** If the `/.well-known` request resulted in an error response, a server is found by resolving
|
||||
an SRV record for `_matrix-fed._tcp.<hostname>`. This may result in a hostname (to be resolved using AAAA or A
|
||||
records) and port. Requests are made to the resolved IP address and port, with a `Host` header of `<hostname>`.
|
||||
The target server must present a valid certificate for `<hostname>`.
|
||||
|
||||
5. **(DEPRECATED)** If the `/.well-known` request resulted in an error response, a server is found by resolving
|
||||
an SRV record for `_matrix._tcp.<hostname>`. This may result in a hostname (to be resolved using AAAA or A
|
||||
records) and port. Requests are made to the resolved IP address and port, with a `Host` header of `<hostname>`.
|
||||
The target server must present a valid certificate for `<hostname>`.
|
||||
|
||||
6. (unchanged) If the `/.well-known` request returned an error response, and the SRV record was not found, an IP
|
||||
address is resolved using CNAME, AAAA and A records. Requests are made to the resolved IP address using port
|
||||
8448 and a `Host` header containing the `<hostname>`. The target server must present a valid certificate for
|
||||
`<hostname>`.
|
||||
|
||||
## Potential issues
|
||||
|
||||
Us using `matrix` as a service name has been an issue all along. This MSC aligns the specification with our
|
||||
formal IANA registration.
|
||||
|
||||
## Alternatives
|
||||
|
||||
We could modify our IANA registration further to pick a different name, however the service name needs to be
|
||||
descriptive and short. The author notes that `matrix-server` was attempted in registration, which was declined
|
||||
during Expert Review of the application.
|
||||
|
||||
`matrix` cannot be taken over via IANA process. It was assigned before dates were put on records in 2000.
|
||||
|
||||
Non-options for names include `mxfed`, `matrixf`, and similar.
|
||||
|
||||
A potential way forward is to remove SRV resolution entirely, however prior effort via
|
||||
[MSC3922](https://github.com/matrix-org/matrix-spec-proposals/pull/3922) are expected to be *rejected* instead
|
||||
(as of writing, August 4th, 2023).
|
||||
|
||||
## Security considerations
|
||||
|
||||
There is increased DNS load with this change, due to having to potentially look up 6+ records in the worst case
|
||||
scenario. DNS servers should be more than capable of caching, and handling such a spike of requests.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
None applicable.
|
||||
|
||||
## Dependencies
|
||||
|
||||
None applicable.
|
@ -0,0 +1,50 @@
|
||||
# MSC4041: Use http header Retry-After to enable library-assisted retry handling
|
||||
|
||||
The current Matrix Client-Server API (v1.7) recommends that homeservers should protect themselves from
|
||||
being overloaded by enforcing rate-limits to selected API calls.
|
||||
If homeservers limit access to an API they respond with an http error code 429 and a response body
|
||||
that includes a property `retry_after_ms` to indicate how long a client has to wait before retrying.
|
||||
|
||||
Some http libraries (like [Ky](https://github.com/sindresorhus/ky), [got](https://github.com/sindresorhus/got)
|
||||
and [urllib3](https://urllib3.readthedocs.io/en/stable/reference/urllib3.util.html#urllib3.util.Retry)) ease
|
||||
the burden of handling retries by honoring the http header `Retry-After`. As explained in
|
||||
[RFC 9119 - HTTP Semantics](https://www.rfc-editor.org/rfc/rfc9110#field.retry-after) this header is optional
|
||||
and contains either a (relative) value for the delay in seconds or an (absolute) date.
|
||||
|
||||
The current Matrix Client Server API specification does not take this header into account. This wastes the
|
||||
potential that current http libraries offer in terms of automated retry handling.
|
||||
|
||||
## Proposal
|
||||
|
||||
In order to allow developers to make use of the automated retry handling capabilities of http libraries
|
||||
homeservers shall use the http header `Retry-After` in case they respond with an http error 429.
|
||||
The value of `Retry-After` (in __seconds__) is meant to be a delay after receiving the response and must be
|
||||
calculated in order to comply with the specification in [RFC 9119 - HTTP Semantics](https://www.rfc-editor.org/rfc/rfc9110#field.retry-after).
|
||||
|
||||
With the introduction of the http header `Retry-After` the usage of the existing `retry_after_ms` property in the response body becomes deprecated.
|
||||
|
||||
## Potential issues
|
||||
|
||||
In order to maintain backward compatibility with existing client libraries homeservers shall use both the `Retry-After` header and the
|
||||
`retry_after_ms` property in the response body.
|
||||
|
||||
Client libraries shall use the values in this order:
|
||||
|
||||
1) `Retry-After` http header.
|
||||
2) `retry_after_ms` property in the response body.
|
||||
|
||||
## Alternatives
|
||||
|
||||
N/A
|
||||
|
||||
## Security considerations
|
||||
|
||||
N/A
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
Since this MSC is using a standard HTTP header, it will not use a unstable prefix.
|
||||
|
||||
## Dependencies
|
||||
|
||||
N/A
|
@ -0,0 +1,58 @@
|
||||
# MSC4077: Improved process for handling deprecated HTML features
|
||||
|
||||
The Matrix specification [defines](https://spec.matrix.org/v1.8/client-server-api/#mroommessage-msgtypes)
|
||||
a subset of HTML which clients *should* use when rendering messages, limiting the possibility for
|
||||
Cross-Site Scripting (XSS) and similar attacks. Clients are always welcome to use a different subset
|
||||
in both their send and receive paths, however in practice the recommended set of HTML has become the
|
||||
baseline standard for support among Matrix client developers.
|
||||
|
||||
Additionally, to fix issues like [tags being deprecated](https://github.com/matrix-org/matrix-spec/issues/1492),
|
||||
the existing spec process would require an entire MSC to add or remove the tag. This has precedent
|
||||
through [MSC2422](https://github.com/matrix-org/matrix-spec-proposals/pull/2422) and
|
||||
[MSC2184](https://github.com/matrix-org/matrix-spec-proposals/pull/2184), where additional HTML
|
||||
features are analyzed from a security perspective. For example, whether XSS attacks are more probable
|
||||
or flooding/disruption attempts are made easier.
|
||||
|
||||
This proposal adjusts the MSC process to explicitly allow changes to the supported HTML tags where
|
||||
the WHATWG has deprecated a feature in favour of another, enabling more rapid iteration and reducing
|
||||
paperwork for everyone involved.
|
||||
|
||||
## Proposal
|
||||
|
||||
Where the WHATWG has deprecated a feature of the HTML specification, a Matrix spec PR *may* bypass the
|
||||
MSC process to use the modern feature instead. In the case of [issue#1492](https://github.com/matrix-org/matrix-spec/issues/1492),
|
||||
the spec PR is explicitly able to add the `s` tag and remove the `strike` tag. Note that such changes
|
||||
can also bypass the [deprecation policy](https://spec.matrix.org/v1.8/#deprecation-policy) in this way.
|
||||
|
||||
It is left to the discretion of the spec PR reviewer as to whether an MSC is required. In general, an
|
||||
MSC should be requested when the replacement HTML feature is not quite the same as the old feature.
|
||||
The reviewer *may* also decide whether to keep supporting the old, deprecated, feature for some time.
|
||||
For example, replacing `strike` with `s` may mean that both tags are supported for 1-2 Matrix spec
|
||||
versions before `strike` can be dropped.
|
||||
|
||||
For clarity, an MSC is always required to add net-new features to the HTML subset, or to remove a
|
||||
feature entirely. An example of this is [MSC2398](https://github.com/matrix-org/matrix-spec-proposals/pull/2398).
|
||||
These changes are subject to interoperability and security review, and cannot bypass the MSC process.
|
||||
|
||||
## Potential issues
|
||||
|
||||
The author notes that this MSC might not need to exist under the banner of pragmatism, however for all
|
||||
the effort to *not* write an MSC, an MSC has been written for review.
|
||||
|
||||
## Alternatives
|
||||
|
||||
Critically, without agreement that replacing deprecated HTML features can happen outside the MSC process,
|
||||
changes to the HTML subset become slow and burdensome for no apparent gain.
|
||||
|
||||
## Security considerations
|
||||
|
||||
Special care and attention is expected to be taken by spec PR reviewers to ensure that changes are
|
||||
safe and in line with the semantics of this proposal's guidance.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
Not applicable. This is a process MSC.
|
||||
|
||||
## Dependencies
|
||||
|
||||
None applicable.
|
@ -0,0 +1,74 @@
|
||||
# MSC4126: Deprecation of query string auth
|
||||
|
||||
Presently, the Client-Server API allows clients to provide their access token via the `Authorization`
|
||||
request header or via an `access_token` query string parameter, described [here](https://spec.matrix.org/v1.10/client-server-api/#using-access-tokens).
|
||||
Clients are already encouraged to use the header approach, though the query string option exists for
|
||||
largely backwards compatibility reasons.
|
||||
|
||||
The query string approach is subject a number of security, usability, and practical concerns, discussed
|
||||
on [matrix-spec#1780](https://github.com/matrix-org/matrix-spec/issues/1780):
|
||||
|
||||
* The query string of an HTTP request is often logged by the client itself, middleware reverse proxy,
|
||||
and application/homeserver as well. Though some of these layers may be aware of this issue, they
|
||||
can trivially accidentally break to log sensitive credentials again. By contrast, headers are not
|
||||
typically logged by default.
|
||||
|
||||
* Users often copy and paste URLs from their clients to either get support or provide direct links
|
||||
to content/media. While the media angle is largely expected to be resolved with [MSC3916](https://github.com/matrix-org/matrix-spec-proposals/pull/3916),
|
||||
users are currently able to right click images in their client and copy the URL - if this URL
|
||||
includes authentication in the query string, the user will likely end up disclosing their access
|
||||
token. The same scenario applies when copy/pasting request logs out of a client when getting
|
||||
support.
|
||||
|
||||
* Having two ways of doing things could lead to compatibility issues, where a client using the query
|
||||
string approach is tried against a server which only supports the header. The client ends up not
|
||||
working, leading to subpar user experience.
|
||||
|
||||
* Most clients have already adopted the header approach, largely forgetting that the query string
|
||||
even exists. Continuing to support the query string option leaves some maintenance burden for what
|
||||
is effectively unused code.
|
||||
|
||||
* Matrix has [decided](https://matrix.org/blog/2023/09/matrix-2-0/) to adopt OIDC for authentication,
|
||||
which is based on OAuth 2.0, which [advises against](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.3.2)
|
||||
the query string approach.
|
||||
|
||||
With these conditions in mind, this proposal sets the query string approach on a path towards removal
|
||||
from the Matrix specification. This affects the Client-Server API and [Identity Service API](https://spec.matrix.org/v1.10/identity-service-api/#authentication)
|
||||
as both support the approaches described above.
|
||||
|
||||
## Proposal
|
||||
|
||||
For both the Client-Server API and Identity Service API, the `access_token` query string authentication
|
||||
parameter becomes *deprecated*, and SHOULD NOT be used by clients (as already stated in the specification).
|
||||
Deprecation is required for at least 1 spec version before removal under the [deprecation policy](https://spec.matrix.org/v1.10/#deprecation-policy).
|
||||
|
||||
Removal from the specification requires a second MSC and at least 1 specification release to pass. This
|
||||
is currently described as [MSC4127](https://github.com/matrix-org/matrix-spec-proposals/pull/4127).
|
||||
|
||||
## Potential issues
|
||||
|
||||
Clients which rely on the query string approach may stop working. This is considered acceptable for
|
||||
the purposes of this MSC.
|
||||
|
||||
## Alternatives
|
||||
|
||||
Most alternatives are not practical as they would maintain the security risk described in the introduction
|
||||
for this proposal.
|
||||
|
||||
Alterations to the deprecation policy may be discussed in a future MSC to make this sort of removal
|
||||
easier.
|
||||
|
||||
## Security considerations
|
||||
|
||||
Security considerations are described throughout this proposal.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
This proposal cannot feasibly have an unstable prefix. Clients are already discouraged from using
|
||||
query string authentication and should switch to `Authorization` as soon as possible, regardless of
|
||||
this MSC.
|
||||
|
||||
## Dependencies
|
||||
|
||||
This MSC has no direct dependencies itself. [MSC4127](https://github.com/matrix-org/matrix-spec-proposals/pull/4127)
|
||||
requires this MSC to land first.
|
Loading…
Reference in New Issue