nspasojevic commited on
Commit
97119cb
Β·
verified Β·
1 Parent(s): 1d6ed53

Stop production native USD experiment and restore GLB for every interactive asset

Browse files
Dockerfile CHANGED
@@ -282,7 +282,7 @@ COPY docker/hf-space/search_fields.yaml /app/search_fields.yaml
282
  # own uvicorn; remapped to 8003 here).
283
  COPY docker/hf-space/supervisord-gpu.conf /etc/supervisor/conf.d/hf-space.conf
284
 
285
- COPY docker/hf-space/nginx.conf.template /etc/nginx/hf-space.conf.template
286
 
287
  COPY services/explorer/dist /usr/share/nginx/explorer
288
 
 
282
  # own uvicorn; remapped to 8003 here).
283
  COPY docker/hf-space/supervisord-gpu.conf /etc/supervisor/conf.d/hf-space.conf
284
 
285
+ COPY docker/hf-space/nginx-glb-production.conf.template /etc/nginx/hf-space.conf.template
286
 
287
  COPY services/explorer/dist /usr/share/nginx/explorer
288
 
docker/hf-space/nginx-glb-production.conf.template ADDED
@@ -0,0 +1,371 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Friendly external paths remapped to deepsearch-api's/asset-graph-service's
2
+ # actual routes β€” same mapping as
3
+ # usdsearch/helm/usdsearch/templates/api_gateway_config_map.yaml.
4
+ # deepsearch-api listens on 127.0.0.1:8000, asset-graph-service on
5
+ # 127.0.0.1:8010 (see docker/hf-space/supervisord.conf) β€” nginx is the sole
6
+ # process bound to the externally proxied port, so it can front every route
7
+ # with these rewrites plus CORS.
8
+ #
9
+ # The Explorer UI is served at `/` (root), not proxied to deepsearch-api at
10
+ # all β€” served directly from the static bundle baked into this image at
11
+ # build time (see the Dockerfile). Real difference from the multi-service
12
+ # deployment, which proxies /ui and /static/ to a *separate*
13
+ # deepsearch-explorer container: that bundle is just static files with
14
+ # same-origin relative API calls (REACT_APP_API_URL baked empty) and its
15
+ # own assets already use root-absolute paths (/static/js/..., /ds.png), so
16
+ # serving it directly at `/` β€” where it already expects to live β€” needs no
17
+ # extra process and no /ui prefix-stripping trick. The tradeoff: unlike the
18
+ # old single catch-all proxy, deepsearch-api's own root-level routes
19
+ # (/health, /docs, /redoc, /openapi.json) now need to be listed
20
+ # explicitly below, since the final `location /` falls through to the SPA
21
+ # instead. Also sidesteps a real problem seen live: a Space deployed with
22
+ # `/` returning a 301 (redirecting to `/ui`, the previous approach) broke β€”
23
+ # root cause not fully confirmed, but consistent with Hugging Face's own
24
+ # readiness check wanting a real 200 at `/`, not a redirect.
25
+ #
26
+ # __PORT__ is substituted with $PORT at container start (supervisord.conf),
27
+ # matching the Spaces convention of an operator-configurable app_port.
28
+
29
+ # >>> simready-central slim explorer (http) >>>
30
+ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
31
+ # SPDX-License-Identifier: Apache-2.0
32
+ # Included from nginx.conf's http{} (conf.d/*.conf) β€” an http-level directive is legal here.
33
+ # ONE level under /tmp on purpose: nginx mkdir()s only the last path component (no mkdir -p), and
34
+ # nothing in this image pre-creates a parent β€” /tmp/nginx-cache/slim-stats fails `nginx -t`. The
35
+ # `levels=` subdirectories are different: nginx creates those itself on the first write.
36
+ proxy_cache_path /tmp/slim-stats-cache levels=1 keys_zone=slim_stats_cache:2m max_size=256m inactive=1h use_temp_path=off;
37
+ # Thumbnails (/images): ~1,500 JPEGs of 27-52 KB (~75 MB) fit well inside 1g. Lives in the container's
38
+ # /tmp, so every deploy, restart or sleep starts it cold.
39
+ proxy_cache_path /tmp/slim-images-cache levels=1:2 keys_zone=slim_images_cache:10m max_size=1g inactive=7d use_temp_path=off;
40
+ # Library media (/library_media/ below): a file asked for under its ?v= (its content hash) never changes; the
41
+ # manifest (no ?v=) revalidates, so a new fetch at the next container start shows at once.
42
+ map $arg_v $slim_library_cache {
43
+ "" "no-cache";
44
+ default "public, max-age=31536000, immutable";
45
+ }
46
+ # <<< simready-central slim explorer (http) <<<
47
+ server {
48
+ listen __PORT__;
49
+
50
+ proxy_http_version 1.1;
51
+ proxy_set_header Connection "";
52
+ proxy_connect_timeout 5s;
53
+ proxy_send_timeout 60s;
54
+ proxy_read_timeout 60s;
55
+ proxy_set_header Host $host;
56
+ proxy_set_header X-Real-IP $remote_addr;
57
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
58
+ proxy_set_header X-Forwarded-Proto $scheme;
59
+
60
+ add_header Access-Control-Allow-Origin "*" always;
61
+ add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
62
+ add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
63
+
64
+ location /search {
65
+ if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
66
+ rewrite ^/search(.*)$ /v2/deepsearch/search$1 break;
67
+ proxy_pass http://127.0.0.1:8000;
68
+ }
69
+
70
+ location /search_hybrid {
71
+ if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
72
+ rewrite ^/search_hybrid(.*)$ /v3/deepsearch/search$1 break;
73
+ proxy_pass http://127.0.0.1:8000;
74
+ }
75
+
76
+ location /vlm_validate/search_result {
77
+ if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
78
+ rewrite ^/vlm_validate/search_result(.*)$ /v3/deepsearch/vlm_validate/search_result$1 break;
79
+ proxy_pass http://127.0.0.1:8000;
80
+ }
81
+
82
+ location /llm_parse/ {
83
+ if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
84
+ rewrite ^/llm_parse/(.*)$ /v3/deepsearch/llm_parse/$1 break;
85
+ proxy_pass http://127.0.0.1:8000;
86
+ }
87
+
88
+ # package-download (127.0.0.1:8020, pipeline/package_download/), not deepsearch-api: it answers
89
+ # /download/asset with the asset's whole SimReady package folder, same response contract, and
90
+ # forwards scope=dependencies (and anything outside a catalogued package) to deepsearch-api's
91
+ # own /v3/download/asset. It serves the /download/... paths itself, so no rewrite.
92
+ location /download {
93
+ if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
94
+ proxy_pass http://127.0.0.1:8020;
95
+ # Fetching a whole package (or a forwarded dependency bundle) can take longer than a single thumbnail.
96
+ proxy_read_timeout 300s;
97
+ }
98
+
99
+ location /images {
100
+ if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
101
+ rewrite ^/images(.*)$ /v3/images$1 break;
102
+ proxy_pass http://127.0.0.1:8000;
103
+ }
104
+
105
+ location /static/ {
106
+ alias /usr/share/nginx/explorer/static/;
107
+ }
108
+
109
+ # asset-graph-service routes (query-time graph reads only β€” see
110
+ # docker/Dockerfile.hf-space's header for why there's no graph-builder/
111
+ # asset_graph_generation worker in this image). Same rewrites as the
112
+ # real gateway config's asset_graph_service locations, just proxying to
113
+ # our own internal port instead of a separate service/Space.
114
+ location /asset_graph/usd/scene_summary/ {
115
+ if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
116
+ rewrite ^/asset_graph/usd/scene_summary/(.*)$ /asset_graph/usd/scene_summary/$1 break;
117
+ proxy_pass http://127.0.0.1:8010;
118
+ }
119
+
120
+ location /asset_graph/usd/scene_summary {
121
+ if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
122
+ rewrite ^/asset_graph/usd/scene_summary(.*)$ /asset_graph/usd/scene_summary/$1 break;
123
+ proxy_pass http://127.0.0.1:8010;
124
+ }
125
+
126
+ location /asset_graph/usd/prims {
127
+ if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
128
+ rewrite ^/asset_graph/usd/prims(.*)$ /asset_graph/usd/prims$1 break;
129
+ proxy_pass http://127.0.0.1:8010;
130
+ }
131
+
132
+ location /dependency_graph {
133
+ if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
134
+ rewrite ^/dependency_graph(.*)$ /dependency_graph$1 break;
135
+ proxy_pass http://127.0.0.1:8010;
136
+ }
137
+
138
+ # deepsearch-api's own root-level routes β€” explicit now that `location /`
139
+ # below serves the Explorer SPA instead of proxying everything
140
+ # unmatched. /docs and /redoc are prefix matches, not exact: Swagger
141
+ # UI/ReDoc can request sub-resources under their own path.
142
+ location = /health { proxy_pass http://127.0.0.1:8000; }
143
+ location = /openapi.json { proxy_pass http://127.0.0.1:8000; }
144
+ # Prometheus /metrics stays private to the container (127.0.0.1:8000
145
+ # directly): an explicit JSON 404 rather than no location, which would
146
+ # fall through to the SPA's index.html with a 200.
147
+ location = /metrics {
148
+ default_type application/json;
149
+ return 404 '{"detail":"Not Found"}';
150
+ }
151
+ location /docs { proxy_pass http://127.0.0.1:8000; }
152
+ location /redoc { proxy_pass http://127.0.0.1:8000; }
153
+
154
+ # The Explorer SPA (see header comment) at root: try_files serves any of
155
+ # its own literal files (index.html, ds.png, favicon.ico, manifest.json,
156
+ # ...) directly, and falls back to index.html for anything else
157
+ # (client-side routing) β€” anything actually meant for the API above was
158
+ # already matched by a more specific location before nginx gets here.
159
+ # >>> simready-central slim explorer >>>
160
+ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
161
+ # SPDX-License-Identifier: Apache-2.0
162
+ # services/explorer/dist is SimReady Central's search-only Explorer (repo simready-central,
163
+ # branch slim, slim/devspace/). The locations here are additive β€” exact matches, longer
164
+ # prefixes or a regex β€” and none of his locations is redefined. This block carries: /config.js,
165
+ # a no-cache /index.html, a 10-min
166
+ # proxy cache on /search/stats/usd_properties, a shared proxy cache on /images,
167
+ # /wikidata_hierarchy.json, /library_media/ and JSON 404s for the routes this build does not have. What DOES
168
+ # reach beyond it: client_max_body_size 32m is server-wide (it applies to ALL his locations
169
+ # too); `= /images` takes the requests his `/images` prefix served before (same rewrite +
170
+ # proxy_pass, plus the cache); and an
171
+ # add_header inside one of our locations replaces his server-level headers for THOSE responses
172
+ # β€” /images and the stats cache re-declare his three CORS lines, /config.js and /index.html
173
+ # (same-origin UI files) do not. Applied by slim/devspace/deploy.sh.
174
+ client_max_body_size 32m; # query-image searches POST a base64 JPEG (nginx default 1 MB)
175
+ gzip_types text/css application/javascript application/json image/svg+xml; # stock gzip covers text/html only
176
+
177
+ # Runtime index registry (blocking <script src="/config.js">). The CORPUS_NAME marker is
178
+ # rendered by the same sed that renders the PORT marker (supervisord.conf).
179
+ # __DOWNLOAD_ENABLED__ is rendered the same way, from $DOWNLOAD_ENABLED
180
+ # (baked by docker/Dockerfile.hf-space, set true only for a
181
+ # storage_api-backend corpus β€” pipeline/bake.py's hf_space_build_args()
182
+ # β€” since that's the only backend this image runs a live hf-storage-api
183
+ # gRPC server for; GET /v3/download/asset works today for neither
184
+ # backend without it running, and this repo hasn't verified an s3-backend
185
+ # download path independently, so s3 corpora keep today's false).
186
+ # seedDefaultScope:false β€” boot browses the corpus. No defaultFilters (owner, 2026-10-07): the boot browse
187
+ # shows every license; License stays one click away in the rail.
188
+ # railFilters + railDefaults ["profiles","simready_metadata_asset_license","category"]: rail = Profiles + License +
189
+ # the Category tree, all on (owner, 2026-09-30). The rail matches a facet by its parser-catalog field NAME:
190
+ # search_fields.yaml names it simready_metadata_asset_license since 2026-09-23 ("license" matched nothing and
191
+ # hid the facet); the parser catalog
192
+ # docker/hf-space/search_fields.yaml stays curated to profile + license. propertyAliases: this API stores the
193
+ # Wikidata code as semantic:wikidata_qcode:params:semanticData (wikidata_qcode= matches nothing here), so the
194
+ # Explorer translates its canonical name at the wire and renames the stats key back on arrival.
195
+ # propertyFilterCombine "and": the API ORs every filter_by_properties_include_any token globally, so with License
196
+ # checked a Category pick would change nothing β€” a property with ONE checked value rides filter_by_properties
197
+ # (AND) instead; a multi-valued one (the tree's qcodes) stays the OR bucket. Measured: license 1488, one qcode 124,
198
+ # both in include_any 1488, license AND qcode 124.
199
+ location = /config.js {
200
+ default_type application/javascript;
201
+ add_header Cache-Control "no-cache, must-revalidate" always;
202
+ return 200 '(function(){var c="__CORPUS_NAME__";if(!c||c.indexOf("__")===0){c="usdsearch-dev";}var e={"field_name":"siglip2-embedding.embedding","dimension":1536};var f={"download":__DOWNLOAD_ENABLED__,"s3UrlRemap":false,"seedDefaultScope":false,"railFilters":["profiles","simready_metadata_asset_license","category"],"railDefaults":["profiles","simready_metadata_asset_license","category"],"propertyAliases":{"wikidata_qcode":"simready_metadata_qcode"},"propertyFilterCombine":"and","submitContentUrl":"__SUBMIT_CONTENT_URL__"};window.__SERVER_MAPPING__={"usdsearch-dev":{"name":c+" (Hugging Face)","apiUrl":"","embedding_config":e,"features":f},"hf-robotiq":{"name":"Robotiq","apiUrl":"","search_path":"/Robotiq-Official/simready-assets/","embedding_config":e,"features":Object.assign({},f,{"libraryPosters":"stills"}),"origin":{"kind":"hf","label":"Robotiq-Official/simready-assets"}},"hf-standardbots":{"name":"Standard Bots","apiUrl":"","search_path":"/standardbots/","embedding_config":e,"features":Object.assign({},f,{"libraryPosters":"stills"}),"origin":{"kind":"hf","label":"standardbots"}}};window.__DEFAULT_SERVER__="usdsearch-dev";})();';
203
+ }
204
+ # index.html must always revalidate (covers the try_files fallback too): a swap or rollback
205
+ # must not leave a browser holding an index.html that names deleted chunks.
206
+ location = /index.html {
207
+ root /usr/share/nginx/explorer;
208
+ add_header Cache-Control "no-cache" always;
209
+ }
210
+
211
+ # Property inventory (rail facets + parser grounding): multi-MB aggregation β€” cached 10 min.
212
+ location = /search/stats/usd_properties {
213
+ if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
214
+ rewrite ^/search(.*)$ /v2/deepsearch/search$1 break;
215
+ proxy_pass http://127.0.0.1:8000;
216
+ proxy_ignore_headers Cache-Control Expires;
217
+ proxy_cache slim_stats_cache;
218
+ proxy_cache_key "$request_uri";
219
+ proxy_cache_valid 200 10m;
220
+ proxy_cache_lock on;
221
+ proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
222
+ proxy_read_timeout 120s;
223
+ add_header X-Cache-Status $upstream_cache_status always;
224
+ # add_header above drops his server-level headers β€” re-declared as in his template
225
+ add_header Access-Control-Allow-Origin "*" always;
226
+ add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
227
+ add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
228
+ }
229
+ # Thumbnails: his `location /images` rewrite + proxy_pass (this exact match wins over his prefix)
230
+ # plus a SHARED cache β€” every cold /images costs the API ~150 CPU-ms on its one event loop.
231
+ # Keyed by the full URI (image_key, or asset_url + img_offset); the API's `Cache-Control: private`
232
+ # is ignored on purpose. Valid ONLY while the image runs with STORAGE_REQUIRE_AUTH=False (deploy.sh
233
+ # refuses a hub Dockerfile without it): with per-user storage auth, add
234
+ # `proxy_no_cache $arg_asset_url; proxy_cache_bypass $arg_asset_url;` so the access-checked
235
+ # asset_url path is never shared (image_key is content-addressed and unchecked). add_header here
236
+ # drops his server-level headers, so his three CORS lines are re-declared; proxy_hide_header
237
+ # keeps a chained nginx (check.sh --replica) to its own X-Cache-Status.
238
+ location = /images {
239
+ if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
240
+ rewrite ^/images(.*)$ /v3/images$1 break;
241
+ proxy_pass http://127.0.0.1:8000;
242
+ proxy_cache slim_images_cache;
243
+ proxy_cache_key "$request_uri";
244
+ proxy_ignore_headers Cache-Control Expires;
245
+ proxy_hide_header X-Cache-Status;
246
+ proxy_cache_valid 200 7d;
247
+ proxy_cache_lock on;
248
+ proxy_cache_lock_timeout 15s;
249
+ proxy_cache_use_stale error timeout updating;
250
+ add_header X-Cache-Status $upstream_cache_status always;
251
+ add_header Access-Control-Allow-Origin "*" always;
252
+ add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
253
+ add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
254
+ }
255
+ # Our 404s are JSON like the API's own (a bare `return 404;` would be nginx's text/html error
256
+ # page): reachable only from the locations below, so nothing of his changes.
257
+ location @slim_not_found {
258
+ default_type application/json;
259
+ return 404 '{"detail":"Not Found"}';
260
+ }
261
+ # The Category tree: the `hierarchy` stage's output, restored with the index run (pipeline/hierarchy/store.py);
262
+ # absent β†’ a real 404 and the Explorer falls back to its __full_path tree.
263
+ location = /wikidata_hierarchy.json {
264
+ root /app/hf-space-pipeline/.build/restore/hierarchy;
265
+ try_files /category_hierarchy.json @slim_not_found;
266
+ }
267
+ # One request per result page (QA 6881558: Hugging Face limits each user to ~2,000 requests a minute,
268
+ # and a page of per-image checks took 50): deepsearch-api's /vlm_validate/search_result_batch streams one
269
+ # NDJSON verdict per hit. The Explorer calls this path; the request and the lines are the same.
270
+ # Unbuffered so verdicts land as they come; heartbeats keep the stream open.
271
+ location = /vlm_validate/batch_stream {
272
+ if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
273
+ rewrite ^ /v3/deepsearch/vlm_validate/search_result_batch break;
274
+ proxy_pass http://127.0.0.1:8000;
275
+ proxy_buffering off;
276
+ proxy_read_timeout 120s;
277
+ gzip off;
278
+ add_header X-Accel-Buffering no always;
279
+ add_header Access-Control-Allow-Origin "*" always;
280
+ add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
281
+ add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
282
+ }
283
+ # Any other /vlm_validate/ path: a JSON 404, never the SPA's index.html.
284
+ location /vlm_validate/ {
285
+ default_type application/json;
286
+ return 404 '{"detail":"Not Found"}';
287
+ }
288
+ # Six qualified partner robots are installed from one SHA-pinned S3 ZIP by
289
+ # pipeline/partner_viewer.py. Its own viewer uses these root-relative paths;
290
+ # the USD path is narrower than the native-USD release service's route.
291
+ location = /trial { absolute_redirect off; return 308 /trial/; }
292
+ location = /trial/ {
293
+ root /app/hf-space-pipeline/.build/partner_viewer;
294
+ try_files /trial/index.html @slim_not_found;
295
+ }
296
+ location ^~ /trial/ { root /app/hf-space-pipeline/.build/partner_viewer; index index.html; try_files $uri @slim_not_found; }
297
+ location ^~ /media/ { root /app/hf-space-pipeline/.build/partner_viewer; try_files $uri @slim_not_found; }
298
+ location ^~ /rust/ { root /app/hf-space-pipeline/.build/partner_viewer; try_files $uri @slim_not_found; }
299
+ location ^~ /three/ { root /app/hf-space-pipeline/.build/partner_viewer; try_files $uri @slim_not_found; }
300
+ location ^~ /usd-round2/ { root /app/hf-space-pipeline/.build/partner_viewer; try_files $uri @slim_not_found; }
301
+ location ^~ /usd/usd-central/rust-assets/hf- {
302
+ root /app/hf-space-pipeline/.build/partner_viewer;
303
+ try_files $uri @slim_not_found;
304
+ }
305
+ # Library media β€” the Explorer's joints viewer (model.glb + articulation.json), moving-parts and drop-test
306
+ # clips, per asset of this corpus: static files pipeline/library_media.py fetches at container start from
307
+ # the artifact bucket (supervisord program library-media). Not there (not fetched yet, or none for
308
+ # this corpus) β†’ a JSON 404 and the Explorer shows no media; never the SPA's index.html. Range requests
309
+ # (Safari's <video>) are nginx's own. add_header drops his server-level headers: his CORS lines re-declared.
310
+ # Native USD is a separately pinned release. Its verified 2 GiB cache keeps
311
+ # the full catalog out of the Space's boot-time restore and disk budget.
312
+ # User-requested production rollback: every interactive asset uses GLB.
313
+ location = /library_media/usdsearch-dev/usd-catalog.json {
314
+ alias /app/hf-space-pipeline/pipeline/native_usd_releases/production-glb-catalog.json;
315
+ default_type application/json;
316
+ add_header Cache-Control "no-store";
317
+ gzip_types application/json;
318
+ }
319
+ location /usd/usd-central/ {
320
+ default_type application/json;
321
+ add_header Cache-Control "no-store";
322
+ return 404 '{"detail":"Native USD experiment is paused; use GLB"}';
323
+ }
324
+ location /usd-rust/ {
325
+ root /usr/share/nginx/explorer;
326
+ try_files $uri =404;
327
+ gzip_static on;
328
+ add_header X-Content-Type-Options nosniff;
329
+ }
330
+ # The three picker entries share one physical corpus and one media archive.
331
+ # Keep partner URLs on the same files so a scoped picker can load their RTX
332
+ # media and native USD catalog without duplicating the archive on disk.
333
+ location = /library_media/hf-robotiq/usd-catalog.json {
334
+ root /app/hf-space-pipeline/.build;
335
+ default_type application/json;
336
+ add_header Cache-Control "no-cache" always;
337
+ }
338
+ location = /library_media/hf-standardbots/usd-catalog.json {
339
+ root /app/hf-space-pipeline/.build;
340
+ default_type application/json;
341
+ add_header Cache-Control "no-cache" always;
342
+ }
343
+ location ^~ /library_media/hf-robotiq/ {
344
+ rewrite ^/library_media/hf-robotiq/(.*)$ /library_media/usdsearch-dev/$1 last;
345
+ }
346
+ location ^~ /library_media/hf-standardbots/ {
347
+ rewrite ^/library_media/hf-standardbots/(.*)$ /library_media/usdsearch-dev/$1 last;
348
+ }
349
+ location /library_media/ {
350
+ root /app/hf-space-pipeline/.build; # .build/library_media/: outside .build/restore/, which the index restore empties
351
+ try_files $uri @slim_not_found;
352
+ types { application/json json; model/gltf-binary glb; video/mp4 mp4; image/jpeg jpg; image/webp webp; }
353
+ default_type application/octet-stream;
354
+ gzip_types application/json model/gltf-binary; # meshopt GLBs still shrink under gzip
355
+ add_header Cache-Control $slim_library_cache always;
356
+ add_header X-Content-Type-Options nosniff always;
357
+ add_header Access-Control-Allow-Origin "*" always;
358
+ add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
359
+ add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
360
+ }
361
+ # Central's per-user surface is absent in this build: hard 404s, never the SPA's index.html.
362
+ location ~ ^/(auth|packs|prefs|chats|created_assets|concept_images|meshy_quota|info|process|folder_hierarchy\.json|category_hierarchy\.json|api/create-chat|api/cad2simready)(/|$) {
363
+ default_type application/json;
364
+ return 404 '{"detail":"Not Found"}';
365
+ }
366
+ # <<< simready-central slim explorer <<<
367
+ location / {
368
+ root /usr/share/nginx/explorer;
369
+ try_files $uri $uri/ /index.html;
370
+ }
371
+ }
docker/hf-space/supervisord-gpu.conf CHANGED
@@ -136,6 +136,8 @@ stderr_logfile=/dev/stderr
136
  stderr_logfile_maxbytes=0
137
 
138
  [program:native-usd]
 
 
139
  command=/usr/bin/env -u PYTHONPATH /bin/sh -c "cd /app/hf-space-pipeline && exec /app/.venv/bin/python -m pipeline.native_usd"
140
  directory=/app/hf-space-pipeline
141
  user=1000
 
136
  stderr_logfile_maxbytes=0
137
 
138
  [program:native-usd]
139
+ ; User stopped the production USD experiment. Preserve artifacts for later.
140
+ autostart=false
141
  command=/usr/bin/env -u PYTHONPATH /bin/sh -c "cd /app/hf-space-pipeline && exec /app/.venv/bin/python -m pipeline.native_usd"
142
  directory=/app/hf-space-pipeline
143
  user=1000
pipeline/native_usd_releases/production-glb-catalog.json ADDED
The diff for this file is too large to render. See raw diff