PC3 Phase 3.2: real age verification (date of birth, not a checkbox)
POST /api/auth/register now requires a real date_of_birth (ISO YYYY-MM-DD). The server computes age (auth.calculate_age) and rejects under-18s with 403; a future/nonsensical date is 400. The DOB is stored and surfaced only to that user (/api/auth/me). Still self-attested (a user can enter a false DOB) -- but a concrete, stored, legally-meaningful data point and the seam for a future ID-check pass. Encryption-at-rest for the column and the Tier-2 hook are not done; the limitation is stated plainly in docs/architecture/content_moderation.md 5.2. - auth.py: RegisterRequest.date_of_birth (date); MIN_AGE=18; register() computes + enforces; UserResponse.date_of_birth typed `date | None` (the old `str | None` would have 500'd /me once a DOB was actually stored). - api_client.gd / main_menu.gd: the Over18 checkbox is now a "Date of birth (YYYY-MM-DD)" field with a client-side sanity check. - tests: test_auth_age_gate.py rewritten around the endpoint + age math (adult/minor/exactly-18/future-dob/stored); ~25 over_18 references across 6 backend test files + 6 game smoke tests updated. Backend 74 passed; game smokes green (auth 6/6, menu_full_flow 12/12, e2e 4/4, etc.); fresh-clone boot PASS. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015jtxAiu5dAW4WxCNdGkrkJ
This commit is contained in:
@@ -227,18 +227,33 @@ An account has an **age verification status**:
|
||||
|
||||
### 5.2 Tier 1 — Self-Declaration Flow
|
||||
|
||||
> **Implemented, PC3 Phase 3.** `POST /api/auth/register` now takes a real
|
||||
> `date_of_birth` (ISO `YYYY-MM-DD`), not the throwaway `over_18` boolean it
|
||||
> had before. The server computes age (`auth.calculate_age`) and rejects
|
||||
> anyone under `auth.MIN_AGE` (18) with a **403** — this platform is
|
||||
> adults-only, so there is no "minor, restricted" tier here (the 13+ rows
|
||||
> below are the general design, not the current gate). A future-in-the-past
|
||||
> or nonsensical date is a **400**. The DOB is stored on the user row and
|
||||
> surfaced only back to that user (`/api/auth/me`), never to other players.
|
||||
>
|
||||
> **Limitation, stated plainly:** this is still self-attested — a determined
|
||||
> user can enter a false DOB. It is a concrete, stored, legally-meaningful
|
||||
> data point (matching how most platforms gate before adding hard checks)
|
||||
> and the seam for Tier 2. Encryption-at-rest for the DOB column and the
|
||||
> Tier 2 ID-check hook below are **not yet implemented**.
|
||||
|
||||
```
|
||||
User submits { date_of_birth }
|
||||
│
|
||||
▼
|
||||
Server validates format & plausibility (age 13–120, not in future)
|
||||
Server validates format & plausibility (real date, not in future)
|
||||
│
|
||||
▼
|
||||
Compute age from DOB
|
||||
│
|
||||
▼
|
||||
age >= 18 ──► status = self_declared (adult)
|
||||
age >= 13 ──► status = self_declared (minor, restricted)
|
||||
age >= 18 ──► status = self_declared (adult) ← the current gate
|
||||
age >= 13 ──► status = self_declared (minor, restricted) ← design only
|
||||
age < 13 ──► status = rejected (below minimum platform age)
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user