jiebi/TextFlow huggingface dataset:
Original text:
HTTP/3 endpoints contain a QPACK encoder and decoder.  Each endpoint MUST initiate at most one encoder stream and at most one decoder stream.  Receipt of a second instance of either stream type MUST be <del> treated as a connection error of type HTTP_WRONG_STREAM_COUNT.  These streams MUST NOT be closed.  Closure of either unidirectional stream type MUST be treated as a connection error of type </del>  HTTP_CLOSED_CRITICAL_STREAM. An endpoint MAY avoid creating its own encoder stream if it's not

Reviewer comments:
On receiving duplicate QPACK streams, the error should be HTTPSTREAMCREATION_ERROR which matches with control stream duplicates.
Technically should have a corresponding issue, but yes. Nice spot!

Revised text:
HTTP/3 endpoints contain a QPACK encoder and decoder.  Each endpoint MUST initiate at most one encoder stream and at most one decoder stream.  Receipt of a second instance of either stream type MUST be  <ins> treated as a connection error of type HTTP_STREAM_CREATION_ERROR. These streams MUST NOT be closed.  Closure of either unidirectional stream type MUST be treated as a connection error of type </ins> HTTP_CLOSED_CRITICAL_STREAM. An endpoint MAY avoid creating its own encoder stream if it's not
Original text:
transport parameter is only sent by a server.  Servers MAY choose to only send a preferred address of one address family by sending an all-zero address and port (0.0.0.0:0 or ::.0) for the other <del> family. </del>  The maximum number of connection IDs from the peer that an endpoint is willing to store.  This value includes only connection

Reviewer comments:
Byte order of IP addresses in PreferredAddress is not explicitly stated. In practice, most OSs keep them in network byte order, and the spec says integers are in network byte order, however the fields for ip addresses are defined as opaque data. The byte order should be stated on this spec.

Revised text:
transport parameter is only sent by a server.  Servers MAY choose to only send a preferred address of one address family by sending an all-zero address and port (0.0.0.0:0 or ::.0) for the other  <ins> family.  IP addresses are encoded in network byte order. </ins> The maximum number of connection IDs from the peer that an endpoint is willing to store.  This value includes only connection
Original text:
values, which might be used to link connection attempts; see validate-future.  19.8. STREAM frames implicitly create a stream and carry stream data.  The

Reviewer comments:
This doesn't add rationale. It doesn't have to. The rationale isn't high-minded, it's just motivated by a desire to complete this protocol.
Should the server just ignore it, or is is a protocol violation?
I vote for protocol violation.
The spec says nothing...
Yeah, there's no need to vote, this is just an omission. A protocol violation (or similar) is what we should mandate.
Playing devils' advocate: what about p2p apps? The token says, you can call me back from that address, I will accept it. The client is not saying anything untrue.
I'll bite. Yes, a P2P app that used mutual authentication in a way that would allow a former server to associate a token with an attempt to connect to a peer that was previously a client, might be able to use NEW_TOKEN. That's a little outside our remit. I'm going to take this as an editorial change on the understanding that a design issue could be opened to allow the asymmetry. Anyone who is serious about that should also consider the fact that NewSessionTicket in TLS is potentially symmetrical by the same logic. Which suggests that 0-RTT isn't out of the question either.
On p2p there is the potential problem of relating a token to previously stored settings and observables from a previous session. This isn't well defined if the client specifies a new token. So perhaps it is better for each peer to "waste" a single 1-RTT connection the first time in a given direction.

Revised text:
values, which might be used to link connection attempts; see validate-future. <ins> Clients MUST NOT send NEW_TOKEN frames.  Servers MUST treat receipt of a NEW_TOKEN frame as a connection error of type PROTOCOL_VIOLATION. </ins> 19.8. STREAM frames implicitly create a stream and carry stream data.  The
Original text:
Retry packets (packet-retry), Version Negotiation packets (packet- version), and packets with a short header (short-header) do not contain a Length field and so cannot be followed by other packets in <del> the same UDP datagram. </del>  12.3.

Reviewer comments:
They don't have a length field, so the only place they could go is at the end of a packet. As the spec currently stands, it's valid to send a packet like this. There's little value in doing that. Do we want to continue to allow this?
My understanding is that they are implicitly forbidden, because coalescing packets belonging to different connections are forbidden, and because there’s nothing to coalesce with when either of the two types of the packets is sent. I am not sure if we need to be more clear on that, considering the fact we generally use MAY for the discarding rules for coalesced packets.
VN certainly causes a new connection based on discussions in Tokyo. Retry does not cause a new connection(ie: same ClientHello). Clarifying this seems wise if it's not already clear.
Yes, however when a Retry packet is being sent, there's nothing a server can send along with. Regarding if we need to clarify, while I do not think it's absolutely necessary, I can see that people might want to have it stated considering the fact that we do utilize corner case rules of coalesced packets (see ).
So, is this editorial?
I'm with NAME but I'm still wondering: what is the clarification that we can provide?
NAME Simply clarifying that "VN and Retry packets will never be coalesced" as part of the changes we would make in might be a good idea. We do not need to use a RFC 2119 word here due to the editorial nature of the issue.

