Bỏ qua để đến nội dung
getnextpdf.com

Enterprise phiên bản

Licensing — Tài liệu tham chiếu chuyên sâu

Trang này là tài liệu tham chiếu chuyên sâu cho bề mặt licensing của NextPDF Enterprise — module phân giải mọi capability Enterprise khác. Nó bao quát mô hình trạng thái quyền sử dụng (EntitlementEvaluator, EntitlementStatus, EntitlementResult), việc kiểm soát capability được thực thi (FeatureGate, CapabilityCode, CapabilityRegistry), máy thực thi kênh hai bộ đếm thời gian (ChannelEnforcementPolicy, OnlineCheckScheduler), và client trực tuyến đã ký (LicenseClient). Việc đánh giá quyền sử dụng thông thường không cần mạng. Client trực tuyến tồn tại cho các thao tác rõ ràng: activate, heartbeat, deactivate, verify-online, và thăm dò gia hạn. Chi tiết cơ chế nội bộ nằm trong tài liệu nội bộ của kho nguồn và ngoài phạm vi của cẩm nang này.

Capability này đi kèm trong NextPDF Enterprise (nextpdf/enterprise) và kích hoạt bằng một license envelope bậc Enterprise. Một triển khai không có quyền sử dụng đó sẽ không nạp các lớp của capability. So sánh các phiên bản và lấy giấy phép.

Licensing là một bề mặt Enterprise nền tảng. Nó luôn hiện diện một khi gói Enterprise được cài đặt cạnh gói Core, vì nó là bề mặt phân giải mọi thứ khác. NextPDF Pro không có bề mặt quyền sử dụng riêng; mô hình trạng thái, máy thực thi, và client trực tuyến chỉ đi kèm trong nextpdf/enterprise. NextPDF Core (Apache-2.0) hoàn toàn không có mô hình quyền sử dụng — một host cần hành vi Apache-2.0 không cấp phép thì dùng engine Core trực tiếp, không phải quy trình Enterprise.

Mọi kiểu đều nằm dưới NextPDF\Enterprise\Licensing. Máy thực thi nằm trong sub-namespace Channel, thành phần runtime trong Runtime, và các kiểu trạng thái đã ký trong Online.

