Files
EchoHub/docs/changelog/v0.2.12.md
T
HueByte e797ec2542 feat: add /meta command for channel metadata retrieval
- Implemented the `/meta` command to fetch and display channel metadata including room ID, topic, message count, unique user count, estimated size, and protection level.
- Added `ChannelMetaDto` to encapsulate channel metadata.
- Updated `ChannelsController` to handle the new `/meta` endpoint.
- Introduced `UploadLimits` configuration for admin-defined upload size limits for files, images, audio, and avatars.
- Enhanced error handling and user feedback for metadata retrieval.
- Updated documentation to reflect changes in encryption and room metadata.
- Added tests for the new functionality and upload limits.
2026-07-16 07:04:58 +02:00

11 KiB
Raw Permalink Blame History

v0.2.12

Private channels are now genuinely private: password-protected channels are end-to-end encrypted, so the server (and its operators) can gate joins and measure storage but cannot read message or file contents. The IRC gateway grows real MODE/TOPIC support and channel keys, and the client gets image "save original", a transparent-light theme, drag-and-drop file sending, Ctrl+V paste, and a fix for the intermittent Ctrl+W crash.

New Features

  • End-to-end encrypted channels — creating a channel with a password now provisions a zero-knowledge room:
    • The passphrase never leaves the client. It derives (PBKDF2-SHA256, 210k iterations) two keys: an auth key sent to the server as the join credential, and a key-encryption key that never leaves the machine.
    • A random room content key encrypts every message and file with AES-256-GCM. The server only ever stores the room key wrapped under the passphrase, so it can gate joins and report a channel's message count, storage size, and attachments — but cannot decrypt any of it. Even the server owner cannot read a private room's contents.
    • Members' clients cache the derived room key locally (in the per-server config, like saved sessions) so the passphrase isn't retyped every launch; joining on a new device prompts for it once.
    • Change the passphrase with /passwd <old> <new> (channel creator only). The room key is re-wrapped, not rotated, so existing history stays readable and members who join later with the new passphrase can still read older messages.
    • Files and images are encrypted client-side before upload; for images the ASCII-art preview is rendered on the client and stored room-encrypted too. Sending images by URL is disabled in encrypted channels (the server can't fetch-and-render without the key).
    • End-to-end encrypted channels cannot be joined over the IRC gateway (that would require the server to hold the room key) — IRC JOIN returns 475 directing users to the EchoHub client.
  • Password-protected channels — set an optional password when creating a channel (masked field in the Create Channel dialog, password on POST /api/channels). Passwords are BCrypt-hashed server-side; the join gate applies on first join only (existing members and the creator are unaffected). Protected channels show a * marker in the channel list and +k in the status bar
  • Save original images — image messages now show a clickable "[↓ save original]" line under the ASCII-art preview that downloads the full-resolution original to your Downloads folder (decrypting locally in encrypted channels)
  • Messages with attachments (Discord-style) — a message is now text plus a list of attachments instead of being either text or a single file. One message can carry a caption and several files (images, audio, docs) together:
    • Compose with a staging tray: /send <file> or dropping files onto the terminal stages them (shown on the input bar); the next Enter sends your typed caption and all staged files as one message. /clear drops staged files. /send <URL> still posts an image immediately.
    • Each image attachment renders its own ASCII preview with its own "save original" action; audio/file attachments each get their own play/download line.
    • In encrypted channels every attachment is encrypted individually (blob + ASCII preview), and the caption is room-encrypted — the server still stores only ciphertext and can report count/size but not contents.
    • Up to 10 attachments per message.
  • Right-click message menu — right-click any message for a context menu: save/download/play its attachment, mention the sender, view their profile, copy the text, copy the message ID (for linking or command arguments), or delete the message. (Keyboard: F6 focuses the message list for arrow-key selection + Delete.) The selected message is now highlighted while the list is focused.
  • Message deletion — press Delete on a selected message to remove it. You can always delete your own messages; moderators and above can delete others' messages, but only from users below their own role (a mod can't delete an admin's or owner's message). Deleting a message also removes its attachment blobs from server storage.
  • Customizable download folder/downloadpath opens your OS-native folder picker (Windows Explorer / macOS Finder / Linux GTK or KDE) to choose where downloaded attachments and saved images go; /downloadpath <path> sets it directly (the fallback when no native picker is available). Downloaded files now land in that folder (with automatic (n) de-duplication) instead of a temp directory.
  • /join <channel> [password] — join protected channels inline, or let the client prompt: joining a protected channel without a password opens a masked prompt that re-prompts on a wrong password
  • IRC channel keys — JOIN #room <key> works against room passwords (RFC 1459 comma-paired key lists supported); keyless or wrong-key joins get 475 ERR_BADCHANNELKEY
  • IRC MODE implemented — MODE #chan reports +k/+, MODE #chan +k <key> sets and -k clears the room password (channel creator or admin only), ban-list probes get a clean empty reply, and CHANMODES is advertised in ISUPPORT
  • IRC TOPIC set support — the channel creator can change the topic from IRC; the change broadcasts to connected TUI clients (previously topic changes were rejected with a stub error)
  • Attach a file by drag & drop or by pasting — drop a file onto the terminal, or copy a file in your file manager and press Ctrl+V, to stage it as an attachment (the next Enter sends it with your caption). Multiple files at once are supported. Ctrl+V still pastes text when the clipboard holds text; Ctrl+Y is a paste alias. On Windows the copied-file paste reads the clipboard's file list directly (Windows Terminal never pastes copied files as text), with xclip/wl-paste used on Linux
  • Pick ASCII-art size for attached images — /size opens a Small/Medium/Large picker (40×40 / 80×80 / 120×120) with descriptions, /size <s|m|l> sets it directly, and /send <file> -l sets it for that message. The choice is a saved preference and applies to copy-paste/drag-drop images (which have no per-file flag); the current size is shown in the staging tray
  • New TransparentLight theme — dark characters on a transparent background, for light terminal color schemes (/theme transparentlight)
  • /meta command — shows a summary of the current room: room id, created date, message count, unique participant count, estimated storage size, and protection level (open / password-protected / end-to-end encrypted). Works for encrypted rooms too, since these are all metadata the server tracks without reading content. (/info is an alias.)
  • Configurable upload limits — a new Uploads section in the server settings sets the maximum size per file, image, audio clip, and avatar, plus the maximum attachments per message. Absent values fall back to the previous built-in limits, so existing servers are unaffected until they opt in.
  • Updater progress bar — the self-updater now draws a real progress bar on the console (Downloading [████████░░] 62%) for each step, replacing the plain status lines, so a large download shows visible progress.
  • Timestamps in messages are culture-aware and now always include the date: today's messages show a compact date + short time, and older messages show the general short date/time.