Revised text:
Retry packets (packet-retry), Version Negotiation packets (packet- version), and packets with a short header (short-header) do not contain a Length field and so cannot be followed by other packets in  <ins> the same UDP datagram.  Note also that there is no situation where a Retry or Version Negotiation packet is coalesced with another packet. </ins> 12.3.
Original text:
described in more detail in QUIC-TRANSPORT.  An endpoint MAY choose to treat a stream error as a connection error.  This section describes HTTP/3-specific error codes which can be used to express the cause of a connection or stream error.

Reviewer comments:
by saying that, since error codes are extensible, you can't treat the receipt of an error code you don't understand or don't think you should have gotten as an error itself. (Though it can still be an error that the stream closed, regardless of the error code.) (Which leads to the question, should we be greasing the error code space?)
Yes! I would create a grease stream and it could be closed (stop sending and/or reset) by peers.
That seems to have very narrow applicability. Would you only be permitted to send a greasing error code in that case? Or to put the question differently, what would happen if you decided to randomly turn a subset of the semantic-ful error codes you generate into greasing codes?
Per the language of this PR, I think that would be fine. Possibly with the exception of the errors that are supposed to inform behavior, like REJECTED and perhaps EARLYRESPONSE.
The HTTP/3 spec is a little light on detail about processing an error code that should have never been sent. At NAME suggestion, this issue is scoped to discussion of HTTP/3 stream errors: Example a) a client receives a STOPSENDING with HTTPREQUESTCANCELLED Example b) a server receives a RESETSTREAM with HTTPLIMITEXCEEDED
I'm mostly inclined to treat this with the same fatalism as an invalid code in an APPLICATIONCLOSE code that makes no sense. The stream is gone, regardless of the error code. If it was a critical stream, then CLOSEDCRITICALSTREAM; otherwise, perhaps a MAY GENERALPROTOCOL_ERROR?
I agree with NAME The error code doesn't matter. What matters is how you handle it. Error codes with no specific handling are fine; error codes with special handling can be ignored. The question of what to do with critical streams is separable. Don't make things worse by coupling the two concepts.
Oh, totally separable. But then you'd then have two competing permissions-to-blow up -- because the critical stream close (regardless of error code) and because a stream closed with an invalid error code (regardless of which stream). And I don't think it matters which reason you have to blow up or what the resulting error is.

Revised text:
described in more detail in QUIC-TRANSPORT.  An endpoint MAY choose to treat a stream error as a connection error. <ins> Because new error codes can be defined without negotiation (see extensions), receipt of an unknown error code or use of an error code in an unexpected context MUST NOT be treated as an error.  However, closing a stream can constitute an error regardless of the error code (see request-response). </ins> This section describes HTTP/3-specific error codes which can be used to express the cause of a connection or stream error.
Original text:
TBD.  8. 8.1.

Reviewer comments:
with some text in the TBD Security Considerations section.
If I understand correctly, the decoder stream buffer which endpoint has to keep grows indefinitely if encoder-side app does not return back flow control credit. The number of Header Acknowledgement instruction is bounded by the number of max blocked streams which decoder can specify. On the other hand, the number of Stream Cancellation is not bounded. So if encoder-side app keeps resetting stream without sending MAXSTREAMDATA, decoder-side has to keep all closed stream in decoder stream. I'm not sure this has been discussed already.
The solution to this seems implementation-dependent, but implementations should place a bound on the amount of data waiting to be sent on the decoder stream.
Hypothetically, this limit would create a way to force the peer to kill the connection by starving the decoder stream of flow control credit and then cancelling lots of streams. However, the consumer of (and therefore the entity which could fail to read) the decoder stream is the encoder, and the encoder can trivially cause the connection to close by emitting an invalid instruction anyway. That seems fine.
NAME writes: This is incorrect: an for each header that references the dynamic table.

