콘텐츠로 이동
getnextpdf.com

Enterprise 에디션

Licensing — 심층 참조

이 페이지는 NextPDF Enterprise 라이선싱 표면 — 다른 모든 Enterprise 기능을 해석하는 모듈 — 에 대한 심층 참조입니다. 사용 권한 상태 모델(EntitlementEvaluator, EntitlementStatus, EntitlementResult), 시행되는 기능 게이팅(FeatureGate, CapabilityCode, CapabilityRegistry), 두 타이머 채널 시행 머신(ChannelEnforcementPolicy, OnlineCheckScheduler), 서명된 온라인 클라이언트(LicenseClient)를 다룹니다. 일반적인 사용 권한 평가에는 네트워크가 필요 없습니다. 온라인 클라이언트는 명시적 activate, heartbeat, deactivate, verify-online, 갱신 프로브 연산을 위해 존재합니다. 내부 메커니즘 세부 사항은 소스 저장소의 내부 문서에 남으며 이 매뉴얼의 범위 밖입니다.

이 기능은 NextPDF Enterprise(nextpdf/enterprise)에 포함되며 Enterprise 등급 라이선스 봉투로 활성화됩니다. 해당 사용 권한이 없는 배포는 이 기능의 클래스를 로드하지 않습니다. 에디션 비교 및 라이선스 받기.

Licensing은 기본 Enterprise 표면입니다. 다른 모든 것을 해석하는 표면이므로, Enterprise 패키지가 Core 패키지 옆에 설치되면 항상 존재합니다. NextPDF Pro에는 별도의 사용 권한 표면이 없습니다. 상태 모델, 시행 머신, 온라인 클라이언트는 nextpdf/enterprise에만 포함됩니다. NextPDF Core(Apache-2.0)에는 사용 권한 모델이 전혀 없습니다 — 라이선스가 없는 Apache-2.0 동작이 필요한 호스트는 Enterprise 파이프라인이 아니라 Core 엔진을 직접 사용합니다.

모든 타입은 NextPDF\Enterprise\Licensing 아래에 있습니다. 시행 머신은 Channel 하위 네임스페이스에, 런타임 구성은 Runtime에, 서명 상태 타입은 Online에 있습니다.

