- Sound files loaded from filesystem (sound_dir in INI config, absolute or relative)
- Per-event enable/disable + volume stored in DB (ui_state table)
- SoundManager: setEvent(), effective volume = master * per-event
- SoundSettingsPage UI: 4 event rows (checkbox + slider)
- chat_core_save_ui_state() for async DB writes via uasync thread
- DbManager::getUiStateInt() for reading settings from GUI thread
- Default sounds copied to sounds/ dir next to DB, config entries written
- chat_core_connect_auto: direct ETCP connect from SQLite (no BGP)
- auto_connect: parallel connect to peers with 3s timeout, retry 10s
- RTT saved to node_addresses on disconnect
- vertical status bar + circle badge with online count per channel
- ChannelListView prevents deselection
- Add CreateGroupDialog with group name input
- Generate X25519+Ed25519 keypairs, random uint64 channel_id,
Ed25519 signature, write to DB via uasync thread
- chat_core_create_channel(): create msg table, topo_node_sqlite_channel_put()
- GUI_EVT_CHANNEL_UPDATED notification to reload channel list
- Per-category debug config: debug_level= + debug_categories= in [gui]
- Unified logging via debug_config: all threads write to same file/console
- debug_enable_console(1) to mirror file output to stderr
- DEBUG_LEVEL_DISABLED=-1: truly disable category, NONE=0 fallback to global
- Fix uasync_post under epoll: process_posted_tasks was never called
- Fix MainWindow constructor parameter ordering (dbPath vs debugFile)
- debug_ui.h: append mode ('a' instead of 'w')
- Add NodeConfig: simplified INI config manager for embedded uTun node
- X25519 key generation via OpenSSL EVP
- Random node_id generation
- addServer/removeServer, addClient/removeClient API
- Auto-creates config with default server on first run
- Integrate UtunNode into MainWindow:
- Creates NodeConfig in ~/.config/chatgui/node.conf
- Starts embedded uTun node (no TUN, no msg_transport)
- In separate thread with uasync_poll event loop
- Replace MsgClient (TCP IPC) with UtunNode (direct calls):
- ChatPropagator now uses UtunNode for send/recv
- send(uint64_t, QByteArray) replaces sendTo
- messageReceived signal replaces received signal
- MainWindow cleanup: remove MsgClient, add UtunNode+NodeConfig