Hi, amichal. Nice finds. I will dig into more of the particulars where sensible. Please feel free to send up a pull request! Thanks for taking a peek.
Pretty sure all those are covered, upon more careful review. PRs open!
Edit: The create account I hadn't thought of for the email enum. Thanks!
Edit 2: Fixed up two schema issues identified and the last mitigated already via call: await passwords.rejectPasswordWithConstantTime(validatedData.password)
On the login... when failing either via user lookup, or password mismatch, I'll usually put a random 500-2500ms (or more) delay before logging and sending the response to handle timing attacks.
You can try a db transaction against a lock table for IP and Username as part of multi-request mitigation during any given request. CF offers Durable objects that can be used for this purpose. Return "too many requests" error if a request is sent before another is finished... this will slow things down.
On the minimum passphrase, there are some libraries you can use to get the printable character length... note: you should always normalize (NFC or NFKC) before doing any hashing or validation.
Personally, I usually just transparently set a max of 1024 bytes, I don't display a hint for it at runtime, only an error on submit though... if someone exceeds that, they deserve the generic error I return.Email validation can be a bit rough, depending on how permissive or restricting you want to be. If you're willing to wait for a DNS/MX check on the domain, that's a good place to start. You most likely don't want less than 5 characters or more than 100.