Ir al contenido
getnextpdf.com

Enterprise edición

Licenciamiento — Referencia detallada

Esta página es la referencia detallada de la superficie de licencias de NextPDF Enterprise: el módulo que resuelve todas las demás capacidades de Enterprise. Abarca el modelo de estados de derecho de uso (EntitlementEvaluator, EntitlementStatus, EntitlementResult), la restricción forzada de capacidades (FeatureGate, CapabilityCode, CapabilityRegistry), la máquina de aplicación de canal con dos temporizadores (ChannelEnforcementPolicy, OnlineCheckScheduler) y el cliente en línea firmado (LicenseClient). La evaluación ordinaria de derechos de uso no necesita red. El cliente en línea existe para las operaciones explícitas de activación, latido, desactivación, verificación en línea y sondeo de renovación. El detalle del mecanismo interno permanece en la documentación interna del repositorio de origen y queda fuera del alcance de este manual.

Esta capacidad se distribuye en NextPDF Enterprise (nextpdf/enterprise) y se activa con un sobre de licencia de nivel Enterprise. Un despliegue sin ese derecho de uso no carga las clases de la capacidad. Comparar ediciones y obtener una licencia.

Licensing es una superficie base de Enterprise. Siempre está presente una vez que el paquete Enterprise se instala junto al paquete Core, porque es la superficie que resuelve todo lo demás. NextPDF Pro no tiene una superficie de derecho de uso separada; el modelo de estados, la máquina de aplicación y el cliente en línea se distribuyen únicamente en nextpdf/enterprise. NextPDF Core (Apache-2.0) no tiene ningún modelo de derecho de uso: un host que necesite el comportamiento Apache-2.0 sin licencia usa el motor Core directamente, no el pipeline de Enterprise.

Todos los tipos residen en NextPDF\Enterprise\Licensing. La máquina de aplicación se encuentra en el subespacio de nombres Channel, la composición del tiempo de ejecución en Runtime y los tipos de estado firmado en Online.

