namespace RelayShared.Services; /// /// The plaintext payload of a chat message before E2E encryption is applied. /// /// Lifecycle of a message: /// 1. Client builds a ChatMessageContent (text + optional reply/attachment/mentions). /// 2. Client JSON-serialises it, encrypts with the server's public key (RSA wrapping an /// AES-GCM key), and sends the encrypted blob wrapped in a SocketEncryptedMessage. /// 3. Server decrypts with its private key, re-encrypts with the channel DB key, stores it. /// 4. For each recipient, server decrypts from DB key and re-encrypts with that recipient's /// public key, then delivers via SocketEncryptedMessage. /// 5. Recipient decrypts with their private key and JSON-deserialises back to ChatMessageContent. /// /// This type is intentionally shared by RelayClient and RelayServer so both ends agree on the /// JSON shape. Adding a field here lights up the whole pipeline automatically. /// public sealed class ChatMessageContent { /// The raw message body, including Markdown syntax and @mentions. public string Text { get; set; } = string.Empty; /// When set, this message is a reply. Carries the Surreal record id of the message being replied to. public string? ReplyToId { get; set; } /// Display name of the user being replied to. Lets the client render the quote bar without a lookup. public string? ReplyToSenderUsername { get; set; } /// Trimmed preview of the replied-to text (≤100 chars). Captured at send time so the server never has to look it up. public string? ReplyPreview { get; set; } /// Extracted usernames + special tokens ("everyone", "here"). Drives the ping-badge in the sidebar. public List? Mentions { get; set; } /// Base64-encoded attachment bytes. Null when there's no attachment. public string? AttachmentBase64 { get; set; } /// MIME type of the attachment (e.g. "image/png"). Used to choose between BuildBase64ImageEmbed and BuildFileCard. public string? AttachmentMimeType { get; set; } /// Original filename as chosen by the sender. Shown as the file card label and used for the download path. public string? AttachmentFileName { get; set; } }