Files
DndGamePlayer/docs/licensing-spec.md
T
2026-04-19 23:22:05 +08:00

3.9 KiB
Raw Blame History

Спецификация лицензирования DNDGamePlayer (этап D1)

Документ фиксирует модель D1: онлайн-активация, срок, число устройств, отзыв, и как это согласуется с клиентом и сервером лицензий.

Исходный код сервера вынесен в отдельный репозиторий: DndGamePlayerLicenseServer.

Модель

  1. Продуктовый ключ — секрет покупателя, известен только ему и серверу. Обменивается на лицензионный токен через POST /v1/activate (онлайн-активация). В поле «Указать ключ» приложение принимает продуктовый ключ DND-… (клиент сам вызывает POST /v1/activate с deviceId) или уже готовый токен (две части base64url через одну точку).
  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 отозванный токен формально криптографически валиден — это осознанный компромисс; при необходимости сокращайте срок жизни токена или добавляйте принудительную онлайн-проверку перед критичными действиями.

Продакшен-сборка

Скрипт npm run build / node scripts/build.mjs --production подставляет в main-бандл базовый URL https://license.mailib.ru/ как process.env.DND_LICENSE_STATUS_URL (если при сборке переменная не задана). Другой хост: DND_LICENSE_STATUS_URL=https://example.com npm run build. В dev по-прежнему можно выставить переменную окружения при запуске Electron без пересборки.

Хранение на клиенте

Токен не хранится открытым текстом в 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).