콘텐츠로 이동

적합성 검증: 인프로세스 사전 점검과 외부 오라클

이 레시피는 NextPDF의 순수 PHP 인프로세스 적합성 검증기를 빠른 구조 사전 점검으로 실행한 뒤, 권위 있는 적합성 판정을 독립 검증기로 넘깁니다. 인프로세스 점검은 필요조건이지 충분조건은 아닙니다: 깨끗한 결과는 구조적 사실일 뿐 적합성 판정이 아닙니다. 이 레시피는 examples/33-validate-conformance.php와 그 tests/Cookbook/Php/ValidateConformanceRecipeTest.php 하니스가 뒷받침합니다.

Terminal window
composer require nextpdf/core:^3

인프로세스 검증기에는 외부 도구 체인이 필요하지 않습니다. 권위 있는 게이트 단계에는 PATH에 있는 외부 검증기가 필요합니다. 예제는 veraPDF를 가리킵니다. Pro 또는 Enterprise 패키지는 필요하지 않습니다.

NextPDF는 \NextPDF\Compliance\Validator 아래에 인프로세스 검증기를 제공합니다. 이 검증기들은 외부 프로세스를 실행하지 않고 특정 규범적 불변식을 검증합니다:

  • PdfRValidator — ISO 23504-1(PDF/R-1) §5/§6 바이트 스트림 점검: 파일 헤더 허용 목록, generation-0 객체, §6.5.7 페이지 콘텐츠 연산자 허용 목록(q/Q/cm/Do만), 그리고 §6.4.3 Info 딕셔너리 키 허용 목록을 점검합니다. 평평한 PdfRValidationFinding[]를 반환하며, 빈 목록은 게이트에 포함된 모든 §6 점검을 통과했음을 의미합니다.
  • ArlingtonValidator — PDF Association의 기계 판독 가능한 Arlington 문법을 **보고 전용(report-only)**으로 실행합니다: 빌드 게이트로 사용하지 않으며, 모든 발견 항목에 고정된 문법 커밋 SHA를 기록해 감사 데이터 소비자가 알려진 업스트림 스냅숏과 연결할 수 있게 합니다.

이 점검들은 의도적으로 범위가 한정되어 있습니다. 이들은 방출 계약과 사양 사이의 드리프트를 잡아내지만, PDF/A-4나 PDF/UA-2 같은 프로파일의 ISO 적합성을 확립하지는 않습니다. 그 판단은 독립 검증기의 몫이며, 그 판정이 곧 빌드 게이트가 됩니다(ISO 19005-4 §6.7.3은 PDF/A에 대해 이를 명시합니다). 이 레시피는 경계를 명확히 유지합니다: 사전 점검을 인프로세스로 실행한 다음, 결정을 내리는 외부 오라클 명령을 출력하고 실행합니다.

아래 다이어그램은 2단계 게이트를 보여줍니다. 이 흐름을 지배하는 규칙은 하나입니다: 외부 오라클의 판정만 적합성으로 보고될 수 있습니다.

Findings

Clean

Pass

Fail

Produced PDF bytes

In-process pre-check

PdfRValidator / Arlington

Structural drift?

Fail fast — cheap reject

NOT a conformance verdict

Necessary, not sufficient

never report as conformance

Independent external validator

the authoritative oracle

Oracle verdict

May report file conforming

Not conforming — do not ship

Diagram

API 표면은 PHPDoc에서 생성됩니다. 주요 진입점은 다음과 같습니다:

  • \NextPDF\Compliance\Validator\PdfRValidator::validate(string $pdfBytes): list<PdfRValidationFinding>
  • \NextPDF\Compliance\Validator\PdfRValidationFinding(readonly: clause, severity, message)
  • \NextPDF\Compliance\Validator\ArlingtonValidator::validateReportOnly(string $pdfPath): list<ArlingtonFinding>
  • \NextPDF\Core\Document::output(?string $filename, OutputDestination $dest): string(원시 바이트의 경우 OutputDestination::String)
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Compliance\Validator\PdfRValidator;
use NextPDF\Contracts\OutputDestination;
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->addPage();
$doc->setFont('helvetica', '', 12);
$doc->cell(0, 10, 'Document under conformance review.', newLine: true);
$bytes = $doc->output(dest: OutputDestination::String);
$findings = (new PdfRValidator())->validate($bytes);
// A finding list is a structural fact, not a conformance verdict.
echo $findings === []
? "No in-process PDF/R-1 findings (necessary, not sufficient).\n"
: count($findings) . " in-process finding(s); not a conformance verdict.\n";

프로덕션 호출자는 인프로세스 검증기를 명백한 구조 드리프트에서 빠르게 실패하는 저렴한 게이트로 취급한 다음, 권위 있는 적합성 판정을 위해 외부 오라클을 실행합니다. 외부 오라클의 판정만 적합성으로 보고될 수 있습니다.

examples/33-validate-conformance.php (gate core)
$bytes = $doc->output(dest: OutputDestination::String);
$doc->save($out);
// 1. In-process pre-check — necessary, not sufficient.
$findings = (new PdfRValidator())->validate($bytes);
foreach ($findings as $finding) {
fwrite(STDERR, sprintf("[%s] §%s — %s\n",
$finding->severity, $finding->clause, $finding->message));
}
// 2. The authoritative gate — the external validator decides.
$exitCode = 0;
$report = [];
exec('verapdf --flavour 4 ' . escapeshellarg($out), $report, $exitCode);
if ($exitCode !== 0) {
fwrite(STDERR, "veraPDF FAILED — not reported conforming\n");
fwrite(STDERR, implode("\n", $report) . "\n");
exit(1);
}
echo "veraPDF PASS — the validator reports the file conforming\n";

