Enterprise edizione
Licensing — Riferimento approfondito
In sintesi
Sezione intitolata “In sintesi”Questa pagina è il riferimento approfondito della superficie di licensing di NextPDF Enterprise — il modulo che risolve ogni altra capability di Enterprise. Copre il modello degli stati di entitlement (EntitlementEvaluator, EntitlementStatus, EntitlementResult), il gating applicato delle capability (FeatureGate, CapabilityCode, CapabilityRegistry), la macchina di enforcement di canale a due timer (ChannelEnforcementPolicy, OnlineCheckScheduler) e il client online firmato (LicenseClient). La normale valutazione dell’entitlement non richiede rete. Il client online esiste per le operazioni esplicite di attivazione, heartbeat, disattivazione, verifica online e sonda di rinnovo. I dettagli del meccanismo interno restano nella documentazione interna del repository sorgente e sono fuori ambito per questo manuale.
Disponibilità e licensing
Sezione intitolata “Disponibilità e licensing”Questa capability è inclusa in NextPDF Enterprise (nextpdf/enterprise) e si attiva con un envelope di licenza di tier Enterprise. Una distribuzione priva di quell’entitlement non carica le classi della capability. Confronta le edizioni e ottieni una licenza.
Il licensing è una superficie di base di Enterprise. È sempre presente una volta installato il pacchetto Enterprise accanto al pacchetto Core, perché è la superficie che risolve tutto il resto. NextPDF Pro non ha una superficie di entitlement separata; il modello degli stati, la macchina di enforcement e il client online sono inclusi esclusivamente in nextpdf/enterprise. NextPDF Core (Apache-2.0) non dispone affatto di un modello di entitlement — un host che necessiti del comportamento Apache-2.0 senza licenza usa direttamente il motore Core, non la pipeline Enterprise.
Superficie API pubblica
Sezione intitolata “Superficie API pubblica”Tutti i tipi risiedono in NextPDF\Enterprise\Licensing. La macchina di enforcement si trova nel sotto-namespace Channel, la composizione di runtime in Runtime e i tipi di stato firmato in Online.
| Simbolo | Parametri | Comportamento predefinito | Restituisce | Lancia o fallisce con | Note |
|---|---|---|---|---|---|
EntitlementEvaluator::evaluate() | ?LicenseKey $license, ?DateTimeImmutable $now = null | Mappa una licenza verificata (o null) sulla decisione di entitlement completa | EntitlementResult | Nessuna | Una licenza null produce il risultato no-license fail-closed |
EntitlementEvaluator::evaluateEnforced() | ?LicenseKey $license, EnforcementOutcome $outcome | Converte un esito di enforcement pre-calcolato in un risultato di entitlement | EntitlementResult | Nessuna | L’edizione effettiva proviene dall’esito; ogni downgrade di enforcement approda a Core |
EntitlementEvaluator::resolveBrandingMode(), ::resolveBrandingStrategy() | ?LicenseKey $license, ?DateTimeImmutable $now = null | Risolve la decisione di branding per l’output generato | BrandingMode / BrandingStrategy | Nessuna | Unica autorità sul branding; solo il canale di valutazione applica la filigrana |
EntitlementResult | Value object readonly | Trasporta stato, edizione, canale, modalità di branding, flag di runtime/aggiornamenti/supporto e un avviso facoltativo | — | Nessuna | Helper: isFullyActive(), isExpired(), isDowngradedToCore(), shouldApplyEvaluationBranding() |
EntitlementStatus | Enum a backing string | Active, GracePeriod, DowngradedToCore, EvaluationExpired, NoLicense | — | Nessuna | PerpetualFallback è mantenuto ma deprecato; conservato solo perché i consumer pre-6.0 continuino a compilare |
FeatureGate::hasCapability() | CapabilityCode $capability | Verifica la capability rispetto all’edizione effettiva applicata e allo stato dei pacchetti | bool | Nessuna | Fail-closed a core in caso di qualsiasi errore del resolver |
FeatureGate::requireCapability() | CapabilityCode $capability | Passa silenziosamente o lancia con contesto di upsell strutturato | void | SpectrumAuthenticationException SPEC-LIC-001 (non concesso in licenza) o SPEC-LIC-002 (pacchetto scaduto) | Il contesto trasporta required_capability, required_pack, current_packs, upgrade_info_url |
FeatureGate::isFeatureEnabled(), ::requireFeature() | string $feature | Controllo legacy per identificatore di funzionalità | bool / void | SpectrumAuthenticationException SPEC-AUTH-007 (percorso require) | Compatibilità legacy; preferire i controlli di capability |
Accessori di FeatureGate | Nessuno | Introspezione della licenza | Variabile | Nessuna | currentEdition(), isLicenseValid(), isInGracePeriod(), getActivePacks(), trialPolicy() |
CapabilityCode | Enum a backing string | Identificatori canonici di capability (core.*, pro.*, enterprise.*, pack.*) | — | Nessuna | isPack(), packName(), minimumEdition(), forEdition() |
CapabilityRegistry | LicenseKey, pattern di rotta | Risoluzione rotta-a-capability e lookup dei pacchetti prima del dispatch | Variabile | Nessuna | registerDefaultRoutes() copre le rotte di servizio documentate |
LicenseKey | Value object readonly | Claim di licenza analizzati e verificati | — | Nessuna | isExpired(), isInGracePeriod(), isFullyExpired(), hasFeature(), hasCapability(), activePackNames(); maxSlots è solo contrattuale |
LicenseValidator::buildVerifiedLicenseKey() | array $data | Costruisce un LicenseKey tipizzato da un payload già verificato | LicenseKey | SpectrumAuthenticationException SPEC-AUTH-001 in caso di violazione dello schema | Supporta gli schemi 2.0, 1.0 e i payload legacy |
PackDefinition / PackRegistry | Value object readonly | Stato dei pacchetti add-on con scadenza e tolleranza indipendenti | Variabile | Nessuna | isActive(), isFullyExpired(), activePacks(), activeCapabilities() |
TrialPolicy | bool $enabled, int $maxPagesPerSecond = 2, campi filigrana | Policy di limitazione del throughput per il trial | — | Nessuna | fromLicenseKey(), disabled(), isThrottled(); l’autorità sul branding resta al valutatore |
ChannelEnforcementPolicy::enforce() | LicenseKey $license, LocalState $state, int $systemNow, bool $revoked = false | Esegue la macchina a due timer più la revoca e la rietichettatura del trial | EnforcementOutcome | Nessuna | La revoca prevale su ogni timer e su ogni stato di trial |
OnlineCheckScheduler::evaluate(), ::recordSuccessfulOnlineCheck() | Licenza, stato locale, timestamp | Valutazione a due timer; rinnovo del lease dal tempo server verificato | EnforcementOutcome / LocalState | Nessuna | ONLINE_GRACE_SECONDS concede 48 ore di tolleranza di liveness oltre il lease |
EnforcementDecision / EnforcementReason / EnforcementOutcome | Enum + value object readonly | Active, Grace, DowngradedToCore più il motivo preciso | — | Nessuna | Ogni motivo mappa in modo deterministico su una sola decisione |
Runtime\EntitlementResolver::currentEntitlement() | Nessuno | Interfaccia: l’entitlement applicato che il runtime serve | EntitlementResult | Definito dall’implementazione | EnforcedEntitlementResolver compone cache, stato, policy e valutatore, fail-closed a Core |
LicenseStateCache::get(), ::getOrThrow() | bool $forceRefresh = false | Cache della licenza verificata a supporto del gate | ?LicenseKey | getOrThrow(): SpectrumAuthenticationException SPEC-AUTH-008; LicenseConfigurationException in caso di wiring non valido | invalidate(), isCacheValid() |
LicenseClient::activate(), ::heartbeat(), ::deactivate(), ::verifyOnline() | string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = null | Un singolo scambio di stato firmato; la risposta è verificata rispetto alla root pinnata e legata al nonce inviato | StatusResponse | LicenseClientException (trasporto, non-200, nonce fornito errato); SpectrumAuthenticationException (risposta contraffatta, manomessa, obsoleta, con nonce errato, licenza errata o tipo errato) | Viene sempre inviato solo l’hash con salt del fingerprint, mai un fingerprint grezzo |
LicenseClient::checkRenewal() | string $licenseId, string $customerId | Sonda di disponibilità del rinnovo; 404 è la normale risposta «nessuno disponibile» | Array di rinnovo (available, download_url, expires_at) | LicenseClientException (irraggiungibile, non-200/404 o download_url respinto dalla policy) | L’URL del corpo non firmato è sottoposto a screening anti-SSRF prima di poter uscire |
LicenseClient::__construct() | Vedere il blocco della firma | Convalida il trasporto, lo schema URL e il set di pin al momento della costruzione | — | LicenseConfigurationException (trasporto che non applica policy, schema non consentito, HTTP in chiaro senza pin, set di pin malformato) | getPinSet() espone il set di pin attivo per gli strumenti di rotazione |
Online\StatusResponse | Value object readonly | Lo stato firmato verificato | — | Nessuna | isLive() è false in stato revoked / expired / released; trasporta leaseExpiresAt, i conteggi degli slot e uno snapshot dell’entitlement |
LicenseChannelMode / OnlineMode / OnlinePolicy | Enum + value object readonly | Claim di canale e di policy online | — | Nessuna | signed_source vs ioncube; modalità online required / optional / disabled con intervalDays e leaseDays |
LicenseEdition | Enum a backing string | Core, Pro, Enterprise | — | Nessuna | satisfies() implementa la gerarchia dei 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): arrayContratto di comportamento
Sezione intitolata “Contratto di comportamento”La valutazione dell’entitlement produce uno di cinque stati correnti, ciascuno con una conseguenza fissa in fase di esecuzione:
| Stato | Runtime | Capability effettive | Aggiornamenti / supporto | Branding |
|---|---|---|---|---|
Active | consentito | edizione concessa + pacchetti attivi | sì (pagata); no (valutazione) | nessuno (pagata); filigrana (valutazione) |
GracePeriod | consentito | edizione concessa + pacchetti attivi | sì | nessuno (pagata) |
DowngradedToCore | consentito | solo Core | no | nessuno (pagata); filigrana (trial) |
EvaluationExpired | limitato | nessuna | no | filigrana |
NoLicense | disabilitato (fail-closed) | nessuna | no | filigrana |
- La scadenza di una licenza pagata non disabilita mai il runtime installato.
runtimeAllowedresta true per ogni stato pagato. Oltre la finestra di tolleranza l’edizione effettiva degrada a Core: le capability Core continuano a funzionare indefinitamente, tutte le capability Pro/Enterprise/pacchetto vengono disattivate dal gate e aggiornamenti e supporto sono revocati. Il caso deprecatoEntitlementStatus::PerpetualFallbacknomina la policy di scadenza pre-6.0 ed esiste solo per compatibilità di compilazione. - Non ogni stato termina con l’esecuzione a livello Core. La tolleranza mantiene l’intera edizione concessa con un avviso di rinnovo datato. La scadenza della valutazione limita il runtime e mantiene la filigrana. Lo stato no-license disabilita i percorsi Enterprise in modalità fail-closed e contrassegna visibilmente con filigrana qualsiasi output legacy, così da non poter mai passare per esecuzione pagata.
- Ordine di risoluzione fisso. Una licenza completamente scaduta non risolve alcuna capability. Le capability di pacchetto rinviano allo stato attivo e alla scadenza indipendente propri del pacchetto. Le capability di edizione si risolvono rispetto all’edizione effettiva applicata sulla gerarchia rigorosa Enterprise ⊇ Pro ⊇ Core.
LicenseKey::$editiongrezzo non viene mai consultato per il gating. - Due timer; vince il più restrittivo. Il timer di entitlement (entrambi i canali) governa Active, Grace e il downgrade a Core oltre la tolleranza. Il timer di liveness online si applica solo al canale
ioncubecon modalità onlinerequired: il lease, più una tolleranza di liveness di 48 ore, deve essere vivo. Offline oltre il lease, il premium si mette in pausa al tier Core; un successivo controllo online verificato ristabilisce il lease e il premium riprende. Il canalesigned_source— e qualsiasi modalità online diversa darequired— non ha timer di liveness e resta capace di funzionare offline e in ambienti air-gap. - L’anti-rollback è deterministico. L’enforcement valuta rispetto a un limite inferiore monotono: il tempo effettivo è il massimo tra l’orologio di sistema e l’ultimo tempo verificato, quindi un’alterazione all’indietro dell’orologio non concede tempo aggiuntivo. Un rollback che superi la tolleranza di scostamento e la tolleranza residua forza il downgrade a Core.
- I lease avanzano solo su tempo fidato. Un controllo online riuscito registra il tempo server verificato e firmato, mai l’orologio locale, così un salto in avanti dell’orologio locale non può gonfiare il lease.
- Il branding ha un’unica autorità. Solo il canale di valutazione attiva la filigrana. Una licenza pagata si risolve in nessun branding in ogni stato, compresi quelli in downgrade.
- Il trial è uno strato di policy sugli stessi timer. Il throughput è limitato (predefinito 2 pagine/secondo), la filigrana di valutazione si applica e la scadenza è rigorosa senza tolleranza. Cambia solo il motivo riportato; la decisione e l’edizione effettiva seguono la macchina della licenza pagata.
- Il contratto online è firmato end-to-end. Ogni richiesta trasporta un nonce client CSPRNG. Ogni risposta è un JWS EdDSA compatto di media type
application/nextpdf-status+jwt, verificato tramite una catena x5c fino a una root pinnata compilata nel codice e legato al nonce inviato, all’id di licenza installato e all’endpoint invocato. Il trasporto legacy con envelope non firmato è dismesso; resta esattamente un solo percorso di fiducia. I pin SPKI configurati viaggiano nell’headerX-NextPDF-Pinned-Public-Keye un set di pin deve includere un pin di backup. - Nessuna applicazione delle postazioni in fase di esecuzione.
maxSlotsè solo contrattuale — nessuna telemetria e nessun phone-home obbligatorio per il normale funzionamento.
Casi limite e modalità di errore
Sezione intitolata “Casi limite e modalità di errore”- Un controllo di capability su una licenza completamente scaduta va in cortocircuito a «non disponibile» prima dell’esecuzione di qualsiasi logica di pacchetto o di edizione.
- Un pacchetto add-on può scadere mentre la licenza di base è attiva. Il diniego riporta allora «pacchetto scaduto» (
SPEC-LIC-002), non «non concesso in licenza» (SPEC-LIC-001), ed elenca i pacchetti attualmente attivi. - Un file di stato di enforcement locale presente ma illeggibile o non analizzabile è un segnale di manomissione. La macchina fallisce in modo chiuso verso il downgrade a Core con
EnforcementReason::CorruptState. Un file legittimamente assente non è corrotto e procede normalmente. - Un rollback dell’orologio al di sotto del limite inferiore monotono che superi la tolleranza di scostamento (predefinita 120 secondi) e la tolleranza residua forza il downgrade a Core in modo deterministico.
- Un lease di liveness scaduto degrada una licenza
ioncubealtrimenti Active; la scadenza dell’entitlement causa il downgrade indipendentemente dallo stato del lease. evaluate(null)è fail-closed: il runtime è negato, la filigrana si applica e l’avviso nomina l’URL dei prezzi. Gli host che necessitano del comportamento Core senza licenza devono costruire direttamente il motore Core.- Una licenza di valutazione scaduta non ha tolleranza né fallback; il runtime è limitato e la filigrana resta.
checkRenewal()tratta l’HTTP 404 come la normale risposta «nessuno disponibile». Qualsiasi altro non-200 sollevaLicenseClientException, e undownload_urlche viola la policy in uscita fallisce in modo chiuso prima di poter uscire dal metodo.- Una risposta di stato contraffatta, manomessa, obsoleta, con nonce errato o licenza errata non produce mai uno
StatusResponse; la verifica lanciaSpectrumAuthenticationException. Uno stato firmato marevoked,expiredoreleasedsi verifica ed emerge come segnale di downgrade (isLive()è false). - Una risposta di stato coniata per uno scambio diverso viene respinta: il
response_typeverificato deve corrispondere all’endpoint invocato. FeatureGatefallisce in modo chiuso in caso di qualsiasi errore del resolver: l’edizione effettiva degrada acoree nessuna capability premium viene concessa.EnforcedEntitlementResolverè fail-closed end-to-end: qualsiasi eccezione nella sua catena produce il risultato no-license (Core) e un log di errore PSR-3, mai una concessione premium.
Comportamento in modalità FIPS
Sezione intitolata “Comportamento in modalità FIPS”Il layer di licensing non aggiunge alcuna politica crittografica propria. Le firme di licenza e di stato sono verifiche Ed25519 eseguite dal provider crittografico dell’host. In una build vincolata a FIPS, un algoritmo che il provider non approva fallisce al confine crittografico con un errore esplicito; nulla degrada silenziosamente. Queste sono affermazioni di capability sul codice NextPDF: NextPDF non è un modulo crittografico validato, non detiene alcuna certificazione e non ne concede alcuna.
Conformità
Sezione intitolata “Conformità”| Affermazione | Standard | Clausola |
|---|---|---|
| I file di licenza e le risposte di stato sono JWS in serializzazione compatta, verificati fail-closed. | RFC 7515 | §3.1 |
| Le firme di licenza e di stato sono Ed25519. | RFC 8032 | §5.1 |
| La catena x5c in una risposta firmata si convalida fino a un trust anchor pinnato compilato nel codice. | RFC 5280 | §6.1 |
| Un set di pin SPKI configurato deve includere un pin di backup per una chiave non ancora distribuita. | RFC 7469 | §4.3 |
I claim verificati (iss, aud, exp, nbf, iat) sono nomi di claim registrati. | RFC 7519 | §4.1 |
Tutte le clausole sono parafrasate; nessun testo normativo è riprodotto. NextPDF non avanza alcuna pretesa di certificazione. Il supporto non equivale alla conformità e la conformità non equivale alla certificazione. Il modulo allinea il proprio comportamento alle clausole citate come capability; l’accettazione di un envelope di licenza o di stato è decisa dal verificatore a root pinnata di NextPDF, non da un’autorità esterna.
Note di sviluppo
Sezione intitolata “Note di sviluppo”- Costruire
LicenseClientcon un trasporto che applica policy (canonicamenteSecurityAwareHttpClient). Un client PSR-18 grezzo viene respinto in costruzione, così il traffico di licenza non possa mai essere inviato senza i controlli anti-SSRF, no-redirect, di limite di byte e di timeout. - Un nonce client fornito dal chiamante deve decodificarsi in almeno 16 byte di entropia. Il sorgente fonda questo limite su RFC 8555 §6.5; quella clausola è al di fuori del corpus citato, quindi il limite è qui indicato solo dal sorgente del prodotto.
- Applicare il gate alle funzionalità tramite
FeatureGate; non diramare mai suLicenseKey::$editiongrezzo. Il gate consulta solo l’edizione effettiva applicata e fallisce in modo chiuso acore. - Non usare lo switch sul deprecato
EntitlementStatus::PerpetualFallbacknel nuovo codice. Testare inveceisDowngradedToCore()o fare match suDowngradedToCore. - Trattare il diniego di una capability come un payload di rimedio. Esporre al chiamante il suo contesto strutturato e l’URL di upgrade anziché ridurlo a un errore generico.
- Questo modulo riguarda funzionalità crittografiche; trattarlo come sensibile alla sicurezza nella propria revisione. I termini di capacità e di postazioni sono governati dal contratto di licenza, non dall’applicazione in fase di esecuzione. Questo riferimento non è un parere legale; consultare i propri consulenti di conformità e legali.
Confine di pubblicazione
Sezione intitolata “Confine di pubblicazione”Questa pagina documenta esclusivamente il comportamento osservabile dall’esterno e la superficie API pubblica supportata. I percorsi di namespace interni, le classi helper, le tabelle di meccanismo, i nomi di file di runbook e i prefissi di ticket sono fuori ambito.
Vedere anche
Sezione intitolata “Vedere anche”- Licensing — NextPDF Enterprise — la pagina della capability con guida a configurazione e integrazione.
- Billing — Riferimento approfondito — tier di piano, policy di eccedenza e rollover.
- SaaS — Riferimento approfondito — la superficie di servizio multi-tenant protetta dalla mappa delle rotte.
- Branding — Riferimento approfondito — le strategie di branding risolte dal valutatore.