'use client' import { useState, useEffect } from 'react' import { Shield, BookOpen, ExternalLink, CheckCircle2, AlertTriangle, Lock, Scale, FileText, Eye, ArrowLeft, } from 'lucide-react' import Link from 'next/link' // ============================================================================= // TYPES // ============================================================================= interface LicenseInfo { license_id: string name: string terms_url: string | null commercial_use: string ai_training_restriction: string | null tdm_allowed_under_44b: string | null deletion_required: boolean notes: string | null } interface SourceInfo { source_id: string title: string publisher: string url: string | null version_label: string | null language: string license_id: string license_name: string commercial_use: string allowed_analysis: boolean allowed_store_excerpt: boolean allowed_ship_embeddings: boolean allowed_ship_in_product: boolean vault_retention_days: number vault_access_tier: string } // ============================================================================= // STATIC PROVENANCE DOCUMENTATION // ============================================================================= const PROVENANCE_SECTIONS = [ { id: 'methodology', title: 'Methodik der Control-Erstellung', content: `## Unabhaengige Formulierung Alle Controls in der Canonical Control Library wurden **eigenstaendig formuliert** und folgen einer **unabhaengigen Taxonomie**. Es werden keine proprietaeren Bezeichner, Nummern oder Strukturen aus geschuetzten Quellen uebernommen. ### Dreistufiger Prozess 1. **Offene Recherche** — Identifikation von Security-Anforderungen aus oeffentlichen, frei zugaenglichen Frameworks (OWASP, NIST, ENISA). Jede Anforderung wird aus mindestens 2 unabhaengigen offenen Quellen belegt. 2. **Eigenstaendige Formulierung** — Jedes Control wird mit eigener Sprache, eigener Struktur und eigener Taxonomie (z.B. AUTH-001, NET-001) verfasst. Kein Copy-Paste, keine Paraphrase geschuetzter Texte. 3. **Too-Close-Pruefung** — Automatisierte Aehnlichkeitspruefung gegen Quelltexte mit 5 Metriken (Token Overlap, N-Gram Jaccard, Embedding Cosine, LCS Ratio, Exact-Phrase). Nur Controls mit Status PASS oder WARN (+ Human Review) werden freigegeben. ### Rechtliche Grundlage - **UrhG §44b** — Text & Data Mining erlaubt fuer Analyse; Kopien werden danach geloescht - **UrhG §23** — Hinreichender Abstand zum Originalwerk durch eigene Formulierung - **BSI Nutzungsbedingungen** — Kommerzielle Nutzung nur mit Zustimmung; wir nutzen BSI-Dokumente ausschliesslich als Analysegrundlage, nicht im Produkt`, }, { id: 'taxonomy', title: 'Unabhaengige Taxonomie', content: `## Eigenes Klassifikationssystem Die Canonical Control Library verwendet ein **eigenes Domain-Schema**, das sich bewusst von proprietaeren Frameworks unterscheidet: | Domain | Name | Abgrenzung | |--------|------|------------| | AUTH | Identity & Access Management | Eigene Struktur, nicht BSI O.Auth_* | | NET | Network & Transport Security | Eigene Struktur, nicht BSI O.Netz_* | | SUP | Software Supply Chain | NIST SSDF / SLSA-basiert | | LOG | Security Operations & Logging | OWASP Logging Best Practices | | WEB | Web Application Security | OWASP ASVS-basiert | | DATA | Data Governance & Classification | NIST SP 800-60 basiert | | CRYP | Cryptographic Operations | NIST SP 800-57 basiert | | REL | Release & Change Governance | OWASP SAMM basiert | ### ID-Format Control-IDs folgen dem Muster \`DOMAIN-NNN\` (z.B. AUTH-001, NET-002). Dieses Format ist **nicht von BSI oder anderen proprietaeren Standards abgeleitet**, sondern folgt einem allgemein ueblichen Nummerierungsschema.`, }, { id: 'open-sources', title: 'Offene Referenzquellen', content: `## Primaere offene Quellen Alle Controls sind in mindestens einer der folgenden **frei zugaenglichen** Quellen verankert: ### OWASP (CC BY-SA 4.0 — kommerziell erlaubt) - **ASVS** — Application Security Verification Standard v4.0.3 - **MASVS** — Mobile Application Security Verification Standard v2.1 - **Top 10** — OWASP Top 10 (2021) - **Cheat Sheets** — OWASP Cheat Sheet Series - **SAMM** — Software Assurance Maturity Model ### NIST (Public Domain — keine Einschraenkungen) - **SP 800-53 Rev.5** — Security and Privacy Controls - **SP 800-63B** — Digital Identity Guidelines (Authentication) - **SP 800-57** — Key Management Recommendations - **SP 800-52 Rev.2** — TLS Implementation Guidelines - **SP 800-92** — Log Management Guide - **SP 800-218 (SSDF)** — Secure Software Development Framework - **SP 800-60** — Information Types to Security Categories ### ENISA (CC BY 4.0 — kommerziell erlaubt) - Good Practices for IoT/Mobile Security - Data Protection Engineering - Algorithms, Key Sizes and Parameters Report ### Weitere offene Quellen - **SLSA** (Supply-chain Levels for Software Artifacts) — Google Open Source - **CIS Controls v8** (CC BY-NC-ND — nur fuer interne Analyse)`, }, { id: 'restricted-sources', title: 'Geschuetzte Quellen — Nur interne Analyse', content: `## Quellen mit eingeschraenkter Nutzung Die folgenden Quellen werden **ausschliesslich intern zur Analyse** verwendet. Kein Text, keine Struktur, keine Bezeichner aus diesen Quellen erscheinen im Produkt. ### BSI (Nutzungsbedingungen — kommerziell eingeschraenkt) - TR-03161 Teil 1-3 (Mobile, Web, Hintergrunddienste) - Nutzung: TDM unter UrhG §44b, Kopien werden geloescht - Kein Shipping von Zitaten, Embeddings oder Strukturen ### ISO/IEC (Kostenpflichtig — kein Shipping) - ISO 27001, ISO 27002 - Nutzung: Nur als Referenz fuer Mapping, kein Text im Produkt ### ETSI (Restriktiv — kein kommerzieller Gebrauch) - Nutzung: Nur als Hintergrundwissen, kein direkter Einfluss ### Trennungsprinzip | Ebene | Geschuetzte Quelle | Offene Quelle | |-------|--------------------|---------------| | Analyse | ✅ Darf gelesen werden | ✅ Darf gelesen werden | | Inspiration | ✅ Darf Ideen liefern | ✅ Darf Ideen liefern | | Formulierung | ❌ Keine Uebernahme | ✅ Darf zitiert werden | | Struktur | ❌ Keine Uebernahme | ✅ Darf verwendet werden | | Produkttext | ❌ Nicht erlaubt | ✅ Erlaubt |`, }, { id: 'validation', title: 'Automatisierte Validierung', content: `## CI/CD-Pruefungen Jedes Control wird bei jedem Commit automatisch geprueft: ### 1. Schema-Validierung - Alle Pflichtfelder vorhanden - Control-ID Format: \`^[A-Z]{2,6}-[0-9]{3}$\` - Severity: low, medium, high, critical - Risk Score: 0-10 ### 2. No-Leak Scanner Regex-Pruefung gegen verbotene Muster in produktfaehigen Feldern: - \`O.[A-Za-z]+_[0-9]+\` — BSI Objective-IDs - \`TR-03161\` — Direkte BSI-TR-Referenzen - \`BSI-TR-\` — BSI-spezifische Locators - \`Anforderung [A-Z].[0-9]+\` — BSI-Anforderungsformat ### 3. Open Anchor Check Jedes freigegebene Control muss mindestens 1 Open-Source-Referenz haben. ### 4. Too-Close Detektor (5 Metriken) | Metrik | Warn | Fail | Beschreibung | |--------|------|------|-------------| | Exact Phrase | ≥8 Tokens | ≥12 Tokens | Laengste identische Token-Sequenz | | Token Overlap | ≥0.20 | ≥0.30 | Jaccard-Aehnlichkeit der Token-Mengen | | 3-Gram Jaccard | ≥0.10 | ≥0.18 | Zeichenketten-Aehnlichkeit | | Embedding Cosine | ≥0.86 | ≥0.92 | Semantische Aehnlichkeit (bge-m3) | | LCS Ratio | ≥0.35 | ≥0.50 | Longest Common Subsequence | **Entscheidungslogik:** - **PASS** — Kein Fail + max 1 Warn - **WARN** — Max 2 Warn, kein Fail → Human Review erforderlich - **FAIL** — Irgendein Fail → Blockiert, Umformulierung noetig`, }, ] // ============================================================================= // PAGE // ============================================================================= export default function ControlProvenancePage() { const [licenses, setLicenses] = useState([]) const [sources, setSources] = useState([]) const [activeSection, setActiveSection] = useState('methodology') const [loading, setLoading] = useState(true) useEffect(() => { async function load() { try { const [licRes, srcRes] = await Promise.all([ fetch('/api/sdk/v1/canonical?endpoint=licenses'), fetch('/api/sdk/v1/canonical?endpoint=sources'), ]) if (licRes.ok) setLicenses(await licRes.json()) if (srcRes.ok) setSources(await srcRes.json()) } catch { // silently continue — static content still shown } finally { setLoading(false) } } load() }, []) const currentSection = PROVENANCE_SECTIONS.find(s => s.id === activeSection) return (
{/* Header */}

