Ir al contenido
getnextpdf.com

Enterprise edición

Evidencia — Referencia detallada

Esta página es la referencia detallada del módulo NextPDF\Enterprise\Evidence. El módulo sella los hallazgos de validación en un EvidencePackage inmutable, lo exporta como JSON determinista con un resumen SHA-256 estable, lo persiste a través de un contrato de almacén conectable y realiza el seguimiento de regresiones entre ejecuciones con ContinuousMonitor. El módulo consume los hallazgos producidos por las superficies de Validation y Compliance; no realiza comprobaciones de conformidad por sí mismo. Para orientación sobre el flujo de trabajo, lee primero la página de capacidad de Evidence.

Esta capacidad se distribuye en NextPDF Enterprise (nextpdf/enterprise) y se activa con un envoltorio 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.

La superficie está licenciada por la capacidad enterprise.compliance.evidence; un derecho de uso denegado deniega la función. Core y Pro producen hallazgos e informes; sellar los hallazgos en un paquete inmutable, determinista, con marca de tiempo opcional y con seguimiento de regresiones no tiene equivalente en el nivel Core ni en el nivel Pro.

Ventana de terminal
composer require nextpdf/enterprise:^3
SímboloParámetrosComportamiento por defectoDevuelveLanza o falla conNotas
EvidencePortal::__constructEvidenceStoreInterface $store, EvidenceExporter $exporterConecta el almacén y el exportadorEvidencePortalNada declaradoAmbos colaboradores son inyectables
EvidencePortal::generateEvidencestring $documentHash, list<EvidenceRecord> $records, ?string $tsaTimestamp = nullCuenta aprobados/fallidos, sella un paquete con un id UUID nuevo y generatedAt de reloj del sistema, y lo persisteEvidencePackageNada declaradoPersiste mediante store(), no persistImmutable()
EvidencePortal::getEvidencestring $documentHashÚltimo paquete almacenado para el hash?EvidencePackageNada declaradonull cuando no hay ninguno almacenado
EvidencePortal::getHistorystring $documentHashHistorial completo, del más reciente al más antiguolist<EvidencePackage>Nada declaradoEl orden lo suministra el almacén
EvidencePortal::exportAsJsonEvidencePackage $packageDelega en el exportadornon-empty-stringJsonExceptionLos mismos bytes que EvidenceExporter::toJson
EvidencePackage::__constructocho parámetros con nombre, ver el bloqueObjeto de valor inmutableEvidencePackageNada declaradoLos recuentos no se validan frente a $records
EvidencePackage::allPassedningunofailedCount === 0boolNada declaradotrue para un paquete vacío; condiciona mediante totalFindings
EvidencePackage::passRateningunopassedCount / totalFindingsfloatNada declarado0.0 cuando totalFindings === 0
EvidenceRecord::__constructstring $policyName, bool $passed, string $details, string $validatorVersion, DateTimeImmutable $timestampResultado inmutable de una única comprobación de políticaEvidenceRecordNada declaradoTodas las propiedades son public readonly
EvidenceExporter::toJsonEvidencePackage $packageJSON con orden de claves fijo; barras y Unicode sin escaparnon-empty-stringJsonExceptionEl orden de las claves es determinante
EvidenceExporter::exportHashEvidencePackage $packageSHA-256 sobre los bytes de toJson()non-empty-string (64 hex)JsonExceptionEstable por paquete
EvidenceStoreInterface::storeEvidencePackage $packageAñade; se permite historial por hash de documentovoidDefinido por la implementaciónSe requiere semántica de solo anexado
EvidenceStoreInterface::persistImmutableEvidencePackage $packageEscritura WORM donde el backend lo admitevoidDefinido por la implementaciónLos backends no WORM se comportan como store()
EvidenceStoreInterface::findByDocumentHashstring $documentHashPaquete más reciente para el hash?EvidencePackageDefinido por la implementación
EvidenceStoreInterface::findAllByDocumentHashstring $documentHashTodos los paquetes para el hash, del más reciente al más antiguolist<EvidencePackage>Definido por la implementación
EvidenceStoreInterface::countningunoNúmero total de paquetes almacenadosint<0, max>Definido por la implementación
InMemoryEvidenceStoreclaseAlmacén respaldado por array para pruebas y desarrollon/an/aNo duradero; sin semántica WORM
ContinuousMonitor::__constructEvidenceStoreInterface $storeConecta el almacénContinuousMonitorNada declarado
ContinuousMonitor::checkEvidencePackage $currentEvidence, string $documentHashCompara los nombres de políticas fallidas con el último paquete almacenadoMonitorResultNada declaradoLa primera comprobación trata cada fallo actual como nuevo
ContinuousMonitor::isDuestring $documentHash, MonitorSchedule $scheduleProcede cuando no hay evidencia previa, ha transcurrido el intervalo o la evidencia almacenada tiene fecha futuraboolNada declaradoA prueba de fallos ante desviación del reloj
MonitorResult::__constructocho parámetros con nombre, ver el bloqueResultado de comparación inmutableMonitorResultNada declaradoIncluye ambos paquetes y checkedAt
MonitorSchedule::__constructMonitorFrequency $frequency, int $retentionDays = 90, bool $alertOnNewIssues = trueObjeto de valor de configuraciónMonitorScheduleNada declaradoLa retención y las alertas las aplica el host
MonitorFrequencyenum respaldado por stringCasos Daily, Weekly, Monthlyn/an/aValores de respaldo daily, weekly, monthly
MonitorFrequency::intervalSecondsningunoIntervalo por caso: 86400, 604800, 2592000positive-intNada declaradoMonthly son 30 días fijos
final class EvidencePortal
{
public function __construct(
private readonly EvidenceStoreInterface $store,
private readonly EvidenceExporter $exporter,
)
public function generateEvidence(string $documentHash, array $records, ?string $tsaTimestamp = null): EvidencePackage
public function getEvidence(string $documentHash): ?EvidencePackage
public function getHistory(string $documentHash): array
public function exportAsJson(EvidencePackage $package): string
}
final readonly class EvidencePackage
{
public function __construct(
public string $packageId,
public string $documentHash,
public array $records,
public int $totalFindings,
public int $passedCount,
public int $failedCount,
public DateTimeImmutable $generatedAt,
public ?string $tsaTimestamp = null,
)
public function allPassed(): bool
public function passRate(): float
}
final readonly class EvidenceRecord
{
public function __construct(
public string $policyName,
public bool $passed,
public string $details,
public string $validatorVersion,
public DateTimeImmutable $timestamp,
)
}
final readonly class EvidenceExporter
{
public function toJson(EvidencePackage $package): string
public function exportHash(EvidencePackage $package): string
}
interface EvidenceStoreInterface
{
public function store(EvidencePackage $package): void;
public function persistImmutable(EvidencePackage $package): void;
public function findByDocumentHash(string $documentHash): ?EvidencePackage;
public function findAllByDocumentHash(string $documentHash): array;
public function count(): int;
}
final class ContinuousMonitor
{
public function __construct(
private readonly EvidenceStoreInterface $store,
)
public function check(EvidencePackage $currentEvidence, string $documentHash): MonitorResult
public function isDue(string $documentHash, MonitorSchedule $schedule): bool
}
final readonly class MonitorSchedule
{
public function __construct(
public MonitorFrequency $frequency,
public int $retentionDays = 90,
public bool $alertOnNewIssues = true,
)
}
enum MonitorFrequency: string
{
case Daily = 'daily';
case Weekly = 'weekly';
case Monthly = 'monthly';
public function intervalSeconds(): int
}

