跳到內容
getnextpdf.com

Enterprise 版本

Compliance — 深入參考

Compliance 模組會將完成的 PDF 導向外部的驗證 sidecar,並回傳單一的正規化結果。ComplianceGateway 會從 ComplianceProfile 解析出負責的 sidecar,強制執行 fail-closed 的可用性政策,並將每個工具的判定包裝進一個 ExternalValidationResult。橋接器隨附於 veraPDF(PDF/A、PDF/UA、PDF 2.0 Arlington)、EU DSS(PAdES 層級)、合併的 Mustang/KoSIT sidecar(ZUGFeRD、Factur-X、EN 16931),以及一個獨立的 KoSIT daemon。本模組也提供 AiReadyCertifier 就緒度蓋章,以及一個用於官方 KoSIT XRechnung 測試套件的執行器。

此能力隨 NextPDF Enterprisenextpdf/enterprise)提供,並以 Enterprise 層級的授權封套啟用。缺少該權益的部署不會載入此能力的類別。比較版本並取得授權

Compliance/Evidence 介面由 enterprise.compliance.evidence 能力授權。缺少或過期的權益會拒絕該功能;它不會默默降級行為。

層級Compliance 介面
Core行程內位元組串流與文法檢查;不委派給外部 sidecar。
Pro行程內 EN 16931 / Factur-X / ZUGFeRD 驗證;無外部 sidecar。
Enterprise外部驗證器閘道器(本模組),採統一結果與 fail-closed 政策。

Pro 的行程內電子發票驗證器與 Enterprise 的外部 ZUGFeRD sidecar 是不同的介面。外部驗證器閘道器僅隨 nextpdf/enterprise 套件提供。

Terminal window
composer require nextpdf/enterprise:^3
符號參數預設行為回傳擲出或失敗於附註
ComplianceGateway::__constructlist<ExternalValidator> $validatorsLoggerInterface $loggerbool $optional = false依工具名稱建立驗證器索引Optional 模式會將可用性檢查降級為僅發出警告
ComplianceGateway::validatestring $pdfContentComplianceProfile $profilearray $options = []ComplianceProfile::toolName() 解析驗證器,檢查可用性,然後委派?ExternalValidationResultComplianceSidecarUnavailableExceptionInvalidArgumentException(該工具未註冊驗證器)僅在 optional 模式且 sidecar 停擺時回傳 null
ComplianceGateway::validateAllProfilesstring $pdfContentstring $toolName驗證對應到該工具的每個 profilelist<ExternalValidationResult>validate() 相同略過 null(optional 模式)結果
ComplianceGateway::healthCheck探測每個已註冊 sidecar 的健康端點array<string, bool>回報可連線性;不驗證任何文件
ComplianceGateway::buildComplianceMatrix(靜態)list<ExternalValidationResult> $resultsstring $commitSha將結果歸納為帶版本化結構描述的矩陣array<string, mixed>結構描述版本 1.0;記錄工具輸出,不主張任何東西
ComplianceProfile(enum)15 個以字串為底的 case將每個 profile 對應到一個標準標籤與一個工具standardReference(): stringtoolName(): string
ExternalValidator(interface)建構於 PSR-18 之上的 sidecar 橋接合約傳輸失敗時 validate() 會擲出 ComplianceSidecarUnavailableExceptiongetToolName()isAvailable()validate()
VeraPdfValidator::validateInterface 簽名以 multipart POST 到 veraPDF REST sidecar;剖析 JSON 報告ExternalValidationResultComplianceSidecarUnavailableExceptionInvalidArgumentException(不支援的 profile)PDF/A、PDF/UA、Arlington;僅剖析 JSON,絕不剖析 XML
DssValidator::validateInterface 簽名以 Base64 JSON POST 到 EU DSS REST sidecarExternalValidationResultComplianceSidecarUnavailableExceptionInvalidArgumentException(不支援的 profile)PAdES B-B 至 B-LTA;建構子拒絕低於一秒的逾時
ZugferdExternalValidator::validateInterface 簽名以 multipart POST 到合併的 Mustang/KoSIT sidecarExternalValidationResultComplianceSidecarUnavailableException(斷路器開啟時亦然);InvalidArgumentException(不支援的 profile)ZUGFeRD 2.4、Factur-X 1.08、EN 16931;可選擇注入斷路器
KoSitValidator::validateInterface 簽名以原始 XML POST 到獨立的 KoSIT daemonExternalValidationResultComplianceSidecarUnavailableExceptionInvalidArgumentException(不支援的 profile)僅 EN 16931;以 fail-closed 方式剖析 Schematron SVRL 報告
ExternalValidationResult唯讀值物件正規化的工具判定passes()fails()nonConformanceCount()toComplianceMatrix()
NonConformance唯讀值物件單一發現項,含規則 id、條款、嚴重度、位置toArray()
ComplianceSidecarUnavailableExceptionstring $toolNamestring $endpointint $code = 0?Throwable $previous = nullFail-closed 的 sidecar 不可用訊號公開唯讀的 toolNameendpoint
AiReadyCertifier::certifystring $pdfBytes評估三項就緒度準則;蓋上 XMP 來源證明array{0: AiReadyCertification, 1: string}InvalidArgumentException(蓋章需要傳統的交叉參照表)當層級為 not_certified 時,第二個元素等於輸入
AiReadyCertification唯讀值物件就緒度評估,含層級、準則數、問題、來源雜湊內部就緒度標籤,非標準認證
XRechnungTestSuiteRunner::__constructstring $suitePathExternalValidator $validatorbool $useCuratedNegativeFallback = true解析已解壓的測試套件目錄InvalidArgumentException(目錄不存在)針對官方 KoSIT XRechnung 測試套件
XRechnungTestSuiteRunner::runbool $stopOnFirstFailure = false透過橋接器驗證套件中的每個實例XRechnungTestSuiteResultXRechnungTestSuiteException(驗證器不可用;沒有 XML 檔案)另有 isAvailable()getSuitePath()discoverTestFiles()
XRechnungTestSuiteResult唯讀值物件彙總的套件結果allPassed()totalCount()getFailures()getErrors()toSummary()
XRechnungTestCaseResult唯讀值物件各案例結果passed()hasError()getFilename()
XRechnungTestSuiteException靜態建構子套件執行期失敗訊號selfvalidatorUnavailable()noTestFilesFound(string $suitePath)
namespace NextPDF\Enterprise\Compliance;
final class ComplianceGateway
{
/** @param list<ExternalValidator> $validators */
public function __construct(
array $validators,
private readonly LoggerInterface $logger,
private readonly bool $optional = false,
);
/** @param array<string, mixed> $options */
public function validate(
string $pdfContent,
ComplianceProfile $profile,
array $options = [],
): ?ExternalValidationResult;
/** @return list<ExternalValidationResult> */
public function validateAllProfiles(string $pdfContent, string $toolName): array;
/** @return array<string, bool> */
public function healthCheck(): array;
/**
* @param list<ExternalValidationResult> $results
* @return array<string, mixed>
*/
public static function buildComplianceMatrix(array $results, string $commitSha): array;
}
interface ExternalValidator
{
public function getToolName(): string;
public function isAvailable(): bool;
/** @param array<string, mixed> $options */
public function validate(
string $pdfContent,
ComplianceProfile $profile,
array $options = [],
): ExternalValidationResult;
}
enum ComplianceProfile: string
{
case PdfA1b = 'pdfa-1b';
// PdfA2b, PdfA3b, PdfA4, PdfA4f, PdfUa1, PdfUa2, Pdf20Arlington,
// PadesBasic, PadesTimestamp, PadesLongTerm, PadesArchive,
// Zugferd24, FacturX108, En16931
public function standardReference(): string;
public function toolName(): string;
}
final class AiReadyCertifier
{
/** @return array{0: AiReadyCertification, 1: string} Tuple of [certification, stamped PDF bytes] */
public function certify(string $pdfBytes): array;
}

