Enterprise edición
Licenciamiento — Referencia detallada
De un vistazo
Sección titulada «De un vistazo»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.
Disponibilidad y licencia
Sección titulada «Disponibilidad y licencia»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.
Superficie de la API pública
Sección titulada «Superficie de la API pública»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ímbolo | Parámetros | Comportamiento predeterminado | Devuelve | Lanza o falla con | Notas |
|---|---|---|---|---|---|
EntitlementEvaluator::evaluate() | ?LicenseKey $license, ?DateTimeImmutable $now = null | Asigna una licencia verificada (o null) a la decisión completa de derecho de uso | EntitlementResult | Ninguna | Una licencia null produce el resultado «sin licencia» cerrado de forma segura |
EntitlementEvaluator::evaluateEnforced() | ?LicenseKey $license, EnforcementOutcome $outcome | Convierte un resultado de aplicación precalculado en un resultado de derecho de uso | EntitlementResult | Ninguna | La edición efectiva proviene del resultado; toda degradación por aplicación recae en Core |
EntitlementEvaluator::resolveBrandingMode(), ::resolveBrandingStrategy() | ?LicenseKey $license, ?DateTimeImmutable $now = null | Resuelve la decisión de marca para la salida generada | BrandingMode / BrandingStrategy | Ninguna | Autoridad única sobre la marca; solo el canal de evaluación aplica marca de agua |
EntitlementResult | Objeto de valor de solo lectura | Transporta el estado, la edición, el canal, el modo de marca, los indicadores de tiempo de ejecución/actualización/soporte y una advertencia opcional | — | Ninguna | Ayudantes: isFullyActive(), isExpired(), isDowngradedToCore(), shouldApplyEvaluationBranding() |
EntitlementStatus | Enum respaldado por cadena | Active, GracePeriod, DowngradedToCore, EvaluationExpired, NoLicense | — | Ninguna | PerpetualFallback se conserva pero está obsoleto; se mantiene solo para que los consumidores anteriores a 6.0 sigan compilando |
FeatureGate::hasCapability() | CapabilityCode $capability | Comprueba la capacidad frente a la edición efectiva forzada y al estado de los paquetes | bool | Ninguna | Se cierra de forma segura a core ante cualquier error del resolvedor |
FeatureGate::requireCapability() | CapabilityCode $capability | Pasa en silencio o lanza con contexto estructurado de venta adicional | void | SpectrumAuthenticationException 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 $feature | Comprobación heredada por identificador de función | bool / void | SpectrumAuthenticationException SPEC-AUTH-007 (vía require) | Compatibilidad heredada; prefiere las comprobaciones de capacidad |
Descriptores de acceso de FeatureGate | Ninguno | Introspección de licencia | Varía | Ninguna | currentEdition(), isLicenseValid(), isInGracePeriod(), getActivePacks(), trialPolicy() |
CapabilityCode | Enum respaldado por cadena | Identificadores canónicos de capacidad (core.*, pro.*, enterprise.*, pack.*) | — | Ninguna | isPack(), packName(), minimumEdition(), forEdition() |
CapabilityRegistry | LicenseKey, patrones de ruta | Resolución de ruta a capacidad y búsqueda de paquete antes del despacho | Varía | Ninguna | registerDefaultRoutes() cubre las rutas de servicio documentadas |
LicenseKey | Objeto de valor de solo lectura | Claims de licencia analizados y verificados | — | Ninguna | isExpired(), isInGracePeriod(), isFullyExpired(), hasFeature(), hasCapability(), activePackNames(); maxSlots es solo contractual |
LicenseValidator::buildVerifiedLicenseKey() | array $data | Construye un LicenseKey tipado a partir de una carga útil ya verificada | LicenseKey | SpectrumAuthenticationException SPEC-AUTH-001 ante una violación de esquema | Admite cargas útiles de esquema 2.0, 1.0 y heredadas |
PackDefinition / PackRegistry | Objetos de valor de solo lectura | Estado de paquete complementario con caducidad y gracia independientes | Varía | Ninguna | isActive(), isFullyExpired(), activePacks(), activeCapabilities() |
TrialPolicy | bool $enabled, int $maxPagesPerSecond = 2, campos de marca de agua | Política de tope de rendimiento del modo de prueba | — | Ninguna | fromLicenseKey(), disabled(), isThrottled(); la autoridad sobre la marca permanece en el evaluador |
ChannelEnforcementPolicy::enforce() | LicenseKey $license, LocalState $state, int $systemNow, bool $revoked = false | Ejecuta la máquina de dos temporizadores más la revocación y el reetiquetado del modo de prueba | EnforcementOutcome | Ninguna | La revocación prevalece sobre todos los temporizadores y sobre el estado de prueba |
OnlineCheckScheduler::evaluate(), ::recordSuccessfulOnlineCheck() | Licencia, estado local, marcas de tiempo | Evaluación de dos temporizadores; renovación del arrendamiento a partir del tiempo verificado del servidor | EnforcementOutcome / LocalState | Ninguna | ONLINE_GRACE_SECONDS concede 48 horas de gracia de vida más allá del arrendamiento |
EnforcementDecision / EnforcementReason / EnforcementOutcome | Enums + objeto de valor de solo lectura | Active, Grace, DowngradedToCore más el motivo preciso | — | Ninguna | Cada motivo se asigna de forma determinista a una decisión |
Runtime\EntitlementResolver::currentEntitlement() | Ninguno | Interfaz: el derecho de uso forzado que sirve el tiempo de ejecución | EntitlementResult | Definido por la implementación | EnforcedEntitlementResolver compone caché, estado, política y evaluador, con cierre seguro a Core |
LicenseStateCache::get(), ::getOrThrow() | bool $forceRefresh = false | Caché de licencia verificada que respalda el indicador | ?LicenseKey | getOrThrow(): SpectrumAuthenticationException SPEC-AUTH-008; LicenseConfigurationException ante un cableado no válido | invalidate(), isCacheValid() |
LicenseClient::activate(), ::heartbeat(), ::deactivate(), ::verifyOnline() | string $licenseJws, string $deploymentId, ?string $machineFingerprintHash = null, ?string $expectedLicenseId = null, ?string $clientNonce = null | Un intercambio de estado firmado; la respuesta se verifica frente a la raíz fijada y se vincula al nonce enviado | StatusResponse | LicenseClientException (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 $customerId | Sondeo 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 firma | Valida el transporte, el esquema de URL y el conjunto de fijaciones en la construcción | — | LicenseConfigurationException (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\StatusResponse | Objeto de valor de solo lectura | El estado firmado verificado | — | Ninguna | isLive() es false en revoked / expired / released; transporta leaseExpiresAt, recuentos de puestos y una instantánea del derecho de uso |
LicenseChannelMode / OnlineMode / OnlinePolicy | Enums + objeto de valor de solo lectura | Claims de canal y de política en línea | — | Ninguna | signed_source frente a ioncube; modo en línea required / optional / disabled con intervalDays y leaseDays |
LicenseEdition | Enum respaldado por cadena | Core, Pro, Enterprise | — | Ninguna | satisfies() implementa la jerarquía de niveles |
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 comportamiento
Sección titulada «Contrato de comportamiento»La evaluación de derechos de uso produce uno de cinco estados actuales, cada uno con una consecuencia fija en tiempo de ejecución:
| Estado | Tiempo de ejecución | Capacidades efectivas | Actualizaciones / soporte | Marca |
|---|---|---|---|---|
Active | permitido | edición con derecho + paquetes activos | sí (de pago); no (evaluación) | ninguna (de pago); marca de agua (evaluación) |
GracePeriod | permitido | edición con derecho + paquetes activos | sí | ninguna (de pago) |
DowngradedToCore | permitido | solo Core | no | ninguna (de pago); marca de agua (prueba) |
EvaluationExpired | restringido | ninguna | no | marca de agua |
NoLicense | deshabilitado (cierre seguro) | ninguna | no | marca de agua |
- La caducidad de pago nunca deshabilita el tiempo de ejecución instalado.
runtimeAllowedpermanece 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 obsoletoEntitlementStatus::PerpetualFallbacknombra 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::$editionen 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
ioncubecon el modo en línearequired: 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 canalsigned_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 encabezadoX-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.
maxSlotses solo contractual: sin telemetría ni phone-home obligatorio para el funcionamiento ordinario.
Casos límite y modos de fallo
Sección titulada «Casos límite y modos de fallo»- 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
ioncubeque 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 lanzaLicenseClientException, y undownload_urlque 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 lanzaSpectrumAuthenticationException. Un estado firmado perorevoked,expiredoreleasedse 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_typeverificado debe coincidir con el endpoint invocado. FeatureGatese cierra de forma segura ante cualquier error del resolvedor: la edición efectiva degrada acorey no se concede ninguna capacidad premium.EnforcedEntitlementResolverse 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.
Comportamiento en modo FIPS
Sección titulada «Comportamiento en modo FIPS»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.
Conformidad
Sección titulada «Conformidad»| Afirmación | Estándar | Clá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.
Notas de desarrollo
Sección titulada «Notas de desarrollo»- Construir
LicenseClientcon un transporte que aplique la política (canónicamenteSecurityAwareHttpClient). 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 elLicenseKey::$editionen bruto. El indicador consulta únicamente la edición efectiva forzada y se cierra de forma segura acore. - No utilizar el caso obsoleto
EntitlementStatus::PerpetualFallbacken código nuevo. En su lugar, comprobarisDowngradedToCore()o hacer coincidirDowngradedToCore. - 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.
Límite de publicación
Sección titulada «Límite de publicación»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.
Consulta también
Sección titulada «Consulta también»- Licensing — NextPDF Enterprise — la página de la capacidad con orientación de configuración e integración.
- Billing — Referencia detallada — niveles de plan, políticas de exceso y traspaso de saldo.
- SaaS — Referencia detallada — la superficie de servicio multiinquilino que protege el mapa de rutas.
- Branding — Referencia detallada — las estrategias de marca que resuelve el evaluador.