Ga naar inhoud
getnextpdf.com

Enterprise editie

Licensing — Diepe referentie

Deze pagina is de diepe referentie voor het NextPDF Enterprise licensing-oppervlak — de module die elke andere Enterprise-capaciteit resolveert. Ze behandelt het entitlementstatusmodel (EntitlementEvaluator, EntitlementStatus, EntitlementResult), de gehandhaafde capaciteitsafscherming (FeatureGate, CapabilityCode, CapabilityRegistry), de twee-timer kanaalhandhavingsmachine (ChannelEnforcementPolicy, OnlineCheckScheduler), en de ondertekende online client (LicenseClient). Gewone entitlementevaluatie heeft geen netwerk nodig. De online client bestaat voor expliciete activate-, heartbeat-, deactivate-, verify-online- en renewal-probe-bewerkingen. Interne mechanismedetails blijven in de interne documentatie van de bronrepository en vallen buiten de scope van deze handleiding.

Deze capaciteit wordt meegeleverd in NextPDF Enterprise (nextpdf/enterprise) en activeert met een licentie-envelop op Enterprise-niveau. Een implementatie zonder dat entitlement laadt de klassen van de capaciteit niet. Vergelijk edities en vraag een licentie aan.

Licensing is een basis-Enterprise-oppervlak. Het is altijd aanwezig zodra het Enterprise-pakket naast het Core-pakket is geïnstalleerd, omdat het het oppervlak is dat al het andere resolveert. NextPDF Pro heeft geen apart entitlementoppervlak; het statusmodel, de handhavingsmachine en de online client worden alleen meegeleverd in nextpdf/enterprise. NextPDF Core (Apache-2.0) heeft helemaal geen entitlementmodel — een host die ongelicentieerd Apache-2.0-gedrag nodig heeft, gebruikt de Core-engine rechtstreeks, niet de Enterprise-pijplijn.

Alle typen bevinden zich onder NextPDF\Enterprise\Licensing. De handhavingsmachine zit in de Channel-subnamespace, de runtimesamenstelling in Runtime, en de signed-status-typen in Online.