EvidencePortal::generateEvidence(string $documentHash, list<EvidenceRecord> $records, ?string $tsaTimestamp = null): EvidencePackage es el punto de entrada de sellado. Reglas observables desde el exterior:

  1. Ensamblaje. generateEvidence cuenta los registros aprobados y fallidos y fija totalFindings como su suma. Asigna un packageId UUID versión 4 nuevo, marca generatedAt con el reloj del sistema, persiste el paquete a través de EvidenceStoreInterface::store y lo devuelve. La lista de registros se incrusta en el orden dado, sin modificar.
  2. Inmutabilidad. EvidencePackage es final readonly y nunca se muta tras su construcción; es apto para almacenamiento WORM. allPassed() es failedCount === 0. passRate() es passedCount / totalFindings, y 0.0 cuando totalFindings === 0.
  3. Exportación determinista. EvidenceExporter::toJson emite el envoltorio y cada registro con un orden de claves fijo y escrito a mano; la secuencia de registros sigue al paquete. La codificación es estricta y lanza una excepción en caso de fallo, con las barras y el Unicode sin escapar (JSON_UNESCAPED_SLASHES). Las marcas de tiempo se serializan con DateTimeInterface::RFC3339_EXTENDED, la forma extendida de RFC 3339 con segundos fraccionarios. exportHash devuelve el resumen hexadecimal SHA-256 de 64 caracteres sobre exactamente esos bytes. El mismo paquete siempre produce el mismo resumen, en cualquier host y en cualquier momento. Regenerar la evidencia para el mismo documento produce un packageId y un generatedAt nuevos, y por tanto un resumen nuevo: el determinismo es por paquete, no por documento.
  4. La marca de tiempo es evidencia del momento, no un veredicto. Un paquete puede transportar un token RFC 3161 opcional suministrado por quien llama (codificado en base64). El token vincula el dato del paquete a un valor de tiempo. El módulo lo incrusta como una cadena opaca; no recupera, analiza ni verifica los tokens, y no avala la TSA. La verificación de tokens corresponde a los módulos Signature y Security.
  5. Seguimiento de regresiones. ContinuousMonitor::check carga el último paquete almacenado para el hash de documento y compara los nombres únicos de políticas fallidas. Los problemas se clasifican como newIssues (falla ahora, no antes), resolvedIssues (falló antes, no ahora) y unchangedIssues (falla en ambos). hasChanges es true solo cuando existen problemas nuevos o resueltos; los fallos sin cambios por sí solos devuelven false. En una primera comprobación, cada fallo actual es nuevo.
  6. Programación. ContinuousMonitor::isDue devuelve true cuando no existe evidencia para el hash, cuando el tiempo transcurrido desde el generatedAt almacenado alcanza el intervalo de frecuencia de la programación, o cuando la evidencia almacenada tiene fecha futura respecto al host que realiza el sondeo. El caso de fecha futura es a prueba de fallos: en el peor caso una recomprobación adicional, nunca una omitida.
  7. Contrato del almacén. Las implementaciones de EvidenceStoreInterface deben admitir semántica de solo anexado; múltiples paquetes por hash de documento forman el historial, del más reciente al más antiguo. persistImmutable está destinado a backends con capacidad WORM; las implementaciones no WORM deben comportarse exactamente como store.
  • Un paquete vacío devuelve allPassed() true y passRate() 0.0. Condiciona mediante totalFindings > 0 antes de tratar un paquete como una aprobación.
  • La construcción directa de EvidencePackage no valida los recuentos frente a $records. Usa el portal, o mantén tú mismo los recuentos coherentes.
  • generateEvidence persiste antes de devolver. Ejecuta ContinuousMonitor::check con el paquete nuevo antes de persistirlo; una comprobación después de la persistencia compara el paquete consigo mismo y no informa de cambios.
  • exportHash cubre exactamente los bytes de toJson. Un resumen recalculado por cualquier otro serializador, orden de claves o política de escapado no coincidirá.
  • MonitorFrequency::Monthly es una ventana fija de 30 días, no un mes natural.
  • MonitorSchedule::$retentionDays y $alertOnNewIssues son configuración que se transporta para los planificadores del host. El módulo nunca elimina evidencia y nunca envía alertas.
  • InMemoryEvidenceStore es para pruebas y desarrollo. Los paquetes se pierden al salir del proceso, y su persistImmutable no tiene semántica WORM.
  • Las cadenas details de los registros se exportan de forma literal; el exportador no redacta. Mantén los secretos y los datos personales regulados fuera de details. La residencia, la retención y el control de acceso dependen de la implementación de almacén del operador.
  • El argumento tsaTimestamp se acepta como una cadena opaca. Un token mal formado se incrusta sin cambios y solo aflora en la verificación posterior.