SímboloParámetrosComportamiento predeterminadoDevuelveLanza o falla conNotas
EntitlementEvaluator::evaluate()?LicenseKey $license, ?DateTimeImmutable $now = nullAsigna una licencia verificada (o null) a la decisión completa de derecho de usoEntitlementResultNingunaUna licencia null produce el resultado «sin licencia» cerrado de forma segura
EntitlementEvaluator::evaluateEnforced()?LicenseKey $license, EnforcementOutcome $outcomeConvierte un resultado de aplicación precalculado en un resultado de derecho de usoEntitlementResultNingunaLa edición efectiva proviene del resultado; toda degradación por aplicación recae en Core
EntitlementEvaluator::resolveBrandingMode(), ::resolveBrandingStrategy()?LicenseKey $license, ?DateTimeImmutable $now = nullResuelve la decisión de marca para la salida generadaBrandingMode / BrandingStrategyNingunaAutoridad única sobre la marca; solo el canal de evaluación aplica marca de agua
EntitlementResultObjeto de valor de solo lecturaTransporta el estado, la edición, el canal, el modo de marca, los indicadores de tiempo de ejecución/actualización/soporte y una advertencia opcionalNingunaAyudantes: isFullyActive(), isExpired(), isDowngradedToCore(), shouldApplyEvaluationBranding()
EntitlementStatusEnum respaldado por cadenaActive, GracePeriod, DowngradedToCore, EvaluationExpired, NoLicenseNingunaPerpetualFallback se conserva pero está obsoleto; se mantiene solo para que los consumidores anteriores a 6.0 sigan compilando
FeatureGate::hasCapability()CapabilityCode $capabilityComprueba la capacidad frente a la edición efectiva forzada y al estado de los paquetesboolNingunaSe cierra de forma segura a core ante cualquier error del resolvedor
FeatureGate::requireCapability()CapabilityCode $capabilityPasa en silencio o lanza con contexto estructurado de venta adicionalvoidSpectrumAuthenticationException SPEC-LIC-001 (sin licencia) o SPEC-LIC-002 (paquete caducado)El contexto transporta required_capability, required_pack, current_packs, upgrade_info_url
FeatureGate::isFeatureEnabled(), ::requireFeature()string $featureComprobación heredada por identificador de funciónbool / voidSpectrumAuthenticationException SPEC-AUTH-007 (vía require)Compatibilidad heredada; prefiere las comprobaciones de capacidad
Descriptores de acceso de FeatureGateNingunoIntrospección de licenciaVaríaNingunacurrentEdition(), isLicenseValid(), isInGracePeriod(), getActivePacks(), trialPolicy()
CapabilityCodeEnum respaldado por cadenaIdentificadores canónicos de capacidad (core.*, pro.*, enterprise.*, pack.*)NingunaisPack(), packName(), minimumEdition(), forEdition()
CapabilityRegistryLicenseKey, patrones de rutaResolución de ruta a capacidad y búsqueda de paquete antes del despachoVaríaNingunaregisterDefaultRoutes() cubre las rutas de servicio documentadas
LicenseKeyObjeto de valor de solo lecturaClaims de licencia analizados y verificadosNingunaisExpired(), isInGracePeriod(), isFullyExpired(), hasFeature(), hasCapability(), activePackNames(); maxSlots es solo contractual
LicenseValidator::buildVerifiedLicenseKey()array $dataConstruye un LicenseKey tipado a partir de una carga útil ya verificadaLicenseKeySpectrumAuthenticationException SPEC-AUTH-001 ante una violación de esquemaAdmite cargas útiles de esquema 2.0, 1.0 y heredadas
PackDefinition / PackRegistryObjetos de valor de solo lecturaEstado de paquete complementario con caducidad y gracia independientesVaríaNingunaisActive(), isFullyExpired(), activePacks(), activeCapabilities()
TrialPolicybool $enabled, int $maxPagesPerSecond = 2, campos de marca de aguaPolítica de tope de rendimiento del modo de pruebaNingunafromLicenseKey(), disabled(), isThrottled(); la autoridad sobre la marca permanece en el evaluador
ChannelEnforcementPolicy::enforce()LicenseKey $license, LocalState $state, int $systemNow, bool $revoked = falseEjecuta la máquina de dos temporizadores más la revocación y el reetiquetado del modo de pruebaEnforcementOutcomeNingunaLa revocación prevalece sobre todos los temporizadores y sobre el estado de prueba
OnlineCheckScheduler::evaluate(), ::recordSuccessfulOnlineCheck()Licencia, estado local, marcas de tiempoEvaluación de dos temporizadores; renovación del arrendamiento a partir del tiempo verificado del servidorEnforcementOutcome / LocalStateNingunaONLINE_GRACE_SECONDS concede 48 horas de gracia de vida más allá del arrendamiento
EnforcementDecision / EnforcementReason / EnforcementOutcomeEnums + objeto de valor de solo lecturaActive, Grace, DowngradedToCore más el motivo precisoNingunaCada motivo se asigna de forma determinista a una decisión
Runtime\EntitlementResolver::currentEntitlement()NingunoInterfaz: el derecho de uso forzado que sirve el tiempo de ejecuciónEntitlementResultDefinido por la implementaciónEnforcedEntitlementResolver compone caché, estado, política y evaluador, con cierre seguro a Core
LicenseStateCache::get(), ::getOrThrow()bool $forceRefresh = falseCaché de licencia verificada que respalda el indicador?LicenseKeygetOrThrow(): SpectrumAuthenticationException SPEC-AUTH-008; LicenseConfigurationException ante un cableado no válidoinvalidate(), isCacheValid()
LicenseClient::activate(), ::heartbeat(), ::deactivate(), ::verifyOnline()string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = nullUn intercambio de estado firmado; la respuesta se verifica frente a la raíz fijada y se vincula al nonce enviadoStatusResponseLicenseClientException (transporte, no-200, nonce suministrado incorrecto); SpectrumAuthenticationException (respuesta falsificada, manipulada, obsoleta, con nonce incorrecto, licencia incorrecta o tipo incorrecto)Solo se envía el hash con sal de la huella digital, nunca una huella digital en bruto
LicenseClient::checkRenewal()string $licenseId, string $customerIdSondeo de disponibilidad de renovación; 404 es la respuesta normal de «ninguna disponible»Arreglo de renovación (available, download_url, expires_at)LicenseClientException (inaccesible, no-200/404 o un download_url rechazado por la política)La URL del cuerpo sin firmar se filtra contra SSRF antes de que pueda escapar
LicenseClient::__construct()Ver el bloque de firmaValida el transporte, el esquema de URL y el conjunto de fijaciones en la construcciónLicenseConfigurationException (transporte que no aplica la política, esquema no permitido, HTTP plano sin fijaciones, conjunto de fijaciones mal formado)getPinSet() expone el conjunto de fijaciones activo para las herramientas de rotación
Online\StatusResponseObjeto de valor de solo lecturaEl estado firmado verificadoNingunaisLive() es false en revoked / expired / released; transporta leaseExpiresAt, recuentos de puestos y una instantánea del derecho de uso
LicenseChannelMode / OnlineMode / OnlinePolicyEnums + objeto de valor de solo lecturaClaims de canal y de política en líneaNingunasigned_source frente a ioncube; modo en línea required / optional / disabled con intervalDays y leaseDays
LicenseEditionEnum respaldado por cadenaCore, Pro, EnterpriseNingunasatisfies() implementa la jerarquía de niveles
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

