# Yonexus.Server Yonexus.Server is the central hub plugin for a Yonexus network. It runs on the main OpenClaw instance and is responsible for: - accepting WebSocket connections from follower instances - enforcing the `followerIdentifiers` allowlist - driving pairing and authenticated reconnects - tracking heartbeat/liveness state - rewriting inbound client rule messages before dispatch - sending pairing notifications to the human admin via Discord DM ## Status Current state: **core runtime MVP with Discord DM transport wired via REST API** Implemented in this repository today: - config validation - runtime lifecycle wiring - JSON persistence for durable trust records - WebSocket transport and single-active-connection promotion model - pairing session creation - auth proof validation flow - heartbeat receive + liveness sweep - rule registry + send-to-client APIs - Discord DM pairing notifications via Discord REST API (`notifyBotToken` + `adminUserId`) Still pending before production use: - broader lifecycle integration with real OpenClaw plugin hooks - more operator-facing hardening / troubleshooting polish - expanded edge-case and live-environment validation beyond the current automated suite ## Install Layout This repo expects the shared protocol repo to be available at: ```text protocol/ ``` In the umbrella repo this is managed as a submodule. ## Configuration Required config shape: ```json { "followerIdentifiers": ["client-a", "client-b"], "notifyBotToken": "", "adminUserId": "123456789012345678", "listenHost": "0.0.0.0", "listenPort": 8787, "publicWsUrl": "wss://example.com/yonexus" } ``` ### Field notes - `followerIdentifiers`: allowlisted client identifiers - `notifyBotToken`: bot token used for pairing notifications - `adminUserId`: Discord user that receives pairing DMs - `listenHost`: optional bind host, defaults to local runtime handling - `listenPort`: required WebSocket listen port - `publicWsUrl`: optional public endpoint to document/share with clients ## Runtime Overview Startup flow: 1. validate config 2. load persisted trust records 3. ensure allowlisted identifiers have base records 4. start WebSocket transport 5. start liveness sweep timer Connection flow: 1. unauthenticated socket connects 2. client sends `hello` 3. server decides `pair_required`, `waiting_pair_confirm`, or `auth_required` 4. if needed, server creates a pending pairing request and notifies admin out-of-band 5. client confirms pairing or authenticates with signed proof 6. authenticated connection is promoted to the active session for that identifier ## Public API Surface Exported runtime helpers currently include: ```ts sendMessageToClient(identifier: string, message: string): Promise sendRuleMessageToClient(identifier: string, ruleIdentifier: string, content: string): Promise registerRule(rule: string, processor: (message: string) => unknown): void ``` Rules: - `builtin` is reserved and cannot be registered - server-side dispatch expects rewritten client-originated messages in the form: ```text ${rule_identifier}::${sender_identifier}::${message_content} ``` ## Persistence Durable state is stored as JSON and includes at least: - identifier - pairing status - public key - secret - pairing metadata - heartbeat / auth timestamps - last known liveness status Rolling nonce and handshake windows are intentionally rebuilt on restart in v1. ## Development Install dependencies and run type checks: ```bash npm install npm run check ``` ## Limitations Current known limitations: - DM delivery depends on Discord bot permissions and the target user's DM settings - no offline message queueing - no multi-server topology - no management UI - transport is covered mainly by automated tests rather than live Discord end-to-end validation ## Related Repos - Umbrella: `../` - Shared protocol: `../Yonexus.Protocol` - Client plugin: `../Yonexus.Client`