import { describe, expect, it } from 'vitest'; import type { CanonicalOutcome, CanonicalSeverity } from '../../src/domain/canonical-model'; import type { UnifiedResultProjection } from '../../src/domain/unified-result'; import { REPORT_PROJECTION_VERSION, buildReportProjection, reportPriorityBases, type ReportDomain, type ReportPolicyEntry, type ReportProjectionInput } from '../../src/domain/report-projection'; import { toolProfileDefinitions } from '../../src/profiles/profile-definition-catalog'; const domains: ReportDomain[] = [ { id: 'identity', label: 'Identity & Account Hygiene' }, { id: 'hardening', label: 'System Hardening' }, { id: 'gpo', label: 'GPO & Baseline' } ]; let sequence = 0; function result(overrides: Partial & { severity?: CanonicalSeverity; outcome?: CanonicalOutcome; } = {}): UnifiedResultProjection { sequence += 1; const severity = overrides.severity ?? 'unknown'; const outcome = overrides.outcome ?? 'fail'; return { resultProjectionId: overrides.resultProjectionId ?? `synthetic-result-${sequence}`, sourceKind: 'scanner-finding', sourceResultId: `synthetic-source-${sequence}`, projectId: 'synthetic-project', collectionRunId: 'synthetic-collection-run', sourceTool: overrides.sourceTool ?? 'synthetic-tool', title: overrides.title ?? `Synthetic finding ${sequence}`, severityOriginal: severity, severityNormalized: severity, outcomeOriginal: outcome, outcomeNormalized: outcome, technicalExecutionState: outcome === 'not_run' ? 'not-run' : 'completed', resultType: 'control_result', isIoe: false, isDeviation: outcome === 'fail' || outcome === 'warning', lifecycleState: 'unknown', mappingConfidence: 1, reviewStatus: 'unreviewed', importedAt: '2026-09-18T08:00:00.000Z', createdAt: '2026-09-18T08:00:00.000Z', categories: [], ...overrides } as UnifiedResultProjection; } function input(overrides: Partial = {}): ReportProjectionInput { return { generatedAt: '2026-09-18T10:00:00.000Z', project: { id: 'synthetic-project', name: 'Synthetic' }, results: [], domains, domainOf: () => 'identity', ...overrides }; } describe('report projection', () => { it('carries its version and the caller supplied generation time', () => { const projection = buildReportProjection(input()); expect(projection.version).toBe(REPORT_PROJECTION_VERSION); expect(projection.generatedAt).toBe('2026-09-18T10:00:00.000Z'); }); it('orders within one source and never merges sources into one ranking', () => { const results = [ result({ sourceTool: 'alpha', severity: 'low', title: 'alpha-low' }), result({ sourceTool: 'alpha', severity: 'critical', title: 'alpha-critical' }), result({ sourceTool: 'beta', severity: 'medium', title: 'beta-medium' }) ]; const projection = buildReportProjection(input({ results, priorityBases: { alpha: { kind: 'severity' }, beta: { kind: 'severity' } } })); const [domain] = projection.priorities; expect(domain.domainId).toBe('identity'); expect(domain.sources.map(source => source.toolId)).toEqual(['alpha', 'beta']); expect(domain.sources[0].shown.map(ref => ref.title)).toEqual(['alpha-critical', 'alpha-low']); expect(domain.sources[1].shown.map(ref => ref.title)).toEqual(['beta-medium']); }); it('refuses a declared severity basis when the source delivers no severity', () => { const results = [ result({ sourceTool: 'cis-cat', severity: 'unknown' }), result({ sourceTool: 'cis-cat', severity: 'unknown' }) ]; const projection = buildReportProjection(input({ results, priorityBases: { 'cis-cat': { kind: 'severity' } } })); const [source] = projection.sourcePriorities; expect(source.declared.kind).toBe('severity'); expect(source.applied.kind).toBe('undeclared'); expect(source.severityCoverage).toBe(0); expect(source.issues).toContain('declared-severity-without-coverage'); expect(projection.priorities[0].sources[0].ranked).toBe(false); expect(projection.diagnostics.some(entry => entry.code === 'report-priority-declared-severity-without-coverage:cis-cat')).toBe(true); }); it('marks an undeclared source as unranked instead of inventing an order', () => { const projection = buildReportProjection(input({ results: [result({ sourceTool: 'undeclared-tool', severity: 'high' })] })); expect(projection.sourcePriorities[0].applied.kind).toBe('undeclared'); expect(projection.sourcePriorities[0].issues).toContain('basis-not-declared'); expect(projection.priorities[0].sources[0].ranked).toBe(false); expect(projection.findings[0].rankValue).toBeUndefined(); }); it('orders a numeric basis by its declared direction', () => { const results = [ result({ sourceTool: 'pingcastle', score: 5, title: 'five' }), result({ sourceTool: 'pingcastle', score: 40, title: 'forty' }) ]; const projection = buildReportProjection(input({ results, priorityBases: { pingcastle: { kind: 'numeric', property: 'points', scale: '0-50+', direction: 'higher-is-worse' } } })); expect(projection.priorities[0].sources[0].shown.map(ref => ref.title)).toEqual(['forty', 'five']); }); it('caps a domain block without losing the true total', () => { const results = Array.from({ length: 5 }, (_unused, index) => result({ sourceTool: 'alpha', severity: 'high', title: `item-${index}` })); const projection = buildReportProjection(input({ results, priorityBases: { alpha: { kind: 'severity' } }, priorityLimitPerDomain: 2 })); expect(projection.priorities[0].sources[0].shown).toHaveLength(2); expect(projection.priorities[0].sources[0].total).toBe(5); }); it('keeps not-run and not-applicable out of the assessed base', () => { const results = [ result({ outcome: 'fail' }), result({ outcome: 'pass' }), result({ outcome: 'not_run' }), result({ outcome: 'not_applicable' }), result({ outcome: 'execution_error' }) ]; const projection = buildReportProjection(input({ results })); expect(projection.coverage.total).toBe(5); expect(projection.coverage.assessed).toBe(2); expect(projection.coverage.notRun).toBe(1); expect(projection.coverage.notApplicable).toBe(1); expect(projection.coverage.executionErrors).toBe(1); expect(projection.domains.find(entry => entry.domainId === 'identity')?.passRate).toBe(0.5); }); it('leaves a pass rate absent rather than reporting zero when nothing was assessed', () => { const projection = buildReportProjection(input({ results: [result({ outcome: 'not_run' })] })); expect(projection.domains.find(entry => entry.domainId === 'identity')?.passRate).toBeUndefined(); }); it('keeps GPO equal-weight with its verdict counts and diagnostic flags separate', () => { const policyEntries: ReportPolicyEntry[] = [ { id: 'p1', verdict: 'Fail', conflict: false, duplicate: true, title: 'setting one', scope: 'computer', identity: 'MinimumPasswordLength', backupInstanceIds: ['b1', 'b2'] }, { id: 'p2', verdict: 'Not configured', conflict: false, duplicate: false, title: 'setting two', scope: 'computer', identity: 'SomeOtherSetting', backupInstanceIds: [] }, { id: 'p3', verdict: 'Fail', conflict: true, duplicate: false, title: 'setting three', scope: 'computer', identity: 'PasswordComplexity', backupInstanceIds: ['b1'] } ]; const projection = buildReportProjection(input({ policyEntries, policyScopeLimited: true })); expect(projection.gpo?.basis.kind).toBe('equal-weight'); expect(projection.gpo?.counts.Fail).toBe(2); expect(projection.gpo?.counts['Not configured']).toBe(1); expect(projection.gpo?.conflicts).toBe(1); expect(projection.gpo?.duplicates).toBe(1); expect(projection.gpo?.affectedSettings).toBe(2); expect(projection.gpo?.affectedBackups).toBe(2); expect(projection.gpo?.scopeLimited).toBe(true); }); it('omits the remediation section entirely when no reviews exist', () => { const projection = buildReportProjection(input({ results: [result()] })); expect(projection.remediation).toBeUndefined(); expect(projection.workItems).toEqual([]); }); it('curates work items through include and marks the summary as self reported', () => { const selected = result({ title: 'selected' }); const skipped = result({ title: 'skipped' }); const projection = buildReportProjection(input({ results: [selected, skipped], reviews: [ { resultProjectionId: selected.resultProjectionId, include: true, status: 'Actionable', priority: 'High', owner: 'team-ad', markers: ['quickwin'], riskAccepted: false }, { resultProjectionId: skipped.resultProjectionId, include: false, status: 'Open', priority: 'Medium', markers: [], riskAccepted: false } ] })); expect(projection.workItems.map(item => item.title)).toEqual(['selected']); expect(projection.remediation?.selfReported).toBe(true); expect(projection.remediation?.items).toBe(1); expect(projection.remediation?.withoutDue).toBe(1); expect(projection.remediation?.byStatus).toEqual({ Actionable: 1 }); }); it('never turns a self reported done status into a resolved finding', () => { const open = result({ outcome: 'fail', title: 'still failing' }); const projection = buildReportProjection(input({ results: [open], reviews: [{ resultProjectionId: open.resultProjectionId, include: true, status: 'Done', priority: 'High', markers: [], riskAccepted: false }] })); expect(projection.coverage.deviations).toBe(1); expect(projection.findings).toHaveLength(1); expect(projection.workItems[0].status).toBe('Done'); }); it('reads the stored comparison and derives no pairing of its own', () => { const open = result({ sourceTool: 'alpha', title: 'persisting' }); const projection = buildReportProjection(input({ results: [open], delta: { comparisonId: 'synthetic-comparison', contractVersion: '1.0.0', referenceRunId: 'run-reference', referenceObservedAt: '2026-06-01T00:00:00.000Z', currentRunId: 'run-current', currentObservedAt: '2026-09-01T00:00:00.000Z', entries: [ { resultProjectionId: open.resultProjectionId, toolId: 'alpha', state: 'confirmed-open', reasons: [] }, { resultProjectionId: 'gone', toolId: 'alpha', state: 'unverified-absent', reasons: ['check-not-run'] }, { resultProjectionId: 'fixed', toolId: 'beta', state: 'verified-remediated', reasons: ['fail-to-pass'] } ] } })); expect(projection.delta?.referenceRunId).toBe('run-reference'); expect(projection.delta?.currentRunId).toBe('run-current'); expect(projection.delta?.counts['unverified-absent']).toBe(1); expect(projection.delta?.counts['verified-remediated']).toBe(1); expect(projection.delta?.counts['confirmed-open']).toBe(1); expect(projection.delta?.perSource.map(entry => entry.toolId)).toEqual(['alpha', 'beta']); expect(projection.delta?.perSource[0].counts['unverified-absent']).toBe(1); expect(projection.delta?.entries[0].title).toBe('persisting'); }); it('has no delta at all without a stored comparison', () => { expect(buildReportProjection(input({ results: [result()] })).delta).toBeUndefined(); }); it('adopts the declared basis of every registered profile', () => { const bases = reportPriorityBases(toolProfileDefinitions); expect(bases['purple-knight']).toEqual({ kind: 'severity' }); expect(bases.maester).toEqual({ kind: 'severity' }); expect(bases.pingcastle).toMatchObject({ kind: 'numeric', direction: 'higher-is-worse' }); expect(bases['cis-cat'].kind).toBe('equal-weight'); expect(bases.generic.kind).toBe('equal-weight'); }); it('treats a declared unavailable basis as a decision, not a missing declaration', () => { const projection = buildReportProjection(input({ results: [result({ sourceTool: 'cis-cat', severity: 'unknown' })], priorityBases: reportPriorityBases(toolProfileDefinitions) })); const [source] = projection.sourcePriorities; expect(source.applied.kind).toBe('equal-weight'); expect(source.issues).toEqual([]); expect(projection.priorities[0].sources[0].ranked).toBe(false); expect(projection.diagnostics).toEqual([]); }); it('ranks a real PingCastle points declaration worst first', () => { const projection = buildReportProjection(input({ results: [ result({ sourceTool: 'pingcastle', score: 10, title: 'ten' }), result({ sourceTool: 'pingcastle', score: 35, title: 'thirtyfive' }) ], priorityBases: reportPriorityBases(toolProfileDefinitions) })); expect(projection.priorities[0].sources[0].shown.map(ref => ref.title)) .toEqual(['thirtyfive', 'ten']); }); });