Aller au contenu
getnextpdf.com

Enterprise édition

Evidence — Référence approfondie

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.

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.

Fenêtre de terminal
composer require nextpdf/enterprise:^3
SymboleParamètresComportement par défautRetourneLève ou échoue avecNotes
EvidencePortal::__constructEvidenceStoreInterface $store, EvidenceExporter $exporterCâble le store et l’exporterEvidencePortalRien de déclaréLes deux collaborateurs sont injectables
EvidencePortal::generateEvidencestring $documentHash, list<EvidenceRecord> $records, ?string $tsaTimestamp = nullCompte les réussites/échecs, scelle un package avec un id UUID neuf et un generatedAt en horloge murale, puis le persisteEvidencePackageRien de déclaréPersiste via store(), pas persistImmutable()
EvidencePortal::getEvidencestring $documentHashDernier package stocké pour ce hash?EvidencePackageRien de déclarénull si aucun n’est stocké
EvidencePortal::getHistorystring $documentHashHistorique complet, du plus récent au plus ancienlist<EvidencePackage>Rien de déclaréL’ordre est fourni par le store
EvidencePortal::exportAsJsonEvidencePackage $packageDélègue à l’exporternon-empty-stringJsonExceptionMêmes octets que EvidenceExporter::toJson
EvidencePackage::__constructhuit paramètres nommés, voir le blocObjet valeur immuableEvidencePackageRien de déclaréLes compteurs ne sont pas validés par rapport à $records
EvidencePackage::allPassedaucunfailedCount === 0boolRien de déclarétrue pour un package vide ; contrôle via totalFindings
EvidencePackage::passRateaucunpassedCount / totalFindingsfloatRien de déclaré0.0 quand totalFindings === 0
EvidenceRecord::__constructstring $policyName, bool $passed, string $details, string $validatorVersion, DateTimeImmutable $timestampRésultat immuable d’une seule vérification de politiqueEvidenceRecordRien de déclaréToutes les propriétés sont public readonly
EvidenceExporter::toJsonEvidencePackage $packageJSON à ordre de clés fixe ; barres obliques et Unicode non échappéesnon-empty-stringJsonExceptionL’ordre des clés est déterminant
EvidenceExporter::exportHashEvidencePackage $packageSHA-256 sur les octets de toJson()non-empty-string (64 hex)JsonExceptionStable par package
EvidenceStoreInterface::storeEvidencePackage $packageAjoute ; l’historique par hash de document est autorisévoidDéfini par l’implémentationSémantique append-only requise
EvidenceStoreInterface::persistImmutableEvidencePackage $packageÉcriture WORM là où le backend le supportevoidDéfini par l’implémentationLes backends non-WORM se comportent comme store()
EvidenceStoreInterface::findByDocumentHashstring $documentHashPackage le plus récent pour ce hash?EvidencePackageDéfini par l’implémentation
EvidenceStoreInterface::findAllByDocumentHashstring $documentHashTous les packages pour ce hash, du plus récent au plus ancienlist<EvidencePackage>Défini par l’implémentation
EvidenceStoreInterface::countaucunNombre total de packages stockésint<0, max>Défini par l’implémentation
InMemoryEvidenceStoreclasseStore basé sur un tableau, pour les tests et le développementn/an/aNon durable ; pas de sémantique WORM
ContinuousMonitor::__constructEvidenceStoreInterface $storeCâble le storeContinuousMonitorRien de déclaré
ContinuousMonitor::checkEvidencePackage $currentEvidence, string $documentHashCompare les noms de politiques en échec avec le dernier package stockéMonitorResultRien de déclaréLa première vérification traite chaque échec courant comme nouveau
ContinuousMonitor::isDuestring $documentHash, MonitorSchedule $scheduleDû 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 futurboolRien de déclaréÀ sûreté intégrée en cas de dérive d’horloge
MonitorResult::__constructhuit paramètres nommés, voir le blocRésultat de comparaison immuableMonitorResultRien de déclaréInclut les deux packages et checkedAt
MonitorSchedule::__constructMonitorFrequency $frequency, int $retentionDays = 90, bool $alertOnNewIssues = trueObjet valeur de configurationMonitorScheduleRien de déclaréLa rétention et les alertes sont appliquées par l’hôte
MonitorFrequencyenum adossé à des stringCas Daily, Weekly, Monthlyn/an/aValeurs sous-jacentes daily, weekly, monthly
MonitorFrequency::intervalSecondsaucunIntervalle par cas : 86400, 604800, 2592000positive-intRien de déclaréMonthly vaut 30 jours fixes
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
}

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 :

  1. Assemblage. generateEvidence compte les enregistrements réussis et échoués et fixe totalFindings à leur somme. Il attribue un packageId UUID version 4 neuf, estampille generatedAt avec l’horloge murale, persiste le package via EvidenceStoreInterface::store, puis le retourne. La liste d’enregistrements est intégrée dans l’ordre fourni, sans modification.
  2. Immuabilité. EvidencePackage est final readonly et n’est jamais muté après sa construction ; il convient au stockage WORM. allPassed() vaut failedCount === 0. passRate() vaut passedCount / totalFindings, et 0.0 quand totalFindings === 0.
  3. 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 avec DateTimeInterface::RFC3339_EXTENDED, la forme étendue RFC 3339 avec fractions de seconde. exportHash retourne 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 nouveau packageId et un nouveau generatedAt, donc un nouveau condensé : le déterminisme est par package, pas par document.
  4. 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.
  5. Suivi des régressions. ContinuousMonitor::check charge le dernier package stocké pour le hash de document et compare les noms de politiques en échec uniques. Les problèmes sont classés en newIssues (en échec maintenant, pas avant), resolvedIssues (en échec avant, pas maintenant) et unchangedIssues (en échec dans les deux cas). hasChanges vaut true uniquement lorsqu’il existe des problèmes nouveaux ou résolus ; des échecs inchangés seuls rapportent false. Lors d’une première vérification, chaque échec courant est nouveau.
  6. Planification. ContinuousMonitor::isDue retourne true lorsqu’aucune preuve n’existe pour le hash, lorsque le temps écoulé depuis le generatedAt stocké 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.
  7. Contrat de store. Les implémentations de EvidenceStoreInterface doivent prendre en charge une sémantique append-only ; plusieurs packages par hash de document forment l’historique, du plus récent au plus ancien. persistImmutable vise les backends compatibles WORM ; les implémentations non-WORM doivent se comporter exactement comme store.
  • Un package vide rapporte allPassed() true et passRate() 0.0. Contrôle via totalFindings > 0 avant de traiter un package comme une réussite.
  • La construction directe d’un EvidencePackage ne valide pas les compteurs par rapport à $records. Utilise le portail, ou maintiens toi-même la cohérence des compteurs.
  • generateEvidence persiste avant de retourner. Exécute ContinuousMonitor::check avec 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.
  • exportHash couvre exactement les octets de toJson. Un condensé recalculé par tout autre sérialiseur, ordre de clés ou politique d’échappement ne correspondra pas.
  • MonitorFrequency::Monthly est une fenêtre fixe de 30 jours, pas un mois calendaire.
  • MonitorSchedule::$retentionDays et $alertOnNewIssues sont une configuration transportée pour les planificateurs de l’hôte. Le module ne supprime jamais de preuve et n’envoie jamais d’alerte.
  • InMemoryEvidenceStore est destiné aux tests et au développement. Les packages sont perdus à la fin du processus, et son persistImmutable n’a pas de sémantique WORM.
  • Les chaînes details des enregistrements sont exportées telles quelles ; l’exporter ne caviarde rien. Garde les secrets et les données personnelles réglementées hors de details. 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 tsaTimestamp est accepté comme une chaîne opaque. Un token malformé est intégré tel quel et n’apparaît qu’à la vérification en aval.

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.

AffirmationStandardClause
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.

  • Le code source du module porte @since 2.2.0 ; cette référence documente la surface telle que livrée dans nextpdf/enterprise 3.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 exportHash et invaliderait les condensés stockés précédemment ; le code source l’interdit.
  • packageId est 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.
  • MonitorResult est un objet valeur final readonly ; ses huit propriétés sont public, y compris checkedAt, l’heure d’horloge murale de la vérification.

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.