Revised text:
TBD. <ins> While the negotiated limit on the dynamic table size accounts for much of the memory that can be consumed by a QPACK implementation, data which cannot be immediately sent due to flow control is not affected by this limit.  Implementations should limit the size of unsent data, especially on the decoder stream where flexibility to choose what to send is limited.  Possible responses to an excess of unsent data might include limiting the ability of the peer to open new streams, reading only from the encoder stream, or closing the connection. </ins> 8. 8.1.
Original text:
9.3. <del> Header protection relies on the packet protection AEAD being a pseudorandom function (PRF), which is not a property that AEAD algorithms guarantee.  Therefore, no strong assurances about the general security of this mechanism can be shown in the general case. The AEAD algorithms described in this document are assumed to be PRFs. The header protection algorithms defined in this document take the form: This construction is secure against chosen plaintext attacks (IND- CPA) IMC. </del>  Use of the same key and ciphertext sample more than once risks compromising header protection.  Protecting two different headers

Reviewer comments:
This paper studies several "nonce hiding" transformations, of which the QUIC header protection algorithm is one. This change replaces the old analysis text with something a bit more crisp.
I'm really happy to see good research on this that confirms our intuitions about one of the most important QUIC-specific constructions. Thanks for doing this Chris. Are you planning to make a similar contribution to DTLS 1.3?
My pleasure. :-) Yep!

Revised text:
9.3.  <ins> NAN analyzes authenticated encryption algorithms which provide nonce privacy, referred to as "Hide Nonce" (HN) transforms.  The general header protection construction in this document is one of those algorithms (HN1).  Header protection uses the output of the packet protection AEAD to derive "sample", and then encrypts the header field using a pseudorandom function (PRF) as follows: The header protection variants in this document use a pseudorandom permutation (PRP) in place of a generic PRF.  However, since all PRPs are also PRFs IMC, these variants do not deviate from the HN1 construction. As "hp_key" is distinct from the packet protection key, it follows that header protection achieves AE2 security as defined in NAN and therefore guarantees privacy of "field", the protected packet header. Future header protection variants based on this construction MUST use a PRF to ensure equivalent security guarantees. </ins> Use of the same key and ciphertext sample more than once risks compromising header protection.  Protecting two different headers
Original text:
packet in the datagram. Every QUIC packet that is coalesced into a single UDP datagram is <del> separate and complete.  Though the values of some fields in the packet header might be redundant, no fields are omitted.  The receiver of coalesced QUIC packets MUST individually process each QUIC packet and separately acknowledge them, as if they were received as the payload of different UDP datagrams.  For example, if decryption fails (because the keys are not available or any other reason), the receiver MAY either discard or buffer the packet for later processing and MUST attempt to process the remaining packets. </del>  Retry packets (packet-retry), Version Negotiation packets (packet- version), and packets with a short header (short-header) do not

Reviewer comments:
At the top of page 66 of the , we read: The second sentence seems to imply that a field could be omitted. Does this sentence sound odd to anyone else?
While it is perhaps technically redundant, I think it is actually quite helpful. The first sentence says, "complete" but that might be open to interpretation. The second sentence makes it clear what that means. I like it. YMMV :)
My issue is not with the redundancy of the second senteance, but rather with its meaning. The specification that "no fields be omitted" implies that fields could be omitted -- but they can't be: There are no optional fields in packet headers.
Maybe change the second sentence to something like:
NAME writes: The third sentence clarifies the first sentence well, too. I would just drop the second sentence altogether.
I can't remember now, but we did have an intermediate design where redundant fields were absent. This sentence may have crept in around then. I agree with NAME : it does seem redundant now.

Revised text:
packet in the datagram. Every QUIC packet that is coalesced into a single UDP datagram is  <ins> separate and complete.  The receiver of coalesced QUIC packets MUST individually process each QUIC packet and separately acknowledge them, as if they were received as the payload of different UDP datagrams.  For example, if decryption fails (because the keys are not available or any other reason), the receiver MAY either discard or buffer the packet for later processing and MUST attempt to process the remaining packets. </ins> Retry packets (packet-retry), Version Negotiation packets (packet- version), and packets with a short header (short-header) do not
Original text:
to authenticate when requested.  The requirements for client authentication vary based on application protocol and deployment. <del> A server MUST NOT use post-handshake client authentication (see Section 4.6.2 of TLS13). </del>  4.5.

