Pro edisistabilitas: Eksperimental
Pratinjau C2PA — Referensi Mendalam
Sekilas
Bagian berjudul “Sekilas”Halaman ini adalah referensi tingkat kontrak untuk permukaan pratinjau C2PA (Content Credentials) di NextPDF Pro. Halaman ini mencakup lima simbol publik di NextPDF\Pro\Compliance\C2pa: SPI C2paManifestEmbedder, value object ManifestStore, JumbfBoxParser, deskriptor C2paCapabilityStatus, dan Experimental\ExperimentalC2paEmbedder yang di-gate. Halaman ini juga mendokumentasikan gate Feature::PREVIEW_C2PA_DRAFT dan variabel lingkungannya, NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT.
Permukaan ini bersifat eksperimental dan terbagi menjadi dua lapisan. Seam yang stabil — ManifestStore, C2paManifestEmbedder, JumbfBoxParser — selalu dapat dijangkau dan membawa byte Manifest Store ke dua arah. Sintesis draf manifest hanya berada di ExperimentalC2paEmbedder dan bersifat default-off. Profil C2PA-PDF belum difinalisasi oleh working group; format wire yang disintesis dipin ke sebuah commit draf. Tidak ada klaim kesesuaian yang dibuat, tidak ada jalur verifikasi, dan mengaktifkan flag pratinjau tidak dapat menciptakan keduanya. Tampilan berorientasi tugas berada di halaman kapabilitas.
Ketersediaan & lisensi
Bagian berjudul “Ketersediaan & lisensi”Kapabilitas ini dikirimkan dalam NextPDF Pro (nextpdf/pro) dan aktif dengan envelope lisensi tier Pro. Deployment tanpa entitlement tersebut tidak memuat kelas-kelas kapabilitas ini. Bandingkan edisi dan dapatkan lisensi.
Lisensi mengaktifkan permukaan compliance Pro secara keseluruhan. Permukaan C2PA di dalamnya tetap menjadi pratinjau tanpa memandang tier lisensi. Sintesis draf selain itu memerlukan gate proses yang didokumentasikan di sini; lisensi Pro saja tidak pernah mengaktifkannya.
Permukaan API publik
Bagian berjudul “Permukaan API publik”| Simbol | Parameter | Perilaku default | Mengembalikan | Melempar atau gagal dengan | Catatan |
|---|---|---|---|---|---|
C2paManifestEmbedder | — | SPI embed/extract hanya-byte; tanpa I/O; tanpa sintesis claim | — | — | Interface seam yang dibekukan dan netral-vendor. |
C2paManifestEmbedder::embed() | string $pdfBytes, ManifestStore $store | Menyematkan $store->toBytes() pada lokasi yang dideklarasikan profil; Store kosong DAPAT round-trip sebagai no-op | string byte PDF baru | C2paException pada setiap kegagalan embed (Store terlalu besar, PDF tidak valid, kolisi lokasi-profil) | Implementasi tidak pernah memutasi atau menyimpan byte input. |
C2paManifestEmbedder::extract() | string $pdfBytes | Probe deteksi murah; kasus tanpa-Store hampir tidak mengalokasikan apa pun | ?ManifestStore (null jika tidak ada) | Subclass C2paException ketika Store ada tetapi melanggar invarian pengerasan | Store non-null telah lolos pengerasan JumbfBoxParser. |
ManifestStore::fromBoxes() | array $boxes (list<JumbfBox>) | Membungkus daftar box terurut yang telah divalidasi parser | self | Tidak melempar sendiri; konstruksi JumbfBox buatan tangan menerapkan pengerasan yang sama | Konstruktor bersifat privat; urutan box menjadi penentu untuk kesetaraan round-trip. |
ManifestStore::empty() | tidak ada | Store dengan nol root box | self | Tidak melempar | toBytes() dari Store kosong adalah string kosong. |
ManifestStore::isEmpty() | tidak ada | Menguji apakah nol root box | bool | Tidak melempar | — |
ManifestStore::toBytes() | tidak ada | Menggabungkan serialisasi root-box | string | Tidak melempar | Urutan byte inilah yang ditulis oleh embedder. |
ManifestStore::size() | tidak ada | Panjang byte dari toBytes() | int (>= 0) | Tidak melempar | — |
JumbfBoxParser::__construct() | tiga override cap opsional | Cap produksi: 64 MiB per box, 128 MiB total, 4096 anak per superbox | JumbfBoxParser | Tidak melempar | Cap kedalaman ditetapkan pada MAX_DEPTH (8) dan tidak dapat disetel melalui konstruktor. |
JumbfBoxParser::parse() | string $bytes | Memvalidasi dan mewujudkan root box; input kosong menghasilkan [] | list<JumbfBox> | JumbfBombException, JumbfCycleDetectedException, JumbfDepthExceededException, MalformedJumbfException | Stateless; tidak pernah mengembalikan graf parsial; panggilan konkuren pada satu instance aman. |
C2paCapabilityStatus::__construct() | enam field readonly bernama | Membangun instance deskriptor sembarang | C2paCapabilityStatus | Tidak melempar | current() adalah konstruktor kanonik. |
C2paCapabilityStatus::current() | tidak ada | Membaca gate secara live; men-hard-code boolean claim | C2paCapabilityStatus | Tidak melempar | generallyAvailable dan conformanceClaimed selalu false. |
C2paCapabilityStatus::summary() | tidak ada | Teks status satu baris | string | Tidak melempar | Diformulasikan agar tidak membawa klaim GA atau kesesuaian. |
Feature | enum string-backed, 1 case | Case tunggal PREVIEW_C2PA_DRAFT; konstanta ENV_PREVIEW_C2PA_DRAFT | case enum | Tidak ada apa pun saat akses case | Gate stabilitas terlingkup; berbeda dari entitlement lisensi. |
Feature::isEnabled() | tidak ada | Membaca getenv() secara live; perbandingan ketat terhadap string 1 | bool | Tidak melempar | Variabel yang tidak ada atau nilai lain apa pun, termasuk 0, true, yes, dianggap off. |
ExperimentalC2paEmbedder::__construct() | tidak ada | Pemeriksaan gate fail-closed pada waktu konstruksi | ExperimentalC2paEmbedder | LogicException ketika Feature::PREVIEW_C2PA_DRAFT off | Tidak ada fallback diam-diam. |
ExperimentalC2paEmbedder::buildManifestStore() | string $sourceBytes, string $producer (non-empty) | Membangun Store berbentuk draf yang mengikat $sourceBytes via SHA-256 | ManifestStore | \JsonException pada kegagalan encode payload; subclass C2paException dari konstruksi box | Menghilangkan box Claim Signature c2cs; output tidak ditandatangani secara konstruksi. |
interface C2paManifestEmbedder
public function embed(string $pdfBytes, ManifestStore $store): string;public function extract(string $pdfBytes): ?ManifestStore;final readonly class ManifestStore
public static function fromBoxes(array $boxes): selfpublic static function empty(): selfpublic function isEmpty(): boolpublic function toBytes(): stringpublic function size(): intfinal class JumbfBoxParser
public const int MAX_DEPTH = 8;public const int MAX_PER_BOX_BYTES = 64 * 1024 * 1024;public const int MAX_TOTAL_BYTES = 128 * 1024 * 1024;public const int MAX_CHILDREN_PER_SUPERBOX = 4096;public const array SUPERBOX_TBOXES = ['jumb', 'c2pa', 'c2ma', 'c2as', 'c2cl', 'c2cs', 'c2vc'];
public function __construct( private readonly int $maxPerBoxBytes = self::MAX_PER_BOX_BYTES, private readonly int $maxTotalBytes = self::MAX_TOTAL_BYTES, private readonly int $maxChildrenPerSuperbox = self::MAX_CHILDREN_PER_SUPERBOX,)
public function parse(string $bytes): arrayfinal readonly class C2paCapabilityStatus
public const string MATURITY_PREVIEW_DRAFT = 'preview-draft';
public function __construct( public bool $previewEnabled, public bool $generallyAvailable, public bool $conformanceClaimed, public string $maturity, public string $specPin, public string $envGate,)
public static function current(): selfpublic function summary(): stringenum Feature: string
case PREVIEW_C2PA_DRAFT = 'preview_c2pa_draft';
public const string ENV_PREVIEW_C2PA_DRAFT = 'NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT';
public function isEnabled(): boolfinal class ExperimentalC2paEmbedder
public const string SPEC_PIN_SHA = '4e2afed8f3ace20d41317e2e386c9340d2959d55';public const string SPEC_PIN_DATE = '2026-04-26';
public function __construct()
public function buildManifestStore(string $sourceBytes, string $producer): ManifestStoreKontrak perilaku
Bagian berjudul “Kontrak perilaku”- Pembagian dua-lapisan. Seam yang stabil (
ManifestStore,C2paManifestEmbedder,JumbfBoxParser) selalu dapat dijangkau. Sintesis draf hanya ada diNextPDF\Pro\Compliance\C2pa\Experimental\ExperimentalC2paEmbedderdi balik gate yang default-off. Ekstraksi dan pembawaan byte tidak pernah memerlukan gate; sintesis selalu memerlukannya. - Invarian seam. Kontrak
C2paManifestEmbedderbersifat hanya-byte: tidak ada objek PDF in-memory yang melintasi seam, implementasi tidak melakukan I/O jaringan atau filesystem, dan seam tidak pernah merakit asersi claim sendiri.extract()mengembalikannulluntuk menandakan ketiadaan; ia tidak pernah melempar untuk ketiadaan. - Semantik Store.
ManifestStoreadalah daftar terurut immutable dari instance rootJumbfBox, sesuai model Manifest Store C2PA 2.1 §11.1.1: satu kontainer JUMBF yang mengagregasi satu atau lebih manifest, dapat dialamatkan via URI. Ia tidak mengekspos accessor tingkat-claim. Urutan box dipertahankan dan menjadi penentu untuk kesetaraan round-trip. - Cap pengerasan.
JumbfBoxParsertanpa syarat menolak input yang melampaui cap apa pun: ukuran per-box di atas 64 MiB, store kumulatif di atas 128 MiB, nesting lebih dalam dari 8 tingkat, atau lebih dari 4096 anak dalam satu superbox. Tidak ada flag kebijakan yang menonaktifkan cap ini. Cap yang lebih ketat dapat di-inject melalui konstruktor untuk proses yang terbatas memori. - Penolakan struktural. Parser juga menolak, fail-closed:
LBox = 0(BMFF hingga-EOF),LBox = 1(XLBox panjang 64-bit),LBoxyang lebih kecil dari header 8-byte, pemotongan melewati sisa input, byte TBox di luar ASCII printable (0x20–0x7E), re-entry offset (siklus), dan tiling anak yang tidak eksak dari payload superbox. Ia tidak pernah mengembalikan graf yang terkonstruksi sebagian. - Perutean superbox. Nilai TBox dalam
SUPERBOX_TBOXESdi-parse secara rekursif sebagai urutan anak; setiap TBox lain adalah leaf dengan payload buram.cborsengaja diperlakukan sebagai leaf demi keamanan parser; lapisan hulu me-re-parse payload-nya saat diperlukan. - Gate proses.
Feature::PREVIEW_C2PA_DRAFToff secara default.isEnabled()mengembalikantruehanya ketikaNEXTPDF_FEATURE_PREVIEW_C2PA_DRAFTpersis sama dengan string1. Pembacaan bersifat live pada setiap panggilan; tidak ada yang di-memoise. - Konstruksi fail-closed.
new ExperimentalC2paEmbedder()melemparLogicExceptionselama gate off. Pesannya menyebutkan flag, variabel lingkungan, serta SHA dan tanggal draf yang dipin. Pemanggil tidak dapat menjangkau sintesis draf secara tidak sengaja. - Bentuk sintesis.
buildManifestStore()memancarkan superboxc2payang berisi satu manifestc2ma, yang menampung sebuah assertion storec2as(satu asersic2pa.hash.data) dan sebuah claimc2cl. Asersi tersebut mencatat asersi hash SHA-256 atas$sourceBytes; karena box Claim Signaturec2csdihilangkan dan output tidak ditandatangani, ini BUKAN hard binding C2PA atau verdict provenance — ia hanya mengikuti bentuk struktural yang dijelaskan §9.1. Payload Description-box membawa UUID tipe, toggle0x03, dan label UTF-8 yang diakhiri null, sesuai C2PA 2.1 §11.1.4.1.1–11.1.4.1.2. - Tanpa Claim Signature. Box
c2cs— sesuai C2PA 2.1 §11.1.4.4 sebuah box konten CBOR tunggal berlabelc2pa.signature— sengaja dihilangkan dari Store yang disintesis. Output tidak ditandatangani secara konstruksi. Ini adalah region profil yang dinilai paling mungkin bergeser sebelum pembekuan oleh working group. - Pin draf, tanpa jaminan BC. Format wire yang disintesis dipin ke
SPEC_PIN_SHA(4e2afed8…, bertanggal2026-04-26) daric2pa-org/specifications. Ia dapat berubah tanpa pemberitahuan dan tidak membawa jaminan backwards-compatibility. - Invarian kejujuran.
C2paCapabilityStatus::current()men-hard-codegenerallyAvailabledanconformanceClaimedmenjadifalse. Tidak ada konfigurasi atau flag lingkungan yang membalik salah satu boolean tersebut. HanyapreviewEnabledyang mencerminkan gate;maturityadalah token non-klaimpreview-draft.
Kasus tepi & mode kegagalan
Bagian berjudul “Kasus tepi & mode kegagalan”- Mengatur variabel gate ke
0,true,yes,on, atau string kosong membiarkan gate off. Hanya string persis1yang mengaktifkannya. - Perubahan
putenv()berlaku pada panggilanisEnabled()berikutnya karena pembacaan bersifat live. Gate yang di-toggle di tengah proses langsung teramati. extract()membedakan dua hasil:nullketika tidak ada Store (murah, bebas-eksepsi), dan subclassC2paExceptionyang dilempar ketika Store ada tetapi berbahaya atau malformed. Ketiadaan tidak pernah menjadi error; keberadaan plus malformasi selalu menjadi error.JumbfBoxParser::parse('')mengembalikan daftar kosong.ManifestStoreyang kosong tetapi ada round-trip menjadi dirinya sendiri; seam tidak meruntuhkannya menjadinull.- Menyematkan Store kosong DAPAT mengembalikan input tanpa perubahan. Kontrak seam mengizinkan no-op ini tetapi tidak mewajibkannya.
- Graf
JumbfBoxbuatan tangan menjalankan pengerasan yang sama pada waktu konstruksi: pemeriksaan panjang dan ASCII TBox, cap kedalaman, invarian kedalaman-anak, aturan eksklusivitas payload-atau-anak, dan cap ukuran per-box. Bomb buatan tangan gagal pada konstruksi, bukan pada waktu embed. - Setiap eksepsi parser membawa field terstruktur —
capKind/observed/cap,offset, ataukind— sehingga telemetri tidak menyisir string pesan. Semua subclass memperluasC2paException(yang sendirinya adalahRuntimeException), yang merupakan tipe catch payung. - Docblock parser melarang penelanan eksepsi ini secara diam-diam; konsumen memunculkannya atau me-remap-nya dengan maksud jelas.
buildManifestStore()meng-encode payload JSON denganJSON_THROW_ON_ERROR; string$produceryang bukan UTF-8 valid gagal dengan\JsonExceptionsebelum box apa pun dibangun.- Hasil
extract()yang well-formed hanyalah pernyataan struktural. Tidak ada validasi claim, tidak ada verifikasi tanda tangan, dan tidak ada evaluasi trust di mana pun pada permukaan ini. Pengenalan bukanlah verdict provenance. - Tidak ada kunci penandatanganan, sertifikat, atau struktur COSE yang diproses oleh permukaan ini. Satu-satunya operasi kriptografis adalah hash konten SHA-256 di dalam jalur sintesis yang di-gate.
Kesesuaian
Bagian berjudul “Kesesuaian”| Klaim | Standar | Klausa |
|---|---|---|
| Manifest diserialisasi ke dalam satu store JUMBF yang menampung banyak manifest, dapat dialamatkan via URI. | C2PA 2.1 | §11.1.1 (p63.b) |
| Label Description-box adalah UTF-8 yang diakhiri null dengan rentang yang dikecualikan; toggle didefinisikan untuk semua Description box. | C2PA 2.1 | §11.1.4.1.1–11.1.4.1.2 (p63.a) |
Box Claim Signature berlabel c2pa.signature, bertipe c2cs, dan menampung satu box konten CBOR. | C2PA 2.1 | §11.1.4.4 (p63.c) |
| Hard binding mengikat manifest ke asetnya secara kriptografis dan mengekspos modifikasi — asersi hash tak-bertanda-tangan pada pratinjau ini TIDAK memenuhi standar ini. | C2PA 2.1 | §9.1 (p57) |
Semua klausa diparafrasakan. NextPDF tidak mereproduksi teks normatif. NextPDF tidak memegang sertifikasi apa pun dan tidak memberikan apa pun. Pernyataan di atas adalah pernyataan penyelarasan-struktural tentang tata letak box, label, dan binding — bukan hasil uji kesesuaian, bukan atestasi pihak ketiga, dan bukan klaim kesesuaian C2PA atau ISO. Profil C2PA-PDF belum difinalisasi; format wire yang disintesis melacak sebuah commit draf yang dipin. C2paCapabilityStatus mengenkode postur ini dalam kode: generallyAvailable dan conformanceClaimed adalah false dalam setiap konfigurasi. Output dari permukaan ini bukan Content Credential yang dapat diverifikasi, dan tidak ada jalur verifikasi di NextPDF.
Catatan pengembangan
Bagian berjudul “Catatan pengembangan”-
Grammar box JUMBF yang diimplementasikan parser (LBox big-endian 4-byte, TBox ASCII 4-byte, payload; superbox menyarangkan child box) mengikuti ISO 19566-5; standar tersebut berada di luar korpus yang dikutip, sehingga perilaku parser digrounding dari sumber produk, bukan kutipan spesifikasi.
-
Biarkan gate off di produksi. Sintesis draf tidak menambah kapabilitas yang tahan lama; byte yang dipancarkan bersifat transien dan sebaiknya di-re-embed setelah adapter yang stabil dikirimkan.
-
Asersikan
ExperimentalC2paEmbedder::SPEC_PIN_SHAterhadap commit draf yang diharapkan pipeline Anda. Jalankancomposer c2pa:draft-statusdi CI (exit 0 segar, 1 soft-warn, 2 hard-fail) untuk mendeteksi keusangan pin. -
Perlakukan
C2paCapabilityStatus::current()sebagai satu-satunya sumber kebenaran saat menampilkan status C2PA di tooling atau UI. Jangan menyatakan ulang boolean-nya secara manual;summary()aman untuk log dan endpoint status. -
Tangkap
C2paExceptionsebagai tipe payung saat mengonsumsiextract()atauparse(). Petakan keempat subclass ke counter telemetri yang berbeda menggunakan field terstrukturnya. -
Inject cap yang lebih ketat melalui konstruktor
JumbfBoxParseruntuk proses verifier yang terbatas memori; default-nya adalah cap produksi yang murah hati. -
C2paCapabilityStatus::__construct()bersifat publik, sehingga instance buatan tangan dapat membawa boolean sembarang. Instance semacam itu hanyalah value object; ia tidak mengubah perilaku apa pun.
Lihat juga
Bagian berjudul “Lihat juga”- Status kapabilitas pratinjau C2PA — halaman kapabilitas
- Keamanan — Referensi Mendalam (Pro)
- Compliance — Referensi Mendalam (Pro)
- Pratinjau penandatanganan post-quantum — Referensi Mendalam (Enterprise)
- Keamanan / Signing (Core)
Batas publikasi
Bagian berjudul “Batas publikasi”Halaman ini mendokumentasikan hanya perilaku yang dapat diamati secara eksternal dan permukaan API publik yang didukung. Jalur namespace internal, kelas helper, tabel mekanisme, nama file runbook, dan prefiks tiket berada di luar cakupan.