Pro editiestabiliteit: Experimenteel
C2PA-preview — Diepe referentie
In één oogopslag
Sectie met titel “In één oogopslag”Deze pagina is de reference op contractniveau voor het C2PA-preview-oppervlak (Content Credentials) in NextPDF Pro. Ze behandelt vijf publieke symbolen in NextPDF\Pro\Compliance\C2pa: de C2paManifestEmbedder SPI, het ManifestStore-waardeobject, de JumbfBoxParser, de C2paCapabilityStatus-descriptor en de gated Experimental\ExperimentalC2paEmbedder. Ook documenteert ze de Feature::PREVIEW_C2PA_DRAFT-gate en de bijbehorende omgevingsvariabele NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT.
Het oppervlak is experimenteel en gesplitst in twee lagen. De stabiele naad — ManifestStore, C2paManifestEmbedder, JumbfBoxParser — is altijd bereikbaar en draagt Manifest Store-bytes in beide richtingen. Draft-manifestsynthese leeft alleen in ExperimentalC2paEmbedder en is standaard uitgeschakeld. Het C2PA-PDF-profiel is niet gefinaliseerd door de werkgroep; het gesynthetiseerde wire-formaat is vastgepind op een draft-commit. Er wordt geen conformiteitsclaim gedaan, er is geen verificatiepad, en het inschakelen van de preview-vlag kan geen van beide creëren. De taakgerichte weergave staat op de capability-pagina.
Beschikbaarheid & licentiëring
Sectie met titel “Beschikbaarheid & licentiëring”Deze mogelijkheid wordt geleverd in NextPDF Pro (nextpdf/pro) en activeert met een Pro-tier-licentie-envelope. Een deployment zonder die entitlement laadt de klassen van de mogelijkheid niet. Vergelijk edities en verkrijg een licentie.
De licentie activeert het Pro-compliance-oppervlak als geheel. Het C2PA-oppervlak daarbinnen blijft een preview, ongeacht de licentie-tier. Draft-synthese vereist bovendien de proces-gate die hier gedocumenteerd staat; een Pro-licentie alleen schakelt die nooit in.
Publiek API-oppervlak
Sectie met titel “Publiek API-oppervlak”| Symbool | Parameters | Standaardgedrag | Retourneert | Gooit of faalt met | Opmerkingen |
|---|---|---|---|---|---|
C2paManifestEmbedder | — | Bytes-only embed/extract SPI; geen I/O; geen claim-synthese | — | — | Bevroren, vendor-neutrale naad-interface. |
C2paManifestEmbedder::embed() | string $pdfBytes, ManifestStore $store | Embedt $store->toBytes() op de door het profiel gedeclareerde locatie; een lege Store MAG als no-op round-trippen | string nieuwe PDF-bytes | C2paException bij elke embed-fout (te grote Store, ongeldige PDF, botsing van profiellocatie) | Implementaties muteren of behouden de invoerbytes nooit. |
C2paManifestEmbedder::extract() | string $pdfBytes | Goedkope detectieprobe; het geval zonder Store alloceert vrijwel niets | ?ManifestStore (null bij miss) | C2paException-subklasse wanneer een Store aanwezig is maar een hardening-invariant schendt | Een niet-null Store is al door de JumbfBoxParser-hardening gekomen. |
ManifestStore::fromBoxes() | array $boxes (list<JumbfBox>) | Wikkelt een door de parser gevalideerde geordende box-lijst | self | Gooit zelf niet; handmatig geconstrueerde JumbfBox dwingt dezelfde hardening af | De constructor is private; de box-volgorde is dragend voor round-trip-gelijkheid. |
ManifestStore::empty() | geen | Store met nul root-boxes | self | Gooit niet | toBytes() van een lege Store is de lege string. |
ManifestStore::isEmpty() | geen | Test op nul root-boxes | bool | Gooit niet | — |
ManifestStore::toBytes() | geen | Concateneert de serialisaties van de root-boxes | string | Gooit niet | Deze byte-reeks is wat een embedder wegschrijft. |
ManifestStore::size() | geen | Byte-lengte van toBytes() | int (>= 0) | Gooit niet | — |
JumbfBoxParser::__construct() | drie optionele cap-overrides | Productie-caps: 64 MiB per box, 128 MiB totaal, 4096 children per superbox | JumbfBoxParser | Gooit niet | De diepte-cap ligt vast op MAX_DEPTH (8) en is niet instelbaar via de constructor. |
JumbfBoxParser::parse() | string $bytes | Valideert en materialiseert de root-boxes; lege invoer levert [] | list<JumbfBox> | JumbfBombException, JumbfCycleDetectedException, JumbfDepthExceededException, MalformedJumbfException | Stateless; retourneert nooit een gedeeltelijke graph; gelijktijdige aanroepen op één instance zijn veilig. |
C2paCapabilityStatus::__construct() | zes benoemde readonly-velden | Bouwt een willekeurige descriptor-instance | C2paCapabilityStatus | Gooit niet | current() is de canonieke constructor. |
C2paCapabilityStatus::current() | geen | Leest de gate live; hardcodeert de claim-booleans | C2paCapabilityStatus | Gooit niet | generallyAvailable en conformanceClaimed zijn altijd false. |
C2paCapabilityStatus::summary() | geen | Statustekst van één regel | string | Gooit niet | Zo geformuleerd dat ze geen GA- of conformiteitsclaim draagt. |
Feature | string-backed enum, 1 case | Enkele case PREVIEW_C2PA_DRAFT; constante ENV_PREVIEW_C2PA_DRAFT | enum-case | Niets bij case-toegang | Gescopete stabiliteits-gate; los van licentie-entitlement. |
Feature::isEnabled() | geen | Leest getenv() live; strikte vergelijking met de string 1 | bool | Gooit niet | Afwezige variabele of elke andere waarde, inclusief 0, true, yes, staat uit. |
ExperimentalC2paEmbedder::__construct() | geen | Fail-closed gate-check bij constructietijd | ExperimentalC2paEmbedder | LogicException wanneer Feature::PREVIEW_C2PA_DRAFT uit staat | Er bestaat geen stille fallback. |
ExperimentalC2paEmbedder::buildManifestStore() | string $sourceBytes, string $producer (non-empty) | Bouwt een draft-vormige Store die $sourceBytes bindt via SHA-256 | ManifestStore | \JsonException bij falen van payload-encode; C2paException-subklassen bij box-constructie | Laat de c2cs Claim Signature box weg; de output is door constructie ongesigneerd. |
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): ManifestStoreGedragscontract
Sectie met titel “Gedragscontract”- Splitsing in twee lagen. De stabiele naad (
ManifestStore,C2paManifestEmbedder,JumbfBoxParser) is altijd bereikbaar. Draft-synthese bestaat alleen inNextPDF\Pro\Compliance\C2pa\Experimental\ExperimentalC2paEmbedderachter de standaard uitgeschakelde gate. Extractie en byte-carry vereisen de gate nooit; synthese altijd wel. - Naad-invarianten. Het
C2paManifestEmbedder-contract is bytes-only: er kruisen geen in-memory PDF-objecten de naad, implementaties voeren geen netwerk- of filesystem-I/O uit, en de naad stelt zelf nooit claim-assertions samen.extract()retourneertnullom afwezigheid te signaleren; het gooit nooit voor afwezigheid. - Store-semantiek.
ManifestStoreis een onveranderbare geordende lijst van root-JumbfBox-instances, conform het Manifest Store-model van C2PA 2.1 §11.1.1: één JUMBF-container die een of meer manifests aggregeert, adresseerbaar per URI. Het legt geen claim-niveau-accessors bloot. De box-volgorde blijft behouden en is dragend voor round-trip-gelijkheid. - Hardening-caps.
JumbfBoxParserweigert onvoorwaardelijk invoer die een cap overschrijdt: per-box-grootte boven 64 MiB, cumulatieve store boven 128 MiB, nesting dieper dan 8 niveaus, of meer dan 4096 children in één superbox. Geen enkele policy-vlag schakelt deze caps uit. Strakkere caps zijn via de constructor injecteerbaar voor geheugen-beperkte processen. - Structurele afwijzing. De parser weigert ook, fail-closed:
LBox = 0(BMFF tot-EOF),LBox = 1(XLBox 64-bit lengte), eenLBoxkleiner dan de 8-byte header, truncatie voorbij de resterende invoer, TBox-bytes buiten printbare ASCII (0x20–0x7E), offset-heringang (cycli), en niet-exacte child-tiling van een superbox-payload. Het retourneert nooit een gedeeltelijk geconstrueerde graph. - Superbox-routing. TBox-waarden in
SUPERBOX_TBOXESparsen recursief als child-sequenties; elke andere TBox is een leaf met een opaque payload.cborwordt bewust als leaf behandeld voor parser-veiligheid; hogere lagen herparsen de payload ervan wanneer nodig. - Proces-gate.
Feature::PREVIEW_C2PA_DRAFTstaat standaard uit.isEnabled()retourneert alleentruewanneerNEXTPDF_FEATURE_PREVIEW_C2PA_DRAFTexact gelijk is aan de string1. De lezing gebeurt live bij elke aanroep; niets wordt gememoïseerd. - Fail-closed constructie.
new ExperimentalC2paEmbedder()gooitLogicExceptionterwijl de gate uit staat. Het bericht noemt de vlag, de omgevingsvariabele en de vastgepinde draft-SHA en -datum. Een caller kan draft-synthese niet per ongeluk bereiken. - Synthese-vorm.
buildManifestStore()emitteert eenc2pa-superbox met daarin éénc2ma-manifest, dat eenc2as-assertion-store (éénc2pa.hash.data-assertion) en eenc2cl-claim bevat. De assertion registreert een SHA-256-hash-assertion over$sourceBytes; omdat dec2csClaim Signature box wordt weggelaten en de output ongesigneerd is, is dit GEEN C2PA hard binding of provenance-verdict — het volgt alleen de structurele vorm die §9.1 beschrijft. Description-box-payloads dragen een type-UUID, toggles0x03en een null-terminated UTF-8-label, conform C2PA 2.1 §11.1.4.1.1–11.1.4.1.2. - Geen Claim Signature. De
c2cs-box — conform C2PA 2.1 §11.1.4.4 een enkele CBOR content box met labelc2pa.signature— wordt opzettelijk weggelaten uit de gesynthetiseerde Store. De output is door constructie ongesigneerd. Dit is de profielregio waarvan geoordeeld is dat die het meest waarschijnlijk drift vóór de bevriezing door de werkgroep. - Draft-pin, geen BC-garantie. Het gesynthetiseerde wire-formaat is vastgepind op
SPEC_PIN_SHA(4e2afed8…, gedateerd2026-04-26) vanc2pa-org/specifications. Het kan zonder aankondiging veranderen en draagt geen backwards-compatibiliteitsgarantie. - Eerlijkheids-invariant.
C2paCapabilityStatus::current()hardcodeertgenerallyAvailableenconformanceClaimedopfalse. Geen configuratie- of omgevingsvlag draait een van beide booleans om. AlleenpreviewEnabledweerspiegelt de gate;maturityis de niet-claimende tokenpreview-draft.
Randgevallen & faalmodi
Sectie met titel “Randgevallen & faalmodi”- Het instellen van de gate-variabele op
0,true,yes,onof een lege string laat de gate uit. Alleen de exacte string1schakelt hem in. - Wijzigingen via
putenv()worden van kracht bij de volgendeisEnabled()-aanroep omdat de lezing live is. Een gate die midden in het proces wordt omgeschakeld, wordt onmiddellijk waargenomen. extract()onderscheidt twee uitkomsten:nullwanneer geen Store aanwezig is (goedkoop, exceptie-vrij), en een geworpenC2paException-subklasse wanneer een Store aanwezig maar vijandig of malformed is. Afwezigheid is nooit een fout; aanwezigheid plus malformatie altijd wel.JumbfBoxParser::parse('')retourneert de lege lijst. Een lege maar aanwezigeManifestStoreround-tript naar zichzelf; de naad reduceert die niet totnull.- Het embedden van een lege Store MAG de invoer ongewijzigd retourneren. Het naad-contract staat deze no-op toe maar verplicht die niet.
- Handmatig geconstrueerde
JumbfBox-graphs draaien dezelfde hardening bij constructietijd: TBox-lengte- en ASCII-checks, de diepte-cap, de child-diepte-invariant, de payload-of-children-exclusiviteitsregel, en de per-box-grootte-cap. Een handmatig geconstrueerde bom faalt bij constructie, niet bij embed-tijd. - Elke parser-exceptie draagt gestructureerde velden —
capKind/observed/cap,offsetofkind— zodat telemetrie geen berichtstrings hoeft te scrapen. Alle subklassen breidenC2paExceptionuit (zelf eenRuntimeException), wat het overkoepelende catch-type is. - Het parser-docblock verbiedt het stil inslikken van deze excepties; consumers laten ze doorkomen of remappen ze met opzet.
buildManifestStore()encodeert JSON-payloads metJSON_THROW_ON_ERROR; een$producer-string die geen geldige UTF-8 is, faalt met\JsonExceptionvoordat er ook maar één box gebouwd wordt.- Een welgevormd
extract()-resultaat is louter een structurele uitspraak. Er is nergens op dit oppervlak claim-validatie, handtekening-verificatie of trust-evaluatie. Herkenning is geen provenance-verdict. - Er wordt geen ondertekeningssleutel, certificaat of COSE-structuur door dit oppervlak verwerkt. De enige cryptografische operatie is een SHA-256-content-hash binnen het gated synthese-pad.
Conformiteit
Sectie met titel “Conformiteit”| Claim | Standaard | Clausule |
|---|---|---|
| Manifests serialiseren in één JUMBF-store die meerdere manifests bevat, adresseerbaar per URI. | C2PA 2.1 | §11.1.1 (p63.b) |
| Description-box-labels zijn null-terminated UTF-8 met uitgesloten ranges; toggles zijn gedefinieerd voor alle Description boxes. | C2PA 2.1 | §11.1.4.1.1–11.1.4.1.2 (p63.a) |
De Claim Signature box heeft label c2pa.signature, type c2cs, en bevat een enkele CBOR content box. | C2PA 2.1 | §11.1.4.4 (p63.c) |
| Een hard binding bindt een manifest cryptografisch aan zijn asset en legt modificatie bloot — de ongesigneerde hash-assertion van de preview voldoet NIET aan deze lat. | C2PA 2.1 | §9.1 (p57) |
Alle clausules zijn geparafraseerd. NextPDF reproduceert geen normatieve tekst. NextPDF houdt geen certificering en verleent er geen. De bovenstaande uitspraken zijn structurele-uitlijningsuitspraken over box-layout, labels en bindings — het zijn geen conformiteitstest-resultaten, geen attestaties van derden, en geen C2PA- of ISO-conformiteitsclaim. Het C2PA-PDF-profiel is niet gefinaliseerd; het gesynthetiseerde wire-formaat volgt een vastgepinde draft-commit. C2paCapabilityStatus codeert deze houding in code: generallyAvailable en conformanceClaimed zijn false in elke configuratie. Output van dit oppervlak is geen verifieerbaar Content Credential, en er bestaat geen verificatiepad in NextPDF.
Ontwikkelnotities
Sectie met titel “Ontwikkelnotities”-
De JUMBF-box-grammatica die de parser implementeert (4-byte big-endian LBox, 4-byte ASCII TBox, payload; superboxes nesten child-boxes) volgt ISO 19566-5; die standaard valt buiten het geciteerde corpus, dus het parser-gedrag is gegrond in de productbron, niet in een spec-citatie.
-
Houd de gate uit in productie. Draft-synthese voegt geen duurzame mogelijkheid toe; de geëmitteerde bytes zijn kortstondig en moeten opnieuw geëmbed worden zodra een stabiele adapter beschikbaar komt.
-
Assert
ExperimentalC2paEmbedder::SPEC_PIN_SHAtegen de draft-commit die je pipeline verwacht. Draaicomposer c2pa:draft-statusin CI (exit 0 vers, 1 soft-warn, 2 hard-fail) om pin-veroudering te detecteren. -
Behandel
C2paCapabilityStatus::current()als de enige bron van waarheid bij het tonen van C2PA-status in tooling of UI. Herformuleer de booleans ervan niet met de hand;summary()is veilig voor logs en status-endpoints. -
Vang
C2paExceptionals overkoepelend type bij het consumeren vanextract()ofparse(). Map de vier subklassen naar afzonderlijke telemetrie-counters met hun gestructureerde velden. -
Injecteer strakkere caps via de
JumbfBoxParser-constructor voor geheugen-beperkte verifier-processen; de defaults zijn ruime productie-caps. -
C2paCapabilityStatus::__construct()is public, dus een handmatig geconstrueerde instance kan willekeurige booleans dragen. Zo’n instance is slechts een waardeobject; het verandert geen enkel gedrag.
Zie ook
Sectie met titel “Zie ook”- C2PA preview-capability-status — capability-pagina
- Security — Deep Reference (Pro)
- Compliance — Deep Reference (Pro)
- Post-quantum signing preview — Deep Reference (Enterprise)
- Security / Signing (Core)
Publicatiegrens
Sectie met titel “Publicatiegrens”Deze pagina documenteert alleen extern waarneembaar gedrag en het ondersteunde publieke API-oppervlak. Interne namespace-paden, helper-klassen, mechanisme-tabellen, runbook-bestandsnamen en ticket-prefixes vallen buiten scope.