Reference room templates
FEAT-032 adds three immutable 2.0.0 template contracts. Initial deployment uses
the Wave 2 catalog: existing create entries remain active until an explicit
guarded activation. Startup never activates the new catalog or migrates rooms.
| Template | Locked scene | Seats | Logical surfaces |
|---|---|---|---|
personal-room-basic@2.0.0 |
personal-workspace-v1@0.4.2 |
1 | workspace-main |
meeting-room-basic@2.0.0 |
warm-modern-meeting-room-candidate-01@0.3.4 |
8 | debug-main, whiteboard-wall |
presentation-room-basic@2.0.0 |
presentation-room-v1@0.4.2 |
8 | debug-main |
Repository revisions, file sizes and SHA-256 locks are in
packages/templates/src/product-room-definitions.ts. Historical 0.1.0 and
1.0.0 definitions remain unchanged. Scene geometry owns physical surface
transforms; signed template context owns IDs and allowed media object types.
Create and edit
GET /api/templates returns the active catalog with version, description, actual
preview URL and defaults. After activation it contains exactly the three entries
above. The control plane applies defaults on selection and confirms replacement
of edited defaults. Personal requires an owner and stays private with guest access
disabled; its notes start private. Presentation starts with join-muted selected.
Explicit audio/notes preferences persist per room.
POST /api/rooms resolves the active version on the server and stores its complete
snapshot and absolute scene URL. Omit templateVersion to use the current version,
or send that exact version. Do not send templateSnapshot or a reference
sceneBundleUrl. Direct API and control-plane creates share materialization.
Errors:
| Input | HTTP / error |
|---|---|
| Unknown template | 400 / unknown_template |
| Malformed version | 400 / invalid_template_version |
| Unknown version | 400 / unknown_template_version |
| Known non-current version | 409 / template_version_not_current |
| Deprecated template | 409 / deprecated_template |
| Client snapshot | 400 / server_owned_template_snapshot |
| Reference scene replacement | 409 / reference_scene_override_not_allowed |
| PATCH template or version change | 409 / template_change_not_supported |
| Missing personal owner | 400 / missing_personal_room_owner |
| Public personal room / guest access | 400 / personal_room_must_be_private / personal_room_guest_access_forbidden |
| Personal owner replacement | 409 / personal_room_owner_immutable |
Existing legacy rooms remain editable with their pinned version and scene URL.
Reference PATCH changes permitted room settings and the snapshot's roomConfig
projection only. It cannot replace the version-owned policy or scene. Runtime
verifies scene manifest and self-contained GLB bytes before parsing/rendering;
checksum or required-surface failures show an explicit fallback diagnostic.
Self-host assets
The default origin is immutable jsDelivr by repository and full commit SHA.
Optionally set ROOM_TEMPLATE_ASSET_BASE_URL=https://mirror.example/scenes on API.
Copy byte-identical files under:
<mirror-root>/<owner>/<repository>/<full-commit-sha>/<locked-relative-path>
Include the locked root manifest.json and all four bundle files. Serve them with
browser-readable CORS, correct content types and immutable caching. HTTPS is
required in production. URL credentials, query strings, fragments and traversal
are rejected. This is separate from document/scene upload storage. Mirror changes
affect catalog previews and future rooms only; existing absolute room URLs stay
pinned and must remain available.
Local verification
Build before package tests. Use a disposable PostgreSQL database via
VRATA_TEST_POSTGRES_URL; set VRATA_TEMPLATE_ROLLBACK_STORAGE_MODULE to the built
API storage module of the exact rollback checkout for the mutating rehearsal.
CI builds that checkout automatically. node tools/fetch-reference-template-fixtures.mjs
downloads and verifies pinned assets; isolated reference e2e uses a per-run
PostgreSQL schema and a byte-identical HTTP mirror.
Run pnpm build, pnpm lint, pnpm typecheck, pnpm test, the six locked
template/scene validations, then full pnpm test:e2e. If choosing non-default test
ports, set BASE_URL as well as E2E_API_PORT so both direct-browser and request
fixtures address the same server.
Source: docs/reference-room-templates.md in vrata-labs/platform at revision 380b2e7ff1dd, license Apache-2.0. GitHub