-
Notifications
You must be signed in to change notification settings - Fork 401
MSC4140: Delayed events #4140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
toger5
wants to merge
92
commits into
main
Choose a base branch
from
toger5/expiring-events-keep-alive
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+841
−0
Open
MSC4140: Delayed events #4140
Changes from 4 commits
Commits
Show all changes
92 commits
Select commit
Hold shift + click to select a range
480b00a
draft for expiring event PR
toger5 8839b8d
Add msc number
toger5 8bf6db7
add security consideration and alternatives
toger5 8ec6374
alternative name and alternative content
toger5 9f45cfa
review andrewF
toger5 54fff99
draft of iteration two (after meeting with the backend team)
toger5 abdfe1c
timeout_refresh_token is not a well description since the same token …
toger5 53f6186
rename msc, rephrase introduction
toger5 087c74e
Add usecase specific section.
toger5 538b853
add GET futures endpoint
toger5 f7a1aad
shorten introduction
toger5 f5f4b38
add alternative section to not include the `m.send_now` field
toger5 c16afbc
Update proposals/4140-delayed-events-futures.md
toger5 c52c80d
batch sending considerations
toger5 bf22260
Update proposals/4140-delayed-events-futures.md
toger5 7f0d80f
Update proposals/4140-delayed-events-futures.md
toger5 7b192ac
Update proposals/4140-delayed-events-futures.md
toger5 f3bf66d
review
toger5 2d7b27d
add background to usecase specific considerations
toger5 1140ce9
Simplify main proposal for widget api usage
toger5 0a7896e
make `future_group_id` server generated and small adjustments
toger5 8fa33d6
review
toger5 49d5294
user scoping details
toger5 7550d9b
Update proposals/4140-delayed-events-futures.md
toger5 a663bb4
add rate limiting section
toger5 99b3a20
rename `/futures` to `/future`
toger5 eb50a19
Update everything to v1
toger5 9ff051e
Update proposals/4140-delayed-events-futures.md
toger5 425b9bf
review
toger5 2e7be46
Swap the alternative of reusing the send and state request with the m…
toger5 5653fe1
add reference to MSC4143 (MatrixRTC)
toger5 af060cf
Meeting feedback:
toger5 bff704c
remove parent concept.
toger5 fa461e2
Refactor + unstable prefixes
hughns d195218
Update to GET /futures
hughns b5ac9b2
Standardise endpoint for interacting with futures
hughns c07dd9b
Make it clear that events can be cancelled
hughns b79e4e2
Make wording more authoritative
hughns e125901
Remove erroneous old example
hughns 0443cd9
Take view that clients don't act on behalf of a user
hughns 7df0919
Use name delay_id and delayed_events
hughns ff95144
Clean up more references to future
hughns 93c932a
event_type => type
hughns 6cce3bd
Tidying
hughns ac2d2c5
Pagination on GET endpoint
hughns 84e20fd
Add alternative of M_INVALID_PARAM
hughns ac3bd9d
change order of manage <-> get sections
toger5 de77a90
Obey lint rules and more renames
toger5 677d6f3
TOC update
hughns 4caecd1
Additional notes on security considerations
hughns c482d58
Add rate limiting requirements
hughns 9098fea
Describe MatrixRTC use case in terms of heartbeats
hughns 7e06e85
"leave" => "hangup" for consistency
hughns a1b8121
Wording clarification
hughns 3a3a5b5
Additional reference to heartbeat
hughns 97d4141
TOC update (use monospace and dont list msc title
toger5 99c9467
be consistent with "restart" wording (we used reset, refresh and rest…
toger5 6f2aa5e
Add compatibility with Cryptographic Identities to potenail issues
hughns 5e43db0
Add placeholder for MSC3277
hughns 84b8dc0
Add note about MSC2716 batch sending
hughns e7d0986
Add alternative of not providing a send action
hughns 850bf9e
Add alternative of using DELETE HTTP method
hughns e1b460a
Add clarification about regular/non-state events not getting cancelled
hughns 114da1e
Clarify contents of content field on GET response
hughns 772590f
Expose transaction ID in GET response
hughns 4a2ca48
Add context on MSC3277 alternative
hughns 37979cd
Add more context to MQTT style alternative
hughns 195ab6a
Add alternative of typing notifications
hughns 0f8a2d1
Update TOC
hughns 886f378
Fix TOC
hughns 8523ed4
Note on alternative names for `running_since`
hughns 883e6b5
Revert "Expose transaction ID in GET response"
AndrewFerr caece4d
Scope GET to only the requesting user's events
AndrewFerr 28970ec
remove all references to future (except where we actually talk about …
toger5 2f57b0b
add terminated events section to GET endpoint
toger5 9d5c93a
use case specific considerations details
toger5 da3d75e
remove batch sending endpoint since that does not make sense in the s…
toger5 f7e4e9b
Clean up iteration with two significant changes:
toger5 b8e317f
terminated -> finalised
toger5 b499995
andrews changes
toger5 8dc05a4
requried -> required
AndrewFerr 0a777f4
Change example of "canceled" outcome to "cancel"
AndrewFerr a09a883
Minor formatting changes
AndrewFerr 72a808e
Allow servers to discard returned finalised events
AndrewFerr d1a37f0
Define finalised events for /sync & /transactions
AndrewFerr 3358138
use current MatrixRTC MSC types.
toger5 904e3d6
review trivial changes
toger5 c25e5a3
Add rate limit section to `GET` `finalized` and `scheduled` endpoint
toger5 96f9063
clarify why there is no rate limiting for the delayed event managemen…
toger5 99b79ba
remove `on push` delayed event finilization section
toger5 dc5fd93
formatting/cleanup
toger5 bf5df9b
fix synapse and MSC inconsistency
toger5 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
170 changes: 170 additions & 0 deletions
170
proposals/4140-expiring-events-with-keep-alive-endpoint.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
# MSC4140: Expiring events with keep alive endpoint | ||
|
||
Currently there is no mechanism for a client to provide a reliable way of | ||
communicating that an event is still valid. The best expiration method is to post | ||
another event that is stores that it is expired. | ||
In some situations the client just looses connection or fails to sent the expired | ||
version of the event. | ||
A generic way is desired in which the event gets marked as expired by the homeserver. | ||
|
||
Clients can then perform custom logic based on if the event is in valid or | ||
expired state. | ||
|
||
This is particularly interesting in the context of matrixRTC where we want | ||
to ignore expired state events of users who left the call without sending a new | ||
state empty `m.call.member` event. | ||
|
||
We would like the homeserver to mark this event as expired in a reasonable | ||
time window after a user disconnected. | ||
|
||
## Proposal | ||
|
||
Events can contain a `m.will_expire: "running" | "expired" | "ended"` field. | ||
This is an enum marking the event as | ||
expired `m.will_expire: "expired" | "ended"` or still alive `m.will_expire: "running"`. | ||
This field lives outside the ciphertext content (hence it also works for encrypted | ||
events) and is set via the usual `PUT` request if the content contains the additional | ||
`m.will_expire: 10` field (similar how it is done with relations), with the desired | ||
timeout duration in seconds. | ||
|
||
Request | ||
|
||
```json | ||
{ | ||
"m.will_expire": 10, | ||
"body": "hello" | ||
} | ||
``` | ||
|
||
If the homeserver detects a `m.expired` field it will store and distribute the | ||
toger5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
event as hiding the timeout duration: | ||
|
||
```json | ||
{ | ||
"content":{ | ||
"m.will_expire": "running", | ||
"body": "hello", | ||
}, | ||
"other_fields":"sender, origin_server_ts ..." | ||
} | ||
``` | ||
|
||
The response to the client will be: | ||
|
||
```json | ||
{ | ||
"eventId": "hash_id", | ||
"expire_refresh_token": "hash_refresh", | ||
} | ||
``` | ||
|
||
The default response is extended with the `expire_refresh_token` which | ||
can be used to reset the expiration timeout (in this example 10 seconds). | ||
A new unauthenticated endpoint is introduced: | ||
`PUT /_matrix/client/v3/expiration/{refresh_method}` | ||
where the `refresh_method` is either: `refresh`, `end` | ||
toger5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
The body contains the refresh token so the homeserver knows what to refresh. | ||
|
||
```json | ||
{ | ||
"expire_refresh_token": "hash_refresh", | ||
} | ||
``` | ||
toger5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
The information required to call this endpoint is very limited so that almost | ||
no metadata is leaked when. This allows to share a refresh link to a different | ||
toger5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
service (an SFU for instance) that can track the current client connection state, | ||
and pings the HS to refresh and informs the HS about a disconnect. | ||
|
||
The homeserver does the following when receiving an event with `m.expired` | ||
toger5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
- It generates a token and stores it alongside with the time of retrieval, | ||
the eventId and the expire duration. | ||
- Starts a counter for the stored expiation token. | ||
toger5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- If a `PUT /_matrix/client/v3/expiration/refresh` is received, the | ||
timer is restarted with the stored expire duration. | ||
AndrewFerr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- If a `PUT /_matrix/client/v3/expiration/end` is received, the | ||
event _gets ended_. | ||
- If the timer times out, the event _gets expired_. | ||
- If the event is a state event only the latest/current state is considered. If | ||
the homeserver receives a new state event without `m.expires` but with the same | ||
toger5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
state key, the expire_refresh_token gets invalidated and the associated timer is | ||
stopped. | ||
|
||
The event _gets expired_/_gets ended_ means: | ||
|
||
- The homeserver **sends a new event** that is a copy of the previous event but: | ||
- If it gets _expired_ the event will include: `"m.will_expire": "expired"` | ||
- If it gets _ended_ the event will include: `"m.will_expire": "ended"`. | ||
- Additionally it includes a relation to the original event with `rel_type: "m.expire.relationship"` | ||
|
||
```json | ||
"m.relates_to": { | ||
"event_id": "$original_event", | ||
"rel_type": "m.expire.relationship" | ||
}, | ||
"m.will_expire": "ended" | "expired", | ||
``` | ||
|
||
- The homeserver stops the associated timer and invalidates (deletes) the `expire_refresh_token` | ||
|
||
So for each event that is sent with `m.will_expire: X` where X is duration in | ||
seconds > 0. The homeserver will sent another event which can be used to trigger | ||
logic on the client. This allows for any generic timeout logic. | ||
|
||
Timed messages/reminders could also be implemented using this where clients ignore | ||
the `"will_expire":"running"` events for a specific event type but render the | ||
`"will_expire":"expired"` events. | ||
|
||
## Potential issues | ||
|
||
## Alternatives | ||
|
||
[MSC4018](https://github.com/matrix-org/matrix-spec-proposals/pull/4018) also | ||
proposes a way to make call memberships reliable. It uses the client sync loop as | ||
an indicator to determine if the event is expired. Instead of letting the SFU | ||
inform about the call termination or using the call app ping loop like we propose | ||
here. | ||
|
||
--- | ||
It might not be necessary to change the value of `"m.will_expire" = 10` to | ||
`"m.will_expire" = "running"` it makes it easier to understand and also | ||
hides more potential metadata but it is questionable if that bring any benefit. | ||
|
||
--- | ||
The name `m.will_expire` has been chosen since it communicates that it becomes | ||
invalid. And that it is an event that automatically changes state | ||
(`will_expire` vs `expired`). But it does not imply what expired vs non expired | ||
means, it is flexible in how can be used. | ||
Alternatives could by: | ||
|
||
- `m.alive` | ||
- pro: communicates it might change (alive is always temporal) | ||
- con: ver strong bias on how to use it `valid/invalid` | ||
- `m.timeout` | ||
- pro: very unbiased in how its used - timeout over can also mean the client | ||
will show a reminder. | ||
- pro: clear that it has something to do with time. | ||
- con: not so clear the homeserver will automatically do sth. | ||
- con: not so clear that this timeout can be refreshed? | ||
|
||
## Security considerations | ||
|
||
We are using unauthenticated endpoint to refresh the expirations. Since we use | ||
the token it is hard to guess a correct endpoint and randomly end `will_expire` | ||
events. | ||
|
||
It is an intentional decision to not provide an endpoint like | ||
`PUT /_matrix/client/v3/expiration/room/{roomId}/event/{eventId}` | ||
where any client with access to the room could also `end` or `refresh` | ||
the expiration. With the token the client sending the event has ownership | ||
over the expiration and only intentional delegation of that ownership | ||
(sharing the token) is possible. | ||
|
||
On the other hand the token makes sure that the instance gets as little | ||
information about the matrix metadata of the associated `will_expire` event. | ||
|
||
## Unstable prefix | ||
|
||
## Dependencies | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.