콘텐츠로 이동
getnextpdf.com

Enterprise 에디션

Evidence — 심층 참조

이 페이지는 NextPDF\Enterprise\Evidence 모듈에 대한 심층 참조입니다. 모듈은 검증 발견 사항을 불변 EvidencePackage로 봉인하고, 안정적인 SHA-256 다이제스트를 갖춘 결정적 JSON으로 익스포트하며, 플러그형 저장소 계약을 통해 영속화하고, ContinuousMonitor로 실행 간 회귀를 추적합니다. 모듈은 Validation 및 Compliance 표면이 생성한 발견 사항을 소비하며, 자체적으로 적합성 검사를 수행하지 않습니다. 워크플로 안내는 Evidence 기능 페이지를 먼저 읽으십시오.

이 기능은 NextPDF Enterprise(nextpdf/enterprise)에 포함되어 Enterprise 등급 라이선스 봉투로 활성화됩니다. 해당 사용 권한이 없는 배포는 기능의 클래스를 로드하지 않습니다. 에디션 비교 및 라이선스 받기.

이 표면은 enterprise.compliance.evidence 기능으로 라이선스됩니다. 사용 권한이 거부되면 기능이 거부됩니다. Core와 Pro는 발견 사항과 보고서를 생성합니다. 발견 사항을 회귀 추적이 가능한 불변, 결정적, 선택적으로 타임스탬프된 패키지로 봉인하는 것은 Core 등급이나 Pro 등급에 해당하는 것이 없습니다.

