Aller au contenu
getnextpdf.com

Enterprise édition

Conformité — Référence détaillée

Le module Compliance achemine un PDF finalisé vers un sidecar de validation externe et renvoie un unique résultat normalisé. ComplianceGateway résout le sidecar responsable à partir d’un ComplianceProfile, applique une politique de disponibilité fail-closed et encapsule chaque verdict d’outil dans un ExternalValidationResult. Des ponts sont fournis pour veraPDF (PDF/A, PDF/UA, PDF 2.0 Arlington), EU DSS (niveaux PAdES), le sidecar combiné Mustang/KoSIT (ZUGFeRD, Factur-X, EN 16931) et un démon KoSIT autonome. Le module fournit également le tamponnage d’aptitude AiReadyCertifier et un exécuteur pour la suite de tests officielle KoSIT XRechnung.

Cette fonctionnalité est fournie dans NextPDF Enterprise (nextpdf/enterprise) et s’active avec une enveloppe de licence de niveau Enterprise. Un déploiement dépourvu de cette autorisation ne charge pas les classes de la fonctionnalité. Compare les éditions et obtiens une licence.

La surface Compliance/Evidence est concédée sous licence par la capacité enterprise.compliance.evidence. Une autorisation manquante ou expirée refuse la fonctionnalité ; elle ne dégrade pas silencieusement le comportement.

NiveauSurface de conformité
CoreVérifications de flux d’octets et de grammaire en interne ; aucune délégation à un sidecar externe.
ProValidation EN 16931 / Factur-X / ZUGFeRD en interne ; aucun sidecar externe.
EnterprisePasserelle de validateurs externes (ce module) avec un résultat unifié et une politique fail-closed.

Le validateur de factures électroniques en interne de Pro et le sidecar ZUGFeRD externe d’Enterprise sont des surfaces distinctes. La passerelle de validateurs externes n’est fournie que dans le paquet nextpdf/enterprise.

