Skip to main content

Chat Module (ItBuild.Chat)

The Chat module provides messaging, notification delivery, and communication infrastructure for the ItBuild platform. It handles SMS, email, Telegram delivery, real-time chat functionality, audio/video calls, and Telegram bot widgets.

Overview

PropertyValue
TypeOptional standard module
PortInternal only (behind AuthProxy)
DatabaseSeparate SQL Server database
Admin Panel/ChatAdmin/
PWA Frontend/chat/ (React 19 + Zustand 5)

Chat admin panel (/ChatAdmin/)

Operator Razor UI is served at /ChatAdmin/ (same origin as AuthProxy in standard deployments). The following routes exist in ItBuild.Chat (Pages/ChatAdmin):

PageRoutePurpose (high level)
Index/ChatAdminDashboard — message/chat aggregates and trends (Chart.js)
Chats/ChatAdmin/ChatsChat list with filters (flags, name, date range)
ChatDetail/ChatAdmin/ChatDetail?ChatId=Single chat — members, messages, moderation-style actions (invalid/missing id redirects to Chats)
Messages/ChatAdmin/MessagesMessage search and delete tooling
Members/ChatAdmin/Memberschat_members registry (optional filters by chat or member id)
Feedback/ChatAdmin/FeedbackFeedback / ratings list
UserFiles/ChatAdmin/UserFilesFile attachment registry (see below)
FileStatistic/ChatAdmin/FileStatisticUsage-focused file statistics
Calls/ChatAdmin/CallsCall history admin view
Escalations/ChatAdmin/EscalationsConsultant escalation queue (AI support flow)
BotWidgets/ChatAdmin/BotWidgetsTelegram bot widget management

User files registry (/ChatAdmin/UserFiles)

Purpose: Operational view of message file attachments — rows in chat_mess that carry a file (non-zero size, file name, or file flag). This is not a separate files table; metadata lives on the message. Binary payload is served by AuthProxy file HTTP API.

Default behavior: Without optional filters, the page loads the latest rows ordered by timetick_update, up to the effective row limit (default 100, clamped 1–10000 via shared AdminFilter).

Download URLs: Each row exposes a download link of the form /auth/v2/file/{messageTimetick} on the current site origin (AuthProxy). This is the raw-ID v2 route; for authenticated operators it is validated through Chat metadata and does not require anonymous raw-ID mode. Code-based guest links continue to use /auth/v2/file/{code}.

Filters (query parameters on UserFiles):

ParameterEffect
OwnerIdCRM-related owner id on the message (chat_mess.owner)
FileNameSubstring match on file_name
FileTypeBucket from extension: image, doc, video, audio, archive, other
MinSize / MaxSizeByte size bounds on file_size
LimitMax rows (see clamp above)
DateFrom / DateToUTC bounds on timetick_update (converted via TimeTick in the query)
TimetickExact message id
FromTickCursor: rows with timetick less than this value
ShowDeletedWhen true, include soft-deleted messages (otherwise Deleted flag excluded)

When OwnerId is set, the page surfaces a quick link to /CrmAdmin/UserDetail?timetick={OwnerId} for CRM dossier context.

Key Capabilities

Message Delivery (5 Channels)

The Chat module is the unified gateway for all outbound communications:

ChannelProvider OptionsUse Cases
SMSTwilio, SMSC, Infobip, Nexmo, SmsApiOTP codes, phone verification
EmailSendGrid, SMTPOTP codes, magic links, password reset, notifications
TelegramTelegram Bot APIOTP delivery, notifications, bot widgets
In-App ChatBuilt-inUser-to-user messaging, support chats
Push NotificationsAuthProxy Web Push transportBackground browser notifications driven by Chat events

Chat System

Full-featured real-time messaging:

  • Private chats — 1-to-1 messaging between users
  • Group chats — multi-user conversations with admin roles
  • Info channels — one-to-many broadcast channels
  • File attachments — files uploaded via AuthProxy file service
  • Message replies — link messages to previous messages
  • Pinned messages — highlight important messages in chat
  • Read tracking — per-user unread message counters
  • Message editing — edit permission tracking with realtime in-place merge via SSE
  • Message search — full-text search across chat history
  • Message forwarding — forward messages between chats
  • Markdown rendering — safe markdown in messages (links, code blocks, lists, quotes; raw HTML and images blocked)
  • Invite chats — personal and group guest links by invite code, with optional 1:1 calls for personal invites

Audio/Video Calls

WebRTC 1:1 calls between chat participants:

  • Direct P2P media via WebRTC
  • Signaling through SSE EventHub (no additional infrastructure for signaling)
  • TURN relay via coturn for NAT traversal
  • Call state machine: Ringing → Connected → Ended
  • Call history with duration tracking
  • Screen share toggle with automatic camera restore
  • Speaker mute, live camera switching between multiple inputs
  • Browser audio processing: echo cancellation, noise suppression, auto gain control
  • No-camera fallback: video calls gracefully fall back to audio-only when no camera is available
  • Stale call cleanup via server heartbeat and browser pagehide
  • Optional embedded STUN in AuthProxy (replaces Google STUN dependency)
  • Call diagnostics panel for ICE connectivity debugging

