well in that version it would be accouturl/unpause: rando would be able to do unpause other's account, but doing so doesn't hurt target at all:
If you can adjust the definition per account, each account could have a "decay timer", the number of seconds (minutes/hours/whatever) for which a failure remains an indicator of consistent failure of that identifier. Each request from a particular identifier happens at time T0, and sets TP (previous time) to the previous value of T0. A failure bumps fail_count by one and if it reaches 50 then we consider the failure to be consistent. A successful validation resets fail_count to zero. If T0 - TP is greater than the decay_timer, then we reduce fail_count by 1, but double decay_timer. This allows consistent failures to continue as long as there are larger and larger delays between them. For your 50 failures in 90 days, the decay timer would start at 43 hours. Cutting the 50-in-90 to 25-in-45 could potentially save a lot of resources.
It might be a good idea to just put the number of identifiers paused into the error message (e.g. "seven" (or however many it actually was) instead of "certain").
"the clients would register new accounts and continue making the same requests. ... the option to 'unpause' themselves... ." stuck out to me. If they would register new accounts without fixing the issue, why wouldn't they also 'unpause' without fixing it?
A slightly higher level of attention can be motivated by simply collecting information at the time the 'unpause' option is used: Require that the user, in addition to pushing the "Please Unpause My Account" button, also select what they fixed:
-
Expired Domain
-
Hostname IP address changed
-
DNS configuration
-
Other webserver settings
-
Multiple or Not Listed
Such data collection would probably benefit ESRG as well.
The sample log entry in Scenario 1 indicates no date/time in the log. Timestamps in the log would be useful.
"... after consistently failing validation attempts" suggests that the attempts may have failed for transient reasons, and so some portion of the "under 1M accounts" will simply use the unpause feature without fixing anything, just to make sure that the consistency of failure is still there. If there is a weak portion of the internet involved and they know it, their simple retry strategy might persist. Perhaps the "consistency of failure" can be spelled out (and maybe even adjusted per account) so that any abusive "simple retry strategy" can be detected and used to raise the bar for those accounts (and possibly even create opportunities for paid support that LetsEncrypt can use for additional revenue).
The staging environment seems very useful. Might it be wise to have every attempt to unpause go through the staging environment before the user can try the real thing? (Maybe that already happens?)
I think it would be a good idea for the Self-Service Portal to describe the heuristics you tell us about here, plus any others. For example, "Your unpause link was created with a lifetime of two weeks, of which N days are left."
In the "Expired unpause URL" message, why not say "two weeks" instead of "a short period of time"? This provides customers with a bit more useful data.
In the "Some identifiers were unpaused" message, why not use "50000" in the sentence instead of "a limited number of identifiers" with (50000) at the end?
Also, "please visit unpause URL from your logs again" should be either "please visit THE unpause URL..." or "please visit A DIFFERENT/NEWER unpause URL...", whichever is best for the LetsEncrypt validation server. The lack of "the" in there confuses the two.