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:
@@ -10,7 +10,7 @@ extends SceneTree
|
||||
## Tests:
|
||||
## 1. Register a unique user → 201 + token stored.
|
||||
## 2. Register the same user again → 409 "Username already registered".
|
||||
## 3. Register with over_18=false → 400 "Must be 18 or older".
|
||||
## 3. Register with an under-18 DOB → 403 "at least 18".
|
||||
## 4. Login with correct credentials → 200 + token stored.
|
||||
## 5. Login with wrong password → 401 "Incorrect username or password".
|
||||
## 6. Login with non-existent user → 401 "Incorrect username or password".
|
||||
@@ -44,7 +44,7 @@ func _run() -> void:
|
||||
var email := "smoke_%d@test.example.com" % unique_id
|
||||
|
||||
print("\n=== Test 1: Register unique user ===")
|
||||
var result := await api.register(username, email, TEST_PASSWORD, true)
|
||||
var result := await api.register(username, email, TEST_PASSWORD, "1990-01-01")
|
||||
if _check("register returns ok", result.ok) \
|
||||
and _check("register status is 201", result.status == 201) \
|
||||
and _check("register stores token", api.has_token()):
|
||||
@@ -55,7 +55,7 @@ func _run() -> void:
|
||||
|
||||
# --- Test 2: Register same user again (duplicate) ---
|
||||
print("\n=== Test 2: Duplicate username ===")
|
||||
result = await api.register(username, email, TEST_PASSWORD, true)
|
||||
result = await api.register(username, email, TEST_PASSWORD, "1990-01-01")
|
||||
if _check("duplicate register not ok", not result.ok) \
|
||||
and _check("duplicate status is 409", result.status == 409) \
|
||||
and _check("duplicate detail mentions username",
|
||||
@@ -65,14 +65,16 @@ func _run() -> void:
|
||||
failed += 1
|
||||
print(" detail: ", result.detail)
|
||||
|
||||
# --- Test 3: Register with over_18=false ---
|
||||
print("\n=== Test 3: over_18=false registration ===")
|
||||
# --- Test 3: Register with an under-18 date of birth ---
|
||||
print("\n=== Test 3: under-18 registration ===")
|
||||
var child_username := "child_%d" % unique_id
|
||||
var child_email := "child_%d@test.example.com" % unique_id
|
||||
result = await api.register(child_username, child_email, TEST_PASSWORD, false)
|
||||
if _check("over_18=false register not ok", not result.ok) \
|
||||
and _check("over_18=false status is 400", result.status == 400) \
|
||||
and _check("over_18=false detail mentions age",
|
||||
var now := Time.get_datetime_dict_from_system()
|
||||
var minor_dob := "%04d-01-01" % (int(now["year"]) - 14)
|
||||
result = await api.register(child_username, child_email, TEST_PASSWORD, minor_dob)
|
||||
if _check("under-18 register not ok", not result.ok) \
|
||||
and _check("under-18 status is 403", result.status == 403) \
|
||||
and _check("under-18 detail mentions age",
|
||||
"18" in result.detail):
|
||||
passed += 1
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user