import { createHash } from 'node:crypto'; import { describe, expect, it } from 'vitest'; import { parseAdvancedAuditCsv, reduceAdvancedAuditPolicy } from '../../server/gpo/advanced-audit-parser'; import type { VerifiedZipFile } from '../../server/gpo/zip-inventory'; const firstGuid = '0cce9210-69ae-11d9-bed3-505054503030'; const secondGuid = '0cce9211-69ae-11d9-bed3-505054503030'; function verifiedFile(content: string | Uint8Array): VerifiedZipFile { const bytes = typeof content === 'string' ? new TextEncoder().encode(content) : content; return { entry: { index: 1, relativePath: 'synthetic/DomainSysvol/GPO/Machine/Microsoft/Windows NT/Audit/audit.csv', kind: 'file', compressionMethod: 8, compressedBytes: bytes.byteLength, uncompressedBytes: bytes.byteLength, crc32: '00000000', sha256: createHash('sha256').update(bytes).digest('hex') }, bytes }; } function context() { return { backupInstanceId: 'backup-synthetic', sourceArtifactId: 'source-synthetic', artifactId: 'entry-synthetic' }; } function csv(rows: string[]): string { return [ 'Machine Name,Policy Target,Subcategory,Subcategory GUID,Inclusion Setting,Exclusion Setting,Setting Value', ...rows ].join('\r\n'); } describe('Advanced Audit Policy parser and reducer', () => { it('uses technical subcategory GUIDs and numeric audit flags instead of display names', () => { const document = parseAdvancedAuditCsv(verifiedFile(csv([ `,System,"Localized, ignored name",{${firstGuid}},Success and Failure,,3`, `,System,Another ignored name,{${secondGuid}},Failure,,2` ])), 'computer'); expect(document).toMatchObject({ status: 'complete', scope: 'computer' }); expect(reduceAdvancedAuditPolicy(document, context())).toEqual(expect.arrayContaining([ expect.objectContaining({ identity: expect.objectContaining({ key: firstGuid }), values: [{ kind: 'audit-flags', code: 3, success: true, failure: true }], sourceLines: [2], effectiveState: 'unknown' }), expect.objectContaining({ identity: expect.objectContaining({ key: secondGuid }), values: [{ kind: 'audit-flags', code: 2, success: false, failure: true }] }) ])); }); it('models differing duplicate GUID settings as a conflict', () => { const document = parseAdvancedAuditCsv(verifiedFile(csv([ `,System,ignored,{${firstGuid}},Success,,1`, `,System,ignored,{${firstGuid}},Failure,,2` ])), 'computer'); expect(reduceAdvancedAuditPolicy(document, context())).toEqual([ expect.objectContaining({ state: 'conflicted', values: [ { kind: 'audit-flags', code: 1, success: true, failure: false }, { kind: 'audit-flags', code: 2, success: false, failure: true } ], diagnosticCodes: ['gpo-advanced-audit-value-conflict'] }) ]); }); it('keeps non-system targets partial without interpreting per-user semantics', () => { const document = parseAdvancedAuditCsv(verifiedFile(csv([ `,SyntheticUser,ignored,{${firstGuid}},Success,,1`, `,System,ignored,{${secondGuid}},Success,,1` ])), 'computer'); expect(document).toMatchObject({ status: 'partial', diagnosticCodes: ['gpo-advanced-audit-target-unsupported'] }); expect(reduceAdvancedAuditPolicy(document, context())).toHaveLength(1); }); it('fails closed for malformed technical GUIDs, setting codes, rows and headers', () => { const invalidValue = parseAdvancedAuditCsv(verifiedFile(csv([ ',System,ignored,not-a-guid,Success,,7' ])), 'computer'); expect(invalidValue).toMatchObject({ status: 'invalid', instructions: [] }); expect(reduceAdvancedAuditPolicy(invalidValue, context())).toEqual([]); const missingHeader = parseAdvancedAuditCsv(verifiedFile('Policy Target,Subcategory GUID\r\nSystem,{0cce9210-69ae-11d9-bed3-505054503030}'), 'computer'); expect(missingHeader).toMatchObject({ status: 'invalid', diagnosticCodes: ['gpo-advanced-audit-required-column-missing'] }); }); it('rejects user-scope interpretation and accepts BOM-marked UTF-16LE', () => { const encoded = Buffer.from(`\ufeff${csv([`,System,ignored,{${firstGuid}},Success,,1`])}`, 'utf16le'); const document = parseAdvancedAuditCsv(verifiedFile(encoded), 'user'); expect(document).toMatchObject({ status: 'partial', diagnosticCodes: ['gpo-advanced-audit-scope-unsupported'] }); expect(reduceAdvancedAuditPolicy(document, context())).toEqual([]); }); });