一致性(conformance):ConformanceMode 的路由与验证边界
NextPDF\Conformance 带有唯一的判别符(discriminator),用来告诉 writer 文件锁定哪一个 ISO 合约。库只输出合约定义的结构。它不会、也无法保证最终产出的文件符合规范。只有外部验证器(validator)才能认证一致性。
composer require nextpdf/core:^3概念总览
标题为“概念总览”的章节Conformance 模块有两个公开类型。ConformanceMode 是一个带底层值的枚举(enum),用来命名目标合约(Plain、PdfUa1、PdfUa2、PdfA2、PdfA3、PdfA3b、PdfA3u、PdfA4、PdfA4e、PdfA4f)。ConformancePolicy 是一个不可变的值对象,把模式与彼此正交的严格度开关组合在一起。
模式是下游 writer 各个闸门(gate)的唯一事实来源。在这个枚举出现之前,引擎会根据零散的标记推断「这份文件是否已按规范添加标签?」——而那些标记四散各处。ConformanceMode::isTagged()、isAccessibility()、isArchival()、pdfaPart()、pdfaConformanceLetter() 与 requiresPdf17() 各自返回一个类型化答案,供 writer 直接读取。目录(catalog)、/MarkInfo、文件头继承关系,以及 XMP 的 pdfaid 标记都会与所声明的意图保持一致。
请准确理解这条支持边界。NextPDF Core 输出 这些标准定义的结构。ISO 19005-4:2020 §6.7.3 规定了用于记录某个文件宣称属于哪个 PDF/A 变体的识别架构。ISO 19005-4:2020 明确规定,一致性的实际判定必须依据其第 5 条进行——也就是依照规范性要求,由检查工具来判定,而不是由生成文件的库来判定。ISO 14289-2:2024 §6 把一致性界定为某个 文件 满足的属性。NextPDF 设置模式是构成合规文件的必要输入。但模式本身并不是一致性的结果。
这正是 CSS 支持矩阵所采用的「已验证对宣称」(Verified-versus-Claimed)纪律。只有在存在一次通过的测试或 oracle 执行结果,并附有引用条号时,某项能力才算 已验证。其余一切都只是库 输出 的实现——有用,但不是一致性保证。一致性是最终文件经过验证器验证后才具备的属性,而不是库的承诺。请用 veraPDF 验证输出(见下方「一致性」一节)。
还有第二条边界对归档工作很重要。PDF/A-4 的 创建——OutputIntent 字典、内嵌的 ICC 配置文件,以及 XMP 扩展架构——随 nextpdf/pro 扩展包提供,而非由 Core 提供。在仅安装 Core 的环境里,Document::enablePdfA() 会抛出 InvalidConfigException,因为 security.pdfa 能力并未注册。Core 仍保留 ConformanceMode 这个判别符(因此自省与 PDF/UA-2 加标签路径都可运行),但它无法独自创建 PDF/A-4 文件。
API 接口
标题为“API 接口”的章节| 类型 | 种类 | 主要成员 |
|---|---|---|
NextPDF\Conformance\ConformanceMode | enum: string | Plain、PdfUa1、PdfUa2、PdfA2、PdfA3、PdfA3b、PdfA3u、PdfA4、PdfA4e、PdfA4f;isTagged()、isAccessibility()、isArchival()、requiresPdfUa2PageTabs()、pdfaPart(): ?int、pdfaConformanceLetter(): string、requiresPdf17(): bool |
NextPDF\Conformance\ConformancePolicy | final readonly class | __construct(ConformanceMode $mode = PdfUa2, bool $strictUa2 = false, bool $rejectUnvalidatedLang = false, …);lax()、strictUa2()、withUax9IsolateSupport()、withoutAstShadowMode()、withBlackPointCompensation()、withStrictOcspProducedAtTolerance()、withAllowStaleOcsp() |
ConformancePolicy 在其构造函数中强制一条不变式:严格的 PDF/UA-2 开关只有在模式为 PdfUa2 时才适用,而且 strictUa2 = true 会强制 rejectUnvalidatedLang = true。不一致的组合会抛出 InvalidConfigException,而不是默默降级。
代码示例——快速上手
标题为“代码示例——快速上手”的章节<?php
declare(strict_types=1);
use NextPDF\Conformance\ConformanceMode;
$mode = ConformanceMode::PdfA4f;
// Introspect the declared contract — these drive writer-side gates.$mode->pdfaPart(); // 4$mode->pdfaConformanceLetter(); // 'F'$mode->requiresPdf17(); // false (PDF/A-4 is PDF 2.0 lineage)$mode->isArchival(); // true代码示例——生产环境
标题为“代码示例——生产环境”的章节Core 随附的、能够端到端演练一份一致性合约的路径,就是 PDF/UA-2 加标签路径。下面这个可执行示例(examples/31-pdfua2-tagged.php)同时也是严格 PDF/UA-2 配置文件的 oracle 目标。
<?php
declare(strict_types=1);
use NextPDF\Core\Document;
$doc = Document::createStandalone();
// Set the tagged-PDF contract BEFORE writing content so the HTML pipeline// wires the TaggedContentEmitter at parser-construction time.$doc->enableTaggedPdf(lang: 'en');
$doc->setTitle('Accessible report');// … write content …
$doc->save(__DIR__ . '/out/report-ua2.pdf');
// The library has now emitted PDF/UA-2 structures. It has NOT asserted// conformance. Verify the file with the pinned veraPDF oracle://// php oracle/run.php pdfua.strict//// (Requires the veraPDF Docker image — opt-in; see "Conformance" below.)边界情况与陷阱
标题为“边界情况与陷阱”的章节- PDF/A-4 的创建属于 Premium。 在仅安装 Core 的环境里,
Document::enablePdfA()会抛出InvalidConfigException(security.pdfa无法使用)。Core 掌握的是判别符,而不是 OutputIntent/ICC/XMP 的输出。请见/specifications/pdfa4/。 - 总括枚举项与变体枚举项。
PdfA4是总括枚举项,返回的pdfaConformanceLetter()为空。ISO 19005-4:2020 §6.7.3 规定,既不符合 PDF/A-4e 也不符合 PDF/A-4f 的文件不提供pdfa:conformance。仅在 Annex B/Annex A 变体时才使用PdfA4e/PdfA4f。 - 严格 PDF/UA-2 采用选择加入。
ConformancePolicy::lax()是不破坏向后兼容的默认值。strictUa2()会强制/MarkInfo /Marked true并拒绝不符合 BCP-47 的内容。在非PdfUa2模式上启用它会抛出异常。 isTagged()会识别变体。Plain、PdfA2、PdfA3b与PdfA4e都会返回未加标签。writer 不得假设归档模式就代表存在一棵结构树。- 通过的模式不等于通过的文件。 设置
PdfA4并不会让输出成为有效的 PDF/A-4 文件。请运行验证器。
ConformanceMode 与 ConformancePolicy 都是纯值类型:枚举项的 resolve(解析)与 match 分派都是 O(1),除了那个不可变的 policy 对象之外不会额外分配内存。它们对写入路径不会增加任何可测量的成本。主导模块预算(wall_ms: 1500)的是 writer,而不是这个判别符。veraPDF oracle 是带外的 CI 步骤,并非文件生成的一部分。
安全性注意事项
标题为“安全性注意事项”的章节应用在 ConformancePolicy 上的严格开关,用来守住 fail-closed 的安全行为:securityPkiRfc5280Strict(RFC 5280 §6 路径验证)、strictOcspProducedAtTolerance(RFC 6960 §4.2.2.1 时间偏移窗口),以及 allowStaleOcsp(默认为 false——拒绝 OCSP 中缺少 nextUpdate 的响应)。这些默认值偏保守,并会按照已文档化的向后兼容策略,在未来某个主版本中切换为严格。关于签名路径的细节,请见 安全性模块与本项目的威胁模型。
一致性
标题为“一致性”的章节NextPDF 不认证一致性。它输出下列标准定义的结构,再由独立的验证器判定某个 文件 是否符合规范。
| 标准 | 条号 | NextPDF Core 的作为 | 状态 |
|---|---|---|---|
| ISO 14289-2:2024(PDF/UA-2) | §6 | 通过 Core 的加标签路径输出结构树、/MarkInfo /Marked true(严格)、/Lang,以及 pdfuaid XMP | 已验证的配置文件:当 veraPDF 二进制文件存在时(选择加入的闸门),pdfua.strict 由 veraPDF oracle 验证(php oracle/run.php pdfua.strict) |
| ISO 19005-4:2020(PDF/A-4 归档格式) | §6.7.3 | 通过 ConformanceMode 输出 pdfaid:part / pdfa:conformance 判别符 | 已宣称(判别符输出,有单元测试佐证);PDF/A-4 文件 的创建仅限 Premium |
| ISO 32000-2:2020(PDF 2.0) | §7.5.2 | 基础的 catalog/document 结构 | 已宣称(基础引擎行为) |
支持不等于一致性。 NextPDF Core 输出 PDF/UA-2 与 PDF/A-4 的识别结构(属于实现,由 tests/Unit/Conformance/ 中的测试佐证)。某个 文件 是否符合 PDF/A-4 或 PDF/UA-2,只能由执行对应配置文件的验证器来断定。根据 ISO 19005-4:2020 第 5 条,一致性判定是验证器的职责,而不是生成文件的库。
veraPDF 闸门会明确说明自身依赖。 这个 oracle(oracle/run.php、oracle/lib/OracleRunner.php)会调用一个固定版本的 veraPDF Docker 镜像。当 Docker 或该镜像不存在时,执行器会以代码 2(基础设施失败)退出,并且不会验证任何内容。因此 pdfua.strict 配置文件是一道选择加入的一致性闸门:它只在存在 veraPDF 二进制文件的机器上证明一致性。NextPDF 不随附任何内置验证器;在验证器缺席时,也不会作出任何一致性宣称。
引用内容由 NextPDF 合规语料库改写而成。完整的 64 字符 reference_id 摘要记录在页面 front-matter 与 _normative-evidence-conf.md 之中。
另请参阅
标题为“另请参阅”的章节- Compliance 模块 —— PDF/R-1 验证器、Arlington 文法、生命周期工具
- Accessibility 模块 —— PDF/UA-2 加标签内容输出器
- PDF/A-4 规格对应 —— ISO 19005-4 涵盖的功能与明确不涵盖的功能
- PDF/UA-2 规格对应 —— ISO 14289-2 无障碍对应
- Security 模块 —— 签名路径的严格开关