Merge branch 'main' into 3077-multi-stream-voip

Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This commit is contained in:
Kévin Commaille 2024-02-28 21:07:10 +01:00
commit 83b3c676f3
No known key found for this signature in database
GPG key ID: 29A48C1F03620416
179 changed files with 3077 additions and 1171 deletions

View file

@ -16,6 +16,7 @@ Previous release: <!-- LINK TO LAST RELEASE'S CHECKLIST -->
Preflight checklist ([release steps](https://github.com/matrix-org/matrix-spec/blob/main/meta/releasing.md)): Preflight checklist ([release steps](https://github.com/matrix-org/matrix-spec/blob/main/meta/releasing.md)):
* [ ] Ensure the social media account holders are available for the release day.
* [ ] Blog post written * [ ] Blog post written
* [ ] Check for release blockers that may have been missed * [ ] Check for release blockers that may have been missed
* [ ] Review/fix the changelog * [ ] Review/fix the changelog

View file

@ -10,7 +10,7 @@ jobs:
if: github.event_name == 'pull_request' if: github.event_name == 'pull_request'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- run: scripts/check-newsfragments - run: scripts/check-newsfragments

View file

@ -18,18 +18,37 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: "📥 Source checkout" - name: "📥 Source checkout"
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: " Setup Node" - name: " Setup Node"
uses: actions/setup-node@v2 uses: actions/setup-node@v3
with: with:
node-version: '14' node-version: '18'
- name: "🔎 Run validator" - name: "🔎 Run validator"
run: | run: |
npx @redocly/cli@latest lint data/api/*/*.yaml npx @redocly/cli@latest lint data/api/*/*.yaml
check-examples: check-event-examples:
name: "🔎 Check Event schema examples" name: "🔎 Check Event schema examples"
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps:
- name: "📥 Source checkout"
uses: actions/checkout@v4
- name: " Setup Python"
uses: actions/setup-python@v4
with:
python-version: '3.9'
cache: 'pip'
cache-dependency-path: scripts/requirements.txt
- name: " Install dependencies"
run: |
pip install -r scripts/requirements.txt
- name: "🔎 Run validator"
run: |
python scripts/check-event-schema-examples.py
check-openapi-examples:
name: "🔎 Check OpenAPI definitions examples"
runs-on: ubuntu-latest
steps: steps:
- name: "📥 Source checkout" - name: "📥 Source checkout"
uses: actions/checkout@v2 uses: actions/checkout@v2
@ -44,7 +63,26 @@ jobs:
pip install -r scripts/requirements.txt pip install -r scripts/requirements.txt
- name: "🔎 Run validator" - name: "🔎 Run validator"
run: | run: |
python scripts/check-event-schema-examples.py python scripts/check-openapi-sources.py
check-schemas-examples:
name: "🔎 Check JSON Schemas inline examples"
runs-on: ubuntu-latest
steps:
- name: "📥 Source checkout"
uses: actions/checkout@v2
- name: " Setup Python"
uses: actions/setup-python@v4
with:
python-version: '3.9'
cache: 'pip'
cache-dependency-path: scripts/requirements.txt
- name: " Install dependencies"
run: |
pip install -r scripts/requirements.txt
- name: "🔎 Run validator"
run: |
python scripts/check-json-schemas.py
calculate-baseurl: calculate-baseurl:
name: "⚙️ Calculate baseURL for later jobs" name: "⚙️ Calculate baseURL for later jobs"
@ -74,7 +112,7 @@ jobs:
needs: [calculate-baseurl] needs: [calculate-baseurl]
steps: steps:
- name: "📥 Source checkout" - name: "📥 Source checkout"
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: " Setup Python" - name: " Setup Python"
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
@ -92,24 +130,29 @@ jobs:
export RELEASE="unstable" export RELEASE="unstable"
fi fi
# The output path matches the final deployment path at spec.matrix.org # The output path matches the final deployment path at spec.matrix.org
scripts/dump-swagger.py \ scripts/dump-openapi.py \
--base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \ --base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \
--api application-service \ --api application-service \
-r "$RELEASE" \ -r "$RELEASE" \
-o spec/application-service-api/api.json -o spec/application-service-api/api.json
scripts/dump-swagger.py \ scripts/dump-openapi.py \
--base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \ --base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \
--api client-server \ --api client-server \
-r "$RELEASE" \ -r "$RELEASE" \
-o spec/client-server-api/api.json -o spec/client-server-api/api.json
scripts/dump-swagger.py \ scripts/dump-openapi.py \
--base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \ --base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \
--api push-gateway \ --api push-gateway \
-r "$RELEASE" \ -r "$RELEASE" \
-o spec/push-gateway-api/api.json -o spec/push-gateway-api/api.json
scripts/dump-openapi.py \
--base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \
--api server-server \
-r "$RELEASE" \
-o spec/server-server-api/api.json
tar -czf openapi.tar.gz spec tar -czf openapi.tar.gz spec
- name: "📤 Artifact upload" - name: "📤 Artifact upload"
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: openapi-artifact name: openapi-artifact
path: openapi.tar.gz path: openapi.tar.gz
@ -121,7 +164,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: "📥 Source checkout" - name: "📥 Source checkout"
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: " Setup Python" - name: " Setup Python"
uses: actions/setup-python@v4 uses: actions/setup-python@v4
- name: " Install towncrier" - name: " Install towncrier"
@ -129,7 +172,7 @@ jobs:
- name: "Generate changelog" - name: "Generate changelog"
run: ./scripts/generate-changelog.sh vUNSTABLE run: ./scripts/generate-changelog.sh vUNSTABLE
- name: "📤 Artifact upload" - name: "📤 Artifact upload"
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: changelog-artifact name: changelog-artifact
path: content/changelog/vUNSTABLE.md path: content/changelog/vUNSTABLE.md
@ -142,16 +185,16 @@ jobs:
if: ${{ always() }} if: ${{ always() }}
steps: steps:
- name: " Setup Node" - name: " Setup Node"
uses: actions/setup-node@v2 uses: actions/setup-node@v3
with: with:
node-version: '14' node-version: '18'
- name: " Setup Hugo" - name: " Setup Hugo"
uses: peaceiris/actions-hugo@c03b5dbed22245418539b65eb9a3b1d5fdd9a0a6 uses: peaceiris/actions-hugo@16361eb4acea8698b220b76c0d4e84e1fd22c61d
with: with:
hugo-version: '0.113.0' hugo-version: '0.113.0'
extended: true extended: true
- name: "📥 Source checkout" - name: "📥 Source checkout"
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: "⚙️ npm" - name: "⚙️ npm"
run: | run: |
npm i npm i
@ -169,7 +212,7 @@ jobs:
# https://spec.matrix.org/latest/client-server-api/api.json # https://spec.matrix.org/latest/client-server-api/api.json
# Works for /unstable/ and /v1.1/ as well. # Works for /unstable/ and /v1.1/ as well.
- name: "📥 Spec definition download" - name: "📥 Spec definition download"
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: openapi-artifact name: openapi-artifact
- name: "📝 Unpack the OpenAPI definitions in the right location" - name: "📝 Unpack the OpenAPI definitions in the right location"
@ -179,7 +222,7 @@ jobs:
- name: "📦 Tarball creation" - name: "📦 Tarball creation"
run: tar -czf spec.tar.gz spec run: tar -czf spec.tar.gz spec
- name: "📤 Artifact upload" - name: "📤 Artifact upload"
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: spec-artifact name: spec-artifact
path: spec.tar.gz path: spec.tar.gz
@ -190,10 +233,10 @@ jobs:
needs: [calculate-baseurl, build-spec] needs: [calculate-baseurl, build-spec]
steps: steps:
- name: "📥 Source checkout" - name: "📥 Source checkout"
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: "📥 Fetch built spec" - name: "📥 Fetch built spec"
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: spec-artifact name: spec-artifact
@ -219,16 +262,16 @@ jobs:
if: ${{ startsWith(github.ref, 'refs/tags/') }} if: ${{ startsWith(github.ref, 'refs/tags/') }}
steps: steps:
- name: " Setup Node" - name: " Setup Node"
uses: actions/setup-node@v2 uses: actions/setup-node@v3
with: with:
node-version: '14' node-version: '18'
- name: " Setup Hugo" - name: " Setup Hugo"
uses: peaceiris/actions-hugo@c03b5dbed22245418539b65eb9a3b1d5fdd9a0a6 uses: peaceiris/actions-hugo@16361eb4acea8698b220b76c0d4e84e1fd22c61d
with: with:
hugo-version: '0.93.3' hugo-version: '0.93.3'
extended: true extended: true
- name: "📥 Source checkout" - name: "📥 Source checkout"
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: "⚙️ npm" - name: "⚙️ npm"
run: | run: |
npm i npm i
@ -240,7 +283,7 @@ jobs:
hugo --config config.toml,historical.toml --baseURL "/${GITHUB_REF/refs\/tags\//}" -d "spec" hugo --config config.toml,historical.toml --baseURL "/${GITHUB_REF/refs\/tags\//}" -d "spec"
- name: "📥 Spec definition download" - name: "📥 Spec definition download"
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: openapi-artifact name: openapi-artifact
- name: "📝 Unpack the OpenAPI definitions in the right location" - name: "📝 Unpack the OpenAPI definitions in the right location"
@ -250,7 +293,7 @@ jobs:
- name: "📦 Tarball creation" - name: "📦 Tarball creation"
run: tar -czf spec-historical.tar.gz spec run: tar -czf spec-historical.tar.gz spec
- name: "📤 Artifact upload" - name: "📤 Artifact upload"
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: spec-historical-artifact name: spec-historical-artifact
path: spec-historical.tar.gz path: spec-historical.tar.gz

View file

@ -35,7 +35,7 @@ jobs:
echo "::set-output name=prnumber::$pr_number" echo "::set-output name=prnumber::$pr_number"
- name: '📥 Download artifact' - name: '📥 Download artifact'
uses: dawidd6/action-download-artifact@af92a8455a59214b7b932932f2662fdefbd78126 # v2.15.0 uses: dawidd6/action-download-artifact@268677152d06ba59fcec7a7f0b5d961b6ccd7e1e # v2.28.0
with: with:
workflow: main.yaml workflow: main.yaml
run_id: ${{ github.event.workflow_run.id }} run_id: ${{ github.event.workflow_run.id }}
@ -46,8 +46,8 @@ jobs:
- name: "📤 Deploy to Netlify" - name: "📤 Deploy to Netlify"
id: netlify id: netlify
# v1.2.2 # v2.1.0
uses: nwtgck/actions-netlify@f517512ae75beec8896aa7b027c1c72f01816200 uses: nwtgck/actions-netlify@7a92f00dde8c92a5a9e8385ec2919775f7647352
with: with:
publish-dir: spec publish-dir: spec
deploy-message: "Deploy from GitHub Actions" deploy-message: "Deploy from GitHub Actions"

41
.github/workflows/release.yaml vendored Normal file
View file

@ -0,0 +1,41 @@
name: Release packages
on:
release:
types: [published]
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
# Releases to npm after bumping the package.json version from 0.0.0 to $TAG.0 as the tags only contain MAJOR.MINOR
npm:
name: Publish to npm
runs-on: ubuntu-latest
if: github.event.release.prerelease == false
defaults:
run:
working-directory: packages/npm
steps:
- name: 🧮 Checkout code
uses: actions/checkout@v4
- name: 🔧 Yarn cache
uses: actions/setup-node@v3
with:
cache: "yarn"
cache-dependency-path: packages/npm/yarn.lock
registry-url: "https://registry.npmjs.org"
- name: 🔨 Install dependencies
run: "yarn install --frozen-lockfile"
- name: 🎖 Bump package.json version
run: "yarn version --new-version $VERSION"
env:
VERSION: ${{ github.event.release.tag_name }}.0
- name: 🚀 Publish to npm
id: npm-publish
uses: JS-DevTools/npm-publish@5a85faf05d2ade2d5b6682bfe5359915d5159c6c # v2.2.1
with:
token: ${{ secrets.NPM_TOKEN }}
package: packages/npm
access: public
ignore-scripts: false

View file

@ -11,9 +11,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Actions Repository - name: Checkout Actions Repository
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: Check spelling of proposals - name: Check spelling of proposals
uses: crate-ci/typos@9be36f97fdbe645ee9a12449fb13aca856c2516a uses: crate-ci/typos@ff3f309513469397e1094520fb7a054e057589e1
with: with:
config: ${{github.workspace}}/.github/_typos.toml config: ${{github.workspace}}/.github/_typos.toml

2
.gitignore vendored
View file

@ -2,7 +2,7 @@ node_modules
/data/msc /data/msc
/env* /env*
/resources /resources
/scripts/swagger /scripts/openapi
/scripts/tmp /scripts/tmp
/hugo-config.toml /hugo-config.toml
/public /public

4
.gitmodules vendored
View file

@ -1,4 +0,0 @@
[submodule "themes/docsy"]
path = themes/docsy
url = https://github.com/matrix-org/docsy.git
branch = master

View file

@ -72,7 +72,7 @@ ask.
Adding to the changelog Adding to the changelog
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
All API specifications require a changelog entry. Adding to the changelog can only All changes to the contents of this repository require a changelog entry. Adding to the changelog can only
be done after you've opened your pull request, so be sure to do that first. be done after you've opened your pull request, so be sure to do that first.
The changelog is managed by `Towncrier <https://github.com/twisted/towncrier>`_ in the The changelog is managed by `Towncrier <https://github.com/twisted/towncrier>`_ in the

View file

@ -22,7 +22,7 @@ The Matrix spec is compiled with [Hugo](https://gohugo.io/) (a static site gener
* `/data`: this can contain TOML, YAML, or JSON files. Files kept here are directly available to template code as * `/data`: this can contain TOML, YAML, or JSON files. Files kept here are directly available to template code as
[data objects](https://gohugo.io/templates/data-templates/), so templates don't need to load them from a file and [data objects](https://gohugo.io/templates/data-templates/), so templates don't need to load them from a file and
parse them. This is also where our Swagger/OpenAPI definitions and schemas are. parse them. This is also where our OpenAPI definitions and schemas are.
* `/layouts`: this contains [Hugo templates](https://gohugo.io/templates/). Some templates define the overall layout of * `/layouts`: this contains [Hugo templates](https://gohugo.io/templates/). Some templates define the overall layout of
a page: for example, whether it has header, footer, sidebar, and so on. a page: for example, whether it has header, footer, sidebar, and so on.
@ -52,6 +52,7 @@ Additionally, the following directories may be of interest:
* `/data-definitions`: Bits of structured data consumable by Matrix implementations. * `/data-definitions`: Bits of structured data consumable by Matrix implementations.
* `/meta`: Documentation relating to the spec's processes that are otherwise untracked (release instructions, etc). * `/meta`: Documentation relating to the spec's processes that are otherwise untracked (release instructions, etc).
* `/scripts`: Various scripts for generating the spec and validating its contents. * `/scripts`: Various scripts for generating the spec and validating its contents.
* `/packages`: Various packages for shipping spec files like OpenAPI bindings and data definitions.
## Authoring changes to the spec ## Authoring changes to the spec
@ -60,13 +61,12 @@ place after an MSC has been accepted, not as part of a proposal itself.
1. Install the extended version (often the OS default) of Hugo: 1. Install the extended version (often the OS default) of Hugo:
<https://gohugo.io/getting-started/installing>. Note that at least Hugo <https://gohugo.io/getting-started/installing>. Note that at least Hugo
v0.93.0 is required. v0.110.0 is required.
Alternatively, use the Docker image at Alternatively, use the Docker image at
https://hub.docker.com/r/klakegg/hugo/. (The "extended edition" is required https://hub.docker.com/r/klakegg/hugo/. (The "extended edition" is required
to process the SCSS.) to process the SCSS.)
2. Run `npm i` to install the dependencies and fetch the docsy git submodule. 2. Run `npm i` to install the dependencies. Note that this will require NodeJS to be installed.
Note that this will require NodeJS to be installed.
3. Run `npm run get-proposals` to seed proposal data. This is merely for populating the content of the "Spec Change Proposals" 3. Run `npm run get-proposals` to seed proposal data. This is merely for populating the content of the "Spec Change Proposals"
page and is not required. page and is not required.
4. Run `hugo serve` (or `docker run --rm -it -v $(pwd):/src -p 1313:1313 4. Run `hugo serve` (or `docker run --rm -it -v $(pwd):/src -p 1313:1313
@ -86,13 +86,13 @@ steps for authoring changes to the specification and instead of `hugo serve` run
spec to `/spec`. If you'd like to serve the spec off a path instead of a domain root (eg: `/unstable`), add `--baseURL "/unstable"` spec to `/spec`. If you'd like to serve the spec off a path instead of a domain root (eg: `/unstable`), add `--baseURL "/unstable"`
to the `hugo -d "spec"` command. to the `hugo -d "spec"` command.
For building the swagger definitions, create a python3 virtualenv and activate it. Then run `pip install -r ./scripts/requirements.txt` For building the OpenAPI definitions, create a python3 virtualenv and activate it. Then run `pip install -r ./scripts/requirements.txt`
and finally `python ./scripts/dump-swagger.py` to generate it to `./scripts/swagger/api-docs.json`. To make use of the generated file, and finally `python ./scripts/dump-openapi.py` to generate it to `./scripts/openapi/api-docs.json`. To make use of the generated file,
there are a number of options: there are a number of options:
* You can open `./scripts/swagger-preview.html` in your browser, and then open the file by clicking on `Local JSON File`. * You can open `./scripts/openapi-preview.html` in your browser, and then open the file by clicking on `Local JSON File`.
* You can run a local HTTP server by running `./scripts/swagger-http-server.py`, and then view the documentation by * You can run a local HTTP server by running `./scripts/openapi-http-server.py`, and then view the documentation by
opening `./scripts/swagger-preview.html` in your browser. opening `./scripts/openapi-preview.html` in your browser.
## Issue tracking ## Issue tracking

View file

@ -18,9 +18,6 @@ limitations under the License.
Custom SCSS for the Matrix spec Custom SCSS for the Matrix spec
*/ */
@import "variables_project";
@import "variables";
/* Import the CSS classes for the syntax highlighter. /* Import the CSS classes for the syntax highlighter.
* *
* This is generated with: * This is generated with:
@ -49,6 +46,10 @@ Custom SCSS for the Matrix spec
} }
.nav-link {
font-weight: normal;
}
a { a {
color: $black; color: $black;
} }
@ -292,7 +293,7 @@ footer {
} }
/* Styles for sections that are rendered from data, such as HTTP APIs and event schemas */ /* Styles for sections that are rendered from data, such as HTTP APIs and event schemas */
.rendered-data { .td-content .rendered-data {
background-color: $secondary-lightest-background; background-color: $secondary-lightest-background;
padding: 0.85rem; padding: 0.85rem;
margin: 0.85rem 0; margin: 0.85rem 0;
@ -346,23 +347,41 @@ footer {
} }
p code, table code { p code, table code {
background-color: inherit; background-color: transparent;
} }
table { table {
/* Docsy makes all tables "responsive tables", which causes Bootstrap 4 to create @media (max-width: 800px) {
* tables with a "display" property of "block". /* Docsy by default applies `overflow-x: auto;` to tables, which
* * results in annoying horizontal scrolling on mobile, so we instead
* However, for "table-layout: fixed" to be effective, an element must have a * switch to a fixed table layout on a narrow browser width.
* "display" property of "table". * (On a wider width the default auto table-layout provides better readability.)
* *
* Thus, we override the "display" property here. This may no longer be necessary once * Docsy makes all tables "responsive tables", which causes Bootstrap 4 to create
* Docsy updates to Bootstrap v5+: https://github.com/google/docsy/issues/470. * tables with a "display" property of "block".
* For more details, see * However, for "table-layout: fixed" to be effective, an element must have a
* https://github.com/matrix-org/matrix-spec/pull/1295/files#r1010759688 */ * "display" property of "table".
display: table; *
table-layout: fixed; * Thus, we override the "display" property here. This may no longer be necessary once
width: 100%; * Docsy updates to Bootstrap v5+: https://github.com/google/docsy/issues/470.
* For more details, see
* https://github.com/matrix-org/matrix-spec/pull/1295/files#r1010759688 */
display: table;
table-layout: fixed;
width: 100%;
.col-name, .col-type, .col-status {
width: 25%;
}
.col-description {
width: 50%;
}
.col-status-description {
width: 75%;
}
}
// add some space between two tables when they are right next to each other // add some space between two tables when they are right next to each other
& + table { & + table {
@ -378,6 +397,7 @@ footer {
th, td, caption { th, td, caption {
padding: 1rem; padding: 1rem;
border-top: 1px $table-border-color solid;
} }
&.object-table, &.response-table, &.content-type-table { &.object-table, &.response-table, &.content-type-table {
@ -390,14 +410,12 @@ footer {
// ... but avoid double border between caption and table // ... but avoid double border between caption and table
border-bottom: 0; border-bottom: 0;
background-color: $secondary-lighter-background;
} }
caption, tbody tr { tbody tr {
background-color: $table-row-default; --bs-table-striped-bg: #{$secondary-lighter-background};
}
tbody tr:nth-child(even) {
background-color: $table-row-alternate;
} }
} }
@ -409,19 +427,6 @@ footer {
&.basic-info th { &.basic-info th {
width: 15rem; width: 15rem;
} }
.col-name, .col-type, .col-status {
width: 25%;
}
.col-description {
width: 50%;
}
.col-status-description {
width: 75%;
}
} }
pre { pre {
@ -512,3 +517,15 @@ dd {
border-radius: 0.25rem; // was $border-radius, but that var isn't accessible here. border-radius: 0.25rem; // was $border-radius, but that var isn't accessible here.
} }
} }
/* Style for breadcrumbs */
.td-breadcrumbs {
padding: .75rem 1rem;
background-color: #eee;
border-radius: .25rem;
margin-bottom: 1rem;
.breadcrumb {
margin: 0;
}
}

View file

@ -20,7 +20,7 @@ $dark: #333;
$gray-100: #FBFBFB; $gray-100: #FBFBFB;
$secondary-background: #E5F5FB; $secondary-background: #E5F5FB;
$secondary-lighter-background: #F4FaFC; $secondary-lighter-background: #F4FAFC;
$secondary-lightest-background: #FBFDFD; $secondary-lightest-background: #FBFDFD;
@ -33,8 +33,7 @@ $warning-background: #FFE0E0;
// colours for definition tables. // colours for definition tables.
// the border colour matches that used for "highlight" divs // the border colour matches that used for "highlight" divs
$table-border-color: rgba(black, .125); $table-border-color: rgba(black, .125);
$table-row-alternate: $secondary-lightest-background; $table-bg: $secondary-lightest-background;
$table-row-default: $secondary-lighter-background;
/* Configure docsy to use the default system fonts instead of Google Fonts. /* Configure docsy to use the default system fonts instead of Google Fonts.
* See https://www.docsy.dev/docs/adding-content/lookandfeel/#fonts */ * See https://www.docsy.dev/docs/adding-content/lookandfeel/#fonts */

View file

@ -1 +0,0 @@
Clarify spec re canonical JSON to handle negative-zero; also, give an example of negative-zero and a large power of ten

View file

@ -1 +0,0 @@
Allow `+` in Matrix IDs, per [MSC4009](https://github.com/matrix-org/matrix-spec-proposals/pull/4009).

View file

@ -1 +0,0 @@
Fix JSON schema of custom fields in query.

View file

@ -1 +0,0 @@
Fix missing `type` property in the JSON schema definition of the `m.reaction` event. Contributed by @chebureki.

View file

@ -1 +0,0 @@
Make sure examples types match schema in definitions.

View file

@ -1 +0,0 @@
Allow `null` in `room_types` in `POST /publicRooms` endpoints schemas.

View file

@ -1 +0,0 @@
Fix broken header formatting. Contributed by @midnightveil.

View file

@ -1 +0,0 @@
Render binary request and response bodies.

View file

@ -1 +0,0 @@
Remove unnecessary `oneOf`s in JSON schemas.

View file

@ -1 +0,0 @@
Fix description of MAC calculation in SAS verification.

View file

@ -1 +0,0 @@
Update link to SAS emoji definition data.

View file

@ -1 +0,0 @@
Fix various typos throughout the specification.

View file

@ -0,0 +1 @@
The [strike](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strike) element is deprecated in the HTML spec. Clients should prefer [s](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s) instead.

View file

@ -0,0 +1 @@
Clarify that read-receipts should be batched by thread as well as room.

View file

@ -0,0 +1 @@
Clarify that threads can be created based on replies.

View file

@ -0,0 +1 @@
Make clearer in the example for reply fallbacks that the prefix sequence should be repeated for each line.

View file

@ -0,0 +1 @@
Clarify the format of account data objects for secret storage.

View file

@ -0,0 +1 @@
Clarify that the key backup MAC is implemented incorrectly and does not pass the ciphertext through HMAC-SHA-256.

View file

@ -0,0 +1 @@
Clarify one-time key and fallback key types in examples.

View file

@ -0,0 +1 @@
Clarify that the HKDF calculation for SAS uses base64-encoded keys rather than the raw key bytes.

View file

@ -0,0 +1 @@
Clarify how to perform the ECDH exchange in step 12 of the SAS process.

View file

@ -0,0 +1 @@
Add local erasure requests, as per [MSC4025](https://github.com/matrix-org/matrix-spec-proposals/pull/4025).

View file

@ -0,0 +1 @@
Use the `body` field as media caption, as per [MSC2530](https://github.com/matrix-org/matrix-spec-proposals/pull/2530).

View file

@ -0,0 +1 @@
Clarify the format of account data objects for secret storage.

View file

@ -1 +0,0 @@
Make sure examples types match schema in definitions.

View file

@ -1 +0,0 @@
Upgrade Swagger data to OpenAPI 3.1.

View file

@ -1 +0,0 @@
Update the CI to validate the file extension of changelog entries.

View file

@ -1 +0,0 @@
Disclosure sections now only display their title when collapsed.

View file

@ -1 +0,0 @@
Fix the sidebar in recent versions of Hugo

View file

@ -1 +0,0 @@
Bump jsonschema to validate JSON Schemas against Draft 2020-12.

View file

@ -1 +0,0 @@
Use Redocly CLI to validate OpenAPI definitions.

View file

@ -1 +0,0 @@
Use tag name as the OpenAPI definition version.

View file

@ -1 +0,0 @@
Make sure version in x-changedInMatrixVersion is a string.

View file

@ -1 +0,0 @@
Clarify usage of ABNF for grammar in the documentation style guide.

View file

@ -1 +0,0 @@
Update the version of Hugo used to render the spec to v0.113.0.

View file

@ -0,0 +1 @@
Update the spec release process.

View file

@ -0,0 +1 @@
Minor clarifications to the contributing guide.

View file

@ -0,0 +1 @@
Update Docsy to v0.8.0.

View file

@ -0,0 +1 @@
Fix npm release script for `@matrix-org/spec`.

View file

@ -0,0 +1 @@
Update HTML templates to include links to object schema definitions.

View file

@ -1,39 +1,66 @@
[tool.towncrier] [tool.towncrier]
version = "unused" version = "unused"
filename = "../rendered.md" filename = "rendered.md"
issue_format = "[#{issue}](https://github.com/matrix-org/matrix-spec/issues/{issue})" template = "template.md.jinja"
title_format = "### {name}" # Matches rendered spec, even if awkward
underlines = " " # 3 spaces intentionally to hide RST headings
# Note: The names below have the <strong> tag built-in so the rendered spec *and* the generated
# changelog can benefit from sane headings.
[[tool.towncrier.type]] [[tool.towncrier.type]]
directory = "breaking" directory = "breaking"
name = "<strong>Breaking Changes</strong>" name = "Breaking Changes"
showcontent = true showcontent = true
[[tool.towncrier.type]] [[tool.towncrier.type]]
directory = "deprecation" directory = "deprecation"
name = "<strong>Deprecations</strong>" name = "Deprecations"
showcontent = true showcontent = true
[[tool.towncrier.type]] [[tool.towncrier.type]]
directory = "new" directory = "new"
name = "<strong>New Endpoints</strong>" name = "New Endpoints"
showcontent = true showcontent = true
[[tool.towncrier.type]] [[tool.towncrier.type]]
directory = "removal" directory = "removal"
name = "<strong>Removed Endpoints</strong>" name = "Removed Endpoints"
showcontent = true showcontent = true
[[tool.towncrier.type]] [[tool.towncrier.type]]
directory = "feature" directory = "feature"
name = "<strong>Backwards Compatible Changes</strong>" name = "Backwards Compatible Changes"
showcontent = true showcontent = true
[[tool.towncrier.type]] [[tool.towncrier.type]]
directory = "clarification" directory = "clarification"
name = "<strong>Spec Clarifications</strong>" name = "Spec Clarifications"
showcontent = true showcontent = true
[[tool.towncrier.section]]
name = "Client-Server API"
path = "client_server"
[[tool.towncrier.section]]
name = "Server-Server API"
path = "server_server"
[[tool.towncrier.section]]
name = "Application Service API"
path = "application_service"
[[tool.towncrier.section]]
name = "Identity Service API"
path = "identity_service"
[[tool.towncrier.section]]
name = "Push Gateway API"
path = "push_gateway"
[[tool.towncrier.section]]
name = "Room Versions"
path = "room_versions"
[[tool.towncrier.section]]
name = "Appendices"
path = "appendices"
[[tool.towncrier.section]]
name = "Internal Changes/Tooling"
path = "internal"

View file

@ -0,0 +1 @@
For room versions 7 through 11: Clarify that `invite->knock` is not a legal transition.

View file

@ -1 +0,0 @@
Document why `/state_ids` can respond with a 404.

View file

@ -1 +0,0 @@
Fix definition of response of `POST /_matrix/federation/v1/user/keys/claim`.

View file

@ -1 +0,0 @@
Fix level of examples in server keys definition.

View file

@ -1 +0,0 @@
Make sure examples types match schema in definitions.

View file

@ -1 +0,0 @@
Allow `null` in `room_types` in `POST /publicRooms` endpoints schemas.

View file

@ -1 +0,0 @@
Fix broken header formatting. Contributed by @midnightveil.

View file

@ -0,0 +1 @@
Clarify Server-Server API request signing example by using the `POST` HTTP method, as `GET` requests don't have request bodies.

View file

@ -0,0 +1,24 @@
{% for section_name, section in sections.items() %}
{% if section_name %}
### {{section_name}}
{% endif %}
{% if section %}
{% for category, val in definitions.items() if category in section %}
**{{ definitions[category]['name'] }}**
{% for content, issues in section[category].items() %}
- {{ content }} (
{%- for issue in issues %}
[{{issue}}](https://github.com/matrix-org/matrix-spec/issues/{{issue|trim('#')}}){% if not loop.last %}, {% endif %}
{%- endfor %}
)
{% endfor %}
{% endfor %}
{% else %}
No significant changes.
{% endif %}
{% endfor %}

View file

@ -7,9 +7,6 @@ canonifyURLs = true
enableRobotsTXT = true enableRobotsTXT = true
# Hugo allows theme composition (and inheritance). The precedence is from left to right.
theme = ["docsy"]
# We disable RSS, because (a) it's useless, (b) Hugo seems to generate broken # We disable RSS, because (a) it's useless, (b) Hugo seems to generate broken
# links to it when used with a --baseURL (for example, https://spec.matrix.org/v1.4/ # links to it when used with a --baseURL (for example, https://spec.matrix.org/v1.4/
# contains `<link rel="alternate" type="application/rss&#43;xml" href="/v1.4/v1.4/index.xml">`). # contains `<link rel="alternate" type="application/rss&#43;xml" href="/v1.4/v1.4/index.xml">`).
@ -23,6 +20,21 @@ languageName ="English"
# Weight used for sorting. # Weight used for sorting.
weight = 1 weight = 1
# Entries in the main menu in the header.
[menus]
[[menus.main]]
name = 'Foundation'
url = 'https://matrix.org/foundation/'
weight = 10
[[menus.main]]
name = 'FAQs'
url = 'https://matrix.org/faq'
weight = 20
[[menus.main]]
name = 'Blog'
url = 'https://matrix.org/blog/posts'
weight = 30
[markup] [markup]
[markup.goldmark] [markup.goldmark]
[markup.goldmark.renderer] [markup.goldmark.renderer]
@ -53,8 +65,8 @@ current_version_url = "https://spec.matrix.org/latest"
# The following is used when status = "stable", and is displayed in various UI elements on a released version # The following is used when status = "stable", and is displayed in various UI elements on a released version
# of the spec. CI will set these values here automatically when a release git tag (i.e `v1.5`) is created. # of the spec. CI will set these values here automatically when a release git tag (i.e `v1.5`) is created.
# major = "1" # major = "1"
# minor = "7" # minor = "9"
# release_date = "May 25, 2023" # release_date = "November 29, 2023"
# User interface configuration # User interface configuration
[params.ui] [params.ui]
@ -111,3 +123,13 @@ sidebar_menu_compact = true
X-Frame-Options = "sameorigin" X-Frame-Options = "sameorigin"
Access-Control-Allow-Origin = "*" Access-Control-Allow-Origin = "*"
Access-Control-Allow-Methods = "GET" Access-Control-Allow-Methods = "GET"
# hugo module configuration
[module]
[module.hugoVersion]
extended = true
min = "0.110.0"
[[module.imports]]
path = "github.com/matrix-org/docsy"
disable = false

View file

@ -419,9 +419,16 @@ into the `m.` namespace.
### Timestamps ### Timestamps
Unless otherwise stated, timestamps are measured as milliseconds since Unless otherwise stated, timestamps are the number of milliseconds
the Unix epoch. Throughout the specification this may be referred to as elapsed since the unix epoch (1970-01-01 00:00:00 UTC), but not counting
POSIX, Unix, or just "time in milliseconds". leap seconds, so that each day is precisely 86,400,000 milliseconds.
This means that timestamps can repeat during leap seconds. Most
programming languages provide timestamps in that format natively, e.g.
[ECMAScript](https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-time-values-and-time-range).
Throughout the specification this may be referred to as POSIX,
[Unix](https://en.wikipedia.org/wiki/Unix_time), or just "time in
milliseconds".
## Specification Versions ## Specification Versions

View file

@ -136,12 +136,12 @@ removing insignificant whitespace, fractions, exponents and redundant
character escapes. character escapes.
value = false / null / true / object / array / number / string value = false / null / true / object / array / number / string
false = %x66.61.6c.73.65 false = %x66.61.6C.73.65
null = %x6e.75.6c.6c null = %x6E.75.6C.6C
true = %x74.72.75.65 true = %x74.72.75.65
object = %x7B [ member *( %x2C member ) ] %7D object = %x7B [ member *( %x2C member ) ] %x7D
member = string %x3A value member = string %x3A value
array = %x5B [ value *( %x2C value ) ] %5B array = %x5B [ value *( %x2C value ) ] %x5D
number = [ %x2D ] int number = [ %x2D ] int
int = %x30 / ( %x31-39 *digit ) int = %x30 / ( %x31-39 *digit )
digit = %x30-39 digit = %x30-39

122
content/changelog/v1.8.md Normal file
View file

@ -0,0 +1,122 @@
---
date: 2023-08-23T09:23:53-06:00
---
<!--
This is a header file for the generated changelog.
Variables:
v1.8 = Replaced by the version number (eg: v1.2)
August 23, 2023 = Replaced by the date (eg: April 01, 2021)
-->
## v1.8
<table class="release-info">
<tr><th>Git commit</th><td><a href="https://github.com/matrix-org/matrix-spec/tree/v1.8">https://github.com/matrix-org/matrix-spec/tree/v1.8</a></td>
<tr><th>Release date</th><td>August 23, 2023</td>
</table>
<!-- Intentionally blank line to ensure headers work in the concatenated changelog -->
### Client-Server API
**Backwards Compatible Changes**
- Require callers to be joined to the room to report its events, as per [MSC2249](https://github.com/matrix-org/matrix-spec-proposals/pull/2249). ([#1517](https://github.com/matrix-org/matrix-spec/issues/1517))
**Spec Clarifications**
- Fix missing `type` property in the JSON schema definition of the `m.reaction` event. Contributed by @chebureki. ([#1552](https://github.com/matrix-org/matrix-spec/issues/1552))
- Make sure examples types match schema in definitions. ([#1563](https://github.com/matrix-org/matrix-spec/issues/1563))
- Allow `null` in `room_types` in `POST /publicRooms` endpoints schemas. ([#1564](https://github.com/matrix-org/matrix-spec/issues/1564))
- Fix broken header formatting. Contributed by @midnightveil. ([#1578](https://github.com/matrix-org/matrix-spec/issues/1578))
- Render binary request and response bodies. ([#1579](https://github.com/matrix-org/matrix-spec/issues/1579))
- Fix description of MAC calculation in SAS verification. ([#1590](https://github.com/matrix-org/matrix-spec/issues/1590))
- Update link to SAS emoji definition data. ([#1593](https://github.com/matrix-org/matrix-spec/issues/1593))
- Fix various typos throughout the specification. ([#1597](https://github.com/matrix-org/matrix-spec/issues/1597))
### Server-Server API
**Deprecations**
- Deprecate `matrix` SRV lookup steps during server discovery, as per [MSC4040](https://github.com/matrix-org/matrix-spec-proposals/pull/4040). ([#1624](https://github.com/matrix-org/matrix-spec/issues/1624))
**Backwards Compatible Changes**
- Add `matrix-fed` SRV lookup steps to server discovery, as per [MSC4040](https://github.com/matrix-org/matrix-spec-proposals/pull/4040). ([#1624](https://github.com/matrix-org/matrix-spec/issues/1624))
**Spec Clarifications**
- Document why `/state_ids` can respond with a 404. ([#1521](https://github.com/matrix-org/matrix-spec/issues/1521))
- Fix response definition for `POST /_matrix/federation/v1/user/keys/claim`. ([#1559](https://github.com/matrix-org/matrix-spec/issues/1559))
- Fix examples in server keys definition. ([#1560](https://github.com/matrix-org/matrix-spec/issues/1560))
- Make sure examples types match schema in definitions. ([#1563](https://github.com/matrix-org/matrix-spec/issues/1563))
- Allow `null` in `room_types` in `POST /publicRooms` endpoints schemas. ([#1564](https://github.com/matrix-org/matrix-spec/issues/1564))
- Fix broken header formatting. Contributed by @midnightveil. ([#1578](https://github.com/matrix-org/matrix-spec/issues/1578))
- Remove spurious mention of a "default port" with respect to SRV record lookup. ([#1615](https://github.com/matrix-org/matrix-spec/issues/1615))
- Switch to ordered list for server name resolution steps. ([#1623](https://github.com/matrix-org/matrix-spec/issues/1623))
### Application Service API
**Spec Clarifications**
- Fix type of custom `fields` in thirdparty lookup queries. ([#1584](https://github.com/matrix-org/matrix-spec/issues/1584))
### Identity Service API
**Spec Clarifications**
- Make sure examples types match schema in definitions. ([#1563](https://github.com/matrix-org/matrix-spec/issues/1563))
### Push Gateway API
No significant changes.
### Room Versions
**Backwards Compatible Changes**
- Add room version 11 as per [MSC3820](https://github.com/matrix-org/matrix-spec-proposals/pull/3820). ([#1604](https://github.com/matrix-org/matrix-spec/issues/1604))
- Move `redacts` from top level to `content` on `m.room.redaction` events in room version 11, as per [MSC2174](https://github.com/matrix-org/matrix-spec-proposals/pull/2174). ([#1604](https://github.com/matrix-org/matrix-spec/issues/1604))
- Remove `creator` from `m.room.creator` events in room version 11, as per [MSC2175](https://github.com/matrix-org/matrix-spec-proposals/pull/2175). ([#1604](https://github.com/matrix-org/matrix-spec/issues/1604))
- Remove remaining usage of `origin` from events in room version 11, as per [MSC3989](https://github.com/matrix-org/matrix-spec-proposals/pull/3989). ([#1604](https://github.com/matrix-org/matrix-spec/issues/1604))
- Update the redaction rules in room version 11, as per [MSC2176](https://github.com/matrix-org/matrix-spec-proposals/pull/2176) and [MSC3821](https://github.com/matrix-org/matrix-spec-proposals/pull/3821). ([#1604](https://github.com/matrix-org/matrix-spec/issues/1604))
### Appendices
**Backwards Compatible Changes**
- Allow `+` in Matrix IDs, as per [MSC4009](https://github.com/matrix-org/matrix-spec-proposals/pull/4009). ([#1583](https://github.com/matrix-org/matrix-spec/issues/1583))
**Spec Clarifications**
- Clarify spec re canonical JSON to handle negative-zero; also, give an example of negative-zero and a large power of ten. ([#1573](https://github.com/matrix-org/matrix-spec/issues/1573))
### Internal Changes/Tooling
**Backwards Compatible Changes**
- Upgrade Swagger data to OpenAPI 3.1. ([#1310](https://github.com/matrix-org/matrix-spec/issues/1310))
- Create `@matrix-org/spec` npm package to ship the SAS Emoji data definitions & translations. ([#1620](https://github.com/matrix-org/matrix-spec/issues/1620))
**Spec Clarifications**
- Update the CI to validate the file extension of changelog entries. ([#1542](https://github.com/matrix-org/matrix-spec/issues/1542))
- Disclosure sections now only display their title when collapsed. ([#1549](https://github.com/matrix-org/matrix-spec/issues/1549))
- Fix the sidebar in recent versions of Hugo. ([#1551](https://github.com/matrix-org/matrix-spec/issues/1551))
- Bump jsonschema to validate JSON Schemas against Draft 2020-12. ([#1556](https://github.com/matrix-org/matrix-spec/issues/1556))
- Use Redocly CLI to validate OpenAPI definitions. ([#1558](https://github.com/matrix-org/matrix-spec/issues/1558))
- Use tag name as the OpenAPI definition version. ([#1561](https://github.com/matrix-org/matrix-spec/issues/1561))
- Make sure version in `x-changedInMatrixVersion` is a string. ([#1562](https://github.com/matrix-org/matrix-spec/issues/1562))
- Clarify usage of ABNF for grammar in the documentation style guide. ([#1582](https://github.com/matrix-org/matrix-spec/issues/1582))
- Remove unnecessary `oneOf`s in JSON schemas. ([#1585](https://github.com/matrix-org/matrix-spec/issues/1585))
- Update the version of Hugo used to render the spec to v0.113.0. ([#1591](https://github.com/matrix-org/matrix-spec/issues/1591))
- Fix rendered changelog with new version of towncrier. ([#1598](https://github.com/matrix-org/matrix-spec/issues/1598))
- Improve the layout of tables on desktop displays. Contributed by Martin Fischer. ([#1601](https://github.com/matrix-org/matrix-spec/issues/1601))

93
content/changelog/v1.9.md Normal file
View file

@ -0,0 +1,93 @@
---
date: 2023-11-29T10:04:26-07:00
---
<!--
This is a header file for the generated changelog.
Variables:
v1.9 = Replaced by the version number (eg: v1.2)
November 29, 2023 = Replaced by the date (eg: April 01, 2021)
-->
## v1.9
<table class="release-info">
<tr><th>Git commit</th><td><a href="https://github.com/matrix-org/matrix-spec/tree/v1.9">https://github.com/matrix-org/matrix-spec/tree/v1.9</a></td>
<tr><th>Release date</th><td>November 29, 2023</td>
</table>
<!-- Intentionally blank line to ensure headers work in the concatenated changelog -->
### Client-Server API
**Backwards Compatible Changes**
- Add the `m.rule.suppress_edits` default push rule, as per [MSC3958](https://github.com/matrix-org/matrix-spec-proposals/pull/3958). ([#1617](https://github.com/matrix-org/matrix-spec/issues/1617))
**Spec Clarifications**
- Fix `m.call.negotiate` schema and example. ([#1546](https://github.com/matrix-org/matrix-spec/issues/1546))
- Clarify that the `via` property is required for `m.space.parent` and `m.space.child` as per [MSC1772](https://github.com/matrix-org/matrix-spec-proposals/pull/1772). Contributed by @PaarthShah. ([#1618](https://github.com/matrix-org/matrix-spec/issues/1618))
- Add a note to the `/publicRooms` API that the server name is case sensitive. ([#1638](https://github.com/matrix-org/matrix-spec/issues/1638))
- Clarify that an `m.room.name` event with an absent `name` field is not expected behavior. ([#1639](https://github.com/matrix-org/matrix-spec/issues/1639))
- Fix schemas used for account data and presence events in `GET /initialSync`. ([#1647](https://github.com/matrix-org/matrix-spec/issues/1647))
- Fix various typos throughout the specification. ([#1658](https://github.com/matrix-org/matrix-spec/issues/1658), [#1661](https://github.com/matrix-org/matrix-spec/issues/1661), [#1665](https://github.com/matrix-org/matrix-spec/issues/1665))
- Fix `.m.rule.suppress_notices` push rule not being valid JSON. ([#1671](https://github.com/matrix-org/matrix-spec/issues/1671))
- Add missing properties for `event_property_is` and `event_property_contains` push conditions to `PushConditions` object. ([#1673](https://github.com/matrix-org/matrix-spec/issues/1673))
- Indicate that fallback keys should have a `fallback` property set to `true`. ([#1676](https://github.com/matrix-org/matrix-spec/issues/1676))
- Clarify that thread roots are not considered within the thread. ([#1677](https://github.com/matrix-org/matrix-spec/issues/1677))
### Server-Server API
**Spec Clarifications**
- Fix schema of `m.receipt` EDU. ([#1636](https://github.com/matrix-org/matrix-spec/issues/1636))
- Fix various typos throughout the specification. ([#1661](https://github.com/matrix-org/matrix-spec/issues/1661))
- Clarify that federation requests for non-local users are invalid. ([#1672](https://github.com/matrix-org/matrix-spec/issues/1672))
### Application Service API
No significant changes.
### Identity Service API
No significant changes.
### Push Gateway API
No significant changes.
### Room Versions
No significant changes.
### Appendices
**Spec Clarifications**
- Clarify timestamp specification with respect to leap seconds. ([#1627](https://github.com/matrix-org/matrix-spec/issues/1627))
- Fix various typos throughout the specification. ([#1652](https://github.com/matrix-org/matrix-spec/issues/1652))
### Internal Changes/Tooling
**Backwards Compatible Changes**
- Add more CI checks for OpenAPI definitions and JSON Schemas. ([#1656](https://github.com/matrix-org/matrix-spec/issues/1656))
- Generate server-server OpenAPI definition. ([#1657](https://github.com/matrix-org/matrix-spec/issues/1657))
**Spec Clarifications**
- Replace all mentions of Swagger by OpenAPI. ([#1633](https://github.com/matrix-org/matrix-spec/issues/1633))
- Fix enum types in JSON schemas. ([#1634](https://github.com/matrix-org/matrix-spec/issues/1634))
- Fix schema of `m.mentions` object. ([#1635](https://github.com/matrix-org/matrix-spec/issues/1635))
- Fix rendering of `m.receipt` event in Client-Server API. ([#1637](https://github.com/matrix-org/matrix-spec/issues/1637))
- Remove required `fieldname` in appservice Protocol definition. ([#1646](https://github.com/matrix-org/matrix-spec/issues/1646))
- Fix github action workflow responsible for releasing of @matrix-org/spec package. ([#1648](https://github.com/matrix-org/matrix-spec/issues/1648))
- Upgrade GitHub actions. ([#1660](https://github.com/matrix-org/matrix-spec/issues/1660))

View file

@ -77,6 +77,7 @@ algorithm is represented by an object with the following properties:
|------------|------------|---------------------------------------------------------------------------------------------------------------------------------------------------| |------------|------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
| key | string | **Required.** The unpadded Base64-encoded 32-byte Curve25519 public key. | | key | string | **Required.** The unpadded Base64-encoded 32-byte Curve25519 public key. |
| signatures | Signatures | **Required.** Signatures of the key object. The signature is calculated using the process described at [Signing JSON](/appendices/#signing-json). | | signatures | Signatures | **Required.** Signatures of the key object. The signature is calculated using the process described at [Signing JSON](/appendices/#signing-json). |
| fallback | boolean | Indicates whether this is a [fallback key](#one-time-and-fallback-keys). Defaults to `false`. |
Example: Example:
@ -150,7 +151,9 @@ JSON](/appendices/#signing-json).
One-time and fallback keys are also uploaded to the homeserver using the One-time and fallback keys are also uploaded to the homeserver using the
[`/keys/upload`](/client-server-api/#post_matrixclientv3keysupload) API. New [`/keys/upload`](/client-server-api/#post_matrixclientv3keysupload) API. New
one-time and fallback keys are uploaded as needed. one-time and fallback keys are uploaded as needed. Fallback keys for key
algorithms whose format is a signed JSON object should contain a property named
`fallback` with a value of `true`.
Devices must store the private part of each key they upload. They can Devices must store the private part of each key they upload. They can
discard the private part of a one-time key when they receive a message discard the private part of a one-time key when they receive a message
@ -657,10 +660,12 @@ The process between Alice and Bob verifying each other would be:
11. Alice's device receives Bob's message and verifies the commitment 11. Alice's device receives Bob's message and verifies the commitment
hash from earlier matches the hash of the key Bob's device just sent hash from earlier matches the hash of the key Bob's device just sent
and the content of Alice's `m.key.verification.start` message. and the content of Alice's `m.key.verification.start` message.
12. Both Alice and Bob's devices perform an Elliptic-curve 12. Both Alice's and Bob's devices perform an Elliptic-curve Diffie-Hellman using
Diffie-Hellman their private ephemeral key, and the other device's ephemeral public key
(*ECDH(K<sub>A</sub><sup>private</sup>*,*K<sub>B</sub><sup>public</sup>*)), (*ECDH(K<sub>A</sub><sup>private</sup>*,*K<sub>B</sub><sup>public</sup>*)
using the result as the shared secret. for Alice's device and
*ECDH(K<sub>B</sub><sup>private</sup>*,*K<sub>A</sub><sup>public</sup>*)
for Bob's device), using the result as the shared secret.
13. Both Alice and Bob's devices display a SAS to their users, which is 13. Both Alice and Bob's devices display a SAS to their users, which is
derived from the shared key using one of the methods in this derived from the shared key using one of the methods in this
section. If multiple SAS methods are available, clients should allow section. If multiple SAS methods are available, clients should allow
@ -833,15 +838,15 @@ is the concatenation of:
- The Device ID of the device which sent the - The Device ID of the device which sent the
`m.key.verification.start` message, followed by `|`. `m.key.verification.start` message, followed by `|`.
- The public key from the `m.key.verification.key` message sent by - The public key from the `m.key.verification.key` message sent by
the device which sent the `m.key.verification.start` message, the device which sent the `m.key.verification.start` message, encoded as
followed by `|`. unpadded base64, followed by `|`.
- The Matrix ID of the user who sent the `m.key.verification.accept` - The Matrix ID of the user who sent the `m.key.verification.accept`
message, followed by `|`. message, followed by `|`.
- The Device ID of the device which sent the - The Device ID of the device which sent the
`m.key.verification.accept` message, followed by `|`. `m.key.verification.accept` message, followed by `|`.
- The public key from the `m.key.verification.key` message sent by - The public key from the `m.key.verification.key` message sent by
the device which sent the `m.key.verification.accept` message, the device which sent the `m.key.verification.accept` message, encoded as
followed by `|`. unpadded base64, followed by `|`.
- The `transaction_id` being used. - The `transaction_id` being used.
When the `key_agreement_protocol` is the deprecated method `curve25519`, When the `key_agreement_protocol` is the deprecated method `curve25519`,
@ -1361,10 +1366,18 @@ The `session_data` field in the backups is constructed as follows:
PKCS\#7 padding. This encrypted data, encoded using unpadded base64, PKCS\#7 padding. This encrypted data, encoded using unpadded base64,
becomes the `ciphertext` property of the `session_data`. becomes the `ciphertext` property of the `session_data`.
5. Pass the raw encrypted data (prior to base64 encoding) through 5. Pass an empty string through HMAC-SHA-256 using the MAC key generated above.
HMAC-SHA-256 using the MAC key generated above. The first 8 bytes of The first 8 bytes of the resulting MAC are base64-encoded, and become the
the resulting MAC are base64-encoded, and become the `mac` property `mac` property of the `session_data`.
of the `session_data`.
{{% boxes/warning %}}
Step 5 was intended to pass the raw encrypted data, but due to a bug in libolm,
all implementations have since passed an empty string instead.
Future versions of the spec will fix this problem. See
[MSC4048](https://github.com/matrix-org/matrix-spec-proposals/pull/4048) for a
potential new key backup algorithm version that would fix this issue.
{{% /boxes/warning %}}
{{% definition path="api/client-server/definitions/key_backup_session_data" %}} {{% definition path="api/client-server/definitions/key_backup_session_data" %}}
@ -1765,9 +1778,9 @@ Example response:
], ],
}, },
"device_one_time_keys_count": { "device_one_time_keys_count": {
"curve25519": 10,
"signed_curve25519": 20 "signed_curve25519": 20
} },
"device_unused_fallback_key_types": ["signed_curve25519"]
} }
``` ```

View file

@ -14,7 +14,7 @@ event with the corresponding emoji (👍). Another potential usage is to allow
bots to send an event indicating the success or failure of a command. bots to send an event indicating the success or failure of a command.
Along with the normal properties `event_id` and `rel_type`, an `m.relates_to` Along with the normal properties `event_id` and `rel_type`, an `m.relates_to`
property with `rel_type: m.annotion` should contain a `key` that indicates the property with `rel_type: m.annotation` should contain a `key` that indicates the
annotation being applied. For example, when reacting with emojis, the key annotation being applied. For example, when reacting with emojis, the key
contains the emoji being used. contains the emoji being used.

View file

@ -27,17 +27,25 @@ instead.
Some message types support HTML in the event content that clients should Some message types support HTML in the event content that clients should
prefer to display if available. Currently `m.text`, `m.emote`, `m.notice`, prefer to display if available. Currently `m.text`, `m.emote`, `m.notice`,
and `m.key.verification.request` support an additional `format` parameter of `m.image`, `m.file`, `m.audio`, `m.video` and `m.key.verification.request`
`org.matrix.custom.html`. When this field is present, a `formatted_body` support an additional `format` parameter of `org.matrix.custom.html`. When this
with the HTML must be provided. The plain text version of the HTML field is present, a `formatted_body` with the HTML must be provided. The plain
should be provided in the `body`. text version of the HTML should be provided in the `body`.
{{% boxes/note %}}
{{% changed-in v="1.10" %}}
In previous versions of the specification, the `format` and `formatted` fields
were limited to `m.text`, `m.emote`, `m.notice`, and
`m.key.verification.request`. This list is expanded to include `m.image`,
`m.file`, `m.audio` and `m.video` for [media captions](#media-captions).
{{% /boxes/note %}}
Clients should limit the HTML they render to avoid Cross-Site Scripting, Clients should limit the HTML they render to avoid Cross-Site Scripting,
HTML injection, and similar attacks. The strongly suggested set of HTML HTML injection, and similar attacks. The strongly suggested set of HTML
tags to permit, denying the use and rendering of anything else, is: tags to permit, denying the use and rendering of anything else, is:
`font`, `del`, `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `blockquote`, `p`, `font`, `del`, `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `blockquote`, `p`,
`a`, `ul`, `ol`, `sup`, `sub`, `li`, `b`, `i`, `u`, `strong`, `em`, `a`, `ul`, `ol`, `sup`, `sub`, `li`, `b`, `i`, `u`, `strong`, `em`,
`strike`, `code`, `hr`, `br`, `div`, `table`, `thead`, `tbody`, `tr`, `s`, `code`, `hr`, `br`, `div`, `table`, `thead`, `tbody`, `tr`,
`th`, `td`, `caption`, `pre`, `span`, `img`, `details`, `summary`. `th`, `td`, `caption`, `pre`, `span`, `img`, `details`, `summary`.
Not all attributes on those tags should be permitted as they may be Not all attributes on those tags should be permitted as they may be
@ -320,6 +328,49 @@ to the media repository, then reference the `mxc://` URI in a markdown-style lin
Clients SHOULD render spoilers differently with some sort of disclosure. For example, the Clients SHOULD render spoilers differently with some sort of disclosure. For example, the
client could blur the actual text and ask the user to click on it for it to be revealed. client could blur the actual text and ask the user to click on it for it to be revealed.
##### Media captions
{{% added-in v="1.10" %}}
Media messages, comprised of `m.image`, `m.file`, `m.audio` and `m.video`, can
include a caption to convey additional information about the media.
To send captions, clients MUST use the `filename` and the `body`, and optionally
the `formatted_body` with the `org.matrix.custom.html` format, described above.
If the `filename` is present, and its value is different than `body`, then
`body` is considered to be a caption, otherwise `body` is a filename. `format`
and `formatted_body` are only used for captions.
{{% boxes/note %}}
In previous versions of the specification, `body` was usually used to set the
filename of the uploaded file, and `filename` was only present on `m.file` with
the same purpose.
{{% /boxes/note %}}
An example of a media message with a caption is:
```json
{
"msgtype": "m.image",
"url": "mxc://example.org/abc123",
"filename": "dog.jpg",
"body": "this is a ~~cat~~ picture :3",
"format": "org.matrix.custom.html",
"formatted_body": "this is a <s>cat</s> picture :3",
"info": {
"w": 479,
"h": 640,
"mimetype": "image/jpeg",
"size": 27253
},
"m.mentions": {}
}
```
Clients MUST render the caption alongside the media and SHOULD prefer its
formatted representation.
#### Server behaviour #### Server behaviour
Homeservers SHOULD reject `m.room.message` events which don't have a Homeservers SHOULD reject `m.room.message` events which don't have a

View file

@ -13,6 +13,20 @@ the event to reference the entity being mentioned.
{{% definition path="api/client-server/definitions/m.mentions" %}} {{% definition path="api/client-server/definitions/m.mentions" %}}
An event's content will then look like this:
```json
{
"body": "Hello Alice!",
"msgtype": "m.text",
"format": "org.matrix.custom.html",
"formatted_body": "Hello <a href='https://matrix.to/#/@alice:example.org'>Alice</a>!",
"m.mentions": {
"user_ids": ["@alice:example.org"]
}
}
```
Additionally, see the [`.m.rule.is_user_mention`](#_m_rule_is_user_mention) and Additionally, see the [`.m.rule.is_user_mention`](#_m_rule_is_user_mention) and
[`.m.rule.is_room_mention`](#_m_rule_is_room_mention) push rules. [`.m.rule.is_room_mention`](#_m_rule_is_room_mention) push rules.
Users should not add their own Matrix ID to the `m.mentions` property as outgoing Users should not add their own Matrix ID to the `m.mentions` property as outgoing

View file

@ -454,7 +454,7 @@ Definition:
{ {
"kind": "event_match", "kind": "event_match",
"key": "content.msgtype", "key": "content.msgtype",
"pattern": "m.notice", "pattern": "m.notice"
} }
], ],
"actions": [] "actions": []
@ -750,6 +750,30 @@ Definition:
} }
``` ```
**`.m.rule.suppress_edits`**
{{% added-in v="1.9" %}}
Suppresses notifications related to [event replacements](#event-replacements).
Definition:
```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": []
}
```
##### Default Content Rules ##### Default Content Rules
<a id="_m_rule_contains_user_name"/> **`.m.rule.contains_user_name`** <a id="_m_rule_contains_user_name"/> **`.m.rule.contains_user_name`**
@ -1046,16 +1070,16 @@ ahead), however if the `m.read.private` receipt were to be updated to
event D then the user has read up to D (the `m.read` receipt is now event D then the user has read up to D (the `m.read` receipt is now
behind the `m.read.private` receipt). behind the `m.read.private` receipt).
{{< added-in v="1.4" >}} When handling threaded read receipts, the server {{< added-in v="1.4" >}} When handling threaded read receipts, the server is to
is to partition the notification count to each thread (with the main timeline partition the notification count to each thread (with the main timeline being
being its own thread). To determine if an event is part of a thread the its own thread). To determine if an event is part of a thread the server follows
server follows the [event relationship](#forming-relationships-between-events) the [event relationship](#forming-relationships-between-events) until it finds a
until it finds a thread root (as specified by the [threading module](#threading)), thread root via an `m.thread` relation (as specified by the [threading
however it is not recommended that the server traverse infinitely. Instead, module](#threading)), however it is not recommended that the server traverse
implementations are encouraged to do a maximum of 3 hops to find a thread infinitely. Instead, implementations are encouraged to do a maximum of 3 hops to
before deciding that the event does not belong to a thread. This is primarily find a thread before deciding that the event does not belong to a thread. This
to ensure that future events, like `m.reaction`, are correctly considered is primarily to ensure that future events, like `m.reaction`, are correctly
"part of" a given thread. considered "part of" a given thread.
#### Server behaviour #### Server behaviour

View file

@ -137,16 +137,20 @@ either a thread root's event ID or `main` for the main timeline.
Threading introduces a concept of multiple conversations being held in the same Threading introduces a concept of multiple conversations being held in the same
room and thus deserve their own read receipts and notification counts. An event is room and thus deserve their own read receipts and notification counts. An event is
considered to be "in a thread" if it meets any of the following criteria: considered to be "in a thread" if:
* It has a `rel_type` of `m.thread`.
* It has child events with a `rel_type` of `m.thread` (in which case it'd be the
thread root).
* Following the event relationships, it has a parent event which qualifies for
one of the above. Implementations should not recurse infinitely, though: a
maximum of 3 hops is recommended to cover indirect relationships.
Events not in a thread but still in the room are considered to be part of the * It has a `rel_type` of `m.thread`, or
"main timeline", or a special thread with an ID of `main`. * Following the event relationships, it has a parent event which references
the thread root with a `rel_type` of `m.thread`. Implementations should
not recurse infinitely, though: a maximum of 3 hops is recommended to
cover indirect relationships.
Events not in a thread but still in the room are considered to be in the "main
timeline". When referring to the main timeline as a thread (e.g. in receipts
and notifications counts) a special thread ID of `main` is used.
Thread roots are considered to be in the main timeline, as are events that are
related to a thread root via non-thread relations.
The following is an example DAG for a room, with dotted lines showing event The following is an example DAG for a room, with dotted lines showing event
relationships and solid lines showing topological ordering. relationships and solid lines showing topological ordering.
@ -204,7 +208,7 @@ event when the user expands that thread.
#### Server behaviour #### Server behaviour
For efficiency, receipts SHOULD be batched into one event per room For efficiency, receipts SHOULD be batched into one event per room and thread
before delivering them to clients. before delivering them to clients.
Some receipts are sent across federation as EDUs with type `m.receipt`. The Some receipts are sent across federation as EDUs with type `m.receipt`. The

View file

@ -18,3 +18,7 @@ Servers are free to handle the reported content however they desire.
This may be a dedicated room to alert server administrators to the This may be a dedicated room to alert server administrators to the
reported content or some other mechanism for notifying the appropriate reported content or some other mechanism for notifying the appropriate
people. people.
{{< changed-in v="1.8" >}} The server MUST verify that the user
reporting the event is currently joined to the room the event is
in before accepting a report.

View file

@ -60,7 +60,8 @@ specific fallback text is different for each `msgtype`, however the
general format for the `body` is: general format for the `body` is:
```text ```text
> <@alice:example.org> This is the original body > <@alice:example.org> This is the first line of the original body
> This is the second line
This is where the reply goes This is where the reply goes
``` ```

View file

@ -66,6 +66,70 @@ default key.
|------------|-----------|------------------------------------------| |------------|-----------|------------------------------------------|
| key | string | **Required.** The ID of the default key. | | key | string | **Required.** The ID of the default key. |
###### `m.secret_storage.v1.aes-hmac-sha2`
For the purposes of allowing clients to check whether a user has correctly
entered the key, keys for use with the `m.secret_storage.v1.aes-hmac-sha2`
algorithm are stored with some additional data.
When storing a key, clients SHOULD:
1. Given the secret storage key, generate 64 bytes by performing an
HKDF with SHA-256 as the hash, a salt of 32 bytes of 0, and the empty
string as the info. The first 32 bytes are used as the AES key,
and the next 32 bytes are used as the MAC key.
2. Generate 16 random bytes, set bit 63 to 0 (in order to work around
differences in AES-CTR implementations), and use this as the AES
initialization vector (IV).
3. Encrypt a message consisting of 32 bytes of 0, using AES-CTR-256 using the
AES key and IV generated above.
4. Pass the raw encrypted data through HMAC-SHA-256 using the MAC key
generated above.
5. Encode the IV from step 2, and the MAC from step 4, using [unpadded
base64](/appendices/#unpadded-base64), and store the results in the `iv`
and `mac` properties respectively in the `m.secret_storage.key.[key ID]`
account-data. (The ciphertext from step 3 is discarded after passing
through the MAC calculation.)
This process can be repeated by a client checking if the key is correct: the
MAC should match if the key is correct. Note, however, that these properties
are **optional**. If they are not present, clients must assume that the key is
valid.
Note also, that although clients SHOULD use unpadded base64 as specified above,
some existing implementations use standard [RFC4648-compliant
base64](https://datatracker.ietf.org/doc/html/rfc4648#section-4) with padding,
so clients must accept either encoding.
The structure of a `m.secret_storage.key.[key ID]` account data object for use
with this algorithm is therefore as follows:
`AesHmacSha2KeyDescription`
| Parameter | Type | Description |
|-------------|--------|------------------------------------------------------------------------------------------------------|
| name | string | Optional. The name of the key. |
| algorithm | string | **Required.** The encryption algorithm to be used for this key: `m.secret_storage.v1.aes-hmac-sha2`. |
| passphrase | object | See [deriving keys from passphrases](#deriving-keys-from-passphrases) section for a description of this property. |
| iv | string | Optional. The 16-byte initialization vector for the validation check, encoded as base64. |
| mac | string | Optional. The MAC of the result of encrypting 32 bytes of 0, encoded as base64. |
For example, it could look like:
```json
{
"name": "m.default",
"algorithm": "m.secret_storage.v1.aes-hmac-sha2",
"iv": "random+data",
"mac": "mac+of+encrypted+zeros"
}
```
##### Secret storage ##### Secret storage
Encrypted data is stored in the user's account data using the event Encrypted data is stored in the user's account data using the event
@ -82,7 +146,7 @@ of the data.
| Parameter | Type | Description | | Parameter | Type | Description |
|-----------|------------------|-------------| |-----------|------------------|-------------|
| encrypted | {string: object} | **Required.** Map from key ID the encrypted data. The exact format for the encrypted data is dependent on the key algorithm. See the definition of `AesHmacSha2EncryptedData` in the [m.secret_storage.v1.aes-hmac-sha2](#msecret_storagev1aes-hmac-sha2) section. | | encrypted | {string: object} | **Required.** Map from key ID the encrypted data. The exact format for the encrypted data is dependent on the key algorithm. See the definition of `AesHmacSha2EncryptedData` in the [m.secret_storage.v1.aes-hmac-sha2](#msecret_storagev1aes-hmac-sha2-1) section. |
Example: Example:
@ -147,58 +211,41 @@ HMAC-SHA-256. The secret is encrypted as follows:
1. Given the secret storage key, generate 64 bytes by performing an 1. Given the secret storage key, generate 64 bytes by performing an
HKDF with SHA-256 as the hash, a salt of 32 bytes of 0, and with the HKDF with SHA-256 as the hash, a salt of 32 bytes of 0, and with the
secret name as the info. The first 32 bytes are used as the AES key, secret name as the info. The first 32 bytes are used as the AES key,
and the next 32 bytes are used as the MAC key and the next 32 bytes are used as the MAC key.
2. Generate 16 random bytes, set bit 63 to 0 (in order to work around 2. Generate 16 random bytes, set bit 63 to 0 (in order to work around
differences in AES-CTR implementations), and use this as the AES differences in AES-CTR implementations), and use this as the AES
initialization vector. This becomes the `iv` property, encoded using initialization vector (IV).
base64.
3. Encrypt the data using AES-CTR-256 using the AES key generated 3. Encrypt the data using AES-CTR-256 using the AES key and IV generated
above. This encrypted data, encoded using base64, becomes the above.
`ciphertext` property.
4. Pass the raw encrypted data (prior to base64 encoding) through 4. Pass the raw encrypted data through HMAC-SHA-256 using the MAC key
HMAC-SHA-256 using the MAC key generated above. The resulting MAC is generated above.
base64-encoded and becomes the `mac` property.
5. Encode the IV from step 2, the ciphertext from step 3, and MAC from step 4,
using [unpadded base64](/appendices/#unpadded-base64), and store them as
the `iv`, `ciphertext`, and `mac` properties respectively in the account
data object.
**Note**: some existing implementations encode these properties using
standard [RFC4648-compliant
base64](https://datatracker.ietf.org/doc/html/rfc4648#section-4) with
padding, so clients must accept either encoding.
The structure of the `encrypted` property of an account data object encrypted
with this algorithm is therefore as follows:
`AesHmacSha2EncryptedData` `AesHmacSha2EncryptedData`
| Parameter | Type | Description | Parameter | Type | Description
|------------|---------|------------------------------------------------------------------------| |------------|---------|------------------------------------------------------------------------|
| iv | string | **Required.** The 16-byte initialization vector, encoded as base64. | | iv | string | **Required.** The 16-byte initialization vector, encoded as base64. |
| ciphertext | string | **Required.** The AES-CTR-encrypted data, encoded as base64. | | ciphertext | string | **Required.** The AES-CTR-encrypted data, encoded as base64. |
| mac | string | **Required.** The MAC, encoded as base64. | | mac | string | **Required.** The MAC, encoded as base64. |
For the purposes of allowing clients to check whether a user has
correctly entered the key, clients should:
1. encrypt and MAC a message consisting of 32 bytes of 0 as described For example, data encrypted using this algorithm could look like this:
above, using the empty string as the info parameter to the HKDF in
step 1.
2. store the `iv` and `mac` in the `m.secret_storage.key.[key ID]`
account-data.
`AesHmacSha2KeyDescription`
| Parameter | Type | Description |
|-------------|--------|-----------------------------------------------------------------------------------------------------------------------------------|
| name | string | Optional. The name of the key. |
| algorithm | string | **Required.** The encryption algorithm to be used for this key. Currently, only `m.secret_storage.v1.aes-hmac-sha2` is supported. |
| passphrase | object | See [deriving keys from passphrases](#deriving-keys-from-passphrases) section for a description of this property. |
| iv | string | The 16-byte initialization vector, encoded as base64. |
| mac | string | The MAC of the result of encrypting 32 bytes of 0, encoded as base64. |
For example, the `m.secret_storage.key.key_id` for a key using this
algorithm could look like:
```json
{
"name": "m.default",
"algorithm": "m.secret_storage.v1.aes-hmac-sha2",
"iv": "random+data",
"mac": "mac+of+encrypted+zeros"
}
```
and data encrypted using this algorithm could look like this:
```json ```json
{ {
@ -212,7 +259,7 @@ and data encrypted using this algorithm could look like this:
} }
``` ```
###### Key representation ##### Key representation
When a user is given a raw key for `m.secret_storage.v1.aes-hmac-sha2`, When a user is given a raw key for `m.secret_storage.v1.aes-hmac-sha2`,
it will be presented as a string constructed as follows: it will be presented as a string constructed as follows:
@ -232,7 +279,7 @@ it will be presented as a string constructed as follows:
When decoding a raw key, the process should be reversed, with the When decoding a raw key, the process should be reversed, with the
exception that whitespace is insignificant in the user's input. exception that whitespace is insignificant in the user's input.
###### Deriving keys from passphrases ##### Deriving keys from passphrases
A user may wish to use a chosen passphrase rather than a randomly A user may wish to use a chosen passphrase rather than a randomly
generated key. In this case, information on how to generate the key from generated key. In this case, information on how to generate the key from

View file

@ -12,11 +12,13 @@ as by providing some context to what is going on in the thread but keeping the f
history behind a disclosure. history behind a disclosure.
Threads are established using a `rel_type` of `m.thread` and reference the Threads are established using a `rel_type` of `m.thread` and reference the
*thread root* (the first event in a thread). It is not possible to create a *thread root* (the main timeline event to which the thread events refer). It is not possible to create a thread from an event which itself
thread from an event which itself is the child of an event relationship (i.e., is the child of an event relationship (i.e., one with an `m.relates_to`
one with an `m.relates_to` property). It is therefore also not possible to nest property with a `rel_type` property - see [Relationship types](#relationship-types)).
threads. All events in a thread reference the thread root instead of the It is therefore also not possible to nest threads.
most recent message, unlike rich reply chains.
Unlike rich reply chains, all events in a thread reference the thread root
instead of the most recent message.
As a worked example, the following represents a thread and how it would be formed: As a worked example, the following represents a thread and how it would be formed:

View file

@ -36,11 +36,11 @@ Alternatively, consider flipping the column/row organization to be features
up top and versions on the left. up top and versions on the left.
--> -->
| Feature \ Version | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | | Feature \ Version | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
|-------------------|---|---|---|---|---|---|---|---|---|----| |-------------------|---|---|---|---|---|---|---|---|---|----|----|
| **Knocking** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | | **Knocking** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ |
| **Restricted join rules** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | ✔ | ✔ | | **Restricted join rules** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ |
| **`knock_restricted` join rule** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | | **`knock_restricted` join rule** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | ✔ |
## Complete list of room versions ## Complete list of room versions
@ -57,8 +57,7 @@ the default room version when creating new rooms.
The available room versions are: The available room versions are:
- [Version 1](/rooms/v1) - **Stable**. The current version of most - [Version 1](/rooms/v1) - **Stable**. The initial room version.
rooms.
- [Version 2](/rooms/v2) - **Stable**. Implements State Resolution - [Version 2](/rooms/v2) - **Stable**. Implements State Resolution
Version 2. Version 2.
- [Version 3](/rooms/v3) - **Stable**. Introduces events whose IDs - [Version 3](/rooms/v3) - **Stable**. Introduces events whose IDs
@ -76,6 +75,7 @@ The available room versions are:
redacting some membership events. redacting some membership events.
- [Version 10](/rooms/v10) - **Stable**. Enforces integer-only power levels - [Version 10](/rooms/v10) - **Stable**. Enforces integer-only power levels
and adds `knock_restricted` join rule. and adds `knock_restricted` join rule.
- [Version 11](/rooms/v11) - **Stable**. Clarifies the redaction algorithm.
## Room version grammar ## Room version grammar

View file

@ -19,12 +19,14 @@ not in the following list:
- `membership` - `membership`
The content object must also be stripped of all keys, unless it is one The content object must also be stripped of all keys, unless it is one
of one of the following event types: of the following event types:
- `m.room.member` allows key `membership`. - [`m.room.member`](/client-server-api#mroommember) allows key `membership`.
- `m.room.create` allows key `creator`. - [`m.room.create`](/client-server-api#mroomcreate) allows key `creator`.
- `m.room.join_rules` allows key `join_rule`. - [`m.room.join_rules`](/client-server-api#mroomjoin_rules) allows key `join_rule`.
- `m.room.power_levels` allows keys `ban`, `events`, `events_default`, - [`m.room.power_levels`](/client-server-api#mroompower_levels) allows keys
`kick`, `redact`, `state_default`, `users`, `users_default`. `ban`, `events`, `events_default`, `kick`, `redact`, `state_default`, `users`,
- `m.room.aliases` allows key `aliases`. `users_default`.
- `m.room.history_visibility` allows key `history_visibility`. - [`m.room.aliases`](/client-server-api#historical-events) allows key `aliases`.
- [`m.room.history_visibility`](/client-server-api#mroomhistory_visibility) allows
key `history_visibility`.

View file

@ -0,0 +1,4 @@
Events in rooms of this version have the following structure:
{{% definition path="api/server-server/definitions/pdu_v11" %}}

View file

@ -0,0 +1,30 @@
Upon receipt of a redaction event, the server must strip off any keys
not in the following list:
- `event_id`
- `type`
- `room_id`
- `sender`
- `state_key`
- `content`
- `hashes`
- `signatures`
- `depth`
- `prev_events`
- `auth_events`
- `origin_server_ts`
The content object must also be stripped of all keys, unless it is one
of the following event types:
- [`m.room.member`](/client-server-api#mroommember) allows keys `membership`, `join_authorised_via_users_server`.
Additionally, it allows the `signed` key of the `third_party_invite` key.
- [`m.room.create`](/client-server-api#mroomcreate) allows all keys.
- [`m.room.join_rules`](/client-server-api#mroomjoin_rules) allows keys `join_rule`, `allow`.
- [`m.room.power_levels`](/client-server-api#mroompower_levels) allows keys
`ban`, `events`, `events_default`, `invite`, `kick`, `redact`, `state_default`,
`users`, `users_default`.
- [`m.room.history_visibility`](/client-server-api#mroomhistory_visibility)
allows key `history_visibility`.
- [`m.room.redaction`](/client-server-api#mroomredaction) allows key `redacts`.

View file

@ -19,11 +19,13 @@ not in the following list:
- `membership` - `membership`
The content object must also be stripped of all keys, unless it is one The content object must also be stripped of all keys, unless it is one
of one of the following event types: of the following event types:
- `m.room.member` allows key `membership`. - [`m.room.member`](/client-server-api#mroommember) allows key `membership`.
- `m.room.create` allows key `creator`. - [`m.room.create`](/client-server-api#mroomcreate) allows key `creator`.
- `m.room.join_rules` allows key `join_rule`. - [`m.room.join_rules`](/client-server-api#mroomjoin_rules) allows key `join_rule`.
- `m.room.power_levels` allows keys `ban`, `events`, `events_default`, - [`m.room.power_levels`](/client-server-api#mroompower_levels) allows keys
`kick`, `redact`, `state_default`, `users`, `users_default`. `ban`, `events`, `events_default`, `kick`, `redact`, `state_default`, `users`,
- `m.room.history_visibility` allows key `history_visibility`. `users_default`.
- [`m.room.history_visibility`](/client-server-api#mroomhistory_visibility) allows
key `history_visibility`.

View file

@ -117,7 +117,8 @@ The rules are as follows:
7. If `membership` is `knock`: 7. If `membership` is `knock`:
1. If the `join_rule` is anything other than `knock`, reject. 1. If the `join_rule` is anything other than `knock`, reject.
2. If `sender` does not match `state_key`, reject. 2. If `sender` does not match `state_key`, reject.
3. If the `sender`'s current membership is not `ban` or `join`, allow. 3. If the `sender`'s current membership is not `ban`, `invite`,
or `join`, allow.
4. Otherwise, reject. 4. Otherwise, reject.
8. Otherwise, the membership is unknown. Reject. 8. Otherwise, the membership is unknown. Reject.
5. If the `sender`'s current membership state is not `join`, reject. 5. If the `sender`'s current membership state is not `join`, reject.

View file

@ -1,24 +1,3 @@
---
---
{{% added-in this=true %}} `m.room.member` events now keep `join_authorised_via_users_server`
in addition to other keys in `content` when being redacted.
{{% boxes/rationale %}}
Without the `join_authorised_via_users_server` property, redacted join events
can become invalid when verifying the auth chain of a given event, thus creating
a split-brain scenario where the user is able to speak from one server's
perspective but most others will continually reject their events.
This can theoretically be worked around with a rejoin to the room, being careful
not to use the faulty events as `prev_events`, though instead it is encouraged
to use v9 rooms over v8 rooms to outright avoid the situation.
[Issue #3373](https://github.com/matrix-org/matrix-doc/issues/3373) has further
information.
{{% /boxes/rationale %}}
The full redaction algorithm follows.
Upon receipt of a redaction event, the server must strip off any keys Upon receipt of a redaction event, the server must strip off any keys
not in the following list: not in the following list:
@ -40,11 +19,15 @@ not in the following list:
- `membership` - `membership`
The content object must also be stripped of all keys, unless it is one The content object must also be stripped of all keys, unless it is one
of one of the following event types: of the following event types:
- `m.room.member` allows keys `membership`, `join_authorised_via_users_server`. - [`m.room.member`](/client-server-api#mroommember) allows keys `membership`,
- `m.room.create` allows key `creator`. `join_authorised_via_users_server`.
- `m.room.join_rules` allows keys `join_rule`, `allow`. - [`m.room.create`](/client-server-api#mroomcreate) allows key `creator`.
- `m.room.power_levels` allows keys `ban`, `events`, `events_default`, - [`m.room.join_rules`](/client-server-api#mroomjoin_rules) allows keys `join_rule`,
`kick`, `redact`, `state_default`, `users`, `users_default`. `allow`.
- `m.room.history_visibility` allows key `history_visibility`. - [`m.room.power_levels`](/client-server-api#mroompower_levels) allows keys
`ban`, `events`, `events_default`, `kick`, `redact`, `state_default`, `users`,
`users_default`.
- [`m.room.history_visibility`](/client-server-api#mroomhistory_visibility)
allows key `history_visibility`.

View file

@ -194,7 +194,8 @@ The rules are as follows:
If the `join_rule` is anything other than `knock` or If the `join_rule` is anything other than `knock` or
`knock_restricted`, reject. `knock_restricted`, reject.
2. If `sender` does not match `state_key`, reject. 2. If `sender` does not match `state_key`, reject.
3. If the `sender`'s current membership is not `ban` or `join`, allow. 3. If the `sender`'s current membership is not `ban`, `invite`,
or `join`, allow.
4. Otherwise, reject. 4. Otherwise, reject.
8. Otherwise, the membership is unknown. Reject. 8. Otherwise, the membership is unknown. Reject.
5. If the `sender`'s current membership state is not `join`, reject. 5. If the `sender`'s current membership state is not `join`, reject.

285
content/rooms/v11.md Normal file
View file

@ -0,0 +1,285 @@
---
title: Room Version 11
type: docs
weight: 100
---
This room version builds on [version 10](/rooms/v10) while clarifying redaction
rules.
## Client considerations
### Redactions
{{< added-in this=true >}} The top-level `origin`, `membership`, and `prev_state` properties
are no longer protected from redaction. The [`m.room.create`](/client-server-api#mroomcreate)
event now keeps the entire `content` property. The [`m.room.redaction`](/client-server-api#mroomredaction)
event keeps the `redacts` property under `content`. The
[`m.room.power_levels`](/client-server-api#mroompower_levels) event keeps the
`invite` property under `content`.
The full redaction algorithm follows.
{{% rver-fragment name="v11-redactions" withVersioning="true" %}}
### Event format
Clients should no longer depend on the `creator` property in the `content` of
[`m.room.create`](/client-server-api#mroomcreate) events. In all room versions,
clients can rely on `sender` instead to determine a room creator.
The format of [`m.room.redaction`](/client-server-api#mroomredaction)
events has been modified. Client should look for the `redacts` key under `content`
instead of a top-level event property.
The `third_party_invite` key of [`m.room.member`](/client-server-api#mroommember)
events is no longer redacted, *but* will only contain the `signed` key after redaction.
## Server implementation components
{{% boxes/warning %}}
The information contained in this section is strictly for server
implementors. Applications which use the Client-Server API are generally
unaffected by the intricacies contained here. The section above
regarding client considerations is the resource that Client-Server API
use cases should reference.
{{% /boxes/warning %}}
This room version updates the redaction algorithm and modifies how servers should
create `m.room.create` and `m.room.redaction` events.
Room version 11 is based upon room version 10 with the following considerations.
### Redactions
[See above](#redactions).
### Event format
The core event format is the same as [room version 10](/rooms/v10#event-format).
However, this room version changes some properties of some event types.
{{% rver-fragment name="v11-event-format" %}}
#### Remove the `creator` property of `m.room.create` events
The `content` of a `m.room.create` event no longer has a `creator` property,
which previously was always equivalent to the `sender` of the event.
#### Moving the `redacts` property of `m.room.redaction` events to a `content` property
The `redacts` property of `m.room.redaction` events is moved from a top-level
event property to a property under the event `content`.
For backwards-compatibility with older clients, servers should add a `redacts` property
to the top level of `m.room.redaction` events in when serving such events over the
Client-Server API.
For improved compatibility with newer clients, servers should add a `redacts` property
to the `content` of `m.room.redaction` events in *older* room versions when serving
such events over the Client-Server API.
### Authorization rules
Events must be signed by the server denoted by the `sender` property.
`m.room.redaction` events are not explicitly part of the auth rules.
They are still subject to the minimum power level rules, but should always
fall into "10. Otherwise, allow". Instead of being authorized at the time
of receipt, they are authorized at a later stage: see the
[Redactions](#redactions) section below for more information.
The types of state events that affect authorization are:
- [`m.room.create`](/client-server-api#mroomcreate)
- [`m.room.member`](/client-server-api#mroommember)
- [`m.room.join_rules`](/client-server-api#mroomjoin_rules)
- [`m.room.power_levels`](/client-server-api#mroompower_levels)
- [`m.room.third_party_invite`](/client-server-api#mroomthird_party_invite)
{{% boxes/note %}}
Power levels are inferred from defaults when not explicitly supplied.
For example, mentions of the `sender`'s power level can also refer to
the default power level for users in the room.
{{% /boxes/note %}}
The rules are as follows:
1. {{< changed-in this="true" >}}
If type is `m.room.create`:
1. If it has any `prev_events`, reject.
2. If the domain of the `room_id` does not match the domain of the
`sender`, reject.
3. If `content.room_version` is present and is not a recognised
version, reject.
4. Otherwise, allow.
2. Considering the event's `auth_events`:
1. If there are duplicate entries for a given `type` and `state_key` pair,
reject.
2. If there are entries whose `type` and `state_key` don't match those
specified by the [auth events
selection](/server-server-api#auth-events-selection)
algorithm described in the server specification, reject.
3. If there are entries which were themselves rejected under the [checks
performed on receipt of a
PDU](/server-server-api/#checks-performed-on-receipt-of-a-pdu), reject.
4. If there is no `m.room.create` event among the entries, reject.
3. If the `content` of the `m.room.create` event in the room state has the
property `m.federate` set to `false`, and the `sender` domain of the event
does not match the `sender` domain of the create event, reject.
4. If type is `m.room.member`:
1. If there is no `state_key` property, or no `membership` property in
`content`, reject.
2. If `content` has a `join_authorised_via_users_server`
key:
1. If the event is not validly signed by the homeserver of the user ID denoted
by the key, reject.
3. If `membership` is `join`:
1. {{< changed-in this="true" >}}
If the only previous event is an `m.room.create` and the
`state_key` is the sender, allow.
2. If the `sender` does not match `state_key`, reject.
3. If the `sender` is banned, reject.
4. If the `join_rule` is `invite` or `knock` then allow if
membership state is `invite` or `join`.
5. If the `join_rule` is `restricted` or `knock_restricted`:
1. If membership state is `join` or `invite`, allow.
2. If the `join_authorised_via_users_server` key in `content`
is not a user with sufficient permission to invite other
users, reject.
3. Otherwise, allow.
6. If the `join_rule` is `public`, allow.
7. Otherwise, reject.
4. If `membership` is `invite`:
1. If `content` has a `third_party_invite` property:
1. If *target user* is banned, reject.
2. If `content.third_party_invite` does not have a `signed`
property, reject.
3. If `signed` does not have `mxid` and `token` properties,
reject.
4. If `mxid` does not match `state_key`, reject.
5. If there is no `m.room.third_party_invite` event in the
current room state with `state_key` matching `token`,
reject.
6. If `sender` does not match `sender` of the
`m.room.third_party_invite`, reject.
7. If any signature in `signed` matches any public key in
the `m.room.third_party_invite` event, allow. The public
keys are in `content` of `m.room.third_party_invite` as:
1. A single public key in the `public_key` property.
2. A list of public keys in the `public_keys` property.
8. Otherwise, reject.
2. If the `sender`'s current membership state is not `join`,
reject.
3. If *target user*'s current membership state is `join` or
`ban`, reject.
4. If the `sender`'s power level is greater than or equal to
the *invite level*, allow.
5. Otherwise, reject.
5. If `membership` is `leave`:
1. If the `sender` matches `state_key`, allow if and only if
that user's current membership state is `invite`, `join`,
or `knock`.
2. If the `sender`'s current membership state is not `join`,
reject.
3. If the *target user*'s current membership state is `ban`,
and the `sender`'s power level is less than the *ban level*,
reject.
4. If the `sender`'s power level is greater than or equal to
the *kick level*, and the *target user*'s power level is
less than the `sender`'s power level, allow.
5. Otherwise, reject.
6. If `membership` is `ban`:
1. If the `sender`'s current membership state is not `join`,
reject.
2. If the `sender`'s power level is greater than or equal to
the *ban level*, and the *target user*'s power level is less
than the `sender`'s power level, allow.
3. Otherwise, reject.
7. If `membership` is `knock`:
1. If the `join_rule` is anything other than `knock` or
`knock_restricted`, reject.
2. If `sender` does not match `state_key`, reject.
3. If the `sender`'s current membership is not `ban`, `invite`,
or `join`, allow.
4. Otherwise, reject.
8. Otherwise, the membership is unknown. Reject.
5. If the `sender`'s current membership state is not `join`, reject.
6. If type is `m.room.third_party_invite`:
1. Allow if and only if `sender`'s current power level is greater
than or equal to the *invite level*.
7. If the event type's *required power level* is greater than the
`sender`'s power level, reject.
8. If the event has a `state_key` that starts with an `@` and does not
match the `sender`, reject.
9. If type is `m.room.power_levels`:
1. If any of the properties `users_default`, `events_default`, `state_default`,
`ban`, `redact`, `kick`, or `invite` in `content` are present and
not an integer, reject.
2. If either of the properties `events` or `notifications` in `content`
are present and not an object with values that are integers,
reject.
3. If the `users` property in `content` is not an obiect with keys that
are valid user IDs with values that are integers, reject.
4. If there is no previous `m.room.power_levels` event in the room,
allow.
5. For the properties `users_default`, `events_default`, `state_default`,
`ban`, `redact`, `kick`, `invite` check if they were added,
changed or removed. For each found alteration:
1. If the current value is higher than the `sender`'s current
power level, reject.
2. If the new value is higher than the `sender`'s current power
level, reject.
6. For each entry being changed in, or removed from, the `events` or
`notifications` properties:
1. If the current value is greater than the `sender`'s current
power level, reject.
7. For each entry being added to, or changed in, the `events` or
`notifications` properties:
1. If the new value is greater than the `sender`'s current power
level, reject.
8. For each entry being changed in, or removed from, the `users` property,
other than the `sender`'s own entry:
1. If the current value is greater than or equal to the `sender`'s
current power level, reject.
9. For each entry being added to, or changed in, the `users` property:
1. If the new value is greater than the `sender`'s current power
level, reject.
10. Otherwise, allow.
10. Otherwise, allow.
{{% boxes/note %}}
Some consequences of these rules:
- Unless you are a member of the room, the only permitted operations
(apart from the initial create/join) are: joining a public room;
accepting or rejecting an invitation to a room.
- To unban somebody, you must have power level greater than or equal
to both the kick *and* ban levels, *and* greater than the target
user's power level.
{{% /boxes/note %}}
## Unchanged from v10
The following sections have not been modified since v10, but are included for
completeness.
### Handling redactions
{{% rver-fragment name="v3-handling-redactions" %}}
### Event IDs
{{% rver-fragment name="v4-event-ids" %}}
### State resolution
{{% rver-fragment name="v2-state-res" %}}
### Canonical JSON
{{% rver-fragment name="v6-canonical-json" %}}
### Signing key validity period
{{% rver-fragment name="v5-signing-requirements" %}}

View file

@ -15,7 +15,7 @@ which implement the redaction algorithm locally should refer to the
### Redactions ### Redactions
{{% added-in this=true %}} All significant meaning for `m.room.aliases` {{< added-in this=true >}} All significant meaning for `m.room.aliases`
has been removed from the redaction algorithm. The remaining rules are has been removed from the redaction algorithm. The remaining rules are
the same as past room versions. the same as past room versions.

View file

@ -139,7 +139,8 @@ The rules are as follows:
If `membership` is `knock`: If `membership` is `knock`:
1. If the `join_rule` is anything other than `knock`, reject. 1. If the `join_rule` is anything other than `knock`, reject.
2. If `sender` does not match `state_key`, reject. 2. If `sender` does not match `state_key`, reject.
3. If the `sender`'s current membership is not `ban` or `join`, allow. 3. If the `sender`'s current membership is not `ban`, `invite`,
or `join`, allow.
4. Otherwise, reject. 4. Otherwise, reject.
7. Otherwise, the membership is unknown. Reject. 7. Otherwise, the membership is unknown. Reject.
5. If the `sender`'s current membership state is not `join`, reject. 5. If the `sender`'s current membership state is not `join`, reject.

View file

@ -17,6 +17,27 @@ Clients which implement the redaction algorithm locally should refer to the
### Redactions ### Redactions
{{< added-in this=true >}} [`m.room.member`](/client-server-api#mroommember) events
now keep `join_authorised_via_users_server` in addition to other keys in `content`
when being redacted.
{{% boxes/rationale %}}
Without the `join_authorised_via_users_server` property, redacted join events
can become invalid when verifying the auth chain of a given event, thus creating
a split-brain scenario where the user is able to speak from one server's
perspective but most others will continually reject their events.
This can theoretically be worked around with a rejoin to the room, being careful
not to use the faulty events as `prev_events`, though instead it is encouraged
to use v9 rooms over v8 rooms to outright avoid the situation.
[Issue #3373](https://github.com/matrix-org/matrix-doc/issues/3373) has further
information.
{{% /boxes/rationale %}}
The full redaction algorithm follows.
{{% rver-fragment name="v9-redactions" withVersioning="true" %}} {{% rver-fragment name="v9-redactions" withVersioning="true" %}}
## Server implementation components ## Server implementation components

View file

@ -135,43 +135,59 @@ to send. The process overall is as follows:
to step 4. If the response is valid, the `m.server` property is to step 4. If the response is valid, the `m.server` property is
parsed as `<delegated_hostname>[:<delegated_port>]` and processed as parsed as `<delegated_hostname>[:<delegated_port>]` and processed as
follows: follows:
- If `<delegated_hostname>` is an IP literal, then that IP address 1. If `<delegated_hostname>` is an IP literal, then that IP address
should be used together with the `<delegated_port>` or 8448 if should be used together with the `<delegated_port>` or 8448 if
no port is provided. The target server must present a valid TLS no port is provided. The target server must present a valid TLS
certificate for the IP address. Requests must be made with a certificate for the IP address. Requests must be made with a
`Host` header containing the IP address, including the port if `Host` header containing the IP address, including the port if
one was provided. one was provided.
- If `<delegated_hostname>` is not an IP literal, and 2. If `<delegated_hostname>` is not an IP literal, and
`<delegated_port>` is present, an IP address is discovered by `<delegated_port>` is present, an IP address is discovered by
looking up CNAME, AAAA or A records for `<delegated_hostname>`. The looking up CNAME, AAAA or A records for `<delegated_hostname>`. The
resulting IP address is used, alongside the `<delegated_port>`. resulting IP address is used, alongside the `<delegated_port>`.
Requests must be made with a `Host` header of Requests must be made with a `Host` header of
`<delegated_hostname>:<delegated_port>`. The target server must `<delegated_hostname>:<delegated_port>`. The target server must
present a valid certificate for `<delegated_hostname>`. present a valid certificate for `<delegated_hostname>`.
- If `<delegated_hostname>` is not an IP literal and no 3. {{< added-in v="1.8" >}} If `<delegated_hostname>` is not an IP literal and no
`<delegated_port>` is present, an SRV record is looked up for `<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, no
`<delegated_port>` is present, and a `_matrix-fed._tcp.<delegated_hostname>`
SRV record was not found, an SRV record is looked up for
`_matrix._tcp.<delegated_hostname>`. This may result in another `_matrix._tcp.<delegated_hostname>`. This may result in another
hostname (to be resolved using AAAA or A records) and port. hostname (to be resolved using AAAA or A records) and port.
Requests should be made to the resolved IP address and port with Requests should be made to the resolved IP address and port with
a `Host` header containing the `<delegated_hostname>`. The a `Host` header containing the `<delegated_hostname>`. The
target server must present a valid certificate for target server must present a valid certificate for
`<delegated_hostname>`. `<delegated_hostname>`.
- If no SRV record is found, an IP address is resolved using CNAME, AAAA 5. 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 or A records. Requests are then made to the resolve IP address
and a port of 8448, using a `Host` header of and a port of 8448, using a `Host` header of
`<delegated_hostname>`. The target server must present a valid `<delegated_hostname>`. The target server must present a valid
certificate for `<delegated_hostname>`. certificate for `<delegated_hostname>`.
4. If the `/.well-known` request resulted in an error response, a 4. {{< added-in v="1.8" >}} If the `/.well-known` request resulted in an error response, a server is
server is found by resolving an SRV record for found by resolving an SRV record for `_matrix-fed._tcp.<hostname>`. This may
`_matrix._tcp.<hostname>`. This may result in a hostname (to be result in a hostname (to be resolved using AAAA or A records) and
resolved using AAAA or A records) and port. Requests are made to the port. Requests are made to the resolved IP address and port, with a `Host`
resolved IP address and port, using 8448 as a default port, with a header of `<hostname>`. The target server must present a valid certificate
`Host` header of `<hostname>`. The target server must present a for `<hostname>`.
valid certificate for `<hostname>`.
5. If the `/.well-known` request returned an error response, and the 5. **[Deprecated]** If the `/.well-known` request resulted in an error response,
SRV record was not found, an IP address is resolved using CNAME, AAAA and A and a `_matrix-fed._tcp.<hostname>` SRV record was not found, 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. If the `/.well-known` request returned an error response, and
no SRV records were found, an IP address is resolved using CNAME, AAAA and A
records. Requests are made to the resolved IP address using port records. Requests are made to the resolved IP address using port
8448 and a `Host` header containing the `<hostname>`. The target 8448 and a `Host` header containing the `<hostname>`. The target
server must present a valid certificate for `<hostname>`. server must present a valid certificate for `<hostname>`.
@ -192,6 +208,14 @@ mandated by [RFC2782](https://www.rfc-editor.org/rfc/rfc2782.html):
> the name MUST NOT be an alias (in the sense of RFC 1034 or RFC 2181) > the name MUST NOT be an alias (in the sense of RFC 1034 or RFC 2181)
{{% /boxes/note %}} {{% /boxes/note %}}
{{% boxes/note %}}
Steps 3.4 and 5 are deprecated because they use a service name not registered by IANA.
They may be removed in a future version of the specification. Server admins are encouraged
to use `.well-known` over any form of SRV records.
The IANA registration for port 8448 and `matrix-fed` can be found [here](https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=matrix-fed).
{{% /boxes/note %}}
{{% http-api spec="server-server" api="wellknown" %}} {{% http-api spec="server-server" api="wellknown" %}}
### Server implementation ### Server implementation
@ -266,7 +290,7 @@ Step 1 sign JSON:
``` ```
{ {
"method": "GET", "method": "POST",
"uri": "/target", "uri": "/target",
"origin": "origin.hs.example.com", "origin": "origin.hs.example.com",
"destination": "destination.hs.example.com", "destination": "destination.hs.example.com",
@ -287,7 +311,7 @@ condition applies throughout the request signing process.
Step 2 add Authorization header: Step 2 add Authorization header:
GET /target HTTP/1.1 POST /target HTTP/1.1
Authorization: X-Matrix origin="origin.hs.example.com",destination="destination.hs.example.com",key="ed25519:key1",sig="ABCDEF..." Authorization: X-Matrix origin="origin.hs.example.com",destination="destination.hs.example.com",key="ed25519:key1",sig="ABCDEF..."
Content-Type: application/json Content-Type: application/json

View file

@ -50,17 +50,17 @@
"Flower": "زَهرَة", "Flower": "زَهرَة",
"Butterfly": "فَرَاشَة", "Butterfly": "فَرَاشَة",
"Octopus": "أُخطُبُوط", "Octopus": "أُخطُبُوط",
"Fish": "سَمَكَة", "Fish": "سَمَكة",
"Turtle": "سُلحفاة", "Turtle": "سُلحفاة",
"Penguin": ِطريق", "Penguin": طريق",
"Rooster": "دِيك", "Rooster": "دِيك",
"Panda": "باندَا", "Panda": "باندَا",
"Rabbit": "أَرنَب", "Rabbit": "أَرنَب",
"Elephant": "فِيل", "Elephant": "فِيل",
"Pig": "خِنزِير", "Pig": "خِنزِير",
"Unicorn": ِصَانٌ بِقَرن", "Unicorn": صان وحيد القرن",
"Horse": "حِصَان", "Horse": "حِصَان",
"Lion": "أَسَد", "Lion": "أَسَد",
"Cat": "هِرَّة", "Cat": "هِرَّة",
"Dog": َلب" "Dog": لب"
} }

View file

@ -15,7 +15,7 @@
"Flag": "Vlajka", "Flag": "Vlajka",
"Telephone": "Telefon", "Telephone": "Telefon",
"Hammer": "Kladivo", "Hammer": "Kladivo",
"Key": "Klíč", "Key": "Klíč ke dveřím",
"Lock": "Zámek", "Lock": "Zámek",
"Scissors": "Nůžky", "Scissors": "Nůžky",
"Paperclip": "Sponka", "Paperclip": "Sponka",

View file

@ -11,7 +11,7 @@
"Pencil": "Lápiz", "Pencil": "Lápiz",
"Key": "Llave", "Key": "Llave",
"Hammer": "Martillo", "Hammer": "Martillo",
"Telephone": "Telefono", "Telephone": "Teléfono",
"Train": "Tren", "Train": "Tren",
"Bicycle": "Bicicleta", "Bicycle": "Bicicleta",
"Ball": "Bola", "Ball": "Bola",

View file

@ -0,0 +1,66 @@
{
"Pin": "سنجاق",
"Folder": "پوشه",
"Headphones": "هدفون",
"Anchor": "لنگر",
"Bell": "زنگ",
"Trumpet": "شیپور",
"Guitar": "گیتار",
"Ball": "توپ",
"Trophy": "جام",
"Rocket": "موشک",
"Aeroplane": "هواپیما",
"Bicycle": "دوچرخه",
"Train": "قطار",
"Flag": "پرچم",
"Telephone": "تلفن",
"Hammer": "چکش",
"Key": "کلید",
"Lock": "قفل",
"Scissors": "قیچی",
"Paperclip": "گیره کاغذ",
"Pencil": "مداد",
"Book": "کتاب",
"Light Bulb": "لامپ",
"Gift": "هدیه",
"Clock": "ساعت",
"Hourglass": "ساعت شنی",
"Umbrella": "چتر",
"Thumbs Up": "لایک",
"Santa": "بابا نوئل",
"Spanner": "آچار",
"Glasses": "عینک",
"Hat": "کلاه",
"Robot": "ربات",
"Smiley": "خنده",
"Heart": "قلب",
"Cake": "کیک",
"Pizza": "پیتزا",
"Corn": "ذرت",
"Strawberry": "توت فرنگی",
"Apple": "سیب",
"Banana": "موز",
"Fire": "آتش",
"Cloud": "ابر",
"Moon": "ماه",
"Globe": "زمین",
"Mushroom": "قارچ",
"Cactus": "کاکتوس",
"Tree": "درخت",
"Flower": "گل",
"Butterfly": "پروانه",
"Octopus": "اختاپوس",
"Fish": "ماهی",
"Turtle": "لاک‌پشت",
"Penguin": "پنگوئن",
"Rooster": "خروس",
"Panda": "پاندا",
"Rabbit": "خرگوش",
"Elephant": "فیل",
"Pig": "خوک",
"Unicorn": "تک شاخ",
"Horse": "اسب",
"Lion": "شیر",
"Cat": "گربه",
"Dog": "سگ"
}

View file

@ -9,14 +9,14 @@
"Moon": "月", "Moon": "月",
"Apple": "リンゴ", "Apple": "リンゴ",
"Cake": "ケーキ", "Cake": "ケーキ",
"Robot": "ロボ", "Robot": "ロボット",
"Glasses": "めがね", "Glasses": "めがね",
"Book": "本", "Book": "本",
"Telephone": "電話機", "Telephone": "電話機",
"Train": "電車", "Train": "電車",
"Bicycle": "自転車", "Bicycle": "自転車",
"Pin": "ピン", "Pin": "ピン",
"Folder": "フォルダ", "Folder": "フォルダ",
"Headphones": "ヘッドホン", "Headphones": "ヘッドホン",
"Anchor": "いかり", "Anchor": "いかり",
"Bell": "ベル", "Bell": "ベル",

View file

@ -0,0 +1,66 @@
{
"Thumbs Up": "Polegar para cima",
"Pin": "Pionés",
"Folder": "Pasta",
"Headphones": "Fones",
"Anchor": "Âncora",
"Bell": "Sino",
"Trumpet": "Trompete",
"Guitar": "Guitarra",
"Ball": "Bola",
"Trophy": "Troféu",
"Rocket": "Foguetão",
"Aeroplane": "Avião",
"Bicycle": "Bicicleta",
"Train": "Comboio",
"Flag": "Bandeira",
"Telephone": "Telefone",
"Hammer": "Martelo",
"Key": "Chave",
"Lock": "Cadeado",
"Scissors": "Tesoura",
"Paperclip": "Clipe",
"Pencil": "Lápis",
"Book": "Livro",
"Light Bulb": "Lâmpada",
"Gift": "Presente",
"Clock": "Relógio",
"Hourglass": "Ampulheta",
"Umbrella": "Guarda-chuva",
"Santa": "Pai Natal",
"Spanner": "Chave inglesa",
"Glasses": "Óculos",
"Hat": "Chapéu",
"Robot": "Robô",
"Smiley": "Sorriso",
"Heart": "Coração",
"Cake": "Bolo",
"Pizza": "Piza",
"Corn": "Milho",
"Strawberry": "Morango",
"Apple": "Maçã",
"Banana": "Banana",
"Fire": "Fogo",
"Cloud": "Nuvem",
"Moon": "Lua",
"Globe": "Globo",
"Mushroom": "Cogumelo",
"Cactus": "Cato",
"Tree": "Árvore",
"Flower": "Flor",
"Butterfly": "Borboleta",
"Octopus": "Polvo",
"Fish": "Peixe",
"Turtle": "Tartaruga",
"Penguin": "Pinguim",
"Rooster": "Galo",
"Panda": "Panda",
"Rabbit": "Coelho",
"Elephant": "Elefante",
"Pig": "Porco",
"Unicorn": "Unicórnio",
"Horse": "Cavalo",
"Lion": "Leão",
"Cat": "Gato",
"Dog": "Cão"
}

View file

@ -1,64 +1,64 @@
{ {
"Dog": "Hlava psa", "Dog": "Pes",
"Cat": "Hlava mačky", "Cat": "Mačka",
"Lion": "Hlava leva", "Lion": "Lev",
"Horse": "Kôň", "Horse": "Kôň",
"Unicorn": "Hlava jednorožca", "Unicorn": "Jednorožec",
"Pig": "Hlava prasaťa", "Pig": "Prasa",
"Elephant": "Slon", "Elephant": "Slon",
"Rabbit": "Hlava zajaca", "Rabbit": "Zajac",
"Panda": "Hlava pandy", "Panda": "Panda",
"Rooster": "Kohút", "Rooster": "Kohút",
"Penguin": "Tučniak", "Penguin": "Tučniak",
"Turtle": "Korytnačka", "Turtle": "Korytnačka",
"Fish": "Ryba", "Fish": "Ryba",
"Octopus": "Chobotnica", "Octopus": "Chobotnica",
"Butterfly": "Motýľ", "Butterfly": "Motýľ",
"Flower": "Tulipán", "Flower": "Kvet",
"Tree": "Listnatý strom", "Tree": "Strom",
"Cactus": "Kaktus", "Cactus": "Kaktus",
"Mushroom": "Huba", "Mushroom": "Huba",
"Globe": "Zemeguľa", "Globe": "Zemeguľa",
"Moon": "Polmesiac", "Moon": "Mesiac",
"Cloud": "Oblak", "Cloud": "Oblak",
"Fire": "Oheň", "Fire": "Oheň",
"Banana": "Banán", "Banana": "Banán",
"Apple": "Červené jablko", "Apple": "Jablko",
"Strawberry": "Jahoda", "Strawberry": "Jahoda",
"Corn": "Kukuričný klas", "Corn": "Kukurica",
"Pizza": "Pizza", "Pizza": "Pizza",
"Cake": "Narodeninová torta", "Cake": "Torta",
"Heart": "červené srdce", "Heart": "Srdce",
"Smiley": "Škeriaca sa tvár", "Smiley": "Smajlík",
"Robot": "Robot", "Robot": "Robot",
"Hat": "Cilinder", "Hat": "Klobúk",
"Glasses": "Okuliare", "Glasses": "Okuliare",
"Spanner": "Francúzsky kľúč", "Spanner": "Vidlicový kľúč",
"Santa": "Santa Claus", "Santa": "Mikuláš",
"Thumbs Up": "Palec nahor", "Thumbs Up": "Palec nahor",
"Umbrella": "Dáždnik", "Umbrella": "Dáždnik",
"Hourglass": "Presýpacie hodiny", "Hourglass": "Presýpacie hodiny",
"Clock": "Budík", "Clock": "Budík",
"Gift": "Zabalený darček", "Gift": "Darček",
"Light Bulb": "Žiarovka", "Light Bulb": "Žiarovka",
"Book": "Zatvorená kniha", "Book": "Kniha",
"Pencil": "Ceruzka", "Pencil": "Ceruzka",
"Paperclip": "Sponka na papier", "Paperclip": "Kancelárska sponka",
"Scissors": "Nožnice", "Scissors": "Nožnice",
"Lock": "Zatvorená zámka", "Lock": "Zámka",
"Key": "Kľúč", "Key": "Kľúč",
"Hammer": "Kladivo", "Hammer": "Kladivo",
"Telephone": "Telefón", "Telephone": "Telefón",
"Flag": "Kockovaná zástava", "Flag": "Zástava",
"Train": "Rušeň", "Train": "Vlak",
"Bicycle": "Bicykel", "Bicycle": "Bicykel",
"Aeroplane": "Lietadlo", "Aeroplane": "Lietadlo",
"Rocket": "Raketa", "Rocket": "Raketa",
"Trophy": "Trofej", "Trophy": "Trofej",
"Ball": "Futbal", "Ball": "Lopta",
"Guitar": "Gitara", "Guitar": "Gitara",
"Trumpet": "Trúbka", "Trumpet": "Trúbka",
"Bell": "Zvon", "Bell": "Zvonec",
"Anchor": "Kotva", "Anchor": "Kotva",
"Headphones": "Slúchadlá", "Headphones": "Slúchadlá",
"Folder": "Fascikel", "Folder": "Fascikel",

View file

@ -17,20 +17,20 @@
"Hammer": "Búa", "Hammer": "Búa",
"Key": "Chìa khóa", "Key": "Chìa khóa",
"Lock": "Ổ khóa", "Lock": "Ổ khóa",
"Scissors": "Cây kéo", "Scissors": "Cái kéo",
"Paperclip": "Kẹp giấy", "Paperclip": "Kẹp giấy",
"Pencil": "Viết chì", "Pencil": "Viết chì",
"Book": "Sách", "Book": "Sách",
"Light Bulb": "Bóng đèn tròn", "Light Bulb": "Bóng đèn tròn",
"Gift": "Quà", "Gift": "Quà tặng",
"Clock": "Đồng hồ", "Clock": "Đồng hồ",
"Hourglass": "Đồng hồ cát", "Hourglass": "Đồng hồ cát",
"Umbrella": "Cây dù", "Umbrella": "Cái ô",
"Thumbs Up": "Thích", "Thumbs Up": "Thích",
"Santa": "ông già Noel", "Santa": "ông già Nô-en",
"Spanner": "Cờ-lê", "Spanner": "Cờ-lê",
"Glasses": "Mắt kiếng", "Glasses": "Kính mắt",
"Hat": "Nón", "Hat": "",
"Robot": "Rô-bô", "Robot": "Rô-bô",
"Smiley": "Mặt cười", "Smiley": "Mặt cười",
"Heart": "Tim", "Heart": "Tim",

View file

@ -0,0 +1,66 @@
{
"Pin": "圖釘",
"Folder": "資料夾",
"Headphones": "耳機",
"Anchor": "船錨",
"Bell": "鈴鐺",
"Trumpet": "喇叭",
"Guitar": "吉他",
"Ball": "足球",
"Trophy": "獎盃",
"Rocket": "火箭",
"Aeroplane": "飛機",
"Bicycle": "腳踏車",
"Train": "火車",
"Flag": "旗幟",
"Telephone": "電話",
"Hammer": "鎚子",
"Key": "鑰匙",
"Lock": "鎖頭",
"Scissors": "剪刀",
"Paperclip": "迴紋針",
"Pencil": "鉛筆",
"Book": "書",
"Light Bulb": "燈泡",
"Gift": "禮物",
"Clock": "時鐘",
"Hourglass": "沙漏",
"Umbrella": "雨傘",
"Thumbs Up": "讚",
"Santa": "聖誕老人",
"Spanner": "扳手",
"Glasses": "眼鏡",
"Hat": "帽子",
"Robot": "機器人",
"Smiley": "笑臉",
"Heart": "愛心",
"Cake": "蛋糕",
"Pizza": "披薩",
"Corn": "玉米",
"Strawberry": "草莓",
"Apple": "蘋果",
"Banana": "香蕉",
"Fire": "火",
"Cloud": "雲朵",
"Moon": "月亮",
"Globe": "地球",
"Mushroom": "蘑菇",
"Cactus": "仙人掌",
"Tree": "樹",
"Flower": "花",
"Butterfly": "蝴蝶",
"Octopus": "章魚",
"Fish": "魚",
"Turtle": "烏龜",
"Penguin": "企鵝",
"Rooster": "公雞",
"Panda": "熊貓",
"Rabbit": "兔子",
"Elephant": "大象",
"Pig": "豬",
"Unicorn": "獨角獸",
"Horse": "馬",
"Lion": "獅子",
"Cat": "貓",
"Dog": "狗"
}

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more