refactor: Consolidate standalone services into admin-v2, add new SDK modules
Remove standalone services (ai-compliance-sdk root, developer-portal, dsms-gateway, dsms-node, night-scheduler) and legacy compliance/dsgvo pages. Add new SDK pipeline modules (academy, document-crawler, dsb-portal, incidents, whistleblower, reporting, sso, multi-tenant, industry-templates). Add drafting engine, legal corpus files (AT/CH/DE), pitch-deck, blog and Förderantrag pages. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
317
docs-src/architecture/sdk-protection.md
Normal file
317
docs-src/architecture/sdk-protection.md
Normal file
@@ -0,0 +1,317 @@
|
||||
# SDK Protection Middleware
|
||||
|
||||
## 1. Worum geht es?
|
||||
|
||||
Die SDK Protection Middleware schuetzt die Compliance-SDK-Endpunkte vor einer bestimmten Art von Angriff: der **systematischen Enumeration**. Was bedeutet das?
|
||||
|
||||
> *Ein Wettbewerber registriert sich als zahlender Kunde und laesst ein Skript langsam und verteilt alle TOM-Controls, alle Pruefaspekte und alle Assessment-Kriterien abfragen. Aus den Ergebnissen rekonstruiert er die gesamte Compliance-Framework-Logik.*
|
||||
|
||||
Der klassische Rate Limiter (100 Requests/Minute) hilft hier nicht, weil ein cleverer Angreifer langsam vorgeht -- vielleicht nur 20 Anfragen pro Minute, dafuer systematisch und ueber Stunden. Die SDK Protection erkennt solche Muster und reagiert darauf.
|
||||
|
||||
!!! info "Kern-Designprinzip"
|
||||
**Normale Nutzer merken nichts.** Ein Lehrer, der im TOM-Modul arbeitet, greift typischerweise auf 3-5 Kategorien zu und wiederholt Anfragen an gleiche Endpunkte. Ein Angreifer durchlaeuft dagegen 40+ Kategorien in alphabetischer Reihenfolge. Genau diesen Unterschied erkennt die Middleware.
|
||||
|
||||
---
|
||||
|
||||
## 2. Wie funktioniert der Schutz?
|
||||
|
||||
Die Middleware nutzt ein **Anomaly-Score-System**. Jeder Benutzer hat einen Score, der bei 0 beginnt. Verschiedene verdaechtige Verhaltensweisen erhoehen den Score. Ueber die Zeit sinkt er wieder ab. Je hoeher der Score, desto staerker wird der Benutzer gebremst.
|
||||
|
||||
Man kann es sich wie eine Ampel vorstellen:
|
||||
|
||||
| Score | Ampel | Wirkung | Beispiel |
|
||||
|-------|-------|---------|----------|
|
||||
| 0-29 | Gruen | Keine Einschraenkung | Normaler Nutzer |
|
||||
| 30-59 | Gelb | 1-3 Sekunden Verzoegerung | Leicht auffaelliges Muster |
|
||||
| 60-84 | Orange | 5-10 Sekunden Verzoegerung, reduzierte Details | Deutlich verdaechtiges Verhalten |
|
||||
| 85+ | Rot | Zugriff blockiert (HTTP 429) | Sehr wahrscheinlich automatisierter Angriff |
|
||||
|
||||
### Score-Zerfall
|
||||
|
||||
Der Score sinkt automatisch: Alle 5 Minuten wird er mit dem Faktor 0,95 multipliziert. Ein Score von 60 faellt also innerhalb einer Stunde auf etwa 30 -- wenn kein neues verdaechtiges Verhalten hinzukommt.
|
||||
|
||||
---
|
||||
|
||||
## 3. Was wird erkannt?
|
||||
|
||||
Die Middleware erkennt fuenf verschiedene Anomalie-Muster:
|
||||
|
||||
### 3.1 Hohe Kategorie-Diversitaet
|
||||
|
||||
**Was:** Ein Benutzer greift innerhalb einer Stunde auf mehr als 40 verschiedene SDK-Kategorien zu.
|
||||
|
||||
**Warum verdaechtig:** Ein normaler Nutzer arbeitet in der Regel mit 3-10 Kategorien. Wer systematisch alle durchlaeuft, sammelt vermutlich Daten.
|
||||
|
||||
**Score-Erhoehung:** +15
|
||||
|
||||
```
|
||||
Normal: tom/access-control → tom/access-control → tom/encryption → tom/encryption
|
||||
(3 verschiedene Kategorien in einer Stunde)
|
||||
|
||||
Verdaechtig: tom/access-control → tom/encryption → tom/pseudonymization → tom/integrity
|
||||
→ tom/availability → tom/resilience → dsfa/threshold → dsfa/necessity → ...
|
||||
(40+ verschiedene Kategorien in einer Stunde)
|
||||
```
|
||||
|
||||
### 3.2 Burst-Erkennung
|
||||
|
||||
**Was:** Ein Benutzer sendet mehr als 15 Anfragen an die gleiche Kategorie innerhalb von 2 Minuten.
|
||||
|
||||
**Warum verdaechtig:** Selbst ein eifriger Nutzer klickt nicht 15-mal pro Minute auf denselben Endpunkt. Das deutet auf automatisiertes Scraping hin.
|
||||
|
||||
**Score-Erhoehung:** +20
|
||||
|
||||
### 3.3 Sequentielle Enumeration
|
||||
|
||||
**Was:** Die letzten 10 aufgerufenen Kategorien sind zu mindestens 70% in alphabetischer oder numerischer Reihenfolge.
|
||||
|
||||
**Warum verdaechtig:** Menschen springen zwischen Kategorien -- sie arbeiten thematisch, nicht alphabetisch. Ein Skript dagegen iteriert oft ueber eine sortierte Liste.
|
||||
|
||||
**Score-Erhoehung:** +25
|
||||
|
||||
```
|
||||
Verdaechtig: assessment_general → compliance_general → controls_general
|
||||
→ dsfa_measures → dsfa_necessity → dsfa_residual → dsfa_risks
|
||||
→ dsfa_threshold → eh_general → namespace_general
|
||||
(alphabetisch sortiert = Skript-Verhalten)
|
||||
```
|
||||
|
||||
### 3.4 Ungewoehnliche Uhrzeiten
|
||||
|
||||
**Was:** Anfragen zwischen 0:00 und 5:00 Uhr UTC.
|
||||
|
||||
**Warum verdaechtig:** Lehrer arbeiten tagsüber. Wer um 3 Uhr morgens SDK-Endpunkte abfragt, ist wahrscheinlich ein automatisierter Prozess.
|
||||
|
||||
**Score-Erhoehung:** +10
|
||||
|
||||
### 3.5 Multi-Tenant-Zugriff
|
||||
|
||||
**Was:** Ein Benutzer greift innerhalb einer Stunde auf mehr als 3 verschiedene Mandanten (Tenants) zu.
|
||||
|
||||
**Warum verdaechtig:** Ein normaler Nutzer gehoert zu einem Mandanten. Wer mehrere durchprobiert, koennte versuchen, mandantenuebergreifend Daten zu sammeln.
|
||||
|
||||
**Score-Erhoehung:** +15
|
||||
|
||||
---
|
||||
|
||||
## 4. Quota-System (Mengenbegrenzung)
|
||||
|
||||
Zusaetzlich zum Anomaly-Score gibt es klassische Mengenbegrenzungen in vier Zeitfenstern:
|
||||
|
||||
| Tier | pro Minute | pro Stunde | pro Tag | pro Monat |
|
||||
|------|-----------|-----------|---------|-----------|
|
||||
| **Free** | 30 | 500 | 3.000 | 50.000 |
|
||||
| **Standard** | 60 | 1.500 | 10.000 | 200.000 |
|
||||
| **Enterprise** | 120 | 5.000 | 50.000 | 1.000.000 |
|
||||
|
||||
Wenn ein Limit in irgendeinem Zeitfenster ueberschritten wird, erhaelt der Nutzer sofort HTTP 429 -- unabhaengig vom Anomaly-Score.
|
||||
|
||||
---
|
||||
|
||||
## 5. Architektur
|
||||
|
||||
### Datenfluss eines SDK-Requests
|
||||
|
||||
```
|
||||
Request kommt an
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Ist der Pfad geschuetzt? │
|
||||
│ (/api/sdk/*, /api/v1/tom/*, /api/v1/dsfa/*, ...) │
|
||||
│ Nein → direkt weiterleiten │
|
||||
└──────────────┬──────────────────────────────────────────────┘
|
||||
│ Ja
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ User + Tier + Kategorie extrahieren │
|
||||
│ (aus Session, API-Key oder X-SDK-Tier Header) │
|
||||
└──────────────┬──────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Multi-Window Quota pruefen │
|
||||
│ (Minute / Stunde / Tag / Monat) │
|
||||
│ Ueberschritten → HTTP 429 zurueck │
|
||||
└──────────────┬──────────────────────────────────────────────┘
|
||||
│ OK
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Anomaly-Score laden (aus Valkey) │
|
||||
│ Zeitbasierten Zerfall anwenden (×0,95 alle 5 min) │
|
||||
└──────────────┬──────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Anomalie-Detektoren ausfuehren: │
|
||||
│ ├── Diversity-Tracking (+15 wenn >40 Kategorien/h) │
|
||||
│ ├── Burst-Detection (+20 wenn >15 gleiche/2min) │
|
||||
│ ├── Sequential-Enumeration (+25 wenn sortiert) │
|
||||
│ ├── Unusual-Hours (+10 wenn 0-5 Uhr UTC) │
|
||||
│ └── Multi-Tenant (+15 wenn >3 Tenants/h) │
|
||||
└──────────────┬──────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Throttle-Level bestimmen │
|
||||
│ Level 3 (Score ≥85) → HTTP 429 │
|
||||
│ Level 2 (Score ≥60) → 5-10s Delay + reduzierte Details │
|
||||
│ Level 1 (Score ≥30) → 1-3s Delay │
|
||||
│ Level 0 → keine Einschraenkung │
|
||||
└──────────────┬──────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Request weiterleiten │
|
||||
│ Response-Headers setzen: │
|
||||
│ ├── X-SDK-Quota-Remaining-Minute/Hour │
|
||||
│ ├── X-SDK-Throttle-Level │
|
||||
│ ├── X-SDK-Detail-Reduced (bei Level ≥2) │
|
||||
│ └── X-BP-Trace (HMAC-Watermark) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Valkey-Datenstrukturen
|
||||
|
||||
Die Middleware speichert alle Tracking-Daten in Valkey (Redis-Fork). Wenn Valkey nicht erreichbar ist, wird automatisch auf eine In-Memory-Implementierung zurueckgefallen.
|
||||
|
||||
| Zweck | Valkey-Typ | Key-Muster | TTL |
|
||||
|-------|-----------|------------|-----|
|
||||
| Quota pro Zeitfenster | Sorted Set | `sdk_protect:quota:{user}:{window}` | Fenster + 10s |
|
||||
| Kategorie-Diversitaet | Set | `sdk_protect:diversity:{user}:{stunde}` | 3660s |
|
||||
| Burst-Tracking | Sorted Set | `sdk_protect:burst:{user}:{kategorie}` | 130s |
|
||||
| Sequenz-Tracking | List | `sdk_protect:seq:{user}` | 310s |
|
||||
| Anomaly-Score | Hash | `sdk_protect:score:{user}` | 86400s |
|
||||
| Tenant-Tracking | Set | `sdk_protect:tenants:{user}:{stunde}` | 3660s |
|
||||
|
||||
### Watermarking
|
||||
|
||||
Jede Antwort enthaelt einen `X-BP-Trace` Header mit einem HMAC-basierten Fingerabdruck. Damit kann nachtraeglich nachgewiesen werden, welcher Benutzer wann welche Daten abgerufen hat -- ohne dass der Benutzer den Trace veraendern kann.
|
||||
|
||||
---
|
||||
|
||||
## 6. Geschuetzte Endpunkte
|
||||
|
||||
Die Middleware schuetzt alle Pfade, die SDK- und Compliance-relevante Daten liefern:
|
||||
|
||||
| Pfad-Prefix | Bereich |
|
||||
|-------------|---------|
|
||||
| `/api/sdk/*` | SDK-Hauptendpunkte |
|
||||
| `/api/compliance/*` | Compliance-Bewertungen |
|
||||
| `/api/v1/tom/*` | Technisch-organisatorische Massnahmen |
|
||||
| `/api/v1/dsfa/*` | Datenschutz-Folgenabschaetzung |
|
||||
| `/api/v1/vvt/*` | Verarbeitungsverzeichnis |
|
||||
| `/api/v1/controls/*` | Controls und Massnahmen |
|
||||
| `/api/v1/assessment/*` | Assessment-Bewertungen |
|
||||
| `/api/v1/eh/*` | Erwartungshorizonte |
|
||||
| `/api/v1/namespace/*` | Namespace-Verwaltung |
|
||||
|
||||
Nicht geschuetzt sind `/health`, `/metrics` und `/api/health`.
|
||||
|
||||
---
|
||||
|
||||
## 7. Admin-Verwaltung
|
||||
|
||||
Ueber das Admin-Dashboard koennen Anomaly-Scores eingesehen und verwaltet werden:
|
||||
|
||||
| Endpoint | Methode | Beschreibung |
|
||||
|----------|---------|--------------|
|
||||
| `/api/admin/middleware/sdk-protection/scores` | GET | Aktuelle Anomaly-Scores aller Benutzer |
|
||||
| `/api/admin/middleware/sdk-protection/stats` | GET | Statistik: Benutzer pro Throttle-Level |
|
||||
| `/api/admin/middleware/sdk-protection/reset-score/{user_id}` | POST | Score eines Benutzers zuruecksetzen |
|
||||
| `/api/admin/middleware/sdk-protection/tiers` | GET | Tier-Konfigurationen anzeigen |
|
||||
| `/api/admin/middleware/sdk-protection/tiers/{name}` | PUT | Tier-Limits aendern |
|
||||
|
||||
---
|
||||
|
||||
## 8. Dateien und Quellcode
|
||||
|
||||
| Datei | Beschreibung |
|
||||
|-------|--------------|
|
||||
| `backend/middleware/sdk_protection.py` | Kern-Middleware (~460 Zeilen) |
|
||||
| `backend/middleware/__init__.py` | Export der Middleware-Klassen |
|
||||
| `backend/main.py` | Registrierung im FastAPI-Stack |
|
||||
| `backend/middleware_admin_api.py` | Admin-API-Endpoints |
|
||||
| `backend/migrations/add_sdk_protection_tables.sql` | Datenbank-Migration |
|
||||
| `backend/tests/test_middleware.py` | 14 Tests fuer alle Erkennungsmechanismen |
|
||||
|
||||
---
|
||||
|
||||
## 9. Datenbank-Tabellen
|
||||
|
||||
### sdk_anomaly_scores
|
||||
|
||||
Speichert Snapshots der Anomaly-Scores fuer Audit und Analyse.
|
||||
|
||||
| Spalte | Typ | Beschreibung |
|
||||
|--------|-----|--------------|
|
||||
| `id` | UUID | Primaerschluessel |
|
||||
| `user_id` | VARCHAR(255) | Benutzer-Identifikation |
|
||||
| `score` | DECIMAL(5,2) | Aktueller Anomaly-Score |
|
||||
| `throttle_level` | SMALLINT | Aktueller Throttle-Level (0-3) |
|
||||
| `triggered_rules` | JSONB | Welche Regeln ausgeloest wurden |
|
||||
| `endpoint_diversity_count` | INT | Anzahl verschiedener Kategorien |
|
||||
| `request_count_1h` | INT | Anfragen in der letzten Stunde |
|
||||
| `snapshot_at` | TIMESTAMPTZ | Zeitpunkt des Snapshots |
|
||||
|
||||
### sdk_protection_tiers
|
||||
|
||||
Konfigurierbare Quota-Tiers, editierbar ueber die Admin-API.
|
||||
|
||||
| Spalte | Typ | Beschreibung |
|
||||
|--------|-----|--------------|
|
||||
| `tier_name` | VARCHAR(50) | Name des Tiers (free, standard, enterprise) |
|
||||
| `quota_per_minute` | INT | Maximale Anfragen pro Minute |
|
||||
| `quota_per_hour` | INT | Maximale Anfragen pro Stunde |
|
||||
| `quota_per_day` | INT | Maximale Anfragen pro Tag |
|
||||
| `quota_per_month` | INT | Maximale Anfragen pro Monat |
|
||||
| `diversity_threshold` | INT | Max verschiedene Kategorien pro Stunde |
|
||||
| `burst_threshold` | INT | Max gleiche Kategorie in 2 Minuten |
|
||||
|
||||
---
|
||||
|
||||
## 10. Konfiguration
|
||||
|
||||
Die Middleware wird in `main.py` registriert:
|
||||
|
||||
```python
|
||||
from middleware import SDKProtectionMiddleware
|
||||
|
||||
app.add_middleware(SDKProtectionMiddleware)
|
||||
```
|
||||
|
||||
Alle Parameter koennen ueber die `SDKProtectionConfig` Dataclass angepasst werden. Die wichtigsten Umgebungsvariablen:
|
||||
|
||||
| Variable | Default | Beschreibung |
|
||||
|----------|---------|--------------|
|
||||
| `VALKEY_URL` | `redis://localhost:6379` | Verbindung zur Valkey-Instanz |
|
||||
| `SDK_WATERMARK_SECRET` | (generiert) | HMAC-Secret fuer Watermarks |
|
||||
|
||||
---
|
||||
|
||||
## 11. Tests
|
||||
|
||||
Die Middleware wird durch 14 automatisierte Tests abgedeckt:
|
||||
|
||||
```bash
|
||||
# Alle SDK Protection Tests ausfuehren
|
||||
docker compose run --rm --no-deps backend \
|
||||
python -m pytest tests/test_middleware.py -v -k sdk
|
||||
```
|
||||
|
||||
| Test | Prueft |
|
||||
|------|--------|
|
||||
| `test_allows_normal_request` | Normaler Request wird durchgelassen |
|
||||
| `test_blocks_after_quota_exceeded` | 429 bei Quota-Ueberschreitung |
|
||||
| `test_diversity_tracking_increments_score` | Viele Kategorien erhoehen den Score |
|
||||
| `test_burst_detection` | Schnelle gleiche Anfragen erhoehen den Score |
|
||||
| `test_sequential_enumeration_detection` | Alphabetische Muster werden erkannt |
|
||||
| `test_progressive_throttling_level_1` | Delay bei Score >= 30 |
|
||||
| `test_progressive_throttling_level_3_blocks` | Block bei Score >= 85 |
|
||||
| `test_score_decay_over_time` | Score sinkt ueber die Zeit |
|
||||
| `test_skips_non_protected_paths` | Nicht-SDK-Pfade bleiben frei |
|
||||
| `test_watermark_header_present` | X-BP-Trace Header vorhanden |
|
||||
| `test_fallback_to_inmemory` | Funktioniert ohne Valkey |
|
||||
| `test_no_user_passes_through` | Anonyme Requests passieren |
|
||||
| `test_category_extraction` | Korrekte Kategorie-Zuordnung |
|
||||
| `test_quota_headers_present` | Response-Headers vorhanden |
|
||||
456
docs-src/services/klausur-service/byoeh-system-erklaerung.md
Normal file
456
docs-src/services/klausur-service/byoeh-system-erklaerung.md
Normal file
@@ -0,0 +1,456 @@
|
||||
# Wie funktioniert das Klausur-Namespace-System?
|
||||
|
||||
Eine umfassende Erklaerung des BYOEH-Systems -- von der Anonymisierung bis zur sicheren KI-Korrektur.
|
||||
|
||||
---
|
||||
|
||||
## 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:
|
||||
|
||||
1. **Pseudonymisierung:** Namen werden durch zufaellige Codes ersetzt. Niemand ausser dem Lehrer kennt die Zuordnung.
|
||||
2. **Verschluesselung:** Alles wird *im Browser des Lehrers* verschluesselt, bevor es den Rechner verlaesst. Der Server sieht nur unlesbaren Datensalat.
|
||||
3. **Namespace-Isolation:** Jeder Lehrer hat einen eigenen, abgeschotteten Bereich (Namespace). Kein Lehrer kann auf die Daten eines anderen zugreifen.
|
||||
4. **KI-Korrektur:** Die KI arbeitet mit den verschluesselten Daten und dem Erwartungshorizont (EH) des Lehrers. Korrekturvorschlaege gehen zurueck an den Lehrer.
|
||||
|
||||
!!! info "Kern-Designprinzip: Operator Blindness"
|
||||
**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 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:
|
||||
|
||||
```text title="Der komplette Workflow: Von der Klausur zur KI-Korrektur"
|
||||
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: 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:
|
||||
|
||||
```text title="Datenbank: ExamSession (vereinfacht)"
|
||||
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)
|
||||
```
|
||||
|
||||
!!! success "DSGVO Art. 4 Nr. 5 konform"
|
||||
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: Wie Daten geschuetzt werden
|
||||
|
||||
Die Verschluesselung ist das Herzstueck 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:
|
||||
|
||||
```text title="Client-seitige Verschluesselung (im Browser)"
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 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 will mitlesen** | Verschluesselte Blobs, kein Schluessel | Operator Blindness |
|
||||
| **Anderer Lehrer versucht Zugriff** | Nichts (Tenant-Isolation) | Namespace blockiert |
|
||||
|
||||
---
|
||||
|
||||
## 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:
|
||||
|
||||
```text title="Tenant-Isolation in der Vektordatenbank (Qdrant)"
|
||||
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
|
||||
|
||||
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 |
|
||||
|
||||
!!! warning "Kein Training mit Lehrerdaten"
|
||||
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: 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:
|
||||
|
||||
```text title="Indexierung: Vom PDF zum durchsuchbaren EH"
|
||||
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 fuer Kontext)
|
||||
└──────────┬─────────────────────┘
|
||||
|
|
||||
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:
|
||||
|
||||
1. **Frage formulieren:** Das System erstellt eine Suchanfrage aus dem Klausurtext und dem aktuellen Bewertungskriterium.
|
||||
2. **Semantische Suche:** Die Anfrage wird in einen Vektor umgewandelt und gegen die EH-Vektoren in Qdrant gesucht -- *nur im Namespace des Lehrers*.
|
||||
3. **Entschluesselung:** Die gefundenen Chunks werden mit der Passphrase des Lehrers entschluesselt.
|
||||
4. **KI-Antwort:** Die entschluesselten EH-Passagen werden als Kontext an die KI uebergeben, die daraus einen Korrekturvorschlag generiert.
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
|
||||
```text title="Key Sharing: Sicheres Teilen zwischen Pruefern"
|
||||
Erstpruefer Server Zweitpruefer
|
||||
│ │ │
|
||||
│ 1. Einladung senden │ │
|
||||
│ (E-Mail + Rolle + Klausur) │ │
|
||||
│─────────────────────────────────▶ │
|
||||
│ │ │
|
||||
│ │ 2. Einladung erstellt │
|
||||
│ │ (14 Tage gueltig) │
|
||||
│ │ │
|
||||
│ │ 3. Benachrichtigung ──────▶│
|
||||
│ │ │
|
||||
│ │ 4. Annehmen
|
||||
│ │◀─────────────────────────────│
|
||||
│ │ │
|
||||
│ │ 5. Key-Share erstellt │
|
||||
│ │ │
|
||||
│ │ 6. Zweitpruefer kann ──────▶│
|
||||
│ │ RAG-Queries ausfuehren │
|
||||
│ │ │
|
||||
│ 7. Zugriff widerrufen │ │
|
||||
│ (jederzeit moeglich) │ │
|
||||
│─────────────────────────────────▶ │
|
||||
```
|
||||
|
||||
### 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. 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) der gymnasialen Oberstufe.
|
||||
|
||||
!!! info "KI schlaegt vor, Lehrer entscheidet"
|
||||
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: 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 (Technische Referenz)
|
||||
|
||||
Alle Endpunkte laufen ueber den **klausur-service** auf Port 8086.
|
||||
|
||||
### 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 im Code
|
||||
|
||||
```text title="Relevante Dateien im Repository"
|
||||
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: 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 |
|
||||
|
||||
!!! success "Das Wichtigste in einem Satz"
|
||||
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.
|
||||
Reference in New Issue
Block a user