예제는 php examples/33-validate-conformance.php로 실행하세요. 예제는 일반 PDF를 빌드한 다음 인프로세스 발견 항목을 출력합니다. 일반 PDF는 PDF/R-1 발견 항목을 생성할 것으로 예상되며, 그 결과가 바로 학습 포인트입니다. 그런 다음 예제는 권위 있는 외부 오라클 명령을 출력합니다.

  • 필요조건이지 충분조건은 아닙니다.PdfRValidator 발견 목록은 게이트에 포함된 §6 점검을 통과했다는 것 이상을 의미하지 않습니다. 이는 PDF/A-4 또는 PDF/UA-2 적합성 주장이 아닙니다. 인프로세스 결과만으로는 절대 적합성을 보고하지 마세요.
  • 일반 PDF는 설계상 PDF/R-1을 통과하지 못합니다. PDF/R-1은 이미지 전용 래스터 프로파일입니다. 일반 텍스트 PDF는 정당하게 §6.5.7 및 §6.4.3 발견 항목을 생성합니다. 예제는 인프로세스 출력이 판정이 아니라 구조적 사실임을 보여주기 위해 의도적으로 이를 시연합니다.
  • Arlington은 보고 전용입니다. ArlingtonValidator::validateReportOnly()는 절대 예외를 던지지 않으며 게이트하지도 않습니다. 문법 전용 모드에서는 고정된 문법 SHA가 로드되었음을 증명하는 info 발견 항목 하나를 방출하며, 문법이 구체화되지 않은 경우 빈 목록을 반환합니다. 이를 기반으로 pass/fail 게이트를 만들지 마세요 — 이는 교차 점검 산출물입니다.
  • 바이트 대 파일. PdfRValidator::validate()는 원시 바이트 문자열(OutputDestination::String)을 받지만, 외부 오라클은 파일 경로가 필요합니다. 오라클 단계를 위해 save()로 영구 저장하세요.
  • 빈 입력. PdfRValidator::validate()에 비어 있거나 헤더가 없는 문자열을 전달하면 예외를 던지는 대신 §6.2.2 오류 발견 항목을 반환합니다. 발견 목록을 확인하세요. 예외가 발생한다고 가정하지 마세요.

인프로세스 검증기는 PDF에 대한 단일 패스 정규식 및 바이트 스캔입니다. 일반적인 문서에서는 빠르고 메모리 할당이 가벼우며, 2000ms / 128MB 예산 안에 머무릅니다. 외부 오라클이 있는 경우 전체 소요 시간의 대부분을 차지하지만, 프로세스 외부에서 실행됩니다. 의미론적 재현성 프로파일이 적용됩니다. 예제의 가치는 관찰 가능한 검증 동작에 있으며, 하니스는 구조적 AST와 메타데이터 비교를 통해 그 동작을 확인합니다.

검증기는 문서 바이트를 프로세스 안에서 읽으며, 어떤 것도 프로세스 밖으로 내보내지 않습니다. 그러나 외부 오라클은 파일을 받습니다. 호스팅된 검증기를 실행하면 문서 콘텐츠가 사용자 환경의 경계를 벗어납니다. 민감한 콘텐츠는 로컬 검증기 바이너리를 우선 사용하거나, 검증하기 전에 편집(redact)하세요.

안전한 텔레메트리 및 로그 정제

섹션 제목: “안전한 텔레메트리 및 로그 정제”

발견 항목은 객체 경로와 연산자 조각을 인용할 수 있습니다. 예제는 발견 항목을 STDERR에, 고정된 진행 라인을 STDOUT에 기록합니다. 민감한 문서의 경우 발견 항목 로그를 공유 싱크로 보내지 마세요. 원시 PDF 바이트는 절대 로깅하지 마세요.

깨끗한 인프로세스 결과는 무결성 또는 진위 신호가 아닙니다. 악의적인 생산자는 범위가 한정된 인프로세스 점검은 통과하지만 전체 검증기는 통과하지 못하는 파일, 또는 형식은 올바르지만 오해를 유발하는 파일을 제작할 수 있습니다. 인프로세스 통과를 빠른 필터로 취급하되, 절대 신뢰로 취급하지 마세요.

이 레시피는 어떠한 암호화 연산도 수행하지 않습니다. FIPS 모드는 그 동작을 변경하지 않습니다. 서명, 암호화 또는 신뢰 자료에 대한 다이제스트가 발생하지 않습니다.

문장사양조항reference_id(참조 ID)
PDF/R-1 페이지 콘텐츠는 q/Q/cm/Do 연산자 허용 목록만 사용합니다.ISO 23504-1§6.5.7
PDF/R-1 페이지는 이미지 전용 래스터 콘텐츠입니다.ISO 23504-1§6.5.5
PDF/R-1은 문서 정보 딕셔너리 키를 제약합니다.ISO 23504-1§6.4.4
Arlington 문법은 기계 판독 가능한 객체 모델 교차 점검입니다.Arlington PDF Model 사양grammar(문법)
적합성은 생산자가 아니라 검증기가 결정합니다.ISO 19005-4§6.7.3

NextPDF의 인프로세스 검증기는 특정 규범적 불변식을 검증합니다. 지원은 적합성이 아니며, 검증은 인증이 아닙니다. 깨끗한 인프로세스 결과는 ISO 적합성을 확립하지 않습니다. 독립 검증기(예: veraPDF)가 그 판단을 내립니다. 그 판정을 빌드 게이트로 삼으세요.