Ký hiệuTham sốHành vi mặc địnhTrả vềNém hoặc thất bại vớiGhi chú
EntitlementEvaluator::evaluate()?LicenseKey $license, ?DateTimeImmutable $now = nullÁnh xạ một giấy phép đã xác minh (hoặc null) sang quyết định quyền sử dụng đầy đủEntitlementResultKhôngMột giấy phép null cho ra kết quả no-license fail-closed
EntitlementEvaluator::evaluateEnforced()?LicenseKey $license, EnforcementOutcome $outcomeChuyển một kết cục thực thi đã tính sẵn thành một kết quả quyền sử dụngEntitlementResultKhôngPhiên bản hiệu lực đến từ kết cục; mọi lần hạ cấp thực thi đều rơi về Core
EntitlementEvaluator::resolveBrandingMode(), ::resolveBrandingStrategy()?LicenseKey $license, ?DateTimeImmutable $now = nullPhân giải quyết định branding cho đầu ra được tạo raBrandingMode / BrandingStrategyKhôngThẩm quyền branding duy nhất; chỉ kênh đánh giá mới đóng hình mờ
EntitlementResultValue object chỉ đọcMang theo trạng thái, phiên bản, kênh, chế độ branding, các cờ runtime/cập nhật/hỗ trợ, và một cảnh báo tùy chọnKhôngTrợ giúp: isFullyActive(), isExpired(), isDowngradedToCore(), shouldApplyEvaluationBranding()
EntitlementStatusEnum nền chuỗiActive, GracePeriod, DowngradedToCore, EvaluationExpired, NoLicenseKhôngPerpetualFallback được giữ lại nhưng đã lỗi thời; chỉ giữ để các consumer trước 6.0 vẫn biên dịch được
FeatureGate::hasCapability()CapabilityCode $capabilityKiểm tra capability so với phiên bản hiệu lực được thực thi và trạng thái góiboolKhôngFail-closed về core khi có bất kỳ lỗi resolver nào
FeatureGate::requireCapability()CapabilityCode $capabilityVượt qua âm thầm hoặc ném kèm bối cảnh upsell có cấu trúcvoidSpectrumAuthenticationException SPEC-LIC-001 (chưa cấp phép) hoặc SPEC-LIC-002 (gói hết hạn)Bối cảnh mang theo required_capability, required_pack, current_packs, upgrade_info_url
FeatureGate::isFeatureEnabled(), ::requireFeature()string $featureKiểm tra định danh feature kế thừabool / voidSpectrumAuthenticationException SPEC-AUTH-007 (đường require)Tương thích kế thừa; ưu tiên kiểm tra capability
FeatureGate accessorsKhôngNội quan giấy phépTùyKhôngcurrentEdition(), isLicenseValid(), isInGracePeriod(), getActivePacks(), trialPolicy()
CapabilityCodeEnum nền chuỗiCác định danh capability chuẩn tắc (core.*, pro.*, enterprise.*, pack.*)KhôngisPack(), packName(), minimumEdition(), forEdition()
CapabilityRegistryLicenseKey, các mẫu routePhân giải route-to-capability và tra cứu gói trước khi dispatchTùyKhôngregisterDefaultRoutes() bao quát các route dịch vụ đã được tài liệu hóa
LicenseKeyValue object chỉ đọcCác claim giấy phép đã phân tích và xác minhKhôngisExpired(), isInGracePeriod(), isFullyExpired(), hasFeature(), hasCapability(), activePackNames(); maxSlots chỉ mang tính hợp đồng
LicenseValidator::buildVerifiedLicenseKey()array $dataDựng một LicenseKey có kiểu từ một payload đã được xác minhLicenseKeySpectrumAuthenticationException SPEC-AUTH-001 khi vi phạm schemaHỗ trợ schema 2.0, 1.0, và các payload kế thừa
PackDefinition / PackRegistryCác value object chỉ đọcTrạng thái gói bổ trợ với thời hạn và ân hạn độc lậpTùyKhôngisActive(), isFullyExpired(), activePacks(), activeCapabilities()
TrialPolicybool $enabled, int $maxPagesPerSecond = 2, các trường hình mờChính sách giới hạn thông lượng dùng thửKhôngfromLicenseKey(), disabled(), isThrottled(); thẩm quyền branding vẫn thuộc bộ đánh giá
ChannelEnforcementPolicy::enforce()LicenseKey $license, LocalState $state, int $systemNow, bool $revoked = falseChạy máy hai bộ đếm thời gian cộng với thu hồi và gắn nhãn lại dùng thửEnforcementOutcomeKhôngViệc thu hồi ghi đè mọi bộ đếm thời gian và trạng thái dùng thử
OnlineCheckScheduler::evaluate(), ::recordSuccessfulOnlineCheck()Giấy phép, trạng thái cục bộ, các dấu thời gianĐánh giá hai bộ đếm thời gian; gia hạn lease từ thời gian máy chủ đã xác minhEnforcementOutcome / LocalStateKhôngONLINE_GRACE_SECONDS cấp 48 giờ ân hạn liveness sau khi lease hết
EnforcementDecision / EnforcementReason / EnforcementOutcomeCác enum + value object chỉ đọcActive, Grace, DowngradedToCore cộng với lý do chính xácKhôngMỗi lý do ánh xạ tất định tới một quyết định
Runtime\EntitlementResolver::currentEntitlement()KhôngInterface: quyền sử dụng được thực thi mà runtime phục vụEntitlementResultDo hiện thực quy địnhEnforcedEntitlementResolver kết hợp cache, state, policy, và evaluator, fail-closed về Core
LicenseStateCache::get(), ::getOrThrow()bool $forceRefresh = falseCache giấy phép đã xác minh làm nền cho gate?LicenseKeygetOrThrow(): SpectrumAuthenticationException SPEC-AUTH-008; LicenseConfigurationException khi đấu nối không hợp lệinvalidate(), isCacheValid()
LicenseClient::activate(), ::heartbeat(), ::deactivate(), ::verifyOnline()string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = nullMột lần trao đổi trạng thái đã ký; phản hồi được xác minh so với pinned root và ràng buộc với nonce đã gửiStatusResponseLicenseClientException (transport, không phải 200, nonce cung cấp sai); SpectrumAuthenticationException (phản hồi giả mạo, bị can thiệp, cũ, sai nonce, sai giấy phép, sai kiểu)Chỉ hash fingerprint đã salt mới được gửi, không bao giờ gửi fingerprint thô
LicenseClient::checkRenewal()string $licenseId, string $customerIdThăm dò khả dụng gia hạn; 404 là câu trả lời “none available” bình thườngMảng gia hạn (available, download_url, expires_at)LicenseClientException (không truy cập được, không phải 200/404, hoặc download_url bị chính sách từ chối)URL trong body không ký được sàng lọc SSRF trước khi có thể thoát ra
LicenseClient::__construct()Xem khối chữ kýXác thực transport, scheme URL, và pin set khi khởi tạoLicenseConfigurationException (transport không thực thi chính sách, scheme không được phép, HTTP thuần không có pin, pin set dị dạng)getPinSet() hiển thị pin set đang hoạt động cho công cụ xoay vòng
Online\StatusResponseValue object chỉ đọcTrạng thái đã ký đã xác minhKhôngisLive() là false với revoked / expired / released; mang theo leaseExpiresAt, số lượng slot, và một ảnh chụp quyền sử dụng
LicenseChannelMode / OnlineMode / OnlinePolicyCác enum + value object chỉ đọcCác claim về kênh và chính sách trực tuyếnKhôngsigned_source so với ioncube; chế độ trực tuyến required / optional / disabled với intervalDaysleaseDays
LicenseEditionEnum nền chuỗiCore, Pro, EnterpriseKhôngsatisfies() hiện thực phân cấp bậc
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

