create([ 'status' => 'active', 'name' => 'Absent Backup Tenant', ]); [$user, $absentTenant] = createUserWithTenant($absentTenant, role: 'owner', workspaceRole: 'readonly'); workspaceOverviewSeedQuietTenantTruth($absentTenant); $staleTenant = Tenant::factory()->create([ 'status' => 'active', 'workspace_id' => (int) $absentTenant->workspace_id, 'name' => 'Stale Backup Tenant', ]); createUserWithTenant($staleTenant, $user, role: 'owner', workspaceRole: 'readonly'); workspaceOverviewSeedQuietTenantTruth($staleTenant); workspaceOverviewSeedHealthyBackup($staleTenant, [ 'name' => 'Stale backup', 'completed_at' => now()->subDays(2), ]); $degradedTenant = Tenant::factory()->create([ 'status' => 'active', 'workspace_id' => (int) $absentTenant->workspace_id, 'name' => 'Degraded Backup Tenant', ]); createUserWithTenant($degradedTenant, $user, role: 'owner', workspaceRole: 'readonly'); workspaceOverviewSeedQuietTenantTruth($degradedTenant); workspaceOverviewSeedHealthyBackup($degradedTenant, [ 'name' => 'Degraded backup', 'completed_at' => now()->subMinutes(30), ], [ 'payload' => [], 'metadata' => [ 'source' => 'metadata_only', 'assignments_fetch_failed' => true, ], 'assignments' => [], ]); $weakenedTenant = Tenant::factory()->create([ 'status' => 'active', 'workspace_id' => (int) $absentTenant->workspace_id, 'name' => 'Weakened Recovery Tenant', ]); createUserWithTenant($weakenedTenant, $user, role: 'owner', workspaceRole: 'readonly'); workspaceOverviewSeedQuietTenantTruth($weakenedTenant); $weakenedBackup = workspaceOverviewSeedHealthyBackup($weakenedTenant, [ 'name' => 'Weakened backup', 'completed_at' => now()->subMinutes(25), ]); workspaceOverviewSeedRestoreHistory($weakenedTenant, $weakenedBackup, 'follow_up'); $unvalidatedTenant = Tenant::factory()->create([ 'status' => 'active', 'workspace_id' => (int) $absentTenant->workspace_id, 'name' => 'Unvalidated Recovery Tenant', ]); createUserWithTenant($unvalidatedTenant, $user, role: 'owner', workspaceRole: 'readonly'); workspaceOverviewSeedQuietTenantTruth($unvalidatedTenant); workspaceOverviewSeedHealthyBackup($unvalidatedTenant, [ 'name' => 'Unvalidated backup', 'completed_at' => now()->subMinutes(20), ]); $calmTenant = Tenant::factory()->create([ 'status' => 'active', 'workspace_id' => (int) $absentTenant->workspace_id, 'name' => 'Calm Tenant', ]); createUserWithTenant($calmTenant, $user, role: 'owner', workspaceRole: 'readonly'); workspaceOverviewSeedQuietTenantTruth($calmTenant); $calmBackup = workspaceOverviewSeedHealthyBackup($calmTenant, [ 'name' => 'Calm backup', 'completed_at' => now()->subMinutes(15), ]); workspaceOverviewSeedRestoreHistory($calmTenant, $calmBackup, 'completed'); $workspace = $absentTenant->workspace()->firstOrFail(); $overview = app(WorkspaceOverviewBuilder::class)->build($workspace, $user); $items = collect($overview['attention_items']); expect($items)->toHaveCount(5) ->and($items->where('family', 'backup_health')->pluck('reason_context.state')->values()->all()) ->toBe(['absent', 'stale', 'degraded']) ->and($items->where('family', 'recovery_evidence')->pluck('reason_context.state')->values()->all()) ->toBe(['weakened', 'unvalidated']) ->and($items->pluck('tenant_label')->all())->not->toContain((string) $calmTenant->name) ->and($items->pluck('reason_context.reason')->filter()->all())->not->toContain('no_recent_issues_visible'); });