Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 4m7s
Implemented deterministic Baseline Result Semantics (Spec 383), introducing CompareSubjectResult and CompareEvidenceResult. Replaced generic arrays with strict Data Transfer Objects for Baseline engine output.
262 lines
9.9 KiB
PHP
262 lines
9.9 KiB
PHP
<?php
|
|
|
|
use App\Models\BaselineProfile;
|
|
use App\Models\BaselineSnapshot;
|
|
use App\Models\BaselineTenantAssignment;
|
|
use App\Models\OperationRun;
|
|
use App\Support\Baselines\BaselineCompareReasonCode;
|
|
use App\Support\Baselines\BaselineCompareStats;
|
|
use App\Support\OperationRunOutcome;
|
|
use App\Support\OperationRunStatus;
|
|
use App\Support\OperationRunType;
|
|
use Filament\Facades\Filament;
|
|
|
|
it('shows a clear why-no-findings explanation when the last run had zero drift', function (): void {
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
$this->actingAs($user);
|
|
|
|
$tenant->makeCurrent();
|
|
Filament::setTenant($tenant, true);
|
|
|
|
$profile = BaselineProfile::factory()->active()->create([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
]);
|
|
|
|
$snapshot = BaselineSnapshot::factory()->create([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'baseline_profile_id' => (int) $profile->getKey(),
|
|
]);
|
|
|
|
$profile->update(['active_snapshot_id' => (int) $snapshot->getKey()]);
|
|
|
|
BaselineTenantAssignment::factory()->create([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'baseline_profile_id' => (int) $profile->getKey(),
|
|
]);
|
|
|
|
OperationRun::factory()->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'type' => OperationRunType::BaselineCompare->value,
|
|
'status' => OperationRunStatus::Completed->value,
|
|
'outcome' => OperationRunOutcome::Succeeded->value,
|
|
'completed_at' => now(),
|
|
'context' => [
|
|
'baseline_profile_id' => (int) $profile->getKey(),
|
|
'baseline_snapshot_id' => (int) $snapshot->getKey(),
|
|
'baseline_compare' => [
|
|
'reason_code' => BaselineCompareReasonCode::NoDriftDetected->value,
|
|
'coverage' => [
|
|
'effective_types' => ['deviceConfiguration'],
|
|
'covered_types' => ['deviceConfiguration'],
|
|
'uncovered_types' => [],
|
|
'proof' => true,
|
|
],
|
|
'fidelity' => 'meta',
|
|
],
|
|
],
|
|
]);
|
|
|
|
$summary = BaselineCompareStats::forTenant($tenant)->summaryAssessment();
|
|
|
|
baselineCompareLandingLivewire($tenant)
|
|
->assertSee($summary->headline)
|
|
->assertSee('Aligned');
|
|
});
|
|
|
|
it('shows explicit missing-detail fallback when evidence gaps were counted without recorded subject rows', function (): void {
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
$this->actingAs($user);
|
|
|
|
$tenant->makeCurrent();
|
|
Filament::setTenant($tenant, true);
|
|
|
|
$profile = BaselineProfile::factory()->active()->create([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
]);
|
|
|
|
$snapshot = BaselineSnapshot::factory()->create([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'baseline_profile_id' => (int) $profile->getKey(),
|
|
]);
|
|
|
|
$profile->update(['active_snapshot_id' => (int) $snapshot->getKey()]);
|
|
|
|
BaselineTenantAssignment::factory()->create([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'baseline_profile_id' => (int) $profile->getKey(),
|
|
]);
|
|
|
|
OperationRun::factory()->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'type' => OperationRunType::BaselineCompare->value,
|
|
'status' => OperationRunStatus::Completed->value,
|
|
'outcome' => OperationRunOutcome::PartiallySucceeded->value,
|
|
'completed_at' => now(),
|
|
'context' => [
|
|
'baseline_profile_id' => (int) $profile->getKey(),
|
|
'baseline_snapshot_id' => (int) $snapshot->getKey(),
|
|
'baseline_compare' => [
|
|
'reason_code' => BaselineCompareReasonCode::EvidenceCaptureIncomplete->value,
|
|
'coverage' => [
|
|
'effective_types' => ['deviceConfiguration'],
|
|
'covered_types' => ['deviceConfiguration'],
|
|
'uncovered_types' => [],
|
|
'proof' => true,
|
|
],
|
|
'fidelity' => 'meta',
|
|
'evidence_gaps' => [
|
|
'count' => 2,
|
|
'by_reason' => [
|
|
'missing_local_evidence' => 2,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
]);
|
|
|
|
baselineCompareLandingLivewire($tenant)
|
|
->assertSee('Evidence gap details')
|
|
->assertSee('Detailed rows were not recorded for this run')
|
|
->assertSee('Baseline compare evidence');
|
|
});
|
|
|
|
it('does not imply missing detail when the latest run has no evidence gaps', function (): void {
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
$this->actingAs($user);
|
|
|
|
$tenant->makeCurrent();
|
|
Filament::setTenant($tenant, true);
|
|
|
|
$profile = BaselineProfile::factory()->active()->create([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
]);
|
|
|
|
$snapshot = BaselineSnapshot::factory()->create([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'baseline_profile_id' => (int) $profile->getKey(),
|
|
]);
|
|
|
|
$profile->update(['active_snapshot_id' => (int) $snapshot->getKey()]);
|
|
|
|
BaselineTenantAssignment::factory()->create([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'baseline_profile_id' => (int) $profile->getKey(),
|
|
]);
|
|
|
|
OperationRun::factory()->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'type' => OperationRunType::BaselineCompare->value,
|
|
'status' => OperationRunStatus::Completed->value,
|
|
'outcome' => OperationRunOutcome::Succeeded->value,
|
|
'completed_at' => now(),
|
|
'context' => [
|
|
'baseline_profile_id' => (int) $profile->getKey(),
|
|
'baseline_snapshot_id' => (int) $snapshot->getKey(),
|
|
'baseline_compare' => [
|
|
'reason_code' => BaselineCompareReasonCode::NoDriftDetected->value,
|
|
'coverage' => [
|
|
'effective_types' => ['deviceConfiguration'],
|
|
'covered_types' => ['deviceConfiguration'],
|
|
'uncovered_types' => [],
|
|
'proof' => true,
|
|
],
|
|
'fidelity' => 'meta',
|
|
'evidence_gaps' => [
|
|
'count' => 0,
|
|
'by_reason' => [],
|
|
'subjects' => [],
|
|
],
|
|
],
|
|
],
|
|
]);
|
|
|
|
baselineCompareLandingLivewire($tenant)
|
|
->assertDontSee('Evidence gap details')
|
|
->assertSee('Baseline compare evidence');
|
|
});
|
|
|
|
it('includes strategy diagnostics in the landing evidence payload when strategy-owned compare processing fails', function (): void {
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
$this->actingAs($user);
|
|
|
|
$tenant->makeCurrent();
|
|
Filament::setTenant($tenant, true);
|
|
|
|
$profile = BaselineProfile::factory()->active()->create([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
]);
|
|
|
|
$snapshot = BaselineSnapshot::factory()->create([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'baseline_profile_id' => (int) $profile->getKey(),
|
|
]);
|
|
|
|
$profile->update(['active_snapshot_id' => (int) $snapshot->getKey()]);
|
|
|
|
BaselineTenantAssignment::factory()->create([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'baseline_profile_id' => (int) $profile->getKey(),
|
|
]);
|
|
|
|
OperationRun::factory()->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'type' => OperationRunType::BaselineCompare->value,
|
|
'status' => OperationRunStatus::Completed->value,
|
|
'outcome' => OperationRunOutcome::PartiallySucceeded->value,
|
|
'completed_at' => now(),
|
|
'context' => [
|
|
'baseline_profile_id' => (int) $profile->getKey(),
|
|
'baseline_snapshot_id' => (int) $snapshot->getKey(),
|
|
'baseline_compare' => [
|
|
'reason_code' => BaselineCompareReasonCode::StrategyFailed->value,
|
|
'coverage' => [
|
|
'effective_types' => ['deviceConfiguration'],
|
|
'covered_types' => ['deviceConfiguration'],
|
|
'uncovered_types' => [],
|
|
'proof' => true,
|
|
],
|
|
'fidelity' => 'meta',
|
|
'strategy' => [
|
|
'key' => 'intune_policy',
|
|
'selection_state' => 'supported',
|
|
'operator_reason' => 'Compare strategy resolved successfully.',
|
|
'execution_diagnostics' => [
|
|
'failed' => true,
|
|
'exception_class' => RuntimeException::class,
|
|
],
|
|
'state_counts' => [
|
|
'failed' => 1,
|
|
],
|
|
],
|
|
'evidence_gaps' => [
|
|
'count' => 1,
|
|
'by_reason' => [
|
|
'compare_failed' => 1,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
]);
|
|
|
|
$stats = BaselineCompareStats::forTenant($tenant);
|
|
|
|
expect($stats->baselineCompareDiagnostics)
|
|
->toHaveKey('strategy')
|
|
->and(data_get($stats->baselineCompareDiagnostics, 'strategy.key'))->toBe('intune_policy')
|
|
->and(data_get($stats->baselineCompareDiagnostics, 'strategy.execution_diagnostics.exception_class'))->toBe(RuntimeException::class);
|
|
|
|
baselineCompareLandingLivewire($tenant)
|
|
->assertSee('Baseline compare evidence')
|
|
->assertSee('Support diagnostics remain available after the operator summary and searchable detail.')
|
|
->assertDontSee('intune_policy')
|
|
->assertDontSee('RuntimeException');
|
|
});
|