Assessor_2.0/tests/domain/policy-analysis-overview.te...

232 lines
10 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import {
buildPolicyAnalysisOverview,
type BuildPolicyAnalysisOverviewInput
} from '../../src/domain/policy-analysis-overview';
const timestamp = '2026-08-04T15:00:00.000Z';
function syntheticInput(): BuildPolicyAnalysisOverviewInput {
return {
projectId: 'synthetic-project',
generatedAt: timestamp,
profiles: [{
version: 1, id: 'profile-1', projectId: 'synthetic-project', name: 'Synthetic Windows',
revision: 1, createdAt: timestamp,
contexts: [{
version: 1, id: 'context-1', kind: 'operating-system', productFamily: 'Windows Server',
productVersion: '2025', role: 'Member Server', scope: 'computer'
}]
}],
identityAnalyses: [{
run: {
version: 1, id: 'identity-run-1', projectId: 'synthetic-project', artifactId: 'artifact-1',
sourceProcessingRunId: 'processing-1', analyzer: { id: 'gpo-policy-identity-analysis', version: '1' },
identityResolver: { id: 'resolver', version: '1' }, status: 'partial', observationCount: 1,
resolvedCount: 0, diagnosticCodes: ['gpo-policy-identity-analysis-partial'],
startedAt: timestamp, completedAt: timestamp
},
resolutions: [{
version: 1, id: 'resolution-1', projectId: 'synthetic-project', analysisRunId: 'identity-run-1',
sourceProcessingRunId: 'processing-1', backupInstanceId: 'backup-1', observationId: 'observation-1',
resolution: { version: 1, status: 'unresolved', reasonCode: 'gpo-policy-identity-unsupported-observation' }
}]
}],
aggregations: [{
version: 1,
run: {
version: 1, id: 'aggregation-1', projectId: 'synthetic-project', environmentProfileId: 'profile-1',
sourceAnalysisRunIds: ['identity-run-1'], snapshotId: 'snapshot-1',
aggregator: { id: 'gpo-policy-snapshot-aggregation', version: '1.0.0' }, status: 'partial',
stateCount: 1, conflictCount: 1, unresolvedIdentityCount: 1, reviewHintCount: 1,
permitsFindingGeneration: false, diagnosticCodes: ['policy-snapshot-incomplete'],
startedAt: timestamp, completedAt: timestamp
},
snapshot: {
version: 1, id: 'snapshot-1', projectId: 'synthetic-project',
domain: { version: 1, dnsName: 'synthetic.invalid', evidence: 'backup-metadata' },
instanceIds: ['backup-1'], status: 'indeterminate', completeness: 'selected-subset',
permitsSetAbsenceConclusions: false, diagnosticCodes: [], createdAt: timestamp
},
states: [{
version: 1, id: 'state-1', aggregationRunId: 'aggregation-1',
identity: { version: 1, id: 'identity-1' }, deliveryMechanism: 'registry-policy',
status: 'conflicted', values: [{ kind: 'registry', type: 'REG_DWORD', value: 1 }],
observationIds: ['observation-1'], backupInstanceIds: ['backup-1'], applicableContextIds: ['context-1'],
ordering: 'cross-gpo-conflict', targeting: 'none', completeness: 'complete', effectiveState: 'unknown',
diagnosticCodes: ['policy-snapshot-customer-conflict']
}],
reviewHints: [{
version: 1, id: 'hint-1', code: 'policy-targeting-unknown', identityId: 'identity-1',
observationIds: ['observation-1'], backupInstanceIds: ['backup-1']
}]
}],
evaluations: [{
version: 1,
run: {
version: 1, id: 'evaluation-1', projectId: 'synthetic-project', aggregationRunId: 'aggregation-1',
environmentProfileId: 'profile-1', baselineAnalysisIds: ['baseline-analysis-1'],
evaluator: { id: 'policy-baseline-evaluation', version: '1.1.0' },
comparatorCatalog: { id: 'policy-comparator-catalog', version: '1.1.0' },
dependencyRules: { id: 'policy-dependency-rules', version: '1.1.0' },
riskRules: { id: 'policy-risk-rules', version: '1.1.0' },
ruleCatalog: { version: 1, id: 'rules', catalog: { id: 'rules', version: '1' }, status: 'released', rules: [] },
status: 'partial', resultCount: 2, matchCount: 0, deviationCount: 1, notApplicableCount: 0,
reviewCount: 1, projectedFindingCount: 0, diagnosticCodes: ['policy-evaluation-partial'],
startedAt: timestamp, completedAt: timestamp
},
results: [{
version: 1, id: 'evaluation-result-review', evaluationRunId: 'evaluation-1', aggregationStateId: 'state-1',
identity: { version: 1, id: 'identity-1' }, classification: 'review_required',
comparator: { version: 1, comparator: { kind: 'equality' }, relation: 'incomparable', diagnosticCodes: [] },
baselineState: 'catalog-gap', contextIds: ['context-1'], ruleIds: [], dependencyRuleIds: [], riskRuleIds: [],
observationIds: ['observation-1'], backupInstanceIds: ['backup-1'], baselineAnalysisIds: [], baselineSettingIds: [],
findingEligibility: 'ineligible', effectiveState: 'unknown', diagnosticCodes: ['policy-evaluation-baseline-missing']
}],
evidence: []
}],
findingRuns: [{
version: 1,
run: {
version: 1, id: 'finding-run-1', projectId: 'synthetic-project', evaluationRunId: 'evaluation-1',
factory: { id: 'policy-finding-factory', version: '1.0.0' }, status: 'partial', eligibleResultCount: 2,
findingCount: 1, rejectedResultCount: 1, startedAt: timestamp, completedAt: timestamp
},
definitions: [], occurrences: [{} as never],
rejections: [{ version: 1, evaluationResultId: 'evaluation-result-rejected', diagnosticCodes: ['policy-finding-evidence-incomplete'] }]
}]
} as unknown as BuildPolicyAnalysisOverviewInput;
}
describe('policy analysis overview', () => {
it('keeps confirmed findings separate from deviations and all review-only evidence', () => {
const overview = buildPolicyAnalysisOverview(syntheticInput());
expect(overview.summary.confirmedDeviations).toBe(1);
expect(overview.summary.policyFindings).toBe(1);
expect(overview.summary.conflicts).toBe(1);
expect(overview.summary.unresolvedIdentities).toBe(1);
expect(overview.summary.catalogGaps).toBe(1);
expect(overview.summary.partialRuns).toBe(4);
expect(overview.current.summary).toEqual(overview.summary);
expect(overview.current.evaluationRunIds).toEqual(['evaluation-1']);
expect(overview.current.findingRunIds).toEqual(['finding-run-1']);
expect(overview.reviewItems.map(item => item.category)).toEqual(expect.arrayContaining([
'conflict', 'unresolved-identity', 'catalog-gap', 'partial-analysis',
'targeting-unknown', 'incomplete-evidence'
]));
expect(overview.evaluations[0]).toMatchObject({ findingCount: 1, rejectedFindingCount: 1, reviewCount: 1 });
});
it('returns an empty, deterministic project view without inventing findings', () => {
const overview = buildPolicyAnalysisOverview({
projectId: 'empty-project', generatedAt: timestamp,
identityAnalyses: [], profiles: [], aggregations: [], evaluations: [], findingRuns: []
});
expect(overview).toMatchObject({
version: 1, projectId: 'empty-project', generatedAt: timestamp,
summary: { policyFindings: 0, reviewItems: 0, conflicts: 0, partialRuns: 0 },
current: {
version: 1,
summary: { policyFindings: 0, reviewItems: 0, conflicts: 0, partialRuns: 0 },
evaluationRunIds: [], findingRunIds: [], reviewItems: []
},
evaluations: [], reviewItems: []
});
});
it('keeps superseded processing chains in history but excludes them from the current snapshot', () => {
const input = syntheticInput();
const currentTimestamp = '2026-08-05T15:00:00.000Z';
input.identityAnalyses.push({
run: {
...input.identityAnalyses[0].run,
id: 'identity-run-2',
sourceProcessingRunId: 'processing-2',
supersedesAnalysisRunId: 'identity-run-1',
status: 'complete',
resolvedCount: 1,
diagnosticCodes: [],
startedAt: currentTimestamp,
completedAt: currentTimestamp
},
resolutions: []
});
input.aggregations.push({
...input.aggregations[0],
run: {
...input.aggregations[0].run,
id: 'aggregation-2',
sourceAnalysisRunIds: ['identity-run-2'],
snapshotId: 'snapshot-2',
status: 'complete',
conflictCount: 0,
unresolvedIdentityCount: 0,
reviewHintCount: 0,
diagnosticCodes: [],
startedAt: currentTimestamp,
completedAt: currentTimestamp
},
snapshot: {
...input.aggregations[0].snapshot,
id: 'snapshot-2',
status: 'consistent',
completeness: 'complete'
},
states: [],
reviewHints: []
});
input.evaluations.push({
...input.evaluations[0],
run: {
...input.evaluations[0].run,
id: 'evaluation-2',
aggregationRunId: 'aggregation-2',
status: 'complete',
matchCount: 3,
deviationCount: 2,
reviewCount: 0,
diagnosticCodes: [],
startedAt: currentTimestamp,
completedAt: currentTimestamp
},
results: [],
evidence: []
});
input.findingRuns.push({
...input.findingRuns[0],
run: {
...input.findingRuns[0].run,
id: 'finding-run-2',
evaluationRunId: 'evaluation-2',
status: 'complete',
eligibleResultCount: 2,
findingCount: 2,
rejectedResultCount: 0,
startedAt: currentTimestamp,
completedAt: currentTimestamp
},
occurrences: [{}, {}] as never[],
rejections: []
});
const overview = buildPolicyAnalysisOverview(input);
expect(overview.summary).toMatchObject({
identityAnalysisRuns: 2, aggregationRuns: 2, evaluationRuns: 2, findingRuns: 2,
confirmedDeviations: 3, policyFindings: 3
});
expect(overview.current.summary).toMatchObject({
identityAnalysisRuns: 1, aggregationRuns: 1, evaluationRuns: 1, findingRuns: 1,
configuredMatches: 3, confirmedDeviations: 2, policyFindings: 2,
reviewItems: 0, conflicts: 0, unresolvedIdentities: 0, partialRuns: 0
});
expect(overview.current.evaluationRunIds).toEqual(['evaluation-2']);
expect(overview.current.findingRunIds).toEqual(['finding-run-2']);
expect(overview.current.reviewItems).toEqual([]);
expect(overview.reviewItems.length).toBeGreaterThan(0);
expect(overview.actions.evaluate.map(action => action.aggregationRunId)).toEqual(['aggregation-2']);
expect(overview.actions.createFindings.map(action => action.evaluationRunId)).toEqual(['evaluation-2']);
});
});