Terminal window
composer require nextpdf/enterprise:^3
심볼매개변수기본 동작반환발생 예외 또는 실패비고
EvidencePortal::__constructEvidenceStoreInterface $store, EvidenceExporter $exporter저장소와 익스포터를 연결합니다EvidencePortal선언된 것 없음두 협력자 모두 주입 가능합니다
EvidencePortal::generateEvidencestring $documentHash, list<EvidenceRecord> $records, ?string $tsaTimestamp = null통과/실패를 계산하고, 새 UUID id와 벽시계 generatedAt으로 패키지를 봉인하며, 이를 영속화합니다EvidencePackage선언된 것 없음persistImmutable()이 아니라 store()를 통해 영속화합니다
EvidencePortal::getEvidencestring $documentHash해시에 대해 저장된 최신 패키지?EvidencePackage선언된 것 없음저장된 것이 없으면 null
EvidencePortal::getHistorystring $documentHash전체 이력, 최신순list<EvidencePackage>선언된 것 없음정렬은 저장소가 제공합니다
EvidencePortal::exportAsJsonEvidencePackage $package익스포터에 위임합니다non-empty-stringJsonExceptionEvidenceExporter::toJson과 동일한 바이트
EvidencePackage::__construct명명된 매개변수 8개, 펜스 참조불변 값 객체EvidencePackage선언된 것 없음카운트는 $records에 대해 검증되지 않습니다
EvidencePackage::allPassed없음failedCount === 0bool선언된 것 없음빈 패키지에 대해 true; totalFindings로 게이트하십시오
EvidencePackage::passRate없음passedCount / totalFindingsfloat선언된 것 없음totalFindings === 0일 때 0.0
EvidenceRecord::__constructstring $policyName, bool $passed, string $details, string $validatorVersion, DateTimeImmutable $timestamp불변의 단일 정책 검사 결과EvidenceRecord선언된 것 없음모든 프로퍼티는 public readonly입니다
EvidenceExporter::toJsonEvidencePackage $package고정 키 순서 JSON; 이스케이프되지 않은 슬래시와 유니코드non-empty-stringJsonException키 순서가 핵심적입니다
EvidenceExporter::exportHashEvidencePackage $packagetoJson() 바이트에 대한 SHA-256non-empty-string (64자리 16진수)JsonException패키지마다 안정적
EvidenceStoreInterface::storeEvidencePackage $package추가합니다; 문서 해시별 이력이 허용됩니다void구현 정의추가 전용(append-only) 시맨틱이 필요합니다
EvidenceStoreInterface::persistImmutableEvidencePackage $package백엔드가 지원하는 경우 WORM 쓰기void구현 정의비-WORM 백엔드는 store()처럼 동작합니다
EvidenceStoreInterface::findByDocumentHashstring $documentHash해시에 대한 가장 최근 패키지?EvidencePackage구현 정의
EvidenceStoreInterface::findAllByDocumentHashstring $documentHash해시에 대한 모든 패키지, 최신순list<EvidencePackage>구현 정의
EvidenceStoreInterface::count없음저장된 패키지의 총 개수int<0, max>구현 정의
InMemoryEvidenceStore클래스테스트 및 개발용 배열 기반 저장소해당 없음해당 없음내구성 없음; WORM 시맨틱 없음
ContinuousMonitor::__constructEvidenceStoreInterface $store저장소를 연결합니다ContinuousMonitor선언된 것 없음
ContinuousMonitor::checkEvidencePackage $currentEvidence, string $documentHash실패한 정책 이름을 저장된 최신 패키지와 비교합니다MonitorResult선언된 것 없음첫 검사는 현재의 모든 실패를 새 문제로 취급합니다
ContinuousMonitor::isDuestring $documentHash, MonitorSchedule $schedule이전 증거가 없거나, 간격이 경과했거나, 저장된 증거가 미래 시각일 때 도래합니다bool선언된 것 없음클록 스큐에 대해 페일세이프
MonitorResult::__construct명명된 매개변수 8개, 펜스 참조불변 diff 결과MonitorResult선언된 것 없음두 패키지와 checkedAt을 포함합니다
MonitorSchedule::__constructMonitorFrequency $frequency, int $retentionDays = 90, bool $alertOnNewIssues = true구성 값 객체MonitorSchedule선언된 것 없음보존과 알림은 호스트가 시행합니다
MonitorFrequency문자열 기반 enum케이스 Daily, Weekly, Monthly해당 없음해당 없음백킹 값 daily, weekly, monthly
MonitorFrequency::intervalSeconds없음케이스별 간격: 86400, 604800, 2592000positive-int선언된 것 없음Monthly는 고정 30일입니다
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는 봉인 진입점입니다. 외부에서 관찰 가능한 규칙은 다음과 같습니다.

  1. 조립. generateEvidence는 통과 및 실패 레코드를 계산하고 totalFindings를 그 합으로 설정합니다. 새 버전 4 UUID packageId를 할당하고, generatedAt을 벽시계로 기록하며, EvidenceStoreInterface::store를 통해 패키지를 영속화한 뒤 반환합니다. 레코드 목록은 주어진 순서 그대로 수정 없이 임베드됩니다.
  2. 불변성. EvidencePackagefinal readonly이며 생성 후 결코 변경되지 않습니다. WORM 저장소에 적합합니다. allPassed()failedCount === 0입니다. passRate()passedCount / totalFindings이며, totalFindings === 0일 때 0.0입니다.
  3. 결정적 익스포트. EvidenceExporter::toJson은 봉투와 각 레코드를 고정된 수작업 키 순서로 방출하며, 레코드 순서는 패키지를 따릅니다. 인코딩은 엄격하며 실패 시 예외를 던지고, 슬래시와 유니코드는 이스케이프되지 않은 상태로 둡니다(JSON_UNESCAPED_SLASHES). 타임스탬프는 DateTimeInterface::RFC3339_EXTENDED, 즉 소수 초를 포함하는 RFC 3339 확장 형식으로 직렬화됩니다. exportHash는 정확히 그 바이트에 대한 64자 SHA-256 16진수 다이제스트를 반환합니다. 동일한 패키지는 어떤 호스트에서든 어느 시점에든 항상 동일한 다이제스트를 산출합니다. 동일 문서에 대한 증거를 재생성하면 새 packageIdgeneratedAt, 따라서 새 다이제스트가 생성됩니다. 결정성은 문서 단위가 아니라 패키지 단위입니다.
  4. 타임스탬프는 시점의 증거이지 판정이 아닙니다. 패키지는 호출자가 제공한 선택적 RFC 3161 토큰(base64 인코딩)을 담을 수 있습니다. 이 토큰은 패키지 데이텀을 시간 값에 바인딩합니다. 모듈은 이를 불투명 문자열로 임베드합니다. 토큰을 가져오거나 파싱하거나 검증하지 않으며, TSA를 보증하지도 않습니다. 토큰 검증은 Signature 및 Security 모듈의 몫입니다.
  5. 회귀 추적. ContinuousMonitor::check는 문서 해시에 대해 저장된 최신 패키지를 로드하고 고유한 실패 정책 이름을 비교합니다. 문제는 newIssues(지금 실패, 이전에는 아님), resolvedIssues(이전 실패, 지금은 아님), unchangedIssues(양쪽 모두 실패)로 분류됩니다. hasChanges는 새 문제 또는 해결된 문제가 존재할 때만 true입니다. 변경되지 않은 실패만 있는 경우 false를 보고합니다. 첫 검사에서는 현재의 모든 실패가 새 문제입니다.
  6. 스케줄링. ContinuousMonitor::isDue는 해시에 대한 증거가 없을 때, 저장된 generatedAt 이후 경과 시간이 스케줄 빈도 간격에 도달할 때, 또는 저장된 증거가 폴링 호스트 기준으로 미래 시각일 때 true를 반환합니다. 미래 시각 경우는 페일세이프입니다. 최악의 경우 추가 재검사일 뿐, 결코 놓치지 않습니다.
  7. 저장소 계약. EvidenceStoreInterface 구현은 추가 전용(append-only) 시맨틱을 지원해야 합니다. 문서 해시당 여러 패키지가 최신순으로 이력을 형성합니다. persistImmutable은 WORM 지원 백엔드를 대상으로 합니다. 비-WORM 구현은 store와 정확히 동일하게 동작해야 합니다.
  • 빈 패키지는 allPassed() truepassRate() 0.0을 보고합니다. 패키지를 통과로 취급하기 전에 totalFindings > 0으로 게이트하십시오.
  • EvidencePackage를 직접 생성하면 카운트가 $records에 대해 검증되지 않습니다. 포털을 사용하거나 카운트를 직접 일관되게 유지하십시오.
  • generateEvidence는 반환하기 전에 영속화합니다. 새 패키지를 영속화하기 전에 ContinuousMonitor::check를 실행하십시오. 영속화 후의 검사는 패키지를 자기 자신과 비교하여 변경 없음을 보고합니다.
  • exportHash는 정확한 toJson 바이트를 대상으로 합니다. 다른 직렬화기, 키 순서, 이스케이프 정책으로 재계산된 다이제스트는 일치하지 않습니다.
  • MonitorFrequency::Monthly는 달력상의 한 달이 아니라 고정 30일 윈도입니다.
  • MonitorSchedule::$retentionDays$alertOnNewIssues는 호스트 스케줄러를 위해 전달되는 구성입니다. 모듈은 결코 증거를 삭제하지 않으며 알림도 보내지 않습니다.
  • InMemoryEvidenceStore는 테스트 및 개발용입니다. 패키지는 프로세스 종료 시 소실되며, 그 persistImmutable에는 WORM 시맨틱이 없습니다.
  • 레코드 details 문자열은 그대로 익스포트되며, 익스포터는 편집(redact)하지 않습니다. 비밀 정보와 규제 대상 개인 데이터를 details에서 제외하십시오. 레지던시, 보존, 접근 제어는 운영자의 저장소 구현을 따릅니다.
  • tsaTimestamp 인수는 불투명 문자열로 받아들여집니다. 잘못된 형식의 토큰은 변경 없이 임베드되며 다운스트림 검증에서만 드러납니다.

