Implement QR pairing window and mDNS announcements; update documentation and tests

This commit is contained in:
2026-09-09 09:53:37 +03:00
parent d5e827112a
commit 2da3c9544b
7 changed files with 321 additions and 61 deletions
+53 -31
View File
@@ -1,41 +1,63 @@
# Заготовки подключения — iOS не начинать до команды пользователя
# Подключение MusicBridge — Windows
## Уже есть
Разработка iOS начинается только после отдельной команды пользователя.
- `ConnectionInvitation`: проверяет домашний IPv4 HTTPS-адрес, код/срок и SHA-256
сертификата; создаёт строку `musicbridge://pair?data=<base64url UTF-8 JSON>`.
- Клавиша `I` в агенте выводит эту строку для каждого подходящего адреса при
открытом сопряжении (`B`) и запуске с `--lan`. Это **данные для QR, не QR-картинка**.
- В JSON: `version:1`, `endpoint`, `certificateSha256`, `code` (строка из 8 цифр),
`expiresAt` (ISO 8601). Payload содержит секрет сопряжения: не публиковать/не
отправлять внешним генераторам QR. Его срок совпадает со сроком кода.
- `DiscoveryDescriptor`: сервис `_musicbridge._tcp.local.`, имя
`MusicBridge-<12 первых символов отпечатка>`, TXT `v=1`, `id=<полный SHA-256>`.
- Авторизованный `GET /v1/info` возвращает `protocolVersion`, `agentId`,
`serviceType`, `instanceName`; идентификатор равен отпечатку сертификата.
## Что работает
## Следующая реализация на Windows
- `dotnet run -c Release -- --lan` запускает HTTPS/WSS и mDNS для домашней IPv4-сети.
- `B` открывает новое окно сопряжения; `I` открывает отдельное Windows-окно QR.
- В окне можно выбрать адрес адаптера. QR обновляется при смене адреса или кода,
убирается при истечении кода/успешном сопряжении. Проверка состояния — каждые 500 мс.
- QR генерируется локально через QRCoder. Внешних сайтов и временных файлов с кодом нет.
- Payload: `musicbridge://pair?data=<base64url UTF-8 JSON>`, поля `version:1`,
`endpoint`, `certificateSha256`, `code`, `expiresAt`.
- Сервис DNS-SD: `_musicbridge._tcp.local.`, имя `MusicBridge-<12 символов SHA-256>`.
SRV указывает порт HTTPS; A — адреса домашних адаптеров; TXT — версия и ID.
Библиотека также добавляет служебный `txtvers`. Кодов и токенов в объявлениях нет.
- mDNS обслуживает запросы, повторяет объявление раз в 30 секунд. При изменении
списка IPv4-адресов снимает старое объявление и создаёт новое. При остановке
отправляет goodbye. При исчезновении сети ждёт её возвращения.
- `/v1/info` требует Bearer-токен и возвращает идентификатор, равный SHA-256 сертификата.
- [ ] Локальная генерация QR из payload; отображение в окне агента/трее.
- [ ] Закрывать/обновлять показанный QR при истечении кода, сопряжении или смене IP.
- [ ] Выбор адаптера при нескольких адресах; сейчас для каждого свой payload.
- [ ] mDNS/DNS-SD publisher: PTR/SRV/TXT/A, порт HTTPS агента, без кодов и токенов.
- [ ] Обработка конфликтов имён, смены адресов, сна/пробуждения и остановки сервиса.
- [ ] Проверка объявления со второго устройства. Сейчас multicast не отправляется.
Без `--lan` mDNS выключен, а окно QR сообщает, что нужен адрес домашней сети.
Поиск не доказывает подлинность ПК: клиент всегда сверяет закреплённый TLS-сертификат.
## Что проверено
Release-сборка без ошибок/предупреждений. Итоговый прогон — 95 проверок:
```powershell
dotnet run --project tests/MusicBridge.Agent.Tests.csproj -c Release --no-build -- --qr-window-smoke --mdns-smoke --live-read
```
QR декодирован независимой библиотекой ZXing в исходный payload. Окно проверено
в скрытом режиме, его снимок просмотрен, просроченный QR удаляется. Независимый
mDNS-слушатель на этом же ПК получил объявление и goodbye. Это ещё не проверка
доступности с iPhone/другого компьютера. Smoke-тест объявляет временный тестовый
сервис и снимает его после проверки; реальное воспроизведение не меняется.
## Что остаётся на Windows
- [ ] Проверить сканирование с физического устройства и обнаружение со второго ПК.
- [ ] Проверить смену Wi-Fi/IP, сон/пробуждение, несколько адаптеров и VPN.
- [ ] Полноценное разрешение конфликтов имён DNS-SD; сейчас имя строится по хешу
сертификата, а второй локальный экземпляр блокируется хранилищем.
- [ ] Tray, кнопки сопряжения/отзыва, автозапуск и упаковка Windows.
Не заменять mDNS рассылкой секретов. Объявления сети не являются доказательством
подлинности ПК: проверять сохранённый отпечаток TLS перед отправкой токена.
- [ ] Подготовить правила брандмауэра для частной сети, без автоматического открытия
портов сейчас. HTTPS использует выбранный TCP-порт, mDNS — UDP 5353.
## Порядок подключения будущего нативного клиента
1. Считать QR внутри приложения, проверить схему/версию, размер payload,
HTTPS-адрес, отсутствие userinfo/параметров, формат отпечатка/кода и срок.
2. Проверить TLS по отпечатку из QR **до** отправки POST `/v1/pair`.
3. Сохранить токен и отпечаток в Keychain; не сохранять код как постоянный секрет.
1. Считать QR внутри приложения; проверить схему/версию, размер payload, HTTPS-адрес,
формат отпечатка/кода и срок. Не использовать Safari как клиент.
2. Сверить сертификат с отпечатком из QR до POST `/v1/pair`.
3. Сохранить токен и отпечаток в Keychain. Код сопряжения не является постоянным секретом.
4. Получить `/v1/info`, `/v1/state`, открыть WSS `/v1/events`.
5. При переподключении найти адрес по DNS-SD, сопоставить ID, проверить TLS;
при 401 запросить повторное сопряжение, не повторять команды автоматически.
5. При переподключении найти ПК по DNS-SD, сопоставить ID и снова проверить TLS.
При 401 запросить новое сопряжение; не повторять команды автоматически.
Схема `musicbridge://` пока не зарегистрирована на iPhone; Safari ничего делать
с ней не должен. Swift, Xcode-проект, установка и интерфейс iPhone отложены.
Схема `musicbridge://` пока не зарегистрирована на iPhone. Swift/Xcode-проект
и приложение ещё не создавались.
Реализация использует [QRCoder](https://github.com/Shane32/QRCoder) и
[Makaretu.Dns.Multicast](https://github.com/richardschneider/net-mdns).