12 KiB
12 KiB
Protocol Notes
This is a behavior guide for packet semantics beyond raw schemas.
Direction
- Client packet schema lives in
server/app/models.py(ClientPacket). - Browser-side validation/parsing lives in
client/src/network/protocol.ts. - Keep these synchronized on every protocol change.
Client -> Server
auth_register: create account with username/password and optional email.auth_login: authenticate with username/password.auth_resume: resume prior session via stored session token.auth_logout: revoke current session and disconnect.welcome_ready: client confirms it acceptedwelcomepreflight and is ready to join active roster.admin_roles_list: request server role list (with user counts + permission sets).admin_role_create: create role.admin_role_update_permissions: replace one role permission set.admin_role_delete: delete role with replacement role reassignment.admin_users_list: request user list for admin actions (action:set_role | ban | unban | delete_account).admin_user_set_role: set target user role.admin_user_ban/admin_user_unban: disable/enable user account.admin_user_delete: permanently delete target account.update_position: client movement intent; server enforces world bounds and movement rate policy.teleport_complete: client signals teleport landing; server rebroadcasts spatial landing cue.update_nickname: nickname change request (server enforces uniqueness).chat_message: player chat.ping: latency measurement.item_add,item_pickup,item_drop,item_delete,item_use,item_update: item actions.item_transfer_targets: request transfer target accounts for one item (includes online + offline active users, excluding current owner).item_transfer: transfer item ownership to another account (targetUserIdrequired).item_secondary_use: trigger type-specific secondary action when implemented.item_piano_note: realtime piano note on/off for active piano use mode.item_piano_recording: piano record/playback control (toggle_record,playback,stop_playback).
Server -> Client
auth_required: authentication challenge after websocket connect.- includes
gridName,welcomeMessage,serverVersion, andexpectedClientRevision.
- includes
auth_result: auth success/failure and session/account metadata.auth_permissions: server-pushed live role/permission refresh for current session.admin_roles_list: role list response payload.admin_users_list: user list response payload.admin_action_result: structured result for admin actions.- admin mutations include
user_deletefor account deletion.
- admin mutations include
welcome: initial snapshot with users/items plus server UI/world metadata.- Server delays roster activation/login broadcast until
welcome_readyis received.
- Server delays roster activation/login broadcast until
signal: forwarded WebRTC offer/answer/ICE.update_position,update_nickname,user_left: presence updates.teleport_complete: peer teleport landing event with spatial coordinates.chat_message: system and user chat stream.pong: ping response.nickname_result: accepted/rejected nickname result.item_upsert: full item replacement after mutation.item_remove: item deletion.item_action_result: action success/failure and user-facing message.item_transfer_targets: transfer target account list for one item.item_use_sound: spatial one-shot sound on successful item use (ifuseSoundconfigured).item_clock_announce: ordered list of clock speech samples to play sequentially as spatial audio.item_piano_note: broadcast piano note on/off with resolved instrument/envelope/spatial params.item_piano_status: structured piano mode/record/playback state events for client runtime control.
Item Packet Behavior
item_upsertis full-state replacement for one item, not partial patch.item_upsert.item.displayis server-owned display text for readonly/system properties (for example:createdBy,updatedBy,createdAt,updatedAt,capabilities,useSound,emitSound).item_action_resultmessages are intended for direct screen-reader/user status feedback.actionincludes:add,pickup,drop,delete,transfer,use,secondary_use,update
- Successful
item_pickupanditem_dropalso emit system chat lines to other users in the room. - Item transfer ownership is account-based; target accounts do not need to be currently connected.
- Piano runtime control no longer depends on parsing
item_action_result.messagetext. item_piano_statuscarries machine-readable piano events (use_mode_entered, record/playback transitions).item_use_soundcontains absolute item world coordinates (x,y) and sound path.- For carried items, source coordinates resolve to the carrier's current position.
item_clock_announcecontains:itemIdsounds: ordered sample URLs (EL640 phrase parts)- absolute source coordinates
x,y - generated by server for manual clock
use, top-of-hour auto announce, and alarm auto announce (when enabled)
teleport_completecontains absolute player world coordinates (x,y) at teleport landing.- Radio metadata (
params.stationName,params.nowPlaying) is server-managed and delivered through normalitem_upsertupdates. item_piano_notecontains:itemId,senderId,keyId,midi,on- resolved
instrument,voiceMode,octave,attack,decay,release,brightness,emitRange - absolute source coordinates
x,y
Welcome Metadata
welcome.auth: authenticated account identity:authenticateduserIdusernamerolepermissionspolicy(usernameMinLength,usernameMaxLength,passwordMinLength,passwordMaxLength)
auth_required.authPolicy: server auth limits advertised before login/register submit.auth_required.gridName/auth_required.welcomeMessage: server-owned pre-login branding values.auth_required.serverVersion: server diagnostics version text shown in connect/reconnect messaging.auth_required.expectedClientRevision: authoritative browser asset revision required by this server instance.auth_result.authPolicy: server auth limits echoed on auth success/failure responses.auth_result.sessionTokenis used by the client to call the instance-scoped HTTP endpointGET <base_path>auth/session/set(Authorization: Bearer <sessionToken>,X-Chgrid-Auth-Client: 1) so the server can issue an instance-scopedHttpOnlysession cookie.welcome.worldConfig.gridSize: server-authoritative grid size used by clients for bounds/drawing.welcome.worldConfig.movementTickMs: server movement-rate window used for client movement pacing.welcome.worldConfig.movementMaxStepsPerTick: max allowed grid steps per movement window.welcome.player: server-assigned spawn/current self position at connect time.welcome.serverInfo: server process identity/version metadata:instanceId: unique id generated at server startupreleaseVersion: shared public release versionserverVersion: server diagnostics version text (release + server revision)expectedClientRevision: browser asset revision required by this server instancegridName: server-owned user-facing grid namewelcomeMessage: server-owned pre-login welcome string
welcome.uiDefinitions: server-provided item UI definitions:itemTypeOrder: add-item menu orderitemTypes[].tooltip: item-level tooltip/help textitemTypes[].capabilities: server-declared actions supported by the typeitemTypes[].editableProperties: editable property keys by item typeitemTypes[].propertyMetadata: property-level metadata (valueType, optionallabel, optionalrange, optionaltooltip, optionalmaxLength, optionaloptions, optionalvisibleWhen)itemTypes[].globalProperties: non-editable global values (useSound,emitSound,useCooldownMs,emitRange,directional,emitSoundSpeed,emitSoundTempo,emitInitialDelay,emitLoopDelay)commandMetadata.mainModeActions: server-authored labels/tooltips for server-backed main-mode commands used by the client command paletteitemManagement.actions: server-authored labels/tooltips and permission-key metadata for item-management actions (transfer,delete)adminMenu.actions: server-authored admin root menu labels/tooltips/ordering for the authenticated user
- Maintainer note: the current server-owned command/menu metadata definitions live in
server/app/ui_metadata.py. - Client item UI requires this metadata from the server; there is no fallback item definition map.
- Client property help/type rendering is metadata-driven; it does not infer fallback types/tooltips from hardcoded key heuristics.
visibleWhensupports equality checks and string negation via!prefix (example:{"mediaEffect": "!off"}).
Validation Boundaries
- Server is authoritative for all action validation and normalization.
- Server is authoritative for movement acceptance (bounds + rate/delta checks).
- Server persists account state (last nickname + last position) and restores spawn from that state on auth login/resume.
- Server also supports websocket handshake cookie resume:
- accepts browser sockets only when websocket
OriginmatchesCHGRID_HOST_ORIGIN - websocket and auth helper routes are scoped under the configured
server.base_path - reads the instance-scoped session cookie from the websocket
Cookieheader - attempts resume before sending
auth_required - exposes
GET <base_path>auth/session/clearto expire theHttpOnlycookie (X-Chgrid-Auth-Client: 1and matchingOriginrequired)
- accepts browser sockets only when websocket
- Server applies auth hardening before accepting login/register/resume:
- login/register PBKDF2 work runs off the event loop in bounded worker concurrency
- repeated auth failures are rate-limited by IP and IP+identity windows
- auth failures include small randomized response jitter to reduce high-resolution probing
- Client validates incoming packet shapes and applies runtime behavior.
- Server is authoritative for role/permission checks on every privileged packet.
voice.sendpermission changes are pushed at runtime viaauth_permissions.- Sound/media field normalization uses shared server policy helpers:
none/offnormalize to empty values- bare filenames normalize to
sounds/<name>for sound-reference fields - media URL-like fields are trimmed/validated consistently
- radio stream metadata fetches only follow validated public
http/httpsURLs and revalidate redirect hops
- Client-side item edit validation is convenience only; server remains source of truth.
Heartbeat/Stale Recovery
- Client sends automatic heartbeat
pingpackets every 10 seconds while connected. - Heartbeat pings use negative
clientSentAtids and are internal (not user-visible ping status). - If websocket close is observed unexpectedly, client starts reconnect flow.
- If a heartbeat
pongis missed for one interval (10 seconds), client also starts reconnect flow. - Reconnect flow waits 5 seconds and retries up to 3 times before stopping.
- After reconnect, if
welcome.serverInfo.instanceIdchanged, client announcesServer restarted. - Client emits
Connected to server. Version <version>.on initialwelcomeandReconnected to server. Version <version>.after reconnect. - If
auth_required.expectedClientRevisionorwelcome.serverInfo.expectedClientRevisiondiffers from the running client revision, client auto-reloads. - Server-only version changes do not trigger browser reload unless
expectedClientRevisionalso changes.