# FluxDesk 0.3

Рабочий Windows-to-Windows прототип удалённого рабочего стола через интернет
или локальную сеть. Один `FluxDesk.exe` может предоставлять доступ к компьютеру
и подключаться к другому host.

## Что работает

- интернет-подключение без проброса портов через
  `wss://relay.nightlumen.com/v1/tunnel`;
- прямое LAN-подключение как отдельный резервный режим;
- end-to-end TLS внутри relay: сервер пересылает зашифрованные байты и не видит
  изображение, ввод или код подключения;
- 130-битный Internet ID, производный от скрытого 256-битного секрета host, и
  отдельный одноразовый восьмисимвольный код;
- ручная проверка SHA-256 fingerprint до отправки кода;
- захват основного монитора с настраиваемыми 10–60 FPS;
- быстрые JPEG-кадры при движении и lossless BGRA-тайлы для текста;
- слот «только последний кадр»: устаревшие кадры не накапливают задержку;
- удалённые мышь, колесо и клавиатура с аварийным отпусканием кнопок;
- независимые каналы видео и управления, heartbeat и bounded protocol limits;
- установщик Windows, portable-сборка и автоматические релизы из GitLab CI;
- встроенная проверка обновлений по подписанному RSA-PSS manifest с повторной
  проверкой размера и SHA-256 установщика перед запуском;
- полноэкранный viewer по `F11`.

## Установка и обновления

- Страница проекта: <https://nightlumen.com/fluxdesk/>
- Установщик: <https://downloads.nightlumen.com/fluxdesk/FluxDesk-setup.exe>
- Portable: <https://downloads.nightlumen.com/fluxdesk/FluxDesk-portable.zip>
- Контрольные суммы:
  <https://downloads.nightlumen.com/fluxdesk/SHA256SUMS.txt>

Установщик ставит FluxDesk только для текущего пользователя в
`%LOCALAPPDATA%\Programs\FluxDesk` и не требует прав администратора. Через две
секунды после открытия приложение в фоне проверяет
`https://downloads.nightlumen.com/fluxdesk/latest.json`. Доступное обновление
появляется в левой панели; перед установкой FluxDesk корректно завершает host и
viewer. Manifest подписан отдельным release-ключом, а приватная часть ключа
доступна только защищённым release jobs.

## Подключение через интернет

1. Установите FluxDesk либо распакуйте portable-сборку на оба компьютера с
   Windows 10/11 x64.
2. На удалённом компьютере оставьте включённым
   **Интернет через relay.nightlumen.com** и нажмите **Запустить доступ**.
3. Передайте управляющей стороне значения **Internet ID** и **Код**.
4. На управляющем компьютере оставьте режим **Интернет через relay**, введите
   Internet ID и код, затем нажмите **Подключиться**.
5. Сравните TLS SHA-256 fingerprint в обоих окнах и только затем подтвердите
   подключение.

Internet ID является случайным capability-идентификатором, криптографически
привязанным к скрытому секрету текущего запуска host. Код меняется после каждой
завершённой сессии. Ни одно из отображаемых значений не следует публиковать.

## Подключение по LAN

1. На viewer снимите флажок **Интернет через relay**.
2. Введите LAN IP, порт `45990` и код host.
3. Если Windows спросит о брандмауэре, разрешите FluxDesk только в нужном
   профиле сети.

## Сборка и тесты

Требуется .NET SDK 9 на Windows:

```powershell
dotnet build FluxDesk.sln -c Release
dotnet run --project tests/FluxDesk.SelfTest/FluxDesk.SelfTest.csproj -c Release
```

Набор включает девять core-тестов, четыре relay-теста и пять updater-тестов:
отклонение поддельной регистрации host, проверку digest-конфигурации и pilot
admission, локальный Kestrel WebSocket relay, два вложенных TLS-канала,
настоящий кадр захваченного экрана, проверку RSA-PSS manifest, запрет redirect,
проверку installer hash и состояния coordinator.

Тег `vX.Y.Z`, совпадающий с версией в `FluxDesk.csproj`, запускает защищённую
release pipeline: Windows runner собирает single-file EXE и Inno Setup,
формирует portable/source ZIP, `SHA256SUMS.txt` и подписанный `latest.json`;
deploy runner атомарно публикует их на `downloads.nightlumen.com`.

