diff --git a/changelogs/application_service/newsfragments/1094.feature b/changelogs/application_service/newsfragments/1094.feature
new file mode 100644
index 00000000..e1b2d5cb
--- /dev/null
+++ b/changelogs/application_service/newsfragments/1094.feature
@@ -0,0 +1 @@
+Add timestamp massaging as per [MSC3316](https://github.com/matrix-org/matrix-spec-proposals/pull/3316).
\ No newline at end of file
diff --git a/changelogs/client_server/newsfragments/1003.clarification b/changelogs/client_server/newsfragments/1003.clarification
index efe68e48..9b2788cc 100644
--- a/changelogs/client_server/newsfragments/1003.clarification
+++ b/changelogs/client_server/newsfragments/1003.clarification
@@ -1 +1 @@
-Adjust the OpenAPI specification so that the type `Flow information` is explicitly defined when the CS spec is rendered.
+Adjust the OpenAPI specification so that the type `Flow information` is explicitly defined when the client-server API is rendered.
diff --git a/changelogs/client_server/newsfragments/1054.clarification b/changelogs/client_server/newsfragments/1054.clarification
new file mode 100644
index 00000000..3ccb2333
--- /dev/null
+++ b/changelogs/client_server/newsfragments/1054.clarification
@@ -0,0 +1 @@
+Fix various typos throughout the specification.
diff --git a/changelogs/client_server/newsfragments/1059.clarification b/changelogs/client_server/newsfragments/1059.clarification
new file mode 100644
index 00000000..ca5f3aea
--- /dev/null
+++ b/changelogs/client_server/newsfragments/1059.clarification
@@ -0,0 +1 @@
+Fix various typos throughout the specification.
\ No newline at end of file
diff --git a/changelogs/client_server/newsfragments/1081.clarification b/changelogs/client_server/newsfragments/1081.clarification
new file mode 100644
index 00000000..3ccb2333
--- /dev/null
+++ b/changelogs/client_server/newsfragments/1081.clarification
@@ -0,0 +1 @@
+Fix various typos throughout the specification.
diff --git a/changelogs/client_server/newsfragments/1100.clarification b/changelogs/client_server/newsfragments/1100.clarification
new file mode 100644
index 00000000..e17a2538
--- /dev/null
+++ b/changelogs/client_server/newsfragments/1100.clarification
@@ -0,0 +1 @@
+Clarify that state keys starting with `@` are in fact reserved. Regressed from [#3658](https://github.com/matrix-org/matrix-spec-proposals/pull/3658).
\ No newline at end of file
diff --git a/changelogs/client_server/newsfragments/3681.clarification b/changelogs/client_server/newsfragments/3681.clarification
index f7c29003..ca5f3aea 100644
--- a/changelogs/client_server/newsfragments/3681.clarification
+++ b/changelogs/client_server/newsfragments/3681.clarification
@@ -1 +1 @@
-Fix broken syntax in Server Access Control Lists definition.
\ No newline at end of file
+Fix various typos throughout the specification.
\ No newline at end of file
diff --git a/changelogs/room_versions/newsfragments/1037.clarification b/changelogs/room_versions/newsfragments/1037.clarification
index 9ac53c6d..e8aa3349 100644
--- a/changelogs/room_versions/newsfragments/1037.clarification
+++ b/changelogs/room_versions/newsfragments/1037.clarification
@@ -1,2 +1 @@
-Improve readability of definitions in the state resolution v2 algorithm.
-
+Improve readability and understanding of the state resolution algorithms.
\ No newline at end of file
diff --git a/changelogs/room_versions/newsfragments/1042.clarification b/changelogs/room_versions/newsfragments/1042.clarification
new file mode 100644
index 00000000..e8aa3349
--- /dev/null
+++ b/changelogs/room_versions/newsfragments/1042.clarification
@@ -0,0 +1 @@
+Improve readability and understanding of the state resolution algorithms.
\ No newline at end of file
diff --git a/changelogs/room_versions/newsfragments/1043.clarification b/changelogs/room_versions/newsfragments/1043.clarification
new file mode 100644
index 00000000..e8aa3349
--- /dev/null
+++ b/changelogs/room_versions/newsfragments/1043.clarification
@@ -0,0 +1 @@
+Improve readability and understanding of the state resolution algorithms.
\ No newline at end of file
diff --git a/changelogs/room_versions/newsfragments/1050.clarification b/changelogs/room_versions/newsfragments/1050.clarification
new file mode 100644
index 00000000..f548b987
--- /dev/null
+++ b/changelogs/room_versions/newsfragments/1050.clarification
@@ -0,0 +1 @@
+Improve readability of the authorization rules.
\ No newline at end of file
diff --git a/changelogs/room_versions/newsfragments/1093.clarification b/changelogs/room_versions/newsfragments/1093.clarification
new file mode 100644
index 00000000..06145378
--- /dev/null
+++ b/changelogs/room_versions/newsfragments/1093.clarification
@@ -0,0 +1 @@
+For room versions 8, 9, and 10: clarify which homeserver is required to sign the join event.
\ No newline at end of file
diff --git a/changelogs/room_versions/newsfragments/3737.clarification b/changelogs/room_versions/newsfragments/3737.clarification
index c3b51679..6caf519a 100644
--- a/changelogs/room_versions/newsfragments/3737.clarification
+++ b/changelogs/room_versions/newsfragments/3737.clarification
@@ -1 +1 @@
-Fix join membership auth rules when `join_rule` is `knock`.
+For room versions 7, 8, 9, and 10: fix join membership authorization rules when `join_rule` is `knock`.
diff --git a/changelogs/room_versions/newsfragments/3739.feature b/changelogs/room_versions/newsfragments/3739.feature
index c20ec3ad..ddb88446 100644
--- a/changelogs/room_versions/newsfragments/3739.feature
+++ b/changelogs/room_versions/newsfragments/3739.feature
@@ -1 +1 @@
-Update the default room version to 9.
\ No newline at end of file
+Update the default room version to 9 as per [MSC3589](https://github.com/matrix-org/matrix-spec-proposals/pull/3589).
\ No newline at end of file
diff --git a/changelogs/server_server/newsfragments/1038.clarification b/changelogs/server_server/newsfragments/1038.clarification
index 39fbeddb..ad1ca8f0 100644
--- a/changelogs/server_server/newsfragments/1038.clarification
+++ b/changelogs/server_server/newsfragments/1038.clarification
@@ -1 +1 @@
-Fix origin server name in S2S Request Authentication example.
+Clarify the format for the Authorization header.
diff --git a/changelogs/server_server/newsfragments/1045.clarification b/changelogs/server_server/newsfragments/1045.clarification
new file mode 100644
index 00000000..adb3ec16
--- /dev/null
+++ b/changelogs/server_server/newsfragments/1045.clarification
@@ -0,0 +1 @@
+Clarify what a "valid event" means when performing checks on a received PDU.
\ No newline at end of file
diff --git a/changelogs/server_server/newsfragments/1055.clarification b/changelogs/server_server/newsfragments/1055.clarification
new file mode 100644
index 00000000..f9394c6a
--- /dev/null
+++ b/changelogs/server_server/newsfragments/1055.clarification
@@ -0,0 +1 @@
+Clarify that `valid_until_ts` is in milliseconds, like other timestamps used in Matrix.
diff --git a/changelogs/server_server/newsfragments/1067.clarification b/changelogs/server_server/newsfragments/1067.clarification
new file mode 100644
index 00000000..ad1ca8f0
--- /dev/null
+++ b/changelogs/server_server/newsfragments/1067.clarification
@@ -0,0 +1 @@
+Clarify the format for the Authorization header.
diff --git a/changelogs/server_server/newsfragments/1067.feature b/changelogs/server_server/newsfragments/1067.feature
new file mode 100644
index 00000000..0b067b36
--- /dev/null
+++ b/changelogs/server_server/newsfragments/1067.feature
@@ -0,0 +1 @@
+Add a `destination` property to the Authorization header, as per [MSC3383](https://github.com/matrix-org/matrix-spec-proposals/pull/3383).
diff --git a/changelogs/server_server/newsfragments/1070.clarification b/changelogs/server_server/newsfragments/1070.clarification
new file mode 100644
index 00000000..ef4b1e6a
--- /dev/null
+++ b/changelogs/server_server/newsfragments/1070.clarification
@@ -0,0 +1 @@
+Clarify that checks on PDUs should refer to the state *before* an event.
diff --git a/changelogs/server_server/newsfragments/998.clarification b/changelogs/server_server/newsfragments/998.clarification
index c285269a..495fdade 100644
--- a/changelogs/server_server/newsfragments/998.clarification
+++ b/changelogs/server_server/newsfragments/998.clarification
@@ -1 +1 @@
-Remove `origin` field from PDUs which exists on many but not all PDUs in practice and doesn't serve an actual purpose.
+Remove largely unused `origin` field from PDUs.
diff --git a/content/application-service-api.md b/content/application-service-api.md
index 07362c51..61227660 100644
--- a/content/application-service-api.md
+++ b/content/application-service-api.md
@@ -300,13 +300,38 @@ An example request would be:
#### Timestamp massaging
-Previous drafts of the Application Service API permitted application
-services to alter the timestamp of their sent events by providing a `ts`
-query parameter when sending an event. This API has been excluded from
-the first release due to design concerns, however some servers may still
-support the feature. Please visit [issue
-\#1585](https://github.com/matrix-org/matrix-doc/issues/1585) for more
-information.
+{{% added-in v="1.3" %}}
+
+Application services can alter the timestamp associated with an event, allowing
+the application service to better represent the "real" time an event was sent
+at. While this doesn't affect the server-side ordering of the event, it can allow
+an application service to better represent when an event would have been sent/received
+at, such as in the case of bridges where the remote network might have a slight
+delay and the application service wishes to bridge the proper time onto the message.
+
+When authenticating requests as an application service, the caller can append a `ts`
+query string argument to change the `origin_server_ts` of the resulting event. Attempting
+to set the timestamp to anything other than what is accepted by `origin_server_ts` should
+be rejected by the server as a bad request.
+
+When not present, the server's behaviour is unchanged: the local system time of the server
+will be used to provide a timestamp, representing "now".
+
+The `ts` query string argument is only valid on the following endpoints:
+
+* [`PUT /rooms/{roomId}/send/{eventType}/{txnId}`](/client-server-api/#put_matrixclientv3roomsroomidsendeventtypetxnid)
+* [`PUT /rooms/{roomId}/state/{eventType}/{stateKey}`](/client-server-api/#put_matrixclientv3roomsroomidstateeventtypestatekey)
+
+Other endpoints, such as `/kick`, do not support `ts`: instead, callers can use the
+`PUT /state` endpoint to mimic the behaviour of the other APIs.
+
+{{% boxes/warning %}}
+Changing the time of an event does not change the server-side (DAG) ordering for the
+event. The event will still be appended at the tip of the DAG as though the timestamp
+was set to "now". Future MSCs, like [MSC2716](https://github.com/matrix-org/matrix-spec-proposals/pull/2716),
+are expected to provide functionality which can allow DAG order manipulation (for history
+imports and similar behaviour).
+{{% /boxes/warning %}}
#### Server admin style permissions
diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md
index 52398c9c..5eb5f8b5 100644
--- a/content/client-server-api/_index.md
+++ b/content/client-server-api/_index.md
@@ -1107,8 +1107,8 @@ as follows:
}
```
-As with [token-based]() interactive login, the `token` must encode the
-user ID. In the case that the token is not valid, the homeserver must
+The `token` must encode the user ID, since there is no other identifying
+data in the request. In the case that the token is not valid, the homeserver must
respond with `403 Forbidden` and an error code of `M_FORBIDDEN`.
If the homeserver advertises `m.login.sso` as a viable flow, and the
diff --git a/content/rooms/fragments/v1-auth-rules.md b/content/rooms/fragments/v1-auth-rules.md
index d7c4dace..e2429313 100644
--- a/content/rooms/fragments/v1-auth-rules.md
+++ b/content/rooms/fragments/v1-auth-rules.md
@@ -4,11 +4,11 @@ toc_hide: true
The types of state events that affect authorization are:
-- `m.room.create`
-- `m.room.member`
-- `m.room.join_rules`
-- `m.room.power_levels`
-- `m.room.third_party_invite`
+- [`m.room.create`](/client-server-api#mroomcreate)
+- [`m.room.member`](/client-server-api#mroommember)
+- [`m.room.join_rules`](/client-server-api#mroom)
+- [`m.room.power_levels`](/client-server-api#mroompower_levels)
+- [`m.room.third_party_invite`](/client-server-api#mroomthird_party_invite)
{{% boxes/note %}}
Power levels are inferred from defaults when not explicitly supplied.
diff --git a/content/rooms/fragments/v2-state-res.md b/content/rooms/fragments/v2-state-res.md
index b238e1d8..e666d7f8 100644
--- a/content/rooms/fragments/v2-state-res.md
+++ b/content/rooms/fragments/v2-state-res.md
@@ -2,20 +2,19 @@
toc_hide: true
---
-The room state *S*′(*E*) after an event *E* is defined in terms of the
-room state *S*(*E*) before *E*, and depends on whether *E* is a state
+The room state *S′(E)* after an event *E* is defined in terms of the
+room state *S(E)* before *E*, and depends on whether *E* is a state
event or a message event:
-- If *E* is a message event, then *S*′(*E*) = *S*(*E*).
-- If *E* is a state event, then *S*′(*E*) is *S*(*E*), except that its
- entry corresponding to *E*'s `event_type` and `state_key` is
- replaced by *E*'s `event_id`.
+- If *E* is a message event, then *S′(E)* = *S(E)*.
+- If *E* is a state event, then *S′(E)* is *S(E)*, except that its
+ entry corresponding to the `event_type` and `state_key` of *E* is
+ replaced by the `event_id` of *E*.
-The room state *S*(*E*) before *E* is the *resolution* of the set of
-states {*S*′(*E*1), *S*′(*E*2), …} consisting of
-the states after each of *E*'s `prev_event`s
-{*E*1, *E*2, …}, where the resolution of a set of
-states is given in the algorithm below.
+The room state *S(E)* before *E* is the *resolution* of the set of
+states {*S′(E*1*)*, *S′(E*2*)*, …}
+after the `prev_event`s {*E*1, *E*2, …} of *E*.
+The resolution of a set of states is given in the algorithm below.
#### Definitions
@@ -31,11 +30,22 @@ the `membership` is `leave` or `ban` and the `sender` does not match the
might remove someone's ability to do something in the room.
**Unconflicted state map and conflicted state set.**
-The *unconflicted state map* is the state where the value of each key
-exists and is the same in each state *S**i*. The *conflicted
-state set* is the set of all other state events. Note that the
-unconflicted state map only has one event per `(event_type, state_key)`,
-whereas the conflicted state set may have multiple events.
+The keys of the state maps *Si* are 2-tuples of strings of the form
+*K* = `(event_type, state_key)`. The values *V* are state events.
+The key-value pairs (*K*, *V*) across all state maps *Si* can be
+divided into two collections.
+If a given key *K* is present in every *Si* with the same value *V*
+in each state map, then the pair (*K*, *V*) belongs to the *unconflicted state map*.
+Otherwise (*K*, *V*) belongs to the *conflicted state set*.
+
+Note that the unconflicted state map only has one event for each key *K*,
+whereas the conflicted state set may associate multiple events to the same key.
+
+**Auth chain.**
+The *auth chain* of an event *E* is the set containing all of *E*'s auth events,
+all of *their* auth events, and so on recursively, stretching back to the
+start of the room. Put differently, these are the events reachable by walking
+the graph induced by an event's `auth_events` links.
**Auth difference.**
The *auth difference* is calculated by first calculating the full auth
@@ -112,9 +122,9 @@ the auth event is not rejected.
The *resolution* of a set of states is obtained as follows:
-1. Take all *power events* and any events in their auth chains,
- recursively, that appear in the *full conflicted set* and order them
- by the *reverse topological power ordering*.
+1. Select all *power events* that appear in the *full conflicted set*. Compute
+ the union of their auth chains, including the power events themselves.
+ Sort the union using the *reverse topological power ordering*.
2. Apply the *iterative auth checks algorithm*, starting from the
*unconflicted state map*, to the list of events from the previous
step to get a partially resolved state.
diff --git a/content/rooms/fragments/v3-auth-rules.md b/content/rooms/fragments/v3-auth-rules.md
index 1a6ae490..8e902602 100644
--- a/content/rooms/fragments/v3-auth-rules.md
+++ b/content/rooms/fragments/v3-auth-rules.md
@@ -11,11 +11,11 @@ however.
The types of state events that affect authorization are:
-- `m.room.create`
-- `m.room.member`
-- `m.room.join_rules`
-- `m.room.power_levels`
-- `m.room.third_party_invite`
+- [`m.room.create`](/client-server-api#mroomcreate)
+- [`m.room.member`](/client-server-api#mroommember)
+- [`m.room.join_rules`](/client-server-api#mroom)
+- [`m.room.power_levels`](/client-server-api#mroompower_levels)
+- [`m.room.third_party_invite`](/client-server-api#mroomthird_party_invite)
{{% boxes/note %}}
Power levels are inferred from defaults when not explicitly supplied.
diff --git a/content/rooms/fragments/v8-auth-rules.md b/content/rooms/fragments/v8-auth-rules.md
index 4b14762d..6a548787 100644
--- a/content/rooms/fragments/v8-auth-rules.md
+++ b/content/rooms/fragments/v8-auth-rules.md
@@ -12,11 +12,11 @@ of receipt, they are authorized at a later stage: see the
The types of state events that affect authorization are:
-- `m.room.create`
-- `m.room.member`
-- `m.room.join_rules`
-- `m.room.power_levels`
-- `m.room.third_party_invite`
+- [`m.room.create`](/client-server-api#mroomcreate)
+- [`m.room.member`](/client-server-api#mroommember)
+- [`m.room.join_rules`](/client-server-api#mroom)
+- [`m.room.power_levels`](/client-server-api#mroompower_levels)
+- [`m.room.third_party_invite`](/client-server-api#mroomthird_party_invite)
{{% boxes/note %}}
Power levels are inferred from defaults when not explicitly supplied.
@@ -46,7 +46,7 @@ The rules are as follows:
1. If no `state_key` key or `membership` key in `content`, reject.
2. If `content` has a `join_authorised_via_users_server`
key:
- 1. If the event is not validly signed by the user ID denoted
+ 1. If the event is not validly signed by the homeserver of the user ID denoted
by the key, reject.
3. If `membership` is `join`:
1. If the only previous event is an `m.room.create` and the
diff --git a/content/rooms/v1.md b/content/rooms/v1.md
index 1519873b..a69e3d5d 100644
--- a/content/rooms/v1.md
+++ b/content/rooms/v1.md
@@ -66,18 +66,18 @@ This is fixed in the state resolution algorithm introduced in room
version 2.
{{% /boxes/warning %}}
-The room state *S*′(*E*) after an event *E* is defined in terms of the
+The room state *S′*(*E*) after an event *E* is defined in terms of the
room state *S*(*E*) before *E*, and depends on whether *E* is a state
event or a message event:
-- If *E* is a message event, then *S*′(*E*) = *S*(*E*).
-- If *E* is a state event, then *S*′(*E*) is *S*(*E*), except that its
- entry corresponding to *E*'s `event_type` and `state_key` is
- replaced by *E*'s `event_id`.
+- If *E* is a message event, then *S′(E)* = *S(E)*.
+- If *E* is a state event, then *S′(E)* is *S(E)*, except that its
+ entry corresponding to the `event_type` and `state_key` of *E* is
+ replaced by the `event_id` of *E*.
-The room state *S*(*E*) before *E* is the *resolution* of the set of
-states {*S*′(*E*′), *S*′(*E*″), …} consisting of the states after each
-of *E*'s `prev_event`s {*E*′, *E*″, …}.
+The room state *S(E)* before *E* is the *resolution* of the set of
+states {*S′(E′)*, *S′(E″)*, …} after the `prev_events` {*E′*, *E″*, …}.
+of *E*.
The *resolution* of a set of states is defined as follows. The resolved
state is built up in a number of passes; here we use *R* to refer to the
diff --git a/content/rooms/v6.md b/content/rooms/v6.md
index 67131371..cb87082c 100644
--- a/content/rooms/v6.md
+++ b/content/rooms/v6.md
@@ -59,11 +59,11 @@ Events must be signed by the server denoted by the `sender` key.
The types of state events that affect authorization are:
-- `m.room.create`
-- `m.room.member`
-- `m.room.join_rules`
-- `m.room.power_levels`
-- `m.room.third_party_invite`
+- [`m.room.create`](/client-server-api#mroomcreate)
+- [`m.room.member`](/client-server-api#mroommember)
+- [`m.room.join_rules`](/client-server-api#mroom)
+- [`m.room.power_levels`](/client-server-api#mroompower_levels)
+- [`m.room.third_party_invite`](/client-server-api#mroomthird_party_invite)
{{% boxes/note %}}
Power levels are inferred from defaults when not explicitly supplied.
diff --git a/content/rooms/v7.md b/content/rooms/v7.md
index 07e09238..2ada06f7 100644
--- a/content/rooms/v7.md
+++ b/content/rooms/v7.md
@@ -45,11 +45,11 @@ of receipt, they are authorized at a later stage: see the
The types of state events that affect authorization are:
-- `m.room.create`
-- `m.room.member`
-- `m.room.join_rules`
-- `m.room.power_levels`
-- `m.room.third_party_invite`
+- [`m.room.create`](/client-server-api#mroomcreate)
+- [`m.room.member`](/client-server-api#mroommember)
+- [`m.room.join_rules`](/client-server-api#mroom)
+- [`m.room.power_levels`](/client-server-api#mroompower_levels)
+- [`m.room.third_party_invite`](/client-server-api#mroomthird_party_invite)
{{% boxes/note %}}
Power levels are inferred from defaults when not explicitly supplied.
diff --git a/content/server-server-api.md b/content/server-server-api.md
index 349649bd..f70e8994 100644
--- a/content/server-server-api.md
+++ b/content/server-server-api.md
@@ -255,7 +255,7 @@ condition applies throughout the request signing process.
Step 2 add Authorization header:
GET /target HTTP/1.1
- Authorization: X-Matrix origin=origin.hs.example.com,key="ed25519:key1",sig="ABCDEF..."
+ Authorization: X-Matrix origin="origin.hs.example.com",destination="destination.hs.example.com",key="ed25519:key1",sig="ABCDEF..."
Content-Type: application/json
@@ -283,14 +283,52 @@ def authorization_headers(origin_name, origin_signing_key,
for key, sig in signed_json["signatures"][origin_name].items():
authorization_headers.append(bytes(
- "X-Matrix origin=%s,key=\"%s\",sig=\"%s\"" % (
- origin_name, key, sig,
+ "X-Matrix origin=\"%s\",destination=\"%s\",key=\"%s\",sig=\"%s\"" % (
+ origin_name, destination_name, key, sig,
)
))
- return ("Authorization", authorization_headers)
+ return ("Authorization", authorization_headers[0])
```
+The format of the Authorization header is given in
+[RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-2.1). In
+summary, the header begins with authorization scheme `X-Matrix`, followed by
+one or more spaces, followed by a comma-separated list of parameters written as
+name=value pairs. The names are case insensitive and order does not matter. The
+values must be enclosed in quotes if they contain characters that are not
+allowed in `token`s, as defined in
+[RFC 7230](https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.6); if a
+value is a valid `token`, it may or may not be enclosed in quotes. Quoted
+values may include backslash-escaped characters. When parsing the header, the
+recipient must unescape the characters. That is, a backslash-character pair is
+replaced by the character that follows the backslash.
+
+For compatibility with older servers, the sender should
+- only include one space after `X-Matrix`,
+- only use lower-case names, and
+- avoid using backslashes in parameter values.
+
+For compatibility with older servers, the recipient should allow colons to be
+included in values without requiring the value to be enclosed in quotes.
+
+The authorization parameters to include are:
+
+- `origin`: the server name of the sending server. This is the same as the
+ `origin` field from JSON described in step 1.
+- `destination`: {{< added-in v="1.3" >}} the server name of the receiving
+ sender. This is the same as the `destination` field from the JSON described
+ in step 1. For compatibility with older servers, recipients should accept
+ requests without this parameter, but MUST always send it. If this property
+ is included, but the value does not match the receiving server's name, the
+ receiving server must deny the request with an HTTP status code 401
+ Unauthorized.
+- `key`: the ID, including the algorithm name, of the sending server's key used
+ to sign the request.
+- `signature`: the signature of the JSON as calculated in step 1.
+
+Unknown parameters are ignored.
+
### Response Authentication
Responses are authenticated by the TLS server certificate. A homeserver
@@ -356,13 +394,15 @@ specification](/rooms).
Whenever a server receives an event from a remote server, the receiving
server must ensure that the event:
-1. Is a valid event, otherwise it is dropped.
+1. Is a valid event, otherwise it is dropped. For an event to be valid, it
+ must contain a `room_id`, and it must comply with the event format of
+ that [room version](/rooms).
2. Passes signature checks, otherwise it is dropped.
3. Passes hash checks, otherwise it is redacted before being processed
further.
4. Passes authorization rules based on the event's auth events,
otherwise it is rejected.
-5. Passes authorization rules based on the state at the event,
+5. Passes authorization rules based on the state before the event,
otherwise it is rejected.
6. Passes authorization rules based on the current state of the room,
otherwise it is "soft failed".
diff --git a/data/api/client-server/definitions/client_event_without_room_id.yaml b/data/api/client-server/definitions/client_event_without_room_id.yaml
index 1b6d6073..c4db8b0e 100644
--- a/data/api/client-server/definitions/client_event_without_room_id.yaml
+++ b/data/api/client-server/definitions/client_event_without_room_id.yaml
@@ -38,6 +38,10 @@ properties:
Present if, and only if, this event is a *state* event. The key making
this piece of state unique in the room. Note that it is often an empty
string.
+
+ State keys starting with an `@` are reserved for referencing user IDs, such
+ as room members. With the exception of a few events, state events set with a
+ given user's ID as the state key MUST only be set by that user.
type: string
example: '@user:example.org'
sender:
diff --git a/data/api/client-server/room_state.yaml b/data/api/client-server/room_state.yaml
index 89792e63..d43bc802 100644
--- a/data/api/client-server/room_state.yaml
+++ b/data/api/client-server/room_state.yaml
@@ -114,7 +114,7 @@ paths:
Some example error codes include:
- * `M_INVALID_PARAMETER`: One or more aliases within the `m.room.canonical_alias`
+ * `M_INVALID_PARAM`: One or more aliases within the `m.room.canonical_alias`
event have invalid syntax.
* `M_BAD_ALIAS`: One or more aliases within the `m.room.canonical_alias` event
diff --git a/data/api/server-server/definitions/keys.yaml b/data/api/server-server/definitions/keys.yaml
index 135e81ac..97ac1667 100644
--- a/data/api/server-server/definitions/keys.yaml
+++ b/data/api/server-server/definitions/keys.yaml
@@ -88,9 +88,10 @@ properties:
type: integer
format: int64
description: |-
- POSIX timestamp when the list of valid keys should be refreshed. This field MUST
- be ignored in room versions 1, 2, 3, and 4. Keys used beyond this timestamp MUST
- be considered invalid, depending on the [room version specification](/rooms).
+ POSIX timestamp in milliseconds when the list of valid keys should be refreshed.
+ This field MUST be ignored in room versions 1, 2, 3, and 4. Keys used beyond this
+ timestamp MUST be considered invalid, depending on the
+ [room version specification](/rooms).
Servers MUST use the lesser of this field and 7 days into the future when
determining if a key is valid. This is to avoid a situation where an attacker
diff --git a/data/event-schemas/examples/m.call.answer.yaml b/data/event-schemas/examples/m.call.answer.yaml
index a4cfc1e1..aaa4da71 100644
--- a/data/event-schemas/examples/m.call.answer.yaml
+++ b/data/event-schemas/examples/m.call.answer.yaml
@@ -4,7 +4,6 @@
"content": {
"version" : 0,
"call_id": "12345",
- "lifetime": 60000,
"answer": {
"type" : "answer",
"sdp" : "v=0\r\no=- 6584580628695956864 2 IN IP4 127.0.0.1[...]"
diff --git a/layouts/shortcodes/added-in.html b/layouts/shortcodes/added-in.html
index 4113d922..149be685 100644
--- a/layouts/shortcodes/added-in.html
+++ b/layouts/shortcodes/added-in.html
@@ -2,7 +2,7 @@
{{ $this := .Params.this }}
{{ if $this }}
- **[New in this version]**
+ [New in this version]
{{ else }}
- **[Added in `v{{ $ver }}`]**
-{{ end }} {{/* Do not leave an empty line at the end of this file otherwise the inline behaviour breaks. */}}
\ No newline at end of file
+ [Added in v{{ $ver }}
]
+{{ end }} {{/* Do not leave an empty line at the end of this file otherwise the inline behaviour breaks. */}}
diff --git a/layouts/shortcodes/changed-in.html b/layouts/shortcodes/changed-in.html
index 0eb35faa..8da2559a 100644
--- a/layouts/shortcodes/changed-in.html
+++ b/layouts/shortcodes/changed-in.html
@@ -2,7 +2,7 @@
{{ $this := .Params.this }}
{{ if $this }}
- **[Changed in this version]**
+ [Changed in this version]
{{ else }}
- **[Changed in `v{{ $ver }}`]**
-{{ end }} {{/* Do not leave an empty line at the end of this file otherwise the inline behaviour breaks. */}}
\ No newline at end of file
+ [Changed in v{{ $ver }}
]
+{{ end }} {{/* Do not leave an empty line at the end of this file otherwise the inline behaviour breaks. */}}