diff --git a/.github/ISSUE_TEMPLATE/release.md b/.github/ISSUE_TEMPLATE/release.md index 83701f14..e46834b9 100644 --- a/.github/ISSUE_TEMPLATE/release.md +++ b/.github/ISSUE_TEMPLATE/release.md @@ -16,6 +16,7 @@ Previous release: 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 * [ ] Check for release blockers that may have been missed * [ ] Review/fix the changelog diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index 083d6831..694962d1 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -10,7 +10,7 @@ jobs: if: github.event_name == 'pull_request' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 0 - run: scripts/check-newsfragments diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d836b100..5fa57a4f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,18 +18,37 @@ jobs: runs-on: ubuntu-latest steps: - name: "📥 Source checkout" - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: "➕ Setup Node" - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: - node-version: '14' + node-version: '18' - name: "🔎 Run validator" run: | npx @redocly/cli@latest lint data/api/*/*.yaml - check-examples: + check-event-examples: name: "🔎 Check Event schema examples" 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: - name: "📥 Source checkout" uses: actions/checkout@v2 @@ -44,8 +63,27 @@ jobs: pip install -r scripts/requirements.txt - name: "🔎 Run validator" 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: name: "⚙️ Calculate baseURL for later jobs" runs-on: ubuntu-latest @@ -74,7 +112,7 @@ jobs: needs: [calculate-baseurl] steps: - name: "📥 Source checkout" - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: "➕ Setup Python" uses: actions/setup-python@v4 with: @@ -92,24 +130,29 @@ jobs: export RELEASE="unstable" fi # 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 }}" \ --api application-service \ -r "$RELEASE" \ -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 }}" \ --api client-server \ -r "$RELEASE" \ -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 }}" \ --api push-gateway \ -r "$RELEASE" \ -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 - name: "📤 Artifact upload" - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: openapi-artifact path: openapi.tar.gz @@ -121,7 +164,7 @@ jobs: runs-on: ubuntu-latest steps: - name: "📥 Source checkout" - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: "➕ Setup Python" uses: actions/setup-python@v4 - name: "➕ Install towncrier" @@ -129,7 +172,7 @@ jobs: - name: "Generate changelog" run: ./scripts/generate-changelog.sh vUNSTABLE - name: "📤 Artifact upload" - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: changelog-artifact path: content/changelog/vUNSTABLE.md @@ -142,16 +185,16 @@ jobs: if: ${{ always() }} steps: - name: "➕ Setup Node" - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: - node-version: '14' + node-version: '18' - name: "➕ Setup Hugo" - uses: peaceiris/actions-hugo@c03b5dbed22245418539b65eb9a3b1d5fdd9a0a6 + uses: peaceiris/actions-hugo@16361eb4acea8698b220b76c0d4e84e1fd22c61d with: hugo-version: '0.113.0' extended: true - name: "📥 Source checkout" - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: "⚙️ npm" run: | npm i @@ -169,7 +212,7 @@ jobs: # https://spec.matrix.org/latest/client-server-api/api.json # Works for /unstable/ and /v1.1/ as well. - name: "📥 Spec definition download" - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: openapi-artifact - name: "📝 Unpack the OpenAPI definitions in the right location" @@ -179,7 +222,7 @@ jobs: - name: "📦 Tarball creation" run: tar -czf spec.tar.gz spec - name: "📤 Artifact upload" - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: spec-artifact path: spec.tar.gz @@ -190,10 +233,10 @@ jobs: needs: [calculate-baseurl, build-spec] steps: - name: "📥 Source checkout" - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: "📥 Fetch built spec" - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: spec-artifact @@ -219,16 +262,16 @@ jobs: if: ${{ startsWith(github.ref, 'refs/tags/') }} steps: - name: "➕ Setup Node" - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: - node-version: '14' + node-version: '18' - name: "➕ Setup Hugo" - uses: peaceiris/actions-hugo@c03b5dbed22245418539b65eb9a3b1d5fdd9a0a6 + uses: peaceiris/actions-hugo@16361eb4acea8698b220b76c0d4e84e1fd22c61d with: hugo-version: '0.93.3' extended: true - name: "📥 Source checkout" - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: "⚙️ npm" run: | npm i @@ -240,7 +283,7 @@ jobs: hugo --config config.toml,historical.toml --baseURL "/${GITHUB_REF/refs\/tags\//}" -d "spec" - name: "📥 Spec definition download" - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: openapi-artifact - name: "📝 Unpack the OpenAPI definitions in the right location" @@ -250,7 +293,7 @@ jobs: - name: "📦 Tarball creation" run: tar -czf spec-historical.tar.gz spec - name: "📤 Artifact upload" - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: spec-historical-artifact path: spec-historical.tar.gz diff --git a/.github/workflows/netlify.yaml b/.github/workflows/netlify.yaml index 83b6bec5..fb2d05c9 100644 --- a/.github/workflows/netlify.yaml +++ b/.github/workflows/netlify.yaml @@ -35,7 +35,7 @@ jobs: echo "::set-output name=prnumber::$pr_number" - name: '📥 Download artifact' - uses: dawidd6/action-download-artifact@af92a8455a59214b7b932932f2662fdefbd78126 # v2.15.0 + uses: dawidd6/action-download-artifact@268677152d06ba59fcec7a7f0b5d961b6ccd7e1e # v2.28.0 with: workflow: main.yaml run_id: ${{ github.event.workflow_run.id }} @@ -46,8 +46,8 @@ jobs: - name: "📤 Deploy to Netlify" id: netlify - # v1.2.2 - uses: nwtgck/actions-netlify@f517512ae75beec8896aa7b027c1c72f01816200 + # v2.1.0 + uses: nwtgck/actions-netlify@7a92f00dde8c92a5a9e8385ec2919775f7647352 with: publish-dir: spec deploy-message: "Deploy from GitHub Actions" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000..05e5be7a --- /dev/null +++ b/.github/workflows/release.yaml @@ -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 diff --git a/.github/workflows/spell-check.yaml b/.github/workflows/spell-check.yaml index d0b4a40e..b4a9060e 100644 --- a/.github/workflows/spell-check.yaml +++ b/.github/workflows/spell-check.yaml @@ -11,9 +11,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Actions Repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Check spelling of proposals - uses: crate-ci/typos@9be36f97fdbe645ee9a12449fb13aca856c2516a + uses: crate-ci/typos@ff3f309513469397e1094520fb7a054e057589e1 with: config: ${{github.workspace}}/.github/_typos.toml \ No newline at end of file diff --git a/.gitignore b/.gitignore index c1a34c50..09afe2d8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ node_modules /data/msc /env* /resources -/scripts/swagger +/scripts/openapi /scripts/tmp /hugo-config.toml /public diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 5e606ab2..00000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "themes/docsy"] - path = themes/docsy - url = https://github.com/matrix-org/docsy.git - branch = master diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 46c6c560..93763a29 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -72,7 +72,7 @@ ask. 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. The changelog is managed by `Towncrier `_ in the diff --git a/README.md b/README.md index 1482fcdd..8b40c0f5 100644 --- a/README.md +++ b/README.md @@ -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 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 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. * `/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. +* `/packages`: Various packages for shipping spec files like OpenAPI bindings and data definitions. ## 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: . Note that at least Hugo - v0.93.0 is required. + v0.110.0 is required. Alternatively, use the Docker image at https://hub.docker.com/r/klakegg/hugo/. (The "extended edition" is required to process the SCSS.) -2. Run `npm i` to install the dependencies and fetch the docsy git submodule. - Note that this will require NodeJS to be installed. +2. Run `npm i` to install the dependencies. 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" page and is not required. 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"` 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` -and finally `python ./scripts/dump-swagger.py` to generate it to `./scripts/swagger/api-docs.json`. To make use of the generated file, +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-openapi.py` to generate it to `./scripts/openapi/api-docs.json`. To make use of the generated file, 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 run a local HTTP server by running `./scripts/swagger-http-server.py`, and then view the documentation by - opening `./scripts/swagger-preview.html` in your browser. +* 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/openapi-http-server.py`, and then view the documentation by + opening `./scripts/openapi-preview.html` in your browser. ## Issue tracking diff --git a/assets/scss/custom.scss b/assets/scss/_styles_project.scss similarity index 86% rename from assets/scss/custom.scss rename to assets/scss/_styles_project.scss index 047e57d7..b275db4f 100644 --- a/assets/scss/custom.scss +++ b/assets/scss/_styles_project.scss @@ -18,9 +18,6 @@ limitations under the License. Custom SCSS for the Matrix spec */ -@import "variables_project"; -@import "variables"; - /* Import the CSS classes for the syntax highlighter. * * This is generated with: @@ -49,6 +46,10 @@ Custom SCSS for the Matrix spec } + .nav-link { + font-weight: normal; + } + a { color: $black; } @@ -292,7 +293,7 @@ footer { } /* 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; padding: 0.85rem; margin: 0.85rem 0; @@ -346,23 +347,41 @@ footer { } p code, table code { - background-color: inherit; + background-color: transparent; } table { - /* Docsy makes all tables "responsive tables", which causes Bootstrap 4 to create - * tables with a "display" property of "block". - * - * However, for "table-layout: fixed" to be effective, an element must have a - * "display" property of "table". - * - * Thus, we override the "display" property here. This may no longer be necessary once - * 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%; + @media (max-width: 800px) { + /* Docsy by default applies `overflow-x: auto;` to tables, which + * results in annoying horizontal scrolling on mobile, so we instead + * switch to a fixed table layout on a narrow browser width. + * (On a wider width the default auto table-layout provides better readability.) + * + * Docsy makes all tables "responsive tables", which causes Bootstrap 4 to create + * tables with a "display" property of "block". + * However, for "table-layout: fixed" to be effective, an element must have a + * "display" property of "table". + * + * Thus, we override the "display" property here. This may no longer be necessary once + * 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 & + table { @@ -378,6 +397,7 @@ footer { th, td, caption { padding: 1rem; + border-top: 1px $table-border-color solid; } &.object-table, &.response-table, &.content-type-table { @@ -390,14 +410,12 @@ footer { // ... but avoid double border between caption and table border-bottom: 0; + + background-color: $secondary-lighter-background; } - caption, tbody tr { - background-color: $table-row-default; - } - - tbody tr:nth-child(even) { - background-color: $table-row-alternate; + tbody tr { + --bs-table-striped-bg: #{$secondary-lighter-background}; } } @@ -409,19 +427,6 @@ footer { &.basic-info th { width: 15rem; } - - .col-name, .col-type, .col-status { - width: 25%; - } - - .col-description { - width: 50%; - } - - .col-status-description { - width: 75%; - } - } pre { @@ -512,3 +517,15 @@ dd { 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; + } +} \ No newline at end of file diff --git a/assets/scss/_variables_project.scss b/assets/scss/_variables_project.scss index 8ff5fe98..6eec3e7c 100644 --- a/assets/scss/_variables_project.scss +++ b/assets/scss/_variables_project.scss @@ -20,7 +20,7 @@ $dark: #333; $gray-100: #FBFBFB; $secondary-background: #E5F5FB; -$secondary-lighter-background: #F4FaFC; +$secondary-lighter-background: #F4FAFC; $secondary-lightest-background: #FBFDFD; @@ -33,8 +33,7 @@ $warning-background: #FFE0E0; // colours for definition tables. // the border colour matches that used for "highlight" divs $table-border-color: rgba(black, .125); -$table-row-alternate: $secondary-lightest-background; -$table-row-default: $secondary-lighter-background; +$table-bg: $secondary-lightest-background; /* Configure docsy to use the default system fonts instead of Google Fonts. * See https://www.docsy.dev/docs/adding-content/lookandfeel/#fonts */ diff --git a/changelogs/appendices/newsfragments/1573.clarification b/changelogs/appendices/newsfragments/1573.clarification deleted file mode 100644 index 7210ae76..00000000 --- a/changelogs/appendices/newsfragments/1573.clarification +++ /dev/null @@ -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 diff --git a/changelogs/appendices/newsfragments/1583.feature b/changelogs/appendices/newsfragments/1583.feature deleted file mode 100644 index b24077c6..00000000 --- a/changelogs/appendices/newsfragments/1583.feature +++ /dev/null @@ -1 +0,0 @@ -Allow `+` in Matrix IDs, per [MSC4009](https://github.com/matrix-org/matrix-spec-proposals/pull/4009). diff --git a/changelogs/application_service/newsfragments/1584.clarification b/changelogs/application_service/newsfragments/1584.clarification deleted file mode 100644 index 098c1260..00000000 --- a/changelogs/application_service/newsfragments/1584.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix JSON schema of custom fields in query. diff --git a/changelogs/client_server/newsfragments/1552.clarification b/changelogs/client_server/newsfragments/1552.clarification deleted file mode 100644 index 3f8cdbfb..00000000 --- a/changelogs/client_server/newsfragments/1552.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix missing `type` property in the JSON schema definition of the `m.reaction` event. Contributed by @chebureki. diff --git a/changelogs/client_server/newsfragments/1563.clarification b/changelogs/client_server/newsfragments/1563.clarification deleted file mode 100644 index 1d6ef324..00000000 --- a/changelogs/client_server/newsfragments/1563.clarification +++ /dev/null @@ -1 +0,0 @@ -Make sure examples types match schema in definitions. diff --git a/changelogs/client_server/newsfragments/1564.clarification b/changelogs/client_server/newsfragments/1564.clarification deleted file mode 100644 index 59fcf699..00000000 --- a/changelogs/client_server/newsfragments/1564.clarification +++ /dev/null @@ -1 +0,0 @@ -Allow `null` in `room_types` in `POST /publicRooms` endpoints schemas. diff --git a/changelogs/client_server/newsfragments/1578.clarification b/changelogs/client_server/newsfragments/1578.clarification deleted file mode 100644 index 09e9dc70..00000000 --- a/changelogs/client_server/newsfragments/1578.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix broken header formatting. Contributed by @midnightveil. diff --git a/changelogs/client_server/newsfragments/1579.clarification b/changelogs/client_server/newsfragments/1579.clarification deleted file mode 100644 index d53f2352..00000000 --- a/changelogs/client_server/newsfragments/1579.clarification +++ /dev/null @@ -1 +0,0 @@ -Render binary request and response bodies. diff --git a/changelogs/client_server/newsfragments/1585.clarification b/changelogs/client_server/newsfragments/1585.clarification deleted file mode 100644 index 5b26ae97..00000000 --- a/changelogs/client_server/newsfragments/1585.clarification +++ /dev/null @@ -1 +0,0 @@ -Remove unnecessary `oneOf`s in JSON schemas. diff --git a/changelogs/client_server/newsfragments/1590.clarification b/changelogs/client_server/newsfragments/1590.clarification deleted file mode 100644 index 1642357d..00000000 --- a/changelogs/client_server/newsfragments/1590.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix description of MAC calculation in SAS verification. \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/1593.clarification b/changelogs/client_server/newsfragments/1593.clarification deleted file mode 100644 index 2f6cbee6..00000000 --- a/changelogs/client_server/newsfragments/1593.clarification +++ /dev/null @@ -1 +0,0 @@ -Update link to SAS emoji definition data. diff --git a/changelogs/client_server/newsfragments/1597.clarification b/changelogs/client_server/newsfragments/1597.clarification deleted file mode 100644 index 3ccb2333..00000000 --- a/changelogs/client_server/newsfragments/1597.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix various typos throughout the specification. diff --git a/changelogs/client_server/newsfragments/1629.clarification b/changelogs/client_server/newsfragments/1629.clarification new file mode 100644 index 00000000..81ed5aaa --- /dev/null +++ b/changelogs/client_server/newsfragments/1629.clarification @@ -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. \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/1685.clarification b/changelogs/client_server/newsfragments/1685.clarification new file mode 100644 index 00000000..9daf762e --- /dev/null +++ b/changelogs/client_server/newsfragments/1685.clarification @@ -0,0 +1 @@ +Clarify that read-receipts should be batched by thread as well as room. diff --git a/changelogs/client_server/newsfragments/1687.clarification b/changelogs/client_server/newsfragments/1687.clarification new file mode 100644 index 00000000..09bacd28 --- /dev/null +++ b/changelogs/client_server/newsfragments/1687.clarification @@ -0,0 +1 @@ +Clarify that threads can be created based on replies. diff --git a/changelogs/client_server/newsfragments/1690.clarification b/changelogs/client_server/newsfragments/1690.clarification new file mode 100644 index 00000000..02427e33 --- /dev/null +++ b/changelogs/client_server/newsfragments/1690.clarification @@ -0,0 +1 @@ +Make clearer in the example for reply fallbacks that the prefix sequence should be repeated for each line. \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/1695.clarification b/changelogs/client_server/newsfragments/1695.clarification new file mode 100644 index 00000000..32d9bb51 --- /dev/null +++ b/changelogs/client_server/newsfragments/1695.clarification @@ -0,0 +1 @@ +Clarify the format of account data objects for secret storage. diff --git a/changelogs/client_server/newsfragments/1712.clarification b/changelogs/client_server/newsfragments/1712.clarification new file mode 100644 index 00000000..9e1523c5 --- /dev/null +++ b/changelogs/client_server/newsfragments/1712.clarification @@ -0,0 +1 @@ +Clarify that the key backup MAC is implemented incorrectly and does not pass the ciphertext through HMAC-SHA-256. diff --git a/changelogs/client_server/newsfragments/1715.clarification b/changelogs/client_server/newsfragments/1715.clarification new file mode 100644 index 00000000..a1d30432 --- /dev/null +++ b/changelogs/client_server/newsfragments/1715.clarification @@ -0,0 +1 @@ +Clarify one-time key and fallback key types in examples. diff --git a/changelogs/client_server/newsfragments/1719.clarification b/changelogs/client_server/newsfragments/1719.clarification new file mode 100644 index 00000000..031e1e41 --- /dev/null +++ b/changelogs/client_server/newsfragments/1719.clarification @@ -0,0 +1 @@ +Clarify that the HKDF calculation for SAS uses base64-encoded keys rather than the raw key bytes. diff --git a/changelogs/client_server/newsfragments/1720.clarification b/changelogs/client_server/newsfragments/1720.clarification new file mode 100644 index 00000000..e8c8a623 --- /dev/null +++ b/changelogs/client_server/newsfragments/1720.clarification @@ -0,0 +1 @@ +Clarify how to perform the ECDH exchange in step 12 of the SAS process. diff --git a/changelogs/client_server/newsfragments/1730.feature b/changelogs/client_server/newsfragments/1730.feature new file mode 100644 index 00000000..673f7515 --- /dev/null +++ b/changelogs/client_server/newsfragments/1730.feature @@ -0,0 +1 @@ +Add local erasure requests, as per [MSC4025](https://github.com/matrix-org/matrix-spec-proposals/pull/4025). diff --git a/changelogs/client_server/newsfragments/1731.feature b/changelogs/client_server/newsfragments/1731.feature new file mode 100644 index 00000000..f4561bf3 --- /dev/null +++ b/changelogs/client_server/newsfragments/1731.feature @@ -0,0 +1 @@ +Use the `body` field as media caption, as per [MSC2530](https://github.com/matrix-org/matrix-spec-proposals/pull/2530). \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/1734.clarification b/changelogs/client_server/newsfragments/1734.clarification new file mode 100644 index 00000000..32d9bb51 --- /dev/null +++ b/changelogs/client_server/newsfragments/1734.clarification @@ -0,0 +1 @@ +Clarify the format of account data objects for secret storage. diff --git a/changelogs/identity_service/newsfragments/1563.clarification b/changelogs/identity_service/newsfragments/1563.clarification deleted file mode 100644 index 1d6ef324..00000000 --- a/changelogs/identity_service/newsfragments/1563.clarification +++ /dev/null @@ -1 +0,0 @@ -Make sure examples types match schema in definitions. diff --git a/changelogs/internal/newsfragments/1310.feature b/changelogs/internal/newsfragments/1310.feature deleted file mode 100644 index 9aaa18b6..00000000 --- a/changelogs/internal/newsfragments/1310.feature +++ /dev/null @@ -1 +0,0 @@ -Upgrade Swagger data to OpenAPI 3.1. diff --git a/changelogs/internal/newsfragments/1542.clarification b/changelogs/internal/newsfragments/1542.clarification deleted file mode 100644 index 422a4eef..00000000 --- a/changelogs/internal/newsfragments/1542.clarification +++ /dev/null @@ -1 +0,0 @@ -Update the CI to validate the file extension of changelog entries. \ No newline at end of file diff --git a/changelogs/internal/newsfragments/1549.clarification b/changelogs/internal/newsfragments/1549.clarification deleted file mode 100644 index 67dbd67e..00000000 --- a/changelogs/internal/newsfragments/1549.clarification +++ /dev/null @@ -1 +0,0 @@ -Disclosure sections now only display their title when collapsed. diff --git a/changelogs/internal/newsfragments/1551.clarification b/changelogs/internal/newsfragments/1551.clarification deleted file mode 100644 index b9f32571..00000000 --- a/changelogs/internal/newsfragments/1551.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix the sidebar in recent versions of Hugo diff --git a/changelogs/internal/newsfragments/1556.clarification b/changelogs/internal/newsfragments/1556.clarification deleted file mode 100644 index 05c5897e..00000000 --- a/changelogs/internal/newsfragments/1556.clarification +++ /dev/null @@ -1 +0,0 @@ -Bump jsonschema to validate JSON Schemas against Draft 2020-12. diff --git a/changelogs/internal/newsfragments/1558.clarification b/changelogs/internal/newsfragments/1558.clarification deleted file mode 100644 index 29e1c1d0..00000000 --- a/changelogs/internal/newsfragments/1558.clarification +++ /dev/null @@ -1 +0,0 @@ -Use Redocly CLI to validate OpenAPI definitions. diff --git a/changelogs/internal/newsfragments/1561.clarification b/changelogs/internal/newsfragments/1561.clarification deleted file mode 100644 index 6381ddf3..00000000 --- a/changelogs/internal/newsfragments/1561.clarification +++ /dev/null @@ -1 +0,0 @@ -Use tag name as the OpenAPI definition version. diff --git a/changelogs/internal/newsfragments/1562.clarification b/changelogs/internal/newsfragments/1562.clarification deleted file mode 100644 index 6882cad1..00000000 --- a/changelogs/internal/newsfragments/1562.clarification +++ /dev/null @@ -1 +0,0 @@ -Make sure version in x-changedInMatrixVersion is a string. diff --git a/changelogs/internal/newsfragments/1582.clarification b/changelogs/internal/newsfragments/1582.clarification deleted file mode 100644 index 2f048a06..00000000 --- a/changelogs/internal/newsfragments/1582.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify usage of ABNF for grammar in the documentation style guide. diff --git a/changelogs/internal/newsfragments/1591.clarification b/changelogs/internal/newsfragments/1591.clarification deleted file mode 100644 index 3ee889ff..00000000 --- a/changelogs/internal/newsfragments/1591.clarification +++ /dev/null @@ -1 +0,0 @@ -Update the version of Hugo used to render the spec to v0.113.0. diff --git a/changelogs/internal/newsfragments/1680.clarification b/changelogs/internal/newsfragments/1680.clarification new file mode 100644 index 00000000..16352364 --- /dev/null +++ b/changelogs/internal/newsfragments/1680.clarification @@ -0,0 +1 @@ +Update the spec release process. \ No newline at end of file diff --git a/changelogs/internal/newsfragments/1697.clarification b/changelogs/internal/newsfragments/1697.clarification new file mode 100644 index 00000000..d238b2e9 --- /dev/null +++ b/changelogs/internal/newsfragments/1697.clarification @@ -0,0 +1 @@ +Minor clarifications to the contributing guide. diff --git a/changelogs/internal/newsfragments/1699.clarification b/changelogs/internal/newsfragments/1699.clarification new file mode 100644 index 00000000..7d1c0526 --- /dev/null +++ b/changelogs/internal/newsfragments/1699.clarification @@ -0,0 +1 @@ +Update Docsy to v0.8.0. diff --git a/changelogs/internal/newsfragments/1713.misc b/changelogs/internal/newsfragments/1713.misc new file mode 100644 index 00000000..c1b999bf --- /dev/null +++ b/changelogs/internal/newsfragments/1713.misc @@ -0,0 +1 @@ +Fix npm release script for `@matrix-org/spec`. diff --git a/changelogs/internal/newsfragments/1724.clarification b/changelogs/internal/newsfragments/1724.clarification new file mode 100644 index 00000000..12be0c5a --- /dev/null +++ b/changelogs/internal/newsfragments/1724.clarification @@ -0,0 +1 @@ +Update HTML templates to include links to object schema definitions. diff --git a/changelogs/pyproject.toml b/changelogs/pyproject.toml index d32f6415..d42c96d6 100644 --- a/changelogs/pyproject.toml +++ b/changelogs/pyproject.toml @@ -1,39 +1,66 @@ [tool.towncrier] version = "unused" - filename = "../rendered.md" - issue_format = "[#{issue}](https://github.com/matrix-org/matrix-spec/issues/{issue})" - title_format = "### {name}" # Matches rendered spec, even if awkward - underlines = " " # 3 spaces intentionally to hide RST headings - - # Note: The names below have the tag built-in so the rendered spec *and* the generated - # changelog can benefit from sane headings. + filename = "rendered.md" + template = "template.md.jinja" [[tool.towncrier.type]] directory = "breaking" - name = "Breaking Changes" + name = "Breaking Changes" showcontent = true [[tool.towncrier.type]] directory = "deprecation" - name = "Deprecations" + name = "Deprecations" showcontent = true [[tool.towncrier.type]] directory = "new" - name = "New Endpoints" + name = "New Endpoints" showcontent = true [[tool.towncrier.type]] directory = "removal" - name = "Removed Endpoints" + name = "Removed Endpoints" showcontent = true [[tool.towncrier.type]] directory = "feature" - name = "Backwards Compatible Changes" + name = "Backwards Compatible Changes" showcontent = true [[tool.towncrier.type]] directory = "clarification" - name = "Spec Clarifications" + name = "Spec Clarifications" 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" diff --git a/changelogs/room_versions/newsfragments/1717.clarification b/changelogs/room_versions/newsfragments/1717.clarification new file mode 100644 index 00000000..80bc9d55 --- /dev/null +++ b/changelogs/room_versions/newsfragments/1717.clarification @@ -0,0 +1 @@ +For room versions 7 through 11: Clarify that `invite->knock` is not a legal transition. \ No newline at end of file diff --git a/changelogs/server_server/newsfragments/1521.clarification b/changelogs/server_server/newsfragments/1521.clarification deleted file mode 100644 index 6c1ebf9d..00000000 --- a/changelogs/server_server/newsfragments/1521.clarification +++ /dev/null @@ -1 +0,0 @@ -Document why `/state_ids` can respond with a 404. diff --git a/changelogs/server_server/newsfragments/1559.clarification b/changelogs/server_server/newsfragments/1559.clarification deleted file mode 100644 index 401a94e0..00000000 --- a/changelogs/server_server/newsfragments/1559.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix definition of response of `POST /_matrix/federation/v1/user/keys/claim`. diff --git a/changelogs/server_server/newsfragments/1560.clarification b/changelogs/server_server/newsfragments/1560.clarification deleted file mode 100644 index e717dda4..00000000 --- a/changelogs/server_server/newsfragments/1560.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix level of examples in server keys definition. diff --git a/changelogs/server_server/newsfragments/1563.clarification b/changelogs/server_server/newsfragments/1563.clarification deleted file mode 100644 index 1d6ef324..00000000 --- a/changelogs/server_server/newsfragments/1563.clarification +++ /dev/null @@ -1 +0,0 @@ -Make sure examples types match schema in definitions. diff --git a/changelogs/server_server/newsfragments/1564.clarification b/changelogs/server_server/newsfragments/1564.clarification deleted file mode 100644 index 59fcf699..00000000 --- a/changelogs/server_server/newsfragments/1564.clarification +++ /dev/null @@ -1 +0,0 @@ -Allow `null` in `room_types` in `POST /publicRooms` endpoints schemas. diff --git a/changelogs/server_server/newsfragments/1578.clarification b/changelogs/server_server/newsfragments/1578.clarification deleted file mode 100644 index 09e9dc70..00000000 --- a/changelogs/server_server/newsfragments/1578.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix broken header formatting. Contributed by @midnightveil. diff --git a/changelogs/server_server/newsfragments/1721.clarification b/changelogs/server_server/newsfragments/1721.clarification new file mode 100644 index 00000000..a742501b --- /dev/null +++ b/changelogs/server_server/newsfragments/1721.clarification @@ -0,0 +1 @@ +Clarify Server-Server API request signing example by using the `POST` HTTP method, as `GET` requests don't have request bodies. diff --git a/changelogs/template.md.jinja b/changelogs/template.md.jinja new file mode 100644 index 00000000..38de4b92 --- /dev/null +++ b/changelogs/template.md.jinja @@ -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 %} diff --git a/config.toml b/config.toml index c6f1bd45..15a284b5 100644 --- a/config.toml +++ b/config.toml @@ -7,9 +7,6 @@ canonifyURLs = 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 # links to it when used with a --baseURL (for example, https://spec.matrix.org/v1.4/ # contains ``). @@ -23,6 +20,21 @@ languageName ="English" # Weight used for sorting. 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.goldmark] [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 # of the spec. CI will set these values here automatically when a release git tag (i.e `v1.5`) is created. # major = "1" -# minor = "7" -# release_date = "May 25, 2023" +# minor = "9" +# release_date = "November 29, 2023" # User interface configuration [params.ui] @@ -111,3 +123,13 @@ sidebar_menu_compact = true X-Frame-Options = "sameorigin" Access-Control-Allow-Origin = "*" 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 diff --git a/content/_index.md b/content/_index.md index 69832f2e..a8c53809 100644 --- a/content/_index.md +++ b/content/_index.md @@ -419,9 +419,16 @@ into the `m.` namespace. ### Timestamps -Unless otherwise stated, timestamps are measured as milliseconds since -the Unix epoch. Throughout the specification this may be referred to as -POSIX, Unix, or just "time in milliseconds". +Unless otherwise stated, timestamps are the number of milliseconds +elapsed since the unix epoch (1970-01-01 00:00:00 UTC), but not counting +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 diff --git a/content/appendices.md b/content/appendices.md index 59c1b1c3..a5ddb7bf 100644 --- a/content/appendices.md +++ b/content/appendices.md @@ -136,12 +136,12 @@ removing insignificant whitespace, fractions, exponents and redundant character escapes. value = false / null / true / object / array / number / string - false = %x66.61.6c.73.65 - null = %x6e.75.6c.6c + false = %x66.61.6C.73.65 + null = %x6E.75.6C.6C true = %x74.72.75.65 - object = %x7B [ member *( %x2C member ) ] %7D + object = %x7B [ member *( %x2C member ) ] %x7D member = string %x3A value - array = %x5B [ value *( %x2C value ) ] %5B + array = %x5B [ value *( %x2C value ) ] %x5D number = [ %x2D ] int int = %x30 / ( %x31-39 *digit ) digit = %x30-39 diff --git a/content/changelog/v1.8.md b/content/changelog/v1.8.md new file mode 100644 index 00000000..0d25f6a2 --- /dev/null +++ b/content/changelog/v1.8.md @@ -0,0 +1,122 @@ +--- +date: 2023-08-23T09:23:53-06:00 +--- + + +## v1.8 + + + + +
Git commithttps://github.com/matrix-org/matrix-spec/tree/v1.8
Release dateAugust 23, 2023
+ + + +### 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)) diff --git a/content/changelog/v1.9.md b/content/changelog/v1.9.md new file mode 100644 index 00000000..46a79f37 --- /dev/null +++ b/content/changelog/v1.9.md @@ -0,0 +1,93 @@ +--- +date: 2023-11-29T10:04:26-07:00 +--- + + +## v1.9 + + + + +
Git commithttps://github.com/matrix-org/matrix-spec/tree/v1.9
Release dateNovember 29, 2023
+ + + +### 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)) diff --git a/content/client-server-api/modules/end_to_end_encryption.md b/content/client-server-api/modules/end_to_end_encryption.md index f2f75705..6c3bbbea 100644 --- a/content/client-server-api/modules/end_to_end_encryption.md +++ b/content/client-server-api/modules/end_to_end_encryption.md @@ -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. | | 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: @@ -150,7 +151,9 @@ JSON](/appendices/#signing-json). One-time and fallback keys are also uploaded to the homeserver using the [`/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 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 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. -12. Both Alice and Bob's devices perform an Elliptic-curve - Diffie-Hellman - (*ECDH(KAprivate*, *KBpublic*)), - using the result as the shared secret. +12. Both Alice's and Bob's devices perform an Elliptic-curve Diffie-Hellman using + their private ephemeral key, and the other device's ephemeral public key + (*ECDH(KAprivate*, *KBpublic*) + for Alice's device and + *ECDH(KBprivate*, *KApublic*) + 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 derived from the shared key using one of the methods in this 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 `m.key.verification.start` message, followed by `|`. - The public key from the `m.key.verification.key` message sent by - the device which sent the `m.key.verification.start` message, - followed by `|`. + the device which sent the `m.key.verification.start` message, encoded as + unpadded base64, followed by `|`. - The Matrix ID of the user who sent the `m.key.verification.accept` message, followed by `|`. - The Device ID of the device which sent the `m.key.verification.accept` message, followed by `|`. - The public key from the `m.key.verification.key` message sent by - the device which sent the `m.key.verification.accept` message, - followed by `|`. + the device which sent the `m.key.verification.accept` message, encoded as + unpadded base64, followed by `|`. - The `transaction_id` being used. 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, becomes the `ciphertext` property of the `session_data`. -5. Pass the raw encrypted data (prior to base64 encoding) through - HMAC-SHA-256 using the MAC key generated above. The first 8 bytes of - the resulting MAC are base64-encoded, and become the `mac` property - of the `session_data`. +5. Pass an empty string through HMAC-SHA-256 using the MAC key generated above. + The first 8 bytes of the resulting MAC are base64-encoded, and become the + `mac` property 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" %}} @@ -1765,9 +1778,9 @@ Example response: ], }, "device_one_time_keys_count": { - "curve25519": 10, "signed_curve25519": 20 - } + }, + "device_unused_fallback_key_types": ["signed_curve25519"] } ``` diff --git a/content/client-server-api/modules/event_annotations.md b/content/client-server-api/modules/event_annotations.md index 661d8001..6bcfb95d 100644 --- a/content/client-server-api/modules/event_annotations.md +++ b/content/client-server-api/modules/event_annotations.md @@ -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. 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 contains the emoji being used. diff --git a/content/client-server-api/modules/instant_messaging.md b/content/client-server-api/modules/instant_messaging.md index 5fcf379f..8a63dd9e 100644 --- a/content/client-server-api/modules/instant_messaging.md +++ b/content/client-server-api/modules/instant_messaging.md @@ -27,17 +27,25 @@ instead. Some message types support HTML in the event content that clients should prefer to display if available. Currently `m.text`, `m.emote`, `m.notice`, -and `m.key.verification.request` support an additional `format` parameter of -`org.matrix.custom.html`. When this field is present, a `formatted_body` -with the HTML must be provided. The plain text version of the HTML -should be provided in the `body`. +`m.image`, `m.file`, `m.audio`, `m.video` and `m.key.verification.request` +support an additional `format` parameter of `org.matrix.custom.html`. When this +field is present, a `formatted_body` with the HTML must be provided. The plain +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, HTML injection, and similar attacks. The strongly suggested set of HTML tags to permit, denying the use and rendering of anything else, is: `font`, `del`, `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `blockquote`, `p`, `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`. 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 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 cat 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 Homeservers SHOULD reject `m.room.message` events which don't have a diff --git a/content/client-server-api/modules/mentions.md b/content/client-server-api/modules/mentions.md index 32309740..0cdbad77 100644 --- a/content/client-server-api/modules/mentions.md +++ b/content/client-server-api/modules/mentions.md @@ -13,6 +13,20 @@ the event to reference the entity being mentioned. {{% 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 Alice!", + "m.mentions": { + "user_ids": ["@alice:example.org"] + } +} +``` + 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. Users should not add their own Matrix ID to the `m.mentions` property as outgoing diff --git a/content/client-server-api/modules/push.md b/content/client-server-api/modules/push.md index d1855f58..c674bac9 100644 --- a/content/client-server-api/modules/push.md +++ b/content/client-server-api/modules/push.md @@ -454,7 +454,7 @@ Definition: { "kind": "event_match", "key": "content.msgtype", - "pattern": "m.notice", + "pattern": "m.notice" } ], "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 **`.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 behind the `m.read.private` receipt). -{{< added-in v="1.4" >}} When handling threaded read receipts, the server -is to partition the notification count to each thread (with the main timeline -being its own thread). To determine if an event is part of a thread the -server follows the [event relationship](#forming-relationships-between-events) -until it finds a thread root (as specified by the [threading module](#threading)), -however it is not recommended that the server traverse infinitely. Instead, -implementations are encouraged to do a maximum of 3 hops to find a thread -before deciding that the event does not belong to a thread. This is primarily -to ensure that future events, like `m.reaction`, are correctly considered -"part of" a given thread. +{{< added-in v="1.4" >}} When handling threaded read receipts, the server is to +partition the notification count to each thread (with the main timeline being +its own thread). To determine if an event is part of a thread the server follows +the [event relationship](#forming-relationships-between-events) until it finds a +thread root via an `m.thread` relation (as specified by the [threading +module](#threading)), however it is not recommended that the server traverse +infinitely. Instead, implementations are encouraged to do a maximum of 3 hops to +find a thread before deciding that the event does not belong to a thread. This +is primarily to ensure that future events, like `m.reaction`, are correctly +considered "part of" a given thread. #### Server behaviour diff --git a/content/client-server-api/modules/receipts.md b/content/client-server-api/modules/receipts.md index 8cd4e9f6..d8733e19 100644 --- a/content/client-server-api/modules/receipts.md +++ b/content/client-server-api/modules/receipts.md @@ -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 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: -* 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. +considered to be "in a thread" if: -Events not in a thread but still in the room are considered to be part of the -"main timeline", or a special thread with an ID of `main`. +* It has a `rel_type` of `m.thread`, or +* 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 relationships and solid lines showing topological ordering. @@ -204,7 +208,7 @@ event when the user expands that thread. #### 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. Some receipts are sent across federation as EDUs with type `m.receipt`. The diff --git a/content/client-server-api/modules/report_content.md b/content/client-server-api/modules/report_content.md index 02ef002a..c482fbbc 100644 --- a/content/client-server-api/modules/report_content.md +++ b/content/client-server-api/modules/report_content.md @@ -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 reported content or some other mechanism for notifying the appropriate 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. diff --git a/content/client-server-api/modules/rich_replies.md b/content/client-server-api/modules/rich_replies.md index a0018630..ef07b697 100644 --- a/content/client-server-api/modules/rich_replies.md +++ b/content/client-server-api/modules/rich_replies.md @@ -60,7 +60,8 @@ specific fallback text is different for each `msgtype`, however the general format for the `body` is: ```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 ``` diff --git a/content/client-server-api/modules/secrets.md b/content/client-server-api/modules/secrets.md index 2d12d488..e94f361a 100644 --- a/content/client-server-api/modules/secrets.md +++ b/content/client-server-api/modules/secrets.md @@ -66,6 +66,70 @@ 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 Encrypted data is stored in the user's account data using the event @@ -82,7 +146,7 @@ of the data. | 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: @@ -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 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, - 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 differences in AES-CTR implementations), and use this as the AES - initialization vector. This becomes the `iv` property, encoded using - base64. -3. Encrypt the data using AES-CTR-256 using the AES key generated - above. This encrypted data, encoded using base64, becomes the - `ciphertext` property. -4. Pass the raw encrypted data (prior to base64 encoding) through - HMAC-SHA-256 using the MAC key generated above. The resulting MAC is - base64-encoded and becomes the `mac` property. + initialization vector (IV). + +3. Encrypt the data 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, 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` | Parameter | Type | Description |------------|---------|------------------------------------------------------------------------| -| iv | string | **Required.** The 16-byte initialization vector, encoded as base64. | -| ciphertext | string | **Required.** The AES-CTR-encrypted data, encoded as base64. | -| mac | string | **Required.** The MAC, 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. | +| 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 - 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: +For example, data encrypted using this algorithm could look like this: ```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`, 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 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 generated key. In this case, information on how to generate the key from diff --git a/content/client-server-api/modules/threading.md b/content/client-server-api/modules/threading.md index 04440a07..f082f389 100644 --- a/content/client-server-api/modules/threading.md +++ b/content/client-server-api/modules/threading.md @@ -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. 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 from an event which itself is the child of an event relationship (i.e., -one with an `m.relates_to` property). It is therefore also not possible to nest -threads. All events in a thread reference the thread root instead of the -most recent message, unlike rich reply chains. +*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 +is the child of an event relationship (i.e., one with an `m.relates_to` +property with a `rel_type` property - see [Relationship types](#relationship-types)). +It is therefore also not possible to nest threads. + +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: diff --git a/content/rooms/_index.md b/content/rooms/_index.md index e75fbb13..9334c3a1 100644 --- a/content/rooms/_index.md +++ b/content/rooms/_index.md @@ -36,11 +36,11 @@ Alternatively, consider flipping the column/row organization to be features up top and versions on the left. --> -| Feature \ Version | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -|-------------------|---|---|---|---|---|---|---|---|---|----| -| **Knocking** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | -| **Restricted join rules** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | ✔ | ✔ | -| **`knock_restricted` join rule** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | +| Feature \ Version | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | +|-------------------|---|---|---|---|---|---|---|---|---|----|----| +| **Knocking** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | +| **Restricted join rules** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | +| **`knock_restricted` join rule** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | ✔ | ## Complete list of room versions @@ -57,8 +57,7 @@ the default room version when creating new rooms. The available room versions are: -- [Version 1](/rooms/v1) - **Stable**. The current version of most - rooms. +- [Version 1](/rooms/v1) - **Stable**. The initial room version. - [Version 2](/rooms/v2) - **Stable**. Implements State Resolution Version 2. - [Version 3](/rooms/v3) - **Stable**. Introduces events whose IDs @@ -76,6 +75,7 @@ The available room versions are: redacting some membership events. - [Version 10](/rooms/v10) - **Stable**. Enforces integer-only power levels and adds `knock_restricted` join rule. +- [Version 11](/rooms/v11) - **Stable**. Clarifies the redaction algorithm. ## Room version grammar diff --git a/content/rooms/fragments/v1-redactions.md b/content/rooms/fragments/v1-redactions.md index f38c85f3..4731dbab 100644 --- a/content/rooms/fragments/v1-redactions.md +++ b/content/rooms/fragments/v1-redactions.md @@ -19,12 +19,14 @@ not in the following list: - `membership` 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.create` allows key `creator`. -- `m.room.join_rules` allows key `join_rule`. -- `m.room.power_levels` allows keys `ban`, `events`, `events_default`, - `kick`, `redact`, `state_default`, `users`, `users_default`. -- `m.room.aliases` allows key `aliases`. -- `m.room.history_visibility` allows key `history_visibility`. +- [`m.room.member`](/client-server-api#mroommember) allows key `membership`. +- [`m.room.create`](/client-server-api#mroomcreate) allows key `creator`. +- [`m.room.join_rules`](/client-server-api#mroomjoin_rules) allows key `join_rule`. +- [`m.room.power_levels`](/client-server-api#mroompower_levels) allows keys + `ban`, `events`, `events_default`, `kick`, `redact`, `state_default`, `users`, + `users_default`. +- [`m.room.aliases`](/client-server-api#historical-events) allows key `aliases`. +- [`m.room.history_visibility`](/client-server-api#mroomhistory_visibility) allows + key `history_visibility`. diff --git a/content/rooms/fragments/v11-event-format.md b/content/rooms/fragments/v11-event-format.md new file mode 100644 index 00000000..a4da710d --- /dev/null +++ b/content/rooms/fragments/v11-event-format.md @@ -0,0 +1,4 @@ + +Events in rooms of this version have the following structure: + +{{% definition path="api/server-server/definitions/pdu_v11" %}} diff --git a/content/rooms/fragments/v11-redactions.md b/content/rooms/fragments/v11-redactions.md new file mode 100644 index 00000000..3bde94ba --- /dev/null +++ b/content/rooms/fragments/v11-redactions.md @@ -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`. \ No newline at end of file diff --git a/content/rooms/fragments/v6-redactions.md b/content/rooms/fragments/v6-redactions.md index 71ecf854..47b024a2 100644 --- a/content/rooms/fragments/v6-redactions.md +++ b/content/rooms/fragments/v6-redactions.md @@ -19,11 +19,13 @@ not in the following list: - `membership` 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.create` allows key `creator`. -- `m.room.join_rules` allows key `join_rule`. -- `m.room.power_levels` allows keys `ban`, `events`, `events_default`, - `kick`, `redact`, `state_default`, `users`, `users_default`. -- `m.room.history_visibility` allows key `history_visibility`. +- [`m.room.member`](/client-server-api#mroommember) allows key `membership`. +- [`m.room.create`](/client-server-api#mroomcreate) allows key `creator`. +- [`m.room.join_rules`](/client-server-api#mroomjoin_rules) allows key `join_rule`. +- [`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`. diff --git a/content/rooms/fragments/v8-auth-rules.md b/content/rooms/fragments/v8-auth-rules.md index 98a88bf1..3f1a4558 100644 --- a/content/rooms/fragments/v8-auth-rules.md +++ b/content/rooms/fragments/v8-auth-rules.md @@ -117,7 +117,8 @@ The rules are as follows: 7. If `membership` is `knock`: 1. If the `join_rule` is anything other than `knock`, 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. 8. Otherwise, the membership is unknown. Reject. 5. If the `sender`'s current membership state is not `join`, reject. diff --git a/content/rooms/fragments/v9-redactions.md b/content/rooms/fragments/v9-redactions.md index 18c100a5..27cd97f0 100644 --- a/content/rooms/fragments/v9-redactions.md +++ b/content/rooms/fragments/v9-redactions.md @@ -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 not in the following list: @@ -40,11 +19,15 @@ not in the following list: - `membership` 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.create` allows key `creator`. -- `m.room.join_rules` allows keys `join_rule`, `allow`. -- `m.room.power_levels` allows keys `ban`, `events`, `events_default`, - `kick`, `redact`, `state_default`, `users`, `users_default`. -- `m.room.history_visibility` allows key `history_visibility`. \ No newline at end of file +- [`m.room.member`](/client-server-api#mroommember) allows keys `membership`, + `join_authorised_via_users_server`. +- [`m.room.create`](/client-server-api#mroomcreate) allows key `creator`. +- [`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`, `kick`, `redact`, `state_default`, `users`, + `users_default`. +- [`m.room.history_visibility`](/client-server-api#mroomhistory_visibility) + allows key `history_visibility`. \ No newline at end of file diff --git a/content/rooms/v10.md b/content/rooms/v10.md index 46bdb4c7..1d366c8c 100644 --- a/content/rooms/v10.md +++ b/content/rooms/v10.md @@ -194,7 +194,8 @@ The rules are as follows: 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` or `join`, allow. + 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. diff --git a/content/rooms/v11.md b/content/rooms/v11.md new file mode 100644 index 00000000..5d44161c --- /dev/null +++ b/content/rooms/v11.md @@ -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" %}} diff --git a/content/rooms/v6.md b/content/rooms/v6.md index 977f5479..b0309254 100644 --- a/content/rooms/v6.md +++ b/content/rooms/v6.md @@ -15,7 +15,7 @@ which implement the redaction algorithm locally should refer to the ### 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 the same as past room versions. diff --git a/content/rooms/v7.md b/content/rooms/v7.md index 40a9962c..eda351d0 100644 --- a/content/rooms/v7.md +++ b/content/rooms/v7.md @@ -139,7 +139,8 @@ The rules are as follows: If `membership` is `knock`: 1. If the `join_rule` is anything other than `knock`, 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. 7. Otherwise, the membership is unknown. Reject. 5. If the `sender`'s current membership state is not `join`, reject. diff --git a/content/rooms/v9.md b/content/rooms/v9.md index f6735415..cef269c6 100644 --- a/content/rooms/v9.md +++ b/content/rooms/v9.md @@ -17,6 +17,27 @@ Clients which implement the redaction algorithm locally should refer to the ### 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" %}} ## Server implementation components diff --git a/content/server-server-api.md b/content/server-server-api.md index 2dc80da5..fb1b06f4 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -110,7 +110,7 @@ to send. The process overall is as follows: given. The target server must present a valid certificate for the IP address. The `Host` header in the request should be set to the server name, including the port if the server name included one. - + 2. If the hostname is not an IP literal, and the server name includes an explicit port, resolve the hostname to an IP address using CNAME, AAAA or A records. @@ -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 parsed as `[:]` and processed as follows: - - If `` is an IP literal, then that IP address + 1. If `` is an IP literal, then that IP address should be used together with the `` or 8448 if no port is provided. The target server must present a valid TLS certificate for the IP address. Requests must be made with a `Host` header containing the IP address, including the port if one was provided. - - If `` is not an IP literal, and + 2. If `` is not an IP literal, and `` is present, an IP address is discovered by looking up CNAME, AAAA or A records for ``. The resulting IP address is used, alongside the ``. Requests must be made with a `Host` header of `:`. The target server must present a valid certificate for ``. - - If `` is not an IP literal and no + 3. {{< added-in v="1.8" >}} If `` is not an IP literal and no `` is present, an SRV record is looked up for + `_matrix-fed._tcp.`. 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 ``. The + target server must present a valid certificate for + ``. + 4. **[Deprecated]** If `` is not an IP literal, no + `` is present, and a `_matrix-fed._tcp.` + SRV record was not found, an SRV record is looked up for `_matrix._tcp.`. 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 ``. The target server must present a valid certificate for ``. - - 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 and a port of 8448, using a `Host` header of ``. The target server must present a valid certificate for ``. -4. If the `/.well-known` request resulted in an error response, a - server is found by resolving an SRV record for - `_matrix._tcp.`. 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, using 8448 as a default port, with a - `Host` header of ``. The target server must present a - valid certificate for ``. +4. {{< added-in v="1.8" >}} If the `/.well-known` request resulted in an error response, a server is + found by resolving an SRV record for `_matrix-fed._tcp.`. 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 ``. The target server must present a valid certificate + for ``. -5. If the `/.well-known` request returned an error response, and the - SRV record was not found, an IP address is resolved using CNAME, AAAA and A +5. **[Deprecated]** If the `/.well-known` request resulted in an error response, + and a `_matrix-fed._tcp.` SRV record was not found, a server is + found by resolving an SRV record for `_matrix._tcp.`. 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 ``. The target server must present a valid certificate + for ``. + +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 8448 and a `Host` header containing the ``. The target server must present a valid certificate for ``. @@ -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) {{% /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" %}} ### Server implementation @@ -266,7 +290,7 @@ Step 1 sign JSON: ``` { - "method": "GET", + "method": "POST", "uri": "/target", "origin": "origin.hs.example.com", "destination": "destination.hs.example.com", @@ -287,7 +311,7 @@ condition applies throughout the request signing process. 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..." Content-Type: application/json diff --git a/data-definitions/sas-emoji-v1-i18n/ar.json b/data-definitions/sas-emoji-v1-i18n/ar.json index 822d6f1c..5935ffd6 100644 --- a/data-definitions/sas-emoji-v1-i18n/ar.json +++ b/data-definitions/sas-emoji-v1-i18n/ar.json @@ -50,17 +50,17 @@ "Flower": "زَهرَة", "Butterfly": "فَرَاشَة", "Octopus": "أُخطُبُوط", - "Fish": "سَمَكَة", + "Fish": "سَمَكة", "Turtle": "سُلحفاة", - "Penguin": "بِطريق", + "Penguin": "بطريق", "Rooster": "دِيك", "Panda": "باندَا", "Rabbit": "أَرنَب", "Elephant": "فِيل", "Pig": "خِنزِير", - "Unicorn": "حِصَانٌ بِقَرن", + "Unicorn": "حصان وحيد القرن", "Horse": "حِصَان", "Lion": "أَسَد", "Cat": "هِرَّة", - "Dog": "كَلب" + "Dog": "كلب" } diff --git a/data-definitions/sas-emoji-v1-i18n/cs.json b/data-definitions/sas-emoji-v1-i18n/cs.json index 66d3a42a..ce5d6ad7 100644 --- a/data-definitions/sas-emoji-v1-i18n/cs.json +++ b/data-definitions/sas-emoji-v1-i18n/cs.json @@ -15,7 +15,7 @@ "Flag": "Vlajka", "Telephone": "Telefon", "Hammer": "Kladivo", - "Key": "Klíč", + "Key": "Klíč ke dveřím", "Lock": "Zámek", "Scissors": "Nůžky", "Paperclip": "Sponka", diff --git a/data-definitions/sas-emoji-v1-i18n/es.json b/data-definitions/sas-emoji-v1-i18n/es.json index 83d75f57..3651aef1 100644 --- a/data-definitions/sas-emoji-v1-i18n/es.json +++ b/data-definitions/sas-emoji-v1-i18n/es.json @@ -11,7 +11,7 @@ "Pencil": "Lápiz", "Key": "Llave", "Hammer": "Martillo", - "Telephone": "Telefono", + "Telephone": "Teléfono", "Train": "Tren", "Bicycle": "Bicicleta", "Ball": "Bola", diff --git a/data-definitions/sas-emoji-v1-i18n/fa.json b/data-definitions/sas-emoji-v1-i18n/fa.json new file mode 100644 index 00000000..621b0fff --- /dev/null +++ b/data-definitions/sas-emoji-v1-i18n/fa.json @@ -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": "سگ" +} diff --git a/data-definitions/sas-emoji-v1-i18n/ja.json b/data-definitions/sas-emoji-v1-i18n/ja.json index 1ad4cf14..73943c42 100644 --- a/data-definitions/sas-emoji-v1-i18n/ja.json +++ b/data-definitions/sas-emoji-v1-i18n/ja.json @@ -9,14 +9,14 @@ "Moon": "月", "Apple": "リンゴ", "Cake": "ケーキ", - "Robot": "ロボと", + "Robot": "ロボット", "Glasses": "めがね", "Book": "本", "Telephone": "電話機", "Train": "電車", "Bicycle": "自転車", "Pin": "ピン", - "Folder": "フォルダ", + "Folder": "フォルダー", "Headphones": "ヘッドホン", "Anchor": "いかり", "Bell": "ベル", diff --git a/data-definitions/sas-emoji-v1-i18n/pt.json b/data-definitions/sas-emoji-v1-i18n/pt.json new file mode 100644 index 00000000..17cc00d6 --- /dev/null +++ b/data-definitions/sas-emoji-v1-i18n/pt.json @@ -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" +} diff --git a/data-definitions/sas-emoji-v1-i18n/sk.json b/data-definitions/sas-emoji-v1-i18n/sk.json index f0a7176c..f44cb0fc 100644 --- a/data-definitions/sas-emoji-v1-i18n/sk.json +++ b/data-definitions/sas-emoji-v1-i18n/sk.json @@ -1,64 +1,64 @@ { - "Dog": "Hlava psa", - "Cat": "Hlava mačky", - "Lion": "Hlava leva", + "Dog": "Pes", + "Cat": "Mačka", + "Lion": "Lev", "Horse": "Kôň", - "Unicorn": "Hlava jednorožca", - "Pig": "Hlava prasaťa", + "Unicorn": "Jednorožec", + "Pig": "Prasa", "Elephant": "Slon", - "Rabbit": "Hlava zajaca", - "Panda": "Hlava pandy", + "Rabbit": "Zajac", + "Panda": "Panda", "Rooster": "Kohút", "Penguin": "Tučniak", "Turtle": "Korytnačka", "Fish": "Ryba", "Octopus": "Chobotnica", "Butterfly": "Motýľ", - "Flower": "Tulipán", - "Tree": "Listnatý strom", + "Flower": "Kvet", + "Tree": "Strom", "Cactus": "Kaktus", "Mushroom": "Huba", "Globe": "Zemeguľa", - "Moon": "Polmesiac", + "Moon": "Mesiac", "Cloud": "Oblak", "Fire": "Oheň", "Banana": "Banán", - "Apple": "Červené jablko", + "Apple": "Jablko", "Strawberry": "Jahoda", - "Corn": "Kukuričný klas", + "Corn": "Kukurica", "Pizza": "Pizza", - "Cake": "Narodeninová torta", - "Heart": "červené srdce", - "Smiley": "Škeriaca sa tvár", + "Cake": "Torta", + "Heart": "Srdce", + "Smiley": "Smajlík", "Robot": "Robot", - "Hat": "Cilinder", + "Hat": "Klobúk", "Glasses": "Okuliare", - "Spanner": "Francúzsky kľúč", - "Santa": "Santa Claus", + "Spanner": "Vidlicový kľúč", + "Santa": "Mikuláš", "Thumbs Up": "Palec nahor", "Umbrella": "Dáždnik", "Hourglass": "Presýpacie hodiny", "Clock": "Budík", - "Gift": "Zabalený darček", + "Gift": "Darček", "Light Bulb": "Žiarovka", - "Book": "Zatvorená kniha", + "Book": "Kniha", "Pencil": "Ceruzka", - "Paperclip": "Sponka na papier", + "Paperclip": "Kancelárska sponka", "Scissors": "Nožnice", - "Lock": "Zatvorená zámka", + "Lock": "Zámka", "Key": "Kľúč", "Hammer": "Kladivo", "Telephone": "Telefón", - "Flag": "Kockovaná zástava", - "Train": "Rušeň", + "Flag": "Zástava", + "Train": "Vlak", "Bicycle": "Bicykel", "Aeroplane": "Lietadlo", "Rocket": "Raketa", "Trophy": "Trofej", - "Ball": "Futbal", + "Ball": "Lopta", "Guitar": "Gitara", "Trumpet": "Trúbka", - "Bell": "Zvon", + "Bell": "Zvonec", "Anchor": "Kotva", "Headphones": "Slúchadlá", "Folder": "Fascikel", diff --git a/data-definitions/sas-emoji-v1-i18n/vi.json b/data-definitions/sas-emoji-v1-i18n/vi.json index f6e146da..76bb4ff1 100644 --- a/data-definitions/sas-emoji-v1-i18n/vi.json +++ b/data-definitions/sas-emoji-v1-i18n/vi.json @@ -17,20 +17,20 @@ "Hammer": "Búa", "Key": "Chìa khóa", "Lock": "Ổ khóa", - "Scissors": "Cây kéo", + "Scissors": "Cái kéo", "Paperclip": "Kẹp giấy", "Pencil": "Viết chì", "Book": "Sách", "Light Bulb": "Bóng đèn tròn", - "Gift": "Quà", + "Gift": "Quà tặng", "Clock": "Đồng hồ", "Hourglass": "Đồng hồ cát", - "Umbrella": "Cây dù", + "Umbrella": "Cái ô", "Thumbs Up": "Thích", - "Santa": "ông già Noel", + "Santa": "ông già Nô-en", "Spanner": "Cờ-lê", - "Glasses": "Mắt kiếng", - "Hat": "Nón", + "Glasses": "Kính mắt", + "Hat": "Mũ", "Robot": "Rô-bô", "Smiley": "Mặt cười", "Heart": "Tim", diff --git a/data-definitions/sas-emoji-v1-i18n/zh_Hant.json b/data-definitions/sas-emoji-v1-i18n/zh_Hant.json new file mode 100644 index 00000000..45dc1f61 --- /dev/null +++ b/data-definitions/sas-emoji-v1-i18n/zh_Hant.json @@ -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": "狗" +} diff --git a/data-definitions/sas-emoji.json b/data-definitions/sas-emoji.json index e6bc02bf..88d551f0 100644 --- a/data-definitions/sas-emoji.json +++ b/data-definitions/sas-emoji.json @@ -5,7 +5,7 @@ "description": "Dog", "unicode": "U+1F436", "translated_descriptions": { - "ar": "كَلب", + "ar": "كلب", "bg": "Куче", "ca": "Gos", "cs": "Pes", @@ -13,6 +13,7 @@ "eo": "Hundo", "es": "Perro", "et": "Koer", + "fa": "سگ", "fi": "Koira", "fr": "Chien", "hr": "pas", @@ -22,10 +23,11 @@ "ja": "犬", "nb_NO": "Hund", "nl": "Hond", + "pt": "Cão", "pt_BR": "Cachorro", "ru": "Собака", "si": "බල්ලා", - "sk": "Hlava psa", + "sk": "Pes", "sq": "Qen", "sr": "пас", "sv": "Hund", @@ -33,7 +35,8 @@ "tzm": "Aydi", "uk": "Пес", "vi": "Chó", - "zh_Hans": "狗" + "zh_Hans": "狗", + "zh_Hant": "狗" } }, { @@ -50,6 +53,7 @@ "eo": "Kato", "es": "Gato", "et": "Kass", + "fa": "گربه", "fi": "Kissa", "fr": "Chat", "hr": "mačka", @@ -59,10 +63,11 @@ "ja": "猫", "nb_NO": "Katt", "nl": "Kat", + "pt": "Gato", "pt_BR": "Gato", "ru": "Кошка", "si": "පූසා", - "sk": "Hlava mačky", + "sk": "Mačka", "sq": "Mace", "sr": "мачка", "sv": "Katt", @@ -70,7 +75,8 @@ "tzm": "Amuc", "uk": "Кіт", "vi": "Mèo", - "zh_Hans": "猫" + "zh_Hans": "猫", + "zh_Hant": "貓" } }, { @@ -87,6 +93,7 @@ "eo": "Leono", "es": "León", "et": "Lõvi", + "fa": "شیر", "fi": "Leijona", "fr": "Lion", "hr": "lav", @@ -96,10 +103,11 @@ "ja": "ライオン", "nb_NO": "Løve", "nl": "Leeuw", + "pt": "Leão", "pt_BR": "Leão", "ru": "Лев", "si": "සිංහයා", - "sk": "Hlava leva", + "sk": "Lev", "sq": "Luan", "sr": "лав", "sv": "Lejon", @@ -107,7 +115,8 @@ "tzm": "Izem", "uk": "Лев", "vi": "Sư tử", - "zh_Hans": "狮子" + "zh_Hans": "狮子", + "zh_Hant": "獅子" } }, { @@ -124,6 +133,7 @@ "eo": "Ĉevalo", "es": "Caballo", "et": "Hobune", + "fa": "اسب", "fi": "Hevonen", "fr": "Cheval", "hr": "konj", @@ -133,6 +143,7 @@ "ja": "馬", "nb_NO": "Hest", "nl": "Paard", + "pt": "Cavalo", "pt_BR": "Cavalo", "ru": "Лошадь", "si": "අශ්වයා", @@ -144,7 +155,8 @@ "tzm": "Ayyis", "uk": "Кінь", "vi": "Ngựa", - "zh_Hans": "马" + "zh_Hans": "马", + "zh_Hant": "馬" } }, { @@ -153,7 +165,7 @@ "description": "Unicorn", "unicode": "U+1F984", "translated_descriptions": { - "ar": "حِصَانٌ بِقَرن", + "ar": "حصان وحيد القرن", "bg": "Еднорог", "ca": "Unicorn", "cs": "Jednorožec", @@ -161,6 +173,7 @@ "eo": "Unukorno", "es": "Unicornio", "et": "Ükssarvik", + "fa": "تک شاخ", "fi": "Yksisarvinen", "fr": "Licorne", "hr": "jednorog", @@ -170,10 +183,11 @@ "ja": "ユニコーン", "nb_NO": "Enhjørning", "nl": "Eenhoorn", + "pt": "Unicórnio", "pt_BR": "Unicórnio", "ru": "Единорог", "si": null, - "sk": "Hlava jednorožca", + "sk": "Jednorožec", "sq": "Njëbrirësh", "sr": "једнорог", "sv": "Enhörning", @@ -181,7 +195,8 @@ "tzm": null, "uk": "Єдиноріг", "vi": "Kỳ lân", - "zh_Hans": "独角兽" + "zh_Hans": "独角兽", + "zh_Hant": "獨角獸" } }, { @@ -198,6 +213,7 @@ "eo": "Porko", "es": "Cerdo", "et": "Siga", + "fa": "خوک", "fi": "Sika", "fr": "Cochon", "hr": "svinja", @@ -207,10 +223,11 @@ "ja": "ブタ", "nb_NO": "Gris", "nl": "Varken", + "pt": "Porco", "pt_BR": "Porco", "ru": "Свинья", "si": null, - "sk": "Hlava prasaťa", + "sk": "Prasa", "sq": "Derr", "sr": "прасе", "sv": "Gris", @@ -218,7 +235,8 @@ "tzm": "Ilef", "uk": "Свиня", "vi": "Heo", - "zh_Hans": "猪" + "zh_Hans": "猪", + "zh_Hant": "豬" } }, { @@ -235,6 +253,7 @@ "eo": "Elefanto", "es": "Elefante", "et": "Elevant", + "fa": "فیل", "fi": "Norsu", "fr": "Éléphant", "hr": "slon", @@ -244,6 +263,7 @@ "ja": "ゾウ", "nb_NO": "Elefant", "nl": "Olifant", + "pt": "Elefante", "pt_BR": "Elefante", "ru": "Слон", "si": null, @@ -255,7 +275,8 @@ "tzm": "Ilu", "uk": "Слон", "vi": "Voi", - "zh_Hans": "大象" + "zh_Hans": "大象", + "zh_Hant": "大象" } }, { @@ -272,6 +293,7 @@ "eo": "Kuniklo", "es": "Conejo", "et": "Jänes", + "fa": "خرگوش", "fi": "Kani", "fr": "Lapin", "hr": "zec", @@ -281,10 +303,11 @@ "ja": "うさぎ", "nb_NO": "Kanin", "nl": "Konijn", + "pt": "Coelho", "pt_BR": "Coelho", "ru": "Кролик", "si": null, - "sk": "Hlava zajaca", + "sk": "Zajac", "sq": "Lepur", "sr": "зец", "sv": "Kanin", @@ -292,7 +315,8 @@ "tzm": "Agnin", "uk": "Кріль", "vi": "Thỏ", - "zh_Hans": "兔子" + "zh_Hans": "兔子", + "zh_Hant": "兔子" } }, { @@ -309,6 +333,7 @@ "eo": "Pando", "es": "Panda", "et": "Panda", + "fa": "پاندا", "fi": "Panda", "fr": "Panda", "hr": "panda", @@ -318,10 +343,11 @@ "ja": "パンダ", "nb_NO": "Panda", "nl": "Panda", + "pt": "Panda", "pt_BR": "Panda", "ru": "Панда", "si": null, - "sk": "Hlava pandy", + "sk": "Panda", "sq": "Panda", "sr": "панда", "sv": "Panda", @@ -329,7 +355,8 @@ "tzm": null, "uk": "Панда", "vi": "Gấu trúc", - "zh_Hans": "熊猫" + "zh_Hans": "熊猫", + "zh_Hant": "熊貓" } }, { @@ -346,6 +373,7 @@ "eo": "Virkoko", "es": "Gallo", "et": "Kukk", + "fa": "خروس", "fi": "Kukko", "fr": "Coq", "hr": "kokot", @@ -355,6 +383,7 @@ "ja": "ニワトリ", "nb_NO": "Hane", "nl": "Haan", + "pt": "Galo", "pt_BR": "Galo", "ru": "Петух", "si": null, @@ -366,7 +395,8 @@ "tzm": "Ayaẓiḍ", "uk": "Когут", "vi": "Gà trống", - "zh_Hans": "公鸡" + "zh_Hans": "公鸡", + "zh_Hant": "公雞" } }, { @@ -375,7 +405,7 @@ "description": "Penguin", "unicode": "U+1F427", "translated_descriptions": { - "ar": "بِطريق", + "ar": "بطريق", "bg": "Пингвин", "ca": "Pingüí", "cs": "Tučňák", @@ -383,6 +413,7 @@ "eo": "Pingveno", "es": "Pingüino", "et": "Pingviin", + "fa": "پنگوئن", "fi": "Pingviini", "fr": "Manchot", "hr": "pingvin", @@ -392,6 +423,7 @@ "ja": "ペンギン", "nb_NO": "Pingvin", "nl": "Pinguïn", + "pt": "Pinguim", "pt_BR": "Pinguim", "ru": "Пингвин", "si": null, @@ -403,7 +435,8 @@ "tzm": null, "uk": "Пінгвін", "vi": "Chim cánh cụt", - "zh_Hans": "企鹅" + "zh_Hans": "企鹅", + "zh_Hant": "企鵝" } }, { @@ -420,6 +453,7 @@ "eo": "Testudo", "es": "Tortuga", "et": "Kilpkonn", + "fa": "لاک‌پشت", "fi": "Kilpikonna", "fr": "Tortue", "hr": "kornjača", @@ -429,6 +463,7 @@ "ja": "亀", "nb_NO": "Skilpadde", "nl": "Schildpad", + "pt": "Tartaruga", "pt_BR": "Tartaruga", "ru": "Черепаха", "si": null, @@ -440,7 +475,8 @@ "tzm": "Ifker", "uk": "Черепаха", "vi": "Rùa", - "zh_Hans": "乌龟" + "zh_Hans": "乌龟", + "zh_Hant": "烏龜" } }, { @@ -449,7 +485,7 @@ "description": "Fish", "unicode": "U+1F41F", "translated_descriptions": { - "ar": "سَمَكَة", + "ar": "سَمَكة", "bg": "Риба", "ca": "Peix", "cs": "Ryba", @@ -457,6 +493,7 @@ "eo": "Fiŝo", "es": "Pez", "et": "Kala", + "fa": "ماهی", "fi": "Kala", "fr": "Poisson", "hr": "riba", @@ -466,6 +503,7 @@ "ja": "魚", "nb_NO": "Fisk", "nl": "Vis", + "pt": "Peixe", "pt_BR": "Peixe", "ru": "Рыба", "si": null, @@ -477,7 +515,8 @@ "tzm": "Aselm", "uk": "Риба", "vi": "Cá", - "zh_Hans": "鱼" + "zh_Hans": "鱼", + "zh_Hant": "魚" } }, { @@ -494,6 +533,7 @@ "eo": "Polpo", "es": "Pulpo", "et": "Kaheksajalg", + "fa": "اختاپوس", "fi": "Tursas", "fr": "Poulpe", "hr": "hobotnica", @@ -503,6 +543,7 @@ "ja": "たこ", "nb_NO": "Blekksprut", "nl": "Octopus", + "pt": "Polvo", "pt_BR": "Polvo", "ru": "Осьминог", "si": null, @@ -514,7 +555,8 @@ "tzm": null, "uk": "Восьминіг", "vi": "Bạch tuộc", - "zh_Hans": "章鱼" + "zh_Hans": "章鱼", + "zh_Hant": "章魚" } }, { @@ -531,6 +573,7 @@ "eo": "Papilio", "es": "Mariposa", "et": "Liblikas", + "fa": "پروانه", "fi": "Perhonen", "fr": "Papillon", "hr": "leptir", @@ -540,6 +583,7 @@ "ja": "ちょうちょ", "nb_NO": "Sommerfugl", "nl": "Vlinder", + "pt": "Borboleta", "pt_BR": "Borboleta", "ru": "Бабочка", "si": null, @@ -551,7 +595,8 @@ "tzm": null, "uk": "Метелик", "vi": "Bướm", - "zh_Hans": "蝴蝶" + "zh_Hans": "蝴蝶", + "zh_Hant": "蝴蝶" } }, { @@ -568,6 +613,7 @@ "eo": "Floro", "es": "Flor", "et": "Lill", + "fa": "گل", "fi": "Kukka", "fr": "Fleur", "hr": "svijet", @@ -577,10 +623,11 @@ "ja": "花", "nb_NO": "Blomst", "nl": "Bloem", + "pt": "Flor", "pt_BR": "Flor", "ru": "Цветок", "si": null, - "sk": "Tulipán", + "sk": "Kvet", "sq": "Lule", "sr": "цвет", "sv": "Blomma", @@ -588,7 +635,8 @@ "tzm": null, "uk": "Квітка", "vi": "Hoa", - "zh_Hans": "花" + "zh_Hans": "花", + "zh_Hant": "花" } }, { @@ -605,6 +653,7 @@ "eo": "Arbo", "es": "Árbol", "et": "Puu", + "fa": "درخت", "fi": "Puu", "fr": "Arbre", "hr": "drvo", @@ -614,10 +663,11 @@ "ja": "木", "nb_NO": "Tre", "nl": "Boom", + "pt": "Árvore", "pt_BR": "Árvore", "ru": "Дерево", "si": null, - "sk": "Listnatý strom", + "sk": "Strom", "sq": "Pemë", "sr": "дрво", "sv": "Träd", @@ -625,7 +675,8 @@ "tzm": "Aseklu", "uk": "Дерево", "vi": "Cây", - "zh_Hans": "树" + "zh_Hans": "树", + "zh_Hant": "樹" } }, { @@ -642,6 +693,7 @@ "eo": "Kakto", "es": "Cactus", "et": "Kaktus", + "fa": "کاکتوس", "fi": "Kaktus", "fr": "Cactus", "hr": "kaktus", @@ -651,6 +703,7 @@ "ja": "サボテン", "nb_NO": "Kaktus", "nl": "Cactus", + "pt": "Cato", "pt_BR": "Cacto", "ru": "Кактус", "si": null, @@ -662,7 +715,8 @@ "tzm": null, "uk": "Кактус", "vi": "Xương rồng", - "zh_Hans": "仙人掌" + "zh_Hans": "仙人掌", + "zh_Hant": "仙人掌" } }, { @@ -679,6 +733,7 @@ "eo": "Fungo", "es": "Seta", "et": "Seen", + "fa": "قارچ", "fi": "Sieni", "fr": "Champignon", "hr": "gljiva", @@ -688,6 +743,7 @@ "ja": "きのこ", "nb_NO": "Sopp", "nl": "Paddenstoel", + "pt": "Cogumelo", "pt_BR": "Cogumelo", "ru": "Гриб", "si": null, @@ -699,7 +755,8 @@ "tzm": "Agursel", "uk": "Гриб", "vi": "Nấm", - "zh_Hans": "蘑菇" + "zh_Hans": "蘑菇", + "zh_Hant": "蘑菇" } }, { @@ -716,6 +773,7 @@ "eo": "Globo", "es": "Globo", "et": "Maakera", + "fa": "زمین", "fi": "Maapallo", "fr": "Globe", "hr": "Globus", @@ -725,6 +783,7 @@ "ja": "地球", "nb_NO": "Globus", "nl": "Wereldbol", + "pt": "Globo", "pt_BR": "Globo", "ru": "Глобус", "si": null, @@ -736,7 +795,8 @@ "tzm": null, "uk": "Глобус", "vi": "Địa cầu", - "zh_Hans": "地球" + "zh_Hans": "地球", + "zh_Hant": "地球" } }, { @@ -753,6 +813,7 @@ "eo": "Luno", "es": "Luna", "et": "Kuu", + "fa": "ماه", "fi": "Kuu", "fr": "Lune", "hr": "mjesec", @@ -762,10 +823,11 @@ "ja": "月", "nb_NO": "Måne", "nl": "Maan", + "pt": "Lua", "pt_BR": "Lua", "ru": "Луна", "si": null, - "sk": "Polmesiac", + "sk": "Mesiac", "sq": "Hënë", "sr": "месец", "sv": "Måne", @@ -773,7 +835,8 @@ "tzm": "Ayyur", "uk": "Місяць", "vi": "Mặt trăng", - "zh_Hans": "月亮" + "zh_Hans": "月亮", + "zh_Hant": "月亮" } }, { @@ -790,6 +853,7 @@ "eo": "Nubo", "es": "Nube", "et": "Pilv", + "fa": "ابر", "fi": "Pilvi", "fr": "Nuage", "hr": "oblak", @@ -799,6 +863,7 @@ "ja": "雲", "nb_NO": "Sky", "nl": "Wolk", + "pt": "Nuvem", "pt_BR": "Nuvem", "ru": "Облако", "si": null, @@ -810,7 +875,8 @@ "tzm": null, "uk": "Хмара", "vi": "Mây", - "zh_Hans": "云" + "zh_Hans": "云", + "zh_Hant": "雲朵" } }, { @@ -827,6 +893,7 @@ "eo": "Fajro", "es": "Fuego", "et": "Tuli", + "fa": "آتش", "fi": "Tuli", "fr": "Feu", "hr": "vatra", @@ -836,6 +903,7 @@ "ja": "炎", "nb_NO": "Flamme", "nl": "Vuur", + "pt": "Fogo", "pt_BR": "Fogo", "ru": "Огонь", "si": null, @@ -847,7 +915,8 @@ "tzm": "Timessi", "uk": "Вогонь", "vi": "Lửa", - "zh_Hans": "火" + "zh_Hans": "火", + "zh_Hant": "火" } }, { @@ -864,6 +933,7 @@ "eo": "Banano", "es": "Plátano", "et": "Banaan", + "fa": "موز", "fi": "Banaani", "fr": "Banane", "hr": "banana", @@ -873,6 +943,7 @@ "ja": "バナナ", "nb_NO": "Banan", "nl": "Banaan", + "pt": "Banana", "pt_BR": "Banana", "ru": "Банан", "si": null, @@ -884,7 +955,8 @@ "tzm": "Tabanant", "uk": "Банан", "vi": "Chuối", - "zh_Hans": "香蕉" + "zh_Hans": "香蕉", + "zh_Hant": "香蕉" } }, { @@ -901,6 +973,7 @@ "eo": "Pomo", "es": "Manzana", "et": "Õun", + "fa": "سیب", "fi": "Omena", "fr": "Pomme", "hr": "jabuka", @@ -910,10 +983,11 @@ "ja": "リンゴ", "nb_NO": "Eple", "nl": "Appel", + "pt": "Maçã", "pt_BR": "Maçã", "ru": "Яблоко", "si": null, - "sk": "Červené jablko", + "sk": "Jablko", "sq": "Mollë", "sr": "јабука", "sv": "Äpple", @@ -921,7 +995,8 @@ "tzm": "Tadeffuyt", "uk": "Яблуко", "vi": "Táo", - "zh_Hans": "苹果" + "zh_Hans": "苹果", + "zh_Hant": "蘋果" } }, { @@ -938,6 +1013,7 @@ "eo": "Frago", "es": "Fresa", "et": "Maasikas", + "fa": "توت فرنگی", "fi": "Mansikka", "fr": "Fraise", "hr": "jagoda", @@ -947,6 +1023,7 @@ "ja": "いちご", "nb_NO": "Jordbær", "nl": "Aardbei", + "pt": "Morango", "pt_BR": "Morango", "ru": "Клубника", "si": null, @@ -958,7 +1035,8 @@ "tzm": null, "uk": "Полуниця", "vi": "Dâu tây", - "zh_Hans": "草莓" + "zh_Hans": "草莓", + "zh_Hant": "草莓" } }, { @@ -975,6 +1053,7 @@ "eo": "Maizo", "es": "Maíz", "et": "Mais", + "fa": "ذرت", "fi": "Maissi", "fr": "Maïs", "hr": "kukuruza", @@ -984,10 +1063,11 @@ "ja": "とうもろこし", "nb_NO": "Mais", "nl": "Maïs", + "pt": "Milho", "pt_BR": "Milho", "ru": "Кукуруза", "si": null, - "sk": "Kukuričný klas", + "sk": "Kukurica", "sq": "Misër", "sr": "кукуруз", "sv": "Majs", @@ -995,7 +1075,8 @@ "tzm": null, "uk": "Кукурудза", "vi": "Bắp", - "zh_Hans": "玉米" + "zh_Hans": "玉米", + "zh_Hant": "玉米" } }, { @@ -1012,6 +1093,7 @@ "eo": "Pico", "es": "Pizza", "et": "Pitsa", + "fa": "پیتزا", "fi": "Pizza", "fr": "Pizza", "hr": "pizza", @@ -1021,6 +1103,7 @@ "ja": "ピザ", "nb_NO": "Pizza", "nl": "Pizza", + "pt": "Piza", "pt_BR": "Pizza", "ru": "Пицца", "si": null, @@ -1032,7 +1115,8 @@ "tzm": null, "uk": "Піца", "vi": "Pizza", - "zh_Hans": "披萨" + "zh_Hans": "披萨", + "zh_Hant": "披薩" } }, { @@ -1049,6 +1133,7 @@ "eo": "Torto", "es": "Tarta", "et": "Kook", + "fa": "کیک", "fi": "Kakku", "fr": "Gâteau", "hr": "torta", @@ -1058,10 +1143,11 @@ "ja": "ケーキ", "nb_NO": "Kake", "nl": "Taart", + "pt": "Bolo", "pt_BR": "Bolo", "ru": "Торт", "si": null, - "sk": "Narodeninová torta", + "sk": "Torta", "sq": "Tortë", "sr": "торта", "sv": "Tårta", @@ -1069,7 +1155,8 @@ "tzm": null, "uk": "Пиріг", "vi": "Bánh", - "zh_Hans": "蛋糕" + "zh_Hans": "蛋糕", + "zh_Hant": "蛋糕" } }, { @@ -1086,6 +1173,7 @@ "eo": "Koro", "es": "Corazón", "et": "Süda", + "fa": "قلب", "fi": "Sydän", "fr": "Cœur", "hr": "srca", @@ -1095,10 +1183,11 @@ "ja": "ハート", "nb_NO": "Hjerte", "nl": "Hart", + "pt": "Coração", "pt_BR": "Coração", "ru": "Сердце", "si": null, - "sk": "červené srdce", + "sk": "Srdce", "sq": "Zemër", "sr": "срце", "sv": "Hjärta", @@ -1106,7 +1195,8 @@ "tzm": "Ul", "uk": "Серце", "vi": "Tim", - "zh_Hans": "心" + "zh_Hans": "心", + "zh_Hant": "愛心" } }, { @@ -1123,6 +1213,7 @@ "eo": "Rideto", "es": "Emoticono", "et": "Smaili", + "fa": "خنده", "fi": "Hymynaama", "fr": "Sourire", "hr": "smajlića", @@ -1132,10 +1223,11 @@ "ja": "スマイル", "nb_NO": "Smilefjes", "nl": "Smiley", + "pt": "Sorriso", "pt_BR": "Sorriso", "ru": "Улыбка", "si": null, - "sk": "Škeriaca sa tvár", + "sk": "Smajlík", "sq": "Emotikon", "sr": "смајли", "sv": "Smiley", @@ -1143,7 +1235,8 @@ "tzm": null, "uk": "Посмішка", "vi": "Mặt cười", - "zh_Hans": "笑脸" + "zh_Hans": "笑脸", + "zh_Hant": "笑臉" } }, { @@ -1160,15 +1253,17 @@ "eo": "Roboto", "es": "Robot", "et": "Robot", + "fa": "ربات", "fi": "Robotti", "fr": "Robot", "hr": "robot", "hu": "Robot", "id": "Robot", "it": "Robot", - "ja": "ロボと", + "ja": "ロボット", "nb_NO": "Robot", "nl": "Robot", + "pt": "Robô", "pt_BR": "Robô", "ru": "Робот", "si": null, @@ -1180,7 +1275,8 @@ "tzm": "Aṛubu", "uk": "Робот", "vi": "Rô-bô", - "zh_Hans": "机器人" + "zh_Hans": "机器人", + "zh_Hant": "機器人" } }, { @@ -1197,6 +1293,7 @@ "eo": "Ĉapelo", "es": "Sombrero", "et": "Kübar", + "fa": "کلاه", "fi": "Hattu", "fr": "Chapeau", "hr": "kapa", @@ -1206,18 +1303,20 @@ "ja": "帽子", "nb_NO": "Hatt", "nl": "Hoed", + "pt": "Chapéu", "pt_BR": "Chapéu", "ru": "Шляпа", "si": null, - "sk": "Cilinder", + "sk": "Klobúk", "sq": "Kapë", "sr": "шешир", "sv": "Hatt", "szl": null, "tzm": "Taraza", "uk": "Капелюх", - "vi": "Nón", - "zh_Hans": "帽子" + "vi": "Mũ", + "zh_Hans": "帽子", + "zh_Hant": "帽子" } }, { @@ -1234,6 +1333,7 @@ "eo": "Okulvitroj", "es": "Gafas", "et": "Prillid", + "fa": "عینک", "fi": "Silmälasit", "fr": "Lunettes", "hr": "naočale", @@ -1243,6 +1343,7 @@ "ja": "めがね", "nb_NO": "Briller", "nl": "Bril", + "pt": "Óculos", "pt_BR": "Óculos", "ru": "Очки", "si": null, @@ -1253,8 +1354,9 @@ "szl": null, "tzm": null, "uk": "Окуляри", - "vi": "Mắt kiếng", - "zh_Hans": "眼镜" + "vi": "Kính mắt", + "zh_Hans": "眼镜", + "zh_Hant": "眼鏡" } }, { @@ -1271,6 +1373,7 @@ "eo": "Ŝraŭbŝlosilo", "es": "Llave inglesa", "et": "Mutrivõti", + "fa": "آچار", "fi": "Kiintoavain", "fr": "Clé à molette", "hr": "ključ", @@ -1280,10 +1383,11 @@ "ja": "スパナ", "nb_NO": "Fastnøkkel", "nl": "Moersleutel", + "pt": "Chave inglesa", "pt_BR": "Chave inglesa", "ru": "Ключ", "si": null, - "sk": "Francúzsky kľúč", + "sk": "Vidlicový kľúč", "sq": "Çelës", "sr": "кључ", "sv": "Skruvnyckel", @@ -1291,7 +1395,8 @@ "tzm": null, "uk": "Гайковий ключ", "vi": "Cờ-lê", - "zh_Hans": "扳手" + "zh_Hans": "扳手", + "zh_Hant": "扳手" } }, { @@ -1308,6 +1413,7 @@ "eo": "Kristnaska viro", "es": "Papá Noel", "et": "Jõuluvana", + "fa": "بابا نوئل", "fi": "Joulupukki", "fr": "Père Noël", "hr": "deda Mraz", @@ -1317,18 +1423,20 @@ "ja": "サンタ", "nb_NO": "Julenisse", "nl": "Kerstman", + "pt": "Pai Natal", "pt_BR": "Papai-noel", "ru": "Санта", "si": null, - "sk": "Santa Claus", + "sk": "Mikuláš", "sq": "Babagjyshi i Vitit të Ri", "sr": "деда Мраз", "sv": "Tomte", "szl": null, "tzm": null, "uk": "Санта Клаус", - "vi": "ông già Noel", - "zh_Hans": "圣诞老人" + "vi": "ông già Nô-en", + "zh_Hans": "圣诞老人", + "zh_Hant": "聖誕老人" } }, { @@ -1345,6 +1453,7 @@ "eo": "Dikfingro supren", "es": "Pulgar arriba", "et": "Pöidlad püsti", + "fa": "لایک", "fi": "Peukalo ylös", "fr": "Pouce en l’air", "hr": "palac gore", @@ -1354,6 +1463,7 @@ "ja": "いいね", "nb_NO": "Tommel Opp", "nl": "Duim omhoog", + "pt": "Polegar para cima", "pt_BR": "Joinha", "ru": "Большой палец вверх", "si": null, @@ -1365,7 +1475,8 @@ "tzm": null, "uk": "Великий палець вгору", "vi": "Thích", - "zh_Hans": "赞" + "zh_Hans": "赞", + "zh_Hant": "讚" } }, { @@ -1382,6 +1493,7 @@ "eo": "Ombrelo", "es": "Paraguas", "et": "Vihmavari", + "fa": "چتر", "fi": "Sateenvarjo", "fr": "Parapluie", "hr": "kišobran", @@ -1391,6 +1503,7 @@ "ja": "傘", "nb_NO": "Paraply", "nl": "Paraplu", + "pt": "Guarda-chuva", "pt_BR": "Guarda-chuva", "ru": "Зонт", "si": null, @@ -1401,8 +1514,9 @@ "szl": null, "tzm": null, "uk": "Парасолька", - "vi": "Cây dù", - "zh_Hans": "伞" + "vi": "Cái ô", + "zh_Hans": "伞", + "zh_Hant": "雨傘" } }, { @@ -1419,6 +1533,7 @@ "eo": "Sablohorloĝo", "es": "Reloj de arena", "et": "Liivakell", + "fa": "ساعت شنی", "fi": "Tiimalasi", "fr": "Sablier", "hr": "pješčani sat", @@ -1428,6 +1543,7 @@ "ja": "砂時計", "nb_NO": "Timeglass", "nl": "Zandloper", + "pt": "Ampulheta", "pt_BR": "Ampulheta", "ru": "Песочные часы", "si": null, @@ -1439,7 +1555,8 @@ "tzm": null, "uk": "Пісковий годинник", "vi": "Đồng hồ cát", - "zh_Hans": "沙漏" + "zh_Hans": "沙漏", + "zh_Hant": "沙漏" } }, { @@ -1456,6 +1573,7 @@ "eo": "Horloĝo", "es": "Reloj", "et": "Kell", + "fa": "ساعت", "fi": "Pöytäkello", "fr": "Réveil", "hr": "sat", @@ -1465,6 +1583,7 @@ "ja": "時計", "nb_NO": "Klokke", "nl": "Wekker", + "pt": "Relógio", "pt_BR": "Relógio", "ru": "Часы", "si": null, @@ -1476,7 +1595,8 @@ "tzm": null, "uk": "Годинник", "vi": "Đồng hồ", - "zh_Hans": "时钟" + "zh_Hans": "时钟", + "zh_Hant": "時鐘" } }, { @@ -1493,6 +1613,7 @@ "eo": "Donaco", "es": "Regalo", "et": "Kingitus", + "fa": "هدیه", "fi": "Lahja", "fr": "Cadeau", "hr": "poklon", @@ -1502,18 +1623,20 @@ "ja": "ギフト", "nb_NO": "Gave", "nl": "Geschenk", + "pt": "Presente", "pt_BR": "Presente", "ru": "Подарок", "si": null, - "sk": "Zabalený darček", + "sk": "Darček", "sq": "Dhuratë", "sr": "поклон", "sv": "Present", "szl": null, "tzm": null, "uk": "Подарунок", - "vi": "Quà", - "zh_Hans": "礼物" + "vi": "Quà tặng", + "zh_Hans": "礼物", + "zh_Hant": "禮物" } }, { @@ -1530,6 +1653,7 @@ "eo": "Lampo", "es": "Bombilla", "et": "Lambipirn", + "fa": "لامپ", "fi": "Hehkulamppu", "fr": "Ampoule", "hr": "žarulja", @@ -1539,6 +1663,7 @@ "ja": "電球", "nb_NO": "Lyspære", "nl": "Gloeilamp", + "pt": "Lâmpada", "pt_BR": "Lâmpada", "ru": "Лампочка", "si": null, @@ -1550,7 +1675,8 @@ "tzm": null, "uk": "Лампочка", "vi": "Bóng đèn tròn", - "zh_Hans": "灯泡" + "zh_Hans": "灯泡", + "zh_Hant": "燈泡" } }, { @@ -1567,6 +1693,7 @@ "eo": "Libro", "es": "Libro", "et": "Raamat", + "fa": "کتاب", "fi": "Kirja", "fr": "Livre", "hr": "knjiga", @@ -1576,10 +1703,11 @@ "ja": "本", "nb_NO": "Bok", "nl": "Boek", + "pt": "Livro", "pt_BR": "Livro", "ru": "Книга", "si": null, - "sk": "Zatvorená kniha", + "sk": "Kniha", "sq": "Libër", "sr": "књига", "sv": "Bok", @@ -1587,7 +1715,8 @@ "tzm": "Adlis", "uk": "Книга", "vi": "Sách", - "zh_Hans": "书" + "zh_Hans": "书", + "zh_Hant": "書" } }, { @@ -1604,6 +1733,7 @@ "eo": "Krajono", "es": "Lápiz", "et": "Pliiats", + "fa": "مداد", "fi": "Lyijykynä", "fr": "Crayon", "hr": "olovka", @@ -1613,6 +1743,7 @@ "ja": "鉛筆", "nb_NO": "Blyant", "nl": "Potlood", + "pt": "Lápis", "pt_BR": "Lápis", "ru": "Карандаш", "si": null, @@ -1624,7 +1755,8 @@ "tzm": null, "uk": "Олівець", "vi": "Viết chì", - "zh_Hans": "铅笔" + "zh_Hans": "铅笔", + "zh_Hant": "鉛筆" } }, { @@ -1641,6 +1773,7 @@ "eo": "Paperkuntenilo", "es": "Clip", "et": "Kirjaklamber", + "fa": "گیره کاغذ", "fi": "Paperiliitin", "fr": "Trombone", "hr": "spajalica", @@ -1650,10 +1783,11 @@ "ja": "クリップ", "nb_NO": "BInders", "nl": "Papierklemmetje", + "pt": "Clipe", "pt_BR": "Clipe de papel", "ru": "Скрепка", "si": null, - "sk": "Sponka na papier", + "sk": "Kancelárska sponka", "sq": "Kapëse", "sr": "спајалица", "sv": "Gem", @@ -1661,7 +1795,8 @@ "tzm": null, "uk": "Спиначка", "vi": "Kẹp giấy", - "zh_Hans": "回形针" + "zh_Hans": "回形针", + "zh_Hant": "迴紋針" } }, { @@ -1678,6 +1813,7 @@ "eo": "Tondilo", "es": "Tijeras", "et": "Käärid", + "fa": "قیچی", "fi": "Sakset", "fr": "Ciseaux", "hr": "škare", @@ -1687,6 +1823,7 @@ "ja": "はさみ", "nb_NO": "Saks", "nl": "Schaar", + "pt": "Tesoura", "pt_BR": "Tesoura", "ru": "Ножницы", "si": null, @@ -1697,8 +1834,9 @@ "szl": null, "tzm": null, "uk": "Ножиці", - "vi": "Cây kéo", - "zh_Hans": "剪刀" + "vi": "Cái kéo", + "zh_Hans": "剪刀", + "zh_Hant": "剪刀" } }, { @@ -1715,6 +1853,7 @@ "eo": "Seruro", "es": "Candado", "et": "Lukk", + "fa": "قفل", "fi": "Lukko", "fr": "Cadenas", "hr": "zaključati", @@ -1724,10 +1863,11 @@ "ja": "錠前", "nb_NO": "Lås", "nl": "Slot", + "pt": "Cadeado", "pt_BR": "Cadeado", "ru": "Замок", "si": null, - "sk": "Zatvorená zámka", + "sk": "Zámka", "sq": "Dry", "sr": "катанац", "sv": "Lås", @@ -1735,7 +1875,8 @@ "tzm": null, "uk": "Замок", "vi": "Ổ khóa", - "zh_Hans": "锁" + "zh_Hans": "锁", + "zh_Hant": "鎖頭" } }, { @@ -1747,11 +1888,12 @@ "ar": "مِفتَاح", "bg": "Ключ", "ca": "Clau", - "cs": "Klíč", + "cs": "Klíč ke dveřím", "de": "Schlüssel", "eo": "Ŝlosilo", "es": "Llave", "et": "Võti", + "fa": "کلید", "fi": "Avain", "fr": "Clé", "hr": "ključ", @@ -1761,6 +1903,7 @@ "ja": "鍵", "nb_NO": "Nøkkel", "nl": "Sleutel", + "pt": "Chave", "pt_BR": "Chave", "ru": "Ключ", "si": null, @@ -1772,7 +1915,8 @@ "tzm": "Tasarut", "uk": "Ключ", "vi": "Chìa khóa", - "zh_Hans": "钥匙" + "zh_Hans": "钥匙", + "zh_Hant": "鑰匙" } }, { @@ -1789,6 +1933,7 @@ "eo": "Martelo", "es": "Martillo", "et": "Haamer", + "fa": "چکش", "fi": "Vasara", "fr": "Marteau", "hr": "čekić", @@ -1798,6 +1943,7 @@ "ja": "金槌", "nb_NO": "Hammer", "nl": "Hamer", + "pt": "Martelo", "pt_BR": "Martelo", "ru": "Молоток", "si": null, @@ -1809,7 +1955,8 @@ "tzm": null, "uk": "Молоток", "vi": "Búa", - "zh_Hans": "锤子" + "zh_Hans": "锤子", + "zh_Hant": "鎚子" } }, { @@ -1824,8 +1971,9 @@ "cs": "Telefon", "de": "Telefon", "eo": "Telefono", - "es": "Telefono", + "es": "Teléfono", "et": "Telefon", + "fa": "تلفن", "fi": "Puhelin", "fr": "Téléphone", "hr": "telefon", @@ -1835,6 +1983,7 @@ "ja": "電話機", "nb_NO": "Telefon", "nl": "Telefoon", + "pt": "Telefone", "pt_BR": "Telefone", "ru": "Телефон", "si": null, @@ -1846,7 +1995,8 @@ "tzm": "Atilifun", "uk": "Телефон", "vi": "Điện thoại", - "zh_Hans": "电话" + "zh_Hans": "电话", + "zh_Hant": "電話" } }, { @@ -1863,6 +2013,7 @@ "eo": "Flago", "es": "Bandera", "et": "Lipp", + "fa": "پرچم", "fi": "Lippu", "fr": "Drapeau", "hr": "zastava", @@ -1872,10 +2023,11 @@ "ja": "旗", "nb_NO": "Flagg", "nl": "Vlag", + "pt": "Bandeira", "pt_BR": "Bandeira", "ru": "Флаг", "si": null, - "sk": "Kockovaná zástava", + "sk": "Zástava", "sq": "Flamur", "sr": "застава", "sv": "Flagga", @@ -1883,7 +2035,8 @@ "tzm": "Acenyal", "uk": "Прапор", "vi": "Lá cờ", - "zh_Hans": "旗帜" + "zh_Hans": "旗帜", + "zh_Hant": "旗幟" } }, { @@ -1900,6 +2053,7 @@ "eo": "Vagonaro", "es": "Tren", "et": "Rong", + "fa": "قطار", "fi": "Juna", "fr": "Train", "hr": "vlak", @@ -1909,10 +2063,11 @@ "ja": "電車", "nb_NO": "Tog", "nl": "Trein", + "pt": "Comboio", "pt_BR": "Trem", "ru": "Поезд", "si": null, - "sk": "Rušeň", + "sk": "Vlak", "sq": "Tren", "sr": "воз", "sv": "Tåg", @@ -1920,7 +2075,8 @@ "tzm": null, "uk": "Потяг", "vi": "Xe lửa", - "zh_Hans": "火车" + "zh_Hans": "火车", + "zh_Hant": "火車" } }, { @@ -1937,6 +2093,7 @@ "eo": "Biciklo", "es": "Bicicleta", "et": "Jalgratas", + "fa": "دوچرخه", "fi": "Polkupyörä", "fr": "Vélo", "hr": "bicikl", @@ -1946,6 +2103,7 @@ "ja": "自転車", "nb_NO": "Sykkel", "nl": "Fiets", + "pt": "Bicicleta", "pt_BR": "Bicicleta", "ru": "Велосипед", "si": null, @@ -1957,7 +2115,8 @@ "tzm": null, "uk": "Велосипед", "vi": "Xe đạp", - "zh_Hans": "自行车" + "zh_Hans": "自行车", + "zh_Hant": "腳踏車" } }, { @@ -1974,6 +2133,7 @@ "eo": "Aviadilo", "es": "Avión", "et": "Lennuk", + "fa": "هواپیما", "fi": "Lentokone", "fr": "Avion", "hr": "avion", @@ -1983,6 +2143,7 @@ "ja": "飛行機", "nb_NO": "Fly", "nl": "Vliegtuig", + "pt": "Avião", "pt_BR": "Avião", "ru": "Самолет", "si": null, @@ -1994,7 +2155,8 @@ "tzm": null, "uk": "Літак", "vi": "Máy bay", - "zh_Hans": "飞机" + "zh_Hans": "飞机", + "zh_Hant": "飛機" } }, { @@ -2011,6 +2173,7 @@ "eo": "Raketo", "es": "Cohete", "et": "Rakett", + "fa": "موشک", "fi": "Raketti", "fr": "Fusée", "hr": "raketa", @@ -2020,6 +2183,7 @@ "ja": "ロケット", "nb_NO": "Rakett", "nl": "Raket", + "pt": "Foguetão", "pt_BR": "Foguete", "ru": "Ракета", "si": null, @@ -2031,7 +2195,8 @@ "tzm": null, "uk": "Ракета", "vi": "Tên lửa", - "zh_Hans": "火箭" + "zh_Hans": "火箭", + "zh_Hant": "火箭" } }, { @@ -2048,6 +2213,7 @@ "eo": "Trofeo", "es": "Trofeo", "et": "Auhind", + "fa": "جام", "fi": "Palkinto", "fr": "Trophée", "hr": "trofej", @@ -2057,6 +2223,7 @@ "ja": "トロフィー", "nb_NO": "Pokal", "nl": "Trofee", + "pt": "Troféu", "pt_BR": "Troféu", "ru": "Кубок", "si": null, @@ -2068,7 +2235,8 @@ "tzm": null, "uk": "Приз", "vi": "Cúp", - "zh_Hans": "奖杯" + "zh_Hans": "奖杯", + "zh_Hant": "獎盃" } }, { @@ -2085,6 +2253,7 @@ "eo": "Pilko", "es": "Bola", "et": "Pall", + "fa": "توپ", "fi": "Pallo", "fr": "Ballon", "hr": "lopta", @@ -2094,10 +2263,11 @@ "ja": "ボール", "nb_NO": "Ball", "nl": "Bal", + "pt": "Bola", "pt_BR": "Bola", "ru": "Мяч", "si": null, - "sk": "Futbal", + "sk": "Lopta", "sq": "Top", "sr": "лопта", "sv": "Boll", @@ -2105,7 +2275,8 @@ "tzm": "Tcama", "uk": "М'яч", "vi": "Banh", - "zh_Hans": "球" + "zh_Hans": "球", + "zh_Hant": "足球" } }, { @@ -2122,6 +2293,7 @@ "eo": "Gitaro", "es": "Guitarra", "et": "Kitarr", + "fa": "گیتار", "fi": "Kitara", "fr": "Guitare", "hr": "gitara", @@ -2131,6 +2303,7 @@ "ja": "ギター", "nb_NO": "Gitar", "nl": "Gitaar", + "pt": "Guitarra", "pt_BR": "Guitarra", "ru": "Гитара", "si": null, @@ -2142,7 +2315,8 @@ "tzm": "Agiṭaṛ", "uk": "Гітара", "vi": "Ghi-ta", - "zh_Hans": "吉他" + "zh_Hans": "吉他", + "zh_Hant": "吉他" } }, { @@ -2159,6 +2333,7 @@ "eo": "Trumpeto", "es": "Trompeta", "et": "Trompet", + "fa": "شیپور", "fi": "Trumpetti", "fr": "Trompette", "hr": "truba", @@ -2168,6 +2343,7 @@ "ja": "トランペット", "nb_NO": "Trompet", "nl": "Trompet", + "pt": "Trompete", "pt_BR": "Trombeta", "ru": "Труба", "si": null, @@ -2179,7 +2355,8 @@ "tzm": null, "uk": "Труба", "vi": "Kèn", - "zh_Hans": "喇叭" + "zh_Hans": "喇叭", + "zh_Hant": "喇叭" } }, { @@ -2196,6 +2373,7 @@ "eo": "Sonorilo", "es": "Campana", "et": "Kelluke", + "fa": "زنگ", "fi": "Soittokello", "fr": "Cloche", "hr": "zvono", @@ -2205,10 +2383,11 @@ "ja": "ベル", "nb_NO": "Bjelle", "nl": "Bel", + "pt": "Sino", "pt_BR": "Sino", "ru": "Колокол", "si": null, - "sk": "Zvon", + "sk": "Zvonec", "sq": "Kambanë", "sr": "звоно", "sv": "Bjällra", @@ -2216,7 +2395,8 @@ "tzm": null, "uk": "Дзвін", "vi": "Chuông", - "zh_Hans": "铃铛" + "zh_Hans": "铃铛", + "zh_Hant": "鈴鐺" } }, { @@ -2233,6 +2413,7 @@ "eo": "Ankro", "es": "Ancla", "et": "Ankur", + "fa": "لنگر", "fi": "Ankkuri", "fr": "Ancre", "hr": "sidro", @@ -2242,6 +2423,7 @@ "ja": "いかり", "nb_NO": "Anker", "nl": "Anker", + "pt": "Âncora", "pt_BR": "Âncora", "ru": "Якорь", "si": null, @@ -2253,7 +2435,8 @@ "tzm": null, "uk": "Якір", "vi": "Mỏ neo", - "zh_Hans": "锚" + "zh_Hans": "锚", + "zh_Hant": "船錨" } }, { @@ -2270,6 +2453,7 @@ "eo": "Kapaŭdilo", "es": "Cascos", "et": "Kõrvaklapid", + "fa": "هدفون", "fi": "Kuulokkeet", "fr": "Casque audio", "hr": "slušalice", @@ -2279,6 +2463,7 @@ "ja": "ヘッドホン", "nb_NO": "Hodetelefoner", "nl": "Koptelefoon", + "pt": "Fones", "pt_BR": "Fones de ouvido", "ru": "Наушники", "si": null, @@ -2290,7 +2475,8 @@ "tzm": null, "uk": "Навушники", "vi": "Tai nghe", - "zh_Hans": "耳机" + "zh_Hans": "耳机", + "zh_Hant": "耳機" } }, { @@ -2307,15 +2493,17 @@ "eo": "Dosierujo", "es": "Carpeta", "et": "Kaust", + "fa": "پوشه", "fi": "Kansio", "fr": "Dossier", "hr": "mapu", "hu": "Mappa", "id": "Map", "it": "Cartella", - "ja": "フォルダ", + "ja": "フォルダー", "nb_NO": "Mappe", "nl": "Map", + "pt": "Pasta", "pt_BR": "Pasta", "ru": "Папка", "si": null, @@ -2327,7 +2515,8 @@ "tzm": "Asdaw", "uk": "Тека", "vi": "Thư mục", - "zh_Hans": "文件夹" + "zh_Hans": "文件夹", + "zh_Hant": "資料夾" } }, { @@ -2344,6 +2533,7 @@ "eo": "Pinglo", "es": "Alfiler", "et": "Nööpnõel", + "fa": "سنجاق", "fi": "Nuppineula", "fr": "Punaise", "hr": "pribadača", @@ -2353,6 +2543,7 @@ "ja": "ピン", "nb_NO": "Tegnestift", "nl": "Duimspijker", + "pt": "Pionés", "pt_BR": "Alfinete", "ru": "Булавка", "si": null, @@ -2364,7 +2555,8 @@ "tzm": null, "uk": "Кнопка", "vi": "Ghim", - "zh_Hans": "图钉" + "zh_Hans": "图钉", + "zh_Hant": "圖釘" } } ] \ No newline at end of file diff --git a/data/api/application-service/definitions/protocol.yaml b/data/api/application-service/definitions/protocol.yaml index f29d72e8..c442a1b1 100644 --- a/data/api/application-service/definitions/protocol.yaml +++ b/data/api/application-service/definitions/protocol.yaml @@ -41,7 +41,6 @@ properties: type: string example: "mxc://example.org/aBcDeFgH" field_types: - title: Field Types description: |- The type definitions for the fields defined in the `user_fields` and `location_fields`. Each entry in those arrays MUST have an entry here. The @@ -64,7 +63,6 @@ properties: description: An placeholder serving as a valid example of the field value. type: string required: ['regexp', 'placeholder'] - required: ['fieldname'] example: { "network": { "regexp": "([a-z0-9]+\\.)*[a-z0-9]+", diff --git a/data/api/client-server/create_room.yaml b/data/api/client-server/create_room.yaml index 2188a370..3c04de00 100644 --- a/data/api/client-server/create_room.yaml +++ b/data/api/client-server/create_room.yaml @@ -209,7 +209,7 @@ paths: based on a preset. If unspecified, the server should use the `visibility` to determine - which preset to use. A visbility of `public` equates to a preset of + which preset to use. A visibility of `public` equates to a preset of `public_chat` and `private` visibility equates to a preset of `private_chat`. is_direct: diff --git a/data/api/client-server/cross_signing.yaml b/data/api/client-server/cross_signing.yaml index 2f038e80..15d093c2 100644 --- a/data/api/client-server/cross_signing.yaml +++ b/data/api/client-server/cross_signing.yaml @@ -150,7 +150,6 @@ paths: description: |- Publishes cross-signing signatures for the user. - The request body is a map from user ID to key ID to signed JSON object. The signed JSON object must match the key previously uploaded or retrieved for the given key ID, with the exception of the `signatures` property, which contains the new signature(s) to add. @@ -162,7 +161,8 @@ paths: application/json: schema: type: object - title: Signatures + description: |- + A map of user ID to a map of key ID to signed JSON object. additionalProperties: type: object additionalProperties: diff --git a/data/api/client-server/definitions/m.mentions.yaml b/data/api/client-server/definitions/m.mentions.yaml index 806897b4..271ee5c5 100644 --- a/data/api/client-server/definitions/m.mentions.yaml +++ b/data/api/client-server/definitions/m.mentions.yaml @@ -18,17 +18,13 @@ description: |- Describes whether the event mentions other users or the room. This is contained within the event's `content` alongside other fields for the relevant event type. example: { - "body": "Hello Alice!", - "msgtype": "m.text", - "format": "org.matrix.custom.html", - "formatted_body": "Hello Alice!", - "m.mentions": { - "user_ids": ["@alice:example.org"] - } + "user_ids": ["@alice:example.org"] } properties: user_ids: - type: string[] + type: array + items: + type: string description: A list of Matrix IDs of mentioned users. room: type: boolean diff --git a/data/api/client-server/definitions/push_condition.yaml b/data/api/client-server/definitions/push_condition.yaml index 8a3a9f32..4c35cfe4 100644 --- a/data/api/client-server/definitions/push_condition.yaml +++ b/data/api/client-server/definitions/push_condition.yaml @@ -23,8 +23,8 @@ properties: key: type: string description: |- - Required for `event_match` conditions. The dot-separated field of the - event to match. + Required for `event_match`, `event_property_is` and `event_property_contains` + conditions. The dot-separated field of the event to match. Required for `sender_notification_permission` conditions. The field in the power level event the user needs a minimum power level for. Fields @@ -43,5 +43,11 @@ properties: optionally prefixed by one of, ==, <, >, >= or <=. A prefix of < matches rooms where the member count is strictly less than the given number and so forth. If no prefix is present, this parameter defaults to ==. + value: + type: ["string", "integer", "boolean", "null"] + description: |- + Required for `event_property_is` and `event_property_contains` conditions. + A non-compound [canonical JSON](/appendices#canonical-json) value to match + against. required: - kind diff --git a/data/api/client-server/definitions/sso_login_flow.yaml b/data/api/client-server/definitions/sso_login_flow.yaml index ca2a6602..e30b18f9 100644 --- a/data/api/client-server/definitions/sso_login_flow.yaml +++ b/data/api/client-server/definitions/sso_login_flow.yaml @@ -15,7 +15,7 @@ type: object title: m.login.sso flow schema properties: type: - type: enum + type: string enum: ["m.login.sso"] description: The string `m.login.sso` example: "m.login.sso" diff --git a/data/api/client-server/keys.yaml b/data/api/client-server/keys.yaml index cb8a11db..3ec2a977 100644 --- a/data/api/client-server/keys.yaml +++ b/data/api/client-server/keys.yaml @@ -40,7 +40,7 @@ paths: one_time_keys: # $ref: "definitions/one_time_keys.yaml" # XXX: We can't define an actual object here, so we have to hope - # that people will look at the swagger source or can figure it out + # that people will look at the OpenAPI source or can figure it out # from the other endpoints/example. type: object title: OneTimeKeys @@ -52,7 +52,6 @@ paths: May be absent if no new one-time keys are required. example: - curve25519:AAAAAQ: /qyvZvwjiTxGdGU0RCguDCLeR+nmsb3FfNG3/Ve4vU8 signed_curve25519:AAAAHg: key: zKbLg+NrIjpnagy+pIY6uPL4ZwEG2v+8F9lmgsnlZzs signatures: @@ -84,7 +83,6 @@ paths: May be absent if a new fallback key is not required. example: - curve25519:AAAAAG: /qyvZvwjiTxGdGU0RCguDCLeR+nmsb3FfNG3/Ve4vU8 signed_curve25519:AAAAGj: key: zKbLg+NrIjpnagy+pIY6uPL4ZwEG2v+8F9lmgsnlZzs fallback: true @@ -111,7 +109,6 @@ paths: If an algorithm is not listed, the count for that algorithm is to be assumed zero. example: - curve25519: 10 signed_curve25519: 20 required: - one_time_key_counts diff --git a/data/api/client-server/list_public_rooms.yaml b/data/api/client-server/list_public_rooms.yaml index ba816b06..678f52ad 100644 --- a/data/api/client-server/list_public_rooms.yaml +++ b/data/api/client-server/list_public_rooms.yaml @@ -154,7 +154,7 @@ paths: name: server description: |- The server to fetch the public room lists from. Defaults to the - local server. + local server. Case sensitive. schema: type: string responses: @@ -181,7 +181,7 @@ paths: name: server description: |- The server to fetch the public room lists from. Defaults to the - local server. + local server. Case sensitive. schema: type: string requestBody: diff --git a/data/api/client-server/login_token.yaml b/data/api/client-server/login_token.yaml index 73e607d1..d31607fb 100644 --- a/data/api/client-server/login_token.yaml +++ b/data/api/client-server/login_token.yaml @@ -39,7 +39,7 @@ paths: In v1.7 of the specification, transmission of the generated token to an unauthenticated client is left as an implementation detail. Future MSCs such as [MSC3906](https://github.com/matrix-org/matrix-spec-proposals/pull/3906) - might standarise a way to transmit the token between clients. + might standardise a way to transmit the token between clients. The generated token MUST only be valid for a single login, enforced by the server. Clients which intend to log in multiple devices must generate a token for each. diff --git a/data/api/client-server/old_sync.yaml b/data/api/client-server/old_sync.yaml index 540c97c7..2d1e4f61 100644 --- a/data/api/client-server/old_sync.yaml +++ b/data/api/client-server/old_sync.yaml @@ -137,7 +137,7 @@ paths: type: array description: A list of presence events. items: - $ref: definitions/client_event.yaml + $ref: ../../event-schemas/schema/core-event-schema/event.yaml rooms: type: array items: @@ -219,7 +219,7 @@ paths: The private data that this user has attached to this room. items: - $ref: definitions/client_event.yaml + $ref: ../../event-schemas/schema/core-event-schema/event.yaml required: - room_id - membership @@ -227,10 +227,7 @@ paths: type: array description: The global private data created by this user. items: - title: Event - type: object - allOf: - - $ref: ../../event-schemas/schema/core-event-schema/event.yaml + $ref: ../../event-schemas/schema/core-event-schema/event.yaml required: - end - rooms diff --git a/data/api/client-server/registration.yaml b/data/api/client-server/registration.yaml index 1f823ac8..5679d02c 100644 --- a/data/api/client-server/registration.yaml +++ b/data/api/client-server/registration.yaml @@ -614,6 +614,26 @@ paths: it must return an `id_server_unbind_result` of `no-support`. example: example.org + erase: + x-addedInMatrixVersion: "1.10" + type: boolean + description: |- + Whether the user would like their content to be erased as + much as possible from the server. + + Erasure means that any users (or servers) which join the + room after the erasure request are served redacted copies of + the events sent by this account. Users which had visibility + on those events prior to the erasure are still able to see + unredacted copies. No redactions are sent and the erasure + request is not shared over federation, so other servers + might still serve unredacted copies. + + The server should additionally erase any non-event data + associated with the user, such as [account data](/client-server-api/#client-config) + and [contact 3PIDs](/client-server-api/#adding-account-administrative-contact-information). + + Defaults to `false` if not present. required: true responses: "200": diff --git a/data/api/client-server/report_content.yaml b/data/api/client-server/report_content.yaml index 5ea7b634..9241705a 100644 --- a/data/api/client-server/report_content.yaml +++ b/data/api/client-server/report_content.yaml @@ -18,10 +18,17 @@ info: paths: "/rooms/{roomId}/report/{eventId}": post: - summary: Reports an event as inappropriate. + summary: Report an event in a joined room as inappropriate. description: |- Reports an event as inappropriate to the server, which may then notify - the appropriate people. + the appropriate people. The caller must be joined to the room to report + it. + + It might be possible for clients to deduce whether an event exists by + timing the response, as only a report for an event that does exist + will require the homeserver to check whether a user is joined to + the room. To combat this, homeserver implementations should add + a random delay when generating a response. operationId: reportContent parameters: - in: path @@ -59,6 +66,9 @@ paths: required: true security: - accessToken: [] + x-changedInMatrixVersion: + 1.8: | + This endpoint now requires the user to be joined to the room. responses: "200": description: The event has been reported successfully. @@ -69,6 +79,23 @@ paths: examples: response: value: {} + "404": + description: |- + The event was not found or you are not joined to the room where the + event resides. + + Homeserver implementations can additionally return this error if the + reported event has been redacted. + content: + application/json: + schema: + $ref: definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_NOT_FOUND", + "error": "The event was not found or you are not joined to the room." + } tags: - Reporting content servers: diff --git a/data/api/server-server/definitions/event-schemas/m.device_list_update.yaml b/data/api/server-server/definitions/event-schemas/m.device_list_update.yaml index 81519e66..8bb8a7dd 100644 --- a/data/api/server-server/definitions/event-schemas/m.device_list_update.yaml +++ b/data/api/server-server/definitions/event-schemas/m.device_list_update.yaml @@ -31,7 +31,7 @@ allOf: - type: object properties: edu_type: - type: enum + type: string enum: ['m.device_list_update'] description: The string `m.device_list_update`. example: "m.device_list_update" diff --git a/data/api/server-server/definitions/event-schemas/m.direct_to_device.yaml b/data/api/server-server/definitions/event-schemas/m.direct_to_device.yaml index f628ebe0..6cb59fdd 100644 --- a/data/api/server-server/definitions/event-schemas/m.direct_to_device.yaml +++ b/data/api/server-server/definitions/event-schemas/m.direct_to_device.yaml @@ -23,7 +23,7 @@ allOf: - type: object properties: edu_type: - type: enum + type: string enum: ['m.direct_to_device'] description: The string `m.direct_to_device`. example: "m.direct_to_device" diff --git a/data/api/server-server/definitions/event-schemas/m.presence.yaml b/data/api/server-server/definitions/event-schemas/m.presence.yaml index 09d5d0d2..c79729e0 100644 --- a/data/api/server-server/definitions/event-schemas/m.presence.yaml +++ b/data/api/server-server/definitions/event-schemas/m.presence.yaml @@ -21,7 +21,7 @@ allOf: - type: object properties: edu_type: - type: enum + type: string enum: ['m.presence'] description: The string `m.presence` example: "m.presence" @@ -44,7 +44,7 @@ allOf: description: The user ID this presence EDU is for. example: "@john:matrix.org" presence: - type: enum + type: string enum: ['offline', 'unavailable', 'online'] description: The presence of the user. example: "online" diff --git a/data/api/server-server/definitions/event-schemas/m.receipt.yaml b/data/api/server-server/definitions/event-schemas/m.receipt.yaml index bbc3ac67..677dc28d 100644 --- a/data/api/server-server/definitions/event-schemas/m.receipt.yaml +++ b/data/api/server-server/definitions/event-schemas/m.receipt.yaml @@ -24,7 +24,7 @@ allOf: - type: object properties: edu_type: - type: enum + type: string enum: ['m.receipt'] description: The string `m.receipt` example: "m.receipt" @@ -41,41 +41,45 @@ allOf: # on. At that point, m.read can become optional (maybe). "m.read": type: object - description: Read receipts for users in the room. - title: User Read Receipt - properties: - event_ids: - type: array - description: |- - The extremity event IDs that the user has read up to. - minItems: 1 - maxItems: 1 - items: - type: string - example: ['$read_this_event:matrix.org'] - data: - type: object - description: Metadata for the read receipt. - title: Read Receipt Metadata - properties: - ts: - type: integer - format: int64 - description: |- - A POSIX timestamp in milliseconds for when the user read - the event specified in the read receipt. - example: 1533358089009 - thread_id: - type: string - x-addedInMatrixVersion: "1.4" + description: |- + Read receipts for users in the room. The string key is the user + ID the receipt belongs to. + additionalProperties: + type: object + title: User Read Receipt + properties: + event_ids: + type: array + description: |- + The extremity event IDs that the user has read up to. + minItems: 1 + maxItems: 1 + items: + type: string + example: ['$read_this_event:matrix.org'] + data: + type: object + description: Metadata for the read receipt. + title: Read Receipt Metadata + properties: + ts: + type: integer + format: int64 description: |- - The root thread event's ID (or `main`) for which - thread this receipt is intended to be under. If - not specified, the read receipt is *unthreaded* - (default). - example: "$threadroot" - required: ['ts'] - required: ['event_ids', 'data'] + A POSIX timestamp in milliseconds for when the user read + the event specified in the read receipt. + example: 1533358089009 + thread_id: + type: string + x-addedInMatrixVersion: "1.4" + description: |- + The root thread event's ID (or `main`) for which + thread this receipt is intended to be under. If + not specified, the read receipt is *unthreaded* + (default). + example: "$threadroot" + required: ['ts'] + required: ['event_ids', 'data'] required: ['m.read'] example: { "!some_room:example.org": { diff --git a/data/api/server-server/definitions/event-schemas/m.signing_key_update.yaml b/data/api/server-server/definitions/event-schemas/m.signing_key_update.yaml index aea99fe0..0748bc35 100644 --- a/data/api/server-server/definitions/event-schemas/m.signing_key_update.yaml +++ b/data/api/server-server/definitions/event-schemas/m.signing_key_update.yaml @@ -23,7 +23,7 @@ allOf: - type: object properties: edu_type: - type: enum + type: string enum: ['m.signing_key_update'] description: The string `m.signing_update`. example: "m.signing_key_update" diff --git a/data/api/server-server/definitions/event-schemas/m.typing.yaml b/data/api/server-server/definitions/event-schemas/m.typing.yaml index 7f23bae1..fa36a871 100644 --- a/data/api/server-server/definitions/event-schemas/m.typing.yaml +++ b/data/api/server-server/definitions/event-schemas/m.typing.yaml @@ -20,7 +20,7 @@ allOf: - type: object properties: edu_type: - type: enum + type: string enum: ['m.typing'] description: The string `m.typing` example: "m.typing" diff --git a/data/api/server-server/definitions/pdu.yaml b/data/api/server-server/definitions/pdu.yaml index d87db1a3..5903f80e 100644 --- a/data/api/server-server/definitions/pdu.yaml +++ b/data/api/server-server/definitions/pdu.yaml @@ -20,6 +20,10 @@ allOf: - $ref: "unsigned_pdu.yaml" - type: object properties: + redacts: + type: string + description: For redaction events, the ID of the event being redacted. + example: "$def456:matrix.org" hashes: type: object title: Event Hash diff --git a/data/api/server-server/definitions/pdu_v11.yaml b/data/api/server-server/definitions/pdu_v11.yaml new file mode 100644 index 00000000..3edfb6c8 --- /dev/null +++ b/data/api/server-server/definitions/pdu_v11.yaml @@ -0,0 +1,81 @@ +# Copyright 2019-2023 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +type: object +title: Persistent Data Unit +description: A persistent data unit (event) for room version 11 and beyond. +example: + $ref: "../examples/pdu_v11.json" +allOf: + # v11 is the v4 event, but without redacts. Copy the auth_events/prev_events + # from pdu_v4.yaml and hashes and signatures from pdu_v3.yaml. + - $ref: "unsigned_pdu_base.yaml" + - type: object + properties: + auth_events: + type: array + items: + type: string + description: Event ID. + description: |- + Event IDs for the authorization events that would + allow this event to be in the room. + + Must contain less than or equal to 10 events. Note that if the relevant + auth event selection rules are used, this restriction should never be + encountered. + example: ["$URLsafe-base64EncodedHash", "$Another_Event"] + prev_events: + type: array + items: + type: string + description: Event ID. + description: |- + Event IDs for the most recent events in the room + that the homeserver was aware of when it made this event. + + Must contain less than or equal to 20 events. + example: ["$URLsafe-base64EncodedHash", "$Another_Event"] + hashes: + type: object + title: Event Hash + description: |- + Content hashes of the PDU, following the algorithm specified in [Signing Events](/server-server-api/#signing-events). + example: { + "sha256": "ThisHashCoversAllFieldsInCaseThisIsRedacted" + } + properties: + sha256: + type: string + description: The hash. + example: ThisHashCoversAllFieldsInCaseThisIsRedacted + required: ['sha256'] + signatures: + type: object + description: |- + Signatures for the PDU, following the algorithm specified in [Signing Events](/server-server-api/#signing-events). + example: { + "example.com": { + "ed25519:key_version:": "86BytesOfSignatureOfTheRedactedEvent" + } + } + additionalProperties: + type: object + title: Server Signatures + additionalProperties: + type: string + required: + - auth_events + - prev_events + - hashes + - signatures diff --git a/data/api/server-server/definitions/unsigned_pdu_base.yaml b/data/api/server-server/definitions/unsigned_pdu_base.yaml index c21149f6..ce42236f 100644 --- a/data/api/server-server/definitions/unsigned_pdu_base.yaml +++ b/data/api/server-server/definitions/unsigned_pdu_base.yaml @@ -107,10 +107,6 @@ properties: description: The event hash. example: Base64EncodedSha256HashesShouldBe43BytesLong required: ['sha256'] - redacts: - type: string - description: For redaction events, the ID of the event being redacted. - example: "$def456:matrix.org" unsigned: type: object title: UnsignedData diff --git a/data/api/server-server/examples/pdu_v11.json b/data/api/server-server/examples/pdu_v11.json new file mode 100644 index 00000000..292f38a0 --- /dev/null +++ b/data/api/server-server/examples/pdu_v11.json @@ -0,0 +1,19 @@ +{ + "$ref": "unsigned_pdu_base.json", + "hashes": { + "sha256": "thishashcoversallfieldsincasethisisredacted" + }, + "signatures": { + "example.com": { + "ed25519:key_version:": "these86bytesofbase64signaturecoveressentialfieldsincludinghashessocancheckredactedpdus" + } + }, + "auth_events": [ + "$urlsafe_base64_encoded_eventid", + "$a-different-event-id" + ], + "prev_events": [ + "$urlsafe_base64_encoded_eventid", + "$a-different-event-id" + ] +} diff --git a/data/api/server-server/joins-v2.yaml b/data/api/server-server/joins-v2.yaml index 32819193..1182e100 100644 --- a/data/api/server-server/joins-v2.yaml +++ b/data/api/server-server/joins-v2.yaml @@ -27,7 +27,7 @@ paths: exception of the response format being fixed. This endpoint is preferred over the v1 API as it provides - a more standarised response format. Senders which receive + a more standardised response format. Senders which receive a 400, 404, or other status code which indicates this endpoint is not available should retry using the v1 API instead. diff --git a/data/api/server-server/leaving-v2.yaml b/data/api/server-server/leaving-v2.yaml index b79ce008..60064cfc 100644 --- a/data/api/server-server/leaving-v2.yaml +++ b/data/api/server-server/leaving-v2.yaml @@ -27,7 +27,7 @@ paths: exception of the response format being fixed. This endpoint is preferred over the v1 API as it provides - a more standarised response format. Senders which receive + a more standardised response format. Senders which receive a 400, 404, or other status code which indicates this endpoint is not available should retry using the v1 API instead. diff --git a/data/api/server-server/query.yaml b/data/api/server-server/query.yaml index 23a6dffd..8d727a57 100644 --- a/data/api/server-server/query.yaml +++ b/data/api/server-server/query.yaml @@ -121,7 +121,7 @@ paths: parameters: - in: query name: user_id - description: The user ID to query. + description: The user ID to query. Must be a user local to the receiving homeserver. required: true example: "@someone:example.org" schema: diff --git a/data/api/server-server/user_keys.yaml b/data/api/server-server/user_keys.yaml index fb598e94..be50fcea 100644 --- a/data/api/server-server/user_keys.yaml +++ b/data/api/server-server/user_keys.yaml @@ -34,7 +34,8 @@ paths: type: object description: |- The keys to be claimed. A map from user ID, to a map from - device ID to algorithm name. + device ID to algorithm name. Requested users must be local + to the receiving homeserver. additionalProperties: type: object additionalProperties: @@ -121,7 +122,8 @@ paths: description: |- The keys to be downloaded. A map from user ID, to a list of device IDs, or to an empty list to indicate all devices for the - corresponding user. + corresponding user. Requested users must be local to the + receiving homeserver. additionalProperties: type: array items: diff --git a/data/event-schemas/examples/m.call.negotiate.yaml b/data/event-schemas/examples/m.call.negotiate.yaml index 3120ee54..aaf9daf2 100644 --- a/data/event-schemas/examples/m.call.negotiate.yaml +++ b/data/event-schemas/examples/m.call.negotiate.yaml @@ -6,7 +6,7 @@ "party_id": "67890", "call_id": "12345", "lifetime": 10000, - "offer": { + "description": { "type" : "offer", "sdp" : "v=0\r\no=- 6584580628695956864 2 IN IP4 127.0.0.1[...]" }, diff --git a/data/event-schemas/examples/m.receipt.yaml b/data/event-schemas/examples/m.receipt.yaml index 17e5a67e..f09872b5 100644 --- a/data/event-schemas/examples/m.receipt.yaml +++ b/data/event-schemas/examples/m.receipt.yaml @@ -4,7 +4,7 @@ "content": { "$1435641916114394fHBLK:matrix.org": { "m.read": { - "@rikj:jki.re": { + "@erikj:jki.re": { "ts": 1436451550453 } }, diff --git a/data/event-schemas/examples/m.room.create.yaml b/data/event-schemas/examples/m.room.create.yaml index e33dbc3b..390ea78d 100644 --- a/data/event-schemas/examples/m.room.create.yaml +++ b/data/event-schemas/examples/m.room.create.yaml @@ -3,8 +3,7 @@ "type": "m.room.create", "state_key": "", "content": { - "creator": "@example:example.org", - "room_version": "1", + "room_version": "11", "m.federate": true, "predecessor": { "event_id": "$something:example.org", diff --git a/data/event-schemas/examples/m.room.redaction.yaml b/data/event-schemas/examples/m.room.redaction.yaml index 42bc8411..457b0a37 100644 --- a/data/event-schemas/examples/m.room.redaction.yaml +++ b/data/event-schemas/examples/m.room.redaction.yaml @@ -1,8 +1,8 @@ { "$ref": "core/room_event.json", "type": "m.room.redaction", - "redacts": "$fukweghifu23:localhost", "content": { + "redacts": "$fukweghifu23:localhost", "reason": "Spamming" } } diff --git a/data/event-schemas/schema/core-event-schema/msgtype_infos/image_info.yaml b/data/event-schemas/schema/core-event-schema/msgtype_infos/image_info.yaml index 9607d6fd..7cbfcc87 100644 --- a/data/event-schemas/schema/core-event-schema/msgtype_infos/image_info.yaml +++ b/data/event-schemas/schema/core-event-schema/msgtype_infos/image_info.yaml @@ -1,4 +1,3 @@ -$schema: http://json-schema.org/draft-04/schema# description: Metadata about an image. properties: h: diff --git a/data/event-schemas/schema/core-event-schema/msgtype_infos/thumbnail_info.yaml b/data/event-schemas/schema/core-event-schema/msgtype_infos/thumbnail_info.yaml index 79f7c253..31a3b1b2 100644 --- a/data/event-schemas/schema/core-event-schema/msgtype_infos/thumbnail_info.yaml +++ b/data/event-schemas/schema/core-event-schema/msgtype_infos/thumbnail_info.yaml @@ -1,4 +1,3 @@ -$schema: http://json-schema.org/draft-04/schema# description: Metadata about a thumbnail image. properties: h: diff --git a/data/event-schemas/schema/m.call.negotiate.yaml b/data/event-schemas/schema/m.call.negotiate.yaml index f34d6502..2fb4b0aa 100644 --- a/data/event-schemas/schema/m.call.negotiate.yaml +++ b/data/event-schemas/schema/m.call.negotiate.yaml @@ -42,15 +42,16 @@ properties: allOf: - "$ref": core-event-schema/call_event.yaml properties: - offer: + description: type: object - title: Offer + title: Description description: The session description object properties: type: type: string enum: - offer + - answer description: The type of session description. sdp: type: string @@ -60,10 +61,8 @@ properties: - sdp lifetime: type: integer - description: The time in milliseconds that the invite is valid for. - Once the invite age exceeds this value, clients should discard it. - They should also no longer show the call as awaiting an answer in the - UI. + description: The time in milliseconds that the negotiation is valid for. + Once the negotiation age exceeds this value, clients should discard it. sdp_stream_metadata: type: object title: SDP Stream Metadata @@ -82,7 +81,7 @@ properties: - purpose required: - - offer + - description - lifetime type: type: string diff --git a/data/event-schemas/schema/m.direct.yaml b/data/event-schemas/schema/m.direct.yaml index f00b83bc..3256b574 100644 --- a/data/event-schemas/schema/m.direct.yaml +++ b/data/event-schemas/schema/m.direct.yaml @@ -11,10 +11,12 @@ properties: content: additionalProperties: type: array - title: User ID items: type: string type: object + description: |- + The mapping of user ID to a list of room IDs of the 'direct' rooms for + that user ID. type: enum: - m.direct diff --git a/data/event-schemas/schema/m.ignored_user_list.yaml b/data/event-schemas/schema/m.ignored_user_list.yaml index 0f0b2f85..32cc6a46 100644 --- a/data/event-schemas/schema/m.ignored_user_list.yaml +++ b/data/event-schemas/schema/m.ignored_user_list.yaml @@ -10,12 +10,12 @@ properties: properties: ignored_users: type: object - title: "Ignored users" - description: "The map of users to ignore" + description: |- + The map of users to ignore. This is a mapping of user ID to empty + object. patternProperties: "^@": type: "object" - title: "Ignored User" description: "An empty object for future enhancement" x-pattern: "$USER_ID" required: diff --git a/data/event-schemas/schema/m.receipt.yaml b/data/event-schemas/schema/m.receipt.yaml index 6062d31f..702191d1 100644 --- a/data/event-schemas/schema/m.receipt.yaml +++ b/data/event-schemas/schema/m.receipt.yaml @@ -9,22 +9,24 @@ allOf: properties: content: type: object + description: |- + The mapping of event ID to a collection of receipts for this + event ID. The event ID is the ID of the event being acknowledged + and *not* an ID for the receipt itself. patternProperties: "^\\$": type: object x-pattern: "$EVENT_ID" - title: Receipts + title: Event Receipts description: |- - The mapping of event ID to a collection of receipts for this - event ID. The event ID is the ID of the event being acknowledged - and *not* an ID for the receipt itself. + The collection of receipts for this event ID. properties: "m.read": type: object - title: Users description: |- A collection of users who have sent `m.read` receipts for - this event. + this event. The string key is the user ID the receipt + belongs to. patternProperties: "^@": &receiptUserMap type: object @@ -48,7 +50,6 @@ properties: (default). "m.read.private": type: object - title: Own User description: |- Similar to `m.read`, the users who have sent `m.read.private` receipts for this event. Due to the nature of private read diff --git a/data/event-schemas/schema/m.room.create.yaml b/data/event-schemas/schema/m.room.create.yaml index 44c9c84e..1ca37865 100644 --- a/data/event-schemas/schema/m.room.create.yaml +++ b/data/event-schemas/schema/m.room.create.yaml @@ -6,7 +6,9 @@ properties: content: properties: creator: - description: The `user_id` of the room creator. This is set by the homeserver. + description: |- + The `user_id` of the room creator. **Required** for, and only present in, room versions 1 - 10. Starting with + room version 11 the event `sender` should be used instead. type: string m.federate: description: Whether users on other servers can join this room. Defaults to `true` if key does not exist. @@ -32,8 +34,6 @@ properties: type: string description: The event ID of the last known event in the old room. required: [room_id, event_id] - required: - - creator type: object state_key: description: A zero-length string. diff --git a/data/event-schemas/schema/m.room.message$m.audio.yaml b/data/event-schemas/schema/m.room.message$m.audio.yaml index 6cf742e4..825419bd 100644 --- a/data/event-schemas/schema/m.room.message$m.audio.yaml +++ b/data/event-schemas/schema/m.room.message$m.audio.yaml @@ -6,8 +6,29 @@ properties: content: properties: body: - description: "A description of the audio e.g. 'Bee Gees - Stayin' Alive', or some kind of content description for accessibility e.g. 'audio attachment'." + description: |- + If `filename` is not set or the value of both properties are + identical, this is the filename of the original upload. Otherwise, + this is a caption for the audio. type: string + x-changedInMatrixVersion: + "1.10": This property can act as a caption for the audio. + format: + description: |- + The format used in the `formatted_body`. Currently only + `org.matrix.custom.html` is supported. + type: string + x-addedInMatrixVersion: "1.10" + formatted_body: + description: |- + The formatted version of the `body`, when it acts as a caption. This + is required if `format` is specified. + type: string + x-addedInMatrixVersion: "1.10" + filename: + description: The original filename of the uploaded file. + type: string + x-addedInMatrixVersion: "1.10" info: description: Metadata for the audio clip referred to in `url`. properties: diff --git a/data/event-schemas/schema/m.room.message$m.file.yaml b/data/event-schemas/schema/m.room.message$m.file.yaml index af181964..8e269366 100644 --- a/data/event-schemas/schema/m.room.message$m.file.yaml +++ b/data/event-schemas/schema/m.room.message$m.file.yaml @@ -6,8 +6,25 @@ properties: content: properties: body: - description: A human-readable description of the file. This is recommended to be the filename of the original upload. + description: |- + If `filename` is not set or the value of both properties are + identical, this is the filename of the original upload. Otherwise, + this is a caption for the file. type: string + x-changedInMatrixVersion: + "1.10": This property can act as a caption for the file. + format: + description: |- + The format used in the `formatted_body`. Currently only + `org.matrix.custom.html` is supported. + type: string + x-addedInMatrixVersion: "1.10" + formatted_body: + description: |- + The formatted version of the `body`, when it acts as a caption. This + is required if `format` is specified. + type: string + x-addedInMatrixVersion: "1.10" filename: description: The original filename of the uploaded file. type: string diff --git a/data/event-schemas/schema/m.room.message$m.image.yaml b/data/event-schemas/schema/m.room.message$m.image.yaml index 91985ed0..15bdeda4 100644 --- a/data/event-schemas/schema/m.room.message$m.image.yaml +++ b/data/event-schemas/schema/m.room.message$m.image.yaml @@ -6,8 +6,29 @@ properties: content: properties: body: - description: "A textual representation of the image. This could be the alt text of the image, the filename of the image, or some kind of content description for accessibility e.g. 'image attachment'." + description: |- + If `filename` is not set or the value of both properties are + identical, this is the filename of the original upload. Otherwise, + this is a caption for the image. type: string + x-changedInMatrixVersion: + "1.10": This property can act as a caption for the image. + format: + description: |- + The format used in the `formatted_body`. Currently only + `org.matrix.custom.html` is supported. + type: string + x-addedInMatrixVersion: "1.10" + formatted_body: + description: |- + The formatted version of the `body`, when it acts as a caption. This + is required if `format` is specified. + type: string + x-addedInMatrixVersion: "1.10" + filename: + description: The original filename of the uploaded file. + type: string + x-addedInMatrixVersion: "1.10" info: allOf: - $ref: core-event-schema/msgtype_infos/image_info.yaml diff --git a/data/event-schemas/schema/m.room.message$m.video.yaml b/data/event-schemas/schema/m.room.message$m.video.yaml index e3b782b8..75752534 100644 --- a/data/event-schemas/schema/m.room.message$m.video.yaml +++ b/data/event-schemas/schema/m.room.message$m.video.yaml @@ -6,8 +6,29 @@ properties: content: properties: body: - description: "A description of the video e.g. 'Gangnam style', or some kind of content description for accessibility e.g. 'video attachment'." + description: |- + If `filename` is not set or the value of both properties are + identical, this is the filename of the original upload. Otherwise, + this is a caption for the video. type: string + x-changedInMatrixVersion: + "1.10": This property can act as a caption for the video. + format: + description: |- + The format used in the `formatted_body`. Currently only + `org.matrix.custom.html` is supported. + type: string + x-addedInMatrixVersion: "1.10" + formatted_body: + description: |- + The formatted version of the `body`, when it acts as a caption. This + is required if `format` is specified. + type: string + x-addedInMatrixVersion: "1.10" + filename: + description: The original filename of the uploaded file. + type: string + x-addedInMatrixVersion: "1.10" info: description: Metadata about the video clip referred to in `url`. properties: diff --git a/data/event-schemas/schema/m.room.name.yaml b/data/event-schemas/schema/m.room.name.yaml index c9236de0..0b3b34dc 100644 --- a/data/event-schemas/schema/m.room.name.yaml +++ b/data/event-schemas/schema/m.room.name.yaml @@ -7,9 +7,8 @@ description: |- is a human-friendly string designed to be displayed to the end-user. The room name is not unique, as multiple rooms can have the same room name set. - A room with an `m.room.name` event with an absent, null, or empty - `name` field should be treated the same as a room with no `m.room.name` - event. + If a room has an `m.room.name` event with an absent, null, or empty `name` + field, it should be treated the same as a room with no `m.room.name` event. An event of this type is automatically created when creating a room using `/createRoom` with the `name` key. diff --git a/data/event-schemas/schema/m.room.redaction.yaml b/data/event-schemas/schema/m.room.redaction.yaml index 143e7eff..8a7edeba 100644 --- a/data/event-schemas/schema/m.room.redaction.yaml +++ b/data/event-schemas/schema/m.room.redaction.yaml @@ -5,18 +5,19 @@ description: 'This event is created by the server to describe which event has be properties: content: properties: + redacts: + description: The event ID that was redacted. Required for, and present starting in, room version 11. + type: string reason: description: 'The reason for the redaction, if any.' type: string type: object redacts: - description: The event ID that was redacted. + description: Required for, and only present in, room versions 1 - 10. The event ID that was redacted. type: string type: enum: - m.room.redaction type: string -required: - - redacts title: Redaction type: object diff --git a/data/event-schemas/schema/m.room.third_party_invite.yaml b/data/event-schemas/schema/m.room.third_party_invite.yaml index 7a00616b..bb4883f5 100644 --- a/data/event-schemas/schema/m.room.third_party_invite.yaml +++ b/data/event-schemas/schema/m.room.third_party_invite.yaml @@ -1,5 +1,4 @@ --- -$schema: http://json-schema.org/draft-04/schema# allOf: - $ref: core-event-schema/state_event.yaml description: "Acts as an `m.room.member` invite event, where there isn't a target user_id to invite. This event contains a token and a public key whose private key must be used to sign the token. Any user who can present that signature may use this invitation to join the target room." diff --git a/data/event-schemas/schema/m.space.child.yaml b/data/event-schemas/schema/m.space.child.yaml index feef0adc..c73d440f 100644 --- a/data/event-schemas/schema/m.space.child.yaml +++ b/data/event-schemas/schema/m.space.child.yaml @@ -34,6 +34,8 @@ properties: Optional (default `false`) flag to denote whether the child is "suggested" or of interest to members of the space. This is primarily intended as a rendering hint for clients to display the room differently, such as eagerly rendering them in the room list. + required: + - via type: object state_key: description: The child room ID being described. diff --git a/data/event-schemas/schema/m.space.parent.yaml b/data/event-schemas/schema/m.space.parent.yaml index ced24d70..fb633789 100644 --- a/data/event-schemas/schema/m.space.parent.yaml +++ b/data/event-schemas/schema/m.space.parent.yaml @@ -20,6 +20,8 @@ properties: When multiple `canonical` parents are found, the lowest parent when ordering by room ID lexicographically by Unicode code-points should be used. + required: + - via type: object state_key: description: The parent room ID. diff --git a/go.mod b/go.mod new file mode 100644 index 00000000..7988b29f --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/matrix-org/matrix-spec + +go 1.12 + +require github.com/matrix-org/docsy v0.0.0-20231227121313-d55dbaf3aaaf // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 00000000..1fb47ebd --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/FortAwesome/Font-Awesome v0.0.0-20230327165841-0698449d50f2/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo= +github.com/matrix-org/docsy v0.0.0-20231227121313-d55dbaf3aaaf h1:e1mutHvMYJ92F/VkAp2ixQthXf6zNHJll4wYGbBHznI= +github.com/matrix-org/docsy v0.0.0-20231227121313-d55dbaf3aaaf/go.mod h1:TAN2cSMJzy0hnx9OYDbBYluS8raV61UHxT/tfjaLt3g= +github.com/twbs/bootstrap v5.2.3+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0= diff --git a/layouts/partials/breadcrumb.html b/layouts/partials/breadcrumb.html index 8e1fb9b2..af3a9551 100644 --- a/layouts/partials/breadcrumb.html +++ b/layouts/partials/breadcrumb.html @@ -8,8 +8,8 @@ */}} {{ if not .IsHome }} -