Reviewer comments:
Add short explanation and reference to explain why QUIC-TLS bans the use of post-handshake client authentication.
draft-tls section 4.4 (Peer Authentication) states: This sounds like there are security implications, but what they are is unclear. As a reader of the document, this makes me doubt my understanding of the protocol. If we don't have a good justification for banning this, we shouldn't be banning it. (This is me reopening since that was closed for being a question.)
Is the text unclear, or are you asking to re-enable post-handshake authentication?
At least I am curious about the reasoning behind this, not that I am against it.
NAME The best way to understand the rationale is to try to work through how a particular protocol might use this feature. Read , look at the design and discussion and see the sorts of problems it tries to address. In that case, some of the problems are with server-authentication, which you can safely ignore, but the general class of problems related to concurrency and how that relates to the status of authentication produce a fairly complex design. Now I might concede that it is possible to build a protocol that uses this TLS feature well, but I would still hold that are a far superior design.
NAME Thanks for the explantion and pointers. On exported authenticators I guess there is some overlap with OAuth2, Fido, and temporary web service tokens once you get past the handshake.
NAME if we have a good reason (which it sounds like we do), then this issue tracks adding that reason to the draft.
Now that NAME has clearly written this up, perhaps we can resolve this issue by adding a reference to URL in draft-ietf-quic-tls. If that sounds good to the editors I can write a PR.
I'd prefer more direct text. You get references to HTTP/2 doc and that in turn references TLS 1.2 with compression rules etc. that needs to be filtered out.
NAME : that sounds like a good way forward.
I'm going to say that this is editorial-enough to just merge. MUST NOT implies PROTOCOL_VIOLATION, so the new normative language is fine as editorial. I'll give others a chance to disagree though.

Revised text:
to authenticate when requested.  The requirements for client authentication vary based on application protocol and deployment.  <ins> A server MUST NOT use post-handshake client authentication (as defined in Section 4.6.2 of TLS13), because the multiplexing offered by QUIC prevents clients from correlating the certificate request with the application-level event that triggered it (see HTTP2-TLS13). More specifically, servers MUST NOT send post-handshake TLS CertificateRequest messages and clients MUST treat receipt of such messages as a connection error of type PROTOCOL_VIOLATION. </ins> 4.5.
Original text:
stream.  Once an endpoint sends a RESET_STREAM frame, no further STREAM frames are needed. <del> The most recent set of acknowledgments are sent in ACK frames.  An ACK frame SHOULD contain all unacknowledged acknowledgments, as described in sending-acknowledgements. </del>  Cancellation of stream transmission, as carried in a RESET_STREAM frame, is sent until acknowledged or until all stream data is

Reviewer comments:
It can result in an inflated RTT, as well as being a waste of bytes.
Even though a sender is encouraged to assemble frames containing up-to-date information every time it sends a packet, it is not forbidden to retransmit copies of frames from lost packets. A receiver MUST accept packets containing an outdated frame, such as a MAX_DATA frame carrying a smaller maximum data than one found in an older packet. URL If a packet containing an ACK is lost and the payload is retransmitted with a new packet number AND no ACKs are received prior to the retransmitted ACK frame arriving, the peer will calculate and RTT sample that is 2 RTTs + loss recovery delay. As such, I'd suggest we add a warning that retransmitting ACKs can cause RTT inflation and is heavily discouraged. There may be other issues with retransmitting ACKs, but this is the first that comes to mind.

Revised text:
stream.  Once an endpoint sends a RESET_STREAM frame, no further STREAM frames are needed.  <ins> ACK frames carry the most recent set of acknowledgements and the Ack Delay from the largest acknowledged packet, as described in sending-acknowledgements.  Delaying the transmission of packets containing ACK frames or sending old ACK frames can cause the peer to generate an inflated RTT sample or unnecessarily disable ECN. </ins> Cancellation of stream transmission, as carried in a RESET_STREAM frame, is sent until acknowledged or until all stream data is
Original text:
might be destroyed sooner, as soon as handshake keys are available (see Section 4.9.1 of QUIC-TLS). <del> 5.6. The majority of constants were derived from best common practices among widely deployed TCP implementations on the internet. Exceptions follow. A shorter delayed ack time of 25ms was chosen because longer delayed acks can delay loss recovery and for the small number of connections where less than packet per 25ms is delivered, acking every packet is beneficial to congestion control and loss recovery. </del> 6. QUIC's congestion control is based on TCP NewReno RFC6582.  NewReno

Reviewer comments:
The recommendation for a 25ms delayed ack time is in transport, not recovery, so remove it from recovery. Should this paragraph be moved to transport?
I think that it's fine to just cut this.
This paragraph didn't seem to relate to anything else in the document: Is it left-over from a previous version?
Thanks for pointing this out. The intent was to explain why 25ms was chosen, given it's smaller than most TCP implementations default delayed ack time. There were more exceptions before, but now there's only the one, which makes the preceding paragraph awkward as well. "The majority of constants were derived from best common practices among widely deployed TCP implementations on the internet. Exceptions follow."
I realized that the 25ms recommendation is in transport, so this is just out of place now.
Ah, I see, I remember I went looking for it in transport, but I think I looked for "delayed ack" and didn't come up with anything fitting. I've got no concrete suggestion how to resolve it but moving the notice to transport in some form would probably make sense.

Revised text:
might be destroyed sooner, as soon as handshake keys are available (see Section 4.9.1 of QUIC-TLS).  6. QUIC's congestion control is based on TCP NewReno RFC6582.  NewReno