354 lines
39 KiB
Markdown
354 lines
39 KiB
Markdown
# MusicBridge iOS — план
|
||
|
||
Обновлено: 2026-09-14. Пользователь разрешил начать нативное iOS-приложение.
|
||
Репозиторий: `C:/Users/areso/iOS MusicBridge`; origin — dev.yukinoki.ru/musicbridge/ios.
|
||
Windows-агент — соседний проект `C:/Users/areso/MusicBridge/MusicBridge.Agent`.
|
||
|
||
## Системный пульт 0.7.0 (8) — текущий этап
|
||
|
||
- [x] Реализация NowPlaying RemoteMediaSession и отдельного ExtensionKit target для iOS 27.
|
||
- [x] Кнопка включения/выключения в приложении; музыка продолжает играть на ПК.
|
||
- [x] Метаданные, обложка, play/pause, предыдущий/следующий трек, перемотка, громкость ПК.
|
||
- [x] Перед командой проверяются свежие capabilities и действующее сопряжение; команды не повторяются автоматически.
|
||
- [x] Токен хранится в общем Keychain, не передаётся в атрибутах системной сессии.
|
||
- [x] Перемотка переводится из позиции относительно трека в диапазон Windows API.
|
||
- [x] Выключение и удаление сопряжения удаляют доступ расширения; возврат запоздавшего restore не восстанавливает сессию.
|
||
- [x] Итоговый `91e305a`: [Actions 34785082289](https://github.com/polskikh13/musicbridgeios/actions/runs/34785082289), Xcode 27, 36 XCTest без отказов, успешный Release archive. Первая попытка 34783380221 выявила Double/Float и исправлена.
|
||
- [ ] Установка с подписью обоих расширений и общим Keychain; проверка на физическом iPhone.
|
||
- [ ] Пункт управления: кнопки, перемотка, громкость; блокировка телефона, сон ПК, отзыв токена, повторная подпись.
|
||
|
||
IPA скачана в `build/iPhone-0.7.0/MusicBridge-iPhone.ipa` (без подписи).
|
||
Локально проверены ZIP, ARM64 iPhoneOS всех трёх исполняемых файлов,
|
||
совпадение версий, ExtensionKit extension point и общий Keychain suffix.
|
||
SHA-256: `a84e146a5259c0c7250dab829f2eb07093f33d5e212ff1e1880f6c3fd29d65ee`.
|
||
Логи тестов находятся в `build/iPhone-0.7.0/tests`, снимки — в `preview`.
|
||
Просмотрены светлый плеер и дополнительный iPhone: кнопка пульта видна снизу,
|
||
пояснения доступны прокруткой. Системная карточка NowPlaying на этих снимках
|
||
не проверялась: для запуска нужен подписанный общий Keychain.
|
||
|
||
**Ограничение iloader:** проверен официальный исходник `nab138/isideload`, ветка
|
||
`apple-codesign-quick`, commit `f6a4d5dba717d72fc2af63eaba26b27ba44116be`, который использует текущий iloader.
|
||
`isideload/src/sideload/bundle.rs` обнаруживает расширения только в `PlugIns`,
|
||
а NowPlaying размещается в `Extensions`. `sign.rs` берёт entitlements из profile,
|
||
добавление shared Keychain реализовано для отдельных SpecialApp, не для MusicBridge.
|
||
Поэтому обычную установку 0.7.0 через iloader нельзя считать поддержанной.
|
||
Не переносить ExtensionKit в PlugIns наугад и не передавать токен через публичные атрибуты.
|
||
Следующий этап установки: совместимый подписыватель или доработка iloader для
|
||
ExtensionKit и общего Keychain с реальными provisioning profiles. Xcode signing
|
||
всех трёх targets — вариант при наличии совместимого Mac и профилей; разрешение
|
||
нового extension point бесплатной командой ещё не подтверждено на устройстве.
|
||
|
||
Без APNs расширение читает ПК при команде; открытое приложение обновляет сессию
|
||
при смене трека/статуса и периодически. Смена трека на самом ПК при приостановленном
|
||
приложении не гарантирует автоматического обновления карточки. Фиктивное аудио не используется.
|
||
|
||
## Инфраструктура — текущее состояние
|
||
|
||
- SSH к macOS проверен: `aresov@10.67.67.28`, macOS 26.6.2, x86_64,
|
||
около 459 ГБ свободно. Xcode не установлен. Локальный отдельный ключ:
|
||
`C:/Users/areso/.ssh/musicbridge_macos_ed25519` (закрытый ключ не включать в репо).
|
||
Использовать `C:/Windows/System32/OpenSSH/ssh.exe` с `-F NUL`,
|
||
`-o ProxyCommand=none -o ProxyJump=none -o IdentitiesOnly=yes` и этим ключом;
|
||
другая установленная версия ssh не подключалась. Host key сохранён в known_hosts.
|
||
- Xcode 27 требует Apple Silicon; эта Intel-виртуалка не подходит для SDK 27.
|
||
CI переведён на GitHub-hosted `xcode-27`: Xcode 27.0 (27A5252f), Swift 6.4, SDK iOS 27.0.
|
||
[Actions 34764552877](https://github.com/polskikh13/musicbridgeios/actions/runs/34764552877)
|
||
для `1e14bf7`: 32 XCTest, 0 отказов, успешный Release archive.
|
||
IPA: `build/iPhone-0.6.0-xcode27/MusicBridge-iPhone.ipa`; проверены SDK 27, ARM64
|
||
приложения/расширения и структура пакета. Предпросмотр карточки просмотрен.
|
||
Версия осталась 0.6.0 (7); новые функции в пересборке не добавлены.
|
||
Просроченный тестовый сертификат создаётся с явными датами через
|
||
cryptography==46.0.3 в отдельном venv, поскольку новый OpenSSL отвергает -days -1.
|
||
- Пользователь подтвердил бесплатный Apple Account через iloader.
|
||
Фоновая доставка APNs заблокирована отсутствием Push Notifications capability
|
||
и соответствующей подписи. Платная Developer Program, App ID, ключ APNs и
|
||
provisioning profile пока отсутствуют; не обещать работу push после простой
|
||
смены Xcode. После появления доступа нужны регистрация токенов, отправитель
|
||
обновлений с Windows/сервера и тестирование доставки на физическом iPhone.
|
||
|
||
## Правила реализации
|
||
|
||
- SwiftUI, без веб-клиента. Музыка играет на Windows.
|
||
- Сверять контракт с Windows PROTOCOL.md; не менять серверный протокол молча.
|
||
- Токены только в Keychain, проверка сертификата до сопряжения, запрет redirect.
|
||
- Не повторять команды автоматически после потери ответа.
|
||
- Не называть проверки Python сборкой Swift или запуском XCTest.
|
||
- После этапа обновлять этот файл: реализация, проверки, ограничения, следующий шаг.
|
||
|
||
## Реализовано в исходниках
|
||
|
||
- [x] Проект Xcode, shared scheme, iOS 17+, SwiftUI, без внешних зависимостей.
|
||
- [x] Модели состояния и команд v1; валидация HTTPS IPv4 домашней сети и QR-строки.
|
||
- [x] Ручное сопряжение, импорт приглашения, проверка SHA-256 DER-сертификата.
|
||
- [x] Keychain: адрес, отпечаток и bearer-токен; удаление локального сопряжения.
|
||
- [x] HTTPS-команды, обложка до 2 МиБ, поток WSS с ограничением размера сообщения.
|
||
- [x] Экран трека, возможности кнопок, прогресс, перемотка, громкость, mute.
|
||
- [x] Переподключение 1…16 секунд, watchdog потока, отключение в фоне, возврат.
|
||
- [x] XCTest исходники: диапазоны адресов, отказ опасным URL, отпечатки,
|
||
QR/срок/коды, JSON Windows, расчёт позиции, формат команд.
|
||
- [x] GitHub Actions: сборка/тесты симулятора, логи, xcresult и артефакт приложения.
|
||
|
||
## Проверки и следующие шаги
|
||
|
||
- [x] Первый успешный xcodebuild + XCTest на macOS: 7 тестов, 0 отказов.
|
||
- [x] Подключён GitHub remote polskikh13/musicbridgeios; Actions и чтение логов через gh работают.
|
||
- [x] Интеграционные тесты TLS: верный/чужой/истёкший сертификат, HTTPS и WSS.
|
||
- [x] Пройдены интеграционные проверки redirect, 401, возврата из фона и загрузки обложки.
|
||
- [ ] Проверить реальный Keychain после переустановки/блокировки и отзыв устройства на физическом iPhone.
|
||
- [x] Установить на физический iPhone: пользователь подтвердил установку через iloader 2026-09-12.
|
||
- [x] Первое подключение к настоящему Windows-агенту: пользователь подтвердил рабочий пилот на iPhone 2026-09-12.
|
||
- [ ] Полная ручная проверка каждого действия, обложки и устойчивости в Яндекс Музыке и SoundCloud.
|
||
- [x] Камера для QR, запрос доступа, сообщение при отказе, остановка камеры при закрытии/уходе в фон.
|
||
- [x] Bonjour-поиск `_musicbridge._tcp`, список адресов ПК и восстановление адреса с сохранённым сертификатом.
|
||
- [x] QR через камеру работает на физическом iPhone — подтверждено пользователем после установки 0.2.0.
|
||
- [ ] Отдельно проверить оба входа (встроенный сканер и стандартная камера), отказ в доступе к камере, Bonjour и смену IP на физическом iPhone.
|
||
- [x] Реализованы понятные ошибки сопряжения по кодам сервера, повтор загрузки обложки после 404 и ручной повтор.
|
||
- [x] Иконка приложения и обновлённый интерфейс подключения/плеера.
|
||
- [x] Просмотрены снимки 0.4.0: подключение, светлая/тёмная темы, iPhone SE и крупный текст.
|
||
- [x] Пользователь подтвердил работу 0.4.0 на iPhone: «всё вроде работает».
|
||
- [x] Локальная Live Activity и Dynamic Island: реализация отображения трека в 0.5.0.
|
||
- [ ] Проверить Live Activity на экране блокировки и Dynamic Island после подписи через iloader.
|
||
- [x] LiveActivityIntent: предыдущий/следующий трек, play/pause и обновление — 0.6.0.
|
||
- [ ] Проверить команды из Live Activity/Island при блокировке на физическом iPhone.
|
||
- [ ] Команды Siri.
|
||
- [x] NowPlaying RemoteMediaSession (iOS 27+): SDK 27 и remote-media extension реализованы в 0.7.0; установка и физическая проверка — в текущем этапе выше.
|
||
- [ ] APNs: отдельный проект обновлений при приостановленном приложении, если нужен постоянный актуальный трек в фоне.
|
||
|
||
Ограничения: хранится один доверенный ПК; адрес при смене IP восстанавливается через
|
||
Bonjour, если доступны объявления того же агента. Новый адрес сохраняется только
|
||
после успешного HTTPS-запроса с прежним отпечатком и токеном.
|
||
Нет фонового воспроизведения, App Store/TestFlight и подписанной IPA.
|
||
Потеря ответа на успешное сопряжение может оставить устройство на ПК: удалить его
|
||
в окне агента перед повтором. Облачный runner не имеет доступа к домашней LAN.
|
||
|
||
## Проверка на iPhone 2026-09-12
|
||
|
||
- Windows GUI запущен с `--tray --lan`, порт TCP 8765 слушает.
|
||
- На iPhone первая попытка сопряжения завершилась ошибкой недействительного
|
||
сертификата сервера. Установка приложения уже работает; это отдельная TLS-проблема.
|
||
- Ошибка воспроизведена настоящим HTTPS-запросом в iOS Simulator: старый код
|
||
возвращает NSURLErrorDomain -1202 даже с верным отпечатком. Одни ATS-исключения
|
||
её не устранили. Исправление: обрабатывать server trust также в
|
||
`URLSessionTaskDelegate.didReceive`, направляя его в общую проверку отпечатка
|
||
и срока сертификата. После этого HTTPS и WSS проходят.
|
||
- Подготовлены ATS-исключения только для RFC1918 CIDR: `10.0.0.0/8`,
|
||
`172.16.0.0/12`, `192.168.0.0/16`. Начиная с iOS 17, для IP нужны явные
|
||
исключения. Клиент продолжает требовать HTTPS, точный SHA-256 отпечаток,
|
||
действующий сертификат и запрещает redirect. Глобального отключения ATS нет.
|
||
- Добавлены настоящие HTTPS/WSS проверки в симуляторе с сертификатом того же
|
||
типа, что у агента: RSA 2048, самоподписанный, CA:FALSE, SAN localhost/127.0.0.1,
|
||
срок пять лет. Отдельно проверяются чужой отпечаток и истёкший сертификат.
|
||
`tools/tls_fixture.py` запускается в CI перед сборкой тестов; закрытые ключи
|
||
создаются временно на runner и не включаются в приложение или артефакты.
|
||
- Сообщение «непригодные данные» при импорте приглашения пока не разобрано:
|
||
пользователь попросил отложить его. Следующий этап — исправить импорт и добавить
|
||
сканер 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 ↔ Windows; полная матрица ручных
|
||
проверок и длительная работа пока не подтверждены.
|
||
|
||
## Карта
|
||
|
||
- `MusicBridge/Models.swift`: контракт и проверка входных данных.
|
||
- `BridgeClient.swift`: сертификат, HTTPS, WSS, ограничения ответов.
|
||
- `KeychainStore.swift`: хранение сопряжения.
|
||
- `PlayerStore.swift`: состояние, команды, жизненный цикл и восстановление.
|
||
- `ContentView.swift`: подключение и плеер.
|
||
- `QRScanner.swift`: камера AVFoundation, доступ, сканирование и жизненный цикл.
|
||
- `DiscoveryStore.swift`: Bonjour, разрешение адресов, TXT и безопасный выбор адреса.
|
||
- `ConnectionStorage.swift`: доступ к Keychain и подмена хранилища для изолированных тестов жизненного цикла.
|
||
- `LiveActivityManager.swift`: запуск, обновление, устаревание и завершение одной локальной Live Activity.
|
||
- `Shared/`: ограниченный публичный снимок трека и общие SwiftUI-компоненты карточки.
|
||
- `MusicBridgeWidgets/`: расширение WidgetKit, экран блокировки и все представления Dynamic Island.
|
||
- `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 не эмулируются этими тестами.
|
||
- Итоговый `e384e9a`: [Actions 34695228108](https://github.com/polskikh13/musicbridgeios/actions/runs/34695228108)
|
||
— 14 XCTest без отказов и успешный Release archive. Экран подключения просмотрен
|
||
на снимке симулятора; исправлен статус при возвращении без сохранённого ПК.
|
||
IPA скачана в `build/iPhone-0.2.0/MusicBridge-iPhone.ipa`; проверены ZIP, ARM64
|
||
iPhoneOS, версия 0.2.0 (3), разрешение камеры, Bonjour и обработчик URL в готовом пакете.
|
||
Пользователь подтвердил работу QR через камеру на iPhone. Следующий шаг:
|
||
проверить Bonjour/смену IP и устойчивость, улучшить ошибки и восстановление обложки.
|
||
|
||
## Следующие этапы — выполнять последовательно
|
||
|
||
1. **Устойчивость и ошибки — версия 0.3.0 (build 4).** Исправления и автоматические
|
||
проверки завершены. Следующий ручной шаг — проверка на iPhone.
|
||
2. **Интерфейс — версия 0.4.0 (build 5).** Добавлены иконка, компактный экран QR,
|
||
раскрываемые ручные поля, крупная play/pause, процент громкости и меню ПК.
|
||
Сборка и 23 XCTest прошли; просмотрены темы, компактный экран и крупный текст.
|
||
Пользователь подтвердил работу обновления на телефоне перед началом этапа 3.
|
||
3. **Системные интеграции — 0.6.0 (build 7).** Добавлены прямые действия LiveActivityIntent.
|
||
Убрана ошибка устаревания при обычном сворачивании; каждое нажатие перечитывает ПК.
|
||
32 XCTest и Release archive прошли. APNs и встроенный системный музыкальный пульт ещё не реализованы.
|
||
Не имитировать фоновое аудио. Не обещать постоянный WSS при блокировке.
|
||
4. **Несколько сохранённых ПК** — последующее расширение, сейчас сохраняется один.
|
||
|
||
Продолжение третьего этапа — 0.6.0:
|
||
|
||
- Итоговый `43c78b2`: [Actions 34748340408](https://github.com/polskikh13/musicbridgeios/actions/runs/34748340408)
|
||
— 32 XCTest без отказов, успешный Release archive. IPA 0.6.0 (7) скачана в
|
||
`build/iPhone-0.6.0/MusicBridge-iPhone.ipa`; проверены ARM64 iPhoneOS приложения
|
||
и расширения, версии, метаданные интентов. Просмотрены светлая и тёмная карточки.
|
||
Работа системного запуска LiveActivityIntent и Keychain после блокировки требует
|
||
проверки на телефоне: обновить IPA, выключить/включить карточку, заблокировать,
|
||
проверить next/previous/toggle/refresh; затем повторить после перезагрузки и первого unlock.
|
||
- Пользователь сообщил, что карточка постоянно пишет об устаревших данных.
|
||
Причина: `PlayerStore.stop()` вызывал `unavailable()` при каждом уходе в фон.
|
||
Удалён этот вызов; реальные сетевые отказы продолжают отмечаться отдельно.
|
||
Карточка показывает время последнего снимка и отдельные ошибки запросов.
|
||
- Shared `MusicControlIntent` соответствует LiveActivityIntent. WidgetKit содержит
|
||
определение интента, выполнение сети компилируется только в основной app target;
|
||
iOS запускает процесс приложения без открытия UI. На компактном/минимальном Island
|
||
кнопок нет: нужно раскрыть долгим нажатием. Кнопки не отключаются из-за старого снимка.
|
||
- `LiveActivityCommands`: одно действие одновременно, проверка живой Activity и связи
|
||
её ID с fingerprint текущего сопряжения. После чтения состояния повторно проверяется
|
||
актуальность карточки, затем проверяются capabilities и отправляется максимум одна
|
||
команда. Refresh вообще не отправляет команду. Повторов команд нет.
|
||
- После успеха перечитывается трек и обновляется Activity. 401 завершает её;
|
||
неизвестный результат и неудача чтения после успеха имеют разные сообщения.
|
||
Нет бесконечного WSS/Bonjour в фоне; после смены IP сначала открыть приложение.
|
||
- Keychain: AfterFirstUnlockThisDeviceOnly вместо WhenUnlockedThisDeviceOnly,
|
||
чтобы команды работали при заблокированном iPhone. Существующий токен мигрирует
|
||
при повторном включении карточки. Он не покидает Keychain и не попадает в payload.
|
||
В UserDefaults сохраняется только соответствие ID активности и публичного pin.
|
||
После обновления с 0.5.0 карточку выключить и включить заново в приложении.
|
||
- HTTPS-тесты проверяют одну отправку next и новый трек, refresh без команды,
|
||
закрытую карточку, неподдерживаемую команду, отсутствие повторов отказавшей команды,
|
||
ошибку чтения после успешной команды. Физический запуск интента проверяется отдельно.
|
||
- Ответ на вопрос пользователя о встроенном музыкальном центре: официальный
|
||
[NowPlaying RemoteMediaSession](https://developer.apple.com/documentation/nowplaying/publishing-remote-media-sessions)
|
||
предназначен для внешнего воспроизведения. Metadata Apple указывает iOS 27.0.
|
||
Текущий runner собирает Xcode 16.4: следующий этап — SDK/Xcode 27 и отдельное
|
||
`com.apple.nowplaying.remote-media` расширение. Интеграция ещё не реализована.
|
||
|
||
История третьего этапа — Live Activities 0.5.0 (поведение фона изменено в 0.6.0):
|
||
|
||
- Итоговый `ddd44e8`: [Actions 34747772034](https://github.com/polskikh13/musicbridgeios/actions/runs/34747772034)
|
||
— 26 XCTest без отказов, сборка приложения и WidgetKit-расширения, успешный Release archive.
|
||
IPA скачана в `build/iPhone-0.5.0/MusicBridge-iPhone.ipa`; проверены оба ARM64
|
||
iPhoneOS исполняемых файла, структура `.appex`, версии и NSSupportsLiveActivities.
|
||
Светлый/тёмный предпросмотр карточки просмотрен: текст и отметка устаревания читаемы.
|
||
Установка/регистрация Live Activity на физическом iPhone остаются ручной проверкой.
|
||
- ActivityKit без push: старт только кнопкой пользователя при активном приложении
|
||
и медиасессии. Восстанавливается существующая активность, дубли завершаются;
|
||
после удаления пользователем автоматического пересоздания нет.
|
||
- WidgetKit-расширение встроено в приложение. В attributes/content нет адреса ПК,
|
||
токена, fingerprint или обложки; только публичные данные трека, ограниченные
|
||
по UTF-8 (по 256 байт для названия и исполнителя).
|
||
- Обычные позиции объединяются до одного обновления в пять секунд; смена трека,
|
||
длительности или состояния воспроизведения отправляется сразу. Прогресс статический,
|
||
соответствует последнему снимку. В фоне/без сети помечается устаревшим;
|
||
`staleDate` через 15 секунд страхует внезапную остановку приложения.
|
||
- Нет медиасессии, отзыв доступа, «Забыть компьютер» или ручное выключение — завершение.
|
||
Нажатие карточки открывает `musicbridge://player`, не попадает в импорт QR.
|
||
- Новые XCTest: позиция относительно startSeconds, нулевая длительность/пауза,
|
||
чрезмерные Unicode-метаданные и размер Codable payload. Проверка IPA требует
|
||
встроенную ARM64 iPhoneOS `.appex`, совпадающие версии и поддержку Live Activities.
|
||
- CI-предпросмотр общей разметки карточки проверяет светлую/тёмную темы и устаревшие
|
||
данные. Это не проверка системной регистрации ActivityKit/Island. На физическом
|
||
iPhone проверить старт, блокировку, раскрытие Island, переход в плеер, возврат,
|
||
удаление карточки, отсутствие автопересоздания, окончание сессии и отзыв доступа.
|
||
- Следующие отдельные задачи: LiveActivityIntent с безопасным выполнением команды
|
||
(проверить доступность Keychain/локальной сети при блокировке); Siri; APNs, если
|
||
требуются актуальные данные после приостановки приложения. Постоянный WSS в фоне
|
||
не реализован и не обещается. Windows-протокол не менялся.
|
||
- Основание: [Apple ActivityKit](https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities)
|
||
и [WidgetKit extension](https://developer.apple.com/documentation/widgetkit/creating-a-widget-extension).
|
||
|
||
Изменения второго этапа:
|
||
|
||
- Итоговый `aa0b0f0`: [Actions 34746477145](https://github.com/polskikh13/musicbridgeios/actions/runs/34746477145)
|
||
— 23 XCTest без отказов и успешный Release archive. Итоговая IPA скачана в
|
||
`build/iPhone-0.4.0/MusicBridge-iPhone.ipa`; проверены ZIP, iPhoneOS ARM64,
|
||
версия 0.4.0 (5), AppIcon в Info.plist и скомпилированный каталог Assets.car.
|
||
Снимки находятся в `build/iPhone-0.4.0/final-preview`. На маленьком экране
|
||
основные кнопки видны сразу; для нижней части громкости может требоваться прокрутка.
|
||
- `cbd3c0f`: добавлены оригинальная иконка 1024×1024 и каталог AppIcon,
|
||
карточка QR, раскрываемые ручные поля, меню ПК, крупная play/pause и процент громкости.
|
||
- `aa0b0f0`: после просмотра iPhone SE уменьшена обложка по доступной высоте окна;
|
||
размеры заданы явно, чтобы заглушка оставалась квадратной. Исполнитель выровнен по центру.
|
||
- В Debug есть изолированный предпросмотр с примером трека и памятью вместо Keychain;
|
||
в Release этот режим недоступен. CI сохраняет светлый/тёмный плеер, крупный текст,
|
||
компактный экран и подключение. Ошибка Keychain -34018 на снимке подключения
|
||
относится к неподписанному запуску в CI; доступ к Keychain на телефоне требует подписи.
|
||
- Ручная проверка обновления: установить IPA через iloader, проверить иконку,
|
||
сохранённое сопряжение, QR, меню ПК, перемотку и громкость; повторить с крупным
|
||
системным шрифтом и тёмной темой. Реальную камеру и домашнюю сеть CI не проверяет.
|
||
|
||
Изменения первого этапа:
|
||
|
||
- Итоговый `bde6f7a`: [Actions 34712051233](https://github.com/polskikh13/musicbridgeios/actions/runs/34712051233)
|
||
— 23 XCTest без отказов, Release archive успешен. IPA 0.3.0 (build 4) скачана
|
||
в `build/iPhone-0.3.0/MusicBridge-iPhone.ipa`; проверены ZIP, платформа iPhoneOS,
|
||
ARM64 и версия. Экран подключения просмотрен на снимке симулятора.
|
||
|
||
- Четыре попытки загрузить обложку, паузы 2/4/8 секунд, отдельное сообщение и кнопка
|
||
ручного повтора. После 404 перечитывается состояние, чтобы заметить смену трека.
|
||
Старая обложка не должна подменять новую после запоздавшего ответа.
|
||
- При уходе в фон закрываются текущие соединения и незавершённое сопряжение;
|
||
его поздний ответ не сохраняется. Если сервер уже создал запись устройства,
|
||
пользователь получает указание удалить её перед повторным сопряжением.
|
||
- Ответ 401 переводит приложение в состояние повторного сопряжения, останавливает
|
||
автоматические повторы и сохраняет этот статус при возвращении из фона.
|
||
- Понятные сообщения для invalid_code, pairing_closed, device_limit, storage_failed,
|
||
HTTP-ошибок, сетевых сбоев и TLS. Текст отказа команды не стирается обновлением
|
||
прогресса; сообщение можно скрыть. Команды не повторяются автоматически.
|
||
- Успех команды и неудача последующего чтения состояния различаются в интерфейсе.
|
||
После недоступности Keychain при запуске чтение повторяется при активации приложения.
|
||
- Реальные HTTPS/WSS тесты используют временный сервер CI с задержками, 404/401/503,
|
||
redirect, ошибками сопряжения и сменой обложки. Реальный пользовательский Keychain
|
||
в этих тестах не изменяется. Сон ПК, Wi-Fi и системную блокировку надо проверить
|
||
отдельно на физических устройствах.
|
||
|
||
## Результаты 2026-09-10
|
||
|
||
- `07322c2`: успешный [Actions run 34445566212](https://github.com/polskikh13/musicbridgeios/actions/runs/34445566212).
|
||
Добавлен Release archive и неподписанный IPA для Sideloadly. Скачан в
|
||
`build/Sideloadly/MusicBridge-iPhone.ipa` (112334 байта). Локальная проверка ZIP,
|
||
Info.plist и Mach-O подтвердила iPhoneOS ARM64, минимум iOS 17.0.
|
||
Подпись и установка выполняются пользователем в Sideloadly; на физическом
|
||
iPhone ещё не проверено. Инструкция добавлена в README.md.
|
||
- `a761431`: успешный [Actions run 34444563869](https://github.com/polskikh13/musicbridgeios/actions/runs/34444563869),
|
||
macos-15, Xcode 16.4, Swift 6.1.2, симулятор iOS 18.5; 7 XCTest прошли.
|
||
Артефакты: MusicBridge-simulator и ios-test-results (лог и xcresult), хранение 7 дней.
|
||
- Первый CI-прогон не дошёл до компиляции: исправлены регистр UDID и выбор runtime
|
||
по версии активного SDK. Две регрессионные Python-проверки прошли локально.
|
||
- Структурная проверка Python прошла: генератор детерминирован, ссылки проекта,
|
||
состав исходников, Info.plist, схема и JSON согласованы.
|
||
- В CI есть предупреждения инструментов о подписанных библиотеках XCTest,
|
||
отсутствии AppIntents и Node 20 в checkout/upload-artifact v4; тесты прошли.
|
||
Миграция Actions на актуальные версии — отдельное небольшое обновление.
|
||
- Следующий шаг: интеграционные проверки TLS/WSS и UI, затем сканер QR/Bonjour.
|
||
Физический iPhone, Apple-подпись и управление настоящим ПК ещё не проверены.
|