Enterprise редакция
Validation — углублённый справочник
Модуль Validation применяет готовые структурные политики соответствия только для чтения к необработанным байтам PDF. Compliance::assess() применяет ровно одну CompliancePolicy и возвращает ComplianceReport с замечаниями, разделёнными по серьёзности, и обязательным юридическим дисклеймером. Политики поставляются для PDF/A-4 (плюс варианты e и f), базовой структуры PAdES, структурного профиля eIDAS, состояния LTV/DSS, ZUGFeRD / Factur-X, FDA 21 CFR Part 11 и WORM-архивирования по SEC Rule 17a-4. Каждая политика — чистая функция: на входе байты, на выходе замечания. Validation никогда не изменяет документ и никогда не выполняет криптографическую проверку.
Доступность и лицензирование
Заголовок раздела «Доступность и лицензирование»Эта возможность поставляется в NextPDF Enterprise (nextpdf/enterprise) и активируется лицензионным конвертом уровня Enterprise. Развёртывание без этого права доступа не загружает классы этой возможности. Сравните редакции и получите лицензию.
Поверхность Validation/Evidence лицензируется возможностью enterprise.compliance.evidence. Отказ в праве доступа отказывает в функции, а не понижает уровень молча.
| Редакция | Поверхность Validation |
|---|---|
| Core | Внутрипроцессные валидаторы байтового потока и перекрёстная проверка грамматики; результат без замечаний — это проверенный результат, а не сертификат. |
| Pro | Внутрипроцессная валидация EN 16931 / Factur-X / ZUGFeRD на уровне электронного счёта; без готовых политик PDF/A-4, PAdES, LTV, FDA или SEC. |
| Enterprise | Готовые структурные политики для PDF/A-4, PAdES, LTV, ZUGFeRD, FDA Part 11 и SEC 17a-4 с единым отчётом (этот модуль). |
Внешний sidecar-шлюз Enterprise Compliance — это отдельный, самостоятельный модуль.
Поверхность публичного API
Заголовок раздела «Поверхность публичного API»composer require nextpdf/enterprise:^3| Символ | Параметры | Поведение по умолчанию | Возвращает | Бросает или завершается с | Примечания |
|---|---|---|---|---|---|
Compliance::__construct | ?ClockInterface $clock = null | Системные часы, когда часы не внедрены | — | — | Экземплярная форма, удобная для DI; часы проставляют validatedAt |
Compliance::run | string $pdfData, CompliancePolicy $policy, array $context = [] | Применяет ровно одну политику и измеряет реальную длительность | ComplianceReport | Пробрасывает исключения пользовательских политик; встроенные политики собирают замечания вместо выбрасывания | Экземплярный метод |
Compliance::assess (статический) | string $pdfData, CompliancePolicy $policy, array $context = [] | Создаёт экземпляр по умолчанию и делегирует в run() | ComplianceReport | То же, что и run() | Быстрый путь без конфигурации |
Policies::pdfA4 / ::pdfA4e / ::pdfA4f (статический) | — | Структурная политика PDF/A-4 согласно ISO 19005-4:2020 | CompliancePolicy | — | e разрешает 3D/rich-media аннотации; f добавляет проверки отношений встроенных файлов |
Policies::padesBaseline (статический) | — | Структурные проверки PAdES B-B | CompliancePolicy | — | Только структура; без криптографической проверки |
Policies::eidasQualified (статический) | — | Структурные проверки PAdES в рамках профиля с меткой eIDAS | CompliancePolicy | — | Квалификация зависит от TSP и квалифицированного сертификата |
Policies::ltvHealth (статический) | — | Проверка структурного состояния DSS | CompliancePolicy | — | Наличие DSS разрешается из активного графа объектов, с отказом в закрытую сторону |
Policies::zugferd (статический) | string $profile = 'BASIC' | Нормализует псевдоним профиля и строит валидатор ZUGFeRD | CompliancePolicy | \ValueError (неизвестный профиль) | Профили: MINIMUM, BASIC, BASIC_WL, EN16931, EXTENDED |
Policies::fdaPart11 (статический) | — | Структурная политика FDA 21 CFR Part 11 | CompliancePolicy | — | Семь структурных проверок, включая целостность хеш-цепочки журнала аудита |
Policies::sec17a4 / ::sec17a4Compatible / ::sec17a4Structural / ::sec17a4PreSign (статический) | — | Политика SEC 17a-4 WORM с указанной строгостью | CompliancePolicy | — | Строгость сопоставляется с WormComplianceLevel |
CompliancePolicy (интерфейс) | — | Контракт стратегии для одного стандарта | — | — | getName(), getIdentifier(), getStandardReference(), validate(); реализуемый заказчиком |
ComplianceReport | Readonly-объект-значение | Замечания разделяются по серьёзности при конструировании | — | — | passes(), fails(), totalFindings(), getDisclaimer(); публичные findings, errors, warnings, infos, policyName, policyId, standard, validatedAt, durationMs |
ComplianceFinding | Severity $severity, string $ruleId, string $message, string $clause = '', string $suggestion = '' | Результат одного правила со ссылкой на пункт и подсказкой по исправлению | — | — | Статические error() / warning() / info(); isError() |
Severity (перечисление) | 3 варианта на основе строк | Error, Warning, Info | — | — | Только Error делает отчёт неуспешным |
WormComplianceLevel (перечисление) | 4 варианта на основе строк | Full, Compatible, Structural, PreSign | — | — | requiresSignature(), requiresDocMdp(), requiresLtv(), maxDocMdpLevel() |
PdfAPolicy, PadesValidator, LtvHealthCheck, ZugferdValidator, Sec17a4WormPolicy, Fda\FdaPart11Policy | Конструкторы для каждого класса | Реализуют CompliancePolicy, каждый для одного стандарта | list<ComplianceFinding> из validate() | — | Получаются через Policies; Sec17a4WormPolicy::getLevel() предоставляет настроенную строгость |
Fda\FdaSigningIntent (перечисление) | 6 вариантов на основе строк | Authoring, Review, Approval, Certification, Verification, Rejection | — | — | toPdfReasonString() выдаёт каноническую строку /Reason |
Fda\FdaAuditEvent::__construct | DateTimeImmutable $timestamp, string $actor, FdaSigningIntent $action, string $documentHash, string $certificateSerial, string $previousEventHash = '' | Вычисляет хеш цепочки SHA-256 при конструировании | — | InvalidArgumentException (метка времени не UTC) | Публичный eventHash; toXmpRdf() сериализует один элемент списка XMP |
Fda\FdaAuditTrail::addEvent | FdaAuditEvent $event | Добавляет событие, когда его звено цепочки совпадает с хвостом цепочки | self | InvalidArgumentException (хеш-цепочка разорвана) | Также createEvent(), verifyChain(), getLastEventHash(), getEvents(), embedInMetadata() |
Fda\FdaSignatureEnforcer::configureSeedValue | FdaSigningIntent $intent, string $tsaUrl | Строит конфигурацию seed-value подписи с ограничениями FDA | SeedValueConfig | — | Требует набор причин FDA, метку времени и дайджесты SHA-256 или сильнее |
Fda\FdaSignatureEnforcer::applyTo | SequentialSigner $signer, SigningStrategy $strategy, string $signerName, FdaSigningIntent $intent, string $tsaUrl, string $fieldName = '', ?string $reason = null | Добавляет подписанта с ограничениями FDA к SequentialSigner из Pro | SequentialSigner | — | Сериализует ограничения в создаваемое поле подписи |
namespace NextPDF\Enterprise\Validation;
final readonly class Compliance{ public function __construct(?ClockInterface $clock = null);
/** @param array<string, mixed> $context */ public function run(string $pdfData, CompliancePolicy $policy, array $context = []): ComplianceReport;
/** @param array<string, mixed> $context */ public static function assess(string $pdfData, CompliancePolicy $policy, array $context = []): ComplianceReport;}final class Policies{ public static function pdfA4(): CompliancePolicy; // also pdfA4e(), pdfA4f() public static function padesBaseline(): CompliancePolicy; public static function eidasQualified(): CompliancePolicy; public static function ltvHealth(): CompliancePolicy; public static function zugferd(string $profile = 'BASIC'): CompliancePolicy; public static function fdaPart11(): CompliancePolicy; public static function sec17a4(): CompliancePolicy; // also sec17a4Compatible(), sec17a4Structural(), sec17a4PreSign()}interface CompliancePolicy{ public function getName(): string;
public function getIdentifier(): string;
public function getStandardReference(): string;
/** * @param array<string, mixed> $context * @return list<ComplianceFinding> */ public function validate(string $pdfData, array $context = []): array;}
final readonly class ComplianceReport{ public const string LEGAL_DISCLAIMER;
public function passes(): bool;
public function fails(): bool;
public function totalFindings(): int;
public function getDisclaimer(): string;}Контракт поведения
Заголовок раздела «Контракт поведения»Compliance::assess() (статический) и Compliance::run() (экземплярный, с внедряемым Psr\Clock\ClockInterface) применяют ровно одну политику и возвращают ComplianceReport. Внешне наблюдаемые правила:
- Чисто только для чтения. Каждый
CompliancePolicy::validate()— чистая функция: на входе байты, на выходе замечания. Политика никогда не изменяет байты PDF. Этот архитектурный инвариант отделяет валидацию от автоматического исправления и от модуля Evidence. - Гейт серьёзности.
ComplianceReport::passes()истинно только тогда, когдаerrors === []. Предупреждения и информационные сообщения никогда не делают отчёт неуспешным.fails()— дополнение. - Обязательный дисклеймер.
ComplianceReport::getDisclaimer()возвращает константный текст юридического дисклеймера. Отображение его в выводе, предназначенном для пользователя, требуется контрактом. - Происхождение отчёта. Отчёт несёт имя политики, идентификатор и ссылку на стандарт из политики, метку времени валидации из внедрённых или системных часов и измеренную длительность в миллисекундах.
- Собирать, а не прерывать. Встроенные политики выполняют все применимые проверки и собирают каждое замечание, а не останавливаются на первой ошибке.
- Только достижимый из каталога DSS.
LtvHealthCheckразрешает наличие DSS из активного графа объектов: активный трейлер, затем каталог/Root, затем/DSSи его подключи. Байты-маркеры, размещённые в комментариях, строках, объектах-сиротах или замещённых ревизиях, не учитываются. Неразбираемый вход трактуется как отсутствие DSS, поэтому проверка отказывает в закрытую сторону. Проверка структурная; она не выполняет криптографическую проверку встроенных данных OCSP/CRL. - Структурные проверки подписи.
Policies::padesBaseline()иPolicies::eidasQualified()проверяют структуру PAdES только на уровне PDF. Квалификация в рамках eIDAS зависит от TSP и квалифицированного сертификата, которые находятся за пределами этого модуля. - Политики регулируемых отраслей структурные.
FdaPart11Policyпроверяет наличие подписи, намерение/Reason, время подписания/M, идентичность/Name, отсутствие JavaScript, пространство имён журнала аудита FDA и целостность хеш-цепочки.Sec17a4WormPolicyпроверяет до 13 правил WORM;WormComplianceLevelвыбирает строгость.Fullтребует DocMDP уровня 1,Compatibleдопускает уровень 2, аStructural/PreSignпропускают правила подписи, DocMDP и DSS. Ни одна из политик не устанавливает юридического соответствия. - Контекст ZUGFeRD.
Policies::zugferd()всегда проверяет требования уровня PDF. XML счёта он валидирует только когда вызывающая сторона передаёт['xml' => $xmlData]в$context; иначе он выдаёт информационное замечаниеzugferd-xml-skipped. - Защищённый от подделки журнал аудита.
FdaAuditTrail— это хеш-цепочка SHA-256 с добавлением только в конец.addEvent()отклоняет разорванное звено,verifyChain()заново выводит каждый хеш, аembedInMetadata()записывает журнал в XMP подhttp://ns.nextpdf.dev/fda/1.0/со схемой расширения PDF/A.
Граничные случаи и режимы отказа
Заголовок раздела «Граничные случаи и режимы отказа»- Не-PDF или пустой вход даёт замечания об ошибках, а не исключение во встроенных политиках. Всегда проверяйте
passes()и отображайте дисклеймер. Policies::zugferd()нормализует псевдонимы профилей (BASIC_WL,EN16931,EN_16931). Неизвестный профиль вызывает\ValueErrorна этапе фабрики, до запуска какой-либо валидации.- DSS с CRL, но без ответов OCSP удовлетворяет проверке материала об отзыве; замечание отмечает допустимую альтернативу. Отсутствие обоих является ошибкой.
- Отсутствующий словарь
/VRIили массив/Certsпорождает предупреждения, а не ошибки; отчёт всё равно может пройти. FdaAuditEventотклоняет любую метку времени не в UTC сInvalidArgumentExceptionпри конструировании.FdaAuditTrail::verifyChain()возвращает false при любом подделанном или переупорядоченном событии; он никогда не выбрасывает исключение.- Пользовательские реализации
CompliancePolicyмогут выбрасывать исключения изvalidate();Compliance::run()их не перехватывает, поэтому такие исключения пробрасываются вызывающей стороне.
Поведение в режиме FIPS
Заголовок раздела «Поведение в режиме FIPS»Этот модуль не выполняет подписания, криптографической проверки и хранения ключей. Политика алгоритмов в режиме FIPS управляется модулями Security и Signature. Значения seed-value FdaSignatureEnforcer ограничивают поля подписи, привязанные к FDA, методами дайджеста SHA-256, SHA-384 или SHA-512.
Соответствие
Заголовок раздела «Соответствие»Эти политики проверяют структурные атрибуты относительно именованных стандартов. Заключение о соответствии для профилей ISO/ETSI остаётся свойством итогового файла вместе с внешним валидатором.
| Поведение | Ссылка |
|---|---|
| Соответствие определяется относительно стандарта, а не производителя | ISO 19005-4:2020 §5.2 |
| Словарь цифровой подписи / DSS для долгосрочной проверки | ISO 32000-2:2020 §12.8 |
DSS — это словарь, содержащийся под ключом DSS каталога документа | ISO 32000-2:2020 §12.8.4.3 |
| Базовые уровни подписи PAdES | ETSI EN 319 142-1 §5.4.3 |
| Семантическая модель профиля EN 16931 (вспомогательная ссылка) | Factur-X 1.08 (EN 16931) |
Политики FDA 21 CFR Part 11 и SEC 17a-4 проверяют только структурные атрибуты; эти регламенты находятся вне корпуса верификации и не несут подтверждённого заявления о соответствии. Строки пунктов внутри замечаний FDA (например, §11.50, §11.10(e)) — это ссылки на правила, выдаваемые продуктом. Строка EN 16931 — вспомогательная ссылка ниже порога извлечения; это не жёсткое заявление о соответствии. Поддержка стандарта не является соответствием ему, а соответствие не является сертификацией — NextPDF не имеет сертификации и не предоставляет её. Этот справочник не является юридическим заключением; по вопросам юридической достаточности обращайтесь к своей команде по соответствию.
Заметки по разработке
Заголовок раздела «Заметки по разработке»- Validation выполняется внутри процесса и локально, без сетевого ввода-вывода. Политика не может изменить входные данные.
- Относитесь к байтам PDF из недоверенных источников как к враждебным. Встроенные политики тотальны над произвольными байтами и отказывают в закрытую сторону там, где структуру нельзя разрешить.
- Отображайте
ComplianceReport::getDisclaimer()при каждом отображении отчёта, предназначенном для пользователя. - Отчёты и замечания могут содержать персональные данные из подписанных документов и метаданных журнала аудита (имена подписантов, серийные номера сертификатов). Оператор владеет мерами контроля хранения и минимизации.
- Пользовательские политики реализуют
CompliancePolicy; сохраняйтеgetIdentifier()уникальным среди всех политик для сериализации и кеширования. - Этот модуль касается криптографической функциональности; относитесь к нему как к чувствительному к безопасности в собственном ревью.
- Детали внутреннего механизма остаются во внутренней документации исходного репозитория и выходят за рамки этого руководства.
Граница публикации
Заголовок раздела «Граница публикации»Эта страница документирует только внешне наблюдаемое поведение и поддерживаемую поверхность публичного API. Внутренние пути пространств имён, вспомогательные классы, таблицы механизмов, имена файлов runbook и префиксы тикетов выходят за рамки.