ИКАР

Иконка ИКАР

Самостоятельный Android-мессенджер с сервером ikar_server. Имя приложения — ИКАР, пакет Android — ru.ikar.app, версия исходников — 1.0.4+5 (не опубликована), вариант сборки — ikar. Опубликованный выпуск — 1.0.3+4.

Клиент находится в C:\Repos\IKAR, сервер — в ikar_server/. Иконка перенесена из прежнего Икара. Исходный каталог C:\Repos\Qlyra не изменён; использованный клиентский код и библиотеки сохраняют свои авторские сведения и лицензии.

Возможности

Личные сообщения, групповые чаты и каналы, редактирование и удаление сообщений, ответы и форматирование, реакции, поиск, контакты, блокировки, папки, опросы, истории, загрузка и скачивание файлов, фото, видео и голосовых сообщений, расшифровка русской речи на Pi, стикеры, отложенная отправка, голосовые и видеозвонки, фоновые уведомления, боты и мини-приложения. Настройки оформления, масштаба отметок доставки, плагины и остальные локальные возможности исходного клиента сохранены.

Сервер предоставляет собственный HTTPS API и события SignalR; клиент не авторизуется на серверах MAX. Файлы выдаются по подписанным ссылкам, сообщения сохраняются в SQLite. Сервер проверяет участие в чате и права публикации в каналах. Повтор запроса с тем же идентификатором сообщения возвращает сохранённое сообщение. Задания отложенной отправки переживают перезапуск сервера.

Регистрация привязывает аккаунт к ключу Android Keystore. Номер служит идентификатором и не подтверждается SMS. Вход на другом устройстве требует доступного механизма привязки/восстановления собственного сервера; приложение не использует SMS-службу MAX. До передачи приложения другим людям нужно определить способ подтверждения номера и восстановления потерянного ключа. Старые аккаунты MAX автоматически не переносятся.

«Карточка ИКАР» показывает собственный профиль и QR-ссылку. Государственный Цифровой ID, Сферум и чужие каталоги/мини-приложения не являются сервисами ИКАР. Собственные мини-приложения настраиваются владельцем бота через PUT /api/bots/{botId}/web-app с телом {"url":"https://..."}; данные запуска подписаны HMAC, номер передаётся отдельным запросом после подтверждения в клиенте.

Сквозное шифрование исходного клиента сохранено в коде как отдельная функция. Обычные сообщения сервер принимает и хранит в читаемом виде; HTTPS обеспечивает шифрование транспорта. Проверки не доказывают работу всех режимов сквозного шифрования и звонков с большим количеством участников.

Доработки из Komet

Адаптированы изменения ветки feature/FullStack (58576bc1) и жесты из PR №166 (10a194ed). Ползунок качества видео получил полноценную область касания; качество и обрезка учитывают края системных жестов Android. Копирование, выделение и редактирование зашифрованных сообщений используют доступный расшифрованный текст. Недоступный текст не подменяется шифротекстом; локальное хранение и отправка сохраняют существующую схему шифрования.

В настройках темы добавлена «Собственная тема»: выбор цветов, поворота и анимации градиента. Градиент сохраняется для аккаунта между запусками, отдельные фоны чатов продолжают иметь приоритет. Жесты назад, ответа, закрытия фото и скрытия клавиатуры согласованы между собой; короткий отменённый свайп возвращает фото, масштабирование не закрывает просмотр.

«Невидимка» передаёт interactive=false в авторизованный ping и подключение SignalR, включая переподключения. Переключение настройки и уход приложения в фон обновляют активность сервера. Сервер учитывает отдельные соединения и сессии, сохраняет соединение для доставки сообщений и звонков, но не показывает невидимую сессию онлайн. Публичное время появления хранится отдельно от служебной активности сессии и не обновляется невидимыми запросами. Обновление схемы SQLite переносит прежнее время появления один раз. Видимая сессия на другом устройстве по-прежнему показывает аккаунт онлайн.