SymboolParametersStandaardgedragRetourneertWerpt of faalt metOpmerkingen
EntitlementEvaluator::evaluate()?LicenseKey $license, ?DateTimeImmutable $now = nullMapt een geverifieerde licentie (of null) naar de volledige entitlementbeslissingEntitlementResultGeenEen null-licentie levert het fail-closed no-license-resultaat op
EntitlementEvaluator::evaluateEnforced()?LicenseKey $license, EnforcementOutcome $outcomeZet een vooraf berekende handhavingsuitkomst om in een entitlementresultaatEntitlementResultGeenDe effectieve editie komt uit de uitkomst; elke handhavings-downgrade komt uit op Core
EntitlementEvaluator::resolveBrandingMode(), ::resolveBrandingStrategy()?LicenseKey $license, ?DateTimeImmutable $now = nullResolveert de brandingbeslissing voor gegenereerde uitvoerBrandingMode / BrandingStrategyGeenEnig brandinggezag; alleen het evaluatiekanaal plaatst een watermerk
EntitlementResultReadonly value-objectDraagt status, editie, kanaal, brandingmodus, runtime-/update-/ondersteuningsvlaggen en een optionele waarschuwingGeenHelpers: isFullyActive(), isExpired(), isDowngradedToCore(), shouldApplyEvaluationBranding()
EntitlementStatusString-backed enumActive, GracePeriod, DowngradedToCore, EvaluationExpired, NoLicenseGeenPerpetualFallback blijft behouden maar is deprecated; alleen bewaard zodat pre-6.0-consumers nog compileren
FeatureGate::hasCapability()CapabilityCode $capabilityControleert de capaciteit tegen de gehandhaafde effectieve editie en packstatusboolGeenFail-closed naar core bij elke resolver-fout
FeatureGate::requireCapability()CapabilityCode $capabilitySlaagt stil of werpt met gestructureerde upsell-contextvoidSpectrumAuthenticationException SPEC-LIC-001 (niet gelicentieerd) of SPEC-LIC-002 (pack verlopen)De context draagt required_capability, required_pack, current_packs, upgrade_info_url
FeatureGate::isFeatureEnabled(), ::requireFeature()string $featureLegacy feature-identifier-controlebool / voidSpectrumAuthenticationException SPEC-AUTH-007 (require-pad)Legacy-compatibiliteit; geef de voorkeur aan capaciteitscontroles
FeatureGate-accessorsGeenLicentie-introspectieWisseltGeencurrentEdition(), isLicenseValid(), isInGracePeriod(), getActivePacks(), trialPolicy()
CapabilityCodeString-backed enumCanonieke capaciteitsidentifiers (core.*, pro.*, enterprise.*, pack.*)GeenisPack(), packName(), minimumEdition(), forEdition()
CapabilityRegistryLicenseKey, routepatronenRoute-naar-capaciteit-resolutie en pack-lookup vóór dispatchWisseltGeenregisterDefaultRoutes() dekt de gedocumenteerde serviceroutes
LicenseKeyReadonly value-objectGeparseerde, geverifieerde licentieclaimsGeenisExpired(), isInGracePeriod(), isFullyExpired(), hasFeature(), hasCapability(), activePackNames(); maxSlots is alleen contractueel
LicenseValidator::buildVerifiedLicenseKey()array $dataBouwt een getypeerde LicenseKey uit een reeds geverifieerde payloadLicenseKeySpectrumAuthenticationException SPEC-AUTH-001 bij schemaschendingOndersteunt schema 2.0, 1.0 en legacy-payloads
PackDefinition / PackRegistryReadonly value-objectsAdd-on-packstatus met onafhankelijk verloop en graceWisseltGeenisActive(), isFullyExpired(), activePacks(), activeCapabilities()
TrialPolicybool $enabled, int $maxPagesPerSecond = 2, watermerkveldenTrial-doorvoerbegrenzingsbeleidGeenfromLicenseKey(), disabled(), isThrottled(); het brandinggezag blijft bij de evaluator
ChannelEnforcementPolicy::enforce()LicenseKey $license, LocalState $state, int $systemNow, bool $revoked = falseDraait de twee-timer machine plus herroeping en trial-herlabelingEnforcementOutcomeGeenHerroeping overschrijft elke timer- en trial-status
OnlineCheckScheduler::evaluate(), ::recordSuccessfulOnlineCheck()Licentie, lokale status, timestampsTwee-timer evaluatie; lease-vernieuwing op basis van geverifieerde servertijdEnforcementOutcome / LocalStateGeenONLINE_GRACE_SECONDS verleent 48 uur liveness-grace voorbij de lease
EnforcementDecision / EnforcementReason / EnforcementOutcomeEnums + readonly value-objectActive, Grace, DowngradedToCore plus de precieze redenGeenElke reden mapt deterministisch naar één beslissing
Runtime\EntitlementResolver::currentEntitlement()GeenInterface: het gehandhaafde entitlement dat de runtime bedientEntitlementResultImplementatie-afhankelijkEnforcedEntitlementResolver stelt cache, status, beleid en evaluator samen, fail-closed naar Core
LicenseStateCache::get(), ::getOrThrow()bool $forceRefresh = falseGeverifieerde-licentiecache achter de gate?LicenseKeygetOrThrow(): SpectrumAuthenticationException SPEC-AUTH-008; LicenseConfigurationException bij ongeldige bedradinginvalidate(), isCacheValid()
LicenseClient::activate(), ::heartbeat(), ::deactivate(), ::verifyOnline()string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = nullEén signed-status-uitwisseling; het antwoord wordt geverifieerd tegen de pinned root en gebonden aan de verzonden nonceStatusResponseLicenseClientException (transport, non-200, ongeldige opgegeven nonce); SpectrumAuthenticationException (vervalst, gemanipuleerd, verouderd, verkeerde-nonce, verkeerde-licentie, verkeerd-type antwoord)Alleen de gesalte fingerprint-hash wordt ooit verzonden, nooit een ruwe fingerprint
LicenseClient::checkRenewal()string $licenseId, string $customerIdBeschikbaarheidsprobe voor vernieuwing; 404 is het normale “geen beschikbaar”-antwoordRenewal-array (available, download_url, expires_at)LicenseClientException (onbereikbaar, non-200/404, of een door beleid geweigerde download_url)De URL in de unsigned body wordt SSRF-gescreend voordat deze kan ontsnappen
LicenseClient::__construct()Zie signatuurblokValideert het transport, URL-schema en de pinset bij constructieLicenseConfigurationException (transport dat geen beleid afdwingt, niet-toegestaan schema, plain HTTP zonder pins, misvormde pinset)getPinSet() stelt de actieve pinset beschikbaar voor rotatietooling
Online\StatusResponseReadonly value-objectDe geverifieerde ondertekende statusGeenisLive() is false bij revoked / expired / released; draagt leaseExpiresAt, slot-aantallen en een entitlement-snapshot
LicenseChannelMode / OnlineMode / OnlinePolicyEnums + readonly value-objectKanaal- en online-beleidsclaimsGeensigned_source vs ioncube; online-modus required / optional / disabled met intervalDays en leaseDays
LicenseEditionString-backed enumCore, Pro, EnterpriseGeensatisfies() implementeert de tier-hiërarchie
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

