timescale.info
Sign inSign up

How OpenChronology was built

Every merged pull request of openchronology/timeline-app, its first week of commits and its releases; and before them the 2020 PureScript editor, from snapshots of its deleted repositories in the Wayback Machine. Written to this server through the HTTP API.

327 moments · 2020-03-09T00:15:08Z CE – 2026-11-02T20:11:21Z CE · by @athan · @athan

#410 · Sign-in: verification instead of a per-account limit, and queued password checks

  • timeline-app
  • pull request
  • security

## Summary **Per-account sign-in handling** - Removes the hard per-username sign-in limit. After three failures in fifteen minutes for an account (or from an address), each further attempt must pass human verification. This existing check is now the only per-account measure, so the account's owner can always sign in by passing it. - With `CHALLENGE_PROVIDER=off`, the same failures delay each further sign-in for that account by 1.5 seconds. They are never refused. - Directory (LDAP) sign-in follows the same rule. Linking a directory account is now limited per signed-in account and per address, not per directory name. - The per-address limits are unchanged. **Password-check capacity** - The concurrent scrypt cap is now sized from `os.availableParallelism()`: one slot per core, at least two, and below libuv's worker threads (`UV_THREADPOOL_SIZE`, default 4). That gives three slots with the defaults. - The new setting `PASSWORD_HASH_CONCURRENCY` (1–64) overrides it. - A check that finds every slot busy waits in a first-come, first-served line for up to five seconds before getting `503`. Before, it got `503` at once. The line is bounded at 32 waiters per slot. - Sign-in, registration, password reset and change, and the admin password tools all share these slots. - Unknown usernames still do the same derivation through the same line and slot. Timing equalisation and the scrypt parameters are unchanged. - A password reset link is checked to exist before the breach lookup and the hashing. **Docs** - `docs/authentication.md`, the OpenAPI descriptions (sign-in, register, reset), `.env.example`, `compose.yml` and the Debian env template are updated. ## Tests - `test/challenge-postgres.mjs` (`pow`): a dozen challenged failures for an account, each from its own address, then its owner signs in. Without this change this gets 429. - `test/postgres.mjs` (`off`): - A dozen failures for an account, then its owner signs in, delayed but not refused. Without this change this gets 429. - A burst of unknown-username sign-ins plus the owner's sign-in against two slots: all are answered. Without this change some get 503. - `test/auth.test.mjs`: parsing of the slot setting; checks queue and finish; a wait that runs out gives 503. - `test/challenge.test.mjs`: `signInGate` delays under `off` and asks for verification (428) under `pow`. - Also passing: `npm test` (404 tests), `test/account-security-postgres.mjs` and `test/ldap-postgres.mjs`.

Sources

Open #410 · Sign-in: verification instead of a per-account limit, and queued password checks in the timeline