Przejdź do głównej zawartości
getnextpdf.com

Pro edycjastabilność: Eksperymentalna

Podgląd C2PA — szczegółowa dokumentacja referencyjna

Ta strona jest dokumentacją na poziomie kontraktu dla powierzchni podglądu C2PA (Content Credentials) w NextPDF Pro. Obejmuje pięć publicznych symboli w NextPDF\Pro\Compliance\C2pa: SPI C2paManifestEmbedder, obiekt wartości ManifestStore, JumbfBoxParser, deskryptor C2paCapabilityStatus oraz bramkowany Experimental\ExperimentalC2paEmbedder. Dokumentuje także bramkę Feature::PREVIEW_C2PA_DRAFT i jej zmienną środowiskową NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT.

Powierzchnia jest eksperymentalna i podzielona na dwie warstwy. Stabilna złączka — ManifestStore, C2paManifestEmbedder, JumbfBoxParser — jest zawsze osiągalna i przenosi bajty Manifest Store w obie strony. Synteza roboczego manifestu istnieje wyłącznie w ExperimentalC2paEmbedder i jest domyślnie wyłączona. Profil C2PA-PDF nie został sfinalizowany przez grupę roboczą; syntezowany format transmisji jest przypięty do roboczego commitu. Nie deklaruje się żadnej zgodności, nie istnieje ścieżka weryfikacji, a włączenie flagi podglądu nie może stworzyć żadnej z nich. Widok zorientowany na zadania znajduje się na stronie możliwości.

Ta możliwość jest dostarczana w NextPDF Pro (nextpdf/pro) i aktywuje się wraz z kopertą licencyjną poziomu Pro. Wdrożenie bez tego uprawnienia nie ładuje klas tej możliwości. Porównaj edycje i uzyskaj licencję.

Licencja aktywuje całą powierzchnię zgodności Pro. Powierzchnia C2PA wewnątrz niej pozostaje podglądem niezależnie od poziomu licencji. Synteza wersji roboczej dodatkowo wymaga bramki procesu opisanej tutaj; sama licencja Pro nigdy jej nie włącza.