Việc đánh giá quyền sử dụng tạo ra một trong năm trạng thái hiện tại, mỗi trạng thái kèm một hệ quả runtime cố định:

Trạng tháiRuntimeCapability hiệu lựcCập nhật / hỗ trợBranding
Activecho phépphiên bản được cấp quyền + các gói đang hoạt độngcó (trả phí); không (đánh giá)không có (trả phí); hình mờ (đánh giá)
GracePeriodcho phépphiên bản được cấp quyền + các gói đang hoạt độngkhông có (trả phí)
DowngradedToCorecho phépchỉ Corekhôngkhông có (trả phí); hình mờ (dùng thử)
EvaluationExpiredhạn chếkhông cókhônghình mờ
NoLicensevô hiệu hóa (fail-closed)không cókhônghình mờ
  • Việc hết hạn trả phí không bao giờ vô hiệu hóa runtime đã cài đặt. runtimeAllowed vẫn là true với mọi trạng thái trả phí. Sau cửa sổ ân hạn, phiên bản hiệu lực hạ cấp về Core: các capability Core tiếp tục chạy vô thời hạn, mọi capability Pro/Enterprise/gói bị kiểm soát tắt, và cập nhật và hỗ trợ bị thu hồi. Case đã lỗi thời EntitlementStatus::PerpetualFallback đặt tên cho chính sách hết hạn trước 6.0 và chỉ tồn tại để tương thích biên dịch.
  • Không phải trạng thái nào cũng kết thúc ở việc thực thi Core. Ân hạn giữ nguyên phiên bản được cấp quyền đầy đủ kèm một cảnh báo gia hạn có ghi ngày. Việc hết hạn đánh giá hạn chế runtime và giữ hình mờ. Trạng thái no-license vô hiệu hóa các đường Enterprise theo fail-closed và đóng hình mờ hiển thị rõ lên mọi đầu ra kế thừa, nên nó không bao giờ có thể bị nhầm thành một lần thực thi trả phí.
  • Thứ tự phân giải cố định. Một giấy phép đã hết hạn hoàn toàn không phân giải capability nào. Các capability gói nhường cho trạng thái hoạt động và thời hạn độc lập của riêng gói. Các capability phiên bản phân giải so với phiên bản hiệu lực được thực thi theo phân cấp chặt Enterprise ⊇ Pro ⊇ Core. LicenseKey::$edition thô không bao giờ được tham chiếu để kiểm soát.
  • Hai bộ đếm thời gian; cái hạn chế nhất thắng. Bộ đếm quyền sử dụng (cả hai kênh) điều khiển Active, Grace, và việc hạ cấp Core sau ân hạn. Bộ đếm liveness trực tuyến chỉ áp dụng cho kênh ioncube với chế độ trực tuyến required: lease, cộng thêm 48 giờ ân hạn liveness, phải còn sống. Ngoại tuyến sau khi lease hết, premium tạm dừng ở bậc Core; một lần kiểm tra trực tuyến đã xác minh sau đó tái lập lease và premium tiếp tục. Kênh signed_source — và bất kỳ chế độ trực tuyến không-required nào — không có bộ đếm liveness và vẫn ngoại tuyến và có khả năng air-gap.
  • Chống lùi thời gian là tất định. Việc thực thi đánh giá so với một sàn đơn điệu: thời gian hiệu lực là giá trị lớn nhất giữa đồng hồ hệ thống và thời gian đã xác minh gần nhất, nên một thay đổi đồng hồ về sau không cấp thêm thời gian. Một lần lùi vượt quá dung sai lệch và phần ân hạn còn lại buộc hạ cấp Core.
  • Lease chỉ tiến theo thời gian đáng tin cậy. Một lần kiểm tra trực tuyến thành công ghi lại thời gian máy chủ đã ký và đã xác minh, không bao giờ ghi đồng hồ cục bộ, nên một cú nhảy đồng hồ cục bộ về phía trước không thể thổi phồng lease.
  • Branding có một thẩm quyền duy nhất. Chỉ kênh đánh giá mới kích hoạt hình mờ. Một giấy phép trả phí phân giải thành không có branding ở mọi trạng thái, kể cả các trạng thái đã hạ cấp.
  • Dùng thử là một lớp chính sách trên cùng các bộ đếm thời gian đó. Thông lượng bị giới hạn (mặc định 2 trang/giây), hình mờ đánh giá được áp dụng, và việc hết hạn là nghiêm ngặt không có ân hạn. Chỉ lý do được báo cáo thay đổi; quyết định và phiên bản hiệu lực đi theo máy trả phí.
  • Hợp đồng trực tuyến được ký đầu-cuối. Mỗi yêu cầu mang theo một client nonce CSPRNG. Mỗi phản hồi là một JWS EdDSA compact có media type application/nextpdf-status+jwt, được xác minh qua một chuỗi x5c tới một pinned root biên dịch sẵn và ràng buộc với nonce đã gửi, id giấy phép đã cài đặt, và endpoint được gọi. Transport envelope không ký kế thừa đã bị loại bỏ; đúng một đường tin cậy còn lại. Các pin SPKI được cấu hình đi trong header X-NextPDF-Pinned-Public-Key, và một pin set phải bao gồm một backup pin.
  • Không thực thi số ghế tại runtime. maxSlots chỉ mang tính hợp đồng — không có telemetry và không có phone-home bắt buộc cho hoạt động thông thường.
  • Một lần kiểm tra capability trên một giấy phép đã hết hạn hoàn toàn rẽ tắt thành “unavailable” trước khi bất kỳ logic gói hay phiên bản nào chạy.
  • Một gói bổ trợ có thể hết hạn trong khi giấy phép nền tảng đang hoạt động. Việc từ chối khi đó đọc là gói hết hạn (SPEC-LIC-002), không phải chưa cấp phép (SPEC-LIC-001), và liệt kê các gói đang hoạt động hiện tại.
  • Một tệp trạng thái thực thi cục bộ hiện diện nhưng không đọc được hoặc không phân tích được là một tín hiệu can thiệp. Máy fail-closed về hạ cấp Core với EnforcementReason::CorruptState. Một tệp vắng mặt một cách hợp lệ thì không hỏng và tiếp tục bình thường.
  • Một lần lùi đồng hồ xuống dưới sàn đơn điệu, vượt quá dung sai lệch (mặc định 120 giây) và phần ân hạn còn lại, buộc hạ cấp Core một cách tất định.
  • Một lease liveness đã hết hạ cấp một giấy phép ioncube vốn đang Active; việc hết hạn quyền sử dụng hạ cấp bất kể trạng thái lease.
  • evaluate(null) là fail-closed: runtime bị cấm, hình mờ được áp dụng, và cảnh báo nêu tên URL bảng giá. Các host cần hành vi Core không cấp phép phải dựng engine Core trực tiếp.
  • Một giấy phép đánh giá đã hết hạn không có ân hạn và không có dự phòng; runtime bị hạn chế và hình mờ vẫn còn.
  • checkRenewal() coi HTTP 404 là câu trả lời “none available” bình thường. Bất kỳ non-200 nào khác đều ném LicenseClientException, và một download_url vi phạm chính sách ra ngoài sẽ fail-closed trước khi có thể thoát khỏi phương thức.
  • Một phản hồi trạng thái giả mạo, bị can thiệp, cũ, sai nonce, hoặc sai giấy phép không bao giờ cho ra một StatusResponse; việc xác minh ném SpectrumAuthenticationException. Một trạng thái đã ký nhưng revoked, expired, hoặc released thì xác minh được và hiện lên như một tín hiệu hạ cấp (isLive() là false).
  • Một phản hồi trạng thái được đúc cho một lần trao đổi khác sẽ bị từ chối: response_type đã xác minh phải khớp với endpoint được gọi.
  • FeatureGate fail-closed khi có bất kỳ lỗi resolver nào: phiên bản hiệu lực suy giảm về core và không capability premium nào được cấp.
  • EnforcedEntitlementResolver là fail-closed đầu-cuối: bất kỳ ngoại lệ nào trong chuỗi của nó đều cho ra kết quả no-license (Core) và một log lỗi PSR-3, không bao giờ cấp premium.

