middleware()), fn (Closure $next, object $middleware): Closure => fn (object $job): mixed => $middleware->handle($job, $next), $terminal, ); return $pipeline($job); } it('blocks provider execution families consistently when provider capability is lost', function (string $operationType, string $jobClass): void { [$user, $tenant] = createUserWithTenant(role: 'owner'); $connection = ProviderConnection::factory()->platform()->consentGranted()->create([ 'tenant_id' => (int) $tenant->getKey(), 'provider' => 'microsoft', 'entra_tenant_id' => fake()->uuid(), 'status' => 'connected', ]); $run = app(OperationRunService::class)->ensureRun( tenant: $tenant, type: $operationType, inputs: [ 'provider_connection_id' => (int) $connection->getKey(), 'required_capability' => Capabilities::PROVIDER_RUN, ], initiator: $user, ); $job = new $jobClass( tenantId: (int) $tenant->getKey(), userId: (int) $user->getKey(), providerConnectionId: (int) $connection->getKey(), operationRun: $run, ); $user->tenantMemberships()->where('tenant_id', $tenant->getKey())->update(['role' => 'readonly']); app(CapabilityResolver::class)->clearCache(); $terminalInvoked = false; runQueuedContractMatrixJobThroughMiddleware( $job, function () use (&$terminalInvoked): string { $terminalInvoked = true; return 'ran'; }, ); $run->refresh(); expect($terminalInvoked)->toBeFalse() ->and($run->outcome)->toBe('blocked') ->and($run->context['reason_code'] ?? null)->toBe('missing_capability') ->and($run->context['execution_legitimacy']['metadata']['required_capability'] ?? null)->toBe(Capabilities::PROVIDER_RUN); })->with([ 'provider inventory sync' => ['inventory_sync', ProviderInventorySyncJob::class], 'provider compliance snapshot' => ['compliance.snapshot', ProviderComplianceSnapshotJob::class], ]); it('blocks policy sync before side effects when sync capability is lost', function (): void { [$user, $tenant] = createUserWithTenant(role: 'owner'); $run = app(OperationRunService::class)->ensureRun( tenant: $tenant, type: 'policy.sync', inputs: [ 'scope' => 'all', 'types' => ['deviceConfiguration'], ], initiator: $user, ); $job = new SyncPoliciesJob( tenantId: (int) $tenant->getKey(), types: ['deviceConfiguration'], policyIds: null, operationRun: $run, ); $user->tenantMemberships()->where('tenant_id', $tenant->getKey())->update(['role' => 'readonly']); app(CapabilityResolver::class)->clearCache(); $terminalInvoked = false; runQueuedContractMatrixJobThroughMiddleware( $job, function () use (&$terminalInvoked): string { $terminalInvoked = true; return 'ran'; }, ); $run->refresh(); expect($terminalInvoked)->toBeFalse() ->and($run->outcome)->toBe('blocked') ->and($run->context['reason_code'] ?? null)->toBe('missing_capability') ->and($run->context['execution_legitimacy']['metadata']['required_capability'] ?? null)->toBe(Capabilities::TENANT_SYNC); }); it('blocks scheduled backup runs under system authority when tenant operability drifts', function (): void { [, $tenant] = createUserWithTenant(role: 'owner'); $schedule = BackupSchedule::query()->create([ 'tenant_id' => (int) $tenant->getKey(), 'name' => 'Queued legitimacy contract', 'is_enabled' => true, 'timezone' => 'UTC', 'frequency' => 'daily', 'time_of_day' => '01:00:00', 'days_of_week' => null, 'policy_types' => ['deviceConfiguration'], 'include_foundations' => true, 'retention_keep_last' => 30, 'next_run_at' => null, ]); $run = app(OperationRunService::class)->ensureRunWithIdentityStrict( tenant: $tenant, type: 'backup_schedule_run', identityInputs: [ 'backup_schedule_id' => (int) $schedule->getKey(), 'scheduled_for' => now()->toDateTimeString(), ], context: [ 'backup_schedule_id' => (int) $schedule->getKey(), 'trigger' => 'scheduled', ], ); $otherWorkspace = Workspace::factory()->create(); $tenant->forceFill([ 'workspace_id' => (int) $otherWorkspace->getKey(), ])->save(); $job = new RunBackupScheduleJob(operationRun: $run, backupScheduleId: (int) $schedule->getKey()); $terminalInvoked = false; runQueuedContractMatrixJobThroughMiddleware( $job, function () use (&$terminalInvoked): string { $terminalInvoked = true; return 'ran'; }, ); $run->refresh(); expect($terminalInvoked)->toBeFalse() ->and($run->outcome)->toBe('blocked') ->and($run->context['reason_code'] ?? null)->toBe('workspace_mismatch') ->and($run->context['execution_legitimacy']['authority_mode'] ?? null)->toBe('system_authority'); }); it('stores canonical execution metadata in existing operation run context structures', function (): void { [$user, $tenant] = createUserWithTenant(role: 'owner'); $policyRun = app(OperationRunService::class)->ensureRun( tenant: $tenant, type: 'policy.sync', inputs: [ 'scope' => 'all', 'types' => ['deviceConfiguration'], ], initiator: $user, ); $scheduleRun = app(OperationRunService::class)->ensureRunWithIdentityStrict( tenant: $tenant, type: 'backup_schedule_run', identityInputs: [ 'backup_schedule_id' => 99, 'scheduled_for' => now()->toDateTimeString(), ], context: [ 'backup_schedule_id' => 99, 'trigger' => 'scheduled', ], ); $connection = ProviderConnection::factory()->platform()->consentGranted()->create([ 'tenant_id' => (int) $tenant->getKey(), 'provider' => 'microsoft', 'entra_tenant_id' => fake()->uuid(), 'status' => 'connected', ]); $result = app(ProviderOperationStartGate::class)->start( tenant: $tenant, connection: $connection, operationType: 'inventory_sync', dispatcher: static fn (OperationRun $run): null => null, initiator: $user, ); expect($policyRun->context)->toMatchArray([ 'execution_authority_mode' => 'actor_bound', 'required_capability' => Capabilities::TENANT_SYNC, ]) ->and($scheduleRun->context)->toMatchArray([ 'execution_authority_mode' => 'system_authority', 'required_capability' => Capabilities::TENANT_BACKUP_SCHEDULES_RUN, ]) ->and($result->run->context)->toMatchArray([ 'execution_authority_mode' => 'actor_bound', 'required_capability' => Capabilities::PROVIDER_RUN, 'provider_connection_id' => (int) $connection->getKey(), ]); });