Tavroo Руководитель — техническое приложение 2.1.0 ================================================== Дата: 16.10.2026. Документ ТЗ: v2.2. Продукт: 2.1.0. Установочная сборка с поддержкой Android 12 и новее. Полная приёмка ТЗ не завершена. Рабочий режим с настоящими данными не включён. Состав ------ Нативный Kotlin/Android-клиент, package ru.tavroo.director, minSdk 31 (Android 12), targetSdk 35, ARM64; x86_64 включён для стендовых испытаний. Сборка Gradle 8.11.1, AGP 8.10.1, Kotlin 2.1.20, JDK 17. Сборка подписана отдельным сохранённым ключом. Обновления должны использовать тот же ключ. Закрытые ключи не входят в APK, публикацию и исходники модуля. Интерфейс содержит обзор, задачи, голосовой/текстовый черновик, команду, отчёты BI, согласования казначейства, чаты, аудио- и видеозвонки Tavroo, имитатор Телфин и очередь действий. Серверные сведения берутся из учебной базы, а не из встроенных карточек. Публичный сервер: https://www.tavroo.ru, база tavroo_demo, вход demo/demo. Внешние уведомления имитируются. Данные общие и ежедневно восстанавливаются; реальные личные, медицинские и финансовые сведения вводить не следует. Локальная речь -------------- GigaAM v3 E2E CTC INT8, ONNX Runtime Android 1.22.0, 2 потока инференса. Silero VAD v5.1.2, ONNX, 1 поток. Обе модели выполняются на устройстве. Манифест mobile/director/app/src/main/assets/model-manifest.json содержит закреплённую ревизию, исходные адреса, размеры и SHA-256 каждого файла. При загрузке с Tavroo проверяются размер и SHA-256; неполная загрузка продолжается HTTP Range. Только проверенные файлы получают признак готовности. Аудио: PCM16 mono, 16000 Гц, источник VOICE_RECOGNITION. Микрофон работает после нажатия кнопки и выдачи Android-разрешения. Фоновое ключевое слово не включено. VAD: блок 512 отсчётов, контекст 64, порог 0.5, завершение после 1.2 секунды тишины вслед за речью. Предел одной записи — 120 секунд. Аудио хранится в оперативной памяти; серверу передаётся подтверждённый текст. Признаки: periodic Hann 320, FFT 320, hop 160, center=false, HTK 64 mel, log clamp 1e-9…1e9. Greedy CTC, blank=256, unknown=0, SentencePiece boundary. Длинная запись обрабатывается фрагментами по 20 секунд с перекрытием 0.4 с. Устранение перекрытия — точное сравнение нормализованных последних/первых слов. Качество стыков и длинных команд требует проверки на телефонах. Подготовка признаков сопоставлена с независимым NumPy-расчётом на контрольной записи. Десктопный ORT распознал эталон; результаты в output/director. Это не подтверждает скорость, расход памяти, батареи или WER на телефоне. В настройках APK предусмотрены эталонная запись и показ длительности обработки, модели телефона и версии Android. Телефонные замеры ещё не приняты. Разбор команды -------------- Локальные правила выделяют фамилию, отдел, группу, срочность, завтра/сегодня, день недели, цифровое время и перечисленные пункты. Неоднозначное имя требует ручного выбора. Предлагаемое время при названном дне без часа — 18:00; оно показано для редактирования. Прошедшая дата не переносится молча. Перед отправкой пользователь подтверждает название, получателей, режим отдельных/общей задачи, приоритет и точную дату с часовым поясом. Автоматического выбора исполнителя по нагрузке нет (VT-45). Серверная карта -------------- POST /web/session/authenticate — стандартная сессия учебного Tavroo. POST /director/api/v1 — JSON-RPC, auth=user, метод в params: * snapshot: staff, departments, tasks, approvals, bi, channels, capabilities; * messages: channel_id, проверка текущего членства; * receipt: key и generation, только собственная операция текущей компании; * execute: key, generation, action, неизменяемый payload. Действия: task.create, task.complete, approval.decide, chat.send. task.create создаёт project.task в настроенном project.project, требует project.group_project_manager, допускает 1…50 действующих сотрудников текущей компании. individual — задача на каждого, shared — одна общая. hr.employee.public и res.users дают доступный состав команды. Завершение проверяет права на project.task, компанию и полную write_date с микросекундами под блокировкой строки. Согласование использует tavroo.treasury.request._decision без sudo: проверяются сохранённая версия, текущее состояние, маршрут, роль, авторство. PIN/биометрия Android подтверждает действие на устройстве и не заменяет серверную проверку. Согласование не исполняет банковский платёж. BI использует tavroo.bi.workspace.dashboard_data и его исходные правила. CRM показывает количество и ожидаемую сумму доступных сделок по этапам; ожидаемая сумма не обозначается выручкой. Чаты — discuss.channel/mail.message. Защита от повторов ----------------- Идентификатор UUID сохраняется в зашифрованной очереди до первого запроса. Перед исполнением клиент запрашивает receipt. Сервер использует ключ (company_id,user_id,key), SHA-256 канонического action/payload, транзакционную advisory lock и уникальный индекс. Журнал и бизнес-изменения фиксируются одной транзакцией. Конкурирующая транзакция с устаревшим снимком повторяется механизмом Tavroo/PostgreSQL. Изменение содержимого запрещено. Клиентские состояния: pending, done, unknown, blocked, rejected. Нет ответа — unknown; пользователь запускает сверку с тем же ключом. Отсутствие квитанции допускает повтор только с тем же ключом идемпотентности. Сетевая ошибка не создаёт новый UUID. Автоматической отправки финансовых решений при восстановлении связи нет; повтор требует подтверждения устройства. При сбросе публичного набора меняется generation; старые команды отклоняются. При неизвестном результате нельзя создавать самостоятельную замену действия. Локальное хранение и права ------------------------- AES/GCM, ключ Android Keystore, AtomicFile в noBackupFilesDir. Сессия, снимок, черновики и журнал хранятся шифрованно; пароль не сохраняется. Cloud backup/device transfer запрещены. Модели — несекретные файлы во внутреннем каталоге. Кэш доступен до 24 часов; при истечении закрывается, при полученном отказе доступа очищается немедленно. Выход очищает локальные данные. Смена пользователя не переносит кэш/очередь другой учётной записи. Онлайн-действия всегда повторно проверяются сервером. Мгновенный отзыв прав на полностью отключённом устройстве не заявляется. Проверки и открытая приёмка -------------------------- Пройдены: сборка APK, проверка подписи, lint без ошибок; JVM-проверки признаков, имён, отдела, группы, срока и часового пояса; серверные проверки отдельной и общей задачи, дублей, конфликта содержимого, устаревшей редакции, поколения, чужого пользователя/компании, самосогласования, двух одновременных запросов, сохранения квитанций после нового процесса. Отчёты находятся в output/director и artifacts/director/qa на сервере. Установочные испытания фиксируются отдельно. Не закрыты полной приёмкой: AC-01…AC-35 и AC-35a/b как единый набор; микрофон/скорость/WER/энергопотребление на физических Android-устройствах, полный набор голосовых намерений и распределение по нагрузке, локальная автоблокировка с биометрией, полный жизненный цикл офлайн-изменений, подтверждения участников общей задачи/оповещений, вложения и их кэш, push/email/SMS-доставка, прочтение чатов, SIP, видеосвязь/конференции, расширенный план-факт и персональные рабочие кабинеты. Рабочий режим запрещён. Полные результаты и границы приёмки фиксируются в техническом приложении. Видимый текст страницы загрузки и новости по запросу владельца не содержит обозначений alpha/первой тестовой версии и названия модели. Совместимость Android 12 ------------------------ В обновлении 2.0.0-alpha.2 минимальный уровень Android снижен с API 33 (Android 13) до API 31 (Android 12). targetSdk остаётся 35. versionCode увеличен с 1 до 2; приложение подписано прежним ключом для обновления поверх установленной версии. Архитектура телефона — ARM64. Владелец подтвердил установку и работу предыдущей сборки на Android 12. Числовые замеры распознавания и полный протокол устройства не предоставлены. Обновление 2.1.0: связь и обновление APK --------------------------------------- versionCode 3, minSdk 31, targetSdk 35. Ключ подписи сохранён. Сборка устанавливается поверх предыдущей. Модель речи, очередь и Vault не мигрируют и не удаляются. Эту сборку требуется установить вручную один раз. Следующие версии: Настройки → Проверить обновление приложения. Манифест: GET https://tavroo.ru/downloads/director/latest.json. Поля: versionCode, versionName, minSdk, url, size, sha256, notes. Принимается только HTTPS tavroo.ru/downloads/director/tavroo-director-*.apk, без редиректов, параметров или другого хоста. Загрузка ограничена размером; проверяются SHA-256, package ru.tavroo.director, увеличение versionCode, совместимость SDK и совпадение сертификата с установленным приложением. FileProvider передаёт проверенный APK системному установщику. Установка требует разрешения Android и подтверждения пользователя; скрытой установки нет. Общение использует Android WebView с сессией текущего пользователя и существующие Tavroo Discuss/RTC, discuss.channel и mail.message. Новые чаты, группы, сообщения, вложения, аудио- и видеозвонки — общий веб-интерфейс внутри приложения. Отдельная копия переписки для него не создаётся. Входящие доступны, пока экран общения открыт; фоновый приём при закрытии приложения и полноценный Android foreground call service не реализованы. Выход из экрана завершает его звонок. Для соединения требуется сеть. Камера/микрофон выдаются только HTTPS-origin www.tavroo.ru после согласия пользователя и системного разрешения. Ошибки TLS не обходятся; доступ к file:// и content:// из WebView, смешанный контент, сторонние cookies и JavaScript-мост к Android отключены. Локальный WebView-кэш не сохраняется, cookies/WebStorage очищаются при выходе. Вложения выбираются системным проводником. Скачивание вложений ограничено 30 МБ и текущим HTTPS-origin. Телфин — по прямому уточнению владельца только имитатор с существующими синтетическими записями. В Android добавлены история и переходы в формы исходящего/внутреннего звонка, имитации входящего и сотрудников/номеров. Действия разрешаются серверными правами; параметры подключения и контекст берутся из действий tavroo_telphin, а не копируются в отдельный Android-стенд. Сотрудники учебного набора имеют номера 201, 202, 203. Настоящий SIP, реальные внешние и внутренние телефонные разговоры этим выпуском не включены. Обновление не меняет существующие сетевые подключения на сервере. Серверные capability sip/video старого director API описывают его собственные нативные сценарии. Общение 2.1.0 использует отдельный существующий Discuss/RTC. Приведённый выше перечень непрошедшей полной приёмки остаётся перечнем приёмки всего ТЗ: он не означает отсутствие интерфейса общения в 2.1.0. Физическая проверка камеры, микрофона, звука и двухстороннего WebRTC на Android 12 для этого выпуска ещё не выполнена. Сборка, JVM-проверки, lint, серверные формы и имитатор проверяются отдельно от качества медиасвязи. Обновление 2.2.1: фоновые звонки -------------------------------- versionCode 5, minSdk 31, targetSdk 35. Прежний сертификат подписи. Описанные выше ограничения фоновых звонков относятся к версии 2.1.0. В 2.2.1 добавлена явно включаемая foreground service с типом specialUse: авторизованный calls.poll каждые 5 секунд, постоянное уведомление, частичный WakeLock с ограниченным сроком и продлением. Внешний push-провайдер не нужен. Ожидание звонка само по себе не открывает микрофон или камеру. Их типы foreground service включаются из видимого экрана после выдачи разрешений. На Android 13+ требуется POST_NOTIFICATIONS. Для выключенного экрана пользователь может разрешить исключение из оптимизации батареи; на Android 14+ отдельно проверяется разрешение full-screen intent. Отказ сохраняет обычное уведомление. Без сети, после Force stop или при запрете фоновой работы производителем доставка не гарантируется. Режим расходует батарею. Boot/package replacement возобновляют включённую службу; Force stop требует ручного запуска. Это не утверждение о гарантированной push-доставке. Приватные RTC-приглашения ограничены получателем, токеном конкретного приглашения и TTL 45 с. Время сервера переводится в elapsedRealtime. Перед ответом выполняется сверка, затем повторная проверка под блокировкой строки перед штатным join_call. Смена приглашения и поколения набора отклоняет старое действие. Телфин разрешён только в режиме simulator; назначение и конкретное соединение проверяются перед каждым действием. Действия используют существующий журнал идемпотентности. Повтор не создаёт нового звонка. Активное соединение сверяется для снятия уведомления. Один WebView сохраняется на время RTC-разговора при закрытии Activity, а foreground service поддерживает процесс и уведомление завершения. Origin-scoped WebMessageListener принимает только сообщения main frame https://www.tavroo.ru. Общий addJavascriptInterface не используется. Смена пользователя и выход останавливают службу и очищают WebView. Телфин не передаёт реальный звук; сохраняются события общего имитатора. Приёмка 2.2.1: сборка, подпись, JVM и серверные проверки, bridge-проверки выполняются автоматически. Физическое устройство недоступно в среде: двухсторонний звук/видео, экран блокировки, Doze, перезапуск ОС, расход батареи и ограничения конкретного производителя проверяются на телефоне. Минимальный сценарий: два разных сотрудника; веб-клиент звонит телефону с закрытым экраном общения; ответ/отклонение, Home, блокировка, завершение с обоих концов, потеря сети, повтор уведомления, смена пользователя. Для Телфин — синтетический входящий назначенному сотруднику, сверка ответа и завершения с веб-карточкой; настоящие внешние вызовы не выполняются.