middleware()), fn (Closure $next, object $middleware): Closure => fn (object $job): mixed => $middleware->handle($job, $next), $terminal, ); return $pipeline($job); } it('stores actor-bound execution metadata when inventory sync is queued', function (): void { Queue::fake(); [$user, $tenant] = createUserWithTenant(role: 'owner'); $this->actingAs($user); $tenant->makeCurrent(); Filament::setTenant($tenant, true); Livewire::test(ListInventoryItems::class) ->callAction('run_inventory_sync', data: [ 'policy_types' => ['deviceConfiguration'], 'include_foundations' => false, 'include_dependencies' => false, ]); $opRun = OperationRun::query() ->where('tenant_id', $tenant->getKey()) ->where('type', 'inventory_sync') ->latest('id') ->first(); expect($opRun)->not->toBeNull() ->and($opRun?->context)->toMatchArray([ 'execution_authority_mode' => 'actor_bound', 'required_capability' => Capabilities::TENANT_INVENTORY_SYNC_RUN, ]); }); it('blocks inventory execution when the initiator loses inventory capability before start', function (): void { Queue::fake(); [$user, $tenant] = createUserWithTenant(role: 'owner'); $this->actingAs($user); $tenant->makeCurrent(); Filament::setTenant($tenant, true); Livewire::test(ListInventoryItems::class) ->callAction('run_inventory_sync', data: [ 'policy_types' => ['deviceConfiguration'], 'include_foundations' => false, 'include_dependencies' => false, ]); $capturedJob = null; Queue::assertPushed(RunInventorySyncJob::class, function (RunInventorySyncJob $job) use (&$capturedJob): bool { $capturedJob = $job; return true; }); expect($capturedJob)->toBeInstanceOf(RunInventorySyncJob::class); $user->tenantMemberships()->where('tenant_id', $tenant->getKey())->update(['role' => 'readonly']); app(CapabilityResolver::class)->clearCache(); $terminalInvoked = false; runQueuedInventoryJobThroughMiddleware( $capturedJob, function (RunInventorySyncJob $job) use (&$terminalInvoked): mixed { $terminalInvoked = true; return $job; }, ); $capturedJob->operationRun?->refresh(); expect($terminalInvoked)->toBeFalse() ->and($capturedJob->operationRun?->outcome?->value ?? $capturedJob->operationRun?->outcome)->toBe('blocked') ->and($capturedJob->operationRun?->context['reason_code'] ?? null)->toBe('missing_capability') ->and($capturedJob->operationRun?->context['execution_legitimacy']['metadata']['required_capability'] ?? null)->toBe(Capabilities::TENANT_INVENTORY_SYNC_RUN); }); it('allows inventory execution when legitimacy still holds', function (): void { Queue::fake(); [$user, $tenant] = createUserWithTenant(role: 'owner'); $this->actingAs($user); $tenant->makeCurrent(); Filament::setTenant($tenant, true); Livewire::test(ListInventoryItems::class) ->callAction('run_inventory_sync', data: [ 'policy_types' => ['deviceConfiguration'], 'include_foundations' => false, 'include_dependencies' => false, ]); $capturedJob = null; Queue::assertPushed(RunInventorySyncJob::class, function (RunInventorySyncJob $job) use (&$capturedJob): bool { $capturedJob = $job; return true; }); $this->mock(InventorySyncService::class, function ($mock): void { $mock->shouldReceive('executeSelection') ->once() ->andReturn([ 'status' => 'success', 'had_errors' => false, 'error_codes' => [], 'error_context' => [], 'errors_count' => 0, 'items_observed_count' => 0, 'items_upserted_count' => 0, 'processed_policy_types' => ['deviceConfiguration'], 'failed_policy_types' => [], 'skipped_policy_types' => [], ]); }); runQueuedInventoryJobThroughMiddleware( $capturedJob, fn (RunInventorySyncJob $job): mixed => $job->handle( app(InventorySyncService::class), app(AuditLogger::class), app(OperationRunService::class), ), ); $capturedJob->operationRun?->refresh(); expect($capturedJob->operationRun?->outcome?->value ?? $capturedJob->operationRun?->outcome)->toBe('succeeded'); });