Перейти к содержимому
getnextpdf.com

Enterprise редакция

Evidence — глубокий справочник

Эта страница — глубокий справочник по модулю NextPDF\Enterprise\Evidence. Модуль запечатывает выявленные при валидации проблемы в неизменяемый EvidencePackage, экспортирует его как детерминированный JSON со стабильным дайджестом SHA-256, сохраняет через подключаемый контракт хранилища и отслеживает регрессии между прогонами с помощью ContinuousMonitor. Модуль потребляет находки, произведённые поверхностями Validation и Compliance; сам он не выполняет проверок соответствия. За рекомендациями по рабочему процессу сначала прочитайте страницу возможности Evidence.

Эта возможность поставляется в NextPDF Enterprise (nextpdf/enterprise) и активируется лицензионным конвертом уровня Enterprise. Развёртывание без этого права не загружает классы возможности. Сравнить редакции и получить лицензию.

Поверхность лицензируется возможностью enterprise.compliance.evidence; отказанное право отказывает в функции. Core и Pro производят находки и отчёты; запечатывание находок в неизменяемый, детерминированный, при необходимости снабжённый меткой времени пакет с отслеживанием регрессий не имеет эквивалента уровня Core или Pro.

Окно терминала
composer require nextpdf/enterprise:^3
СимволПараметрыПоведение по умолчаниюВозвращаетБросает или завершается ошибкойПримечания
EvidencePortal::__constructEvidenceStoreInterface $store, EvidenceExporter $exporterСвязывает хранилище и экспортёрEvidencePortalНичего не объявленоОба сотрудника внедряемы
EvidencePortal::generateEvidencestring $documentHash, list<EvidenceRecord> $records, ?string $tsaTimestamp = nullПодсчитывает pass/fail, запечатывает пакет со свежим UUID id и системным generatedAt, сохраняет егоEvidencePackageНичего не объявленоСохраняет через store(), а не persistImmutable()
EvidencePortal::getEvidencestring $documentHashПоследний сохранённый пакет для хеша?EvidencePackageНичего не объявленоnull, когда ничего не сохранено
EvidencePortal::getHistorystring $documentHashПолная история, новейшие первымиlist<EvidencePackage>Ничего не объявленоПорядок задаётся хранилищем
EvidencePortal::exportAsJsonEvidencePackage $packageДелегирует экспортёруnon-empty-stringJsonExceptionТе же байты, что и EvidenceExporter::toJson
EvidencePackage::__constructвосемь именованных параметров, см. блок кодаНеизменяемый объект-значениеEvidencePackageНичего не объявленоСчётчики не проверяются относительно $records
EvidencePackage::allPassedнетfailedCount === 0boolНичего не объявленоtrue для пустого пакета; проверяйте totalFindings
EvidencePackage::passRateнетpassedCount / totalFindingsfloatНичего не объявлено0.0, когда totalFindings === 0
EvidenceRecord::__constructstring $policyName, bool $passed, string $details, string $validatorVersion, DateTimeImmutable $timestampНеизменяемый результат одной проверки политикиEvidenceRecordНичего не объявленоВсе свойства public readonly
EvidenceExporter::toJsonEvidencePackage $packageJSON с фиксированным порядком ключей; неэкранированные слэши и Unicodenon-empty-stringJsonExceptionПорядок ключей несущий
EvidenceExporter::exportHashEvidencePackage $packageSHA-256 над байтами toJson()non-empty-string (64 hex)JsonExceptionСтабилен для пакета
EvidenceStoreInterface::storeEvidencePackage $packageДобавляет; допускается история по хешу документаvoidОпределяется реализациейТребуется семантика только-добавления
EvidenceStoreInterface::persistImmutableEvidencePackage $packageWORM-запись там, где бэкенд её поддерживаетvoidОпределяется реализациейНе-WORM бэкенды ведут себя как store()
EvidenceStoreInterface::findByDocumentHashstring $documentHashСамый свежий пакет для хеша?EvidencePackageОпределяется реализацией
EvidenceStoreInterface::findAllByDocumentHashstring $documentHashВсе пакеты для хеша, новейшие первымиlist<EvidencePackage>Определяется реализацией
EvidenceStoreInterface::countнетОбщее число сохранённых пакетовint<0, max>Определяется реализацией
InMemoryEvidenceStoreклассХранилище на массиве для тестов и разработкиn/an/aНе долговечно; без семантики WORM
ContinuousMonitor::__constructEvidenceStoreInterface $storeСвязывает хранилищеContinuousMonitorНичего не объявлено
ContinuousMonitor::checkEvidencePackage $currentEvidence, string $documentHashСравнивает имена проваленных политик с сохранённым последним пакетомMonitorResultНичего не объявленоПервая проверка считает каждый текущий провал новым
ContinuousMonitor::isDuestring $documentHash, MonitorSchedule $scheduleНаступает, когда прежних доказательств нет, интервал истёк или сохранённые доказательства датированы будущимboolНичего не объявленоОтказоустойчивость при рассинхронизации часов
MonitorResult::__constructвосемь именованных параметров, см. блок кодаНеизменяемый результат сравненияMonitorResultНичего не объявленоВключает оба пакета и checkedAt
MonitorSchedule::__constructMonitorFrequency $frequency, int $retentionDays = 90, bool $alertOnNewIssues = trueОбъект-значение конфигурацииMonitorScheduleНичего не объявленоХранение и оповещения обеспечиваются хостом
MonitorFrequencyперечисление на строкахСлучаи Daily, Weekly, Monthlyn/an/aБазовые значения daily, weekly, monthly
MonitorFrequency::intervalSecondsнетИнтервал на случай: 86400, 604800, 2592000positive-intНичего не объявленоMonthly — фиксированные 30 дней
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 — точка входа запечатывания. Внешне наблюдаемые правила:

  1. Сборка. generateEvidence подсчитывает прошедшие и проваленные записи и устанавливает totalFindings в их сумму. Он присваивает свежий UUID packageId версии 4, штампует generatedAt по системным часам, сохраняет пакет через EvidenceStoreInterface::store и возвращает его. Список записей встраивается в заданном порядке, без изменений.
  2. Неизменяемость. EvidencePackagefinal readonly и никогда не мутирует после конструирования; он пригоден для WORM-хранения. allPassed() — это failedCount === 0. passRate() — это passedCount / totalFindings и 0.0, когда totalFindings === 0.
  3. Детерминированный экспорт. EvidenceExporter::toJson выдаёт конверт и каждую запись с фиксированным, написанным вручную порядком ключей; последовательность записей следует за пакетом. Кодирование строгое и бросает исключение при сбое, слэши и Unicode остаются неэкранированными (JSON_UNESCAPED_SLASHES). Метки времени сериализуются с DateTimeInterface::RFC3339_EXTENDED — расширенной формой RFC 3339 с дробными секундами. exportHash возвращает 64-символьный шестнадцатеричный дайджест SHA-256 ровно над этими байтами. Один и тот же пакет всегда даёт один и тот же дайджест, на любом хосте, в любое время. Повторная генерация доказательств для того же документа даёт новые packageId и generatedAt, а значит новый дайджест: детерминизм привязан к пакету, а не к документу.
  4. Метка времени — свидетельство времени, а не вердикт. Пакет может нести необязательный предоставленный вызывающим токен RFC 3161 (в кодировке base64). Токен привязывает данные пакета к значению времени. Модуль встраивает его как непрозрачную строку; он не запрашивает, не разбирает и не проверяет токены и не ручается за TSA. Проверка токена относится к модулям Signature и Security.
  5. Отслеживание регрессий. ContinuousMonitor::check загружает сохранённый последний пакет для хеша документа и сравнивает уникальные имена проваленных политик. Проблемы классифицируются как newIssues (провалено сейчас, не раньше), resolvedIssues (провалено раньше, не сейчас) и unchangedIssues (провалено в обоих). hasChanges равно true только когда есть новые или устранённые проблемы; одни лишь неизменившиеся провалы сообщают false. При первой проверке каждый текущий провал является новым.
  6. Планирование. ContinuousMonitor::isDue возвращает true, когда для хеша нет доказательств, когда прошедшее с сохранённого generatedAt время достигает интервала частоты расписания или когда сохранённые доказательства датированы будущим относительно опрашивающего хоста. Случай будущей даты отказоустойчив: в худшем случае лишняя перепроверка, но никогда не пропущенная.
  7. Контракт хранилища. Реализации EvidenceStoreInterface должны поддерживать семантику только-добавления; несколько пакетов на хеш документа образуют историю, новейшие первыми. persistImmutable нацелен на WORM-совместимые бэкенды; не-WORM реализации должны вести себя точно как store.
  • Пустой пакет сообщает allPassed() true и passRate() 0.0. Проверяйте totalFindings > 0, прежде чем трактовать пакет как прохождение.
  • Прямое конструирование EvidencePackage не проверяет счётчики относительно $records. Используйте портал или сами поддерживайте согласованность счётчиков.
  • generateEvidence сохраняет перед возвратом. Запускайте ContinuousMonitor::check с новым пакетом до его сохранения; проверка после сохранения сравнивает пакет сам с собой и сообщает об отсутствии изменений.
  • exportHash покрывает точные байты toJson. Дайджест, пересчитанный любым другим сериализатором, порядком ключей или политикой экранирования, не совпадёт.
  • MonitorFrequency::Monthly — фиксированное окно в 30 дней, а не календарный месяц.
  • MonitorSchedule::$retentionDays и $alertOnNewIssues — конфигурация, переносимая для планировщиков хоста. Модуль никогда не удаляет доказательства и никогда не отправляет оповещения.
  • InMemoryEvidenceStore предназначено для тестов и разработки. Пакеты теряются при выходе процесса, а его persistImmutable не имеет семантики WORM.
  • Строки details записи экспортируются дословно; экспортёр ничего не редактирует. Держите секреты и регулируемые персональные данные вне details. Резидентность, хранение и контроль доступа следуют реализации хранилища оператора.
  • Аргумент tsaTimestamp принимается как непрозрачная строка. Некорректный токен встраивается без изменений и проявляется только при последующей проверке.