심볼매개변수기본 동작반환예외 또는 실패비고
EntitlementEvaluator::evaluate()?LicenseKey $license, ?DateTimeImmutable $now = null검증된 라이선스(또는 null)를 전체 사용 권한 결정으로 매핑합니다EntitlementResult없음null 라이선스는 실패-차단 no-license 결과를 산출합니다
EntitlementEvaluator::evaluateEnforced()?LicenseKey $license, EnforcementOutcome $outcome미리 계산된 시행 결과를 사용 권한 결과로 변환합니다EntitlementResult없음유효 에디션은 결과에서 나옵니다. 모든 시행 격하는 Core로 귀결됩니다
EntitlementEvaluator::resolveBrandingMode(), ::resolveBrandingStrategy()?LicenseKey $license, ?DateTimeImmutable $now = null생성 출력의 브랜딩 결정을 해석합니다BrandingMode / BrandingStrategy없음유일한 브랜딩 권한. 평가 채널만 워터마크를 적용합니다
EntitlementResult읽기 전용 값 객체상태, 에디션, 채널, 브랜딩 모드, 런타임/업데이트/지원 플래그, 선택적 경고를 담습니다없음헬퍼: isFullyActive(), isExpired(), isDowngradedToCore(), shouldApplyEvaluationBranding()
EntitlementStatus문자열 기반 열거형Active, GracePeriod, DowngradedToCore, EvaluationExpired, NoLicense없음PerpetualFallback은 유지되지만 폐기 예정입니다. 6.0 이전 소비자가 여전히 컴파일되도록 유지될 뿐입니다
FeatureGate::hasCapability()CapabilityCode $capability시행되는 유효 에디션과 팩 상태에 대해 기능을 검사합니다bool없음리졸버 오류 시 core로 실패-차단합니다
FeatureGate::requireCapability()CapabilityCode $capability조용히 통과하거나 구조화된 업셀 컨텍스트와 함께 예외를 던집니다voidSpectrumAuthenticationException SPEC-LIC-001(not licensed) 또는 SPEC-LIC-002(pack expired)컨텍스트는 required_capability, required_pack, current_packs, upgrade_info_url을 담습니다
FeatureGate::isFeatureEnabled(), ::requireFeature()string $feature레거시 기능 식별자 검사bool / voidSpectrumAuthenticationException SPEC-AUTH-007(require 경로)레거시 호환성. 기능(capability) 검사를 선호하십시오
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를 빌드합니다LicenseKey스키마 위반 시 SpectrumAuthenticationException 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()없음인터페이스: 런타임이 제공하는 시행된 사용 권한EntitlementResult구현 정의EnforcedEntitlementResolver는 캐시, 상태, 정책, 평가기를 구성하며 Core로 실패-차단합니다
LicenseStateCache::get(), ::getOrThrow()bool $forceRefresh = false게이트를 뒷받침하는 검증된 라이선스 캐시?LicenseKeygetOrThrow(): SpectrumAuthenticationException SPEC-AUTH-008; 잘못된 연결 시 LicenseConfigurationExceptioninvalidate(), isCacheValid()
LicenseClient::activate(), ::heartbeat(), ::deactivate(), ::verifyOnline()string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = null하나의 서명된 상태 교환. 응답은 고정된 루트에 대해 검증되고 전송된 nonce에 바인딩됩니다StatusResponseLicenseClientException(전송, 비-200, 잘못된 제공 nonce); SpectrumAuthenticationException(위조, 변조, 오래됨, 잘못된 nonce, 잘못된 라이선스, 잘못된 타입 응답)솔트된 지문 해시만 전송되며, 원시 지문은 결코 전송되지 않습니다
LicenseClient::checkRenewal()string $licenseId, string $customerId갱신 가용성 프로브. 404는 정상적인 “none available” 응답입니다갱신 배열 (available, download_url, expires_at)LicenseClientException(도달 불가, 비-200/404, 또는 정책 거부된 download_url)미서명 본문의 URL은 벗어나기 전에 SSRF 검사됩니다
LicenseClient::__construct()시그니처 펜스 참조생성 시 전송, URL 스킴, 핀 세트를 검증합니다LicenseConfigurationException(정책 미시행 전송, 허용되지 않는 스킴, 핀 없는 평문 HTTP, 잘못된 핀 세트)getPinSet()은 회전 도구를 위해 활성 핀 세트를 노출합니다
Online\StatusResponse읽기 전용 값 객체검증된 서명 상태없음isLive()revoked / expired / released에서 false입니다. leaseExpiresAt, 슬롯 수, 사용 권한 스냅샷을 담습니다
LicenseChannelMode / OnlineMode / OnlinePolicy열거형 + 읽기 전용 값 객체채널 및 온라인 정책 클레임없음signed_sourceioncube. intervalDaysleaseDays를 갖는 온라인 모드 required / optional / disabled
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

사용 권한 평가는 다섯 가지 현재 상태 중 하나를 산출하며, 각각 고정된 런타임 결과를 가집니다.

