refactor(developer-portal): split iace, docs, byoeh pages

Extract each page into colocated _components/ sections to bring
page.tsx files from 1008/891/769 LOC down to 57/23/21 LOC,
well within the 500-line hard cap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-04-18 08:45:13 +02:00
parent a7fe32fb82
commit 9ec72ed681
25 changed files with 2182 additions and 2614 deletions

View File

@@ -0,0 +1,123 @@
import { InfoBox } from '@/components/DevPortalLayout'
export function AuditApiSummarySection() {
return (
<>
<h2 id="audit">10. Audit-Trail: Vollstaendige Nachvollziehbarkeit</h2>
<p>
Jede Aktion im Namespace wird revisionssicher im <strong>Audit-Log</strong> gespeichert.
</p>
<div className="not-prose my-4 overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200 text-sm">
<thead className="bg-gray-50">
<tr>
<th className="px-4 py-3 text-left font-medium text-gray-500">Event</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Was protokolliert wird</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
<tr><td className="px-4 py-3 font-medium">upload</td><td className="px-4 py-3">Dokument hochgeladen (Dateigroesse, Metadaten, Zeitstempel)</td></tr>
<tr><td className="px-4 py-3 font-medium">index</td><td className="px-4 py-3">Referenzdokument indexiert (Anzahl Chunks, Dauer)</td></tr>
<tr><td className="px-4 py-3 font-medium">rag_query</td><td className="px-4 py-3">RAG-Suchanfrage ausgefuehrt (Query-Hash, Anzahl Ergebnisse)</td></tr>
<tr><td className="px-4 py-3 font-medium">analyze</td><td className="px-4 py-3">KI-Verarbeitung gestartet (Dokument-Token, Modell, Dauer)</td></tr>
<tr><td className="px-4 py-3 font-medium">share</td><td className="px-4 py-3">Namespace mit anderem Nutzer geteilt (Empfaenger, Rolle)</td></tr>
<tr><td className="px-4 py-3 font-medium">revoke_share</td><td className="px-4 py-3">Zugriff widerrufen (wer, wann)</td></tr>
<tr><td className="px-4 py-3 font-medium">decrypt</td><td className="px-4 py-3">Ergebnis entschluesselt (durch wen, Zeitstempel)</td></tr>
<tr><td className="px-4 py-3 font-medium">delete</td><td className="px-4 py-3">Dokument geloescht (Soft Delete, bleibt in Logs)</td></tr>
</tbody>
</table>
</div>
<h2 id="api">11. API-Endpunkte (SDK-Referenz)</h2>
<p>Authentifizierung erfolgt ueber API-Key + JWT-Token.</p>
<h3>11.1 Namespace-Verwaltung</h3>
<div className="not-prose my-4 overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200 text-sm">
<thead className="bg-gray-50">
<tr>
<th className="px-4 py-3 text-left font-medium text-gray-500">Methode</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Endpunkt</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Beschreibung</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
<tr><td className="px-4 py-3"><span className="px-2 py-0.5 rounded bg-blue-100 text-blue-800 text-xs font-bold">POST</span></td><td className="px-4 py-3 font-mono text-sm">/api/v1/namespace/upload</td><td className="px-4 py-3">Verschluesseltes Dokument hochladen</td></tr>
<tr><td className="px-4 py-3"><span className="px-2 py-0.5 rounded bg-green-100 text-green-800 text-xs font-bold">GET</span></td><td className="px-4 py-3 font-mono text-sm">/api/v1/namespace/documents</td><td className="px-4 py-3">Eigene Dokumente auflisten</td></tr>
<tr><td className="px-4 py-3"><span className="px-2 py-0.5 rounded bg-green-100 text-green-800 text-xs font-bold">GET</span></td><td className="px-4 py-3 font-mono text-sm">/api/v1/namespace/documents/{'{id}'}</td><td className="px-4 py-3">Einzelnes Dokument abrufen</td></tr>
<tr><td className="px-4 py-3"><span className="px-2 py-0.5 rounded bg-red-100 text-red-800 text-xs font-bold">DELETE</span></td><td className="px-4 py-3 font-mono text-sm">/api/v1/namespace/documents/{'{id}'}</td><td className="px-4 py-3">Dokument loeschen (Soft Delete)</td></tr>
</tbody>
</table>
</div>
<h3>11.2 Referenzdokumente &amp; RAG</h3>
<div className="not-prose my-4 overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200 text-sm">
<thead className="bg-gray-50">
<tr>
<th className="px-4 py-3 text-left font-medium text-gray-500">Methode</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Endpunkt</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Beschreibung</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
<tr><td className="px-4 py-3"><span className="px-2 py-0.5 rounded bg-blue-100 text-blue-800 text-xs font-bold">POST</span></td><td className="px-4 py-3 font-mono text-sm">/api/v1/namespace/references/upload</td><td className="px-4 py-3">Referenzdokument hochladen</td></tr>
<tr><td className="px-4 py-3"><span className="px-2 py-0.5 rounded bg-blue-100 text-blue-800 text-xs font-bold">POST</span></td><td className="px-4 py-3 font-mono text-sm">/api/v1/namespace/references/{'{id}'}/index</td><td className="px-4 py-3">Referenz fuer RAG indexieren</td></tr>
<tr><td className="px-4 py-3"><span className="px-2 py-0.5 rounded bg-blue-100 text-blue-800 text-xs font-bold">POST</span></td><td className="px-4 py-3 font-mono text-sm">/api/v1/namespace/rag-query</td><td className="px-4 py-3">RAG-Suchanfrage ausfuehren</td></tr>
<tr><td className="px-4 py-3"><span className="px-2 py-0.5 rounded bg-blue-100 text-blue-800 text-xs font-bold">POST</span></td><td className="px-4 py-3 font-mono text-sm">/api/v1/namespace/analyze</td><td className="px-4 py-3">KI-Verarbeitung anstossen</td></tr>
</tbody>
</table>
</div>
<h3>11.3 Key Sharing</h3>
<div className="not-prose my-4 overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200 text-sm">
<thead className="bg-gray-50">
<tr>
<th className="px-4 py-3 text-left font-medium text-gray-500">Methode</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Endpunkt</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Beschreibung</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
<tr><td className="px-4 py-3"><span className="px-2 py-0.5 rounded bg-blue-100 text-blue-800 text-xs font-bold">POST</span></td><td className="px-4 py-3 font-mono text-sm">/api/v1/namespace/share</td><td className="px-4 py-3">Namespace mit anderem Nutzer teilen</td></tr>
<tr><td className="px-4 py-3"><span className="px-2 py-0.5 rounded bg-green-100 text-green-800 text-xs font-bold">GET</span></td><td className="px-4 py-3 font-mono text-sm">/api/v1/namespace/shares</td><td className="px-4 py-3">Aktive Shares auflisten</td></tr>
<tr><td className="px-4 py-3"><span className="px-2 py-0.5 rounded bg-red-100 text-red-800 text-xs font-bold">DELETE</span></td><td className="px-4 py-3 font-mono text-sm">/api/v1/namespace/shares/{'{shareId}'}</td><td className="px-4 py-3">Zugriff widerrufen</td></tr>
<tr><td className="px-4 py-3"><span className="px-2 py-0.5 rounded bg-green-100 text-green-800 text-xs font-bold">GET</span></td><td className="px-4 py-3 font-mono text-sm">/api/v1/namespace/shared-with-me</td><td className="px-4 py-3">Mit mir geteilte Namespaces</td></tr>
</tbody>
</table>
</div>
<h2 id="zusammenfassung">12. Zusammenfassung: Compliance-Garantien</h2>
<div className="not-prose my-6 overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200 text-sm">
<thead className="bg-gray-50">
<tr>
<th className="px-4 py-3 text-left font-medium text-gray-500">Garantie</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Wie umgesetzt</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Regelwerk</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
<tr><td className="px-4 py-3 font-medium">Keine PII verlaesst das Kundensystem</td><td className="px-4 py-3">Header-Redaction + verschluesselte Identity-Map</td><td className="px-4 py-3">DSGVO Art. 4 Nr. 5</td></tr>
<tr><td className="px-4 py-3 font-medium">Betreiber kann nicht mitlesen</td><td className="px-4 py-3">Client-seitige AES-256-GCM Verschluesselung</td><td className="px-4 py-3">DSGVO Art. 32</td></tr>
<tr><td className="px-4 py-3 font-medium">Kein Zugriff durch andere Kunden</td><td className="px-4 py-3">Tenant-Isolation (Namespace) auf allen 3 Ebenen</td><td className="px-4 py-3">DSGVO Art. 25</td></tr>
<tr><td className="px-4 py-3 font-medium">Kein KI-Training mit Kundendaten</td><td className="px-4 py-3"><code>training_allowed: false</code> auf allen Vektoren</td><td className="px-4 py-3">AI Act Art. 10</td></tr>
<tr><td className="px-4 py-3 font-medium">Alles nachvollziehbar</td><td className="px-4 py-3">Vollstaendiger Audit-Trail aller Aktionen</td><td className="px-4 py-3">DSGVO Art. 5 Abs. 2</td></tr>
<tr><td className="px-4 py-3 font-medium">Kunde behaelt volle Kontrolle</td><td className="px-4 py-3">Jederzeitiger Widerruf, Loeschung, Datenexport</td><td className="px-4 py-3">DSGVO Art. 17, 20</td></tr>
</tbody>
</table>
</div>
<InfoBox type="success" title="Das Wichtigste in einem Satz">
Die Namespace-Technologie ermoeglicht KI-gestuetzte Datenverarbeitung in der Cloud, bei der
<strong> keine personenbezogenen Daten das Kundensystem verlassen</strong>, alle Daten
<strong> Ende-zu-Ende verschluesselt</strong> sind, jeder Kunde seinen
<strong> eigenen abgeschotteten Namespace</strong> hat, und ein
<strong> vollstaendiger Audit-Trail</strong> jede Aktion dokumentiert.
</InfoBox>
</>
)
}

