This commit is contained in:
Andrew Morgan 2025-12-16 18:10:32 +00:00 committed by GitHub
commit e4df2002a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 290 additions and 79 deletions

View file

@ -257,6 +257,69 @@ Custom SCSS for the Matrix spec
}
.endpoints-toc {
summary {
cursor: pointer;
font-weight: $font-weight-bold;
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 */
.alert {
&.note {
@ -581,4 +644,4 @@ dd {
.breadcrumb {
margin: 0;
}
}
}

View file

@ -0,0 +1 @@
Add a list of endpoints to the top of each spec page.

View file

@ -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

View file

@ -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 %}}

View file

@ -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

View file

@ -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

View file

@ -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

39
data/cs_modules.yaml Normal file
View file

@ -0,0 +1,39 @@
account_data: "Client Config"
admin: "Server Administration"
content_repo: "Content repository"
device_management: "Device Management"
dm: "Direct Messaging"
end_to_end_encryption: "End-to-End Encryption"
event_annotations: "Event annotations and reactions"
event_context: "Event Context"
event_replacements: "Event replacements"
guest_access: "Guest Access"
history_visibility: "Room History Visibility"
ignore_users: "Ignoring Users"
instant_messaging: "Instant Messaging"
mentions: "User and room mentions"
moderation_policies: "Moderation policy lists"
openid: "OpenID"
presence: "Presence"
push: "Push Notifications"
read_markers: "Read and unread markers"
receipts: "Receipts"
reference_relations: "Reference relations"
report_content: "Reporting Content"
rich_replies: "Rich replies"
room_previews: "Room Previews"
room_upgrades: "Room Upgrades"
search: "Server Side Search"
secrets: "Secrets"
send_to_device: "Send-to-Device messaging"
server_acls: "Server Access Control Lists (ACLs) for rooms"
server_notices: "Server Notices"
spaces: "Spaces"
sso_login: "SSO client login/authentication"
stickers: "Sticker Messages"
tags: "Room Tagging"
third_party_invites: "Third-party invites"
third_party_networks: "Third-party Networks"
threading: "Threading"
typing_notifications: "Typing Notifications"
voip_events: "Voice over IP"

View file

@ -0,0 +1,42 @@
{{/* Minimal list of API endpoints for the current page. */}}
{{ $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 }}
<div class="endpoints-toc mb-4">
<details>
<summary>List of Endpoints</summary>
{{/* 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 }}</ul></div>{{ end }}
<div class="endpoint-module">
<div class="endpoint-module-title">{{ $mod }}</div>
<ul class="endpoint-list">
{{ $current = $mod }}
{{ end }}
{{ $key := printf "%s|%s" .method .anchor }}
<li>
<a href="#{{ .anchor }}">
<span class="http-api-method">{{ .method }}</span>
<span class="endpoint-path">{{ .endpoint }}</span>
{{ if .deprecated }}<span class="endpoint-deprecated">(deprecated)</span>{{ end }}
</a>
</li>
{{ end }}
{{ if $current }}</ul></div>{{ end }}
</details>
</div>
{{ end }}

View file

@ -15,6 +15,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 +28,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 }}

View file

@ -22,6 +22,8 @@
{{ $method := .method }}
{{ $endpoint := .endpoint }}
{{ $operation_data := .operation_data }}
{{ $page := .page }}
{{ $module := .module }}
{{ $anchor := "" }}
{{ if .anchor_base }}
@ -29,6 +31,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 }}
<section class="rendered-data">
<details {{ if not site.Params.ui.rendered_data_collapsed }}open{{ end }}>

View file

@ -0,0 +1,11 @@
{{- /* Shared render for spec pages: title, optional description, endpoints list, body, and last-mod info. */ -}}
<div class="td-content">
<h1>{{ .Title }}</h1>
{{ with .Params.description }}<p class="page-description">{{ . | markdownify }}</p>{{ end }}
{{ partial "endpoints-toc.html" . }}
{{ .Content }}
{{ partial "page-meta-lastmod.html" . }}
</div>

View file

@ -11,6 +11,34 @@
{{ with .Site.GetPage "client-server-api/modules" }}
{{ with .Resources.GetMatch (printf "%s%s" $name ".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 */}}
{{ $display := $.Get "title" }}
{{ if not $display }}
{{ $display = index $.Site.Data.cs_modules $name }}
{{ end }}
{{ if not $display }}
{{ $display = $name }}
{{ end }}
{{ .Scratch.Set "endpoint_module" $display }}
{{ .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 }}

View file

@ -23,6 +23,13 @@
{{ $api := .Params.api}}
{{ $anchor_base := .Params.anchor_base}}
{{/* Allow an outer page to collect endpoints (used for modules). */}}
{{ $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 +37,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) }}

View file

@ -1,4 +1,3 @@
<div class="td-content">
<h1>{{ .Title }}</h1>
{{ .Content }}
</div>
{{ define "main" }}
{{ partial "spec-content.html" . }}
{{ end }}

View file

@ -7,7 +7,8 @@
{{ define "main" }}
<div class="td-content">
<h1>{{ .Title }}</h1>
{{ with .Params.description }}<div class="lead">{{ . | markdownify }}</div>{{ end }}
{{ with .Params.description }}<p class="page-description">{{ . | markdownify }}</p>{{ end }}
{{ partial "endpoints-toc.html" . }}
{{ .Content }}
</div>
{{ end }}

3
layouts/docs/single.html Normal file
View file

@ -0,0 +1,3 @@
{{ define "main" }}
{{ partial "spec-content.html" . }}
{{ end }}