interacting with the captive portal is out of scope of this document. [ This document is being collaborated on in Github at: <del> https://github.com/wkumari/draft-ekwk-capport-rfc7710bis.  The most recent version of the document, open issues, etc should all be available here.  The authors (gratefully) accept pull requests.  Text in square brackets will be removed before publication. ] </del>  1.

…ptive-portals/vIDCvkyKXdvMGjwvOHuTsSgFzt8/
LGTM, for this change to address 1/2 of the referenced comments.

interacting with the captive portal is out of scope of this document. [ This document is being collaborated on in Github at:  <ins> https://github.com/capport-wg/7710bis.  The most recent version of the document, open issues, etc should all be available here.  The authors (gratefully) accept pull requests.  Text in square brackets will be removed before publication. ] </ins> 1.


If the URIs learned via more than one option described in option are not all identical, this condition should be logged for the device <del> owner or administrator.  URI precedence in this situation is not specified by this document. </del>  4.

If the URIs learned via more than one option described in option are not all identical, this condition should be logged for the device  <ins> owner or administrator.  Implementations can select their own precedence order. </ins> 4.


credentials, etc.  By handing out a URI using which is protected with TLS, the captive portal operator can attempt to reassure the user that the captive portal is not malicious. <del> Operating systems should conduct all interactions with the API in a sand-boxed environment and with a configuration that minimizes tracking risks. </del>


but not the requested action. The client cannot always know a priori if an Authorized Resource <del> Request will succeed.  If the client repeatedly gets error responses containing AS Creation Hints (cf.  Section 5.1.2 of I-D.ietf-ace- oauth-authz as response to its requests, it SHOULD request a new access token from the authorization server in order to continue communication with the resource server. </del>  Unauthorized requests that have been received over a DTLS session SHOULD be treated as non-fatal by the RS, i.e., the DTLS session

This change addresses the issue raised by NAME among the authors that it is worth mentioning This is already addressed in the framework document but to avoid implementation errors it seems worth mentioning here as well.
Merged as two other authors have agreed.

but not the requested action. The client cannot always know a priori if an Authorized Resource  <ins> Request will succeed.  It must check the validity of its keying material before sending a request or processing a response.  If the client repeatedly gets error responses containing AS Creation Hints (cf.  Section 5.1.2 of I-D.ietf-ace-oauth-authz as response to its requests, it SHOULD request a new access token from the authorization server in order to continue communication with the resource server. </ins> Unauthorized requests that have been received over a DTLS session SHOULD be treated as non-fatal by the RS, i.e., the DTLS session


if the token is later transferred over an insecure connection (e.g. when it is sent to the authz-info endpoint). <del> Developers MUST ensure that the ephemeral credentials (i.e., the private key or the session key) are not leaked to third parties.  An adversary in possession of the ephemeral credentials bound to the access token will be able to impersonate the client.  Be aware that this is a real risk with many constrained environments, since adversaries can often easily get physical access to the devices and therefore use phyical extraction techniques to gain access to memory contents.  This risk can also be mitigated to some extent by making sure that keys are refreshed more frequently. </del>  6.3.

I removed the part about the DoS via AS Discovery hints since it was unrealistic.
I changed the text. Text added. Text added. Here is the text from Section 7.2 of draft-ietf-ace-dtls-authorize: URL All editorial comments addressed.
PR addressing comments can be found here: URL
Merged

if the token is later transferred over an insecure connection (e.g. when it is sent to the authz-info endpoint).  <ins> Care must by taken by developers to prevent leakage of the PoP credentials (i.e., the private key or the symmetric key).  An adversary in possession of the PoP credentials bound to the access token will be able to impersonate the client.  Be aware that this is a real risk with many constrained environments, since adversaries may get physical access to the devices and can therefore use phyical extraction techniques to gain access to memory contents.  This risk can be mitigated to some extent by making sure that keys are refreshed frequently, by using software isolation techniques and by using hardware security. </ins> 6.3.


9. <del> There are tradeoffs inherent in a sender sending an ACK_FREQUENCY frame to the receiver.  As such it is recommended that implementers experiment with different strategies and find those which best suit their applications and congestion controllers.  There are, however, noteworthy considerations when devising strategies for sending ACK_FREQUENCY frames. </del>  9.1. <del> A sender relies on receipt of acknowledgements to determine the amount of data in flight and to detect losses, e.g. when packets experience reordering, see QUIC-RECOVERY.  Consequently, how often a receiver sends acknowledgments determines how long it takes for losses to be detected at the sender. </del>  9.2. <del> Many congestion control algorithms have a startup mechanism during the beginning phases of a connection.  It is typical that in this period the congestion controller will quickly increase the amount of data in the network until it is signalled to stop.  While the mechanism used to achieve this increase varies, acknowledgments by the peer are generally critical during this phase to drive the congestion controller's machinery.  A sender can send ACK_FREQUENCY frames while its congestion controller is in this state, ensuring that the receiver will send acknowledgments at a rate which is optimal for the the sender's congestion controller. </del>  9.3. <del> Congestion controllers that are purely window-based and strictly adherent to packet conservation, such as the one defined in QUIC- RECOVERY, rely on receipt of acknowledgments to move the congestion window forward and send additional data into the network.  Such controllers will suffer degraded performance if acknowledgments are delayed excessively.  Similarly, if these controllers rely on the timing of peer acknowledgments (an "ACK clock"), delaying acknowledgments will cause undesirable bursts of data into the network. </del>  9.4.

I don't fully understand when would someone want to set ignore-order = true, i.e., what is a valid use case for this? Lets say for whatever reason the sender sets this to True, this would if there is actual packet loss and receiver receives OOO packets, it won't send an immediate ACK. Meaning the sender won't enter loss recovery immediately and will continue sending packets at the same rate. This is not good, as it directly increases queuing on the network node and for a tail drop queue (most widespread deployment), it will also affect other flows. Meaning, other flows will experience packet loss due to non-responsiveness of this flow for certain period of time. I probably missed past conversations about ignore-order field, so my apologies if this has already been discussed. I read the draft and didn't see any explanation about where would this be useful and what are the fallbacks of setting this to true.
One use case that I know and care is for sending QUIC traffic from a server cluster. Some packets would be sent directly from a server node that governs the connections, but others would be sent via different nodes within the same cluster. Once we deploy a sender like this, the receiver would observe what looks like reordering (because most packets will be essentially delivered through an additional hop, and that would cause delays). But we do not want the receiver to send ACK for each packet being received. Regarding the problem, I'm not sure I agree with the impact. Typically, congestion controllers react to congestion after 1 RTT. When packet-number-based detection is turned off, that changes to 9/8 RTT. That does cause more pressure on the bottleneck queue, but it is no worse than that caused by a path with an 9/8 greater RTT. Assuming that congestion controllers are designed to be fair against flows having different RTTs, I tend to believe that this is a non-issue.
I agree with NAME though I think adding a SHOULD NOT use a delay longer than an RTT(URL) would be a good addition, since if the delay is extremely large(ie multiple RTTs), that could be bad.
In general, the spirit of this draft is to provide control over acking behavior to the sender, since it is the consumer of this information and ought to be able to control how frequently it needs to see this information. If there are subtle consequences to these decisions, it is worth noting them in the draft. It seems useful to add some text on the consequences of using Ignore Order, so that senders can make informed decisions. We can do that.
NAME is this something that Fastly does or is planning to do? How would you share the connection secrets between different server nodes? When we set ignore-reorder = true, and lets assume that max ACK delay > 1RTT, it can be 1RTT or 2 or 10RTT. this would result in loss recovery to be delayed by at least an additional RTT, i.e. it will take >16/8RTT (>2RTT) instead of 9/8RTT to declare packets lost. That is significant IMO. >Assuming that congestion controllers are designed to be fair against flows having different RTTs, I tend to believe that this is a non-issue. CUBIC throughput is inversely proportional to RTT in New Reno mode. Nonetheless, I am more concerned about high queuing in bottleneck due to late loss recovery. Specifying the use-cases where ignore-order = true SHOULD be used will prevent new implementors from using it randomly. And as Jana said, some text around the consequences when it is used would allow informed decision making.
NAME I do not speak for Fastly's plan, but the OSS branch of H2O has a working prototype that does this: URL The calculation is correct. At the same time, I do not think that senders will be willing to use Max Ack Delay as large as that, when setting the Ignore Order bit. The problem here is the impact on loss recovery. If Max Ack Delay is set to a value as large as 1 RTT, then the sender needs to spend more than 2 RTTs for detecting a loss. That means that the size of the send and receive buffers have to be twice as large, and that it would take as twice as long to recover from a loss. Based on existing advice that we have in other RFCs, I think we should discourage Max Ack Delay that is greater than 9/8 RTT when Ignore Order bit is used (please see my comment on ).
I'd suggest 5/4, but otherwise agree with you NAME
Should the Max ACK Delay be restricted to 1/8 or 1/4 RTT as there is inherent 1RTT time spent while sending data and receiving ACKs? That would make a total of 1 + 1/8 or 1 +1/4 RTT total/
I think this is best as a sender-side SHOULD, since it knows what time threshold it's using. For example, we use 1/4 RTT, but have considered making it adaptive(ie: 1/16 RTT to 1 RTT) based on observed reordering. Also, if your RTT is 100us, and your timers have coarser granularity, 1/8 RTT or 1/4 RTT just doesn't make sense. I'm not sure what does, because I'm not an expert in datacenter networking, but that's why I think this is a SHOULD, not a MUST. Of course, it's also unenforceable, which is a good reason for a SHOULD.
+1 to SHOULD. The only argument I might disagree with NAME is that it is unenforceable (IMO a receiver can enforce by capping Ack Delay to a fraction of the RTT that the receiver has observed). But I do not think there's any reason to require the receiver to enforce, considering the fact that a sender can send as many packets as it likes, regardless of ACKs the receiver sends (or lack of).
I am fine with SHOULD and with a mention of how a sender would compute Max ACK Delay when he sets ignore-order = true. An example is fine too.
I believe this is the same issue as
There are two things that are impacted by setting a high value for ack delay: congestion control and time-threshold loss detection. On congestion control, we need some protection for the network, so we should recommend something. On loss detection, a sender that chooses and sets an ack delay higher than the time-threshold loss detection time period risks triggering unnecessary retransmissions. So, I propose adding the following for a sender: SHOULD set the ack frequency to be at least one ack per RTT (so that congestion control responses are reasonably quick) a word of caution that setting the ack delay to be longer than time threshold can cause the sender to unnecessary retransmit
In 9.3. Window-based Congestion Controllers I thought that unless there is loss reported, a QUIC ACK Frame releases sending window. In a similar manner as the accurate byte counting style in TCP, a QUIC sender solely operates on the basis of bytes acked, not the number of ACK frames received. So while a delayed ACK could delay a round of growth when the ACK Ratio is larger, it is only delayed by the time to ACK the set of received packets. In looking at various QUIC CC over medium and longer path RTTs this effect was quite small, and the default ACK delay was not unreasonable; for shorter path RTTs this might be different
See PR
To me, ACK Clocking is a separate point that applies to any type of CC when the cwnd limits the sender. I agree there could be a concern is around whether a less frequent ACK policy can induce a cwnd-limited sender to send bursts of packets that could induce loss or disrupt sharing of the path with other flows. The QUIC specification already permits an initial window of 10 packets, and motivates the need for pacing. I think it is important this text refers to the QUIC transport section on pacing to mitigate bursts.
Better worded perhaps in PR .
Section 9.1 - There are CC considerations with respect to how long it is reasonable for a flow to hold-off detecting congestion and responding. This needs to be discussed. When an endpoint detects persistent congestion, it MUST promptly reduce the rate of transmission when it receive or detects an indication of congestion (e.g., loss or ECN marking) [RFC2914], the Ignore Order value of true (0x01) in this ID allows a sender to extend that period, postponing detection of loss. That might be reasonable, but excessive delay can be dangerous - and therefore the impact really needs to be discussed: delaying a fraction of a RTT is in my mind safe, intentionally delaying by an RTT is arguable. A delay of many RTTs is endangers other flows, and we need to at least say that in some way ([RFC8084] took an alternate view of how long might be safe).
See PR
I think this warrants a note about how a sender SHOULD NOT use a delay that is larger than an RTT unless the sender has other information about either the network or current network conditions. Otherwise, the receiver does not need to enforce anything here.
NAME Delay of loss detection has negative impact on loss recovery as well. Considering that the time threshold defined in RFC 9002 is 9/8 RTT, I might ague that, when Ignore Order is set to true, then the maximum delay being advertised SHOULD be no greater than 9/8 RTT. These values provide responsiveness comparable to Rack when a packet is lost - the loss would be detected within 5/4 RTT. (stuck out, as this point is already covered by Section 8).

9.  <ins> This section provides some guidance on a sender's choice of acknowledgment frequency and discusses some additional considerations.  Implementers can select an appropriate strategy to meet the needs of their applications and congestion controllers. </ins> 9.1.  <ins> A sender needs to be responsive to notifications of congestion, such as a packet loss or an ECN CE marking.  Also, window-based congestion controllers that strictly adhere to packet conservation, such as the one defined in QUIC-RECOVERY, rely on receipt of acknowledgments to send additional data into the network, and will suffer degraded performance if acknowledgments are delayed excessively. To enable a sender to respond to potential network congestion, a sender SHOULD cause a receiver to send an acknowledgement at least once per RTT if there are unacknowledged ack-eliciting packets in flight.  A sender can accomplish this by sending an IMMEDIATE_ACK frame once per round-trip time (RTT), or it can set the Ack-Eliciting Threshold and Request Max Ack Delay values to be no more than a congestion window and an estimated RTT, respectively. </ins> 9.2.  <ins> Receiving an acknowledgement can allow a sender to release new packets into the network.  If a sender is designed to rely on the timing of peer acknowledgments ("ACK clock"), delaying acknowledgments can cause undesirable bursts of data into the network.  A sender MUST limit such bursts.  In keeping with Section 7.7 of QUIC-RECOVERY, a sender can either employ pacing or cause a receiver to send an acknowledgement for at least each initial congestion window of received data. </ins> 9.3.  <ins> Acknowledgements are fundamental to reliability in QUIC. Consequently, delaying or reducing the frequency of acknowledgments can cause loss detection at the sender to be delayed. A QUIC sender detects loss using packet thresholds on receiving an acknowledgement (Section 6.1.1 of QUIC-RECOVERY); delaying the acknowledgement therefore delays this method of detecting losses. Reducing acknowledgement frequency reduces the number of RTT samples that a sender receives (Section 5 of QUIC-RECOVERY), making a sender's RTT estimate less responsive to changes in the path's RTT. As a result, any mechanisms that rely on an accurate RTT estimate, such as time-threshold loss detection (Section 6.1.2 of QUIC- RECOVERY) or Probe Timeout (Section 6.2 of QUIC-RECOVERY), will be less responsive to changes in the path's RTT, resulting in either delayed or unnecessary packet transmissions. To limit these consequences of reduced acknowledgement frequency, a sender SHOULD cause a receiver to send an acknowledgement at least once per RTT if there are unacknowledged ack-eliciting packets in flight.  A sender can accomplish this by sending an IMMEDIATE_ACK frame once per round-trip time (RTT), or it can set the Ack-Eliciting Threshold and Request Max Ack Delay values to be no more than a congestion window and an estimated RTT, respectively. A sender might use timers to detect loss of PMTUD probe packets.  A sender SHOULD bundle an IMMEDIATE_ACK frame with any PTMUD probes to avoid triggering such timers. </ins> 9.4.


connection SHOULD update and send a new ACK_FREQUENCY frame immediately upon confirmation of connection migration. <del> 9.5. A sender might use timers to detect loss of PMTUD probe packets.  A sender SHOULD bundle an IMMEDIATE_ACK frame with any PTMUD probes to avoid triggering such timers. </del> 10. TBD.

connection SHOULD update and send a new ACK_FREQUENCY frame immediately upon confirmation of connection migration.  10. TBD.


6.3. <del> For performance reasons, an endpoint can receive incoming packets from the underlying platform in a batch of multiple packets.  This batch can contain enough packets to cause multiple acknowledgements to be sent. </del> To avoid sending multiple acknowledgements in rapid succession, an endpoint can process all packets in a batch before determining whether to send an ACK frame in response, as stated in Section 13.2.2

Defer to RFC9000.
The text says: "For performance reasons, an endpoint can receive incoming packets from the underlying platform in a batch of multiple packets." is this the network layer... or something else?
It could be the OS or the hardware.
I think the sentence needs some work - I can believe the network; interface; operating system; etc. Are examples of reasons why there is bunching of packets so that a batch of packets arrive at the receiver. The current text doesn't really say quite what I'd expect.

6.3.  To avoid sending multiple acknowledgements in rapid succession, an endpoint can process all packets in a batch before determining whether to send an ACK frame in response, as stated in Section 13.2.2


number of acknowledgments allows connection throughput to scale much further. <del> Unfortunately, there are undesirable consequences to simply reducing the acknowledgement frequency, especially to an arbitrary fixed value, as follows: A sender relies on receipt of acknowledgements to determine the amount of data in flight and to detect losses, see QUIC-RECOVERY. Consequently, how often a receiver sends acknowledgments dictates how long it takes for losses to be detected at the sender. Starting a connection up quickly without inducing excess queue is important for latency reduction, for both short and long flows. The sender often needs more frequent acknowledgments during this phase. Congestion controllers that are purely window based and strictly adherent to packet conservation, such as the one defined in QUIC- RECOVERY, rely on receipt of acknowledgments to move the congestion window forward and release additional data.  Such controllers suffer performance penalties when acknowledgements are not sent frequently enough.  On the other hand, for long-running flows, congestion controllers that are not window-based, such as BBR, can perform well with very few acknowledgements per RTT. New sender startup mechanisms will need a way for the sender to increase the frequency of acknowledgements when fine-grained feedback is required. </del>  QUIC-TRANSPORT currently specifies a simple delayed acknowledgement mechanism that a receiver can use: send an acknowledgement for every

I think the motivations section as-is is too long. It spends a lot of time talking about what are effectively the tradeoffs. IMO the motivations section should specify why it's useful to have the sender control the receiver's ACK frequency, and then we can have a separate section for the tradeoffs. This takes a stab at that section, lifting things from motivations and adding some new text specifically addressing the nascent stages of a connection. I also made some editorial changes to the existing text. I am happy to add any additional considerations we think might need to be called out. This attempts to
Thanks for the PR, NAME ! I like the new text you propose (I've proposed some changes), but I think you might be assuming that ACK_FREQUENCY is only used for delaying acks further. An important point that bears bringing out in the motivation is that a sender might want more frequent acks as well, for example during startup. That's worth capturing in the modified motivation section.
NAME this PR is almost done, any chance you can do another round of updates and we can get it in?
NAME sorry, I'll do some updates today.
NAME NAME I've updated the PR, I'll watch and iterate on any remaining feedback quickly this time.
thanks NAME Something about vim and the macbook pro keyboard apparently makes me incapable of spelling things properly. I want my desk keyboard back
As discussed on in the base draft, we have some confidence in a particular heuristic (default tolerance of 2 for the first 100 packets, followed by a tolerance of 10) which we know to work fairly well in multiple deployments serving "typical" Internet resources to typical users. Do we want to make that recommendation explicit, or otherwise give guidance in this extension?
I think it's a good idea to describe the values for which we have experience, while encouraging experimentation. We don't need to recommend the strategy, we just need to document it as an example strategy.
I think a section on considerations and maybe past experience would be very helpful. I think it's going to be a bit of a challenge to write, but I'm happy to take a stab if no one else wants to.
What I'd want to see is just a simple explanation of what a sender could do... I would not describe results from experience, since those are anecdotal and are going to change over time. This could be a fairly short section.
NAME NAME I can take a stab at writing something and we can go from there.
Thanks, NAME !
I do think the pitfalls of e.g. should be conveyed in such "cautionary" text as well. I will submit a PR this week time permitting between interop.
Thanks, NAME

number of acknowledgments allows connection throughput to scale much further.  <ins> As discussed in implementation, there are undesirable consequences to congestion control and loss recovery if a receiver uniltaerally reduces the acknowledgment frequency.  Consequently, a sender needs the ability to express its constraints on the acknowledgement frequency to maximize congestion controller performance. </ins> QUIC-TRANSPORT currently specifies a simple delayed acknowledgement mechanism that a receiver can use: send an acknowledgement for every


8.  <ins> There are tradeoffs inherent in a sender sending an ACK_FREQUENCY frame to the receiver.  As such it is recommended that implementers experiment with different strategies and find those which best suit their applications and congestion controllers.  There are, however, noteworthy considerations when devising strategies for sending ACK_FREQUENCY frames. 8.1. A sender relies on receipt of acknowledgements to determine the amount of data in flight and to detect losses, e.g. when packets experience reordering, see QUIC-RECOVERY.  Consequently, how often a receiver sends acknowledgments determines how long it takes for losses to be detected at the sender. 8.2. Many congestion control algorithms have a startup mechanism during the beginning phases of a connection.  It is typical that in this period the congestion controller will quickly increase the amount of data in the network until it is signalled to stop.  While the mechanism used to achieve this increase varies, acknowledgments by the peer are generally critical during this phase to drive the congestion controller's machinery.  A sender can send ACK_FREQUENCY frames while its congestion controller is in this state, ensuring that the receiver will send acknowledgments at a rate which is optimal for the the sender's congestion controller. 8.3. Congestion controllers that are purely window-based and strictly adherent to packet conservation, such as the one defined in QUIC- RECOVERY, rely on receipt of acknowledgments to move the congestion window forward and send additional data into the network.  Such controllers will suffer degraded performance if acknowledgments are delayed excessively.  Similarly, if these controllers rely on the timing of peer acknowledgments (an "ACK clock"), delaying acknowledgments will cause undesirable bursts of data into the network. </ins> 9. TBD. <ins> 10. TBD. </ins>


receivers to ignore obsolete frames, see multiple-frames. A variable-length integer representing the maximum number of ack- <del> eliciting packets after which the receiver sends an acknowledgement.  A value of 1 will result in an acknowledgement being sent for every ack-eliciting packet received.  A value of 0 is invalid.  Receipt of an invalid value MUST be treated as a connection error of type FRAME_ENCODING_ERROR.  If an endpoint receives an ACK-eliciting threshold value that is larger than the maximum value it can represent, the endpoint MUST use the largest representable value instead. </del>  A variable-length integer representing the value to which the endpoint requests the peer update its "max_ack_delay"

Also updates the transport parameter codepoint to 0xff03de1a from 0xff02de1a.
While reading the latest ack-frequency draft, I am confused with the wording that was added in URL If I have ack-eliciting threshold = 1, to me it means that I can receive 1 ack-eliciting packet before sending an ACK, i.e. I have to send ACK after receiving 1 packet. But looking at the example of 0, this interpretation looks wrong. NAME suggested, maybe the "before" needs to be "without" and an additional sentence added: "An immediate acknowledgement is sent when more than this number of packets have been received." I agree with his suggestion.
Thanks for the issues, this is a bit unclear. PTAL at
The definition that I use internally is "the number of packets you can receive without sending an immediate acknowledgment". This is different than saying "please acknowledge every N packets". The main benefit of this definition is that there are no invalid values for the number. I recommend making this adjustment in the frame definition: it will be more efficient (by a tiny amount), but it also removes the need to validate the value.
This seems like a good change, it's just a matter of writing the text.

receivers to ignore obsolete frames, see multiple-frames. A variable-length integer representing the maximum number of ack-  <ins> eliciting packets the recipient of this frame can receive before sending an immediate acknowledgment.  A value of 0 will result in an immediate acknowledgement whenever an ack-eliciting packet received.  If an endpoint receives an ACK-eliciting threshold value that is larger than the maximum value it can represent, the endpoint MUST use the largest representable value instead. </ins> A variable-length integer representing the value to which the endpoint requests the peer update its "max_ack_delay"


Every time an acknowledgement is sent, bundled or otherwise, all counters and timers related to delaying of acknowledgments are reset.  6.1. As specified in Section 13.2.1 of QUIC-TRANSPORT, endpoints are

Every time an acknowledgement is sent, bundled or otherwise, all counters and timers related to delaying of acknowledgments are reset. <ins> The receiver of an ACK_FREQUENCY frame can continue to process multiple available packets before determining whether to send an ACK frame in response, as stated in Section 13.2.2 of QUIC-TRANSPORT. </ins> 6.1. As specified in Section 13.2.1 of QUIC-TRANSPORT, endpoints are


6.  Prior to receiving an ACK_FREQUENCY frame, endpoints send acknowledgements as specified in Section 13.2.1 of QUIC-TRANSPORT.

by adding a one byte IMMEDIATE_ACK frame.
editorial nit: my preference would be for frame diagrams to use the notation in QUIC transport. I see that ACK_FREQUENCY is defined using ASCII art, so perhaps you want to consider a separate follow up PR to switch styles after this lands.
Thanks Lucas, I filed to update them.
They currently use ascii art. Will write this up once is merged.
sgtm, thanks!
When sending a PTO packet, a sender wants to induce an immediate ACK. The only trick I know to induce such an ACK is intentionally skip the packet number. However, the problem of that approach is that it relies on the receiver not ignoring reorders. When an ACKFREQUENCY frame previously sent had set the bit, then it become impossible for a sender to induce an immediate ACK when sending a PTO packet. At the moment, the only solution is to bundle an ACK_FREQUENCY packet in each PTO packet, but that seems like a bit of unnecessary overhead to me. Should we have a dedicated frame for inducing immediate ACKs instead?
That's an option. Another option is to revisit the max_reordering idea discussed in . If the max reordering was 5, then you could skip 5 PNs. I do feel like it'd be nice to allow specifying an int for max reordering, since that matches up with adaptive packet threshold loss detection, but as I expressed in , I think getting the details right are deceptively difficult, so I'm torn.
This does seem like a real problem. I like the idea of a single "ELICIT_ACK" type frame. With one byte a sender could effectively mark its PTOs ensuring they get an ACK without relying on the trick. An explicit frame is also easier to implement for the sender than the packet number skipping.
There's quite a bit of discussion on this on the tcpm mailing list at the moment, ie: URL I'm increasingly thinking it's worth using an unused protected bit in the header for this. It'd end up competing with the 2-bit packet loss measurements, but given those are experimental and may never be widely deployed, I think it might be worth it. For example, I believe this could allow an implementation to not include maxackdelay in PTO if it set the "ACK-pull"(or whatever it's called) bit on the final packet. That already seems possible if more than the threshold number of ack-eliciting packets are outstanding.
I've thought more about this, and I think most of the time a 1-byte frame would be acceptable, but it definitely adds some implementation complexity, so I'd be curious which design others prefer? If we can decide, then I'll be happy to write a PR(or NAME can). Besides PTO, a use case would be making the last packet before becoming app-limited elicit an immediate ACK. This could allow skipping maxackdelay for all PTOs(see ), though always doing it could be a bit much in some cases. For example, browsers commonly send a series of requests, but to the transport it seems app-limited between them, because it doesn't know the browser has another request to send. It might be useful for 'chirping' as well, but I've never tried that, so it's mostly speculation.
We don't currently have any intention of deploying them either, and I think that's unlikely to change. I haven't seen a lot of good evidence that they are terribly helpful, and content providers don't seem to have a good incentive for implementing it. For us at least, the difference in complexity for a frame versus a bit in the header is negligible. A frame is actually be slightly easier to implement and losing a byte here and there isn't so bad.
I strongly prefer using the header bit. Although it will be a bit more work to implement, the fact that I won't end up with a 1-byte STREAM frame that I have to split off at the end of the packet will be worth the effort.
Is testimony of network operators not taken as evidence? I remember a line of people, from different companies -- BT, ATT, and so on, at IETF 101 practically begging for some information in QUIC packets to be exposed for monitoring and troubleshooting.
I do not see anyone propose a 1-byte STREAM frame. I believe what is meant is a new frame type. If anything, using a new frame type to elicit an ACK is easier than using a header bit, as it involves fewer parts of the code to change.
Nobody is proposing a 1-byte STREAM frame (you can't just make up stream data anyway). The problem is that a new frame would consume bytes (or probably one byte) in the packet payload. Given that you set this signal on a PTO, and PTOs are often retransmissions of packets, this would require you to repackage (and, most likely, cut off a single byte from a STREAM frame). Using a header bit would solve that problem.
NAME and I discussed this and there are number of ways to fix this, but given this issue of not being able to elicit an immediate ACK by skipping packet numbers is introduced by the draft, we feel it's important it be fixed in some way. One more option is new STREAM frame codepoints that elicit an immediate ACK.
I'm ready to write a PR, but I'd appreciate thoughts on whether the existing PING frame should be repurposed or we should add a new frame(ACK, PONG, etc). I lean towards a new frame, since there are enough code-points and I believe there are use cases for the existing PING frame that does not elicit an immediate ACK.
+1. While I would not be opposed to repurposing the existing PING frame, I do not see the necessity of doing that. Let's simply consume one code point of the remaining 33.
Thanks, now for bikeshedding time. Some possible names: ACKME ACKPULL (from TCP) FAST_ACK PONG
Putting on my bikeshedding hat: I don't think we should prefix the frame name with ACK since that almost makes it looks like yet another variant of the ACK frame. The "pull" TCP terminology is fine (e.g. PULLACK) but we could also be more explicit with something like SOLICIT_ACK.
SCTP has something similar and calls it SACK-IMMEDIATELY (RFC 7053).
Thanks, I'd be happy with ACKIMMEDIATELY or IMMEDIATEACK
For those two options I'd prefer IMMEDIATE_ACK for the same reasoning as above -- so it appears less like an ACK variant.
IMMEDIATEACK sounds good to me. Alternatively, I'd be also fine with something like ACKNOW.
IMMEDIATE_ACK it is, PR coming.

6. <ins> The IMMEDIATE_ACK Frame is a frame which causes the peer to send a packet containing an ACK frame immediately, similar to the receipt of Initial and Handshake packets during the QUIC handshake. Receivers of the IMMEDIATE_ACK frame MAY choose to delay sending the ACK if the vast majority of received packets contain an IMMEDIATE_ACK or the receiver is under heavy load.  Senders MAY include multiple IMMEDIATE_ACK frames in a single QUIC packet, but the behavior is identical to a single IMMEDIATE_ACK frame. 7. </ins> Prior to receiving an ACK_FREQUENCY frame, endpoints send acknowledgements as specified in Section 13.2.1 of QUIC-TRANSPORT.


multiple available packets before determining whether to send an ACK frame in response, as stated in Section 13.2.2 of QUIC-TRANSPORT. <del> 6.1. </del>  As specified in Section 13.2.1 of QUIC-TRANSPORT, endpoints are expected to send an acknowledgement immediately on receiving a

multiple available packets before determining whether to send an ACK frame in response, as stated in Section 13.2.2 of QUIC-TRANSPORT.  <ins> 7.1. </ins> As specified in Section 13.2.1 of QUIC-TRANSPORT, endpoints are expected to send an acknowledgement immediately on receiving a


instead continues to use the peer's "Ack-Eliciting Threshold" and "max_ack_delay" thresholds for sending acknowledgements. <del> 6.2. </del>  As specified in Section 13.2.1 of QUIC-TRANSPORT, an endpoint SHOULD immediately acknowledge packets marked with the ECN Congestion Experienced (CE) codepoint in the IP header.  Doing so reduces the peer's response time to congestion events. <del> 6.3. </del>  For performance reasons, an endpoint can receive incoming packets from the underlying platform in a batch of multiple packets.  This

instead continues to use the peer's "Ack-Eliciting Threshold" and "max_ack_delay" thresholds for sending acknowledgements.  <ins> 7.2. </ins> As specified in Section 13.2.1 of QUIC-TRANSPORT, an endpoint SHOULD immediately acknowledge packets marked with the ECN Congestion Experienced (CE) codepoint in the IP header.  Doing so reduces the peer's response time to congestion events.  <ins> 7.3. </ins> For performance reasons, an endpoint can receive incoming packets from the underlying platform in a batch of multiple packets.  This


whether a threshold has been met and an acknowledgement is to be sent in response. <del> 7. </del>  On sending an update to the peer's "max_ack_delay", an endpoint can use this new value in later computations of its Probe Timeout (PTO)

whether a threshold has been met and an acknowledgement is to be sent in response.  <ins> 8. </ins> On sending an update to the peer's "max_ack_delay", an endpoint can use this new value in later computations of its Probe Timeout (PTO)


optimization requires some care in implementation, since it can cause premature PTOs under packet loss when "ignore_order" is enabled. <del> 8. </del>  There are tradeoffs inherent in a sender sending an ACK_FREQUENCY frame to the receiver.  As such it is recommended that implementers

optimization requires some care in implementation, since it can cause premature PTOs under packet loss when "ignore_order" is enabled.  <ins> 9. </ins> There are tradeoffs inherent in a sender sending an ACK_FREQUENCY frame to the receiver.  As such it is recommended that implementers


noteworthy considerations when devising strategies for sending ACK_FREQUENCY frames. <del> 8.1. </del>  A sender relies on receipt of acknowledgements to determine the amount of data in flight and to detect losses, e.g. when packets

noteworthy considerations when devising strategies for sending ACK_FREQUENCY frames.  <ins> 9.1. </ins> A sender relies on receipt of acknowledgements to determine the amount of data in flight and to detect losses, e.g. when packets


receiver sends acknowledgments determines how long it takes for losses to be detected at the sender. <del> 8.2. </del>  Many congestion control algorithms have a startup mechanism during the beginning phases of a connection.  It is typical that in this

receiver sends acknowledgments determines how long it takes for losses to be detected at the sender.  <ins> 9.2. </ins> Many congestion control algorithms have a startup mechanism during the beginning phases of a connection.  It is typical that in this


that the receiver will send acknowledgments at a rate which is optimal for the the sender's congestion controller. <del> 8.3. </del>  Congestion controllers that are purely window-based and strictly adherent to packet conservation, such as the one defined in QUIC-

that the receiver will send acknowledgments at a rate which is optimal for the the sender's congestion controller.  <ins> 9.3. </ins> Congestion controllers that are purely window-based and strictly adherent to packet conservation, such as the one defined in QUIC-


acknowledgments will cause undesirable bursts of data into the network. <del> 9. </del>  TBD. <del> 10. </del>  TBD. <del> 11.  References </del>  <del> 11.1.  URIs </del>  [1] https://mailarchive.ietf.org/arch/search/?email_list=quic

acknowledgments will cause undesirable bursts of data into the network.  <ins> 10. </ins> TBD.  <ins> 11. </ins> TBD.  <ins> 12.  References </ins>  <ins> 12.1.  URIs </ins> [1] https://mailarchive.ietf.org/arch/search/?email_list=quic


Discussion of this draft takes place on the QUIC working group mailing list (quic@ietf.org), which is archived at <del> https://mailarchive.ietf.org/arch/search/?email_list=quic [1]. Source code and issues list for this draft can be found at https://github.com/quicwg/ack-frequency [2]. </del>  <del> Working Group information can be found at https://github.com/quicwg [3]; </del>  1.

You aren't using URL, so remove it. I updated the links so that the text rendering doesn't include them twice.

Discussion of this draft takes place on the QUIC working group mailing list (quic@ietf.org), which is archived at  <ins> <https://mailarchive.ietf.org/arch/search/?email_list=quic>.  Source code and issues list for this draft can be found at <https://github.com/quicwg/ack-frequency>. </ins>  <ins> Working Group information can be found at <https://github.com/ quicwg>. </ins> 1.


11. TBD. <del> 12.  References 12.1.  URIs [1] https://mailarchive.ietf.org/arch/search/?email_list=quic [2] https://github.com/quicwg/ack-frequency [3] https://github.com/quicwg </del>


QUIC-TRANSPORT currently specifies a simple delayed acknowledgement mechanism that a receiver can use: send an acknowledgement for every <del> other packet, and for every packet when reordering is observed.  This simple mechanism does not allow a sender to signal its constraints. This extension provides a mechanism to solve this problem. </del>  3.

NAME tell me if this is sufficient, or if you wanted more references to RFC9000.
Thanks, I'm open to other suggestions if you have them, but nothing else stuck out at me. I'm reluctant to repeat the full definition of out of order in this document, given it's well defined in RFC9000.
When reviewing the draft I got caught on this part: As specified in Section 13.2.1 of [QUIC-TRANSPORT], endpoints are expected to send an acknowledgement immediately on receiving a reordered ack-eliciting packet. This extension modifies this behavior. There is an issue here in how this draft uses "reordering". Section 13.2.1 of RFC 9000 does say that ACKs should be sent immediately if: "In order to assist loss detection at the sender, an endpoint SHOULD generate and send an ACK frame without delay when it receives an ack-eliciting packet either: when the received packet has a packet number less than another ack-eliciting packet that has been received, orwhen the packet has a packet number larger than the highest-numbered ack-eliciting packet that has been received and there are missing packets between that packet and this packet." Although the first bullet clearly is reordering, the second could be caused by three different mechanisms: Reordering of packets, loss of packets, or sender intentional gap (as discussed in ) Thus, I think this section needs to be clear if actually means both of the above bullets for when to send ACK or only one of them?
Thanks Magnus, the intent was to follow the RFC9000 definition, so I'll write a PR to clarify that was the intent.
A couple of minor edits, but lgtmOk, I think this is truly the bare minimal to resolve my issue. There exist a clearer chain back towards Section 13.2.1 in RFC9000 and I guess that is sufficient.

QUIC-TRANSPORT currently specifies a simple delayed acknowledgement mechanism that a receiver can use: send an acknowledgement for every  <ins> other packet, and for every packet that is received out of order (Section 13.2.1 of QUIC-TRANSPORT).  This simple mechanism does not allow a sender to signal its constraints.  This extension provides a mechanism to solve this problem. </ins> 3.


A 1-bit field representing a boolean truth value.  This field is set to "true" by an endpoint that does not wish to receive an <del> immediate acknowledgement when the peer observes reordering (reordering).  0 represents 'false' and 1 represents 'true'. </del>  A 1-bit field representing a boolean truth value.  This field is set to "true" by an endpoint that does not wish to receive an immediate acknowledgement when the peer receives CE-marked packets <del> (reordering).  0 represents 'false' and 1 represents 'true'. </del>  ACK_FREQUENCY frames are ack-eliciting.  However, their loss does not require retransmission if an ACK_FREQUENCY frame with a larger

A 1-bit field representing a boolean truth value.  This field is set to "true" by an endpoint that does not wish to receive an  <ins> immediate acknowledgement when the peer receives a packet out of order (out-of-order). 0 represents 'false' and 1 represents 'true'. </ins> A 1-bit field representing a boolean truth value.  This field is set to "true" by an endpoint that does not wish to receive an immediate acknowledgement when the peer receives CE-marked packets  <ins> (out-of-order).  0 represents 'false' and 1 represents 'true'. </ins> ACK_FREQUENCY frames are ack-eliciting.  However, their loss does not require retransmission if an ACK_FREQUENCY frame with a larger


Since the last acknowledgement was sent, "max_ack_delay" amount of time has passed. <del> reordering, congestion, and batch describe exceptions to this </del>  strategy. An endpoint is expected to bundle acknowledgements when possible.

Since the last acknowledgement was sent, "max_ack_delay" amount of time has passed.  <ins> out-of-order, congestion, and batch describe exceptions to this </ins> strategy. An endpoint is expected to bundle acknowledgements when possible.


Different challenges allow the server to obtain proof of different aspects of control over an identifier.  In some challenges, like HTTP and TLS SNI, the client directly proves its ability to do certain <del> things related to the identifier.  In the Proof of Possession challenge, the client proves historical control of the identifier, by reference to a prior authorization transaction or certificate. The choice of which challenges to offer to a client under which circumstances is a matter of server policy.  A CA may choose different sets of challenges depending on whether it has interacted with a domain before, and how.  For example: New domain with no known certificates: Domain Validation (HTTP or TLS SNI) Domain for which known certs exist from other CAs: DV + Proof of Possession of previous CA-signed key Domain with a cert from this CA, lost account key: DV + PoP of ACME-certified Subject key Domain with a cert from this CA, all keys and recovery mechanisms lost: Out of band proof of authority for the domain </del>  The identifier validation challenges described in this section all relate to validation of domain names.  If ACME is extended in the

There has been no implementer interest in the proof-of-possession challenge, and it makes the document more complex by having a completely different structure than the other challenges. If it is decided later that such a challenge is necessary, it can be added in a follow-on extension specificiation.
Generally this seems fine, and I wholeheartedly agree with the purpose of the removal (for now). One problem I can't open a comment for: Line 2099, the last paragraph before "Preventing Authorization Hijacking", still refers to the PoP Challenge. Without the PoP Challenge wording, a new reader may take that this to be referring to the implicit Proof of Possession of the ACME Account Key and thus be confused. Since it's non-normative, perhaps you could simply modify that paragraph into something more like:

Different challenges allow the server to obtain proof of different aspects of control over an identifier.  In some challenges, like HTTP and TLS SNI, the client directly proves its ability to do certain  <ins> things related to the identifier.  The choice of which challenges to offer to a client under which circumstances is a matter of server policy. </ins> The identifier validation challenges described in this section all relate to validation of domain names.  If ACME is extended in the


7.4. <del> The Proof of Possession challenge verifies that a client possesses a private key corresponding to a server-specified public key, as demonstrated by its ability to sign with that key.  This challenge is meant to be used when the server knows of a public key that is already associated with the identifier being claimed, and wishes for new authorizations to be authorized by the holder of the corresponding private key.  For DNS identifiers, for example, this can help guard against domain hijacking. This method is useful if a server policy calls for issuing a certificate only to an entity that already possesses the subject private key of a particular prior related certificate (perhaps issued by a different CA).  It may also help enable other kinds of server policy that are related to authenticating a client's identity using digital signatures. This challenge proceeds in much the same way as the proof of possession of the authorized key pair in the main ACME flow (challenge + authorizationRequest).  The server provides a nonce and the client signs over the nonce.  The main difference is that rather than signing with the private key of the key pair being authorized, the client signs with a private key specified by the server.  The server can specify which key pair(s) are acceptable directly (by indicating a public key), or by asking for the key corresponding to a certificate. The server provides the following fields as part of the challenge: The string "proof-of-possession-01" An array of certificates, in base64url-encoded DER format, that contain acceptable public keys. In response to this challenge, the client uses the private key corresponding to one of the acceptable public keys to sign a JWS object including data related to the challenge.  The validation object covered by the signature has the following fields: The string "proof-of-possession" A list of identifiers for which the holder of the prior key authorizes the new key The client's account public key This JWS is NOT REQUIRED to have a "nonce" header parameter (as with the JWS objects that carry ACME request objects).  This allows proof- of-possession response objects to be computed off-line.  For example, as part of a domain transfer, the new domain owner might require the old domain owner to sign a proof-of-possession validation object, so that the new domain owner can present that in an ACME transaction later. The validation JWS MUST contain a "jwk" header parameter indicating the public key under which the server should verify the JWS. The client's response includes the server-provided nonce, together with a signature over that nonce by one of the private keys requested by the server. The string "proof-of-possession" The validation JWS To validate a proof-of-possession challenge, the server performs the following steps: Verify that the public key in the "jwk" header of the "authorization" JWS corresponds to one of the certificates in the "certs" field of the challenge Verify the "authorization" JWS using the key indicated in its "jwk" header Decode the payload of the JWS as UTF-8 encoded JSON Verify that there are exactly three fields in the decoded object, and that: * The "type" field is set to "proof-of-possession" * The "identifier" field contains the identifier for which authorization is being validated * The "accountKey" field matches the account key for which the challenge was issued If all of the above verifications succeed, then the validation is successful.  Otherwise, the validation fails. 7.5. </del> When the identifier being validated is a domain name, the client can prove control of that domain by provisioning a resource record under it.  The DNS challenge requires the client to provision a TXT record

7.4.  When the identifier being validated is a domain name, the client can prove control of that domain by provisioning a resource record under it.  The DNS challenge requires the client to provision a TXT record


DNS: The MAC covers the account key, and the MAC key is derived from an ECDH public key signed with the account private key. <del> Proof of possession of a prior key: The signature by the prior key covers the account public key. </del> The association of challenges to identifiers is typically done by requiring the client to perform some action that only someone who effectively controls the identifier can perform.  For the challenges

DNS: The MAC covers the account key, and the MAC key is derived from an ECDH public key signed with the account private key.  The association of challenges to identifiers is typically done by requiring the client to perform some action that only someone who effectively controls the identifier can perform.  For the challenges


DNS: Provision DNS resource records for the domain <del> Proof of possession of a prior key: Sign using the private key specified by the server </del> There are several ways that these assumptions can be violated, both by misconfiguration and by attack.  For example, on a web server that allows non-administrative users to write to .well-known, any user can

DNS: Provision DNS resource records for the domain  There are several ways that these assumptions can be violated, both by misconfiguration and by attack.  For example, on a web server that allows non-administrative users to write to .well-known, any user can


process, by performing normal ACME transactions and providing a validation response for his own account key.  The risks due to hosting providers noted above are a particular case.  For identifiers <del> where the server already has some credential associated with the domain this attack can be prevented by requiring the client to complete a proof-of-possession challenge. </del>  10.3.

process, by performing normal ACME transactions and providing a validation response for his own account key.  The risks due to hosting providers noted above are a particular case.  For identifiers  <ins> where the server already has some public key associated with the domain this attack can be prevented by requiring the client to prove control of the corresponding private key. </ins> 10.3.


any web server that is accessible to the ACME server, even if it is not accessible to the ACME client. <del> The risk of SSRF through this channel is limited by the fact that the attacker can only control the domain of the URL, not the path. Nonetheless, in order to further limit the SSRF risk, ACME server operators should ensure that validation queries can only be sent to servers on the public Internet, and not, say, web services within the server operator's internal network.  Since the attacker could make requests to these public servers himself, he can't gain anything extra through an SSRF attack on ACME aside from a layer of anonymization. </del>  9.5.

NAME does this look better?
LGTM, though I'd change the attacker from a "he" to a "they" on general principles.
Not a huge fan of the singular "they", but can't be bothered to rewrite around it :)
Yes, this is clearer. Thanks. Saying "will cause the server to query an arbitrary URI" is good. Technically you can even specify a non-HTTP protocol in an HTTP redirect, and this language should cover that too. (Go's net/http used by Boulder only does HTTP and HTTPS I think, but things like libcurl support a slightly insane number of protocols.) I'm not sure if the usages of "URI" vs "URL" in this section are correct, you may want to make them consistent. I never know which one to actually use. This looks good to me.

any web server that is accessible to the ACME server, even if it is not accessible to the ACME client.  <ins> It might seem that the risk of SSRF through this channel is limited by the fact that the attacker can only control the domain of the URL, not the path.  However, if the attacker first sets the domain to one they control, then they can send the server an HTTP redirect (e.g., a 302 response) which will cause the server to query an arbitrary URI. In order to further limit the SSRF risk, ACME server operators should ensure that validation queries can only be sent to servers on the public Internet, and not, say, web services within the server operator's internal network.  Since the attacker could make requests to these public servers himself, he can't gain anything extra through an SSRF attack on ACME aside from a layer of anonymization. </ins> 9.5.


The JWK representation of the new key <del> Both of these thumbprints MUST be computed as specified in RFC7638, using the SHA-256 digest.  The values in the "oldKey" and "newKey" fields MUST be the base64url encodings of the thumbprints. </del> The client then encapsulates the key-change object in a JWS, signed with the client's current account key (i.e., the key matching the "oldKey" value).

We aren't using thumbprints for key-change anymore, so this paragraph doesn't make sense.

The JWK representation of the new key  The client then encapsulates the key-change object in a JWS, signed with the client's current account key (i.e., the key matching the "oldKey" value).


MUST be the exact string provided in the Location header field in response to the new-registration request that created the account. <del> The JWK representation of the original key (i.e., the client's current account key) </del> The JWK representation of the new key The client then encapsulates the key-change object in a JWS, signed

This was part of URL (see removal of oldKey from example payload), but I missed these two other spots. oldKey is fully specified by the account URL in the payload.

MUST be the exact string provided in the Location header field in response to the new-registration request that created the account.  The JWK representation of the new key The client then encapsulates the key-change object in a JWS, signed


Check that the "account" field of the key-change object contains the URL for the registration matching the old key <del> Check that the "oldKey" field of the key-change object contains the current account key. </del> Check that the "newKey" field of the key-change object contains the key used to sign the inner JWS.

Check that the "account" field of the key-change object contains the URL for the registration matching the old key  Check that the "newKey" field of the key-change object contains the key used to sign the inner JWS.


6.3.2.  A client may wish to change the public key that is associated with a account in order to recover from a key compromise or proactively mitigate the impact of an unnoticed key compromise.

This is a variant of that uses a MAC key to perform the account binding instead of a bearer token. Thanks to NAME for pointing out the need for this on the ACME mailing list.
Question: will you require a CA that doesn't use external account bindings to reject a request if it contains an external-account-binding member? nit: s/field/member/g, consistent with RFC 7159.
StartCom plan to use ACME protocol for StartEncrypt, we need to identify the client's validation level, so the subscriber administration can generate a special token in the URL account that send this token to the email address used in the registration. At the registration, user need to enter email and this token with the certificate to let the CA system know this customer's validation level. After the CA system receive the email, the token and signing certificate, CA system know what type of certificate we can issue to this client; if this client account is class 4 validated, then the client can get EV SSL certificate, not DV SSL. please add this a parameter to the ACME protocol, thanks.
This request should be sent to the ACME mailing list (EMAIL) for further discussion, it would also be very useful to know what your EV (or OV) validation flow would look like using ACME as most likely the current certificate application object would need to be changed to identify those requirements to the server.
This was fixed by
Minor editorial comments.

6.3.2. <ins> The server MAY require a value to be present for the "external- account-binding" field.  This can be used to an ACME account with an existing account in a non-ACME system, such as a CA customer database. To enable ACME account binding, a CA needs to provision the ACME client with a MAC key and a key identifier.  The key identifier MUST be an ASCII string.  The MAC key SHOULD be provided in base64url- encoded form, to maximize compatibility between provisioning systems and ACME clients. The ACME client then computes a binding JWS to indicate the external account's approval of the ACME account key.  The payload of this JWS is the account key being registered, in JWK form.  The protected header of the JWS MUST meet the following criteria: The "alg" field MUST indicate a MAC-based algorithm The "kid" field MUST contain the key identifier provided by the CA The "nonce" field MUST NOT be present The "url" field MUST be set to the same value as the outer JWS The "signature" field of the JWS will contain the MAC value computed with the MAC key provided by the CA. When a CA receives a new-registration request containing an "external-account-binding" field, it must decide whether or not to verify the binding.  If the CA does not verify the binding, then it MUST NOT reflect the "external-account-binding" field in the resulting account object (if any).  To verify the account binding, the CA MUST take the following steps: Verify that the value of the field is a well-formed JWS Verify that the JWS protected meets the above criteria Retrieve the MAC key corresponding to the key identifier in the "kid" field Verify that the MAC on the JWS verifies using that MAC key Verify that the payload of the JWS represents the same key as was used to verify the outer JWS (i.e., the "jwk" field of the outer JWS) If all of these checks pass and the CA creates a new account, then the CA may consider the new account associated with the external account corresponding to the MAC key, and MUST reflect value of the "external-account-binding" field in the resulting account object.  If any of these checks fail, then the CA MUST reject the new- registration request. 6.3.3. </ins> A client may wish to change the public key that is associated with a account in order to recover from a key compromise or proactively mitigate the impact of an unnoticed key compromise.


responds with an error status code and a problem document describing the error. <del> 6.3.3. </del>  A client may deactivate an account by posting a signed update to the server with a status field of "deactivated."  Clients may wish to do

responds with an error status code and a problem document describing the error.  <ins> 6.3.4. </ins> A client may deactivate an account by posting a signed update to the server with a status field of "deactivated."  Clients may wish to do


attacker from guessing it.  It MUST NOT contain any characters outside the URL-safe Base64 alphabet. <del> Number of tls-sni-01 iterations </del> A client responds to this challenge by constructing a key authorization from the "token" value provided in the challenge and <del> the client's account key.  The client first computes the SHA-256 digest Z0 of the UTF8-encoded key authorization, and encodes Z0 in UTF-8 lower-case hexadecimal form.  The client then generates iterated hash values Z1...Z(n-1) as follows: The client generates a self-signed certificate for each iteration of Zi with a single subjectAlternativeName extension dNSName that is "<Zi[0:32]>.<Zi[32:64]>.acme.invalid", where "Zi[0:32]" and "Zi[32:64]" represent the first 32 and last 32 characters of the hex- encoded value, respectively (following the notation used in Python). The client then configures the TLS server at the domain such that when a handshake is initiated with the Server Name Indication extension set to "<Zi[0:32]>.<Zi[32:64]>.acme.invalid", the corresponding generated certificate is presented. </del>  The response to the TLS SNI challenge simply acknowledges that the client is ready to fulfill this challenge.

Simplify the TLS SNI challenge by removing the iterations concept, which I believe is not necessary in practice and complicates the protocol needlessly.
Implementing TLS SNI is currently really complicated, yes.
FYI, URL implements protocol according to the contents of this PR - i.e. without iterations.
(so does current Boulder)
I think this will be OK to land once lands. We should consider whether we want to bump the version number in the challenge. Principle would dictate that we should, since this breaks compatibility with what was published in -01. But since I'm not aware of any implementation of "tls-sni-01" as specified in -01 (vs. the off-spec implementation in boulder), I'm inclined to just leave it.
FWIW on the client side of things, xenolf/lego did not implement the iterations for the tls-sni-01 challenge.
URL implements iterations but takes the absence of an "n" parameter to be equivalent to an "n" parameter of 1, which is compatible.
Great, I'm taking this as sufficient evidence that a version bump is not needed :)

attacker from guessing it.  It MUST NOT contain any characters outside the URL-safe Base64 alphabet.  A client responds to this challenge by constructing a key authorization from the "token" value provided in the challenge and  <ins> the client's account key.  The client computes the SHA-256 digest Z of the UTF8-encoded key authorization, and encodes Z in UTF-8 lower- case hexadecimal form. The client generates a self-signed certificate for with a single subjectAlternativeName extension dNSName that is "<Z[0:32]>.<Z[32:64]>.acme.invalid", where "Z[0:32]" and "Z[32:64]" represent the first 32 and last 32 characters of the hex-encoded value, respectively (following the notation used in Python).  The client then configures the TLS server at the domain such that when a handshake is initiated with the Server Name Indication extension set to "<Z[0:32]>.<Z[32:64]>.acme.invalid", the corresponding generated certificate is presented. </ins> The response to the TLS SNI challenge simply acknowledges that the client is ready to fulfill this challenge.


Given a Challenge/Response pair, the ACME server verifies the client's control of the domain by verifying that the TLS server was <del> configured appropriately. Choose a subset of the N iterations to check, according to local policy. </del>  <del> For each iteration, compute the Zi-value from the key authorization in the same way as the client. </del>  Open a TLS connection to the domain name being validated on the requested port, presenting the value <del> "<Zi[0:32]>.<Zi[32:64]>.acme.invalid" in the SNI field (where the </del>  comparison is case-insensitive). Verify that the certificate contains a subjectAltName extension

Given a Challenge/Response pair, the ACME server verifies the client's control of the domain by verifying that the TLS server was  <ins> configured appropriately, using these steps: </ins>  <ins> Compute the Z-value from the key authorization in the same way as the client. </ins> Open a TLS connection to the domain name being validated on the requested port, presenting the value  <ins> "<Z[0:32]>.<Z[32:64]>.acme.invalid" in the SNI field (where the </ins> comparison is case-insensitive). Verify that the certificate contains a subjectAltName extension


no other dNSName entries of the form "*.acme.invalid" are present in the subjectAltName extension. <del> It is RECOMMENDED that the ACME server verify a random subset of the N iterations with an appropriate sized to ensure that an attacker who can provision certs for a default virtual host, but not for arbitrary simultaneous virtual hosts, cannot pass the challenge.  For instance, testing a subset of 5 of N=25 domains ensures that such an attacker has only a one in 25/5 chance of success if they post certs Zn in random succession.  (This probability is enforced by the requirement that each certificate have only one Zi value.) </del> It is RECOMMENDED that the ACME server validation TLS connections from multiple vantage points to reduce the risk of DNS hijacking attacks.

no other dNSName entries of the form "*.acme.invalid" are present in the subjectAltName extension.  It is RECOMMENDED that the ACME server validation TLS connections from multiple vantage points to reduce the risk of DNS hijacking attacks.


This registry lists field names that are defined for use in ACME order objects.  Fields marked as "client configurable" may be <del> included in a new-account request. </del>  Template:

This PR fixes a typo reported by NAME in the "Fields in Order Objects" section. Previously it referred to the listed fields as relating to the "new-account request". This PR changes the text to make it clear they relate to a "new-order request". Resolves URL
Merging based on manual review; CircleCI seems to be busted at the moment.
The section on the "" registry says that "Fields marked as "client configurable" may be included in a new-account request". This seems like a copy-paste-o, and perhaps should say that such fields may be included in a new-order request.
Good catch. I opened URL to fix. Thanks!

This registry lists field names that are defined for use in ACME order objects.  Fields marked as "client configurable" may be  <ins> included in a new-order request. </ins> Template:


Each ACME function is accomplished by the client sending a sequence of HTTPS requests to the server, carrying JSON messages RFC7159.  Use <del> of HTTPS is REQUIRED.  Clients SHOULD support HTTP public key pinning RFC7469, and servers SHOULD emit pinning headers.  Each subsection of certificate-management below describes the message formats used by the function and the order in which messages are sent. </del>  In most HTTPS transactions used by ACME, the ACME client is the HTTPS client and the ACME server is the HTTPS server.  The ACME server acts

Public key pinning isn't implemented in most HTTPS libraries outside of browsers, so this is a considerable burden on implementers. Public key pinning carries a fairly high risk of footgunning. The consequence of a failed pin for a CA that serves many ACME clients would be that some of those clients would fail to renew their certs, causing cascading breakage. There is relatively little confidential information conveyed in ACME, and there are other defenses built into ACME (like including the account key as part of the challenge data), so HPKP is not strongly necessary.

Each ACME function is accomplished by the client sending a sequence of HTTPS requests to the server, carrying JSON messages RFC7159.  Use  <ins> of HTTPS is REQUIRED.  Each subsection of certificate-management below describes the message formats used by the function and the order in which messages are sent. </ins> In most HTTPS transactions used by ACME, the ACME client is the HTTPS client and the ACME server is the HTTPS server.  The ACME server acts


As noted above, DNS forgery attacks against the ACME server can result in the server making incorrect decisions about domain control <del> and thus mis-issuing certificates.  Servers SHOULD verify DNSSEC when it is available for a domain.  When DNSSEC is not available, servers SHOULD perform DNS queries over TCP, which provides better resistance to some forgery attacks than DNS over UDP. </del>  10.2.

Instead of just when not using DNSSEC since you don't know if a domain is secured by DNSSEC until the query is finished. Also rename the section 'DNS Security' since it also talks about DNSSEC. Also combines the 'DNS Security' and 'Use of DNSSEC resolvers sections.

As noted above, DNS forgery attacks against the ACME server can result in the server making incorrect decisions about domain control  <ins> and thus mis-issuing certificates.  Servers SHOULD perform DNS queries over TCP, which provides better resistance to some forgery attacks than DNS over UDP. An ACME-based CA will often need to make DNS queries, e.g., to validate control of DNS names.  Because the security of such validations ultimately depends on the authenticity of DNS data, every possible precaution should be taken to secure DNS queries done by the CA.  It is therefore RECOMMENDED that ACME-based CAs make all DNS queries via DNSSEC-validating stub or recursive resolvers.  This provides additional protection to domains which choose to make use of DNSSEC. An ACME-based CA must use only a resolver if it trusts the resolver and every component of the network route by which it is accessed.  It is therefore RECOMMENDED that ACME-based CAs operate their own DNSSEC-validating resolvers within their trusted network and use these resolvers both for both CAA record lookups and all record lookups in furtherance of a challenge scheme (A, AAAA, TXT, etc.). </ins> 10.2.


the namespace used for the TLS-based challenge (the "acme.invalid" namespace for "tls-sni-02"). <del> 10.3. An ACME-based CA will often need to make DNS queries, e.g., to validate control of DNS names.  Because the security of such validations ultimately depends on the authenticity of DNS data, every possible precaution should be taken to secure DNS queries done by the CA.  It is therefore RECOMMENDED that ACME-based CAs make all DNS queries via DNSSEC-validating stub or recursive resolvers.  This provides additional protection to domains which choose to make use of DNSSEC. An ACME-based CA must use only a resolver if it trusts the resolver and every component of the network route by which it is accessed.  It is therefore RECOMMENDED that ACME-based CAs operate their own DNSSEC-validating resolvers within their trusted network and use these resolvers both for both CAA record lookups and all record lookups in furtherance of a challenge scheme (A, AAAA, TXT, etc.). </del> 11.  References 11.1.  URIs

the namespace used for the TLS-based challenge (the "acme.invalid" namespace for "tls-sni-02").  11.  References 11.1.  URIs


other certificate management functions, such as certificate revocation. <del> DISCLAIMER: This is a work in progress draft of ACME and has not yet had a thorough security analysis. </del> RFC EDITOR: PLEASE REMOVE THE FOLLOWING PARAGRAPH: The source for this draft is maintained in GitHub.  Suggested changes should be submitted as pull requests at https://github.com/ietf-wg-acme/acme

Addresses Martin Stiemerling's TSV-ART review
Merging based on NAME review
On the mailing list, Rifaat Shekh-Yusuf pointed out these issues: Section 7.3.5, first paragraph, second line: A "bind" word is missing between the words "to" and "an" Section 7.4.1, second paragraph, second sentence: "case" should be "cases". When the server builds the authorization object, the document is stating that the response would include "challenges" and "combinations". Remove the "combinations" as it is not being used. Section 7.5.1, the Request URIs in the examples: Should not this be /acme/authz/1234/0?
In "Responding to challenges," we use the term "response fields." These fields are defined by each challenge type, but are not described as "response fields" there. We should add a heading describing them as such in the challenge type definitions.
The other challenges don't expect you to post a payload containing a type field, so it's inconsistent for OOB-01 to do so. It should just take an empty object "{}" as its payload.
This seems fine. It seems to be protected from replay by the and parameters. I think we're OK leaving the challenge name at "oob-01", since this isn't a breaking change.

other certificate management functions, such as certificate revocation.  RFC EDITOR: PLEASE REMOVE THE FOLLOWING PARAGRAPH: The source for this draft is maintained in GitHub.  Suggested changes should be submitted as pull requests at https://github.com/ietf-wg-acme/acme


7.3.5. The server MAY require a value to be present for the "external- <del> account-binding" field.  This can be used to an ACME account with an existing account in a non-ACME system, such as a CA customer database. </del>  To enable ACME account binding, a CA needs to provision the ACME client with a MAC key and a key identifier.  The key identifier MUST

7.3.5. The server MAY require a value to be present for the "external-  <ins> account-binding" field.  This can be used to associate an ACME account with an existing account in a non-ACME system, such as a CA customer database. </ins> To enable ACME account binding, a CA needs to provision the ACME client with a MAC key and a key identifier.  The key identifier MUST


In some cases, a CA running an ACME server might have a completely external, non-ACME process for authorizing a client to issue for an <del> identifier.  In these case, the CA should provision its ACME server </del>  with authorization objects corresponding to these authorizations and reflect them as already valid in any orders submitted by the client.

In some cases, a CA running an ACME server might have a completely external, non-ACME process for authorizing a client to issue for an  <ins> identifier.  In these cases, the CA should provision its ACME server </ins> with authorization objects corresponding to these authorizations and reflect them as already valid in any orders submitted by the client.


the "challenges" dictionary. The client sends these updates back to the server in the form of a <del> JSON object with the response fields required by the challenge type, carried in a POST request to the challenge URL (not authorization URL) once it is ready for the server to attempt validation. </del>  For example, if the client were to respond to the "http-01" challenge in the above authorization, it would send the following request: The server updates the authorization document by updating its <del> representation of the challenge with the response fields provided by </del>  the client.  The server MUST ignore any fields in the response object that are not specified as response fields for this type of challenge. The server provides a 200 (OK) response with the updated challenge

the "challenges" dictionary. The client sends these updates back to the server in the form of a  <ins> JSON object with contents as specified by the challenge type, carried in a POST request to the challenge URL (not authorization URL) once it is ready for the server to attempt validation. </ins> For example, if the client were to respond to the "http-01" challenge in the above authorization, it would send the following request: The server updates the authorization document by updating its  <ins> representation of the challenge with the response object provided by </ins> the client.  The server MUST ignore any fields in the response object that are not specified as response fields for this type of challenge. The server provides a 200 (OK) response with the updated challenge


Clients SHOULD NOT respond to challenges until they believe that the server's queries will succeed.  If a server's initial validation <del> query fails, the server SHOULD retry the query after some time. While the server is still trying, the status of the challenge remains "pending"; it is only marked "invalid" once the server has given up. </del>  The server MUST provide information about its retry state to the client via the "errors" field in the challenge and the Retry-After

Clients SHOULD NOT respond to challenges until they believe that the server's queries will succeed.  If a server's initial validation  <ins> query fails, the server SHOULD retry the query after some time, in order to account for delay in setting up responses such as DNS records or HTTP resources.  The precise retry schedule is up to the server, but server operators should keep in mind the operational scenarios that the schedule is trying to accommodate.  Given that retries are intended to address things like propagation delays in HTTP or DNS provisioning, there should not usually be any reason to retry more often than every 5 or 10 seconds.  While the server is still trying, the status of the challenge remains "pending"; it is only marked "invalid" once the server has given up. </ins> The server MUST provide information about its retry state to the client via the "errors" field in the challenge and the Retry-After


for a human user to navigate to.  If the user chooses to complete this challenge (by visiting the website and completing its instructions), the client indicates this by sending a simple <del> acknowledgement response to the server. The string "oob-01" </del>  On receiving a response, the server MUST verify that the value of the "type" field is "oob-01".  Otherwise, the steps the server takes to

for a human user to navigate to.  If the user chooses to complete this challenge (by visiting the website and completing its instructions), the client indicates this by sending a simple  <ins> acknowledgement response to the server.  The payload of this response is an empty JSON object ("{}", or "e30" base64url-encoded). </ins> On receiving a response, the server MUST verify that the value of the "type" field is "oob-01".  Otherwise, the steps the server takes to


according to this encoding, then the verifier MUST reject the JWS as malformed. <del> 5.6. Certain elements of the protocol will require the establishment of a shared secret between the client and the server, in such a way that an entity observing the ACME protocol cannot derive the secret.  In these cases, we use a simple ECDH key exchange, based on the system used by CMS RFC5753: Inputs: Client-generated key pair Server-generated key pair Length of the shared secret to be derived Label Perform the ECDH primitive operation to obtain Z (Section 3.3.1 of SEC1) Select a hash algorithm according to the curve being used: For "P-256", use SHA-256 For "P-384", use SHA-384 For "P-521", use SHA-512 Derive the shared secret value using the KDF in Section 3.6.1 of SEC1 using Z and the selected hash algorithm, and with the UTF-8 encoding of the label as the SharedInfo value In cases where the length of the derived secret is shorter than the output length of the chosen hash algorithm, the KDF referenced above reduces to a single hash invocation.  The shared secret is equal to the leftmost octets of the following: </del> 6. In this section, we describe the certificate management functions

As discussed at the F2F meeting at IETF94, MAC-based account recovery is not adding a lot of value, and it adds significant complexity to the spec. (And nobody has implemented it.) This PR removes MAC-based recovery and the crypto that it depends on.
Seeing no complaints on the mailing list, merging.

according to this encoding, then the verifier MUST reject the JWS as malformed.  6. In this section, we describe the certificate management functions


registration, to allow a client to retrieve the "new-authorization" and "terms-of-service" URI <del> 6.3.1. If the client wishes to establish a secret key with the server that it can use to recover this account later (a "recovery key"), then it must perform a simple key agreement protocol as part of the new- registration transaction.  The client and server perform an ECDH exchange through the new-registration transaction (using the technique in key-agreement), and the result is the recovery key. To request a recovery key, the client includes a "recoveryKey" field in its new-registration request.  The value of this field is a JSON object. The client's ECDH public key The length of the derived secret, in octets. In the client's request, this object contains a JWK for a random ECDH public key generated by the client and the client-selected length value.  Clients need to choose length values that balance security and usability.  On the one hand, a longer secret makes it more difficult for an attacker to recover the secret when it is used for recovery (see mac-based-recovery).  On the other hand, clients may wish to make the recovery key short enough for a user to easily write it down. The server MUST validate that the elliptic curve ("crv") and length value chosen by the client are acceptable, and that it is otherwise willing to create a recovery key.  If not, then it MUST reject the new-registration request. If the server agrees to create a recovery key, then it generates its own random ECDH key pair and combines it with the client's public key as described in key-agreement above, using the label "recovery".  The derived secret value is the recovery key.  The server then returns to the client the ECDH key that it generated.  The server MUST generate a fresh key pair for every transaction. The server's ECDH public key On receiving the server's response, the client can compute the recovery key by combining the server's public key together with the private key corresponding to the public key that it sent to the server. Clients may refresh the recovery key associated with a registration by sending a POST request with a new recoveryKey object.  If the server agrees to refresh the recovery key, then it responds in the same way as to a new registration request that asks for a recovery key. </del> 6.4. Once a client has created an account with an ACME server, it is

registration, to allow a client to retrieve the "new-authorization" and "terms-of-service" URI  6.4. Once a client has created an account with an ACME server, it is


storage provider, and give the encryption key to the user as a recovery value. <del> 6.4.1. With MAC-based recovery, the client proves to the server that it holds a secret value established in the initial registration transaction.  The client requests MAC-based recovery by sending a MAC over the new account key, using the recovery key from the initial registration. The string "mac" The URI for the registration to be recovered. A JSON-formatted JWS object using an HMAC algorithm, whose payload is the JWK representation of the public key of the new account key pair. On receiving such a request the server MUST verify that: The base registration has a recovery key associated with it The "alg" value in the "mac" JWS represents a MAC algorithm The "mac" JWS is valid according to the validation rules in RFC7515, using the recovery key as the MAC key The JWK in the payload represents the new account key (i.e. the key used to verify the ACME message) If those conditions are met, and the recovery request is otherwise acceptable to the server, then the recovery process has succeeded. The server creates a new registration resource based on the base registration and the new account key, and returns it on a 201 (Created) response, together with a Location header indicating a URI for the new registration.  If the recovery request is unsuccessful, the server returns an error response, such as 403 (Forbidden). 6.4.2. In the contact-based recovery process, the client requests that the server send a message to one of the contact URIs registered for the account.  That message indicates some action that the server requires the client's user to perform, e.g., clicking a link in an email.  If the user successfully completes the server's required actions, then the server will bind the account to the new account key. </del>  (Note that this process is almost entirely out of band with respect to ACME.  ACME only allows the client to initiate the process, and the server to indicate the result.) <del> To initiate contact-based recovery, the client sends a POST request to the server's recover-registration URI, with a body specifying which registration is to be recovered.  The body of the request MUST be signed by the client's new account key pair. </del>  The string "contact" The URI for the registration to be recovered. <del> If the server agrees to attempt contact-based recovery, then it creates a new registration resource containing a stub registration object.  The stub registration has the client's new account key and contacts, but no authorizations or certificates associated.  The server returns the stub contact in a 201 (Created) response, along with a Location header field indicating the URI for the new registration resource (which will be the registration URI if the recovery succeeds). </del>  After recovery has been initiated, the server follows its chosen recovery process, out-of-band to ACME.  While the recovery process is

storage provider, and give the encryption key to the user as a recovery value.  <ins> The client requests recovery by asking that the server send a message to one of the contact URIs registered for the account.  That message indicates some action that the server requires the client's user to perform, e.g., clicking a link in an email.  If the user successfully completes the server's required actions, then the server will bind the account to the new account key. </ins> (Note that this process is almost entirely out of band with respect to ACME.  ACME only allows the client to initiate the process, and the server to indicate the result.)  <ins> To initiate recovery, the client sends a POST request to the server's recover-registration URI, with a body specifying which registration is to be recovered.  The body of the request MUST be signed by the client's new account key pair. </ins> The string "contact" The URI for the registration to be recovered.  <ins> If the server agrees to attempt recovery, then it creates a new registration resource containing a stub registration object.  The stub registration has the client's new account key and contacts, but no authorizations or certificates associated.  The server returns the stub contact in a 201 (Created) response, along with a Location header field indicating the URI for the new registration resource (which will be the registration URI if the recovery succeeds). </ins> After recovery has been initiated, the server follows its chosen recovery process, out-of-band to ACME.  While the recovery process is


is the only one that can choose the new account key that receives the capabilities held by the account being recovered. <del> MAC-based recovery can be performed if the attacker knows the account key and registration URI for the account being recovered.  Both of these are difficult to obtain for a network attacker, because ACME uses HTTPS, though if the recovery key and registration URI are sufficiently predictable, the attacker might be able to guess them. An ACME MitM can see the registration URI, but still has to guess the recovery key, since neither the ECDH in the provisioning phase nor HMAC in the recovery phase will reveal it to him. ACME clients can thus mitigate problems with MAC-based recovery by using long recovery keys.  ACME servers should enforce a minimum recovery key length, and impose rate limits on recovery to limit an attacker's ability to test different guesses about the recovery key. Contact-based recovery uses both the ACME channel and the contact channel.  The provisioning process is only visible to an ACME MitM, and even then, the MitM can only observe the contact information provided.  If the ACME attacker does not also have access to the contact channel, there is no risk. The security of the contact-based recovery process is entirely dependent on the security of the contact channel.  The details of this will depend on the specific out-of-band technique used by the server.  For example: </del>  If the server requires a user to click a link in a message sent to a contact address, then the contact channel will need to ensure

is the only one that can choose the new account key that receives the capabilities held by the account being recovered.  <ins> Account recovery uses both the ACME channel and the contact channel. The provisioning process is only visible to an ACME MitM, and even then, the MitM can only observe the contact information provided.  If the ACME attacker does not also have access to the contact channel, there is no risk. The security of the recovery process is entirely dependent on the security of the contact channel.  The details of this will depend on the specific out-of-band technique used by the server.  For example: </ins> If the server requires a user to click a link in a message sent to a contact address, then the contact channel will need to ensure


In practice, many contact channels that can be used to reach many clients do not provide strong assurances of the types noted above. <del> In designing and deploying contact-based recovery schemes, ACME servers operators will need to find an appropriate balance between using contact channels that can reach many clients and using contact- based recovery schemes that achieve an appropriate level of risk using those contact channels. </del>  9.4.

In practice, many contact channels that can be used to reach many clients do not provide strong assurances of the types noted above.  <ins> In designing and deploying recovery schemes, ACME servers operators will need to find an appropriate balance between using contact channels that can reach many clients and using contact-based recovery schemes that achieve an appropriate level of risk using those contact channels. </ins> 9.4.


certificate. If the revocation succeeds, the server responds with status code 200 <del> (OK).  If the revocation fails, the server returns an error. </del>  8.

NAME This definitely needs to be reviewed.
This looks good to me.
I like the idea of a special compound error type to indicate that the subproblems field is used.
In s7.6, it seems like we should indicate what error is returned: If the revocation fails, the server returns an error. The draft this nicely in many others places in the draft.
I mentioned this earlier on the mailing list, but it did not receive any feedback: as a ACME client developer, I would like to be able to distinguish between errors which do not require user interaction (that would be "certificate is already revoked, so can't revoke it again"), and ones where the user must be warned that the operation did not succeed ("certificate could not be revoked", "bad credentials", etc.). This is currently only possible with server-specific ugly hacks (for example, returns this information, but other servers might return it differently or this might change in later versions of Boulder as it is not specified).
This is a good idea, sorry for missing it earlier. NAME - Do you have any thoughts on other cases besides "already revoked" that would (a) not require user interaction and (b) not be covered by other current error codes? NAME - Would you mind making a PR to add an error code (and anything else that NAME comes up with), and note it in the revocation section?
I thought of one to consider in :
It looks like Boulder uses 404 and a generic malformed problem type for this case: URL URL
NAME So far I couldn't think of anything else. I'm totally happy with :-)
Fixed by
:+1: Thanks!

certificate. If the revocation succeeds, the server responds with status code 200  <ins> (OK).  If the revocation fails, the server returns an error.  For example, if the certificate has already been revoked the server returns an error response with status code 400 (Bad Request) and type "urn:ietf:params:acme:error:alreadyRevoked". </ins> 8.