docs(repo): count sign-in failures per email and IP, in an ADR superseding 0041 #549

Merged
root merged 2 commits from docs/439-adr-0041-email-and-ip into main 2026-10-16 07:19:11 +00:00
root commented 2026-10-16 07:00:33 +00:00 (Migrated from gitlab.core-project.space)

Summary

ADR 0041 said every counter is keyed by IP and by lowercased email; since !546, sign-in failures are keyed by email and IP together. The ADR format says a partly overturned ADR is superseded, so ADR 0045 restates 0041 with the new key, and 0041 only changes its Status.

 docs/adr/
-├── 0041-rate-limits-are-in-memory-counters-in-the-api.md   # accepted
+├── 0041-rate-limits-are-in-memory-counters-in-the-api.md   # superseded by 0045
+├── 0045-rate-limits-are-in-memory-counters-and-sign-in-failures-count-per-email-and-ip.md
 └── README.md                                               # 0041 row superseded, 0045 row added

What 0045 adds to 0041:

 Decision
-  Counters are keyed by IP and by lowercased email
+  ...; sign-in failures by IP and by email and IP together
-  the per-email limits keep production values everywhere
+  dev, CI and previews raise only per-IP ones
 Why
+  A stranger's wrong passwords never lock a Player out; in exchange,
+  one email guessed from many addresses is capped per address only.
 Rejected
+  Sign-in failures keyed by email alone: anyone could lock a Player out.
 Revisit when
+  ... or one email guessed from many addresses.

The "per-email limits" comments in deploy/compose.preview.yaml and scripts/assign-dev-rate-limits.sh now say "the limits keyed by email" (alone or with the IP) and cite ADR 0045. 0045's Governs row adds those two files to 0041's paths. GLOSSARY.md has no rate-limit term, so it is unchanged.

A second commit moves the ten code comments in apps/api, apps/front and packages/contracts that said "see ADR 0041" to "see ADR 0045", as 4c3398c3 did when 0042 superseded 0034. Only the citations change.

Evidence

  • Before: the ADR said a stranger's failures count against the owner's email, which the code no longer does.
    After: the ADR matches auth.controller.ts (signInFailuresPerEmailAndIp keyed "email ip", signInFailuresPerIp keyed ip). 0045 is 299 words (cap 300). pnpm lint (including lint:adr: "45 ADRs, each numbered once and indexed"), typecheck, test, build and format:check are green.
  • grep -rn RATE_LIMIT_SIGN_IN_FAILURES_PER_EMAIL over the repo finds only the new ..._PER_EMAIL_AND_IP name, so nothing in the repo sets the old variable.

Merge Danger

Door: two-way

Docs and comments only; revert restores 0041.

Blast Radius: docs

