符规验证:进程内预检查配合外部 oracle
快速概览
标题为“快速概览”的章节本示例先运行 NextPDF 的纯 PHP 进程内符规验证器,将其作为快速的结构性预检查,再把决定性的符规判定交给独立验证器。进程内检查是必要条件,而非充分条件:通过只说明一个结构性事实,并非符规裁决。本示例由 examples/33-validate-conformance.php 及其 tests/Cookbook/Php/ValidateConformanceRecipeTest.php 测试文件支撑。
composer require nextpdf/core:^3进程内验证器不需要任何外部工具链。决定性的 gate 步骤需要在 PATH 中准备好一个外部验证器。本示例使用 veraPDF。你不需要 Pro 或 Enterprise 包。
概念总览
标题为“概念总览”的章节NextPDF 在 \NextPDF\Compliance\Validator 下提供进程内验证器。它们会验证特定的规范性不变量,无需执行任何外部进程:
PdfRValidator— ISO 23504-1(PDF/R-1)§5/§6 的字节流检查:文件头允许清单、generation-0 对象、§6.5.7 页面内容运算符允许清单(仅限q/Q/cm/Do),以及 §6.4.3 Info 字典键允许清单。它会返回一个扁平的PdfRValidationFinding[];空清单表示每一项受控的 §6 检查都通过了。ArlingtonValidator— 以仅报告模式驱动 PDF Association 的机器可读 Arlington 文法:它绝不会充当构建 gate,并会在每一条 finding 上记录已固定的文法提交 SHA,方便审计端对照已知的上游快照。
这些检查的范围有意收窄。它们能发现输出契约与规范之间的偏移,但并不为 PDF/A-4 或 PDF/UA-2 之类的配置文件建立 ISO 符规。这一判定属于独立验证器;它的裁决才应作为构建 gate(ISO 19005-4 §6.7.3 对 PDF/A 明确说明了这一点)。本示例清楚划定边界:先在进程内运行预检查,再打印并执行起决定作用的外部 oracle 命令。
下图展示了这道两阶段 gate。它只受一条规则约束:唯有外部 oracle 的裁决才能报告为符规。
API 接口
标题为“API 接口”的章节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";代码示例 — 生产环境
标题为“代码示例 — 生产环境”的章节生产环境的调用端会把进程内验证器作为一道低成本 gate,用来在出现明显结构性偏移时快速失败,随后再执行外部 oracle,获得决定性的符规判定。唯有 oracle 的裁决才能报告为符规。
$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,然后打印进程内 findings。普通 PDF 按预期会产生 PDF/R-1 findings,这个结果正是教学重点。随后,本示例会打印决定性的外部 oracle 命令。
边界情况与陷阱
标题为“边界情况与陷阱”的章节- 必要而非充分。
PdfRValidator返回空 finding 清单只表示受控的 §6 检查已通过,仅此而已。它不是 PDF/A-4 或 PDF/UA-2 的符规主张。绝不可仅凭进程内结果报告符规。 - 普通 PDF 按设计无法通过 PDF/R-1。 PDF/R-1 是仅含图像的栅格配置文件;普通文本 PDF 产生 §6.5.7 与 §6.4.3 findings 是合理且符合预期的。本示例刻意展示这一点,用来说明进程内输出是一项结构性事实,而非裁决。
- Arlington 是仅报告的。
ArlingtonValidator::validateReportOnly()绝不会抛出异常,也绝不会充当 gate。在仅文法模式下,它会发出一条infofinding,证明已固定的文法 SHA 已加载;当文法尚未具现化时,它会返回一个空清单。切勿基于它构建 pass/fail gate — 它是一项交叉检查产物。 - 字节 vs. 文件。
PdfRValidator::validate()接收原始字节字符串(OutputDestination::String);外部 oracle 则需要一个文件路径。请用save()持久化,供 oracle 步骤使用。 - 空输入。 将空字符串或不含文件头的字符串传给
PdfRValidator::validate()会返回一条§6.2.2错误 finding,而不是抛出异常。请检查 finding 清单;不要假定一定会抛出异常。
进程内验证器会对 PDF 进行单趟正则表达式与字节扫描。对一般文档而言,它们速度快、内存分配负担轻,并保持在 2000 ms / 128 MB 的预算之内。使用外部 oracle 时,它会主导整体耗时,但执行位置在进程外。本示例适用语义可重现性配置文件。本示例的价值在于可观察的验证行为;测试文件通过结构化 AST 与元数据比对来检查该行为。
安全性注意事项
标题为“安全性注意事项”的章节数据驻留与 PII 缓解
标题为“数据驻留与 PII 缓解”的章节验证器会在进程内读取文档字节,不会有任何内容离开该进程。然而,外部 oracle 会接收该文件。如果你运行的是托管验证器,文档内容就会离开你的边界。对于敏感内容,请优先使用本机验证器可执行文件,或先脱敏再验证。
安全遥测与日志清理
标题为“安全遥测与日志清理”的章节Findings 可能引用对象路径与运算符片段。本示例将 findings 写入 STDERR,并将一行固定的进度信息写入 STDOUT。对于敏感文档,请避免让 finding 日志进入共用接收端。绝不可记录原始 PDF 字节。
威胁模型
标题为“威胁模型”的章节干净的进程内结果并不代表完整性或真实性。恶意生成端可以制作一份能通过有限范围的进程内检查、却通不过完整验证器的文件,也可以制作一份格式正确但具有误导性的文件。请把进程内通过视为一道快速过滤,绝不可视为信任依据。
FIPS 模式行为
标题为“FIPS 模式行为”的章节本示例不执行任何密码学运算。FIPS 模式不会改变其行为。它不会执行签名、加密,也不会对信任素材做摘要。
| 陈述 | 规范 | 条款 | 参考 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 模型 | 文法 | |
| 符规由验证器决定,而非生成端。 | ISO 19005-4 | §6.7.3 |
NextPDF 的进程内验证器会验证特定的规范性不变量。支持不等于符规;验证不等于认证。 干净的进程内结果并不能建立 ISO 符规;这一判定必须由独立验证器(例如 veraPDF)作出。请将它的裁决作为构建 gate。