跳到內容

一致性(conformance):ConformanceMode 的路由與驗證邊界

NextPDF\Conformance 提供唯一的鑑別子(discriminator),用來告訴 writer 文件鎖定的是哪一個 ISO 合約。函式庫只會輸出合約定義的結構;它不會、也無法保證最終產出的檔案符合規範。只有外部驗證器(validator)才能認證一致性。

Terminal window
composer require nextpdf/core:^3

Conformance 模組公開兩個型別。ConformanceMode 是帶底層值的列舉(enum),用來命名目標合約(PlainPdfUa1PdfUa2PdfA2PdfA3PdfA3bPdfA3uPdfA4PdfA4ePdfA4f)。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 檔案。

型別種類主要成員
NextPDF\Conformance\ConformanceModeenum: stringPlainPdfUa1PdfUa2PdfA2PdfA3PdfA3bPdfA3uPdfA4PdfA4ePdfA4fisTagged()isAccessibility()isArchival()requiresPdfUa2PageTabs()pdfaPart(): ?intpdfaConformanceLetter(): stringrequiresPdf17(): bool
NextPDF\Conformance\ConformancePolicyfinal 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() 會擲出 InvalidConfigExceptionsecurity.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() 會辨識變體。 PlainPdfA2PdfA3bPdfA4e 都回報為未加標籤。writer 不得假設封存模式就代表存在一棵結構樹。
  • 通過的模式不等於通過的檔案。 設定 PdfA4 並不會讓輸出成為有效的 PDF/A-4 檔案。請執行驗證器。

ConformanceModeConformancePolicy 都是純粹的值型別:列舉案例的 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.phporacle/lib/OracleRunner.php)會呼叫外部的釘選版本 veraPDF Docker 映像。當 Docker 或該映像不存在時,執行器會以代碼 2(基礎設施失敗)退出,且不會驗證任何內容。因此 pdfua.strict 設定檔是一道選擇加入的一致性閘門:它只有在存在 veraPDF 二進位檔的機器上證明一致性。NextPDF 不隨附任何內嵌的驗證器;缺少它時,也不會提出任何一致性宣稱。

引用內容係改寫自 NextPDF 合規語料庫。完整的 64 字元 reference_id 摘要記錄於頁面 front-matter 與 _normative-evidence-conf.md 之中。