Owner step: check that no deployed environment (production's .env, GitLab CI/CD variables, VPS stack files) still sets RATE_LIMIT_SIGN_IN_FAILURES_PER_EMAIL. If one does, it is ignored and the default of 5 applies, so rename it to RATE_LIMIT_SIGN_IN_FAILURES_PER_EMAIL_AND_IP or drop it.

Closes #439

## Summary ADR 0041 said every counter is keyed by IP and by lowercased email; since !546, sign-in failures are keyed by email and IP together. The ADR format says a partly overturned ADR is superseded, so ADR 0045 restates 0041 with the new key, and 0041 only changes its Status. ```diff docs/adr/ -├── 0041-rate-limits-are-in-memory-counters-in-the-api.md # accepted +├── 0041-rate-limits-are-in-memory-counters-in-the-api.md # superseded by 0045 +├── 0045-rate-limits-are-in-memory-counters-and-sign-in-failures-count-per-email-and-ip.md └── README.md # 0041 row superseded, 0045 row added ``` What 0045 adds to 0041: ```diff Decision - Counters are keyed by IP and by lowercased email + ...; sign-in failures by IP and by email and IP together - the per-email limits keep production values everywhere + dev, CI and previews raise only per-IP ones Why + A stranger's wrong passwords never lock a Player out; in exchange, + one email guessed from many addresses is capped per address only. Rejected + Sign-in failures keyed by email alone: anyone could lock a Player out. Revisit when + ... or one email guessed from many addresses. ``` The "per-email limits" comments in `deploy/compose.preview.yaml` and `scripts/assign-dev-rate-limits.sh` now say "the limits keyed by email" (alone or with the IP) and cite ADR 0045. 0045's Governs row adds those two files to 0041's paths. `GLOSSARY.md` has no rate-limit term, so it is unchanged. A second commit moves the ten code comments in `apps/api`, `apps/front` and `packages/contracts` that said "see ADR 0041" to "see ADR 0045", as 4c3398c3 did when 0042 superseded 0034. Only the citations change. ## Evidence - **Before:** the ADR said a stranger's failures count against the owner's email, which the code no longer does. **After:** the ADR matches `auth.controller.ts` (`signInFailuresPerEmailAndIp` keyed `"email ip"`, `signInFailuresPerIp` keyed `ip`). 0045 is 299 words (cap 300). `pnpm lint` (including `lint:adr`: "45 ADRs, each numbered once and indexed"), `typecheck`, `test`, `build` and `format:check` are green. - `grep -rn RATE_LIMIT_SIGN_IN_FAILURES_PER_EMAIL` over the repo finds only the new `..._PER_EMAIL_AND_IP` name, so nothing in the repo sets the old variable. ## Merge Danger **Door:** two-way Docs and comments only; revert restores 0041. **Blast Radius:** docs Owner step: check that no deployed environment (production's `.env`, GitLab CI/CD variables, VPS stack files) still sets `RATE_LIMIT_SIGN_IN_FAILURES_PER_EMAIL`. If one does, it is ignored and the default of 5 applies, so rename it to `RATE_LIMIT_SIGN_IN_FAILURES_PER_EMAIL_AND_IP` or drop it. Closes #439
root commented 2026-10-16 07:00:38 +00:00 (Migrated from gitlab.core-project.space)

changed the description

changed the description
root commented 2026-10-16 07:03:47 +00:00 (Migrated from gitlab.core-project.space)

added 1 commit

  • c182f1eb - docs(repo): point what ADR 0041 decided and 0045 keeps at ADR 0045

Compare with previous version

added 1 commit <ul><li>c182f1eb - docs(repo): point what ADR 0041 decided and 0045 keeps at ADR 0045</li></ul> [Compare with previous version](/amaurycoudr/chess-project/-/merge_requests/49/diffs?diff_id=316&start_sha=fe9f2e3bbb8c9c7f21fad05879afbe9f7de459de)
root commented 2026-10-16 07:03:50 +00:00 (Migrated from gitlab.core-project.space)

changed the description

changed the description
root commented 2026-10-16 07:07:13 +00:00 (Migrated from gitlab.core-project.space)

added 3 commits

  • 87f541fd - 1 commit from branch main
  • 56cc57af - docs(repo): count sign-in failures per email and IP, in an ADR superseding 0041
  • 697b60f8 - docs(repo): point what ADR 0041 decided and 0045 keeps at ADR 0045

Compare with previous version

added 3 commits <ul><li>87f541fd - 1 commit from branch <code>main</code></li><li>56cc57af - docs(repo): count sign-in failures per email and IP, in an ADR superseding 0041</li><li>697b60f8 - docs(repo): point what ADR 0041 decided and 0045 keeps at ADR 0045</li></ul> [Compare with previous version](/amaurycoudr/chess-project/-/merge_requests/49/diffs?diff_id=319&start_sha=c182f1ebb7ee782f49f26e730a4f25c8e6dd35bc)
project_1_bot_a8dd9262857d850eef8dca5206e61de5 commented 2026-10-16 07:14:57 +00:00 (Migrated from gitlab.core-project.space)

Screenshots

Before is production, after is this merge request's review app at 697b60f.

Desktop

Page Before After
Home
Local game
Room

Mobile

Page Before After
Home
Local game
Room
<!-- chess-screenshots --> ### Screenshots Before is production, after is this merge request's review app at 697b60f. #### Desktop | Page | Before | After | | --- | --- | --- | | Home | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/1848/artifacts/raw/review-screenshots/before/home-desktop.png" width="400"> | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/1848/artifacts/raw/review-screenshots/after/home-desktop.png" width="400"> | | Local game | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/1848/artifacts/raw/review-screenshots/before/local-desktop.png" width="400"> | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/1848/artifacts/raw/review-screenshots/after/local-desktop.png" width="400"> | | Room | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/1848/artifacts/raw/review-screenshots/before/room-desktop.png" width="400"> | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/1848/artifacts/raw/review-screenshots/after/room-desktop.png" width="400"> | #### Mobile | Page | Before | After | | --- | --- | --- | | Home | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/1848/artifacts/raw/review-screenshots/before/home-mobile.png" width="200"> | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/1848/artifacts/raw/review-screenshots/after/home-mobile.png" width="200"> | | Local game | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/1848/artifacts/raw/review-screenshots/before/local-mobile.png" width="200"> | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/1848/artifacts/raw/review-screenshots/after/local-mobile.png" width="200"> | | Room | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/1848/artifacts/raw/review-screenshots/before/room-mobile.png" width="200"> | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/1848/artifacts/raw/review-screenshots/after/room-mobile.png" width="200"> |
root (Migrated from gitlab.core-project.space) merged commit into main 2026-10-16 07:19:11 +00:00
Sign in to join this conversation.
No description provided.