toBeFile(); $contents = (string) file_get_contents($path); expect($contents) ->toContain('Findings') ->toContain('Finding Exceptions / Accepted Risks') ->toContain('OperationRun links') ->toContain('Workspace / Environment filter state') ->toContain('Diagnostics'); }); it('renders the Spec 327 decision-first workbench for the highest-priority finding', function (): void { $tenant = ManagedEnvironment::factory()->create([ 'status' => 'active', 'name' => 'Spec327 Environment Alpha', ]); [$user, $tenant] = createUserWithTenant($tenant, role: 'owner', workspaceRole: 'owner'); Finding::factory() ->for($tenant) ->assignedTo((int) $user->getKey()) ->ownedBy((int) $user->getKey()) ->overdueByHours() ->create([ 'workspace_id' => (int) $tenant->workspace_id, 'subject_external_id' => 'spec327-priority-finding', 'severity' => Finding::SEVERITY_HIGH, 'status' => Finding::STATUS_IN_PROGRESS, 'evidence_jsonb' => [ 'summary' => [ 'kind' => 'policy_snapshot', 'raw_payload' => 'raw payload should stay hidden', 'debug_metadata' => 'debug metadata should stay hidden', ], ], ]); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get(GovernanceInbox::getUrl(panel: 'admin')) ->assertOk() ->assertSee('Governance Inbox') ->assertSee('Daily operator queue for governance follow-up, accepted risk, evidence gaps, and review handoff.') ->assertSee('Open governance work') ->assertSee('Primary inbox lanes') ->assertSee('Reason') ->assertSee('Impact') ->assertSee('Environment') ->assertSee('Review finding') ->assertSee('Evidence captured on finding') ->assertSee('No accepted risk') ->assertSee('More context') ->assertSee('Owner / due') ->assertSee('Next recommended action') ->assertSee('Linked records') ->assertSee('Source detail') ->assertDontSee('No governance items need attention.') ->assertDontSee('tenant filter') ->assertDontSee('current tenant') ->assertDontSee('entitled tenant') ->assertDontSee('all tenants') ->assertDontSee('raw payload should stay hidden') ->assertDontSee('debug metadata should stay hidden'); }); it('renders a compact empty decision state without primary zero metric cards', function (): void { $tenant = ManagedEnvironment::factory()->create([ 'status' => 'active', 'name' => 'Spec327 Empty Environment', ]); [$user, $tenant] = createUserWithTenant($tenant, role: 'owner', workspaceRole: 'owner'); $response = $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get(GovernanceInbox::getUrl(panel: 'admin')); $response ->assertOk() ->assertSee('Open governance work') ->assertSee('No governance items need attention.') ->assertSee('Findings, decisions, accepted-risk reviews, evidence gaps, and review follow-ups will appear here when they need operator attention.') ->assertSee('Diagnostics / source detail') ->assertSee('Collapsed') ->assertDontSee('Decision workbench') ->assertDontSee('raw payload') ->assertDontSee('stack trace') ->assertDontSee('debug metadata') ->assertDontSee('provider secret'); }); it('renders honest missing owner due evidence and accepted-risk states', function (): void { $tenant = ManagedEnvironment::factory()->create([ 'status' => 'active', 'name' => 'Spec327 Environment Missing State', ]); [$user, $tenant] = createUserWithTenant($tenant, role: 'owner', workspaceRole: 'owner'); Finding::factory() ->for($tenant) ->create([ 'workspace_id' => (int) $tenant->workspace_id, 'subject_external_id' => 'spec327-missing-state-finding', 'owner_user_id' => null, 'assignee_user_id' => null, 'due_at' => null, 'evidence_jsonb' => [], ]); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get(GovernanceInbox::getUrl(panel: 'admin')) ->assertOk() ->assertSee('Owner missing') ->assertSee('Due date unavailable') ->assertSee('Evidence missing') ->assertSee('No accepted risk') ->assertSee('Triage finding'); }); it('renders accepted-risk and exception state without exposing raw diagnostics by default', function (): void { $tenant = ManagedEnvironment::factory()->create([ 'status' => 'active', 'name' => 'Spec327 Environment Exception', ]); [$user, $tenant] = createUserWithTenant($tenant, role: 'owner', workspaceRole: 'owner'); $finding = Finding::factory() ->for($tenant) ->riskAccepted() ->create([ 'workspace_id' => (int) $tenant->workspace_id, 'subject_external_id' => 'spec327-exception-finding', ]); FindingException::query()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'managed_environment_id' => (int) $tenant->getKey(), 'finding_id' => (int) $finding->getKey(), 'requested_by_user_id' => (int) $user->getKey(), 'owner_user_id' => null, 'status' => FindingException::STATUS_PENDING, 'current_validity_state' => FindingException::VALIDITY_MISSING_SUPPORT, 'request_reason' => 'Exception needs governance evidence', 'requested_at' => now()->subDay(), 'review_due_at' => now()->addDay(), 'evidence_summary' => ['reference_count' => 0], ]); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get(GovernanceInbox::getUrl(panel: 'admin').'?family=finding_exceptions') ->assertOk() ->assertSee('Risk / exception review') ->assertSee('Exception needs governance evidence') ->assertSee('Pending exception') ->assertSee('Evidence missing') ->assertSee('Review accepted risk') ->assertSee('Diagnostics / source detail') ->assertSee('Collapsed') ->assertDontSee('raw payload') ->assertDontSee('stack trace') ->assertDontSee('provider secret') ->assertDontSee('internal exception') ->assertDontSee('debug metadata'); }); it('keeps source-family filter navigation anchored and expanded on filtered inbox URLs', function (): void { [$user, $tenant] = createUserWithTenant(role: 'owner'); Finding::factory() ->for($tenant) ->assignedTo((int) $user->getKey()) ->create([ 'workspace_id' => (int) $tenant->workspace_id, 'subject_external_id' => 'anchored-source-family-finding', ]); $response = $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get(GovernanceInbox::getUrl(panel: 'admin').'?family=assigned_findings') ->assertOk() ->assertSee('Assigned findings') ->assertSee('Open my findings'); $content = $response->getContent(); expect($content) ->toContain('id="source-detail"') ->toContain('family=assigned_findings#source-detail') ->toContain('family=finding_exceptions#source-detail'); expect((bool) preg_match('/]*id="source-detail"[^>]*open|]*open[^>]*id="source-detail"/s', $content)) ->toBeTrue(); expect((bool) preg_match('/]*family=assigned_findings#source-detail[^>]*aria-current="page"|]*aria-current="page"[^>]*family=assigned_findings#source-detail/s', $content)) ->toBeTrue(); }); it('renders visible governance attention sections on the governance inbox page', function (): void { $alphaTenant = ManagedEnvironment::factory()->create([ 'status' => 'active', 'name' => 'Alpha ManagedEnvironment', 'external_id' => 'alpha-tenant', ]); [$user, $alphaTenant] = createUserWithTenant($alphaTenant, role: 'owner', workspaceRole: 'owner'); $bravoTenant = ManagedEnvironment::factory()->create([ 'status' => 'active', 'workspace_id' => (int) $alphaTenant->workspace_id, 'name' => 'Bravo ManagedEnvironment', 'external_id' => 'bravo-tenant', ]); $user->tenants()->syncWithoutDetaching([ (int) $bravoTenant->getKey() => ['role' => 'owner'], ]); Finding::factory() ->for($alphaTenant) ->assignedTo((int) $user->getKey()) ->ownedBy((int) $user->getKey()) ->overdueByHours() ->create(); Finding::factory() ->for($bravoTenant) ->reopened() ->create(); $exceptionFinding = Finding::factory() ->for($alphaTenant) ->riskAccepted() ->create([ 'workspace_id' => (int) $alphaTenant->workspace_id, 'subject_external_id' => 'exception-governance-home', ]); FindingException::query()->create([ 'workspace_id' => (int) $alphaTenant->workspace_id, 'managed_environment_id' => (int) $alphaTenant->getKey(), 'finding_id' => (int) $exceptionFinding->getKey(), 'requested_by_user_id' => (int) $user->getKey(), 'owner_user_id' => (int) $user->getKey(), 'status' => FindingException::STATUS_PENDING, 'current_validity_state' => FindingException::VALIDITY_MISSING_SUPPORT, 'request_reason' => 'Governance home exception review', 'requested_at' => now()->subDay(), 'review_due_at' => now()->addDay(), 'evidence_summary' => ['reference_count' => 0], ]); OperationRun::factory() ->forTenant($alphaTenant) ->create([ 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Failed->value, 'completed_at' => now()->subMinute(), ]); AlertDelivery::factory()->create([ 'managed_environment_id' => null, 'workspace_id' => (int) $alphaTenant->workspace_id, 'status' => AlertDelivery::STATUS_FAILED, 'payload' => [ 'title' => 'Delivery failed', 'body' => 'A notification destination failed.', ], ]); $backupHealthResolver = app(TenantBackupHealthResolver::class); $fingerprints = app(ManagedEnvironmentTriageReviewFingerprint::class); $alphaBackupFingerprint = $fingerprints->forBackupHealth($backupHealthResolver->assess($alphaTenant)); expect($alphaBackupFingerprint)->not->toBeNull(); ManagedEnvironmentTriageReview::factory() ->for($alphaTenant) ->followUpNeeded() ->create([ 'workspace_id' => (int) $alphaTenant->workspace_id, 'reviewed_by_user_id' => (int) $user->getKey(), 'concern_family' => PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH, 'review_fingerprint' => $alphaBackupFingerprint['fingerprint'], 'review_snapshot' => $alphaBackupFingerprint['snapshot'], ]); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $alphaTenant->workspace_id]) ->get(GovernanceInbox::getUrl(panel: 'admin')) ->assertOk() ->assertSee('Assigned findings') ->assertSee('Findings intake') ->assertSee('Finding exceptions') ->assertSee('Operations follow-up') ->assertSee('Alert delivery failures') ->assertSee('Review follow-up') ->assertSee('Open my findings') ->assertSee('Open finding exceptions') ->assertSee('Open terminal follow-up') ->assertSee('Open alert deliveries') ->assertSee('Open customer review workspace'); }); it('renders honest empty states for tenant and family filtering on the governance inbox page', function (): void { $alphaTenant = ManagedEnvironment::factory()->create([ 'status' => 'active', 'name' => 'Alpha ManagedEnvironment', 'external_id' => 'alpha-tenant', ]); [$user, $alphaTenant] = createUserWithTenant($alphaTenant, role: 'owner', workspaceRole: 'owner'); $bravoTenant = ManagedEnvironment::factory()->create([ 'status' => 'active', 'workspace_id' => (int) $alphaTenant->workspace_id, 'name' => 'Bravo ManagedEnvironment', 'external_id' => 'bravo-tenant', ]); $user->tenants()->syncWithoutDetaching([ (int) $bravoTenant->getKey() => ['role' => 'owner'], ]); Finding::factory() ->for($bravoTenant) ->assignedTo((int) $user->getKey()) ->create(); AlertDelivery::factory()->create([ 'managed_environment_id' => null, 'workspace_id' => (int) $alphaTenant->workspace_id, 'status' => AlertDelivery::STATUS_FAILED, ]); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $alphaTenant->workspace_id]) ->get(GovernanceInbox::getUrl(panel: 'admin').'?environment_id='.(string) $alphaTenant->getKey()) ->assertOk() ->assertSee('This environment filter is hiding other visible attention') ->assertSee('Clear environment filter'); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $alphaTenant->workspace_id]) ->get(GovernanceInbox::getUrl(panel: 'admin').'?environment_id='.(string) $alphaTenant->getKey().'&family=alert_delivery_failures') ->assertOk() ->assertSee('Alert delivery failures') ->assertSee('No failed alert deliveries match this environment filter right now.') ->assertDontSee('Open my findings'); }); it('omits the finding exceptions lane when the workspace capability is not visible', function (): void { $tenant = ManagedEnvironment::factory()->create([ 'status' => 'active', 'name' => 'Alpha ManagedEnvironment', ]); [$user, $tenant] = createUserWithTenant($tenant, role: 'owner', workspaceRole: 'readonly'); Finding::factory() ->for($tenant) ->assignedTo((int) $user->getKey()) ->create([ 'workspace_id' => (int) $tenant->workspace_id, ]); $exceptionFinding = Finding::factory() ->for($tenant) ->riskAccepted() ->create([ 'workspace_id' => (int) $tenant->workspace_id, ]); FindingException::query()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'managed_environment_id' => (int) $tenant->getKey(), 'finding_id' => (int) $exceptionFinding->getKey(), 'requested_by_user_id' => (int) $user->getKey(), 'owner_user_id' => (int) $user->getKey(), 'status' => FindingException::STATUS_PENDING, 'current_validity_state' => FindingException::VALIDITY_MISSING_SUPPORT, 'request_reason' => 'Hidden exception lane', 'requested_at' => now()->subDay(), 'review_due_at' => now()->addDay(), 'evidence_summary' => ['reference_count' => 0], ]); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get(GovernanceInbox::getUrl(panel: 'admin')) ->assertOk() ->assertSee('Assigned findings') ->assertDontSee('Finding exceptions') ->assertDontSee('Hidden exception lane'); });