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

Проверка соответствия: внутрипроцессная предпроверка и внешний оракул

Этот рецепт запускает внутрипроцессные валидаторы соответствия NextPDF на чистом PHP для быстрой структурной предпроверки, а затем передаёт авторитетное решение о соответствии независимому валидатору. Внутрипроцессные проверки необходимы, но недостаточны: результат без замечаний — это структурный факт, а не вердикт о соответствии. В рецепте используются examples/33-validate-conformance.php и тестовая обвязка tests/Cookbook/Php/ValidateConformanceRecipeTest.php.

Окно терминала
composer require nextpdf/core:^3

Внутрипроцессным валидаторам не нужны внешние инструменты. Для этапа с авторитетным шлюзом нужен внешний валидатор в PATH. В примере используется veraPDF. Пакет Pro или Enterprise не требуется.

NextPDF включает внутрипроцессные валидаторы в пространстве имён \NextPDF\Compliance\Validator. Они проверяют конкретные нормативные инварианты без запуска внешнего процесса:

  • PdfRValidator — проверяет байтовый поток по ISO 23504-1 (PDF/R-1) §5/§6: список разрешённых заголовков файла, объекты поколения 0, список разрешённых операторов содержимого страницы по §6.5.7 (только q/Q/cm/Do) и список разрешённых ключей словаря Info по §6.4.3. Он возвращает плоский PdfRValidationFinding[]; пустой список означает, что все контролируемые проверки §6 пройдены.
  • ArlingtonValidator — выполняет машиночитаемую грамматику Arlington от PDF Association в режиме только отчёта. Он никогда не блокирует сборку и записывает в каждое замечание зафиксированный SHA коммита грамматики, чтобы участники аудита могли сопоставить его с известным снимком из апстрима.

Эти проверки намеренно ограничены по покрытию. Они выявляют расхождение между контрактом вывода и спецификацией, но не устанавливают соответствие ISO для такого профиля, как PDF/A-4 или PDF/UA-2. Это решает независимый валидатор, и именно его вердикт служит шлюзом сборки (ISO 19005-4 §6.7.3 прямо указывает это для PDF/A). Рецепт чётко проводит границу: он запускает предпроверку внутри процесса, а затем выводит и выполняет команду внешнего оракула, которая принимает решение.

Схема ниже показывает двухэтапный шлюз. Потоком управляет одно правило: только вердикт внешнего оракула можно представлять как соответствие.

Findings

Clean

Pass

Fail

Produced PDF bytes

In-process pre-check

PdfRValidator / Arlington

Structural drift?

Fail fast — cheap reject

NOT a conformance verdict

Necessary, not sufficient

never report as conformance

Independent external validator

the authoritative oracle

Oracle verdict

May report file conforming

Not conforming — do not ship

Diagram

Поверхность API генерируется из PHPDoc. Используйте эти основные точки входа:

  • \NextPDF\Compliance\Validator\PdfRValidator::validate(string $pdfBytes): list<PdfRValidationFinding>
  • \NextPDF\Compliance\Validator\PdfRValidationFinding (readonly: clause, severity, message)
  • \NextPDF\Compliance\Validator\ArlingtonValidator::validateReportOnly(string $pdfPath): list<ArlingtonFinding>
  • \NextPDF\Core\Document::output(?string $filename, OutputDestination $dest): string (OutputDestination::String для необработанных байтов)
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Compliance\Validator\PdfRValidator;
use NextPDF\Contracts\OutputDestination;
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->addPage();
$doc->setFont('helvetica', '', 12);
$doc->cell(0, 10, 'Document under conformance review.', newLine: true);
$bytes = $doc->output(dest: OutputDestination::String);
$findings = (new PdfRValidator())->validate($bytes);
// A finding list is a structural fact, not a conformance verdict.
echo $findings === []
? "No in-process PDF/R-1 findings (necessary, not sufficient).\n"
: count($findings) . " in-process finding(s); not a conformance verdict.\n";

В продакшене рассматривайте внутрипроцессный валидатор как недорогой шлюз, который быстро отклоняет очевидное структурное расхождение. Затем запускайте внешний оракул как источник авторитетного решения о соответствии. Только вердикт оракула можно объявлять соответствием.