Bug Fixes

  • Transparent themes no longer draw an opaque box behind the message input. The input TextView renders with the Editable visual role, which Terminal.Gui derives as an opaque color when a theme leaves it unset; the themes now pin Editable/ReadOnly to their base colors so the input matches its (transparent) background.
  • Attachments whose files have been pruned (retention cleanup deletes blobs older than Storage:RetentionDays but left the message rows) no longer render a dead download/preview. When channel history loads, the server checks which attachment blobs still exist: missing ones are dropped from the message, and an attachment-only message whose files are all gone is removed from the database.
  • Fixed intermittent crash on Ctrl+W — Terminal.Gui binds Ctrl+W to clipboard-cut, and Windows clipboard contention (another app holding the clipboard) threw an unhandled Win32Exception that took the app down. Ctrl+W now deletes the previous word (readline behavior, no clipboard), and all clipboard shortcuts (Ctrl+X/C/V/Y) are guarded so transient clipboard failures log a warning instead of crashing
  • Fixed emoji shortcode replacement permanently disabling itself if a cursor update threw mid-replacement
  • Fixed new messages showing no date — today's messages rendered time-only, and the "is it today?" check compared the server's UTC date against the local date, so the classification could also be wrong near midnight. Timestamps are now converted to local time first and always include the date.
  • Fixed the self-updater hanging at "extracting" — the update ran while the Terminal.Gui main loop still owned the console, so the old and new processes deadlocked over it. The update now runs after the TUI shuts down, on a clean console
  • IRC LIST no longer leaks private channels; protected channels are marked [+k]

API Changes

  • ChannelDto gains isProtected and isEncrypted; CreateChannelRequest gains optional password, encryptionSalt, and wrappedRoomKey; SignalR JoinChannel takes an optional second password argument and JoinChannelResult gains passwordRequired, encryptionSalt, and wrappedRoomKey (older clients must update to join over SignalR)
  • New endpoints: GET /api/channels/{channel}/crypto (public crypto metadata — salt only, never the wrapped key) and POST /api/channels/{channel}/rekey (creator-only passphrase change)
  • New endpoint GET /api/channels/{channel}/meta returns a ChannelMetaDto (room id, name, topic, encrypted/protected flags, message count, unique user count, estimated size, created date) backing the /meta command
  • New server Uploads configuration section (MaxFileSizeMB, MaxImageSizeMB, MaxAudioSizeMB, MaxAvatarSizeMB, MaxAttachmentsPerMessage); the message-upload endpoint's request-body ceiling is now derived from these values at runtime rather than from compile-time constants
  • The upload endpoint accepts type and content form fields for encrypted channels, where the client supplies the declared message type and room-encrypted content
  • ImageToAsciiService and FileValidationHelper moved from EchoHub.Server to EchoHub.Core so the client can render ASCII art and detect file types for encrypted uploads
  • Message shape change: MessageDto drops Type/AttachmentUrl/AttachmentFileName/AttachmentFileSize and gains Attachments (a list of AttachmentDto { Kind, Url, FileName, FileSize, AsciiPreview }, null/empty for plain text). New Attachment entity + table with a cascade FK to Message
  • New endpoint POST /api/channels/{channel}/messages (multipart: content + N files, plus kind/preview per file for encrypted channels) replaces the single-file upload endpoint; DELETE /api/moderation/messages/{id} now enforces the own-or-higher-role rule
  • New EF migrations AddChannelPasswordHash, AddChannelEncryptionEnvelope, and AddMessageAttachments (applied automatically on server start); a one-time startup data migration folds legacy single-attachment messages into the new model