Pular para o conteúdo
getnextpdf.com

Pro ediçãoestabilidade: Experimental

Preview do C2PA — Referência Profunda

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.

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.

SímboloParâmetrosComportamento padrãoRetornaLança ou falha comObservações
C2paManifestEmbedderSPI de embed/extract somente-bytes; sem I/O; sem síntese de claimInterface de costura congelada e neutra em relação a fornecedor.
C2paManifestEmbedder::embed()string $pdfBytes, ManifestStore $storeEmbute $store->toBytes() no local declarado pelo perfil; um Store vazio PODE fazer round-trip como no-opstring novos bytes do PDFC2paException 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 $pdfBytesSonda 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çoUm 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 parserselfNão lança por si só; a construção manual de JumbfBox aplica o mesmo reforçoO construtor é privado; a ordem dos boxes é determinante para a igualdade em round-trip.
ManifestStore::empty()nenhumStore com zero boxes-raizselfNão lançatoBytes() de um Store vazio é a string vazia.
ManifestStore::isEmpty()nenhumTesta se há zero boxes-raizboolNão lança
ManifestStore::toBytes()nenhumConcatena as serializações dos boxes-raizstringNão lançaEssa sequência de bytes é o que um embedder escreve.
ManifestStore::size()nenhumComprimento em bytes de toBytes()int (>= 0)Não lança
JumbfBoxParser::__construct()três overrides opcionais de limiteLimites de produção: 64 MiB por box, 128 MiB no total, 4096 filhos por superboxJumbfBoxParserNão lançaO limite de profundidade é fixo em MAX_DEPTH (8) e não é ajustável pelo construtor.
JumbfBoxParser::parse()string $bytesValida e materializa os boxes-raiz; entrada vazia produz []list<JumbfBox>JumbfBombException, JumbfCycleDetectedException, JumbfDepthExceededException, MalformedJumbfExceptionSem estado; nunca retorna um grafo parcial; chamadas concorrentes em uma instância são seguras.
C2paCapabilityStatus::__construct()seis campos readonly nomeadosConstrói uma instância de descritor arbitráriaC2paCapabilityStatusNão lançacurrent() é o construtor canônico.
C2paCapabilityStatus::current()nenhumLê o gate ao vivo; fixa os booleanos de alegação no códigoC2paCapabilityStatusNão lançagenerallyAvailable e conformanceClaimed são sempre false.
C2paCapabilityStatus::summary()nenhumTexto de status de uma linhastringNão lançaRedigido para não carregar nenhuma alegação de GA ou conformidade.
Featureenum baseado em string, 1 casoCaso único PREVIEW_C2PA_DRAFT; constante ENV_PREVIEW_C2PA_DRAFTcaso do enumNada ao acessar o casoGate de estabilidade delimitado; distinto do direito de uso da licença.
Feature::isEnabled()nenhumgetenv() ao vivo; comparação estrita com a string 1boolNão lançaVariável ausente ou qualquer outro valor, incluindo 0, true, yes, está desligado.
ExperimentalC2paEmbedder::__construct()nenhumVerificação de gate fail-closed no momento da construçãoExperimentalC2paEmbedderLogicException quando Feature::PREVIEW_C2PA_DRAFT está desligadoNã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-256ManifestStore\JsonException em falha de codificação do payload; subclasses de C2paException a partir da construção de boxesOmite 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): 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
  • Divisão em duas camadas. A costura estável (ManifestStore, C2paManifestEmbedder, JumbfBoxParser) está sempre acessível. A síntese de rascunho existe apenas em NextPDF\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() retorna null para sinalizar ausência; ela nunca lança por ausência.
  • Semântica do Store. ManifestStore é uma lista ordenada e imutável de instâncias JumbfBox raiz, 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 JumbfBoxParser rejeita 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), um LBox menor 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_TBOXES sã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_DRAFT está desligado por padrão. isEnabled() retorna true somente quando NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT é exatamente igual à string 1. A leitura é ao vivo a cada chamada; nada é memoizado.
  • Construção fail-closed. new ExperimentalC2paEmbedder() lança LogicException enquanto 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 superbox c2pa contendo um manifest c2ma, que contém um assertion store c2as (uma assertion c2pa.hash.data) e um claim c2cl. A assertion registra uma assertion de hash SHA-256 sobre $sourceBytes; como o box de Claim Signature c2cs é 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, toggles 0x03 e 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 rotulado c2pa.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 de 2026-04-26) de c2pa-org/specifications. Ele pode mudar sem aviso e não carrega nenhuma garantia de compatibilidade retroativa.
  • Invariante de honestidade. C2paCapabilityStatus::current() fixa generallyAvailable e conformanceClaimed como false no código. Nenhuma flag de configuração ou de ambiente inverte qualquer um dos booleanos. Apenas previewEnabled reflete o gate; maturity é o token que não faz alegações preview-draft.
  • Definir a variável do gate como 0, true, yes, on ou uma string vazia deixa o gate desligado. Apenas a string exata 1 o habilita.
  • Alterações via putenv() entram em vigor na próxima chamada de isEnabled() porque a leitura é ao vivo. Um gate alternado durante o processo é observado imediatamente.
  • extract() distingue dois resultados: null quando nenhum Store está presente (barato, sem exceção) e uma subclasse de C2paException lanç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. Um ManifestStore vazio mas presente faz round-trip para si mesmo; a costura não o colapsa para null.
  • Embutir um Store vazio PODE retornar a entrada inalterada. O contrato da costura permite esse no-op, mas não o exige.
  • Grafos JumbfBox construí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, offset ou kind — para que a telemetria não precise raspar strings de mensagem. Todas as subclasses estendem C2paException (ela mesma uma RuntimeException), 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 com JSON_THROW_ON_ERROR; uma string $producer que não seja UTF-8 válido falha com \JsonException antes 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.
AlegaçãoNormaClá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.

  • 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_SHA contra o commit de rascunho que seu pipeline espera. Rode composer c2pa:draft-status no 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 C2paException como o tipo guarda-chuva ao consumir extract() ou parse(). Mapeie as quatro subclasses para contadores de telemetria distintos usando seus campos estruturados.

  • Injete limites mais estritos pelo construtor do JumbfBoxParser para 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.

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.