Lớp licensing không thêm chính sách mật mã nào của riêng nó. Chữ ký giấy phép và trạng thái là các phép xác minh Ed25519 do host crypto provider thực hiện. Trong một build bị ràng buộc FIPS, một thuật toán mà provider không phê duyệt sẽ thất bại tại ranh giới mật mã với một lỗi rõ ràng; không có gì âm thầm hạ cấp. Đây là các tuyên bố về khả năng của mã NextPDF: NextPDF không phải là một module mật mã đã được thẩm định, không nắm giữ chứng nhận nào, và không cấp chứng nhận nào.

Tuyên bốTiêu chuẩnĐiều khoản
Các tệp giấy phép và phản hồi trạng thái là JWS compact-serialization, được xác minh fail-closed.RFC 7515§3.1
Chữ ký giấy phép và trạng thái là Ed25519.RFC 8032§5.1
Chuỗi x5c trong một phản hồi đã ký xác thực ngược về một trust anchor được ghim biên dịch sẵn.RFC 5280§6.1
Một pin set SPKI được cấu hình phải bao gồm một backup pin cho một key chưa được triển khai.RFC 7469§4.3
Các claim đã xác minh (iss, aud, exp, nbf, iat) là các registered claim name.RFC 7519§4.1

Mọi điều khoản đều được diễn giải lại; không có văn bản quy phạm nào được tái hiện. NextPDF không đưa ra tuyên bố chứng nhận nào. Hỗ trợ không đồng nghĩa với phù hợp, và phù hợp không đồng nghĩa với chứng nhận. Module căn chỉnh hành vi của nó theo các điều khoản được trích dẫn như một khả năng; việc chấp nhận một license hay status envelope do bộ xác minh pinned-root của riêng NextPDF quyết định, không phải do một cơ quan bên ngoài.

  • Dựng LicenseClient với một transport thực thi chính sách (chuẩn tắc là SecurityAwareHttpClient). Một client PSR-18 thô bị từ chối khi khởi tạo để lưu lượng giấy phép không bao giờ có thể được gửi mà thiếu các kiểm soát chống SSRF, không redirect, giới hạn byte, và timeout.
  • Một client nonce do bên gọi cung cấp phải giải mã ra ít nhất 16 byte entropy. Mã nguồn căn cứ giới hạn này vào RFC 8555 §6.5; điều khoản đó nằm ngoài kho được trích dẫn, nên giới hạn ở đây chỉ được nêu từ mã nguồn sản phẩm.
  • Kiểm soát các feature qua FeatureGate; không bao giờ rẽ nhánh trên LicenseKey::$edition thô. Gate chỉ tham chiếu phiên bản hiệu lực được thực thi và fail-closed về core.
  • Đừng switch trên case đã lỗi thời EntitlementStatus::PerpetualFallback trong mã mới. Thay vào đó hãy kiểm tra isDowngradedToCore() hoặc match DowngradedToCore.
  • Hãy coi việc từ chối capability như một payload khắc phục. Đưa bối cảnh có cấu trúc và URL nâng cấp của nó lên bên gọi thay vì rút gọn thành một lỗi chung chung.
  • Module này liên quan đến chức năng mật mã; hãy coi nó là nhạy cảm về bảo mật trong quá trình rà soát của riêng bạn. Các điều khoản về dung lượng và số ghế do thỏa thuận giấy phép quản lý, không phải do việc thực thi tại runtime. Tài liệu tham chiếu này không phải là một ý kiến pháp lý; hãy tham khảo các cố vấn tuân thủ và pháp lý của riêng bạn.

Trang này chỉ mô tả hành vi quan sát được từ bên ngoài và bề mặt API công khai được hỗ trợ. Các đường dẫn namespace nội bộ, các lớp trợ giúp, các bảng cơ chế, tên tệp runbook, và các tiền tố ticket nằm ngoài phạm vi.