diff --git a/proposals/3395-synthetic-appservice-events.md b/proposals/3395-synthetic-appservice-events.md new file mode 100644 index 000000000..595e0022b --- /dev/null +++ b/proposals/3395-synthetic-appservice-events.md @@ -0,0 +1,162 @@ +# MSC3395: Synthetic Appservice Events + +Most services today have the concept of a webhook, which is used to inform an external service about +the state of another service. For instance when a new user is registered on a platform, it is useful +to alert a bot to send a welcome message. + +In Matrix we already have the concept of services which complement the homeserver, known as Application +Services. However, they can only be informed of user actions that have taken place in rooms (with +the notable exception of presence / device updates via EDUs). This proposal aims to extend the existing +AS spec to include "synthetic" events where the homeserver can inform the appservice when a variety of +things have happened on the homeserver. + +For clarity, this MSC introduces a modest set events that could be extended by further MSCs: + +- User registration +- User login +- User logout +- User deactivation + +## Proposal + +An appservice must subscribe to the changes that it wishes to listen for. This can be done by setting a new +key in the appservice registration file: `m.synthetic_events`, under the `namespaces` key: + +```yaml +namespaces: + users: + - exclusive: false # This needs to be false to allow for registrations + regex: "@.*:mydomain" + m.events: false # Allow or disallow normal events to be sent from this namespace. + m.synthetic_events: + events: + - "m.user.registration" + - "m.user.login" + - "m.user.logout" + - "m.user.deactivated" +``` + +Currently only the `namespaces.users` field can contain this key, though the door is left open for +future MSCs to expand upon this feature and allow synthetic events for different contexts. + +Then, when the homeserver wishes to inform a appservice of an event it would send the event over the +appservice `/transaction` API. If the application service is down, these events SHOULD be retried when +the appservice comes back up. + +As the synthetic events are namespaced, the AS should only be sent events for users in that namespace. + +Because a namespace is listed for these users, the AS will also recieve room events for these users by default. To opt-out +of sending room events to the AS (and allow only synthetic events to be sent), the key `m.events` can be set to `false`. + +``` +PUT /_matrix/app/v1/transactions/{txnId} +``` + +```json5 +{ + "m.synthetic_events": [{ + "type": "m.user.deactivated", + "content": { + "user_id": "@alice:example.com" + }, + "ts": 1432735824653, + }], + "events": [/* ... */] +} +``` + +For each of the event types given above, there is an expected schema. As with all Matrix +event contents, this can be extended to include implementation specific metadata. + +### `m.user.registration` + +This should be sent when a new user registers on the homeserver. + +```json5 +{ + "type": "m.user.registration", + "content": { + "user_id": "@alice:example.com" + } +} +``` + +### `m.user.login` + +This should be sent when an existing user logs in on the homeserver. + +```json5 +{ + "type": "m.user.login", + "content": { + "user_id": "@alice:example.com", + "device_id": "ABCDEF" + } +} +``` + +### `m.user.logout` + +This should be sent when an existing user logs out of their session. + +```json5 +{ + "type": "m.user.logout", + "content": { + "user_id": "@alice:example.com", + "soft_logout": true, + "device_id": "ABCDEF" + } +} +``` + +### `m.user.deactivated` + +This should be sent when an existing user deactivates their account. + +```json5 +{ + "type": "m.user.logout", + "content": { + "user_id": "@alice:example.com" + } +} +``` + +## Potential issues + +Appservices can now request permissions to reveal quite intimate details about each user, which means that homeserver +administrators will need to be more careful when adding new appservice registrations. However, it has always been the +case that appservices should be considered powerful tools that need review before being connected. The ability to +namespace the events sent allows for fine-grained control. + +This proposal would not work over a federated context, as federated homeservers are not aware of foregin appservices. +That being said the events suggested in this proposal are sensitive and are expected to only be shared with immediate +appservices connected to the homeserver. It would be possible for an appservice to "proxy" these events to a seperate room +if federation of the information is desired, though. + +## Alternatives + +One alternative would be to have homeserver implementations make an "events" room, which sends these events +as normal room events rather than synthetic events. Appservices would be joined and left to this room and would +recieve events organically. However there are some problems with this approach: + +- It increases the burden on the homeserver implementor to manage these rooms, including membership of + each appservice. +- It would require each of these events to be stored in the homeserver database, which would increase storage + costs over time and would require homeservers to store lots of activity in the database. +- While varying by implementation, it would be slower to store an event in a room and send it to an AS, than + just to send it. +- Each event type would need it's own room to allow fine grained control over which events the appservice would + recieve, at least until a form of per-message ACLs lands in the spec. + +For these reasons, the suggested proposal was chosen. + +## Security considerations + +These events will be sent down the same channel as other AS events, and so the security footprint +is not impacted. + +## Unstable prefix + +All keys mentioned in this document beginning with `m.` will use `uk.half-shot.msc3395.` as the prefix.