Entitlementevaluatie levert een van vijf huidige statussen op, elk met een vast runtime-gevolg:

StatusRuntimeEffectieve capaciteitenUpdates / ondersteuningBranding
Activetoegestaangerechtigde editie + actieve packsja (betaald); nee (evaluatie)geen (betaald); watermerk (evaluatie)
GracePeriodtoegestaangerechtigde editie + actieve packsjageen (betaald)
DowngradedToCoretoegestaanalleen Coreneegeen (betaald); watermerk (trial)
EvaluationExpiredbeperktgeenneewatermerk
NoLicenseuitgeschakeld (fail-closed)geenneewatermerk
  • Betaald verloop schakelt de geïnstalleerde runtime nooit uit. runtimeAllowed blijft true voor elke betaalde status. Voorbij het grace-venster downgradet de effectieve editie naar Core: Core-capaciteiten blijven onbeperkt draaien, alle Pro-/Enterprise-/pack-capaciteiten schakelen uit, en updates en ondersteuning worden herroepen. De deprecated EntitlementStatus::PerpetualFallback-case benoemt het pre-6.0-verloopbeleid en bestaat alleen voor compile-compatibiliteit.
  • Niet elke status eindigt in Core-uitvoering. Grace behoudt de volledige gerechtigde editie met een gedateerde vernieuwingswaarschuwing. Evaluatieverloop beperkt de runtime en behoudt het watermerk. De no-license-status schakelt Enterprise-paden fail-closed uit en voorziet elke legacy-uitvoer zichtbaar van een watermerk, zodat deze nooit kan doorgaan voor een betaalde uitvoering.
  • Vaste resolutievolgorde. Een volledig verlopen licentie resolveert geen enkele capaciteit. Pack-capaciteiten schuiven door naar de eigen actieve status en het onafhankelijke verloop van het pack. Editiecapaciteiten resolveren tegen de gehandhaafde effectieve editie op de strikte hiërarchie Enterprise ⊇ Pro ⊇ Core. Ruwe LicenseKey::$edition wordt nooit geraadpleegd voor afscherming.
  • Twee timers; de meest beperkende wint. De entitlement-timer (beide kanalen) stuurt Active, Grace en de post-grace Core-downgrade aan. De online-liveness-timer geldt alleen voor het ioncube-kanaal met online-modus required: de lease, plus 48 uur liveness-grace, moet live zijn. Offline voorbij de lease pauzeert premium op de Core-tier; een latere geverifieerde online check herstelt de lease en premium hervat. Het signed_source-kanaal — en elke niet-vereiste online-modus — heeft geen liveness-timer en blijft offline en air-gap-capabel.
  • Anti-rollback is deterministisch. Handhaving evalueert tegen een monotone ondergrens: de effectieve tijd is het maximum van de systeemklok en de laatst geverifieerde tijd, zodat een terugwaartse klokwijziging geen extra tijd oplevert. Een rollback die de skew-tolerantie en de resterende grace overschrijdt, forceert de Core-downgrade.
  • Leases lopen alleen vooruit op vertrouwde tijd. Een geslaagde online check registreert de geverifieerde, ondertekende servertijd, nooit de lokale klok, zodat een lokale voorwaartse kloksprong de lease niet kan opblazen.
  • Branding heeft één gezag. Alleen het evaluatiekanaal activeert het watermerk. Een betaalde licentie resolveert in elke status naar geen branding, inclusief de gedowngradede statussen.
  • Trial is een beleidslaag op dezelfde timers. De doorvoer wordt begrensd (standaard 2 pagina’s/seconde), het evaluatiewatermerk is van toepassing, en het verloop is strikt zonder grace. Alleen de gerapporteerde reden verandert; de beslissing en de effectieve editie volgen de betaalde machine.
  • Het online contract is end-to-end ondertekend. Elke aanvraag draagt een CSPRNG-client-nonce. Elk antwoord is een compacte EdDSA JWS met mediatype application/nextpdf-status+jwt, geverifieerd via een x5c-keten naar een ingecompileerde pinned root en gebonden aan de verzonden nonce, de geïnstalleerde license-id en het aangeroepen endpoint. Het legacy unsigned-enveloptransport is uitgefaseerd; er blijft precies één trust-pad over. Geconfigureerde SPKI-pins reizen mee als de X-NextPDF-Pinned-Public-Key-header, en een pinset moet een backuppin bevatten.
  • Geen runtime seat-handhaving. maxSlots is alleen contractueel — geen telemetrie en geen verplichte phone-home voor gewone werking.
  • Een capaciteitscontrole op een volledig verlopen licentie kortsluit naar “niet beschikbaar” voordat er pack- of editielogica draait.
  • Een add-on-pack kan verlopen terwijl de basislicentie actief is. De weigering leest dan pack verlopen (SPEC-LIC-002), niet niet-gelicentieerd (SPEC-LIC-001), en somt de momenteel actieve packs op.
  • Een lokaal handhavingsstatusbestand dat aanwezig maar onleesbaar of niet-parseerbaar is, is een manipulatiesignaal. De machine faalt gesloten naar de Core-downgrade met EnforcementReason::CorruptState. Een legitiem ontbrekend bestand is niet corrupt en verloopt normaal.
  • Een klok-rollback onder de monotone ondergrens die de skew-tolerantie (standaard 120 seconden) en de resterende grace overschrijdt, forceert de Core-downgrade deterministisch.
  • Een verlopen liveness-lease downgradet een verder Active ioncube-licentie; entitlementverloop downgradet ongeacht de lease-status.
  • evaluate(null) is fail-closed: de runtime is niet toegestaan, het watermerk is van toepassing, en de waarschuwing benoemt de pricing-URL. Hosts die ongelicentieerd Core-gedrag nodig hebben, moeten de Core-engine rechtstreeks construeren.
  • Een verlopen evaluatielicentie heeft geen grace en geen fallback; de runtime is beperkt en het watermerk blijft.
  • checkRenewal() behandelt HTTP 404 als het normale “geen beschikbaar”-antwoord. Elke andere non-200 werpt LicenseClientException, en een download_url die het uitgaande beleid schendt, faalt gesloten voordat deze de methode kan ontsnappen.
  • Een vervalst, gemanipuleerd, verouderd, verkeerde-nonce- of verkeerde-licentie-statusantwoord levert nooit een StatusResponse op; verificatie werpt SpectrumAuthenticationException. Een ondertekende maar revoked-, expired- of released-status verifieert en verschijnt als een downgrade-signaal (isLive() is false).
  • Een statusantwoord dat voor een andere uitwisseling is aangemaakt, wordt afgewezen: het geverifieerde response_type moet overeenkomen met het aangeroepen endpoint.
  • FeatureGate faalt gesloten bij elke resolver-fout: de effectieve editie degradeert naar core en er wordt geen premium-capaciteit verleend.
  • EnforcedEntitlementResolver is end-to-end fail-closed: elke exception in zijn keten levert het no-license (Core)-resultaat en een PSR-3-foutlog op, nooit een premium-verlening.

