diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3bcc6010..92b841f4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,8 +1,9 @@ name: "Spec" env: - HUGO_VERSION: 0.148.1 + HUGO_VERSION: 0.153.3 PYTHON_VERSION: 3.13 + NODE_VERSION: 24 on: push: @@ -27,7 +28,7 @@ jobs: - name: "βž• Setup Node" uses: actions/setup-node@v4 with: - node-version: '20' + node-version: ${{ env.NODE_VERSION }} - name: "πŸ”Ž Run validator" run: | npx @redocly/cli@latest lint data/api/*/*.yaml @@ -195,11 +196,13 @@ jobs: needs: [calculate-baseurl, build-openapi, generate-changelog] # run even if generate-changelog was skipped if: ${{ always() }} + env: + baseURL: "${{ needs.calculate-baseurl.outputs.baseURL }}" steps: - name: "βž• Setup Node" uses: actions/setup-node@v4 with: - node-version: '20' + node-version: ${{ env.NODE_VERSION }} - name: "βž• Setup Hugo" uses: peaceiris/actions-hugo@75d2e84710de30f6ff7268e08f310b60ef14033f # v3.0.0 with: @@ -217,8 +220,10 @@ jobs: with: name: changelog-artifact path: content/changelog + - name: "βš™οΈ hugo" - run: hugo --baseURL "${{ needs.calculate-baseurl.outputs.baseURL }}" -d "spec" + run: hugo --baseURL "${baseURL}" -d "spec${baseURL}" + # We manually unpack the spec OpenAPI definition JSON to the website tree # to make it available to the world in a canonical place: # https://spec.matrix.org/latest/client-server-api/api.json @@ -229,10 +234,13 @@ jobs: name: openapi-artifact - name: "πŸ“ Unpack the OpenAPI definitions in the right location" run: | - tar -xzf openapi.tar.gz + tar -C "spec${baseURL}" --strip-components=1 -xzf openapi.tar.gz - name: "πŸ“¦ Tarball creation" - run: tar -czf spec.tar.gz spec + run: | + cd spec + tar -czf ../spec.tar.gz * + - name: "πŸ“€ Artifact upload" uses: actions/upload-artifact@v4 with: @@ -243,6 +251,14 @@ jobs: name: "πŸ”Ž Validate generated HTML" runs-on: ubuntu-latest needs: [calculate-baseurl, build-spec] + # Run even if `generate-changelog` was skipped. + # + # `build-spec` has a dependency on `generate-changelog` to ensure order of execution + # and to access `needs.generate-changelog.result`. However, `generate-changelog` is + # skipped on tag builds; even a transient dependency on `generate-changelog` is then + # enough for this step to also be skipped by default on tag builds. Hence the need for + # this explicit `if`. + if: ${{ !failure() && !cancelled() }} steps: - name: "πŸ“₯ Source checkout" uses: actions/checkout@v4 @@ -253,14 +269,9 @@ jobs: name: spec-artifact - name: "πŸ“ Unpack the spec" - # we have to unpack it into the right path given the baseurl, so that the - # links are correct. - # eg if baseurl is `/unstable`, we want to put the site in `spec/unstable`. run: | - mkdir -p "spec${baseURL}" - tar -C "spec${baseURL}" --strip-components=1 -xvzf spec.tar.gz - env: - baseURL: "${{ needs.calculate-baseurl.outputs.baseURL }}" + mkdir spec + tar -C spec -xvzf spec.tar.gz - name: "Run htmltest" uses: wjdp/htmltest-action@master @@ -270,13 +281,15 @@ jobs: build-historical-spec: name: "πŸ“– Build the historical backup spec" runs-on: ubuntu-latest - needs: [build-openapi] + needs: [calculate-baseurl, build-openapi] if: ${{ startsWith(github.ref, 'refs/tags/') }} + env: + baseURL: "${{ needs.calculate-baseurl.outputs.baseURL }}" steps: - name: "βž• Setup Node" uses: actions/setup-node@v4 with: - node-version: '20' + node-version: ${{ env.NODE_VERSION }} - name: "βž• Setup Hugo" uses: peaceiris/actions-hugo@75d2e84710de30f6ff7268e08f310b60ef14033f # v3.0.0 with: @@ -291,9 +304,8 @@ jobs: - name: "βš™οΈ hugo" env: HUGO_PARAMS_VERSION_STATUS: "historical" - # Create a baseURL like `/v1.2` out of the `v1.2` tag run: | - hugo --baseURL "/${GITHUB_REF/refs\/tags\//}" -d "spec" + hugo --baseURL "${baseURL}" -d "spec${baseURL}" - name: "πŸ“₯ Spec definition download" uses: actions/download-artifact@v4 @@ -301,12 +313,51 @@ jobs: name: openapi-artifact - name: "πŸ“ Unpack the OpenAPI definitions in the right location" run: | - tar -xzf openapi.tar.gz + tar -C "spec${baseURL}" --strip-components=1 -xzf openapi.tar.gz - name: "πŸ“¦ Tarball creation" - run: tar -czf spec-historical.tar.gz spec + run: | + cd spec + tar -czf ../spec-historical.tar.gz * + - name: "πŸ“€ Artifact upload" uses: actions/upload-artifact@v4 with: name: spec-historical-artifact path: spec-historical.tar.gz + + # If we're building a tag, create a release and publish the artifacts + create_release: + name: "Create release" + if: ${{ !failure() && !cancelled() && startsWith(github.ref, 'refs/tags/') }} + needs: + - build-spec + - build-historical-spec + runs-on: ubuntu-latest + steps: + - name: "πŸ“₯ Check out changelogs" + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + with: + sparse-checkout: | + content/changelog + - name: "πŸ“₯ Download built spec" + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + with: + name: spec-artifact + - name: "πŸ“₯ Download historical spec artifact" + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + with: + name: spec-historical-artifact + - name: "✨ Create draft release" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Remove front-matter from changelog + sed '1,/^---$/d' "content/changelog/${{ github.ref_name }}.md" > changelog.md + + # Create a draft release, using the changelog as release notes, and attaching the spec artifacts. + gh release create -d -t "${{ github.ref_name }}" \ + -F "changelog.md" \ + "${{ github.ref_name }}" \ + spec.tar.gz \ + spec-historical.tar.gz diff --git a/.github/workflows/netlify.yaml b/.github/workflows/netlify.yaml index 7c59f64c..6b4258a1 100644 --- a/.github/workflows/netlify.yaml +++ b/.github/workflows/netlify.yaml @@ -45,7 +45,9 @@ jobs: name: spec-artifact - name: "πŸ“¦ Extract Artifacts" - run: tar -xzvf spec.tar.gz && rm spec.tar.gz + run: | + mkdir spec + tar -C spec -xzvf spec.tar.gz && rm spec.tar.gz - name: "πŸ“€ Deploy to Netlify" id: netlify diff --git a/assets/js/toc.js b/assets/js/toc.js index 89a83ced..a7103f9d 100644 --- a/assets/js/toc.js +++ b/assets/js/toc.js @@ -50,7 +50,7 @@ function getHeadings() { let headings = []; // First get the anchors in the ToC. - const toc_anchors = document.querySelectorAll("#toc nav a"); + const toc_anchors = document.querySelectorAll("#TableOfContents a"); for (const anchor of toc_anchors) { // Then get the heading from its selector in the anchor's href. @@ -59,7 +59,7 @@ function getHeadings() { console.error("Got ToC anchor without href"); continue; } - + const heading = document.querySelector(selector); if (!heading) { console.error("Heading not found for selector:", selector); @@ -122,13 +122,13 @@ function getCurrentHeading(headings, headerOffset) { */ function selectTocEntry(id) { // Deselect previously selected entries. - const activeEntries = document.querySelectorAll("#toc nav a.active"); + const activeEntries = document.querySelectorAll("#TableOfContents a.active"); for (const activeEntry of activeEntries) { activeEntry.classList.remove('active'); } // Find the new entry and select it. - const newEntry = document.querySelector(`#toc nav a[href="#${id}"]`); + const newEntry = document.querySelector(`#TableOfContents a[href="#${id}"]`); if (!newEntry) { console.error("ToC entry not found for ID:", id); return; diff --git a/assets/scss/_styles_project.scss b/assets/scss/_styles_project.scss index 0131f1f1..cd9937a9 100644 --- a/assets/scss/_styles_project.scss +++ b/assets/scss/_styles_project.scss @@ -76,52 +76,126 @@ Custom SCSS for the Matrix spec scroll-behavior: smooth; overscroll-behavior: contain; - &>.td-sidebar-nav__section { + & > .td-sidebar-nav__section { margin-top: 1rem; - } - .td-sidebar-nav__section .ul-1 ul { - padding-left: 0; - } - - /* This is to make the width of the items that have sub-items (like room versions) - the same as the width of items that don't (like changelog) */ - .pr-md-3, .px-md-3 { - padding-right: 0 !important; - } - - .ul-1 > li > a { - padding-left: 1rem !important; - } - - .ul-2 > li > a { - padding-left: 2rem !important; - } - - a.td-sidebar-link.tree-root { - color: $gray-800; - font-weight: $font-weight-bold; - font-size: 1.3rem; - margin-bottom: 0; - border-bottom: none; - } - - a, a.td-sidebar-link { - color: $gray-800; - font-weight: $font-weight-normal; - padding-top: .2rem; - padding-bottom: .2rem; - - display: block; - transition: all 100ms ease-in-out; - - &:hover { - background-color: $secondary-lighter-background; - color: $gray-800; + .ul-1 ul { + padding-left: 0; } - &.active, &active:hover { - background-color: $secondary-background; + /* This is to make the width of the items that have sub-items (like room versions) + the same as the width of items that don't (like changelog) */ + .pr-md-3, .px-md-3 { + padding-right: 0 !important; + } + + .ul-1 > li > a { + padding-left: 1rem !important; + } + + .ul-2 > li > a { + padding-left: 2rem !important; + } + } + + /* Styles for the table of contents */ + & > .td-toc { + padding-top: 1rem; + padding-left: 1.5rem; + /* Add border above the toc */ + border-top: 1px solid var(--bs-tertiary-color); + + ol { + padding-left: 1rem; + counter-reset: section; + list-style-type: none; + } + + #TableOfContents { + /* Remove the space between the title and the ToC */ + margin-top: 0; + + &>ol>li { + margin-bottom: .5rem; + + &>a { + font-weight: $font-weight-bold; + } + } + + ol { + padding-left: 0; + } + + &>ol>li>a { + padding-left: 1rem; + } + + &>ol>li>ol>li>a { + padding-left: 2rem; + } + + &>ol>li>ol>li>ol>li>a { + padding-left: 3rem; + } + + &>ol>li>ol>li>ol>li>ol>li>a { + padding-left: 4rem; + } + + &>ol>li>ol>li>ol>li>ol>li>ol>li>a { + padding-left: 5rem; + } + + } + + li a:before { + counter-increment: section; + content: counters(section, ".") " "; + } + + .td-toc-title { + font-weight: $font-weight-bold; + font-size: 1.3rem; + + /* Remove the border under the title */ + border-bottom: 0; + /* Remove the space under the title */ + margin-bottom: 0; + + /* Fix the top of page link color */ + a, a:hover { + color: $secondary; + } + } + } + + /* Apply the same style to links in the navigation and in the ToC */ + & > .td-sidebar-nav__section, & > .td-toc #TableOfContents { + li a.td-sidebar-link.tree-root { + color: $gray-800; + font-weight: $font-weight-bold; + font-size: 1.3rem; + margin-bottom: 0; + border-bottom: none; + } + + li a, li a.td-sidebar-link { + color: $gray-800; + font-weight: $font-weight-normal; + padding-top: .2rem; + padding-bottom: .2rem; + + transition: all 100ms ease-in-out; + + &:hover { + background-color: $secondary-lighter-background; + color: $gray-800; + } + + &.active, &active:hover { + background-color: $secondary-background; + } } } } @@ -199,62 +273,67 @@ Custom SCSS for the Matrix spec scroll-margin-top: 5.5rem; } -/* Styles for the table of contents */ -#toc { - padding-top: .5rem; - padding-left: 1.5rem; - - ol { - padding-left: 1rem; - counter-reset: section; - list-style-type: none; - } - - #TableOfContents { - &>ol>li { - margin-bottom: .5rem; - - &>a { - font-weight: $font-weight-bold; - } - } - - ol { - padding-left: 0; - } - - &>ol>li>a { - padding-left: 1rem; - } - - &>ol>li>ol>li>a { - padding-left: 2rem; - } - - &>ol>li>ol>li>ol>li>a { - padding-left: 3rem; - } - - &>ol>li>ol>li>ol>li>ol>li>a { - padding-left: 4rem; - } - - &>ol>li>ol>li>ol>li>ol>li>ol>li>a { - padding-left: 5rem; - } - - } - - li a:before { - counter-increment: section; - content: counters(section, ".") " "; - } - - #toc-title { +.endpoints-toc { + summary { + cursor: pointer; font-weight: $font-weight-bold; - font-size: 1.3rem; + font-size: 1.05rem; + margin-bottom: 0.5rem; } + .endpoint-list { + list-style: none; + padding-left: 0; + margin: 0; + } + + .endpoint-list li { + margin: 0.2rem 0; + } + + .endpoint-list a { + text-decoration: none; + color: inherit; + padding: 0.05rem 0.25rem; + border-radius: 0.2rem; + + &:hover { + background-color: $secondary-background; + } + } + + .endpoint-list .http-api-method { + margin-right: 0.35rem; + font-weight: $font-weight-bold; + } + + .endpoint-path { + font-family: $font-family-monospace; + color: $secondary; + } + + .endpoint-deprecated { + color: $danger; + font-weight: $font-weight-bold; + margin-left: 0.35rem; + } + + .endpoint-module { + &:not(:first-child) { + margin-top: 0.75rem; + } + } + + .endpoint-module-title { + // font-weight: $font-weight-bold; + font-size: 1.20rem; + margin-bottom: 0.35rem; + } +} + +.page-description { + margin-bottom: 1rem; + color: inherit; } /* Styles for alert boxes */ @@ -581,4 +660,4 @@ dd { .breadcrumb { margin: 0; } -} \ No newline at end of file +} diff --git a/assets/scss/_variables_project.scss b/assets/scss/_variables_project.scss index c2ec03c6..75e5379f 100644 --- a/assets/scss/_variables_project.scss +++ b/assets/scss/_variables_project.scss @@ -18,6 +18,7 @@ $primary: #FFF; $secondary: #0098D4; $dark: #333; $gray-100: #FBFBFB; +$code-color: #005b7f; $secondary-background: #E5F5FB; $secondary-lighter-background: #F4FAFC; diff --git a/changelogs/application_service/newsfragments/2213.clarification b/changelogs/application_service/newsfragments/2213.clarification deleted file mode 100644 index a8c06342..00000000 --- a/changelogs/application_service/newsfragments/2213.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix JSON formatting in the "Server admin style permissions" examples. diff --git a/changelogs/application_service/newsfragments/2221.feature b/changelogs/application_service/newsfragments/2221.feature deleted file mode 100644 index 400d98ef..00000000 --- a/changelogs/application_service/newsfragments/2221.feature +++ /dev/null @@ -1 +0,0 @@ -Allow application services to masquerade as specific devices belonging to users, as per [MSC4326](https://github.com/matrix-org/matrix-spec-proposals/pull/4326). \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/2186.removal b/changelogs/client_server/newsfragments/2186.removal deleted file mode 100644 index c40f001f..00000000 --- a/changelogs/client_server/newsfragments/2186.removal +++ /dev/null @@ -1 +0,0 @@ -Remove legacy mentions, as per [MSC4210](https://github.com/matrix-org/matrix-spec-proposals/issues/4210). diff --git a/changelogs/client_server/newsfragments/2214.clarification b/changelogs/client_server/newsfragments/2214.clarification deleted file mode 100644 index 50121eaa..00000000 --- a/changelogs/client_server/newsfragments/2214.clarification +++ /dev/null @@ -1 +0,0 @@ -Push rule IDs are globally unique within their kind. diff --git a/changelogs/client_server/newsfragments/2215.clarification b/changelogs/client_server/newsfragments/2215.clarification deleted file mode 100644 index f76c952d..00000000 --- a/changelogs/client_server/newsfragments/2215.clarification +++ /dev/null @@ -1 +0,0 @@ -Don't advertise `creator` field in description of room creation. diff --git a/changelogs/client_server/newsfragments/2216.clarification b/changelogs/client_server/newsfragments/2216.clarification deleted file mode 100644 index a777ad87..00000000 --- a/changelogs/client_server/newsfragments/2216.clarification +++ /dev/null @@ -1 +0,0 @@ -`room_id` is required for peeking via `/_matrix/client/v3/events`. diff --git a/changelogs/client_server/newsfragments/2217.clarification b/changelogs/client_server/newsfragments/2217.clarification deleted file mode 100644 index ea895054..00000000 --- a/changelogs/client_server/newsfragments/2217.clarification +++ /dev/null @@ -1 +0,0 @@ -The `server-name` segment of MXC URIs is sanitised differently from the `media-id` segment. diff --git a/changelogs/client_server/newsfragments/2221.feature b/changelogs/client_server/newsfragments/2221.feature deleted file mode 100644 index 400d98ef..00000000 --- a/changelogs/client_server/newsfragments/2221.feature +++ /dev/null @@ -1 +0,0 @@ -Allow application services to masquerade as specific devices belonging to users, as per [MSC4326](https://github.com/matrix-org/matrix-spec-proposals/pull/4326). \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/2223.clarification b/changelogs/client_server/newsfragments/2223.clarification deleted file mode 100644 index 401a1f95..00000000 --- a/changelogs/client_server/newsfragments/2223.clarification +++ /dev/null @@ -1 +0,0 @@ -Add note to each endpoint that uses capability negotiation. diff --git a/changelogs/client_server/newsfragments/2224.clarification b/changelogs/client_server/newsfragments/2224.clarification deleted file mode 100644 index 3ccb2333..00000000 --- a/changelogs/client_server/newsfragments/2224.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix various typos throughout the specification. diff --git a/changelogs/client_server/newsfragments/2225.clarification b/changelogs/client_server/newsfragments/2225.clarification deleted file mode 100644 index 6a62eb99..00000000 --- a/changelogs/client_server/newsfragments/2225.clarification +++ /dev/null @@ -1 +0,0 @@ -Additional OpenGraph properties can be present in URL previews. diff --git a/changelogs/client_server/newsfragments/2227.clarification b/changelogs/client_server/newsfragments/2227.clarification deleted file mode 100644 index 3ccb2333..00000000 --- a/changelogs/client_server/newsfragments/2227.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix various typos throughout the specification. diff --git a/changelogs/client_server/newsfragments/2231.clarification b/changelogs/client_server/newsfragments/2231.clarification deleted file mode 100644 index 58343ac0..00000000 --- a/changelogs/client_server/newsfragments/2231.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify the special casing of membership events and redactions in power levels. diff --git a/changelogs/client_server/newsfragments/2232.clarification b/changelogs/client_server/newsfragments/2232.clarification deleted file mode 100644 index 78304051..00000000 --- a/changelogs/client_server/newsfragments/2232.clarification +++ /dev/null @@ -1 +0,0 @@ -`M_RESOURCE_LIMIT_EXCEEDED` is now listed as a common error code. diff --git a/changelogs/client_server/newsfragments/2233.clarification b/changelogs/client_server/newsfragments/2233.clarification deleted file mode 100644 index 9c4afa28..00000000 --- a/changelogs/client_server/newsfragments/2233.clarification +++ /dev/null @@ -1 +0,0 @@ -Add `m.login.terms` to enumeration of authentication types. diff --git a/changelogs/client_server/newsfragments/2234.feature b/changelogs/client_server/newsfragments/2234.feature deleted file mode 100644 index 2dd33f67..00000000 --- a/changelogs/client_server/newsfragments/2234.feature +++ /dev/null @@ -1 +0,0 @@ -Add the `m.oauth` authentication type for User-Interactive Authentication as per [MSC4312](https://github.com/matrix-org/matrix-spec-proposals/pull/4312). diff --git a/changelogs/client_server/newsfragments/2240.clarification b/changelogs/client_server/newsfragments/2240.clarification deleted file mode 100644 index 07081f28..00000000 --- a/changelogs/client_server/newsfragments/2240.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify how to use `state_after` ahead of declaring full support for its spec version. diff --git a/changelogs/client_server/newsfragments/2245.clarification b/changelogs/client_server/newsfragments/2245.clarification deleted file mode 100644 index 2d0453a2..00000000 --- a/changelogs/client_server/newsfragments/2245.clarification +++ /dev/null @@ -1 +0,0 @@ -`device_one_time_keys_count` is only optional if no unclaimed one-time keys exist. diff --git a/changelogs/client_server/newsfragments/2246.clarification b/changelogs/client_server/newsfragments/2246.clarification deleted file mode 100644 index 7d2625a6..00000000 --- a/changelogs/client_server/newsfragments/2246.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify that servers may choose not to use `M_USER_DEACTIVATED` at login time, for example for privacy reasons when they can't authenticate deactivated users. diff --git a/changelogs/client_server/newsfragments/2250.clarification b/changelogs/client_server/newsfragments/2250.clarification deleted file mode 100644 index 12efe875..00000000 --- a/changelogs/client_server/newsfragments/2250.clarification +++ /dev/null @@ -1 +0,0 @@ -Minor grammatical fix in the Secrets module description. \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/2255.clarification b/changelogs/client_server/newsfragments/2255.clarification deleted file mode 100644 index 4429fccf..00000000 --- a/changelogs/client_server/newsfragments/2255.clarification +++ /dev/null @@ -1 +0,0 @@ -Usage of the `event_id_only` format for push notifications is not mandatory. diff --git a/changelogs/client_server/newsfragments/2270.feature b/changelogs/client_server/newsfragments/2270.feature new file mode 100644 index 00000000..b675c947 --- /dev/null +++ b/changelogs/client_server/newsfragments/2270.feature @@ -0,0 +1 @@ +Add the account management capabilities for the OAuth 2.0 authentication API, as per [MSC4191](https://github.com/matrix-org/matrix-spec-proposals/pull/4191). diff --git a/changelogs/client_server/newsfragments/2277.clarification b/changelogs/client_server/newsfragments/2277.clarification new file mode 100644 index 00000000..bf818eaf --- /dev/null +++ b/changelogs/client_server/newsfragments/2277.clarification @@ -0,0 +1,3 @@ +The optional `submit_url` response parameter of the `/requestToken` endpoints uses the same request +and response parameters and error codes as the Identity Service API's `POST /_matrix/identity/v2/validate/email/submitToken`, +as per [MSC4183](https://github.com/matrix-org/matrix-spec-proposals/pull/4183). diff --git a/changelogs/client_server/newsfragments/2280.clarification b/changelogs/client_server/newsfragments/2280.clarification new file mode 100644 index 00000000..38fa5012 --- /dev/null +++ b/changelogs/client_server/newsfragments/2280.clarification @@ -0,0 +1 @@ +Update non-historic mentions of matrix-doc repo to matrix-spec/-proposals. Contributed by @HarHarLinks. diff --git a/changelogs/client_server/newsfragments/2283.clarification b/changelogs/client_server/newsfragments/2283.clarification new file mode 100644 index 00000000..2dc18986 --- /dev/null +++ b/changelogs/client_server/newsfragments/2283.clarification @@ -0,0 +1 @@ +Remove unintended TeX formatting. Contributed by @HarHarLinks. diff --git a/changelogs/client_server/newsfragments/2291.feature b/changelogs/client_server/newsfragments/2291.feature new file mode 100644 index 00000000..93a509dc --- /dev/null +++ b/changelogs/client_server/newsfragments/2291.feature @@ -0,0 +1 @@ +Add `m.recent_emoji` account data event to track recently used emoji as per [MSC4356](https://github.com/matrix-org/matrix-spec-proposals/pull/4356). diff --git a/changelogs/identity_service/newsfragments/2277.clarification b/changelogs/identity_service/newsfragments/2277.clarification new file mode 100644 index 00000000..58510ecf --- /dev/null +++ b/changelogs/identity_service/newsfragments/2277.clarification @@ -0,0 +1,3 @@ +Clarify the error codes that can be returned with a 400 HTTP status code by the `POST /_matrix/identity/v2/validate/email/submitToken` +and `POST /_matrix/identity/v2/validate/msisdn/submitToken` endpoints, introducing the `M_TOKEN_INCORRECT` +error code, as per [MSC4183](https://github.com/matrix-org/matrix-spec-proposals/pull/4183). diff --git a/changelogs/internal/newsfragments/2219.clarification b/changelogs/internal/newsfragments/2219.clarification deleted file mode 100644 index ef0721b4..00000000 --- a/changelogs/internal/newsfragments/2219.clarification +++ /dev/null @@ -1 +0,0 @@ -Swapped icon for X (fka. twitter) to updated logo in footer. \ No newline at end of file diff --git a/changelogs/internal/newsfragments/2222.clarification b/changelogs/internal/newsfragments/2222.clarification new file mode 100644 index 00000000..188d64bb --- /dev/null +++ b/changelogs/internal/newsfragments/2222.clarification @@ -0,0 +1 @@ +Clarify vendor prefixing requirements. diff --git a/changelogs/internal/newsfragments/2226.clarification b/changelogs/internal/newsfragments/2226.clarification deleted file mode 100644 index 68758818..00000000 --- a/changelogs/internal/newsfragments/2226.clarification +++ /dev/null @@ -1 +0,0 @@ -Inline Olm & Megolm specifications. diff --git a/changelogs/internal/newsfragments/2238.clarification b/changelogs/internal/newsfragments/2238.clarification deleted file mode 100644 index b91abc53..00000000 --- a/changelogs/internal/newsfragments/2238.clarification +++ /dev/null @@ -1 +0,0 @@ -Silence failing redocly-cli rule. diff --git a/changelogs/internal/newsfragments/2239.clarification b/changelogs/internal/newsfragments/2239.clarification deleted file mode 100644 index 6b8cf712..00000000 --- a/changelogs/internal/newsfragments/2239.clarification +++ /dev/null @@ -1 +0,0 @@ -Use NPM Trusted Publishers for publishing `@matrix-org/spec` to npm. \ No newline at end of file diff --git a/changelogs/internal/newsfragments/2241.clarification b/changelogs/internal/newsfragments/2241.clarification deleted file mode 100644 index 68758818..00000000 --- a/changelogs/internal/newsfragments/2241.clarification +++ /dev/null @@ -1 +0,0 @@ -Inline Olm & Megolm specifications. diff --git a/changelogs/internal/newsfragments/2242.clarification b/changelogs/internal/newsfragments/2242.clarification deleted file mode 100644 index 68758818..00000000 --- a/changelogs/internal/newsfragments/2242.clarification +++ /dev/null @@ -1 +0,0 @@ -Inline Olm & Megolm specifications. diff --git a/changelogs/internal/newsfragments/2256.clarification b/changelogs/internal/newsfragments/2256.clarification deleted file mode 100644 index 468f55d5..00000000 --- a/changelogs/internal/newsfragments/2256.clarification +++ /dev/null @@ -1 +0,0 @@ -Add version picker in the navbar. diff --git a/changelogs/internal/newsfragments/2258.clarification b/changelogs/internal/newsfragments/2258.clarification deleted file mode 100644 index 468f55d5..00000000 --- a/changelogs/internal/newsfragments/2258.clarification +++ /dev/null @@ -1 +0,0 @@ -Add version picker in the navbar. diff --git a/changelogs/internal/newsfragments/2259.clarification b/changelogs/internal/newsfragments/2259.clarification deleted file mode 100644 index 468f55d5..00000000 --- a/changelogs/internal/newsfragments/2259.clarification +++ /dev/null @@ -1 +0,0 @@ -Add version picker in the navbar. diff --git a/changelogs/internal/newsfragments/2260.clarification b/changelogs/internal/newsfragments/2260.clarification deleted file mode 100644 index de578d64..00000000 --- a/changelogs/internal/newsfragments/2260.clarification +++ /dev/null @@ -1 +0,0 @@ -Add version picker in the navbar. \ No newline at end of file diff --git a/changelogs/internal/newsfragments/2261.clarification b/changelogs/internal/newsfragments/2261.clarification deleted file mode 100644 index 468f55d5..00000000 --- a/changelogs/internal/newsfragments/2261.clarification +++ /dev/null @@ -1 +0,0 @@ -Add version picker in the navbar. diff --git a/changelogs/internal/newsfragments/2264.clarification b/changelogs/internal/newsfragments/2264.clarification deleted file mode 100644 index 468f55d5..00000000 --- a/changelogs/internal/newsfragments/2264.clarification +++ /dev/null @@ -1 +0,0 @@ -Add version picker in the navbar. diff --git a/changelogs/internal/newsfragments/2268.clarification b/changelogs/internal/newsfragments/2268.clarification deleted file mode 100644 index 468f55d5..00000000 --- a/changelogs/internal/newsfragments/2268.clarification +++ /dev/null @@ -1 +0,0 @@ -Add version picker in the navbar. diff --git a/changelogs/internal/newsfragments/2275.clarification b/changelogs/internal/newsfragments/2275.clarification new file mode 100644 index 00000000..0a0f28a7 --- /dev/null +++ b/changelogs/internal/newsfragments/2275.clarification @@ -0,0 +1 @@ +Auto-create draft releases when building release tags. diff --git a/changelogs/internal/newsfragments/2276.feature b/changelogs/internal/newsfragments/2276.feature new file mode 100644 index 00000000..a0e2b795 --- /dev/null +++ b/changelogs/internal/newsfragments/2276.feature @@ -0,0 +1 @@ +Include the spec release version in the filenames in the tarballs generated by CI. diff --git a/changelogs/internal/newsfragments/2282.clarification b/changelogs/internal/newsfragments/2282.clarification new file mode 100644 index 00000000..25fafc6f --- /dev/null +++ b/changelogs/internal/newsfragments/2282.clarification @@ -0,0 +1 @@ +Replace the Twitter link in the footer with our BlueSky and Mastodon socials. \ No newline at end of file diff --git a/changelogs/internal/newsfragments/2287.clarification b/changelogs/internal/newsfragments/2287.clarification new file mode 100644 index 00000000..5d0bdcc5 --- /dev/null +++ b/changelogs/internal/newsfragments/2287.clarification @@ -0,0 +1 @@ +Upgrade to docsy v0.13.0. diff --git a/changelogs/internal/newsfragments/2289.clarification b/changelogs/internal/newsfragments/2289.clarification new file mode 100644 index 00000000..7991ce2e --- /dev/null +++ b/changelogs/internal/newsfragments/2289.clarification @@ -0,0 +1 @@ +Updates to the release documentation. diff --git a/changelogs/internal/newsfragments/2290.clarification b/changelogs/internal/newsfragments/2290.clarification new file mode 100644 index 00000000..30231938 --- /dev/null +++ b/changelogs/internal/newsfragments/2290.clarification @@ -0,0 +1 @@ +Remove unused leftover CSS files. diff --git a/changelogs/room_versions/newsfragments/2220.clarification b/changelogs/room_versions/newsfragments/2220.clarification deleted file mode 100644 index 4141e31a..00000000 --- a/changelogs/room_versions/newsfragments/2220.clarification +++ /dev/null @@ -1 +0,0 @@ -In room versions 8 through 12, clarify that "sufficient permission to invite users" on restricted joins also includes being a joined member of the room. \ No newline at end of file diff --git a/changelogs/room_versions/newsfragments/2249.clarification b/changelogs/room_versions/newsfragments/2249.clarification deleted file mode 100644 index 7578edc3..00000000 --- a/changelogs/room_versions/newsfragments/2249.clarification +++ /dev/null @@ -1 +0,0 @@ -In room versions 3 through 12, clarify that when you have the power to redact, it is possible to redact events that you don't have the power to send. \ No newline at end of file diff --git a/changelogs/server_server/newsfragments/2288.clarification b/changelogs/server_server/newsfragments/2288.clarification new file mode 100644 index 00000000..3558f255 --- /dev/null +++ b/changelogs/server_server/newsfragments/2288.clarification @@ -0,0 +1 @@ +Specify that callers of `/_matrix/federation/v1/openid/userinfo` must validate the returned user ID. diff --git a/config/_default/hugo.toml b/config/_default/hugo.toml index b09b9562..76c3f9bb 100644 --- a/config/_default/hugo.toml +++ b/config/_default/hugo.toml @@ -75,8 +75,8 @@ status = "unstable" 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. -# major = "1" -# minor = "16" +#major = "1" +#minor = "17" [[params.versions]] # We must include this parameter to enable docsy's version picker in the navbar. The picker @@ -106,25 +106,30 @@ sidebar_menu_compact = true # desc = "Matrix on GitHub" # Custom links shown in the center of the footer. (Only supported by our fork of docsy's 'footer/central' partial.) [[params.links.bottom]] - name = "GitHub" - url = "https://github.com/matrix-org" - icon = "fab fa-github" + name = "GitHub" + url = "https://github.com/matrix-org" + icon = "fab fa-github" desc = "Matrix on GitHub" [[params.links.bottom]] - name = "GitLab" - url = "https://gitlab.matrix.org/matrix-org" - icon = "fab fa-gitlab" + name = "GitLab" + url = "https://gitlab.matrix.org/matrix-org" + icon = "fab fa-gitlab" desc = "Matrix on GitLab" [[params.links.bottom]] - name = "YouTube" - url = "https://www.youtube.com/channel/UCVFkW-chclhuyYRbmmfwt6w" - icon = "fab fa-youtube" + name = "YouTube" + url = "https://www.youtube.com/channel/UCVFkW-chclhuyYRbmmfwt6w" + icon = "fab fa-youtube" desc = "Matrix YouTube channel" [[params.links.bottom]] - name = "Twitter" - url = "https://twitter.com/matrixdotorg" - icon = "fab fa-x-twitter" - desc = "Matrix on Twitter" + name = "Mastodon" + url = "https://mastodon.matrix.org/@matrix" + icon = "fab fa-mastodon" + desc = "Matrix on Mastodon" +[[params.links.bottom]] + name = "Bluesky" + url = "https://bsky.app/profile/matrix.org" + icon = "fab fa-bluesky" + desc = "Matrix on Bluesky" # configuration for the hugo development server @@ -161,3 +166,11 @@ sidebar_menu_compact = true mediaType = "text/markdown" isPlainText = true baseName = "checklist" + +# Add font media types for downloading KaTeX fonts. +# See: https://www.docsy.dev/docs/content/diagrams-and-formulae/#create-media-types-for-katex-fonts +[mediaTypes] + [mediaTypes.'font/woff'] + suffixes = ['woff'] + [mediaTypes.'font/woff2'] + suffixes = ['woff2'] diff --git a/content/application-service-api.md b/content/application-service-api.md index cc2c25ca..d1b9c638 100644 --- a/content/application-service-api.md +++ b/content/application-service-api.md @@ -2,16 +2,14 @@ title: "Application Service API" weight: 30 type: docs +description: | + The Matrix client-server API and server-server APIs provide a consistent, + self-contained federated messaging fabric but leave little room for custom + server-side behaviour such as gateways, filters, or extensible hooks. The + Application Service API defines a standard way to add this extensible + functionality, independent of the underlying homeserver implementation. --- -The Matrix client-server API and server-server APIs provide the means to -implement a consistent self-contained federated messaging fabric. -However, they provide limited means of implementing custom server-side -behaviour in Matrix (e.g. gateways, filters, extensible hooks etc). The -Application Service API (AS API) defines a standard API to allow such -extensible functionality to be implemented irrespective of the -underlying homeserver implementation. - ## Application Services Application services are passive and can only observe events from the @@ -428,6 +426,8 @@ imports and similar behaviour). #### Server admin style permissions +{{% changed-in v="1.17" %}} + The homeserver needs to give the application service *full control* over its namespace, both for users and for room aliases. This means that the AS should be able to manage any users and room alias in its namespace. No additional API @@ -444,33 +444,59 @@ achieved by including the `as_token` on a `/register` request, along with a login type of `m.login.application_service` to set the desired user ID without a password. - POST /_matrix/client/v3/register - Authorization: Bearer YourApplicationServiceTokenHere +```http +POST /_matrix/client/v3/register +Authorization: Bearer YourApplicationServiceTokenHere +``` - Content: - { - "type": "m.login.application_service", - "username": "_irc_example" - } +```json +{ + "type": "m.login.application_service", + "username": "_irc_example" +} +``` -Similarly, logging in as users needs API changes in order to allow the AS to -log in without needing the user's password. This is achieved by including the -`as_token` on a `/login` request, along with a login type of -`m.login.application_service`: +{{% boxes/note %}} +{{% added-in v="1.17" %}} +Servers MUST still allow application services to use the `/register` endpoint +with a login type of `m.login.application_service` even if they don't support +the [Legacy Authentication API](/client-server-api/#legacy-api). + +In that case application services MUST set the `"inhibit_login": true` parameter +as they cannot use it to log in as users. If the `inhibit_login` parameter is +not set to `true`, the server MUST return a 400 HTTP status code with an +`M_APPSERVICE_LOGIN_UNSUPPORTED` error code. +{{% /boxes/note %}} + +Similarly, logging in as users using the [Legacy authentication API](/client-server-api/#legacy-api) +needs API changes in order to allow the AS to log in without needing the user's +password. This is achieved by including the `as_token` on a `/login` request, +along with a login type of `m.login.application_service`: {{% added-in v="1.2" %}} - POST /_matrix/client/v3/login - Authorization: Bearer YourApplicationServiceTokenHere +```http +POST /_matrix/client/v3/login +Authorization: Bearer YourApplicationServiceTokenHere +``` - Content: - { - "type": "m.login.application_service", - "identifier": { - "type": "m.id.user", - "user": "_irc_example" - } - } +```json +{ + "type": "m.login.application_service", + "identifier": { + "type": "m.id.user", + "user": "_irc_example" + } +} +``` + +{{% boxes/note %}} +{{% added-in v="1.17" %}} +Application services MUST NOT use the `/login` endpoint if the server doesn't +support the Legacy authentication API. If `/login` is called with the +`m.login.application_service` login type the server MUST return a 400 HTTP +status code with an `M_APPSERVICE_LOGIN_UNSUPPORTED` error code. +{{% /boxes/note %}} Application services which attempt to create users or aliases *outside* of their defined namespaces, or log in as users outside of their defined @@ -512,6 +538,38 @@ client-server endpoint. {{% http-api spec="client-server" api="appservice_room_directory" %}} +#### Device management + +{{% added-in v="1.17" %}} + +Application services need to be able to create and delete devices to manage the +encryption for their users without having to rely on `/login`, which also +generates an access token for the user, and which might not be available for +homeservers that only support the [OAuth 2.0 API](/client-server-api/#oauth-20-api). + +##### Creating devices + +Application services can use the [`PUT /_matrix/client/v3/devices/{deviceId}`](/client-server-api/#put_matrixclientv3devicesdeviceid) +endpoint to create new devices. + +##### Deleting devices + +The following endpoints used to delete devices MUST NOT require [User-Interactive +Authentication](/client-server-api/#user-interactive-authentication-api) when +used by an application service: + +* [`DELETE /_matrix/client/v3/devices/{deviceId}`](/client-server-api/#delete_matrixclientv3devicesdeviceid) +* [`POST /_matrix/client/v3/delete_devices`](/client-server-api/#post_matrixclientv3delete_devices) + +#### Cross-signing + +{{% added-in v="1.17" %}} + +Appservices need to be able to verify themselves and replace their cross-signing +keys, so the [`POST /_matrix/client/v3/keys/device_signing/upload`](/client-server-api/#post_matrixclientv3keysdevice_signingupload) +endpoint MUST NOT require [User-Interactive Authentication](/client-server-api/#user-interactive-authentication-api) +when used by an application service, even if cross-signing keys already exist. + ### Referencing messages from a third-party network Application services should include an `external_url` in the `content` diff --git a/content/changelog/v1.17.md b/content/changelog/v1.17.md new file mode 100644 index 00000000..b154b32c --- /dev/null +++ b/content/changelog/v1.17.md @@ -0,0 +1,91 @@ +--- +title: v1.17 Changelog +linkTitle: v1.17 +type: docs +layout: changelog +outputs: + - html + - checklist +date: 2025-12-18 +--- + +## Client-Server API + +**Removed Endpoints** + +- Remove legacy mentions, as per [MSC4210](https://github.com/matrix-org/matrix-spec-proposals/issues/4210). ([#2186](https://github.com/matrix-org/matrix-spec/issues/2186)) + +**Backwards Compatible Changes** + +- Allow application services to masquerade as specific devices belonging to users, as per [MSC4326](https://github.com/matrix-org/matrix-spec-proposals/pull/4326). ([#2221](https://github.com/matrix-org/matrix-spec/issues/2221)) +- Add the `m.oauth` authentication type for User-Interactive Authentication, as per [MSC4312](https://github.com/matrix-org/matrix-spec-proposals/pull/4312). ([#2234](https://github.com/matrix-org/matrix-spec/issues/2234)) +- Allow application services to manage devices and register users without the legacy authentication API, as per [MSC4190](https://github.com/matrix-org/matrix-spec-proposals/pull/4190). ([#2267](https://github.com/matrix-org/matrix-spec/issues/2267)) + +**Spec Clarifications** + +- Push rule IDs are globally unique within their kind. ([#2214](https://github.com/matrix-org/matrix-spec/issues/2214)) +- Don't advertise `creator` field in description of room creation. ([#2215](https://github.com/matrix-org/matrix-spec/issues/2215)) +- `room_id` is required for peeking via `/_matrix/client/v3/events`. ([#2216](https://github.com/matrix-org/matrix-spec/issues/2216)) +- The `server-name` segment of MXC URIs is sanitised differently from the `media-id` segment. ([#2217](https://github.com/matrix-org/matrix-spec/issues/2217)) +- Add note to each endpoint that uses capability negotiation. ([#2223](https://github.com/matrix-org/matrix-spec/issues/2223)) +- Additional OpenGraph properties can be present in URL previews. ([#2225](https://github.com/matrix-org/matrix-spec/issues/2225)) +- Clarify the special casing of membership events and redactions in power levels. ([#2231](https://github.com/matrix-org/matrix-spec/issues/2231)) +- `M_RESOURCE_LIMIT_EXCEEDED` is now listed as a common error code. ([#2232](https://github.com/matrix-org/matrix-spec/issues/2232)) +- Add `m.login.terms` to enumeration of authentication types. ([#2233](https://github.com/matrix-org/matrix-spec/issues/2233)) +- Clarify how to use `state_after` ahead of declaring full support for its spec version. ([#2240](https://github.com/matrix-org/matrix-spec/issues/2240)) +- `device_one_time_keys_count` is only optional if no unclaimed one-time keys exist. ([#2245](https://github.com/matrix-org/matrix-spec/issues/2245)) +- Clarify that servers may choose not to use `M_USER_DEACTIVATED` at login time, for example for privacy reasons when they can't authenticate deactivated users. ([#2246](https://github.com/matrix-org/matrix-spec/issues/2246)) +- Usage of the `event_id_only` format for push notifications is not mandatory. ([#2255](https://github.com/matrix-org/matrix-spec/issues/2255)) +- Fix various typos throughout the specification. ([#2224](https://github.com/matrix-org/matrix-spec/issues/2224), [#2227](https://github.com/matrix-org/matrix-spec/issues/2227), [#2250](https://github.com/matrix-org/matrix-spec/issues/2250)) + + +## Server-Server API + +No significant changes. + + +## Application Service API + +**Backwards Compatible Changes** + +- Allow application services to masquerade as specific devices belonging to users, as per [MSC4326](https://github.com/matrix-org/matrix-spec-proposals/pull/4326). ([#2221](https://github.com/matrix-org/matrix-spec/issues/2221)) +- Allow application services to manage devices and register users without the legacy authentication API, as per [MSC4190](https://github.com/matrix-org/matrix-spec-proposals/pull/4190). ([#2267](https://github.com/matrix-org/matrix-spec/issues/2267)) + +**Spec Clarifications** + +- Fix JSON formatting in the "Server admin style permissions" examples. ([#2213](https://github.com/matrix-org/matrix-spec/issues/2213)) + + +## Identity Service API + +No significant changes. + + +## Push Gateway API + +No significant changes. + + +## Room Versions + +**Spec Clarifications** + +- In room versions 8 through 12, clarify that "sufficient permission to invite users" on restricted joins also includes being a joined member of the room. ([#2220](https://github.com/matrix-org/matrix-spec/issues/2220)) +- In room versions 3 through 12, clarify that when you have the power to redact, it is possible to redact events that you don't have the power to send. ([#2249](https://github.com/matrix-org/matrix-spec/issues/2249)) + + +## Appendices + +No significant changes. + + +## Internal Changes/Tooling + +**Spec Clarifications** + +- Swapped icon for X (fka. twitter) to updated logo in footer. ([#2219](https://github.com/matrix-org/matrix-spec/issues/2219)) +- Inline Olm & Megolm specifications. ([#2226](https://github.com/matrix-org/matrix-spec/issues/2226), [#2241](https://github.com/matrix-org/matrix-spec/issues/2241), [#2242](https://github.com/matrix-org/matrix-spec/issues/2242)) +- Silence failing redocly-cli rule. ([#2238](https://github.com/matrix-org/matrix-spec/issues/2238)) +- Use NPM Trusted Publishers for publishing `@matrix-org/spec` to npm. ([#2239](https://github.com/matrix-org/matrix-spec/issues/2239)) +- Add version picker in the navbar. ([#2256](https://github.com/matrix-org/matrix-spec/issues/2256), [#2258](https://github.com/matrix-org/matrix-spec/issues/2258), [#2259](https://github.com/matrix-org/matrix-spec/issues/2259), [#2260](https://github.com/matrix-org/matrix-spec/issues/2260), [#2261](https://github.com/matrix-org/matrix-spec/issues/2261), [#2264](https://github.com/matrix-org/matrix-spec/issues/2264), [#2268](https://github.com/matrix-org/matrix-spec/issues/2268)) +- Add a list of endpoints to the top of each spec page. ([#2262](https://github.com/matrix-org/matrix-spec/issues/2262)) diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index 5a611587..9cc3aba6 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -2,14 +2,14 @@ title: "Client-Server API" weight: 10 type: docs +description: | + The client-server API allows clients to send messages, control rooms and + synchronise conversation history. It is designed to support both lightweight + clients which store no state and lazy-load data from the server as required, + as well as heavyweight clients which maintain a full local persistent copy of + server state. --- -The client-server API allows clients to -send messages, control rooms and synchronise conversation history. It is -designed to support both lightweight clients which store no state and -lazy-load data from the server as required - as well as heavyweight -clients which maintain a full local persistent copy of server state. - ## API Standards {{% boxes/note %}} @@ -477,8 +477,7 @@ the API that was used to obtain their current access token. {{% boxes/note %}} Currently the OAuth 2.0 API doesn't cover all the use cases of the legacy API, -such as automated applications that cannot use a web browser, or -user management by [application services](application-service-api/#server-admin-style-permissions). +such as automated applications that cannot use a web browser. {{% /boxes/note %}} {{% boxes/note %}} @@ -509,6 +508,12 @@ user must do that directly in the homeserver's web UI. However, the client can signal to the homeserver that the user wishes to create a new account with the [`prompt=create`](#user-registration) parameter during authorization. +{{% boxes/note %}} +{{% added-in v="1.17" %}} +Application services can use the `/register` endpoint to create users regardless +of the authentication API supported by the homeserver. +{{% /boxes/note %}} + ### Login With the legacy API, a client can obtain an access token by using one of the @@ -647,7 +652,7 @@ manage their account like [changing their password](#password-management), [deactivating their account](#account-deactivation). With the OAuth 2.0 API, all account management is done via the homeserver's web -UI. +UI that can be accessed by users via the [account management URL](#oauth-20-account-management). ### Legacy API @@ -1574,6 +1579,10 @@ If the access token does correspond to an appservice, but the user id does not lie within its namespace then the homeserver will respond with an errcode of `M_EXCLUSIVE`. +{{% added-in v="1.17" %}} If this login type is used and the server doesn't +support logging in via the Legacy authentication API, it MUST return a 400 HTTP +status code with an `M_APPSERVICE_LOGIN_UNSUPPORTED` error code. + ##### Login Fallback If a client does not recognize any or all login flows it can use the @@ -2340,6 +2349,46 @@ The server SHOULD return one of the following responses: - For other errors, the server returns a `400 Bad Request` response with error details +#### Account management {id="oauth-20-account-management"} + +{{% added-in v="1.18" %}} + +All account management is done via the homeserver's web UI. + +This specification defines extensions to the [OAuth Authorization Server +Metadata registry](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#authorization-server-metadata) +to offer clients a way to deep-link to the account management capabilities of +the homeserver to allow the user to complete the account management operations +in a browser. + +##### Account management URL discovery + +The [OAuth 2.0 authorization server metadata](#server-metadata-discovery) is +extended to include the following **optional** fields. + +{{% definition path="schemas/oauth2-account-management-server-metadata" %}} + +##### Account management URL parameters + +The account management URL MAY accept the following minimum query parameters. + +{{% definition path="schemas/oauth2-account-management-url" %}} + +##### Account management URL actions + +Account management actions are unique to the application. They SHOULD follow the +[Common Namespaced Identifier Grammar](/appendices/#common-namespaced-identifier-grammar) +where feasible. The Matrix-specific actions are: + +| Action | Description | +|----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------| +| `org.matrix.profile` | The user wishes to view/edit their profile (name, avatar, contact details). | +| `org.matrix.devices_list` | The user wishes to view a list of their devices. | +| `org.matrix.device_view` | The user wishes to view the details of a specific device. A `device_id` SHOULD be provided. | +| `org.matrix.device_delete` | The user wishes to delete/log out a specific device. A `device_id` SHOULD be provided. | +| `org.matrix.account_deactivate` | The user wishes to deactivate their account. | +| `org.matrix.cross_signing_reset` | The user wishes to reset their cross-signing identity. Servers SHOULD use this action in the URL of the [`m.oauth`](#oauth-authentication) UIA type. | + ### Account moderation #### Account locking @@ -3967,6 +4016,7 @@ that profile. | [Guest Access](#guest-access) | Optional | Optional | Optional | Optional | Optional | | [Moderation Policy Lists](#moderation-policy-lists) | Optional | Optional | Optional | Optional | Optional | | [OpenID](#openid) | Optional | Optional | Optional | Optional | Optional | +| [Recently used emoji](#recently-used-emoji) | Optional | Optional | Optional | Optional | Optional | | [Reference Relations](#reference-relations) | Optional | Optional | Optional | Optional | Optional | | [Reporting Content](#reporting-content) | Optional | Optional | Optional | Optional | Optional | | [Rich replies](#rich-replies) | Optional | Optional | Optional | Optional | Optional | @@ -4031,42 +4081,43 @@ operations and run in a resource constrained environment. Like embedded applications, they are not intended to be fully-fledged communication systems. -{{% cs-module name="instant_messaging" %}} -{{% cs-module name="rich_replies" %}} -{{% cs-module name="voip_events" %}} -{{% cs-module name="typing_notifications" %}} -{{% cs-module name="receipts" %}} -{{% cs-module name="read_markers" %}} -{{% cs-module name="presence" %}} -{{% cs-module name="content_repo" %}} -{{% cs-module name="send_to_device" %}} -{{% cs-module name="device_management" %}} -{{% cs-module name="end_to_end_encryption" %}} -{{% cs-module name="secrets" %}} -{{% cs-module name="history_visibility" %}} -{{% cs-module name="push" %}} -{{% cs-module name="third_party_invites" %}} -{{% cs-module name="search" %}} -{{% cs-module name="guest_access" %}} -{{% cs-module name="room_previews" %}} -{{% cs-module name="tags" %}} -{{% cs-module name="account_data" %}} -{{% cs-module name="admin" %}} -{{% cs-module name="event_context" %}} -{{% cs-module name="sso_login" %}} -{{% cs-module name="dm" %}} -{{% cs-module name="ignore_users" %}} -{{% cs-module name="stickers" %}} -{{% cs-module name="report_content" %}} -{{% cs-module name="third_party_networks" %}} -{{% cs-module name="openid" %}} -{{% cs-module name="server_acls" %}} -{{% cs-module name="mentions" %}} -{{% cs-module name="room_upgrades" %}} -{{% cs-module name="server_notices" %}} -{{% cs-module name="moderation_policies" %}} -{{% cs-module name="spaces" %}} -{{% cs-module name="event_replacements" %}} -{{% cs-module name="event_annotations" %}} -{{% cs-module name="threading" %}} -{{% cs-module name="reference_relations" %}} +{{% cs-module name="Instant Messaging" filename="instant_messaging" %}} +{{% cs-module name="Rich replies" filename="rich_replies" %}} +{{% cs-module name="Voice over IP" filename="voip_events" %}} +{{% cs-module name="Typing Notifications" filename="typing_notifications" %}} +{{% cs-module name="Receipts" filename="receipts" %}} +{{% cs-module name="Read and unread markers" filename="read_markers" %}} +{{% cs-module name="Presence" filename="presence" %}} +{{% cs-module name="Content repository" filename="content_repo" %}} +{{% cs-module name="Send-to-Device messaging" filename="send_to_device" %}} +{{% cs-module name="Device Management" filename="device_management" %}} +{{% cs-module name="End-to-End Encryption" filename="end_to_end_encryption" %}} +{{% cs-module name="Secrets" filename="secrets" %}} +{{% cs-module name="Room History Visibility" filename="history_visibility" %}} +{{% cs-module name="Push Notifications" filename="push" %}} +{{% cs-module name="Third-party invites" filename="third_party_invites" %}} +{{% cs-module name="Server Side Search" filename="search" %}} +{{% cs-module name="Guest Access" filename="guest_access" %}} +{{% cs-module name="Room Previews" filename="room_previews" %}} +{{% cs-module name="Room Tagging" filename="tags" %}} +{{% cs-module name="Client Config" filename="account_data" %}} +{{% cs-module name="Server Administration" filename="admin" %}} +{{% cs-module name="Event Context" filename="event_context" %}} +{{% cs-module name="SSO client login/authentication" filename="sso_login" %}} +{{% cs-module name="Direct Messaging" filename="dm" %}} +{{% cs-module name="Ignoring Users" filename="ignore_users" %}} +{{% cs-module name="Sticker Messages" filename="stickers" %}} +{{% cs-module name="Reporting Content" filename="report_content" %}} +{{% cs-module name="Third-party Networks" filename="third_party_networks" %}} +{{% cs-module name="OpenID" filename="openid" %}} +{{% cs-module name="Server Access Control Lists (ACLs) for rooms" filename="server_acls" %}} +{{% cs-module name="User and room mentions" filename="mentions" %}} +{{% cs-module name="Room Upgrades" filename="room_upgrades" %}} +{{% cs-module name="Server Notices" filename="server_notices" %}} +{{% cs-module name="Moderation policy lists" filename="moderation_policies" %}} +{{% cs-module name="Spaces" filename="spaces" %}} +{{% cs-module name="Event replacements" filename="event_replacements" %}} +{{% cs-module name="Event annotations and reactions" filename="event_annotations" %}} +{{% cs-module name="Recently used emoji" filename="recent_emoji" %}} +{{% cs-module name="Threading" filename="threading" %}} +{{% cs-module name="Reference relations" filename="reference_relations" %}} diff --git a/content/client-server-api/modules/content_repo.md b/content/client-server-api/modules/content_repo.md index 39fe33ec..ad65ea42 100644 --- a/content/client-server-api/modules/content_repo.md +++ b/content/client-server-api/modules/content_repo.md @@ -87,7 +87,7 @@ Matrix 1.12 is expected to be released in the July-September 2024 calendar quart The homeserver SHOULD be able to supply thumbnails for uploaded images and videos. The exact file types which can be thumbnailed are not currently specified - see [Issue -\#1938](https://github.com/matrix-org/matrix-doc/issues/1938) for more +\#1938](https://github.com/matrix-org/matrix-spec/issues/453) for more information. The thumbnail methods are "crop" and "scale". "scale" tries to return an 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 97786f59..25617978 100644 --- a/content/client-server-api/modules/end_to_end_encryption.md +++ b/content/client-server-api/modules/end_to_end_encryption.md @@ -921,7 +921,7 @@ collaborate to create a common set of translations for all languages. {{% boxes/note %}} Known translations for the emoji are available from - + and can be translated online: {{% /boxes/note %}} diff --git a/content/client-server-api/modules/instant_messaging.md b/content/client-server-api/modules/instant_messaging.md index d5c0cb6a..5c8a802c 100644 --- a/content/client-server-api/modules/instant_messaging.md +++ b/content/client-server-api/modules/instant_messaging.md @@ -119,7 +119,7 @@ Clients SHOULD verify the structure of incoming events to ensure that the expected keys exist and that they are of the right type. Clients can discard malformed events or display a placeholder message to the user. Redacted `m.room.message` events MUST be removed from the client. This -can either be replaced with placeholder text (e.g. "\[REDACTED\]") or +can either be replaced with placeholder text (e.g. "[REDACTED]") or the redacted message can be removed entirely from the messages view. Events which have attachments (e.g. `m.image`, `m.file`) SHOULD be diff --git a/content/client-server-api/modules/recent_emoji.md b/content/client-server-api/modules/recent_emoji.md new file mode 100644 index 00000000..77c0c12b --- /dev/null +++ b/content/client-server-api/modules/recent_emoji.md @@ -0,0 +1,40 @@ +### Recently used emoji + +{{% added-in v="1.18" %}} + +This module enables clients to track a user's cumulated emoji usage across different +devices. The data is stored in the [`m.recent_emoji`](#mrecent_emoji) +global [account data](#client-config) and can, among other things, be used to +generate recommendations in emoji pickers. + +#### Events + +{{% event event="m.recent_emoji" %}} + +#### Client behaviour + +What exactly constitutes trackable emoji usage is left as an implementation detail +for clients. It is RECOMMENDED to include sending emoji in both messages and +annotations. + +When an emoji is used, the sending client moves (or adds) it to the beginning of +the `recent_emoji` array and increments (or initializes) its counter. This keeps +the array ordered by last usage time which facilitates evaluating the data. How +exactly the client evaluates and uses the collected data is deliberately left +unspecified. + +To prevent excessive growth of the event as new emoji are being used, clients +SHOULD limit the length of the `recent_emoji` array by dropping elements from +its end. A RECOMMENDED maximum length is 100 emoji. + +To enable future extension, clients MUST tolerate and preserve array elements +within `recent_emoji` regardless of whether they understand or support the +contained `emoji` value. This means ignoring entries with unrecognised values +of `emoji` when deciding what to display to the user while retaining them when +modifying the array (unless the modification is for truncation). + +To prevent undefined behavior, clients SHOULD remove array elements that +don't conform to the event schema such as elements with negative counters. + + + diff --git a/content/identity-service-api.md b/content/identity-service-api.md index 3c20a12a..8946ad34 100644 --- a/content/identity-service-api.md +++ b/content/identity-service-api.md @@ -2,17 +2,15 @@ title: "Identity Service API" weight: 40 type: docs +description: | + The Matrix client-server and server-server APIs are largely expressed in + Matrix user identifiers. Sometimes it is useful to refer to users by other + (β€œthird-party”) identifiers such as email addresses or phone numbers. The + Identity Service API describes how mappings between 3PIDs and Matrix user + IDs can be established, validated, and used; in practice this has been + applied to email addresses and phone numbers. --- -The Matrix client-server and server-server APIs are largely expressed in -Matrix user identifiers. From time to time, it is useful to refer to -users by other ("third-party") identifiers, or "3PID"s, e.g. their email -address or phone number. This Identity Service Specification describes -how mappings between third-party identifiers and Matrix user identifiers -can be established, validated, and used. This description technically -may apply to any 3PID, but in practice has only been applied -specifically to email addresses and phone numbers. - ## General principles The purpose of an identity server is to validate, store, and answer diff --git a/content/proposals.md b/content/proposals.md index 8abf79d1..3b9a707f 100644 --- a/content/proposals.md +++ b/content/proposals.md @@ -408,41 +408,9 @@ development or testing data. that a particular MSC works) do not have to follow this process. 1. Have an idea for a feature. -1. Implement the feature using unstable endpoints, vendor prefixes, and - unstable feature flags as appropriate. - - When using unstable endpoints, they MUST include a vendor - prefix. For example: - `/_matrix/client/unstable/com.example/login`. Vendor prefixes - throughout Matrix always use the Java package naming convention. - The MSC for the feature should identify which preferred vendor - prefix is to be used by early adopters. - - Note that unstable namespaces do not automatically inherit - endpoints from stable namespaces: for example, the fact that - `/_matrix/client/r0/sync` exists does not imply that - `/_matrix/client/unstable/com.example/sync` exists. - - If the client needs to be sure the server supports the feature, - an unstable feature flag that MUST be vendor prefixed is to be - used. This kind of flag shows up in the `unstable_features` - section of `/versions` as, for example, `com.example.new_login`. - The MSC for the feature should identify which preferred feature - flag is to be used by early adopters. - - When using this approach correctly, the implementation can - ship/release the feature at any time, so long as the - implementation is able to accept the technical debt that results - from needing to provide adequate backwards and forwards - compatibility. The implementation MUST support the flag (and - server-side implementation) disappearing and be generally safe - for users. Note that implementations early in the MSC review - process may also be required to provide backwards compatibility - with earlier editions of the proposal. - - If the implementation cannot support the technical debt (or if - it's impossible to provide forwards/backwards compatibility - - e.g. a user authentication change which can't be safely rolled - back), the implementation should not attempt to implement the - feature and should instead wait for a spec release. - - If at any point after early release, the idea changes in a - backwards-incompatible way, the feature flag should also change - so that implementations can adapt as needed. +1. Implement the feature using [unstable endpoints, vendor prefixes, and + unstable feature flags](#unstable-endpoints-features-and-vendor-prefixes) + as appropriate. 1. In parallel, or ahead of implementation, open an MSC and solicit review per above. 1. Before FCP can be called, the Spec Core Team will require evidence @@ -452,10 +420,7 @@ that a particular MSC works) do not have to follow this process. forwards/backwards compatibility concerns mentioned here. 1. The FCP process is completed, and assuming nothing is flagged the MSC lands. -1. Implementations can now switch to using stable prefixes - (for example, for an endpoint, moving from - `/unstable/org.matrix.mscxxxx/frobnicate` - to `/v1/frobnicate`), assuming that the change +1. Implementations can now switch to using stable prefixes, assuming that the change is backwards compatible with older implementations. In the rare occasion where backwards compatibility is not possible without a new spec release, implementations should continue to use unstable prefixes. @@ -471,13 +436,6 @@ that a particular MSC works) do not have to follow this process. started supporting the new spec release, some noise should be raised in the general direction of the implementation. -{{% boxes/note %}} -MSCs MUST still describe what the stable endpoints/feature looks like -with a note towards the bottom for what the unstable feature -flag/prefixes are. For example, an MSC would propose `/_matrix/client/r0/new/endpoint`, not `/_matrix/client/unstable/ -com.example/new/endpoint`. -{{% /boxes/note %}} - In summary: - Implementations MUST NOT use stable endpoints before the MSC has @@ -489,14 +447,90 @@ In summary: - Implementations SHOULD be wary of the technical debt they are incurring by moving faster than the spec. - The vendor prefix is chosen by the developer of the feature, using - the Java package naming convention. The foundation's preferred - vendor prefix is `org.matrix`. + the Java package naming convention. - The vendor prefixes, unstable feature flags, and unstable endpoints should be included in the MSC, though the MSC MUST be written in a way that proposes new stable endpoints. Typically this is solved by a small table at the bottom mapping the various values from stable to unstable. +#### Unstable endpoints, features and vendor prefixes + +Unstable endpoints MUST use `/unstable` as the endpoint version and a +vendor prefix in Java package naming format. For example: +`/_matrix/client/unstable/com.example.mscxxxx/login`. + +{{% boxes/note %}} +Proposal authors operating with a Matrix.org Foundation mandate SHOULD use +a vendor prefix within the `org.matrix` namespace. This namespace is otherwise +restricted. Authors who don't own a domain MAY use the `io.github` namespace +instead. +{{% /boxes/note %}} + +Note that unstable namespaces do not automatically inherit endpoints from +stable namespaces: for example, the fact that `/_matrix/client/v3/sync` +exists does not imply that `/_matrix/client/unstable/com.example.mscxxxx/sync` +exists. + +Vendor prefixes MUST also be used for: + +- New parameters on existing endpoints. For example: + `/_matrix/client/v3/publicRooms?com.example.mscxxxx.ordered_by=member_count`. +- New properties in existing JSON objects. For example: + + ```json + { + "avatar_url": "mxc://matrix.org/SDGdghriugerRg", + "displayname": "Alice Margatroid", + "com.example.mscxxxx.phone": [{ + "type": "landline", + "number": "+1-206-555-7000" + }], + ... + } + ``` + +- New values for existing parameters or properties. For example: + + ```json + { + "errcode": "COM.EXAMPLE.MSCXXXX.M_INVALID_EMAIL", + "error": "The email address you provided is invalid." + } + ``` + +If the client needs to be sure the server supports the feature, an +unstable feature flag that MUST also be vendor prefixed is to be used. +This flag shows up in the `unstable_features` section of +[`/_matrix/client/versions`](/client-server-api/#get_matrixclientversions) +as, for example, `com.example.mscxxxx.new_login`. + +{{% boxes/note %}} +MSCs MUST still describe what the stable endpoints/feature looks like +with a note towards the bottom for what the unstable feature +flag/prefixes are. For example, an MSC would propose `/_matrix/client/v1/new/endpoint`, +not `/_matrix/client/unstable/com.example.mscxxxx/new/endpoint`. +{{% /boxes/note %}} + +When using this approach correctly, the implementation can release +the feature at any time, so long as the implementation is able to +accept the technical debt that results from needing to provide +adequate backwards and forwards compatibility. The implementation +MUST support the flag (and server-side implementation) disappearing +and be generally safe for users. Note that implementations early in +the MSC review process may also be required to provide backwards +compatibility with earlier editions of the proposal. + +If the implementation cannot support the technical debt (or if it's +impossible to provide forwards/backwards compatibility - e.g. a user +authentication change which can't be safely rolled back), the +implementation should not attempt to implement the feature and should +instead wait for a spec release. + +If at any point after early release, the idea changes in a +backwards-incompatible way, the feature flag should also change so +that implementations can adapt as needed. + ### Placeholder MSCs Some proposals may contain security-sensitive or private context which can't be diff --git a/content/push-gateway-api.md b/content/push-gateway-api.md index 161cf24f..f74decd9 100644 --- a/content/push-gateway-api.md +++ b/content/push-gateway-api.md @@ -2,12 +2,11 @@ title: "Push Gateway API" weight: 50 type: docs +description: | + Clients may want to receive push notifications when events are received at the + homeserver. This is managed by a distinct entity called the Push Gateway. --- -Clients may want to receive push notifications when events are received -at the homeserver. This is managed by a distinct entity called the Push -Gateway. - ## Overview A client's homeserver forwards information about received events to the diff --git a/content/server-server-api.md b/content/server-server-api.md index ca1cdd2e..1ab7e3ba 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -2,49 +2,46 @@ title: "Server-Server API" weight: 20 type: docs +description: | + Matrix homeservers use the Federation APIs (also known as server-server APIs) + to communicate with each other. Homeservers use these APIs to push messages in + real-time, retrieve historic messages, and query profile or presence + information about users on other servers. The APIs are implemented over HTTPS, + with authentication provided by public key signatures both at the TLS + transport layer and in HTTP Authorization headers. + + There are three main kinds of communication that occur between + homeservers: + + Persistent Data Units (PDUs): + These events are broadcast from one homeserver to any others that have + joined the same room (identified by Room ID). They are persisted in + long-term storage and record the history of messages and state for a + room. + + Like email, it is the responsibility of the originating server of a PDU + to deliver that event to its recipient servers. However PDUs are signed + using the originating server's private key so that it is possible to + deliver them through third-party servers. + + Ephemeral Data Units (EDUs): + These events are pushed between pairs of homeservers. They are not + persisted and are not part of the history of a room, nor does the + receiving homeserver have to reply to them. + + Queries: + These are single request/response interactions between a given pair of + servers, initiated by one side sending an HTTPS GET request to obtain + some information, and responded by the other. They are not persisted and + contain no long-term significant history. They simply request a snapshot + state at the instant the query is made. + + EDUs and PDUs are further wrapped in an envelope called a Transaction, + which is transferred from the origin to the destination homeserver using + an HTTPS PUT request. + --- -Matrix homeservers use the Federation APIs (also known as server-server -APIs) to communicate with each other. Homeservers use these APIs to push -messages to each other in real-time, to retrieve historic messages from -each other, and to query profile and presence information about users on -each other's servers. - -The APIs are implemented using HTTPS requests between each of the -servers. These HTTPS requests are strongly authenticated using public -key signatures at the TLS transport layer and using public key -signatures in HTTP Authorization headers at the HTTP layer. - -There are three main kinds of communication that occur between -homeservers: - -Persistent Data Units (PDUs): -These events are broadcast from one homeserver to any others that have -joined the same room (identified by Room ID). They are persisted in -long-term storage and record the history of messages and state for a -room. - -Like email, it is the responsibility of the originating server of a PDU -to deliver that event to its recipient servers. However PDUs are signed -using the originating server's private key so that it is possible to -deliver them through third-party servers. - -Ephemeral Data Units (EDUs): -These events are pushed between pairs of homeservers. They are not -persisted and are not part of the history of a room, nor does the -receiving homeserver have to reply to them. - -Queries: -These are single request/response interactions between a given pair of -servers, initiated by one side sending an HTTPS GET request to obtain -some information, and responded by the other. They are not persisted and -contain no long-term significant history. They simply request a snapshot -state at the instant the query is made. - -EDUs and PDUs are further wrapped in an envelope called a Transaction, -which is transferred from the origin to the destination homeserver using -an HTTPS PUT request. - ## API standards The mandatory baseline for server-server communication in Matrix is diff --git a/data/api/client-server/cross_signing.yaml b/data/api/client-server/cross_signing.yaml index ec490b2a..f340bd59 100644 --- a/data/api/client-server/cross_signing.yaml +++ b/data/api/client-server/cross_signing.yaml @@ -21,13 +21,17 @@ paths: x-addedInMatrixVersion: "1.1" x-changedInMatrixVersion: "1.11": UIA is not always required for this endpoint. + "1.17": |- + This endpoint no longer requires User-Interactive Authentication when used by an + application service. summary: Upload cross-signing keys. description: |- Publishes cross-signing keys for the user. - This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api). + This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api), + except when used by an application service. - User-Interactive Authentication MUST be performed, except in these cases: + User-Interactive Authentication MUST be performed for regular clients, except in these cases: - there is no existing cross-signing master key uploaded to the homeserver, OR - there is an existing cross-signing master key and it exactly matches the cross-signing master key provided in the request body. If there are any additional diff --git a/data/api/client-server/definitions/recent_emoji.yaml b/data/api/client-server/definitions/recent_emoji.yaml new file mode 100644 index 00000000..c2deab94 --- /dev/null +++ b/data/api/client-server/definitions/recent_emoji.yaml @@ -0,0 +1,29 @@ +# Copyright 2026 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. + +title: Recent Emoji +type: object +properties: + emoji: + type: string + description: The Unicode emoji as string. + example: πŸš€ + total: + type: number + description: |- + The number of times the emoji has been used. + MUST be non-negative and smaller than 2^53. +required: + - emoji + - total diff --git a/data/api/client-server/definitions/request_token_response.yaml b/data/api/client-server/definitions/request_token_response.yaml index 0f8c8cab..693cffce 100644 --- a/data/api/client-server/definitions/request_token_response.yaml +++ b/data/api/client-server/definitions/request_token_response.yaml @@ -24,16 +24,23 @@ properties: submit_url: type: string format: uri + x-changedInMatrixVersion: + "1.18": |- + The URL has the same request and response parameters and error codes as + the Identity Service API's endpoint. description: |- An optional field containing a URL where the client must submit the - validation token to, with identical parameters to the Identity Service - API's `POST /validate/email/submitToken` endpoint (without the requirement - for an access token). The homeserver must send this token to the user (if - applicable), who should then be prompted to provide it to the client. + validation token, with identical request and response parameters and error + codes to the Identity Service API's + [`POST /validate/email/submitToken`](/identity-service-api/#post_matrixidentityv2validateemailsubmittoken) + and [`POST /validate/msisdn/submitToken`](/identity-service-api/#post_matrixidentityv2validatemsisdnsubmittoken) + endpoints (without the requirement for an access token). The homeserver + must send this token to the user (if applicable), who should then be + prompted to provide it to the client. If this field is not present, the client can assume that verification will happen without the client's involvement provided the homeserver - advertises this specification version in the `/versions` response - (ie: r0.5.0). + advertises a sufficiently recent version in the [`GET /versions`](/client-server-api/#get_matrixclientversions) + response (ie: r0.5.0). example: "https://example.org/path/to/submitToken" required: ['sid'] diff --git a/data/api/client-server/device_management.yaml b/data/api/client-server/device_management.yaml index 1f66f856..e5ae56ce 100644 --- a/data/api/client-server/device_management.yaml +++ b/data/api/client-server/device_management.yaml @@ -87,8 +87,21 @@ paths: tags: - Device management put: - summary: Update a device - description: Updates the metadata on the given device. + summary: Create or update a device + x-changedInMatrixVersion: + "1.17": The ability to create new devices was added. + description: |- + Updates the metadata on the given device, or creates a new device. + + The ability to create new devices is only available to application + services: regular clients may only update existing devices. + + When a new device was created, the homeserver MUST return a 201 HTTP + status code. It MUST return a 200 HTTP status code if a device was + updated. + + This endpoint is rate-limited for device creation. Servers MAY use login + rate limits. operationId: updateDevice security: - accessTokenQuery: [] @@ -127,19 +140,34 @@ paths: examples: response: value: {} + "201": + description: |- + The device was successfully created by the application service. + content: + application/json: + schema: + type: object + examples: + response: + value: {} "404": description: The current user has no device with the given ID. tags: - Device management delete: summary: Delete a device + x-changedInMatrixVersion: + "1.17": |- + This endpoint no longer requires User-Interactive Authentication when used by an + application service. description: |- - This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api). + This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api), + except when used by an application service. Deletes the given device, and invalidates any access token associated with it. {{% boxes/warning %}} - Since this endpoint uses User-Interactive Authentication, it cannot be used when the access token was obtained + When this endpoint requires User-Interactive Authentication, it cannot be used when the access token was obtained via the [OAuth 2.0 API](/client-server-api/#oauth-20-api). {{% /boxes/warning %}} @@ -197,13 +225,18 @@ paths: /delete_devices: post: summary: Bulk deletion of devices + x-changedInMatrixVersion: + "1.17": |- + This endpoint no longer requires User-Interactive Authentication when used by an + application service. description: |- - This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api). + This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api), + except when used by an application service. Deletes the given devices, and invalidates any access token associated with them. {{% boxes/warning %}} - Since this endpoint uses User-Interactive Authentication, it cannot be used when the access token was obtained + When this endpoint requires User-Interactive Authentication, it cannot be used when the access token was obtained via the [OAuth 2.0 API](/client-server-api/#oauth-20-api). {{% /boxes/warning %}} diff --git a/data/api/client-server/login.yaml b/data/api/client-server/login.yaml index 4eba954e..7251d4ff 100644 --- a/data/api/client-server/login.yaml +++ b/data/api/client-server/login.yaml @@ -243,8 +243,13 @@ paths: } } "400": - description: Part of the request was invalid. For example, the login type may - not be recognised. + description: |- + Part of the request was invalid. For example, the login type may not be recognised. + + Specific error codes used with this status code include: + * {{% added-in v="1.17" %}} `M_APPSERVICE_LOGIN_UNSUPPORTED`: an application service + used the `m.login.application_service` type, but the server doesn't support logging + in via the Legacy authentication API. content: application/json: schema: diff --git a/data/api/client-server/oauth_server_metadata.yaml b/data/api/client-server/oauth_server_metadata.yaml index 4cdb3aa6..719a1e16 100644 --- a/data/api/client-server/oauth_server_metadata.yaml +++ b/data/api/client-server/oauth_server_metadata.yaml @@ -139,6 +139,32 @@ paths: items: type: string description: A prompt value that the server supports. + account_management_uri: + x-addedInMatrixVersion: "1.18" + type: string + format: uri + description: |- + The URL where the user is able to access the account management capabilities + of the homeserver. + + This is an extension [defined in this specification](/client-server-api/#oauth-20-account-management). + account_management_actions_supported: + x-addedInMatrixVersion: "1.18" + type: array + description: |- + List of actions that the account management URL supports. + + This is an extension [defined in this specification](/client-server-api/#oauth-20-account-management). + items: + type: string + enum: + - "org.matrix.profile" + - "org.matrix.devices_list" + - "org.matrix.device_view" + - "org.matrix.device_delete" + - "org.matrix.account_deactivate" + - "org.matrix.cross_signing_reset" + description: An action that the account management URL supports. required: - issuer - authorization_endpoint @@ -159,6 +185,15 @@ paths: "grant_types_supported": ["authorization_code", "refresh_token"], "response_modes_supported": ["query", "fragment"], "code_challenge_methods_supported": ["S256"], + "account_management_uri": "https://account.example.com/manage", + "account_management_actions_supported": [ + "org.matrix.profile", + "org.matrix.devices_list", + "org.matrix.device_view", + "org.matrix.device_delete", + "org.matrix.account_deactivate", + "org.matrix.cross_signing_reset", + ], } tags: - Session management diff --git a/data/api/client-server/registration.yaml b/data/api/client-server/registration.yaml index 0e88870a..25c6bf4a 100644 --- a/data/api/client-server/registration.yaml +++ b/data/api/client-server/registration.yaml @@ -61,6 +61,18 @@ paths: Any user ID returned by this API must conform to the grammar given in the [Matrix specification](/appendices/#user-identifiers). + {{% boxes/note %}} + {{% added-in v="1.17" %}} + Even if the server doesn't support the Legacy authentication API, it + MUST support this endpoint for application services to be able to + [create users](/application-service-api/#server-admin-style-permissions). + + In that case application services MUST set the `"inhibit_login": true` + parameter as they cannot use it to log in as users. If the + `inhibit_login` parameter is not set to `true`, the server MUST return a + 400 HTTP status code with an `M_APPSERVICE_LOGIN_UNSUPPORTED` error code. + {{% /boxes/note %}} + {{% boxes/warning %}} {{% added-in v="1.18" %}} [OAuth 2.0 aware clients](/client-server-api/#oauth-20-aware-clients) MUST NOT use this endpoint when the server offers the [`m.login.sso` @@ -211,6 +223,9 @@ paths: * `M_INVALID_USERNAME` : The desired user ID is not a valid user name. * `M_EXCLUSIVE` : The desired user ID is in the exclusive namespace claimed by an application service. + * {{% added-in v="1.17" %}} `M_APPSERVICE_LOGIN_UNSUPPORTED`: an application service + used the `m.login.application_service` type without setting `inhibit_login` to `true`, + but the server doesn't support logging in via the Legacy authentication API. These errors may be returned at any stage of the registration process, including after authentication if the requested user ID was registered diff --git a/data/api/client-server/rooms.yaml b/data/api/client-server/rooms.yaml index a5c9977e..3716b6a4 100644 --- a/data/api/client-server/rooms.yaml +++ b/data/api/client-server/rooms.yaml @@ -223,7 +223,7 @@ paths: type: string # XXX: As mentioned in MSC1227, replacing `[not_]membership` with a JSON # filter might be a better alternative. - # See https://github.com/matrix-org/matrix-doc/issues/1337 + # See https://github.com/matrix-org/matrix-doc/issues/1227 - in: query name: membership description: |- diff --git a/data/api/client-server/third_party_lookup.yaml b/data/api/client-server/third_party_lookup.yaml index 152f277d..32adb094 100644 --- a/data/api/client-server/third_party_lookup.yaml +++ b/data/api/client-server/third_party_lookup.yaml @@ -78,7 +78,7 @@ paths: }, "room": { "regexp": "[^\\s]+\\/[^\\s]+", - "placeholder": "matrix-org/matrix-doc" + "placeholder": "matrix-org/matrix-spec" } }, "instances": [ diff --git a/data/api/identity/v2_email_associations.yaml b/data/api/identity/v2_email_associations.yaml index 81f4486c..da6c9c1b 100644 --- a/data/api/identity/v2_email_associations.yaml +++ b/data/api/identity/v2_email_associations.yaml @@ -153,6 +153,24 @@ paths: value: { "success": true } + "400": + description: | + An error occurred. Some possible errors are: + + - {{% added-in v="1.18" %}} `M_TOKEN_INCORRECT`: The token that the user entered to validate the session is + incorrect. + - {{% added-in v="1.18" %}} `M_INVALID_PARAM`: One of the supplied parameters is not valid. + - {{% added-in v="1.18" %}} `M_SESSION_EXPIRED`: The validation session in question has expired. + content: + application/json: + schema: + $ref: ../client-server/definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_TOKEN_INCORRECT", + "error": "The token is incorrect" + } "403": description: | The user must do something in order to use this endpoint. One example diff --git a/data/api/identity/v2_phone_associations.yaml b/data/api/identity/v2_phone_associations.yaml index b985a972..5ebf58bc 100644 --- a/data/api/identity/v2_phone_associations.yaml +++ b/data/api/identity/v2_phone_associations.yaml @@ -155,6 +155,24 @@ paths: value: { "success": true } + "400": + description: | + An error occurred. Some possible errors are: + + - {{% added-in v="1.18" %}} `M_TOKEN_INCORRECT`: The token that the user entered to validate the session is + incorrect. + - {{% added-in v="1.18" %}} `M_INVALID_PARAM`: One of the supplied parameters is not valid. + - {{% added-in v="1.18" %}} `M_SESSION_EXPIRED`: The validation session in question has expired. + content: + application/json: + schema: + $ref: ../client-server/definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_TOKEN_INCORRECT", + "error": "The token is incorrect" + } "403": description: | The user must do something in order to use this endpoint. One example diff --git a/data/api/server-server/openid.yaml b/data/api/server-server/openid.yaml index ce7d8866..22b7f941 100644 --- a/data/api/server-server/openid.yaml +++ b/data/api/server-server/openid.yaml @@ -43,7 +43,12 @@ paths: properties: sub: type: string - description: The Matrix User ID who generated the token. + description: | + The Matrix User ID who generated the token. + + The caller MUST validate that the returned user ID is on the server they + called (i.e. if you make a request to example.com and it returns + `@alice:matrix.org`, the result is invalid). example: "@alice:example.com" required: - sub diff --git a/data/event-schemas/examples/m.recent_emoji.yaml b/data/event-schemas/examples/m.recent_emoji.yaml new file mode 100644 index 00000000..85b15cc6 --- /dev/null +++ b/data/event-schemas/examples/m.recent_emoji.yaml @@ -0,0 +1,16 @@ +{ + "$ref": "core/event.json", + "type": "m.recent_emoji", + "content": { + "recent_emoji": [{ + "emoji": "πŸ€”", + "total": 19 + }, { + "emoji": "πŸ‘", + "total": 7 + }, { + "emoji": "πŸ˜…", + "total": 84 + }] + } +} diff --git a/data/event-schemas/schema/m.recent_emoji.yaml b/data/event-schemas/schema/m.recent_emoji.yaml new file mode 100644 index 00000000..8db49a48 --- /dev/null +++ b/data/event-schemas/schema/m.recent_emoji.yaml @@ -0,0 +1,29 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "title": "Recent Emoji Event", + "description": "Lets clients maintain a list of recently used emoji.", + "allOf": [{ + "$ref": "core-event-schema/event.yaml" + }], + "properties": { + "type": { + "type": "string", + "enum": ["m.recent_emoji"] + }, + "content": { + "type": "object", + "properties": { + "recent_emoji": { + "description": "The list of recently used emoji. Elements in the list are ordered descendingly by last usage time.", + "type": "array", + "items": { + "$ref": "../../api/client-server/definitions/recent_emoji.yaml" + }, + } + }, + "required": ["recent_emoji"] + } + }, + "required": ["type", "content"] +} diff --git a/data/schemas/oauth2-account-management-server-metadata.yaml b/data/schemas/oauth2-account-management-server-metadata.yaml new file mode 100644 index 00000000..7bb43db4 --- /dev/null +++ b/data/schemas/oauth2-account-management-server-metadata.yaml @@ -0,0 +1,30 @@ +# Copyright 2026 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: OAuth 2.0 Server Metadata Account Management Extension +properties: + account_management_uri: + type: string + format: uri + description: |- + The URL where the user is able to access the account management capabilities of the + server. + account_management_actions_supported: + type: array + description: |- + List of [actions](/client-server-api/#account-management-url-actions) that the account + management URL supports. + items: + type: string + description: An action that the account management URL supports. diff --git a/data/schemas/oauth2-account-management-url.yaml b/data/schemas/oauth2-account-management-url.yaml new file mode 100644 index 00000000..d6220841 --- /dev/null +++ b/data/schemas/oauth2-account-management-url.yaml @@ -0,0 +1,29 @@ +# Copyright 2026 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: OAuth 2.0 Account Management URL Query Parameters +properties: + action: + type: string + description: |- + The action that the user wishes to take. Must match one of the actions advertised by the + server in [`account_management_actions_supported`](/client-server-api/#account-management-url-discovery). + device_id: + type: string + description: |- + For Matrix-specific actions, the user's device ID. Actions which don't support the device ID + will ignore it. + + If the `org.matrix.device_view` or `org.matrix.device_delete` actions are advertised as + supported by the server then the server SHOULD support the `device_id` parameter. diff --git a/go.mod b/go.mod index 60143ea9..6b13c46b 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module github.com/matrix-org/matrix-spec go 1.12 -require github.com/matrix-org/docsy v0.0.0-20250722140156-5df72519f5af // indirect +require github.com/matrix-org/docsy v0.0.0-20260106184755-71d103ebb20a // indirect diff --git a/go.sum b/go.sum index ea991476..3897374a 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,4 @@ github.com/FortAwesome/Font-Awesome v0.0.0-20241216213156-af620534bfc3/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo= -github.com/matrix-org/docsy v0.0.0-20250722140156-5df72519f5af h1:XghgUC0H5BoGrvtT9/oWBUi+5Zux875qRHhpAZ0RURI= -github.com/matrix-org/docsy v0.0.0-20250722140156-5df72519f5af/go.mod h1:4/t21g/nPraob/DVMm3jrk26k0CDL5I7Mxf+ar0IAgs= -github.com/twbs/bootstrap v5.3.6+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0= +github.com/matrix-org/docsy v0.0.0-20260106184755-71d103ebb20a h1:WB3unuZJy7ewAf33sxbtEwYnC+i+Jt1sJpAR3BtzvEo= +github.com/matrix-org/docsy v0.0.0-20260106184755-71d103ebb20a/go.mod h1:mdn1m5HJug6ZddQgrOyCrXNegbtdl5evHiqqbEQLzdI= +github.com/twbs/bootstrap v5.3.8+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0= diff --git a/layouts/_markup/render-passthrough.html b/layouts/_markup/render-passthrough.html index 425471a9..d5f85ded 100644 --- a/layouts/_markup/render-passthrough.html +++ b/layouts/_markup/render-passthrough.html @@ -5,15 +5,7 @@ We use it to send the delimited passthrough element through KaTeX to render maths in the Olm / Megolm spec. - See: https://gohugo.io/functions/transform/tomath/#step-2 + See: https://www.docsy.dev/docs/content/diagrams-and-formulae/#add-passthrough-render-hook */ -}} -{{- $opts := dict "output" "htmlAndMathml" "displayMode" (eq .Type "block") }} -{{- with try (transform.ToMath .Inner $opts) }} - {{- with .Err }} - {{- errorf "Unable to render mathematical markup to HTML using the transform.ToMath function. The KaTeX display engine threw the following error: %s: see %s." . $.Position }} - {{- else }} - {{- .Value }} - {{- $.Page.Store.Set "hasMath" true }} - {{- end }} -{{- end -}} +{{ partial "scripts/math.html" . }} diff --git a/layouts/_partials/breadcrumb.html b/layouts/_partials/breadcrumb.html index af3a9551..bfe89399 100644 --- a/layouts/_partials/breadcrumb.html +++ b/layouts/_partials/breadcrumb.html @@ -1,28 +1,35 @@ {{/* - A copy of the breadcrumb.html partial in Docsy, modified - to: + A copy of the breadcrumb.html partial in Docsy, modified to: + + * show the breadcrumbs by default by removing the `td-breadcrumbs__single` + class * omit breadcrumbs when this is the homepage * otherwise, include the homepage in the breadcrumbs */}} -{{ if not .IsHome }} +{{ if not .IsHome -}} -{{ end }} + + +{{ end -}} -{{ define "breadcrumbnav" }} -{{ if .p1.Parent }} -{{ template "breadcrumbnav" (dict "p1" .p1.Parent "p2" .p2 ) }} -{{ else if not .p1.IsHome }} -{{ template "breadcrumbnav" (dict "p1" .p1.Site.Home "p2" .p2 ) }} -{{ end }} -{{ $isActive := eq .p1 .p2 }} - -{{ end }} +{{- define "breadcrumbnav" -}} + {{ if .p1.Parent -}} + {{ template "breadcrumbnav" (dict "p1" .p1.Parent "p2" .p2 ) -}} + {{ else if not .p1.IsHome -}} + {{ template "breadcrumbnav" (dict "p1" .p1.Site.Home "p2" .p2 ) -}} + {{ end -}} + {{ $isActive := eq .p1 .p2 }} + +{{- end -}} diff --git a/layouts/_partials/endpoints-toc.html b/layouts/_partials/endpoints-toc.html new file mode 100644 index 00000000..f5a652ef --- /dev/null +++ b/layouts/_partials/endpoints-toc.html @@ -0,0 +1,61 @@ +{{/* + + Renders a list of API endpoints for the current page, given: + + The outer page's Scratch must contain an "api_endpoints" key, which is either + a slice of maps (a list of endpoint metadata dicts) or a map of module name -> + slice of endpoint metadata dicts (representing the API modules and the + endpoints they each contain). Each endpoint dict must contain the following + keys: + + * `anchor`: the HTML anchor for the endpoint + * `method`: the HTTP method + * `endpoint`: the endpoint path + * `summary`: a short summary of the endpoint + * `deprecated`: whether the endpoint is deprecated + * `module`: the CS API module name, if any, for grouping purposes. If empty, + the endpoint is considered "base" or "required". + +*/}} + +{{ $raw := .Scratch.Get "api_endpoints" }} +{{/* Normalize to a slice */}} +{{ $endpoints := slice }} +{{ if reflect.IsSlice $raw }} + {{ $endpoints = $raw }} +{{ else if reflect.IsMap $raw }} + {{ range $raw }} + {{ $endpoints = append $endpoints . }} + {{ end }} +{{ end }} +{{ if gt (len $endpoints) 0 }} +
+
+ List of Endpoints + {{/* Sort by module to group visually */}} + {{ $sorted := sort $endpoints "module" }} + {{ $current := "" }} + {{ range $sorted }} + {{ $mod := .module }} + {{/* Set a title for the base endpoints */}} + {{ if not $mod }}{{ $mod = "Required" }}{{ end }} + {{ if ne $mod $current }} + {{ if $current }}
{{ end }} +
+
{{ $mod }}
+
{{ end }} + + +{{ end }} diff --git a/layouts/_partials/navbar.html b/layouts/_partials/navbar.html index 0de6f46c..0a563d8f 100644 --- a/layouts/_partials/navbar.html +++ b/layouts/_partials/navbar.html @@ -1,8 +1,11 @@ {{- /* - A version of the navbar.html partial in Docsy, only modified - to include the spec version, which is calculated using an - inline `version-string` partial. + A copy of the navbar.html partial in Docsy, modified to: + + * remove `data-bs-theme` at L20, otherwise the title disappears on hover. + * replace the site title with "specification" at L31. + * include the spec version from the config at L34-35, which is calculated + using an inline `version-string` partial. */ -}} @@ -13,8 +16,8 @@ {{ $baseURL := urls.Parse $.Site.Params.Baseurl -}} -{{ define "_partials/version-string" }} - {{ $ret := "unstable version"}} +{{- define "_partials/version-string" -}} + {{ $ret := "unstable version" -}} - {{ $status := .Site.Params.version.status }} + {{ $status := .Site.Params.version.status -}} - {{ if ne $status "unstable"}} - {{ $path := path.Join "changelogs" }} + {{ if ne $status "unstable" -}} + {{ $path := path.Join "changelogs" -}} - {{/* produces a string similar to "version v1.5" */}} - {{ $ret = delimit (slice "version v" .Site.Params.version.major "." .Site.Params.version.minor) "" }} - {{ end }} + {{/* produces a string similar to "version v1.5" */ -}} + {{ $ret = delimit (slice "version v" .Site.Params.version.major "." .Site.Params.version.minor) "" -}} + {{ end -}} - {{ return $ret }} -{{ end }} + {{ return $ret -}} +{{- end -}} diff --git a/layouts/_partials/openapi/render-api.html b/layouts/_partials/openapi/render-api.html index 608cfa33..92d2bdd8 100644 --- a/layouts/_partials/openapi/render-api.html +++ b/layouts/_partials/openapi/render-api.html @@ -7,6 +7,8 @@ of each value in `paths` to get a complete URL. * `anchor_base`: an optional prefix for the HTML IDs generated by this template. + * `page`: the (Hugo) Page object to store endpoint metadata in the Scratch of. Used to build the endpoints TOC. + * `module`: the current CS API module name, if any. Used to group endpoints in the TOC. This template replaces the old {{*_http_api}} template. @@ -15,6 +17,8 @@ {{ $api_data := index .api_data }} {{ $base_url := .base_url }} {{ $anchor_base := .anchor_base }} +{{ $page := .page }} +{{ $module := .module }} {{ range $path_name, $path_data := $api_data.paths }} @@ -26,28 +30,28 @@ {{ with $path_data.get }} - {{ $operation_params := merge $params (dict "method" "GET" "operation_data" . "anchor_base" $anchor_base) }} + {{ $operation_params := merge $params (dict "method" "GET" "operation_data" . "anchor_base" $anchor_base "page" $page "module" $module) }} {{ partial "openapi/render-operation" $operation_params }} {{ end }} {{ with $path_data.post }} - {{ $operation_params := merge $params (dict "method" "POST" "operation_data" . "anchor_base" $anchor_base) }} + {{ $operation_params := merge $params (dict "method" "POST" "operation_data" . "anchor_base" $anchor_base "page" $page "module" $module) }} {{ partial "openapi/render-operation" $operation_params }} {{ end }} {{ with $path_data.put }} - {{ $operation_params := merge $params (dict "method" "PUT" "operation_data" . "anchor_base" $anchor_base) }} + {{ $operation_params := merge $params (dict "method" "PUT" "operation_data" . "anchor_base" $anchor_base "page" $page "module" $module) }} {{ partial "openapi/render-operation" $operation_params }} {{ end }} {{ with $path_data.delete }} - {{ $operation_params := merge $params (dict "method" "DELETE" "operation_data" . "anchor_base" $anchor_base) }} + {{ $operation_params := merge $params (dict "method" "DELETE" "operation_data" . "anchor_base" $anchor_base "page" $page "module" $module) }} {{ partial "openapi/render-operation" $operation_params }} {{ end }} diff --git a/layouts/_partials/openapi/render-operation.html b/layouts/_partials/openapi/render-operation.html index c1e34ddf..d90a1d7e 100644 --- a/layouts/_partials/openapi/render-operation.html +++ b/layouts/_partials/openapi/render-operation.html @@ -7,6 +7,8 @@ * `operation_data`: the OpenAPI data for the operation * `anchor_base`: an optional prefix for the HTML IDs generated by this template. + * `page`: the (Hugo) Page object to store endpoint metadata in the Scratch of. Used to build the endpoints TOC. + * `module`: the current CS API module name, if any. Used to group endpoints in the TOC. This template renders the operation as a `
` containing: @@ -22,6 +24,8 @@ {{ $method := .method }} {{ $endpoint := .endpoint }} {{ $operation_data := .operation_data }} +{{ $page := .page }} +{{ $module := .module }} {{ $anchor := "" }} {{ if .anchor_base }} @@ -29,6 +33,27 @@ {{ end }} {{ $anchor = printf "%s%s%s" $anchor (lower $method) (anchorize $endpoint) }} +{{/* Collect endpoints for the on-page endpoints TOC */}} +{{ if $page }} + {{/* Store each endpoint's metadata in a scratch variable */}} + {{ $entry := dict "anchor" $anchor "method" $method "endpoint" $endpoint "summary" $operation_data.summary "deprecated" $operation_data.deprecated "module" $module }} + {{ if not ($page.Scratch.Get "api_endpoints_seen") }} + {{ $page.Scratch.Set "api_endpoints_seen" dict }} + {{ end }} + {{/* Keep a map of seen endpoints. This is necessary as this partial may be + rendered multiple times for the same endpoint (e.g. in the TOC and + in the main content), leading to duplicates. */}} + {{ $seen := $page.Scratch.Get "api_endpoints_seen" }} + {{ $key := printf "%s|%s" $method $endpoint }} + {{ if not (index $seen $key) }} + {{ if not (reflect.IsSlice ($page.Scratch.Get "api_endpoints")) }} + {{ $page.Scratch.Set "api_endpoints" (slice) }} + {{ end }} + {{ $page.Scratch.Add "api_endpoints" (slice $entry) }} + {{ $page.Scratch.SetInMap "api_endpoints_seen" $key true }} + {{ end }} +{{ end }} +
diff --git a/layouts/_partials/sidebar-tree.html b/layouts/_partials/sidebar-tree.html index dba63f3a..e5f00807 100644 --- a/layouts/_partials/sidebar-tree.html +++ b/layouts/_partials/sidebar-tree.html @@ -1,37 +1,57 @@ {{- /* - A modified version of the siderbar-tree.html partial in Docsy, adding: - - * The "toc.html" partial at L45. + A copy of the siderbar-tree.html partial in Docsy, modified to: + + * Ignore the `sidebarRoot` parameter, because of this regression: + + * Add the "toc.html" partial at L68. */ -}} -{{/* We cache this partial for bigger sites and set the active class client side. */ -}} -{{ $sidebarCacheLimit := .Site.Params.ui.sidebar_cache_limit | default 2000 -}} -{{ $shouldDelayActive := ge (len .Site.Pages) $sidebarCacheLimit -}} +{{ $context := .context -}} +{{ $sidebarRoot := .sidebarRoot -}} +{{ $sidebarRootID := .sidebarRootID -}} +{{ $cacheSidebar := .cacheSidebar -}} + +{{ with $context -}} +{{/* When the sidebar is cached, "active" class is set client side. */ -}} +{{ $shouldDelayActive := $cacheSidebar -}} +
{{ if not .Site.Params.ui.sidebar_search_disable -}} + - {{ else -}} + + {{- else -}} +
- {{ end -}} + + {{- end }} + {{/* */ -}} +
+ +{{- end }}{{/* with $context */ -}} + {{ define "section-tree-nav-section" -}} -{{ $s := .section -}} -{{ $p := .page -}} -{{ $shouldDelayActive := .shouldDelayActive -}} -{{ $sidebarMenuTruncate := .sidebarMenuTruncate -}} -{{ $treeRoot := cond (eq .ulNr 0) true false -}} -{{ $ulNr := .ulNr -}} -{{ $ulShow := .ulShow -}} -{{ $active := and (not $shouldDelayActive) (eq $s $p) -}} -{{ $activePath := and (not $shouldDelayActive) (or (eq $p $s) ($p.IsDescendant $s)) -}} -{{ $show := cond (or (lt $ulNr $ulShow) $activePath (and (not $shouldDelayActive) (eq $s.Parent $p.Parent)) (and (not $shouldDelayActive) (eq $s.Parent $p)) (not $p.Site.Params.ui.sidebar_menu_compact) (and (not $shouldDelayActive) ($p.IsDescendant $s.Parent))) true false -}} -{{ $mid := printf "m-%s" ($s.RelPermalink | anchorize) -}} -{{ $pages_tmp := where (union $s.Pages $s.Sections).ByWeight ".Params.toc_hide" "!=" true -}} -{{ $pages := $pages_tmp | first $sidebarMenuTruncate -}} -{{ $truncatedEntryCount := sub (len $pages_tmp) $sidebarMenuTruncate -}} -{{ if gt $truncatedEntryCount 0 -}} - {{ warnf "WARNING: %d sidebar entries have been truncated. To avoid this, increase `params.ui.sidebar_menu_truncate` to at least %d (from %d) in your config file. Section: %s" - $truncatedEntryCount (len $pages_tmp) $sidebarMenuTruncate $s.Path -}} -{{ end -}} -{{ $withChild := gt (len $pages) 0 -}} -{{ $manualLink := cond (isset $s.Params "manuallink") $s.Params.manualLink ( cond (isset $s.Params "manuallinkrelref") (relref $s $s.Params.manualLinkRelref) $s.RelPermalink) -}} -{{ $manualLinkTitle := cond (isset $s.Params "manuallinktitle") $s.Params.manualLinkTitle $s.Title -}} -
  • - {{ if (and $p.Site.Params.ui.sidebar_menu_foldable (ge $ulNr 1)) -}} - - - {{ else -}} - {{ with $s.Params.Icon}}{{ end }}{{ $s.LinkTitle }} - {{- end }} - {{- if $withChild }} - {{- $ulNr := add $ulNr 1 }} -
      - {{ range $pages -}} - {{ if (not (and (eq $s $p.Site.Home) (eq .Params.toc_root true))) -}} - {{ template "section-tree-nav-section" (dict "page" $p "section" . "shouldDelayActive" $shouldDelayActive "sidebarMenuTruncate" $sidebarMenuTruncate "ulNr" $ulNr "ulShow" $ulShow) }} + {{/* cSpell:ignore manuallink manuallinkrelref manuallinktitle */ -}} + {{ $s := .section -}} + {{ $p := .page -}} + {{ $shouldDelayActive := .shouldDelayActive -}} + {{ $sidebarMenuTruncate := .sidebarMenuTruncate -}} + {{ $treeRoot := cond (eq .ulNr 0) true false -}} + {{ $ulNr := .ulNr -}} + {{ $ulShow := .ulShow -}} + {{ $active := and (not $shouldDelayActive) (eq $s $p) -}} + {{ $activePath := and (not $shouldDelayActive) (or (eq $p $s) ($p.IsDescendant $s)) -}} + {{ $show := cond + (or + (lt $ulNr $ulShow) + $activePath + (and (not $shouldDelayActive) (eq $s.Parent $p.Parent)) + (and (not $shouldDelayActive) (eq $s.Parent $p)) + (not $p.Site.Params.ui.sidebar_menu_compact) + (and (not $shouldDelayActive) ($p.IsDescendant $s.Parent)) + ) + true false + -}} + {{ $mid := printf "m-%s" ($s.RelPermalink | anchorize) -}} + {{ $pages_tmp := where (union $s.Pages $s.Sections).ByWeight ".Params.toc_hide" "!=" true -}} + {{ $pages := $pages_tmp | first $sidebarMenuTruncate -}} + {{ $truncatedEntryCount := sub (len $pages_tmp) $sidebarMenuTruncate -}} + + {{ if gt $truncatedEntryCount 0 -}} + {{ warnf "WARNING: %d sidebar entries have been truncated. To avoid this, increase `params.ui.sidebar_menu_truncate` to at least %d (from %d) in your config file. Section: %s" + $truncatedEntryCount (len $pages_tmp) $sidebarMenuTruncate $s.Path -}} + {{ end -}} + + {{ $withChild := gt (len $pages) 0 -}} + {{ $manualLink := + cond + (isset $s.Params "manuallink") + $s.Params.manualLink + (cond + (isset $s.Params "manuallinkrelref") + (relref $s $s.Params.manualLinkRelref) + $s.RelPermalink + ) + -}} + {{ $manualLinkTitle := + cond + (isset $s.Params "manuallinktitle") + $s.Params.manualLinkTitle + $s.Title + -}} + {{ if and $treeRoot (eq $s.Params.sidebar_root_for "self") -}} + {{ with $s.Parent -}} + {{ $manualLink = .RelPermalink -}} + {{ end -}} + {{ end -}} +
    • + {{ if (and $p.Site.Params.ui.sidebar_menu_foldable (ge $ulNr 1)) -}} + + + {{ else -}} + + {{- with $s.Params.Icon -}} + + {{- end -}} + + {{- $s.LinkTitle -}} + + {{- end -}} + {{ if $withChild -}} + {{ $ulNr := add $ulNr 1 }} +
        + {{ range $pages -}} + {{ if (not (and (eq $s $p.Site.Home) (eq .Params.toc_root true))) -}} + {{ template "section-tree-nav-section" (dict "page" $p "section" . "shouldDelayActive" $shouldDelayActive "sidebarMenuTruncate" $sidebarMenuTruncate "ulNr" $ulNr "ulShow" $ulShow) }} + {{- end }} + {{- end }} +
      {{- end }} - {{- end }} -
    - {{- end }} -
  • -{{- end -}} + +{{- end }} diff --git a/layouts/_partials/spec-content.html b/layouts/_partials/spec-content.html new file mode 100644 index 00000000..23e5a807 --- /dev/null +++ b/layouts/_partials/spec-content.html @@ -0,0 +1,14 @@ +{{- /* Shared render for spec pages: title, optional description, endpoints list, body, and last-mod info. */ -}} +
    +

    {{ .Title }}

    + {{ with .Params.description }}

    {{ . | markdownify }}

    {{ end }} + + {{/* + Render an endpoints table of contents. This is the main difference + between our templates (which call the spec-content partial) and the default + Docsy template. + */}} + {{ partial "endpoints-toc.html" . }} + + {{ .Content }} +
    \ No newline at end of file diff --git a/layouts/_partials/toc.html b/layouts/_partials/toc.html index 318335f2..adfbd161 100644 --- a/layouts/_partials/toc.html +++ b/layouts/_partials/toc.html @@ -1,15 +1,29 @@ {{/* - A modified version of the toc.html partial in Docsy. + A copy of the toc.html partial in Docsy, modified to: -*/}} -{{ $page := .Params }} + * show the page's title instead of "on this page" + +*/ -}} + +{{/* + + Always render the td-toc element. ScrollSpy is counting on it to exist, + even if it's empty. + + cSpell:ignore notoc +*/ -}} + +
    {{ if not .Params.notoc -}} - {{ with .TableOfContents -}} -
    -
    - {{ $page.Title }} - {{ . }} + {{ $toc := .TableOfContents -}} + {{ if and $toc (ne $toc ``) -}} +
    + {{ .Params.Title }} +
    + {{ $toc | safeHTML }} {{ end -}} {{ end -}} +
    +{{/* */ -}} diff --git a/layouts/_shortcodes/cs-module.html b/layouts/_shortcodes/cs-module.html index 52c9a5d9..6385d914 100644 --- a/layouts/_shortcodes/cs-module.html +++ b/layouts/_shortcodes/cs-module.html @@ -3,14 +3,39 @@ This template is used to render a Client-Server API Module. Modules are defined alongside the `_index.md` for the CS API. - The `name` parameter is the file name without extension. + The following parameters are expected: + + * `filename` the name of the module file to render, without extension (i.e. `spaces`). + * `name` the display name of the module (i.e. `Spaces`). */}} {{ $name := .Params.name }} +{{ $filename := .Params.filename }} {{ with .Site.GetPage "client-server-api/modules" }} - {{ with .Resources.GetMatch (printf "%s%s" $name ".md") }} + {{ with .Resources.GetMatch (printf "%s%s" $filename ".md") }} + {{/* Preserve previous scratch values so nested modules don't leak */}} + {{ $prevPage := .Scratch.Get "endpoint_page" }} + {{ $prevModule := .Scratch.Get "endpoint_module" }} + + {{/* Allow endpoints rendered in the module to accumulate on the parent page */}} + {{ .Scratch.Set "endpoint_page" $.Page }} + {{/* Name the module for grouping in the endpoints list */}} + {{ .Scratch.Set "endpoint_module" $name }} + {{ .RenderShortcodes }} + + {{/* Restore previous scratch values */}} + {{ if $prevPage }} + {{ .Scratch.Set "endpoint_page" $prevPage }} + {{ else }} + {{ .Scratch.Delete "endpoint_page" }} + {{ end }} + {{ if $prevModule }} + {{ .Scratch.Set "endpoint_module" $prevModule }} + {{ else }} + {{ .Scratch.Delete "endpoint_module" }} + {{ end }} {{ end }} {{ end }} diff --git a/layouts/_shortcodes/http-api.html b/layouts/_shortcodes/http-api.html index b5201c49..a5268323 100644 --- a/layouts/_shortcodes/http-api.html +++ b/layouts/_shortcodes/http-api.html @@ -23,6 +23,20 @@ {{ $api := .Params.api}} {{ $anchor_base := .Params.anchor_base}} +{{/* + + Figure out which Page object to pass to the `openapi/render-api` partial. + Either our own, or one stored under `endpoint_page` in the Scratch, if one + exists. + +*/}} +{{ $target_page := .Page }} +{{ with .Page.Scratch.Get "endpoint_page" }} + {{ $target_page = . }} +{{ end }} + +{{ $module_name := .Page.Scratch.Get "endpoint_module" }} + {{ $api_data := index .Site.Data.api .Params.spec .Params.api }} {{ $base_url := (index $api_data.servers 0).variables.basePath.default }} {{ $path := delimit (slice "api" $spec $api) "/" }} @@ -30,4 +44,4 @@ {{ $api_data = partial "json-schema/resolve-refs" (dict "schema" $api_data "path" $path) }} {{ $api_data = partial "json-schema/resolve-allof" $api_data }} -{{ partial "openapi/render-api" (dict "api_data" $api_data "base_url" $base_url "anchor_base" $anchor_base) }} +{{ partial "openapi/render-api" (dict "api_data" $api_data "base_url" $base_url "anchor_base" $anchor_base "page" $target_page "module" $module_name) }} diff --git a/layouts/content.html b/layouts/content.html deleted file mode 100644 index e58073f3..00000000 --- a/layouts/content.html +++ /dev/null @@ -1,4 +0,0 @@ -
    -

    {{ .Title }}

    - {{ .Content }} -
    diff --git a/layouts/docs/baseof.html b/layouts/docs/baseof.html index b5b7a0f0..e18864dd 100644 --- a/layouts/docs/baseof.html +++ b/layouts/docs/baseof.html @@ -1,11 +1,14 @@ {{/* - A copy of the baseof.html partial in Docsy, modified - to remove the right-hand column from the layout. + A copy of the baseof.html partial in Docsy, modified to: -*/}} + * generate a static file `versions.json` that can be used to populate the + version picker. + * remove the right-hand column from the layout. -{{/* Generate a static file versions.json that can be used to populate the version picker */}} +*/ -}} + +{{/* Generate a static file versions.json that can be used to populate the version picker */ -}} {{ if .IsHome }} {{- /* Load all changelog subpages, sorted by release date */ -}} {{ $changelog := site.GetPage "changelog" }} @@ -28,20 +31,18 @@ + class="no-js" + {{- $darkMode := partialCached "dark-mode-config.html" "dark-mode-global" -}} + {{- if $darkMode.enable }} data-theme-init{{ end }}> {{ partial "head.html" . }} - {{ if .Page.Store.Get "hasMath" }} - - - {{ end }}
    {{ partial "navbar.html" . }}
    -
    +