From 9c61e78e816255a1f79b852ec389ff76c1a4c849 Mon Sep 17 00:00:00 2001 From: Valerie Liu <79415174+ValwareIRC@users.noreply.github.com> Date: Sun, 17 May 2026 02:04:56 +0100 Subject: [PATCH 1/4] Introduce value concatenation semantics This goes towards solving problems that exist with ISUPPORT token values that have the potential to overflow the line limit. This came after a conversation on #ircv3 on Libera regarding `CLIENTTAGDENY`. While I will be recommending we take `CLIENTTAGDENY` another direction in another spec addendum, I still think this goes towards solving other problems that may come up in future, like with `draft/FILEHOST` which expects a URL which technically can be thousands of bytes long, and just makes 005 a bit unsuitable for that kind of stuff. I'd like to both try to solve this with concatenation logic as well as still suggest moving some things out of ISUPPORT altogether in a separate PR. --- extensions/extended-isupport.md | 86 +++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/extensions/extended-isupport.md b/extensions/extended-isupport.md index 7936e1dbd..4528cb7ab 100644 --- a/extensions/extended-isupport.md +++ b/extensions/extended-isupport.md @@ -7,6 +7,10 @@ copyrights: name: "Simon Ser" period: "2024" email: "contact@emersion.fr" + - + name: "Valerie Pond" + period: "2026" + email: "v.a.pond@outlook.com" --- ## Notes for implementing work-in-progress version @@ -29,6 +33,12 @@ extension adds a mechanism to send `RPL_ISUPPORT` messages before connection registration, as well as a dedicated command to request the `ISUPPORT` list and a batch for `RPL_ISUPPORT` messages. +Additionally, the standard `RPL_ISUPPORT` semantics treat a repeated token as +a replacement, not an extension, which combined with the 512-byte line limit +bounds the size of any single token's value at roughly 400 bytes. This +extension defines an opt-in append form (`KEY+=value`) for list-valued tokens +that allows a server to deliver a value across multiple lines. + ## Implementation ### `ISUPPORT` command @@ -71,6 +81,67 @@ contain any other message. As usual, servers can update or delete existing values by sending additional `RPL_ISUPPORT` messages in a `draft/isupport` batch after the initial batch. +### Append syntax for list-valued tokens + +When the `draft/extended-isupport` capability is enabled, the syntax of an +`RPL_ISUPPORT` token is extended to: + + token = ( key "+=" value ) ; append form + / ( key "=" value ) ; replacement form + / ( key ) ; flag form + / ( "-" key ) ; deletion form + +The `+=` delimiter is treated atomically and MUST NOT be split across two +tokens. + +The append form is defined as byte-wise concatenation. The client +performs no interpretation of either the current value or the appended +chunk; it simply appends the bytes of `value` to whatever bytes are +currently held for `key`. Any structural delimiter required by the +token's grammar (such as a separating comma) MUST be included by the +server inside the appended `value`. To extend a non-empty +comma-separated list, for example, the server sends the appended chunk +with a leading comma: + + KEY=foo,bar,baz + KEY+=,qux,quux,corge + +producing the final value `foo,bar,baz,qux,quux,corge`. + +The `+=` form has meaning only for `RPL_ISUPPORT` tokens whose value +grammar is explicitly defined to permit it. A token specification that +wishes to permit `+=` MUST state so explicitly, and MAY constrain +behaviour beyond byte-wise concatenation (for example, the semantics of +appending an element that is already present, or how wildcard or +exclusion markers in the token's grammar combine across appended +chunks). + +For tokens whose specification does not permit `+=`, a server MUST NOT +send the `+=` form. A client receiving `+=` for a token whose grammar is +unknown to it, or whose specification does not permit `+=`, SHOULD ignore +the append; it MUST NOT interpret it as a replacement. + +Processing rules apply token-by-token to the value the client currently +holds: + +- `KEY=value` sets the value to `value`, replacing any prior value. +- `KEY+=value` sets the value to the byte-wise concatenation of the + current value and `value`. If no value is currently held (the token has + not been advertised in this session, or was deleted), the result is + simply `value`; the server is responsible for emitting the appended + chunk without a leading separator in that case. +- `-KEY` removes the value entirely; a subsequent `KEY+=value` then + behaves as in the unset case above. +- `KEY+=` (append form with an empty value) is a no-op. + +Multiple `+=` tokens for the same key MAY appear within a single +`RPL_ISUPPORT` reply, across multiple replies, and across batches. The +order of concatenation is the order in which the tokens are received. + +A server that can fit a token's value in a single `RPL_ISUPPORT` line +SHOULD continue to use the plain `=` form. A server MUST NOT use `+=` to +clients that have not negotiated `draft/extended-isupport`. + ## Examples Enabling the capability: @@ -94,4 +165,19 @@ Sending a change: S: @batch=asdf :irc.example.org 005 * CHANNELLEN=64 NICKLEN=42 -FOO S: :irc.example.org BATCH -asdf +Delivering a list-valued token (here a hypothetical `EXAMPLELIST`) across +two lines using the append form. Note the leading comma on the appended +chunk: the server is responsible for emitting any separator required by +the token's grammar. + + S: :irc.example.org BATCH +xyz draft/isupport + S: @batch=xyz :irc.example.org 005 * EXAMPLELIST=foo,bar,baz + S: @batch=xyz :irc.example.org 005 * EXAMPLELIST+=,qux,quux,corge + S: :irc.example.org BATCH -xyz + +The resulting value held by the client is `foo,bar,baz,qux,quux,corge`. A +later plain `=` resets the accumulation; a later `-EXAMPLELIST` clears +it. If `EXAMPLELIST` were unset (or had just been deleted), the first +chunk would use `=` without a leading separator: `EXAMPLELIST=qux,...`. + [batch]: ../extensions/batch.html From 3e646117132b1dc663acff7be44fe2d1a0d21c33 Mon Sep 17 00:00:00 2001 From: Valerie Liu <79415174+ValwareIRC@users.noreply.github.com> Date: Sun, 17 May 2026 02:10:30 +0100 Subject: [PATCH 2/4] Actually we don't care about starting off with separators Separators are none of our business --- extensions/extended-isupport.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/extensions/extended-isupport.md b/extensions/extended-isupport.md index 4528cb7ab..b5a8add90 100644 --- a/extensions/extended-isupport.md +++ b/extensions/extended-isupport.md @@ -128,8 +128,8 @@ holds: - `KEY+=value` sets the value to the byte-wise concatenation of the current value and `value`. If no value is currently held (the token has not been advertised in this session, or was deleted), the result is - simply `value`; the server is responsible for emitting the appended - chunk without a leading separator in that case. + simply `value`. Whether the resulting bytes form a well-formed value + for the token is the token specification's concern, not this one's. - `-KEY` removes the value entirely; a subsequent `KEY+=value` then behaves as in the unset case above. - `KEY+=` (append form with an empty value) is a no-op. @@ -177,7 +177,6 @@ the token's grammar. The resulting value held by the client is `foo,bar,baz,qux,quux,corge`. A later plain `=` resets the accumulation; a later `-EXAMPLELIST` clears -it. If `EXAMPLELIST` were unset (or had just been deleted), the first -chunk would use `=` without a leading separator: `EXAMPLELIST=qux,...`. +it. [batch]: ../extensions/batch.html From e257bf8d27c56b2abb0a960aec90ea59f5a5d159 Mon Sep 17 00:00:00 2001 From: Valerie Liu <79415174+ValwareIRC@users.noreply.github.com> Date: Sun, 17 May 2026 02:16:08 +0100 Subject: [PATCH 3/4] remembered `+` isn't valid in ISUPPORT key names anyway so this was redundant --- extensions/extended-isupport.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/extensions/extended-isupport.md b/extensions/extended-isupport.md index b5a8add90..fb607d9f0 100644 --- a/extensions/extended-isupport.md +++ b/extensions/extended-isupport.md @@ -91,8 +91,6 @@ When the `draft/extended-isupport` capability is enabled, the syntax of an / ( key ) ; flag form / ( "-" key ) ; deletion form -The `+=` delimiter is treated atomically and MUST NOT be split across two -tokens. The append form is defined as byte-wise concatenation. The client performs no interpretation of either the current value or the appended From 15434f27fa5ec1594d4309cea46b576cf46cae2c Mon Sep 17 00:00:00 2001 From: Valerie Liu <79415174+ValwareIRC@users.noreply.github.com> Date: Sun, 17 May 2026 11:52:02 +0100 Subject: [PATCH 4/4] Bump draft cap version so we don't break clients --- extensions/extended-isupport.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/extensions/extended-isupport.md b/extensions/extended-isupport.md index fb607d9f0..116035eda 100644 --- a/extensions/extended-isupport.md +++ b/extensions/extended-isupport.md @@ -18,10 +18,11 @@ copyrights: This is a work-in-progress specification. Software implementing this work-in-progress specification MUST NOT use the -unprefixed `extended-isupport` capability name. Instead, implementations SHOULD -use the `draft/extended-isupport` capability name to be interoperable with -other software implementing a compatible work-in-progress version. The final -version of the specification will use unprefixed capability names. +unprefixed `extended-isupport` capability name or `isupport` batch name. +Instead, implementations SHOULD use the `draft/extended-isupport-0.2` +capability name and the `draft/isupport` batch name to be interoperable +with other software implementing a compatible work-in-progress version. +The final version of the specification will use unprefixed names. ## Introduction @@ -46,16 +47,16 @@ that allows a server to deliver a value across multiple lines. A new `ISUPPORT` command is introduced to request the full `RPL_ISUPPORT` list. When receiving this command, the server MUST reply with one or more `RPL_ISUPPORT` messages (grouped inside a `draft/isupport` batch if the `batch` -and `draft/extended-isupport` capabilities are enabled, see below). +and `draft/extended-isupport-0.2` capabilities are enabled, see below). -### `draft/extended-isupport` capability +### `draft/extended-isupport-0.2` capability -When the `draft/extended-isupport` capability is enabled by the client, the +When the `draft/extended-isupport-0.2` capability is enabled by the client, the server MUST accept `ISUPPORT` commands before connection registration completes (ie, before the client sends `CAP END`, and before the server sends `RPL_WELCOME`). -Before connection registration completes, while `draft/extended-isupport` is +Before connection registration completes, while `draft/extended-isupport-0.2` is enabled, the server MAY send updates to the key-value entries via subsequent `RPL_ISUPPORT` messages (the same way it would after connection registration completes without this extension). @@ -70,7 +71,7 @@ when connection registration completes with entries previously omitted. ### `draft/isupport` batch The server MUST group all `RPL_ISUPPORT` messages inside a `draft/isupport` -batch when the [`batch`][batch] and `draft/extended-isupport` capabilities are +batch when the [`batch`][batch] and `draft/extended-isupport-0.2` capabilities are enabled. The server MUST NOT send any unbatched `RPL_ISUPPORT` message while both of these capabilities are enabled. The order in which the capabilities are enabled is not significant. @@ -83,7 +84,7 @@ As usual, servers can update or delete existing values by sending additional ### Append syntax for list-valued tokens -When the `draft/extended-isupport` capability is enabled, the syntax of an +When the `draft/extended-isupport-0.2` capability is enabled, the syntax of an `RPL_ISUPPORT` token is extended to: token = ( key "+=" value ) ; append form @@ -91,7 +92,6 @@ When the `draft/extended-isupport` capability is enabled, the syntax of an / ( key ) ; flag form / ( "-" key ) ; deletion form - The append form is defined as byte-wise concatenation. The client performs no interpretation of either the current value or the appended chunk; it simply appends the bytes of `value` to whatever bytes are @@ -138,16 +138,16 @@ order of concatenation is the order in which the tokens are received. A server that can fit a token's value in a single `RPL_ISUPPORT` line SHOULD continue to use the plain `=` form. A server MUST NOT use `+=` to -clients that have not negotiated `draft/extended-isupport`. +clients that have not negotiated `draft/extended-isupport-0.2`. ## Examples Enabling the capability: C: CAP LS 302 - S: :irc.example.org CAP * LS :multi-prefix sasl batch draft/extended-isupport - C: CAP REQ batch draft/extended-isupport - S: :irc.example.org CAP * ACK :batch draft/extended-isupport + S: :irc.example.org CAP * LS :multi-prefix sasl batch draft/extended-isupport-0.2 + C: CAP REQ batch draft/extended-isupport-0.2 + S: :irc.example.org CAP * ACK :batch draft/extended-isupport-0.2 C: ISUPPORT S: :irc.example.org BATCH +asdf draft/isupport S: @batch=asdf :irc.example.org 005 * NETWORK=Example NICKLEN=30 FOO=bar