feat: permissions, a console for everyone who manages something, and catalog management
Pull request / title (pull_request) Successful in 1s
CI / test (pull_request) Successful in 1m1s
CI / image (apps/api/Dockerfile, t5de-hub-api) (pull_request) Skipped
CI / image (apps/web/Dockerfile, t5de-hub-web) (pull_request) Skipped

Phase 1 of docs/console.md: permissions as resource:action strings in role
bundles at a scope; the console for anyone controlling a catalog, product
or room, with a tagged audit log scoped by permission and filters;
catalog settings (rating ceiling, upload policy), key rotation, operators,
membership (approval, invitations, bans) enforced when getting and
wearing products, delisting, suspension, and the catalogs' changes feed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
dhkatzandClaude Opus 5.5 committed 2026-11-04 23:19:15 -08:00
1 parent 76497c9b41
commit 370ae0646a
29 files changed
+5657 -181

No files matched your search

+14 -3
View File
@@ -20,7 +20,7 @@ is. Codes: `invalid`, `signed_out`, `forbidden`, `not_found`, `no_such_imvu_acco
| `POST /api/auth/sign-up/email` | `{email, password, name, username}`. Usernames 3-32 of `A-Za-z0-9_`; passwords 10-256 characters. The first account is an admin. With registration closed, the others wait for approval (`approved: false`): every route but `/me` answers 403 `awaiting_approval`, and the rest of the hub treats them as signed out. |
| `POST /api/auth/sign-in/username` | `{username, password}` |
| `POST /api/auth/sign-out` | |
| `GET /api/v1/me` | `{person}` (`approved` false while waiting), with `picture`: the avatar picture of their first linked IMVU account (from IMVU, kept an hour), or `null` |
| `GET /api/v1/me` | `{person}` (`approved` false while waiting), with `picture`: the avatar picture of their first linked IMVU account (from IMVU, kept an hour), or `null`, and `console`: whether the console is for them |
| `GET /api/v1/hub` | (anyone) `{registration}`: `open` or `closed` |
## Proxies
@@ -103,11 +103,22 @@ person-level providers (phone wallets, document checks) are started here.
| `POST /api/v1/age/:provider/complete` | `{ref, response}`: the browser's answer, for wallet providers |
| `POST /api/v1/age/webhook/:provider` | the provider's webhook; the provider checks its signature (401 if it isn't the provider's). A later answer replaces an earlier one (an adult answer taken back is `revoked`) |
## Console (moderators; roles: admins)
## Console
Permissions, roles and scopes are in docs/console.md. A missing permission answers 403 `forbidden` with
`missing: {permission, scope}`. Catalog management routes are in docs/products.md.
| | |
| --- | --- |
| `GET /api/v1/console` | (anyone controlling a catalog, product or hosted room, and moderators; else 403) `{sections, mine, todo, moderation, audit}`: `moderation` (`{counts, connections, online}`) only for moderators, `audit` the latest 20 entries they may see |
| `GET /api/v1/console/audit?catalog=&product=&room=&person=&actor=&action=&q=&from=&to=&before=&limit=` | `{entries, before}`: entries the person may see (docs/console.md), newest first; `action` matches a prefix, `from`/`to` are days, `before` an entry ID for the next page. Entries are `{id, at, actor, action, target, tags, tagNames, detail}` |
| `GET /api/v1/console/permissions?catalog=&product=` | `{roles, permissions}` at that scope (the hub if neither) |
| `GET /api/v1/console/catalogs` | `{catalogs, moderator}`: every catalog for moderators, else those on whose team the person is |
Moderators:
| | |
| --- | --- |
| `GET /api/v1/console` | `{counts, connections, online, audit}` |
| `GET /api/v1/console/people?q=&waiting=true` | `{people}` (`waiting`: only accounts waiting for approval) |
| `POST /api/v1/console/people/:id/approve` | `{person}` |
| `POST /api/v1/console/people/:id/decline` | an account waiting for approval: deletes it |
+2
View File
@@ -470,6 +470,8 @@ Phases for products, catalogs and imports (products.md, console.md, imports.md):
1. Permissions and console foundations: the permission check, roles, the console for everyone who controls
something, a tagged audit log, membership enforced, catalog settings, team and key rotation, suspension.
**Done** (2026-11-05), except catalog deletion requests and the hosted rooms' scope, which come with cases
(phase 3). Built-in roles are code (`apps/api/src/permissions.ts`); the `role` table comes with custom roles.
2. Product info: drafts, moderator edits with reasons and locks, info history, unlisted products, tags and category.
3. Cases (reports, appeals, reviews), file blocks and the catalogs' changes feed; notifications; API tokens;
two-factor sign-in for sensitive permissions.