Skip to content
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

MSC2753: Peeking via sync (take 2) #2753

Open
wants to merge 21 commits into
base: old_master
Choose a base branch
from
Open

MSC2753: Peeking via sync (take 2) #2753

wants to merge 21 commits into from

Conversation

ara4n
Copy link
Member

@ara4n ara4n commented Aug 29, 2020

Rendered

A first cut at an alternative solution to peeking via /sync, using a /peek method rather than messing around with filters.

Hopefully obsoletes #1776. Credit to @Half-Shot for suggesting this approach at #1776 (review).

@ara4n ara4n added proposal A matrix spec change proposal kind:core MSC which is critical to the protocol's success labels Aug 29, 2020
@ara4n ara4n mentioned this pull request Aug 30, 2020
15 tasks
@bwindels
Copy link
Contributor

Overall, this looks like a nice API to work with as a client developer. Have left some comments for the specific use cases mentioned though, which each seem to have their own intuitive scope and lifetime for a peek.

proposals/2753-peeking-via-sync-v2.md Outdated Show resolved Hide resolved
proposals/2753-peeking-via-sync-v2.md Outdated Show resolved Hide resolved
proposals/2753-peeking-via-sync-v2.md Outdated Show resolved Hide resolved
proposals/2753-peeking-via-sync-v2.md Outdated Show resolved Hide resolved
Copy link
Member

@turt2live turt2live left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generally seems in the right direction - just a few comments in addition to the other ongoing threads.

Please also line wrap at ~100 characters.

proposals/2753-peeking-via-sync-v2.md Outdated Show resolved Hide resolved
proposals/2753-peeking-via-sync-v2.md Show resolved Hide resolved
proposals/2753-peeking-via-sync-v2.md Outdated Show resolved Hide resolved
proposals/2753-peeking-via-sync-v2.md Outdated Show resolved Hide resolved
@richvdh richvdh added this to Awaiting SCT input in Spec Core Team Backlog Sep 10, 2020
@erikjohnston
Copy link
Member

This seems relatively sane, modulo concerns with clients accidentally not cleaning up after themselves. (Plus to what extent this interacts with the request format for paginated sync).

I wholeheartedly approve of putting these rooms in a dedicated peek section in /sync response

clokep added a commit to matrix-org/synapse that referenced this pull request Sep 18, 2020
Synapse 1.20.0rc5 (2020-09-18)
==============================

In addition to the below, Synapse 1.20.0rc5 also includes the bug fix that was included in 1.19.3.

Features
--------

