Commit 8c430f898a

8c430f898a0bccf46414f87769d5655678fda7c0

parent: b24bfe450b

Verified · cmc

cmc <hello@cleberg.net> · 2026-09-05 03:10 UTC

Design: name the store file, specify the empty identifier

Ref #155

Layout: unified · split

docs/specs/2026-09-04-email-login-design.md +3 −2
@@ -62,7 +62,8 @@ anyone at a terminal has SSH and already has `web login`.
62Resolution: an identifier containing `@` goes to `store.UserIDByVerifiedEmail`; 62Resolution: an identifier containing `@` goes to `store.UserIDByVerifiedEmail`;
63otherwise look up the username and take `store.PrimaryVerifiedEmail`. Both 63otherwise look up the username and take `store.PrimaryVerifiedEmail`. Both
64exist. Only verified addresses resolve; an unverified one is treated as no 64exist. Only verified addresses resolve; an unverified one is treated as no
65match. 65match. An empty or whitespace-only identifier resolves to no match by the same
66path, so it draws the same response as everything else.
66 67
67The body follows `sendVerification` (`internal/control/register.go:41`) and 68The body follows `sendVerification` (`internal/control/register.go:41`) and
68ends in `mail.Send`. 69ends in `mail.Send`.
@@ -126,7 +127,7 @@ separate policy question that widens the open-registration spam surface.
126| Path | Change | 127| Path | Change |
127|---|---| 128|---|---|
128| `internal/control/loginlink.go` | new — `RequestLoginLink` | 129| `internal/control/loginlink.go` | new — `RequestLoginLink` |
129| `internal/store/` | new — `CountLoginTokensSince` | 130| `internal/store/sessions.go` | new — `CountLoginTokensSince`, beside `CreateLoginToken` |
130| `internal/httpd/accounts.go` | `loginSubmit` handler; cookie `SameSite` | 131| `internal/httpd/accounts.go` | `loginSubmit` handler; cookie `SameSite` |
131| `internal/httpd/routes.go` | `POST /login` | 132| `internal/httpd/routes.go` | `POST /login` |
132| `internal/web/templates/login.html` | the request form | 133| `internal/web/templates/login.html` | the request form |