feat(admin): Tab "Browser-Verhalten" — Per-Browser-Matrix + Screenshots (Phase 3)

- BrowserBehaviorView: laedt gespeicherte Matrix (GET), sonst "Browser-Test
  starten" (POST run, Live-Lauf). Per-Browser-Tabelle (Cookies vor Consent /
  nach Ablehnen / Ablehnen respektiert / Oberflaeche / Score), Engine-Detail
  mit Banner-Screenshot + Oberflaechen-Befunden, Mobil-Badge, "nicht
  verfuegbar"-Zeilen fuer fehlende Browser (arm64-Dev).
- Proxys browser-behavior (GET) + browser-behavior/run (POST, langer Timeout).
- page.tsx: Tab "Browser-Verhalten" (sichtbar sobald scanbare URL im Snapshot).
- consent-tester scan_matrix_summary: banner_findings je Engine im summary
  (Text/Severity/Norm) → Oberflaechen-Befunde im Tab.
- tsc strict clean; Vitest BrowserBehaviorView (2).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-06-12 23:15:06 +02:00
parent c7fde93061
commit 9587726936
6 changed files with 359 additions and 0 deletions
@@ -0,0 +1,33 @@
/**
* Browser-Verhaltens-Matrix — gespeichertes Ergebnis (kein Re-Crawl)
* GET /api/sdk/v1/agent/snapshots/{snapshotId}/browser-behavior
* → backend /api/compliance/agent/snapshots/{snapshotId}/browser-behavior
*
* `browser_matrix` ist null, solange der On-demand-Lauf nie ausgelöst wurde.
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL =
process.env.BACKEND_API_URL || process.env.BACKEND_URL ||
'http://backend-compliance:8002'
export async function GET(
_request: NextRequest,
{ params }: { params: Promise<{ snapshotId: string }> },
) {
const { snapshotId } = await params
try {
const response = await fetch(
`${BACKEND_URL}/api/compliance/agent/snapshots/${snapshotId}/browser-behavior`,
{ signal: AbortSignal.timeout(30_000) },
)
const data = await response.json()
return NextResponse.json(data, { status: response.status })
} catch {
return NextResponse.json(
{ browser_matrix: null, error: 'Browser-Matrix laden fehlgeschlagen' },
{ status: 503 },
)
}
}
@@ -0,0 +1,44 @@
/**
* Browser-Verhaltens-Matrix — On-demand LIVE-Lauf (Re-Crawl je Engine)
* POST /api/sdk/v1/agent/snapshots/{snapshotId}/browser-behavior/run
* → backend /api/compliance/agent/snapshots/{snapshotId}/browser-behavior/run
*
* Teuer (mehrere Browser × 3 Phasen) → langer Timeout. Persistenz passiert
* im Backend; die Antwort ist die frische Matrix.
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL =
process.env.BACKEND_API_URL || process.env.BACKEND_URL ||
'http://backend-compliance:8002'
// Vercel-only Hinweis; self-hosted ignoriert es — schadet nicht.
export const maxDuration = 400
export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ snapshotId: string }> },
) {
const { snapshotId } = await params
let body: unknown = {}
try { body = await request.json() } catch { body = {} }
try {
const response = await fetch(
`${BACKEND_URL}/api/compliance/agent/snapshots/${snapshotId}/browser-behavior/run`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body ?? {}),
signal: AbortSignal.timeout(380_000),
},
)
const data = await response.json()
return NextResponse.json(data, { status: response.status })
} catch (e) {
return NextResponse.json(
{ error: `Browser-Test fehlgeschlagen: ${String(e)}` },
{ status: 504 },
)
}
}