From 5db4939799d3df545b6c558cfdf8095ab9180d06 Mon Sep 17 00:00:00 2001 From: dhkatz Date: Thu, 29 Oct 2026 02:33:16 -0700 Subject: [PATCH] Product revisions with a public history Co-Authored-By: Claude Opus 5.5 --- docs/design.md | 48 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/docs/design.md b/docs/design.md index d1108c7..36f387a 100644 --- a/docs/design.md +++ b/docs/design.md @@ -73,7 +73,7 @@ age, not verified) and `tagline`. ### Proxy (`t5de-proxy`) - **IMVU passthrough**: as today. -- **Product resolver**: community products are named (global product ID, version) everywhere outside the machine. +- **Product resolver**: community products are named (global product ID, revision) everywhere outside the machine. The client only understands 32-bit integers (XML-RPC), so the proxy maps each to a local ID in a reserved range near the top (about 1.9-2.1 billion), stored per install. It answers the client's permission, product-info and file requests for them, and splits mixed requests (the IMVU part forwarded unchanged). @@ -114,13 +114,14 @@ age, not verified) and `tagline`. ## Products and catalogs -- **The hub is the registry.** Products have **global IDs** owned by their creator. A **version** is a file list - (path, sha256, size), signed by the hub on the creator's behalf (creator-held keys later). Versions never change. +- **The hub is the registry.** Products have **global IDs** owned by their creator. A **revision** is a file list + (path, sha256, size), signed by the hub on the creator's behalf (creator-held keys later). Revisions never change. - **Catalogs host and curate**: their own rules, ratings ceiling and community. A catalog stores files and tells the - hub which versions it hosts. The same version on several catalogs is mirrored, not duplicated: uploading a file - list identical to an existing version links to it. Variants link with **derived from** (credit, and the original + hub which revisions it hosts. The same revision on several catalogs is mirrored, not duplicated: uploading a file + list identical to an existing revision links to it. Variants link with **derived from** (credit, and the original creator's derive permission). -- **Outfits and rooms refer to (product, version)**, so any catalog hosting it can serve it. +- **Outfits and rooms refer to products and revisions** (see Revisions), so any catalog hosting a revision can serve + it. - **Files** are named by hash, immutable, served from object storage or a CDN; never through Go. - **Ratings**: general and adult, as IMVU. Catalogs declare the highest rating they host. - **Uploads** go from the creator's browser (or the proxy) straight to the catalog's API with a hub token, so large @@ -128,9 +129,28 @@ age, not verified) and `tagline`. thumbnails generated, extra texture maps accepted (see Better looks). - **Format**: IMVU's own product files, as the client loads them, so creators keep using IMVU's tools. +### Revisions (**Decided**: public history) + +A **revision** is the product itself: its files. IMVU has revisions too (its file addresses carry a revision +number, `productdata///`) but hardly shows them; T5DE shows them openly. + +- **Numbered** 1, 2, 3... per product. Uploading changed files makes a new revision; editing info doesn't. +- **History on every product's page**, for everyone: each revision's number and date, the creator's notes (what + changed, required when publishing), a preview image, the files added, removed or changed (with sizes), its + rating, and which catalogs host it. Any two revisions can be compared. +- **Which revision people get**: by default an outfit follows the **latest** revision, as on IMVU. A wearer can + instead **stay on** a revision (if they prefer an older look), shown as such on their outfit. What a wearer + broadcasts in a room is always a concrete revision, so everyone sees the same one. +- **Old revisions stay available**, so outfits and rooms keep working. A creator can **retract** a broken + revision: it's marked retracted in the history, and anyone following or staying on it moves to the nearest + revision that isn't. Only moderation removes a revision outright (shown as "removed by moderation", with the + files gone). +- **Derived from** points to a specific revision of the original. +- Moderators see the same history, plus who uploaded each revision and from where. + ### Product info (**Decided**: editable) -- A product's **files** come in versions that never change; its **info** belongs to the product and its creator +- A product's **files** come in revisions that never change; its **info** belongs to the product and its creator can edit it at any time on the hub's website: name, description, icon, tags, category. Stored at the hub, so an edit shows everywhere (every catalog, every client) without re-uploading anything. - **Icon**: an image uploaded to the hub, re-encoded there (decoded and saved again as PNG or WebP at fixed sizes, @@ -159,7 +179,7 @@ age, not verified) and `tagline`. ### Catalogs (`t5de-catalog`) - Go program, SQLite or Postgres, S3-compatible storage, docker-compose for operators. -- **API**: catalog and search, versions, files by hash, uploads, reports, takedowns. +- **API**: catalog and search, revisions, files by hash, uploads, reports, takedowns. - **No user-facing site** (**Decided**): users, creators and operators use the hub's website. Operators' rights come from hub tokens ("operator of catalog X"); the catalog enforces them itself, so operators stay in charge of their server. @@ -217,7 +237,7 @@ is per person, shared across their accounts. ## Better looks -Versions can carry extra texture maps (normal, roughness, ...) beside the standard ones. The proxy hands them to +Revisions can carry extra texture maps (normal, roughness, ...) beside the standard ones. The proxy hands them to T5DE's renderer, which uses them when drawing the item; IMVU products and other clients get the standard textures. Hub and catalogs only store and label the files; the work is in t5de-renderer. @@ -249,7 +269,7 @@ One Go program in modules (split into services only if load requires it): - **IMVU checks**: background jobs reading IMVU's public API (tagline when linking; `is_ageverified` when linking and at most daily). Called rarely and cached: IMVU could block the hub's address, and nothing but linking may depend on IMVU being up. -- **Registry**: products, versions, ratings, derivations, catalogs and what they host, search (Postgres full-text +- **Registry**: products, revisions, ratings, derivations, catalogs and what they host, search (Postgres full-text first; Meilisearch when needed). - **Realtime gateway** (WebSocket): presence, badge, room channels, hosted rooms. Live room state in memory on the node owning the room; NATS passes it between nodes once there's more than one. @@ -269,10 +289,10 @@ imvu_link(person, imvu_id, pairwise_id, linked_at, age_verified, age_checked_at, creator(id, person, name, page) catalog(id, url, operators, max_rating, status, signing_key) product(id, creator, rating, slot, derived_from, price) -version(product, number, manifest_sha256, signature, extra_maps) -hosting(catalog, version) +revision(product, number, manifest_sha256, signature, notes, created_at, status, extra_maps) +hosting(catalog, revision) ownership(person, product, source, price) -outfit(imvu_link, items[(product, version)]) +outfit(imvu_link, items[(product, pinned revision or latest)]) room(id, owner, scene, furniture[], roles, bans) report(...), moderation_action(...), audit(...) ``` @@ -298,7 +318,7 @@ The proxy streams and adds no waiting. - **Hub down**: community items fall back to IMVU's defaults; everything IMVU keeps working; hosted rooms are unavailable. -- **Catalog down**: its items come from the proxy's cache or another catalog hosting the same version, else +- **Catalog down**: its items come from the proxy's cache or another catalog hosting the same revision, else defaults. - **IMVU's API down**: linking and age checks wait; existing links and cached checks keep working.