feat(browser-matrix): Cross-Browser-Befunde + Browser-Default-Einordnung (Phase 4)
- browser_cross_finding: deterministische Sicht ueber die Matrix (keine 2. Engine, kein LLM). Findet Inkonsistenzen ZWISCHEN Browsern (Cookies vor Consent / Ablehnen nicht universell respektiert / Banner-Links fehlend) und ordnet ein: Safari-ITP / Brave-Shields / Firefox-ETP maskieren Verstoesse clientseitig → strenge Engine "sauber" ist KEIN Compliance-Beleg, massgeblich sind die nachgiebigen (Chrome/Edge). Coverage-Hinweis fuer nicht verfuegbare Browser. Je Befund Titel/Detail/Severity/affected/Massnahme. - snapshot_check_routes: cross_findings frisch in run + GET (nicht persistiert). - BrowserBehaviorView: "Cross-Browser-Befunde"-Block ueber der Tabelle. - Tests: test_browser_cross_finding (6). Offen (Folge-Task): Borlabs-Consent-Historie-Live-Erkennung (braucht consent-tester-Storage-Scan). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -22,7 +22,11 @@ type Row = {
|
||||
profile_id: string; label: string; engine?: string; is_mobile?: boolean
|
||||
score?: number; verbal?: string; summary?: Summary | null; error?: string
|
||||
}
|
||||
type Matrix = { browser_matrix?: Row[]; aggregate?: Record<string, unknown>; url?: string; scanned_at?: string }
|
||||
type CrossFinding = { title: string; detail?: string; severity: string; affected?: string[]; measure?: string }
|
||||
type Matrix = {
|
||||
browser_matrix?: Row[]; aggregate?: Record<string, unknown>
|
||||
url?: string; scanned_at?: string; cross_findings?: CrossFinding[]
|
||||
}
|
||||
|
||||
const sevCls = (s: string) => {
|
||||
const u = (s || '').toUpperCase()
|
||||
@@ -119,6 +123,30 @@ export function BrowserBehaviorView({ snapshotId }: { snapshotId: string }) {
|
||||
</div>
|
||||
{error && <div className="text-sm text-red-600">{error}</div>}
|
||||
|
||||
{/* Cross-Browser-Befunde — der Mehrwert ggü. Einzel-Browser-Scan */}
|
||||
{(matrix.cross_findings?.length ?? 0) > 0 && (
|
||||
<div className="space-y-2">
|
||||
<h3 className="text-sm font-semibold text-gray-900">Cross-Browser-Befunde</h3>
|
||||
{matrix.cross_findings!.map((f, i) => (
|
||||
<div key={i} className="border border-gray-200 rounded-xl p-3 space-y-1">
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<span className={`text-[10px] px-1.5 py-0.5 rounded uppercase ${sevCls(f.severity)}`}>{f.severity}</span>
|
||||
<span className="text-sm font-medium text-gray-900">{f.title}</span>
|
||||
</div>
|
||||
{f.detail && <p className="text-sm text-gray-600">{f.detail}</p>}
|
||||
{(f.affected?.length ?? 0) > 0 && (
|
||||
<div className="flex gap-1 flex-wrap">
|
||||
{f.affected!.map((a, j) => (
|
||||
<span key={j} className="text-[10px] px-1.5 py-0.5 rounded bg-gray-100 text-gray-600">{a}</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{f.measure && <p className="text-sm text-gray-700"><span className="text-gray-400">Maßnahme: </span>{f.measure}</p>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="overflow-x-auto border border-gray-200 rounded-xl">
|
||||
<table className="w-full text-sm">
|
||||
<thead className="bg-gray-50 text-gray-500 text-xs">
|
||||
|
||||
Reference in New Issue
Block a user