From 6afafcf0e29b991bd6274a74995c7aa98836e808 Mon Sep 17 00:00:00 2001 From: ares Date: Sat, 12 Sep 2026 15:55:33 +0300 Subject: [PATCH] Make pairing fingerprint readable and capture simulator UI in CI --- .github/workflows/ios.yml | 11 +++++++++ MusicBridge/ContentView.swift | 3 ++- PLAN.md | 45 +++++++++++++++++++++++++++++------ README.md | 17 +++++++++++-- 4 files changed, 66 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml index b07ccce..ee572a3 100644 --- a/.github/workflows/ios.yml +++ b/.github/workflows/ios.yml @@ -68,6 +68,17 @@ jobs: retention-days: 7 - name: Archive simulator application run: ditto -c -k --sequesterRsrc --keepParent DerivedData/Build/Products/Debug-iphonesimulator/MusicBridge.app build/MusicBridge-simulator.zip + - name: Capture pairing screen + run: | + xcrun simctl launch "$SIMULATOR_ID" ru.yukinoki.musicbridge + sleep 3 + xcrun simctl io "$SIMULATOR_ID" screenshot build/pairing-screen.png + - name: Save pairing screen + uses: actions/upload-artifact@v4 + with: + name: ios-ui-preview + path: build/pairing-screen.png + retention-days: 7 - name: Save simulator application uses: actions/upload-artifact@v4 with: diff --git a/MusicBridge/ContentView.swift b/MusicBridge/ContentView.swift index 7426881..80df7bb 100644 --- a/MusicBridge/ContentView.swift +++ b/MusicBridge/ContentView.swift @@ -87,7 +87,8 @@ private struct PairingView: View { }.disabled(store.pairing) Group { TextField("Адрес ПК: https://192.168.1.10:8765", text: $endpoint).keyboardType(.URL) - TextField("SHA-256 сертификата с экрана ПК", text: $fingerprint) + TextField("SHA-256 сертификата с экрана ПК", text: $fingerprint, axis: .vertical) + .lineLimit(2...4).font(.system(.footnote, design: .monospaced)) TextField("Восьмизначный код", text: $code).keyboardType(.numberPad) }.textFieldStyle(.roundedBorder).textInputAutocapitalization(.never).autocorrectionDisabled() Text("Сверьте весь отпечаток с экраном ПК перед подключением.").font(.caption).foregroundStyle(.secondary) diff --git a/PLAN.md b/PLAN.md index 4fc9a17..0470275 100644 --- a/PLAN.md +++ b/PLAN.md @@ -34,14 +34,18 @@ Windows-агент — соседний проект `C:/Users/areso/MusicBridge - [ ] Интеграционный тест отказа от redirect. - [ ] Проверить 401 и отзыв устройства, Keychain после переустановки/блокировки. - [x] Установить на физический iPhone: пользователь подтвердил установку через iloader 2026-09-12. -- [ ] Проверить LAN/плеер/команды/обложку с настоящим Windows-агентом. -- [ ] Камера для QR, системные разрешения и обработка отказа. -- [ ] Bonjour-поиск `_musicbridge._tcp`, список ПК и обновление адреса при смене IP. +- [x] Первое подключение к настоящему Windows-агенту: пользователь подтвердил рабочий пилот на iPhone 2026-09-12. +- [ ] Полная ручная проверка каждого действия, обложки и устойчивости в Яндекс Музыке и SoundCloud. +- [x] Камера для QR, запрос доступа, сообщение при отказе, остановка камеры при закрытии/уходе в фон. +- [x] Bonjour-поиск `_musicbridge._tcp`, список адресов ПК и восстановление адреса с сохранённым сертификатом. +- [ ] Проверить камеру, открытие QR стандартной камерой, Bonjour и смену IP на физическом iPhone. - [ ] Улучшить ошибки сопряжения по серверным кодам; повтор загрузки обложки после 404. - [ ] Иконка приложения, визуальная проверка разных размеров экрана и Dynamic Type. - [ ] Live Activities / Dynamic Island / App Intents — отдельный последующий этап. -Ограничения: хранится один ПК; при смене его IP пока нужно повторное сопряжение. +Ограничения: хранится один доверенный ПК; адрес при смене IP восстанавливается через +Bonjour, если доступны объявления того же агента. Новый адрес сохраняется только +после успешного HTTPS-запроса с прежним отпечатком и токеном. Нет фонового воспроизведения, App Store/TestFlight и подписанной IPA. Потеря ответа на успешное сопряжение может оставить устройство на ПК: удалить его в окне агента перед повтором. Облачный runner не имеет доступа к домашней LAN. @@ -66,13 +70,15 @@ Windows-агент — соседний проект `C:/Users/areso/MusicBridge `tools/tls_fixture.py` запускается в CI перед сборкой тестов; закрытые ключи создаются временно на runner и не включаются в приложение или артефакты. - Сообщение «непригодные данные» при импорте приглашения пока не разобрано: - пользователь попросил отложить его. Следующий ручной шаг — повторить сопряжение - после установки новой IPA, затем проверить команды, прогресс и обложку. + пользователь попросил отложить его. Следующий этап — исправить импорт и добавить + сканер QR, затем поиск ПК и проверки устойчивости. - `93f7c9c`: [Actions 34694138394](https://github.com/polskikh13/musicbridgeios/actions/runs/34694138394) — 10 XCTest, 0 отказов, успешный Release archive. Версия 0.1.1 (build 2), IPA скачана в `build/iPhone-0.1.1/MusicBridge-iPhone.ipa`; локально проверены ZIP, iPhoneOS ARM64, версия и ATS-настройки внутри готовой IPA. - Сопряжение на физическом iPhone после этого исправления ещё не подтверждено. + После обновления пользователь подтвердил: «всё работает в пилотном режиме». + Это подтверждает первую рабочую связку iPhone ↔ Windows; полная матрица ручных + проверок и длительная работа пока не подтверждены. ## Карта @@ -81,12 +87,37 @@ Windows-агент — соседний проект `C:/Users/areso/MusicBridge - `KeychainStore.swift`: хранение сопряжения. - `PlayerStore.swift`: состояние, команды, жизненный цикл и восстановление. - `ContentView.swift`: подключение и плеер. +- `QRScanner.swift`: камера AVFoundation, доступ, сканирование и жизненный цикл. +- `DiscoveryStore.swift`: Bonjour, разрешение адресов, TXT и безопасный выбор адреса. - `MusicBridgeTests/`: XCTest и пример Windows JSON. - `tools/`: генератор проекта, структурные проверки, выбор симулятора для CI. - `.github/workflows/ios.yml`: CI на macOS. - `tools/package_ipa.sh`: Release archive для настоящего iPhone и упаковка Payload. - `tools/verify_ipa.py`: проверка ZIP, Info.plist, ARM64 и платформы Mach-O (iOS, не Simulator). +## QR и поиск ПК — 0.2.0 (build 3) + +- Добавлен сканер внутри приложения; после сканирования заполняются адрес, + отпечаток и код, подключение запускает пользователь. Также зарегистрирована + схема `musicbridge://`, приглашения принимаются через `onOpenURL`. + Посторонний QR, повреждённый JSON и истёкший код дают понятную ошибку. +- Регистрация URL-схемы устраняет отсутствие обработчика ссылки при чтении QR + стандартной камерой. Исходное сообщение «непригодные данные» ещё нужно + перепроверить на телефоне, точный источник той ошибки не был установлен. +- Поиск использует NSBonjourServices и NetServiceBrowser. Объявления версии 1 + принимаются только с допустимым SHA-256 и частным IPv4. При первом выборе + найденного ПК пользователь сверяет полный отпечаток с его экраном. +- При восстановлении адреса TXT служит только подсказкой: сертификат из сети + не заменяет сохранённый. Чужой fingerprint не используется; токен отправляется + только через соединение с прежним TLS pin. После успеха адрес обновляется в Keychain. +- Поиск приостанавливается в фоне; адреса повторно разрешаются раз в 15 секунд, + список ограничен 64 сервисами и 16 адресами на сервис. Есть повторный поиск + и переход в настройки разрешений. +- `397caf2`: Actions 34694893204 — 14 XCTest, 0 отказов, Release archive успешен. + Проверены формат объявления Windows, разбор sockaddr, отказы чужим данным, + сохранение pin/token при смене адреса и .NET timestamp с семью дробными цифрами. + Камера и реальный multicast iPhone ↔ Windows не эмулируются этими тестами. + ## Результаты 2026-09-10 - `07322c2`: успешный [Actions run 34445566212](https://github.com/polskikh13/musicbridgeios/actions/runs/34445566212). diff --git a/README.md b/README.md index aaf96dd..33fce5d 100644 --- a/README.md +++ b/README.md @@ -51,11 +51,24 @@ Apple ID и сертификаты для этой проверки не тре Код автоматически не зеркалируется между серверами. Локальная регрессионная проверка выбора симулятора: `python tools/test_select_simulator.py`. +## Подключение через QR и поиск ПК + +В версии 0.2.0 откройте окно сопряжения в Windows-агенте (`--tray --lan`), +на iPhone нажмите «Сканировать QR с ПК» и разрешите камеру. После сканирования +нажмите «Подключить компьютер». Ссылки `musicbridge://` также открываются +из стандартной камеры. Приглашение должно быть свежим. + +В разделе «Найти ПК в сети» можно выбрать найденный адрес. Сверьте **весь** +предложенный отпечаток с экраном ПК и введите код. Если поиск не работает, +проверьте доступ к локальной сети в настройках MusicBridge; ручной ввод остаётся. +При смене адреса уже доверенного ПК приложение пробует объявления с тем же +отпечатком и сохраняет новый адрес только после успешной TLS-проверки и авторизации. + ## Установка на iPhone через Sideloadly Пользователь также подтвердил установку через iloader. Для повторной установки -после исправления TLS используйте версию **0.1.1 (build 2)**: -`build/iPhone-0.1.1/MusicBridge-iPhone.ipa`. Выберите этот файл в iloader и +с QR и поиском ПК используйте версию **0.2.0 (build 3)**: +`build/iPhone-0.2.0/MusicBridge-iPhone.ipa`. Выберите этот файл в iloader и подпишите тем же Apple Account, которым установлена первая версия. Workflow также выполняет Release archive для `generic/platform=iOS` и создаёт