跳到內容
getnextpdf.com

Pro 版本穩定性: 實驗性

C2PA 預覽能力狀態

預覽能力狀態。絕非 GA。 本頁陳述 C2PA 介面今日作為一個預覽所做的事。它不是一個一致性主張、不是一個認證,也不是一個 NextPDF 產生 C2PA 簽署檔案的陳述。此介面是一個預覽,且絕不會被描述為一般可用。

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 一致」或「C2PA 相容」。
  • 「C2PA 認證」。
  • 作為一項已完成、已斷言能力的「C2PA 已簽署」。
  • 「GA」/「一般可用」。

此介面誠實地是什麼:一個能解析(擷取)並攜帶(嵌入)一個 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(exit 0 為新鮮 / 1 為軟性警告 / 2 為硬性失敗),以偵測被固定的草案快照何時過時。
  • 沒有一致性裁決。 狀態物件回報預覽狀態,而非一致性結果。一個外部驗證器與一個凍結的工作組設定檔,會是任何一致性討論的前提,而兩者皆未被假定。
  • 措辭紀律。 請勿將輸出描述為「C2PA 已簽署」、「一致」、「相容」、「已認證」或「GA」。請使用「預覽能力狀態」。

一個預覽介面不是一項安全控制。攜帶或合成一個草案 Manifest Store 並不等同於產生或驗證一個證實——而且實驗性嵌入器完全省略了 Claim Signature 框,因此依其建構方式其輸出是未簽署的。請勿在正式環境中依賴此預覽取得來源保證;它不斷言一個憑證有效,也不斷言一個檔案已簽署。

此介面作任何一致性主張。C2PA 設定檔由一個外部工作組維護,且尚未凍結;因此 NextPDF 陳述的是一個預覽能力狀態與一個草案/工作組邊界,而非一致性或認證。未重現任何規範文字。

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