PRO1VPN: обновления с собственного HTTPS-сервера

Клиент проверяет update.json и загружает подходящий APK примерно каждые 12 часов
в сети без тарификации (обычно Wi-Fi). Android может откладывать фоновые задачи.
Проверить и скачать вручную можно через «Ещё» → «Обновления приложения».
Требуются уведомления для фонового сообщения о готовности. При их отключении
обновление доступно на экране обновлений. Установка подтверждается в Android.
Во время замены приложения VPN может отключиться.

На сервере хранятся только статические файлы:
/updates/android/update.json
/updates/android/1.0.3/PRO1VPN_1.0.3_arm64-v8a.apk
/updates/android/1.0.3/PRO1VPN_1.0.3_armeabi-v7a.apk
/updates/android/1.0.3/PRO1VPN_1.0.3_x86_64.apk
/updates/android/1.0.3/PRO1VPN_1.0.3_x86.apk
/updates/android/1.0.3/PRO1VPN_1.0.3_universal.apk

ПОДГОТОВКА РЕЛИЗА
1. Увеличить versionCode и versionName в V2rayNG/app/build.gradle.kts.
2. Собрать APK: bash scripts/build-release.sh. Использовать тот же ключ подписи.
3. Подготовить серверные файлы:
   ANDROID_SDK_ROOT=/path/to/sdk python3 scripts/prepare-update-server.py \
     --base-url https://cabinet.pro1technology.ru/updates/android
4. Опубликовать файлы и соответствующие исходники:
   python3 scripts/publish-update-server.py --host deploy@YOUR_SERVER --identity /path/to/ssh_key
   Нужны права записи в /srv/cabinet/updates/android и /srv/.pro1vpn-update-staging.
   Для описания изменений добавьте --notes "Описание новой версии".
   Скрипт проверяет контрольные суммы после загрузки, затем атомарно переключает JSON.
   Одинаковую версию с другими файлами не перезаписывает; канал назад не переводит.
5. Проверить доступ к JSON и каждому APK через HTTPS без авторизации.
   update.json отдаётся с Cache-Control: no-store, каталоги версий — immutable.
   Маршрут Caddy /updates/android/* уже настроен без SPA fallback.
   Ключ подписи, пароль и SSH-ключ не загружаются на публичный сервер.

НАСТРОЙКА КЛИЕНТА
Адрес JSON задаётся на экране «Обновления приложения» → «Сервер обновлений».
Можно встроить адрес в сборку, добавив в V2rayNG/gradle.properties:
PRO1VPN_UPDATE_URL=https://cabinet.pro1technology.ru/updates/android/update.json
По умолчанию уже встроен адрес cabinet.pro1technology.ru/updates/android/update.json. Адреса GitHub и приватные токены не требуются.
HTTPS должен иметь действующий доверенный сертификат; самоподписанный не принимается.

Приложение проверяет формат, Android package ID, увеличение versionCode,
совместимость Android/архитектуры, длину файла, SHA-256 и сертификат текущего APK.
Сам установщик Android также проверяет подпись. HTTP и переход HTTPS→HTTP запрещены.
Запрос не отправляет подписки, ключи VPN, Android ID или персональные данные.
Подтверждение установки обязательно; обход системных разрешений не используется.

Версии 1.0.0–1.0.2 рекомендуется один раз обновить через браузер:
https://cabinet.pro1technology.ru/updates/android/1.0.3/PRO1VPN_1.0.3_universal.apk
Установить поверх приложения, не удаляя его: ключ подписи и данные сохраняются.
В 1.0.0 нет автообновлений; в 1.0.1/1.0.2 два FileProvider имеют один класс,
из-за чего установщик может не получить APK и сообщить об ошибке пакета.
В 1.0.3 для обновлений выделен отдельный класс провайдера; перед запуском
установщика также проверяется чтение и SHA-256 APK через его content URI.
Серверный каталог: /srv/cabinet/updates/android/. Windows размещён отдельно.

ANDROID TV: ПОСТОЯННАЯ ССЫЛКА ДЛЯ DOWNLOADER
https://lk.pro1technology.ru/tv.apk
Код Downloader by AFTVnews: 6300701 (https://aftv.news/6300701).
Код ведёт на указанную постоянную ссылку, а не на номер версии.
В кабинете раздел /tv содержит инструкцию, копирование кода и ссылку на APK.

При публикации с --tv скрипт publish-update-server.py проверяет universal APK
актуального TV-фида и атомарно меняет /srv/cabinet/updates/android-tv/latest.apk
на относительную символьную ссылку. Более новая версия фида сохраняется.
Маршрут /tv.apk в pro-lk принимает GET/HEAD и перенаправляет на latest.apk.
В Caddy TV-фид и latest.apk отдаются с no-store, версионные APK — immutable.
После следующего релиза проверить размер и SHA256 загрузки через /tv.apk.
Цифровой код используется для загрузки APK, код с экрана ТВ — для подписки.
