File size: 8,146 Bytes
31be700
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0470239
 
31be700
 
 
 
 
 
 
 
34b32b9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31be700
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0672639
31be700
 
 
 
 
 
 
 
 
 
 
 
 
 
8d9c703
 
 
 
 
31be700
 
0470239
 
 
 
 
 
 
 
 
31be700
 
 
 
 
0672639
31be700
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# Community interactions — 2026-11-01

## Scope and viewer extension

Only idol-commons-dev is changed. The original Scenario Space is untouched.
The minimum viewer extensions are an orbit-direction getter on the splat engine,
optional community metadata in the collection adapter, a same-origin refresh/hide
message, and an inspector layout override. Spatial placement, d3 navigation,
search, original download bytes and engine lifetime are preserved. The shared
canvas is not replaced. Community metadata changes do not recreate a selected
WebGL scene.

## Thumbnail selection

`POST /api/generations/{uuid}/thumbnail` accepts only a strict unit direction
vector and an Idempotency-Key. Session, origin, CSRF, owner and TTL are checked;
authenticated sessions are reverified with HF. No image, URL, path, camera target,
projection or browser screenshot is accepted. The server fits the validated PLY
bounds at the existing 35-degree field of view, with IDOL's -Y up axis. Zoom is
normalized for consistent collection framing; the chosen angle is retained.
Limits: 12 updates per anonymous session/day, 30 per HF account/day, 100 globally
per hour. Anonymous quotas are not per-person quotas. One preview renderer runs
at a time with the existing process memory/time limits. Preview failure remains
recoverable without inference. Requests with the same key and body are idempotent.

Publication is locked out until the new PNGs, hashes, crop and camera are ready.
The private bucket acknowledges files before the ready state. A publication
reservation prevents later edits to that private generation. Authors can edit
the published thumbnail separately through My contributions. PLY bytes remain unchanged.
The preview URL includes its hash to invalidate the private browser image cache.

## Likes and activity

`PUT /api/assets/{uuid}/like` accepts only `{"liked": true|false}`.
A real verified HF account owns one vote, independently of the browser session.
The desired-state API makes repeats safe; unlike decrements the current total.

`GET /api/basket` establishes a signed, HttpOnly browser cookie and returns the
current private version. `PUT /api/basket` accepts only a version and a bounded
list of asset IDs, with session/origin/CSRF checks. It replaces that browser's
selection atomically; repeated syncs cannot add duplicate memberships. Version
conflicts trigger a refresh/retry. Adding, removing, clearing, reopening, going
back online and cross-tab storage changes synchronize the full local selection.
The cookie survives sign-in/sign-out, so these are browser baskets, not people
or account counts. Browsers are counted separately. No asset list is returned
by the read endpoint; only aggregate counts are public.

The viewer's `baskets` value counts memberships synchronized within 90 days.
The signed cookie and private hashed membership records expire after 90 days of
inactivity. The app renews active baskets; local selections remain local even
if a count sync fails. Removed/unknown objects are excluded on synchronization.
Old cumulative `basket_adds` values are preserved separately; historical
occupancy cannot be reconstructed. Existing baskets enter the new count when
the app is reopened. Dataset stats schema 1.1.0 adds `baskets` and still accepts
1.0.0 snapshots. No old totals are relabelled as current memberships.

`POST /api/assets/{uuid}/activity` accepts only `basket_add` or `download_request`.
These are app activity signals, available to valid anonymous sessions as well as
verified contributors. Identity is HMAC-derived server-side. Each kind is counted
at most once per asset/actor/UTC day. `basket_adds` is cumulative additions, NOT
current basket occupancy. `download_requests` includes requesting a ZIP, PLY,
script or copying the download command; it does NOT prove a file was saved and
excludes direct Hub downloads. Cancellations/network failures can still count.
A reset anonymous session can count again; these are estimates, not unique people.
Activity tracking is best-effort in the client and never blocks local basket use
or original-file downloads. Votes show recoverable errors and require sign-in.

Quota: 60 changes per actor/10 minutes and 2,000 globally/10 minutes. Recent
activity deduplication records are removed after 48 hours; rate windows after
one day. Active vote hashes remain to support unlikes; inactive rows expire after
7 days. Only aggregates enter the public dataset. The existing private encrypted
HF bucket is reused; no extra secrets or infrastructure are introduced. Keep
SESSION_SECRET stable: it keys the private actor identities.

`social/stats.json` is the validated versioned aggregate envelope;
`social/stats.jsonl` exposes rows keyed by asset_id;
`social/stats.schema.json` documents strict types and limits. No usernames,
subjects, actor hashes or event logs are exported. Canonical records retain their declared licence and schema; new publications use 1.2.0. A stream ID prevents silent replacement
of public totals by a fresh/incorrect private journal. Remote-newer revisions fail
closed and persist a synchronization guard; later clicks cannot advance an older
restored journal until it overwrites lost votes. An operator must restore and
verify the correct private journal; never delete the guard merely to reset counts. Updates use the dataset-only writer, parent-commit CAS, bounded retry and
lost-response reconciliation. The maintenance loop flushes at most once per
minute when dirty; no per-click git commit. Rows for withdrawn assets disappear
on the next successful flush. Public historical counters may remain in Git.

The viewer reads private-journal aggregates through /api/catalogue immediately;
the dataset snapshot is eventually consistent. Personal liked state and report
visibility are included in a private no-store ETag, never a shared cached response.
The catalogue refresh interval is 15 seconds; explicit successful actions request
an earlier refresh. Navigation and zoom are retained.

HTML entry points revalidate on navigation. The explorer frame URL includes the
host's hashed bundle name to invalidate previously cached unversioned HTML. A
reload therefore upgrades both workspaces together; hashed asset files are kept
available for already-open sessions.

## Reports

A successful verified report now quarantines the object from **all public viewer
responses**, including anonymous requests. Existing open reports are included.
Author/moderator inspection is through private management APIs, not an exception
in the public catalogue. Selection and basket reconcile on refresh (up to 15 s).
Hiding is not removal from the public dataset: immutable file URLs still work.
Reports are private; authors do not receive reporter details/messages. Current
report messages are available only to the configured moderator subjects.
See [ASSET-MANAGEMENT.md](ASSET-MANAGEMENT.md) for authorization, removal and
post-publication thumbnail updates. This supersedes reporter-only hiding.

## Publishing UX and rights

An inline panel replaces the long modal: Details, then Rights & publish. SVG
signals supplement text; they never replace affirmative rights/consent checks.
Input and prompt remain private. Publication terms/schema 1.2.0 offer five per-asset licences with explicit consent, full legal documents and retained prior grants. No existing contribution is automatically relicensed. The IDOL repo declaration does not independently clear its demo images. See [LICENSING.md](LICENSING.md) for the precise source/result distinction and restrictions.

## Validation boundaries

Automated API tests use isolated HF issuer/repository fixtures, including both
local and encrypted bucket backends. They are not real multi-account OAuth tests.
Browser acceptance uses the actual public PLY and its recorded camera, with
mocked local API identity/actions so tests cannot create public votes, reports,
metrics or assets. WebGL, software renderer, viewport sizes and physical-device
limits are recorded separately in the acceptance report. Inference kernels,
model weights, ZeroGPU scheduling and secrets are not changed by this release.