Enterprise edição
Licensing — Referência Profunda
Visão geral
Seção intitulada “Visão geral”Esta página é a referência aprofundada da superfície de licenciamento do NextPDF Enterprise — o módulo que resolve todas as outras capacidades do Enterprise. Ela cobre o modelo de estados de direito de uso (EntitlementEvaluator, EntitlementStatus, EntitlementResult), a restrição de capacidades imposta (FeatureGate, CapabilityCode, CapabilityRegistry), a máquina de imposição de canal de dois temporizadores (ChannelEnforcementPolicy, OnlineCheckScheduler) e o cliente on-line assinado (LicenseClient). A avaliação comum de direito de uso não precisa de rede. O cliente on-line existe para as operações explícitas de ativação, heartbeat, desativação, verificação on-line e sondagem de renovação. O detalhe de mecanismo interno permanece na documentação interna do repositório de origem e está fora do escopo deste manual.
Disponibilidade e licenciamento
Seção intitulada “Disponibilidade e licenciamento”Esta capacidade é distribuída no NextPDF Enterprise (nextpdf/enterprise) e é ativada com um envelope de licença de nível Enterprise. Uma implantação sem esse direito de uso não carrega as classes da capacidade. Compare edições e obtenha uma licença.
O licenciamento é uma superfície base do Enterprise. Ele está sempre presente assim que o pacote Enterprise é instalado ao lado do pacote Core, porque é a superfície que resolve todo o resto. O NextPDF Pro não tem uma superfície de direito de uso separada; o modelo de estados, a máquina de imposição e o cliente on-line são distribuídos apenas em nextpdf/enterprise. O NextPDF Core (Apache-2.0) não tem nenhum modelo de direito de uso — um host que precisa do comportamento Apache-2.0 sem licença usa o mecanismo Core diretamente, não o pipeline do Enterprise.
Superfície da API pública
Seção intitulada “Superfície da API pública”Todos os tipos ficam sob NextPDF\Enterprise\Licensing. A máquina de imposição fica no sub-namespace Channel, a composição de runtime em Runtime e os tipos de status assinado em Online.
| Símbolo | Parâmetros | Comportamento padrão | Retorna | Lança ou falha com | Notas |
|---|---|---|---|---|---|
EntitlementEvaluator::evaluate() | ?LicenseKey $license, ?DateTimeImmutable $now = null | Mapeia uma licença verificada (ou null) para a decisão completa de direito de uso | EntitlementResult | Nenhuma | Uma licença null produz o resultado fail-closed de sem licença |
EntitlementEvaluator::evaluateEnforced() | ?LicenseKey $license, EnforcementOutcome $outcome | Converte um resultado de imposição pré-computado em um resultado de direito de uso | EntitlementResult | Nenhuma | A edição efetiva vem do resultado; todo rebaixamento de imposição termina em Core |
EntitlementEvaluator::resolveBrandingMode(), ::resolveBrandingStrategy() | ?LicenseKey $license, ?DateTimeImmutable $now = null | Resolve a decisão de marca para a saída gerada | BrandingMode / BrandingStrategy | Nenhuma | Autoridade única de marca; apenas o canal de avaliação aplica marca d’água |
EntitlementResult | Objeto de valor readonly | Carrega status, edição, canal, modo de marca, sinalizadores de runtime/atualização/suporte e um aviso opcional | — | Nenhuma | Auxiliares: isFullyActive(), isExpired(), isDowngradedToCore(), shouldApplyEvaluationBranding() |
EntitlementStatus | Enum baseado em string | Active, GracePeriod, DowngradedToCore, EvaluationExpired, NoLicense | — | Nenhuma | PerpetualFallback é mantido, mas obsoleto; conservado apenas para que consumidores pré-6.0 ainda compilem |
FeatureGate::hasCapability() | CapabilityCode $capability | Verifica a capacidade contra a edição efetiva imposta e o estado do pacote | bool | Nenhuma | Fail-closed para core em qualquer erro do resolvedor |
FeatureGate::requireCapability() | CapabilityCode $capability | Passa silenciosamente ou lança com contexto estruturado de upsell | void | SpectrumAuthenticationException SPEC-LIC-001 (não licenciado) ou SPEC-LIC-002 (pacote expirado) | O contexto carrega required_capability, required_pack, current_packs, upgrade_info_url |
FeatureGate::isFeatureEnabled(), ::requireFeature() | string $feature | Verificação legada por identificador de recurso | bool / void | SpectrumAuthenticationException SPEC-AUTH-007 (caminho require) | Compatibilidade legada; prefira verificações de capacidade |
Acessores de FeatureGate | Nenhum | Introspecção de licença | Varia | Nenhuma | currentEdition(), isLicenseValid(), isInGracePeriod(), getActivePacks(), trialPolicy() |
CapabilityCode | Enum baseado em string | Identificadores canônicos de capacidade (core.*, pro.*, enterprise.*, pack.*) | — | Nenhuma | isPack(), packName(), minimumEdition(), forEdition() |
CapabilityRegistry | LicenseKey, padrões de rota | Resolução de rota para capacidade e busca de pacote antes do dispatch | Varia | Nenhuma | registerDefaultRoutes() cobre as rotas de serviço documentadas |
LicenseKey | Objeto de valor readonly | Claims de licença analisados e verificados | — | Nenhuma | isExpired(), isInGracePeriod(), isFullyExpired(), hasFeature(), hasCapability(), activePackNames(); maxSlots é apenas contratual |
LicenseValidator::buildVerifiedLicenseKey() | array $data | Constrói um LicenseKey tipado a partir de uma carga útil já verificada | LicenseKey | SpectrumAuthenticationException SPEC-AUTH-001 em violação de schema | Suporta schema 2.0, 1.0 e cargas úteis legadas |
PackDefinition / PackRegistry | Objetos de valor readonly | Estado de pacote de complemento com expiração e carência independentes | Varia | Nenhuma | isActive(), isFullyExpired(), activePacks(), activeCapabilities() |
TrialPolicy | bool $enabled, int $maxPagesPerSecond = 2, campos de marca d’água | Política de teto de taxa de processamento de avaliação | — | Nenhuma | fromLicenseKey(), disabled(), isThrottled(); a autoridade de marca permanece com o avaliador |
ChannelEnforcementPolicy::enforce() | LicenseKey $license, LocalState $state, int $systemNow, bool $revoked = false | Executa a máquina de dois temporizadores mais a revogação e a rerrotulagem de avaliação | EnforcementOutcome | Nenhuma | A revogação sobrepõe todo temporizador e estado de avaliação |
OnlineCheckScheduler::evaluate(), ::recordSuccessfulOnlineCheck() | Licença, estado local, timestamps | Avaliação de dois temporizadores; renovação de lease a partir do tempo verificado do servidor | EnforcementOutcome / LocalState | Nenhuma | ONLINE_GRACE_SECONDS concede 48 horas de carência de atividade após o lease |
EnforcementDecision / EnforcementReason / EnforcementOutcome | Enums + objeto de valor readonly | Active, Grace, DowngradedToCore mais o motivo preciso | — | Nenhuma | Cada motivo mapeia deterministicamente para uma decisão |
Runtime\EntitlementResolver::currentEntitlement() | Nenhum | Interface: o direito de uso imposto que o runtime serve | EntitlementResult | Definido pela implementação | EnforcedEntitlementResolver compõe cache, estado, política e avaliador, fail-closed para Core |
LicenseStateCache::get(), ::getOrThrow() | bool $forceRefresh = false | Cache de licença verificada que dá suporte ao gate | ?LicenseKey | getOrThrow(): SpectrumAuthenticationException SPEC-AUTH-008; LicenseConfigurationException em ligação inválida | invalidate(), isCacheValid() |
LicenseClient::activate(), ::heartbeat(), ::deactivate(), ::verifyOnline() | string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = null | Uma troca de status assinado; a resposta é verificada contra a raiz fixada (pinned) e vinculada ao nonce enviado | StatusResponse | LicenseClientException (transporte, não-200, nonce fornecido inválido); SpectrumAuthenticationException (resposta forjada, adulterada, desatualizada, com nonce incorreto, licença incorreta ou tipo incorreto) | Apenas o hash da impressão digital com salt é enviado, nunca uma impressão digital bruta |
LicenseClient::checkRenewal() | string $licenseId, string $customerId | Sondagem de disponibilidade de renovação; 404 é a resposta normal de “nenhuma disponível” | Array de renovação (available, download_url, expires_at) | LicenseClientException (inacessível, não-200/404 ou um download_url rejeitado pela política) | A URL do corpo não assinado passa por triagem anti-SSRF antes de poder escapar |
LicenseClient::__construct() | Ver bloco de assinatura | Valida o transporte, o esquema de URL e o conjunto de pins na construção | — | LicenseConfigurationException (transporte que não impõe política, esquema não permitido, HTTP simples sem pins, conjunto de pins malformado) | getPinSet() expõe o conjunto de pins ativo para ferramentas de rotação |
Online\StatusResponse | Objeto de valor readonly | O status assinado verificado | — | Nenhuma | isLive() é false em revoked / expired / released; carrega leaseExpiresAt, contagens de slots e um snapshot de direito de uso |
LicenseChannelMode / OnlineMode / OnlinePolicy | Enums + objeto de valor readonly | Claims de canal e de política on-line | — | Nenhuma | signed_source vs ioncube; modo on-line required / optional / disabled com intervalDays e leaseDays |
LicenseEdition | Enum baseado em string | Core, Pro, Enterprise | — | Nenhuma | satisfies() implementa a hierarquia de níveis |
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): arrayContrato de comportamento
Seção intitulada “Contrato de comportamento”A avaliação de direito de uso produz um de cinco estados atuais, cada um com uma consequência fixa em tempo de execução:
| Status | Runtime | Capacidades efetivas | Atualizações / suporte | Marca |
|---|---|---|---|---|
Active | permitido | edição concedida + pacotes ativos | sim (paga); não (avaliação) | nenhuma (paga); marca d’água (avaliação) |
GracePeriod | permitido | edição concedida + pacotes ativos | sim | nenhuma (paga) |
DowngradedToCore | permitido | apenas Core | não | nenhuma (paga); marca d’água (trial) |
EvaluationExpired | restrito | nenhuma | não | marca d’água |
NoLicense | desabilitado (fail-closed) | nenhuma | não | marca d’água |
- A expiração paga nunca desabilita o runtime instalado.
runtimeAllowedpermanece true para todo estado pago. Após a janela de carência, a edição efetiva é rebaixada para Core: as capacidades do Core continuam executando indefinidamente, todas as capacidades Pro/Enterprise/pacote são restringidas, e atualizações e suporte são revogados. O caso obsoletoEntitlementStatus::PerpetualFallbacknomeia a política de expiração pré-6.0 e existe apenas para compatibilidade de compilação. - Nem todo estado termina em execução no Core. A carência mantém a edição concedida completa com um aviso de renovação com data. A expiração de avaliação restringe o runtime e mantém a marca d’água. O estado sem licença desabilita os caminhos do Enterprise de forma fail-closed e aplica marca d’água visível a qualquer saída legada, de modo que nunca possa passar por execução paga.
- Ordem de resolução fixa. Uma licença totalmente expirada não resolve nenhuma capacidade. As capacidades de pacote recorrem ao próprio estado ativo e à expiração independente do pacote. As capacidades de edição são resolvidas contra a edição efetiva imposta, na hierarquia estrita Enterprise ⊇ Pro ⊇ Core. O
LicenseKey::$editionbruto nunca é consultado para restrição. - Dois temporizadores; o mais restritivo vence. O temporizador de direito de uso (ambos os canais) determina Ativo, Carência e o rebaixamento para Core após a carência. O temporizador de atividade on-line aplica-se apenas ao canal
ioncubecom o modo on-linerequired: o lease, mais uma carência de atividade de 48 horas, deve estar ativo. Offline após o lease, o premium pausa no nível Core; uma verificação on-line verificada posterior restabelece o lease e o premium é retomado. O canalsigned_source— e qualquer modo on-line não obrigatório — não tem temporizador de atividade e permanece offline e capaz de operar em air-gap. - O anti-rollback é determinístico. A imposição avalia contra um piso monotônico: o tempo efetivo é o máximo entre o relógio do sistema e o último tempo verificado, de modo que uma mudança de relógio para trás não concede tempo extra. Um rollback que excede a tolerância de desvio e a carência restante força o rebaixamento para Core.
- Os leases avançam apenas com tempo confiável. Uma verificação on-line bem-sucedida registra o tempo do servidor verificado e assinado, nunca o relógio local, de modo que um salto do relógio local para frente não pode inflar o lease.
- A marca tem uma única autoridade. Apenas o canal de avaliação aciona a marca d’água. Uma licença paga resolve para nenhuma marca em todos os estados, inclusive nos rebaixados.
- A avaliação (trial) é uma camada de política sobre os mesmos temporizadores. A taxa de processamento é limitada (padrão de 2 páginas/segundo), a marca d’água de avaliação é aplicada, e a expiração é estrita, sem carência. Apenas o motivo relatado muda; a decisão e a edição efetiva seguem a máquina paga.
- O contrato on-line é assinado de ponta a ponta. Cada requisição carrega um nonce de cliente CSPRNG. Cada resposta é um JWS EdDSA compacto de tipo de mídia
application/nextpdf-status+jwt, verificado por uma cadeia x5c até uma raiz fixada compilada no código e vinculado ao nonce enviado, ao id da licença instalada e ao endpoint invocado. O transporte legado de envelope não assinado foi descontinuado; resta exatamente um caminho de confiança. Os pins SPKI configurados viajam no cabeçalhoX-NextPDF-Pinned-Public-Key, e um conjunto de pins deve incluir um pin de backup. - Nenhuma imposição de assentos em tempo de execução.
maxSlotsé apenas contratual — sem telemetria e sem phone-home obrigatório para a operação comum.
Casos extremos e modos de falha
Seção intitulada “Casos extremos e modos de falha”- Uma verificação de capacidade em uma licença totalmente expirada faz curto-circuito para “indisponível” antes que qualquer lógica de pacote ou edição seja executada.
- Um pacote de complemento pode expirar enquanto a licença base está ativa. A negação passa então a ser pacote expirado (
SPEC-LIC-002), não não licenciado (SPEC-LIC-001), e lista os pacotes atualmente ativos. - Um arquivo local de estado de imposição que está presente, mas ilegível ou não analisável, é um sinal de adulteração. A máquina falha fechada (fail-closed) para o rebaixamento para Core com
EnforcementReason::CorruptState. Um arquivo legitimamente ausente não é corrompido e prossegue normalmente. - Um rollback de relógio abaixo do piso monotônico que excede a tolerância de desvio (padrão de 120 segundos) e a carência restante força o rebaixamento para Core de forma determinística.
- Um lease de atividade expirado rebaixa uma licença
ioncubeque de outra forma estaria Ativa; a expiração de direito de uso rebaixa independentemente do estado do lease. evaluate(null)é fail-closed: o runtime não é permitido, a marca d’água é aplicada, e o aviso nomeia a URL de preços. Hosts que precisam do comportamento Core sem licença devem construir o mecanismo Core diretamente.- Uma licença de avaliação expirada não tem carência nem fallback; o runtime fica restrito e a marca d’água permanece.
checkRenewal()trata o HTTP 404 como a resposta normal de “nenhuma disponível”. Qualquer outro não-200 lançaLicenseClientException, e umdownload_urlque viola a política de saída falha fechado antes de poder escapar do método.- Uma resposta de status forjada, adulterada, desatualizada, com nonce incorreto ou com licença incorreta nunca produz um
StatusResponse; a verificação lançaSpectrumAuthenticationException. Um status assinado, masrevoked,expiredoureleased, é verificado e se apresenta como um sinal de rebaixamento (isLive()é false). - Uma resposta de status emitida para uma troca diferente é rejeitada: o
response_typeverificado deve corresponder ao endpoint invocado. FeatureGatefalha fechado em qualquer erro do resolvedor: a edição efetiva é rebaixada paracoree nenhuma capacidade premium é concedida.EnforcedEntitlementResolveré fail-closed de ponta a ponta: qualquer exceção em sua cadeia produz o resultado sem licença (Core) e um log de erro PSR-3, nunca uma concessão premium.
Comportamento em modo FIPS
Seção intitulada “Comportamento em modo FIPS”A camada de licenciamento não adiciona nenhuma política criptográfica própria. As assinaturas de licença e de status são verificações Ed25519 realizadas pelo provedor de criptografia do host. Em um build com restrição FIPS, um algoritmo que o provedor não aprova falha no limite criptográfico com um erro explícito; nada é rebaixado silenciosamente. Estas são declarações de capacidade sobre o código do NextPDF: o NextPDF não é um módulo criptográfico validado, não possui nenhuma certificação e não concede nenhuma.
Conformidade
Seção intitulada “Conformidade”| Declaração | Padrão | Cláusula |
|---|---|---|
| Os arquivos de licença e as respostas de status são JWS de serialização compacta, verificados de forma fail-closed. | RFC 7515 | §3.1 |
| As assinaturas de licença e de status são Ed25519. | RFC 8032 | §5.1 |
| A cadeia x5c em uma resposta assinada valida até uma âncora de confiança fixada compilada no código. | RFC 5280 | §6.1 |
| Um conjunto de pins SPKI configurado deve incluir um pin de backup para uma chave ainda não implantada. | RFC 7469 | §4.3 |
Os claims verificados (iss, aud, exp, nbf, iat) são nomes de claim registrados. | RFC 7519 | §4.1 |
Todas as cláusulas são parafraseadas; nenhum texto normativo é reproduzido. O NextPDF não faz nenhuma declaração de certificação. Suporte não é igual a conformidade, e conformidade não é igual a certificação. O módulo alinha seu comportamento com as cláusulas citadas como uma capacidade; a aceitação de um envelope de licença ou de status é decidida pelo próprio verificador de raiz fixada do NextPDF, não por uma autoridade externa.
Notas de desenvolvimento
Seção intitulada “Notas de desenvolvimento”- Construa o
LicenseClientcom um transporte que imponha política (canonicamenteSecurityAwareHttpClient). Um cliente PSR-18 bruto é rejeitado na construção, de modo que o tráfego de licença nunca possa ser enviado sem os controles anti-SSRF, de não redirecionamento, de limite de bytes e de tempo limite. - Um nonce de cliente fornecido pelo chamador deve decodificar para pelo menos 16 bytes de entropia. A origem fundamenta esse limite na RFC 8555 §6.5; essa cláusula está fora do corpus citado, então o limite é declarado aqui apenas a partir da origem do produto.
- Restrinja recursos por meio de
FeatureGate; nunca ramifique com base noLicenseKey::$editionbruto. O gate consulta apenas a edição efetiva imposta e falha fechado paracore. - Não faça switch sobre o caso obsoleto
EntitlementStatus::PerpetualFallbackem código novo. Em vez disso, testeisDowngradedToCore()ou faça match emDowngradedToCore. - Trate uma negação de capacidade como uma carga útil de remediação. Apresente seu contexto estruturado e a URL de upgrade ao chamador em vez de reduzi-la a um erro genérico.
- Este módulo diz respeito a funcionalidade criptográfica; trate-o como sensível à segurança em sua própria revisão. Os termos de capacidade e de assentos são regidos pelo contrato de licença, não pela imposição em tempo de execução. Esta referência não é um parecer jurídico; consulte seus próprios assessores de conformidade e jurídicos.
Limite de publicação
Seção intitulada “Limite de publicação”Esta página documenta apenas o comportamento observável externamente e a superfície pública de API suportada. Caminhos de namespace internos, classes auxiliares, tabelas de mecanismo, nomes de arquivo de runbook e prefixos de tíquete estão fora do escopo.
Veja também
Seção intitulada “Veja também”- Licensing — NextPDF Enterprise — a página de capacidade com orientação de configuração e integração.
- Billing — Referência Profunda — níveis de plano, políticas de excedente e rollover.
- SaaS — Referência aprofundada — a superfície de serviço multi-tenant que o mapa de rotas protege.
- Branding — Referência aprofundada — as estratégias de marca que o avaliador resolve.