Fenêtre de terminal
composer require nextpdf/enterprise:^3
SymboleParamètresComportement par défautRenvoieLève ou échoue avecNotes
ComplianceGateway::__constructlist<ExternalValidator> $validators, LoggerInterface $logger, bool $optional = falseIndexe les validateurs par nom d’outilLe mode optionnel réduit la vérification de disponibilité à un simple avertissement
ComplianceGateway::validatestring $pdfContent, ComplianceProfile $profile, array $options = []Résout le validateur via ComplianceProfile::toolName(), vérifie la disponibilité, délègue?ExternalValidationResultComplianceSidecarUnavailableException ; InvalidArgumentException (aucun validateur enregistré pour l’outil)Ne renvoie null qu’en mode optionnel lorsque le sidecar est indisponible
ComplianceGateway::validateAllProfilesstring $pdfContent, string $toolNameValide chaque profil associé à l’outillist<ExternalValidationResult>Identique à validate()Ignore les résultats null (mode optionnel)
ComplianceGateway::healthCheckSonde le point de terminaison de santé de chaque sidecar enregistréarray<string, bool>Signale l’accessibilité ; ne valide aucun document
ComplianceGateway::buildComplianceMatrix (statique)list<ExternalValidationResult> $results, string $commitShaRéduit les résultats en une matrice versionnée par schémaarray<string, mixed>Version de schéma 1.0 ; enregistre la sortie de l’outil, n’affirme rien
ComplianceProfile (enum)15 cas adossés à des chaînesAssocie chaque profil à un libellé de norme et à un outilstandardReference(): string, toolName(): string
ExternalValidator (interface)Contrat de pont sidecar sur PSR-18validate() lève ComplianceSidecarUnavailableException en cas d’échec de transportgetToolName(), isAvailable(), validate()
VeraPdfValidator::validateSignature de l’interfacePOST multipart vers le sidecar REST veraPDF ; analyse du rapport JSONExternalValidationResultComplianceSidecarUnavailableException ; InvalidArgumentException (profil non pris en charge)PDF/A, PDF/UA, Arlington ; analyse uniquement du JSON, jamais du XML
DssValidator::validateSignature de l’interfacePOST JSON en Base64 vers le sidecar REST EU DSSExternalValidationResultComplianceSidecarUnavailableException ; InvalidArgumentException (profil non pris en charge)PAdES B-B à B-LTA ; le constructeur rejette les délais inférieurs à une seconde
ZugferdExternalValidator::validateSignature de l’interfacePOST multipart vers le sidecar combiné Mustang/KoSITExternalValidationResultComplianceSidecarUnavailableException (également sur un disjoncteur ouvert) ; InvalidArgumentException (profil non pris en charge)ZUGFeRD 2.4, Factur-X 1.08, EN 16931 ; disjoncteur injecté facultatif
KoSitValidator::validateSignature de l’interfacePOST XML brut vers un démon KoSIT autonomeExternalValidationResultComplianceSidecarUnavailableException ; InvalidArgumentException (profil non pris en charge)EN 16931 uniquement ; analyse le rapport SVRL Schematron en mode fail-closed
ExternalValidationResultObjet-valeur en lecture seuleVerdict d’outil normalisépasses(), fails(), nonConformanceCount(), toComplianceMatrix()
NonConformanceObjet-valeur en lecture seuleConstat unique avec identifiant de règle, clause, sévérité, emplacementtoArray()
ComplianceSidecarUnavailableExceptionstring $toolName, string $endpoint, int $code = 0, ?Throwable $previous = nullSignal d’indisponibilité de sidecar en mode fail-closedtoolName et endpoint publics en lecture seule
AiReadyCertifier::certifystring $pdfBytesÉvalue trois critères d’aptitude ; tamponne la provenance XMParray{0: AiReadyCertification, 1: string}InvalidArgumentException (le tamponnage requiert une table de références croisées classique)Le second élément est identique à l’entrée lorsque le niveau est not_certified
AiReadyCertificationObjet-valeur en lecture seuleÉvaluation d’aptitude avec niveau, nombre de critères, problèmes, empreinte sourceLibellé d’aptitude interne, pas une certification normative
XRechnungTestSuiteRunner::__constructstring $suitePath, ExternalValidator $validator, bool $useCuratedNegativeFallback = trueRésout le répertoire de la suite extraiteInvalidArgumentException (le répertoire n’existe pas)Cible la suite de tests officielle KoSIT XRechnung
XRechnungTestSuiteRunner::runbool $stopOnFirstFailure = falseValide chaque instance de la suite via le pontXRechnungTestSuiteResultXRechnungTestSuiteException (validateur indisponible ; aucun fichier XML)Également isAvailable(), getSuitePath(), discoverTestFiles()
XRechnungTestSuiteResultObjet-valeur en lecture seuleRésultat agrégé de la suiteallPassed(), totalCount(), getFailures(), getErrors(), toSummary()
XRechnungTestCaseResultObjet-valeur en lecture seuleRésultat par caspassed(), hasError(), getFilename()
XRechnungTestSuiteExceptionConstructeurs statiquesSignal d’échec d’exécution de la suiteselfvalidatorUnavailable(), noTestFilesFound(string $suitePath)
namespace NextPDF\Enterprise\Compliance;
final class ComplianceGateway
{
/** @param list<ExternalValidator> $validators */
public function __construct(
array $validators,
private readonly LoggerInterface $logger,
private readonly bool $optional = false,
);
/** @param array<string, mixed> $options */
public function validate(
string $pdfContent,
ComplianceProfile $profile,
array $options = [],
): ?ExternalValidationResult;
/** @return list<ExternalValidationResult> */
public function validateAllProfiles(string $pdfContent, string $toolName): array;
/** @return array<string, bool> */
public function healthCheck(): array;
/**
* @param list<ExternalValidationResult> $results
* @return array<string, mixed>
*/
public static function buildComplianceMatrix(array $results, string $commitSha): array;
}
interface ExternalValidator
{
public function getToolName(): string;
public function isAvailable(): bool;
/** @param array<string, mixed> $options */
public function validate(
string $pdfContent,
ComplianceProfile $profile,
array $options = [],
): ExternalValidationResult;
}
enum ComplianceProfile: string
{
case PdfA1b = 'pdfa-1b';
// PdfA2b, PdfA3b, PdfA4, PdfA4f, PdfUa1, PdfUa2, Pdf20Arlington,
// PadesBasic, PadesTimestamp, PadesLongTerm, PadesArchive,
// Zugferd24, FacturX108, En16931
public function standardReference(): string;
public function toolName(): string;
}
final class AiReadyCertifier
{
/** @return array{0: AiReadyCertification, 1: string} Tuple of [certification, stamped PDF bytes] */
public function certify(string $pdfBytes): array;
}

