2fa20da94d
- Main: license service, IPC, router; закрытие окон; yauzl закрытие zip (EMFILE), zipRead тест - Editor: стабильный projectState без мигания, логотип и меню, строки UI, LayoutShell overlay - Control: ластик для всех типов эффектов, затухание/нарастание музыки при смене сцены - Сборка: vite, build/dev scripts, obfuscate-main и build-env скрипты с тестами; package.json Made-with: Cursor
22 lines
3.1 KiB
Markdown
22 lines
3.1 KiB
Markdown
# Спецификация лицензирования DNDGamePlayer (этап D1)
|
||
|
||
Документ фиксирует модель **D1**: онлайн-активация, срок, число устройств, отзыв, и как это согласуется с клиентом и сервером лицензий.
|
||
|
||
Исходный код сервера вынесен в отдельный репозиторий: [DndGamePlayerLicenseServer](https://git.mailib.ru/ifontosh/DndGamePlayerLicenseServer.git).
|
||
|
||
## Модель
|
||
|
||
1. **Продуктовый ключ** — секрет покупателя, известен только ему и серверу. Обменивается на **лицензионный токен** через `POST /v1/activate` (онлайн-активация).
|
||
2. **Лицензионный токен** — публичная полезная нагрузка (`sub`, `pid`, `iat`, `exp`, `did`) + подпись **Ed25519**. Клиент хранит только токен и **публичный** ключ (вшит в приложение); подделать валидный токен без приватного ключа сервера невозможно.
|
||
3. **Срок** — поле `exp` (unix секунды). Клиент отклоняет истёкший токен без сети.
|
||
4. **Устройства** — поле `did` в токене: при активации сервер привязывает токен к `deviceId` клиента и ведёт учёт списка устройств на `sub` в `data.json` (`maxDevices`).
|
||
5. **Отзыв** — сервер помечает `sub` в `revokedSubs`. Клиент при наличии `DND_LICENSE_STATUS_URL` запрашивает `GET /v1/status?sub=…`; при `revoked: true` лицензия считается недействительной **без обновления** приложения. Офлайн до истечения `exp` отозванный токен формально криптографически валиден — это осознанный компромисс; при необходимости сокращайте срок жизни токена или добавляйте принудительную онлайн-проверку перед критичными действиями.
|
||
|
||
## Хранение на клиенте
|
||
|
||
Токен не хранится открытым текстом в JSON userData: используется **Electron `safeStorage`** (на macOS — связка с Keychain, на Windows — DPAPI). Идентификатор устройства — отдельный файл `device.id` (не секрет). Принятие EULA — `preferences.json` (версия текста).
|
||
|
||
## Юридическое (D9)
|
||
|
||
Текст EULA в приложении (`app/renderer/legal/eulaRu.ts`) и формулировки про активацию/отзыв/устройства. Перед первым вводом ключа пользователь принимает EULA (версия `EULA_CURRENT_VERSION` в `app/shared/license/eulaVersion.ts`).
|