跳转到内容
getnextpdf.com

Pro 版本稳定性: 实验性

C2PA 预览能力状态

预览能力状态。永远不是 GA。 本页陈述 C2PA 接口作为预览今天所做的事。它不是一项符合性主张,不是一项认证,也不是 NextPDF 产出 C2PA 签章文件的声明。该接口是预览,且永远不会被描述为正式发布(GA)。

NextPDF Pro 通过 C2paCapabilityStatus 暴露一个 Content Credentials(C2PA)预览接口。本页是该接口的诚实边界:什么始终可用、什么停留在一个可选启用的草案标志之后,以及为什么不作任何终态主张。

两层:稳定接缝与受标志门控的合成

标题为“两层:稳定接缝与受标志门控的合成”的章节

该接口有两个清晰分隔的层,而这一区分正是该边界的全部要点:

  • 始终可用——稳定接缝。 ManifestStoreC2paManifestEmbedder 接口是一个冻结的、厂商中立的接缝。它们可以双向承载一个 Manifest Store:embed() 把调用方提供的 Store 字节写入一个 PDF,而 extract() 把一个 Store 解析回来(当不存在时返回 null)。此接缝不作任何主张合成——它从不自行组装断言或主张;它移动的是一个调用方已持有的不透明 ManifestStore
  • 在可选启用的标志之后——主张合成。 真正构建一个 Manifest Store(组装主张与成分散列断言)只存在于 ExperimentalC2paEmbedder 中,受一个默认关闭的环境变量标志门控。这是草案形态、会在不预先通知的情况下破坏性变更的部分。

因此,确切的陈述是:提取与字节承载始终可达;清单内容的合成仅在预览标志被显式启用时才可达。

这个承载性的决策是把一个稳定的传输接缝与易变的合成路径分开,而非让一个嵌入器包办一切。C2PA-PDF 配置文件仍由一个外部工作组拥有,且尚未冻结。它的 Claim Signature 框(c2cs,一个 COSE_Sign1 结构)是最可能漂移的部分。因此合成省略了该框并置于一个默认关闭的标志之后,而提取与承载不依赖任何未冻结的字段,对所有人保持可达。状态对象把成熟度作为数据暴露,generallyAvailableconformanceClaimed 被硬编码为 false,使调用方不会把产出方意图误认为一项经验证的结果。这一分隔让团队现在就采用这个持久的接缝,并在之后加入一个签章适配器,而不必给出 NextPDF 尚无法兑现的传输格式承诺。

设计背景:可交给审计员的合规

C2paCapabilityStatus 把该接口的状态显式地作为数据而非散文来报告。它的 generallyAvailableconformanceClaimed 属性被硬编码为 false,且无论标志如何都保持为 false;启用预览只会翻转 previewEnabledmaturity 令牌是不作主张的标签 preview-draft,而 specPin 记录被钉定的草案提交。调用方读到的是“preview”,而非“已签章并已验证”。

use NextPDF\Pro\Compliance\C2pa\C2paCapabilityStatus;
// Reads the env flag live; performs no I/O.
$status = C2paCapabilityStatus::current();
$status->previewEnabled; // bool — true only if the opt-in env flag is set
$status->generallyAvailable; // false (always)
$status->conformanceClaimed; // false (always)
$status->maturity; // 'preview-draft'
$status->specPin; // '4e2afed8' (pinned draft commit, short)
$status->envGate; // 'NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT'
echo $status->summary();
// "C2PA preview-draft surface is present but switched off;
// the C2PA-PDF profile is not yet final."

C2PA 规范由一个外部工作组维护,而 NextPDF 将要瞄准的配置文件尚未冻结。由于该配置文件未冻结,本预览刻意不作任何终态主张。当工作组配置文件稳定下来时,会改变的是该接口的状态——而非它的营销表述。

可选开关是一个单一的进程环境变量 NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT。它被实时读取,并严格地与字符串 "1" 比对——任何其他值(包括 0trueyes、空字符串或缺失)都被当作关闭。仅有一份 Pro 许可证并不会启用它;操作者必须有意识地选择启用。

// Opt in for the current process BEFORE constructing the embedder.
putenv('NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT=1');
use NextPDF\Pro\Compliance\C2pa\Experimental\ExperimentalC2paEmbedder;
$embedder = new ExperimentalC2paEmbedder();
// Synthesise a draft-shaped Manifest Store binding the host PDF by SHA-256.
$pdfBytes = file_get_contents('input.pdf');
$store = $embedder->buildManifestStore($pdfBytes, 'my-app/1.0.0');
// The result is an opaque ManifestStore; $store->toBytes() is its serialisation.

在一个真实部署中,请在启动时设置该标志(而非在运行时经由 putenv()),将其门控于一次显式的人工选择启用,并在触及实验性嵌入器之前检查能力状态,使草案路径只在有意为之时才被触达。