상태런타임유효 기능업데이트 / 지원브랜딩
Active허용사용 권한 에디션 + 활성 팩예(유료), 아니요(평가)없음(유료), 워터마크(평가)
GracePeriod허용사용 권한 에디션 + 활성 팩없음(유료)
DowngradedToCore허용Core만아니요없음(유료), 워터마크(평가판)
EvaluationExpired제한됨없음아니요워터마크
NoLicense비활성(실패-차단)없음아니요워터마크
  • 유료 만료는 결코 설치된 런타임을 비활성화하지 않습니다. runtimeAllowed는 모든 유료 상태에서 true를 유지합니다. 유예 기간을 지나면 유효 에디션이 Core로 격하됩니다: Core 기능은 무기한 계속 실행되고, 모든 Pro/Enterprise/pack 기능은 게이트 오프되며, 업데이트와 지원은 철회됩니다. 폐기 예정인 EntitlementStatus::PerpetualFallback 케이스는 6.0 이전 만료 정책을 명명하며 컴파일 호환성을 위해서만 존재합니다.
  • 모든 상태가 Core 실행으로 끝나는 것은 아닙니다. Grace는 날짜가 명시된 갱신 경고와 함께 전체 사용 권한 에디션을 유지합니다. 평가 만료는 런타임을 제한하고 워터마크를 유지합니다. no-license 상태는 Enterprise 경로를 실패-차단으로 비활성화하고 모든 레거시 출력에 가시적으로 워터마크를 표시하므로, 결코 유료 실행으로 통과할 수 없습니다.
  • 고정된 해석 순서. 완전히 만료된 라이선스는 어떤 기능도 해석하지 않습니다. 팩 기능은 팩 자체의 활성 상태와 독립적 만료로 미룹니다. 에디션 기능은 엄격한 계층 Enterprise ⊇ Pro ⊇ Core에서 시행되는 유효 에디션에 대해 해석됩니다. 게이팅을 위해 원시 LicenseKey::$edition은 결코 참조되지 않습니다.
  • 두 타이머 중 가장 제한적인 것이 우선합니다. 사용 권한 타이머(양 채널)는 Active, Grace, 유예 이후 Core 격하를 구동합니다. 온라인 활성 타이머는 온라인 모드가 requiredioncube 채널에만 적용됩니다: 리스에 48시간 활성 유예를 더한 것이 유효해야 합니다. 리스를 지나 오프라인이면 프리미엄은 Core 등급에서 일시 정지하고, 이후 검증된 온라인 검사가 리스를 재수립하면 프리미엄이 재개됩니다. signed_source 채널 — 및 required가 아닌 모든 온라인 모드 — 에는 활성 타이머가 없으며 오프라인 및 에어갭 상태를 유지할 수 있습니다.
  • 롤백 방지는 결정론적입니다. 시행은 단조 하한에 대해 평가합니다: 유효 시간은 시스템 시계와 마지막 검증 시간의 최댓값이므로, 뒤로 가는 시계 변경은 추가 시간을 부여하지 않습니다. 편차 허용 오차와 남은 유예를 초과하는 롤백은 Core 격하를 강제합니다.
  • 리스는 신뢰된 시간으로만 전진합니다. 성공한 온라인 검사는 로컬 시계가 아니라 검증된 서명 서버 시간을 기록하므로, 로컬 시계를 앞으로 점프해도 리스를 부풀릴 수 없습니다.
  • 브랜딩에는 하나의 권한이 있습니다. 평가 채널만 워터마크를 트리거합니다. 유료 라이선스는 격하된 상태를 포함한 모든 상태에서 브랜딩 없음으로 해석됩니다.
  • 평가판은 동일한 타이머 위의 정책 계층입니다. 처리량이 상한 제한되고(기본 2 pages/second), 평가 워터마크가 적용되며, 만료는 유예 없이 엄격합니다. 보고되는 사유만 바뀌며, 결정과 유효 에디션은 유료 머신을 따릅니다.
  • 온라인 계약은 종단 간 서명됩니다. 각 요청은 CSPRNG 클라이언트 nonce를 담습니다. 각 응답은 미디어 타입 application/nextpdf-status+jwt의 compact EdDSA JWS이며, x5c 체인을 통해 컴파일된 고정 루트까지 검증되고 전송된 nonce, 설치된 라이선스 id, 호출된 엔드포인트에 바인딩됩니다. 레거시 미서명 봉투 전송은 폐기되었으며, 정확히 하나의 신뢰 경로만 남습니다. 구성된 SPKI 핀은 X-NextPDF-Pinned-Public-Key 헤더로 전달되며, 핀 세트는 백업 핀을 포함해야 합니다.
  • 런타임 좌석 시행 없음. maxSlots는 계약상으로만 의미가 있습니다 — 일반 운영을 위한 텔레메트리나 의무적 phone-home이 없습니다.
  • 완전히 만료된 라이선스에 대한 기능 검사는 어떤 팩이나 에디션 로직이 실행되기 전에 “unavailable”로 단락됩니다.
  • 기본 라이선스가 활성인 동안 애드온 팩이 만료될 수 있습니다. 그러면 거부는 not-licensed(SPEC-LIC-001)가 아니라 pack expired(SPEC-LIC-002)로 읽히며, 현재 활성 팩을 나열합니다.
  • 존재하지만 읽을 수 없거나 파싱할 수 없는 로컬 시행 상태 파일은 변조 신호입니다. 머신은 EnforcementReason::CorruptState와 함께 Core 격하로 실패-차단합니다. 정당하게 부재한 파일은 손상이 아니며 정상적으로 진행됩니다.
  • 편차 허용 오차(기본 120초)와 남은 유예를 초과하며 단조 하한 아래로 내려가는 시계 롤백은 Core 격하를 결정론적으로 강제합니다.
  • 만료된 활성 리스는 그 외에는 Active인 ioncube 라이선스를 격하시킵니다. 사용 권한 만료는 리스 상태와 무관하게 격하합니다.
  • evaluate(null)은 실패-차단입니다: 런타임이 허용되지 않고, 워터마크가 적용되며, 경고가 가격 URL을 명시합니다. 라이선스가 없는 Core 동작이 필요한 호스트는 Core 엔진을 직접 구성해야 합니다.
  • 만료된 평가 라이선스에는 유예도 폴백도 없습니다. 런타임이 제한되고 워터마크가 유지됩니다.
  • checkRenewal()은 HTTP 404를 정상적인 “none available” 응답으로 취급합니다. 그 외의 비-200은 LicenseClientException을 발생시키고, 아웃바운드 정책을 위반하는 download_url은 메서드를 벗어나기 전에 실패-차단됩니다.
  • 위조, 변조, 오래됨, 잘못된 nonce, 또는 잘못된 라이선스 상태 응답은 결코 StatusResponse를 산출하지 않습니다. 검증은 SpectrumAuthenticationException을 던집니다. 서명되었지만 revoked, expired, 또는 released인 상태는 검증되어 격하 신호로 드러납니다(isLive()는 false).
  • 다른 교환을 위해 발행된 상태 응답은 거부됩니다: 검증된 response_type은 호출된 엔드포인트와 일치해야 합니다.
  • FeatureGate는 모든 리졸버 오류에서 실패-차단합니다: 유효 에디션이 core로 격하되고 어떤 프리미엄 기능도 부여되지 않습니다.
  • EnforcedEntitlementResolver는 종단 간 실패-차단입니다: 그 체인의 모든 예외는 no-license(Core) 결과와 PSR-3 오류 로그를 산출하며, 결코 프리미엄 부여를 산출하지 않습니다.

