Skip to main content

auth

First-run setup, sessions and TOTP over TCP. The Unix socket needs none of this — it is peer-credential trusted — but these operations still run on it, unauthenticated, exactly as they do on TCP, since the same handlers serve both transports.

📄️Log in

Username is matched case-insensitively, using simple lowercasing rather than full Unicode case folding. Password, plus a TOTP code once the account has TOTP enrolled. Rate-limited and lockout-protected per account and per source address: an unknown username and a wrong password against a real one get the same status and error code (`invalid_credentials`), reach lockout (`rate_limited`) at the same failure threshold, and cost the same bounded argon2id-shaped work either way, for similar timing, under ordinary load — under a sustained flood large enough to fill and evict from the unknown-username table's own 10,000-entry cap, an unknown username's lockout can lift early, where a real account's own (never capped or evicted) would not. Once the password is correct, `totp_required` (no code supplied) versus `totp_invalid` (a wrong one) does reveal that an account has TOTP enrolled — an unavoidable, rate-limited signal, not one this API tries to hide.

📄️Start TOTP enrolment for the signed-in user

Generates a new secret (RFC 6238), stored encrypted with the machine key but not yet active — the account's existing active credential, if any, is untouched until confirmTotp activates the new one. Enrolling again before confirming replaces the still-pending secret. Once TOTP is already active on this account, replacing it requires proving the caller still holds the account: exactly one of the current password or a current TOTP code, in TotpEnrollRequest. Omitting both while TOTP is active is refused (totp_reverify_required); supplying both is refused too (totp_reverify_ambiguous), since each is one guess at the active credential and honouring both would spend two for the price of one request. Neither is required for a first enrolment.