generateFromReview($review, $user, [ 'include_pii' => true, 'include_operations' => false, ]); app()->call([new GenerateReviewPackJob( reviewPackId: (int) $pack->getKey(), operationRunId: (int) $pack->operation_run_id, ), 'handle']); $pack->refresh(); [$zip, $tempFile, $filenames] = spec347OpenPackZip($pack); $metadata = json_decode((string) $zip->getFromName('metadata.json'), true, 512, JSON_THROW_ON_ERROR); $summary = json_decode((string) $zip->getFromName('summary.json'), true, 512, JSON_THROW_ON_ERROR); $sections = json_decode((string) $zip->getFromName('sections.json'), true, 512, JSON_THROW_ON_ERROR); expect($filenames)->toContain( 'metadata.json', 'summary.json', 'sections.json', ReviewPackService::EXECUTIVE_ENTRYPOINT_FILENAME, )->and(data_get($metadata, 'delivery_bundle.contract'))->toBe(ReviewPackService::REVIEW_DERIVED_DELIVERY_CONTRACT) ->and(data_get($metadata, 'delivery_bundle.artifact_family'))->toBe('review_pack') ->and(data_get($metadata, 'delivery_bundle.review_pack_id'))->toBe((int) $pack->getKey()) ->and(data_get($metadata, 'delivery_bundle.released_review.id'))->toBe((int) $review->getKey()) ->and(data_get($metadata, 'delivery_bundle.released_review.status'))->toBe((string) $review->status) ->and(data_get($metadata, 'delivery_bundle.entrypoint.file'))->toBe(ReviewPackService::EXECUTIVE_ENTRYPOINT_FILENAME) ->and(data_get($metadata, 'delivery_bundle.entrypoint.role'))->toBe('executive_entrypoint') ->and(data_get($metadata, 'delivery_bundle.appendix.0.file'))->toBe('metadata.json') ->and(data_get($metadata, 'environment_review.id'))->toBe((int) $review->getKey()) ->and(data_get($metadata, 'environment_review.status'))->toBe((string) $review->status) ->and(data_get($metadata, 'evidence_snapshot.id'))->toBe((int) $review->evidence_snapshot_id) ->and(data_get($metadata, 'evidence_snapshot.fingerprint'))->toBe((string) $review->evidenceSnapshot?->fingerprint) ->and(data_get($metadata, 'options.include_pii'))->toBeTrue() ->and(data_get($metadata, 'options.include_operations'))->toBeFalse() ->and(data_get($metadata, 'redaction_integrity.protected_values_hidden'))->toBeTrue() ->and(data_get($summary, 'has_ready_export'))->toBeTrue() ->and(data_get($summary, 'delivery_bundle.contract'))->toBe(ReviewPackService::REVIEW_DERIVED_DELIVERY_CONTRACT) ->and(data_get($summary, 'evidence_basis.completeness_state'))->toBe((string) $review->evidenceSnapshot?->completeness_state) ->and(data_get($summary, 'output_readiness.has_ready_export'))->toBeTrue() ->and(data_get($summary, 'output_readiness.contains_pii'))->toBeTrue() ->and($sections)->toBeArray()->not->toBeEmpty(); $firstSection = $sections[0]; $firstSectionFilename = sprintf( 'sections/%02d-%s.json', (int) $firstSection['sort_order'], (string) $firstSection['section_key'], ); $firstSectionFile = json_decode((string) $zip->getFromName($firstSectionFilename), true, 512, JSON_THROW_ON_ERROR); expect($filenames)->toContain($firstSectionFilename) ->and($firstSectionFile['section_key'] ?? null)->toBe($firstSection['section_key']) ->and($firstSectionFile['title'] ?? null)->toBe($firstSection['title']) ->and($firstSectionFile['sort_order'] ?? null)->toBe($firstSection['sort_order']) ->and($firstSectionFile['required'] ?? null)->toBe($firstSection['required']) ->and($firstSectionFile['completeness_state'] ?? null)->toBe($firstSection['completeness_state']); $zip->close(); unlink($tempFile); }); /** * @return array{0: ZipArchive, 1: string, 2: list} */ function spec347OpenPackZip(ReviewPack $pack): array { $zipContent = Storage::disk('exports')->get((string) $pack->file_path); $tempFile = tempnam(sys_get_temp_dir(), 'spec347-review-pack-'); file_put_contents($tempFile, $zipContent); $zip = new ZipArchive; $zip->open($tempFile); $filenames = collect(range(0, $zip->numFiles - 1)) ->map(fn (int $index): string => (string) $zip->getNameIndex($index)) ->values() ->all(); return [$zip, $tempFile, $filenames]; }