17 KiB
Umsetzungsauftrag: Report A (Management) und Report B (Technical)
Hinweis 2026-09-30: Historischer Auftrag. Die hier genannten Report-Dateien liegen seit der Verschiebung ohne Logikaenderung in
src/reporting/(siehedocs/REPORT_STRATEGY.md, Report Engine boundary).
Adressat: Codex. Dieser Auftrag ist verbindlich und abschließend formuliert.
Wo dieser Auftrag schweigt, gelten AGENTS.md, docs/REPORT_STRATEGY.md,
docs/SCORING_MODEL.md und .claude/skills/assessor-ui/SKILL.md unverändert
weiter. Bei einem Widerspruch zwischen diesem Auftrag und einer dieser Quellen:
anhalten und den Widerspruch melden, nicht eigenmächtig auflösen.
Plan-Zuordnung: Die Artefakte A–D sind in docs/REPORT_STRATEGY.md als
Deliverable ohne zugewiesene Plan-Phase festgehalten. Dieser Auftrag setzt A und
B um und ändert die Strategie inhaltlich nicht.
0. Ausgangszustand im Code (verifiziert)
| Baustein | Zustand |
|---|---|
src/domain/report-projection.ts |
vorhanden, REPORT_PROJECTION_VERSION = '1.0.0', getestet |
src/exports/management-overview-report.ts |
vorhanden, buildManagementOverviewHtml, Renderer-Version '1.0.0', getestet |
Produktiver Aufrufer von buildReportProjection |
existiert nicht — nur Tests |
Produktiver Aufrufer von buildManagementOverviewHtml |
existiert nicht — nur Tests |
| Report B (Technical) | existiert nicht |
Security-Domain-Zuordnung über UnifiedResultProjection |
existiert nicht (Katalog arbeitet auf FindingRecord) |
| Framework-Referenzen (MITRE ATT&CK / D3FEND) in der Unified-Projektion | nicht enthalten (nur targetRole === 'category' wird übernommen) |
Die beiden vorhandenen Bausteine sind korrekt und werden nicht neu geschrieben, sondern additiv erweitert.
1. Lieferumfang
Acht Arbeitspakete, in dieser Reihenfolge. Jedes Paket ist einzeln lauffähig, getestet und wird einzeln committet.
AP1 — Security-Domain-Zuordnung für UnifiedResultProjection
Datei: src/features/dashboard/security-domains.ts (erweitern, nicht ersetzen)
Neue Funktion:
export function securityDomainIdForUnifiedResult(result: UnifiedResultProjection): string
Bindende Semantik:
- Es gilt derselbe
securityDomainCatalogin derselben Reihenfolge. Kein zweiter Katalog, keine zweite Regex-Menge, keine report-eigene Zuordnung. - Evidenztext ist:
title,descriptionsowiecategoryLabelaller Einträge ausresult.categories. - Die explizite GPO-Erkennung geht wie bisher der Regex-Prüfung vor: erfüllt,
wenn
result.sourceKindeiner von'policy-evaluation' | 'policy-observation'ist oder eincategoryLabelexaktGPO/GPOslautet (case-insensitiv). - Kein Treffer ⇒
unclassifiedSecurityDomain.id.
Akzeptanzkriterium (Pflichttest): Für einen synthetischen Fall, der sowohl
als FindingRecord als auch als UnifiedResultProjection gebaut wird, liefern
securityDomainIdForRecord und securityDomainIdForUnifiedResult dieselbe
Domain — für alle acht Katalogeinträge, für den GPO-Sonderfall und für
unclassified. Grund: Client-Info-Drilldown und Reports müssen dieselben
Datensatzidentitäten auswählen (AGENTS.md, Abschnitt UI Work filter context).
AP2 — Framework-Referenzen in der Unified-Projektion sichtbar machen
Datei: src/domain/unified-result.ts
Neu:
export interface UnifiedResultFrameworkReference {
namespace: string; // Tool-ID der Quelle
value: string; // normalizedValue der Mapping-Eintragung, unverändert
sourceFieldKey?: string; // sourceFieldKeys[0], falls vorhanden
sourceLabel?: string; // Original-Spaltenüberschrift, falls vorhanden
}
und additiv auf UnifiedResultProjection:
frameworkReferences: UnifiedResultFrameworkReference[];
Befüllung analog zu scannerResultCategories, aber aus den Mappings mit
targetRole === 'framework-reference'. Leere Werte werden verworfen, alle
übrigen unverändert und unnormalisiert übernommen.
Bindende Randbedingungen:
- Die Ableitung erfolgt zur Projektionszeit aus bereits persistierten
fieldMappings. Es wird keine neue Spalte, Tabelle oder Migration angelegt und kein Parsing geändert. - Damit ist dies presentation-only über bereits gespeicherte Fakten:
kein neuer Processing-Manifest-Eintrag, keine Reimport-Markierung
(
docs/REIMPORT_POLICY.md). - Sollte sich beim Umsetzen zeigen, dass eine Persistenzänderung nötig wäre: anhalten und melden, nicht persistieren.
Akzeptanzkriterium: Synthetische Occurrence mit zwei
framework-reference-Mappings und einem category-Mapping ⇒ zwei
frameworkReferences, eine category, keine Vermischung, Originalwerte identisch.
AP3 — Korrelationsmodul (Domain, plattformneutral)
Neue Datei: src/domain/report-correlation.ts
Konstante: export const REPORT_CORRELATION_VERSION = '1.0.0';
Kein Storage, keine Uhr, kein Netzwerk, keine Präsentationstypen. Drei Ergebnisse:
(a) Quellenkonvergenz je Security Domain
export interface ReportDomainConvergence {
domainId: string;
sources: Array<{ toolId: string; assessed: number; deviations: number }>;
sourceCount: number; // Quellen mit mindestens einer Abweichung
evidence: 'shared-framework-reference' | 'domain-only';
}
evidence ist 'shared-framework-reference' nur dann, wenn mindestens zwei
Quellen in dieser Domain eine exakt gleiche, nicht leere
frameworkReferences-Zeichenkette tragen. Andernfalls 'domain-only'.
(b) Maßnahmenbündel
export interface ReportRemediationBundle {
key: string; // die Framework-Referenz, unverändert
namespace: string;
members: string[]; // resultProjectionIds
toolIds: string[];
domainIds: string[];
}
Gebildet über identische frameworkReferences-Werte von Abweichungen. Bündel
mit weniger als zwei Mitgliedern entfallen. Sortierung: Mitgliederzahl absteigend,
danach key alphabetisch — stabil, damit Ausgaben reproduzierbar sind.
(c) GPO-Einzelquellen-Maßnahmen
export interface ReportSingleSourcePolicyAction {
policyEntryId: string;
backupInstanceId: string;
}
Genau die ReportPolicyEntry mit verdict === 'Fail', conflict === false,
duplicate === false und exakt einem Eintrag in backupInstanceIds.
Bindende Verbote für AP3:
- Keine Titel-, Wort-, Fuzzy- oder Ähnlichkeitsheuristik über Quellen hinweg.
- Kein quellenübergreifender Score, Rang oder normalisierter Schweregrad.
- Keine Aussage „gleicher Befund" — die Aussage lautet ausschließlich „dieselbe Domain" bzw. „dieselbe Framework-Referenz".
- Keine Aufwands-, Kosten- oder Quick-Win-Schätzung. Ein Bündel trägt eine Mitgliederzahl, keine Bewertung.
AP4 — Projektion erweitern
Datei: src/domain/report-projection.ts
Version: REPORT_PROJECTION_VERSION von '1.0.0' auf '1.1.0'.
Additiv auf ReportProjection:
convergence: ReportDomainConvergence[];
bundles: ReportRemediationBundle[];
singleSourcePolicyActions: ReportSingleSourcePolicyAction[];
Bestehende Felder, Typen und Semantiken bleiben unverändert. Die bestehenden
Zusicherungen in tests/domain/report-projection.test.ts müssen ohne Änderung
grün bleiben; neue Tests kommen hinzu.
AP5 — Report-Eingabe zusammenstellen
Neue Datei: src/features/reports/report-input-assembler.ts
export async function assembleReportProjectionInput(
repository: AssessorRepository,
scope: { projectId: string; assessmentId?: string; generatedAt: string }
): Promise<ReportProjectionInput>
Quellen, ausschließlich:
- Ergebnisse:
repository.queryUnifiedResultsüber den Scope. domainOf:securityDomainIdForUnifiedResultaus AP1.priorityBases:reportPriorityBases(...)über die registrierten Profile.scoreSources/overallScore: die vorhandene Scoring-Schicht (src/domain/security-scoring.ts,src/features/dashboard/dashboard-security-score.ts). Keine eigene Score-Arithmetik.environment: normalisierte Fakten aus dem Environment-Snapshot. Fehlende Fakten bleiben absent und werden nie zu0.policyEntries/policyScopeLimited: aus der Evaluations- und Aggregationsschicht mit dem autoritativen, hochgerollten Verdict. Kein Verdict wird hier neu abgeleitet.reviews,diagnostics,provenance: aus den vorhandenen Repository-Pfaden.delta: nur, wenn ein gespeicherter Timeslot-Vergleich existiert. Es wird keine Referenzlauf-Auswahl und keine Paarung im Export gebildet.
Die Zusammenstellung läuft nur beim Export, nie beim Laden eines Workspace.
AP6 — Management-Renderer erweitern
Datei: src/exports/management-overview-report.ts
Version: MANAGEMENT_OVERVIEW_RENDERER_VERSION auf '1.1.0'.
Bestehende Abschnitte bleiben unverändert. Zwei neue Abschnitte:
- „Konvergenz der Quellen" — direkt nach
Security Domains. Je Domain: Anzahl unabhängiger Quellen mit Abweichungen, die Quellen namentlich, und eine sichtbare Unterscheidung zwischen belegter Konvergenz (shared-framework-reference) und thematischer Nähe (domain-only). Letztere trägt im Fließtext ausdrücklich den Hinweis auf Validierungsbedarf. - „Maßnahmenbündel" — direkt nach
Priority Findings. Die Bündel aus AP3(b) mit Referenz und Mitgliederzahl sowie die Anzahl der Einzelquellen-GPO- Maßnahmen aus AP3(c). Keine Aufwands- oder Nutzenaussage.
Der Abschnitt „Abdeckung und Lücken" wird vor „Priority Findings" gezogen und
zeigt zusätzlich je Quelle den Anteil not_run an der Gesamtzahl. Begründung:
Die Aussagegrenze muss vor der Priorisierung stehen.
Unverändert bindend: keine Registry-Keys, SIDs, Evidenzpfade, Parser- oder Manifest-Versionen in Report A.
AP7 — Report B (Technical)
Neue Datei: src/exports/technical-report.ts
Konstante: export const TECHNICAL_REPORT_RENDERER_VERSION = '1.0.0';
Signatur: export function buildTechnicalReportHtml(projection: ReportProjection): string
Abschnitte in dieser Reihenfolge, gemäß docs/REPORT_STRATEGY.md Report B:
- Scope und Provenance — Importe, Processing-, Analyzer- und Manifest-Versionen, Reimport-Status, Aggregations- und Evaluations-Run-IDs.
- Ergebnisinventar — Totals je Status, Severity, Domain und Tool, inklusive der score-neutralen Klassen; Passed erscheint als Zahl.
- Findings im Detail — gruppiert je Domain, innerhalb der Gruppe nach Severity.
- GPO-Policy-Register — alle sieben Verdicts vollständig; die score-neutralen sind am Ort der Anzeige als score-neutral gekennzeichnet.
- Konvergenz-Nachweis — die Paare aus AP3(a) mit ihrer Begründung, damit die Managementaussage aus AP6 nachprüfbar ist.
- Scope-Grenzen — ausdrücklich: kein RSoP, keine Aussage über wirksame
Endpoint-Konfiguration, GPO-Aussagen gelten für das importierte Backup-Set,
not_runist kein Pass. - Diagnostik — jede Beobachtung einmal, mit ihrem autoritativen Resolver-Grund.
- Anhang — vollständiger Ergebnisindex.
AP8 — Auslösung in der Anwendung
Zwei Aktionen in der bestehenden Oberfläche, die den Scope des aktuellen Projekts
bzw. Assessments verwenden und über src/exports/download-adapter.ts bzw.
src/exports/text-download.ts ausliefern. Keine neue Navigationsebene, keine neue
Shell, keine neuen Farb- oder Geometrie-Tokens. Es gilt
.claude/skills/assessor-ui/SKILL.md und der 20px-Panel-Inset.
2. Gestaltungsvorgaben für beide Dateien
- Sprache: Deutsch. Etablierte englische Fachbegriffe bleiben englisch
(
Deviation,Passed,Not configured,No baseline rule,Not comparable,Conflicts,Duplicates,Finding,Baseline,Score,Pass Rate, Security-Domain-Namen,Group Policy,Registry,Domain Controller). - Zahlen und Daten in deutscher Formatierung. Unbekanntes ist ein Geviertstrich,
niemals eine
0. - Getrennte Dateien. Report A enthält keine technischen Identifikatoren.
- Vollständig eigenständig: alle Styles inline, kein CDN, keine externe Font, kein Skript, kein Bild, kein Netzwerkzugriff beim Öffnen. Druckbar nach PDF ohne Layoutverlust.
- Typografie-Rollen, Donut-Geometrie, Tile- und Segment-Grammatik, Statusfarbregeln und Panel-Inset wie in der Anwendung. Statusfarbe nur in Akzentlinie, Marker, Arc oder Score-Node — nie als Flächenfüllung.
3. Harte Verbote
Nicht verhandelbar, auch dann nicht, wenn sie eine Lücke schließen würden:
- Kein quellenübergreifender, normalisierter Schweregrad, Rang oder Risiko-Score.
- Keine Aussage über wirksame Endpoint-Konfiguration aus einem Backup-Vergleich.
- Kein GPO-Verdict aus Vergleichsprosa, Historie, Baseline-Text, Guidance oder Evidenz — ausschließlich das autoritative hochgerollte Verdict plus die expliziten Conflict- und Duplicate-Flags.
- Ein selbst gemeldeter Review-Status wird nie zu einem gelösten Finding.
- Kein Delta ohne gespeicherten Vergleich; keine Referenzlauf-Auswahl im Export.
- Keine Score-Arithmetik, kein quellenspezifisches Parsing und kein Datenbankzugriff in einem Renderer.
Not configured,No baseline ruleundNot comparablebleiben score-neutral und erscheinen nie in den Priority Findings.- Keine Titel- oder Ähnlichkeitsheuristik als Beleg für „gleicher Befund".
- Keine echten Kunden-, Mandanten- oder Scan-Inhalte in Tests, Fixtures, Logs oder Commit-Nachrichten. Ausschließlich synthetische Fixtures.
4. Tests (Pflicht, synthetisch)
| Paket | Testdatei | Muss nachweisen |
|---|---|---|
| AP1 | tests/features/security-domain-unified.test.ts |
Gleichstand beider Klassifizierer über alle acht Domains, GPO-Sonderfall, unclassified |
| AP2 | tests/domain/unified-result-framework-references.test.ts |
Trennung category / framework-reference, Originalwerte unverändert, leere Werte verworfen |
| AP3 | tests/domain/report-correlation.test.ts |
shared-framework-reference nur bei exakter Übereinstimmung über mindestens zwei Quellen; Bündel unter zwei Mitgliedern entfallen; stabile Sortierung; GPO-Einzelquelle schließt Conflict, Duplicate und Mehrfach-Backups aus |
| AP4 | Erweiterung tests/domain/report-projection.test.ts |
Neue Felder vorhanden, bestehende Zusicherungen unverändert grün |
| AP5 | tests/features/report-input-assembler.test.ts |
Kein Verdict wird neu abgeleitet; fehlende Fakten bleiben absent; delta bleibt ohne gespeicherten Vergleich undefined; Zusammenstellung nur beim Export |
| AP6 | Erweiterung tests/exports/management-overview-report.test.ts |
Beide neuen Abschnitte vorhanden; domain-only trägt den Validierungshinweis; keine Registry-Keys, SIDs, Pfade oder Versionen im Output; Abdeckung steht vor Priority Findings |
| AP7 | tests/exports/technical-report.test.ts |
Alle acht Abschnitte; score-neutrale Verdicts als solche gekennzeichnet; Diagnostik je Beobachtung genau einmal; Scope-Grenzen-Abschnitt vorhanden |
| AP8 | Verhaltenstest der Auslösung | Export läuft nur auf Klick, nicht beim Laden des Workspace |
Zusätzlich für Report A und B je ein Selbstgenügsamkeits-Test: der erzeugte
HTML-String enthält kein <script, kein @import, keine externe Font-URL und
keine http- oder https-Ressourcenreferenz in src oder href.
5. Verifikation
npm test
npm run build
Beide müssen grün sein. Zusätzlich ist zu belegen, dass die bestehenden Tests zu
report-projection und management-overview-report ohne inhaltliche Änderung
weiter bestehen.
6. Nicht Teil dieses Auftrags
- Artefakt C (Arbeitsgrundlage) und Artefakt D (Delta Report). D ist mangels gespeicherter Vergleiche ohnehin nicht lieferbar.
- Framework-Abdeckung aus Maester-Tags (CISA SCuBA, CIS M365, Lizenzstufen).
Grund: Die Tag-Liste ist heute als eine opake Category-Zeichenkette
gespeichert, teils doppelt in zwei Serialisierungen. Eine belastbare Tag-Sicht
erfordert eine Profil- und Importer-Änderung mit Reimport-Pflicht nach
docs/REIMPORT_POLICY.mdund ist als eigener Auftrag zu beschließen. Bis dahin wird die Zeichenkette nicht geraten, gesplittet oder interpretiert. - Asset- und Angriffspfad-Korrelation.
assessor_canonical_assetsundassessor_asset_edgessind leer,affectedAssetist nur bei einer Quelle und dort nahezu konstant belegt. Ein Pfad-Graph wäre eine Erfindung. - Änderungen an Data Hub, Work, Pathfinder oder Client Info, die über die Auslösung aus AP8 hinausgehen.
7. Abschluss
Nach Abschluss aller Pakete ist docs/REPORT_STRATEGY.md im selben Change um
einen Change-Log-Eintrag zu ergänzen, der festhält: Report A auf Renderer-Version
1.1.0 erweitert, Report B in Version 1.0.0 implementiert, Projektion auf
1.1.0, Korrelationsmodul in 1.0.0 eingeführt, Reimport nicht erforderlich.
Kein Meilenstein wird als erfüllt markiert, bevor seine Akzeptanzkriterien
verifiziert sind.