De licensing-laag voegt geen eigen cryptografisch beleid toe. Licentie- en statushandtekeningen zijn Ed25519-verificaties uitgevoerd door de crypto-provider van de host. In een FIPS-beperkte build faalt een algoritme dat de provider niet goedkeurt op de cryptografische grens met een expliciete fout; er degradeert niets stilzwijgend. Dit zijn capaciteitsclaims over NextPDF-code: NextPDF is geen gevalideerde cryptografische module, houdt geen certificering en verleent er geen.

ClaimStandaardClausule
Licentiebestanden en statusantwoorden zijn compact-serialization JWS, fail-closed geverifieerd.RFC 7515§3.1
Licentie- en statushandtekeningen zijn Ed25519.RFC 8032§5.1
De x5c-keten in een ondertekend antwoord valideert terug naar een ingecompileerde pinned trust-anchor.RFC 5280§6.1
Een geconfigureerde SPKI-pinset moet een backuppin bevatten voor een nog-niet-uitgerolde sleutel.RFC 7469§4.3
Geverifieerde claims (iss, aud, exp, nbf, iat) zijn geregistreerde claim-namen.RFC 7519§4.1

Alle clausules zijn geparafraseerd; er wordt geen normatieve tekst gereproduceerd. NextPDF doet geen enkele certificeringsclaim. Ondersteuning staat niet gelijk aan conformiteit, en conformiteit staat niet gelijk aan certificering. De module stemt haar gedrag af op de aangehaalde clausules als een capaciteit; de acceptatie van een licentie- of status-envelop wordt beslist door NextPDF’s eigen pinned-root-verifier, niet door een externe autoriteit.

  • Construeer LicenseClient met een transport dat beleid afdwingt (canoniek SecurityAwareHttpClient). Een ruwe PSR-18-client wordt bij constructie afgewezen, zodat licentieverkeer nooit kan worden verzonden zonder de anti-SSRF-, no-redirect-, byte-cap- en time-outcontroles.
  • Een door de aanroeper opgegeven client-nonce moet decoderen naar minstens 16 bytes entropie. De bron grondt deze ondergrens in RFC 8555 §6.5; die clausule valt buiten het aangehaalde corpus, dus de ondergrens wordt hier alleen op basis van de productbron vermeld.
  • Scherm functies af via FeatureGate; vertak nooit op ruwe LicenseKey::$edition. De gate raadpleegt alleen de gehandhaafde effectieve editie en faalt gesloten naar core.
  • Schakel in nieuwe code niet op de deprecated EntitlementStatus::PerpetualFallback. Test in plaats daarvan isDowngradedToCore() of match DowngradedToCore.
  • Behandel een capaciteitsweigering als een remediatiepayload. Toon de gestructureerde context en upgrade-URL aan de aanroeper in plaats van deze te reduceren tot een generieke fout.
  • Deze module betreft cryptografische functionaliteit; behandel deze in je eigen review als beveiligingsgevoelig. Capaciteits- en seat-voorwaarden worden beheerst door de licentieovereenkomst, niet door runtime-handhaving. Deze referentie is geen juridisch advies; raadpleeg je eigen compliance- en juridische adviseurs.

Deze pagina documenteert alleen extern waarneembaar gedrag en het ondersteunde publieke API-oppervlak. Interne namespace-paden, helperklassen, mechanismetabellen, runbook-bestandsnamen en ticketprefixen vallen buiten de scope.