import { describe, expect, it } from 'vitest'; import type { UnifiedResultProjection } from '../../src/domain/unified-result'; import type { ImportedDataset } from '../../src/domain/dataset'; import type { PolicyEvaluationResult, StoredPolicyEvaluation } from '../../src/domain/policy-evaluation'; import { makeSheet } from '../../src/importers/sheet-factory'; import { appendPolicyObservationsToDataset } from '../../src/features/project-import/policy-observations-to-dataset'; import { buildPolicyWorkResults, countPolicyWorkResults, policyMisconfigurationImpact } from '../../src/evaluation/policy-work-results'; import { genericProfile } from '../../src/profiles/generic/generic-profile'; import { outcomeForStatusValue, toolIdForRecord } from '../../src/importers/status-normalization'; function source(id: string, value = 1, patch: Partial = {}): UnifiedResultProjection { return { sourceKind: 'policy-observation', sourceResultId: id, resultProjectionId: 'policy-observation:' + id, projectId: 'synthetic', assessmentId: 'slot', title: 'Mode', importedAt: '2026-09-06T00:00:00Z', policyScope: 'computer', policyDeliveryMechanism: 'registry-policy', policyState: 'configured', policyIdentityStatus: 'resolved', policyIdentityKey: 'identity-mode', policyBackupInstanceId: 'backup-' + id, policyValues: [{ kind: 'registry-policy', key: 'Software\\Policies\\Synthetic', valueName: 'Mode', operation: 'set-value', typeCode: 4, data: { kind: 'uint32', value } }], ...patch } as UnifiedResultProjection; } function comparison(id: string, ids: string[], patch: Partial = {}): PolicyEvaluationResult { return { id, observationIds: ids, baselineId: 'ms-baseline', baselineLabel: 'Synthetic Microsoft Baseline', baselineState: 'explicit-recommendation', classification: 'configured_match', customerState: 'configured', comparator: { version: 1, comparator: { kind: 'equality' }, relation: 'match', actual: { kind: 'integer', value: '1' }, baseline: { kind: 'integer', value: '1' }, diagnosticCodes: [] }, identity: { id: 'identity-mode', scope: 'computer', target: { kind: 'registry-value', hive: 'HKEY_LOCAL_MACHINE', key: 'Software\\Policies\\Synthetic', valueName: 'Mode' } }, diagnosticCodes: [], ...patch } as PolicyEvaluationResult; } const run = (results: PolicyEvaluationResult[]) => ({ run: { completedAt: '2026-09-06T00:00:00Z' }, results }) as StoredPolicyEvaluation; const statuses = (sources: UnifiedResultProjection[], comparisons: PolicyEvaluationResult[] = []) => buildPolicyWorkResults(sources, [run(comparisons)]).map(result => result.status); describe('Policy Analyzer outcome contract in Work', () => { it('omits unevaluated drive maps and unsupported comparisons', () => { const drive = source('drive', 1, { policyDeliveryMechanism: 'group-policy-preference', policyIdentityStatus: 'unresolved' }); expect(appendPolicyObservationsToDataset(null, 'Synthetic', [drive])).toBeNull(); expect(statuses([drive, { ...drive, sourceResultId: 'drive2' }])).toEqual([]); expect(statuses([source('a')], [comparison('r', ['a'], { classification: 'review_required' })])).toEqual([]); expect(statuses([source('a')])).toEqual([]); }); it('requires an explicit nonempty baseline and retains explicit zero and empty principal sets', () => { const good = comparison('r', ['a']); for (const baseline of [undefined, { kind: 'none' }, { kind: 'text', value: '' }] as const) { expect(statuses([source('a')], [{ ...good, comparator: { ...good.comparator, baseline } }])).toEqual([]); } expect(statuses([source('a')], [{ ...good, baselineState: 'catalog-gap' }])).toEqual([]); expect(statuses([source('a')], [{ ...good, comparator: { ...good.comparator, baseline: { kind: 'integer', value: '0' } } }])).toEqual(['Pass']); expect(statuses([source('a')], [{ ...good, comparator: { ...good.comparator, baseline: { kind: 'string-set', values: [] } } }])).toEqual(['Pass']); }); it('shows one Pass/Fail per comparison with all sources and one Duplicate group', () => { const pass = comparison('pass', ['a', 'b']); const fail = comparison('fail', ['a', 'b'], { baselineLabel: 'Another baseline', classification: 'confirmed_configured_deviation', comparator: { ...pass.comparator, relation: 'different', baseline: { kind: 'integer', value: '2' } } }); const results = buildPolicyWorkResults([source('a'), source('b')], [run([pass, fail, pass])]); expect(countPolicyWorkResults(results)).toEqual({ Fail: 1, Pass: 1, Conflicts: 0, Duplicates: 1, 'Not configured': 0 }); expect(policyMisconfigurationImpact([...results, ...results])).toEqual({ settings: 1, backups: 2 }); expect(results.find(result => result.status === 'Pass')?.sources).toHaveLength(2); }); it('keeps baseline-only missing settings separate from Fail and Deviation', () => { const missing = comparison('missing', [], { classification: 'confirmed_configured_deviation', customerState: 'missing' }); missing.comparator = { ...missing.comparator, actual: undefined, relation: 'different' }; const dataset = appendPolicyObservationsToDataset(null, 'Synthetic', [], [run([missing])])!; const [headers, row] = dataset.sheets[0].rows; expect(row[headers.indexOf('Status')]).toBe('Not configured'); expect(row[headers.indexOf('Configured Value')]).toBe('Not configured'); const record = dataset.sheets[0].analysis.records[0]; expect(genericProfile.matchesStatus(record, 'deviation')).toBe(false); expect(genericProfile.matchesStatus(record, 'not-configured')).toBe(true); expect(genericProfile.matchesStatus(record, 'all')).toBe(true); expect(outcomeForStatusValue('group-policy', 'Not configured')).toBe('informational'); }); it('keeps only configured mismatches in Deviation even when other fields contain Fail or Open', () => { for (const status of ['Pass', 'Not configured', 'Conflicts', 'Duplicates']) { const sheet = makeSheet('GPOs', [['Category', 'Status', 'Description'], ['GPOs', status, 'Fail']], '', 'Synthetic'); expect(genericProfile.matchesStatus(sheet.analysis.records[0], 'deviation')).toBe(false); } const fail = makeSheet('GPOs', [['Category', 'Status', 'Configured Value'], ['GPOs', 'Fail', '0']], '', 'Synthetic'); expect(genericProfile.matchesStatus(fail.analysis.records[0], 'deviation')).toBe(true); }); it('classifies different values for one target as Conflicts without guessing a winning GPO', () => { expect(statuses([source('a', 0), source('b', 1)], [comparison('r', ['a', 'b'])])).toEqual(['Conflicts']); }); it('compares registry address case-insensitively while preserving value data and type', () => { const lower = source('b', 1, { policyValues: [{ kind: 'registry-policy', key: 'software\\policies\\synthetic', valueName: 'MODE', operation: 'set-value', typeCode: 4, data: { kind: 'uint32', value: 1 } }] }); expect(statuses([source('a'), lower])).toEqual(['Duplicates']); const text = source('b', 1, { policyValues: [{ kind: 'registry-policy', key: 'Software\\Policies\\Synthetic', valueName: 'Mode', operation: 'set-value', typeCode: 1, data: { kind: 'string', value: '1' } }] }); expect(statuses([source('a'), text])).toEqual(['Conflicts']); const expanded = { ...text, sourceResultId: 'c', policyValues: [{ ...(text.policyValues![0] as object), typeCode: 2 }] } as UnifiedResultProjection; expect(statuses([text, expanded])).toEqual(['Conflicts']); }); it('keeps distinct value names, user/computer scopes, and timeslots separate', () => { const otherName = source('b', 1, { policyValues: [{ kind: 'registry-policy', key: 'Software\\Policies\\Synthetic', valueName: 'Another', operation: 'set-value', typeCode: 4, data: { kind: 'uint32', value: 1 } }] }); expect(statuses([source('a'), otherName])).toEqual([]); expect(statuses([source('a'), source('b', 1, { policyScope: 'user' })])).toEqual([]); expect(statuses([source('a'), source('b', 1, { assessmentId: 'another-slot' })])).toEqual([]); expect(statuses([source('a')], [comparison('mixed', ['a', 'absent-source'])])).toEqual([]); }); it('deduplicates repeated read rows without counting baseline comparisons as duplicate customer settings', () => { const a = source('a'); expect(statuses([a, a])).toEqual([]); expect(statuses([a], [comparison('r1', ['a']), comparison('r2', ['a'])])).toEqual(['Pass', 'Pass']); }); it('surfaces explicitly conflicting baseline recommendations', () => { expect(statuses([source('a')], [comparison('r', ['a'], { classification: 'review_required', diagnosticCodes: ['policy-evaluation-baseline-consensus-conflict'] })])).toEqual(['Conflicts']); }); it('does not repeat stale aggregation conflicts when the source evidence proves identical values', () => { expect(statuses([source('a'), source('b')], [comparison('old', ['a', 'b'], { classification: 'review_required', customerState: 'conflicted' })])).toEqual(['Duplicates']); }); it('handles a 2300-GPO source set with one deterministic row per duplicate group', () => { const sources = Array.from({ length: 2300 }, (_, index) => source(String(index))); const result = buildPolicyWorkResults(sources, []); expect(result).toHaveLength(1); expect(result[0].status).toBe('Duplicates'); expect(result[0].sources).toHaveLength(2300); }); it('preserves scanner sheets and exposes GPO warning statuses in the project aggregate', () => { const aggregate = makeSheet('All Records', [['Source: Scan', 'Title', 'Status'], ['PurpleKnight ยท 2026-09-06', 'Synthetic scanner finding', 'Failed']], '', 'Synthetic', { isProjectSheet: true }); const scanner = makeSheet('Scanner', [['Title'], ['Synthetic']], '', 'Synthetic', { toolId: 'purple-knight' }); const dataset = { fileName: 'Synthetic', fileSize: 0, lastModified: 0, format: 'Project', rawText: '', sheets: [aggregate, scanner], profileId: 'generic' } as ImportedDataset; const result = appendPolicyObservationsToDataset(dataset, 'Synthetic', [source('a'), source('b')])!; expect(result.sheets).toHaveLength(3); expect(result.sheets[2]).toBe(scanner); const record = result.sheets[0].analysis.records.find(record => record.fields.some(field => field.value === 'Duplicates'))!; expect(toolIdForRecord(record, 'generic')).toBe('group-policy'); expect(outcomeForStatusValue('group-policy', 'Duplicates')).toBe('warning'); expect(outcomeForStatusValue('group-policy', 'Conflicts')).toBe('warning'); expect(appendPolicyObservationsToDataset(dataset, 'Synthetic', [source('a')])).toBe(dataset); }); });