Enterprise édition
Evidence — Référence approfondie
En un coup d’œil
Section intitulée « En un coup d’œil »Cette page est la référence approfondie du module NextPDF\Enterprise\Evidence. Le module scelle les constats de validation dans un EvidencePackage immuable, l’exporte en JSON déterministe avec un condensé SHA-256 stable, le persiste via un contrat de store enfichable et suit les régressions entre les exécutions avec ContinuousMonitor. Le module consomme les constats produits par les surfaces Validation et Compliance ; il n’effectue lui-même aucune vérification de conformité. Pour des conseils de workflow, lis d’abord la page de capacité Evidence.
Disponibilité et licence
Section intitulée « Disponibilité et licence »Cette capacité est livrée dans NextPDF Enterprise (nextpdf/enterprise) et s’active avec une enveloppe de licence de niveau Enterprise. Un déploiement dépourvu de ce droit ne charge pas les classes de la capacité. Compare les éditions et obtiens une licence.
La surface est licenciée par la capacité enterprise.compliance.evidence ; un droit refusé refuse la fonctionnalité. Core et Pro produisent des constats et des rapports ; sceller des constats dans un package immuable, déterministe et éventuellement horodaté, avec suivi des régressions, n’a aucun équivalent de niveau Core ou Pro.
Surface d’API publique
Section intitulée « Surface d’API publique »composer require nextpdf/enterprise:^3| Symbole | Paramètres | Comportement par défaut | Retourne | Lève ou échoue avec | Notes |
|---|---|---|---|---|---|
EvidencePortal::__construct | EvidenceStoreInterface $store, EvidenceExporter $exporter | Câble le store et l’exporter | EvidencePortal | Rien de déclaré | Les deux collaborateurs sont injectables |
EvidencePortal::generateEvidence | string $documentHash, list<EvidenceRecord> $records, ?string $tsaTimestamp = null | Compte les réussites/échecs, scelle un package avec un id UUID neuf et un generatedAt en horloge murale, puis le persiste | EvidencePackage | Rien de déclaré | Persiste via store(), pas persistImmutable() |
EvidencePortal::getEvidence | string $documentHash | Dernier package stocké pour ce hash | ?EvidencePackage | Rien de déclaré | null si aucun n’est stocké |
EvidencePortal::getHistory | string $documentHash | Historique complet, du plus récent au plus ancien | list<EvidencePackage> | Rien de déclaré | L’ordre est fourni par le store |
EvidencePortal::exportAsJson | EvidencePackage $package | Délègue à l’exporter | non-empty-string | JsonException | Mêmes octets que EvidenceExporter::toJson |
EvidencePackage::__construct | huit paramètres nommés, voir le bloc | Objet valeur immuable | EvidencePackage | Rien de déclaré | Les compteurs ne sont pas validés par rapport à $records |
EvidencePackage::allPassed | aucun | failedCount === 0 | bool | Rien de déclaré | true pour un package vide ; contrôle via totalFindings |
EvidencePackage::passRate | aucun | passedCount / totalFindings | float | Rien de déclaré | 0.0 quand totalFindings === 0 |
EvidenceRecord::__construct | string $policyName, bool $passed, string $details, string $validatorVersion, DateTimeImmutable $timestamp | Résultat immuable d’une seule vérification de politique | EvidenceRecord | Rien de déclaré | Toutes les propriétés sont public readonly |
EvidenceExporter::toJson | EvidencePackage $package | JSON à ordre de clés fixe ; barres obliques et Unicode non échappées | non-empty-string | JsonException | L’ordre des clés est déterminant |
EvidenceExporter::exportHash | EvidencePackage $package | SHA-256 sur les octets de toJson() | non-empty-string (64 hex) | JsonException | Stable par package |
EvidenceStoreInterface::store | EvidencePackage $package | Ajoute ; l’historique par hash de document est autorisé | void | Défini par l’implémentation | Sémantique append-only requise |
EvidenceStoreInterface::persistImmutable | EvidencePackage $package | Écriture WORM là où le backend le supporte | void | Défini par l’implémentation | Les backends non-WORM se comportent comme store() |
EvidenceStoreInterface::findByDocumentHash | string $documentHash | Package le plus récent pour ce hash | ?EvidencePackage | Défini par l’implémentation | |
EvidenceStoreInterface::findAllByDocumentHash | string $documentHash | Tous les packages pour ce hash, du plus récent au plus ancien | list<EvidencePackage> | Défini par l’implémentation | |
EvidenceStoreInterface::count | aucun | Nombre total de packages stockés | int<0, max> | Défini par l’implémentation | |
InMemoryEvidenceStore | classe | Store basé sur un tableau, pour les tests et le développement | n/a | n/a | Non durable ; pas de sémantique WORM |
ContinuousMonitor::__construct | EvidenceStoreInterface $store | Câble le store | ContinuousMonitor | Rien de déclaré | |
ContinuousMonitor::check | EvidencePackage $currentEvidence, string $documentHash | Compare les noms de politiques en échec avec le dernier package stocké | MonitorResult | Rien de déclaré | La première vérification traite chaque échec courant comme nouveau |
ContinuousMonitor::isDue | string $documentHash, MonitorSchedule $schedule | Dû quand il n’y a pas de preuve antérieure, que l’intervalle est écoulé, ou que la preuve stockée est datée dans le futur | bool | Rien de déclaré | À sûreté intégrée en cas de dérive d’horloge |
MonitorResult::__construct | huit paramètres nommés, voir le bloc | Résultat de comparaison immuable | MonitorResult | Rien de déclaré | Inclut les deux packages et checkedAt |
MonitorSchedule::__construct | MonitorFrequency $frequency, int $retentionDays = 90, bool $alertOnNewIssues = true | Objet valeur de configuration | MonitorSchedule | Rien de déclaré | La rétention et les alertes sont appliquées par l’hôte |
MonitorFrequency | enum adossé à des string | Cas Daily, Weekly, Monthly | n/a | n/a | Valeurs sous-jacentes daily, weekly, monthly |
MonitorFrequency::intervalSeconds | aucun | Intervalle par cas : 86400, 604800, 2592000 | positive-int | Rien de déclaré | Monthly vaut 30 jours fixes |
Signatures des points d’entrée
Section intitulée « Signatures des points d’entrée »final class EvidencePortal{ public function __construct( private readonly EvidenceStoreInterface $store, private readonly EvidenceExporter $exporter, )
public function generateEvidence(string $documentHash, array $records, ?string $tsaTimestamp = null): EvidencePackage
public function getEvidence(string $documentHash): ?EvidencePackage
public function getHistory(string $documentHash): array
public function exportAsJson(EvidencePackage $package): string}final readonly class EvidencePackage{ public function __construct( public string $packageId, public string $documentHash, public array $records, public int $totalFindings, public int $passedCount, public int $failedCount, public DateTimeImmutable $generatedAt, public ?string $tsaTimestamp = null, )
public function allPassed(): bool
public function passRate(): float}final readonly class EvidenceRecord{ public function __construct( public string $policyName, public bool $passed, public string $details, public string $validatorVersion, public DateTimeImmutable $timestamp, )}final readonly class EvidenceExporter{ public function toJson(EvidencePackage $package): string
public function exportHash(EvidencePackage $package): string}interface EvidenceStoreInterface{ public function store(EvidencePackage $package): void;
public function persistImmutable(EvidencePackage $package): void;
public function findByDocumentHash(string $documentHash): ?EvidencePackage;
public function findAllByDocumentHash(string $documentHash): array;
public function count(): int;}final class ContinuousMonitor{ public function __construct( private readonly EvidenceStoreInterface $store, )
public function check(EvidencePackage $currentEvidence, string $documentHash): MonitorResult
public function isDue(string $documentHash, MonitorSchedule $schedule): bool}final readonly class MonitorSchedule{ public function __construct( public MonitorFrequency $frequency, public int $retentionDays = 90, public bool $alertOnNewIssues = true, )}
enum MonitorFrequency: string{ case Daily = 'daily'; case Weekly = 'weekly'; case Monthly = 'monthly';
public function intervalSeconds(): int}Contrat de comportement
Section intitulée « Contrat de comportement »EvidencePortal::generateEvidence(string $documentHash, list<EvidenceRecord> $records, ?string $tsaTimestamp = null): EvidencePackage est le point d’entrée de scellement. Règles observables de l’extérieur :
- Assemblage.
generateEvidencecompte les enregistrements réussis et échoués et fixetotalFindingsà leur somme. Il attribue unpackageIdUUID version 4 neuf, estampillegeneratedAtavec l’horloge murale, persiste le package viaEvidenceStoreInterface::store, puis le retourne. La liste d’enregistrements est intégrée dans l’ordre fourni, sans modification. - Immuabilité.
EvidencePackageestfinal readonlyet n’est jamais muté après sa construction ; il convient au stockage WORM.allPassed()vautfailedCount === 0.passRate()vautpassedCount / totalFindings, et0.0quandtotalFindings === 0. - Export déterministe.
EvidenceExporter::toJsonémet l’enveloppe et chaque enregistrement selon un ordre de clés fixe, écrit à la main ; la séquence des enregistrements suit le package. L’encodage est strict et lève une exception en cas d’échec, avec les barres obliques et l’Unicode laissés non échappés (JSON_UNESCAPED_SLASHES). Les horodatages sont sérialisés avecDateTimeInterface::RFC3339_EXTENDED, la forme étendue RFC 3339 avec fractions de seconde.exportHashretourne le condensé hexadécimal SHA-256 de 64 caractères portant exactement sur ces octets. Le même package produit toujours le même condensé, sur n’importe quel hôte, à n’importe quel moment. Régénérer les preuves pour le même document produit un nouveaupackageIdet un nouveaugeneratedAt, donc un nouveau condensé : le déterminisme est par package, pas par document. - L’horodatage est une preuve de temps, pas un verdict. Un package peut porter un token RFC 3161 optionnel fourni par l’appelant (encodé en base64). Le token lie le datum du package à une valeur temporelle. Le module l’intègre comme une chaîne opaque ; il ne récupère, n’analyse ni ne vérifie les tokens, et il ne se porte pas garant de la TSA. La vérification des tokens relève des modules Signature et Security.
- Suivi des régressions.
ContinuousMonitor::checkcharge le dernier package stocké pour le hash de document et compare les noms de politiques en échec uniques. Les problèmes sont classés ennewIssues(en échec maintenant, pas avant),resolvedIssues(en échec avant, pas maintenant) etunchangedIssues(en échec dans les deux cas).hasChangesvauttrueuniquement lorsqu’il existe des problèmes nouveaux ou résolus ; des échecs inchangés seuls rapportentfalse. Lors d’une première vérification, chaque échec courant est nouveau. - Planification.
ContinuousMonitor::isDueretournetruelorsqu’aucune preuve n’existe pour le hash, lorsque le temps écoulé depuis legeneratedAtstocké atteint l’intervalle de fréquence de la planification, ou lorsque la preuve stockée est datée dans le futur par rapport à l’hôte qui interroge. Le cas daté dans le futur est à sûreté intégrée : au pire une re-vérification supplémentaire, jamais une manquée. - Contrat de store. Les implémentations de
EvidenceStoreInterfacedoivent prendre en charge une sémantique append-only ; plusieurs packages par hash de document forment l’historique, du plus récent au plus ancien.persistImmutablevise les backends compatibles WORM ; les implémentations non-WORM doivent se comporter exactement commestore.
Cas limites et modes de défaillance
Section intitulée « Cas limites et modes de défaillance »- Un package vide rapporte
allPassed()trueetpassRate()0.0. Contrôle viatotalFindings > 0avant de traiter un package comme une réussite. - La construction directe d’un
EvidencePackagene valide pas les compteurs par rapport à$records. Utilise le portail, ou maintiens toi-même la cohérence des compteurs. generateEvidencepersiste avant de retourner. ExécuteContinuousMonitor::checkavec le nouveau package avant de le persister ; une vérification après la persistance compare le package à lui-même et ne rapporte aucun changement.exportHashcouvre exactement les octets detoJson. Un condensé recalculé par tout autre sérialiseur, ordre de clés ou politique d’échappement ne correspondra pas.MonitorFrequency::Monthlyest une fenêtre fixe de 30 jours, pas un mois calendaire.MonitorSchedule::$retentionDayset$alertOnNewIssuessont une configuration transportée pour les planificateurs de l’hôte. Le module ne supprime jamais de preuve et n’envoie jamais d’alerte.InMemoryEvidenceStoreest destiné aux tests et au développement. Les packages sont perdus à la fin du processus, et sonpersistImmutablen’a pas de sémantique WORM.- Les chaînes
detailsdes enregistrements sont exportées telles quelles ; l’exporter ne caviarde rien. Garde les secrets et les données personnelles réglementées hors dedetails. La résidence, la rétention et le contrôle d’accès suivent l’implémentation de store de l’opérateur. - L’argument
tsaTimestampest accepté comme une chaîne opaque. Un token malformé est intégré tel quel et n’apparaît qu’à la vérification en aval.
Comportement en mode FIPS
Section intitulée « Comportement en mode FIPS »Ce module calcule des condensés SHA-256 et intègre un token RFC 3161 fourni par l’appelant. Il n’effectue aucune signature ni aucune conservation de clé. Le comportement en mode FIPS est régi par les modules Security et Signature.
Conformité
Section intitulée « Conformité »| Affirmation | Standard | Clause |
|---|---|---|
| Un token d’horodatage indique qu’un datum existait à un instant particulier dans le temps. | IETF RFC 3161 | §2 |
| Les horodatages exportés utilisent le profil Internet date/heure d’ISO 8601, avec fractions de seconde. | IETF RFC 3339 | §5.6 |
| Le matériel de validation intégré dans un PDF appartient au Document Security Store ; cette surface relève du module Signature, pas de celui-ci. | ISO 32000-2:2020 | §12.8.4 |
Toutes les clauses sont paraphrasées ; NextPDF ne reproduit pas le texte normatif. NextPDF ne formule aucune revendication de certification. La capture de preuves soutient les workflows d’audit ; ce n’est pas une attestation légale ni une certification d’audit. Un token d’horodatage est une preuve de temps uniquement, et ce module n’affirme pas qu’un quelconque contenu est conforme. La validité et la conformité restent des propriétés du fichier final associé à un validateur. Cette référence n’est pas un avis juridique ; consulte tes propres conseillers en conformité et juridiques.
Notes de développement
Section intitulée « Notes de développement »- Le code source du module porte
@since 2.2.0; cette référence documente la surface telle que livrée dansnextpdf/enterprise3.1.0. - Tout s’exécute en processus sur ton hôte. Le module n’effectue aucune E/S réseau et ne contacte jamais lui-même une TSA.
- L’ordre des clés du littéral de tableau de l’exporter est structurant par conception. Le réordonner changerait
exportHashet invaliderait les condensés stockés précédemment ; le code source l’interdit. packageIdest un UUID version 4 assemblé à partir de la sortie de\random_bytes(16); les identifiants sont uniques mais non reproductibles.- La persistance durable est fournie par l’hôte. L’application du WORM et le contrôle d’accès sont de la responsabilité de l’opérateur ; le store en mémoire est la seule implémentation fournie.
MonitorResultest un objet valeurfinal readonly; ses huit propriétés sontpublic, y comprischeckedAt, l’heure d’horloge murale de la vérification.
Périmètre de publication
Section intitulée « Périmètre de publication »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 ticket sont hors périmètre.
Voir aussi
Section intitulée « Voir aussi »- Evidence — la page de capacité avec les conseils de workflow.
- Validation — Référence approfondie
- Compliance — Référence approfondie
- Piste d’audit AST — Référence approfondie
- Spécifications : PAdES