/** * Named Socket.IO namespaces. * - TRADING: all authenticated users; receives user-scoped bot state * - ADMIN: admin-only; receives full cross-user state + admin-specific events * * Root namespace (/) is kept for backward compatibility. */ export const SOCKET_NAMESPACES = { TRADING: '/trading', ADMIN: '/admin', } as const; export type SocketNamespace = typeof SOCKET_NAMESPACES[keyof typeof SOCKET_NAMESPACES]; export function buildTradingSocketOptions(token: string, socketPath?: string) { return { transports: ['polling', 'websocket'] as ('polling' | 'websocket')[], auth: { token }, ...(socketPath ? { path: socketPath } : {}), }; } export function isUnauthorizedSocketError(message: string) { const normalizedMessage = message.toLowerCase(); return normalizedMessage.includes('unauthorized') || normalizedMessage.includes('invalid token'); }