7.8 KiB
MSC4046: Make & send PDU endpoints
Though extremely uncommon, there are cases where a client wants to send a fully-formed
PDU to a room instead of just the fields exposed by /send
.
This proposal introduces both Client-Server API endpoints and Server-Server API endpoints for creating and sending PDUs into rooms.
Proposal
Two new Client-Server API endpoints are introduced:
GET /_matrix/client/v1/room/:roomId/make_pdu/:eventType
PUT /_matrix/client/v1/room/:roomId/send_pdu/:txnId
These endpoints are inspired by the federation join sequence. Both require authentication and can be rate limited. Both endpoints also accept
any number of server_name
query parameters for federation routing, similar to
POST /join/:idOrAlias
.
GET /make_pdu
returns a PDU (minus some fields) the client can populate and the room version
of the room. After the client has added useful content
and other fields, it populates hashes
and signatures
(if relevant/possible) before sending the event with PUT /send_pdu
.
GET /make_pdu
's 200 response looks as follows:
{
"room_version": "11",
"pdu": {
// event goes here
}
}
Servers MUST pre-populate the following fields of the pdu
:
sender
as the authenticated user ID.- If
:eventType
is a known state event type,state_key
must be present.- For
m.room.member
events,state_key
is the authenticated user ID. - For all other event types, an empty string is used.
- For
- All other fields required by a PDU in the room's version, except for
content
,hashes
, andsignatures
.
GET /make_pdu
returns the following error codes as applicable:
403 M_FORBIDDEN
- The user won't be able to send an event in the room at all. Note that this make-and-send sequence can be used by users to join public rooms if they wish.404 M_NOT_FOUND
- The room is unknown to the server, and can't be located over federation (see later in this proposal).400 M_INCOMPATIBLE_ROOM_VERSION
- The server doesn't support the room version. The room's version is populated asroom_version
on the returned error.
PUT /send_pdu
takes a request body of the PDU to be sent. The
:txnId
can be
anything, though callers are encouraged to use the event ID as it's always consistent. The server
appends signatures
which are missing and validates
the resulting event.
PUT /send_pdu
's 200 response is an empty JSON object. No event ID is returned because in room versions
1 and 2 the event ID is part of the content hash, which the server validates upon receipt. For all other
room versions (as of writing), the event ID is a calculated reference hash where calculating the wrong
reference hash would manifest as a content hash issue as well. Therefore, since the client is always
aware of the event ID it is sending, it is not returned.
PUT /send_pdu
returns the following error codes as applicable:
403 M_FORBIDDEN
- The PDU was rejected.400 M_BAD_STATE
- The PDU was soft-failed, or the event ID is already in use (applies to room versions 1 and 2).- Blocking on soft failure is to prevent clients from sending events which reference ancient parts of the DAG, for example.
404 M_NOT_FOUND
- The room is unknown to the server, and can't be located over federation (see later in this proposal).400 M_INCOMPATIBLE_ROOM_VERSION
- The server doesn't support the room version. The room's version is populated asroom_version
on the returned error.
For both endpoints, if the server is not aware of the room then it can use the caller-supplied server_name
query parameters to make federation requests instead. Two new Server-Server API endpoints are introduced
to mirror the Client-Server API ones:
GET /_matrix/federation/v1/make_pdu/:roomId
PUT /_matrix/federation/v1/send_pdu/:roomId
Like the Client-Server API endpoints, both are inspired by GET /make_join
and PUT /send_join
. Both
require authentication, and both can be rate limited.
GET /make_pdu/:roomId
has the same request and response shape as the Client-Server API with the notable
difference that instead of server_name
query parameters the sender SHOULD supply ver
parameters. ver
is exactly as defined by GET /make_join
.
PUT /send_pdu/:roomId
also shares its request and response shape with the Client-Server API, notably
missing server_name
query parameters. ver
is not required on this endpoint, so is not included.
In both endpoints, the server SHOULD proxy the error through to the client. Servers might also prefer to
call each server_name
in parallel for GET /make_pdu
and use the first to respond (and use the first
200 OK as a successful response).
Both endpoints are additionally affected by Server ACLs.
Potential issues
The client APIs described by this MSC are likely to be used very often. Future MSCs might make better use of them.
The federation APIs described by this MSC are slightly scary: they allow servers to potentially send through
them instead of using the normal PUT /send
API. Servers SHOULD reject PUT /_matrix/federation/v1/send_pdu/:roomId
requests with 400 M_UNAUTHORIZED
when the calling server (or sender
) is able to send the event themselves. For example, them being joined
to the room.
This MSC does not deprecate the existing federation /make_*
and /send_*
APIs. This might be considered a
bug in the proposal, however.
Alternatives
Give clients context for the auth chain
If a client was given enough information for useful prev_events
and auth_events
, it could likely skip
the "make" step and jump to "send". prev_events
is easy because the client can just use the end of its known
timeline, but auth_events
is harder: clients don't traditionally become aware of state resets and similar,
and so can become desynced from reality. If "current state" was highly reliable for the client then it could
calculate auth_events
trivially - the server already fully resolves and linearizes the DAG for the client.
Assuming infrequent use of this MSC's APIs, a workaround might be for a client to call
GET /state
, cache the
response for a short while, generate its events, and send them. The client should be sure to mutate its cache
with any events it generates to keep it as up to date as possible. The client can also refresh the cache from
time to time.
Security considerations
See "Potential issues" section.
TODO: Other security details.
Unstable prefix
While this proposal is not considered stable, the org.matrix.msc4046
unstable prefix should be used on
all new endpoints.
Stable | Unstable |
---|---|
GET /_matrix/client/v1/room/:roomId/make_pdu/:eventType |
GET /_matrix/client/unstable/org.matrix.msc4046/room/:roomId/make_pdu/:eventType |
PUT /_matrix/client/v1/room/:roomId/send_pdu/:txnId |
PUT /_matrix/client/unstable/org.matrix.msc4046/room/:roomId/send_pdu/:txnId |
GET /_matrix/federation/v1/make_pdu/:roomId |
GET /_matrix/federation/unstable/org.matrix.msc4046/make_pdu/:roomId |
PUT /_matrix/federation/v1/send_pdu/:roomId |
PUT /_matrix/federation/unstable/org.matrix.msc4046/send_pdu/:roomId |