feat: age verification with an ID document (Didit), and closed registration
Pull request / title (pull_request) Successful in 1s
CI / test (pull_request) Successful in 58s
CI / image (apps/api/Dockerfile, t5de-hub-api) (pull_request) Skipped
CI / image (apps/web/Dockerfile, t5de-hub-web) (pull_request) Skipped

Age: a Didit provider behind the vendor-neutral age interface. A person
verifies once (ID document, passive liveness, face match) and all their
linked IMVU accounts count as adult. Webhooks are checked against Didit's
signatures; only "over 18" is kept. A later answer replaces an earlier one
(an approval taken back is revoked). Checks are limited: one unfinished
check per person, 3 in 30 days, none once verified, and a monthly cap
(DIDIT_MONTHLY_LIMIT, default 30: Didit's free plan is $10 of credit a
month and a check costs $0.30). The Account page gets an Age Verification
card.

Registration: open or closed, an admin's setting in the console
(default from REGISTRATION). Closed: new accounts can only sign in until
a moderator approves them (or declines, deleting the account); the
website shows them a waiting page and the API treats them as signed out.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
dhkatzandClaude Opus 5.5 committed 2026-11-03 04:15:47 -08:00
1 parent 86ebe976ba
commit c75a4c9afc
28 files changed
+3260 -89

No files matched your search

+5 -2
View File
@@ -8,11 +8,14 @@ catalogs, T5DE-hosted rooms, and the moderation console. Part of T5DE (git.t5de.
## What works
- **Accounts** (Better Auth): sign-up with email, username and password; sign-in by username. The first account is
an admin; roles user, moderator, admin.
an admin; roles user, moderator, admin. Registration open or closed (new accounts wait for a moderator's
approval): an admin's setting in the console, defaulting to the API's `REGISTRATION`.
- **Linking IMVU accounts**: the person puts a code in the account's tagline; the hub reads it from IMVU's public
API. The most recent proof wins (an account linked elsewhere moves, with a new pairwise ID). Link caps per person
(default 10).
- **Age**: an IMVU account counts as adult if IMVU says it's age verified or has Access Pass, checked by the hub.
- **Age**: an IMVU account counts as adult if IMVU says it's age verified or has Access Pass, checked by the hub, or
if its person verified their age with an ID document and a selfie (Didit, when configured: `AGE_PROVIDERS`, see
`apps/api/src/index.ts` and docs/design.md, "Age").
- **Proxy sign-in**: OAuth 2.0 device authorization (`t5de-proxy signin` shows a code to enter at `/device`); the
proxy then uses its session as a bearer token. JWTs with published keys (`/.well-known/jwks.json`) for catalogs.
- **Presence**: signed-in proxies keep a WebSocket (`/api/v1/realtime`) telling the hub which IMVU account is in