docs: permissions, console and imported IMVU products
Design for managing products, catalogs and importers: permissions as resource:action strings bundled into roles at a scope, one console scoped by permission, a tagged audit log, cases, notifications, API tokens and charts (console.md); catalogs importing IMVU products with their creators' grants (imports.md); and the contract changes (products.md). Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
d5cd2be5d0
commit
76497c9b41
4 files changed
+482
-11
No files matched your search
+167
@@ -0,0 +1,167 @@
|
||||
# Imported IMVU products
|
||||
|
||||
Creators who sell on IMVU can let T5DE users wear their IMVU products for free: a catalog imports the products from
|
||||
IMVU, hosts them as ordinary T5 products, and serves them to its members. Decided 2026-11-04 (the user's
|
||||
discussion). The contract with catalogs and proxies is in `products.md`; permissions and the console are in
|
||||
`console.md`.
|
||||
|
||||
## Why the catalog imports
|
||||
|
||||
- **Responsibility stays with catalogs**, as for uploads: the catalog that imports a product stores and serves its
|
||||
files, and its takedown contact answers for them. End users only download from catalogs, as for any T5 product.
|
||||
- **Nothing changes for proxies**: an imported product is a hub product with revisions. No aliasing of IMVU IDs, no
|
||||
re-signed IMVU requests.
|
||||
- **Only consenting creators**: nothing is imported without a grant from the creator (or one an admin records on
|
||||
their behalf, with evidence).
|
||||
|
||||
## Words
|
||||
|
||||
- **Grant**: a creator's consent for one catalog to import their products: the whole shop, or listed products.
|
||||
- **Importer** (`t5de-importer`): a program that fetches products from IMVU and uploads them to its catalog. Run by
|
||||
the catalog's operator beside an ordinary `t5de-catalog`. T5DE runs one for its own import catalog; any catalog
|
||||
may enable imports.
|
||||
- **Import job**: one product to import or re-check, queued at the hub.
|
||||
- **Request**: someone asking for a creator's product, or whole shop, to be on T5DE.
|
||||
- **Unclaimed creator**: a placeholder creator for IMVU creators without a hub account, whose consent an admin
|
||||
recorded. Claimed when they join and link that IMVU account.
|
||||
|
||||
## What's imported
|
||||
|
||||
- **The product's own files**: its CFL's entries, with the 16x16 placeholder textures replaced by the full-size
|
||||
originals its `_contents.json` lists (fetched from IMVU's CDN beside the CFL), and without `_contents.json` (packs
|
||||
don't use it). Its `index.xml` keeps its `__DATAIMPORT` of the parent.
|
||||
- **The parent stays on IMVU** (**Decided**, for now): the revision's `parent` is the IMVU product it derives from,
|
||||
as for uploaded products, and the client loads it from IMVU as it does for anyone's outfit. Option B
|
||||
(**Decided**): any product the creator made may be imported, whatever it derives from; deriving from a derivable
|
||||
product is what IMVU's derive permission allows. If keeping the parent on IMVU becomes a problem, imports can be
|
||||
flattened later (the whole chain in one product, parent 0).
|
||||
- **Info**: name and rating from IMVU's public API (`api.imvu.com/product/product-<id>`: `product_name`, `rating`,
|
||||
`creator_cid`), the higher of IMVU's rating and the files' `ProductRating`; a description saying it's imported
|
||||
with the creator's permission, linking its IMVU page. Creators edit it afterwards like any product.
|
||||
- **Revisions**: each IMVU revision imported becomes a hub revision ("Imported from IMVU revision 12"). Revision
|
||||
history and staying on a revision work as for any product.
|
||||
- One hub product per IMVU product (`product.imvu_product`, unique). Two catalogs importing the same product mirror
|
||||
the same revisions.
|
||||
|
||||
## Grants
|
||||
|
||||
```
|
||||
import_grant(id, catalog, creator person, imvu_id, scope ("shop" | "products"), products bigint[], exclude bigint[],
|
||||
listed, consent_version, consented_at, consent_kind ("verified" | "recorded"), evidence, recorded_by,
|
||||
proof_checked_at, accepted_at, accepted_by, withdrawn_at, status ("pending" | "active" | "suspended" | "withdrawn"))
|
||||
```
|
||||
|
||||
- **Made by the creator**: on the hub website, "Bring my IMVU shop": choose one of their linked IMVU accounts, a
|
||||
catalog with imports on, the scope (whole shop with exclusions, or listed products), listed or unlisted, and agree
|
||||
to the consent text. The text is versioned; the version and time are stored.
|
||||
- **Accepted by the catalog**: the catalog's team (`import:accept`) accepts or declines it, so nobody pushes imports
|
||||
onto a catalog without its operator agreeing. Until then it's `pending`.
|
||||
- **Recorded by an admin** (`import:grant-on-behalf`, hub-wide; for creators who won't make an account): the IMVU
|
||||
creator (ID or name), scope, catalog, and **evidence** (required: how they agreed, e.g. "Discord DM, 2026-11-04",
|
||||
optionally a screenshot). Optional **proof without an account**: the console gives a code to send the creator;
|
||||
they put it in their IMVU tagline, and the hub checks it as for linking. Shown as "consent verified" or "consent
|
||||
recorded by admin". The products belong to an unclaimed creator.
|
||||
- **Scope "shop"**: any product whose `creator_cid` is the grant's IMVU account, including new ones, except
|
||||
exclusions. **Scope "products"**: only those listed; the creator can add more (requests show as suggestions).
|
||||
- **Changes**: the creator (or an admin, for recorded grants) changes the scope, list and exclusions any time.
|
||||
Removing a product from a grant withdraws it (below).
|
||||
- **Ending**: the creator withdraws the grant, or the catalog's team ends it, or the IMVU account's link moves to
|
||||
another person (the grant is `suspended` until the new owner consents again), or the account is unlinked
|
||||
(`suspended`). Admins can withdraw any grant.
|
||||
|
||||
### Unclaimed creators and claiming
|
||||
|
||||
An unclaimed creator is a hub person without credentials (can't sign in), named after the IMVU account ("Bar, on
|
||||
IMVU"), marked unclaimed. When someone links that IMVU account, the hub offers them the claim: the products, grants,
|
||||
requests and stats move to them, and the placeholder is deleted. Until then, withdrawal goes through admins
|
||||
(contacting T5DE, or the catalog's takedown contact).
|
||||
|
||||
## Requests
|
||||
|
||||
```
|
||||
import_request(person, imvu_creator, imvu_product (0: the whole shop), created_at) -- unique per person and target
|
||||
```
|
||||
|
||||
- Anyone signed in can request a product (by IMVU ID or from its shop page in the client) or a creator's whole shop.
|
||||
At most 50 a day per person; one per person and target, so counts can't be inflated.
|
||||
- The hub looks up the product's creator (public API, cached in `imvu_product_info`).
|
||||
- **Covered by an active grant**: queued for import at once; the person gets the product in their library when it's
|
||||
done (pending until then; nothing on screen waits for it).
|
||||
- **Not covered, grant by products**: a suggestion for the creator ("12 people asked for X"), added with one click.
|
||||
- **No grant**: counted. The creator sees the demand when they bring their shop; the hub's creator page for a shop
|
||||
that hasn't joined can show "requested by 47 people". The hub never contacts creators through IMVU.
|
||||
- Admins see request counts per IMVU creator in the console (whom it's worth asking).
|
||||
|
||||
## Import jobs
|
||||
|
||||
```
|
||||
import_job(id, catalog, grant, imvu_product, kind ("import" | "recheck"), status ("queued" | "claimed" | "done" | "failed"),
|
||||
imvu_revision, reason, attempts, claimed_at, next_at, created_at, updated_at)
|
||||
```
|
||||
|
||||
- **Queued by the hub**: a request covered by a grant, a product added to a grant, a "shop" grant accepted (the
|
||||
products people requested so far, and all the shop's products if a way to list them is found), and a daily
|
||||
**recheck** of each imported product.
|
||||
- **The hub checks IMVU's public API** before queuing and at each recheck (rate-limited, as for parents): the
|
||||
product exists, its creator is the grant's account, its rating. Gone from IMVU: withdrawn. Rating changed to AP:
|
||||
adult at once. Retired (`is_purchasable` false): kept unless the creator excludes it.
|
||||
- **The importer claims jobs**, fetches, converts, uploads with a `t5de-import` token (products.md), and reports the
|
||||
outcome. Rechecks probe IMVU's CDN for revisions after the last imported one; a new one is imported.
|
||||
- Failures retry with backoff (1 min, 10 min, 1 h, then daily; failed for good after 5); the reason is shown in the
|
||||
console. The catalog's team can retry or re-import one product, and pause the importer (`import:pause`): the hub
|
||||
hands out no jobs while paused.
|
||||
|
||||
## Withdrawal
|
||||
|
||||
A withdrawn imported product (grant withdrawn or narrowed, gone from IMVU, account link moved) is removed as
|
||||
moderation removes products: it leaves libraries, outfits and rooms; its page says it was withdrawn; the catalog
|
||||
deletes its files (the catalog changes feed, products.md). Unlike deleting an uploaded product, people who had it
|
||||
don't keep it: the consent is gone.
|
||||
|
||||
## `t5de-importer`
|
||||
|
||||
A Go program (its own repository) beside a `t5de-catalog`; it stores nothing lasting but its working files.
|
||||
|
||||
- Configuration: `HUB_URL`, `CATALOG_ID`, `IMPORTER_KEY` (from enabling imports on the catalog), `IMPORTER_RATE`
|
||||
(requests a second to IMVU, default 2), optionally an IMVU account for exact revisions (`IMVU_USERNAME`,
|
||||
`IMVU_PASSWORD`; the operator's choice and risk; the hub never holds IMVU credentials).
|
||||
- Revisions: without an IMVU account, the CDN is probed (`HEAD productdata/<id>/<n>`) once per product; afterwards a
|
||||
recheck tries the next few numbers. With one, `authorizeProducts` gives exact revisions.
|
||||
- Reads CFLs with t5de-api's `cfl` package; the conversion follows `@imvu/chkn` (dhkatz/imvu.js) as a reference.
|
||||
- Validates with t5de-api's `pack` rules before uploading; a product breaking them fails with the reason. (The spike
|
||||
checks whether typical IMVU products fit; imports may need their own limits.)
|
||||
|
||||
## Hub routes
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| `GET /api/v1/imports/catalogs` | approved catalogs with imports on, accepting grants |
|
||||
| `POST /api/v1/imports/grants` | `{catalog, imvuId, scope, products?, exclude?, listed, consentVersion}` → 201 `{grant}` (pending). With `onBehalf: {imvuId, evidence, proof?}` instead of a linked `imvuId`: an admin-recorded grant. |
|
||||
| `GET /api/v1/imports/grants` | the person's grants; with `catalog=`, a catalog's (its team) |
|
||||
| `PATCH /api/v1/imports/grants/:id` | `{scope?, products?, exclude?, listed?}` |
|
||||
| `POST /api/v1/imports/grants/:id/accept`, `.../decline` | the catalog's team |
|
||||
| `DELETE /api/v1/imports/grants/:id` | withdraw |
|
||||
| `POST /api/v1/imports/proofs` | (admins) `{imvuId}` → `{proof, code}`; `POST .../proofs/:id/check` |
|
||||
| `POST /api/v1/imports/requests` | `{imvuProduct}` or `{imvuCreator}` → `{status: "queued" \| "suggested" \| "counted", product?}` |
|
||||
| `GET /api/v1/imports/requests?imvuCreator=` | counts (the creator, admins) |
|
||||
| `GET /api/v1/imports/available?imvuProducts=a,b` | for the proxy's shop button: which can the person get (and the hub product ID), already have, or request |
|
||||
| `GET /api/v1/imports/jobs?catalog=&status=` | the catalog's team: the queue; `POST .../jobs/:id/retry` |
|
||||
| `POST /api/v1/imports/claim` | `{imvuId}`: claim an unclaimed creator's products for a linked account |
|
||||
|
||||
For importers (`Authorization: Importer <catalog ID>:<key>`) in products.md.
|
||||
|
||||
## Spike (before building the importer)
|
||||
|
||||
1. Import one product by hand as a local pack (full-size textures, no `_contents.json`, parent kept). Does the
|
||||
client wear it as a T5 product, with the parent loading from IMVU? (Never committed: it's IMVU's files.)
|
||||
2. Do typical IMVU products fit the `pack` limits?
|
||||
3. How many HEAD requests does probing take for real shops; does the CDN limit them?
|
||||
4. Is there a public way to list a creator's products (for importing a whole shop at once)?
|
||||
|
||||
## Later
|
||||
|
||||
- Flattened imports (parent included), if keeping the parent on IMVU causes problems.
|
||||
- A dry run: preview an import (and anything over the pack limits) before it's published.
|
||||
- "Get on T5DE" on IMVU's shop and product pages in the client (a t5de patch, using
|
||||
`/api/v1/imports/available`).
|
||||
- Creators who don't want their products as parents of imports (an opt-out hiding imports that derive from theirs).
|
||||
Reference in new issue
Block a user