ComplianceGateway::validate() 會解析已註冊、其 getToolName()ComplianceProfile::toolName() 相符的 ExternalValidator,檢查 isAvailable(),委派執行,並回傳一個正規化的 ExternalValidationResult。外部可觀察的規則如下:

  • **Fail-closed 預設。**當所解析的 sidecar 不可用且 optional 模式關閉時,呼叫會引發 ComplianceSidecarUnavailableException。文件未被檢查;它絕不會被視為通過。
  • **Optional 模式。**以 optional: true 建構閘道器(操作者從 NEXTPDF_COMPLIANCE_OPTIONAL 環境變數接線)會將不可用的 sidecar 降級為一筆記錄下來的警告與 null 回傳。呼叫端必須將 null 視為「未檢查」。Optional 模式僅涵蓋預檢的可用性探測;驗證呼叫本身期間發生的傳輸失敗,在兩種模式下都會引發 ComplianceSidecarUnavailableException
  • **未知 profile。**沒有已註冊驗證器的 profile 會引發 InvalidArgumentException;它絕不會默默通過。
  • 通過語意。ExternalValidationResult::passes() 要求 conformant 為 true 零個不符合項。每筆結果都帶有 profile、工具名稱與版本、主張數、發現項、已驗證位元組的 SHA-256、一個 UTC 時間戳,以及呼叫時長。
  • 矩陣是記錄,而非主張。buildComplianceMatrix() 是一個靜態歸納器,會產生一個帶版本化結構描述的結構,內含工具版本與一個用於可追溯性的 commit SHA。它記錄工具輸出;它不主張任何東西。
  • **資料流。**完整的 PDF 位元組串流會透過一個 PSR-18 用戶端傳輸到所設定的 sidecar。每次驗證都會透過 PSR-3 記錄,內含 profile、工具、通過/失敗、主張數與時長。

Profile 到工具的路由,如 ComplianceProfile::standardReference()::toolName() 所回傳:

