SPB Git

Repository Public MIT

0009-human-authentication-v1.md 2.1 KB

# ADR-0009 — Human authentication in V1

Status: accepted for V1, 2026-11-09. Deviation from the brief, which preferred Auth.js with passkeys and OAuth.

# Context

Passkeys and OAuth sign-in need registered OAuth applications, a mail sender for verification and recovery, and product decisions about open registration. None of these were available at build time, and the launch has one human user: the owner.

# Decision

  • Email and password. Passwords are 12–200 characters, hashed with argon2id (19 MiB memory, 2 iterations).
  • Sessions are rows in PostgreSQL. The cookie skills_session carries a 256-bit random value; the database stores only its keyed HMAC. Lifetime 12 hours.
  • Cookie-authenticated writes to the API require a same-origin Origin header and a per-session CSRF token in X-CSRF-Token.
  • Sensitive actions (creating or rotating tokens) require the password to have been entered within the last 15 minutes.
  • Login is rate limited per IP and email (8 attempts per 15 minutes). Unknown accounts are verified against a dummy hash so timing does not reveal whether an email exists. Failures are audited.
  • Changing the password revokes the user's other sessions.
  • Accounts are created by the operator from the server console (pnpm admin:bootstrap, pnpm admin user create) with a generated initial password that must be changed at first sign-in. Until it is changed, the session cannot use the API.
  • Recovery is a console command (pnpm admin recover), which also revokes all of the user's sessions.
  • The first administrator is bound to the owner by possession of shell access on the server. The email is recorded as verified with the note operator-attested; no mail is sent.

# Planned

TOTP, passkeys (WebAuthn), OAuth sign-in (the auth_identities table is in place), self-service registration with email verification, mailed password reset.

# Consequences

  • No second factor yet: the owner account is protected by one strong password and by the fact that elevated API tokens are short-lived.
  • No open registration: contributors are onboarded by the operator.
  • No dependency on an external identity provider.
Files main
Menu

Theme