193 lines
8.1 KiB
TypeScript
193 lines
8.1 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
POLICY_COMPARATOR_CATALOG,
|
|
POLICY_DEPENDENCY_RULESET,
|
|
POLICY_EVALUATION_ENGINE,
|
|
POLICY_RISK_RULESET,
|
|
type PolicyEvaluationResult,
|
|
type PolicyEvaluationRun,
|
|
type StoredPolicyEvaluation
|
|
} from '../../src/domain/policy-evaluation';
|
|
import {
|
|
createPolicyEvaluationUnifiedResult,
|
|
createPolicyUnifiedResult,
|
|
deriveUnifiedResultFacets,
|
|
queryUnifiedResultItems,
|
|
selectCurrentPolicyEvaluations
|
|
} from '../../src/domain/unified-result';
|
|
|
|
const timestamp = '2026-09-06T10:00:00.000Z';
|
|
|
|
function evaluationRun(id = 'evaluation-one', baselineAnalysisIds = ['baseline-analysis-one']): PolicyEvaluationRun {
|
|
return {
|
|
version: 1,
|
|
id,
|
|
projectId: 'project-synthetic',
|
|
aggregationRunId: 'aggregation-one',
|
|
environmentProfileId: 'environment-one',
|
|
baselineAnalysisIds,
|
|
evaluator: POLICY_EVALUATION_ENGINE,
|
|
comparatorCatalog: POLICY_COMPARATOR_CATALOG,
|
|
dependencyRules: POLICY_DEPENDENCY_RULESET,
|
|
riskRules: POLICY_RISK_RULESET,
|
|
ruleCatalog: {} as PolicyEvaluationRun['ruleCatalog'],
|
|
status: 'complete',
|
|
resultCount: 1,
|
|
matchCount: 0,
|
|
deviationCount: 1,
|
|
notApplicableCount: 0,
|
|
reviewCount: 0,
|
|
projectedFindingCount: 0,
|
|
diagnosticCodes: [],
|
|
startedAt: timestamp,
|
|
completedAt: timestamp
|
|
};
|
|
}
|
|
|
|
function evaluationResult(
|
|
classification: PolicyEvaluationResult['classification'] = 'confirmed_configured_deviation'
|
|
): PolicyEvaluationResult {
|
|
return {
|
|
version: 1,
|
|
id: `result-${classification}`,
|
|
evaluationRunId: 'evaluation-one',
|
|
aggregationStateId: 'state-one',
|
|
baselineAnalysisId: 'baseline-analysis-one',
|
|
baselineId: 'baseline-one',
|
|
baselineLabel: 'Synthetic Windows baseline',
|
|
customerState: 'configured',
|
|
identity: {
|
|
version: 1,
|
|
id: 'gpo-policy-identity-synthetic',
|
|
resolver: { id: 'gpo-technical-registry-target', version: '1.0.0' },
|
|
scope: 'computer',
|
|
target: {
|
|
kind: 'registry-value',
|
|
hive: 'HKEY_LOCAL_MACHINE',
|
|
key: 'Software\\Policies\\Synthetic',
|
|
valueName: 'Enabled'
|
|
},
|
|
admx: { status: 'not-found' }
|
|
},
|
|
classification,
|
|
comparator: {
|
|
version: 1,
|
|
comparator: { kind: 'equality' },
|
|
relation: classification === 'configured_match' ? 'match' : 'different',
|
|
actual: { kind: 'integer', value: '0' },
|
|
baseline: { kind: 'integer', value: '1' },
|
|
diagnosticCodes: []
|
|
},
|
|
baselineState: 'explicit-recommendation',
|
|
contextIds: [],
|
|
ruleIds: [],
|
|
dependencyRuleIds: [],
|
|
riskRuleIds: [],
|
|
observationIds: ['observation-one'],
|
|
backupInstanceIds: ['backup-one'],
|
|
baselineAnalysisIds: ['baseline-analysis-one'],
|
|
baselineSettingIds: ['baseline-setting-one'],
|
|
findingEligibility: 'ineligible',
|
|
effectiveState: 'unknown',
|
|
diagnosticCodes: []
|
|
};
|
|
}
|
|
|
|
describe('GPO unified Result DB projection', () => {
|
|
it('requires configured-value evidence even for previously materialized factory findings', () => {
|
|
const source = { definition: { id: 'definition', title: 'Synthetic setting', description: '', recommendation: '' },
|
|
occurrence: { id: 'occurrence', projectId: 'synthetic', classification: 'confirmed_configured_deviation', outcome: 'fail', createdAt: timestamp },
|
|
comparison: evaluationResult() } as unknown as Parameters<typeof createPolicyUnifiedResult>[0];
|
|
expect(createPolicyUnifiedResult(source)).toMatchObject({ outcomeNormalized: 'fail', isDeviation: true });
|
|
source.comparison!.customerState = 'missing';
|
|
source.comparison!.comparator.actual = undefined;
|
|
expect(createPolicyUnifiedResult(source)).toMatchObject({ outcomeNormalized: 'informational', isDeviation: false });
|
|
delete source.comparison;
|
|
expect(createPolicyUnifiedResult(source)).toMatchObject({ outcomeNormalized: 'not_evaluated', isDeviation: false });
|
|
});
|
|
|
|
it('does not treat missing recommendations or inconsistent customer evidence as misconfiguration', () => {
|
|
for (const patch of [
|
|
{ customerState: 'missing' },
|
|
{ customerState: 'unknown' },
|
|
{ baselineState: 'catalog-gap' },
|
|
{ diagnosticCodes: ['policy-evaluation-baseline-consensus-conflict'] },
|
|
]) {
|
|
const value = Object.assign(evaluationResult(), patch);
|
|
expect(createPolicyEvaluationUnifiedResult(evaluationRun(), value).isDeviation).toBe(false);
|
|
}
|
|
const value = evaluationResult();
|
|
value.comparator.actual = { kind: 'none' };
|
|
expect(createPolicyEvaluationUnifiedResult(evaluationRun(), value).isDeviation).toBe(false);
|
|
value.comparator.actual = { kind: 'integer', value: '0' };
|
|
value.comparator.baseline = { kind: 'text', value: '' };
|
|
expect(createPolicyEvaluationUnifiedResult(evaluationRun(), value).isDeviation).toBe(false);
|
|
});
|
|
|
|
it('keeps missing settings and review-only conflicts out of Deviation without hiding them', () => {
|
|
const missing = evaluationResult();
|
|
missing.customerState = 'missing';
|
|
missing.comparator.actual = undefined;
|
|
const before = JSON.stringify(missing);
|
|
const item = createPolicyEvaluationUnifiedResult(evaluationRun(), missing);
|
|
expect(item).toMatchObject({
|
|
outcomeNormalized: 'informational', isDeviation: false, policyCustomerState: 'missing',
|
|
policyClassification: 'not-configured'
|
|
});
|
|
expect(queryUnifiedResultItems([item], { deviation: true }).total).toBe(0);
|
|
expect(queryUnifiedResultItems([item], { deviation: false }).total).toBe(1);
|
|
expect(JSON.stringify(missing)).toBe(before);
|
|
const conflict = evaluationResult('review_required');
|
|
conflict.diagnosticCodes = ['policy-evaluation-baseline-consensus-conflict'];
|
|
expect(createPolicyEvaluationUnifiedResult(evaluationRun(), conflict)).toMatchObject({
|
|
outcomeNormalized: 'warning', isDeviation: false, policyClassification: 'conflict'
|
|
});
|
|
});
|
|
|
|
it('exposes a failed baseline comparison as a normal GPO deviation without inventing severity', () => {
|
|
const item = createPolicyEvaluationUnifiedResult(evaluationRun(), evaluationResult(), {
|
|
assessmentId: 'assessment-one',
|
|
importArtifactId: 'artifact-one',
|
|
snapshotId: 'snapshot-one'
|
|
});
|
|
|
|
expect(item).toMatchObject({
|
|
resultProjectionId: 'policy-evaluation-comparison:result-confirmed_configured_deviation',
|
|
sourceKind: 'policy-evaluation',
|
|
sourceTool: 'GPOs',
|
|
assessmentId: 'assessment-one',
|
|
outcomeNormalized: 'fail',
|
|
resultType: 'policy_deviation',
|
|
isDeviation: true,
|
|
severityNormalized: 'unknown',
|
|
policyBaselineLabel: 'Synthetic Windows baseline',
|
|
policyComparisonRelation: 'different',
|
|
policyCustomerState: 'configured',
|
|
policyClassification: 'misconfigured',
|
|
categories: [expect.objectContaining({ categoryLabel: 'GPOs', sourceTool: 'GPOs' })]
|
|
});
|
|
expect(queryUnifiedResultItems([item], { sourceTool: ['GPOs'], deviation: true }).total).toBe(1);
|
|
expect(deriveUnifiedResultFacets([item]).facets.find(facet => facet.id === 'sourceTool')?.values)
|
|
.toContainEqual({ value: 'GPOs', label: 'GPOs', count: 1 });
|
|
});
|
|
|
|
it('maps matching comparisons to Passed and selects the fullest current run per snapshot', () => {
|
|
const passed = createPolicyEvaluationUnifiedResult(evaluationRun(), evaluationResult('configured_match'));
|
|
expect(passed).toMatchObject({ outcomeNormalized: 'pass', isDeviation: false, policyClassification: 'match' });
|
|
|
|
const sparse = { version: 1, run: evaluationRun('evaluation-sparse', ['baseline-analysis-one']), results: [], evidence: [] } as StoredPolicyEvaluation;
|
|
const full = {
|
|
version: 1,
|
|
run: { ...evaluationRun('evaluation-full', ['baseline-analysis-one', 'baseline-analysis-two']), completedAt: '2026-09-06T09:00:00.000Z' },
|
|
results: [], evidence: []
|
|
} as StoredPolicyEvaluation;
|
|
const obsolete = {
|
|
version: 1,
|
|
run: { ...evaluationRun('evaluation-obsolete', ['a', 'b', 'c']), evaluator: { ...POLICY_EVALUATION_ENGINE, version: '0.0.0' } },
|
|
results: [], evidence: []
|
|
} as unknown as StoredPolicyEvaluation;
|
|
|
|
expect(selectCurrentPolicyEvaluations([sparse, full, obsolete]).map(record => record.run.id)).toEqual(['evaluation-full']);
|
|
});
|
|
});
|