> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nudj.cx/llms.txt
> Use this file to discover all available pages before exploring further.

# Release v2.475.14

> Released August 11, 2026

## 🟡 Release v2.475.14

⭐⭐ Moderate Complexity • 3 commits • 24 files

<Note>
  This release hardens security around email sign-in with rate limiting and improves reliability by persisting rate-limit state to MongoDB. Sign-in email callbacks are now protected against brute force attacks with a 5-attempt limit and 15-minute lockout, and this protection survives server restarts.
</Note>

## What's New

* **Rate-Limited Email Sign-Ins**: Email sign-in attempts are now rate-limited to 5 per 15 minutes, preventing brute force attacks on both user and admin platforms
* **Persistent Rate Limiting**: OTP failure counters now persist in MongoDB instead of in-memory storage, surviving server restarts and deployments
* **Clear User Feedback**: Users see a helpful error message with a 15-minute recovery window when rate-limited

## Apps Updated

<CardGroup cols={3}>
  <Card title="User App" icon="mobile">
    ✓ Updated - Rate limiting on email sign-in callbacks
  </Card>

  <Card title="API" icon="server">
    — No changes
  </Card>

  <Card title="Admin" icon="gear">
    ✓ Updated - Rate limiting on email sign-in callbacks
  </Card>

  <Card title="MCP Server" icon="robot">
    — No changes
  </Card>

  <Card title="Website" icon="globe">
    — No changes
  </Card>

  <Card title="Games" icon="gamepad">
    — No changes
  </Card>
</CardGroup>

## Detailed Changes

<AccordionGroup>
  <Accordion title="User App" icon="mobile">
    * Rate limit email sign-in callbacks to 5 attempts per 15 minutes
    * Return HTTP 429 with user-friendly error message when rate limit exceeded
    * Clear rate limit on successful sign-in
    * Comprehensive test coverage for rate limiting and callback validation
  </Accordion>

  <Accordion title="Admin" icon="gear">
    * Rate limit email sign-in callbacks to 5 attempts per 15 minutes
    * Return HTTP 429 with user-friendly error message when rate limit exceeded
    * Clear rate limit on successful sign-in
    * Comprehensive test coverage for rate limiting and callback validation
  </Accordion>

  <Accordion title="Database" icon="database">
    * Add new `OTP_FAILED_ATTEMPTS` collection for persisting OTP failure counters
    * Create unique index on `(location, organisationId, appSurface, normalizedEmail)` for atomic rate limit tracking
    * Add TTL index with automatic cleanup of expired rate limit records
    * Move OTP failure counter from in-memory Map to MongoDB for cross-restart persistence
  </Accordion>
</AccordionGroup>

## Technical Details

### Rate Limiting Strategy

The email sign-in rate limiting uses atomic MongoDB operations to prevent race conditions:

* **Shared bucket per email**: Each unique (location, organisationId, appSurface, normalizedEmail) combination gets its own counter
* **Atomic increment**: Counter is updated atomically within MongoDB, supporting concurrent requests
* **Automatic reset**: Counter resets after 15 minutes of inactivity
* **Fail-open behavior**: If MongoDB is unavailable, the limiter permits the attempt to preserve sign-in availability

### Data Persistence

OTP failure counters now survive server restarts:

* Previously: In-memory Map (lost on restart)
* Now: MongoDB documents with TTL-based cleanup
* Ensures consistent rate limiting across deployments and outages

## Contributors

<CardGroup cols={4}>
  <Card>
    <img src="https://github.com/hienhang@hotmail.co.uk.png" alt="hienhang@hotmail.co.uk" style={{borderRadius: '50%', width: 48}} />

    **@hienhang**

    2 commits • +1401/-195 lines
  </Card>

  <Card>
    <img src="https://github.com/nudj-changelog-bot[bot].png" alt="nudj-changelog-bot" style={{borderRadius: '50%', width: 48}} />

    **@nudj-changelog-bot**

    1 commit • Generated changelog
  </Card>
</CardGroup>

## Release Stats

| Metric        | Value  |
| ------------- | ------ |
| Total Commits | 3      |
| Lines Added   | +1,560 |
| Lines Removed | -196   |
| Files Changed | 24     |

***

*v2.475.14 deployed on August 11, 2026*
