import { useCallback, useEffect, useState } from 'react'; import { AssessorApiClient } from '../../api/assessor-api-client'; import type { PolicyAnalysisOverview, PolicyAnalysisReviewCategory, PolicyAnalysisReviewItem } from '../../domain/policy-analysis-overview'; import { PolicyAnalysisActions } from './PolicyAnalysisActions'; import { PanelLoadingState } from '../../components/PanelLoadingState/PanelLoadingState'; import { queryAllUnifiedResults } from '../../exports/unified-result-jsonl'; import { currentPolicyEvaluationsForWork } from './load-canonical-project-workspace'; import { buildPolicyWorkResults, countPolicyWorkResults, policyMisconfigurationImpact, type PolicyWorkCounts } from '../../evaluation/policy-work-results'; const assessorApi = new AssessorApiClient(); const categoryLabels: Record = { conflict: 'Conflict', 'unresolved-identity': 'Unresolved setting', 'catalog-gap': 'Baseline mapping unavailable', 'parser-gap': 'Unsupported setting format', 'partial-analysis': 'Evaluation incomplete', 'targeting-unknown': 'Targeting not resolved', 'incomplete-evidence': 'Source evidence incomplete', other: 'Review required' }; function formatTimestamp(value: string): string { return new Intl.DateTimeFormat('en-US', { dateStyle: 'short', timeStyle: 'medium' }).format(new Date(value)); } function ReviewRow({ item }: { item: PolicyAnalysisReviewItem }) { return
{categoryLabels[item.category]} {item.observationCount} observation{item.observationCount === 1 ? '' : 's'} · {item.backupCount} GPO source{item.backupCount === 1 ? '' : 's'}
Source: {item.source} {item.identityId && Technical identity: {item.identityId}} Diagnostic{item.codes.length === 1 ? '' : 's'}: {item.codes.map(code => {code})}
; } export function PolicyAnalysisPanelView({ overview, counts, impact }: { overview: PolicyAnalysisOverview; counts?: PolicyWorkCounts; impact?: ReturnType }) { const visibleReviews = overview.current.reviewItems.slice(0, 100); const currentSummary = overview.current.summary; const profileById = new Map(overview.profiles.map(profile => [profile.id, profile])); const hasPipelineData = overview.summary.identityAnalysisRuns > 0 || overview.summary.aggregationRuns > 0 || overview.summary.evaluationRuns > 0 || overview.summary.findingRuns > 0; return
GPO Analysis

Baseline Evaluation

Backup settings are compared with the imported Microsoft Security Baselines. Effective application requires RSoP or GP Results.

{!hasPipelineData ?

No policy analysis runs yet

Imported GPO backups remain processing evidence until snapshot aggregation and baseline evaluation have run.

: <>

Processing

Analysis runs{currentSummary.identityAnalysisRuns}
Evaluation runs{currentSummary.evaluationRuns}
GPO backups with failing settings{impact?.backups ?? '–'}Inspect source-linked comparisons with the same-named filter in Work.

Policy verdicts

One verdict per technical policy setting.

Misconfigured{counts?.Fail ?? '–'}
Pass{counts?.Pass ?? '–'}
Not configured{counts?.['Not configured'] ?? '–'}
Review required{counts?.['Review required'] ?? '–'}
No baseline rule{counts?.['No baseline rule'] ?? '–'}Configured settings with no applicable Microsoft baseline recommendation. Score-neutral.
Not comparable{counts?.['Not comparable'] ?? '–'}Group Policy Preferences. No comparable technical policy setting. Score-neutral.

Diagnostic flags

May overlap with each other and with policy verdicts. Score-neutral.

Conflicts{counts?.Conflicts ?? '–'}Different customer values for one technical setting.
Duplicates{counts?.Duplicates ?? '–'}Identical values from multiple GPO sources.

Analysis gaps

Observation-level diagnostics. No score impact.

Unresolved identity{currentSummary.unresolvedIdentities}Observations that could not be mapped to one technical policy setting. Their settings appear in Work as Not comparable.
Comparison not supported{currentSummary.parserGaps}The retained value cannot yet be compared safely; the setting stays under Review required.
Technical details

Evaluation history

{overview.evaluations.length}
{!overview.evaluations.length ?

No baseline evaluation has been persisted yet.

:
{overview.evaluations.map(run =>
{profileById.get(run.environmentProfileId)?.name ?? 'Environment profile'} · {run.status === 'complete' ? 'complete' : run.status}{formatTimestamp(run.completedAt)}
{run.matchCount} matches{run.deviationCount} stored mismatches (including missing settings){run.notApplicableCount} not applicable{run.reviewCount} review required
{run.findingCount} confirmed finding{run.findingCount === 1 ? '' : 's'}{run.rejectedFindingCount > 0 && {run.rejectedFindingCount} factory rejection{run.rejectedFindingCount === 1 ? '' : 's'}}
)}
}

Current review queue

{overview.current.reviewItems.length}
{!visibleReviews.length ?

No conflicts or unresolved evidence in the persisted runs.

:
{visibleReviews.map(item => )}
} {overview.current.reviewItems.length > visibleReviews.length &&

Showing the first 100 deterministic review hints.

}
}
; } export function PolicyAnalysisPanel({ projectId }: { projectId: string }) { const [overview, setOverview] = useState(); const [counts, setCounts] = useState(); const [impact, setImpact] = useState>(); const [error, setError] = useState(); const [loading, setLoading] = useState(true); const load = useCallback(async () => { try { const [nextOverview, observations, evaluations] = await Promise.all([ assessorApi.getPolicyAnalysisOverview(projectId), queryAllUnifiedResults(query => assessorApi.queryUnifiedResults(query), { audience: 'internal-analysis', projectId, sourceKind: ['policy-observation'] }), assessorApi.listPolicyEvaluations(projectId) ]); setOverview(nextOverview); const currentEvaluationIds = new Set(nextOverview.current.evaluationRunIds); const workResults = buildPolicyWorkResults(observations, currentPolicyEvaluationsForWork(evaluations.records, new Set(observations.map(source => source.sourceResultId)), currentEvaluationIds)); setCounts(countPolicyWorkResults(workResults)); setImpact(policyMisconfigurationImpact(workResults)); setError(undefined); } catch (reason) { setCounts(undefined); setImpact(undefined); setError(reason instanceof Error ? reason.message : 'Policy analysis could not be loaded.'); } finally { setLoading(false); } }, [projectId]); useEffect(() => { void load(); const refresh = (event: Event) => { if (event instanceof CustomEvent && event.detail?.projectId && event.detail.projectId !== projectId) return; void load(); }; globalThis.addEventListener('assessor:gpo-changed', refresh); globalThis.addEventListener('focus', refresh); return () => { globalThis.removeEventListener('assessor:gpo-changed', refresh); globalThis.removeEventListener('focus', refresh); }; }, [load, projectId]); if (loading && !overview) return
; if (error && !overview) return
{error}
; return overview ? <> {error &&
Analysis could not be refreshed.
}
Processing controls { await load(); globalThis.dispatchEvent(new CustomEvent('assessor:gpo-changed', { detail: { projectId } })); }}/>
: null; }