# CertifiEd.Client Клиентский SDK для [CertifiEd](https://git.ofarandagon.tj/Ofarandagon/CertifiEd) — self-hosted платформы лицензирования on-prem ПО от [Ofarandagon](https://ofarandagon.tj). SDK проверяет лицензию **локально** по публичному ключу Ed25519: приложение работает без связи с сервером до 30 дней, а конфигурация (feature-флаги и лимиты) читается из самого подписанного токена — подделать нельзя. ## Установка ```bash dotnet add package CertifiEd.Client ``` ## Быстрый старт ```csharp using CertifiEd.Client; await using var license = new CertifiEdLicenseClient(new CertifiEdClientOptions { ServerUrl = "https://api.licensing.example.com", LicenseFilePath = "license.ced", // выданный клиенту файл PublicKey = Convert.FromHexString(publicKeyHex), // 32 байта Ed25519 }); if (!await license.InitializeAsync()) { Console.Error.WriteLine("Лицензия отсутствует, повреждена, подделана или истекла."); return 1; } if (license.Status is not (CertifiEdLicenseStatus.Active or CertifiEdLicenseStatus.GracePeriod)) return 1; if (license.HasFeature("reports.export")) EnableReportExport(); var seats = license.GetConfig("limits.maxSeats") ?? 1; ``` `InitializeAsync` загружает токен, **офлайн** проверяет подпись Ed25519 и срок, затем (best-effort) активируется на сервере и запускает фоновый heartbeat. Отсутствие сети не роняет приложение. Публичный ключ выдаёт панель или API: `GET /api/v1/client/public-key/{licenseKey}` (hex → `Convert.FromHexString`). Ключ безопасно зашивать в приложение. ## API | Член | Назначение | |---|---| | `InitializeAsync(ct)` | Загрузка + офлайн-проверка подписи, активация, старт heartbeat. `false` — лицензия невалидна | | `Status` | `Active` · `GracePeriod` · `Expired` · `Invalid` · `Revoked` | | `HasFeature(name)` | Флаг из массива `features` подписанного конфига | | `GetConfig(path)` | Значение по dotted-path, напр. `"limits.maxSeats"` | | `DisposeAsync()` | Best-effort деактивация (освобождает место) и остановка таймера. Идемпотентен | ### Опции | Опция | Описание | |---|---| | `ServerUrl` | Базовый URL сервера CertifiEd | | `LicenseFilePath` | Путь к `.ced` (голый токен или скачанный JSON-конверт) | | `PublicKey` | Сырые 32 байта публичного ключа Ed25519 | | `HwFingerprint` | Переопределить отпечаток железа (по умолчанию вычисляется автоматически) | ## Офлайн-режим После каждого успешного heartbeat сервер возвращает подписанный маркер; SDK кэширует его рядом с файлом лицензии (`license.ced.hb`). Перезапуски без сети остаются лицензированными, пока маркер жив (до `maxOfflineDays`, максимум 30). Далее — `GracePeriod`, затем `Expired`. Рекомендация: не блокируйте работу при первом же сбое сети — ориентируйтесь на `Status`, а не на факт ответа сервера. ## Привязка к железу Лицензия может быть привязана к машине по аппаратному отпечатку. Отпечаток вычисляется автоматически (`HwFingerprint.Get()`), при необходимости переопределяется через `CertifiEdClientOptions.HwFingerprint` — например, если у вас своя стабильная идентификация узла. Если лицензия привязана к другой машине, активация вернёт ошибку несовпадения отпечатка. Перепривязка (замена оборудования) выполняется на стороне платформы оператором или администратором тенанта. ## Обработка ошибок - `InitializeAsync` возвращает `false` — файла нет, токен повреждён/подделан или срок истёк. Не бросает при недоступном сервере. - Сетевые сбои и таймауты внутри активации/heartbeat проглатываются осознанно — работает офлайн-окно. - Проверяйте `Status` перед выдачей платной функциональности, а не только результат `InitializeAsync`. ## Документация Полная документация — в [`docs/`](https://git.ofarandagon.tj/Ofarandagon/CertifiEd) репозитория: протокол лицензирования, справочник API, webhooks и руководство по SDK. Рабочий пример — `examples/CertifiEd.QuickStart`. --- © Ofarandagon, 2026. SDK распространяется по лицензии MIT.