import { createHash } from 'node:crypto';
import { describe, expect, it } from 'vitest';
import { parseGroupPolicyPreferenceXml, reduceGroupPolicyPreferences } from '../../server/gpo/group-policy-preference-parser';
import type { VerifiedZipFile } from '../../server/gpo/zip-inventory';
import { gpoPolicyObservationValidationErrors } from '../../src/domain/gpo-policy';
const rootClsid = '{2CFB484A-4E96-4b5d-A0B6-093D2F91E6AE}';
const itemClsid = '{AB6F0B67-341F-4e51-92F9-005FBFBA1A43}';
function verifiedFile(content: string): VerifiedZipFile {
const bytes = new TextEncoder().encode(content);
return {
entry: {
index: 1,
relativePath: 'synthetic/DomainSysvol/GPO/Machine/Preferences/Services/Services.xml',
kind: 'file',
compressionMethod: 8,
compressedBytes: bytes.byteLength,
uncompressedBytes: bytes.byteLength,
crc32: '00000000',
sha256: createHash('sha256').update(bytes).digest('hex')
},
bytes
};
}
const context = { backupInstanceId: 'backup-synthetic', sourceArtifactId: 'source-synthetic', artifactId: 'entry-synthetic' };
describe('Services preference CSE', () => {
it('preserves service, startup, failure and targeting semantics without retaining cPassword', () => {
const secret = 'synthetic-service-secret-never-return';
const document = parseGroupPolicyPreferenceXml(verifiedFile([
``,
` `,
` `,
' ',
' ',
''
].join('\r\n')), 'computer');
expect(document).toMatchObject({ preferenceType: 'services', status: 'complete', secretIndicatorStatus: 'present' });
expect(JSON.stringify(document)).not.toContain(secret);
const observations = reduceGroupPolicyPreferences(document, context);
expect(JSON.stringify(observations)).not.toContain(secret);
expect(observations).toEqual([expect.objectContaining({
identity: { status: 'unresolved', namespace: 'group-policy-preference', section: 'service', key: 'syntheticservice' },
state: 'instruction',
values: [{
kind: 'service-preference', serviceName: 'SyntheticService', serviceAction: 'restart-if-required',
startupType: 'automatic', timeout: 30, accountName: 'Synthetic\\Service', passwordAttributePresent: true,
interact: false, firstFailure: 'no-action', secondFailure: 'start', thirdFailure: 'restart',
resetFailCountDelay: 0, restartServiceDelay: 900000, restartComputerDelay: 120,
restartMessage: '', program: 'C:\\Synthetic\\recover.exe', args: '--safe', append: ''
}],
preference: expect.objectContaining({
cse: 'services', operation: 'configure', sequence: 0, removePolicy: true, applyOnce: true,
targeting: expect.objectContaining({ status: 'present', evaluability: 'unknown' })
}),
sourceLines: [2],
effectiveState: 'unknown',
diagnosticCodes: ['gpo-preference-targeting-unevaluated', 'gpo-secret-indicator-present']
})]);
});
it('defaults an omitted serviceAction to no-change as in the Microsoft example', () => {
const document = parseGroupPolicyPreferenceXml(verifiedFile(
``
), 'computer');
expect(document).toMatchObject({ status: 'complete', instructions: [{ value: { serviceAction: 'no-change', startupType: 'no-change' } }] });
});
it('fails closed for malformed supported enums, numbers and booleans', () => {
const document = parseGroupPolicyPreferenceXml(verifiedFile(
``
), 'computer');
expect(document).toMatchObject({ status: 'invalid', instructions: [] });
expect(document.diagnosticCodes).toEqual(expect.arrayContaining([
'gpo-preference-boolean-invalid', 'gpo-preference-service-enum-invalid', 'gpo-preference-service-number-invalid'
]));
expect(reduceGroupPolicyPreferences(document, context)).toEqual([]);
});
it('rejects malformed persisted Services observations at the runtime contract', () => {
const document = parseGroupPolicyPreferenceXml(verifiedFile(
``
), 'computer');
const observation = structuredClone(reduceGroupPolicyPreferences(document, context)[0]) as any;
observation.scope = 'user';
observation.preference.operation = 'update';
observation.values[0].passwordAttributePresent = 'yes';
expect(gpoPolicyObservationValidationErrors(observation)).toContain('Eine Service-Preference ist ungültig.');
});
it('keeps unknown supported-CSE properties and user scope partial without inventing semantics', () => {
const unknown = parseGroupPolicyPreferenceXml(verifiedFile(
``
), 'computer');
expect(unknown).toMatchObject({
status: 'partial', instructions: [], diagnosticCodes: ['gpo-preference-service-item-unsupported']
});
const userScoped = parseGroupPolicyPreferenceXml(verifiedFile(
``
), 'user');
expect(userScoped).toMatchObject({ status: 'partial' });
expect(userScoped.diagnosticCodes).toContain('gpo-preference-services-scope-unsupported');
expect(reduceGroupPolicyPreferences(userScoped, context)).toEqual([]);
});
});