export declare const ROOM_CREDENTIAL_AUDIENCE: "helix-instant-room"; export interface RoomTrialClaim { id: string; itemId: string; kind: 'avatar' | 'vehicle'; /** Trial expiry as Unix epoch seconds, sealed into the room credential. */ expiresAt: number; } /** A scalar an `openRoom` effect may seed a declared roomVar / playerVar with (credential `roomInit` / `playerInit`). */ export type RoomInitValue = number | boolean | string; /** * Claims the backend signs (HS384) and the room verifies. Mirrors the world_session claim shape * (sub/displayName/worldId/scopes/jti) plus the immutable buildId the room loads its config from. */ export interface RoomCredentialClaims { /** Player/user id. */ sub: string; /** Sanitized display name for nameplates. */ displayName: string; /** * CDN URL of the user's equipped universal avatar, absent/null when they have none. The backend * only mints it when the avatar's web asset is stamped `skeleton: 'helix-humanoid'` AND has a * usable glbUrl — so a present claim is loadable by definition. The room copies it into * `PlayerState.avatarUrl` (the ONLY identity-derived claim replicated besides displayName; `sub` * never is). (v17) */ avatarUrl?: string | null; /** World the room belongs to. */ worldId: string; /** Immutable build the room loads its declarative config (allowed messages, room-var shape) from. */ buildId: string; /** Active published Build UUID used to resolve the fleet snapshot. Absent for Home and legacy credentials. */ baseBuildId?: string; /** Scopes from manifest.permissions; must include 'multiplayer' to join a room. */ scopes: string[]; /** Manifest maxPlayers (authoritative) → the room's maxClients cap, so it auto-locks + spills when full. */ maxPlayers: number; /** Monotonic per-world build counter (1, 2, 3 …) of the active build — telemetry + config cache key. */ buildNumber: number; /** * Signed URL of this build's `multiplayer.json` — the validated declarative config baked into the * published bundle. Derived server-side from the build, NEVER client-supplied, so the room fetches its * config from an authentic, immutable location and caches the parsed result by buildId. The room * tolerates its absence (older credentials / a build with no declared config) by running the fixed schema. */ configUrl: string; /** Server-minted, page-view-scoped marketplace trial carried into the reserved room. */ trial?: RoomTrialClaim; /** * Named room type this credential admits to (manifest `multiplayer.roomTypes.`). ABSENT = the world's * default room type, which is what every credential minted before room types carries — so an older room * server, which never reads the claim, keeps working. The room treats the client-supplied `roomType` join * option as untrusted and rejects unless it equals this claim (absent on both sides = default), the same * treatment as `trial.id` vs the `trialId` option. For a typed room `maxPlayers` is that TYPE's cap. */ roomType?: string; /** * Ticketed rooms only: the room instance id (a backend-minted uuid, `world_room_instances.id`). Unguessable, * and minted only into credentials for holders of a ticket to that instance — it is what partitions one * ticketed match from another of the same type. Absent for the default type and for `open` types. */ instanceKey?: string; /** * Initial values for the target type's DECLARED roomVars, fixed by the `openRoom` effect that created the * instance. Applied once, at room creation, from the creating credential; unknown keys or wrong scalar types * are ignored by the room with a warning. */ roomInit?: Record; /** * Initial values for THIS player's declared playerVars in the target type, evaluated per selected player by * the `openRoom` effect. Applied at join; unknown keys or wrong scalar types are ignored with a warning. */ playerInit?: Record; /** Always ROOM_CREDENTIAL_AUDIENCE. */ aud: typeof ROOM_CREDENTIAL_AUDIENCE; iss: string; exp: number; iat: number; jti: string; }