Este módulo calcula resúmenes SHA-256 e incrusta un token RFC 3161 suministrado por quien llama. No realiza firma ni custodia de claves. El comportamiento en modo FIPS lo gobiernan los módulos Security y Signature.

AfirmaciónEstándarCláusula
Un token de marca de tiempo indica que un dato existió en un momento concreto.IETF RFC 3161§2
Las marcas de tiempo exportadas usan el perfil de fecha/hora de Internet de ISO 8601, con segundos fraccionarios.IETF RFC 3339§5.6
El material de validación incrustado dentro de un PDF pertenece al Document Security Store; esa superficie es del módulo Signature, no de este.ISO 32000-2:2020§12.8.4

Todas las cláusulas están parafraseadas; NextPDF no reproduce el texto normativo. NextPDF no formula ninguna afirmación de certificación. La captura de evidencia respalda los flujos de trabajo de auditoría; no es una atestación jurídica ni una certificación de auditoría. Un token de marca de tiempo es evidencia del momento únicamente, y este módulo no afirma que ningún contenido sea conforme. La validez y la conformidad siguen siendo propiedades del archivo final más un validador. Esta referencia no constituye una opinión jurídica; consulta a tus propios asesores de cumplimiento y jurídicos.

  • El código fuente del módulo lleva @since 2.2.0; esta referencia documenta la superficie tal como se distribuye en nextpdf/enterprise 3.1.0.
  • Todo se ejecuta en proceso en tu host. El módulo no realiza E/S de red y nunca contacta por sí mismo con una TSA.
  • El orden de claves del literal de array del exportador es determinante por diseño. Reordenarlo cambiaría exportHash e invalidaría los resúmenes almacenados previamente; el código fuente lo prohíbe.
  • packageId es un UUID versión 4 ensamblado a partir de la salida de \random_bytes(16); los identificadores son únicos pero no reproducibles.
  • La persistencia duradera la suministra el host. La aplicación de WORM y el control de acceso son responsabilidad del operador; el almacén en memoria es la única implementación incluida.
  • MonitorResult es un objeto de valor final readonly; sus ocho propiedades son public, incluida checkedAt, la hora de reloj del sistema de la comprobación.

Esta página documenta únicamente el comportamiento observable desde el exterior y la superficie de API pública compatible. 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.