Skip to content
This repository was archived by the owner on Oct 5, 2026. It is now read-only.

Rate-limit numbers: magic-link 429 tests and documented quotas with reasoning - #52

Merged
ParallelEntrepreneur merged 1 commit into
mainfrom
colonizer/issue-12-f9b67d10
Sep 22, 2026
Merged

ParallelEntrepreneur merged 1 commit into
mainfrom
colonizer/issue-12-f9b67d10

Conversation

@ParallelEntrepreneur

Copy link
Copy Markdown
Contributor

Closes the remaining unverified half of #12. The enforcement (#42 password,
#43 magic links) already shipped; what was missing was the last acceptance
box — "limits documented with the reasoning for each number" — plus any
assertion of the numbers at all.

What changed and why:

  • crates/auth-magic-link/tests/magic_link.rs: the test kit now wires a
    FakeRateLimiter (default allow-all, so existing tests are unaffected) and
    gains two tests mirroring the password suite — a denied limiter yields 429
    • Retry-After with zero mails and zero single_use_tokens rows, and one
      request produces >= 2 limit() calls, proving the normalized email is a
      key alongside the caller (so a botnet cannot walk past the per-IP limit).
  • crates/auth-password/README.md and crates/auth-magic-link/README.md:
    new "Rate limits" sections tabling every limit with its reasoning —
    login per-IP 10/min, per-email 5/15min, lockout 10 failures/hour + 15-min
    freeze, magic-link request per-IP 5/10min and per-email 3/hour,
    registration/change per-IP (the proposal sets no number there; the docs say
    so and recommend the login IP-bucket policy). Both sections state plainly
    that this repo owns the key strings (auth-password:, auth-magic-link:
    over rate_limit_keys(ip, email)) and the 429/Retry-After behavior while
    the numeric quotas live in harness RateLimiter adapter/deployment config.

Notes for reviewers:

  • Verified against code that magic-link/passkey login bypasses but never
    clears a password lockout (zero lockout-column writes outside auth-password
    and set_password_hash); the docs describe bypass + 15-min age-out, not
    clearing. Neither README previously claimed otherwise, so no correction
    was needed there.
  • One wording fix applied in review: refusals are 429 either way (the limit
    check in request runs before the account lookup), so the limit cannot be
    used as an account oracle. A second flagged line (password change clearing
    the lockout) turned out to be correct — change calls set_password_hash,
    which resets all three lockout columns (store.rs:1550-1569).
  • Lockout defaults (threshold 10, window 3600s, lock 900s) were already
    pinned by the_defaults_are_the_ones_the_docs_quote
    (crates/auth-password/src/lib.rs:306-312); no change needed.
  • Shared-scaffolding note: none added. Only the three files above are
    touched; no handler, lockout, migration, or harness-config changes.

How verified:

  • cargo test -p factory0-auth-magic-link --test magic_link: 14 passed,
    0 failed (12 existing + 2 new).
  • cargo test -p factory0-auth-password: all green (20 unit + 2
    conformance + 16 integration + 1 doctest).
  • cargo fmt --check and
    cargo clippy -p factory0-auth-magic-link --all-targets clean.
  • Diff: 3 files, ~120 insertions, 1 deletion — within ceiling.

Closes #12


🤖 Generated by Colonizer in a microVM

…easoning

Refs #12

Co-Authored-By: Colonizer <noreply@colonizer.dev>
@ParallelEntrepreneur
ParallelEntrepreneur merged commit 4637a23 into main Sep 22, 2026
7 checks passed
@ParallelEntrepreneur
ParallelEntrepreneur deleted the colonizer/issue-12-f9b67d10 branch September 22, 2026 19:52
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rate limiting and lockout on password and magic-link endpoints

1 participant