Files
Toju/agents-docs/features/server-directory.md
T
2026-07-14 00:41:05 +02:00

5.5 KiB

Server Directory

Area: server-directory Status: Active Last updated: 2026-07-05

Overview

Server directory is the cross-context contract for which signaling servers exist, how clients health-check and route to them, and how public/private chat-servers are created, joined, updated, moderated, and discovered over REST. It spans the signaling server (server/src/routes/servers.ts, CQRS handlers) and the product client (server-directory domain + ServerDirectoryFacade).

Curated browse lists (featured/trending) are documented separately in server-discovery.md. WebSocket membership (join_server, presence) is in signaling.md.

Responsibilities

  • Server: persist public server records, memberships, channels, roles, bans, invites, join requests; expose REST CRUD and access checks.
  • Client: maintain configured endpoint list, health/compatibility probes, canonical endpoint dedup by serverInstanceId, room sourceId/sourceUrl affinity, and HTTP orchestration for all server operations.
  • It does NOT own: P2P chat transport, voice WebRTC, or local Electron room/message persistence (except mirroring server metadata into local DB after join).

Key concepts

  • ServerEndpoint: configured signaling base URL with health status, latency, and version compatibility.
  • ServerInfo: public server card shape returned by search/discovery/GET — includes sourceId, sourceName, sourceUrl filled by the client API layer.
  • Room signal affinity: each saved room records which endpoint registered it; reconnect prefers that URL before fallback endpoints.
  • serverInstanceId: stable id from GET /api/health used to collapse alias URLs to one canonical endpoint.

Public REST (no bearer)

Method Path Purpose
GET /api/health Liveness, serverVersion, serverInstanceId, optional serverTag
GET /api/servers Free-text search / public listing (q, limit)
GET /api/servers/featured Curated popular list — server-discovery.md
GET /api/servers/trending Curated active list — server-discovery.md
GET /api/servers/:id Single server metadata

Protected REST (bearer required)

All mutations derive the actor from the session token; body user ids are not trusted.

Method Path Purpose
POST /api/servers Register a new public server
PUT /api/servers/:id Update name, description, channels, icon metadata, access settings
DELETE /api/servers/:id Unregister server (owner)
POST /api/servers/:id/join Join or request access (password, invite, public)
POST /api/servers/:id/leave Leave membership
POST /api/servers/:id/heartbeat Refresh lastSeen for trending ranking
POST /api/servers/:id/invites Create invite link — invites-join-requests.md
GET /api/servers/:id/requests List pending join requests (moderators)
POST /api/servers/:id/moderation/kick Remove member
POST /api/servers/:id/moderation/ban Ban member (optional expiry)
POST /api/servers/:id/moderation/unban Lift ban

Join-request approval: PUT /api/requests/:idinvites-join-requests.md.

Plugin metadata under /api/servers/:serverId/pluginsplugins.md.

Client endpoint lifecycle

  1. Load endpoints from localStorage (metoyou_server_endpoints); reconcile with environment defaults.
  2. testAllServers() probes GET /api/health (5 s timeout); on failure falls back to GET /api/servers.
  3. Mark incompatible when serverVersion fails semantic compatibility check.
  4. resolveCanonicalEndpoint() collapses aliases sharing the same serverInstanceId.
  5. Cold-start room reconnect waits for the initial health sweep before opening WebSockets.

Multi-endpoint behavior

Operation Fan-out
Search (searchServers with searchAllServers) All online endpoints, dedupe by server id
Discovery (featured/trending) All online endpoints + 404→public list fallback
Room CRUD/join Authoritative room sourceUrl first; temporary fallback to other compatible endpoints on outage

Only status === 'incompatible' stops fallback with an update-required message. Network errors and Cloudflare 521/522 must continue to the next endpoint.

Server-owned channel metadata

PUT /api/servers/:id persists the server's channels array (text + voice). The client round-trips channel create/rename/delete through this API — local-only channel state is not authoritative. Server-side normalisation deduplicates names within each channel type.

WebSocket complement

After REST join, the client sends join_server on the room's signaling URL. Presence (server_users, user_joined, user_left) is room-scoped on the WebSocket — see signaling.md.

Changelog

Date Change
2026-07-05 Initial cross-context server-directory REST contract