View File

@@ -0,0 +1,86 @@
import { CodeBlock, InfoBox } from '@/components/DevPortalLayout'
export function ByoehIntroSection() {
return (
<>
<h2 id="einfuehrung">1. Was ist die Namespace-Technologie?</h2>
<p>
Unsere <strong>Namespace-Technologie</strong> (intern BYOEH -- Bring Your Own Expectation Horizon)
ist eine Privacy-First-Architektur, die es Geschaeftskunden ermoeglicht, <strong>sensible Daten
anonym und verschluesselt</strong> von KI-Services in der Cloud verarbeiten zu lassen -- ohne dass
personenbezogene Informationen jemals den Client verlassen.
</p>
<blockquote>
<em>&ldquo;Daten gehen pseudonymisiert und verschluesselt in die Cloud, werden dort
von KI verarbeitet, und kommen verarbeitet zurueck. Nur der Kunde kann die Ergebnisse
wieder den Originaldaten zuordnen -- denn nur sein System hat den Schluessel dafuer.&rdquo;</em>
</blockquote>
<p>Die Architektur basiert auf vier Bausteinen:</p>
<ol>
<li><strong>Pseudonymisierung:</strong> Personenbezogene Daten werden durch zufaellige Tokens ersetzt. Nur der Kunde kennt die Zuordnung.</li>
<li><strong>Client-seitige Verschluesselung:</strong> Alle Daten werden <em>auf dem System des Kunden</em> verschluesselt, bevor sie die Infrastruktur verlassen.</li>
<li><strong>Namespace-Isolation:</strong> Jeder Kunde erhaelt einen eigenen, vollstaendig abgeschotteten Namespace.</li>
<li><strong>KI-Verarbeitung in der Cloud:</strong> Die KI arbeitet mit den pseudonymisierten Daten. Ergebnisse gehen zurueck an den Kunden zur lokalen Entschluesselung.</li>
</ol>
<InfoBox type="info" title="Kern-Designprinzip: Operator Blindness">
<strong>Breakpilot kann die Kundendaten nicht lesen.</strong> Der Server sieht nur
verschluesselte Blobs und einen Schluessel-Hash (nicht den Schluessel selbst). Die
Passphrase zum Entschluesseln existiert <em>ausschliesslich</em> auf dem System des Kunden.
</InfoBox>
<h2 id="anwendungsfaelle">2. Typische Anwendungsfaelle</h2>
<div className="not-prose my-6 overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200 text-sm">
<thead className="bg-gray-50">
<tr>
<th className="px-4 py-3 text-left font-medium text-gray-500">Branche</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Anwendungsfall</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Sensible Daten</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
<tr><td className="px-4 py-3 font-medium">Bildung</td><td className="px-4 py-3">KI-gestuetzte Klausurkorrektur</td><td className="px-4 py-3">Schuelernamen, Noten, Leistungsdaten</td></tr>
<tr><td className="px-4 py-3 font-medium">Gesundheitswesen</td><td className="px-4 py-3">Medizinische Befundanalyse</td><td className="px-4 py-3">Patientennamen, Diagnosen, Befunde</td></tr>
<tr><td className="px-4 py-3 font-medium">Recht</td><td className="px-4 py-3">Vertragsanalyse, Due Diligence</td><td className="px-4 py-3">Mandantendaten, Vertragsinhalte</td></tr>
<tr><td className="px-4 py-3 font-medium">Personalwesen</td><td className="px-4 py-3">Bewerbungsscreening, Zeugnisanalyse</td><td className="px-4 py-3">Bewerberdaten, Gehaltsinformationen</td></tr>
<tr><td className="px-4 py-3 font-medium">Finanzwesen</td><td className="px-4 py-3">Dokumentenpruefung, Compliance-Checks</td><td className="px-4 py-3">Kontodaten, Transaktionen, Identitaeten</td></tr>
</tbody>
</table>
</div>
<h2 id="ablauf">3. Der komplette Ablauf im Ueberblick</h2>
<CodeBlock language="text" filename="Workflow: Vom Quelldokument zur KI-verarbeiteten Ausgabe">
{`SCHRITT 1: DOKUMENTE ERFASSEN & PSEUDONYMISIEREN
SDK empfaengt Dokumente (PDF, Bild, Text)
→ Personenbezogene Daten werden erkannt (Header, Namen, IDs)
→ PII wird durch zufaellige Tokens ersetzt (doc_token, UUID4)
→ Zuordnung "Token → Originalname" wird lokal gesichert
SCHRITT 2: CLIENT-SEITIGE VERSCHLUESSELUNG
Kunde konfiguriert eine Passphrase im SDK
→ SDK leitet daraus einen 256-Bit-Schluessel ab (PBKDF2, 100k Runden)
→ Dokumente werden mit AES-256-GCM verschluesselt
→ Nur der Hash des Schluessels wird an den Server gesendet
SCHRITT 3: IDENTITAETS-MAP SICHERN
→ Nur mit der Passphrase des Kunden rekonstruierbar
SCHRITT 4: UPLOAD IN DEN KUNDEN-NAMESPACE
→ Jeder Kunde hat eine eigene tenant_id
→ Daten werden in MinIO (Storage) + Qdrant (Vektoren) gespeichert
SCHRITT 5: KI-VERARBEITUNG IN DER CLOUD
→ RAG-System durchsucht Referenzdokumente des Kunden
→ KI generiert Ergebnisse basierend auf Kundenkontext
SCHRITT 6: ERGEBNISSE ZURUECK
→ SDK entschluesselt die Ergebnisse mit der Passphrase
SCHRITT 7: RE-IDENTIFIZIERUNG & FINALISIERUNG
→ Identitaets-Map wird entschluesselt
→ Tokens werden wieder den echten Datensaetzen zugeordnet`}
</CodeBlock>
</>
)
}