Проверки: полный клиентский прогон — 1189 прошли, 3 пропущены; сервер — 150 прошли, без пропусков. Анализ lib и test не выявил ошибок и предупреждений, остались 42 информационных замечания стиля. Проверены выбор качества видео, сохранение темы, доступ к расшифрованному тексту, жесты, переключение невидимости, переподключение и сохранение публичной активности при обновлении схемы. Локальные отчёты: artifacts/komet-full-flutter-tests.log, artifacts/komet-server-tests.log, artifacts/komet-implementation-analyze.log.

Рабочий API обновлён до releases/20261007-komet. Проверены совпадение SHA-256 серверной сборки, целостность рабочей базы и резервной копии, новая колонка публичной активности, /health, отсутствие перезапусков API и сохранность соседних контейнеров. Резервная копия перед обновлением: /mnt/data/ikar_server/backups/ikar-20261007T191617Z.tar.gz; предыдущий выпуск сохранён для отката. Через публичный HTTPS прошли 15 общих проверок API, 8 проверок невидимости и 5 проверок видео. Они охватывают регистрацию, доставку и историю, права доступа, файлы, речь на Pi, группы, каналы, реакции, опросы, отложенную отправку и сигнализацию звонков. Невидимая сессия получает сообщения и приглашения звонка, не меняя публичное время активности. Отчёты: artifacts/deployment-komet.json, artifacts/ghost-live-verification.json, artifacts/live-smoke.json, artifacts/video-live-verification.json.

Главная иконка содержит только рисунок Икара без надписей. Размер рисунка — около 90% диаметра круглой области; адаптивный слой учитывает расширение Android с 72 до 108 dp. Исходный рисунок — assets/ikar_mark.png, основные ресурсы — assets/ikar_icon.png и assets/ikar.png. Пересоздание: dart run tool/make_ikar_icons.dart, затем dart run flutter_launcher_icons. Ресурсы основной иконки обновлены для Android, iOS, Windows и macOS; альтернативная иконка сохранена.

Новая иконка и клиентские изменения требуют нового APK; текущий опубликованный выпуск их не содержит. Выпуск APK и проверка этих клиентских изменений на телефоне в этой задаче не выполнялись.

Размещение на Pi

Внешний диск: /mnt/data (/dev/sdb1, ext4). Корень новой установки: /mnt/data/ikar_server.

  • current — ссылка на действующий выпуск в releases/20261007-komet;
  • shared/data — SQLite, вложения, данные устройств и публикация APK;
  • shared/server.env, shared/turn.env — закрытые настройки, доступ 0600;
  • backups — ежедневные согласованные копии SQLite и вложений, хранение 14 дней;
  • rollback — резервная копия прежнего Икара, сохранённая перед удалением.

Собственный Compose-проект ikar_server содержит контейнеры ikar_server, ikar_server_turn и ikar_server_asr. API слушает 127.0.0.1:5099, TURN — 3478 с портами ретрансляции 49160–49200, распознавание речи доступно только во внутренней сети контейнеров. Использован уже существовавший маршрут Caddy; конфигурации соседних программ не менялись.

Автозапуск: ikar_server.service; резервные копии: ikar_server-backup.timer (03:30 с небольшим разбросом времени). Старт требует смонтированного внешнего диска и маркера в каталоге данных.

systemctl status ikar_server.service ikar_server-backup.timer
curl http://127.0.0.1:5099/health
sudo systemctl start ikar_server-backup.service

Адрес сервера — https://ikar.kusoft.xyz. На проверке 7 октября 2026 года DNS-запись разрешалась в 195.216.241.165. APK также умеет подключаться к этому IP с сохранением проверки сертификата имени ikar.kusoft.xyz, если DNS временно недоступен.

Для звонков через разные NAT нужен проброс на роутере: 3478 TCP/UDP и 49160–49200 UDP на 192.168.0.185. При проверке TURN работал через локальный адрес Pi; запросы на внешний адрес не получили ответа TURN. Публичная ретрансляция пока не подтверждена. Звонок с аудио/видео в эмуляторе прошёл через прямое WebRTC-соединение; это не доказывает работу через любую мобильную сеть.

