+ {/* ============================================================ */}
+ {/* 1. EINLEITUNG */}
+ {/* ============================================================ */}
+ 1. Was ist das Namespace-System?
+
+ Das BYOEH-System (Bring Your Own Expectation Horizon) ist eine
+ Datenschutz-Architektur, die es Lehrern ermoeglicht, Klausuren anonym und
+ verschluesselt von einer KI korrigieren zu lassen -- ohne dass jemals der Name
+ eines Schuelers den Rechner des Lehrers verlaesst.
+
+
+ “Die Klausuren gehen anonym in die Cloud, werden dort von KI korrigiert,
+ und kommen korrigiert zurueck. Nur der Lehrer kann die Ergebnisse wieder den
+ Schuelern zuordnen -- denn nur seine Hardware hat den Schluessel dafuer.”
+
+
+ Das System loest ein grundlegendes Problem: Klausurkorrektur mit KI-Unterstuetzung
+ ohne Datenschutzrisiko. Die Loesung besteht aus vier Bausteinen:
+
+
+ -
+ Pseudonymisierung: Namen werden durch zufaellige Codes ersetzt.
+ Niemand ausser dem Lehrer kennt die Zuordnung.
+
+ -
+ Verschluesselung: Alles wird im Browser des Lehrers
+ verschluesselt, bevor es den Rechner verlaesst. Der Server sieht nur unlesbaren
+ Datensalat.
+
+ -
+ Namespace-Isolation: Jeder Lehrer hat einen eigenen, abgeschotteten
+ Bereich (Namespace). Kein Lehrer kann auf die Daten eines anderen zugreifen.
+
+ -
+ KI-Korrektur: Die KI arbeitet mit den verschluesselten Daten
+ und dem Erwartungshorizont (EH) des Lehrers. Korrekturvorschlaege gehen zurueck
+ an den Lehrer.
+
+
+
+
+ Breakpilot kann die Klausuren nicht lesen. Der Server sieht nur
+ verschluesselte Daten und einen Schluessel-Hash (nicht den Schluessel selbst). Die
+ Passphrase zum Entschluesseln existiert nur im Browser des Lehrers und
+ wird niemals uebertragen. Selbst ein Angriff auf den Server wuerde keine
+ Klausurtexte preisgeben.
+
+
+ {/* ============================================================ */}
+ {/* 2. DER KOMPLETTE ABLAUF */}
+ {/* ============================================================ */}
+ 2. Der komplette Ablauf im Ueberblick
+
+ Der Prozess laesst sich in sieben Schritte unterteilen. Stellen Sie sich vor, der
+ Lehrer sitzt an seinem Rechner und hat einen Stapel gescannter Klausuren:
+
+
+
+{`SCHRITT 1: KLAUSUREN SCANNEN & HOCHLADEN
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+Lehrer scannt Klausuren ein (PDF oder Bild)
+ → System erkennt automatisch den Kopfbereich mit Namen
+ → Kopfbereich wird permanent entfernt (Header-Redaction)
+ → Jede Klausur erhaelt einen zufaelligen Code (doc_token)
+
+SCHRITT 2: VERSCHLUESSELUNG IM BROWSER
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+Lehrer gibt eine Passphrase ein (z.B. "MeinGeheimesPasswort2025!")
+ → Browser leitet daraus einen 256-Bit-Schluessel ab (PBKDF2)
+ → Klausur wird mit AES-256-GCM verschluesselt
+ → Nur der Hash des Schluessels wird an den Server gesendet
+ → Passphrase und Schluessel verlassen NIEMALS den Browser
+
+SCHRITT 3: IDENTITAETS-MAP SICHERN
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+Die Zuordnung "doc_token → Schuelername" wird verschluesselt:
+ → Tabelle: "a7f3c2d1... = Max Mustermann, b9e4a1f8... = Anna Schmidt"
+ → Diese Tabelle wird mit dem gleichen Schluessel verschluesselt
+ → Ohne Passphrase kann niemand die Zuordnung wiederherstellen
+
+SCHRITT 4: UPLOAD IN DEN NAMESPACE
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+Die verschluesselten Dateien gehen in den persoenlichen Namespace:
+ → Jeder Lehrer hat eine eigene tenant_id
+ → Daten werden in MinIO (verschluesselt) + Qdrant (Vektoren) gespeichert
+ → Server sieht: verschluesselter Blob + Schluessel-Hash + Salt
+
+SCHRITT 5: KI-KORREKTUR
+━━━━━━━━━━━━━━━━━━━━━━━
+Der Lehrer startet die KI-Korrektur:
+ → RAG-System durchsucht den Erwartungshorizont (EH)
+ → KI generiert Korrekturvorschlaege pro Kriterium
+ → Vorschlaege basieren auf dem EH, nicht auf Halluzinationen
+
+SCHRITT 6: ERGEBNISSE ZURUECK
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+Korrekturvorschlaege gehen an den Lehrer:
+ → Lehrer gibt Passphrase ein
+ → Browser entschluesselt die Ergebnisse
+ → Lehrer sieht: Vorschlaege pro Kriterium + Gesamtnote
+
+SCHRITT 7: ZUORDNUNG & FINALISIERUNG
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+Lehrer ordnet Ergebnisse den Schuelern zu:
+ → Identitaets-Map wird entschluesselt
+ → doc_token wird wieder dem echten Namen zugeordnet
+ → Lehrer ueberprueft/korrigiert KI-Vorschlaege
+ → Fertige Korrektur + Gutachten koennen exportiert werden`}
+
+
+ {/* ============================================================ */}
+ {/* 3. PSEUDONYMISIERUNG */}
+ {/* ============================================================ */}
+ 3. Pseudonymisierung: Wie Namen verschwinden
+
+ Pseudonymisierung bedeutet: personenbezogene Daten werden durch zufaellige
+ Codes ersetzt, sodass ohne Zusatzinformation kein Rueckschluss auf die Person
+ moeglich ist. Im BYOEH-System passiert das auf zwei Ebenen:
+
+
+ 3.1 Der doc_token: Ein zufaelliger Ausweis
+
+ Jede Klausur erhaelt einen doc_token -- einen 128-Bit-Zufallscode im
+ UUID4-Format (z.B. a7f3c2d1-4e9b-4a5f-8c7d-6b2e1f0a9d3c). Dieser Code:
+
+
+ - Ist kryptographisch zufaellig -- es gibt keinen Zusammenhang zwischen
+ Token und Schueler
+ - Kann nicht zurueckgerechnet werden -- auch mit Kenntnis des Algorithmus
+ ist kein Rueckschluss moeglich
+ - Wird auf der Klausur aufgedruckt (als QR-Code), damit die physische
+ Klausur spaeter wieder zugeordnet werden kann
+
+
+ 3.2 Header-Redaction: Der Name wird entfernt
+
+ Bevor eine Klausur verarbeitet wird, entfernt das System den Kopfbereich
+ der gescannten Seite -- dort, wo typischerweise Name, Klasse und Datum stehen. Diese
+ Entfernung ist permanent: Die Originaldaten werden nicht gespeichert.
+
+
+
+
+
+
+ | Methode |
+ Wie es funktioniert |
+ Wann verwendet |
+
+
+
+
+ | Einfache Redaction |
+ Obere ~2,5 cm der Seite werden weiss ueberschrieben |
+ Standard bei allen Uploads |
+
+
+ | Smarte Redaction |
+ OpenCV erkennt Textbereiche und entfernt gezielt den Kopf, verschont aber QR-Codes |
+ Wenn QR-Codes auf der Klausur sind |
+
+
+
+
+
+ 3.3 Die Identitaets-Map: Nur der Lehrer kennt die Zuordnung
+
+ Die Zuordnung doc_token → Schuelername wird als verschluesselte Tabelle
+ gespeichert. Das Datenbankmodell sieht so aus:
+
+
+
+{`ExamSession
+├── teacher_id = "lehrer-uuid-123" ← Pflichtfeld (Isolation)
+├── encrypted_identity_map = [verschluesselte Bytes] ← Nur mit Passphrase lesbar
+├── identity_map_iv = "a3f2c1..." ← Initialisierungsvektor (fuer AES)
+│
+└── PseudonymizedDocument (pro Klausur)
+ ├── doc_token = "a7f3c2d1-..." ← Zufaelliger Code (Primary Key)
+ ├── exam_session_id = [Referenz]
+ └── (Kein Name, keine Klasse, kein persoenliches Datum)`}
+
+
+
+ Die Pseudonymisierung erfuellt die Definition aus der DSGVO: Die personenbezogenen Daten
+ (Schuelernamen) koennen ohne Hinzuziehung zusaetzlicher Informationen
+ (der verschluesselten Identitaets-Map + der Passphrase des Lehrers) nicht mehr einer
+ bestimmten Person zugeordnet werden.
+
+
+ {/* ============================================================ */}
+ {/* 4. VERSCHLUESSELUNG */}
+ {/* ============================================================ */}
+ 4. Verschluesselung: Wie Daten geschuetzt werden
+
+ Die Verschluesselung ist das Herzsstueck des Datenschutzes. Sie findet vollstaendig
+ im Browser statt -- der Server bekommt nur verschluesselte Daten zu sehen.
+
+
+ 4.1 Der Verschluesselungsvorgang
+
+ Wenn der Lehrer eine Klausur oder einen Erwartungshorizont hochlaedt, passiert im
+ Browser folgendes:
+
+
+
+{`┌─────────────────────────────────────────────────────────────────┐
+│ Browser des Lehrers │
+├─────────────────────────────────────────────────────────────────┤
+│ │
+│ 1. Lehrer gibt Passphrase ein (z.B. "MeinGeheimesPasswort!") │
+│ │ ↑ │
+│ │ │ Passphrase bleibt hier -- wird NIE gesendet │
+│ ▼ │
+│ 2. Schluessel-Ableitung: │
+│ PBKDF2-SHA256(Passphrase, zufaelliger Salt, 100.000 Runden) │
+│ │ │
+│ │ → Ergebnis: 256-Bit-Schluessel (32 Bytes) │
+│ │ → Selbst bei Kenntnis des Salts sind 100.000 Runden │
+│ │ noetig, um den Schluessel zu erraten │
+│ ▼ │
+│ 3. Verschluesselung: │
+│ AES-256-GCM(Schluessel, zufaelliger IV, Datei-Inhalt) │
+│ │ │
+│ │ → AES-256: Militaerstandard, 2^256 moegliche Schluessel │
+│ │ → GCM: Garantiert Integritaet (Manipulation erkennbar) │
+│ ▼ │
+│ 4. Schluessel-Hash: │
+│ SHA-256(abgeleiteter Schluessel) → Hash fuer Verifikation │
+│ │ │
+│ │ → Der Server speichert nur diesen Hash │
+│ │ → Damit kann geprueft werden ob die Passphrase stimmt │
+│ │ → Vom Hash kann der Schluessel NICHT zurueckgerechnet │
+│ │ werden │
+│ ▼ │
+│ 5. Upload: Nur diese Daten gehen an den Server: │
+│ • Verschluesselter Blob (unlesbar ohne Schluessel) │
+│ • Salt (zufaellige Bytes, harmlos) │
+│ • IV (Initialisierungsvektor, harmlos) │
+│ • Schluessel-Hash (zur Verifikation, nicht umkehrbar) │
+│ │
+│ Was NICHT an den Server geht: │
+│ ✗ Passphrase │
+│ ✗ Abgeleiteter Schluessel │
+│ ✗ Unverschluesselter Klartext │
+└─────────────────────────────────────────────────────────────────┘`}
+
+
+ 4.2 Warum ist das sicher?
+
+
+
+
+ | Angriffsszenario |
+ Was der Angreifer sieht |
+ Ergebnis |
+
+
+
+
+ | Server wird gehackt |
+ Verschluesselte Blobs + Hashes |
+ Keine lesbaren Klausuren |
+
+
+ | Datenbank wird geleakt |
+ encrypted_identity_map (verschluesselt) |
+ Keine Schuelernamen |
+
+
+ | Netzwerkverkehr abgefangen |
+ Verschluesselte Daten (HTTPS + AES) |
+ Doppelt verschluesselt |
+
+
+ | Betreiber (Breakpilot) will mitlesen |
+ Verschluesselte Blobs, kein Schluessel |
+ Operator Blindness |
+
+
+ | Anderer Lehrer versucht Zugriff |
+ Nichts (Tenant-Isolation) |
+ Namespace blockiert |
+
+
+
+
+
+ {/* ============================================================ */}
+ {/* 5. NAMESPACE / TENANT-ISOLATION */}
+ {/* ============================================================ */}
+ 5. Namespace-Isolation: Jeder Lehrer hat seinen eigenen Bereich
+
+ Ein Namespace (auch “Tenant” genannt) ist ein abgeschotteter
+ Bereich im System. Man kann es sich wie separate Schliessfaecher in einer
+ Bank vorstellen: Jeder Lehrer hat sein eigenes Fach, und kein Schluessel passt in ein
+ anderes Fach.
+
+
+ 5.1 Wie die Isolation funktioniert
+
+ Jeder Lehrer erhaelt beim ersten Login eine eindeutige tenant_id. Diese ID wird
+ bei jeder einzelnen Datenbankabfrage als Pflichtfilter mitgefuehrt:
+
+
+
+{`Lehrer A (tenant_id: "school-A-lehrer-1")
+├── Klausur 1 (verschluesselt)
+├── Klausur 2 (verschluesselt)
+└── Erwartungshorizont Deutsch LK 2025
+
+Lehrer B (tenant_id: "school-B-lehrer-2")
+├── Klausur 1 (verschluesselt)
+└── Erwartungshorizont Mathe GK 2025
+
+Suchanfrage von Lehrer A:
+ "Wie soll die Einleitung strukturiert sein?"
+ → Suche NUR in tenant_id = "school-A-lehrer-1"
+ → Lehrer B's Daten sind UNSICHTBAR
+
+Jede Qdrant-Query hat diesen Pflichtfilter:
+ must_conditions = [
+ FieldCondition(key="tenant_id", match="school-A-lehrer-1")
+ ]
+
+Es gibt KEINE Abfrage ohne tenant_id-Filter.`}
+
+
+ 5.2 Drei Ebenen der Isolation
+
+
+
+
+ | Ebene |
+ System |
+ Isolation |
+
+
+
+
+ | Dateisystem |
+ MinIO (S3-Storage) |
+ Eigener Ordner pro Lehrer: /tenant-id/eh-id/encrypted.bin |
+
+
+ | Vektordatenbank |
+ Qdrant |
+ Pflichtfilter tenant_id bei jeder Suche |
+
+
+ | Metadaten-DB |
+ PostgreSQL |
+ Jede Tabelle hat teacher_id als Pflichtfeld |
+
+
+
+
+
+
+ Auf allen Vektoren in Qdrant ist das Flag training_allowed: false gesetzt.
+ Das bedeutet: Die Inhalte der Lehrer werden ausschliesslich fuer RAG-Suchen
+ (Abruf relevanter Textpassagen) verwendet und niemals zum Trainieren eines
+ KI-Modells eingesetzt.
+
+
+ {/* ============================================================ */}
+ {/* 6. DER ERWARTUNGSHORIZONT (EH) */}
+ {/* ============================================================ */}
+ 6. Der Erwartungshorizont: Die Grundlage fuer KI-Korrektur
+
+ Ein Erwartungshorizont (EH) ist das Dokument, das beschreibt, was in
+ einer Klausur erwartet wird: welche Inhalte in welcher Qualitaet vorkommen sollen.
+ Im BYOEH-System laedt der Lehrer seinen eigenen EH hoch, und die KI nutzt ihn als
+ Referenz fuer Korrekturvorschlaege.
+
+
+ 6.1 Upload-Wizard (5 Schritte)
+
+
+
+
+ | Schritt |
+ Was passiert |
+ Warum |
+
+
+
+ | 1. Datei waehlen | PDF per Drag & Drop hochladen | Der EH als digitales Dokument |
+ | 2. Metadaten | Titel, Fach, Niveau (eA/gA), Jahr | Fuer Filterung und Organisation |
+ | 3. Rechtebestaetigung | Checkbox: “Ich bin berechtigt” | Rechtliche Absicherung (Urheberrecht) |
+ | 4. Verschluesselung | Passphrase eingeben (2x bestaetigen) | Schluessel fuer Ende-zu-Ende-Verschluesselung |
+ | 5. Zusammenfassung | Pruefen und bestaetigen | Letzte Kontrolle vor dem Upload |
+
+
+
+
+ 6.2 RAG-Pipeline: Wie der EH fuer die KI nutzbar wird
+
+ Nach dem Upload wird der EH fuer die KI-Suche vorbereitet. Dieser Vorgang heisst
+ Indexierung und funktioniert wie das Erstellen eines Stichwortverzeichnisses
+ fuer ein Buch:
+
+
+
+{`Erwartungshorizont (verschluesselt auf Server)
+ |
+ v
+┌────────────────────────────────┐
+│ 1. Passphrase-Verifikation │ ← Lehrer gibt Passphrase ein
+│ Hash pruefen │ Server vergleicht mit gespeichertem Hash
+└──────────┬─────────────────────┘
+ |
+ v
+┌────────────────────────────────┐
+│ 2. Entschluesselung │ ← Temporaer im Arbeitsspeicher
+│ AES-256-GCM Decrypt │ (wird nach Verarbeitung geloescht)
+└──────────┬─────────────────────┘
+ |
+ v
+┌────────────────────────────────┐
+│ 3. Text-Extraktion │ ← PDF → Klartext
+│ Tabellen, Listen erkennen │
+└──────────┬─────────────────────┘
+ |
+ v
+┌────────────────────────────────┐
+│ 4. Chunking │ ← Text in 1.000-Zeichen-Abschnitte zerlegen
+│ Ueberlappung: 200 Zeichen │ (mit Ueberlappung, damit kein Kontext
+│ │ verloren geht)
+└──────────┬─────────────────────┘
+ |
+ v
+┌────────────────────────────────┐
+│ 5. Embedding │ ← Jeder Abschnitt wird in einen
+│ Text → 1.536 Zahlen │ Bedeutungsvektor umgewandelt
+└──────────┬─────────────────────┘
+ |
+ v
+┌────────────────────────────────┐
+│ 6. Re-Encryption │ ← Jeder Chunk wird ERNEUT verschluesselt
+│ AES-256-GCM pro Chunk │ bevor er gespeichert wird
+└──────────┬─────────────────────┘
+ |
+ v
+┌────────────────────────────────┐
+│ 7. Qdrant-Indexierung │ ← Vektor + verschluesselter Chunk
+│ tenant_id: "lehrer-123" │ werden mit Tenant-Filter gespeichert
+│ training_allowed: false │
+└────────────────────────────────┘`}
+
+
+ 6.3 Wie die KI den EH nutzt (RAG-Query)
+
+ Wenn der Lehrer bei der Korrektur einen Vorschlag anfordert, passiert folgendes:
+
+
+ -
+ Frage formulieren: Das System erstellt eine Suchanfrage aus dem
+ Klausurtext und dem aktuellen Bewertungskriterium (z.B. “Wie gut ist die
+ Einleitung im Vergleich zum Erwartungshorizont?”).
+
+ -
+ Semantische Suche: Die Anfrage wird in einen Vektor umgewandelt und
+ gegen die EH-Vektoren in Qdrant gesucht -- nur im Namespace des Lehrers.
+
+ -
+ Entschluesselung: Die gefundenen Chunks werden mit der Passphrase
+ des Lehrers entschluesselt.
+
+ -
+ KI-Antwort: Die entschluesselten EH-Passagen werden als Kontext
+ an die KI uebergeben, die daraus einen Korrekturvorschlag generiert.
+
+
+
+ {/* ============================================================ */}
+ {/* 7. KEY SHARING */}
+ {/* ============================================================ */}
+ 7. Key Sharing: Zweitkorrektur ermoeglichen
+
+ Bei Abiturklausuren muss eine Zweitkorrektur durch einen anderen Lehrer
+ erfolgen. Das Key-Sharing-System ermoeglicht es dem Erstpruefer, seinen Erwartungshorizont
+ sicher mit dem Zweitpruefer zu teilen -- ohne die Verschluesselung aufzugeben.
+
+
+ 7.1 Einladungs-Workflow
+
+{`Erstpruefer Server Zweitpruefer
+ │ │ │
+ │ 1. Einladung senden │ │
+ │ (E-Mail + Rolle + Klausur) │ │
+ │─────────────────────────────────▶ │
+ │ │ │
+ │ │ 2. Einladung erstellt │
+ │ │ (14 Tage gueltig) │
+ │ │ │
+ │ │ 3. Benachrichtigung ──────▶│
+ │ │ │
+ │ │ 4. Einladung annehmen
+ │ │◀─────────────────────────────│
+ │ │ │
+ │ │ 5. Key-Share erstellt │
+ │ │ (verschluesselte │
+ │ │ Passphrase) │
+ │ │ │
+ │ │ 6. Zweitpruefer kann ──────▶│
+ │ │ jetzt RAG-Queries │
+ │ │ ausfuehren │
+ │ │ │
+ │ 7. Zugriff widerrufen │ │
+ │ (jederzeit moeglich) │ │
+ │─────────────────────────────────▶ │
+ │ │ Share deaktiviert │`}
+
+
+ 7.2 Rollen beim Key-Sharing
+
+
+
+
+ | Rolle |
+ Wer |
+ Rechte |
+
+
+
+ | Erstpruefer (EK) | Kurslehrer | Vollzugriff, kann teilen & widerrufen |
+ | Zweitpruefer (ZK) | Anderer Fachlehrer | Nur Lesen, RAG-Queries, eigene Annotations |
+ | Drittpruefer (DK) | Bei Differenz ≥ 4 Punkte | Nur Lesen, RAG-Queries |
+ | Fachvorsitz | Fachbereichsleitung | Nur Lesen (Aufsichtsfunktion) |
+
+
+
+
+ {/* ============================================================ */}
+ {/* 8. BEWERTUNGSKRITERIEN */}
+ {/* ============================================================ */}
+ 8. KI-gestuetzte Bewertung: Wie die Korrektur funktioniert
+
+ Die KI bewertet jede Klausur anhand von fuenf Kriterien, die
+ zusammen 100% ergeben:
+
+
+
+
+
+ | Kriterium |
+ Gewichtung |
+ Was geprueft wird |
+
+
+
+ | Rechtschreibung | 15% | Orthographie, Zeichensetzung |
+ | Grammatik | 15% | Satzbau, Kongruenz, Tempus |
+ | Inhalt | 40% | Bezug zum EH, Vollstaendigkeit, Argumentation |
+ | Struktur | 15% | Gliederung, Einleitung/Schluss, roter Faden |
+ | Stil | 15% | Ausdruck, Wortwahl, Fachsprache |
+
+
+
+
+
+ Die Bewertung folgt dem 15-Punkte-System (0-15 Notenpunkte),
+ das fuer die gymnasiale Oberstufe gilt. Aus den Teilbewertungen wird automatisch
+ eine Gesamtnote berechnet.
+
+
+
+ Alle KI-Bewertungen sind Vorschlaege. Der Lehrer hat bei jedem
+ Kriterium die volle Kontrolle: Er kann den Vorschlag annehmen, aendern oder
+ komplett ueberschreiben. Die finale Note setzt immer der Lehrer.
+
+
+ {/* ============================================================ */}
+ {/* 9. AUDIT-TRAIL */}
+ {/* ============================================================ */}
+ 9. Audit-Trail: Alles wird protokolliert
+
+ Jede Aktion im System wird revisionssicher im Audit-Log gespeichert.
+ Das ist wichtig fuer die Nachvollziehbarkeit und fuer den Fall, dass Schueler oder
+ Eltern eine Korrektur anfechten.
+
+
+
+
+
+
+ | Aktion |
+ Was protokolliert wird |
+
+
+
+ | upload | EH hochgeladen (Dateigroesse, Metadaten, Zeitstempel) |
+ | index | EH fuer RAG indexiert (Anzahl Chunks, Dauer) |
+ | rag_query | RAG-Suchanfrage ausgefuehrt (Query-Hash, Anzahl Ergebnisse, Score) |
+ | share | EH mit anderem Pruefer geteilt (Empfaenger, Rolle) |
+ | revoke_share | Zugriff widerrufen (wer, wann) |
+ | link_klausur | EH mit Klausur verknuepft |
+ | delete | EH geloescht (Soft Delete, bleibt in Logs) |
+
+
+
+
+ {/* ============================================================ */}
+ {/* 10. API-ENDPUNKTE */}
+ {/* ============================================================ */}
+ 10. API-Endpunkte (Technische Referenz)
+
+ Alle Endpunkte laufen ueber den klausur-service auf Port 8086.
+ Authentifizierung erfolgt ueber JWT-Token.
+
+
+ 10.1 Erwartungshorizont-Verwaltung
+
+
+
+
+ | Methode |
+ Endpunkt |
+ Beschreibung |
+
+
+
+ | POST | /api/v1/eh/upload | Verschluesselten EH hochladen |
+ | GET | /api/v1/eh | Eigene EHs auflisten |
+ | GET | /api/v1/eh/{'{id}'} | Einzelnen EH abrufen |
+ | DELETE | /api/v1/eh/{'{id}'} | EH loeschen (Soft Delete) |
+ | POST | /api/v1/eh/{'{id}'}/index | EH fuer RAG indexieren |
+ | POST | /api/v1/eh/rag-query | RAG-Suchanfrage ausfuehren |
+
+
+
+
+ 10.2 Key Sharing
+
+
+
+
+ | Methode |
+ Endpunkt |
+ Beschreibung |
+
+
+
+ | POST | /api/v1/eh/{'{id}'}/share | EH mit Pruefer teilen |
+ | GET | /api/v1/eh/{'{id}'}/shares | Geteilte Zugriffe auflisten |
+ | DELETE | /api/v1/eh/{'{id}'}/shares/{'{shareId}'} | Zugriff widerrufen |
+ | GET | /api/v1/eh/shared-with-me | Mit mir geteilte EHs |
+
+
+
+
+ 10.3 Klausur-Integration
+
+
+
+
+ | Methode |
+ Endpunkt |
+ Beschreibung |
+
+
+
+ | POST | /api/v1/eh/{'{id}'}/link-klausur | EH mit Klausur verknuepfen |
+ | DELETE | /api/v1/eh/{'{id}'}/link-klausur/{'{klausurId}'} | Verknuepfung loesen |
+ | GET | /api/v1/klausuren/{'{id}'}/linked-eh | Verknuepften EH abrufen |
+
+
+
+
+ {/* ============================================================ */}
+ {/* 11. DATEISTRUKTUR */}
+ {/* ============================================================ */}
+ 11. Dateistruktur im Code
+
+
+{`klausur-service/
+├── backend/
+│ ├── main.py # API-Endpunkte + Datenmodelle
+│ ├── qdrant_service.py # Vektordatenbank-Operationen (Tenant-Filter)
+│ └── eh_pipeline.py # Chunking, Embedding, Verschluesselung
+│
+├── frontend/
+│ └── src/
+│ ├── components/
+│ │ └── EHUploadWizard.tsx # 5-Schritt-Upload-Wizard
+│ └── services/
+│ ├── api.ts # API-Client
+│ └── encryption.ts # Client-seitige Kryptographie
+│
+└── docs/
+ ├── BYOEH-Architecture.md # Technische Architektur
+ └── BYOEH-Developer-Guide.md # Entwickler-Handbuch
+
+backend/klausur/
+├── db_models.py # ExamSession, PseudonymizedDocument
+└── services/
+ └── pseudonymizer.py # QR-Codes, Header-Redaction, doc_tokens`}
+
+
+ {/* ============================================================ */}
+ {/* 12. ZUSAMMENFASSUNG */}
+ {/* ============================================================ */}
+ 12. Zusammenfassung: Die Sicherheitsgarantien
+
+
+
+
+
+ | Garantie |
+ Wie umgesetzt |
+ Regelwerk |
+
+
+
+
+ | Kein Name verlaesst den Rechner |
+ Header-Redaction + verschluesselte Identity-Map |
+ DSGVO Art. 4 Nr. 5 |
+
+
+ | Betreiber kann nicht mitlesen |
+ Client-seitige AES-256-GCM Verschluesselung |
+ DSGVO Art. 32 |
+
+
+ | Kein Zugriff durch andere Lehrer |
+ Tenant-Isolation (Namespace) auf allen 3 Ebenen |
+ DSGVO Art. 25 |
+
+
+ | Kein KI-Training mit Schuelerdaten |
+ training_allowed: false auf allen Vektoren |
+ AI Act Art. 10 |
+
+
+ | Alles nachvollziehbar |
+ Vollstaendiger Audit-Trail aller Aktionen |
+ DSGVO Art. 5 Abs. 2 |
+
+
+ | Lehrer behaelt volle Kontrolle |
+ KI-Vorschlaege, keine KI-Entscheidungen + jederzeitiger Widerruf |
+ DSGVO Art. 22 |
+
+
+
+
+
+
+ Das BYOEH-System ermoeglicht KI-gestuetzte Klausurkorrektur, bei der
+ kein Schuelername den Rechner des Lehrers verlaesst, alle Daten
+ Ende-zu-Ende verschluesselt sind, jeder Lehrer seinen
+ eigenen abgeschotteten Namespace hat, und die KI
+ nur Vorschlaege macht -- die finale Bewertung trifft immer der Lehrer.
+
+
+ )
+}
diff --git a/developer-portal/components/DevPortalLayout.tsx b/developer-portal/components/DevPortalLayout.tsx
index 0c202ff..c1ec019 100644
--- a/developer-portal/components/DevPortalLayout.tsx
+++ b/developer-portal/components/DevPortalLayout.tsx
@@ -72,6 +72,7 @@ const navigation: NavItem[] = [
icon: