跳转到内容
getnextpdf.com

Enterprise 版本

Compliance — 深度参考

Compliance 模块会将一份完成的 PDF 路由到一个外部校验 sidecar,并返回一份归一化后的结果。ComplianceGatewayComplianceProfile 解析出负责的 sidecar,强制执行失败即关闭的可用性策略,并把每个工具的判定包装进 ExternalValidationResult。桥接器随附于 veraPDF(PDF/A、PDF/UA、PDF 2.0 Arlington)、EU DSS(PAdES 级别)、组合式 Mustang/KoSIT sidecar(ZUGFeRD、Factur-X、EN 16931)以及一个独立的 KoSIT 守护进程。该模块还提供 AiReadyCertifier 就绪度盖戳,以及一个用于运行官方 KoSIT XRechnung 测试套件的运行器。

此能力随附于 NextPDF Enterprisenextpdf/enterprise),并通过一个 Enterprise 层级的授权信封激活。缺少该权益的部署不会加载此能力的类。比较各版本并获取授权

Compliance/Evidence 接口面受 enterprise.compliance.evidence 能力授权。缺失或过期的权益会拒绝该功能;它不会静默降级行为。

层级Compliance 接口面
Core进程内的字节流与语法检查;不委派给外部 sidecar。
Pro进程内的 EN 16931 / Factur-X / ZUGFeRD 校验;无外部 sidecar。
Enterprise外部校验器网关(本模块),带有归一化结果与失败即关闭策略。

Pro 的进程内电子发票校验器与 Enterprise 的外部 ZUGFeRD sidecar 是两个不同的接口面。外部校验器网关仅随 nextpdf/enterprise 包发行。

Terminal window
composer require nextpdf/enterprise:^3
符号参数默认行为返回抛出或失败于说明
ComplianceGateway::__constructlist<ExternalValidator> $validators, LoggerInterface $logger, bool $optional = false按工具名索引各校验器可选模式将可用性检查降级为仅告警
ComplianceGateway::validatestring $pdfContent, ComplianceProfile $profile, array $options = []通过 ComplianceProfile::toolName() 解析校验器,检查可用性,委派调用?ExternalValidationResultComplianceSidecarUnavailableExceptionInvalidArgumentException(该工具未注册校验器)仅在可选模式且 sidecar 宕机时返回 null
ComplianceGateway::validateAllProfilesstring $pdfContent, string $toolName校验映射到该工具的每个 profilelist<ExternalValidationResult>validate() 相同跳过 null(可选模式)结果
ComplianceGateway::healthCheck探测每个已注册 sidecar 的健康端点array<string, bool>报告可达性;不校验任何文档
ComplianceGateway::buildComplianceMatrix(静态)list<ExternalValidationResult> $results, string $commitSha将结果归约为一个带版本化 schema 的矩阵array<string, mixed>schema 版本 1.0;记录工具输出,不作任何断言
ComplianceProfile(枚举)15 个以字符串为底的 case将每个 profile 映射到一个标准标签与一个工具standardReference(): stringtoolName(): string
ExternalValidator(接口)PSR-18 之上的 sidecar 桥接契约传输失败时 validate() 抛出 ComplianceSidecarUnavailableExceptiongetToolName()isAvailable()validate()
VeraPdfValidator::validate接口签名向 veraPDF REST sidecar 发起 multipart POST;解析 JSON 报告ExternalValidationResultComplianceSidecarUnavailableExceptionInvalidArgumentException(不支持的 profile)PDF/A、PDF/UA、Arlington;仅解析 JSON,绝不解析 XML
DssValidator::validate接口签名向 EU DSS REST sidecar 发起 Base64 JSON POSTExternalValidationResultComplianceSidecarUnavailableExceptionInvalidArgumentException(不支持的 profile)PAdES B-B 到 B-LTA;构造函数拒绝低于一秒的超时
ZugferdExternalValidator::validate接口签名向组合式 Mustang/KoSIT sidecar 发起 multipart POSTExternalValidationResultComplianceSidecarUnavailableException(断路器开启时亦然);InvalidArgumentException(不支持的 profile)ZUGFeRD 2.4、Factur-X 1.08、EN 16931;可选注入的断路器
KoSitValidator::validate接口签名向独立 KoSIT 守护进程发起原始 XML POSTExternalValidationResultComplianceSidecarUnavailableExceptionInvalidArgumentException(不支持的 profile)仅 EN 16931;以失败即关闭的方式解析 Schematron SVRL 报告
ExternalValidationResult只读值对象归一化的工具判定passes()fails()nonConformanceCount()toComplianceMatrix()
NonConformance只读值对象单条发现,含规则 id、条款、严重度、位置toArray()
ComplianceSidecarUnavailableExceptionstring $toolName, string $endpoint, int $code = 0, ?Throwable $previous = null失败即关闭的 sidecar 不可用信号公开只读的 toolNameendpoint
AiReadyCertifier::certifystring $pdfBytes评估三项就绪度准则;盖上 XMP 溯源信息array{0: AiReadyCertification, 1: string}InvalidArgumentException(盖戳要求经典交叉引用表)当级别为 not_certified 时,第二个元素等于输入
AiReadyCertification只读值对象就绪度评估,含级别、准则数量、问题、源哈希内部就绪度标签,并非标准认证
XRechnungTestSuiteRunner::__constructstring $suitePath, ExternalValidator $validator, bool $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。可从外部观察到的规则如下:

  • 失败即关闭的默认行为。 当解析出的 sidecar 不可用且未开启可选模式时,该调用会抛出 ComplianceSidecarUnavailableException。文档未被检查;它绝不会被当作已通过。
  • 可选模式。optional: true 构造网关(运营方从 NEXTPDF_COMPLIANCE_OPTIONAL 环境变量接入)会把不可用的 sidecar 降级为一条日志警告并返回 null。调用方必须将 null 视为“未检查”。可选模式仅覆盖预检的可用性探测;校验调用本身期间发生的传输失败在两种模式下都会抛出 ComplianceSidecarUnavailableException
  • 未知 profile。 没有已注册校验器的 profile 会抛出 InvalidArgumentException;它绝不会静默通过。
  • 通过语义。 ExternalValidationResult::passes() 要求 conformant 为真零个不符合项。每份结果都携带 profile、工具名与版本、断言数量、各项发现、被校验字节的 SHA-256、一个 UTC 时间戳,以及调用耗时。
  • 矩阵是一条记录,而非一次断言。 buildComplianceMatrix() 是一个静态归约器,产出一个带版本化 schema 的结构,其中含有工具版本以及用于可追溯性的 commit SHA。它记录工具输出;它本身不作任何断言。
  • 数据流。 完整的 PDF 字节流会通过一个 PSR-18 客户端传输到所配置的 sidecar。每次校验都会通过 PSR-3 记录 profile、工具、通过/失败、断言数量以及耗时。

