Import IKAR messenger client and server
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
# ИКАР
|
||||
|
||||
<img src="assets/ikar_icon.png" width="96" alt="Иконка ИКАР">
|
||||
|
||||
Самостоятельный Android-мессенджер с сервером `ikar_server`. Имя приложения — **ИКАР**, пакет Android — `ru.ikar.app`, версия — `1.0.3+4`, вариант сборки — `ikar`.
|
||||
|
||||
Клиент находится в `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 обеспечивает шифрование транспорта. Проверки не доказывают работу всех режимов сквозного шифрования и звонков с большим количеством участников.
|
||||
|
||||
## Размещение на Pi
|
||||
|
||||
Внешний диск: `/mnt/data` (`/dev/sdb1`, ext4). Корень новой установки: `/mnt/data/ikar_server`.
|
||||
|
||||
- `current` — ссылка на действующий выпуск в `releases/20261007-video`;
|
||||
- `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 с небольшим разбросом времени). Старт требует смонтированного внешнего диска и маркера в каталоге данных.
|
||||
|
||||
```sh
|
||||
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`.
|
||||
|
||||
```powershell
|
||||
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.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`. Выпуск опубликован в [Аргусе](https://argus.kusoft.xyz/#app=ikar): [скачать ИКАР 1.0.3](https://argus.kusoft.xyz/api/apps/ikar/releases/22ec0d08-3407-464e-bf04-871a4a42315a/download). Публичные манифест, каталог и скачанный 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`.
|
||||
|
||||
Выпуск опубликован в [Аргусе](https://argus.kusoft.xyz/#app=ikar). [Скачать ИКАР 1.0.2](https://argus.kusoft.xyz/api/apps/ikar/releases/9419489c-6cd6-467d-9f05-3bf3298d92f0/download). Публичные каталог, манифест и скачанный 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`.
|
||||
|
||||
Выпуск опубликован в [Аргусе](https://argus.kusoft.xyz/#app=ikar). [Скачать ИКАР 1.0.1](https://argus.kusoft.xyz/api/apps/ikar/releases/ae0be8b6-9033-4b76-afce-42c9cac566c8/download). База каталога и резервная копия проверены; другие карточки и работающие сервисы сохранены. Передача на физический телефон и проверка исправлений на нём не выполнены: 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) опубликован в [Аргусе](https://argus.kusoft.xyz/#app=ikar).
|
||||
[Скачать APK](https://argus.kusoft.xyz/api/apps/ikar/releases/5def8cec-6349-437f-ad7b-68ad99bf4a84/download).
|
||||
Публичный файл совпадает с `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](https://github.com/googlefonts/noto-emoji/tree/v2.047), Apache 2.0 (лицензия рядом с изображениями). Распознавание: [Vosk, русская модель small-ru-0.22](https://alphacephei.com/vosk/models), Apache 2.0.
|
||||
Reference in New Issue
Block a user