to again minimize risk of remote servers flagging the policy server as down.
Logical servers may prefer to have dedicated software run their `/sign` API, but otherwise leave the
remaining Federation API endpoints to be served by their existing software.
Existing homeserver software, such as Synapse, may further benefit by supporting `/sign`, but deferring
the actual spam/neutral check to a module or appservice (via API not defined by this MSC). In this
setup, Synapse would take on the request authentication and signature requirements while the module
simply returns `spam: true/false`. This would support moderation bots being policy servers themselves
without needing to implement the same requirements as dedicated hosts above.
Rooms which elect to use a policy server would do so via the new `m.room.policy` state
event (empty state key). The `content` would be something like:
event (empty state key). The `content`has the following implied schema:
```json5
{
"via": "policy.example.org"
"via": "policy.example.org", // the server name of the policy server
"public_key": "unpadded_base64_signing_key" // that server's *public* signing key used for `/sign`
}
```
@ -86,27 +96,100 @@ ensure the policy server has agency to decide which rooms it actually generates
as otherwise any random (potentially malicious) community could drag the policy server into rooms and
overwhelm it.
If a policy server is in use by the room, homeservers SHOULD call the `/check` API defined below on
all locally-generated events before fanning them out, and on all remote events before delivering them
to local users. If the policy server recommends treating the event as spam, the event SHOULD be soft
failed if remote and rejected if local. This means local users should encounter an error if they
attempt to send "spam" (by the policy server's definition), and events sent by remote users will
never make it to a local user's client. If the policy server recommends allowing the event, the event
should pass unimpeded.
When creating an event locally, homeservers SHOULD call the `/sign` API defined below to acquire a
signature from the policy server, if one is configured for the room. The homeserver then appends the
signature to the event prior to delivering the event to other servers in the room.
Upon receipt of an event in a room with a policy server, the homeserver SHOULD verify that the policy
server's signature is present on the event *and* uses the key from the `m.room.policy` state event.
If the signature is missing, invalid, or for the wrong key, the homeserver SHOULD [soft fail](https://spec.matrix.org/v1.15/server-server-api/#soft-failure)
the event.
Servers MUST NOT validate that policy server signatures exist on `m.room.policy` state events with
empty state keys. This is to ensure that rooms have agency to remove/disable the policy server,
especially if the policy server they're using has become obstructive to the room's function.
**Note**: Policy servers are consulted on *all* other event types. This includes membership events,
power level changes, room name changes, room messages, reactions, redactions, etc.
For clarity, when a room doesn't use a policy server (either because the state event is unset, or
because the policy server isn't joined), events SHOULD NOT be impeded by lack of policy server signatures.
This also applies to events which are topologically ordered at a point in the DAG where a policy
server was not in effect, but were received late.
When implemented fully, users attempting to send "spammy" events according to the policy server will
not be sent to the room because the homeserver will have failed to acquire a signature. Users also
won't see events which lacked a valid signature from the policy server, for events which originate
from a homeserver that sent events without asking the policy server to sign them (or did ask and got
a refusal to sign, but sent the event anyway).
**Note**: A future MSC may make the signature required in a future room version, otherwise the event
is rejected. The centralization concerns of that architecture are best reserved for that future MSC.
The new `/sign` endpoint uses normal Federation API authentication, per above, and MAY be rate limited.
It has the following implied schema:
```
POST /_matrix/policy/v1/sign
Authorization: X-Matrix ...
Content-Type: application/json
{PDU-formatted event}
```
The request body is **required**.
If the policy server deems the event "neutral" (or "probably not spam"), the policy server returns
a signature for the event using the key implied by `public_key` in the state event and a Key ID of