Control Provenance Wiki

Dokumentation der unabhaengigen Herkunft aller Security Controls — rechtssicherer Nachweis

Zur Control Library
{/* Left: Navigation */}

Dokumentation

{PROVENANCE_SECTIONS.map(section => ( ))}

Live-Daten

{/* Right: Content */}
{/* Static documentation sections */} {currentSection && (

{currentSection.title}

)} {/* License Matrix (live data) */} {activeSection === 'license-matrix' && (

Lizenz-Matrix

Uebersicht aller Lizenzen mit ihren erlaubten Nutzungsarten.

{loading ? (
) : (
{licenses.map(lic => ( ))}
Lizenz Kommerziell AI-Training TDM (§44b) Loeschpflicht
{lic.license_id}
{lic.name}
{lic.deletion_required ? ( Ja ) : ( Nein )}
)}
)} {/* Source Registry (live data) */} {activeSection === 'source-registry' && (

Quellenregister

Alle registrierten Quellen mit ihren Berechtigungen.

{loading ? (
) : (
{sources.map(src => (

{src.title}

{src.publisher} — {src.license_name}

{src.url && ( Quelle )}
))}
)}
)}
) } // ============================================================================= // HELPER COMPONENTS // ============================================================================= function UsageBadge({ value }: { value: string }) { const config: Record = { allowed: { bg: 'bg-green-100 text-green-800', label: 'Erlaubt' }, restricted: { bg: 'bg-yellow-100 text-yellow-800', label: 'Eingeschraenkt' }, prohibited: { bg: 'bg-red-100 text-red-800', label: 'Verboten' }, unclear: { bg: 'bg-gray-100 text-gray-600', label: 'Unklar' }, yes: { bg: 'bg-green-100 text-green-800', label: 'Ja' }, no: { bg: 'bg-red-100 text-red-800', label: 'Nein' }, 'n/a': { bg: 'bg-gray-100 text-gray-400', label: 'k.A.' }, } const c = config[value] || config.unclear return {c.label} } function PermBadge({ label, allowed }: { label: string; allowed: boolean }) { return (
{allowed ? ( ) : ( )} {label}
) } function MarkdownRenderer({ content }: { content: string }) { let html = content .replace(/&/g, '&') .replace(//g, '>') // Code blocks html = html.replace( /^```[\w]*\n([\s\S]*?)^```$/gm, (_m, code: string) => `
${code.trimEnd()}
` ) // Tables html = html.replace( /^(\|.+\|)\n(\|[\s:|-]+\|)\n((?:\|.+\|\n?)*)/gm, (_m, header: string, _sep: string, body: string) => { const ths = header.split('|').filter((c: string) => c.trim()).map((c: string) => `${c.trim()}` ).join('') const rows = body.trim().split('\n').map((row: string) => { const tds = row.split('|').filter((c: string) => c.trim()).map((c: string) => `${c.trim()}` ).join('') return `${tds}` }).join('') return `${ths}${rows}
` } ) // Headers html = html.replace(/^### (.+)$/gm, '

$1

') html = html.replace(/^## (.+)$/gm, '

$1

') // Bold html = html.replace(/\*\*(.+?)\*\*/g, '$1') // Inline code html = html.replace(/`([^`]+)`/g, '$1') // Lists html = html.replace(/^- (.+)$/gm, '
  • $1
  • ') html = html.replace(/((?:]*>.*<\/li>\n?)+)/g, '
      $1
    ') // Numbered lists html = html.replace(/^(\d+)\. (.+)$/gm, '
  • $2
  • ') // Paragraphs html = html.replace(/^(?!<[hultdp]|$)(.+)$/gm, '

    $1

    ') return
    }