World Permissions
TL;DR: World scripts can request elevated capabilities (read the local player’s user ID, make HTTPS calls to a domain whitelist, increase the file-storage quota). The user sees a prompt and either approves, denies, or adjusts before the world continues. Decisions are stored per-world at %APPDATA%/ChilloutVR/WorldData/{worldId}/WasmPermissions.json.
The permission flags
Section titled “The permission flags”Source: CVR-GameFiles/WasmScripting/WasmWorldPermissions.cs.
public class WasmWorldPermissions { public string WorldId; // CVR world content ID public bool AccessUserIdentity; // UserId only (Username is un-gated) public bool FileStorageApiAllowed; // persistent KV store public bool FileStorageReadRawFiles; // read user-provided files, no quota public long FileStorageStorageLimit; // bytes (default 4 MB) public bool HttpApiAllowed; // HTTPS outbound public string[] HttpAllowedDomains; // host allow-list}Detail per flag (behaviour verified from CVR-GameFiles/WasmScripting/PlayerBindings.cs and FileStorageManager.cs):
- AccessUserIdentity — Without it,
CVR_Player_GetUserIdreturnsGuid.Empty.ToString()(the decompiled shipped version also walks a per-session counter to stand in for usernames; the CCK source releasedGetUsernamefrom the gate entirely in Preview.27-WASM.27). A world that depends on canonical user IDs (scoreboards, role gates, ban lists) still needs this flag. - FileStorageApiAllowed — Turns on the
FileStorage_*binding family for this world. Without it,FileStorageManager.CheckAPIAccessthrowsWasmAccessDeniedExceptionon every read/write/list call. - FileStorageReadRawFiles — Lets
FileStorageManager.GetInfofall through to user-placed raw files inLocalStorage/. These files are read-only from the script (writes still go through the encrypted path) and don’t count toward the quota. - FileStorageStorageLimit — Bytes. Default
4_194_304(4 MB). User-adjustable via a 46-value palette running 1 KB → 16 GB inWasmPermissionsPage. - HttpApiAllowed — Enables outbound HTTPS once a future binding lands. The permission is persisted and surfaced through
OnWorldPermissionsChangedtoday; no HTTP host binding is live yet. - HttpAllowedDomains — Each entry is required to start with
https://(WorldPermissionsMarshalStruct.ToPermissionsthrows otherwise). HTTPS only; no raw TCP, no cleartext HTTP.
Request flow
Section titled “Request flow”Source: CVR-GameFiles/WasmScripting/WorldPermissionsManager.cs.
- At world load —
CVRGameEventSystem.World.OnLoadfires,LoadPermissions(worldId)readsWasmPermissions.json(or falls back to the defaults), andOnPermissionsChanged(CurrentPermissions)is invoked. World-VM scripts withOnWorldPermissionsChangedreceive the initial state throughWasmVM.CallOnWorldPermissionsChanged. - Guest requests — the script calls the host binding
WorldPermissions_RequestPermissions(marshalStructPtr). The marshal struct is a flattenedWasmWorldPermissionswith pointer+length arrays for the domain list; seeWorldPermissionsMarshalStruct.cs. The binding first callsCheckAccess(World, Any)— non-world scripts throwWasmAccessDeniedException. - Compare — the manager only prompts
_promptedThisSession == false && !CurrentPermissions.IsContentsSame(requested). A matching set short-circuits silently._promptedThisSessionis reset each world load, so one prompt per session per world is the upper bound. - Prompt — otherwise
WasmPermissionsPage.RequestPermissionsopens a confirm dialog (“Review” / “Ignore”). On “Review” the user sees:- toggle for each flag,
- the storage-limit slider (46 steps),
- the domain list as read-only text (user can’t add domains; they either accept the list as-is or deny
HttpApiAllowed), - “Open Storage Folder” shortcut,
- “Apply” button (disabled until the pending set differs from the saved set).
- Save — on Apply,
AcceptPermissionswritesWasmPermissions.jsonin%LocalAppData%/ChilloutVR/WorldData/{worldId}/and overwritesCurrentPermissionsiff the saved permissions’WorldIdmatchesInstances.CurrentWorldId. - Broadcast —
OnPermissionsChangedfires; the host calls the guest exportCVR_WorldPermissions_OnWorldPermissionsChanged(marshalStructPtr)with the accepted permissions, and the guest-side dispatcher fans it out to every behaviour that definedOnWorldPermissionsChanged. Non-world VMs never receive this event.
Storage file
Section titled “Storage file”%APPDATA%/ChilloutVR/WorldData/{worldId}/├── WasmPermissions.json # permission decisions└── {hash}.part.wasmdata # FileStorage data, XOR-encrypted{worldId} is the published CVR world ID.
The UI
Section titled “The UI”Source: CVR-GameFiles/ABI_RC.Systems.WasmScripting/WasmPermissionsPage.cs.
- Toggle buttons per flag.
- Storage quota slider with a 46-value palette from 1 KB to ~17 TB.
- Domain list viewer — read-only; the world requested them, the user either accepts the list as-is or denies the HTTP permission entirely.
- “Open Storage Folder” — reveals
{WorldData}/{worldId}/in the OS file browser. - “Apply” — commits to disk and fires the change event.
Context axes are still enforced
Section titled “Context axes are still enforced”World permissions do not widen the three-axis ObjectContext/OwnerContext/ScopeContext check. For example, enabling FileStorageApiAllowed on an avatar has no effect — the binding is gated to ObjectContext.World. World permissions layer on top of that to gate world-scoped features that are otherwise dangerous (user identity, HTTP).
Querying current permissions
Section titled “Querying current permissions”From a guest script:
// Pseudocode against the intended high-level wrapper exposed by CCKWasmModule:var current = WorldPermissions.Current;if (current.HttpApiAllowed && current.HttpAllowedDomains.Contains("api.example.com")){ // safe to do an HTTP call}Exact API name depends on the CCKWasmModule version. From the binding side the only request function is WorldPermissions_RequestPermissions; query happens via the OnWorldPermissionsChanged event (which fires once on startup with the current state).
Source
Section titled “Source”CVR-GameFiles/WasmScripting/WasmWorldPermissions.cs— the six-flag shape stored per world.CVR-GameFiles/WasmScripting/WorldPermissionsManager.cs— load/save + prompt-once-per-session gate.CVR-GameFiles/WasmScripting/WorldPermissionsBindings.cs— host binding forWorldPermissions_RequestPermissions.CVR-GameFiles/WasmScripting/WorldPermissionsMarshalStruct.cs— guest↔host serialization, enforceshttps://prefix.CVR-GameFiles/ABI_RC.Systems.WasmScripting/WasmPermissionsPage.cs— CVR UI wiring (Init,OpenPage, 46-step storage slider).
Related
Section titled “Related”- Permissions — the lower, always-on access control.
- File Storage — the API this unlocks.
- Networking — CVR’s in-instance networking is unaffected; HTTP is the flag for external calls.