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 등급에 해당하는 것이 없습니다.
공개 API 표면
섹션 제목: “공개 API 표면”composer require nextpdf/enterprise:^3| 심볼 | 매개변수 | 기본 동작 | 반환 | 발생 예외 또는 실패 | 비고 |
|---|---|---|---|---|---|
EvidencePortal::__construct | EvidenceStoreInterface $store, EvidenceExporter $exporter | 저장소와 익스포터를 연결합니다 | EvidencePortal | 선언된 것 없음 | 두 협력자 모두 주입 가능합니다 |
EvidencePortal::generateEvidence | string $documentHash, list<EvidenceRecord> $records, ?string $tsaTimestamp = null | 통과/실패를 계산하고, 새 UUID id와 벽시계 generatedAt으로 패키지를 봉인하며, 이를 영속화합니다 | EvidencePackage | 선언된 것 없음 | persistImmutable()이 아니라 store()를 통해 영속화합니다 |
EvidencePortal::getEvidence | string $documentHash | 해시에 대해 저장된 최신 패키지 | ?EvidencePackage | 선언된 것 없음 | 저장된 것이 없으면 null |
EvidencePortal::getHistory | string $documentHash | 전체 이력, 최신순 | list<EvidencePackage> | 선언된 것 없음 | 정렬은 저장소가 제공합니다 |
EvidencePortal::exportAsJson | EvidencePackage $package | 익스포터에 위임합니다 | non-empty-string | JsonException | EvidenceExporter::toJson과 동일한 바이트 |
EvidencePackage::__construct | 명명된 매개변수 8개, 펜스 참조 | 불변 값 객체 | EvidencePackage | 선언된 것 없음 | 카운트는 $records에 대해 검증되지 않습니다 |
EvidencePackage::allPassed | 없음 | failedCount === 0 | bool | 선언된 것 없음 | 빈 패키지에 대해 true; totalFindings로 게이트하십시오 |
EvidencePackage::passRate | 없음 | passedCount / totalFindings | float | 선언된 것 없음 | totalFindings === 0일 때 0.0 |
EvidenceRecord::__construct | string $policyName, bool $passed, string $details, string $validatorVersion, DateTimeImmutable $timestamp | 불변의 단일 정책 검사 결과 | EvidenceRecord | 선언된 것 없음 | 모든 프로퍼티는 public readonly입니다 |
EvidenceExporter::toJson | EvidencePackage $package | 고정 키 순서 JSON; 이스케이프되지 않은 슬래시와 유니코드 | non-empty-string | JsonException | 키 순서가 핵심적입니다 |
EvidenceExporter::exportHash | EvidencePackage $package | toJson() 바이트에 대한 SHA-256 | non-empty-string (64자리 16진수) | JsonException | 패키지마다 안정적 |
EvidenceStoreInterface::store | EvidencePackage $package | 추가합니다; 문서 해시별 이력이 허용됩니다 | void | 구현 정의 | 추가 전용(append-only) 시맨틱이 필요합니다 |
EvidenceStoreInterface::persistImmutable | EvidencePackage $package | 백엔드가 지원하는 경우 WORM 쓰기 | void | 구현 정의 | 비-WORM 백엔드는 store()처럼 동작합니다 |
EvidenceStoreInterface::findByDocumentHash | string $documentHash | 해시에 대한 가장 최근 패키지 | ?EvidencePackage | 구현 정의 | |
EvidenceStoreInterface::findAllByDocumentHash | string $documentHash | 해시에 대한 모든 패키지, 최신순 | list<EvidencePackage> | 구현 정의 | |
EvidenceStoreInterface::count | 없음 | 저장된 패키지의 총 개수 | int<0, max> | 구현 정의 | |
InMemoryEvidenceStore | 클래스 | 테스트 및 개발용 배열 기반 저장소 | 해당 없음 | 해당 없음 | 내구성 없음; WORM 시맨틱 없음 |
ContinuousMonitor::__construct | EvidenceStoreInterface $store | 저장소를 연결합니다 | ContinuousMonitor | 선언된 것 없음 | |
ContinuousMonitor::check | EvidencePackage $currentEvidence, string $documentHash | 실패한 정책 이름을 저장된 최신 패키지와 비교합니다 | MonitorResult | 선언된 것 없음 | 첫 검사는 현재의 모든 실패를 새 문제로 취급합니다 |
ContinuousMonitor::isDue | string $documentHash, MonitorSchedule $schedule | 이전 증거가 없거나, 간격이 경과했거나, 저장된 증거가 미래 시각일 때 도래합니다 | bool | 선언된 것 없음 | 클록 스큐에 대해 페일세이프 |
MonitorResult::__construct | 명명된 매개변수 8개, 펜스 참조 | 불변 diff 결과 | MonitorResult | 선언된 것 없음 | 두 패키지와 checkedAt을 포함합니다 |
MonitorSchedule::__construct | MonitorFrequency $frequency, int $retentionDays = 90, bool $alertOnNewIssues = true | 구성 값 객체 | MonitorSchedule | 선언된 것 없음 | 보존과 알림은 호스트가 시행합니다 |
MonitorFrequency | 문자열 기반 enum | 케이스 Daily, Weekly, Monthly | 해당 없음 | 해당 없음 | 백킹 값 daily, weekly, monthly |
MonitorFrequency::intervalSeconds | 없음 | 케이스별 간격: 86400, 604800, 2592000 | positive-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는 봉인 진입점입니다. 외부에서 관찰 가능한 규칙은 다음과 같습니다.
- 조립.
generateEvidence는 통과 및 실패 레코드를 계산하고totalFindings를 그 합으로 설정합니다. 새 버전 4 UUIDpackageId를 할당하고,generatedAt을 벽시계로 기록하며,EvidenceStoreInterface::store를 통해 패키지를 영속화한 뒤 반환합니다. 레코드 목록은 주어진 순서 그대로 수정 없이 임베드됩니다. - 불변성.
EvidencePackage는final readonly이며 생성 후 결코 변경되지 않습니다. WORM 저장소에 적합합니다.allPassed()는failedCount === 0입니다.passRate()는passedCount / totalFindings이며,totalFindings === 0일 때0.0입니다. - 결정적 익스포트.
EvidenceExporter::toJson은 봉투와 각 레코드를 고정된 수작업 키 순서로 방출하며, 레코드 순서는 패키지를 따릅니다. 인코딩은 엄격하며 실패 시 예외를 던지고, 슬래시와 유니코드는 이스케이프되지 않은 상태로 둡니다(JSON_UNESCAPED_SLASHES). 타임스탬프는DateTimeInterface::RFC3339_EXTENDED, 즉 소수 초를 포함하는 RFC 3339 확장 형식으로 직렬화됩니다.exportHash는 정확히 그 바이트에 대한 64자 SHA-256 16진수 다이제스트를 반환합니다. 동일한 패키지는 어떤 호스트에서든 어느 시점에든 항상 동일한 다이제스트를 산출합니다. 동일 문서에 대한 증거를 재생성하면 새packageId와generatedAt, 따라서 새 다이제스트가 생성됩니다. 결정성은 문서 단위가 아니라 패키지 단위입니다. - 타임스탬프는 시점의 증거이지 판정이 아닙니다. 패키지는 호출자가 제공한 선택적 RFC 3161 토큰(base64 인코딩)을 담을 수 있습니다. 이 토큰은 패키지 데이텀을 시간 값에 바인딩합니다. 모듈은 이를 불투명 문자열로 임베드합니다. 토큰을 가져오거나 파싱하거나 검증하지 않으며, TSA를 보증하지도 않습니다. 토큰 검증은 Signature 및 Security 모듈의 몫입니다.
- 회귀 추적.
ContinuousMonitor::check는 문서 해시에 대해 저장된 최신 패키지를 로드하고 고유한 실패 정책 이름을 비교합니다. 문제는newIssues(지금 실패, 이전에는 아님),resolvedIssues(이전 실패, 지금은 아님),unchangedIssues(양쪽 모두 실패)로 분류됩니다.hasChanges는 새 문제 또는 해결된 문제가 존재할 때만true입니다. 변경되지 않은 실패만 있는 경우false를 보고합니다. 첫 검사에서는 현재의 모든 실패가 새 문제입니다. - 스케줄링.
ContinuousMonitor::isDue는 해시에 대한 증거가 없을 때, 저장된generatedAt이후 경과 시간이 스케줄 빈도 간격에 도달할 때, 또는 저장된 증거가 폴링 호스트 기준으로 미래 시각일 때true를 반환합니다. 미래 시각 경우는 페일세이프입니다. 최악의 경우 추가 재검사일 뿐, 결코 놓치지 않습니다. - 저장소 계약.
EvidenceStoreInterface구현은 추가 전용(append-only) 시맨틱을 지원해야 합니다. 문서 해시당 여러 패키지가 최신순으로 이력을 형성합니다.persistImmutable은 WORM 지원 백엔드를 대상으로 합니다. 비-WORM 구현은store와 정확히 동일하게 동작해야 합니다.
엣지 케이스 및 실패 모드
섹션 제목: “엣지 케이스 및 실패 모드”- 빈 패키지는
allPassed()true와passRate()0.0을 보고합니다. 패키지를 통과로 취급하기 전에totalFindings > 0으로 게이트하십시오. EvidencePackage를 직접 생성하면 카운트가$records에 대해 검증되지 않습니다. 포털을 사용하거나 카운트를 직접 일관되게 유지하십시오.generateEvidence는 반환하기 전에 영속화합니다. 새 패키지를 영속화하기 전에ContinuousMonitor::check를 실행하십시오. 영속화 후의 검사는 패키지를 자기 자신과 비교하여 변경 없음을 보고합니다.exportHash는 정확한toJson바이트를 대상으로 합니다. 다른 직렬화기, 키 순서, 이스케이프 정책으로 재계산된 다이제스트는 일치하지 않습니다.MonitorFrequency::Monthly는 달력상의 한 달이 아니라 고정 30일 윈도입니다.MonitorSchedule::$retentionDays와$alertOnNewIssues는 호스트 스케줄러를 위해 전달되는 구성입니다. 모듈은 결코 증거를 삭제하지 않으며 알림도 보내지 않습니다.InMemoryEvidenceStore는 테스트 및 개발용입니다. 패키지는 프로세스 종료 시 소실되며, 그persistImmutable에는 WORM 시맨틱이 없습니다.- 레코드
details문자열은 그대로 익스포트되며, 익스포터는 편집(redact)하지 않습니다. 비밀 정보와 규제 대상 개인 데이터를details에서 제외하십시오. 레지던시, 보존, 접근 제어는 운영자의 저장소 구현을 따릅니다. tsaTimestamp인수는 불투명 문자열로 받아들여집니다. 잘못된 형식의 토큰은 변경 없이 임베드되며 다운스트림 검증에서만 드러납니다.
FIPS 모드 동작
섹션 제목: “FIPS 모드 동작”이 모듈은 SHA-256 다이제스트를 계산하고 호출자가 제공한 RFC 3161 토큰을 임베드합니다. 서명이나 키 보관은 수행하지 않습니다. FIPS 모드 동작은 Security 및 Signature 모듈이 관장합니다.
적합성
섹션 제목: “적합성”| 주장 | 표준 | 절 |
|---|---|---|
| 타임스탬프 토큰은 데이텀이 특정 시점에 존재했음을 나타냅니다. | 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/enterprise3.1.0으로 출시된 표면을 문서화합니다. - 모든 것은 사용자의 호스트에서 인프로세스로 실행됩니다. 모듈은 네트워크 I/O를 수행하지 않으며 결코 직접 TSA에 접속하지 않습니다.
- 익스포터의 배열 리터럴 키 순서는 설계상 핵심적입니다. 이를 재정렬하면
exportHash가 바뀌어 이전에 저장된 다이제스트가 무효화됩니다. 소스는 이를 금지합니다. packageId는\random_bytes(16)출력으로 조립된 버전 4 UUID입니다. 식별자는 고유하지만 재현 가능하지 않습니다.- 내구성 있는 영속화는 호스트가 공급합니다. WORM 시행과 접근 제어는 운영자의 책임이며, 인메모리 저장소가 유일하게 번들된 구현입니다.
MonitorResult는final readonly값 객체입니다. 그 8개 프로퍼티는public이며, 검사의 벽시계 시각인checkedAt을 포함합니다.
공개 경계
섹션 제목: “공개 경계”이 페이지는 외부에서 관찰 가능한 동작과 지원되는 공개 API 표면만 문서화합니다. 내부 네임스페이스 경로, 헬퍼 클래스, 메커니즘 표, 런북 파일명, 티켓 접두사는 범위 밖입니다.
함께 보기
섹션 제목: “함께 보기”- Evidence — 워크플로 안내가 포함된 기능 페이지.
- Validation — 심층 참조
- Compliance — 심층 참조
- AST audit trail — 심층 참조
- Specifications: PAdES