Сборка

Flutter 3.44.3, Java 17, Android SDK, Rust; для сервера .NET 10. На этой машине используются C:\Tools\jdk-17, C:\Tools\AndroidSdk, C:\Tools\gradle-home и C:\Tools\pub-cache.

flutter pub get
flutter build apk --release --flavor ikar --no-pub
flutter test --no-pub
flutter analyze --no-pub --no-fatal-infos lib test
dotnet test ikar_server/src/Ikar.Server.Tests/Ikar.Server.Tests.csproj

Подпись выпуска хранится в закрытом локальном каталоге .secrets; android/key.properties не публикуется. Для тестов криптографии нужны нативные библиотеки текущей ОС: можно указать QLYRA_CRYPTO_LIBRARY и добавить каталог остальных DLL в PATH. Имена библиотек — внутренние имена зависимостей и не определяют название приложения.

tool/deploy_ikar.ps1 упаковывает опубликованный linux-arm64 сервер и обновляет только новый Compose-проект на Pi. Модель Vosk в ikar_server/asr/model.zip проверяется по SHA-256 при сборке контейнера. Скрипты в tool/ для проверок используют временные тестовые аккаунты и удаляют их по завершении.

Меню расшифровки голосовых сообщений 1.0.4 (не опубликовано)

Расшифровка сохранена и перенесена из маленькой кнопки «Т» в меню голосового сообщения. Нажатие на облако открывает меню с пунктом «Расшифровка голосового сообщения»: нажимается вся строка, её высота не меньше 48 логических пикселей и увеличивается при переносе текста или увеличенном шрифте. У обычных сообщений, файлов, видео, удалённых и ещё не отправленных записей этого пункта нет. Пересланные записи используют идентификаторы исходного голосового сообщения.

Под записью отображается состояние распознавания, затем готовый текст; через меню его можно скрыть и показать снова без повторного запроса. Одновременные нажатия не создают повторные запросы. Ошибку можно повторить; результат, уже полученный через push, не затирается поздним ответом о постановке в очередь или сетевой ошибкой.

Целевые тесты: artifacts/voice-menu-tests.log. Анализ изменённых UI-файлов и новых тестов: artifacts/voice-menu-analyze-final.log. Живая проверка тестовой записи подтвердила загрузку, запрос получателя, завершение распознавания через push, сохранение текста для обоих участников и запрет доступа постороннему: artifacts/voice-transcription-live-verification.json. Тестовые аккаунты удалены. Новая версия не публиковалась и не устанавливалась на телефон по указанию пользователя; нового APK нет.

Исправления видео 1.0.3

Серверный ответ на VIDEO_PLAY раньше содержал external и hls: стандартная JSON-сериализация меняла регистр ключей EXTERNAL и HLS, которые ожидает клиент. Теперь ключ EXTERNAL сохраняет точное написание, а исходный MP4 больше не выдаётся за HLS-плейлист. Выдача файла поддерживает HTTP byte ranges для перемотки.

Сервер создаёт JPEG-превью и определяет реальные размеры и длительность видео с помощью FFmpeg/FFprobe. Превью сохраняется рядом с исходным файлом; повторные запросы используют готовый результат. Это работает и для прежних загрузок. Картинка выдаётся участникам чата по отдельной подписанной ссылке: токен видео нельзя использовать для превью, удалённые и истёкшие сообщения недоступны. В клиенте обновление вложения или подписанной ссылки перерисовывает существующий пузырь, даже если текст и статус сообщения не изменились.

142 серверных теста прошли. Живая проверка охватила загрузку MP4 чанком, доставку получателю, историю, скачивание с проверкой SHA-256 обоими участниками, ответы 206 для перемотки, JPEG-превью, метаданные и защиту доступа. На подключённом физическом телефоне с установленной версией 1.0.2 исходное видео 33 092 306 байт открылось в плеере; превью и длительность 0:05 появились в чате после обновления серверных данных. Сервер обновлён с согласованной резервной копией базы и вложений; рабочая база и база из копии прошли проверку целостности. Отчёты: artifacts/video-server-tests.log, artifacts/video-live-verification.json, artifacts/deployment-video.json, artifacts/video-server-runtime-verification.json.

