*/ function concurrencyBaselineCompareDriftItem(int $baselineProfileId, int $compareOperationRunId, string $subjectKey): array { return [ 'change_type' => 'different_version', 'severity' => Finding::SEVERITY_MEDIUM, 'subject_type' => 'policy', 'subject_external_id' => $subjectKey, 'subject_key' => $subjectKey, 'policy_type' => 'deviceConfiguration', 'baseline_hash' => 'baseline', 'current_hash' => 'current', 'evidence_fidelity' => 'meta', 'evidence' => [ 'change_type' => 'different_version', 'policy_type' => 'deviceConfiguration', 'subject_key' => $subjectKey, 'summary' => ['kind' => 'policy_snapshot'], 'baseline' => ['policy_version_id' => null, 'hash' => 'baseline'], 'current' => ['policy_version_id' => null, 'hash' => 'current'], 'fidelity' => 'meta', 'provenance' => [ 'baseline_profile_id' => $baselineProfileId, 'baseline_snapshot_id' => 1, 'compare_operation_run_id' => $compareOperationRunId, 'inventory_sync_run_id' => null, ], ], ]; } } if (! function_exists('invokeConcurrencyBaselineCompareUpsertFindings')) { /** * @param array> $driftResults * @return array{processed_count:int,created_count:int,reopened_count:int,unchanged_count:int,seen_fingerprints:array} */ function invokeConcurrencyBaselineCompareUpsertFindings( CompareBaselineToTenantJob $job, \App\Models\Tenant $tenant, BaselineProfile $profile, string $scopeKey, array $driftResults, ): array { $reflection = new ReflectionMethod($job, 'upsertFindings'); /** @var array{processed_count:int,created_count:int,reopened_count:int,unchanged_count:int,seen_fingerprints:array} $result */ $result = $reflection->invoke($job, $tenant, $profile, $scopeKey, $driftResults); return $result; } } it('does not reopen when a later human resolve beats an older automated recurrence observation', function (): void { [$user, $tenant] = createUserWithTenant(role: 'manager'); $profile = BaselineProfile::factory()->active()->create([ 'workspace_id' => (int) $tenant->workspace_id, ]); $scopeKey = 'baseline_profile:'.$profile->getKey(); $run1 = OperationRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'baseline_compare', ]); CarbonImmutable::setTestNow(CarbonImmutable::parse('2026-03-18T08:00:00Z')); invokeConcurrencyBaselineCompareUpsertFindings( new CompareBaselineToTenantJob($run1), $tenant, $profile, $scopeKey, [concurrencyBaselineCompareDriftItem((int) $profile->getKey(), (int) $run1->getKey(), 'policy-concurrency')], ); $finding = Finding::query() ->where('tenant_id', (int) $tenant->getKey()) ->where('source', 'baseline.compare') ->firstOrFail(); CarbonImmutable::setTestNow(CarbonImmutable::parse('2026-03-18T10:00:00Z')); app(FindingWorkflowService::class)->resolve($finding, $tenant, $user, 'human-won'); $run2 = OperationRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'baseline_compare', ]); CarbonImmutable::setTestNow(CarbonImmutable::parse('2026-03-18T09:00:00Z')); $result = invokeConcurrencyBaselineCompareUpsertFindings( new CompareBaselineToTenantJob($run2), $tenant, $profile, $scopeKey, [concurrencyBaselineCompareDriftItem((int) $profile->getKey(), (int) $run2->getKey(), 'policy-concurrency')], ); expect($result['reopened_count'])->toBe(0) ->and($finding->fresh()->status)->toBe(Finding::STATUS_RESOLVED) ->and(AuditLog::query() ->where('resource_type', 'finding') ->where('resource_id', (string) $finding->getKey()) ->where('action', AuditActionId::FindingReopened->value) ->count())->toBe(0); }); it('keeps closed findings terminal when recurrence is detected after a human close', function (): void { [$user, $tenant] = createUserWithTenant(role: 'manager'); $profile = BaselineProfile::factory()->active()->create([ 'workspace_id' => (int) $tenant->workspace_id, ]); $scopeKey = 'baseline_profile:'.$profile->getKey(); $run1 = OperationRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'baseline_compare', ]); CarbonImmutable::setTestNow(CarbonImmutable::parse('2026-03-18T08:00:00Z')); invokeConcurrencyBaselineCompareUpsertFindings( new CompareBaselineToTenantJob($run1), $tenant, $profile, $scopeKey, [concurrencyBaselineCompareDriftItem((int) $profile->getKey(), (int) $run1->getKey(), 'policy-closed')], ); $finding = Finding::query() ->where('tenant_id', (int) $tenant->getKey()) ->where('source', 'baseline.compare') ->where('subject_external_id', 'policy-closed') ->firstOrFail(); CarbonImmutable::setTestNow(CarbonImmutable::parse('2026-03-18T09:00:00Z')); app(FindingWorkflowService::class)->close($finding, $tenant, $user, 'accepted'); $run2 = OperationRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'baseline_compare', ]); CarbonImmutable::setTestNow(CarbonImmutable::parse('2026-03-18T10:00:00Z')); $result = invokeConcurrencyBaselineCompareUpsertFindings( new CompareBaselineToTenantJob($run2), $tenant, $profile, $scopeKey, [concurrencyBaselineCompareDriftItem((int) $profile->getKey(), (int) $run2->getKey(), 'policy-closed')], ); expect($result['reopened_count'])->toBe(0) ->and($finding->fresh()->status)->toBe(Finding::STATUS_CLOSED) ->and(AuditLog::query() ->where('resource_type', 'finding') ->where('resource_id', (string) $finding->getKey()) ->where('action', AuditActionId::FindingReopened->value) ->count())->toBe(0); });