Files
chat_grid/docs/protocol-notes.md
2026-02-28 04:52:44 -05:00

9.1 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.
  • 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).
  • admin_user_set_role: set target user role.
  • admin_user_ban / admin_user_unban: disable/enable user 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_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.
  • 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.
  • welcome: initial snapshot with users/items plus server UI/world metadata.
  • 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_use_sound: spatial one-shot sound on successful item use (if useSound configured).
  • 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_upsert is full-state replacement for one item, not partial patch.
  • item_upsert.item.display is server-owned display text for readonly/system properties (for example: createdBy, updatedBy, createdAt, updatedAt, capabilities, useSound, emitSound).
  • item_action_result messages are intended for direct screen-reader/user status feedback.
  • Successful item_pickup and item_drop also emit system chat lines to other users in the room.
  • Piano runtime control no longer depends on parsing item_action_result.message text.
  • item_piano_status carries machine-readable piano events (use_mode_entered, record/playback transitions).
  • item_use_sound contains absolute item world coordinates (x, y) and sound path.
    • For carried items, source coordinates resolve to the carrier's current position.
  • item_clock_announce contains:
    • itemId
    • sounds: 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_complete contains absolute player world coordinates (x, y) at teleport landing.
  • Radio metadata (params.stationName, params.nowPlaying) is server-managed and delivered through normal item_upsert updates.
  • item_piano_note contains:
    • 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:
    • authenticated
    • userId
    • username
    • role
    • permissions
    • policy (usernameMinLength, usernameMaxLength, passwordMinLength, passwordMaxLength)
  • auth_required.authPolicy: server auth limits advertised before login/register submit.
  • auth_result.authPolicy: server auth limits echoed on auth success/failure responses.
  • auth_result.sessionToken is used by the client to call server HTTP endpoint GET /auth/session/set (Authorization: Bearer <sessionToken>, X-Chgrid-Auth-Client: 1) so the server can issue Set-Cookie: chgrid_session_token=...; HttpOnly.
  • 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 startup
    • version: server package version (or unknown fallback)
  • welcome.uiDefinitions: server-provided item UI definitions:
    • itemTypeOrder: add-item menu order
    • itemTypes[].tooltip: item-level tooltip/help text
    • itemTypes[].capabilities: server-declared actions supported by the type
    • itemTypes[].editableProperties: editable property keys by item type
    • itemTypes[].propertyMetadata: property-level metadata (valueType, optional label, optional range, optional tooltip, optional maxLength, optional options, optional visibleWhen)
    • itemTypes[].globalProperties: non-editable global values (useSound, emitSound, useCooldownMs, emitRange, directional, emitSoundSpeed, emitSoundTempo, emitInitialDelay, emitLoopDelay)
    • adminMenu.actions: server-authored admin root menu labels/ordering for the authenticated user.
  • 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.
  • visibleWhen supports 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:
    • reads chgrid_session_token from websocket Cookie header
    • attempts resume before sending auth_required
    • exposes GET /auth/session/clear to expire the HttpOnly cookie (X-Chgrid-Auth-Client: 1 required)
  • 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.send permission changes are pushed at runtime via auth_permissions.
  • Sound/media field normalization uses shared server policy helpers:
    • none/off normalize to empty values
    • bare filenames normalize to sounds/<name> for sound-reference fields
    • media URL-like fields are trimmed/validated consistently
  • Client-side item edit validation is convenience only; server remains source of truth.

Heartbeat/Stale Recovery

  • Client sends automatic heartbeat ping packets every 10 seconds while connected.
  • Heartbeat pings use negative clientSentAt ids and are internal (not user-visible ping status).
  • If websocket close is observed unexpectedly, client starts reconnect flow.
  • If a heartbeat pong is 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.instanceId changed, client announces Server restarted.
  • Client emits Connected to server. Version <version>. on initial welcome and Reconnected to server. Version <version>. after reconnect.
  • If welcome.serverInfo.version differs from running client version, client auto-reloads.