See Chat Calls for details.

Telegram Bot Widgets

Live-updating dashboards inside Telegram chats:

  • 7 built-in widgets (rates, balances, orders, health monitoring)
  • Custom widget creation via the Chat widget extension mechanism
  • Scope-based authorization for admin widgets
  • Auto-refresh with configurable intervals

See Telegram Bot Widgets for details.

Feedback & Reviews

Built-in feedback system for collecting user reviews:

  • Rating system (5-point scale, positive and negative)
  • Chat-based feedback with conversation support
  • Object-type ratings (App, Service, Product, Order, etc.)
  • Owner rating tracking

Deployment Modes

The Chat module provides the full API regardless of mode. The mode determines which features are enabled in the client PWA:

ModeFeaturesExample
SupportPrivate chats + files + notificationsCustomer support widget
Chat + FeedbackAll chats + feedback + notificationsMarketplace with reviews
FullAll chats + calls + channels + file browser + feedbackCorporate communication (+coturn required)

Mode is configured in chat-settings.js on the client side.

Notification Delivery Model

Chat itself emits typed events through GET /private/v1/events. AuthProxy then fans those events out over two browser transports:

  • SSE via GET /auth/v1/subscribe for active tabs, unread badges, and live UI refresh
  • Web Push via /auth/v1/notifications/* + root sw.js for background delivery

Operational notes:

  • a successful AuthProxy push test proves the sender transport, not the full Chat event pipeline
  • if test push works but a real chat message does not, inspect Chat private/v1/events, AuthProxy EventPoller, and subscription flags
  • for incoming private chats, the notification route should open the peer conversation (/chat/c/{peerCrmId}), not the current user's own CRM id

API Endpoints

Chat Operations (/msg/v1/)

EndpointMethodDescription
send_messagePOSTSend message to chat (regular text, widget JSON, reaction, reply)
get_chat_messagesGETGet messages with pagination
get_unread_messagesGETGet unread messages for user
create_chatPOSTCreate new chat (private, group, channel)
create_private_chatPOSTCreate or get existing 1:1 chat
update_chatPOSTUpdate chat metadata
archive_chatPOSTArchive a private chat
leave_chatPOSTLeave a group chat
add_chat_memberPOSTAdd member to group/channel
remove_memberPOSTRemove member from group/channel
update_memberPOSTUpdate member flags (admin, pinned, hidden)
get_chat_infoGETGet chat details and member count
get_chat_membersGETGet member list
get_chat_filesGETGet files shared in chat
search_messagesGETFull-text search across chat messages
forward_messagePOSTForward message to another chat
edit_messagePOSTEdit a sent message
pin_message / unpin_messagePOSTToggle pinned state on a message
toggle_message_reactionPOSTAdd or remove a reaction (linkKind=reaction)
soft_delete_messagePOSTSoft-delete a message
hard_delete_messagePOSTHard-delete a message (config-gated)
hard_delete_chatPOSTHard-delete a group chat (config-gated)
create_feedbackPOSTCreate feedback/review

Call Endpoints (/msg/v1/call/)

EndpointMethodDescription
initiatePOSTStart a call
answerPOSTAnswer incoming call
rejectPOSTReject incoming call
endPOSTEnd active call
send_signalPOSTExchange SDP/ICE candidates
historyGETGet call history

Internal API (/private/v1/)

Used by other modules (AuthProxy, Core) for delivery:

EndpointMethodDescription
SendSMSPOSTSend SMS via configured provider
SendOTPPOSTSend OTP (auto-selects best channel)
SendEmailPOSTSend arbitrary email
SendEmailPassResetPOSTSend password reset email
SendEmailOTPPOSTSend OTP via email
SendToTelegramPOSTSend message to Telegram bot
get_chat_infoGETGet chat info (internal)
get_chat_membersGETGet member list (internal)
add_memberPOSTAdd member (internal)
remove_memberPOSTRemove member (internal)
delete_messagePOSTDelete message (internal soft/hard flow)

Chat Data Model

Chat Types

FlagValueDescription
Private11-to-1 chat (name = other user's name)
Group2Multi-user conversation
InfoChannel4Broadcast channel (admins post, members read)

Chat Member Roles

FlagValueDescription
Owner1Chat creator (full control)
Admin2Can manage members and settings
Private4Private chat participant
Hidden8Chat hidden from user's list
Pinned16Chat pinned to top

Message Flags

ChatMessFlags is a [Flags] bitmask carried on every chat_mess row. The most relevant bits:

FlagValueDescription
File1Message carries a file attachment (file name + size live on the row, blob in AuthProxy file service).
Pin2Pinned message; pin_message / unpin_message toggle this bit.
Email64Message originated from the AuthProxy inbound email bridge.
Widget256Renderable widget message (live dashboard cell, dev-stand panel, etc.).
WidgetCommand1024Hidden command row produced by widget interaction (_sys.close, refresh, etc.); never shown in the regular feed.
Call512Call event row — content is CallMessageContent JSON. Replaces the dropped video_calls table.
Deleted1<<30Soft-deleted message.

linked_message_id + linkKind build composite messages on top of these flags:

  • linkKind = reply — standard quoted reply; the linked message is shown as a preview.
  • linkKind = reaction — emoji reaction stored as its own chat_mess row aggregated under the target message in the UI.

This flag-based approach lets reactions, widgets, and call rows reuse the entire chat_mess pipeline (search, forward, soft-delete, federation) without separate tables.

OTP Delivery Logic

When SendOTP is called, the Chat module automatically selects the best delivery channel:

1. Check if user has Telegram linked → Send via Telegram (free, instant)
2. Check if user has email → Send via Email
3. Fallback → Send via SMS (paid)

The CommunicationChannel flags control which channels are allowed:

FlagValueDescription
SMS1Allow SMS delivery
Email2Allow email delivery
Messenger4Allow Telegram/messenger delivery

Frontend Architecture (chat.pwa)

The chat PWA is built as a multi-context application — each context is a separate route with its own layout but shared core components (MessageList + MessageInput).

Stack: React 19, Zustand 5, react-router-dom 6, Tailwind CSS 4, Vite 6

Routes

RoutePageDescription
/chat/MessengerChat list, groups, channels
/chat/c/:idChatUniversal message view (works for all chat types)
/chat?code=K8HS73G8CJB7PInvite Chat (personal or group)Public guest shell resolved by invite code + device guid
/chat/supportSupportAuto-create support chat with team routing
/chat/callsCallsCall history with state indicators
/chat/feedback/:type/:idFeedbackRating form + discussion
/chat/files/:chatIdFilesFile browser and gallery
/chat/discuss/:type/:idDiscussionObject discussion without rating

Invite Chat Flow

Invite links open chat.pwa without a browser session. Two invite types are supported:

  • Personal invite — creates a 1:1 private dialog between the link owner and the guest
  • Group invite — adds the guest to an existing group chat (text-only, calls disabled)

The backend resolves a deterministic synthetic guest identity from invite code + X-Device-Guid, so reopening the same code on the same device returns the user to the same guest conversation. Reopening an existing private chat preserves pinned/archive state and read cursors.

Owner-facing UX: logged-in users create personal invites from the new-chat modal and per-group invites from the group members modal in regular chat.pwa. Owned invite links are listed in a dedicated "Invite chats" block on /chat.

Guest capability rules:

  • text messaging is allowed; messages render safe markdown (links, code, lists, quotes)
  • incoming group messages show sender names
  • 1:1 calls are allowed only for personal invite links; group guest links keep calls disabled
  • guest users cannot upload files or use file browser/search flows
  • existing avatar / attachment content can still be opened from the dialog, but guest payloads use code-based AuthProxy URLs (/auth/v2/file/{code}) instead of raw message/file timeticks
  • regular authenticated chat continues to use canonical identifier-based links (/auth/v1/file/{id}) and session-validated download flow

Integration with Other PWAs

Other applications can integrate Chat via deep links plus AuthProxy notification transport:

// Open messenger
window.location.href = '/chat/';

// Open support chat
window.location.href = '/chat/support';

// Open feedback for a product
window.location.href = '/chat/feedback/product/12345';

// Embed support widget (iframe)
<iframe src="/chat/support" style="border:none" />

// Listen for chat events via SSE (active tabs)
const sse = new EventSource('/auth/v1/subscribe', { withCredentials: true });
sse.onmessage = (e) => {
const event = JSON.parse(e.data);
if (event.module === 'chat') updateUnreadBadge(event.data);
};

Background browser notifications use the same Chat events, but browser subscription lifecycle stays on AuthProxy (/auth/v1/notifications/public_key|subscribe|unsubscribe|test) and the shared root service worker.

Configuration

{
"Config": {
"DBConnections": {
"ChatDB": "Server=...;Database=chat_db;..."
},
"SmsSender": "Twilio",
"TwilioSettings": {
"AccountSid": "...",
"AuthToken": "...",
"FromNumber": "+1234567890"
},
"SmtpSettings": {
"Host": "smtp.sendgrid.net",
"Port": 587,
"Username": "apikey",
"Password": "..."
},
"TelegramBot": "bot_token_from_botfather"
}
}

Client Configuration (chat-settings.js)

Per-project chat configuration served by AuthProxy:

window.ChatConfig = {
mode: "full", // "support" | "feedback" | "full"
contexts: {
messenger: true, // Chat list, groups, channels
support: true, // Support auto-chat
feedback: true, // Rating forms, reviews
calls: true, // Call history, WebRTC
fileBrowser: true, // File gallery, search
},
support: {
teamCrmIds: [], // Support team CRM IDs (auto-assign)
welcomeMessage: "", // First message in support chat
},
feedback: {
types: [1], // Allowed FeedbackType values
ratingScale: 5, // 1-5 stars
}
};

Integration

Other modules access Chat through the MessageService client in ItBuild.Shared:

Implementation detail

Source-level examples and database statements are maintained in the module repositories. This public page describes the operational contract and configuration intent.