ComplianceGateway::validate() résout l’ExternalValidator enregistré dont le getToolName() correspond à ComplianceProfile::toolName(), vérifie isAvailable(), délègue et renvoie un ExternalValidationResult normalisé. Règles observables de l’extérieur :

  • Fail-closed par défaut. Lorsque le sidecar résolu est indisponible et que le mode optionnel est désactivé, l’appel lève ComplianceSidecarUnavailableException. Le document n’est pas vérifié ; il n’est jamais considéré comme réussi.
  • Mode optionnel. Construire la passerelle avec optional: true (les opérateurs le câblent depuis la variable d’environnement NEXTPDF_COMPLIANCE_OPTIONAL) réduit un sidecar indisponible à un avertissement journalisé et à un retour null. Les appelants doivent traiter null comme « non vérifié ». Le mode optionnel ne couvre que la sonde de disponibilité préalable ; un échec de transport pendant l’appel de validation lui-même lève ComplianceSidecarUnavailableException dans les deux modes.
  • Profil inconnu. Un profil sans validateur enregistré lève InvalidArgumentException ; il ne réussit jamais silencieusement.
  • Sémantique de réussite. ExternalValidationResult::passes() exige que conformant soit vrai et qu’il n’y ait aucune non-conformité. Chaque résultat porte le profil, le nom et la version de l’outil, le nombre d’assertions, les constats, le SHA-256 des octets validés, un horodatage UTC et la durée de l’appel.
  • La matrice est un enregistrement, pas une affirmation. buildComplianceMatrix() est un réducteur statique produisant une structure versionnée par schéma avec les versions des outils et un SHA de commit pour la traçabilité. Elle enregistre la sortie de l’outil ; elle n’affirme rien.
  • Flux de données. Le flux d’octets complet du PDF est transmis au sidecar configuré via un client PSR-18. Chaque validation est journalisée via PSR-3 avec le profil, l’outil, réussite/échec, le nombre d’assertions et la durée.

Routage profil-vers-outil, tel que renvoyé par ComplianceProfile::standardReference() et ::toolName() :

Cas de profilRéférence de normeOutil
pdfa-1b, pdfa-2b, pdfa-3b, pdfa-4, pdfa-4fISO 19005-1/-2/-3/-4 (niveau B ; niveau F pour 4f)veraPDF
pdfua-1, pdfua-2ISO 14289-1:2014, ISO 14289-2:2024veraPDF
pdf20-arlingtonISO 32000-2:2020 (modèle Arlington)veraPDF
pades-b-b, pades-b-t, pades-b-lt, pades-b-ltaETSI EN 319 142-1 B-B à B-LTAEU DSS
zugferd-2.4, factur-x-1.08, en-16931ZUGFeRD 2.4 / Factur-X 1.08 / EN 16931-1:2017Mustang/KoSIT

AiReadyCertifier::certify() évalue trois critères : présence d’une signature structurelle, santé LTV et absence de chiffrement. Trois critères réussis donnent le niveau certified ; un ou deux donnent partial ; zéro donne not_certified. Au niveau certified ou partial, il ajoute une mise à jour incrémentielle portant un flux de provenance XMP et une redéfinition du Catalog ; les octets d’origine ne sont jamais modifiés. Le niveau « certified » est un libellé d’aptitude interne à NextPDF, pas une certification normative.

