146 lines
5.3 KiB
TypeScript
146 lines
5.3 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import type { StoredGpoBackupInstance, StoredGpoPolicyAnalysis } from '../../src/domain/gpo-analysis-persistence';
|
|
import type { ImportArtifact, ImportProcessingRun } from '../../src/domain/ingestion-persistence';
|
|
import {
|
|
createCurrentPolicyObservationUnifiedResults,
|
|
deriveUnifiedResultFacets,
|
|
queryUnifiedResultItems
|
|
} from '../../src/domain/unified-result';
|
|
|
|
const timestamp = '2026-09-03T12:00:00.000Z';
|
|
const artifact: ImportArtifact = {
|
|
version: 1,
|
|
id: 'artifact-gpo-synthetic',
|
|
projectId: 'project-gpo-synthetic',
|
|
assessmentId: 'assessment-gpo-synthetic',
|
|
kind: 'source-file',
|
|
relativePath: 'synthetic-gpo.zip',
|
|
sha256: 'a'.repeat(64),
|
|
sizeBytes: 100,
|
|
sensitivity: 'secret',
|
|
parseStatus: 'partial',
|
|
storage: { kind: 'not-retained', reason: 'synthetic' },
|
|
createdAt: timestamp
|
|
};
|
|
const processing: ImportProcessingRun = {
|
|
version: 1,
|
|
id: 'processing-gpo-synthetic',
|
|
projectId: artifact.projectId,
|
|
artifactId: artifact.id,
|
|
status: 'partial',
|
|
processors: [{ kind: 'artifact-parser', id: 'synthetic-gpo-parser', version: '1.0.0' }],
|
|
diagnosticCodes: [],
|
|
startedAt: timestamp,
|
|
completedAt: timestamp
|
|
};
|
|
const backup: StoredGpoBackupInstance = {
|
|
version: 1,
|
|
id: 'stored-backup-gpo-synthetic',
|
|
projectId: artifact.projectId,
|
|
artifactId: artifact.id,
|
|
processingRunId: processing.id,
|
|
createdAt: timestamp,
|
|
instance: {
|
|
version: 1,
|
|
id: 'backup-gpo-synthetic',
|
|
projectId: artifact.projectId,
|
|
sourceArtifactId: artifact.id,
|
|
identity: { status: 'unresolved', reasonCode: 'synthetic' },
|
|
domain: { status: 'unknown' },
|
|
collection: { status: 'unknown' },
|
|
backupSet: { scope: 'selected-gpos', evidence: 'user-selection' },
|
|
metadataStatus: 'partial',
|
|
sections: { computer: 'present', user: 'unknown' },
|
|
inventory: {
|
|
version: 1,
|
|
status: 'partial',
|
|
diagnosticCodes: [],
|
|
entries: [{
|
|
version: 1,
|
|
artifactId: 'entry-gpo-synthetic',
|
|
relativePath: 'DomainSysvol/GPO/Machine/Microsoft/Windows NT/SecEdit/GptTmpl.inf',
|
|
role: 'security-template',
|
|
scope: 'computer',
|
|
disposition: 'supported',
|
|
secretIndicatorStatus: 'not-detected'
|
|
}]
|
|
},
|
|
policyObservations: [{
|
|
version: 1,
|
|
id: 'observation-gpo-synthetic',
|
|
backupInstanceId: 'backup-gpo-synthetic',
|
|
sourceArtifactId: artifact.id,
|
|
artifactId: 'entry-gpo-synthetic',
|
|
sourcePath: 'DomainSysvol/GPO/Machine/Microsoft/Windows NT/SecEdit/GptTmpl.inf',
|
|
sourceSha256: 'b'.repeat(64),
|
|
scope: 'computer',
|
|
deliveryMechanism: 'security-template',
|
|
parser: { id: 'security-template-parser', version: '1.0.0' },
|
|
reducer: { id: 'security-template-reducer', version: '1.0.0' },
|
|
identity: { status: 'unresolved', namespace: 'security-template', section: 'System Access', key: 'MinimumPasswordLength' },
|
|
state: 'configured',
|
|
values: [{ kind: 'scalar', raw: '14' }],
|
|
sourceLines: [3],
|
|
effectiveState: 'unknown',
|
|
diagnosticCodes: []
|
|
}],
|
|
discoveredAt: timestamp
|
|
}
|
|
};
|
|
const analysis: StoredGpoPolicyAnalysis = {
|
|
run: {
|
|
version: 1,
|
|
id: 'analysis-gpo-synthetic',
|
|
projectId: artifact.projectId,
|
|
artifactId: artifact.id,
|
|
sourceProcessingRunId: processing.id,
|
|
analyzer: { id: 'gpo-policy-identity-analysis', version: '1.0.0' },
|
|
identityResolver: { id: 'synthetic-resolver', version: '1.0.0' },
|
|
status: 'partial',
|
|
observationCount: 1,
|
|
resolvedCount: 0,
|
|
diagnosticCodes: ['identity-review-required'],
|
|
startedAt: timestamp,
|
|
completedAt: timestamp
|
|
},
|
|
resolutions: [{
|
|
version: 1,
|
|
id: 'resolution-gpo-synthetic',
|
|
projectId: artifact.projectId,
|
|
analysisRunId: 'analysis-gpo-synthetic',
|
|
sourceProcessingRunId: processing.id,
|
|
backupInstanceId: 'backup-gpo-synthetic',
|
|
observationId: 'observation-gpo-synthetic',
|
|
resolution: { version: 1, status: 'unresolved', reasonCode: 'identity-resolver-unsupported-security-template' }
|
|
}]
|
|
};
|
|
|
|
describe('GPO observations in the unified result read model', () => {
|
|
it('keeps raw policy evidence visible in its assessment without claiming a deviation', () => {
|
|
const results = createCurrentPolicyObservationUnifiedResults([artifact], [processing], [backup], [analysis]);
|
|
expect(results).toHaveLength(1);
|
|
expect(results[0]).toMatchObject({
|
|
resultProjectionId: 'policy-observation:observation-gpo-synthetic',
|
|
sourceKind: 'policy-observation',
|
|
assessmentId: artifact.assessmentId,
|
|
sourceTool: 'group-policy',
|
|
title: 'System Access · MinimumPasswordLength',
|
|
resultType: 'informational',
|
|
isDeviation: false,
|
|
policyIdentityStatus: 'unresolved',
|
|
policyValues: [{ kind: 'scalar', raw: '14' }]
|
|
});
|
|
|
|
expect(queryUnifiedResultItems(results, {
|
|
projectId: artifact.projectId,
|
|
scanRunIds: ['scanner-run-in-same-timeslot'],
|
|
assessmentIds: [artifact.assessmentId!],
|
|
deviation: true
|
|
}).total).toBe(1);
|
|
expect(queryUnifiedResultItems(results, { assessmentIds: ['another-assessment'] }).total).toBe(0);
|
|
expect(deriveUnifiedResultFacets(results, { assessmentIds: [artifact.assessmentId!] })
|
|
.facets.find(facet => facet.id === 'sourceKind')?.values)
|
|
.toContainEqual({ value: 'policy-observation', label: 'policy-observation', count: 1 });
|
|
});
|
|
});
|