Commit Graph

3 Commits

Author SHA1 Message Date
Wanjohi
74391714d0 feat(auth): draw the sign-in screen in the product's design language
The screen was still the upstream template's: its font, its accent, its
logo, and a theme that tried to serve a light and a dark scheme from one
set of colours by deriving each one from the background's lightness.

That derivation is replaced with stated values, and the page is dark only.
Black, a neutral grey ramp, one brand accent, Mona Sans for the display
line and Geist for anything read or typed; two dashed bands closing into a
box on a wide screen, a dashed vertical either side of the column, the
wordmark, and the line of copy the rest of the product opens with.

The email field keeps the fix from the previous commit and takes the brand
colour on focus, which is the only place it appears besides the wordmark.

Measured against a render of the same design built from its own source:
the band rules, the column rules, the wordmark box and the button height
land on identical pixels.
2026-09-17 23:05:39 +03:00
Wanjohi
355d1492d9 fix(auth): give a sign-in code a budget of guesses and a short life
A six-digit code has a million values, and nothing was counting how many
of them a caller tried. The code travelled in an encrypted cookie the
caller held, verification compared against that cookie, and a wrong
answer simply re-rendered the form. Nobody has to be the person the code
was mailed to: type somebody else's address into the first screen and the
code goes to their mailbox while the cookie stays with you. At that point
the only thing between a stranger and an account is a million requests,
and the constant-time comparison protecting the code was guarding a door
you could just keep knocking on.

Guesses are now counted on the server, under a name that changes with
every code. That placement is the point: a counter kept beside the code,
in the cookie, is a counter the guesser can wind back by replaying an
older copy. Starting over is still allowed and still costs a fresh code
sent to the mailbox being aimed at, which is where somebody notices. A
correct code spends its record too, so its remaining guesses do not carry
into the next one.

The cookie also lived for twenty-four hours, which made the pin a
password with a million possible values and a day to try them. Ten
minutes now, and the code stops being accepted when the clock says so
rather than when the cookie happens to go away.

Resend had no limit either, so the button was a way to mail a stranger as
fast as requests go out. Codes to one address are spaced, and one attempt
at signing in can only ask for so many.

Both refusals say the same thing on purpose. Which of the two it was is a
fact about somebody else's mailbox.
2026-09-05 09:44:32 +03:00
Wanjohi
3faac3008f feat: Sync to OSS repo 2026-08-06 22:13:51 +03:00