VeraPdfValidator n’analyse que les réponses JSON du sidecar (pas de XML ; exempt de XXE par construction). KoSitValidator analyse le rapport SVRL XML du démon avec les déclarations DOCTYPE rejetées et l’accès réseau désactivé, et traite un rapport non analysable comme un échec de l’appel.

  • Un délai dépassé du sidecar ou une erreur de transport remonte sous la forme de ComplianceSidecarUnavailableException depuis le pont ; le comportement fail-closed par défaut s’applique.
  • Une réponse du sidecar autre que 200 produit un résultat en échec avec un constat propre à l’outil (par exemple VERAPDF-HTTP-ERROR) ; ce n’est jamais une réussite de conformité.
  • Un corps JSON ou XML mal formé du sidecar constitue un échec de validation de l’appel, pas une réussite de conformité.
  • Les résultats EU DSS sans signature échouent avec DSS-NO-SIGNATURES. Une indication autre que TOTAL_PASSED échoue avec DSS-SIG-INVALID. Un niveau de signature inférieur au socle attendu échoue avec DSS-LEVEL-MISMATCH.
  • DssValidator publie son budget de délai par requête sur chaque requête via l’en-tête X-NextPDF-Timeout-Seconds ; le client PSR-18 de l’intégrateur doit le respecter afin qu’un sidecar bloqué ne puisse pas bloquer indéfiniment le thread appelant.
  • ZugferdExternalValidator achemine facultativement les appels au sidecar via un disjoncteur injecté ; un disjoncteur ouvert se traduit par ComplianceSidecarUnavailableException (fail-fast, toujours fail-closed). Par défaut, le disjoncteur est inopérant.
  • KoSitValidator::isAvailable() accepte les codes HTTP 200 et 405 de la sonde de santé du démon ; le démon répond aux requêtes GET par 405 lorsqu’il est en bonne santé.
  • Le tamponnage AiReadyCertifier échoue en mode fail-closed avec InvalidArgumentException lorsque le document d’origine ne dispose pas d’une table de références croisées classique (par exemple, des flux de références croisées).
  • XRechnungTestSuiteRunner::run() refuse de s’exécuter lorsque le validateur est indisponible ou que la suite ne contient aucun fichier XML ; avec useCuratedNegativeFallback activé, il substitue un corpus négatif sélectionné lorsque la suite ne fournit aucune instance invalide.

Ce module n’effectue aucune signature ni aucune conservation de clés. La politique d’algorithmes en mode FIPS est régie par les modules Security et Signature. La conformité des signatures est déléguée à EU DSS, qui rend sa propre décision.

La passerelle délègue le verdict de conformité à un outil externe ; la conception reflète la limite propre aux normes selon laquelle la conformité est déterminée par rapport aux exigences, et non affirmée par un producteur.

ComportementRéférence
Obligation du processeur conforme ; conformité déterminée par rapport à la normeISO 19005-4:2020 §5.2
Exigences de fichier PDF/A-4 vs auto-affirmation du producteurISO 19005-4:2020 §6.6.4
La conformité PDF/UA-2 est une propriété du fichierISO 14289-2:2024 §6
Niveaux de signature de base PAdESETSI EN 319 142-1 §5.4.3

L’outil externe produit le verdict. NextPDF ne détient aucune certification et n’en accorde aucune ; la prise en charge d’un profil n’équivaut pas à sa conformité. Les résultats de validation sont des enregistrements techniques de vérification de structure fournis à titre de référence, pas des conseils juridiques ; consulte ton équipe conformité pour juger de la suffisance réglementaire.

  • L’opérateur héberge et exploite les sidecars, épingle leurs versions, restreint leur portée réseau, valide leur TLS et contrôle l’environnement qui active le mode optionnel. Les points de terminaison des sidecars constituent une frontière de confiance ; les contrôles de résidence et de rétention des documents, des résultats et des journaux relèvent de la responsabilité de l’opérateur.
  • La sortie de buildComplianceMatrix() est conçue pour la traçabilité CI : épingle le SHA de commit et archive la matrice à côté des artefacts de build.
  • L’exécuteur XRechnung attend la suite de tests officielle extraite dans un répertoire local ; le message de son constructeur nomme la source de téléchargement publique.
  • Les détails des mécanismes internes restent dans la documentation interne du dépôt source et sortent du périmètre de ce manuel.

Cette page documente uniquement le comportement observable de l’extérieur et la surface d’API publique prise en charge. Les chemins de namespace internes, les classes utilitaires, les tables de mécanismes, les noms de fichiers de runbook et les préfixes de tickets sortent du périmètre.