feat(web): finish RE 5000PBR lesson video and fix non-ASCII GLB import
- Add 11:07 Chinese-narrated lesson video, VTT, poster and 13 chapter screenshots. - Regenerate 20-render WebGL2 matrix and 15 operation captures on RTX 4060. - Fix WASM staging for non-ASCII import filenames (猴头.glb); rebuild web_engine. - Harden lesson video recording pipeline; fix stale lesson-link E2E selector. - Add RE PBR derived libraries, lesson page, evidence and status report. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,7 @@ when every response, including errors and SPA fallbacks, preserves these headers
|
||||
| `Cross-Origin-Opener-Policy` | `same-origin` |
|
||||
| `Cross-Origin-Embedder-Policy` | `require-corp` |
|
||||
| `Cross-Origin-Resource-Policy` | `same-origin` |
|
||||
| `Content-Security-Policy` | `default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; worker-src 'self'; connect-src 'self'; font-src 'self'; img-src 'self' blob:; media-src 'self' blob:; object-src 'none'; base-uri 'none'; frame-ancestors 'none'` |
|
||||
| `Content-Security-Policy` | `default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self'; style-src-attr 'unsafe-inline'; worker-src 'self'; connect-src 'self'; font-src 'self'; img-src 'self' blob:; media-src 'self' blob:; object-src 'none'; base-uri 'none'; frame-ancestors 'none'` |
|
||||
|
||||
Production uses HTTPS. Loopback development may use `http://127.0.0.1`; `file://` is unsupported.
|
||||
Runtime assets are same-origin. A reverse proxy must not strip the isolation, range, cache, MIME or
|
||||
@@ -204,7 +204,7 @@ NanoVDB is `application/x-nanovdb`.
|
||||
|
||||
## Range and validators
|
||||
|
||||
`.wasm`, `.blend` and `.nvdb` accept a single `bytes` range. A valid range returns `206` with
|
||||
`.wasm`, `.blend`, `.nvdb`, `.mp4` and `.webm` accept a single `bytes` range. A valid range returns `206` with
|
||||
`Accept-Ranges`, `Content-Range`, `Content-Length` and a strong content SHA-256 ETag. An invalid or
|
||||
unsatisfied range returns `416`. An `If-Range` mismatch ignores the range and returns the complete
|
||||
resource with status `200`; partial bytes from a different revision must never be combined.
|
||||
|
||||
@@ -2,20 +2,47 @@
|
||||
"schemaVersion": 1,
|
||||
"product": "Web Blender Modeler V1",
|
||||
"browserScope": "Chromium",
|
||||
"privateDeployment": { "scope": "current Linux host, single authorized user", "usernameEnvironment": "WEB_BLENDER_USERNAME", "defaultUsername": "owner", "passwordEnvironment": "WEB_BLENDER_PASSWORD", "authentication": "HTTP Basic over HTTPS", "productionIngress": "HTTPS reverse proxy preserving Host and Authorization; HTTP listener remains loopback by default", "unauthenticatedExternalBinding": "reject", "authenticatedCacheControl": "private, no-store", "crossOriginMutation": "reject", "validation": "NOT_RUN", "acceptance": "NOT_CLAIMED" },
|
||||
"privateDeployment": {
|
||||
"scope": "current Linux host, single authorized user",
|
||||
"usernameEnvironment": "WEB_BLENDER_USERNAME",
|
||||
"defaultUsername": "owner",
|
||||
"passwordEnvironment": "WEB_BLENDER_PASSWORD",
|
||||
"authentication": "HTTP Basic over HTTPS",
|
||||
"productionIngress": "HTTPS reverse proxy preserving Host and Authorization; HTTP listener remains loopback by default",
|
||||
"unauthenticatedExternalBinding": "reject",
|
||||
"authenticatedCacheControl": "private, no-store",
|
||||
"crossOriginMutation": "reject",
|
||||
"validation": "NOT_RUN",
|
||||
"acceptance": "NOT_CLAIMED"
|
||||
},
|
||||
"transport": {
|
||||
"production": "https",
|
||||
"localDevelopment": "http://127.0.0.1",
|
||||
"fileProtocolSupported": false,
|
||||
"sameOriginRuntimeAssets": true
|
||||
},
|
||||
"methods": ["GET", "HEAD"],
|
||||
"methods": [
|
||||
"GET",
|
||||
"HEAD"
|
||||
],
|
||||
"serverOperator": {
|
||||
"path": "/api/server-operator-job",
|
||||
"methods": ["GET", "POST"],
|
||||
"actions": { "describe": "POST", "submit": "POST", "read": "GET|POST", "cancel": "POST" },
|
||||
"methods": [
|
||||
"GET",
|
||||
"POST"
|
||||
],
|
||||
"actions": {
|
||||
"describe": "POST",
|
||||
"submit": "POST",
|
||||
"read": "GET|POST",
|
||||
"cancel": "POST"
|
||||
},
|
||||
"cacheControl": "no-store",
|
||||
"configuration": ["BLENDER_BIN", "PYTHON_BIN", "SERVER_OPERATOR_WORKSPACE_ROOT"]
|
||||
"configuration": [
|
||||
"BLENDER_BIN",
|
||||
"PYTHON_BIN",
|
||||
"SERVER_OPERATOR_WORKSPACE_ROOT"
|
||||
]
|
||||
},
|
||||
"responseHeaders": {
|
||||
"allResponses": {
|
||||
@@ -27,27 +54,38 @@
|
||||
"routes": [
|
||||
{
|
||||
"id": "entry-document",
|
||||
"patterns": ["/", "/index.html"],
|
||||
"patterns": [
|
||||
"/",
|
||||
"/index.html"
|
||||
],
|
||||
"cacheControl": "no-cache"
|
||||
},
|
||||
{
|
||||
"id": "runtime-manifest",
|
||||
"patterns": ["/engine-manifest.json"],
|
||||
"patterns": [
|
||||
"/engine-manifest.json"
|
||||
],
|
||||
"cacheControl": "no-cache"
|
||||
},
|
||||
{
|
||||
"id": "content-hashed-assets",
|
||||
"patterns": ["/assets/*"],
|
||||
"patterns": [
|
||||
"/assets/*"
|
||||
],
|
||||
"cacheControl": "public, max-age=31536000, immutable"
|
||||
},
|
||||
{
|
||||
"id": "stable-engine-assets",
|
||||
"patterns": ["/vendor/blender/*"],
|
||||
"patterns": [
|
||||
"/vendor/blender/*"
|
||||
],
|
||||
"cacheControl": "no-cache"
|
||||
},
|
||||
{
|
||||
"id": "fallback",
|
||||
"patterns": ["*"],
|
||||
"patterns": [
|
||||
"*"
|
||||
],
|
||||
"cacheControl": "no-cache"
|
||||
}
|
||||
]
|
||||
@@ -73,16 +111,28 @@
|
||||
".mp4": "video/mp4",
|
||||
".webm": "video/webm",
|
||||
".blend": "application/octet-stream",
|
||||
".nvdb": "application/x-nanovdb"
|
||||
".nvdb": "application/x-nanovdb",
|
||||
".vtt": "text/vtt; charset=utf-8"
|
||||
},
|
||||
"rangeRequests": {
|
||||
"extensions": [".wasm", ".blend", ".nvdb"],
|
||||
"extensions": [
|
||||
".wasm",
|
||||
".blend",
|
||||
".nvdb",
|
||||
".mp4",
|
||||
".webm"
|
||||
],
|
||||
"unit": "bytes",
|
||||
"singleRangeOnly": true,
|
||||
"etag": "strong-sha256",
|
||||
"satisfiedStatus": 206,
|
||||
"unsatisfiedStatus": 416,
|
||||
"requiredSatisfiedHeaders": ["Accept-Ranges", "Content-Range", "Content-Length", "ETag"],
|
||||
"requiredSatisfiedHeaders": [
|
||||
"Accept-Ranges",
|
||||
"Content-Range",
|
||||
"Content-Length",
|
||||
"ETag"
|
||||
],
|
||||
"ifRangeMismatch": "return-full-200"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user