Клиент: 17 целевых тестов прошли; полный прогон — 1147 прошли, 9 пропущены. Анализ изменённых файлов не выявил ошибок и предупреждений (19 информационных замечаний стиля). Отчёты: artifacts/video-client-tests.log, artifacts/flutter-tests-1.0.3.log, artifacts/video-client-analyze.log.

APK artifacts/ikar-1.0.3+4.apk подписан прежним ключом ИКАР; свежие Flutter-библиотеки всех трёх ABI проверены в итоговом файле. SHA-256: 5dd485f9a797f28c0eb522f8098c574c0e523796cd83cf50414cffea86747b71. Выпуск опубликован в Аргусе: скачать ИКАР 1.0.3. Публичные манифест, каталог и скачанный APK совпадают по версии, размеру и SHA-256; TLS проверен, база каталога и резервная копия целостны. Другие карточки и сервисы публикация не изменяла. Установка нового APK на физический телефон не выполнена: USB перешёл в offline, затем пользователь выбрал завершить публикацию без установки. Отчёты: artifacts/apk-jni-verification-1.0.3.json, artifacts/argus-publication-1.0.3.json, artifacts/argus-public-verification-1.0.3.json.

Исправления 1.0.2

Раздел FKM убран из настроек уведомлений. FKM принудительно выключена в клиенте и Android: включённая настройка прежнего выпуска сбрасывается, служба останавливается, постоянное уведомление удаляется. Повторный запуск и загрузка Android не включают её обратно. Обычные настройки уведомлений сохранены.

При отсутствии связи с сервером шапка показывает «Соединение...»; после восстановления связи возвращается обычный заголовок. Сбои подключения, тайм-ауты и ответы шлюза 502/503/504 запускают переподключение без повторяющихся служебных сообщений снизу. Ошибки конкретных операций при работающем соединении по-прежнему отображаются.

Проверки: полный клиентский прогон — 1144 прошли, 9 пропущены; 15 целевых тестов проверяют отключение FKM, отсутствие её меню, переходы состояния сети и сохранение ошибок операций. Анализ изменённых файлов не выявил ошибок и предупреждений (19 информационных замечаний стиля). Отчёты: artifacts/flutter-tests-1.0.2.log, artifacts/offline-fkm-tests-1.0.2.log, artifacts/offline-fkm-analyze-1.0.2.log.

APK artifacts/ikar-1.0.2+3.apk подписан прежним ключом ИКАР; свежие Flutter-библиотеки всех трёх ABI сверены с содержимым APK. SHA-256: fd3f4347ea7fe1e078dce3f5d442430eb79ede5bf529a49e8890956e7668b3a6. В эмуляторе Android API 35 обновление сохранило данные и сбросило старую настройку enabled=true в false; повторный запуск сохранил отключённое состояние. Служба FKM и её постоянное уведомление отсутствуют, ошибок Android Runtime и Flutter не зарегистрировано. На физическом телефоне этот выпуск не проверялся. Отчёты: artifacts/apk-jni-verification-1.0.2.json, artifacts/emulator-fkm-verification-1.0.2.json.

Выпуск опубликован в Аргусе. Скачать ИКАР 1.0.2. Публичные каталог, манифест и скачанный APK проверены по версии, размеру и SHA-256 с проверкой TLS. Перед публикацией создана согласованная резервная копия базы Аргуса; база и копия целостны, другие карточки и работающие сервисы сохранены. Сервер остался на выпуске 1.0.1: изменение относится к Android-клиенту. Отчёты: artifacts/argus-publication-1.0.2.json, artifacts/argus-public-verification-1.0.2.json.

Исправления 1.0.1

Первое сообщение нового диалога раньше отклонялось локальной SQLite: запись сообщения создавалась до родительской записи чата. Теперь диалог и сообщение сохраняются атомарно; подготовка первого диалога также охватывает фото, файлы, голосовые сообщения и стикеры. Отмена подтверждения отправки не создаёт пустой чат.

