Settings › Security & sessions still had the full 2FA enrolment flow — QR code, secret key, Set up — for something you cannot then sign in with. Turning 2FA on there took a working account and made webmail unreachable from any device not already signed in: ihasmail has nowhere to send a TOTP code, because Stalwart accepts one through an OAuth flow alone and offers no password grant (#75). The one mercy was that enabling reseals the current session onto a fresh app password, so the browser doing it stayed in — and the next sign-in elsewhere did not.
The enrolment path is gone until sign-in with a code works.
Turning 2FA off stays. It is a plain registry write, it was verified live on 0.16.19, and anyone already enrolled — here or in Stalwart's own settings — needs a way back. That control is now the whole section, and it renders only for an account with otpEnabled; everyone else no longer sees the heading at all.
The password form keeps its authenticator-code field on the same condition, since Stalwart demands a code on every credential write once 2FA is on.
Not changed
Server — /api/account/2fa/begin and /enable are untouched and still tested, ready for the OAuth work that makes them usable.
Sign-in page — its code field already explains itself and points at app passwords (#77).
web/src/ui/qrcode.tsx has no caller now; left in place for when enrolment returns.
Docs
README no longer advertises enrolment by QR code, and the roadmap entry says which direction the setting still moves.
Verification
npm run typecheck, npm test (77 pass), npm run build all clean.
Settings › Security & sessions still had the full 2FA enrolment flow — QR code, secret key, **Set up** — for something you cannot then sign in with. Turning 2FA on there took a working account and made webmail unreachable from any device not already signed in: ihasmail has nowhere to send a TOTP code, because Stalwart accepts one through an OAuth flow alone and offers no password grant ([#75](https://github.com/LINUXexpert-org/ihasmail/issues/75)). The one mercy was that enabling reseals the current session onto a fresh app password, so the browser doing it stayed in — and the next sign-in elsewhere did not.
The enrolment path is gone until sign-in with a code works.
**Turning 2FA off stays.** It is a plain registry write, it was verified live on 0.16.19, and anyone already enrolled — here or in Stalwart's own settings — needs a way back. That control is now the whole section, and it renders only for an account with `otpEnabled`; everyone else no longer sees the heading at all.
The password form keeps its authenticator-code field on the same condition, since Stalwart demands a code on every credential write once 2FA is on.
### Not changed
- **Server** — `/api/account/2fa/begin` and `/enable` are untouched and still tested, ready for the OAuth work that makes them usable.
- **Sign-in page** — its code field already explains itself and points at app passwords (#77).
- `web/src/ui/qrcode.tsx` has no caller now; left in place for when enrolment returns.
### Docs
README no longer advertises enrolment by QR code, and the roadmap entry says which direction the setting still moves.
### Verification
`npm run typecheck`, `npm test` (77 pass), `npm run build` all clean.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
**Merged** 2026-08-26 as coffey-labs/ihasmail@4dd46b156c55
<sub>Rebuilt from: git history, session transcript.</sub>
This repo is archived. You cannot comment on issues.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Settings › Security & sessions still had the full 2FA enrolment flow — QR code, secret key, Set up — for something you cannot then sign in with. Turning 2FA on there took a working account and made webmail unreachable from any device not already signed in: ihasmail has nowhere to send a TOTP code, because Stalwart accepts one through an OAuth flow alone and offers no password grant (#75). The one mercy was that enabling reseals the current session onto a fresh app password, so the browser doing it stayed in — and the next sign-in elsewhere did not.
The enrolment path is gone until sign-in with a code works.
Turning 2FA off stays. It is a plain registry write, it was verified live on 0.16.19, and anyone already enrolled — here or in Stalwart's own settings — needs a way back. That control is now the whole section, and it renders only for an account with
otpEnabled; everyone else no longer sees the heading at all.The password form keeps its authenticator-code field on the same condition, since Stalwart demands a code on every credential write once 2FA is on.
Not changed
/api/account/2fa/beginand/enableare untouched and still tested, ready for the OAuth work that makes them usable.web/src/ui/qrcode.tsxhas no caller now; left in place for when enrolment returns.Docs
README no longer advertises enrolment by QR code, and the roadmap entry says which direction the setting still moves.
Verification
npm run typecheck,npm test(77 pass),npm run buildall clean.🤖 Generated with Claude Code
Merged 2026-08-26 as coffey-labs/ihasmail@4dd46b156c
Rebuilt from: git history, session transcript.