SymbolParametryZachowanie domyślneZwracaZgłasza lub kończy się niepowodzeniem zUwagi
C2paManifestEmbedderWyłącznie bajtowe SPI osadzania/wyodrębniania; brak I/O; brak syntezy deklaracjiZamrożony, neutralny wobec dostawcy interfejs złączki.
C2paManifestEmbedder::embed()string $pdfBytes, ManifestStore $storeOsadza $store->toBytes() w miejscu zadeklarowanym w profilu; pusty Store MOŻE przejść tam i z powrotem jako no-opstring nowe bajty PDFC2paException przy dowolnym niepowodzeniu osadzania (nadmiarowy Store, nieprawidłowy PDF, kolizja lokalizacji profilu)Implementacje nigdy nie modyfikują ani nie zatrzymują wejściowych bajtów.
C2paManifestEmbedder::extract()string $pdfBytesTania sonda wykrywająca; przypadek braku Store alokuje niemal nic?ManifestStore (null przy braku)Podklasa C2paException, gdy Store jest obecny, ale narusza niezmiennik utwardzeniaNiepusty Store przeszedł już utwardzenie JumbfBoxParser.
ManifestStore::fromBoxes()array $boxes (list<JumbfBox>)Opakowuje uporządkowaną listę pól zwalidowaną przez parserselfSam nie zgłasza; ręczna konstrukcja JumbfBox wymusza to samo utwardzenieKonstruktor jest prywatny; kolejność pól ma znaczenie dla równości przy przejściu tam i z powrotem.
ManifestStore::empty()brakStore z zerową liczbą pól głównychselfNie zgłaszatoBytes() pustego Store to pusty ciąg znaków.
ManifestStore::isEmpty()brakSprawdza brak pól głównychboolNie zgłasza
ManifestStore::toBytes()brakŁączy serializacje pól głównychstringNie zgłaszaTa sekwencja bajtów jest tym, co zapisuje mechanizm osadzający.
ManifestStore::size()brakDługość w bajtach toBytes()int (>= 0)Nie zgłasza
JumbfBoxParser::__construct()trzy opcjonalne nadpisania limitówLimity produkcyjne: 64 MiB na pole, 128 MiB łącznie, 4096 elementów potomnych na superpoleJumbfBoxParserNie zgłaszaLimit głębokości jest ustalony na MAX_DEPTH (8) i nie jest konfigurowalny przez konstruktor.
JumbfBoxParser::parse()string $bytesWaliduje i materializuje pola główne; puste wejście daje []list<JumbfBox>JumbfBombException, JumbfCycleDetectedException, JumbfDepthExceededException, MalformedJumbfExceptionBezstanowy; nigdy nie zwraca częściowego grafu; równoczesne wywołania na jednej instancji są bezpieczne.
C2paCapabilityStatus::__construct()sześć nazwanych pól readonlyBuduje dowolną instancję deskryptoraC2paCapabilityStatusNie zgłaszacurrent() jest kanonicznym konstruktorem.
C2paCapabilityStatus::current()brakOdczytuje bramkę na żywo; ustawia wartości logiczne deklaracji na stałeC2paCapabilityStatusNie zgłaszagenerallyAvailable i conformanceClaimed są zawsze false.
C2paCapabilityStatus::summary()brakJednowierszowy tekst statusustringNie zgłaszaSformułowany tak, by nie zawierać deklaracji GA ani zgodności.
Featureenum oparty na string, 1 przypadekPojedynczy przypadek PREVIEW_C2PA_DRAFT; stała ENV_PREVIEW_C2PA_DRAFTprzypadek enumNic przy dostępie do przypadkuZakresowa bramka stabilności; odrębna od uprawnienia licencyjnego.
Feature::isEnabled()brakOdczytuje getenv() na żywo; ścisłe porównanie z ciągiem 1boolNie zgłaszaBrak zmiennej lub dowolna inna wartość, w tym 0, true, yes, oznacza wyłączenie.
ExperimentalC2paEmbedder::__construct()brakKontrola bramki fail-closed w czasie konstrukcjiExperimentalC2paEmbedderLogicException, gdy Feature::PREVIEW_C2PA_DRAFT jest wyłączonaNie istnieje żaden cichy mechanizm awaryjny.
ExperimentalC2paEmbedder::buildManifestStore()string $sourceBytes, string $producer (niepusty)Buduje Store o kształcie roboczym wiążący $sourceBytes przez SHA-256ManifestStore\JsonException przy niepowodzeniu kodowania ładunku; podklasy C2paException z konstrukcji pólPomija pole c2cs Claim Signature; wyjście jest z założenia niepodpisane.
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): self
public static function empty(): self
public function isEmpty(): bool
public function toBytes(): string
public function size(): int
final 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): array
final 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(): self
public function summary(): string
enum Feature: string
case PREVIEW_C2PA_DRAFT = 'preview_c2pa_draft';
public const string ENV_PREVIEW_C2PA_DRAFT = 'NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT';
public function isEnabled(): bool
final 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): ManifestStore
  • Podział dwuwarstwowy. Stabilna złączka (ManifestStore, C2paManifestEmbedder, JumbfBoxParser) jest zawsze osiągalna. Synteza wersji roboczej istnieje wyłącznie w NextPDF\Pro\Compliance\C2pa\Experimental\ExperimentalC2paEmbedder za domyślnie wyłączoną bramką. Wyodrębnianie i przenoszenie bajtów nigdy nie wymaga bramki; synteza wymaga jej zawsze.
  • Niezmienniki złączki. Kontrakt C2paManifestEmbedder jest wyłącznie bajtowy: przez złączkę nie przechodzą żadne obiekty PDF w pamięci, implementacje nie wykonują I/O sieciowego ani plikowego, a złączka nigdy sama nie składa asercji deklaracji. extract() zwraca null, aby zasygnalizować brak; nigdy nie zgłasza wyjątku z powodu braku.
  • Semantyka Store. ManifestStore jest niezmienną, uporządkowaną listą głównych instancji JumbfBox, zgodnie z modelem Manifest Store z C2PA 2.1 §11.1.1: jeden kontener JUMBF agregujący jeden lub więcej manifestów, adresowalny przez URI. Nie udostępnia żadnych akcesorów na poziomie deklaracji. Kolejność pól jest zachowywana i ma znaczenie dla równości przy przejściu tam i z powrotem.
  • Limity utwardzenia. JumbfBoxParser bezwarunkowo odrzuca wejścia przekraczające dowolny limit: rozmiar pojedynczego pola powyżej 64 MiB, skumulowany store powyżej 128 MiB, zagnieżdżenie głębsze niż 8 poziomów lub więcej niż 4096 elementów potomnych w jednym superpolu. Żadna flaga polityki nie wyłącza tych limitów. Ściślejsze limity można wstrzyknąć przez konstruktor dla procesów o ograniczonej pamięci.
  • Odrzucenie strukturalne. Parser odrzuca również, fail-closed: LBox = 0 (BMFF do EOF), LBox = 1 (XLBox 64-bitowa długość), LBox mniejszy niż 8-bajtowy nagłówek, obcięcie poza pozostałym wejściem, bajty TBox spoza drukowalnego ASCII (0x20–0x7E), ponowne wejście po offsecie (cykle) oraz niedokładne kafelkowanie potomków w ładunku superpola. Nigdy nie zwraca częściowo skonstruowanego grafu.
  • Routing superpól. Wartości TBox w SUPERBOX_TBOXES są parsowane rekurencyjnie jako sekwencje potomków; każdy inny TBox jest liściem z nieprzejrzystym ładunkiem. cbor jest celowo traktowany jako liść ze względu na bezpieczeństwo parsera; warstwy nadrzędne ponownie parsują jego ładunek, gdy jest to potrzebne.
  • Bramka procesu. Feature::PREVIEW_C2PA_DRAFT jest domyślnie wyłączona. isEnabled() zwraca true tylko wtedy, gdy NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT jest dokładnie równe ciągowi 1. Odczyt jest na żywo przy każdym wywołaniu; nic nie jest zapamiętywane.
  • Konstrukcja fail-closed. new ExperimentalC2paEmbedder() zgłasza LogicException, gdy bramka jest wyłączona. Komunikat wymienia flagę, zmienną środowiskową oraz przypięty roboczy SHA i datę. Wywołujący nie może przypadkowo dotrzeć do syntezy wersji roboczej.
  • Kształt syntezy. buildManifestStore() emituje superpole c2pa zawierające jeden manifest c2ma, który przechowuje magazyn asercji c2as (jedna asercja c2pa.hash.data) oraz deklarację c2cl. Asercja zapisuje asercję skrótu SHA-256 nad $sourceBytes; ponieważ pole c2cs Claim Signature jest pominięte, a wyjście jest niepodpisane, NIE jest to twarde wiązanie (hard binding) C2PA ani werdykt o proweniencji — podąża jedynie za kształtem strukturalnym opisanym w §9.1. Ładunki pól Description niosą UUID typu, przełączniki 0x03 oraz zakończoną znakiem null etykietę UTF-8, zgodnie z C2PA 2.1 §11.1.4.1.1–11.1.4.1.2.
  • Brak Claim Signature. Pole c2cs — zgodnie z C2PA 2.1 §11.1.4.4 pojedyncze pole zawartości CBOR z etykietą c2pa.signature — jest celowo pomijane w syntezowanym Store. Wyjście jest z założenia niepodpisane. To obszar profilu oceniony jako najbardziej prawdopodobny do zmiany przed zamrożeniem przez grupę roboczą.
  • Przypięcie wersji roboczej, brak gwarancji BC. Syntezowany format transmisji jest przypięty do SPEC_PIN_SHA (4e2afed8…, z datą 2026-04-26) repozytorium c2pa-org/specifications. Może się zmienić bez powiadomienia i nie niesie żadnej gwarancji wstecznej kompatybilności.
  • Niezmiennik uczciwości. C2paCapabilityStatus::current() ustawia na stałe generallyAvailable i conformanceClaimed na false. Żadna konfiguracja ani flaga środowiskowa nie przełącza żadnej z tych wartości logicznych. Tylko previewEnabled odzwierciedla bramkę; maturity jest niedeklarującym tokenem preview-draft.
  • Ustawienie zmiennej bramki na 0, true, yes, on lub pusty ciąg pozostawia bramkę wyłączoną. Tylko dokładny ciąg 1 ją włącza.
  • Zmiany putenv() wchodzą w życie przy następnym wywołaniu isEnabled(), ponieważ odczyt jest na żywo. Bramka przełączona w trakcie procesu jest obserwowana natychmiast.
  • extract() rozróżnia dwa wyniki: null, gdy nie ma żadnego Store (tanie, bez wyjątków), oraz zgłoszoną podklasę C2paException, gdy Store jest obecny, ale wrogi lub zniekształcony. Brak nigdy nie jest błędem; obecność wraz ze zniekształceniem zawsze nim jest.
  • JumbfBoxParser::parse('') zwraca pustą listę. Pusty, lecz obecny ManifestStore przechodzi tam i z powrotem do samego siebie; złączka nie zwija go do null.
  • Osadzenie pustego Store MOŻE zwrócić wejście bez zmian. Kontrakt złączki dopuszcza ten no-op, lecz go nie nakazuje.
  • Ręcznie zbudowane grafy JumbfBox przechodzą to samo utwardzenie w czasie konstrukcji: kontrole długości i ASCII TBox, limit głębokości, niezmiennik głębokości potomków, regułę wyłączności ładunek-lub-potomkowie oraz limit rozmiaru pojedynczego pola. Ręcznie zbudowana bomba kończy się niepowodzeniem przy konstrukcji, a nie przy osadzaniu.
  • Każdy wyjątek parsera niesie ustrukturyzowane pola — capKind/observed/cap, offset lub kind — dzięki czemu telemetria nie zeskrobuje ciągów komunikatów. Wszystkie podklasy rozszerzają C2paException (samą będącą RuntimeException), która jest parasolowym typem przechwytywania.
  • Docblock parsera zakazuje cichego połykania tych wyjątków; konsumenci wynoszą je na powierzchnię lub przemapowują je z intencją.
  • buildManifestStore() koduje ładunki JSON z JSON_THROW_ON_ERROR; ciąg $producer, który nie jest prawidłowym UTF-8, kończy się niepowodzeniem z \JsonException, zanim zbudowane zostanie jakiekolwiek pole.
  • Poprawnie sformułowany wynik extract() jest wyłącznie stwierdzeniem strukturalnym. Nigdzie na tej powierzchni nie ma walidacji deklaracji, weryfikacji podpisu ani oceny zaufania. Rozpoznanie nie jest werdyktem o proweniencji.
  • Ta powierzchnia nie przetwarza żadnego klucza podpisu, certyfikatu ani struktury COSE. Jedyną operacją kryptograficzną jest skrót zawartości SHA-256 wewnątrz bramkowanej ścieżki syntezy.
