Перейти к содержимому
getnextpdf.com

Enterprise редакция

Licensing — глубокий справочник

Эта страница — глубокий справочник по поверхности лицензирования NextPDF Enterprise, модулю, который разрешает все остальные возможности Enterprise. Она охватывает модель состояний прав (EntitlementEvaluator, EntitlementStatus, EntitlementResult), навязываемое закрытие возможностей (FeatureGate, CapabilityCode, CapabilityRegistry), машину навязывания канала с двумя таймерами (ChannelEnforcementPolicy, OnlineCheckScheduler) и подписанный онлайн-клиент (LicenseClient). Обычная оценка прав не требует сети. Онлайн-клиент существует для явных операций активации, контрольного сигнала, деактивации, онлайн-проверки и зондирования продления. Детали внутреннего механизма остаются во внутренней документации исходного репозитория и вне области действия этого руководства.

Эта возможность поставляется в NextPDF Enterprise (nextpdf/enterprise) и активируется лицензионным конвертом уровня Enterprise. Развёртывание без этого права не загружает классы возможности. Сравнить редакции и получить лицензию.

Лицензирование — это базовая поверхность Enterprise. Она всегда присутствует, как только пакет Enterprise установлен рядом с пакетом Core, потому что именно эта поверхность разрешает всё остальное. У NextPDF Pro нет отдельной поверхности прав; модель состояний, машина навязывания и онлайн-клиент поставляются только в nextpdf/enterprise. У NextPDF Core (Apache-2.0) вообще нет модели прав — хост, которому нужно нелицензированное поведение Apache-2.0, использует движок Core напрямую, а не конвейер Enterprise.

Все типы находятся в NextPDF\Enterprise\Licensing. Машина навязывания расположена в подпространстве имён Channel, компоновка runtime — в Runtime, а типы подписанного статуса — в Online.