use NextPDF\Pro\Compliance\C2pa\C2paCapabilityStatus;
use NextPDF\Pro\Compliance\C2pa\Experimental\ExperimentalC2paEmbedder;
// Set NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT=1 in the environment at process boot.
$status = C2paCapabilityStatus::current();
if (!$status->previewEnabled) {
// Flag off: do NOT instantiate the experimental embedder — its
// constructor would throw. Fall back to your non-preview path.
return;
}
// Surface the draft pin to the operator. The bytes are transient:
// re-embed once a stable adapter ships. Run `composer c2pa:draft-status`
// in CI to fail the build if the pinned snapshot goes stale.
$pinnedDraft = ExperimentalC2paEmbedder::SPEC_PIN_SHA; // 4e2afed8…
$pinnedDate = ExperimentalC2paEmbedder::SPEC_PIN_DATE; // 2026-04-26
$embedder = new ExperimentalC2paEmbedder();
$store = $embedder->buildManifestStore($pdfBytes, 'my-app/1.0.0');

不存在沉默的回退。如果在 NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT 不恰好为 "1" 时构造 ExperimentalC2paEmbedder,构造器会抛出一个 LogicException,其消息会命名该标志、该环境变量,以及被钉定的草案 SHA/日期。一个调用方不会仅仅因为持有一份 Pro 许可证就意外地把草案形态的字节序列化进一份正式环境 PDF。

稳定的提取路径也是 fail-closed 的,但方式不同:当不存在 Manifest Store 时 extract() 返回 null(常见情形,保持低开销且无异常),而当一个 Store 确实存在但违反解析器的对抗性加固不变量(深度、循环、大小、计数)时,它会抛出一个 C2paException 子类——JumbfBombExceptionJumbfCycleDetectedExceptionJumbfDepthExceededExceptionMalformedJumbfException。这些异常绝不会被沉默吞掉。

按照策略,以下用语对此接口使用,且不应出现在由它衍生的任何文档、UI 或营销中:

  • “C2PA conformant”或“C2PA compliant”。
  • “C2PA certified”。
  • 作为一项已完成、已断言的能力的“C2PA signed”。
  • “GA”/“generally available”。

该接口诚实地是什么:一个能解析(提取)并承载(嵌入)一个 C2PA Manifest Store 的稳定接缝,加上一个默认关闭、会合成草案形态清单内容的实验性嵌入器,以及一个报告自身预览状态的状态对象。它不是什么:一个经证明、可验证的 C2PA 凭据的产出者。值得注意的是,实验性嵌入器刻意省略了 Claim Signature(c2cs)框——即规范中最可能漂移的 COSE_Sign1 部分——因此即使标志开启,输出也是未签章、草案形态的字节。工作组配置文件尚未冻结;该边界正是要点所在。

实验性嵌入器所发出的传输格式被钉定于 c2pa-org/specifications 的一个草案提交(SPEC_PIN_SHA = 4e2afed8…,日期 2026-04-26),并以一个公共常量暴露,使调用方能钉定他们所期望的 SHA。

符号角色
C2paCapabilityStatus诚实、机器可读的状态值对象。current() 实时读取环境变量标志;generallyAvailable / conformanceClaimed 始终为 falsesummary() 不携带任何 GA/符合性主张。
ManifestStore不可变的 Manifest Store 值对象。稳定接缝类型;双向承载字节。没有主张层级的访问器。始终可用。
C2paManifestEmbedder冻结的、厂商中立的 SPI:embed() / extract()。不作主张合成。extract() 在未命中时返回 null。始终可用。
ExperimentalC2paEmbedder默认关闭的合成。buildManifestStore() 组装一份草案清单;除非环境变量标志恰好为 "1",否则构造器会抛出 LogicException
Feature::PREVIEW_C2PA_DRAFT受限范围的可选启用标志。ENV_PREVIEW_C2PA_DRAFT = NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFTisEnabled() 是严格的 === '1'
  • 默认关闭,严格选择启用。 合成位于 NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT 之后,被严格读为 === '1'。其他任何值都为关闭;仅有一份 Pro 许可证并不会启用它。
  • 构造时 fail-closed。 当标志关闭时,new ExperimentalC2paEmbedder() 会抛出 LogicException——绝不是一个沉默的空操作。
  • 输出是未签章且短暂的。 即便标志开启,Claim Signature 框也被省略;把这些字节当作草案形态来对待,并在一个稳定适配器分发后重新嵌入。
  • 钉定陈旧性检查。 在 CI 中运行 composer c2pa:draft-status(退出码 0 为新鲜 / 1 为软警告 / 2 为硬失败)以检测被钉定的草案快照何时过期。
  • 没有符合性裁决。 状态对象报告的是预览状态,而非一项符合性结果。任何符合性讨论的前提都将是一个外部验证器与一个已冻结的工作组配置文件,而两者都未被假定。
  • 用语纪律。 不要把输出描述为“C2PA signed”、“conformant”、“compliant”、“certified”或“GA”。请使用“预览能力状态”。

一个预览接口不是一项安全控制。承载或合成一个草案 Manifest Store,与产出或验证一项证明并不相同——而且实验性嵌入器完全省略了 Claim Signature 框,因此其输出按构造即为未签章。不要在正式环境中依赖此预览来获得来源保证;它不断言一个凭据有效,也不断言一份文件已签章。

此接口作任何符合性主张。C2PA 配置文件由一个外部工作组维护,且尚未冻结;NextPDF 因此陈述的是一个预览能力状态以及一条草案/工作组边界,而非符合性或认证。未重制任何标准原文。

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