import { describe, expect, it } from 'vitest'; import { comparePolicyValues } from '../../src/evaluation/policy-comparator'; import type { GpoPolicyValue } from '../../src/domain/gpo-policy'; const integer = (value: number): GpoPolicyValue => ({ kind: 'registry-policy', operation: 'set-value', key: 'Software\\Policies\\Synthetic', valueName: 'Mode', typeCode: 4, data: { kind: 'uint32', value } }); describe('typed policy comparators', () => { it('compares exact typed values', () => { expect(comparePolicyValues(integer(2), integer(2), { kind: 'equality' }).relation).toBe('match'); expect(comparePolicyValues(integer(1), integer(2), { kind: 'equality' }).relation).toBe('different'); }); it('retains supported Registry.pol state operations as comparable requirements', () => { const instruction = (operation: 'delete-value' | 'delete-all-values' | 'create-key'): GpoPolicyValue => ({ kind: 'registry-policy', operation, key: 'Software\\Policies\\Synthetic', ...(operation === 'delete-value' ? { valueName: 'Mode' } : {}), ...(operation === 'create-key' ? { typeCode: 0 as const, data: { kind: 'none' as const } } : {}) }); for (const operation of ['delete-value', 'delete-all-values', 'create-key'] as const) { expect(comparePolicyValues(instruction(operation), instruction(operation), { kind: 'equality' })) .toMatchObject({ relation: 'match', diagnosticCodes: [] }); } expect(comparePolicyValues(integer(1), instruction('delete-value'), { kind: 'equality' }).relation).toBe('different'); }); it('treats an explicitly empty typed string as a value', () => { const empty: GpoPolicyValue = { kind: 'registry-policy', operation: 'set-value', key: 'Software\\Policies\\Synthetic', valueName: 'Hosts', typeCode: 2, data: { kind: 'string', value: '' } }; expect(comparePolicyValues(empty, empty, { kind: 'equality' })).toMatchObject({ relation: 'match', baseline: { kind: 'text', value: '' } }); }); it('compares registry values parsed from security templates with their type intact', () => { const baseline = { kind: 'registry', typeCode: 4, rawData: '1' } as const; expect(comparePolicyValues(baseline, baseline, { kind: 'equality' })).toMatchObject({ relation: 'match', baseline: { kind: 'text', value: '4,1' } }); expect(comparePolicyValues( { kind: 'registry', typeCode: 4, rawData: '0' }, baseline, { kind: 'equality' } ).relation).toBe('different'); }); it('orders minimum and maximum requirements', () => { expect(comparePolicyValues(integer(3), integer(2), { kind: 'minimum' }).relation).toBe('stronger'); expect(comparePolicyValues(integer(3), integer(2), { kind: 'maximum' }).relation).toBe('weaker'); }); it('orders explicit enum catalogs only', () => { const low = { kind: 'scalar', raw: 'low' } as const; const high = { kind: 'scalar', raw: 'high' } as const; expect(comparePolicyValues(high, low, { kind: 'enum', orderedValues: ['low', 'medium', 'high'], direction: 'higher-is-stronger' }).relation).toBe('stronger'); }); it('compares bitmasks, sets and audit flags with explicit semantics', () => { expect(comparePolicyValues(integer(3), integer(1), { kind: 'bitmask', mode: 'contains-baseline' }).relation).toBe('stronger'); expect(comparePolicyValues( { kind: 'principal-set', principals: ['A', 'B'] }, { kind: 'principal-set', principals: ['A'] }, { kind: 'set', mode: 'superset' } ).relation).toBe('stronger'); expect(comparePolicyValues( { kind: 'audit-flags', code: 3, success: true, failure: true }, { kind: 'audit-flags', code: 1, success: true, failure: false }, { kind: 'audit-flags', mode: 'contains-baseline' } ).relation).toBe('stronger'); }); it('never coerces unsupported values into a comparison', () => { expect(comparePolicyValues( { kind: 'service-preference', serviceName: 'Synthetic', serviceAction: 'start', startupType: 'automatic', passwordAttributePresent: false }, integer(1), { kind: 'equality' } )).toMatchObject({ relation: 'incomparable', diagnosticCodes: ['policy-comparator-value-unsupported'] }); }); });