라이선싱 계층은 자체 암호 정책을 추가하지 않습니다. 라이선스와 상태 서명은 호스트 암호 제공자가 수행하는 Ed25519 검증입니다. FIPS 제약 빌드에서, 제공자가 승인하지 않는 알고리즘은 명시적 오류와 함께 암호 경계에서 실패하며, 어떤 것도 조용히 격하되지 않습니다. 이는 NextPDF 코드에 대한 기능 주장입니다: NextPDF는 검증된 암호 모듈이 아니며, 어떤 인증도 보유하지 않고, 어떤 인증도 부여하지 않습니다.

주장표준
라이선스 파일과 상태 응답은 compact-serialization JWS이며 실패-차단으로 검증됩니다.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 자체의 고정 루트 검증기에 의해 결정됩니다.

  • 정책을 시행하는 전송(정규적으로 SecurityAwareHttpClient)으로 LicenseClient를 구성하십시오. 원시 PSR-18 클라이언트는 생성 시 거부되므로, 라이선스 트래픽은 anti-SSRF, 리디렉션 없음, 바이트 상한, 시간 초과 제어 없이는 결코 전송될 수 없습니다.
  • 호출자가 제공하는 클라이언트 nonce는 최소 16바이트의 엔트로피로 디코딩되어야 합니다. 소스는 이 한계를 RFC 8555 §6.5에 근거합니다. 그 절은 인용된 코퍼스 밖에 있으므로, 여기서 그 한계는 제품 소스로부터만 명시됩니다.
  • FeatureGate를 통해 기능을 게이트하십시오. 원시 LicenseKey::$edition으로 결코 분기하지 마십시오. 게이트는 시행되는 유효 에디션만 참조하며 core로 실패-차단합니다.
  • 새 코드에서 폐기 예정인 EntitlementStatus::PerpetualFallback으로 switch하지 마십시오. 대신 isDowngradedToCore()를 테스트하거나 DowngradedToCore를 매치하십시오.
  • 기능 거부를 해결 페이로드로 취급하십시오. 일반 오류로 축소하지 말고 구조화된 컨텍스트와 업그레이드 URL을 호출자에게 노출하십시오.
  • 이 모듈은 암호 기능과 관련되므로, 자체 검토에서 보안 민감 사항으로 취급하십시오. 용량 및 좌석 약관은 런타임 시행이 아니라 라이선스 계약에 의해 관장됩니다. 이 참조는 법률 의견이 아닙니다. 자체 규정 준수 및 법률 자문에게 문의하십시오.

이 페이지는 외부에서 관찰 가능한 동작과 지원되는 공개 API 표면만을 문서화합니다. 내부 네임스페이스 경로, 헬퍼 클래스, 메커니즘 표, 런북 파일명, 티켓 접두사는 범위 밖입니다.