- Add flags to the `/versions` endpoint for whether new rooms default to using E2EE. ([\#8343](#8343))

Bugfixes
--------

- Fix rate limiting of federation `/send` requests. ([\#8342](#8342))
- Fix a longstanding bug where back pagination over federation could get stuck if it failed to handle a received event. ([\#8349](#8349))

Internal Changes
----------------

- Blacklist [MSC2753](matrix-org/matrix-spec-proposals#2753) SyTests until it is implemented. ([\#8285](#8285))
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Sep 22, 2020
Synapse 1.20.0 (2020-09-22)
===========================

No significant changes since v1.20.0rc5.

Removal warning
---------------

Historically, the [Synapse Admin
API](https://github.com/matrix-org/synapse/tree/master/docs) has been
accessible under the `/_matrix/client/api/v1/admin`,
`/_matrix/client/unstable/admin`, `/_matrix/client/r0/admin` and
`/_synapse/admin` prefixes. In a future release, we will be dropping support
for accessing Synapse's Admin API using the `/_matrix/client/*` prefixes. This
makes it easier for homeserver admins to lock down external access to the Admin
API endpoints.

Synapse 1.20.0rc5 (2020-09-18)
==============================

In addition to the below, Synapse 1.20.0rc5 also includes the bug fix that was included in 1.19.3.

Features
--------

- Add flags to the `/versions` endpoint for whether new rooms default to using E2EE. ([\#8343](matrix-org/synapse#8343))


Bugfixes
--------

- Fix rate limiting of federation `/send` requests. ([\#8342](matrix-org/synapse#8342))
- Fix a longstanding bug where back pagination over federation could get stuck if it failed to handle a received event. ([\#8349](matrix-org/synapse#8349))


Internal Changes
----------------

- Blacklist [MSC2753](matrix-org/matrix-spec-proposals#2753) SyTests until it is implemented. ([\#8285](matrix-org/synapse#8285))


Synapse 1.20.0rc4 (2020-09-16)
==============================

Synapse 1.20.0rc4 is identical to 1.20.0rc3, with the addition of the security fix that was included in 1.19.2.


Synapse 1.20.0rc3 (2020-09-11)
==============================

Bugfixes
--------

- Fix a bug introduced in v1.20.0rc1 where the wrong exception was raised when invalid JSON data is encountered. ([\#8291](matrix-org/synapse#8291))


Synapse 1.20.0rc2 (2020-09-09)
==============================

Bugfixes
--------

- Fix a bug introduced in v1.20.0rc1 causing some features related to notifications to misbehave following the implementation of unread counts. ([\#8280](matrix-org/synapse#8280))


Synapse 1.20.0rc1 (2020-09-08)
==============================

Removal warning
---------------

Some older clients used a [disallowed character](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-register-email-requesttoken) (`:`) in the `client_secret` parameter of various endpoints. The incorrect behaviour was allowed for backwards compatibility, but is now being removed from Synapse as most users have updated their client. Further context can be found at [\#6766](matrix-org/synapse#6766).

Features
--------

- Add an endpoint to query your shared rooms with another user as an implementation of [MSC2666](matrix-org/matrix-spec-proposals#2666). ([\#7785](matrix-org/synapse#7785))
- Iteratively encode JSON to avoid blocking the reactor. ([\#8013](matrix-org/synapse#8013), [\#8116](matrix-org/synapse#8116))
- Add support for shadow-banning users (ignoring any message send requests). ([\#8034](matrix-org/synapse#8034), [\#8092](matrix-org/synapse#8092), [\#8095](matrix-org/synapse#8095), [\#8142](matrix-org/synapse#8142), [\#8152](matrix-org/synapse#8152), [\#8157](matrix-org/synapse#8157), [\#8158](matrix-org/synapse#8158), [\#8176](matrix-org/synapse#8176))
- Use the default template file when its equivalent is not found in a custom template directory. ([\#8037](matrix-org/synapse#8037), [\#8107](matrix-org/synapse#8107), [\#8252](matrix-org/synapse#8252))
- Add unread messages count to sync responses, as specified in [MSC2654](matrix-org/matrix-spec-proposals#2654). ([\#8059](matrix-org/synapse#8059), [\#8254](matrix-org/synapse#8254), [\#8270](matrix-org/synapse#8270), [\#8274](matrix-org/synapse#8274))
- Optimise `/federation/v1/user/devices/` API by only returning devices with encryption keys. ([\#8198](matrix-org/synapse#8198))


Bugfixes
--------

- Fix a memory leak by limiting the length of time that messages will be queued for a remote server that has been unreachable. ([\#7864](matrix-org/synapse#7864))
- Fix `Re-starting finished log context PUT-nnnn` warning when event persistence failed. ([\#8081](matrix-org/synapse#8081))
- Synapse now correctly enforces the valid characters in the `client_secret` parameter used in various endpoints. ([\#8101](matrix-org/synapse#8101))
- Fix a bug introduced in v1.7.2 impacting message retention policies that would allow federated homeservers to dictate a retention period that's lower than the configured minimum allowed duration in the configuration file. ([\#8104](matrix-org/synapse#8104))
- Fix a long-standing bug where invalid JSON would be accepted by Synapse. ([\#8106](matrix-org/synapse#8106))
- Fix a bug introduced in Synapse v1.12.0 which could cause `/sync` requests to fail with a 404 if you had a very old outstanding room invite. ([\#8110](matrix-org/synapse#8110))
- Return a proper error code when the rooms of an invalid group are requested. ([\#8129](matrix-org/synapse#8129))
- Fix a bug which could cause a leaked postgres connection if synapse was set to daemonize. ([\#8131](matrix-org/synapse#8131))
- Clarify the error code if a user tries to register with a numeric ID. This bug was introduced in v1.15.0. ([\#8135](matrix-org/synapse#8135))
- Fix a bug where appservices with ratelimiting disabled would still be ratelimited when joining rooms. This bug was introduced in v1.19.0. ([\#8139](matrix-org/synapse#8139))
- Fix logging in via OpenID Connect with a provider that uses integer user IDs. ([\#8190](matrix-org/synapse#8190))
- Fix a longstanding bug where user directory updates could break when unexpected profile data was included in events. ([\#8223](matrix-org/synapse#8223))
- Fix a longstanding bug where stats updates could break when unexpected profile data was included in events. ([\#8226](matrix-org/synapse#8226))
- Fix slow start times for large servers by removing a table scan of the `users` table from startup code. ([\#8271](matrix-org/synapse#8271))


Updates to the Docker image
---------------------------

- Fix builds of the Docker image on non-x86 platforms. ([\#8144](matrix-org/synapse#8144))
- Added curl for healthcheck support and readme updates for the change. Contributed by @maquis196. ([\#8147](matrix-org/synapse#8147))


Improved Documentation
----------------------

- Link to matrix-synapse-rest-password-provider in the password provider documentation. ([\#8111](matrix-org/synapse#8111))
- Updated documentation to note that Synapse does not follow `HTTP 308` redirects due to an upstream library not supporting them. Contributed by Ryan Cole. ([\#8120](matrix-org/synapse#8120))
- Explain better what GDPR-erased means when deactivating a user. ([\#8189](matrix-org/synapse#8189))


Internal Changes
----------------

- Add filter `name` to the `/users` admin API, which filters by user ID or displayname. Contributed by Awesome Technologies Innovationslabor GmbH. ([\#7377](matrix-org/synapse#7377), [\#8163](matrix-org/synapse#8163))
- Reduce run times of some unit tests by advancing the reactor a fewer number of times. ([\#7757](matrix-org/synapse#7757))
- Don't fail `/submit_token` requests on incorrect session ID if `request_token_inhibit_3pid_errors` is turned on. ([\#7991](matrix-org/synapse#7991))
- Convert various parts of the codebase to async/await. ([\#8071](matrix-org/synapse#8071), [\#8072](matrix-org/synapse#8072), [\#8074](matrix-org/synapse#8074), [\#8075](matrix-org/synapse#8075), [\#8076](matrix-org/synapse#8076), [\#8087](matrix-org/synapse#8087), [\#8100](matrix-org/synapse#8100), [\#8119](matrix-org/synapse#8119), [\#8121](matrix-org/synapse#8121), [\#8133](matrix-org/synapse#8133), [\#8156](matrix-org/synapse#8156), [\#8162](matrix-org/synapse#8162), [\#8166](matrix-org/synapse#8166), [\#8168](matrix-org/synapse#8168), [\#8173](matrix-org/synapse#8173), [\#8191](matrix-org/synapse#8191), [\#8192](matrix-org/synapse#8192), [\#8193](matrix-org/synapse#8193), [\#8194](matrix-org/synapse#8194), [\#8195](matrix-org/synapse#8195), [\#8197](matrix-org/synapse#8197), [\#8199](matrix-org/synapse#8199), [\#8200](matrix-org/synapse#8200), [\#8201](matrix-org/synapse#8201), [\#8202](matrix-org/synapse#8202), [\#8207](matrix-org/synapse#8207), [\#8213](matrix-org/synapse#8213), [\#8214](matrix-org/synapse#8214))
- Remove some unused database functions. ([\#8085](matrix-org/synapse#8085))
- Add type hints to various parts of the codebase. ([\#8090](matrix-org/synapse#8090), [\#8127](matrix-org/synapse#8127), [\#8187](matrix-org/synapse#8187), [\#8241](matrix-org/synapse#8241), [\#8140](matrix-org/synapse#8140), [\#8183](matrix-org/synapse#8183), [\#8232](matrix-org/synapse#8232), [\#8235](matrix-org/synapse#8235), [\#8237](matrix-org/synapse#8237), [\#8244](matrix-org/synapse#8244))
- Return the previous stream token if a non-member event is a duplicate. ([\#8093](matrix-org/synapse#8093), [\#8112](matrix-org/synapse#8112))
- Separate `get_current_token` into two since there are two different use cases for it. ([\#8113](matrix-org/synapse#8113))
- Remove `ChainedIdGenerator`. ([\#8123](matrix-org/synapse#8123))
- Reduce the amount of whitespace in JSON stored and sent in responses. ([\#8124](matrix-org/synapse#8124))
- Update the test federation client to handle streaming responses. ([\#8130](matrix-org/synapse#8130))
- Micro-optimisations to `get_auth_chain_ids`. ([\#8132](matrix-org/synapse#8132))
- Refactor `StreamIdGenerator` and `MultiWriterIdGenerator` to have the same interface. ([\#8161](matrix-org/synapse#8161))
- Add functions to `MultiWriterIdGen` used by events stream. ([\#8164](matrix-org/synapse#8164), [\#8179](matrix-org/synapse#8179))
- Fix tests that were broken due to the merge of 1.19.1. ([\#8167](matrix-org/synapse#8167))
- Make `SlavedIdTracker.advance` have the same interface as `MultiWriterIDGenerator`. ([\#8171](matrix-org/synapse#8171))
- Remove unused `is_guest` parameter from, and add safeguard to, `MessageHandler.get_room_data`. ([\#8174](matrix-org/synapse#8174), [\#8181](matrix-org/synapse#8181))
- Standardize the mypy configuration. ([\#8175](matrix-org/synapse#8175))
- Refactor some of `LoginRestServlet`'s helper methods, and move them to `AuthHandler` for easier reuse. ([\#8182](matrix-org/synapse#8182))
- Fix `wait_for_stream_position` to allow multiple waiters on same stream ID. ([\#8196](matrix-org/synapse#8196))
- Make `MultiWriterIDGenerator` work for streams that use negative values. ([\#8203](matrix-org/synapse#8203))
- Refactor queries for device keys and cross-signatures. ([\#8204](matrix-org/synapse#8204), [\#8205](matrix-org/synapse#8205), [\#8222](matrix-org/synapse#8222), [\#8224](matrix-org/synapse#8224), [\#8225](matrix-org/synapse#8225), [\#8231](matrix-org/synapse#8231), [\#8233](matrix-org/synapse#8233), [\#8234](matrix-org/synapse#8234))
- Fix type hints for functions decorated with `@cached`. ([\#8240](matrix-org/synapse#8240))
- Remove obsolete `order` field from federation send queues. ([\#8245](matrix-org/synapse#8245))
- Stop sub-classing from object. ([\#8249](matrix-org/synapse#8249))
- Add more logging to debug slow startup. ([\#8264](matrix-org/synapse#8264))
- Do not attempt to upgrade database schema on worker processes. ([\#8266](matrix-org/synapse#8266), [\#8276](matrix-org/synapse#8276))
@carlbordum
Copy link

Hi, we are building something slightly-novel on matrix. Just wanted to let you know that this MSC would be an improvement for us 👍

Comment on lines +76 to +80
XXX: should we limit this API to room IDs, and require clients to do a `GET
/_matrix/client/r0/directory/room/{roomAlias}` request if they have a room
alias? (In which case, `/_matrix/client/r0/room/{room_id}/peek` might be a
better name for it.) On the one hand: cleaner, simpler API. On the other: more
requests needed for each operation.
Copy link
Member

@richvdh richvdh Nov 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on this particularly welcome. (I in no way promise to follow the result, but feel free to express opinion with a reaction on this comment: 👍 for "require an ID", 👎 for "allow either ID or alias")

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

require an ID for me. If a client is trying to peek an alias, they will have likely already (or should have) called the directory API to confirm it's existence, IMO.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we want peeks to be as fast as possible, and adding in a roundtrip to first lookup the alias is completely unnecessary and so adds latency for no good reason. So i reckon we should keep it supporting aliases.

Copy link
Member

@richvdh richvdh Nov 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(a) if the peek is over federation, there are going to be multiple requests anyway, and it's going to be slow anyway, and having two API calls gives better feedback to the client as to which part failed. (b) As H-S says, in most cases we'll know the ID anyway (in particular #1772 uses IDs everywhere).

I'm about 80% in favour of requiring an ID but can see both arguments.

```
{
"room_id": "<resolved room id>",
"peek_expiry_ts": 1605534210000
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expecting clients to maintain a clock and be NTP synced feels unnecessary. it's also inconsistent with the renewal_interval approach that #2444 takes. can't we just return a lifetime for the peek?

Copy link
Contributor

@neilalexander neilalexander Nov 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Don't we already expect clients to maintain a clock to keep TLS alive?)

Copy link
Member

@richvdh richvdh Nov 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't we just return a lifetime for the peek?

yes we can, and I was in somewhat two minds about it. renewal_interval? ttl for consistency with /voip/turnServer ? lifetime for consistency with m.call.invite ? <something>_ms for consistency with retry_after_ms ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Don't we already expect clients to maintain a clock to keep TLS alive?)

I'm not following this. Most client impls have nothing to do with TLS.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not following this. Most client impls have nothing to do with TLS.

I mean that if the client's clock is that far out of sync, that they aren't going to be able to set up a TLS connection to the CS API anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, I see. Possibly, yes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so can we make it a renewal_interval for consistency with #2444 (and to avoid people having to be NTP synced?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well I agree that it may as well be consistent with #2444, but we can change #2444 to match whatever we decide here.

renewal_interval implies a fixed interval, whereas the server might want to vary the lifetime depending on what else is going on. I'd prefer lifetime.

OTOH I don't feel that strongly and don't want to bikeshed it, so if you are keen on renewal_interval we can go with that.

Matthew wants us to drop the `_room` suffix. I worry that this is somewhat
confusing (it's not obvious to the casual observer what it is that we are
peeking), and risks a lot of confusion in the future when we find something
else to peek, but he seems to feel strongly.
For example:

```
POST /_matrix/client/r0/peek HTTP/1.1
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels really weird to lose the room id or alias from the URL - we won't be able to see it in logs, and given it's the main object of the method, it feels like it should be in the URL rather than buried as a field in the POST request body.

I'm happy to dump the servers into the post body (rather than being querystring params) if it makes folks feel happier though.

Otherwise this is looking good to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, why can't this use the same existing shape as /_matrix/client/r0/join/{roomIdOrAlias}?server_name=x&server_name=y

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll stick the room ID/alias back in the URI. As for the server_name, we went round this a few times in a chat room, but I'll try to summarise:

Comment on lines +184 to +186
* "snapshot" API, for a one-time peek operation which returns the current
state of the room without adding the room to future `/sync` responses. Might
be useful for certain usecases (eg, looking at a user's public profile)?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and for things like matrix-static which do not want to maintain /sync and actively peek over a large set of rooms.

* it's a misnomer (given the user hasn't joined the rooms)
* `join` refers to rooms which the *user* is in, rather than that they are
peeking into using a given *device*
* we risk breaking clients who aren't aware of the new style of peeking.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

surely not given that it would still be per-device and those clients wouldn't be calling the new /peek API

@turt2live turt2live added the needs-implementation This MSC does not have a qualifying implementation for the SCT to review. The MSC cannot enter FCP. label Jun 8, 2021
### Keep /peek closer to /join

Given that peeking has parallels to joining, it might be preferable to keep the
API closer to `/join`. On the other hand, they probabably aren't actually
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo

Suggested change
API closer to `/join`. On the other hand, they probabably aren't actually
API closer to `/join`. On the other hand, they probably aren't actually

Copy link
Contributor

@Dominaezzz Dominaezzz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pointing out some issues with the /sync side of things.

A potential solution could be to provide some sort of "continuation token" in the leave section, when peeking ends.
When a client does /join or /peek again, they also pass this optional "continuation token", then the server may send a delta instead of the full state of the room.
The server may decide to ignore the token if it's too old or it is too expensive to calculate the delta.
This could also make it easier for clients to manage their peeks. Instead of keeping track of time, they can just pass this token to continue peeking.

This continuation token would be an awesome enhancement to the /join and /leave sync state management too.

If the client requests lazy-loading via `lazy_load_members`, then redundant
membership events are excluded in the same way as they are for joined rooms.

If a user subsequently `/join`s a room they are peeking, the room will
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If someone /peeks, they'll see the room in the peek section and eventually the leave section.
If someone /peeks, then eventually joins the room, it will further appear in the join section.
Now, what if we have these sequence of events.

  • Device A /peeks into a room.
  • Device A /syncs once and gets the (initial) state of the peeked room.
  • Device B /joins the room that Device A is peeking.
  • Device B leaves the room almost immediately.
  • Device A /syncs again ... and gets what?

According to this paragraph, it's reasonable to infer that Device A will see the room appear in the leave section, since the user has left the room but this client has some state that needs updating.

Does this mean my (Device A) device specific /peek has been cancelled by this other random device?
Sure, I could /peek again but room state can be expensive to get. I already have fairly fresh state locally that just needs an incremental update.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other question is what is the desired UX. I would expect that if I was peeking a room in the context of considering joining I would expect that joining on another device transitioned the view into the room itself as a member. In that case leaving the room should bring me to whatever the "left room" experience is.

However there are other cases for peeking such as spaces or "X as rooms" (such as "profiles as rooms") where you would not want to be unpeeked based on joining the space. However this likely applies for both this device and another device joining the space.

It seems that the best option is the the room is left in the peek list if it is left, whether on this client or another one. Then this client can decide if it still needs that peek (for example it is peeking the space for membership info) or if it is no longer necessary (for example it was for a room preview, and after joining and leaving the user should now be in a "left room" UX where no new info is required).


When a room stops being peeked (either because the client called `/unpeek` or
because the server timed out the peek), the room will be included in the
`leave` section of the `/sync` response, including any events that occured
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm peeking into a room, then someone invites me to it, then rescinds the invitation, has my peek been cancelled?
How do I differentiate between my invite being rescinded and my peek ending?

Also, if my peek ended, I have to start again, etc. More on this in the previous comment.

response. `peek_expiry_ts` gives a timestamp (milliseconds since the unix
epoch) when the server will *expire* the peek if the client does not renew it.

The server ratelimit requests to `/peek` and returns a 429 error with

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The server ratelimit requests to `/peek` and returns a 429 error with
The server should ratelimit requests to `/peek` and returns a 429 error with

needed.

If there is already an active peek for the room in question, it is renewed and
a successful response is returned with the updated `peek_expiry_ts`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
a successful response is returned with the updated `peek_expiry_ts`.
a successful response is returned with an updated `peek_expiry_ts`.

"an" seems to imply that the client is providing the expiry which is not the case here.

a successful response is returned with the updated `peek_expiry_ts`.

If the user is already *joined* to the room in question, the server returns a
400 error with `M_BAD_STATE`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be useful to have a specific error code here. Especially if an alias is accepted as the client may not be able that it is joined to the room already. In particular it seems that at least the resolved room ID should be returned.

A successful response has an empty body.

If the room is unknown or was not previously being peeked the server returns a
400 error with `M_BAD_STATE`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This leads to an unhappy situation where a delayed request may fail because the peek has expired. IIUC this would be hard for for the client to handle gracefully in any other way then just assuming success. Since this is the case why do we differentiate here? Why not make this return success in any case where the client is not peeking when the response is returned. AKA why not make this idempotent.

If the client requests lazy-loading via `lazy_load_members`, then redundant
membership events are excluded in the same way as they are for joined rooms.

If a user subsequently `/join`s a room they are peeking, the room will

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other question is what is the desired UX. I would expect that if I was peeking a room in the context of considering joining I would expect that joining on another device transitioned the view into the room itself as a member. In that case leaving the room should bring me to whatever the "left room" experience is.

However there are other cases for peeking such as spaces or "X as rooms" (such as "profiles as rooms") where you would not want to be unpeeked based on joining the space. However this likely applies for both this device and another device joining the space.

It seems that the best option is the the room is left in the peek list if it is left, whether on this client or another one. Then this client can decide if it still needs that peek (for example it is peeking the space for membership info) or if it is no longer necessary (for example it was for a room preview, and after joining and leaving the user should now be in a "left room" UX where no new info is required).

* Allow peeks to stack up without limit and trust that clients will not forget
about them: after all, it is in clients' best interest not to leak
resources, to reduce the amount of data to be handled, and it is not obvious
that leaking peeks is easier than leaking joins.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The client cost to "forgetting" a peek is very low. However the server may need to do some work (if /sync is poll-based for all rooms). I think the only client cost is if you are offline for a while and get a huge number of events before you get the chance to unpeek a room you no longer need.

One option would be to return all peeked rooms in the sync response even if they have no events. The upside is that you constantly (or periodically) remind the clients what they are peeking but the downside is some extra transfer and parsing (although this can be made arbitrarily low by only sending a "reminder" for each room occasionally).

Comment on lines +99 to +101
If the room does not allow peeking (ie, it does not have `history_visibility`
of `world_readable` <sup id="a1">[1](#f1)</sup>), the server returns a 403
error with `M_FORBIDDEN`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could a rule be added where a user can peek the room if they have been invited to that room? (If history_visibility is shared or invited)

This would allow "previewing the room before joining it", i.e. "do you want to join this room" with some context.

This would also allow clients to implement "accept/reject DM request", and display DMs in a similar manner as they do in many IM clients today; by adding the DM to the DM list as any other DM.

Such a rule could probably synergize with MSC2199 and MSC2444, providing users more context about the rooms/DMs they're invited to, and be able to accept/reject with more information at hand.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is mentioned, but it would be better to explicitly state under what conditions a user can peek into a given room.

@@ -0,0 +1,301 @@
# MSC2753: Peeking via Sync (Take 2)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something this should also handle is supporting /event and /context into peeked rooms.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't that be accepted/handled automatically as long as a peek is active?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:core MSC which is critical to the protocol's success needs-implementation This MSC does not have a qualifying implementation for the SCT to review. The MSC cannot enter FCP. proposal A matrix spec change proposal
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet