From 664da1610b4734b898c607cafed3ea4dde580ffc Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Tue, 9 Jun 2026 21:53:29 -0400 Subject: [PATCH 1/8] Pagination token clarificaitons --- .../xxxx-directionless-pagination-tokens.md | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 proposals/xxxx-directionless-pagination-tokens.md diff --git a/proposals/xxxx-directionless-pagination-tokens.md b/proposals/xxxx-directionless-pagination-tokens.md new file mode 100644 index 00000000000..4a48bc38e98 --- /dev/null +++ b/proposals/xxxx-directionless-pagination-tokens.md @@ -0,0 +1,165 @@ +# MSCXXXX: Clarify that pagination tokens are directionless + +The Matrix client-server API has several endpoints which handle pagination over events: + +* [`/messages`][messages] +* [`/sync`][sync] +* [`/relations`][relations] +* [`/context`][context] +* [`/search`][search] + +Each returns tokens that can be used for further pagination, though over time the +specification has accumulated inconsistencies around which tokens can be used with +which endpoints. + +There is a [spec PR](spec2357) which attempts +to fix an inconsistency in the `/relations` endpoint: the `from` parameter currently lists +`next_batch` from `/sync` as an acceptable value, but this was likely meant to be +`prev_batch`. + +From discussions, this has raised a broader question: are tokens directional or are they +just opaque positions in the timeline? + +Synapse has always used a single [`StreamToken`][synapse-streamtoken] type at the API +level across `/sync`, `/messages`, and `/relations`. These tokens are accepted and returned +interchangeably between endpoints — the same `StreamToken.from_string()` parses +them regardless of which endpoint produced or consumes them. This makes +directionless tokens the de facto behavior, though it has never been explicitly +documented. + +Note that Synapse internally embeds a [`RoomStreamToken`][synapse-roomstreamtoken] +within `StreamToken` which can represent either a stream position (`s` prefix) or a +topological position (`t` prefix). This distinction is an internal implementation +detail — the API-visible `StreamToken` envelope is the same type everywhere. + +This MSC aims to codify that understanding and clean up the +inconsistencies across endpoints. + +## Proposal + +Pagination tokens returned by any of the pagination endpoints ([`/messages`][messages], +[`/sync`][sync], [`/relations`][relations], [`/context`][context], [`/search`][search]) +represent opaque positions in the event timeline and are interchangeable between endpoints. +The direction of pagination is determined solely by the `dir` parameter where present, +not by the type of token. + +The following updates are made to the spec text. + +### [`/relations`][relations] endpoint + +The `from` and `to` parameter descriptions are updated to note they can accept a token +from any pagination endpoint, rather than the narrow list currently specified. + +### [`/messages`][messages] endpoint + +The `from` and `to` parameter descriptions are updated to note they can accept a token +from [`/context`][context] or [`/search`][search], and the "not required to support" caveat +on `start` tokens is removed. + +### [`/context`][context] endpoint + +The `/context` endpoint returns `start` and `end` tokens in its response, currently +described with directional language ("A token that can be used to paginate backwards +with" / "A token that can be used to paginate forwards with"). These descriptions are +updated to remove the directional language. + +### [`/search`][search] endpoint + +The `/search` endpoint returns a `next_batch` token. Its description is sufficient +as-is, but it is noted that this token can be used with other pagination endpoints +as well. + +## Potential issues + +Implementations which perform validation on the shape or format of pagination +tokens might reject tokens from other endpoints. The extent to which tokens are +interchangeable varies by implementation. + +### Synapse + +Synapse uses a single [`StreamToken`][synapse-streamtoken] type for all pagination +tokens across `/sync`, `/messages`, `/relations`, `/context`, and `/search`. It +does not distinguish direction or origin in the token itself. (Internally, the +`room_key` sub-field is a [`RoomStreamToken`][synapse-roomstreamtoken] which can +represent a stream or topological position, but this is an implementation detail +— the API-visible token envelope is the same everywhere.) No changes are required. + +### Conduit lineage (conduwuit / continuwuity / Tuwunel) + +These implementations use a [`PduCount`][conduit-pducount] type (a signed integer +with `Normal(u64)` / `Backfilled(i64)` variants) across `/messages`, `/relations`, +`/threads`, and `/context`. Tokens from these endpoints are interchangeable. + +However, `/sync` parses its `since` parameter as a `u64` — it accepts **only** +non-negative integers. A `PduCount::Backfilled` (negative) token from `/relations` +or `/messages` would fail to parse in `/sync`. The reverse direction works: sync +tokens are always non-negative and parse cleanly as `PduCount::Normal`. + +**Changes needed:** `/sync` should accept `PduCount` (signed) instead of `u64` to +fully interoperate with other endpoints. + +### Dendrite lineage (Dendrite / Zendrite) + +These implementations use **three separate token types** with strict prefix-based +validation: + +* [`StreamingToken`][dendrite-streaming] (`s{...}`) — used by `/sync`. +* [`TopologyToken`][dendrite-topology] (`t{...}`) — used by `/messages` and `/context`. +* [`StreamPosition`][dendrite-streampos] (bare integer) — used by `/relations`. + +`/relations` parses its tokens via `strconv.Atoi`, which rejects both `s`- and +`t`-prefixed strings. Conversely, `/sync` expects only `StreamingToken` and +rejects bare integers and `t`-prefixed strings. Only `/messages` has dual-parsing +logic that tries `TopologyToken` first and falls back to `StreamingToken`, +converting server-side. + +**Tokens are not interchangeable** across `/sync`, `/relations`, `/messages`, and +`/context` in these implementations. This MSC would call for them to become more +permissive. + +**Changes needed:** At minimum, `/relations` should accept `StreamingToken` and +`TopologyToken` formats (or their underlying values), and `/sync` should accept +`TopologyToken` and bare integers. A pattern like `/messages` already uses +(try one format, fall back to another, converting server-side) could be applied +to the other endpoints. + +## Alternatives + +The main alternative is to leave the current inconsistencies as-is. The [spec PR](spec2357) +could land its minimal fix, though the review discussion showed it is unclear which +direction is correct without addressing the broader question of interchangeability. + +Another alternative is to acknowledge the divergence: declare that tokens are specific +to each endpoint and not interchangeable. This would match Dendrite's current design +but would be a departure from Synapse's long-standing behavior and is inconsistent +with how developers use these tokens in practice (e.g. using a `/sync` `prev_batch` +token as the `from` parameter to `/messages`). + +## Security considerations + +None. + +## Unstable prefix + +N/A + +## Dependencies + +N/A + +[messages]: https://spec.matrix.org/latest/client-server-api/#get_matrixclientv3roomsroomidmessages +[sync]: https://spec.matrix.org/latest/client-server-api/#get_matrixclientv3sync +[relations]: https://spec.matrix.org/latest/client-server-api/#get_matrixclientv1roomsroomidrelationseventid +[context]: https://spec.matrix.org/latest/client-server-api/#get_matrixclientv3roomsroomidcontexteventid +[search]: https://spec.matrix.org/latest/client-server-api/#post_matrixclientv3search + +[spec2357]: https://github.com/matrix-org/matrix-spec/pull/2357 + +[synapse-streamtoken]: https://github.com/element-hq/synapse/blob/76b4fdceed0739d83ac79588416dc88f25d8d14e/synapse/streams/config.py#L39-L45 +[synapse-roomstreamtoken]: https://github.com/element-hq/synapse/blob/76b4fdceed0739d83ac79588416dc88f25d8d14e/synapse/types/__init__.py#L722 + +[conduit-pducount]: https://github.com/continuwuation/continuwuity/blob/main/src/core/matrix/pdu/count.rs#L13-L17 + +[dendrite-streaming]: https://github.com/element-hq/dendrite/blob/main/syncapi/types/types.go#L106-L118 +[dendrite-topology]: https://github.com/element-hq/dendrite/blob/main/syncapi/types/types.go#L213-L218 +[dendrite-streampos]: https://github.com/element-hq/dendrite/blob/main/syncapi/types/types.go#L41-L52 From 5a2eab8d2341e359fe3b1ef68f5b66407aa4868a Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 12 Jun 2026 14:40:41 -0400 Subject: [PATCH 2/8] Simplify a bit to only be directionless --- .../xxxx-directionless-pagination-tokens.md | 128 ++++++++---------- 1 file changed, 54 insertions(+), 74 deletions(-) diff --git a/proposals/xxxx-directionless-pagination-tokens.md b/proposals/xxxx-directionless-pagination-tokens.md index 4a48bc38e98..bad182401c4 100644 --- a/proposals/xxxx-directionless-pagination-tokens.md +++ b/proposals/xxxx-directionless-pagination-tokens.md @@ -6,74 +6,65 @@ The Matrix client-server API has several endpoints which handle pagination over * [`/sync`][sync] * [`/relations`][relations] * [`/context`][context] -* [`/search`][search] +* [`/search`][search]'s `context` field for each result -Each returns tokens that can be used for further pagination, though over time the -specification has accumulated inconsistencies around which tokens can be used with -which endpoints. +Each returns tokens that can be used for further pagination, though the specification is +vague around which tokens can be used with which endpoints. -There is a [spec PR](spec2357) which attempts -to fix an inconsistency in the `/relations` endpoint: the `from` parameter currently lists -`next_batch` from `/sync` as an acceptable value, but this was likely meant to be -`prev_batch`. +There is a [spec PR](spec2357) which attempts to fix an inconsistency in the `/relations` +endpoint: the `from` parameter currently lists `next_batch` from `/sync` as an acceptable +value, but this was likely meant to be `prev_batch`. This has raised a broader question: +are pagination tokens directional, or do they represent an opaque position in the event +stream without inherent direction? -From discussions, this has raised a broader question: are tokens directional or are they -just opaque positions in the timeline? +Synapse has always treated tokens as opaque positions — a [`StreamToken`][synapse-streamtoken] +can be used for both forward and backward pagination depending on the `dir` parameter. +(Internally it embeds a [`RoomStreamToken`][synapse-roomstreamtoken] with stream (`s`) +and topological (`t`) variants, but this is an implementation detail — the API-visible +type is the same everywhere.) -Synapse has always used a single [`StreamToken`][synapse-streamtoken] type at the API -level across `/sync`, `/messages`, and `/relations`. These tokens are accepted and returned -interchangeably between endpoints — the same `StreamToken.from_string()` parses -them regardless of which endpoint produced or consumes them. This makes -directionless tokens the de facto behavior, though it has never been explicitly -documented. - -Note that Synapse internally embeds a [`RoomStreamToken`][synapse-roomstreamtoken] -within `StreamToken` which can represent either a stream position (`s` prefix) or a -topological position (`t` prefix). This distinction is an internal implementation -detail — the API-visible `StreamToken` envelope is the same type everywhere. - -This MSC aims to codify that understanding and clean up the -inconsistencies across endpoints. +This MSC aims to codify that understanding: pagination tokens do not have an +inherent direction, even if they happen to be labelled `next_batch` or +`prev_batch`. The direction is always determined by the `dir` parameter. ## Proposal -Pagination tokens returned by any of the pagination endpoints ([`/messages`][messages], -[`/sync`][sync], [`/relations`][relations], [`/context`][context], [`/search`][search]) -represent opaque positions in the event timeline and are interchangeable between endpoints. -The direction of pagination is determined solely by the `dir` parameter where present, -not by the type of token. - -The following updates are made to the spec text. - -### [`/relations`][relations] endpoint +Pagination tokens produced by `/messages`, `/relations`, `/context`, and `/search`'s +`context` field represent a position in the event stream and MUST be indistinguisable. +Tokens SHOULD +only be used within the context of a single room. (E.g. a request for `/messages` in +room #test:matrix.org does not make sense to re-use for #foo:matrix.org.) -The `from` and `to` parameter descriptions are updated to note they can accept a token -from any pagination endpoint, rather than the narrow list currently specified. +A token produced by `/messages`, `/relations`, or `/context` is tied to the room it +was produced and clients MUST NOT be used for another room. There are no guarnatees +using one in a different room will produce the correct results, servers MAY throw +an error in this case. -### [`/messages`][messages] endpoint +Tokens produced by [`/sync` `since` parameter][sync] resolve against the server's +global event stream and is safe to use across rooms for `/messages`, `/relations`, +and `/context`. `/sync` only accepts tokens produced by `/sync`. -The `from` and `to` parameter descriptions are updated to note they can accept a token -from [`/context`][context] or [`/search`][search], and the "not required to support" caveat -on `start` tokens is removed. +The following table summarises which tokens each endpoint currently accepts and proposed changes: -### [`/context`][context] endpoint +| Endpoint | Input | Currently accepts | Output | Change | +|---|---|---|---|---| +| `/sync` | `since` | Its own `next_batch` | `next_batch`, `prev_batch` | None | +| `/messages` | `from` | `/sync` (`prev_batch`/`next_batch`), itself (`end`), optionally itself (`start`) | `start`, `end` | `/sync`, `/messages`, `/relations`, `/context`, and `/search`'s `context | +| `/messages` | `to` | `/sync` (`prev_batch`/`next_batch`), itself (`end`) | — | `/sync`, `/messages`, `/relations`, `/context`, and `/search`'s `context | +| `/relations` | `from` | Itself, `/messages` (`start`), `/sync` (`next_batch`) | `next_batch`, `prev_batch` | `/sync`, `/messages`, `/relations`, `/context`, and `/search`'s `context | +| `/relations` | `to` | Itself, `/messages`, `/sync` (vague) | — | `/sync`, `/messages`, `/relations`, `/context`, and `/search`'s `context | +| `/context` | (none) | Output only | `start` ("backwards"), `end` ("forwards") | Remove directional language | +| `/search` result | (none) | Output only | `start`, `end` (no directional language) | None | -The `/context` endpoint returns `start` and `end` tokens in its response, currently -described with directional language ("A token that can be used to paginate backwards -with" / "A token that can be used to paginate forwards with"). These descriptions are -updated to remove the directional language. +Note that this does not modify the pagination of `/search` results itself, which are +only usable within `/search`. -### [`/search`][search] endpoint - -The `/search` endpoint returns a `next_batch` token. Its description is sufficient -as-is, but it is noted that this token can be used with other pagination endpoints -as well. +Open question: should `/threads` also be part of this list? ## Potential issues -Implementations which perform validation on the shape or format of pagination -tokens might reject tokens from other endpoints. The extent to which tokens are -interchangeable varies by implementation. +Homeserver implementations differ in how they structure pagination tokens. The rules +above may drastically break how a homeserver generates pagination tokens. ### Synapse @@ -88,23 +79,21 @@ represent a stream or topological position, but this is an implementation detail These implementations use a [`PduCount`][conduit-pducount] type (a signed integer with `Normal(u64)` / `Backfilled(i64)` variants) across `/messages`, `/relations`, -`/threads`, and `/context`. Tokens from these endpoints are interchangeable. +and `/context`. Tokens from these endpoints do not encode direction. -However, `/sync` parses its `since` parameter as a `u64` — it accepts **only** +`/sync` parses its `since` parameter as a `u64` — it accepts **only** non-negative integers. A `PduCount::Backfilled` (negative) token from `/relations` or `/messages` would fail to parse in `/sync`. The reverse direction works: sync tokens are always non-negative and parse cleanly as `PduCount::Normal`. -**Changes needed:** `/sync` should accept `PduCount` (signed) instead of `u64` to -fully interoperate with other endpoints. - ### Dendrite lineage (Dendrite / Zendrite) -These implementations use **three separate token types** with strict prefix-based -validation: +These implementations use **three separate token types** where each type is tied to +a specific endpoint, encoding both direction and origin in the token format: * [`StreamingToken`][dendrite-streaming] (`s{...}`) — used by `/sync`. -* [`TopologyToken`][dendrite-topology] (`t{...}`) — used by `/messages` and `/context`. +* [`TopologyToken`][dendrite-topology] (`t{...}`) — used by `/messages`, `/context`, + and `/search`'s `context`. * [`StreamPosition`][dendrite-streampos] (bare integer) — used by `/relations`. `/relations` parses its tokens via `strconv.Atoi`, which rejects both `s`- and @@ -113,15 +102,9 @@ rejects bare integers and `t`-prefixed strings. Only `/messages` has dual-parsin logic that tries `TopologyToken` first and falls back to `StreamingToken`, converting server-side. -**Tokens are not interchangeable** across `/sync`, `/relations`, `/messages`, and -`/context` in these implementations. This MSC would call for them to become more -permissive. - -**Changes needed:** At minimum, `/relations` should accept `StreamingToken` and -`TopologyToken` formats (or their underlying values), and `/sync` should accept -`TopologyToken` and bare integers. A pattern like `/messages` already uses -(try one format, fall back to another, converting server-side) could be applied -to the other endpoints. +**Changes needed:** At minimum, `/relations` should accept any token format (not +just bare integers). A pattern like `/messages` already uses (try one format, +fall back to another, converting server-side) could be applied to the other endpoints. ## Alternatives @@ -129,11 +112,8 @@ The main alternative is to leave the current inconsistencies as-is. The [spec PR could land its minimal fix, though the review discussion showed it is unclear which direction is correct without addressing the broader question of interchangeability. -Another alternative is to acknowledge the divergence: declare that tokens are specific -to each endpoint and not interchangeable. This would match Dendrite's current design -but would be a departure from Synapse's long-standing behavior and is inconsistent -with how developers use these tokens in practice (e.g. using a `/sync` `prev_batch` -token as the `from` parameter to `/messages`). +Another alternative is to leave each endpoint describing its own accepted token +types independently, with no general principle. This is the status quo. ## Security considerations From 534066ab140f26189958d2709ae577603ca1789a Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 12 Jun 2026 14:42:03 -0400 Subject: [PATCH 3/8] Typo fix --- proposals/xxxx-directionless-pagination-tokens.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/xxxx-directionless-pagination-tokens.md b/proposals/xxxx-directionless-pagination-tokens.md index bad182401c4..de256732878 100644 --- a/proposals/xxxx-directionless-pagination-tokens.md +++ b/proposals/xxxx-directionless-pagination-tokens.md @@ -49,10 +49,10 @@ The following table summarises which tokens each endpoint currently accepts and | Endpoint | Input | Currently accepts | Output | Change | |---|---|---|---|---| | `/sync` | `since` | Its own `next_batch` | `next_batch`, `prev_batch` | None | -| `/messages` | `from` | `/sync` (`prev_batch`/`next_batch`), itself (`end`), optionally itself (`start`) | `start`, `end` | `/sync`, `/messages`, `/relations`, `/context`, and `/search`'s `context | -| `/messages` | `to` | `/sync` (`prev_batch`/`next_batch`), itself (`end`) | — | `/sync`, `/messages`, `/relations`, `/context`, and `/search`'s `context | -| `/relations` | `from` | Itself, `/messages` (`start`), `/sync` (`next_batch`) | `next_batch`, `prev_batch` | `/sync`, `/messages`, `/relations`, `/context`, and `/search`'s `context | -| `/relations` | `to` | Itself, `/messages`, `/sync` (vague) | — | `/sync`, `/messages`, `/relations`, `/context`, and `/search`'s `context | +| `/messages` | `from` | `/sync` (`prev_batch`/`next_batch`), itself (`end`), optionally itself (`start`) | `start`, `end` | `/sync`, `/messages`, `/relations`, `/context`, and `/search`'s `context` | +| `/messages` | `to` | `/sync` (`prev_batch`/`next_batch`), itself (`end`) | — | `/sync`, `/messages`, `/relations`, `/context`, and `/search`'s `context` | +| `/relations` | `from` | Itself, `/messages` (`start`), `/sync` (`next_batch`) | `next_batch`, `prev_batch` | `/sync`, `/messages`, `/relations`, `/context`, and `/search`'s `context` | +| `/relations` | `to` | Itself, `/messages`, `/sync` (vague) | — | `/sync`, `/messages`, `/relations`, `/context`, and `/search`'s `context` | | `/context` | (none) | Output only | `start` ("backwards"), `end` ("forwards") | Remove directional language | | `/search` result | (none) | Output only | `start`, `end` (no directional language) | None | From a0cccb9f02c53f994fe946f3391c94a8ff574d1b Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Tue, 16 Jun 2026 17:28:01 -0400 Subject: [PATCH 4/8] Rename MSC --- ...nation-tokens.md => 4492-directionless-pagination-tokens.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename proposals/{xxxx-directionless-pagination-tokens.md => 4492-directionless-pagination-tokens.md} (99%) diff --git a/proposals/xxxx-directionless-pagination-tokens.md b/proposals/4492-directionless-pagination-tokens.md similarity index 99% rename from proposals/xxxx-directionless-pagination-tokens.md rename to proposals/4492-directionless-pagination-tokens.md index de256732878..c09fb70a59c 100644 --- a/proposals/xxxx-directionless-pagination-tokens.md +++ b/proposals/4492-directionless-pagination-tokens.md @@ -1,4 +1,4 @@ -# MSCXXXX: Clarify that pagination tokens are directionless +# MSC4492: Clarify that pagination tokens are directionless The Matrix client-server API has several endpoints which handle pagination over events: From 9c8e12fabd9ff71a62e7d9d779942a610caf1fdf Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Tue, 16 Jun 2026 17:31:43 -0400 Subject: [PATCH 5/8] Fix typos --- proposals/4492-directionless-pagination-tokens.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/4492-directionless-pagination-tokens.md b/proposals/4492-directionless-pagination-tokens.md index c09fb70a59c..81aaef90811 100644 --- a/proposals/4492-directionless-pagination-tokens.md +++ b/proposals/4492-directionless-pagination-tokens.md @@ -30,13 +30,13 @@ inherent direction, even if they happen to be labelled `next_batch` or ## Proposal Pagination tokens produced by `/messages`, `/relations`, `/context`, and `/search`'s -`context` field represent a position in the event stream and MUST be indistinguisable. +`context` field represent a position in the event stream and MUST be indistinguishable. Tokens SHOULD only be used within the context of a single room. (E.g. a request for `/messages` in room #test:matrix.org does not make sense to re-use for #foo:matrix.org.) A token produced by `/messages`, `/relations`, or `/context` is tied to the room it -was produced and clients MUST NOT be used for another room. There are no guarnatees +was produced and clients MUST NOT be used for another room. There are no guarantees using one in a different room will produce the correct results, servers MAY throw an error in this case. From c342075044dbcae9f400edc5ef9e2dfdd0e29476 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Wed, 17 Jun 2026 08:50:30 -0400 Subject: [PATCH 6/8] Apply suggestions from code review Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/4492-directionless-pagination-tokens.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/4492-directionless-pagination-tokens.md b/proposals/4492-directionless-pagination-tokens.md index 81aaef90811..750b0c6a2ad 100644 --- a/proposals/4492-directionless-pagination-tokens.md +++ b/proposals/4492-directionless-pagination-tokens.md @@ -35,9 +35,9 @@ Tokens SHOULD only be used within the context of a single room. (E.g. a request for `/messages` in room #test:matrix.org does not make sense to re-use for #foo:matrix.org.) -A token produced by `/messages`, `/relations`, or `/context` is tied to the room it -was produced and clients MUST NOT be used for another room. There are no guarantees -using one in a different room will produce the correct results, servers MAY throw +A token produced by `/messages`, `/relations`, `/context`, the `context` response field of `/search`, or the `prev_batch` response field of `/sync`, is tied to the room it +was produced for and clients MUST NOT use them for another room. There are no guarantees +using one in a different room will produce the correct results; servers MAY throw an error in this case. Tokens produced by [`/sync` `since` parameter][sync] resolve against the server's From 4bea7fdf5048afd0af6fdfe7d55fc7fce6fcf71a Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Wed, 17 Jun 2026 17:07:03 -0400 Subject: [PATCH 7/8] Clarify next_batch behavior Co-authored-by: Patrick Cloke --- proposals/4492-directionless-pagination-tokens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/4492-directionless-pagination-tokens.md b/proposals/4492-directionless-pagination-tokens.md index 750b0c6a2ad..c02543cda72 100644 --- a/proposals/4492-directionless-pagination-tokens.md +++ b/proposals/4492-directionless-pagination-tokens.md @@ -40,7 +40,7 @@ was produced for and clients MUST NOT use them for another room. There are no gu using one in a different room will produce the correct results; servers MAY throw an error in this case. -Tokens produced by [`/sync` `since` parameter][sync] resolve against the server's +`next_batch` tokens produced by [`/sync`][sync] resolve against the server's global event stream and is safe to use across rooms for `/messages`, `/relations`, and `/context`. `/sync` only accepts tokens produced by `/sync`. From 5979ee84d1cf1dd155e390296c2eef1439b23fc0 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Wed, 17 Jun 2026 17:14:37 -0400 Subject: [PATCH 8/8] Review comments and clarifications --- .../4492-directionless-pagination-tokens.md | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/proposals/4492-directionless-pagination-tokens.md b/proposals/4492-directionless-pagination-tokens.md index c02543cda72..81d43a299b0 100644 --- a/proposals/4492-directionless-pagination-tokens.md +++ b/proposals/4492-directionless-pagination-tokens.md @@ -29,20 +29,22 @@ inherent direction, even if they happen to be labelled `next_batch` or ## Proposal -Pagination tokens produced by `/messages`, `/relations`, `/context`, and `/search`'s -`context` field represent a position in the event stream and MUST be indistinguishable. -Tokens SHOULD -only be used within the context of a single room. (E.g. a request for `/messages` in -room #test:matrix.org does not make sense to re-use for #foo:matrix.org.) - -A token produced by `/messages`, `/relations`, `/context`, the `context` response field of `/search`, or the `prev_batch` response field of `/sync`, is tied to the room it -was produced for and clients MUST NOT use them for another room. There are no guarantees -using one in a different room will produce the correct results; servers MAY throw -an error in this case. +Pagination tokens produced by `/messages`, `/relations`, `/context`, the `context` +response field of `/search`, and the `prev_batch` response field of `/sync` represent +a posiiton in the event stream and MUST be indistinguishable. These tokens are referred +to as "room event stream tokens" in the rest of the proposal text. (Although it is not +proposed to use that term in the spec itself.) + +"Room event stream tokens" MUST only be used within the context of a single room. +(E.g. a request for `/messages` in room `#test:matrix.org` does not make sense to re-use +for `#foo:matrix.org`.) There are no guarantees using a "room event stream token" in a +different room will produce sensible results; servers MAY throw an error if a client attempts +to use one in the wrong room. `next_batch` tokens produced by [`/sync`][sync] resolve against the server's -global event stream and is safe to use across rooms for `/messages`, `/relations`, -and `/context`. `/sync` only accepts tokens produced by `/sync`. +global event stream and are safe to use in any room for `/messages`, `/relations`, +and `/context`. The `since` parameter of `/sync` only accepts `next_batch` tokens produced +by `/sync`. The following table summarises which tokens each endpoint currently accepts and proposed changes: @@ -59,7 +61,8 @@ The following table summarises which tokens each endpoint currently accepts and Note that this does not modify the pagination of `/search` results itself, which are only usable within `/search`. -Open question: should `/threads` also be part of this list? +This does not affect the pagination of any other endpoints, such as `/threads` or +[`/hierarchy`](hierarchy). ## Potential issues @@ -127,11 +130,13 @@ N/A N/A -[messages]: https://spec.matrix.org/latest/client-server-api/#get_matrixclientv3roomsroomidmessages -[sync]: https://spec.matrix.org/latest/client-server-api/#get_matrixclientv3sync -[relations]: https://spec.matrix.org/latest/client-server-api/#get_matrixclientv1roomsroomidrelationseventid -[context]: https://spec.matrix.org/latest/client-server-api/#get_matrixclientv3roomsroomidcontexteventid -[search]: https://spec.matrix.org/latest/client-server-api/#post_matrixclientv3search +[messages]: https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3roomsroomidmessages +[sync]: https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync +[relations]: https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv1roomsroomidrelationseventid +[context]: https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3roomsroomidcontexteventid +[search]: https://spec.matrix.org/v1.18/client-server-api/#post_matrixclientv3search +[threads]: https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv1roomsroomidthreads +[hierarchy]: https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv1roomsroomidhierarchy [spec2357]: https://github.com/matrix-org/matrix-spec/pull/2357