View File

@@ -0,0 +1,110 @@
import { CodeBlock, InfoBox } from '@/components/DevPortalLayout'
export function EncryptionNamespaceSection() {
return (
<>
<h2 id="verschluesselung">6. Ende-zu-Ende-Verschluesselung</h2>
<p>
Die Verschluesselung findet <strong>vollstaendig auf dem System des Kunden</strong> statt --
der Cloud-Server bekommt nur verschluesselte Daten zu sehen.
</p>
<h3>6.1 Der Verschluesselungsvorgang</h3>
<CodeBlock language="text" filename="Client-seitige Verschluesselung (im SDK)">
{`┌─────────────────────────────────────────────────────────────────┐
│ System des Kunden (SDK) │
├─────────────────────────────────────────────────────────────────┤
│ 1. Kunde konfiguriert Passphrase im SDK │
│ → Passphrase bleibt hier -- wird NIE gesendet │
│ │
│ 2. Schluessel-Ableitung: │
│ PBKDF2-SHA256(Passphrase, zufaelliger Salt, 100.000 Runden) │
│ → Ergebnis: 256-Bit-Schluessel (32 Bytes) │
│ │
│ 3. Verschluesselung: │
│ AES-256-GCM(Schluessel, zufaelliger IV, Dokument) │
│ → GCM: Garantiert Integritaet (Manipulation erkennbar) │
│ │
│ 4. Schluessel-Hash: │
│ SHA-256(abgeleiteter Schluessel) → Hash fuer Verifikation │
│ → Vom Hash kann der Schluessel NICHT zurueckberechnet werden│
│ │
│ 5. Upload: Nur diese Daten gehen an den Cloud-Server: │
│ • Verschluesselter Blob • Salt • IV • Schluessel-Hash │
│ │
│ Was NICHT an den Server geht: │
│ ✗ Passphrase ✗ Abgeleiteter Schluessel ✗ Klartext │
└─────────────────────────────────────────────────────────────────┘`}
</CodeBlock>
<h3>6.2 Sicherheitsgarantien</h3>
<div className="not-prose my-6 overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200 text-sm">
<thead className="bg-gray-50">
<tr>
<th className="px-4 py-3 text-left font-medium text-gray-500">Angriffsszenario</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Was der Angreifer sieht</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Ergebnis</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
<tr><td className="px-4 py-3 font-medium">Cloud-Server wird gehackt</td><td className="px-4 py-3">Verschluesselte Blobs + Hashes</td><td className="px-4 py-3 text-green-700 font-medium">Keine lesbaren Dokumente</td></tr>
<tr><td className="px-4 py-3 font-medium">Datenbank wird geleakt</td><td className="px-4 py-3">encrypted_identity_map (verschluesselt)</td><td className="px-4 py-3 text-green-700 font-medium">Keine personenbezogenen Daten</td></tr>
<tr><td className="px-4 py-3 font-medium">Netzwerkverkehr abgefangen</td><td className="px-4 py-3">Verschluesselte Daten (TLS + AES)</td><td className="px-4 py-3 text-green-700 font-medium">Doppelt verschluesselt</td></tr>
<tr><td className="px-4 py-3 font-medium">Betreiber (Breakpilot) will mitlesen</td><td className="px-4 py-3">Verschluesselte Blobs, kein Schluessel</td><td className="px-4 py-3 text-green-700 font-medium">Operator Blindness</td></tr>
<tr><td className="px-4 py-3 font-medium">Anderer Kunde versucht Zugriff</td><td className="px-4 py-3">Nichts (Tenant-Isolation)</td><td className="px-4 py-3 text-green-700 font-medium">Namespace blockiert</td></tr>
</tbody>
</table>
</div>
<h2 id="namespace">7. Namespace-Isolation: Jeder Kunde hat seinen eigenen Bereich</h2>
<p>
Ein <strong>Namespace</strong> ist ein vollstaendig abgeschotteter Bereich im System -- wie
<strong> separate Tresorraeume in einer Bank</strong>. Jeder Kunde hat seinen eigenen Raum,
und kein Schluessel passt in einen anderen.
</p>
<CodeBlock language="text" filename="Tenant-Isolation in der Vektordatenbank (Qdrant)">
{`Kunde A (tenant_id: "firma-alpha-001")
├── Dokument 1 (verschluesselt)
└── Referenz: Pruefkriterien 2025
Kunde B (tenant_id: "firma-beta-002")
└── Referenz: Compliance-Vorgaben 2025
Suchanfrage von Kunde A:
→ Suche NUR in tenant_id = "firma-alpha-001"
→ Kunde B's Daten sind UNSICHTBAR
Jede Qdrant-Query hat diesen Pflichtfilter:
must_conditions = [
FieldCondition(key="tenant_id", match="firma-alpha-001")
]`}
</CodeBlock>
<h3>7.2 Drei Ebenen der Isolation</h3>
<div className="not-prose my-6 overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200 text-sm">
<thead className="bg-gray-50">
<tr>
<th className="px-4 py-3 text-left font-medium text-gray-500">Ebene</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">System</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Isolation</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
<tr><td className="px-4 py-3 font-medium">Dateisystem</td><td className="px-4 py-3">MinIO (S3-Storage)</td><td className="px-4 py-3">Eigener Bucket/Pfad pro Kunde</td></tr>
<tr><td className="px-4 py-3 font-medium">Vektordatenbank</td><td className="px-4 py-3">Qdrant</td><td className="px-4 py-3">Pflichtfilter <code>tenant_id</code> bei jeder Suche</td></tr>
<tr><td className="px-4 py-3 font-medium">Metadaten-DB</td><td className="px-4 py-3">PostgreSQL</td><td className="px-4 py-3">Jede Tabelle hat <code>tenant_id</code> als Pflichtfeld</td></tr>
</tbody>
</table>
</div>
<InfoBox type="warning" title="Kein Training mit Kundendaten">
Auf allen Vektoren in Qdrant ist das Flag <code>training_allowed: false</code> gesetzt.
Kundeninhalte werden <strong>ausschliesslich fuer RAG-Suchen</strong> innerhalb des
Kunden-Namespace verwendet.
</InfoBox>
</>
)
}

