Enterprise edisi
Lisensi — Referensi Mendalam
Sekilas
Bagian berjudul “Sekilas”Halaman ini adalah referensi mendalam untuk permukaan licensing NextPDF Enterprise — modul yang menyelesaikan setiap kapabilitas Enterprise lainnya. Halaman ini mencakup model status entitlement (EntitlementEvaluator, EntitlementStatus, EntitlementResult), gating kapabilitas yang diberlakukan (FeatureGate, CapabilityCode, CapabilityRegistry), mesin enforcement channel dua-timer (ChannelEnforcementPolicy, OnlineCheckScheduler), dan klien online tertandatangani (LicenseClient). Evaluasi entitlement biasa tidak membutuhkan jaringan. Klien online ada untuk operasi activate, heartbeat, deactivate, verify-online, dan renewal-probe yang eksplisit. Detail mekanisme internal tetap berada di dokumentasi internal repositori sumber dan berada di luar cakupan manual ini.
Ketersediaan & lisensi
Bagian berjudul “Ketersediaan & lisensi”Kapabilitas ini dikirimkan dalam NextPDF Enterprise (nextpdf/enterprise) dan aktif dengan amplop lisensi tier Enterprise. Deployment tanpa entitlement tersebut tidak memuat kelas kapabilitas ini. Bandingkan edisi dan dapatkan lisensi.
Licensing adalah permukaan dasar Enterprise. Ia selalu hadir setelah paket Enterprise dipasang di samping paket Core, karena ia adalah permukaan yang menyelesaikan segala sesuatu yang lain. NextPDF Pro tidak memiliki permukaan entitlement terpisah; model status, mesin enforcement, dan klien online hanya dikirimkan dalam nextpdf/enterprise. NextPDF Core (Apache-2.0) sama sekali tidak memiliki model entitlement — host yang membutuhkan perilaku Apache-2.0 tak-berlisensi menggunakan engine Core secara langsung, bukan pipeline Enterprise.
Permukaan API publik
Bagian berjudul “Permukaan API publik”Semua tipe berada di bawah NextPDF\Enterprise\Licensing. Mesin enforcement berada di sub-namespace Channel, komposisi runtime di Runtime, dan tipe signed-status di Online.
| Simbol | Parameter | Perilaku default | Mengembalikan | Melempar atau gagal dengan | Catatan |
|---|---|---|---|---|---|
EntitlementEvaluator::evaluate() | ?LicenseKey $license, ?DateTimeImmutable $now = null | Memetakan lisensi terverifikasi (atau null) ke keputusan entitlement lengkap | EntitlementResult | Tidak ada | Lisensi null menghasilkan hasil no-license yang fail-closed |
EntitlementEvaluator::evaluateEnforced() | ?LicenseKey $license, EnforcementOutcome $outcome | Mengubah outcome enforcement yang telah dihitung sebelumnya menjadi hasil entitlement | EntitlementResult | Tidak ada | Edisi efektif berasal dari outcome; setiap penurunan enforcement mendarat di Core |
EntitlementEvaluator::resolveBrandingMode(), ::resolveBrandingStrategy() | ?LicenseKey $license, ?DateTimeImmutable $now = null | Menyelesaikan keputusan branding untuk output yang dihasilkan | BrandingMode / BrandingStrategy | Tidak ada | Satu-satunya otoritas branding; hanya channel evaluasi yang memberi watermark |
EntitlementResult | Objek nilai readonly | Membawa status, edisi, channel, mode branding, flag runtime/update/support, dan peringatan opsional | — | Tidak ada | Helper: isFullyActive(), isExpired(), isDowngradedToCore(), shouldApplyEvaluationBranding() |
EntitlementStatus | Enum berbasis string | Active, GracePeriod, DowngradedToCore, EvaluationExpired, NoLicense | — | Tidak ada | PerpetualFallback dipertahankan tetapi usang; disimpan hanya agar konsumen pra-6.0 tetap dapat dikompilasi |
FeatureGate::hasCapability() | CapabilityCode $capability | Memeriksa kapabilitas terhadap edisi efektif yang diberlakukan dan status pack | bool | Tidak ada | Fail-closed ke core pada kesalahan resolver apa pun |
FeatureGate::requireCapability() | CapabilityCode $capability | Lolos secara diam-diam atau melempar dengan konteks upsell terstruktur | void | SpectrumAuthenticationException SPEC-LIC-001 (tidak berlisensi) atau SPEC-LIC-002 (pack kedaluwarsa) | Konteks membawa required_capability, required_pack, current_packs, upgrade_info_url |
FeatureGate::isFeatureEnabled(), ::requireFeature() | string $feature | Pemeriksaan pengenal fitur legacy | bool / void | SpectrumAuthenticationException SPEC-AUTH-007 (jalur require) | Kompatibilitas legacy; utamakan pemeriksaan kapabilitas |
Accessor FeatureGate | Tidak ada | Introspeksi lisensi | Bervariasi | Tidak ada | currentEdition(), isLicenseValid(), isInGracePeriod(), getActivePacks(), trialPolicy() |
CapabilityCode | Enum berbasis string | Pengenal kapabilitas kanonik (core.*, pro.*, enterprise.*, pack.*) | — | Tidak ada | isPack(), packName(), minimumEdition(), forEdition() |
CapabilityRegistry | LicenseKey, pola rute | Resolusi rute-ke-kapabilitas dan pencarian pack sebelum dispatch | Bervariasi | Tidak ada | registerDefaultRoutes() mencakup rute layanan yang terdokumentasi |
LicenseKey | Objek nilai readonly | Klaim lisensi yang diurai dan terverifikasi | — | Tidak ada | isExpired(), isInGracePeriod(), isFullyExpired(), hasFeature(), hasCapability(), activePackNames(); maxSlots bersifat kontraktual saja |
LicenseValidator::buildVerifiedLicenseKey() | array $data | Membangun LicenseKey bertipe dari payload yang sudah terverifikasi | LicenseKey | SpectrumAuthenticationException SPEC-AUTH-001 pada pelanggaran skema | Mendukung skema 2.0, 1.0, dan payload legacy |
PackDefinition / PackRegistry | Objek nilai readonly | Status pack add-on dengan kedaluwarsa dan grace independen | Bervariasi | Tidak ada | isActive(), isFullyExpired(), activePacks(), activeCapabilities() |
TrialPolicy | bool $enabled, int $maxPagesPerSecond = 2, field watermark | Kebijakan batas throughput trial | — | Tidak ada | fromLicenseKey(), disabled(), isThrottled(); otoritas branding tetap pada evaluator |
ChannelEnforcementPolicy::enforce() | LicenseKey $license, LocalState $state, int $systemNow, bool $revoked = false | Menjalankan mesin dua-timer plus pencabutan dan pelabelan ulang trial | EnforcementOutcome | Tidak ada | Pencabutan menimpa setiap timer dan status trial |
OnlineCheckScheduler::evaluate(), ::recordSuccessfulOnlineCheck() | Lisensi, status lokal, timestamp | Evaluasi dua-timer; pembaruan lease dari waktu server terverifikasi | EnforcementOutcome / LocalState | Tidak ada | ONLINE_GRACE_SECONDS memberikan 48 jam grace liveness melewati lease |
EnforcementDecision / EnforcementReason / EnforcementOutcome | Enum + objek nilai readonly | Active, Grace, DowngradedToCore plus alasan yang presisi | — | Tidak ada | Setiap alasan memetakan secara deterministik ke satu keputusan |
Runtime\EntitlementResolver::currentEntitlement() | Tidak ada | Interface: entitlement yang diberlakukan yang dilayani runtime | EntitlementResult | Ditentukan oleh implementasi | EnforcedEntitlementResolver menyusun cache, state, policy, dan evaluator, fail-closed ke Core |
LicenseStateCache::get(), ::getOrThrow() | bool $forceRefresh = false | Cache lisensi terverifikasi yang mendukung gate | ?LicenseKey | getOrThrow(): SpectrumAuthenticationException SPEC-AUTH-008; LicenseConfigurationException pada wiring tidak valid | invalidate(), isCacheValid() |
LicenseClient::activate(), ::heartbeat(), ::deactivate(), ::verifyOnline() | string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = null | Satu pertukaran status-tertandatangani; respons diverifikasi terhadap root yang di-pin dan diikat ke nonce yang dikirim | StatusResponse | LicenseClientException (transport, non-200, nonce yang diberikan buruk); SpectrumAuthenticationException (respons dipalsukan, dirusak, basi, salah-nonce, salah-lisensi, salah-tipe) | Hanya hash fingerprint bergaram yang pernah dikirim, tidak pernah fingerprint mentah |
LicenseClient::checkRenewal() | string $licenseId, string $customerId | Probe ketersediaan pembaruan; 404 adalah jawaban “tidak ada yang tersedia” yang normal | Array pembaruan (available, download_url, expires_at) | LicenseClientException (tidak dapat dijangkau, non-200/404, atau download_url yang ditolak kebijakan) | URL badan tak-bertandatangan disaring SSRF sebelum dapat lolos |
LicenseClient::__construct() | Lihat pagar tanda tangan | Memvalidasi transport, skema URL, dan pin set saat konstruksi | — | LicenseConfigurationException (transport yang tidak menegakkan kebijakan, skema tidak diizinkan, HTTP biasa tanpa pin, pin set salah bentuk) | getPinSet() mengekspos pin set aktif untuk perkakas rotasi |
Online\StatusResponse | Objek nilai readonly | Status tertandatangani yang terverifikasi | — | Tidak ada | isLive() bernilai false pada revoked / expired / released; membawa leaseExpiresAt, jumlah slot, dan snapshot entitlement |
LicenseChannelMode / OnlineMode / OnlinePolicy | Enum + objek nilai readonly | Klaim channel dan kebijakan online | — | Tidak ada | signed_source vs ioncube; mode online required / optional / disabled dengan intervalDays dan leaseDays |
LicenseEdition | Enum berbasis string | Core, Pro, Enterprise | — | Tidak ada | satisfies() mengimplementasikan hierarki tier |
public function __construct(private ?EvaluationBrandingConfig $evaluationBrandingConfig = null)public function evaluate(?LicenseKey $license, ?DateTimeImmutable $now = null): EntitlementResultpublic function evaluateEnforced(?LicenseKey $license, EnforcementOutcome $outcome): EntitlementResultpublic function resolveBrandingMode(?LicenseKey $license, ?DateTimeImmutable $now = null): BrandingModepublic function resolveBrandingStrategy(?LicenseKey $license, ?DateTimeImmutable $now = null): BrandingStrategypublic function __construct(private readonly LicenseStateCache $licenseCache, private readonly EntitlementResolver $entitlementResolver, private readonly string $upgradeInfoUrl = self::DEFAULT_UPGRADE_URL)public function isFeatureEnabled(string $feature): boolpublic function requireFeature(string $feature): voidpublic function currentEdition(): ?stringpublic function isLicenseValid(): boolpublic function isInGracePeriod(): boolpublic function hasCapability(CapabilityCode $capability): boolpublic function requireCapability(CapabilityCode $capability): voidpublic function getActivePacks(): arraypublic function trialPolicy(): TrialPolicypublic 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): StatusResponsepublic function heartbeat(string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = null): StatusResponsepublic function deactivate(string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = null): StatusResponsepublic function verifyOnline(string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = null): StatusResponsepublic function getPinSet(): ?PinSetpublic function checkRenewal(string $licenseId, string $customerId): arrayKontrak perilaku
Bagian berjudul “Kontrak perilaku”Evaluasi entitlement menghasilkan salah satu dari lima status saat ini, masing-masing dengan konsekuensi runtime tetap:
| Status | Runtime | Kapabilitas efektif | Update / support | Branding |
|---|---|---|---|---|
Active | diizinkan | edisi berhak + pack aktif | ya (berbayar); tidak (evaluasi) | tidak ada (berbayar); watermark (evaluasi) |
GracePeriod | diizinkan | edisi berhak + pack aktif | ya | tidak ada (berbayar) |
DowngradedToCore | diizinkan | hanya Core | tidak | tidak ada (berbayar); watermark (trial) |
EvaluationExpired | dibatasi | tidak ada | tidak | watermark |
NoLicense | dinonaktifkan (fail-closed) | tidak ada | tidak | watermark |
- Kedaluwarsa berbayar tidak pernah menonaktifkan runtime yang terpasang.
runtimeAllowedtetap true untuk setiap status berbayar. Melewati jendela grace, edisi efektif turun ke Core: kapabilitas Core terus berjalan tanpa batas, semua kapabilitas Pro/Enterprise/pack digerbangi mati, dan update serta support dicabut. KasusEntitlementStatus::PerpetualFallbackyang usang menamai kebijakan kedaluwarsa pra-6.0 dan hanya ada untuk kompatibilitas kompilasi. - Tidak setiap status berakhir dalam eksekusi Core. Grace mempertahankan edisi berhak penuh dengan peringatan pembaruan bertanggal. Kedaluwarsa evaluasi membatasi runtime dan mempertahankan watermark. Status no-license menonaktifkan jalur Enterprise secara fail-closed dan memberi watermark terlihat pada output legacy apa pun, sehingga tidak pernah bisa lolos sebagai eksekusi berbayar.
- Urutan resolusi tetap. Lisensi yang sepenuhnya kedaluwarsa tidak menyelesaikan kapabilitas apa pun. Kapabilitas pack tunduk pada status aktif pack itu sendiri dan kedaluwarsa independennya. Kapabilitas edisi diselesaikan terhadap edisi efektif yang diberlakukan pada hierarki ketat Enterprise ⊇ Pro ⊇ Core.
LicenseKey::$editionmentah tidak pernah dikonsultasikan untuk gating. - Dua timer; yang paling membatasi menang. Timer entitlement (kedua channel) menggerakkan Active, Grace, dan penurunan Core pasca-grace. Timer liveness-online hanya berlaku pada channel
ioncubedengan mode onlinerequired: lease, plus grace liveness 48 jam, harus hidup. Offline melewati lease, premium berhenti di tier Core; pemeriksaan online terverifikasi berikutnya membangun kembali lease dan premium dilanjutkan. Channelsigned_source— dan mode online non-required apa pun — tidak memiliki timer liveness dan tetap offline serta mampu air-gap. - Anti-rollback bersifat deterministik. Enforcement mengevaluasi terhadap lantai monotonik: waktu efektif adalah maksimum dari jam sistem dan waktu terverifikasi terakhir, sehingga perubahan jam mundur tidak memberi waktu tambahan. Rollback yang melampaui toleransi skew dan sisa grace memaksa penurunan Core.
- Lease hanya maju pada waktu tepercaya. Pemeriksaan online yang berhasil merekam waktu server yang terverifikasi dan ditandatangani, tidak pernah jam lokal, sehingga lompatan jam-maju lokal tidak dapat menggelembungkan lease.
- Branding memiliki satu otoritas. Hanya channel evaluasi yang memicu watermark. Lisensi berbayar diselesaikan ke tanpa branding dalam setiap status, termasuk yang diturunkan.
- Trial adalah lapisan kebijakan pada timer yang sama. Throughput dibatasi (default 2 halaman/detik), watermark evaluasi berlaku, dan kedaluwarsa bersifat ketat tanpa grace. Hanya alasan yang dilaporkan yang berubah; keputusan dan edisi efektif mengikuti mesin berbayar.
- Kontrak online ditandatangani ujung ke ujung. Setiap permintaan membawa nonce klien CSPRNG. Setiap respons adalah JWS EdDSA kompak dengan media type
application/nextpdf-status+jwt, diverifikasi melalui rantai x5c ke root yang di-pin dan dikompilasi masuk serta diikat ke nonce yang dikirim, id lisensi terpasang, dan endpoint yang dipanggil. Transport amplop tak-bertandatangan legacy telah dipensiunkan; tepat satu jalur kepercayaan tersisa. Pin SPKI yang dikonfigurasi berjalan sebagai headerX-NextPDF-Pinned-Public-Key, dan sebuah pin set harus menyertakan pin cadangan. - Tidak ada penegakan seat runtime.
maxSlotsbersifat kontraktual saja — tanpa telemetri dan tanpa phone-home wajib untuk operasi biasa.
Kasus tepi & mode kegagalan
Bagian berjudul “Kasus tepi & mode kegagalan”- Pemeriksaan kapabilitas pada lisensi yang sepenuhnya kedaluwarsa mengalami hubung-singkat ke “tidak tersedia” sebelum logika pack atau edisi apa pun berjalan.
- Pack add-on dapat kedaluwarsa saat lisensi dasar aktif. Penolakan kemudian terbaca pack kedaluwarsa (
SPEC-LIC-002), bukan tidak-berlisensi (SPEC-LIC-001), dan mencantumkan pack yang sedang aktif. - Berkas status enforcement lokal yang ada tetapi tidak dapat dibaca atau diurai adalah sinyal perusakan. Mesin gagal-tertutup ke penurunan Core dengan
EnforcementReason::CorruptState. Berkas yang secara sah tidak ada bukanlah korup dan berlanjut normal. - Rollback jam di bawah lantai monotonik yang melampaui toleransi skew (default 120 detik) dan sisa grace memaksa penurunan Core secara deterministik.
- Lease liveness yang habis menurunkan lisensi
ioncubeyang seharusnya Active; kedaluwarsa entitlement menurunkan terlepas dari status lease. evaluate(null)bersifat fail-closed: runtime tidak diizinkan, watermark berlaku, dan peringatan menyebut URL harga. Host yang membutuhkan perilaku Core tak-berlisensi harus membangun engine Core secara langsung.- Lisensi evaluasi yang kedaluwarsa tidak memiliki grace dan tidak memiliki fallback; runtime dibatasi dan watermark tetap.
checkRenewal()memperlakukan HTTP 404 sebagai jawaban “tidak ada yang tersedia” yang normal. Non-200 lainnya memunculkanLicenseClientException, dandownload_urlyang melanggar kebijakan keluar gagal-tertutup sebelum dapat lolos dari metode.- Respons status yang dipalsukan, dirusak, basi, salah-nonce, atau salah-lisensi tidak pernah menghasilkan
StatusResponse; verifikasi melemparSpectrumAuthenticationException. Status yang ditandatangani tetapirevoked,expired, ataureleasedlolos verifikasi dan muncul sebagai sinyal penurunan (isLive()bernilai false). - Respons status yang dicetak untuk pertukaran berbeda ditolak:
response_typeyang terverifikasi harus cocok dengan endpoint yang dipanggil. FeatureGategagal-tertutup pada kesalahan resolver apa pun: edisi efektif merosot kecoredan tidak ada kapabilitas premium yang diberikan.EnforcedEntitlementResolverbersifat fail-closed ujung ke ujung: pengecualian apa pun dalam rantainya menghasilkan hasil no-license (Core) dan log kesalahan PSR-3, tidak pernah pemberian premium.
Perilaku mode FIPS
Bagian berjudul “Perilaku mode FIPS”Lapisan licensing tidak menambahkan kebijakan kriptografis miliknya sendiri. Tanda tangan lisensi dan status adalah verifikasi Ed25519 yang dilakukan oleh penyedia kripto host. Dalam build yang dibatasi FIPS, algoritma yang tidak disetujui penyedia gagal di batas kriptografis dengan kesalahan eksplisit; tidak ada yang turun secara diam-diam. Ini adalah klaim kapabilitas tentang kode NextPDF: NextPDF bukan modul kriptografis tervalidasi, tidak memegang sertifikasi, dan tidak memberikan sertifikasi apa pun.
Kesesuaian
Bagian berjudul “Kesesuaian”| Klaim | Standar | Klausa |
|---|---|---|
| Berkas lisensi dan respons status adalah JWS serialisasi-kompak, diverifikasi fail-closed. | RFC 7515 | §3.1 |
| Tanda tangan lisensi dan status adalah Ed25519. | RFC 8032 | §5.1 |
| Rantai x5c dalam respons tertandatangani divalidasi kembali ke trust anchor yang di-pin dan dikompilasi masuk. | RFC 5280 | §6.1 |
| Pin set SPKI yang dikonfigurasi harus menyertakan pin cadangan untuk kunci yang belum diterapkan. | RFC 7469 | §4.3 |
Klaim terverifikasi (iss, aud, exp, nbf, iat) adalah nama klaim terdaftar. | RFC 7519 | §4.1 |
Semua klausa diparafrasakan; tidak ada teks normatif yang direproduksi. NextPDF tidak membuat klaim sertifikasi. Support tidak sama dengan kesesuaian, dan kesesuaian tidak sama dengan sertifikasi. Modul menyelaraskan perilakunya dengan klausa yang dikutip sebagai kapabilitas; penerimaan amplop lisensi atau status diputuskan oleh verifier pinned-root milik NextPDF sendiri, bukan oleh otoritas eksternal.
Catatan pengembangan
Bagian berjudul “Catatan pengembangan”- Bangun
LicenseClientdengan transport yang menegakkan kebijakan (secara kanonikSecurityAwareHttpClient). Klien PSR-18 mentah ditolak saat konstruksi sehingga lalu lintas lisensi tidak pernah dapat dikirim tanpa kontrol anti-SSRF, no-redirect, batas-byte, dan timeout. - Nonce klien yang disediakan pemanggil harus terdekode menjadi setidaknya 16 byte entropi. Sumber mendasari batas ini pada RFC 8555 §6.5; klausa tersebut berada di luar korpus yang dikutip, jadi batas ini dinyatakan di sini dari sumber produk saja.
- Gerbangi fitur melalui
FeatureGate; jangan pernah bercabang padaLicenseKey::$editionmentah. Gate hanya mengonsultasikan edisi efektif yang diberlakukan dan gagal-tertutup kecore. - Jangan melakukan switch pada
EntitlementStatus::PerpetualFallbackyang usang dalam kode baru. UjiisDowngradedToCore()atau cocokkanDowngradedToCoresebagai gantinya. - Perlakukan penolakan kapabilitas sebagai payload remediasi. Munculkan konteks terstruktur dan URL upgrade-nya ke pemanggil alih-alih meruntuhkannya menjadi kesalahan generik.
- Modul ini menyangkut fungsi kriptografis; perlakukan sebagai sensitif-keamanan dalam tinjauan Anda sendiri. Ketentuan kapasitas dan seat diatur oleh perjanjian lisensi, bukan oleh penegakan runtime. Referensi ini bukan pendapat hukum; konsultasikan dengan penasihat kepatuhan dan hukum Anda sendiri.
Batas publikasi
Bagian berjudul “Batas publikasi”Halaman ini mendokumentasikan perilaku yang dapat diamati secara eksternal dan permukaan API publik yang didukung saja. Jalur namespace internal, kelas helper, tabel mekanisme, nama berkas runbook, dan prefiks tiket berada di luar cakupan.
Lihat juga
Bagian berjudul “Lihat juga”- Lisensi — NextPDF Enterprise — halaman kapabilitas dengan panduan penyiapan dan integrasi.
- Penagihan — Referensi Mendalam — tier paket, kebijakan overage, dan rollover.
- SaaS — Referensi Mendalam — permukaan layanan multi-tenant yang dijaga oleh peta rute.
- Branding — Referensi Mendalam — strategi branding yang diselesaikan evaluator.