diff --git a/docs/IMPLEMENTATION_PLAN.md b/docs/IMPLEMENTATION_PLAN.md index dc43263..847ad3d 100644 --- a/docs/IMPLEMENTATION_PLAN.md +++ b/docs/IMPLEMENTATION_PLAN.md @@ -4231,6 +4231,7 @@ Verifiziert 2026-09-08 (Phase 7/13B): GPO-Quellenkorrektur fuer Work und Client | 2026-10-06 | Phase 7: Data Hub Deviation/Passed now use the same assessed-percentage helper as Client Info; all six donuts state their population basis. 29 focused tests and synthetic Chrome Dark/Light checks passed; absolute counts, other population shares and assessment semantics retained. Client build, design and UI/API version checks passed. Nine out-of-scope report test failures, a report Local-only failure and report server type errors prevent full release verification; attempted 2.16.9 reverted to 2.16.8 pending successful production builds. | | 2026-10-06 | Phase 7: Client Info Deviations percentage now divides by Passed + Deviations and labels Of assessed checks; zero assessed shows a dash while preserving absolute zero. Permanent UI/click invariance tests in both themes and synthetic Chrome presentation verified; unchanged counts, verdicts, scores and other donuts. Patch 2.16.8: both builds and version contracts passed; full run 1,936 passed/15 skipped with one stale API-version assertion corrected and passed in the 43-test focused rerun; Local-only/design checks passed. | | 2026-10-06 | Phase 13B: GPO folder read diagnostics retain only safe error names, stages and counts, distinguish empty/denied/unreadable selections, preserve cancellation and wrap complete timeslot messages. 27 focused GPO UI tests and synthetic Chrome Dark/Light checks passed; both builds and version contracts verified for patch 2.16.7. Full run: 1,932 passed, 15 skipped, one general import timeout passed on separate rerun; Local-only/design checks passed. Customer-specific read failure remains unconfirmed; no customer path/data used, Phase 13B remains in progress. | +| 2026-10-02 | Phase 7: `08771d5` angepasst uebernommen; `c056c21` (CWE-Links, baut auf der ausgelassenen CVE-Anreicherung auf) ausgelassen, seine Scoring-Zeile fuer `securityToolId` folgt mit dem Result-DB-Werkzeugeintrag. `findingOutcomeMark` liefert die Outcome-Marke fuer Work-Karte und Finding-Reader-Kopf; Werkzeuge ohne Statusspalte erhalten sie aus `missingStatusOutcome` (Defender: `Warning`), alle anderen behalten ihr eigenes Statuswort. Die GPO-Diagnoseplaketten der Karte und die Vergleichs-Outcome-Ableitung des Readers bleiben unveraendert. Das Defender-Panel nutzt den Client-Info-Kopf (`Client`, `Assessment`, `Source`) und eine sechsspaltige Kennzahlzeile mit Container-Queries. Abweichend vom Original bleiben Kacheln, Sichten und Drilldowns auf den gemeinsamen Rollen `--tile-surface`, `--tile-border`, `--tile-radius`, `--text`, `--heading` und `--muted` statt `--client-info-*`, `border: 0` und `--btn-radius`, damit die verbindliche Kachelregel durchgehend gilt. Nicht im Browser geprueft, weil die lokale Datenbank keine Defender-Importe enthaelt. Keine API-, SQL- oder Persistenzaenderung. Verifikation: beide Typechecks, Gesamtlauf mit 1.893 bestandenen und 17 uebersprungenen Tests, Local-only-/Designpruefung und beide Produktionsbuilds erfolgreich. | | 2026-10-02 | Phase 13A: Aus `33d2019` nur die Dokumentation uebernommen. `docs/CANONICAL_MODEL.md` beschreibt `vulnerability_finding` als additive ASSESSOR-Erweiterung des externen `result_type`-Katalogs; der Kommentar an `CanonicalResultType` verweist darauf. Nicht uebernommen: die Backfill-Migration (frueher 023) samt Katalogeintrag und Schema-Assertions, weil die neu angelegte lokale Datenbank keine Defender-Occurrences enthaelt, sowie auf Nutzerentscheidung der lesende Outcome-Fallback in `unified-result.ts` mit seinem Test; neue Importe erhalten `warning` bereits ueber `missingStatusOutcome`. Keine Verhaltens-, API-, SQL- oder Persistenzaenderung. Verifikation: beide Typechecks, Gesamtlauf mit 1.890 bestandenen und 17 uebersprungenen Tests, Local-only-/Designpruefung und beide Produktionsbuilds erfolgreich. | | 2026-10-02 | Phasen 6/13A: `fe71246` uebernommen; `e048295` (NVD-CVE-Anreicherung) auf Nutzerentscheidung vorerst ausgelassen. Der Result-Contract kennt den Typ `vulnerability_finding`; Defender-Findings erhalten ihn. Ein Profil kann `missingStatusOutcome` deklarieren, Defender setzt `warning`, weil jede CVE-Zeile selbst der Befund ist. Das Defender-Profil steigt auf 1.1.0 mit Kompatibilitaetsschluessel `-v2` (semantic-breaking, Reimport erforderlich; die lokale Datenbank enthaelt keine Defender-Importe), 1.0.0 ist nicht mehr aktuell. Der Work-Filter `Deviation` aller Scanner nutzt statt der Regex-Liste `UNIVERSAL_DEVIATION_PATTERNS` nun `isDeviationRecord` und damit das kanonische Result-DB-Praedikat; die GPO-Statuslogik, der Statuscache und die uebrigen Statusfilter der Basis bleiben unveraendert davor. Alle bestehenden Work-, Filter- und Scannertests bestehen unveraendert; eine vollstaendige Gleichwertigkeit fuer jeden realen Statuswert ist damit nicht bewiesen. Migration `027_vulnerability_finding_result_type.sql` (frueher 022) erweitert nur den Check-Constraint und schreibt keine Occurrences um; ohne die ausgelassene CVE-Tabelle. Vor der Anwendung wurde das verifizierte Backup `backups/assessor-pre-027-20261002-123608.dump` erstellt. Verifikation: beide Typechecks, Gesamtlauf mit 1.890 bestandenen und 17 uebersprungenen Tests, Local-only-/Designpruefung und beide Produktionsbuilds erfolgreich. | | 2026-10-02 | Phasen 6/7/13A: `5fbbda2` uebernommen. Der Defender-Extractor erzeugt nun ein Finding je CVE statt je Device-mal-CVE und liefert `Affected Device Count` sowie die Tabelle `Affected Devices` (Device, Scanner, Site); das Profil bildet die Anzahl auf die Asset-Rolle ab, nutzt `Affected Devices` als Ergebnisabschnitt und vergleicht nur noch ueber die CVE. Der Finding Reader blendet das Rohfeld `Source Observations` fuer Defender aus, es bleibt als Provenienz im Datensatz. Nicht uebernommen: die Umbenennung der Asset-Zeile im Result-DB-Zeilendetail, weil die Disclosure-Policy `affectedAsset` fuer jede Zeile zurueckhaelt und eine Device-Anzahl dort nicht erscheinen soll. Die Finding-Identitaet aendert sich wie im Original ohne Profilversionssprung; die neu angelegte lokale Datenbank enthaelt keine Defender-Importe, der Versionssprung folgt mit `c7c716c`. Keine API-, SQL- oder Persistenzmigration. Verifikation: beide Typechecks, Gesamtlauf mit 1.883 bestandenen und 17 uebersprungenen Tests, Local-only-/Designpruefung und beide Produktionsbuilds erfolgreich. | diff --git a/src/components/FindingCard/FindingCard.tsx b/src/components/FindingCard/FindingCard.tsx index 767224d..2d4dc0f 100644 --- a/src/components/FindingCard/FindingCard.tsx +++ b/src/components/FindingCard/FindingCard.tsx @@ -2,8 +2,8 @@ import { memo } from 'react'; import { RelatedFindingRing, useRelatedFindings } from '../../features/related-findings/RelatedFindings'; import type { FindingRecord } from '../../domain/finding'; import { normalizeSeverity } from '../../profiles/purple-knight/presentation'; -import { outcomeForStatusValue, toolIdForRecord } from '../../importers/status-normalization'; -import { resultStatusFieldFor } from '../../features/linked-results/result-message'; +import { toolIdForRecord } from '../../importers/status-normalization'; +import { findingOutcomeMark, resultStatusFieldFor } from '../../features/linked-results/result-message'; import { policyDiagnosticBadges } from '../../profiles/group-policy/categories'; import { highlightText } from '../HighlightText/highlight-text'; @@ -26,9 +26,8 @@ function FindingCardComponent({ record, title, bookmarked, selected, toolId, sea const groupMarked = useRelatedFindings()?.selection?.group.recordIds.includes(record.id); const severityField = record.fields.find(field => /^(severity|criticality|priority)$/i.test(field.label) && field.value); const severity = normalizeSeverity(severityField?.value); - const statusField = findingCardStatus(record, toolId); + const outcomeMark = findingOutcomeMark(record, toolId); const resolvedToolId = toolIdForRecord(record, toolId); - const outcome = outcomeForStatusValue(resolvedToolId, statusField?.value); const diagnostics = policyDiagnosticBadges(record, resolvedToolId); return (
Microsoft Defender for IoT vulnerabilities{model.summaryRowCount.toLocaleString('en-US')} source asset rows{model.diagnostics.length.toLocaleString('en-US')} diagnostics
{model.summaryRowCount.toLocaleString('en-US')} source asset rows{model.diagnostics.length.toLocaleString('en-US')} diagnostics
diff --git a/src/features/finding-reader/FindingReader.tsx b/src/features/finding-reader/FindingReader.tsx index c1bfdc9..a4860e0 100644 --- a/src/features/finding-reader/FindingReader.tsx +++ b/src/features/finding-reader/FindingReader.tsx @@ -26,7 +26,7 @@ import { isFileReference } from '../../profiles/purple-knight/result-linker'; import { highlightText } from '../../components/HighlightText/highlight-text'; import { BookmarkIcon } from '../../components/BookmarkIcon'; import { TriangleIcon } from '../../components/TriangleIcon'; -import { resultSectionFields, resultStatusFieldFor } from '../linked-results/result-message'; +import { findingOutcomeMark, resultSectionFields, resultStatusFieldFor } from '../linked-results/result-message'; import { cisBenchmarkCategories } from '../../profiles/cis-cat/cis-benchmark-hierarchy'; import { cisCategoryRecordTitle } from '../../profiles/cis-cat/cis-benchmark-section-titles'; import { policyComparisonDisplayLines, policyValueName } from '../../profiles/group-policy/presentation'; @@ -428,6 +428,7 @@ export function FindingReader({ record, title, review: storedReview, previousPol const comparisonOutcome = statusField?.value ? outcomeForStatusValue(resolvedToolId, statusField.value) : 'unknown'; const problem = resolvedToolId === 'group-policy' && !policyReadiness ? policyProblemSummary(record) : undefined; const firstRead = resolvedToolId !== 'group-policy' ? findingFirstRead(record, resolvedToolId, linkedSheets, comparisonOutcome) : undefined; + const outcomeMark = findingOutcomeMark(record, toolId); const policyHeading = policyComparisonFields.map(field => policyValueName(field.value)).find(Boolean); // Nur echte Dateiverweise gehoeren in den Hinweis. Werkzeuge, die ihr // Ergebnis als Fliesstext oder Tabelle in dasselbe Feld schreiben, haetten @@ -456,7 +457,7 @@ export function FindingReader({ record, title, review: storedReview, previousPol