Hub: accounts, IMVU linking by tagline, proxy sign-in, presence, console
CI / test (push) Failing after 42s

People sign up on the website and link IMVU accounts by putting a code in the account's tagline, which the
hub reads from IMVU's public API (the most recent proof wins; link caps per person). IMVU's age verification
or Access Pass make an account adult. T5DE's proxy signs in with a device code and keeps a WebSocket open,
reporting the IMVU account in use and the community products it wears; /online shows those who opted in.
Moderators get a console: who's online, people, link caps, bans, roles, and the audit log. Tests run the
website and API against an embedded Postgres and a fake IMVU API.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
dhkatzandClaude Opus 5.5 committed 2026-10-29 03:45:52 -07:00
1 parent 54e569bea3
commit b9dc3f0ec1
36 files changed
+3548 -5

No files matched your search

@@ -0,0 +1,78 @@
-- Accounts (people), their linked IMVU accounts, website sessions, sign-ins from proxies, and the audit log.
create table persons (
id bigserial primary key,
username text not null,
password_hash text not null,
role text not null default 'user' check (role in ('user', 'moderator', 'admin')),
-- How many IMVU accounts the person may link; moderators raise it on request.
link_cap integer not null default 10 check (link_cap >= 0),
created_at timestamptz not null default now(),
banned_at timestamptz,
ban_reason text not null default ''
);
create unique index persons_username on persons (lower(username));
create table sessions (
token_hash bytea primary key,
person_id bigint not null references persons on delete cascade,
csrf text not null,
created_at timestamptz not null default now(),
expires_at timestamptz not null
);
create index sessions_person on sessions (person_id);
-- A linked IMVU account. Linking it again from another person moves it (the most recent proof wins).
create table imvu_links (
imvu_id bigint primary key,
person_id bigint not null references persons on delete cascade,
-- What catalogs and rooms see instead of the person, so a person's accounts can't be connected.
pairwise_id text not null unique,
username text not null,
linked_at timestamptz not null default now(),
age_verified boolean not null default false,
access_pass boolean not null default false,
checked_at timestamptz not null default now(),
show_badge boolean not null default false,
show_presence boolean not null default false
);
create index imvu_links_person on imvu_links (person_id);
-- A code the person is to put in an IMVU account's tagline, proving it's theirs.
create table link_challenges (
person_id bigint not null references persons on delete cascade,
imvu_id bigint not null,
username text not null,
code text not null,
created_at timestamptz not null default now(),
primary key (person_id, imvu_id)
);
-- Signing a proxy in: the proxy shows user_code, the person approves it on the website.
create table device_codes (
device_hash bytea primary key,
user_code text not null unique,
created_at timestamptz not null default now(),
expires_at timestamptz not null,
person_id bigint references persons on delete cascade,
consumed_at timestamptz
);
create table refresh_tokens (
token_hash bytea primary key,
person_id bigint not null references persons on delete cascade,
created_at timestamptz not null default now(),
last_used_at timestamptz not null default now(),
revoked_at timestamptz
);
create index refresh_tokens_person on refresh_tokens (person_id);
create table audit (
id bigserial primary key,
at timestamptz not null default now(),
actor_id bigint references persons on delete set null,
action text not null,
target text not null default '',
detail jsonb not null default '{}'
);
create index audit_at on audit (at desc);