СимволПараметрыПоведение по умолчаниюВозвращаетБросает или проваливается сПримечания
EntitlementEvaluator::evaluate()?LicenseKey $license, ?DateTimeImmutable $now = nullСопоставляет проверенную лицензию (или null) с полным решением о правахEntitlementResultНетNull-лицензия даёт fail-closed-результат без лицензии
EntitlementEvaluator::evaluateEnforced()?LicenseKey $license, EnforcementOutcome $outcomeПреобразует заранее вычисленный исход навязывания в результат о правахEntitlementResultНетЭффективная редакция берётся из исхода; каждое понижение при навязывании приводит к Core
EntitlementEvaluator::resolveBrandingMode(), ::resolveBrandingStrategy()?LicenseKey $license, ?DateTimeImmutable $now = nullРазрешает решение о брендировании для генерируемого выводаBrandingMode / BrandingStrategyНетЕдинственная инстанция брендирования; водяной знак ставит только канал ознакомления
EntitlementResultОбъект-значение только для чтенияНесёт статус, редакцию, канал, режим брендирования, флаги runtime/обновлений/поддержки и необязательное предупреждениеНетХелперы: isFullyActive(), isExpired(), isDowngradedToCore(), shouldApplyEvaluationBranding()
EntitlementStatusПеречисление на основе строкActive, GracePeriod, DowngradedToCore, EvaluationExpired, NoLicenseНетPerpetualFallback сохранён, но устарел; оставлен только чтобы потребители до 6.0 всё ещё компилировались
FeatureGate::hasCapability()CapabilityCode $capabilityПроверяет возможность против навязываемой эффективной редакции и состояния пакетовboolНетFail-closed до core при любой ошибке резолвера
FeatureGate::requireCapability()CapabilityCode $capabilityМолча пропускает или бросает со структурированным контекстом апсейлаvoidSpectrumAuthenticationException SPEC-LIC-001 (не лицензировано) или SPEC-LIC-002 (пакет истёк)Контекст несёт required_capability, required_pack, current_packs, upgrade_info_url
FeatureGate::isFeatureEnabled(), ::requireFeature()string $featureУстаревшая проверка по идентификатору функцииbool / voidSpectrumAuthenticationException SPEC-AUTH-007 (путь require)Обратная совместимость; предпочитайте проверки возможностей
Аксессоры FeatureGateНетИнтроспекция лицензииРазноеНетcurrentEdition(), isLicenseValid(), isInGracePeriod(), getActivePacks(), trialPolicy()
CapabilityCodeПеречисление на основе строкКанонические идентификаторы возможностей (core.*, pro.*, enterprise.*, pack.*)НетisPack(), packName(), minimumEdition(), forEdition()
CapabilityRegistryLicenseKey, шаблоны маршрутовРазрешение «маршрут → возможность» и поиск пакета до диспетчеризацииРазноеНетregisterDefaultRoutes() охватывает задокументированные маршруты служб
LicenseKeyОбъект-значение только для чтенияРазобранные, проверенные утверждения лицензииНетisExpired(), isInGracePeriod(), isFullyExpired(), hasFeature(), hasCapability(), activePackNames(); maxSlots только договорной
LicenseValidator::buildVerifiedLicenseKey()array $dataСтроит типизированный LicenseKey из уже проверенной нагрузкиLicenseKeySpectrumAuthenticationException SPEC-AUTH-001 при нарушении схемыПоддерживает схемы 2.0, 1.0 и устаревшие нагрузки
PackDefinition / PackRegistryОбъекты-значения только для чтенияСостояние пакета дополнений с независимым истечением и льготным периодомРазноеНетisActive(), isFullyExpired(), activePacks(), activeCapabilities()
TrialPolicybool $enabled, int $maxPagesPerSecond = 2, поля водяного знакаПолитика ограничения пропускной способности пробного режимаНетfromLicenseKey(), disabled(), isThrottled(); полномочия брендирования остаются у оценщика
ChannelEnforcementPolicy::enforce()LicenseKey $license, LocalState $state, int $systemNow, bool $revoked = falseЗапускает машину с двумя таймерами плюс отзыв и переобозначение пробного режимаEnforcementOutcomeНетОтзыв перекрывает каждый таймер и состояние пробного режима
OnlineCheckScheduler::evaluate(), ::recordSuccessfulOnlineCheck()Лицензия, локальное состояние, отметки времениОценка двух таймеров; продление аренды по проверенному серверному времениEnforcementOutcome / LocalStateНетONLINE_GRACE_SECONDS даёт 48 часов льготы жизнеспособности сверх аренды
EnforcementDecision / EnforcementReason / EnforcementOutcomeПеречисления + объект-значение только для чтенияActive, Grace, DowngradedToCore плюс точная причинаНетКаждая причина детерминированно отображается в одно решение
Runtime\EntitlementResolver::currentEntitlement()НетИнтерфейс: навязываемое право, которое обслуживает runtimeEntitlementResultОпределяется реализациейEnforcedEntitlementResolver компонует кэш, состояние, политику и оценщик, fail-closed до Core
LicenseStateCache::get(), ::getOrThrow()bool $forceRefresh = falseКэш проверенной лицензии, обеспечивающий работу гейта?LicenseKeygetOrThrow(): SpectrumAuthenticationException SPEC-AUTH-008; LicenseConfigurationException при неверной проводкеinvalidate(), isCacheValid()
LicenseClient::activate(), ::heartbeat(), ::deactivate(), ::verifyOnline()string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = nullОдин обмен подписанным статусом; ответ проверяется против закреплённого корня и привязан к отправленному nonceStatusResponseLicenseClientException (транспорт, не-200, неверный поданный nonce); SpectrumAuthenticationException (подделанный, изменённый, устаревший, с неверным nonce, неверной лицензией, неверным типом ответа)Отправляется только солёный хеш отпечатка, никогда сырой отпечаток
LicenseClient::checkRenewal()string $licenseId, string $customerIdЗондирование доступности продления; 404 — нормальный ответ «нет доступных»Массив продления (available, download_url, expires_at)LicenseClientException (недостижимо, не-200/404 или отклонённый политикой download_url)URL в неподписанном теле проверяется на SSRF, прежде чем сможет выйти наружу
LicenseClient::__construct()См. блок с сигнатуройПроверяет транспорт, схему URL и набор закреплений при конструированииLicenseConfigurationException (транспорт без навязывания политики, недопустимая схема, простой HTTP без закреплений, некорректный набор закреплений)getPinSet() раскрывает активный набор закреплений для инструментов ротации
Online\StatusResponseОбъект-значение только для чтенияПроверенный подписанный статусНетisLive() равен false при revoked / expired / released; несёт leaseExpiresAt, счётчики мест и снимок прав
LicenseChannelMode / OnlineMode / OnlinePolicyПеречисления + объект-значение только для чтенияУтверждения канала и онлайн-политикиНетsigned_source против ioncube; онлайн-режим required / optional / disabled с intervalDays и leaseDays
LicenseEditionПеречисление на основе строкCore, Pro, EnterpriseНетsatisfies() реализует иерархию уровней
public function __construct(private ?EvaluationBrandingConfig $evaluationBrandingConfig = null)
public function evaluate(?LicenseKey $license, ?DateTimeImmutable $now = null): EntitlementResult
public function evaluateEnforced(?LicenseKey $license, EnforcementOutcome $outcome): EntitlementResult
public function resolveBrandingMode(?LicenseKey $license, ?DateTimeImmutable $now = null): BrandingMode
public function resolveBrandingStrategy(?LicenseKey $license, ?DateTimeImmutable $now = null): BrandingStrategy
public function __construct(private readonly LicenseStateCache $licenseCache, private readonly EntitlementResolver $entitlementResolver, private readonly string $upgradeInfoUrl = self::DEFAULT_UPGRADE_URL)
public function isFeatureEnabled(string $feature): bool
public function requireFeature(string $feature): void
public function currentEdition(): ?string
public function isLicenseValid(): bool
public function isInGracePeriod(): bool
public function hasCapability(CapabilityCode $capability): bool
public function requireCapability(CapabilityCode $capability): void
public function getActivePacks(): array
public function trialPolicy(): TrialPolicy
public function __construct(private readonly ClientInterface $httpClient, private readonly RequestFactoryInterface $requestFactory, private readonly StreamFactoryInterface $streamFactory, private readonly StatusX5cValidator $statusValidator, private readonly string $baseUrl = self::DEFAULT_BASE_URL, #[SensitiveParameter] private readonly ?string $apiKey = null, array $pinnedPublicKeys = [], array $backupPins = [], private readonly OutboundHttpPolicy $policy = new OutboundHttpPolicy(allowedSchemes: ['https'], connectTimeoutSeconds: 10, readTimeoutSeconds: 30, maxResponseBytes: 10_485_760, followRedirects: false, allowPrivateTargets: false, retryAttempts: 0, retryBaseBackoffMs: 250))
public function activate(string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = null): StatusResponse
public function heartbeat(string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = null): StatusResponse
public function deactivate(string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = null): StatusResponse
public function verifyOnline(string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = null): StatusResponse
public function getPinSet(): ?PinSet
public function checkRenewal(string $licenseId, string $customerId): array

Оценка прав производит одно из пяти текущих состояний, каждое с фиксированным следствием для runtime:

СтатусRuntimeЭффективные возможностиОбновления / поддержкаБрендирование
Activeразрешёнлицензированная редакция + активные пакетыда (платная); нет (ознакомление)нет (платная); водяной знак (ознакомление)
GracePeriodразрешёнлицензированная редакция + активные пакетыданет (платная)
DowngradedToCoreразрешёнтолько Coreнетнет (платная); водяной знак (пробный)
EvaluationExpiredограниченнетнетводяной знак
NoLicenseотключён (fail-closed)нетнетводяной знак
  • Истечение платной лицензии никогда не отключает установленный runtime. runtimeAllowed остаётся true для каждого платного состояния. За пределами окна льготного периода эффективная редакция понижается до Core: возможности Core продолжают работать бессрочно, все возможности Pro/Enterprise/пакетов закрываются, а обновления и поддержка отзываются. Устаревший случай EntitlementStatus::PerpetualFallback называет политику истечения до 6.0 и существует только для совместимости компиляции.
  • Не каждое состояние заканчивается исполнением на уровне Core. Льготный период сохраняет полную лицензированную редакцию с датированным предупреждением о продлении. Истечение ознакомления ограничивает runtime и сохраняет водяной знак. Состояние без лицензии отключает пути Enterprise по принципу fail-closed и заметно помечает водяным знаком любой унаследованный вывод, поэтому его никогда нельзя принять за платное исполнение.
  • Фиксированный порядок разрешения. Полностью истёкшая лицензия не разрешает ни одной возможности. Возможности пакетов откладываются до собственного активного состояния и независимого истечения пакета. Возможности редакции разрешаются против навязываемой эффективной редакции по строгой иерархии Enterprise ⊇ Pro ⊇ Core. Сырое LicenseKey::$edition никогда не используется для закрытия.
  • Два таймера; побеждает самый строгий. Таймер прав (оба канала) управляет Active, Grace и понижением до Core за пределами льготного периода. Таймер онлайн-жизнеспособности применяется только к каналу ioncube с онлайн-режимом required: аренда плюс 48-часовая льгота жизнеспособности должны быть действующими. В офлайне за пределами аренды premium приостанавливается на уровне Core; более поздняя проверенная онлайн-проверка восстанавливает аренду, и premium возобновляется. У канала signed_source — и у любого необязательного онлайн-режима — нет таймера жизнеспособности, и он остаётся офлайн- и air-gap-способным.
  • Противодействие откату детерминировано. Навязывание оценивается против монотонного пола: эффективное время — это максимум системных часов и последнего проверенного времени, поэтому перевод часов назад не даёт лишнего времени. Откат, превышающий допуск расхождения и оставшийся льготный период, принудительно вызывает понижение до Core.
  • Аренда продвигается только по доверенному времени. Успешная онлайн-проверка записывает проверенное, подписанное серверное время, а не локальные часы, поэтому локальный скачок часов вперёд не может раздуть аренду.
  • У брендирования одна инстанция. Водяной знак включает только канал ознакомления. Платная лицензия разрешается без брендирования в каждом состоянии, включая понижённые.
  • Пробный режим — это слой политики поверх тех же таймеров. Пропускная способность ограничена (по умолчанию 2 страницы/секунду), применяется ознакомительный водяной знак, а истечение строгое, без льготного периода. Меняется только сообщаемая причина; решение и эффективная редакция следуют платной машине.
  • Онлайн-контракт подписан от начала до конца. Каждый запрос несёт CSPRNG-nonce клиента. Каждый ответ — это компактный EdDSA JWS с медиатипом application/nextpdf-status+jwt, проверяемый по цепочке x5c до вкомпилированного закреплённого корня и привязанный к отправленному nonce, идентификатору установленной лицензии и вызванной конечной точке. Унаследованный транспорт неподписанного конверта выведен из эксплуатации; остаётся ровно один путь доверия. Настроенные SPKI-закрепления передаются в заголовке X-NextPDF-Pinned-Public-Key, и набор закреплений должен включать резервное закрепление.
  • Нет навязывания числа мест во время выполнения. maxSlots только договорной — нет телеметрии и обязательного отзвона для обычной работы.
  • Проверка возможности на полностью истёкшей лицензии замыкается на «недоступно» до запуска любой логики пакета или редакции.
  • Пакет дополнений может истечь, пока базовая лицензия активна. Отказ тогда читается как «пакет истёк» (SPEC-LIC-002), а не «не лицензировано» (SPEC-LIC-001), и перечисляет текущие активные пакеты.
  • Локальный файл состояния навязывания, который присутствует, но нечитаем или неразбираем, — это сигнал вмешательства. Машина проваливается закрыто до понижения Core с EnforcementReason::CorruptState. Законно отсутствующий файл не считается повреждённым и обрабатывается нормально.
  • Откат часов ниже монотонного пола, превышающий допуск расхождения (по умолчанию 120 секунд) и оставшийся льготный период, детерминированно вызывает понижение до Core.
  • Истёкшая аренда жизнеспособности понижает в остальном Active-лицензию ioncube; истечение прав понижает независимо от состояния аренды.
  • evaluate(null) работает по принципу fail-closed: runtime запрещён, применяется водяной знак, а предупреждение называет URL с ценами. Хосты, которым нужно нелицензированное поведение Core, должны конструировать движок Core напрямую.
  • У истёкшей ознакомительной лицензии нет ни льготного периода, ни резервного режима; runtime ограничен, и водяной знак остаётся.
  • checkRenewal() трактует HTTP 404 как нормальный ответ «нет доступных». Любой другой не-200 поднимает LicenseClientException, а download_url, нарушающий исходящую политику, проваливается закрыто, прежде чем сможет покинуть метод.
  • Подделанный, изменённый, устаревший, с неверным nonce или неверной лицензией статус-ответ никогда не даёт StatusResponse; проверка бросает SpectrumAuthenticationException. Подписанный, но revoked, expired или released статус проходит проверку и всплывает как сигнал понижения (isLive() равен false).
  • Статус-ответ, выпущенный для другого обмена, отклоняется: проверенный response_type должен совпадать с вызванной конечной точкой.
  • FeatureGate проваливается закрыто при любой ошибке резолвера: эффективная редакция деградирует до core, и ни одна premium-возможность не предоставляется.
  • EnforcedEntitlementResolver работает по принципу fail-closed от начала до конца: любое исключение в его цепочке даёт результат без лицензии (Core) и запись ошибки PSR-3, никогда не premium-предоставление.

Слой лицензирования не добавляет собственной криптографической политики. Подписи лицензии и статуса — это проверки Ed25519, выполняемые криптопровайдером хоста. В FIPS-ограниченной сборке алгоритм, который провайдер не одобряет, проваливается на криптографической границе с явной ошибкой; ничто не понижается молча. Это утверждения о возможностях кода NextPDF: NextPDF не является валидированным криптографическим модулем, не имеет сертификации и не предоставляет её.

УтверждениеСтандартПункт
Файлы лицензий и статус-ответы — это JWS компактной сериализации, проверяемые по принципу fail-closed.RFC 7515§3.1
Подписи лицензии и статуса — Ed25519.RFC 8032§5.1
Цепочка x5c в подписанном ответе валидируется обратно до вкомпилированного закреплённого якоря доверия.RFC 5280§6.1
Настроенный набор SPKI-закреплений должен включать резервное закрепление для ещё не развёрнутого ключа.RFC 7469§4.3
Проверенные утверждения (iss, aud, exp, nbf, iat) — зарегистрированные имена утверждений.RFC 7519§4.1

Все пункты пересказаны; нормативный текст не воспроизводится. NextPDF не делает заявления о сертификации. Поддержка не равна соответствию, а соответствие не равно сертификации. Модуль согласует своё поведение с процитированными пунктами как возможность; принятие лицензионного или статусного конверта решает собственный верификатор NextPDF с закреплённым корнем, а не внешняя инстанция.

  • Конструируйте LicenseClient с транспортом, навязывающим политику (канонически SecurityAwareHttpClient). Сырой PSR-18-клиент отклоняется при конструировании, чтобы лицензионный трафик никогда нельзя было отправить без средств контроля anti-SSRF, без перенаправлений, с ограничением байтов и тайм-аутами.
  • Поданный вызывающим клиентский nonce должен декодироваться минимум в 16 байт энтропии. Исходный код обосновывает эту границу в RFC 8555 §6.5; этот пункт вне процитированного корпуса, поэтому граница указана здесь только по исходному коду продукта.
  • Закрывайте функции через FeatureGate; никогда не ветвитесь по сырому LicenseKey::$edition. Гейт обращается только к навязываемой эффективной редакции и проваливается закрыто до core.
  • Не переключайтесь по устаревшему EntitlementStatus::PerpetualFallback в новом коде. Вместо этого проверяйте isDowngradedToCore() или сопоставляйте DowngradedToCore.
  • Трактуйте отказ в возможности как полезную нагрузку для устранения. Выводите её структурированный контекст и URL обновления вызывающему, а не сворачивайте до общей ошибки.
  • Этот модуль касается криптографической функциональности; трактуйте его как чувствительный к безопасности в собственной проверке. Условия по ёмкости и местам регулируются лицензионным соглашением, а не навязыванием во время выполнения. Этот справочник не является юридическим заключением; обратитесь к собственным консультантам по соответствию и юридическим вопросам.

Эта страница документирует только внешне наблюдаемое поведение и поддерживаемую публичную поверхность API. Внутренние пути пространств имён, вспомогательные классы, таблицы механизмов, имена файлов руководств по эксплуатации и префиксы тикетов вне области действия.