Profile case標準參考工具
pdfa-1b, pdfa-2b, pdfa-3b, pdfa-4, pdfa-4fISO 19005-1/-2/-3/-4 (Level B; Level F for 4f)veraPDF
pdfua-1, pdfua-2ISO 14289-1:2014, ISO 14289-2:2024veraPDF
pdf20-arlingtonISO 32000-2:2020 (Arlington model)veraPDF
pades-b-b, pades-b-t, pades-b-lt, pades-b-ltaETSI EN 319 142-1 B-B through B-LTAEU DSS
zugferd-2.4, factur-x-1.08, en-16931ZUGFeRD 2.4 / Factur-X 1.08 / EN 16931-1:2017Mustang/KoSIT

AiReadyCertifier::certify() 會評估三項準則:結構性簽章的存在、LTV 健康度,以及未加密。三項準則皆通過會得到 certified 層級;通過一或兩項得到 partial;零項得到 not_certified。在 certifiedpartial 時,它會附加一個增量更新,攜帶一個 XMP 來源證明串流與一個 Catalog 覆寫;原始位元組絕不會被更動。「certified」層級是 NextPDF 內部的就緒度標籤,不是標準認證。

VeraPdfValidator 只剖析 JSON sidecar 回應(沒有 XML;依設計即無 XXE 疑慮)。KoSitValidator 會剖析 daemon 的 XML SVRL 報告,並拒絕 DOCTYPE 宣告、停用網路存取,且將無法剖析的報告視為該呼叫的失敗。

  • Sidecar 逾時或傳輸錯誤會從橋接器呈現為 ComplianceSidecarUnavailableException;此時套用 fail-closed 預設。
  • 非 200 的 sidecar 回應會產生一筆失敗結果,帶有工具專屬的發現項(例如 VERAPDF-HTTP-ERROR);它絕不是一致性通過。
  • 格式不正確的 sidecar JSON 或 XML 主體是該呼叫的驗證失敗,而非一致性通過。
  • 沒有簽章的 EU DSS 結果會以 DSS-NO-SIGNATURES 失敗。TOTAL_PASSED 以外的指示會以 DSS-SIG-INVALID 失敗。低於預期基準的簽章層級會以 DSS-LEVEL-MISMATCH 失敗。
  • DssValidator 會在每次請求時,透過 X-NextPDF-Timeout-Seconds 標頭公布其各請求的逾時預算;整合者的 PSR-18 用戶端必須遵守它,如此停擺的 sidecar 才無法無限期地阻塞呼叫執行緒。
  • ZugferdExternalValidator 可選擇透過注入的斷路器路由 sidecar 呼叫;開啟的斷路器會對應到 ComplianceSidecarUnavailableException(fail-fast,仍為 fail-closed)。預設是一個 no-op 斷路器。
  • KoSitValidator::isAvailable() 接受 daemon 健康探測回傳的 HTTP 200 與 405;daemon 在健康時會以 405 回應 GET。
  • 當原始文件缺少傳統的交叉參照表(例如交叉參照串流)時,AiReadyCertifier 蓋章會以 InvalidArgumentException fail-closed。
  • 當驗證器不可用或套件不含 XML 檔案時,XRechnungTestSuiteRunner::run() 會拒絕執行;在啟用 useCuratedNegativeFallback 時,若套件未隨附任何無效實例,它會以一個精選的負面語料庫替代。

本模組不執行任何簽署,也不保管金鑰。FIPS 模式的演算法政策由 Security 與 Signature 模組掌管。簽章一致性委派給 EU DSS,由它做出自己的判定。

閘道器會將一致性判定委派給外部工具;這個設計反映了標準本身的界線——一致性是依要求判定,而不是由產生者主張。

行為參考
符合處理器的義務;一致性依該標準判定ISO 19005-4:2020 §5.2
PDF/A-4 檔案要求對比產生者自我主張ISO 19005-4:2020 §6.6.4
PDF/UA-2 一致性是檔案的屬性ISO 14289-2:2024 §6
PAdES baseline 簽章層級ETSI EN 319 142-1 §5.4.3

外部工具產生判定。NextPDF 並未持有任何認證,也不會授予任何認證;支援某項 profile 不等於符合它。驗證結果是供參考的技術性結構檢查記錄,而非法律意見;請洽詢你的合規團隊以判斷法規上的充分性。

  • 操作者負責託管與營運這些 sidecar、釘選它們的版本、限制它們的網路觸及範圍、驗證它們的 TLS,並掌控啟用 optional 模式的環境。Sidecar 端點是一道信任邊界;文件、結果與日誌的資料落地與保留控制,皆為操作者的責任。
  • buildComplianceMatrix() 的輸出是為 CI 可追溯性而設計:釘選 commit SHA,並將矩陣與建置產物一同封存。
  • XRechnung 執行器預期官方測試套件已解壓到一個本機目錄;其建構子訊息會指名公開的下載來源。
  • 內部機制細節保留在原始碼儲存庫的內部文件中,不在本手冊的範圍內。

本頁僅記載外部可觀察的行為,以及受支援的公開 API 介面。內部命名空間路徑、輔助類別、機制表、runbook 檔名與工單前綴皆不在範圍內。