コンテンツにスキップ

適合性の検証: プロセス内事前チェックと外部オラクル

このレシピでは、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 のバイトストリームチェック。ファイルヘッダーの許可リスト、生成番号 0 のオブジェクト、§6.5.7 のページコンテンツ演算子の許可リスト (q/Q/cm/Do のみ)、および §6.4.3 の Info 辞書キーの許可リストを対象とします。これはフラットな PdfRValidationFinding[] を返します。空のリストは、ゲート対象のすべての §6 チェックに合格したことを意味します。
  • ArlingtonValidator — PDF Association の機械可読な Arlington 文法を レポート専用 で実行します。ビルドのゲートには決してせず、すべての検出結果に固定された文法コミット SHA を記録します。そのため、監査の利用者は既知の上流スナップショットと照合できます。

これらのチェックは、対象範囲が意図的に限定されています。出力契約と仕様とのずれは検出しますが、PDF/A-4 や PDF/UA-2 などのプロファイルに対する ISO 適合性を確立するものでは ありません。その判断は、判定がビルドゲートとなる独立したバリデーターに委ねられます(ISO 19005-4 §6.7.3 は、これを PDF/A について明示しています)。このレシピは境界を明確に保ちます。事前チェックをプロセス内で実行し、その後、判定を担う外部オラクルのコマンドを出力して実行します。

次の図は、2 段階のゲートを示しています。適用する規則は 1 つだけです。適合性として報告してよいのは、外部オラクルの判定だけです。

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 の検出結果を 1 件出力します。文法が実体化されていない場合は、空のリストを返します。これを基にして pass/fail のゲートを構築してはなりません。これはクロスチェック用の成果物です。
  • バイト列とファイルの違い。 PdfRValidator::validate() は生のバイト文字列 (OutputDestination::String) を受け取ります。外部オラクルはファイルパスを必要とします。オラクルのステップでは、save() で永続化してください。
  • 空の入力。 空文字列やヘッダーのない文字列を PdfRValidator::validate() に渡すと、例外をスローするのではなく §6.2.2 のエラー検出結果を返します。検出結果リストを確認してください。例外が発生することを前提にしないでください。

プロセス内バリデーターは、PDF に対して単一パスの正規表現処理とバイトスキャンを行います。一般的なドキュメントでは高速で、メモリ確保も少なく、2000 ms / 128 MB の予算内に収まります。外部オラクルを使う場合、それが実時間の大半を占めますが、プロセス外で実行されます。セマンティック再現性プロファイルが適用されます。この例の価値は、観測可能な検証の挙動にあり、ハーネスはその挙動を、構造的 AST とメタデータの比較によって確認します。

バリデーターはドキュメントのバイト列をプロセス内で読み取り、プロセスの外に出るものは何もありません。ただし、外部オラクルはファイルを受け取ります。ホスト型のバリデーターを実行する場合、ドキュメントの内容は境界の外に出ます。機密性の高い内容については、ローカルのバリデーターバイナリを優先するか、検証前に秘匿処理を施してください。

検出結果には、オブジェクトパスや演算子の断片が引用されることがあります。この例は、検出結果を STDERR に、固定形式の進行状況行を STDOUT に書き込みます。機密性の高いドキュメントについては、検出結果のログを共有シンクに出力しないようにしてください。生の PDF バイト列を決してログに記録しないでください。

プロセス内の結果に問題がないことは、完全性や真正性のシグナルではありません。悪意のある作成者は、範囲を限定したプロセス内チェックには合格するが完全なバリデーターには不合格となるファイル、あるいは整形式ではあるが誤解を招くファイルを作成できます。プロセス内チェックの合格は高速なフィルターとして扱い、決して信頼の根拠としないでください。

このレシピは暗号操作を一切実行しません。FIPS モードはその動作を変えません。信頼情報に対する署名、暗号化、ダイジェストは一切行われません。

記述仕様箇条reference_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 Modelgrammar
適合性を判断する主体は作成者ではなくバリデーターISO 19005-4§6.7.3

NextPDF のプロセス内バリデーターは、特定の規範的な不変条件を検証します。サポートは適合性ではなく、検証は認証ではありません。 プロセス内の結果に問題がないことは、ISO 適合性を確立するものではありません。その判断を行うのは、独立したバリデーター(例: veraPDF)です。その判定をビルドゲートにしてください。