docs: update documentation to OKF v0.1 format

This commit is contained in:
OpenVelo Agent
2026-07-21 21:19:36 +00:00
parent cd97e40030
commit ad40b3b820
2 changed files with 31 additions and 18 deletions
+30 -17
View File
@@ -1,7 +1,7 @@
--- ---
type: api type: api
title: Auth Endpoints title: Auth Endpoints
description: Login, refresh, logout, public self-registration, CSRF, and first-admin registration. description: Login, refresh, logout, public self-registration, CSRF, first-admin registration, and registration throttling.
tags: [api, auth, login, register, refresh, csrf] tags: [api, auth, login, register, refresh, csrf]
timestamp: 2026-07-21T18:28:00Z timestamp: 2026-07-21T18:28:00Z
--- ---
@@ -51,18 +51,27 @@ The refresh token is set as an `HttpOnly` cookie via `setRefreshCookie(res, sess
| 400 | `WEAK_PASSWORD` | Argon2 policy rejects the password. | | 400 | `WEAK_PASSWORD` | Argon2 policy rejects the password. |
| 403 | `REGISTRATIONS_DISABLED`| `setting.registrationsEnabled !== 'true'`. | | 403 | `REGISTRATIONS_DISABLED`| `setting.registrationsEnabled !== 'true'`. |
| 409 | `USERNAME_TAKEN` | A user with that username already exists. | | 409 | `USERNAME_TAKEN` | A user with that username already exists. |
| 429 | `RATE_LIMITED` | `RegistrationRateLimitService` blocked the IP. | | 429 | `RATE_LIMITED` | The per-IP registration limiter has reached 10 attempts in the rolling 60-second window. |
## Wiring ## Wiring
* `AuthService.registerPlayer(dto, ip)` runs inside a single * `AuthService.registerPlayer(dto, ip)` runs inside a single `DataSource.transaction`:
`DataSource.transaction`: 1. `RegistrationRateLimitService.tryConsume(ip)` permits at most 10 attempts per IP in a rolling 60-second window.
1. `RegistrationRateLimitService.isAllowed(ip)` check.
2. `SettingsService.get(SETTINGS_KEYS.REGISTRATIONS_ENABLED, 'false')` check. 2. `SettingsService.get(SETTINGS_KEYS.REGISTRATIONS_ENABLED, 'false')` check.
3. Username uniqueness lookup → `USERNAME_TAKEN` on collision. 3. Username uniqueness lookup → `USERNAME_TAKEN` on collision.
4. Argon2id hash + insert `UserEntity({ role: 'player', status: 'enabled' })`. 4. Argon2id hash + insert `UserEntity({ role: 'player', status: 'enabled' })`.
5. `RegistrationRateLimitService.record(ip)`. 5. `mintSession(manager, user)` → access JWT + refresh row.
6. `mintSession(manager, user)` → access JWT + refresh row. * `AuthService.registerFirstAdmin(username, password, ip)` uses the same limiter before checking whether an administrator already exists.
* The limiter is an in-memory Nest provider in `backend/src/common/services/registration-rate-limit.service.ts`; counters are process-local and reset when the API process restarts.
# Key Files
| File | Responsibility |
|------|----------------|
| `backend/src/modules/auth/auth.service.ts` | Validates registration policy, applies the limiter, creates users, and mints sessions. |
| `backend/src/common/services/registration-rate-limit.service.ts` | Tracks timestamps and enforces the 10-per-minute per-IP limit. |
| `backend/src/modules/auth/auth.controller.ts` | Exposes public registration and authentication routes. |
| `backend/src/modules/auth/dto/auth.dto.ts` | Validates registration request fields. |
# Frontend consumer # Frontend consumer
@@ -70,18 +79,22 @@ The refresh token is set as an `HttpOnly` cookie via `setRefreshCookie(res, sess
`register()`. Both: `register()`. Both:
1. Call `ensureCsrf()``GET /api/v1/auth/csrf` to materialise the `csrf` 1. Call `ensureCsrf()``GET /api/v1/auth/csrf` to materialise the `csrf`
cookie if it isn't set yet (failures are swallowed because the cookie if it isn't set yet.
`CsrfMiddleware` will mint the cookie on the next response anyway).
2. `POST` with `{ withCredentials: true, observe: 'response' }`. 2. `POST` with `{ withCredentials: true, observe: 'response' }`.
3. Return a discriminated union: 3. Return success or the standard [error envelope](/api/rest-overview.md).
* `{ ok: true, accessToken, expiresIn, user }` on success.
* `{ ok: false, status, code, message }` on failure, built by the
private `mapAuthError()` helper from the standard
[error envelope](/api/rest-overview.md).
The `LandingComponent` (`frontend/src/app/features/landing/landing.component.ts`) The `LandingComponent` consumes both methods and maps failures to user-facing
consumes both methods and maps the `code` to user-facing copy via copy (see [Landing Page](/guides/landing-page.md)).
`buildLoginFailureMessage` (see [Landing Page](/guides/landing-page.md)).
# Examples
## Tester flow: registration rate limit
1. Enable registrations in the admin settings.
2. Open the public registration form from the landing page.
3. Submit attempts from the same client IP.
4. The first 10 attempts are processed normally; the 11th within 60 seconds returns HTTP `429` with code `RATE_LIMITED`.
5. After the rolling window expires, a new attempt is accepted if other requirements pass.
# See also # See also
+1 -1
View File
@@ -11,7 +11,7 @@ scoreboard, an event window with a public countdown, theming, and admin
controls. controls.
The docs below are organized by purpose so agents can pull just the slice The docs below are organized by purpose so agents can pull just the slice
they need. Last regenerated 2026-07-21T18:45:54Z. they need. Last regenerated 2026-07-21T21:18:00Z.
# Architecture # Architecture