View File

@@ -0,0 +1,100 @@
import { CodeBlock } from '@/components/DevPortalLayout'
export function RagKeySharingSection() {
return (
<>
<h2 id="rag-pipeline">8. RAG-Pipeline: KI-Verarbeitung mit Kundenkontext</h2>
<p>
Die KI nutzt die vom Kunden hochgeladenen Referenzdokumente als Wissensbasis.
Dieser Prozess heisst <strong>RAG (Retrieval Augmented Generation)</strong>.
</p>
<h3>8.1 Indexierung der Referenzdokumente</h3>
<CodeBlock language="text" filename="Indexierung: Vom Upload zum durchsuchbaren Referenzdokument">
{`Referenzdokument (verschluesselt auf Server)
|
v
┌────────────────────────────────────┐
│ 1. Passphrase-Verifikation │ ← SDK sendet Schluessel-Hash
└──────────┬─────────────────────────┘
v
┌────────────────────────────────────┐
│ 2. Entschluesselung │ ← Temporaer im Arbeitsspeicher
└──────────┬─────────────────────────┘
v
┌────────────────────────────────────┐
│ 3. Text-Extraktion │ ← PDF → Klartext
└──────────┬─────────────────────────┘
v
┌────────────────────────────────────┐
│ 4. Chunking │ ← ~1.000-Zeichen-Abschnitte
└──────────┬─────────────────────────┘
v
┌────────────────────────────────────┐
│ 5. Embedding │ ← Text → 1.536 Zahlen
└──────────┬─────────────────────────┘
v
┌────────────────────────────────────┐
│ 6. Re-Encryption │ ← Jeder Chunk wird erneut verschluesselt
└──────────┬─────────────────────────┘
v
┌────────────────────────────────────┐
│ 7. Qdrant-Indexierung │ ← Vektor + verschluesselter Chunk
│ tenant_id: "firma-alpha-001" │ mit Tenant-Filter gespeichert
│ training_allowed: false │
└────────────────────────────────────┘`}
</CodeBlock>
<h3>8.2 Wie die KI eine Anfrage bearbeitet (RAG-Query)</h3>
<ol>
<li><strong>Anfrage formulieren:</strong> Das SDK sendet eine Suchanfrage mit dem zu verarbeitenden Dokument.</li>
<li><strong>Semantische Suche:</strong> Die Anfrage wird in einen Vektor umgewandelt und gegen die Referenz-Vektoren in Qdrant gesucht -- <em>nur im Namespace des Kunden</em>.</li>
<li><strong>Entschluesselung:</strong> Die gefundenen Chunks werden mit der Passphrase des Kunden entschluesselt.</li>
<li><strong>KI-Antwort:</strong> Die entschluesselten Referenzpassagen werden als Kontext an die KI uebergeben.</li>
</ol>
<h2 id="key-sharing">9. Key Sharing: Zusammenarbeit ermoeglichen</h2>
<p>
Das Key-Sharing-System ermoeglicht es dem Eigentuemer, seinen Namespace sicher mit
anderen zu teilen (z.B. fuer Vier-Augen-Prinzip, Qualitaetskontrolle oder externe Audits).
</p>
<h3>9.1 Einladungs-Workflow</h3>
<CodeBlock language="text" filename="Key Sharing: Sicheres Teilen zwischen Bearbeitern">
{`Eigentuemer Server Eingeladener
│ │ │
│ 1. Einladung senden │ │
│─────────────────────────────────▶ │
│ │ 2. Einladung erstellt │
│ │ (14 Tage gueltig) │
│ │ 3. Benachrichtigung ──────▶│
│ │ 4. Einladung annehmen
│ │◀─────────────────────────────│
│ │ 5. Key-Share erstellt │
│ │ 6. Eingeladener kann ──────▶│
│ │ Daten im Namespace │
│ │ abfragen │
│ 7. Zugriff widerrufen │ │
│─────────────────────────────────▶ Share deaktiviert │`}
</CodeBlock>
<h3>9.2 Rollen beim Key-Sharing</h3>
<div className="not-prose my-4 overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200 text-sm">
<thead className="bg-gray-50">
<tr>
<th className="px-4 py-3 text-left font-medium text-gray-500">Rolle</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Typischer Nutzer</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Rechte</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
<tr><td className="px-4 py-3 font-medium">Owner</td><td className="px-4 py-3">Projektverantwortlicher</td><td className="px-4 py-3">Vollzugriff, kann teilen &amp; widerrufen</td></tr>
<tr><td className="px-4 py-3 font-medium">Reviewer</td><td className="px-4 py-3">Qualitaetssicherung</td><td className="px-4 py-3">Lesen, RAG-Queries, eigene Anmerkungen</td></tr>
<tr><td className="px-4 py-3 font-medium">Auditor</td><td className="px-4 py-3">Externer Pruefer</td><td className="px-4 py-3">Nur Lesen (Aufsichtsfunktion)</td></tr>
</tbody>
</table>
</div>
</>
)
}