Этот модуль вычисляет дайджесты SHA-256 и встраивает предоставленный вызывающим токен RFC 3161. Он не выполняет подписания и не хранит ключей. Поведение в режиме FIPS управляется модулями Security и Signature.

УтверждениеСтандартПункт
Токен метки времени указывает, что данные существовали в конкретный момент времени.IETF RFC 3161§2
Экспортируемые метки времени используют интернет-профиль даты/времени ISO 8601 с дробными секундами.IETF RFC 3339§5.6
Материал проверки, встроенный внутрь PDF, относится к Document Security Store; эта поверхность принадлежит модулю Signature, а не данному.ISO 32000-2:2020§12.8.4

Все пункты пересказаны; NextPDF не воспроизводит нормативный текст. NextPDF не делает заявлений о сертификации. Сбор доказательств поддерживает рабочие процессы аудита; это не юридическая аттестация и не аудиторская сертификация. Токен метки времени — свидетельство только времени, и этот модуль не утверждает, что какое-либо содержимое соответствует требованиям. Валидность и соответствие остаются свойствами итогового файла плюс валидатора. Этот справочник не является юридическим заключением; обратитесь к собственным консультантам по соответствию и юридическим вопросам.

  • Исходный код модуля несёт @since 2.2.0; этот справочник документирует поверхность в том виде, в каком она поставляется в nextpdf/enterprise 3.1.0.
  • Всё выполняется внутри процесса на вашем хосте. Модуль не выполняет сетевого ввода-вывода и никогда не обращается к TSA сам.
  • Порядок ключей в массивном литерале экспортёра несущий по замыслу. Его изменение изменило бы exportHash и сделало бы ранее сохранённые дайджесты недействительными; исходный код это запрещает.
  • packageId — это UUID версии 4, собранный из вывода \random_bytes(16); идентификаторы уникальны, но не воспроизводимы.
  • Долговечное хранение предоставляет хост. Обеспечение WORM и контроль доступа — ответственность оператора; хранилище в памяти — единственная поставляемая реализация.
  • MonitorResult — объект-значение final readonly; его восемь свойств public, включая checkedAt — системное время проверки.

Эта страница документирует только внешне наблюдаемое поведение и поддерживаемую публичную поверхность API. Внутренние пути пространств имён, вспомогательные классы, таблицы механизмов, имена файлов руководств по эксплуатации и префиксы тикетов вне области действия.