이 모듈은 SHA-256 다이제스트를 계산하고 호출자가 제공한 RFC 3161 토큰을 임베드합니다. 서명이나 키 보관은 수행하지 않습니다. FIPS 모드 동작은 SecuritySignature 모듈이 관장합니다.

주장표준
타임스탬프 토큰은 데이텀이 특정 시점에 존재했음을 나타냅니다.IETF RFC 3161§2
익스포트된 타임스탬프는 소수 초를 포함하는 ISO 8601의 인터넷 날짜/시간 프로파일을 사용합니다.IETF RFC 3339§5.6
PDF 내부에 임베드된 검증 자료는 문서 보안 저장소에 속합니다. 그 표면은 이 모듈이 아니라 Signature 모듈의 것입니다.ISO 32000-2:2020§12.8.4

모든 절은 의역된 것이며, NextPDF는 규범 텍스트를 재현하지 않습니다. NextPDF는 어떠한 인증 주장도 하지 않습니다. 증거 캡처는 감사 워크플로를 지원합니다. 법적 증명이 아니며 감사 인증도 아닙니다. 타임스탬프 토큰은 시점의 증거일 뿐이며, 이 모듈은 어떠한 콘텐츠도 적합하다고 단언하지 않습니다. 유효성과 적합성은 최종 파일과 검증기의 속성으로 남습니다. 이 참조는 법률 의견이 아닙니다. 자체 규정 준수 및 법률 자문에게 문의하십시오.

  • 모듈 소스는 @since 2.2.0을 담고 있습니다. 이 참조는 nextpdf/enterprise 3.1.0으로 출시된 표면을 문서화합니다.
  • 모든 것은 사용자의 호스트에서 인프로세스로 실행됩니다. 모듈은 네트워크 I/O를 수행하지 않으며 결코 직접 TSA에 접속하지 않습니다.
  • 익스포터의 배열 리터럴 키 순서는 설계상 핵심적입니다. 이를 재정렬하면 exportHash가 바뀌어 이전에 저장된 다이제스트가 무효화됩니다. 소스는 이를 금지합니다.
  • packageId\random_bytes(16) 출력으로 조립된 버전 4 UUID입니다. 식별자는 고유하지만 재현 가능하지 않습니다.
  • 내구성 있는 영속화는 호스트가 공급합니다. WORM 시행과 접근 제어는 운영자의 책임이며, 인메모리 저장소가 유일하게 번들된 구현입니다.
  • MonitorResultfinal readonly 값 객체입니다. 그 8개 프로퍼티는 public이며, 검사의 벽시계 시각인 checkedAt을 포함합니다.

이 페이지는 외부에서 관찰 가능한 동작과 지원되는 공개 API 표면만 문서화합니다. 내부 네임스페이스 경로, 헬퍼 클래스, 메커니즘 표, 런북 파일명, 티켓 접두사는 범위 밖입니다.