It's...way too many rows, now that I have the actual data. It needs to be reworked.
I originally wasn't going to do passwords, but after struggling with webauthn I decided I'd just go for it. It simplifies the code a lot if I assert that I always have a password, displayname, etc.
This isn't quite perfect, but gets much of the hard work done.