toBeFile(); $contents = file_get_contents($path); expect($contents)->toContain('Tenant Reviews / Environment Reviews') ->and($contents)->toContain('Evidence Snapshots') ->and($contents)->toContain('Review Packs / exports') ->and($contents)->toContain('Accepted Risks / Risk Exceptions') ->and($contents)->toContain('OperationRuns') ->and($contents)->toContain('Audit log'); }); it('lists only the latest published review per entitled environment on the customer review workspace', function (): void { $tenantA = ManagedEnvironment::factory()->create(['name' => 'Alpha ManagedEnvironment']); [$user, $tenantA] = createUserWithTenant(tenant: $tenantA, role: 'readonly'); $tenantB = ManagedEnvironment::factory()->create([ 'workspace_id' => (int) $tenantA->workspace_id, 'name' => 'Beta ManagedEnvironment', ]); createUserWithTenant(tenant: $tenantB, user: $user, role: 'readonly'); $tenantDenied = ManagedEnvironment::factory()->create([ 'workspace_id' => (int) $tenantA->workspace_id, 'name' => 'Denied ManagedEnvironment', ]); $otherOwner = User::factory()->create(); createUserWithTenant(tenant: $tenantDenied, user: $otherOwner, role: 'owner'); $tenantASnapshot = seedEnvironmentReviewEvidence($tenantA); $tenantBSnapshot = seedEnvironmentReviewEvidence($tenantB); $tenantDeniedSnapshot = seedEnvironmentReviewEvidence($tenantDenied); $olderPublishedReview = composeEnvironmentReviewForTest($tenantA, $user, $tenantASnapshot); $olderPublishedReview->forceFill([ 'status' => EnvironmentReviewStatus::Published->value, 'generated_at' => now()->subDays(3), 'published_at' => now()->subDays(3), 'published_by_user_id' => (int) $user->getKey(), ])->save(); $newerInternalReview = $olderPublishedReview->replicate(); $newerInternalReview->forceFill([ 'managed_environment_id' => (int) $tenantA->getKey(), 'workspace_id' => (int) $tenantA->workspace_id, 'evidence_snapshot_id' => (int) $tenantASnapshot->getKey(), 'status' => EnvironmentReviewStatus::Ready->value, 'generated_at' => now()->subDay(), 'published_at' => null, 'published_by_user_id' => null, ])->save(); $latestPublishedReview = $olderPublishedReview->replicate(); $latestPublishedReview->forceFill([ 'managed_environment_id' => (int) $tenantA->getKey(), 'workspace_id' => (int) $tenantA->workspace_id, 'evidence_snapshot_id' => (int) $tenantASnapshot->getKey(), 'status' => EnvironmentReviewStatus::Published->value, 'generated_at' => now(), 'published_at' => now(), 'published_by_user_id' => (int) $user->getKey(), ])->save(); $betaPublishedReview = composeEnvironmentReviewForTest($tenantB, $user, $tenantBSnapshot); $betaPublishedReview->forceFill([ 'status' => EnvironmentReviewStatus::Published->value, 'generated_at' => now()->subHours(2), 'published_at' => now()->subHours(2), 'published_by_user_id' => (int) $user->getKey(), ])->save(); $deniedPublishedReview = composeEnvironmentReviewForTest($tenantDenied, $otherOwner, $tenantDeniedSnapshot); $deniedPublishedReview->forceFill([ 'status' => EnvironmentReviewStatus::Published->value, 'generated_at' => now()->subHours(3), 'published_at' => now()->subHours(3), 'published_by_user_id' => (int) $otherOwner->getKey(), ])->save(); $this->actingAs($user); setAdminPanelContext(); session()->put(WorkspaceContext::SESSION_KEY, (int) $tenantA->workspace_id); Livewire::actingAs($user) ->test(CustomerReviewWorkspace::class) ->assertCanSeeTableRecords([$tenantA->fresh(), $tenantB->fresh()]) ->assertCanNotSeeTableRecords([$tenantDenied->fresh()]) ->assertSee(EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $latestPublishedReview->fresh()], $tenantA), false) ->assertSee('Customer-safe review packages') ->assertSee('Review released governance packages, evidence readiness, accepted risks, and handoff status across entitled environments.') ->assertSee('Service delivery summary only. Does not replace formal audit opinion, certification, or legal attestation.') ->assertSee('Review package index') ->assertSee('Released reviews and customer-safe package entries available in this workspace.') ->assertDontSee('for each entitled tenant') ->assertDontSee('Each row is an index entry') ->assertSee('Governance package') ->assertSee('Status') ->assertSee('Evidence') ->assertSee('Next step') ->assertSee('Open') ->assertSee('Open review') ->assertDontSee('Assessment status') ->assertDontSee('Publishable') ->assertDontSee('No mapped controls') ->assertDontSee('Compliance evidence mapping v1') ->assertDontSee(ComplianceEvidenceMappingV1::VERSION_KEY) ->assertSee(EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $betaPublishedReview->fresh()], $tenantB), false) ->assertDontSee(EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $olderPublishedReview->fresh()], $tenantA), false) ->assertDontSee(EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $newerInternalReview->fresh()], $tenantA), false) ->assertDontSee('Publish review') ->assertDontSee('Refresh review') ->assertDontSee('Create next review') ->assertDontSee('Regenerate') ->assertDontSee('Expire snapshot') ->assertDontSee(EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $deniedPublishedReview->fresh()], $tenantDenied), false); }); it('renders the Spec 326 decision-first review workspace without default raw diagnostics', function (): void { $tenant = ManagedEnvironment::factory()->create(['name' => 'Decision Ready ManagedEnvironment']); [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'readonly'); $snapshot = seedEnvironmentReviewEvidence($tenant); $review = composeEnvironmentReviewForTest($tenant, $user, $snapshot); $summary = is_array($review->summary) ? $review->summary : []; $summary['debug_payload'] = 'raw payload should stay hidden'; $summary['stack_trace'] = 'stack trace should stay hidden'; $summary['internal_exception'] = 'internal exception should stay hidden'; $summary['provider_secret'] = 'provider secret should stay hidden'; $summary['debug_metadata'] = 'debug metadata should stay hidden'; $summary['source_fingerprint'] = 'source fingerprint should stay hidden'; $summary['control_interpretation']['version_key'] = ComplianceEvidenceMappingV1::VERSION_KEY; $summary['control_interpretation']['controls'] = [ [ 'control_key' => 'customer-handoff-readiness', 'title' => 'Customer handoff readiness', 'readiness_bucket' => 'evidence_on_record', 'readiness_label' => 'Evidence on record', 'primary_reason' => 'Evidence path is complete.', 'recommended_next_action' => 'Share the current review pack.', ], ]; $summary['governance_package']['decision_summary']['entries'][] = [ 'title' => 'Customer acceptance checkpoint', 'summary' => 'Confirm stakeholder awareness before handoff.', 'next_action' => 'Record the customer decision trail before the next review.', ]; $review->forceFill([ 'status' => EnvironmentReviewStatus::Published->value, 'summary' => $summary, 'published_at' => now(), 'published_by_user_id' => (int) $user->getKey(), ])->save(); $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) $snapshot->getKey(), 'initiated_by_user_id' => (int) $user->getKey(), ]); $review->forceFill(['current_export_review_pack_id' => (int) $pack->getKey()])->save(); $this->actingAs($user); setAdminPanelContext(); session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id); Livewire::actingAs($user) ->test(CustomerReviewWorkspace::class) ->assertSee('Customer Review Workspace') ->assertSee('What is the current review pack output state?') ->assertSee('Review consumption flow') ->assertSee('Evidence') ->assertSee('Findings needing attention') ->assertSee('Evidence path') ->assertSeeHtml('data-testid="customer-review-evidence-aside"') ->assertSee('Review pack state') ->assertSee('Review pack') ->assertSee('Decision trail') ->assertSee('Accepted risks') ->assertSee('Expiring soon') ->assertSee('Expired') ->assertSee('Pending approval') ->assertSee('Needs attention') ->assertDontSee('Operation proof') ->assertSee('Customer-safe follow-ups') ->assertSee('Review package index') ->assertSee('Disclosure rule') ->assertSee('Decision') ->assertSee('Ready') ->assertSee('Diagnostics') ->assertSee('Not configured') ->assertSee('Raw/support') ->assertSee('Blocked') ->assertSee('Support details stay on authorized diagnostic surfaces') ->assertSee('Customer acceptance checkpoint') ->assertSee('Open review') ->assertDontSee(EvidenceSnapshotResource::getUrl('view', ['record' => $snapshot], tenant: $tenant, panel: 'admin'), false) ->assertDontSeeHtml('data-testid="customer-review-technical-details"') ->assertDontSee('Technical details') ->assertDontSee('Download internal preview') ->assertDontSee('raw payload should stay hidden') ->assertDontSee('stack trace should stay hidden') ->assertDontSee('internal exception should stay hidden') ->assertDontSee('provider secret should stay hidden') ->assertDontSee('debug metadata should stay hidden') ->assertDontSee('source fingerprint should stay hidden') ->assertDontSee('Publish review') ->assertDontSee('Refresh review') ->assertDontSee('Regenerate') ->assertDontSee('Expire snapshot'); }); it('does not show ready to share when accepted-risk follow-up is required', function (): void { $environment = ManagedEnvironment::factory()->create(['name' => 'Accepted Risk Follow-up ManagedEnvironment']); [$user, $environment] = createUserWithTenant(tenant: $environment, role: 'readonly'); $snapshot = seedEnvironmentReviewEvidence($environment, findingCount: 0, driftCount: 0); $review = composeEnvironmentReviewForTest($environment, $user, $snapshot); $summary = is_array($review->summary) ? $review->summary : []; $summary['control_interpretation']['version_key'] = ComplianceEvidenceMappingV1::VERSION_KEY; $summary['control_interpretation']['controls'] = [ [ 'control_key' => 'customer-handoff-readiness', 'title' => 'Customer handoff readiness', 'readiness_bucket' => 'evidence_on_record', 'readiness_label' => 'Evidence on record', 'primary_reason' => 'Evidence path is complete.', 'recommended_next_action' => 'Share the current review pack.', ], ]; $summary['governance_package']['decision_summary'] = [ 'status' => 'none', 'total_count' => 0, 'summary' => 'No decisions require customer awareness.', 'next_action' => 'No customer action is needed.', 'entries' => [], ]; $summary['governance_package']['accepted_risks'] = [ [ 'title' => 'Accepted risk renewal', 'governance_state' => 'expiring_exception', 'customer_summary' => 'Review the accepted-risk follow-up before customer handoff.', ], ]; $review->forceFill([ 'status' => EnvironmentReviewStatus::Published->value, 'summary' => $summary, 'published_at' => now(), 'published_by_user_id' => (int) $user->getKey(), ])->save(); $pack = ReviewPack::factory()->ready()->create([ 'managed_environment_id' => (int) $environment->getKey(), 'workspace_id' => (int) $environment->workspace_id, 'environment_review_id' => (int) $review->getKey(), 'evidence_snapshot_id' => (int) $snapshot->getKey(), 'initiated_by_user_id' => (int) $user->getKey(), 'options' => [ 'include_pii' => false, 'include_operations' => true, ], ]); $review->forceFill(['current_export_review_pack_id' => (int) $pack->getKey()])->save(); $this->actingAs($user); setAdminPanelContext(); session()->put(WorkspaceContext::SESSION_KEY, (int) $environment->workspace_id); Livewire::actingAs($user) ->test(CustomerReviewWorkspace::class) ->assertSee('What is the current review pack output state?') ->assertSee('Needs attention') ->assertSee('Accepted-risk follow-up is recorded for this review') ->assertSee('The pack can be shared only with the accepted-risk context included in the customer handoff.') ->assertSee('Needs attention') ->assertSee('Follow-up required') ->assertSee('Accepted-risk follow-up is required.') ->assertSee('Open review') ->assertSeeInOrder(['Needs attention', 'Open review']) ->assertDontSee('Download internal preview') ->assertDontSee('Ready to share'); }); it('customer_review_workspace_does_not_use_tenant_as_platform_context_copy', function (): void { $environment = ManagedEnvironment::factory()->create(['name' => 'Vocabulary ManagedEnvironment']); [$user, $environment] = createUserWithTenant(tenant: $environment, role: 'readonly'); $snapshot = seedEnvironmentReviewEvidence($environment); $review = composeEnvironmentReviewForTest($environment, $user, $snapshot); $review->forceFill([ 'status' => EnvironmentReviewStatus::Published->value, 'published_at' => now(), 'published_by_user_id' => (int) $user->getKey(), ])->save(); $this->actingAs($user); setAdminPanelContext(); session()->put(WorkspaceContext::SESSION_KEY, (int) $environment->workspace_id); Livewire::actingAs($user) ->test(CustomerReviewWorkspace::class) ->assertSee('Customer-safe review packages') ->assertSee('entitled environments') ->assertDontSee('entitled tenant') ->assertDontSee('entitled tenants') ->assertDontSee('current tenant') ->assertDontSee('tenant filter') ->assertDontSee('for each entitled tenant'); }); it('shows explicit unavailable proof states instead of false share readiness', function (): void { $tenant = ManagedEnvironment::factory()->create(['name' => 'Needs Evidence ManagedEnvironment']); [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'readonly'); $snapshot = seedPartialEnvironmentReviewEvidence($tenant, findingCount: 0, driftCount: 0); $review = composeEnvironmentReviewForTest($tenant, $user, $snapshot); $review->forceFill([ 'status' => EnvironmentReviewStatus::Published->value, 'published_at' => now(), 'published_by_user_id' => (int) $user->getKey(), ])->save(); $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) $snapshot->getKey(), 'initiated_by_user_id' => (int) $user->getKey(), 'options' => [ 'include_pii' => false, 'include_operations' => true, ], ]); $review->forceFill(['current_export_review_pack_id' => (int) $pack->getKey()])->save(); $this->actingAs($user); setAdminPanelContext(); session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id); $component = Livewire::actingAs($user) ->test(CustomerReviewWorkspace::class) ->assertSee('What is the current review pack output state?') ->assertSee('Needs attention') ->assertSee('Review blockers are still recorded for this output.') ->assertDontSee('No operation proof linked') ->assertSee('Ready') ->assertDontSee('Output not customer-ready') ->assertDontSee('Ready to share') ->assertDontSee('Download internal preview'); expect($component->html())->toMatch('/