From f2e0dcdbebd4467bb738a64d51d2be119352a40e Mon Sep 17 00:00:00 2001 From: Simon Woolf Date: Sat, 3 Oct 2026 20:11:23 +0100 Subject: [PATCH 1/2] RTL4m1: decode the subscribe mode flag as MESSAGE_SUBSCRIBE TR3s SUBSCRIBE and TR3u MESSAGE_SUBSCRIBE share a flag value, so RTL4m didn't say which one an SDK should report in RealtimeChannel.modes. Specify the preferred variant, and update the RTL4m UTS test to match. Co-Authored-By: Claude Opus 5.5 (1M context) --- specifications/features.md | 1 + uts/realtime/unit/channels/channel_attach.md | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/specifications/features.md b/specifications/features.md index b64dffae1..a3bdbe64f 100644 --- a/specifications/features.md +++ b/specifications/features.md @@ -723,6 +723,7 @@ The threading and/or asynchronous model for each realtime library will vary by l - `(RTL4k1)` If any channel parameters are requested (which may be through the `params` field of the `ATTACH` message or some other way opaque to the client library), the `ATTACHED` (and any subsequent `ATTACHED` s) will include a `params` property (also a `Dict`) containing the subset of those params that the server has recognised and validated. This should be exposed as a read-only `params` field of the `RealtimeChannel` (or a `getParams()` method where that is more idiomatic). An `ATTACHED` message with no `params` property must be treated as equivalent to a `params` of `{}` (that is, `RealtimeChannel.params` should be set to the empty dict) - `(RTL4l)` If the user has specified a `modes` array in the `ChannelOptions` ([`TB2d`](#TB2d)), it must be encoded as a bitfield per [`TR3`](#TR3) and set as the `flags` field of the `ATTACH` `ProtocolMessage`. (For the avoidance of doubt, when multiple different spec items require flags to be set in the `ATTACH`, the final `flags` field should be the bitwise OR of them all) - `(RTL4m)` On receipt of an `ATTACHED`, the client library should decode the `flags` into an array of `ChannelMode` s (that is, the same format as `ChannelOptions.modes`) and expose it as a read-only `modes` field of the `RealtimeChannel` (or a `getModes()` method where that is more idiomatic). This should only contain `ChannelMode` s: it should not contain flags which are not modes (see [`TB2d`](#TB2d)) + - `(RTL4m1)` Where more than one `ChannelMode` corresponds to the same flag, the `modes` array must contain only the variant that [`TR3`](#TR3) marks as preferred. For example, the flag shared by [`TR3s`](#TR3s) `SUBSCRIBE` and [`TR3u`](#TR3u) `MESSAGE_SUBSCRIBE` must be decoded as `MESSAGE_SUBSCRIBE` - `(RTL5)` `RealtimeChannel#detach` function: - `(RTL5a)` If the channel state is `INITIALIZED` or `DETACHED` nothing is done - `(RTL5i)` If the channel is in a pending state `DETACHING` or `ATTACHING`, do the detach operation after the completion of the pending request diff --git a/uts/realtime/unit/channels/channel_attach.md b/uts/realtime/unit/channels/channel_attach.md index 1cbe5b286..43026c414 100644 --- a/uts/realtime/unit/channels/channel_attach.md +++ b/uts/realtime/unit/channels/channel_attach.md @@ -1,6 +1,6 @@ # RealtimeChannel Attach Tests -Spec points: `RTL4`, `RTL4a`, `RTL4b`, `RTL4c`, `RTL4c1`, `RTL4f`, `RTL4g`, `RTL4h`, `RTL4i`, `RTL4j`, `RTL4k`, `RTL4l`, `RTL4m` +Spec points: `RTL4`, `RTL4a`, `RTL4b`, `RTL4c`, `RTL4c1`, `RTL4f`, `RTL4g`, `RTL4h`, `RTL4i`, `RTL4j`, `RTL4k`, `RTL4l`, `RTL4m`, `RTL4m1` ## Test Type Unit test with mocked WebSocket @@ -859,9 +859,9 @@ CLOSE_CLIENT(client) **Test ID**: `realtime/unit/RTL4m/modes-from-attached-0` -**Spec requirement:** On receipt of an ATTACHED, the client library should decode the flags into an array of ChannelModes and expose it as a read-only modes field. +**Spec requirement:** On receipt of an ATTACHED, the client library should decode the flags into an array of ChannelModes and expose it as a read-only modes field. A flag with more than one ChannelMode name is decoded as the preferred one (RTL4m1). -Tests that modes are decoded from ATTACHED flags. +Tests that modes are decoded from ATTACHED flags, with the TR3s/TR3u flag decoded as `MESSAGE_SUBSCRIBE` rather than `SUBSCRIBE`. ### Setup ```pseudo @@ -874,7 +874,7 @@ mock_ws = MockWebSocket( mock_ws.send_to_client(ProtocolMessage( action: ATTACHED, channel: channel_name, - flags: 393216 # PUBLISH (131072, TR3r) + SUBSCRIBE (262144, TR3s) + flags: 393216 # PUBLISH (131072, TR3r) + MESSAGE_SUBSCRIBE (262144, TR3u) )) } ) @@ -896,7 +896,7 @@ AWAIT channel.attach() ```pseudo ASSERT channel.modes IS NOT null ASSERT ChannelMode.publish IN channel.modes -ASSERT ChannelMode.subscribe IN channel.modes +ASSERT ChannelMode.message_subscribe IN channel.modes CLOSE_CLIENT(client) ``` From eb2a2b6a9627b967ae1e8b553b352cc6d8dfafbc Mon Sep 17 00:00:00 2001 From: Simon Woolf Date: Sat, 3 Oct 2026 20:11:23 +0100 Subject: [PATCH 2/2] Add MESSAGE_SUBSCRIBE to ChannelMode docstrings Follows up the TR3u rename, which updated features.md but not the docstrings. Co-Authored-By: Claude Opus 5.5 (1M context) --- specifications/api-docstrings.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/specifications/api-docstrings.md b/specifications/api-docstrings.md index b578f901b..ce6cf5780 100644 --- a/specifications/api-docstrings.md +++ b/specifications/api-docstrings.md @@ -495,7 +495,8 @@ Describes the possible flags used to configure client capabilities, using [`Chan |---|---|---| | PRESENCE || The client can enter the presence set. | | PUBLISH || The client can publish messages. | -| SUBSCRIBE || The client can subscribe to messages. | +| MESSAGE_SUBSCRIBE || The client can subscribe to messages. | +| SUBSCRIBE || The client can subscribe to messages. Synonymous with [`MESSAGE_SUBSCRIBE`]{@link ChannelMode#MESSAGE_SUBSCRIBE}, which should be preferred. | | PRESENCE_SUBSCRIBE || The client can receive presence messages. | | OBJECT_PUBLISH || The client can publish object messages. | | OBJECT_SUBSCRIBE || The client can receive object messages. | @@ -572,7 +573,7 @@ Contains the metrics associated with a [`RestChannel`]{@link RestChannel} or [`R | presenceMembers: Int ||| CHM2c | The number of members in the presence set of the channel. | | presenceSubscribers: Int ||| CHM2d | The number of realtime attachments receiving presence messages on the channel. This requires the `subscribe` capability and for a client to not have specified a [`ChannelMode`]{@link ChannelMode} flag that excludes [`PRESENCE_SUBSCRIBE`]{@link ChannelMode#PRESENCE_SUBSCRIBE}. | | publishers: Int ||| CHM2e | The number of realtime attachments permitted to publish messages to the channel. This requires the `publish` capability and for a client to not have specified a [`ChannelMode`]{@link ChannelMode} flag that excludes [`PUBLISH`]{@link ChannelMode#PUBLISH}. | -| subscribers: Int ||| CHM2f | The number of realtime attachments receiving messages on the channel. This requires the `subscribe` capability and for a client to not have specified a [`ChannelMode`]{@link ChannelMode} flag that excludes [`SUBSCRIBE`]{@link ChannelMode#SUBSCRIBE}. | +| subscribers: Int ||| CHM2f | The number of realtime attachments receiving messages on the channel. This requires the `subscribe` capability and for a client to not have specified a [`ChannelMode`]{@link ChannelMode} flag that excludes [`MESSAGE_SUBSCRIBE`]{@link ChannelMode#MESSAGE_SUBSCRIBE}. | | objectPublishers: Int ||| CHM2g | The number of realtime attachments permitted to publish object messages to the channel. This requires the `object-publish` capability and for a client to have specified a [`ChannelMode`]{@link ChannelMode} flag that includes [`OBJECT_PUBLISH`]{@link ChannelMode#OBJECT_PUBLISH}. | | objectSubscribers: Int ||| CHM2h | The number of realtime attachments receiving object messages on the channel. This requires the `object-subscribe` capability and for a client to have specified a [`ChannelMode`]{@link ChannelMode} flag that includes [`OBJECT_SUBSCRIBE`]{@link ChannelMode#OBJECT_SUBSCRIBE}. |