namespace SVSim.BattleNode.Bridge; /// /// DI-injected options for the battle node. /// public sealed class BattleNodeOptions { /// /// The Socket.IO v2 endpoint URL echoed back to the client on /*/do_matching /// success (matching_state 3004/3007/3011). Matches the prod do_matching wire format: /// host[:port]/socket.io/ — no scheme prefix, must end with /socket.io/. /// The client's BestHTTP SocketManager parses this string directly; a leading /// http:///https:// or a missing trailing slash will make the client /// fail to connect. Host may be an IP, hostname, or FQDN. /// /// Deployment-time value — no hardcoded fallback. Must be provided via the /// "BattleNode:NodeServerUrl" key in appsettings.json (or an /// equivalently-named env var); /// validates presence at startup and throws if empty. /// /// public string NodeServerUrl { get; set; } = ""; /// /// How long the first arriver's WS waits for a partner before disconnecting. /// Matches the architecture spec's 60s default; override (typically lower) /// in tests via the factory. /// public TimeSpan WaitingRoomTimeout { get; set; } = TimeSpan.FromSeconds(60); /// /// Cadence of the server→client alive ("Gungnir") keepalive emit. The driving timer/loop /// (to live on ) is deferred in v1; this is its future /// home so the interval isn't a magic literal stranded on the Gungnir body factory. /// public TimeSpan AliveEmitInterval { get; set; } = TimeSpan.FromSeconds(5); /// /// When true, emits per-frame /// diagnostic logs at Information level: [sio-in] on every inbound msg/alive/hand /// envelope (URI, pubSeq, ackId, dispatch decision, ack-sent flag, ack arg, inbound /// watermark); [sio-out] on every outbound push (URI, pubSeq, playSeq, stock); /// [ws-rx-text] / [ws-rx-bin] on every WS frame received at the transport /// layer; [ws-recv-exit] / [ws-loop-exit] on read-loop termination /// (with WebSocket state + exception type when applicable). Default false — keeps /// production logs clean. Flip on per session for live WS debugging, PvP investigation, /// or to reproduce the kind of softlock chased in /// docs/audits/battle-node-sio-events-2026-06-02.md. /// public bool DiagnosticLogging { get; set; } = false; }