La evaluación de derechos de uso produce uno de cinco estados actuales, cada uno con una consecuencia fija en tiempo de ejecución:

EstadoTiempo de ejecuciónCapacidades efectivasActualizaciones / soporteMarca
Activepermitidoedición con derecho + paquetes activossí (de pago); no (evaluación)ninguna (de pago); marca de agua (evaluación)
GracePeriodpermitidoedición con derecho + paquetes activosninguna (de pago)
DowngradedToCorepermitidosolo Corenoninguna (de pago); marca de agua (prueba)
EvaluationExpiredrestringidoningunanomarca de agua
NoLicensedeshabilitado (cierre seguro)ningunanomarca de agua
  • La caducidad de pago nunca deshabilita el tiempo de ejecución instalado. runtimeAllowed permanece true en todos los estados de pago. Pasada la ventana de gracia, la edición efectiva degrada a Core: las capacidades de Core siguen ejecutándose indefinidamente, todas las capacidades de Pro/Enterprise/paquete se bloquean y las actualizaciones y el soporte quedan revocados. El caso obsoleto EntitlementStatus::PerpetualFallback nombra la política de caducidad anterior a 6.0 y existe solo por compatibilidad de compilación.
  • No todos los estados terminan en ejecución de Core. La gracia mantiene la edición completa con derecho junto con una advertencia de renovación fechada. La caducidad de evaluación restringe el tiempo de ejecución y mantiene la marca de agua. El estado «sin licencia» deshabilita las vías de Enterprise con cierre seguro y aplica una marca de agua visible a cualquier salida heredada, de modo que nunca pueda pasar por una ejecución de pago.
  • Orden de resolución fijo. Una licencia totalmente caducada no resuelve ninguna capacidad. Las capacidades de paquete se remiten al propio estado activo y a la caducidad independiente del paquete. Las capacidades de edición se resuelven frente a la edición efectiva forzada, en la jerarquía estricta Enterprise ⊇ Pro ⊇ Core. Nunca se consulta el LicenseKey::$edition en bruto para la restricción.
  • Dos temporizadores; gana el más restrictivo. El temporizador de derecho de uso (ambos canales) impulsa Active, Grace y la degradación a Core posterior a la gracia. El temporizador de vida en línea se aplica únicamente al canal ioncube con el modo en línea required: el arrendamiento, más una gracia de vida de 48 horas, debe estar vigente. Sin conexión y pasado el arrendamiento, la funcionalidad premium se pausa en el nivel Core; una comprobación en línea verificada posterior restablece el arrendamiento y la funcionalidad premium se reanuda. El canal signed_source —y cualquier modo en línea distinto de required— no tiene temporizador de vida y sigue siendo capaz de operar sin conexión y con aislamiento total (air-gap).
  • La protección contra retroceso es determinista. La aplicación evalúa frente a un piso monótono: el tiempo efectivo es el máximo entre el reloj del sistema y el último tiempo verificado, de modo que un retroceso del reloj no concede tiempo adicional. Un retroceso que supere la tolerancia de desfase y la gracia restante fuerza la degradación a Core.
  • Los arrendamientos avanzan solo con tiempo de confianza. Una comprobación en línea correcta registra el tiempo del servidor verificado y firmado, nunca el reloj local, de modo que un salto hacia delante del reloj local no puede inflar el arrendamiento.
  • La marca tiene una única autoridad. Solo el canal de evaluación activa la marca de agua. Una licencia de pago se resuelve sin marca en todos los estados, incluidos los degradados.
  • El modo de prueba es una capa de política sobre los mismos temporizadores. El rendimiento tiene un tope (2 páginas por segundo de forma predeterminada), se aplica la marca de agua de evaluación y la caducidad es estricta, sin gracia. Solo cambia el motivo informado; la decisión y la edición efectiva siguen la máquina de pago.
  • El contrato en línea está firmado de extremo a extremo. Cada solicitud transporta un nonce de cliente CSPRNG. Cada respuesta es un JWS EdDSA compacto de tipo de medio application/nextpdf-status+jwt, verificado mediante una cadena x5c hasta una raíz fijada compilada en el binario y vinculado al nonce enviado, al id de licencia instalado y al endpoint invocado. El transporte heredado del sobre sin firma se ha retirado; queda exactamente una vía de confianza. Las fijaciones SPKI configuradas viajan como el encabezado X-NextPDF-Pinned-Public-Key, y un conjunto de fijaciones debe incluir una fijación de respaldo.
  • Sin aplicación de puestos en tiempo de ejecución. maxSlots es solo contractual: sin telemetría ni phone-home obligatorio para el funcionamiento ordinario.
  • Una comprobación de capacidad sobre una licencia totalmente caducada cortocircuita a «no disponible» antes de que se ejecute cualquier lógica de paquete o de edición.
  • Un paquete complementario puede caducar mientras la licencia base está activa. La denegación se lee entonces como paquete caducado (SPEC-LIC-002), no como sin licencia (SPEC-LIC-001), y enumera los paquetes actualmente activos.
  • Un archivo local de estado de aplicación que está presente pero es ilegible o no se puede analizar es una señal de manipulación. La máquina se cierra de forma segura hacia la degradación a Core con EnforcementReason::CorruptState. Un archivo legítimamente ausente no está corrupto y continúa con normalidad.
  • Un retroceso del reloj por debajo del piso monótono que supere la tolerancia de desfase (120 segundos de forma predeterminada) y la gracia restante fuerza la degradación a Core de forma determinista.
  • Un arrendamiento de vida caducado degrada una licencia ioncube que por lo demás estaría Active; la caducidad del derecho de uso degrada con independencia del estado del arrendamiento.
  • evaluate(null) se cierra de forma segura: el tiempo de ejecución no se permite, se aplica la marca de agua y la advertencia indica la URL de precios. Los hosts que necesiten el comportamiento de Core sin licencia deben construir el motor Core directamente.
  • Una licencia de evaluación caducada no tiene gracia ni reserva; el tiempo de ejecución queda restringido y la marca de agua permanece.
  • checkRenewal() trata el HTTP 404 como la respuesta normal de «ninguna disponible». Cualquier otro no-200 lanza LicenseClientException, y un download_url que infrinja la política saliente se cierra de forma segura antes de que pueda escapar del método.
  • Una respuesta de estado falsificada, manipulada, obsoleta, con nonce incorrecto o con licencia incorrecta nunca produce un StatusResponse; la verificación lanza SpectrumAuthenticationException. Un estado firmado pero revoked, expired o released se verifica y aflora como señal de degradación (isLive() es false).
  • Una respuesta de estado acuñada para un intercambio diferente se rechaza: el response_type verificado debe coincidir con el endpoint invocado.
  • FeatureGate se cierra de forma segura ante cualquier error del resolvedor: la edición efectiva degrada a core y no se concede ninguna capacidad premium.
  • EnforcedEntitlementResolver se cierra de forma segura de extremo a extremo: cualquier excepción en su cadena produce el resultado «sin licencia» (Core) y un registro de error PSR-3, nunca una concesión premium.

