feat(cookie): ① Storage Inventory + storage_transparency-Finding

Trennt echte Cookies von anderem Endgeraete-Speicher (Local/Session Storage,
IndexedDB, Salesforce-Framework-Artefakte) — § 25 TDDDG ist technologieneutral.
- cookie_storage_inventory: detect_storage_type (Name-Muster ComponentDefStorage/
  __MUTEX/LSKey + Laufzeit-Text) + build_storage_inventory + storage_transparency-
  Summenbefund ('X als Cookie gelistet -> Y echte + Z andere').
- Endpoint cookie-check liefert storage_inventory; Frontend zeigt den Breakdown.

Tests: 4 + Frontend-Vitest gruen. Differenzierungsmerkmal: '740 -> 132 + 608'.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-06-11 09:05:29 +02:00
parent 577ceae4e6
commit 289988d23e
5 changed files with 207 additions and 1 deletions
@@ -22,6 +22,12 @@ export interface CookieFinding {
interface CheckData {
summary?: { checked?: number; in_library?: number; findings?: number }
findings?: CookieFinding[]
storage_inventory?: {
total?: number
by_type?: Record<string, number>
real_cookies?: number
other_storage?: number
}
}
const SEV_COLOR: Record<string, string> = {
@@ -36,14 +42,38 @@ const TYPE_LABEL: Record<string, string> = {
vague_duration: 'Speicherdauer nicht konkret',
third_country: 'Drittland-Transfer',
eu_alternative: 'EU-Alternative verfügbar',
storage_transparency: 'Speichertyp nicht transparent',
}
const STORAGE_LABEL: Record<string, string> = {
cookie: 'Cookies', local_storage: 'Local Storage',
session_storage: 'Session Storage', indexeddb: 'IndexedDB',
framework_storage: 'Framework-Storage',
}
// Pure, testbar.
export function CookieFindingList({ data }: { data: CheckData }) {
const findings = data.findings || []
const s = data.summary || {}
const inv = data.storage_inventory
return (
<div className="border rounded-lg overflow-hidden">
{inv && (inv.total ?? 0) > 0 && (
<div className="px-4 py-2.5 bg-blue-50 border-b text-xs text-blue-900">
<span className="font-semibold">Storage-Inventar:</span>{' '}
{inv.total} als Cookies" gelistet →{' '}
<strong>{inv.real_cookies} echte Cookies</strong>
{(inv.other_storage ?? 0) > 0 && (
<> + <strong className="text-amber-700">{inv.other_storage} andere Endgeräte-Speicher</strong></>
)}
{inv.by_type && (
<span className="text-blue-700 ml-1">
({Object.entries(inv.by_type)
.map(([k, n]) => `${n} ${STORAGE_LABEL[k] || k}`)
.join(' · ')})
</span>
)}
</div>
)}
<div className="px-4 py-2.5 bg-slate-50 border-b text-sm font-semibold text-gray-800">
Library-Abgleich — {findings.length} Befund{findings.length !== 1 ? 'e' : ''}
<span className="ml-2 text-xs font-normal text-gray-400">