Pro ediçãoestabilidade: Experimental
Preview do C2PA — Referência Profunda
Visão geral
Seção intitulada “Visão geral”Esta página é a referência em nível de contrato para a superfície de preview do C2PA (Content Credentials) no NextPDF Pro. Ela cobre cinco símbolos públicos em NextPDF\Pro\Compliance\C2pa: o SPI C2paManifestEmbedder, o objeto de valor ManifestStore, o JumbfBoxParser, o descritor C2paCapabilityStatus e o Experimental\ExperimentalC2paEmbedder protegido por gate. Ela também documenta o gate Feature::PREVIEW_C2PA_DRAFT e sua variável de ambiente, NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT.
A superfície é experimental e dividida em duas camadas. A costura estável — ManifestStore, C2paManifestEmbedder, JumbfBoxParser — está sempre acessível e transporta os bytes do Manifest Store nos dois sentidos. A síntese de manifest de rascunho vive apenas no ExperimentalC2paEmbedder e fica desativada por padrão. O perfil C2PA-PDF não foi finalizado pelo grupo de trabalho; o formato de fio sintetizado está fixado em um commit de rascunho. Nenhuma alegação de conformidade é feita, não há caminho de verificação, e ativar a flag de preview não cria nem um nem outro. A visão orientada a tarefas fica na página de capacidade.
Disponibilidade e licenciamento
Seção intitulada “Disponibilidade e licenciamento”Esta capacidade acompanha o NextPDF Pro (nextpdf/pro) e é ativada com um envelope de licença de tier Pro. Uma implantação sem esse direito de uso não carrega as classes da capacidade. Compare as edições e obtenha uma licença.
A licença ativa a superfície de conformidade Pro como um todo. A superfície C2PA dentro dela permanece um preview independentemente do tier da licença. A síntese de rascunho exige, adicionalmente, o gate de processo documentado aqui; uma licença Pro sozinha nunca a habilita.
Superfície da API pública
Seção intitulada “Superfície da API pública”| Símbolo | Parâmetros | Comportamento padrão | Retorna | Lança ou falha com | Observações |
|---|---|---|---|---|---|
C2paManifestEmbedder | — | SPI de embed/extract somente-bytes; sem I/O; sem síntese de claim | — | — | Interface de costura congelada e neutra em relação a fornecedor. |
C2paManifestEmbedder::embed() | string $pdfBytes, ManifestStore $store | Embute $store->toBytes() no local declarado pelo perfil; um Store vazio PODE fazer round-trip como no-op | string novos bytes do PDF | C2paException em qualquer falha de embed (Store grande demais, PDF inválido, colisão de local do perfil) | As implementações nunca mutam nem retêm os bytes de entrada. |
C2paManifestEmbedder::extract() | string $pdfBytes | Sonda de detecção barata; o caso sem Store aloca quase nada | ?ManifestStore (null quando não encontra) | Subclasse de C2paException quando um Store está presente mas viola um invariante de reforço | Um Store não nulo já passou pelo reforço do JumbfBoxParser. |
ManifestStore::fromBoxes() | array $boxes (list<JumbfBox>) | Encapsula uma lista ordenada de boxes validada pelo parser | self | Não lança por si só; a construção manual de JumbfBox aplica o mesmo reforço | O construtor é privado; a ordem dos boxes é determinante para a igualdade em round-trip. |
ManifestStore::empty() | nenhum | Store com zero boxes-raiz | self | Não lança | toBytes() de um Store vazio é a string vazia. |
ManifestStore::isEmpty() | nenhum | Testa se há zero boxes-raiz | bool | Não lança | — |
ManifestStore::toBytes() | nenhum | Concatena as serializações dos boxes-raiz | string | Não lança | Essa sequência de bytes é o que um embedder escreve. |
ManifestStore::size() | nenhum | Comprimento em bytes de toBytes() | int (>= 0) | Não lança | — |
JumbfBoxParser::__construct() | três overrides opcionais de limite | Limites de produção: 64 MiB por box, 128 MiB no total, 4096 filhos por superbox | JumbfBoxParser | Não lança | O limite de profundidade é fixo em MAX_DEPTH (8) e não é ajustável pelo construtor. |
JumbfBoxParser::parse() | string $bytes | Valida e materializa os boxes-raiz; entrada vazia produz [] | list<JumbfBox> | JumbfBombException, JumbfCycleDetectedException, JumbfDepthExceededException, MalformedJumbfException | Sem estado; nunca retorna um grafo parcial; chamadas concorrentes em uma instância são seguras. |
C2paCapabilityStatus::__construct() | seis campos readonly nomeados | Constrói uma instância de descritor arbitrária | C2paCapabilityStatus | Não lança | current() é o construtor canônico. |
C2paCapabilityStatus::current() | nenhum | Lê o gate ao vivo; fixa os booleanos de alegação no código | C2paCapabilityStatus | Não lança | generallyAvailable e conformanceClaimed são sempre false. |
C2paCapabilityStatus::summary() | nenhum | Texto de status de uma linha | string | Não lança | Redigido para não carregar nenhuma alegação de GA ou conformidade. |
Feature | enum baseado em string, 1 caso | Caso único PREVIEW_C2PA_DRAFT; constante ENV_PREVIEW_C2PA_DRAFT | caso do enum | Nada ao acessar o caso | Gate de estabilidade delimitado; distinto do direito de uso da licença. |
Feature::isEnabled() | nenhum | Lê getenv() ao vivo; comparação estrita com a string 1 | bool | Não lança | Variável ausente ou qualquer outro valor, incluindo 0, true, yes, está desligado. |
ExperimentalC2paEmbedder::__construct() | nenhum | Verificação de gate fail-closed no momento da construção | ExperimentalC2paEmbedder | LogicException quando Feature::PREVIEW_C2PA_DRAFT está desligado | Não existe fallback silencioso. |
ExperimentalC2paEmbedder::buildManifestStore() | string $sourceBytes, string $producer (não vazio) | Constrói um Store no formato de rascunho vinculando $sourceBytes via SHA-256 | ManifestStore | \JsonException em falha de codificação do payload; subclasses de C2paException a partir da construção de boxes | Omite o box de Claim Signature c2cs; a saída é não assinada por construção. |
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): ManifestStoreContrato de comportamento
Seção intitulada “Contrato de comportamento”- Divisão em duas camadas. A costura estável (
ManifestStore,C2paManifestEmbedder,JumbfBoxParser) está sempre acessível. A síntese de rascunho existe apenas emNextPDF\Pro\Compliance\C2pa\Experimental\ExperimentalC2paEmbedder, atrás do gate desativado por padrão. Extração e transporte de bytes nunca exigem o gate; a síntese sempre exige. - Invariantes da costura. O contrato do
C2paManifestEmbedderé somente-bytes: nenhum objeto PDF em memória cruza a costura, as implementações não realizam I/O de rede ou de sistema de arquivos, e a costura nunca monta assertions de claim por conta própria.extract()retornanullpara sinalizar ausência; ela nunca lança por ausência. - Semântica do Store.
ManifestStoreé uma lista ordenada e imutável de instânciasJumbfBoxraiz, conforme o modelo de Manifest Store do C2PA 2.1 §11.1.1: um contêiner JUMBF agregando um ou mais manifests, endereçáveis por URI. Ele não expõe nenhum accessor em nível de claim. A ordem dos boxes é preservada e é determinante para a igualdade em round-trip. - Limites de reforço. O
JumbfBoxParserrejeita incondicionalmente entradas que excedam qualquer limite: tamanho por box acima de 64 MiB, store acumulado acima de 128 MiB, aninhamento mais profundo que 8 níveis ou mais de 4096 filhos em um superbox. Nenhuma flag de política desabilita esses limites. Limites mais estritos são injetáveis pelo construtor para processos com memória restrita. - Rejeição estrutural. O parser também rejeita, fail-closed:
LBox = 0(BMFF até-EOF),LBox = 1(XLBox de 64 bits), umLBoxmenor que o cabeçalho de 8 bytes, truncamento além da entrada restante, bytes de TBox fora do ASCII imprimível (0x20–0x7E), reentrada de offset (ciclos) e ladrilhamento não exato dos boxes filhos sobre o payload de um superbox. Ele nunca retorna um grafo parcialmente construído. - Roteamento de superbox. Valores de TBox em
SUPERBOX_TBOXESsão parseados recursivamente como sequências de filhos; todo outro TBox é uma folha com um payload opaco.cboré deliberadamente tratado como folha por segurança do parser; camadas superiores reparseiam seu payload quando necessário. - Gate de processo.
Feature::PREVIEW_C2PA_DRAFTestá desligado por padrão.isEnabled()retornatruesomente quandoNEXTPDF_FEATURE_PREVIEW_C2PA_DRAFTé exatamente igual à string1. A leitura é ao vivo a cada chamada; nada é memoizado. - Construção fail-closed.
new ExperimentalC2paEmbedder()lançaLogicExceptionenquanto o gate está desligado. A mensagem nomeia a flag, a variável de ambiente e o SHA e a data do rascunho fixado. Um chamador não pode alcançar a síntese de rascunho por acidente. - Formato da síntese.
buildManifestStore()emite um superboxc2pacontendo um manifestc2ma, que contém um assertion storec2as(uma assertionc2pa.hash.data) e um claimc2cl. A assertion registra uma assertion de hash SHA-256 sobre$sourceBytes; como o box de Claim Signaturec2csé omitido e a saída é não assinada, isto NÃO é um hard binding do C2PA nem um veredito de proveniência — apenas segue o formato estrutural que o §9.1 descreve. Os payloads dos Description boxes carregam um type UUID, toggles0x03e um label UTF-8 terminado em null, conforme C2PA 2.1 §11.1.4.1.1–11.1.4.1.2. - Sem Claim Signature. O box
c2cs— conforme C2PA 2.1 §11.1.4.4 um único CBOR content box rotuladoc2pa.signature— é intencionalmente omitido do Store sintetizado. A saída é não assinada por construção. Esta é a região do perfil considerada mais propensa a mudar antes do congelamento pelo grupo de trabalho. - Pin de rascunho, sem garantia de BC. O formato de fio sintetizado está fixado em
SPEC_PIN_SHA(4e2afed8…, datado de2026-04-26) dec2pa-org/specifications. Ele pode mudar sem aviso e não carrega nenhuma garantia de compatibilidade retroativa. - Invariante de honestidade.
C2paCapabilityStatus::current()fixagenerallyAvailableeconformanceClaimedcomofalseno código. Nenhuma flag de configuração ou de ambiente inverte qualquer um dos booleanos. ApenaspreviewEnabledreflete o gate;maturityé o token que não faz alegaçõespreview-draft.
Casos-limite e modos de falha
Seção intitulada “Casos-limite e modos de falha”- Definir a variável do gate como
0,true,yes,onou uma string vazia deixa o gate desligado. Apenas a string exata1o habilita. - Alterações via
putenv()entram em vigor na próxima chamada deisEnabled()porque a leitura é ao vivo. Um gate alternado durante o processo é observado imediatamente. extract()distingue dois resultados:nullquando nenhum Store está presente (barato, sem exceção) e uma subclasse deC2paExceptionlançada quando um Store está presente mas é hostil ou malformado. Ausência nunca é um erro; presença mais malformação sempre é.JumbfBoxParser::parse('')retorna a lista vazia. UmManifestStorevazio mas presente faz round-trip para si mesmo; a costura não o colapsa paranull.- Embutir um Store vazio PODE retornar a entrada inalterada. O contrato da costura permite esse no-op, mas não o exige.
- Grafos
JumbfBoxconstruídos manualmente passam pelo mesmo reforço no momento da construção: verificações de comprimento e ASCII do TBox, o limite de profundidade, o invariante de profundidade de filhos, a regra de exclusividade payload-ou-filhos e o limite de tamanho por box. Uma bomba construída manualmente falha na construção, não no momento do embed. - Toda exceção do parser carrega campos estruturados —
capKind/observed/cap,offsetoukind— para que a telemetria não precise raspar strings de mensagem. Todas as subclasses estendemC2paException(ela mesma umaRuntimeException), que é o tipo guarda-chuva de captura. - O docblock do parser proíbe engolir silenciosamente essas exceções; os consumidores as expõem ou as remapeiam com intenção.
buildManifestStore()codifica os payloads JSON comJSON_THROW_ON_ERROR; uma string$producerque não seja UTF-8 válido falha com\JsonExceptionantes de qualquer box ser construído.- Um resultado bem formado de
extract()é apenas uma afirmação estrutural. Não há validação de claim, nem verificação de assinatura, nem avaliação de confiança em nenhum ponto desta superfície. Reconhecimento não é um veredito de proveniência. - Nenhuma chave de assinatura, certificado ou estrutura COSE é processada por esta superfície. A única operação criptográfica é um hash de conteúdo SHA-256 dentro do caminho de síntese protegido por gate.
Conformidade
Seção intitulada “Conformidade”| Alegação | Norma | Cláusula |
|---|---|---|
| Os manifests serializam em um único store JUMBF que contém múltiplos manifests, endereçáveis por URI. | C2PA 2.1 | §11.1.1 (p63.b) |
| Os labels dos Description boxes são UTF-8 terminados em null com faixas excluídas; os toggles são definidos para todos os Description boxes. | C2PA 2.1 | §11.1.4.1.1–11.1.4.1.2 (p63.a) |
O box de Claim Signature é rotulado c2pa.signature, tipado c2cs, e contém um único CBOR content box. | C2PA 2.1 | §11.1.4.4 (p63.c) |
| Um hard binding vincula criptograficamente um manifest ao seu asset e expõe modificações — a assertion de hash não assinada do preview NÃO atende a esse critério. | C2PA 2.1 | §9.1 (p57) |
Todas as cláusulas são parafraseadas. O NextPDF não reproduz texto normativo. O NextPDF não possui nenhuma certificação e não concede nenhuma. As afirmações acima são afirmações de alinhamento estrutural sobre layout de boxes, labels e bindings — elas não são resultados de teste de conformidade, não são atestações de terceiros e não são uma alegação de conformidade C2PA ou ISO. O perfil C2PA-PDF não está finalizado; o formato de fio sintetizado acompanha um commit de rascunho fixado. O C2paCapabilityStatus codifica essa postura no código: generallyAvailable e conformanceClaimed são false em toda configuração. A saída desta superfície não é uma Content Credential verificável, e não existe caminho de verificação no NextPDF.
Notas de desenvolvimento
Seção intitulada “Notas de desenvolvimento”-
A gramática de boxes JUMBF que o parser implementa (LBox big-endian de 4 bytes, TBox ASCII de 4 bytes, payload; superboxes aninham boxes filhos) segue a ISO 19566-5; essa norma está fora do corpus citado, então o comportamento do parser é fundamentado no código-fonte do produto, não em uma citação de spec.
-
Mantenha o gate desligado em produção. A síntese de rascunho não adiciona nenhuma capacidade durável; os bytes emitidos são transitórios e devem ser reembutidos assim que um adaptador estável for lançado.
-
Verifique
ExperimentalC2paEmbedder::SPEC_PIN_SHAcontra o commit de rascunho que seu pipeline espera. Rodecomposer c2pa:draft-statusno CI (exit 0 atualizado, 1 aviso leve, 2 falha grave) para detectar defasagem do pin. -
Trate
C2paCapabilityStatus::current()como a única fonte de verdade ao expor o status do C2PA em ferramentas ou UI. Não repita seus booleanos manualmente;summary()é seguro para logs e endpoints de status. -
Capture
C2paExceptioncomo o tipo guarda-chuva ao consumirextract()ouparse(). Mapeie as quatro subclasses para contadores de telemetria distintos usando seus campos estruturados. -
Injete limites mais estritos pelo construtor do
JumbfBoxParserpara processos verificadores com memória restrita; os padrões são limites de produção generosos. -
C2paCapabilityStatus::__construct()é público, então uma instância construída manualmente pode carregar booleanos arbitrários. Tal instância é apenas um objeto de valor; ela não altera nenhum comportamento.
Veja também
Seção intitulada “Veja também”- Status da capacidade de preview do C2PA — página de capacidade
- Segurança — Referência Detalhada (Pro)
- Conformidade — Referência Detalhada (Pro)
- Preview de assinatura pós-quântica — Referência Detalhada (Enterprise)
- Segurança / Assinatura (Core)
Fronteira de publicação
Seção intitulada “Fronteira de publicação”Esta página documenta apenas o comportamento observável externamente e a superfície pública de API suportada. Caminhos de namespace internos, classes auxiliares, tabelas de mecanismos, nomes de arquivos de runbook e prefixos de tickets estão fora de escopo.