La capa de licencias no añade ninguna política criptográfica propia. Las firmas de licencia y de estado son verificaciones Ed25519 que realiza el proveedor criptográfico del host. En una compilación restringida por FIPS, un algoritmo que el proveedor no aprueba falla en el límite criptográfico con un error explícito; nada degrada de forma silenciosa. Estas son afirmaciones de capacidad sobre el código de NextPDF: NextPDF no es un módulo criptográfico validado, no posee ninguna certificación y no concede ninguna.

AfirmaciónEstándarCláusula
Los archivos de licencia y las respuestas de estado son JWS de serialización compacta, verificados con cierre seguro.RFC 7515§3.1
Las firmas de licencia y de estado son Ed25519.RFC 8032§5.1
La cadena x5c de una respuesta firmada se valida hasta un ancla de confianza fijada compilada en el binario.RFC 5280§6.1
Un conjunto de fijaciones SPKI configurado debe incluir una fijación de respaldo para una clave aún no desplegada.RFC 7469§4.3
Los claims verificados (iss, aud, exp, nbf, iat) son nombres de claim registrados.RFC 7519§4.1

Todas las cláusulas están parafraseadas; no se reproduce ningún texto normativo. NextPDF no formula ninguna afirmación de certificación. El soporte no equivale a la conformidad, y la conformidad no equivale a la certificación. El módulo alinea su comportamiento con las cláusulas citadas como una capacidad; la aceptación de un sobre de licencia o de estado la decide el propio verificador de raíz fijada de NextPDF, no una autoridad externa.

  • Construir LicenseClient con un transporte que aplique la política (canónicamente SecurityAwareHttpClient). Un cliente PSR-18 en bruto se rechaza en la construcción para que el tráfico de licencias nunca pueda enviarse sin los controles anti-SSRF, de no redirección, de tope de bytes y de tiempo de espera.
  • Un nonce de cliente suministrado por quien llama debe decodificarse a al menos 16 bytes de entropía. El código de origen fundamenta este límite en RFC 8555 §6.5; esa cláusula queda fuera del corpus citado, por lo que aquí el límite se enuncia únicamente a partir del código de origen del producto.
  • Restringir las funciones a través de FeatureGate; nunca bifurcar según el LicenseKey::$edition en bruto. El indicador consulta únicamente la edición efectiva forzada y se cierra de forma segura a core.
  • No utilizar el caso obsoleto EntitlementStatus::PerpetualFallback en código nuevo. En su lugar, comprobar isDowngradedToCore() o hacer coincidir DowngradedToCore.
  • Tratar una denegación de capacidad como una carga útil de subsanación. Mostrar su contexto estructurado y su URL de actualización a quien llama en lugar de reducirla a un error genérico.
  • Este módulo concierne a funcionalidad criptográfica; tratarlo como sensible para la seguridad en la propia revisión. Los términos de capacidad y de puestos se rigen por el contrato de licencia, no por la aplicación en tiempo de ejecución. Esta referencia no constituye una opinión jurídica; consultar a los propios asesores de cumplimiento y jurídicos.

Esta página documenta únicamente el comportamiento observable desde el exterior y la superficie de API pública admitida. Las rutas de espacio de nombres internas, las clases auxiliares, las tablas de mecanismos, los nombres de archivo de runbook y los prefijos de tickets quedan fuera del alcance.