forceFill([ 'status' => 'published', 'published_at' => now(), 'published_by_user_id' => (int) $user->getKey(), ])->save(); $review = markEnvironmentReviewCustomerSafeReady($review); if (! $customerSafeReady) { restateEnvironmentReviewEvidenceSnapshot($review->evidenceSnapshot, EvidenceCompletenessState::Partial); $review = $review->fresh(['sections', 'evidenceSnapshot']); } $zipBytes = 'spec392 review pack bytes'; $filePath = sprintf('review-packs/%s/spec392-current.zip', $tenant->external_id); Storage::disk('exports')->put($filePath, $zipBytes); $pack = ReviewPack::factory()->ready()->create([ 'managed_environment_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'environment_review_id' => (int) $review->getKey(), 'evidence_snapshot_id' => (int) $review->evidence_snapshot_id, 'initiated_by_user_id' => (int) $user->getKey(), 'options' => [ 'include_pii' => false, 'include_operations' => true, ], 'summary' => [ 'governance_package' => [ 'executive_summary' => 'Spec392 management-ready review pack.', 'top_findings' => [], 'accepted_risks' => [], 'decision_summary' => [ 'entries' => [], ], ], 'control_interpretation' => [ 'non_certification_disclosure' => 'TenantPilot summarizes available service-delivery evidence for governance review. This report is not a certification, legal attestation, audit opinion, or compliance guarantee.', ], 'delivery_bundle' => [ 'executive_entrypoint_file' => 'executive-summary.md', 'appendix_files' => ['metadata.json'], ], ], 'file_disk' => 'exports', 'file_path' => $filePath, 'file_size' => strlen($zipBytes), 'sha256' => hash('sha256', $zipBytes), 'expires_at' => now()->addDay(), ]); $review->forceFill([ 'current_export_review_pack_id' => (int) $pack->getKey(), ])->save(); return [$user, $tenant, $review->fresh(['sections', 'evidenceSnapshot', 'currentExportReviewPack']), $pack->fresh(['tenant', 'environmentReview'])]; } function spec392ReadyManagementPdf(ReviewPack $pack): StoredReport { $pdfBytes = '%PDF-1.7 Spec392 management report'; $filePath = sprintf('management-reports/%s/spec392-%d.pdf', $pack->tenant->external_id, (int) $pack->getKey()); Storage::disk('exports')->put($filePath, $pdfBytes); return StoredReport::factory()->managementReportPdf([ 'title' => 'Spec392 Management Report', ])->create([ 'workspace_id' => (int) $pack->workspace_id, 'managed_environment_id' => (int) $pack->managed_environment_id, 'source_environment_review_id' => (int) $pack->environment_review_id, 'source_review_pack_id' => (int) $pack->getKey(), 'profile' => ReportProfileRegistry::CUSTOMER_EXECUTIVE, 'file_disk' => 'exports', 'file_path' => $filePath, 'file_size' => strlen($pdfBytes), 'sha256' => hash('sha256', $pdfBytes), 'generated_at' => now(), ]); } it('Spec392 blocks unsafe customer-output downloads but allows authorized internal preview', function (): void { [$owner, $tenant, $review, $pack] = spec392RouteCurrentReviewPack(customerSafeReady: false); [$readonly] = createUserWithTenant( tenant: $tenant, user: \App\Models\User::factory()->create(), role: 'readonly', clearCapabilityCaches: true, ); $customerUrl = app(ReviewPackService::class)->generateDownloadUrl($pack, [ 'source_surface' => 'customer_review_workspace', 'review_id' => (int) $review->getKey(), ]); $internalPreviewUrl = app(ReviewPackService::class)->generateDownloadUrl($pack, [ 'source_surface' => 'review_pack', CustomerOutputGate::INTERNAL_PREVIEW_QUERY_KEY => 1, ]); $this->actingAs($owner)->get($customerUrl)->assertForbidden(); $this->actingAs($readonly)->get($internalPreviewUrl)->assertForbidden(); $this->actingAs($owner) ->get($internalPreviewUrl) ->assertOk() ->assertHeader('X-Review-Pack-SHA256', $pack->sha256) ->assertDownload(); $audit = AuditLog::query() ->where('action', AuditActionId::ReviewPackDownloaded->value) ->latest('id') ->first(); expect($audit)->not->toBeNull() ->and(data_get($audit?->metadata, 'download_mode'))->toBe('internal_preview') ->and(data_get($audit?->metadata, 'customer_output_gate_state'))->toBe(CustomerOutputGate::STATE_NEEDS_ATTENTION); }); it('Spec392 renders unsafe reports only on internal profile routes without customer download copy', function (): void { [$owner, $tenant, $review, $pack] = spec392RouteCurrentReviewPack(customerSafeReady: false); [$readonly] = createUserWithTenant( tenant: $tenant, user: \App\Models\User::factory()->create(), role: 'readonly', clearCapabilityCaches: true, ); $customerReportUrl = app(ReviewPackService::class)->generateRenderedReportUrl($pack, [ 'source_surface' => 'customer_review_workspace', \App\Filament\Pages\Reviews\CustomerReviewWorkspace::DETAIL_CONTEXT_QUERY_KEY => 1, 'review_id' => (int) $review->getKey(), ReportProfileRegistry::QUERY_PARAMETER => ReportProfileRegistry::CUSTOMER_EXECUTIVE, ]); $internalReportUrl = app(ReviewPackService::class)->generateRenderedReportUrl($pack, [ 'source_surface' => 'review_pack', 'review_id' => (int) $review->getKey(), ]); $this->actingAs($owner)->get($customerReportUrl)->assertForbidden(); $this->actingAs($readonly)->get($internalReportUrl)->assertForbidden(); $this->actingAs($owner) ->get($internalReportUrl) ->assertOk() ->assertSee('Report with limitations') ->assertSee('Download internal preview') ->assertDontSee('Customer-safe report ready'); }); it('Spec392 blocks management PDF downloads when the source review pack is not customer safe', function (): void { [$owner, , , $pack] = spec392RouteCurrentReviewPack(customerSafeReady: false); $report = spec392ReadyManagementPdf($pack); $url = app(ManagementReportPdfService::class)->generateDownloadUrl($report, [ 'source_surface' => 'review_pack', ]); $this->actingAs($owner) ->get($url) ->assertForbidden(); expect(AuditLog::query() ->where('action', AuditActionId::ManagementReportPdfDownloaded->value) ->count())->toBe(0); });