examples/33-validate-conformance.php (gate core)
$bytes = $doc->output(dest: OutputDestination::String);
$doc->save($out);
// 1. In-process pre-check — necessary, not sufficient.
$findings = (new PdfRValidator())->validate($bytes);
foreach ($findings as $finding) {
fwrite(STDERR, sprintf("[%s] §%s — %s\n",
$finding->severity, $finding->clause, $finding->message));
}
// 2. The authoritative gate — the external validator decides.
$exitCode = 0;
$report = [];
exec('verapdf --flavour 4 ' . escapeshellarg($out), $report, $exitCode);
if ($exitCode !== 0) {
fwrite(STDERR, "veraPDF FAILED — not reported conforming\n");
fwrite(STDERR, implode("\n", $report) . "\n");
exit(1);
}
echo "veraPDF PASS — the validator reports the file conforming\n";

Запустите пример командой php examples/33-validate-conformance.php. Он создаёт обычный PDF и выводит внутрипроцессные замечания. Ожидается, что обычный PDF даст замечания PDF/R-1; этот результат как раз иллюстрирует суть. Затем пример выводит авторитетную команду внешнего оракула.

  • Необходимо, но недостаточно. Пустой список замечаний PdfRValidator означает, что контролируемые проверки §6 пройдены, и не более того. Это не заявление о соответствии PDF/A-4 или PDF/UA-2. Никогда не объявляйте соответствие только на основании внутрипроцессного результата.
  • Обычный PDF не проходит PDF/R-1 по своей природе. PDF/R-1 — это профиль только для растровых изображений; обычный текстовый PDF закономерно даёт замечания §6.5.7 и §6.4.3. Пример намеренно показывает это, чтобы подчеркнуть мысль: внутрипроцессный вывод — структурный факт, а не вердикт.
  • Arlington работает только в режиме отчёта. ArlingtonValidator::validateReportOnly() никогда не выбрасывает исключение и никогда не блокирует. В режиме только грамматики он выдаёт одно замечание уровня info, подтверждающее загрузку зафиксированного SHA грамматики; он возвращает пустой список, если грамматика не материализована. Не стройте на нём шлюз pass/fail — это артефакт перекрёстной проверки.
  • Байты и файл. PdfRValidator::validate() принимает необработанную строку байтов (OutputDestination::String); внешнему оракулу нужен путь к файлу. Сохраните файл с помощью save() для шага с оракулом.
  • Пустой ввод. Передача пустой строки или строки без заголовка в PdfRValidator::validate() возвращает замечание об ошибке §6.2.2, а не выбрасывает исключение. Проверяйте список замечаний; не рассчитывайте на исключение.

Внутрипроцессные валидаторы используют однопроходное сканирование PDF регулярными выражениями и по байтам. Для типичных документов они работают быстро и потребляют мало памяти, оставаясь в пределах бюджета 2000 мс / 128 МБ. Если внешний оракул используется, основное время выполнения уходит на него, но он работает вне процесса. Применяется семантический профиль воспроизводимости. Ценность примера — в его наблюдаемом поведении при проверке, а обвязка контролирует это поведение через сравнение структурного абстрактного синтаксического дерева (AST) и метаданных.

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

Безопасная телеметрия и очистка журналов

Заголовок раздела «Безопасная телеметрия и очистка журналов»

Замечания могут цитировать пути к объектам и фрагменты операторов. Пример выводит замечания в STDERR, а фиксированную строку прогресса — в STDOUT. Для конфиденциальных документов храните журналы замечаний отдельно от общих приёмников. Никогда не записывайте в журнал необработанные байты PDF.

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

Этот рецепт не выполняет криптографических операций. Режим Federal Information Processing Standards (FIPS) не меняет его поведение. Подписание, шифрование или вычисление дайджеста доверенного материала не выполняется.

УтверждениеСпецификацияПунктreference_id (идентификатор ссылки)
Содержимое страницы PDF/R-1 использует только список разрешённых операторов q/Q/cm/Do.ISO 23504-1§6.5.7
Страницы PDF/R-1 содержат только растровое содержимое из изображений.ISO 23504-1§6.5.5
PDF/R-1 ограничивает ключи словаря информации о документе.ISO 23504-1§6.4.4
Грамматика Arlington — машиночитаемая перекрёстная проверка объектной модели.Arlington PDF Model (модель)грамматика (grammar)
Соответствие определяет валидатор, а не производитель.ISO 19005-4§6.7.3

Внутрипроцессные валидаторы NextPDF проверяют конкретные нормативные инварианты. Поддержка — это не соответствие; проверка — это не сертификация. Результат внутрипроцессной проверки без замечаний не устанавливает соответствие ISO; это определяет независимый валидатор (например, veraPDF). Используйте его вердикт как шлюз сборки.