DeklaracjaStandardKlauzula
Manifesty serializują się do jednego store JUMBF przechowującego wiele manifestów, adresowalnych przez URI.C2PA 2.1§11.1.1 (p63.b)
Etykiety pól Description są zakończonym znakiem null UTF-8 z wykluczonymi zakresami; przełączniki są zdefiniowane dla wszystkich pól Description.C2PA 2.1§11.1.4.1.1–11.1.4.1.2 (p63.a)
Pole Claim Signature ma etykietę c2pa.signature, typ c2cs i przechowuje pojedyncze pole zawartości CBOR.C2PA 2.1§11.1.4.4 (p63.c)
Twarde wiązanie kryptograficznie łączy manifest z jego zasobem i ujawnia modyfikację — niepodpisana asercja skrótu w podglądzie NIE spełnia tego progu.C2PA 2.1§9.1 (p57)

Wszystkie klauzule są parafrazowane. NextPDF nie odtwarza tekstu normatywnego. NextPDF nie posiada żadnej certyfikacji i żadnej nie udziela. Powyższe stwierdzenia są stwierdzeniami o zgodności strukturalnej dotyczącymi układu pól, etykiet i wiązań — nie są wynikami testów zgodności, nie są atestacjami stron trzecich ani deklaracją zgodności z C2PA czy ISO. Profil C2PA-PDF nie jest sfinalizowany; syntezowany format transmisji śledzi przypięty roboczy commit. C2paCapabilityStatus koduje tę postawę w kodzie: generallyAvailable i conformanceClaimedfalse w każdej konfiguracji. Wyjście z tej powierzchni nie jest weryfikowalnym Content Credential, a w NextPDF nie istnieje żadna ścieżka weryfikacji.

  • Gramatyka pól JUMBF, którą implementuje parser (4-bajtowy big-endian LBox, 4-bajtowy ASCII TBox, ładunek; superpola zagnieżdżają pola potomne), podąża za ISO 19566-5; standard ten jest poza cytowanym korpusem, więc zachowanie parsera jest oparte na źródle produktu, a nie na cytacie ze specyfikacji.

  • Utrzymuj bramkę wyłączoną w produkcji. Synteza wersji roboczej nie dodaje trwałej możliwości; emitowane bajty są przejściowe i powinny zostać ponownie osadzone, gdy tylko pojawi się stabilny adapter.

  • Weryfikuj ExperimentalC2paEmbedder::SPEC_PIN_SHA względem roboczego commitu, którego oczekuje Twój potok. Uruchom composer c2pa:draft-status w CI (kod wyjścia 0 świeży, 1 miękkie ostrzeżenie, 2 twarda porażka), aby wykryć nieaktualność przypięcia.

  • Traktuj C2paCapabilityStatus::current() jako jedyne źródło prawdy przy prezentowaniu statusu C2PA w narzędziach lub UI. Nie powtarzaj jego wartości logicznych ręcznie; summary() jest bezpieczne dla logów i punktów końcowych statusu.

  • Przechwytuj C2paException jako typ parasolowy podczas konsumowania extract() lub parse(). Mapuj cztery podklasy na odrębne liczniki telemetrii, używając ich ustrukturyzowanych pól.

  • Wstrzyknij ściślejsze limity przez konstruktor JumbfBoxParser dla procesów weryfikatora o ograniczonej pamięci; wartości domyślne są hojnymi limitami produkcyjnymi.

  • C2paCapabilityStatus::__construct() jest publiczny, więc ręcznie zbudowana instancja może nieść dowolne wartości logiczne. Taka instancja jest jedynie obiektem wartości; nie zmienia żadnego zachowania.

Ta strona dokumentuje wyłącznie zewnętrznie obserwowalne zachowanie oraz wspieraną publiczną powierzchnię API. Wewnętrzne ścieżki przestrzeni nazw, klasy pomocnicze, tabele mechanizmów, nazwy plików runbooków oraz prefiksy zgłoszeń są poza zakresem.