create(); $tenantB = Tenant::factory()->create(); [$user] = createUserWithTenant($tenantA, role: 'owner'); $user->tenants()->syncWithoutDetaching([ $tenantB->getKey() => ['role' => 'owner'], ]); OperationRun::factory()->create([ 'tenant_id' => $tenantA->getKey(), 'type' => 'policy.sync', 'status' => 'queued', 'outcome' => 'pending', 'initiator_name' => 'TenantA', ]); OperationRun::factory()->create([ 'tenant_id' => $tenantB->getKey(), 'type' => 'inventory.sync', 'status' => 'queued', 'outcome' => 'pending', 'initiator_name' => 'TenantB', ]); $this->actingAs($user) ->get(OperationRunResource::getUrl('index', tenant: $tenantA)) ->assertOk() ->assertSee('Policy sync') ->assertSee('TenantA') ->assertDontSee('Inventory sync') ->assertDontSee('TenantB'); }); it('scopes Monitoring → Operations tabs to the active tenant', function () { $tenantA = Tenant::factory()->create(); $tenantB = Tenant::factory()->create(); [$user] = createUserWithTenant($tenantA, role: 'owner'); $user->tenants()->syncWithoutDetaching([ $tenantB->getKey() => ['role' => 'owner'], ]); $runActiveA = OperationRun::factory()->create([ 'tenant_id' => $tenantA->getKey(), 'type' => 'policy.sync', 'status' => 'queued', 'outcome' => 'pending', 'initiator_name' => 'A-active', ]); $runSucceededA = OperationRun::factory()->create([ 'tenant_id' => $tenantA->getKey(), 'type' => 'policy.sync', 'status' => 'completed', 'outcome' => 'succeeded', 'initiator_name' => 'A-succeeded', ]); $runPartialA = OperationRun::factory()->create([ 'tenant_id' => $tenantA->getKey(), 'type' => 'policy.sync', 'status' => 'completed', 'outcome' => 'partially_succeeded', 'initiator_name' => 'A-partial', ]); $runFailedA = OperationRun::factory()->create([ 'tenant_id' => $tenantA->getKey(), 'type' => 'policy.sync', 'status' => 'completed', 'outcome' => 'failed', 'initiator_name' => 'A-failed', ]); $runActiveB = OperationRun::factory()->create([ 'tenant_id' => $tenantB->getKey(), 'type' => 'inventory.sync', 'status' => 'queued', 'outcome' => 'pending', 'initiator_name' => 'B-active', ]); $runFailedB = OperationRun::factory()->create([ 'tenant_id' => $tenantB->getKey(), 'type' => 'inventory.sync', 'status' => 'completed', 'outcome' => 'failed', 'initiator_name' => 'B-failed', ]); $tenantA->makeCurrent(); Filament::setTenant($tenantA, true); Livewire::actingAs($user) ->test(ListOperationRuns::class) ->assertCanSeeTableRecords([$runActiveA, $runSucceededA, $runPartialA, $runFailedA]) ->assertCanNotSeeTableRecords([$runActiveB, $runFailedB]) ->set('activeTab', 'active') ->assertCanSeeTableRecords([$runActiveA]) ->assertCanNotSeeTableRecords([$runSucceededA, $runPartialA, $runFailedA, $runActiveB, $runFailedB]) ->set('activeTab', 'succeeded') ->assertCanSeeTableRecords([$runSucceededA]) ->assertCanNotSeeTableRecords([$runActiveA, $runPartialA, $runFailedA, $runActiveB, $runFailedB]) ->set('activeTab', 'partial') ->assertCanSeeTableRecords([$runPartialA]) ->assertCanNotSeeTableRecords([$runActiveA, $runSucceededA, $runFailedA, $runActiveB, $runFailedB]) ->set('activeTab', 'failed') ->assertCanSeeTableRecords([$runFailedA]) ->assertCanNotSeeTableRecords([$runActiveA, $runSucceededA, $runPartialA, $runActiveB, $runFailedB]); }); it('prevents cross-tenant access to Monitoring → Operations detail', function () { $tenantA = Tenant::factory()->create(); $tenantB = Tenant::factory()->create(); [$user] = createUserWithTenant($tenantA, role: 'owner'); $user->tenants()->syncWithoutDetaching([ $tenantB->getKey() => ['role' => 'owner'], ]); $runB = OperationRun::factory()->create([ 'tenant_id' => $tenantB->getKey(), 'type' => 'inventory.sync', 'status' => 'queued', 'outcome' => 'pending', 'initiator_name' => 'TenantB', ]); $this->actingAs($user) ->get(OperationRunResource::getUrl('view', ['record' => $runB], tenant: $tenantA)) ->assertNotFound(); });