Архитектура чата (группового) База данных: SQLite3 (WAL mode), chats.db ================================================================================ Схема БД (10 таблиц) ================================================================================ -- 1. local_identity — текущий локальный узел (одна строка, приватный ключ здесь) -- приватный ключ получаем от utun через MSG_RSP_PRIVKEY (только localhost) CREATE TABLE local_identity ( id INTEGER PRIMARY KEY CHECK (id = 1), node_id INTEGER NOT NULL UNIQUE, name TEXT NOT NULL, x25519_pubkey BLOB NOT NULL, -- 32 bytes x25519_privkey BLOB, -- 32 bytes (только на этом устройстве) ed25519_pubkey BLOB, -- 32 bytes (derive из x25519 privkey) created_at INTEGER DEFAULT (unixepoch()), updated_at INTEGER DEFAULT (unixepoch()) ); -- 2. my_nodes — другие наши ноды (другие устройства, нет приватного ключа) CREATE TABLE my_nodes ( node_id INTEGER PRIMARY KEY, name TEXT NOT NULL, x25519_pubkey BLOB NOT NULL, -- 32 bytes ed25519_pubkey BLOB, -- 32 bytes created_at INTEGER DEFAULT (unixepoch()), updated_at INTEGER DEFAULT (unixepoch()) ); -- 3. nodes — известные удалённые узлы (получаем через utun) CREATE TABLE nodes ( node_id INTEGER PRIMARY KEY, name TEXT, x25519_pubkey BLOB NOT NULL, -- 32 bytes ed25519_pubkey BLOB, -- 32 bytes (для проверки подписи пира) is_online INTEGER DEFAULT 0, last_seen_at INTEGER DEFAULT (unixepoch()), created_at INTEGER DEFAULT (unixepoch()), updated_at INTEGER DEFAULT (unixepoch()) ); -- 3a. accounts — UI-информация об узлах для отображения сообщений CREATE TABLE accounts ( node_id INTEGER PRIMARY KEY REFERENCES nodes(node_id), display_name TEXT NOT NULL, -- "Alice" avatar_color TEXT DEFAULT '#4A90E2', -- hex RGB avatar_letter TEXT NOT NULL, -- "A" is_contact INTEGER DEFAULT 1, -- показывать в боковой панели created_at INTEGER DEFAULT (unixepoch()) ); -- 4. channels — каналы (DM и групповые) CREATE TABLE channels ( id INTEGER PRIMARY KEY AUTOINCREMENT, channel_id TEXT NOT NULL UNIQUE, -- "dm:nodeA_nodeB" (A