learning_ai_invt_trdg/shared/realtime.ts
Saravana Achu Mac 4cfb446f57 feat(backend): WebSocket namespaces, audit persistence, tab flags, telemetry
- Add /trading and /admin named Socket.IO namespaces; root namespace kept for
  backward compat; admin namespace rejects non-admins at connect time
- Wire auditRepository.ts: persist TradeAuditEvent to Cosmos audit-events
  container (best-effort); expose GET /api/admin/audit for admin queries
- Add tradingTelemetry singleton (Node.js Map-based storage adapter); init
  and fatal-error tracking wired in index.ts main()
- Add TAB_MARKETPLACE_ENABLED / TAB_MEMBERSHIP_ENABLED config flags; expose
  tabs.* shape in GET /api/feature-flags response
- Fix SupabaseService URL validation (regex check before createClient)
- Wire check:api-contract and check:audit-repository into npm run test
- Switch @bytelyst/* deps to file:../vendor/* references

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 19:35:00 -04:00

27 lines
886 B
TypeScript

/**
* 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');
}