feat(auth): A2 — sign in by mailed code on web, iOS, Mac and CLI#291
Merged
Conversation
The four clients for the A1 endpoints. Everywhere the shape is the same:
type an address, get six digits, you're in — and if the address is new
that same step creates the account, because reading the mail is the proof.
Passwords move one layer down ("Use a password instead") rather than away.
- web login page: code-first, with the step revealed only after a code is
actually sent, the confirmation naming the address, and editing the
address rewinding a step (an outstanding code belongs to the old one).
A burned or expired code returns to "send one" instead of leaving a
dead field. LOGIN_HTML joins the inline-<script> syntax guard.
- iOS: one form serves both Settings and onboarding, so they can't drift.
SignInCodeError carries the server's typed reason — status alone can't
tell "a code just went out" from "too many today", and those need
different words.
- Mac menu-bar app: "Email me a code", then whichever credential is
filled signs in (code first, else password).
- CLI: `lisa login` mails a code by default; `--password` keeps the old
path. Wrong digits retry in place while the code is still live.
Two fixes found while testing the CLI end-to-end:
- one readline interface per command instead of one per prompt. A fresh
interface drops what the previous reader buffered, so every prompt
after the first read nothing as soon as stdin wasn't a terminal.
- an unreachable server is now a typed `unreachable` result rather than
an exception caught by a blanket handler that reported every error —
including bugs — as "could not reach".
Also documents login/logout/billing in `lisa --help`, which never listed
them.
Plan: docs/PLAN_AUTH_OTP_GOOGLE_v1.0.md (A2).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Owner
Author
|
Reviewed as security-critical client auth. No blockers — ready to merge. Verified good
Non-blocking note
Nice touch disabling the buttons during an in-flight request — it doubles as double-submit / attempt-burn protection. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #290. The four clients for the A1 endpoints.
Everywhere the shape is the same: type an address, get six digits, you're in — and if the address is new that same step creates the account. Passwords move one layer down ("Use a password instead") rather than away.
Per client
LOGIN_HTMLnow joins the inline-<script>syntax guard (it wasn't covered).SignInCodeErrorcarries the server's typed reason: the status alone can't tell "a code just went out" from "too many today", and those need different words.lisa loginmails a code by default;--passwordkeeps the old path. Wrong digits retry in place while the code is still live (the server burns it after five, so three tries is safe).Two fixes found while testing the CLI end-to-end
Both pre-existing, both hit immediately once there was a second prompt:
catcharound the login helper reported every error — including bugs — as "could not reach", which is how the first version of this hid a real failure from me.Also documents
login/logout/billinginlisa --help, which never listed them.Verification
swiftc -typecheckagainst the iOS 17 simulator SDK withLISA_ENABLE_SIWA(xcodegen isn't installed here, so this stands in for a project build; I confirmed the check does catch injected errors rather than passing vacuously).swift buildclean.npm test→ 1173 green, typecheck clean.🤖 Generated with Claude Code