ComplianceProfile::standardReference()::toolName() 返回的 profile-到-工具路由:

Profile case标准参考工具
pdfa-1b, pdfa-2b, pdfa-3b, pdfa-4, pdfa-4fISO 19005-1/-2/-3/-4(Level B;4f 为 Level F)veraPDF
pdfua-1, pdfua-2ISO 14289-1:2014, ISO 14289-2:2024veraPDF
pdf20-arlingtonISO 32000-2:2020(Arlington 模型)veraPDF
pades-b-b, pades-b-t, pades-b-lt, pades-b-ltaETSI EN 319 142-1 B-B 到 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 解析守护进程的 XML SVRL 报告,其中 DOCTYPE 声明被拒绝、网络访问被禁用,并将无法解析的报告视为该调用的一次失败。

  • sidecar 超时或传输错误会从桥接器表现为 ComplianceSidecarUnavailableException;此时适用失败即关闭的默认行为。
  • sidecar 返回非 200 响应会产生一份失败结果,带有工具特定的发现(例如 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(快速失败,仍是失败即关闭)。默认是一个无操作的断路器。
  • KoSitValidator::isAvailable() 接受守护进程健康探测返回的 HTTP 200 与 405;守护进程在健康时以 405 应答 GET。
  • 当原始文档缺少经典交叉引用表(例如交叉引用流)时,AiReadyCertifier 盖戳会以 InvalidArgumentException 失败即关闭。
  • 当校验器不可用或套件不含任何 XML 文件时,XRechnungTestSuiteRunner::run() 拒绝运行;在启用 useCuratedNegativeFallback 时,当套件未随附任何无效实例时,它会替换为一个经过策展的负样本语料。

本模块不执行任何签名,也不进行任何密钥保管。FIPS 模式的算法策略由 Security 与 Signature 模块管辖。签名符合性委派给 EU DSS,由其自行作出判定。

网关将符合性判定委派给外部工具;这一设计反映了各标准自身的界线——符合性是依照各项要求判定的,而非由生成端断言。

行为参考
符合性处理器义务;符合性依照标准判定ISO 19005-4:2020 §5.2
PDF/A-4 文件要求 vs. 生成端自我断言ISO 19005-4:2020 §6.6.4
PDF/UA-2 符合性是文件的一项属性ISO 14289-2:2024 §6
PAdES 基线签名级别ETSI EN 319 142-1 §5.4.3

判定由外部工具产出。NextPDF 不持有任何认证,也不授予任何认证;对某个 profile 的支持并不等于符合该 profile。校验结果是供参考的技术性结构检查记录,并非法律意见;请咨询你的合规团队,以判断监管层面是否充分。

  • 运营方负责托管与运行各 sidecar、对其进行版本固定、限制其网络可达范围、校验其 TLS,并掌控启用可选模式的环境。sidecar 端点是一道信任边界;针对文档、结果与日志的驻留地与留存控制由运营方负责。
  • buildComplianceMatrix() 的输出是为 CI 可追溯性而设计的:固定 commit SHA,并将矩阵与构建产物一并归档。
  • XRechnung 运行器期望官方测试套件已解压到一个本地目录;其构造函数消息会指明公共下载来源。
  • 内部机制细节保留在源代码仓库的内部文档中,不在本手册范围内。

本页仅记录可从外部观察到的行为与受支持的公共 API 接口面。内部命名空间路径、辅助类、机制表、runbook 文件名以及工单前缀均不在范围内。