Для production-пилота bearer генерируется и остаётся на доверенной машине
сборки. Соберите EXE с bearer и вычислите verifier digest:

```powershell
$env:FluxDeskRelayAdmissionToken = '<same-private-pilot-token>'
$tokenBytes = [Text.Encoding]::UTF8.GetBytes($env:FluxDeskRelayAdmissionToken)
$admissionDigest = [Convert]::ToHexString(
  [Security.Cryptography.SHA256]::HashData($tokenBytes))
dotnet publish src/FluxDesk/FluxDesk.csproj -c Release -r win-x64 `
  --self-contained true -p:PublishSingleFile=true `
  -p:IncludeNativeLibrariesForSelfExtract=true
```

Передайте на relay-сервер только 64-символьное значение `$admissionDigest`.
Production Compose требует verifier, но не plaintext bearer:

```powershell
$env:FLUXDESK_RELAY_ADMISSION_TOKEN_SHA256 = '<64-hex-digest>'
docker compose -f deploy/relay/docker-compose.yml up -d --build
```

Без `FLUXDESK_RELAY_ADMISSION_TOKEN_SHA256` production Compose не запускается.
Bearer записан в `AssemblyMetadata` и может быть извлечён из EXE, поэтому это
только барьер приватного пилота от случайного/массового использования relay, а
не аутентификация учётной записи или полноценная авторизация. Не коммитьте
bearer или verifier в репозиторий и не публикуйте их. На сервере допустимо
хранить только verifier в закрытом root-only `.env`; plaintext bearer в
server-side `.env` храниться не должен.

## Архитектура

```text
Host capture → JPEG/lossless tiles → inner TLS ┐
                                               │ WSS/443
                                      claw relay
                                               │ WSS/443
Viewer canvas ← decode ← inner TLS ────────────┘

Viewer input → inner TLS control → relay → inner TLS → SendInput
```

Relay получает регистрационный секрет host и видит Internet ID, IP-адреса, роль,
тип канала, attempt ID, объём и тайминги трафика, а также метаданные рукопожатия
внутреннего TLS (в зависимости от согласованной версии TLS — возможно и
сертификат host). Секрет проверяется до регистрации и не сохраняется в комнате.
Relay не видит прикладное содержимое: изображение рабочего стола, команды ввода
и код подключения защищает отдельный внутренний TLS-сеанс непосредственно между
host и viewer. Подлинность host зависит от ручного сравнения SHA-256 fingerprint
на обеих сторонах.

Backend расположен в отдельном ASP.NET Core контейнере, слушает только
`127.0.0.1:8091` и публикуется Caddy через HTTPS 443. У него нет общей базы,
Redis или контейнеров с NightLumen Chat. Состояние комнат эфемерное.

Детали relay-протокола находятся в [docs/RELAY.md](docs/RELAY.md), а формат
внутреннего desktop-протокола — в [docs/PROTOCOL.md](docs/PROTOCOL.md).

## Текущие ограничения

- internet v0.3 всегда использует один relay-регион; автоматического direct P2P
  и бесшовного переключения пути пока нет;
- основной монитор, без выбора отдельного окна;
- нет звука, clipboard, файлов и unattended access;
- нет управления UAC secure desktop, экраном входа и `Ctrl+Alt+Del`;
- захват и JPEG пока CPU/GDI, а не GPU/H.264;
- TCP/WebSocket при потерях пакетов может кратковременно ожидать повторной
  передачи;
- один relay channel-pair имеет предельное время жизни 12 часов; для продолжения
  нужна новая сессия;
- сертификат временный и меняется при каждом запуске host;
- Windows EXE пока не подписан Authenticode-сертификатом.

Это пилотная интернет-версия для контролируемых сессий, а не агент постоянного
неконтролируемого доступа.

## Следующий производительный этап

1. `Windows.Graphics.Capture`/D3D11 и dirty regions без копирования через CPU.
2. BGRA → NV12 и аппаратный Media Foundation H.264/AV1 low-latency.
3. UDP/WebRTC или QUIC, ICE/STUN и direct P2P с relay fallback.
4. Адаптивные bitrate/FPS/quality по RTT, потерям и времени сетевой записи.
5. Измерение input-to-photon p50/p95 и реальной полосы `claw`.
