# DndGamePlayerLicenseServer Сервис лицензирования для **DNDGamePlayer**: активация по продуктовому ключу, выдача подписанного токена Ed25519, отзыв по `sub` (клиент опрашивает `GET /v1/status`, если задан `DND_LICENSE_STATUS_URL` в Electron main). Репозиторий клиента: отдельный проект `dnd_player` — публичный ключ вшит в `app/shared/license/bundledPublicKey.ts` и должен соответствовать `LICENSE_PRIVATE_KEY_PEM` здесь. ## Переменные окружения | Переменная | Описание | |------------|----------| | `LICENSE_PRIVATE_KEY_PEM` | Приватный ключ Ed25519 в PEM (PKCS#8), **обязательно** | | `LICENSE_ADMIN_TOKEN` | Bearer-токен для `/v1/admin/*` (по умолчанию `change-me-admin`) | | `DND_LICENSE_DATA_PATH` | Путь к `data.json` (по умолчанию `./data.json` в корне репозитория) | | `PORT` | Порт (по умолчанию `3847`) | ## Подготовка 1. Скопируйте `data.example.json` → `data.json`. 2. Сгенерируйте пару Ed25519; **публичный** ключ (SPKI DER base64) вставьте в клиент в `bundledPublicKey.ts`. ```bash node -e "const c=require('crypto');const kp=c.generateKeyPairSync('ed25519');console.log(kp.privateKey.export({type:'pkcs8',format:'pem'}));" ``` ### Демо-ключ (только для разработки) Публичный ключ по умолчанию в клиенте соответствует этому приватному PEM: ``` -----BEGIN PRIVATE KEY----- MC4CAQAwBQYDK2VwBCIEIDNxA9U1VSG9zoOvcJ5uB+JUe25UD5m9UwMi6slXzW44 -----END PRIVATE KEY----- ``` ## Запуск ```bash npm start ``` На Windows перед запуском задайте переменную окружения `LICENSE_PRIVATE_KEY_PEM` (многострочное значение в кавычках или через `.env` и загрузчик по желанию). ## API - `POST /v1/activate` — `{ "productKey": "...", "deviceId": "..." }` → `{ token, sub }`. - `GET /v1/status?sub=...` → `{ revoked: boolean }`. - `POST /v1/admin/revoke` — `Authorization: Bearer `, тело `{ "sub": "..." }`. - `POST /v1/admin/issue` — админская выдача (`sub`, `pid`, `iat`, `exp`, `did`). - `GET /health` — `{ ok: true }`. ## Клиент `DND_LICENSE_STATUS_URL=http://localhost:3847/` (база URL для сборки пути `v1/status`).