Сервер поддерживает приватное «Избранное» с chatId=0, пустую историю нового диалога и подписку по XOR ID. Отключение подписки больше не удаляет участие в чате. Полная синхронизация контактов очищает устаревшие записи, защищена от смены аккаунта и параллельного добавления контакта. Сохранение устаревшего контакта восстанавливает связь через ADD; ошибки поиска различают отсутствие пользователя и сбой сервера и отображаются по-русски.

Проверки: 137 серверных тестов; полный клиентский прогон — 1127 прошли, 9 пропущены; после последних защит синхронизации — 55 целевых тестов. Все 17 живых проверок API прошли, включая отправку в «Избранное», первое сообщение, доставку второму клиенту, историю, контакты и сохранение членства после отключения подписки. Отчёты: artifacts/messaging-fix-after.json, artifacts/focused-tests-1.0.1-final.log, artifacts/deployment-1.0.1.json.

Сервер обновлён с согласованной резервной копией; соседние контейнеры сохранены. APK artifacts/ikar-1.0.1+2.apk имеет прежнюю подпись ИКАР, versionCode 2 и свежие Flutter-библиотеки для всех трёх ABI. SHA-256: 6c23cc0063e63eda03172f10209a09a4dfc11655b435ce7aa982d495e3b329ad.

Выпуск опубликован в Аргусе. Скачать ИКАР 1.0.1. База каталога и резервная копия проверены; другие карточки и работающие сервисы сохранены. Передача на физический телефон и проверка исправлений на нём не выполнены: USB-соединение было отключено. Отчёты публикации: artifacts/argus-publication-1.0.1.json и artifacts/argus-public-verification-1.0.1.json.

Проверка первого выпуска 1.0.0

  • APK: artifacts/ikar-1.0.0+1.apk, контрольная сумма рядом;
  • клиент: 1107 тестов прошли, 9 пропущены;
  • сервер: 133 теста прошли, результаты — artifacts/server-tests.log;
  • живой HTTPS API: artifacts/live-smoke.json;
  • обмен сообщениями из Android-интерфейса: artifacts/native-message.json;
  • звонок с настоящим WebRTC и искусственным аудио/видео: artifacts/native-call.json;
  • фоновое уведомление Android: artifacts/native-background-notification.json;
  • боты и подписанные данные мини-приложений: artifacts/live-bot-smoke.json;
  • локальная ретрансляция TURN в обе стороны: artifacts/local-turn-verification.json;
  • скачивание APK по HTTPS с проверкой SHA-256: artifacts/release-verification.json;
  • итоговое состояние Pi и сохранность соседних сервисов: artifacts/pi-verification.json.

ИКАР 1.0.0 (Android versionCode 1) опубликован в Аргусе. Скачать APK. Публичный файл совпадает с artifacts/ikar-1.0.0+1.apk по размеру, SHA-256 и подписи ИКАР. Перед публикацией сохранена согласованная копия базы Аргуса; база и копия прошли проверку целостности. Публикация не изменяла другие карточки и не перезапускала сервисы на Pi. Отчёты: artifacts/argus-publication.json, artifacts/argus-public-verification.json и artifacts/argus-apk-signature.txt. Скрипты первого выпуска: tool/publish_argus_release.py и tool/verify_argus_release.dart.

Android проверен в эмуляторе API 35. Проверки на физическом телефоне и в разных мобильных сетях не проводились. Отдельные функции исходного клиента проверены модульными тестами; список живых сценариев приведён в отчётах, поэтому он не означает проверку каждого экрана и интеграции.

Стикеры: Noto Emoji v2.047, Apache 2.0 (лицензия рядом с изображениями). Распознавание: Vosk, русская модель small-ru-0.22, Apache 2.0.

S
Description
No description provided
Readme
60 MiB
Languages
Dart 76.8%
C# 13.9%
Kotlin 2.3%
C 2.2%
Python 1.5%
Other 3.1%