Vendor-neutral age verification, with IMVU as the first provider
CI / test (push) Successful in 35s

Age checks are recorded in one table (age_check) by provider, method and result, never with documents or
birth dates; one rule decides whether an IMVU account counts as adult (its person's check, or its own).
Providers implement a small interface (start, webhook or browser completion, re-check) and are chosen by
configuration, so phone wallets and Didit can be added, or swapped, as adapters. IMVU's answer per account
is re-checked when it expires (about daily). Existing links' results move into the new table.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
dhkatzandClaude Opus 5.5 committed 2026-10-29 05:44:36 -07:00
1 parent 339ba8e2d6
commit 7db9fc0370
11 files changed
+1602 -48

No files matched your search

+35 -8
View File
@@ -101,16 +101,43 @@ age, not verified) and `tagline`.
offer to link. Linked to another hub account: no community features that session.
- **Bans** apply to the person, so all linked accounts.
## Age (**Decided**: IMVU's verification)
## Age (**Decided**: free, several providers, vendor-neutral)
- Adult content requires the **IMVU account in use** to be age verified (`is_ageverified`) or to have Access Pass
(`is_ap`; **Decided**: it counts), checked by the hub
itself (never reported by the proxy, which anyone can change): at linking and at most daily after, cached.
Revocations show up at the next check.
- Per IMVU account, not per person, so one verified account doesn't unlock others a minor might use.
No payment for verification (adult content rules out mainstream merchants of record; see the discussion of
2026-10-29). Several ways to prove age, tried in order of privacy, behind one interface so any can be swapped:
1. **IMVU** (live): the IMVU account is age verified (`is_ageverified`) or has Access Pass (`is_ap`), read by the hub
from IMVU's public API. Scope: that IMVU account. Re-checked about daily; a revocation shows at the next check.
Self-reported `is_adult` doesn't count.
2. **Phone wallets** (planned): a government ID in Google Wallet, Apple Wallet or an EU age-verification wallet,
asked for "age over 18" only, through the browser's Digital Credentials API. Free for the hub; no documents or
birth date reach it. Scope: the person.
3. **ID document and selfie** (planned): Didit's hosted check, within its free monthly allowance. Scope: the person
(the liveness step stops someone using another person's ID).
### How it's built
- **One table of results**, `age_check`: subject (a person, or one of their linked IMVU accounts), provider,
method (e.g. `imvu_age_verified`, `imvu_access_pass`, `wallet_mdoc`, `id_document`), status (`pending`,
`complete`, `failed`, `revoked`), over 18 yes/no, the provider's reference, when it was checked and when it
expires. Never a birth date, document, photo or name: providers that see those keep them.
- **One rule**: an IMVU account counts as adult if its person has a current complete check that says over 18, or
the account itself has one. Everything (website, tokens for catalogs, room channels) asks this one function.
- **Providers** implement a small interface: `start` (begin a check: done at once, a page to send the person to,
or a request for the browser to hand to a wallet), `complete` (finish from the provider's callback or signed
webhook), and optionally `recheck` (for providers whose answer can change, like IMVU). Which ones run is
configuration (`AGE_PROVIDERS`), with each provider's keys in its own settings. Adding or replacing a vendor is
one new adapter; nothing else changes.
- Webhooks arrive at `/api/v1/age/webhook/<provider>` and each provider checks its own signature.
- Enforced at three points: catalogs (adult files need an adult token), the hub (adult items left out of room
channels for viewers who aren't verified and opted in), and the viewer's proxy.
- Self-reported `is_adult` doesn't count.
channels for viewers who aren't adult and opted in), and the viewer's proxy.
### To add the planned providers
- Didit: an account, an API key and webhook secret, and a workflow set to ID document plus liveness, returning
only "over 18". Confirm its free monthly allowance covers age checks.
- Wallets: Google's Digital Credentials verifier registration (free), and an `age_over_18` request (OpenID4VP,
mdoc); Apple and the EU wallet through the same browser API where supported.
## Products and catalogs