View File

@@ -0,0 +1,113 @@
import { CodeBlock, InfoBox } from '@/components/DevPortalLayout'
export function SdkPseudonymSection() {
return (
<>
<h2 id="sdk-integration">4. SDK-Integration</h2>
<CodeBlock language="typescript" filename="Beispiel: SDK-Integration (TypeScript)">
{`import { BreakpilotSDK, NamespaceClient } from '@breakpilot/compliance-sdk'
// 1. SDK initialisieren mit API-Key
const sdk = new BreakpilotSDK({
apiKey: process.env.BREAKPILOT_API_KEY,
endpoint: 'https://api.breakpilot.de'
})
// 2. Namespace-Client erstellen (pro Mandant/Abteilung)
const namespace = sdk.createNamespace({
tenantId: 'kunde-firma-abc',
passphrase: process.env.ENCRYPTION_PASSPHRASE // Bleibt lokal!
})
// 3. Dokument pseudonymisieren & verschluesselt hochladen
const result = await namespace.upload({
file: documentBuffer,
metadata: { type: 'vertrag', category: 'due-diligence' },
pseudonymize: true,
headerRedaction: true
})
// result.docToken = "a7f3c2d1-4e9b-4a5f-8c7d-..."
// 4. Referenzdokument hochladen (z.B. Pruefkriterien)
await namespace.uploadReference({
file: referenceBuffer,
title: 'Pruefkriterien Vertrag Typ A'
})
// 5. KI-Verarbeitung anstossen
const analysis = await namespace.analyze({
docToken: result.docToken,
prompt: 'Pruefe den Vertrag gegen die Referenzkriterien',
useRAG: true
})
// 6. Ergebnisse entschluesseln (passiert automatisch im SDK)
console.log(analysis.findings)
console.log(analysis.score)
// 7. Re-Identifizierung (Token → Originalname)
const identityMap = await namespace.getIdentityMap()
const originalName = identityMap[result.docToken]`}
</CodeBlock>
<InfoBox type="success" title="Zero-Knowledge-Architektur">
Die Passphrase verlässt niemals das System des Kunden. Das SDK verschluesselt
und entschluesselt <strong>ausschliesslich lokal</strong>.
</InfoBox>
<h2 id="pseudonymisierung">5. Pseudonymisierung: Wie personenbezogene Daten entfernt werden</h2>
<h3>5.1 Der doc_token: Ein zufaelliger Identifikator</h3>
<p>
Jedes Dokument erhaelt einen <strong>doc_token</strong> -- einen 128-Bit-Zufallscode im
UUID4-Format. Dieser Token ist <strong>kryptographisch zufaellig</strong>, kann
<strong> nicht zurueckgerechnet</strong> werden und dient als <strong>eindeutiger Schluessel</strong>
fuer die spaetere Re-Identifizierung.
</p>
<h3>5.2 Header-Redaction: PII wird entfernt</h3>
<div className="not-prose my-6 overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200 text-sm">
<thead className="bg-gray-50">
<tr>
<th className="px-4 py-3 text-left font-medium text-gray-500">Methode</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Wie es funktioniert</th>
<th className="px-4 py-3 text-left font-medium text-gray-500">Wann verwenden</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
<tr>
<td className="px-4 py-3 font-medium">Einfache Redaction</td>
<td className="px-4 py-3">Definierter Bereich des Dokuments wird entfernt</td>
<td className="px-4 py-3">Standardisierte Formulare mit festem Layout</td>
</tr>
<tr>
<td className="px-4 py-3 font-medium">Smarte Redaction</td>
<td className="px-4 py-3">OpenCV/NER erkennt Textbereiche mit PII und entfernt gezielt</td>
<td className="px-4 py-3">Freitext-Dokumente, variable Layouts</td>
</tr>
</tbody>
</table>
</div>
<h3>5.3 Die Identitaets-Map: Nur der Kunde kennt die Zuordnung</h3>
<CodeBlock language="text" filename="Datenmodell: Namespace-Session (vereinfacht)">
{`NamespaceSession
├── tenant_id = "kunde-firma-abc" ← Pflichtfeld (Isolation)
├── encrypted_identity_map = [verschluesselte Bytes] ← Nur mit Passphrase lesbar
├── identity_map_iv = "a3f2c1..."
└── PseudonymizedDocument (pro Dokument)
├── doc_token = "a7f3c2d1-..." ← Zufaelliger Token (Primary Key)
├── session_id = [Referenz]
└── (Kein Name, keine personenbezogenen Daten)`}
</CodeBlock>
<InfoBox type="success" title="DSGVO Art. 4 Nr. 5 konform">
Die Pseudonymisierung erfuellt die Definition der DSGVO: Personenbezogene Daten
koennen <strong>ohne Hinzuziehung zusaetzlicher Informationen</strong>
(der verschluesselten Identitaets-Map + der Passphrase) nicht mehr einer bestimmten Person zugeordnet werden.
</InfoBox>
</>
)
}