create([ 'managed_environment_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'provider.connection.check', 'status' => 'completed', 'outcome' => 'blocked', 'initiator_name' => 'System', ]); $this->actingAs($user); Bus::fake(); Filament::setTenant(null, true); $session = [ WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id, ]; assertNoOutboundHttp(function () use ($run, $session): void { $this->withSession($session) ->get(route('admin.operations.index', ['workspace' => (int) $run->workspace_id])) ->assertOk() ->assertSee(__('localization.shell.all_environments')) ->assertDontSee('Scope: ManagedEnvironment') ->assertDontSee('Scope: Workspace'); $this->withSession($session) ->get(route('admin.operations.view', [ 'workspace' => (int) $run->workspace_id, 'run' => (int) $run->getKey(), ])) ->assertOk() ->assertSee(__('localization.shell.all_environments')) ->assertDontSee('Scope: ManagedEnvironment') ->assertDontSee('Scope: Workspace'); $this->withSession($session) ->followingRedirects() ->get(AlertsCluster::getUrl(panel: 'admin')) ->assertOk() ->assertSee(__('localization.shell.all_environments')) ->assertDontSee('Scope: ManagedEnvironment') ->assertDontSee('Scope: Workspace'); $this->withSession($session) ->get(route('admin.monitoring.audit-log')) ->assertOk() ->assertSee(__('localization.shell.all_environments')) ->assertDontSee('Scope: ManagedEnvironment') ->assertDontSee('Scope: Workspace'); }); Bus::assertNothingDispatched(); })->group('ops-ux'); it('keeps run detail return affordance workspace-scoped when tenant context is active and entitled', function (): void { [$user, $tenant] = createMinimalUserWithTenant(role: 'owner'); $run = OperationRun::factory()->create([ 'managed_environment_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'policy.sync', 'status' => 'queued', 'outcome' => 'pending', ]); $this->actingAs($user); Filament::setTenant($tenant, true); $response = $this->withSession([ WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id, ])->get(route('admin.operations.view', [ 'workspace' => (int) $run->workspace_id, 'run' => (int) $run->getKey(), ])); $response ->assertOk() ->assertSee('Back to Operations') ->assertDontSee('← Back to '.$tenant->name) ->assertDontSee(EnvironmentDashboard::getUrl(tenant: $tenant), false); $this->withSession([ WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id, ])->followingRedirects() ->get(AlertsCluster::getUrl(panel: 'admin')) ->assertOk() ->assertDontSee('Back to Operations'); expect(substr_count(html_entity_decode((string) $response->getContent(), ENT_QUOTES | ENT_HTML5), 'Back to Operations'))->toBeGreaterThanOrEqual(1); })->group('ops-ux'); it('keeps run detail return affordance workspace-scoped when only last tenant memory exists', function (): void { [$user, $tenant] = createMinimalUserWithTenant(role: 'owner'); $run = OperationRun::factory()->create([ 'managed_environment_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'policy.sync', 'status' => 'queued', 'outcome' => 'pending', ]); $this->actingAs($user); Filament::setTenant(null, true); $workspaceId = (int) $tenant->workspace_id; $lastTenantMap = [(string) $workspaceId => (int) $tenant->getKey()]; $response = $this->withSession([ WorkspaceContext::SESSION_KEY => $workspaceId, WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => $lastTenantMap, ])->get(route('admin.operations.view', [ 'workspace' => (int) $run->workspace_id, 'run' => (int) $run->getKey(), ])); $response ->assertOk() ->assertSee('Back to Operations') ->assertDontSee('← Back to '.$tenant->name) ->assertDontSee(EnvironmentDashboard::getUrl(tenant: $tenant), false); })->group('ops-ux'); it('shows no tenant return affordance when active and last tenant contexts are not entitled', function (): void { [$user, $entitledTenant] = createMinimalUserWithTenant(role: 'owner'); $nonEntitledTenant = ManagedEnvironment::factory()->create([ 'workspace_id' => (int) $entitledTenant->workspace_id, ]); $run = OperationRun::factory()->create([ 'managed_environment_id' => (int) $entitledTenant->getKey(), 'workspace_id' => (int) $entitledTenant->workspace_id, 'type' => 'policy.sync', 'status' => 'queued', 'outcome' => 'pending', ]); $this->actingAs($user); Filament::setTenant($nonEntitledTenant, true); $workspaceId = (int) $entitledTenant->workspace_id; $response = $this->withSession([ WorkspaceContext::SESSION_KEY => $workspaceId, WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [(string) $workspaceId => (int) $nonEntitledTenant->getKey()], ])->get(route('admin.operations.view', [ 'workspace' => (int) $run->workspace_id, 'run' => (int) $run->getKey(), ])); $response ->assertOk() ->assertSee('Back to Operations') ->assertDontSee('← Back to '.$nonEntitledTenant->name) ->assertDontSee('Show all operations'); })->group('ops-ux'); it('renders shared scope and return copy as secondary monitoring context on operations surfaces', function (): void { [$user, $tenant] = createMinimalUserWithTenant(role: 'owner'); $run = OperationRun::factory()->create([ 'managed_environment_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'policy.sync', 'status' => 'queued', 'outcome' => 'pending', ]); $this->actingAs($user); Filament::setTenant($tenant, true); $this->withSession([ WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id, ])->get(route('admin.operations.index', ['workspace' => (int) $tenant->workspace_id])) ->assertOk() ->assertSee('Operations Hub') ->assertSee('Which operation needs attention now?') ->assertDontSee('Scope reset'); $this->withSession([ WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id, ])->get(route('admin.operations.view', [ 'workspace' => (int) $run->workspace_id, 'run' => (int) $run->getKey(), ])) ->assertOk() ->assertSee('Monitoring detail') ->assertSee('Navigation lane') ->assertSee('Follow-up lane'); })->group('ops-ux'); it('returns 404 for non-member workspace access on /admin/operations', function (): void { $user = User::factory()->create(); $workspace = Workspace::factory()->create(); // User is NOT a member — stale workspace context is denied as not found. $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $workspace->getKey()]) ->get(route('admin.operations.index', ['workspace' => (int) $workspace->getKey()])) ->assertNotFound(); })->group('ops-ux'); it('keeps canonical tenant dashboard access available for workspace-entitled actors', function (): void { $tenant = ManagedEnvironment::factory()->create(); $user = User::factory()->create(); WorkspaceMembership::factory()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'user_id' => (int) $user->getKey(), 'role' => 'owner', ]); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get(EnvironmentDashboard::getUrl(tenant: $tenant)) ->assertOk(); })->group('ops-ux'); it('keeps member-without-capability workflow start denial as 403 with no run side effects', function (): void { [$user, $tenant] = createMinimalUserWithTenant(role: 'operator'); $this->actingAs($user); Filament::setTenant($tenant, true); $this->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get(RestoreRunResource::getUrl('create', tenant: $tenant)) ->assertForbidden(); expect(OperationRun::query() ->where('managed_environment_id', (int) $tenant->getKey()) ->exists())->toBeFalse(); })->group('ops-ux'); it('does not mutate workspace or last-tenant session memory on /admin/operations', function (): void { [$user, $tenant] = createMinimalUserWithTenant(role: 'owner'); $this->actingAs($user); Filament::setTenant($tenant, true); $workspaceId = (int) $tenant->workspace_id; $lastTenantMap = [(string) $workspaceId => (int) $tenant->getKey()]; $response = $this->withSession([ WorkspaceContext::SESSION_KEY => $workspaceId, WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => $lastTenantMap, ])->get(route('admin.operations.index', ['workspace' => $workspaceId])); $response->assertOk(); $response->assertSessionHas(WorkspaceContext::SESSION_KEY, $workspaceId); $response->assertSessionHas(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, $lastTenantMap); })->group('ops-ux'); it('prefers the filament tenant over remembered workspace tenant state when both are entitled', function (): void { $tenantA = ManagedEnvironment::factory()->create(); [$user, $tenantA] = createMinimalUserWithTenant(tenant: $tenantA, role: 'owner'); $tenantB = ManagedEnvironment::factory()->create([ 'workspace_id' => (int) $tenantA->workspace_id, ]); createMinimalUserWithTenant(tenant: $tenantB, user: $user, role: 'owner'); $this->actingAs($user); Filament::setTenant($tenantB, true); session()->put(WorkspaceContext::SESSION_KEY, (int) $tenantA->workspace_id); session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [ (string) $tenantA->workspace_id => (int) $tenantA->getKey(), ]); $resolved = app(OperateHubShell::class)->activeEntitledTenant(); expect($resolved?->is($tenantB))->toBeTrue(); })->group('ops-ux'); it('keeps canonical run routes tenantless even when filament and remembered environment state exist', function (): void { $runTenant = ManagedEnvironment::factory()->create([ 'workspace_id' => null, ]); [$user, $runTenant] = createMinimalUserWithTenant(tenant: $runTenant, role: 'owner'); $currentTenant = ManagedEnvironment::factory()->create([ 'workspace_id' => (int) $runTenant->workspace_id, ]); createMinimalUserWithTenant(tenant: $currentTenant, user: $user, role: 'owner'); $run = OperationRun::factory()->create([ 'workspace_id' => (int) $runTenant->workspace_id, 'managed_environment_id' => (int) $runTenant->getKey(), 'type' => 'policy.sync', ]); $this->actingAs($user); Filament::setTenant($currentTenant, true); $workspaceId = (int) $runTenant->workspace_id; session()->put(WorkspaceContext::SESSION_KEY, $workspaceId); session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [ (string) $workspaceId => (int) $runTenant->getKey(), ]); $request = Request::create(route('admin.operations.view', [ 'workspace' => $workspaceId, 'run' => (int) $run->getKey(), ])); $request->setLaravelSession(app('session.store')); $route = app('router')->getRoutes()->match($request); $request->setRouteResolver(static fn () => $route); $resolved = app(OperateHubShell::class)->activeEntitledTenant($request); expect($resolved)->toBeNull(); })->group('ops-ux'); it('keeps canonical run routes tenantless even when current tenant context is selector-ineligible', function (): void { $runTenant = ManagedEnvironment::factory()->active()->create([ 'name' => 'Canonical Run ManagedEnvironment', ]); [$user, $runTenant] = createMinimalUserWithTenant(tenant: $runTenant, role: 'owner'); $currentTenant = ManagedEnvironment::factory()->onboarding()->create([ 'workspace_id' => (int) $runTenant->workspace_id, 'name' => 'Current Onboarding ManagedEnvironment', ]); createMinimalUserWithTenant( tenant: $currentTenant, user: $user, role: 'owner', workspaceRole: 'owner', ensureDefaultMicrosoftProviderConnection: false, ); $run = OperationRun::factory()->create([ 'workspace_id' => (int) $runTenant->workspace_id, 'managed_environment_id' => (int) $runTenant->getKey(), 'type' => 'policy.sync', ]); $this->actingAs($user); Filament::setTenant($currentTenant, true); $workspaceId = (int) $runTenant->workspace_id; session()->put(WorkspaceContext::SESSION_KEY, $workspaceId); session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [ (string) $workspaceId => (int) $runTenant->getKey(), ]); $request = Request::create(route('admin.operations.view', [ 'workspace' => $workspaceId, 'run' => (int) $run->getKey(), ])); $request->setLaravelSession(app('session.store')); $route = app('router')->getRoutes()->match($request); $request->setRouteResolver(static fn () => $route); $resolved = app(OperateHubShell::class)->activeEntitledTenant($request); expect($resolved)->toBeNull(); })->group('ops-ux'); it('clears stale remembered environment ids when the remembered environment is no longer entitled', function (): void { [$user, $tenant] = createMinimalUserWithTenant(role: 'owner'); $staleTenant = ManagedEnvironment::factory()->create([ 'workspace_id' => (int) $tenant->workspace_id, ]); $this->actingAs($user); Filament::setTenant(null, true); $workspaceId = (int) $tenant->workspace_id; session()->put(WorkspaceContext::SESSION_KEY, $workspaceId); session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [ (string) $workspaceId => (int) $staleTenant->getKey(), ]); $resolved = app(OperateHubShell::class)->activeEntitledTenant(); expect($resolved)->toBeNull(); expect(session()->get(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [])) ->not->toHaveKey((string) $workspaceId); })->group('ops-ux'); it('prefers the routed tenant over remembered workspace tenant state when a tenant route parameter is present', function (): void { $rememberedEnvironment = ManagedEnvironment::factory()->create([ 'name' => 'YPTW2', 'environment' => 'dev', 'status' => 'active', ]); [$user, $rememberedEnvironment] = createMinimalUserWithTenant(tenant: $rememberedEnvironment, role: 'owner'); $routedTenant = ManagedEnvironment::factory()->create([ 'workspace_id' => (int) $rememberedEnvironment->workspace_id, 'name' => 'Phoenicon', 'environment' => 'dev', 'status' => 'active', ]); createMinimalUserWithTenant(tenant: $routedTenant, user: $user, role: 'owner'); $this->actingAs($user); Filament::setTenant(null, true); $workspaceId = (int) $rememberedEnvironment->workspace_id; session()->put(WorkspaceContext::SESSION_KEY, $workspaceId); session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [ (string) $workspaceId => (int) $rememberedEnvironment->getKey(), ]); $request = Request::create(EnvironmentRequiredPermissions::getUrl([ 'workspace' => (int) $routedTenant->workspace_id, 'environment' => $routedTenant, ], panel: 'admin')); $request->setLaravelSession(app('session.store')); $route = app('router')->getRoutes()->match($request); $request->setRouteResolver(static fn () => $route); $resolved = app(OperateHubShell::class)->activeEntitledTenant($request); expect($resolved?->is($routedTenant))->toBeTrue(); })->group('ops-ux'); it('prefers the routed tenant resource record over active tenant state on admin tenant view routes', function (): void { $rememberedEnvironment = ManagedEnvironment::factory()->create([ 'name' => 'YPTW2', 'environment' => 'dev', 'status' => 'active', ]); [$user, $rememberedEnvironment] = createMinimalUserWithTenant(tenant: $rememberedEnvironment, role: 'owner'); $routedTenant = ManagedEnvironment::factory()->create([ 'workspace_id' => (int) $rememberedEnvironment->workspace_id, 'name' => 'Test', 'environment' => 'dev', 'status' => ManagedEnvironment::STATUS_ONBOARDING, ]); createMinimalUserWithTenant(tenant: $routedTenant, user: $user, role: 'owner'); $this->actingAs($user); Filament::setTenant($rememberedEnvironment, true); $workspaceId = (int) $rememberedEnvironment->workspace_id; session()->put(WorkspaceContext::SESSION_KEY, $workspaceId); session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [ (string) $workspaceId => (int) $rememberedEnvironment->getKey(), ]); $request = Request::create(EnvironmentDashboard::getUrl(tenant: $routedTenant)); $request->setLaravelSession(app('session.store')); $route = app('router')->getRoutes()->match($request); $request->setRouteResolver(static fn () => $route); $resolved = app(OperateHubShell::class)->activeEntitledTenant($request); expect($resolved?->is($routedTenant))->toBeTrue(); })->group('ops-ux'); it('shows all-environments shell label on workspace operations even when tenant context is active', function (): void { [$user, $tenant] = createMinimalUserWithTenant(role: 'owner'); $this->actingAs($user); Filament::setTenant($tenant, true); $this->withSession([ WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id, ])->get(route('admin.operations.index', ['workspace' => (int) $tenant->workspace_id])) ->assertOk() ->assertSee(__('localization.shell.all_environments')) ->assertDontSee('Scope: ManagedEnvironment') ->assertDontSee('Scope: Workspace') ->assertDontSee(__('localization.shell.environment_scope').': '.$tenant->name); })->group('ops-ux'); it('does not create audit entries when viewing operate hub pages', function (): void { [$user, $tenant] = createMinimalUserWithTenant(role: 'owner'); $run = OperationRun::factory()->create([ 'managed_environment_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'policy.sync', 'status' => 'queued', 'outcome' => 'pending', ]); $this->actingAs($user); Filament::setTenant(null, true); $before = (int) AuditLog::query()->count(); $session = [ WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id, ]; $this->withSession($session) ->get(route('admin.operations.index', ['workspace' => (int) $tenant->workspace_id])) ->assertOk(); $this->withSession($session) ->get(route('admin.operations.view', [ 'workspace' => (int) $run->workspace_id, 'run' => (int) $run->getKey(), ])) ->assertOk(); $this->withSession($session) ->followingRedirects() ->get(AlertsCluster::getUrl(panel: 'admin')) ->assertOk(); $this->withSession($session) ->get(route('admin.monitoring.audit-log')) ->assertOk(); expect((int) AuditLog::query()->count())->toBe($before); })->group('ops-ux'); it('suppresses tenant indicator on alert rules list page (manage page)', function (): void { [$user, $tenant] = createMinimalUserWithTenant(role: 'owner'); $this->actingAs($user); Filament::setTenant($tenant, true); $this->withSession([ WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id, ])->get(AlertRuleResource::getUrl(panel: 'admin')) ->assertOk() ->assertDontSee('Filtered by tenant') ->assertDontSee('Scope: ManagedEnvironment') ->assertDontSee('Scope: Workspace'); })->group('ops-ux'); it('suppresses tenant indicator on alert destinations list page (manage page)', function (): void { [$user, $tenant] = createMinimalUserWithTenant(role: 'owner'); $this->actingAs($user); Filament::setTenant($tenant, true); $this->withSession([ WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id, ])->get(AlertDestinationResource::getUrl(panel: 'admin')) ->assertOk() ->assertDontSee('Filtered by tenant') ->assertDontSee('Scope: ManagedEnvironment') ->assertDontSee('Scope: Workspace'); })->group('ops-ux'); it('suppresses tenant indicator on alert rules list with lastEnvironmentId fallback', function (): void { [$user, $tenant] = createMinimalUserWithTenant(role: 'owner'); $this->actingAs($user); Filament::setTenant(null, true); $workspaceId = (int) $tenant->workspace_id; $lastTenantMap = [(string) $workspaceId => (int) $tenant->getKey()]; $this->withSession([ WorkspaceContext::SESSION_KEY => $workspaceId, WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => $lastTenantMap, ])->get(AlertRuleResource::getUrl(panel: 'admin')) ->assertOk() ->assertDontSee('Filtered by tenant') ->assertDontSee('Scope: ManagedEnvironment'); })->group('ops-ux'); it('treats selector-ineligible remembered environments as no selected tenant on canonical viewer routes', function (): void { $runTenant = ManagedEnvironment::factory()->active()->create([ 'name' => 'Canonical Run ManagedEnvironment', ]); [$user, $runTenant] = createMinimalUserWithTenant(tenant: $runTenant, role: 'owner'); $rememberedEnvironment = ManagedEnvironment::factory()->onboarding()->create([ 'workspace_id' => (int) $runTenant->workspace_id, 'name' => 'Stale Onboarding ManagedEnvironment', ]); createMinimalUserWithTenant( tenant: $rememberedEnvironment, user: $user, role: 'owner', workspaceRole: 'owner', ensureDefaultMicrosoftProviderConnection: false, ); $run = OperationRun::factory()->create([ 'managed_environment_id' => (int) $runTenant->getKey(), 'workspace_id' => (int) $runTenant->workspace_id, 'type' => 'policy.sync', ]); $this->actingAs($user); Filament::setTenant(null, true); $response = $this->withSession([ WorkspaceContext::SESSION_KEY => (int) $runTenant->workspace_id, WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [ (string) $runTenant->workspace_id => (int) $rememberedEnvironment->getKey(), ], ])->get(route('admin.operations.view', [ 'workspace' => (int) $run->workspace_id, 'run' => (int) $run->getKey(), ])); $response ->assertOk() ->assertSee(__('localization.shell.all_environments')) ->assertSee('Canonical workspace view') ->assertSee('No environment context is currently selected.'); })->group('ops-ux');