Initial commit: breakpilot-lehrer - Lehrer KI Platform
Services: Admin-Lehrer, Backend-Lehrer, Studio v2, Website, Klausur-Service, School-Service, Voice-Service, Geo-Service, BreakPilot Drive, Agent-Core Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
468
klausur-service/docs/BYOEH-Architecture.md
Normal file
468
klausur-service/docs/BYOEH-Architecture.md
Normal file
@@ -0,0 +1,468 @@
|
||||
# BYOEH (Bring-Your-Own-Expectation-Horizon) - Architecture Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
The BYOEH module enables teachers to upload their own Erwartungshorizonte (expectation horizons/grading rubrics) and use them for RAG-assisted grading suggestions. Key design principles:
|
||||
|
||||
- **Tenant Isolation**: Each teacher/school has an isolated namespace
|
||||
- **No Training Guarantee**: EH content is only used for RAG, never for model training
|
||||
- **Operator Blindness**: Client-side encryption ensures Breakpilot cannot view plaintext
|
||||
- **Rights Confirmation**: Required legal acknowledgment at upload time
|
||||
|
||||
## Architecture Diagram
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ klausur-service (Port 8086) │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ ┌────────────────────┐ ┌─────────────────────────────────────────┐ │
|
||||
│ │ BYOEH REST API │ │ BYOEH Service Layer │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ POST /api/v1/eh │───▶│ - Upload Wizard Logic │ │
|
||||
│ │ GET /api/v1/eh │ │ - Rights Confirmation │ │
|
||||
│ │ DELETE /api/v1/eh │ │ - Chunking Pipeline │ │
|
||||
│ │ POST /rag-query │ │ - Encryption Service │ │
|
||||
│ └────────────────────┘ └────────────────────┬────────────────────┘ │
|
||||
└─────────────────────────────────────────────────┼────────────────────────┘
|
||||
│
|
||||
┌───────────────────────────────────────┼───────────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌──────────────────────┐ ┌──────────────────────────┐ ┌──────────────────────┐
|
||||
│ PostgreSQL │ │ Qdrant │ │ Encrypted Storage │
|
||||
│ (Metadata + Audit) │ │ (Vector Search) │ │ /app/eh-uploads/ │
|
||||
│ │ │ │ │ │
|
||||
│ In-Memory Storage: │ │ Collection: bp_eh │ │ {tenant}/{eh_id}/ │
|
||||
│ - erwartungshorizonte│ │ - tenant_id (filter) │ │ encrypted.bin │
|
||||
│ - eh_chunks │ │ - eh_id │ │ salt.txt │
|
||||
│ - eh_key_shares │ │ - embedding[1536] │ │ │
|
||||
│ - eh_klausur_links │ │ - encrypted_content │ └──────────────────────┘
|
||||
│ - eh_audit_log │ │ │
|
||||
└──────────────────────┘ └──────────────────────────┘
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
|
||||
### 1. Upload Flow
|
||||
|
||||
```
|
||||
Browser Backend Storage
|
||||
│ │ │
|
||||
│ 1. User selects PDF │ │
|
||||
│ 2. User enters passphrase │ │
|
||||
│ 3. PBKDF2 key derivation │ │
|
||||
│ 4. AES-256-GCM encryption │ │
|
||||
│ 5. SHA-256 key hash │ │
|
||||
│ │ │
|
||||
│──────────────────────────────▶│ │
|
||||
│ POST /api/v1/eh/upload │ │
|
||||
│ (encrypted blob + key_hash) │ │
|
||||
│ │──────────────────────────────▶│
|
||||
│ │ Store encrypted.bin + salt │
|
||||
│ │◀──────────────────────────────│
|
||||
│ │ │
|
||||
│ │ Save metadata to DB │
|
||||
│◀──────────────────────────────│ │
|
||||
│ Return EH record │ │
|
||||
```
|
||||
|
||||
### 2. Indexing Flow (RAG Preparation)
|
||||
|
||||
```
|
||||
Browser Backend Qdrant
|
||||
│ │ │
|
||||
│──────────────────────────────▶│ │
|
||||
│ POST /api/v1/eh/{id}/index │ │
|
||||
│ (passphrase for decryption) │ │
|
||||
│ │ │
|
||||
│ │ 1. Verify key hash │
|
||||
│ │ 2. Decrypt content │
|
||||
│ │ 3. Extract text (PDF) │
|
||||
│ │ 4. Chunk text │
|
||||
│ │ 5. Generate embeddings │
|
||||
│ │ 6. Re-encrypt each chunk │
|
||||
│ │──────────────────────────────▶│
|
||||
│ │ Index vectors + encrypted │
|
||||
│ │ chunks with tenant filter │
|
||||
│◀──────────────────────────────│ │
|
||||
│ Return chunk count │ │
|
||||
```
|
||||
|
||||
### 3. RAG Query Flow
|
||||
|
||||
```
|
||||
Browser Backend Qdrant
|
||||
│ │ │
|
||||
│──────────────────────────────▶│ │
|
||||
│ POST /api/v1/eh/rag-query │ │
|
||||
│ (query + passphrase) │ │
|
||||
│ │ │
|
||||
│ │ 1. Generate query embedding │
|
||||
│ │──────────────────────────────▶│
|
||||
│ │ 2. Semantic search │
|
||||
│ │ (tenant-filtered) │
|
||||
│ │◀──────────────────────────────│
|
||||
│ │ 3. Decrypt matched chunks │
|
||||
│◀──────────────────────────────│ │
|
||||
│ Return decrypted context │ │
|
||||
```
|
||||
|
||||
## Security Architecture
|
||||
|
||||
### Client-Side Encryption
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Browser (Client-Side) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 1. User enters passphrase (NEVER sent to server) │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ 2. Key Derivation: PBKDF2-SHA256(passphrase, salt, 100k iter) │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ 3. Encryption: AES-256-GCM(key, iv, file_content) │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ 4. Key-Hash: SHA-256(derived_key) → server verification only │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ 5. Upload: encrypted_blob + key_hash + salt (NOT key!) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Security Guarantees
|
||||
|
||||
| Guarantee | Implementation |
|
||||
|-----------|----------------|
|
||||
| **No Training** | `training_allowed: false` on all Qdrant points |
|
||||
| **Operator Blindness** | Passphrase never leaves browser; server only sees key hash |
|
||||
| **Tenant Isolation** | Every query filtered by `tenant_id` |
|
||||
| **Audit Trail** | All actions logged with timestamps |
|
||||
|
||||
## Key Sharing System
|
||||
|
||||
The key sharing system enables first examiners to grant access to their EH to second examiners and supervisors.
|
||||
|
||||
### Share Flow
|
||||
|
||||
```
|
||||
First Examiner Backend Second Examiner
|
||||
│ │ │
|
||||
│ 1. Encrypt passphrase for │ │
|
||||
│ recipient (client-side) │ │
|
||||
│ │ │
|
||||
│─────────────────────────────▶ │
|
||||
│ POST /eh/{id}/share │ │
|
||||
│ (encrypted_passphrase, role)│ │
|
||||
│ │ │
|
||||
│ │ Store EHKeyShare │
|
||||
│◀───────────────────────────── │
|
||||
│ │ │
|
||||
│ │ │
|
||||
│ │◀────────────────────────────│
|
||||
│ │ GET /eh/shared-with-me │
|
||||
│ │ │
|
||||
│ │─────────────────────────────▶
|
||||
│ │ Return shared EH list │
|
||||
│ │ │
|
||||
│ │◀────────────────────────────│
|
||||
│ │ RAG query with decrypted │
|
||||
│ │ passphrase │
|
||||
```
|
||||
|
||||
### Data Structures
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EHKeyShare:
|
||||
id: str
|
||||
eh_id: str
|
||||
user_id: str # Recipient
|
||||
encrypted_passphrase: str # Client-encrypted for recipient
|
||||
passphrase_hint: str # Optional hint
|
||||
granted_by: str # Grantor user ID
|
||||
granted_at: datetime
|
||||
role: str # second_examiner, third_examiner, supervisor
|
||||
klausur_id: Optional[str] # Link to specific Klausur
|
||||
active: bool
|
||||
|
||||
@dataclass
|
||||
class EHKlausurLink:
|
||||
id: str
|
||||
eh_id: str
|
||||
klausur_id: str
|
||||
linked_by: str
|
||||
linked_at: datetime
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Core EH Endpoints
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| POST | `/api/v1/eh/upload` | Upload encrypted EH |
|
||||
| GET | `/api/v1/eh` | List user's EH |
|
||||
| GET | `/api/v1/eh/{id}` | Get single EH |
|
||||
| DELETE | `/api/v1/eh/{id}` | Soft delete EH |
|
||||
| POST | `/api/v1/eh/{id}/index` | Index EH for RAG |
|
||||
| POST | `/api/v1/eh/rag-query` | Query EH content |
|
||||
|
||||
### Key Sharing Endpoints
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| POST | `/api/v1/eh/{id}/share` | Share EH with examiner |
|
||||
| GET | `/api/v1/eh/{id}/shares` | List shares (owner) |
|
||||
| DELETE | `/api/v1/eh/{id}/shares/{shareId}` | Revoke share |
|
||||
| GET | `/api/v1/eh/shared-with-me` | List EH shared with user |
|
||||
|
||||
### Klausur Integration Endpoints
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| POST | `/api/v1/eh/{id}/link-klausur` | Link EH to Klausur |
|
||||
| DELETE | `/api/v1/eh/{id}/link-klausur/{klausurId}` | Unlink EH |
|
||||
| GET | `/api/v1/klausuren/{id}/linked-eh` | Get linked EH for Klausur |
|
||||
|
||||
### Audit & Admin Endpoints
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| GET | `/api/v1/eh/audit-log` | Get audit log |
|
||||
| GET | `/api/v1/eh/rights-text` | Get rights confirmation text |
|
||||
| GET | `/api/v1/eh/qdrant-status` | Get Qdrant status (admin) |
|
||||
|
||||
## Frontend Components
|
||||
|
||||
### EHUploadWizard
|
||||
|
||||
5-step wizard for uploading Erwartungshorizonte:
|
||||
|
||||
1. **File Selection** - Choose PDF file
|
||||
2. **Metadata** - Title, Subject, Niveau, Year
|
||||
3. **Rights Confirmation** - Legal acknowledgment
|
||||
4. **Encryption** - Set passphrase (2x confirmation)
|
||||
5. **Summary** - Review and upload
|
||||
|
||||
### Integration Points
|
||||
|
||||
- **KorrekturPage**: Shows EH prompt after first student upload
|
||||
- **GutachtenGeneration**: Uses RAG context from linked EH
|
||||
- **Sidebar Badge**: Shows linked EH count
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
klausur-service/
|
||||
├── backend/
|
||||
│ ├── main.py # API endpoints + data structures
|
||||
│ ├── qdrant_service.py # Vector database operations
|
||||
│ ├── eh_pipeline.py # Chunking, embedding, encryption
|
||||
│ └── requirements.txt # Python dependencies
|
||||
├── frontend/
|
||||
│ └── src/
|
||||
│ ├── components/
|
||||
│ │ └── EHUploadWizard.tsx
|
||||
│ ├── services/
|
||||
│ │ ├── api.ts # API client
|
||||
│ │ └── encryption.ts # Client-side crypto
|
||||
│ ├── pages/
|
||||
│ │ └── KorrekturPage.tsx # EH integration
|
||||
│ └── styles/
|
||||
│ └── eh-wizard.css
|
||||
└── docs/
|
||||
├── BYOEH-Architecture.md
|
||||
└── BYOEH-Developer-Guide.md
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```env
|
||||
QDRANT_URL=http://qdrant:6333
|
||||
OPENAI_API_KEY=sk-... # For embeddings
|
||||
BYOEH_ENCRYPTION_ENABLED=true
|
||||
EH_UPLOAD_DIR=/app/eh-uploads
|
||||
```
|
||||
|
||||
### Docker Services
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
qdrant:
|
||||
image: qdrant/qdrant:v1.7.4
|
||||
ports:
|
||||
- "6333:6333"
|
||||
volumes:
|
||||
- qdrant_data:/qdrant/storage
|
||||
```
|
||||
|
||||
## Audit Events
|
||||
|
||||
| Action | Description |
|
||||
|--------|-------------|
|
||||
| `upload` | EH uploaded |
|
||||
| `index` | EH indexed for RAG |
|
||||
| `rag_query` | RAG query executed |
|
||||
| `delete` | EH soft deleted |
|
||||
| `share` | EH shared with examiner |
|
||||
| `revoke_share` | Share revoked |
|
||||
| `link_klausur` | EH linked to Klausur |
|
||||
| `unlink_klausur` | EH unlinked from Klausur |
|
||||
|
||||
---
|
||||
|
||||
## RBAC Extensions for Zeugnis System
|
||||
|
||||
The RBAC system has been extended to support the Zeugnis (Certificate) workflow. This enables role-based access control for certificate generation, approval, and management.
|
||||
|
||||
### Certificate-Related Roles
|
||||
|
||||
```python
|
||||
class Role(str, Enum):
|
||||
# Existing exam roles
|
||||
ERSTPRUEFER = "erstpruefer" # First examiner
|
||||
ZWEITPRUEFER = "zweitpruefer" # Second examiner
|
||||
DRITTPRUEFER = "drittpruefer" # Third examiner
|
||||
FACHVORSITZ = "fachvorsitz" # Subject chair
|
||||
|
||||
# Certificate workflow roles
|
||||
FACHLEHRER = "fachlehrer" # Subject teacher - enters grades
|
||||
KLASSENLEHRER = "klassenlehrer" # Class teacher - approves grades
|
||||
ZEUGNISBEAUFTRAGTER = "zeugnisbeauftragter" # Certificate coordinator
|
||||
SCHULLEITUNG = "schulleitung" # Principal - final sign-off
|
||||
SEKRETARIAT = "sekretariat" # Secretary - printing
|
||||
```
|
||||
|
||||
### Certificate Resource Types
|
||||
|
||||
```python
|
||||
class ResourceType(str, Enum):
|
||||
# Existing types
|
||||
KLAUSUR = "klausur"
|
||||
ERWARTUNGSHORIZONT = "erwartungshorizont"
|
||||
|
||||
# Certificate types
|
||||
ZEUGNIS = "zeugnis" # Final certificate
|
||||
ZEUGNIS_VORLAGE = "zeugnis_vorlage" # Certificate template
|
||||
ZEUGNIS_ENTWURF = "zeugnis_entwurf" # Draft certificate
|
||||
FACHNOTE = "fachnote" # Subject grade
|
||||
KOPFNOTE = "kopfnote" # Head grade (Arbeits-/Sozialverhalten)
|
||||
BEMERKUNG = "bemerkung" # Certificate remarks
|
||||
STATISTIK = "statistik" # Class/subject statistics
|
||||
NOTENSPIEGEL = "notenspiegel" # Grade distribution
|
||||
```
|
||||
|
||||
### VerfahrenType Extension
|
||||
|
||||
```python
|
||||
class VerfahrenType(str, Enum):
|
||||
# Exam types
|
||||
ABITUR = "abitur"
|
||||
KLAUSUR = "klausur"
|
||||
NACHSCHREIBKLAUSUR = "nachschreibklausur"
|
||||
|
||||
# Certificate types (NEW)
|
||||
HALBJAHRESZEUGNIS = "halbjahreszeugnis" # Mid-year certificate
|
||||
JAHRESZEUGNIS = "jahreszeugnis" # End-of-year certificate
|
||||
ABSCHLUSSZEUGNIS = "abschlusszeugnis" # Graduation certificate
|
||||
ABGANGSZEUGNIS = "abgangszeugnis" # Leaving certificate
|
||||
|
||||
@classmethod
|
||||
def is_certificate_type(cls, verfahren: "VerfahrenType") -> bool:
|
||||
"""Check if this is a certificate type (not an exam)."""
|
||||
cert_types = {
|
||||
cls.HALBJAHRESZEUGNIS,
|
||||
cls.JAHRESZEUGNIS,
|
||||
cls.ABSCHLUSSZEUGNIS,
|
||||
cls.ABGANGSZEUGNIS
|
||||
}
|
||||
return verfahren in cert_types
|
||||
```
|
||||
|
||||
### Certificate Workflow Permissions
|
||||
|
||||
```
|
||||
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────────┐
|
||||
│ FACHLEHRER │───▶│ KLASSENLEHRER │───▶│ ZEUGNISBEAUFTRAGTER │
|
||||
│ │ │ │ │ │
|
||||
│ FACHNOTE: CRUD │ │ ZEUGNIS: CRU │ │ ZEUGNIS: RU │
|
||||
│ ZEUGNIS_ENTWURF:R │ │ ZEUGNIS_ENTWURF: │ │ ZEUGNIS_VORLAGE: RUU │
|
||||
│ │ │ CRUD │ │ │
|
||||
└───────────────────┘ └───────────────────┘ └───────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌───────────────────┐ ┌───────────────────────┐
|
||||
│ SEKRETARIAT │◀───│ SCHULLEITUNG │
|
||||
│ │ │ │
|
||||
│ ZEUGNIS: RD │ │ ZEUGNIS: R/SIGN/LOCK │
|
||||
│ (Print & Archive) │ │ (Final Approval) │
|
||||
└───────────────────┘ └───────────────────────┘
|
||||
```
|
||||
|
||||
### DEFAULT_PERMISSIONS for Certificate Roles
|
||||
|
||||
```python
|
||||
DEFAULT_PERMISSIONS = {
|
||||
# ... existing roles ...
|
||||
|
||||
Role.KLASSENLEHRER: {
|
||||
ResourceType.KLASSE: {Action.READ, Action.UPDATE},
|
||||
ResourceType.SCHUELER: {Action.READ, Action.CREATE, Action.UPDATE},
|
||||
ResourceType.FACHNOTE: {Action.CREATE, Action.READ, Action.UPDATE, Action.DELETE},
|
||||
ResourceType.ZEUGNIS: {Action.CREATE, Action.READ, Action.UPDATE},
|
||||
ResourceType.ZEUGNIS_ENTWURF: {Action.CREATE, Action.READ, Action.UPDATE, Action.DELETE},
|
||||
ResourceType.ZEUGNIS_VORLAGE: {Action.READ},
|
||||
ResourceType.KOPFNOTE: {Action.CREATE, Action.READ, Action.UPDATE},
|
||||
ResourceType.BEMERKUNG: {Action.CREATE, Action.READ, Action.UPDATE, Action.DELETE},
|
||||
ResourceType.STATISTIK: {Action.READ},
|
||||
ResourceType.NOTENSPIEGEL: {Action.READ},
|
||||
},
|
||||
|
||||
Role.ZEUGNISBEAUFTRAGTER: {
|
||||
ResourceType.KLASSE: {Action.READ},
|
||||
ResourceType.ZEUGNIS: {Action.READ, Action.UPDATE},
|
||||
ResourceType.ZEUGNIS_ENTWURF: {Action.READ, Action.UPDATE},
|
||||
ResourceType.ZEUGNIS_VORLAGE: {Action.READ, Action.UPDATE, Action.UPLOAD},
|
||||
ResourceType.STATISTIK: {Action.READ},
|
||||
ResourceType.NOTENSPIEGEL: {Action.READ},
|
||||
},
|
||||
|
||||
Role.SEKRETARIAT: {
|
||||
ResourceType.ZEUGNIS: {Action.READ, Action.DOWNLOAD},
|
||||
ResourceType.ZEUGNIS_VORLAGE: {Action.READ},
|
||||
},
|
||||
|
||||
Role.SCHULLEITUNG: {
|
||||
ResourceType.ZEUGNIS: {Action.READ, Action.SIGN_OFF, Action.LOCK},
|
||||
ResourceType.ZEUGNIS_ENTWURF: {Action.READ, Action.UPDATE},
|
||||
ResourceType.ZEUGNIS_VORLAGE: {Action.READ, Action.UPDATE},
|
||||
ResourceType.STATISTIK: {Action.READ},
|
||||
ResourceType.NOTENSPIEGEL: {Action.READ},
|
||||
},
|
||||
|
||||
Role.FACHLEHRER: {
|
||||
ResourceType.FACHNOTE: {Action.CREATE, Action.READ, Action.UPDATE, Action.DELETE},
|
||||
ResourceType.ZEUGNIS: {Action.READ, Action.UPDATE},
|
||||
ResourceType.ZEUGNIS_ENTWURF: {Action.READ, Action.UPDATE},
|
||||
ResourceType.STATISTIK: {Action.READ},
|
||||
ResourceType.NOTENSPIEGEL: {Action.READ},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### See Also
|
||||
|
||||
For complete Zeugnis system documentation including:
|
||||
- Full workflow diagrams
|
||||
- Statistics API endpoints
|
||||
- Frontend components
|
||||
- Seed data generator
|
||||
|
||||
See: [docs/architecture/zeugnis-system.md](../../docs/architecture/zeugnis-system.md)
|
||||
481
klausur-service/docs/BYOEH-Developer-Guide.md
Normal file
481
klausur-service/docs/BYOEH-Developer-Guide.md
Normal file
@@ -0,0 +1,481 @@
|
||||
# BYOEH Developer Guide
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Python 3.10+
|
||||
- Node.js 18+
|
||||
- Docker & Docker Compose
|
||||
- OpenAI API Key (for embeddings)
|
||||
|
||||
### Setup
|
||||
|
||||
1. **Start services:**
|
||||
```bash
|
||||
docker-compose up -d qdrant
|
||||
```
|
||||
|
||||
2. **Configure environment:**
|
||||
```env
|
||||
QDRANT_URL=http://localhost:6333
|
||||
OPENAI_API_KEY=sk-your-key
|
||||
BYOEH_ENCRYPTION_ENABLED=true
|
||||
```
|
||||
|
||||
3. **Run klausur-service:**
|
||||
```bash
|
||||
cd klausur-service/backend
|
||||
pip install -r requirements.txt
|
||||
uvicorn main:app --reload --port 8086
|
||||
```
|
||||
|
||||
4. **Run frontend:**
|
||||
```bash
|
||||
cd klausur-service/frontend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Client-Side Encryption
|
||||
|
||||
The encryption service (`encryption.ts`) handles all cryptographic operations in the browser:
|
||||
|
||||
### Encrypting a File
|
||||
|
||||
```typescript
|
||||
import { encryptFile, generateSalt } from '../services/encryption'
|
||||
|
||||
const file = document.getElementById('fileInput').files[0]
|
||||
const passphrase = 'user-secret-password'
|
||||
|
||||
const encrypted = await encryptFile(file, passphrase)
|
||||
// Result:
|
||||
// {
|
||||
// encryptedData: ArrayBuffer,
|
||||
// keyHash: string, // SHA-256 hash for verification
|
||||
// salt: string, // Hex-encoded salt
|
||||
// iv: string // Hex-encoded initialization vector
|
||||
// }
|
||||
```
|
||||
|
||||
### Decrypting Content
|
||||
|
||||
```typescript
|
||||
import { decryptText, verifyPassphrase } from '../services/encryption'
|
||||
|
||||
// First verify the passphrase
|
||||
const isValid = await verifyPassphrase(passphrase, salt, expectedKeyHash)
|
||||
|
||||
if (isValid) {
|
||||
const decrypted = await decryptText(encryptedBase64, passphrase, salt)
|
||||
}
|
||||
```
|
||||
|
||||
## Backend API Usage
|
||||
|
||||
### Upload an Erwartungshorizont
|
||||
|
||||
```python
|
||||
# The upload endpoint accepts FormData with:
|
||||
# - file: encrypted binary blob
|
||||
# - metadata_json: JSON string with metadata
|
||||
|
||||
POST /api/v1/eh/upload
|
||||
Content-Type: multipart/form-data
|
||||
|
||||
{
|
||||
"file": <encrypted_blob>,
|
||||
"metadata_json": {
|
||||
"metadata": {
|
||||
"title": "Deutsch LK 2025",
|
||||
"subject": "deutsch",
|
||||
"niveau": "eA",
|
||||
"year": 2025,
|
||||
"aufgaben_nummer": "Aufgabe 1"
|
||||
},
|
||||
"encryption_key_hash": "abc123...",
|
||||
"salt": "def456...",
|
||||
"rights_confirmed": true,
|
||||
"original_filename": "erwartungshorizont.pdf"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Index for RAG
|
||||
|
||||
```python
|
||||
POST /api/v1/eh/{eh_id}/index
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"passphrase": "user-secret-password"
|
||||
}
|
||||
```
|
||||
|
||||
The backend will:
|
||||
1. Verify the passphrase against stored key hash
|
||||
2. Decrypt the file
|
||||
3. Extract text from PDF
|
||||
4. Chunk the text (1000 chars, 200 overlap)
|
||||
5. Generate OpenAI embeddings
|
||||
6. Re-encrypt each chunk
|
||||
7. Index in Qdrant with tenant filter
|
||||
|
||||
### RAG Query
|
||||
|
||||
```python
|
||||
POST /api/v1/eh/rag-query
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"query_text": "Wie sollte die Einleitung strukturiert sein?",
|
||||
"passphrase": "user-secret-password",
|
||||
"subject": "deutsch", # Optional filter
|
||||
"limit": 5 # Max results
|
||||
}
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"context": "Die Einleitung sollte...",
|
||||
"sources": [
|
||||
{
|
||||
"text": "Die Einleitung sollte...",
|
||||
"eh_id": "uuid",
|
||||
"eh_title": "Deutsch LK 2025",
|
||||
"chunk_index": 2,
|
||||
"score": 0.89
|
||||
}
|
||||
],
|
||||
"query": "Wie sollte die Einleitung strukturiert sein?"
|
||||
}
|
||||
```
|
||||
|
||||
## Key Sharing Implementation
|
||||
|
||||
### Invitation Flow (Recommended)
|
||||
|
||||
The invitation flow provides a two-phase sharing process: Invite -> Accept
|
||||
|
||||
```typescript
|
||||
import { ehApi } from '../services/api'
|
||||
|
||||
// 1. First examiner sends invitation to second examiner
|
||||
const invitation = await ehApi.inviteToEH(ehId, {
|
||||
invitee_email: 'zweitkorrektor@school.de',
|
||||
role: 'second_examiner',
|
||||
klausur_id: 'klausur-uuid', // Optional: link to specific Klausur
|
||||
message: 'Bitte fuer Zweitkorrektur nutzen',
|
||||
expires_in_days: 14 // Default: 14 days
|
||||
})
|
||||
// Returns: { invitation_id, eh_id, invitee_email, role, expires_at, eh_title }
|
||||
|
||||
// 2. Second examiner sees pending invitation
|
||||
const pending = await ehApi.getPendingInvitations()
|
||||
// [{ invitation: {...}, eh: { id, title, subject, niveau, year } }]
|
||||
|
||||
// 3. Second examiner accepts invitation
|
||||
const accepted = await ehApi.acceptInvitation(
|
||||
invitationId,
|
||||
encryptedPassphrase // Passphrase encrypted for recipient
|
||||
)
|
||||
// Returns: { status: 'accepted', share_id, eh_id, role, klausur_id }
|
||||
```
|
||||
|
||||
### Invitation Management
|
||||
|
||||
```typescript
|
||||
// Get invitations sent by current user
|
||||
const sent = await ehApi.getSentInvitations()
|
||||
|
||||
// Decline an invitation (as invitee)
|
||||
await ehApi.declineInvitation(invitationId)
|
||||
|
||||
// Revoke a pending invitation (as inviter)
|
||||
await ehApi.revokeInvitation(invitationId)
|
||||
|
||||
// Get complete access chain for an EH
|
||||
const chain = await ehApi.getAccessChain(ehId)
|
||||
// Returns: { eh_id, eh_title, owner, active_shares, pending_invitations, revoked_shares }
|
||||
```
|
||||
|
||||
### Direct Sharing (Legacy)
|
||||
|
||||
For immediate sharing without invitation:
|
||||
|
||||
```typescript
|
||||
// First examiner shares directly with second examiner
|
||||
await ehApi.shareEH(ehId, {
|
||||
user_id: 'second-examiner-uuid',
|
||||
role: 'second_examiner',
|
||||
encrypted_passphrase: encryptedPassphrase, // Encrypted for recipient
|
||||
passphrase_hint: 'Das uebliche Passwort',
|
||||
klausur_id: 'klausur-uuid' // Optional
|
||||
})
|
||||
```
|
||||
|
||||
### Accessing Shared EH
|
||||
|
||||
```typescript
|
||||
// Second examiner gets shared EH
|
||||
const shared = await ehApi.getSharedWithMe()
|
||||
// [{ eh: {...}, share: {...} }]
|
||||
|
||||
// Query using provided passphrase
|
||||
const result = await ehApi.ragQuery({
|
||||
query_text: 'search query',
|
||||
passphrase: decryptedPassphrase,
|
||||
subject: 'deutsch'
|
||||
})
|
||||
```
|
||||
|
||||
### Revoking Access
|
||||
|
||||
```typescript
|
||||
// List all shares for an EH
|
||||
const shares = await ehApi.listShares(ehId)
|
||||
|
||||
// Revoke a share
|
||||
await ehApi.revokeShare(ehId, shareId)
|
||||
```
|
||||
|
||||
## Klausur Integration
|
||||
|
||||
### Automatic EH Prompt
|
||||
|
||||
The `KorrekturPage` shows an EH upload prompt after the first student work is uploaded:
|
||||
|
||||
```typescript
|
||||
// In KorrekturPage.tsx
|
||||
useEffect(() => {
|
||||
if (
|
||||
currentKlausur?.students.length === 1 &&
|
||||
linkedEHs.length === 0 &&
|
||||
!ehPromptDismissed
|
||||
) {
|
||||
setShowEHPrompt(true)
|
||||
}
|
||||
}, [currentKlausur?.students.length])
|
||||
```
|
||||
|
||||
### Linking EH to Klausur
|
||||
|
||||
```typescript
|
||||
// After EH upload, auto-link to Klausur
|
||||
await ehApi.linkToKlausur(ehId, klausurId)
|
||||
|
||||
// Get linked EH for a Klausur
|
||||
const linked = await klausurEHApi.getLinkedEH(klausurId)
|
||||
```
|
||||
|
||||
## Frontend Components
|
||||
|
||||
### EHUploadWizard Props
|
||||
|
||||
```typescript
|
||||
interface EHUploadWizardProps {
|
||||
onClose: () => void
|
||||
onComplete?: (ehId: string) => void
|
||||
defaultSubject?: string // Pre-fill subject
|
||||
defaultYear?: number // Pre-fill year
|
||||
klausurId?: string // Auto-link after upload
|
||||
}
|
||||
|
||||
// Usage
|
||||
<EHUploadWizard
|
||||
onClose={() => setShowWizard(false)}
|
||||
onComplete={(ehId) => console.log('Uploaded:', ehId)}
|
||||
defaultSubject={klausur.subject}
|
||||
defaultYear={klausur.year}
|
||||
klausurId={klausur.id}
|
||||
/>
|
||||
```
|
||||
|
||||
### Wizard Steps
|
||||
|
||||
1. **file** - PDF file selection with drag & drop
|
||||
2. **metadata** - Form for title, subject, niveau, year
|
||||
3. **rights** - Rights confirmation checkbox
|
||||
4. **encryption** - Passphrase input with strength meter
|
||||
5. **summary** - Review and confirm upload
|
||||
|
||||
## Qdrant Operations
|
||||
|
||||
### Collection Schema
|
||||
|
||||
```python
|
||||
# Collection: bp_eh
|
||||
{
|
||||
"vectors": {
|
||||
"size": 1536, # OpenAI text-embedding-3-small
|
||||
"distance": "Cosine"
|
||||
}
|
||||
}
|
||||
|
||||
# Point payload
|
||||
{
|
||||
"tenant_id": "school-uuid",
|
||||
"eh_id": "eh-uuid",
|
||||
"chunk_index": 0,
|
||||
"encrypted_content": "base64...",
|
||||
"training_allowed": false # ALWAYS false
|
||||
}
|
||||
```
|
||||
|
||||
### Tenant-Isolated Search
|
||||
|
||||
```python
|
||||
from qdrant_service import search_eh
|
||||
|
||||
results = await search_eh(
|
||||
query_embedding=embedding,
|
||||
tenant_id="school-uuid",
|
||||
subject="deutsch",
|
||||
limit=5
|
||||
)
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### Unit Tests
|
||||
|
||||
```bash
|
||||
cd klausur-service/backend
|
||||
pytest tests/test_byoeh.py -v
|
||||
```
|
||||
|
||||
### Test Structure
|
||||
|
||||
```python
|
||||
# tests/test_byoeh.py
|
||||
class TestBYOEH:
|
||||
def test_upload_eh(self, client, auth_headers):
|
||||
"""Test EH upload with encryption"""
|
||||
pass
|
||||
|
||||
def test_index_eh(self, client, auth_headers, uploaded_eh):
|
||||
"""Test EH indexing for RAG"""
|
||||
pass
|
||||
|
||||
def test_rag_query(self, client, auth_headers, indexed_eh):
|
||||
"""Test RAG query returns relevant chunks"""
|
||||
pass
|
||||
|
||||
def test_share_eh(self, client, auth_headers, uploaded_eh):
|
||||
"""Test sharing EH with another user"""
|
||||
pass
|
||||
```
|
||||
|
||||
### Frontend Tests
|
||||
|
||||
```typescript
|
||||
// EHUploadWizard.test.tsx
|
||||
describe('EHUploadWizard', () => {
|
||||
it('completes all steps successfully', async () => {
|
||||
// ...
|
||||
})
|
||||
|
||||
it('validates passphrase strength', async () => {
|
||||
// ...
|
||||
})
|
||||
|
||||
it('auto-links to klausur when klausurId provided', async () => {
|
||||
// ...
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Common Errors
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| `Passphrase verification failed` | Wrong passphrase | Ask user to re-enter |
|
||||
| `EH not found` | Invalid ID or deleted | Check ID, reload list |
|
||||
| `Access denied` | User not owner/shared | Check permissions |
|
||||
| `Qdrant connection failed` | Service unavailable | Check Qdrant container |
|
||||
|
||||
### Error Response Format
|
||||
|
||||
```json
|
||||
{
|
||||
"detail": "Passphrase verification failed"
|
||||
}
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Do's
|
||||
|
||||
- Store key hash, never the key itself
|
||||
- Always filter by tenant_id
|
||||
- Log all access in audit trail
|
||||
- Use HTTPS in production
|
||||
|
||||
### Don'ts
|
||||
|
||||
- Never log passphrase or decrypted content
|
||||
- Never store passphrase in localStorage
|
||||
- Never send passphrase as URL parameter
|
||||
- Never return decrypted content without auth
|
||||
|
||||
## Performance Tips
|
||||
|
||||
### Chunking Configuration
|
||||
|
||||
```python
|
||||
CHUNK_SIZE = 1000 # Characters per chunk
|
||||
CHUNK_OVERLAP = 200 # Overlap for context continuity
|
||||
```
|
||||
|
||||
### Embedding Batching
|
||||
|
||||
```python
|
||||
# Generate embeddings in batches of 20
|
||||
EMBEDDING_BATCH_SIZE = 20
|
||||
```
|
||||
|
||||
### Qdrant Optimization
|
||||
|
||||
```python
|
||||
# Use HNSW index for fast approximate search
|
||||
# Collection is automatically optimized on creation
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
### Enable Debug Logging
|
||||
|
||||
```python
|
||||
import logging
|
||||
logging.getLogger('byoeh').setLevel(logging.DEBUG)
|
||||
```
|
||||
|
||||
### Check Qdrant Status
|
||||
|
||||
```bash
|
||||
curl http://localhost:6333/collections/bp_eh
|
||||
```
|
||||
|
||||
### Verify Encryption
|
||||
|
||||
```typescript
|
||||
import { isEncryptionSupported } from '../services/encryption'
|
||||
|
||||
if (!isEncryptionSupported()) {
|
||||
console.error('Web Crypto API not available')
|
||||
}
|
||||
```
|
||||
|
||||
## Migration Notes
|
||||
|
||||
### From v1.0 to v1.1
|
||||
|
||||
1. Added key sharing system
|
||||
2. Added Klausur linking
|
||||
3. EH prompt after student upload
|
||||
|
||||
No database migrations required - all data structures are additive.
|
||||
788
klausur-service/docs/DSGVO-Audit-OCR-Labeling.md
Normal file
788
klausur-service/docs/DSGVO-Audit-OCR-Labeling.md
Normal file
@@ -0,0 +1,788 @@
|
||||
# DSGVO-Audit-Dokumentation: OCR-Labeling-System für Handschrifterkennung
|
||||
|
||||
**Dokumentversion:** 1.0.0
|
||||
**Datum:** 21. Januar 2026
|
||||
**Klassifizierung:** Vertraulich - Nur für internen Gebrauch und Auditoren
|
||||
**Nächste Überprüfung:** 21. Januar 2027
|
||||
|
||||
---
|
||||
|
||||
## 1. Management Summary
|
||||
|
||||
### 1.1 Systemübersicht
|
||||
|
||||
Das OCR-Labeling-System ist eine **vollständig lokal betriebene** Lösung zur Digitalisierung und Auswertung handschriftlicher Schülerarbeiten (Klausuren, Aufsätze). Das System nutzt:
|
||||
|
||||
- **llama3.2-vision:11b** - Open-Source Vision-Language-Modell für OCR (lokal via Ollama)
|
||||
- **TrOCR** - Microsoft Transformer OCR für Handschrifterkennung (lokal)
|
||||
- **qwen2.5:14b** - Open-Source LLM für Korrekturassistenz (lokal via Ollama)
|
||||
|
||||
### 1.2 Datenschutz-Garantien
|
||||
|
||||
| Merkmal | Umsetzung |
|
||||
|---------|-----------|
|
||||
| **Verarbeitungsort** | 100% lokal auf schuleigenem Mac Mini |
|
||||
| **Cloud-Dienste** | Keine - vollständig offline-fähig |
|
||||
| **Datenübertragung** | Keine Übertragung an externe Server |
|
||||
| **KI-Modelle** | Open-Source, lokal ausgeführt, kein Telemetrie |
|
||||
| **Speicherung** | Lokale PostgreSQL-Datenbank, MinIO Object Storage |
|
||||
|
||||
### 1.3 Compliance-Status
|
||||
|
||||
Das System erfüllt die Anforderungen der:
|
||||
- DSGVO (Verordnung (EU) 2016/679)
|
||||
- BDSG (Bundesdatenschutzgesetz)
|
||||
- Niedersächsisches Schulgesetz (NSchG) §31
|
||||
- EU AI Act (Verordnung (EU) 2024/1689)
|
||||
|
||||
---
|
||||
|
||||
## 2. Verzeichnis der Verarbeitungstätigkeiten (Art. 30 DSGVO)
|
||||
|
||||
### 2.1 Verantwortlicher
|
||||
|
||||
| Feld | Inhalt |
|
||||
|------|--------|
|
||||
| **Verantwortlicher** | [Schulname], [Schuladresse] |
|
||||
| **Vertreter** | Schulleitung: [Name] |
|
||||
| **Kontakt** | [E-Mail], [Telefon] |
|
||||
|
||||
### 2.2 Datenschutzbeauftragter
|
||||
|
||||
| Feld | Inhalt |
|
||||
|------|--------|
|
||||
| **Name** | [Name DSB] |
|
||||
| **Organisation** | [Behördlicher/Externer DSB] |
|
||||
| **Kontakt** | [E-Mail], [Telefon] |
|
||||
|
||||
### 2.3 Verarbeitungstätigkeiten
|
||||
|
||||
#### 2.3.1 OCR-Verarbeitung von Klausuren
|
||||
|
||||
| Attribut | Beschreibung |
|
||||
|----------|--------------|
|
||||
| **Zweck** | Digitalisierung handschriftlicher Prüfungsantworten mittels KI-gestützter Texterkennung zur Unterstützung der Lehrkräfte bei der Korrektur |
|
||||
| **Rechtsgrundlage** | Art. 6 Abs. 1 lit. e DSGVO i.V.m. §31 NSchG (öffentliche Aufgabe der Leistungsbewertung) |
|
||||
| **Betroffene Personen** | Schülerinnen und Schüler (Prüfungsarbeiten) |
|
||||
| **Datenkategorien** | Handschriftproben, Prüfungsantworten, Schülerkennung (optional) |
|
||||
| **Empfänger** | Ausschließlich berechtigte Lehrkräfte der Schule |
|
||||
| **Drittlandübermittlung** | Keine |
|
||||
| **Löschfrist** | Gem. Aufbewahrungspflichten für Prüfungsunterlagen (i.d.R. 2-10 Jahre je nach Bundesland) |
|
||||
|
||||
#### 2.3.2 Labeling für Modell-Training
|
||||
|
||||
| Attribut | Beschreibung |
|
||||
|----------|--------------|
|
||||
| **Zweck** | Erstellung von Trainingsdaten für lokales Fine-Tuning der OCR-Modelle zur Verbesserung der Handschrifterkennung |
|
||||
| **Rechtsgrundlage** | Art. 6 Abs. 1 lit. f DSGVO (berechtigtes Interesse) oder Art. 6 Abs. 1 lit. a DSGVO (Einwilligung) |
|
||||
| **Betroffene Personen** | Schülerinnen und Schüler (anonymisierte Handschriftproben) |
|
||||
| **Datenkategorien** | Anonymisierte/pseudonymisierte Handschriftbilder, korrigierter Text |
|
||||
| **Empfänger** | Lokales ML-System, keine externen Empfänger |
|
||||
| **Drittlandübermittlung** | Keine |
|
||||
| **Löschfrist** | Trainingsdaten: Nach Abschluss des Trainings oder auf Widerruf |
|
||||
|
||||
### 2.4 Verweis auf TOM
|
||||
|
||||
Siehe Abschnitt 8: Technisch-Organisatorische Maßnahmen
|
||||
|
||||
---
|
||||
|
||||
## 3. Rechtsgrundlagen (Art. 6 DSGVO)
|
||||
|
||||
### 3.1 Primäre Rechtsgrundlagen
|
||||
|
||||
| Verarbeitungsschritt | Rechtsgrundlage | Begründung |
|
||||
|---------------------|-----------------|------------|
|
||||
| Scan von Klausuren | Art. 6 Abs. 1 lit. e DSGVO | Öffentliche Aufgabe der schulischen Leistungsbewertung |
|
||||
| OCR-Verarbeitung | Art. 6 Abs. 1 lit. e DSGVO | Teil der Bewertungsaufgabe, Effizienzsteigerung |
|
||||
| Lehrerkorrektur | Art. 6 Abs. 1 lit. e DSGVO | Kernaufgabe der Leistungsbewertung |
|
||||
| Export für Training | Art. 6 Abs. 1 lit. f DSGVO | Berechtigtes Interesse an Modellverbesserung |
|
||||
|
||||
### 3.2 Landesrechtliche Grundlagen
|
||||
|
||||
**Niedersachsen:**
|
||||
- §31 NSchG: Erhebung, Verarbeitung und Nutzung personenbezogener Daten
|
||||
- Ergänzende Bestimmungen zur VO-DV I
|
||||
|
||||
**Interesse-Abwägung für Training (Art. 6 Abs. 1 lit. f):**
|
||||
|
||||
| Aspekt | Bewertung |
|
||||
|--------|-----------|
|
||||
| **Interesse des Verantwortlichen** | Verbesserung der OCR-Qualität für effizientere Klausurkorrektur |
|
||||
| **Erwartung der Betroffenen** | Schüler erwarten, dass Prüfungsarbeiten für schulische Zwecke verarbeitet werden |
|
||||
| **Auswirkung auf Betroffene** | Minimal - Daten werden pseudonymisiert, rein lokale Verarbeitung |
|
||||
| **Schutzmaßnahmen** | Pseudonymisierung, keine Weitergabe, lokale Verarbeitung |
|
||||
| **Ergebnis** | Berechtigtes Interesse überwiegt |
|
||||
|
||||
### 3.3 Besondere Kategorien (Art. 9 DSGVO)
|
||||
|
||||
**Prüfung auf besondere Kategorien:**
|
||||
|
||||
Handschriftproben könnten theoretisch Rückschlüsse auf Gesundheitszustände ermöglichen (z.B. Tremor). Dies wird wie folgt adressiert:
|
||||
|
||||
- OCR-Modelle analysieren ausschließlich Textinhalt, nicht Handschriftcharakteristiken
|
||||
- Keine Speicherung von Handschriftanalysen
|
||||
- Bei Training werden nur Textinhalte verwendet, keine biometrischen Merkmale
|
||||
|
||||
**Ergebnis:** Art. 9 ist nicht anwendbar, da keine Verarbeitung besonderer Kategorien erfolgt.
|
||||
|
||||
---
|
||||
|
||||
## 4. Datenschutz-Folgenabschätzung (Art. 35 DSGVO)
|
||||
|
||||
### 4.1 Schwellwertanalyse - Erforderlichkeit der DSFA
|
||||
|
||||
| Kriterium | Erfüllt | Begründung |
|
||||
|-----------|---------|------------|
|
||||
| Neue Technologien (KI/ML) | ✓ | Vision-LLM für OCR |
|
||||
| Umfangreiche Verarbeitung | ✗ | Begrenzt auf einzelne Schule |
|
||||
| Daten von Minderjährigen | ✓ | Schülerarbeiten |
|
||||
| Systematische Überwachung | ✗ | Keine Überwachung |
|
||||
| Scoring/Profiling | ✗ | Keine automatische Bewertung |
|
||||
|
||||
**Ergebnis:** DSFA erforderlich aufgrund KI-Einsatz und Verarbeitung von Daten Minderjähriger.
|
||||
|
||||
### 4.2 Systematische Beschreibung der Verarbeitung
|
||||
|
||||
#### Datenfluss-Diagramm
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ OCR-LABELING DATENFLUSS │
|
||||
├─────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ 1. SCAN │───►│ 2. UPLOAD │───►│ 3. OCR │───►│ 4. LABELING │ │
|
||||
│ │ (Lehrkraft) │ │ (MinIO) │ │ (Ollama) │ │ (Lehrkraft) │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ ▼ ▼ ▼ ▼ │
|
||||
│ Papierdokument Verschlüsselte Lokale LLM- Bestätigung/ │
|
||||
│ → digitaler Scan Bildspeicherung Verarbeitung Korrektur │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ SPEICHERUNG (PostgreSQL) │ │
|
||||
│ │ • Session-ID (UUID) • Status (pending/confirmed/corrected) │ │
|
||||
│ │ • Bild-Hash (SHA256) • Ground Truth (korrigierter Text) │ │
|
||||
│ │ • OCR-Text • Zeitstempel │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────┐ │
|
||||
│ │ 5. EXPORT │ Pseudonymisierte Trainingsdaten (JSONL) │
|
||||
│ │ (Optional) │ → Lokal gespeichert für Fine-Tuning │
|
||||
│ └──────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### Verarbeitungsschritte im Detail
|
||||
|
||||
| Schritt | Beschreibung | Datenschutzmaßnahme |
|
||||
|---------|--------------|---------------------|
|
||||
| 1. Scan | Lehrkraft scannt Papierklausur | Physischer Zugang nur für Lehrkräfte |
|
||||
| 2. Upload | Bild wird in lokales MinIO hochgeladen | SHA256-Deduplizierung, verschlüsselte Speicherung |
|
||||
| 3. OCR | llama3.2-vision erkennt Text | 100% lokal, kein Internet |
|
||||
| 4. Labeling | Lehrkraft prüft/korrigiert OCR-Ergebnis | Protokollierung aller Aktionen |
|
||||
| 5. Export | Optional: Pseudonymisierte Trainingsdaten | Entfernung direkter Identifikatoren |
|
||||
|
||||
### 4.3 Notwendigkeit und Verhältnismäßigkeit
|
||||
|
||||
#### Prüfung der Erforderlichkeit
|
||||
|
||||
| Prinzip | Umsetzung |
|
||||
|---------|-----------|
|
||||
| **Zweckbindung** | Ausschließlich für schulische Leistungsbewertung und Modelltraining |
|
||||
| **Datenminimierung** | Nur Bildausschnitte mit Text, keine vollständigen Klausuren nötig |
|
||||
| **Speicherbegrenzung** | Automatische Löschung nach definierter Aufbewahrungsfrist |
|
||||
|
||||
#### Alternativenprüfung
|
||||
|
||||
| Alternative | Bewertung |
|
||||
|-------------|-----------|
|
||||
| Manuelle Transkription | Zeitaufwändig, fehleranfällig, nicht praktikabel |
|
||||
| Cloud-OCR (Google, Azure) | Datenschutzrisiken durch Drittlandübermittlung |
|
||||
| Kommerzielles lokales OCR | Hohe Kosten, Lizenzabhängigkeit |
|
||||
| **Gewählte Lösung** | Open-Source lokal - optimale Balance |
|
||||
|
||||
### 4.4 Risikobewertung
|
||||
|
||||
#### Identifizierte Risiken
|
||||
|
||||
| Risiko | Eintrittswahrscheinlichkeit | Schwere | Risikostufe | Mitigationsmaßnahme |
|
||||
|--------|---------------------------|---------|-------------|---------------------|
|
||||
| R1: Unbefugter Zugriff auf Schülerdaten | Gering | Hoch | Mittel | Rollenbasierte Zugriffskontrolle, MFA |
|
||||
| R2: Datenleck durch Systemkompromittierung | Gering | Hoch | Mittel | Verschlüsselung, Netzwerkisolation |
|
||||
| R3: Fehlerhaftes OCR beeinflusst Bewertung | Mittel | Mittel | Mittel | Pflicht-Review durch Lehrkraft |
|
||||
| R4: Re-Identifizierung aus Handschrift | Gering | Mittel | Gering | Pseudonymisierung, keine Handschriftanalyse |
|
||||
| R5: Bias im OCR-Modell | Mittel | Mittel | Mittel | Regelmäßige Qualitätsprüfung |
|
||||
|
||||
#### Risikomatrix
|
||||
|
||||
```
|
||||
SCHWERE
|
||||
Gering Mittel Hoch
|
||||
┌───────┬───────┬───────┐
|
||||
Hoch │ │ │ │
|
||||
├───────┼───────┼───────┤
|
||||
Mittel │ │ R3,R5 │ │ WAHRSCHEINLICHKEIT
|
||||
├───────┼───────┼───────┤
|
||||
Gering │ │ R4 │ R1,R2 │
|
||||
└───────┴───────┴───────┘
|
||||
```
|
||||
|
||||
### 4.5 Maßnahmen zur Risikominderung
|
||||
|
||||
| Risiko | Maßnahme | Umsetzungsstatus |
|
||||
|--------|----------|------------------|
|
||||
| R1 | RBAC, MFA, Audit-Logging | ✓ Implementiert |
|
||||
| R2 | FileVault-Verschlüsselung, lokales Netz | ✓ Implementiert |
|
||||
| R3 | Pflicht-Bestätigung durch Lehrkraft | ✓ Implementiert |
|
||||
| R4 | Pseudonymisierung bei Export | ✓ Implementiert |
|
||||
| R5 | Diverse Trainingssamples, manuelle Reviews | ○ In Entwicklung |
|
||||
|
||||
---
|
||||
|
||||
## 5. Informationspflichten (Art. 13/14 DSGVO)
|
||||
|
||||
### 5.1 Informationen für Betroffene
|
||||
|
||||
Folgende Informationen werden Schülern und Erziehungsberechtigten bereitgestellt:
|
||||
|
||||
#### 5.1.1 Pflichtangaben nach Art. 13 DSGVO
|
||||
|
||||
| Information | Bereitstellung |
|
||||
|-------------|----------------|
|
||||
| Identität des Verantwortlichen | Schulwebsite, Datenschutzerklärung |
|
||||
| Kontakt DSB | Schulwebsite, Aushang |
|
||||
| Verarbeitungszwecke | Datenschutzinformation bei Einschulung |
|
||||
| Rechtsgrundlage | Datenschutzinformation |
|
||||
| Empfänger/Kategorien | Datenschutzinformation |
|
||||
| Speicherdauer | Datenschutzinformation |
|
||||
| Betroffenenrechte | Datenschutzinformation, auf Anfrage |
|
||||
| Beschwerderecht | Datenschutzinformation |
|
||||
|
||||
#### 5.1.2 KI-spezifische Transparenz
|
||||
|
||||
Zusätzlich zu den Standard-Informationspflichten:
|
||||
|
||||
| Information | Inhalt |
|
||||
|-------------|--------|
|
||||
| Art der KI | Vision-LLM für Texterkennung, kein automatisches Bewerten |
|
||||
| Menschliche Aufsicht | Jedes OCR-Ergebnis wird von Lehrkraft geprüft |
|
||||
| Keine automatische Entscheidung | System macht Vorschläge, Lehrkraft entscheidet |
|
||||
| Widerspruchsrecht | Opt-out von Training-Verwendung möglich |
|
||||
|
||||
### 5.2 Informationsbereitstellung
|
||||
|
||||
| Kanal | Zeitpunkt | Zielgruppe |
|
||||
|-------|-----------|------------|
|
||||
| Einschulungsunterlagen | Bei Schulanmeldung | Erziehungsberechtigte |
|
||||
| Datenschutzerklärung Website | Dauerhaft | Alle |
|
||||
| Klausur-Deckblatt (optional) | Bei Prüfung | Schüler |
|
||||
| Elternabend | Jährlich | Erziehungsberechtigte |
|
||||
|
||||
---
|
||||
|
||||
## 6. Automatisierte Entscheidungsfindung (Art. 22 DSGVO)
|
||||
|
||||
### 6.1 Anwendbarkeitsprüfung
|
||||
|
||||
**Prüfung der Tatbestandsmerkmale:**
|
||||
|
||||
| Merkmal | Erfüllt | Begründung |
|
||||
|---------|---------|------------|
|
||||
| Automatisierte Verarbeitung | Ja | KI-gestützte Texterkennung |
|
||||
| Entscheidung | Nein | OCR liefert nur Vorschlag |
|
||||
| Rechtliche Wirkung/erhebliche Beeinträchtigung | Nein | Lehrkraft trifft finale Bewertungsentscheidung |
|
||||
|
||||
**Ergebnis:** Art. 22 DSGVO ist **nicht anwendbar**, da keine automatisierte Entscheidung mit rechtlicher Wirkung erfolgt.
|
||||
|
||||
### 6.2 Teacher-in-the-Loop Garantie
|
||||
|
||||
Das System implementiert obligatorische menschliche Aufsicht:
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ OCR-System │────►│ Lehrkraft │────►│ Bewertung │
|
||||
│ (Vorschlag) │ │ (Prüfung) │ │ (Final) │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌──────────────┐ │
|
||||
└───────────►│ Korrektur │◄───────────┘
|
||||
│ (Optional) │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
**Workflow-Garantien:**
|
||||
1. Kein OCR-Ergebnis wird automatisch als korrekt übernommen
|
||||
2. Lehrkraft muss explizit bestätigen ODER korrigieren
|
||||
3. Bewertungsentscheidung liegt ausschließlich bei der Lehrkraft
|
||||
4. System gibt keine Notenvorschläge
|
||||
|
||||
### 6.3 Dokumentation der menschlichen Aufsicht
|
||||
|
||||
| Metrik | Erhebung |
|
||||
|--------|----------|
|
||||
| Bestätigungsrate | % der OCR-Ergebnisse als korrekt bestätigt |
|
||||
| Korrekturrate | % der OCR-Ergebnisse mit Korrekturen |
|
||||
| Durchschnittliche Prüfzeit | Zeit pro Item in Sekunden |
|
||||
| Lehrkraft-ID | Pseudonymisiert für Audit-Trail |
|
||||
|
||||
---
|
||||
|
||||
## 7. Privacy by Design und Default (Art. 25 DSGVO)
|
||||
|
||||
### 7.1 Design-Prinzipien
|
||||
|
||||
| Prinzip | Implementierung |
|
||||
|---------|-----------------|
|
||||
| **Proaktive Maßnahmen** | Datenschutz von Anfang an im System-Design berücksichtigt |
|
||||
| **Standard-Datenschutz** | Minimale Datenerhebung als Default |
|
||||
| **Eingebetteter Datenschutz** | Technische Maßnahmen nicht umgehbar |
|
||||
| **Volle Funktionalität** | Kein Trade-off Datenschutz vs. Funktionalität |
|
||||
| **End-to-End Sicherheit** | Verschlüsselung vom Upload bis zur Löschung |
|
||||
| **Sichtbarkeit/Transparenz** | Alle Verarbeitungen protokolliert und nachvollziehbar |
|
||||
| **Nutzerzentrierung** | Betroffenenrechte einfach ausübbar |
|
||||
|
||||
### 7.2 Umsetzung Datenminimierung
|
||||
|
||||
| Maßnahme | Beschreibung |
|
||||
|----------|--------------|
|
||||
| Bildausschnitte | Nur relevante Textbereiche, nicht vollständige Seiten |
|
||||
| Metadaten-Beschränkung | Keine Speicherung von Geräteinformationen des Scanners |
|
||||
| Pseudonymisierung | Schüler-IDs durch UUIDs ersetzt bei Export |
|
||||
| Automatische Löschung | Konfigurierbare Aufbewahrungsfristen |
|
||||
|
||||
### 7.3 Default-Einstellungen
|
||||
|
||||
| Einstellung | Default | Begründung |
|
||||
|-------------|---------|------------|
|
||||
| OCR-Ergebnis automatisch übernehmen | Nein | Menschliche Prüfung erforderlich |
|
||||
| Training-Export aktiviert | Nein | Opt-in erforderlich |
|
||||
| Metadaten-Speicherung | Minimal | Nur notwendige Daten |
|
||||
| Zugriffsprotokollierung | Ja | Transparenz und Nachvollziehbarkeit |
|
||||
|
||||
### 7.4 Vendor-Auswahl
|
||||
|
||||
Die verwendeten KI-Modelle wurden nach Datenschutzkriterien ausgewählt:
|
||||
|
||||
| Modell | Anbieter | Lizenz | Lokale Ausführung | Telemetrie |
|
||||
|--------|----------|--------|-------------------|------------|
|
||||
| llama3.2-vision:11b | Meta | Llama 3.2 Community | ✓ | Keine |
|
||||
| qwen2.5:14b | Alibaba | Apache 2.0 | ✓ | Keine |
|
||||
| TrOCR | Microsoft | MIT | ✓ | Keine |
|
||||
|
||||
---
|
||||
|
||||
## 8. Technisch-Organisatorische Maßnahmen (Art. 32 DSGVO)
|
||||
|
||||
### 8.1 Vertraulichkeit
|
||||
|
||||
#### 8.1.1 Zutrittskontrolle
|
||||
|
||||
| Maßnahme | Umsetzung |
|
||||
|----------|-----------|
|
||||
| Physische Sicherung | Server in abgeschlossenem Raum |
|
||||
| Zugangsprotokoll | Elektronisches Schloss mit Protokollierung |
|
||||
| Berechtigte Personen | IT-Administrator, Schulleitung |
|
||||
|
||||
#### 8.1.2 Zugangskontrolle
|
||||
|
||||
| Maßnahme | Umsetzung |
|
||||
|----------|-----------|
|
||||
| Authentifizierung | Benutzername + Passwort |
|
||||
| Passwort-Policy | Min. 12 Zeichen, Komplexitätsanforderungen |
|
||||
| Session-Timeout | 30 Minuten Inaktivität |
|
||||
| Fehlversuche | Account-Sperrung nach 5 Fehlversuchen |
|
||||
|
||||
#### 8.1.3 Zugriffskontrolle (RBAC)
|
||||
|
||||
| Rolle | Berechtigungen |
|
||||
|-------|----------------|
|
||||
| **Admin** | Vollzugriff, Benutzerverwaltung |
|
||||
| **Lehrkraft** | Eigene Sessions, Labeling, Export |
|
||||
| **Viewer** | Nur Lesezugriff auf Statistiken |
|
||||
|
||||
#### 8.1.4 Pseudonymisierung
|
||||
|
||||
| Datenfeld | Maßnahme |
|
||||
|-----------|----------|
|
||||
| Schüler-ID | UUID statt Klarname bei Export |
|
||||
| Lehrkraft-ID | Pseudonymisiert in Logs |
|
||||
| Session-Name | Keine Schülernamen erlaubt |
|
||||
|
||||
#### 8.1.5 Verschlüsselung
|
||||
|
||||
| Bereich | Maßnahme |
|
||||
|---------|----------|
|
||||
| Festplatte | FileVault 2 (AES-256) |
|
||||
| Datenbank | Transparent Data Encryption |
|
||||
| MinIO Storage | Server-Side Encryption (SSE) |
|
||||
| Netzwerk | TLS 1.3 für lokale Verbindungen |
|
||||
|
||||
### 8.2 Integrität
|
||||
|
||||
#### 8.2.1 Weitergabekontrolle
|
||||
|
||||
| Maßnahme | Umsetzung |
|
||||
|----------|-----------|
|
||||
| Netzwerkisolation | Lokales Netz, keine Internet-Verbindung erforderlich |
|
||||
| USB-Ports | Administrativ deaktiviert |
|
||||
| Firewall | Eingehende Verbindungen blockiert |
|
||||
|
||||
#### 8.2.2 Eingabekontrolle
|
||||
|
||||
| Maßnahme | Umsetzung |
|
||||
|----------|-----------|
|
||||
| Audit-Log | Alle Aktionen mit Timestamp und User-ID |
|
||||
| Unveränderlichkeit | Append-only Logging |
|
||||
| Log-Retention | 1 Jahr |
|
||||
|
||||
**Protokollierte Aktionen:**
|
||||
- Session erstellen/löschen
|
||||
- Bild hochladen
|
||||
- OCR ausführen
|
||||
- Label bestätigen/korrigieren/überspringen
|
||||
- Export durchführen
|
||||
- Login/Logout
|
||||
|
||||
### 8.3 Verfügbarkeit
|
||||
|
||||
| Maßnahme | Umsetzung |
|
||||
|----------|-----------|
|
||||
| Backup | Tägliches inkrementelles Backup |
|
||||
| USV | Unterbrechungsfreie Stromversorgung |
|
||||
| RAID | RAID 1 Spiegelung für Datenträger |
|
||||
| Recovery-Test | Halbjährlich |
|
||||
|
||||
### 8.4 Belastbarkeit
|
||||
|
||||
| Maßnahme | Umsetzung |
|
||||
|----------|-----------|
|
||||
| Ressourcen-Monitoring | Prometheus + Grafana |
|
||||
| Alerts | E-Mail bei kritischen Schwellwerten |
|
||||
| Kapazitätsplanung | Jährliche Review |
|
||||
|
||||
---
|
||||
|
||||
## 9. BSI-Anforderungen und Sicherheitsrichtlinien
|
||||
|
||||
### 9.1 Angewandte BSI-Publikationen
|
||||
|
||||
| Publikation | Relevanz | Umsetzung |
|
||||
|-------------|----------|-----------|
|
||||
| IT-Grundschutz-Kompendium | Basis-Absicherung | TOM nach Abschnitt 8 |
|
||||
| BSI TR-03116-4 | Kryptographische Verfahren | AES-256, TLS 1.3 |
|
||||
| Kriterienkatalog KI (Juni 2025) | KI-Sicherheit | Siehe 9.2 |
|
||||
| QUAIDAL (Juli 2025) | Trainingsdaten-Qualität | Siehe 9.3 |
|
||||
|
||||
### 9.2 KI-Sicherheitsanforderungen (BSI Kriterienkatalog)
|
||||
|
||||
| Kriterium | Anforderung | Umsetzung |
|
||||
|-----------|-------------|-----------|
|
||||
| Modellintegrität | Schutz vor Manipulation | Lokale Modelle, keine Updates ohne Review |
|
||||
| Eingabevalidierung | Schutz vor Adversarial Attacks | Bildformat-Prüfung, Größenlimits |
|
||||
| Ausgabevalidierung | Plausibilitätsprüfung | Konfidenz-Schwellwerte |
|
||||
| Protokollierung | Nachvollziehbarkeit | Vollständiges Audit-Log |
|
||||
| Incident Response | Reaktion auf Fehlfunktionen | Eskalationsprozess definiert |
|
||||
|
||||
### 9.3 Trainingsdaten-Qualität (QUAIDAL)
|
||||
|
||||
| Qualitätskriterium | Umsetzung |
|
||||
|--------------------|-----------|
|
||||
| **Herkunftsdokumentation** | Alle Trainingsdaten aus eigenem Labeling-Prozess |
|
||||
| **Repräsentativität** | Diverse Handschriften aus verschiedenen Klassenstufen |
|
||||
| **Qualitätskontrolle** | Lehrkraft-Verifikation jedes Samples |
|
||||
| **Bias-Prüfung** | Regelmäßige Stichproben-Analyse |
|
||||
| **Versionierung** | Git-basierte Versionskontrolle für Datasets |
|
||||
|
||||
---
|
||||
|
||||
## 10. EU AI Act Compliance (KI-Verordnung)
|
||||
|
||||
### 10.1 Risikoklassifizierung
|
||||
|
||||
**Prüfung nach Anhang III der KI-Verordnung:**
|
||||
|
||||
| Hochrisiko-Kategorie | Anwendbar | Begründung |
|
||||
|---------------------|-----------|------------|
|
||||
| 3(a) Biometrische Identifizierung | Nein | Keine biometrische Verarbeitung |
|
||||
| 3(b) Kritische Infrastruktur | Nein | Keine kritische Infrastruktur |
|
||||
| 3(c) Allgemeine/berufliche Bildung | **Prüfen** | Bildungsbereich |
|
||||
| 3(d) Beschäftigung | Nein | Nicht anwendbar |
|
||||
|
||||
**Detailprüfung Bildung (Anhang III, Nr. 3c):**
|
||||
|
||||
Das System wird **nicht** für folgende Hochrisiko-Anwendungen genutzt:
|
||||
- ✗ Entscheidung über Zugang zu Bildungseinrichtungen
|
||||
- ✗ Zuweisung zu Bildungseinrichtungen oder -programmen
|
||||
- ✗ Bewertung von Lernergebnissen (nur Unterstützung, keine automatische Bewertung)
|
||||
- ✗ Überwachung von Prüfungen
|
||||
|
||||
**Ergebnis:** Kein Hochrisiko-KI-System nach aktuellem Stand.
|
||||
|
||||
### 10.2 Allgemeine Anforderungen
|
||||
|
||||
Auch ohne Hochrisiko-Klassifizierung werden folgende Transparenzanforderungen erfüllt:
|
||||
|
||||
| Anforderung | Umsetzung |
|
||||
|-------------|-----------|
|
||||
| KI-Literacy (Art. 4) | Schulung der Lehrkräfte |
|
||||
| Transparenz gegenüber Nutzern | Information über KI-Einsatz |
|
||||
| Menschliche Aufsicht | Teacher-in-the-Loop |
|
||||
|
||||
### 10.3 Verbotsprüfung (Art. 5)
|
||||
|
||||
| Verbotene Praxis | Geprüft | Ergebnis |
|
||||
|------------------|---------|----------|
|
||||
| Unterschwellige Manipulation | ✓ | Nicht vorhanden |
|
||||
| Ausnutzung von Schwächen | ✓ | Nicht vorhanden |
|
||||
| Social Scoring | ✓ | Nicht vorhanden |
|
||||
| Echtzeit-Biometrie | ✓ | Nicht vorhanden |
|
||||
| Emotionserkennung in Bildung | ✓ | **Nicht vorhanden** |
|
||||
|
||||
---
|
||||
|
||||
## 11. ML/AI Training Dokumentation
|
||||
|
||||
### 11.1 Trainingsdaten-Quellen
|
||||
|
||||
| Datensatz | Quelle | Rechtsgrundlage | Volumen |
|
||||
|-----------|--------|-----------------|---------|
|
||||
| Klausur-Scans | Schulinterne Prüfungen | Art. 6(1)(e) + Einwilligung | Variabel |
|
||||
| Lehrer-Korrekturen | Labeling-System | Art. 6(1)(e) | Variabel |
|
||||
|
||||
### 11.2 Datenqualitätsmaßnahmen
|
||||
|
||||
| Maßnahme | Beschreibung |
|
||||
|----------|--------------|
|
||||
| Deduplizierung | SHA256-Hash zur Vermeidung von Duplikaten |
|
||||
| Qualitätskontrolle | Jedes Sample von Lehrkraft geprüft |
|
||||
| Repräsentativität | Samples aus verschiedenen Fächern/Klassenstufen |
|
||||
| Dokumentation | Metadaten zu jedem Sample |
|
||||
|
||||
### 11.3 Labeling-Prozess
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ LABELING WORKFLOW │
|
||||
├─────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 1. Bild-Upload 2. OCR-Vorschlag 3. Review │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Scan │─────────►│ LLM-OCR │─────────►│ Lehrkraft │ │
|
||||
│ │ Upload │ │ (lokal) │ │ prüft │ │
|
||||
│ └─────────────┘ └─────────────┘ └──────┬──────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────────────────┴─────┐ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌─────────────┐ ┌─────────┐ │
|
||||
│ │ Bestätigt │ │Korrigiert│ │
|
||||
│ │ (korrekt) │ │(manuell) │ │
|
||||
│ └─────────────┘ └─────────┘ │
|
||||
│ │ │ │
|
||||
│ └──────────┬─────────────────┘ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────┐ │
|
||||
│ │ Ground Truth │ │
|
||||
│ │ (verifiziert) │ │
|
||||
│ └─────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 11.4 Export-Prozeduren
|
||||
|
||||
| Schritt | Beschreibung | Datenschutzmaßnahme |
|
||||
|---------|--------------|---------------------|
|
||||
| 1. Auswahl | Sessions/Items für Export wählen | Nur bestätigte/korrigierte Items |
|
||||
| 2. Pseudonymisierung | Entfernung direkter Identifikatoren | UUID statt Schüler-ID |
|
||||
| 3. Format-Konvertierung | TrOCR/Llama/Generic Format | Nur notwendige Felder |
|
||||
| 4. Speicherung | Lokal in /app/ocr-exports/ | Verschlüsselt, zugriffsbeschränkt |
|
||||
|
||||
### 11.5 Modell-Provenienz
|
||||
|
||||
| Modell | Basis | Fine-Tuning Daten | Training-Parameter |
|
||||
|--------|-------|-------------------|-------------------|
|
||||
| llama3.2-vision:11b | Meta Llama 3.2 | Lokale gelabelte Daten | Dokumentiert pro Training |
|
||||
| TrOCR | Microsoft | Lokale gelabelte Daten | Dokumentiert pro Training |
|
||||
|
||||
---
|
||||
|
||||
## 12. Betroffenenrechte
|
||||
|
||||
### 12.1 Implementierte Rechte
|
||||
|
||||
| Recht | Art. DSGVO | Umsetzung |
|
||||
|-------|-----------|-----------|
|
||||
| **Auskunft** | 15 | Schriftliche Anfrage an DSB |
|
||||
| **Berichtigung** | 16 | Korrektur falscher OCR-Ergebnisse |
|
||||
| **Löschung** | 17 | Nach Aufbewahrungsfrist oder auf Antrag |
|
||||
| **Einschränkung** | 18 | Sperrung der Verarbeitung auf Antrag |
|
||||
| **Datenportabilität** | 20 | Export eigener Daten in JSON |
|
||||
| **Widerspruch** | 21 | Opt-out von Training-Verwendung |
|
||||
|
||||
### 12.2 Sonderrechte bei KI-Training
|
||||
|
||||
| Recht | Umsetzung |
|
||||
|-------|-----------|
|
||||
| Widerspruch gegen Training | Daten werden nicht für Fine-Tuning verwendet |
|
||||
| Löschung aus Trainingsset | "Machine Unlearning" durch Re-Training ohne betroffene Daten |
|
||||
|
||||
### 12.3 Anfrage-Prozess
|
||||
|
||||
| Schritt | Frist | Verantwortlich |
|
||||
|---------|-------|----------------|
|
||||
| Eingang der Anfrage | - | Sekretariat |
|
||||
| Identitätsprüfung | 3 Werktage | DSB |
|
||||
| Bearbeitung | 1 Monat | IT + DSB |
|
||||
| Antwort | 1 Monat | DSB |
|
||||
|
||||
---
|
||||
|
||||
## 13. Schulung und Awareness
|
||||
|
||||
### 13.1 Schulungskonzept
|
||||
|
||||
| Schulung | Zielgruppe | Frequenz | Dokumentation |
|
||||
|----------|------------|----------|---------------|
|
||||
| DSGVO-Grundlagen | Alle Lehrkräfte | Jährlich | Teilnehmerliste |
|
||||
| OCR-System-Nutzung | Nutzende Lehrkräfte | Bei Einführung | Zertifikat |
|
||||
| KI-Kompetenz (AI Act Art. 4) | Alle Nutzenden | Jährlich | Nachweis |
|
||||
|
||||
### 13.2 Schulungsinhalte
|
||||
|
||||
**DSGVO-Grundlagen:**
|
||||
- Prinzipien der Datenverarbeitung
|
||||
- Betroffenenrechte
|
||||
- Meldepflichten bei Datenpannen
|
||||
|
||||
**OCR-System-Nutzung:**
|
||||
- Systemfunktionen und Bedienung
|
||||
- Datenschutzrelevante Einstellungen
|
||||
- Dos and Don'ts
|
||||
|
||||
**KI-Kompetenz:**
|
||||
- Funktionsweise von KI-Systemen
|
||||
- Grenzen und Risiken
|
||||
- Verantwortungsvoller Umgang
|
||||
|
||||
---
|
||||
|
||||
## 14. Review und Audit
|
||||
|
||||
### 14.1 Regelmäßige Überprüfungen
|
||||
|
||||
| Prüfung | Frequenz | Verantwortlich |
|
||||
|---------|----------|----------------|
|
||||
| DSFA-Review | Jährlich | DSB |
|
||||
| TOM-Wirksamkeit | Jährlich | IT-Administrator |
|
||||
| Zugriffsrechte | Halbjährlich | IT-Administrator |
|
||||
| Backup-Test | Halbjährlich | IT-Administrator |
|
||||
| Modell-Bias-Prüfung | Jährlich | IT + Lehrkräfte |
|
||||
|
||||
### 14.2 Audit-Trail
|
||||
|
||||
| Protokollierte Daten | Aufbewahrung | Format |
|
||||
|---------------------|--------------|--------|
|
||||
| Benutzeraktionen | 1 Jahr | PostgreSQL |
|
||||
| Systemereignisse | 1 Jahr | Syslog |
|
||||
| Sicherheitsvorfälle | 3 Jahre | Incident-Dokumentation |
|
||||
|
||||
---
|
||||
|
||||
## 15. Vorfallmanagement
|
||||
|
||||
### 15.1 Datenpannen-Prozess
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ INCIDENT RESPONSE │
|
||||
├─────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Erkennung ──► Bewertung ──► Meldung ──► Eindämmung ──► Behebung │
|
||||
│ │ │ │ │ │ │
|
||||
│ ▼ ▼ ▼ ▼ ▼ │
|
||||
│ Monitoring Risiko- 72h an LfD Isolation Ursachen- │
|
||||
│ Audit-Log einschätzung (Art.33) Forensik analyse │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 15.2 Meldepflichten
|
||||
|
||||
| Ereignis | Frist | Empfänger |
|
||||
|----------|-------|-----------|
|
||||
| Datenpanne mit Risiko | 72 Stunden | Landesbeauftragte/r für Datenschutz |
|
||||
| Hohes Risiko für Betroffene | Unverzüglich | Betroffene Personen |
|
||||
|
||||
### 15.3 KI-spezifische Vorfälle
|
||||
|
||||
| Vorfall | Reaktion |
|
||||
|---------|----------|
|
||||
| Systematisch falsche OCR-Ergebnisse | Modell-Rollback, Analyse |
|
||||
| Bias-Erkennung | Untersuchung, ggf. Re-Training |
|
||||
| Adversarial Attack | System-Isolierung, Forensik |
|
||||
|
||||
---
|
||||
|
||||
## 16. Kontakte
|
||||
|
||||
### 16.1 Interne Kontakte
|
||||
|
||||
| Rolle | Name | Kontakt |
|
||||
|-------|------|---------|
|
||||
| Schulleitung | [Name] | [E-Mail] |
|
||||
| IT-Administrator | [Name] | [E-Mail] |
|
||||
| Datenschutzbeauftragter | [Name] | [E-Mail] |
|
||||
|
||||
### 16.2 Externe Kontakte
|
||||
|
||||
| Institution | Kontakt |
|
||||
|-------------|---------|
|
||||
| LfD Niedersachsen | poststelle@lfd.niedersachsen.de |
|
||||
| BSI | bsi@bsi.bund.de |
|
||||
|
||||
---
|
||||
|
||||
## Anhänge
|
||||
|
||||
### Anhang A: Systemarchitektur-Diagramm
|
||||
|
||||
Siehe Abschnitt 4.2
|
||||
|
||||
### Anhang B: TOM-Checkliste
|
||||
|
||||
| Kategorie | Maßnahme | Status |
|
||||
|-----------|----------|--------|
|
||||
| Zutrittskontrolle | Serverraum verschlossen | ✓ |
|
||||
| Zugangskontrolle | Passwort-Policy | ✓ |
|
||||
| Zugriffskontrolle | RBAC implementiert | ✓ |
|
||||
| Weitergabekontrolle | Netzwerkisolation | ✓ |
|
||||
| Eingabekontrolle | Audit-Logging | ✓ |
|
||||
| Verfügbarkeit | Backup + USV | ✓ |
|
||||
| Trennungskontrolle | Mandantentrennung | ✓ |
|
||||
| Verschlüsselung | FileVault + TLS | ✓ |
|
||||
|
||||
### Anhang C: Muster-Informationsschreiben
|
||||
|
||||
[Zu erstellen für spezifische Schule]
|
||||
|
||||
### Anhang D: Einwilligungserklärung Training
|
||||
|
||||
[Zu erstellen für spezifische Schule]
|
||||
|
||||
### Anhang E: Vendor-Dokumentation
|
||||
|
||||
- llama3.2-vision: https://llama.meta.com/
|
||||
- TrOCR: https://github.com/microsoft/unilm/tree/master/trocr
|
||||
- Ollama: https://ollama.ai/
|
||||
|
||||
---
|
||||
|
||||
**Dokumentende**
|
||||
|
||||
*Diese Dokumentation wird jährlich oder bei wesentlichen Änderungen aktualisiert.*
|
||||
|
||||
*Letzte Aktualisierung: 21. Januar 2026*
|
||||
227
klausur-service/docs/NiBiS-Ingestion-Pipeline.md
Normal file
227
klausur-service/docs/NiBiS-Ingestion-Pipeline.md
Normal file
@@ -0,0 +1,227 @@
|
||||
# NiBiS Ingestion Pipeline
|
||||
|
||||
## Overview
|
||||
|
||||
Die NiBiS Ingestion Pipeline verarbeitet Abitur-Erwartungshorizonte aus Niedersachsen und indexiert sie in Qdrant für RAG-basierte Klausurkorrektur.
|
||||
|
||||
## Unterstützte Daten
|
||||
|
||||
### Verzeichnisse
|
||||
|
||||
| Verzeichnis | Jahre | Namenskonvention |
|
||||
|-------------|-------|------------------|
|
||||
| `docs/za-download` | 2024, 2025 | `{Jahr}_{Fach}_{niveau}_{Nr}_EWH.pdf` |
|
||||
| `docs/za-download-2` | 2016 | `{Jahr}{Fach}{Niveau}Lehrer/{Jahr}{Fach}{Niveau}A{Nr}L.pdf` |
|
||||
| `docs/za-download-3` | 2017 | `{Jahr}{Fach}{Niveau}Lehrer/{Jahr}{Fach}{Niveau}A{Nr}L.pdf` |
|
||||
|
||||
### Dokumenttypen
|
||||
|
||||
- **EWH** - Erwartungshorizont (Hauptziel)
|
||||
- **Aufgabe** - Prüfungsaufgaben
|
||||
- **Material** - Zusatzmaterialien
|
||||
- **GBU** - Gefährdungsbeurteilung (Chemie/Biologie)
|
||||
- **Bewertungsbogen** - Standardisierte Bewertungsbögen
|
||||
|
||||
### Fächer
|
||||
|
||||
Deutsch, Englisch, Mathematik, Informatik, Biologie, Chemie, Physik, Geschichte, Erdkunde, Kunst, Musik, Sport, Latein, Griechisch, Französisch, Spanisch, Katholische Religion, Evangelische Religion, Werte und Normen, BRC, BVW, Gesundheit-Pflege
|
||||
|
||||
## Architektur
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ NiBiS Ingestion Pipeline │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 1. ZIP Extraction │
|
||||
│ └── Entpackt 2024.zip, 2025.zip, etc. │
|
||||
│ │
|
||||
│ 2. Document Discovery │
|
||||
│ ├── Parst alte Namenskonvention (2016/2017) │
|
||||
│ └── Parst neue Namenskonvention (2024/2025) │
|
||||
│ │
|
||||
│ 3. PDF Processing │
|
||||
│ ├── Text-Extraktion (PyPDF2) │
|
||||
│ └── Chunking (1000 chars, 200 overlap) │
|
||||
│ │
|
||||
│ 4. Embedding Generation │
|
||||
│ └── OpenAI text-embedding-3-small (1536 dim) │
|
||||
│ │
|
||||
│ 5. Qdrant Indexing │
|
||||
│ └── Collection: bp_nibis_eh │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Verwendung
|
||||
|
||||
### Via API (empfohlen)
|
||||
|
||||
```bash
|
||||
# 1. Vorschau der verfügbaren Dokumente
|
||||
curl http://localhost:8086/api/v1/admin/nibis/discover
|
||||
|
||||
# 2. ZIP-Dateien entpacken
|
||||
curl -X POST http://localhost:8086/api/v1/admin/nibis/extract-zips
|
||||
|
||||
# 3. Ingestion starten
|
||||
curl -X POST http://localhost:8086/api/v1/admin/nibis/ingest \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"ewh_only": true}'
|
||||
|
||||
# 4. Status prüfen
|
||||
curl http://localhost:8086/api/v1/admin/nibis/status
|
||||
|
||||
# 5. Semantische Suche testen
|
||||
curl -X POST http://localhost:8086/api/v1/admin/nibis/search \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "Analyse literarischer Texte", "subject": "Deutsch", "limit": 5}'
|
||||
```
|
||||
|
||||
### Via CLI
|
||||
|
||||
```bash
|
||||
# Dry-Run (nur analysieren)
|
||||
cd klausur-service/backend
|
||||
python nibis_ingestion.py --dry-run
|
||||
|
||||
# Vollständige Ingestion
|
||||
python nibis_ingestion.py
|
||||
|
||||
# Nur bestimmtes Jahr
|
||||
python nibis_ingestion.py --year 2024
|
||||
|
||||
# Nur bestimmtes Fach
|
||||
python nibis_ingestion.py --subject Deutsch
|
||||
|
||||
# Manifest erstellen
|
||||
python nibis_ingestion.py --manifest /tmp/nibis_manifest.json
|
||||
```
|
||||
|
||||
### Via Shell Script
|
||||
|
||||
```bash
|
||||
./klausur-service/scripts/run_nibis_ingestion.sh --dry-run
|
||||
./klausur-service/scripts/run_nibis_ingestion.sh --year 2024 --subject Deutsch
|
||||
```
|
||||
|
||||
## Qdrant Schema
|
||||
|
||||
### Collection: `bp_nibis_eh`
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "nibis_2024_deutsch_ea_1_abc123_chunk_0",
|
||||
"vector": [1536 dimensions],
|
||||
"payload": {
|
||||
"doc_id": "nibis_2024_deutsch_ea_1_abc123",
|
||||
"chunk_index": 0,
|
||||
"text": "Der Erwartungshorizont...",
|
||||
"year": 2024,
|
||||
"subject": "Deutsch",
|
||||
"niveau": "eA",
|
||||
"task_number": 1,
|
||||
"doc_type": "EWH",
|
||||
"bundesland": "NI",
|
||||
"variant": null,
|
||||
"source": "nibis",
|
||||
"training_allowed": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
| Methode | Endpoint | Beschreibung |
|
||||
|---------|----------|--------------|
|
||||
| GET | `/api/v1/admin/nibis/status` | Ingestion-Status |
|
||||
| POST | `/api/v1/admin/nibis/extract-zips` | ZIP-Dateien entpacken |
|
||||
| GET | `/api/v1/admin/nibis/discover` | Dokumente finden |
|
||||
| POST | `/api/v1/admin/nibis/ingest` | Ingestion starten |
|
||||
| POST | `/api/v1/admin/nibis/search` | Semantische Suche |
|
||||
| GET | `/api/v1/admin/nibis/stats` | Statistiken |
|
||||
| GET | `/api/v1/admin/nibis/collections` | Qdrant Collections |
|
||||
| DELETE | `/api/v1/admin/nibis/collection` | Collection löschen |
|
||||
|
||||
## Erweiterung für andere Bundesländer
|
||||
|
||||
Die Pipeline ist so designed, dass sie leicht erweitert werden kann:
|
||||
|
||||
### 1. Neues Bundesland hinzufügen
|
||||
|
||||
```python
|
||||
# In nibis_ingestion.py
|
||||
|
||||
# Bundesland-Code (ISO 3166-2:DE)
|
||||
BUNDESLAND_CODES = {
|
||||
"NI": "Niedersachsen",
|
||||
"BE": "Berlin",
|
||||
"BY": "Bayern",
|
||||
# ...
|
||||
}
|
||||
|
||||
# Parsing-Funktion für neues Format
|
||||
def parse_filename_berlin(filename: str, file_path: Path) -> Optional[Dict]:
|
||||
# Berlin-spezifische Namenskonvention
|
||||
pass
|
||||
```
|
||||
|
||||
### 2. Neues Verzeichnis registrieren
|
||||
|
||||
```python
|
||||
# docs/za-download-berlin/ hinzufügen
|
||||
ZA_DOWNLOAD_DIRS = [
|
||||
"za-download",
|
||||
"za-download-2",
|
||||
"za-download-3",
|
||||
"za-download-berlin", # NEU
|
||||
]
|
||||
```
|
||||
|
||||
### 3. Dokumenttyp-Erweiterung
|
||||
|
||||
Für Zeugnisgeneration oder andere Dokumenttypen:
|
||||
|
||||
```python
|
||||
DOC_TYPES = {
|
||||
"EWH": "Erwartungshorizont",
|
||||
"ZEUGNIS_VORLAGE": "Zeugnisvorlage",
|
||||
"NOTENSPIEGEL": "Notenspiegel",
|
||||
"BEMERKUNG": "Bemerkungstexte",
|
||||
}
|
||||
```
|
||||
|
||||
## Rechtliche Hinweise
|
||||
|
||||
- NiBiS-Daten sind unter den [NiBiS-Nutzungsbedingungen](https://nibis.de) frei nutzbar
|
||||
- `training_allowed: true` - Strukturelles Wissen darf für KI-Training genutzt werden
|
||||
- Für Lehrer-eigene Erwartungshorizonte (BYOEH) gilt: `training_allowed: false`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Qdrant nicht erreichbar
|
||||
|
||||
```bash
|
||||
# Prüfen ob Qdrant läuft
|
||||
curl http://localhost:6333/health
|
||||
|
||||
# Docker starten
|
||||
docker-compose up -d qdrant
|
||||
```
|
||||
|
||||
### OpenAI API Fehler
|
||||
|
||||
```bash
|
||||
# API Key setzen
|
||||
export OPENAI_API_KEY=sk-...
|
||||
```
|
||||
|
||||
### PDF-Extraktion fehlgeschlagen
|
||||
|
||||
Einige PDFs können problematisch sein (gescannte Dokumente ohne OCR). Diese werden übersprungen und im Error-Log protokolliert.
|
||||
|
||||
## Performance
|
||||
|
||||
- ~500-1000 Chunks pro Minute (abhängig von OpenAI API)
|
||||
- ~2-3 GB Qdrant Storage für alle NiBiS-Daten (2016-2025)
|
||||
- Embeddings werden nur einmal generiert (idempotent via Hash)
|
||||
446
klausur-service/docs/OCR-Labeling-Spec.md
Normal file
446
klausur-service/docs/OCR-Labeling-Spec.md
Normal file
@@ -0,0 +1,446 @@
|
||||
# OCR-Labeling System Spezifikation
|
||||
|
||||
**Version:** 1.1.0
|
||||
**Datum:** 2026-01-23
|
||||
**Status:** In Produktion (Mac Mini)
|
||||
|
||||
## Übersicht
|
||||
|
||||
Das OCR-Labeling System ermöglicht das Erstellen von Trainingsdaten für Handschrift-OCR-Modelle aus eingescannten Klausuren. Es unterstützt folgende OCR-Modelle:
|
||||
|
||||
| Modell | Beschreibung | Geschwindigkeit | Empfohlen für |
|
||||
|--------|--------------|-----------------|---------------|
|
||||
| **llama3.2-vision:11b** | Vision-LLM (Standard) | Langsam | Handschrift, beste Qualität |
|
||||
| **TrOCR** | Microsoft Transformer | Schnell | Gedruckter Text |
|
||||
| **PaddleOCR + LLM** | Hybrid-Ansatz (NEU) | Sehr schnell (4x) | Gemischte Dokumente |
|
||||
| **Donut** | Document Understanding (NEU) | Mittel | Tabellen, Formulare |
|
||||
| **qwen2.5:14b** | Korrektur-LLM | - | Klausurbewertung |
|
||||
|
||||
### Neue OCR-Optionen (v1.1.0)
|
||||
|
||||
#### PaddleOCR + LLM (Empfohlen für Geschwindigkeit)
|
||||
|
||||
PaddleOCR ist ein zweistufiger Ansatz:
|
||||
1. **PaddleOCR** - Schnelle, präzise Texterkennung mit Bounding-Boxes
|
||||
2. **qwen2.5:14b** - Semantische Strukturierung des erkannten Texts
|
||||
|
||||
**Vorteile:**
|
||||
- 4x schneller als Vision-LLM (~7-15 Sek vs 30-60 Sek pro Seite)
|
||||
- Höhere Genauigkeit bei gedrucktem Text (95-99%)
|
||||
- Weniger Halluzinationen (LLM korrigiert nur, erfindet nicht)
|
||||
- Position-basierte Spaltenerkennung möglich
|
||||
|
||||
**Dateien:**
|
||||
- `/klausur-service/backend/hybrid_vocab_extractor.py` - PaddleOCR Integration
|
||||
|
||||
#### Donut (Document Understanding Transformer)
|
||||
|
||||
Donut ist speziell für strukturierte Dokumente optimiert:
|
||||
- Tabellen und Formulare
|
||||
- Rechnungen und Quittungen
|
||||
- Multi-Spalten-Layouts
|
||||
|
||||
**Dateien:**
|
||||
- `/klausur-service/backend/services/donut_ocr_service.py` - Donut Service
|
||||
|
||||
## Architektur
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────────────┐
|
||||
│ OCR-Labeling System │
|
||||
├──────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────────┐ ┌────────────────────────┐ │
|
||||
│ │ Frontend │◄──►│ Klausur-Service │◄──►│ PostgreSQL │ │
|
||||
│ │ (Next.js) │ │ (FastAPI) │ │ - ocr_labeling_sessions│ │
|
||||
│ │ Port 3000 │ │ Port 8086 │ │ - ocr_labeling_items │ │
|
||||
│ └─────────────┘ └────────┬─────────┘ │ - ocr_training_samples │ │
|
||||
│ │ └────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────┼──────────┐ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌───────────┐ ┌─────────┐ ┌───────────────┐ │
|
||||
│ │ MinIO │ │ Ollama │ │ Export Service │ │
|
||||
│ │ (Images) │ │ (OCR) │ │ (Training) │ │
|
||||
│ │ Port 9000 │ │ :11434 │ │ │ │
|
||||
│ └───────────┘ └─────────┘ └───────────────┘ │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Datenmodell
|
||||
|
||||
### PostgreSQL Tabellen
|
||||
|
||||
```sql
|
||||
-- Labeling Sessions (gruppiert zusammengehörige Bilder)
|
||||
CREATE TABLE ocr_labeling_sessions (
|
||||
id VARCHAR(36) PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
source_type VARCHAR(50) NOT NULL, -- 'klausur', 'handwriting_sample', 'scan'
|
||||
description TEXT,
|
||||
ocr_model VARCHAR(100), -- z.B. 'llama3.2-vision:11b'
|
||||
total_items INTEGER DEFAULT 0,
|
||||
labeled_items INTEGER DEFAULT 0,
|
||||
confirmed_items INTEGER DEFAULT 0,
|
||||
corrected_items INTEGER DEFAULT 0,
|
||||
skipped_items INTEGER DEFAULT 0,
|
||||
teacher_id VARCHAR(100),
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Einzelne Labeling Items (Bild + OCR + Ground Truth)
|
||||
CREATE TABLE ocr_labeling_items (
|
||||
id VARCHAR(36) PRIMARY KEY,
|
||||
session_id VARCHAR(36) REFERENCES ocr_labeling_sessions(id),
|
||||
image_path TEXT NOT NULL, -- MinIO Pfad oder lokaler Pfad
|
||||
image_hash VARCHAR(64), -- SHA256 für Deduplizierung
|
||||
ocr_text TEXT, -- Von LLM erkannter Text
|
||||
ocr_confidence FLOAT, -- Konfidenz (0-1)
|
||||
ocr_model VARCHAR(100),
|
||||
ground_truth TEXT, -- Korrigierter/bestätigter Text
|
||||
status VARCHAR(20) DEFAULT 'pending', -- pending/confirmed/corrected/skipped
|
||||
labeled_by VARCHAR(100),
|
||||
labeled_at TIMESTAMP,
|
||||
label_time_seconds INTEGER,
|
||||
metadata JSONB,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Exportierte Training Samples
|
||||
CREATE TABLE ocr_training_samples (
|
||||
id VARCHAR(36) PRIMARY KEY,
|
||||
item_id VARCHAR(36) REFERENCES ocr_labeling_items(id),
|
||||
image_path TEXT NOT NULL,
|
||||
ground_truth TEXT NOT NULL,
|
||||
export_format VARCHAR(50) NOT NULL, -- 'generic', 'trocr', 'llama_vision'
|
||||
exported_at TIMESTAMP DEFAULT NOW(),
|
||||
training_batch VARCHAR(100),
|
||||
used_in_training BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
```
|
||||
|
||||
## API Referenz
|
||||
|
||||
Base URL: `http://macmini:8086/api/v1/ocr-label`
|
||||
|
||||
### Sessions
|
||||
|
||||
#### POST /sessions
|
||||
Neue Labeling-Session erstellen.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"name": "Klausur Deutsch 12a Q1",
|
||||
"source_type": "klausur",
|
||||
"description": "Gedichtanalyse Expressionismus",
|
||||
"ocr_model": "llama3.2-vision:11b"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"id": "abc-123-def",
|
||||
"name": "Klausur Deutsch 12a Q1",
|
||||
"source_type": "klausur",
|
||||
"total_items": 0,
|
||||
"labeled_items": 0,
|
||||
"created_at": "2026-01-21T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
#### GET /sessions
|
||||
Sessions auflisten.
|
||||
|
||||
**Query Parameter:**
|
||||
- `limit` (int, default: 50) - Maximale Anzahl
|
||||
|
||||
#### GET /sessions/{session_id}
|
||||
Einzelne Session abrufen.
|
||||
|
||||
### Upload
|
||||
|
||||
#### POST /sessions/{session_id}/upload
|
||||
Bilder zu einer Session hochladen.
|
||||
|
||||
**Request:** Multipart Form Data
|
||||
- `files` (File[]) - PNG/JPG/PDF Dateien
|
||||
- `run_ocr` (bool, default: true) - OCR direkt ausführen
|
||||
- `metadata` (JSON string) - Optional: Metadaten
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"session_id": "abc-123-def",
|
||||
"uploaded_count": 5,
|
||||
"items": [
|
||||
{
|
||||
"id": "item-1",
|
||||
"filename": "scan_001.png",
|
||||
"image_path": "ocr-labeling/abc-123/item-1.png",
|
||||
"ocr_text": "Die Lösung der Aufgabe...",
|
||||
"ocr_confidence": 0.87,
|
||||
"status": "pending"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Labeling Queue
|
||||
|
||||
#### GET /queue
|
||||
Nächste zu labelnde Items abrufen.
|
||||
|
||||
**Query Parameter:**
|
||||
- `session_id` (str, optional) - Nach Session filtern
|
||||
- `status` (str, default: "pending") - Status-Filter
|
||||
- `limit` (int, default: 10) - Maximale Anzahl
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "item-456",
|
||||
"session_id": "abc-123",
|
||||
"session_name": "Klausur Deutsch",
|
||||
"image_path": "/app/ocr-labeling/abc-123/item-456.png",
|
||||
"image_url": "/api/v1/ocr-label/images/abc-123/item-456.png",
|
||||
"ocr_text": "Erkannter Text...",
|
||||
"ocr_confidence": 0.87,
|
||||
"ground_truth": null,
|
||||
"status": "pending",
|
||||
"metadata": {"page": 1}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Labeling Actions
|
||||
|
||||
#### POST /confirm
|
||||
OCR-Text als korrekt bestätigen.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"item_id": "item-456",
|
||||
"label_time_seconds": 5
|
||||
}
|
||||
```
|
||||
|
||||
**Effect:** `ground_truth = ocr_text`, `status = 'confirmed'`
|
||||
|
||||
#### POST /correct
|
||||
Ground Truth korrigieren.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"item_id": "item-456",
|
||||
"ground_truth": "Korrigierter Text hier",
|
||||
"label_time_seconds": 15
|
||||
}
|
||||
```
|
||||
|
||||
**Effect:** `ground_truth = <input>`, `status = 'corrected'`
|
||||
|
||||
#### POST /skip
|
||||
Item überspringen (unbrauchbar).
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"item_id": "item-456"
|
||||
}
|
||||
```
|
||||
|
||||
**Effect:** `status = 'skipped'` (wird nicht exportiert)
|
||||
|
||||
### Statistiken
|
||||
|
||||
#### GET /stats
|
||||
Labeling-Statistiken abrufen.
|
||||
|
||||
**Query Parameter:**
|
||||
- `session_id` (str, optional) - Für Session-spezifische Stats
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"total_items": 100,
|
||||
"labeled_items": 75,
|
||||
"confirmed_items": 60,
|
||||
"corrected_items": 15,
|
||||
"pending_items": 25,
|
||||
"accuracy_rate": 0.80,
|
||||
"avg_label_time_seconds": 8.5
|
||||
}
|
||||
```
|
||||
|
||||
### Training Export
|
||||
|
||||
#### POST /export
|
||||
Trainingsdaten exportieren.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"export_format": "trocr",
|
||||
"session_id": "abc-123",
|
||||
"batch_id": "batch_20260121"
|
||||
}
|
||||
```
|
||||
|
||||
**Export Formate:**
|
||||
|
||||
| Format | Beschreibung | Output |
|
||||
|--------|--------------|--------|
|
||||
| `generic` | Allgemeines JSONL | `{"id", "image_path", "ground_truth", ...}` |
|
||||
| `trocr` | Microsoft TrOCR | `{"file_name", "text", "id"}` |
|
||||
| `llama_vision` | Llama 3.2 Vision | OpenAI-style Messages mit image_url |
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"export_format": "trocr",
|
||||
"batch_id": "batch_20260121",
|
||||
"exported_count": 75,
|
||||
"export_path": "/app/ocr-exports/trocr/batch_20260121",
|
||||
"manifest_path": "/app/ocr-exports/trocr/batch_20260121/manifest.json",
|
||||
"samples": [...]
|
||||
}
|
||||
```
|
||||
|
||||
#### GET /exports
|
||||
Verfügbare Exports auflisten.
|
||||
|
||||
**Query Parameter:**
|
||||
- `export_format` (str, optional) - Nach Format filtern
|
||||
|
||||
## Export Formate im Detail
|
||||
|
||||
### TrOCR Format
|
||||
|
||||
```
|
||||
batch_20260121/
|
||||
├── manifest.json
|
||||
├── train.jsonl
|
||||
└── images/
|
||||
├── item-1.png
|
||||
└── item-2.png
|
||||
```
|
||||
|
||||
**train.jsonl:**
|
||||
```jsonl
|
||||
{"file_name": "images/item-1.png", "text": "Ground truth text", "id": "item-1"}
|
||||
{"file_name": "images/item-2.png", "text": "Another text", "id": "item-2"}
|
||||
```
|
||||
|
||||
### Llama Vision Format
|
||||
|
||||
```jsonl
|
||||
{
|
||||
"id": "item-1",
|
||||
"messages": [
|
||||
{"role": "system", "content": "Du bist ein OCR-Experte für deutsche Handschrift..."},
|
||||
{"role": "user", "content": [
|
||||
{"type": "image_url", "image_url": {"url": "images/item-1.png"}},
|
||||
{"type": "text", "text": "Lies den handgeschriebenen Text in diesem Bild."}
|
||||
]},
|
||||
{"role": "assistant", "content": "Ground truth text"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Generic Format
|
||||
|
||||
```jsonl
|
||||
{
|
||||
"id": "item-1",
|
||||
"image_path": "images/item-1.png",
|
||||
"ground_truth": "Ground truth text",
|
||||
"ocr_text": "OCR recognized text",
|
||||
"ocr_confidence": 0.87,
|
||||
"metadata": {"page": 1, "session": "Deutsch 12a"}
|
||||
}
|
||||
```
|
||||
|
||||
## Frontend Integration
|
||||
|
||||
Die OCR-Labeling UI ist unter `/admin/ocr-labeling` verfügbar.
|
||||
|
||||
### Keyboard Shortcuts
|
||||
|
||||
| Taste | Aktion |
|
||||
|-------|--------|
|
||||
| `Enter` | Bestätigen (OCR korrekt) |
|
||||
| `Tab` | Ins Korrekturfeld springen |
|
||||
| `Escape` | Überspringen |
|
||||
| `←` / `→` | Navigation (Prev/Next) |
|
||||
|
||||
### Workflow
|
||||
|
||||
1. **Session erstellen** - Name, Typ, OCR-Modell wählen
|
||||
2. **Bilder hochladen** - Drag & Drop oder File-Browser
|
||||
3. **Labeling durchführen** - Bild + OCR-Text vergleichen
|
||||
- Korrekt → Bestätigen (Enter)
|
||||
- Falsch → Korrigieren + Speichern
|
||||
- Unbrauchbar → Überspringen
|
||||
4. **Export** - Format wählen (TrOCR, Llama Vision, Generic)
|
||||
5. **Training starten** - Export-Ordner für Fine-Tuning nutzen
|
||||
|
||||
## Umgebungsvariablen
|
||||
|
||||
```bash
|
||||
# PostgreSQL
|
||||
DATABASE_URL=postgres://user:pass@postgres:5432/breakpilot_db
|
||||
|
||||
# MinIO (S3-kompatibel)
|
||||
MINIO_ENDPOINT=minio:9000
|
||||
MINIO_ACCESS_KEY=breakpilot
|
||||
MINIO_SECRET_KEY=breakpilot123
|
||||
MINIO_BUCKET=breakpilot-rag
|
||||
MINIO_SECURE=false
|
||||
|
||||
# Ollama (Vision-LLM)
|
||||
OLLAMA_BASE_URL=http://host.docker.internal:11434
|
||||
OLLAMA_VISION_MODEL=llama3.2-vision:11b
|
||||
OLLAMA_CORRECTION_MODEL=qwen2.5:14b
|
||||
|
||||
# Export
|
||||
OCR_EXPORT_PATH=/app/ocr-exports
|
||||
OCR_STORAGE_PATH=/app/ocr-labeling
|
||||
```
|
||||
|
||||
## Sicherheit & Datenschutz
|
||||
|
||||
- **100% Lokale Verarbeitung** - Alle Daten bleiben auf dem Mac Mini
|
||||
- **Keine Cloud-Uploads** - Ollama läuft vollständig offline
|
||||
- **DSGVO-konform** - Keine Schülerdaten verlassen das Schulnetzwerk
|
||||
- **Deduplizierung** - SHA256-Hash verhindert doppelte Bilder
|
||||
|
||||
## Dateien
|
||||
|
||||
| Datei | Beschreibung |
|
||||
|-------|--------------|
|
||||
| `klausur-service/backend/ocr_labeling_api.py` | FastAPI Router mit OCR Model Dispatcher |
|
||||
| `klausur-service/backend/training_export_service.py` | Export-Service für TrOCR/Llama |
|
||||
| `klausur-service/backend/metrics_db.py` | PostgreSQL CRUD Funktionen |
|
||||
| `klausur-service/backend/minio_storage.py` | MinIO OCR-Image Storage |
|
||||
| `klausur-service/backend/hybrid_vocab_extractor.py` | PaddleOCR Integration |
|
||||
| `klausur-service/backend/services/donut_ocr_service.py` | Donut OCR Service (NEU) |
|
||||
| `klausur-service/backend/services/trocr_service.py` | TrOCR Service (NEU) |
|
||||
| `website/app/admin/ocr-labeling/page.tsx` | Frontend UI mit Model-Auswahl |
|
||||
| `website/app/admin/ocr-labeling/types.ts` | TypeScript Interfaces inkl. OCRModel Type |
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
# Backend-Tests ausführen
|
||||
cd klausur-service/backend
|
||||
pytest tests/test_ocr_labeling.py -v
|
||||
|
||||
# Mit Coverage
|
||||
pytest tests/test_ocr_labeling.py --cov=. --cov-report=html
|
||||
```
|
||||
472
klausur-service/docs/RAG-Admin-Spec.md
Normal file
472
klausur-service/docs/RAG-Admin-Spec.md
Normal file
@@ -0,0 +1,472 @@
|
||||
# RAG & Daten-Management Spezifikation
|
||||
|
||||
## Übersicht
|
||||
|
||||
Admin-Frontend für die Verwaltung von Trainingsdaten und RAG-Systemen in BreakPilot.
|
||||
|
||||
**Location**: `/admin/docs` → Tab "Daten & RAG"
|
||||
**Backend**: `klausur-service` (Port 8086)
|
||||
**Storage**: MinIO (persistentes Docker Volume `minio_data`)
|
||||
**Vector DB**: Qdrant (Port 6333)
|
||||
|
||||
## Datenmodell
|
||||
|
||||
### Zwei Datentypen mit unterschiedlichen Regeln
|
||||
|
||||
| Typ | Quelle | Training erlaubt | Isolation | Collection |
|
||||
|-----|--------|------------------|-----------|------------|
|
||||
| **Landes-Daten** | NiBiS, andere Bundesländer | ✅ Ja | Pro Bundesland | `bp_{bundesland}_{usecase}` |
|
||||
| **Lehrer-Daten** | Lehrer-Upload (BYOEH) | ❌ Nein | Pro Tenant (Schule/Lehrer) | `bp_eh` (verschlüsselt) |
|
||||
|
||||
### Bundesland-Codes (ISO 3166-2:DE)
|
||||
|
||||
```
|
||||
NI = Niedersachsen BY = Bayern BW = Baden-Württemberg
|
||||
NW = Nordrhein-Westf. HE = Hessen SN = Sachsen
|
||||
BE = Berlin HH = Hamburg SH = Schleswig-Holstein
|
||||
BB = Brandenburg MV = Meckl.-Vorp. ST = Sachsen-Anhalt
|
||||
TH = Thüringen RP = Rheinland-Pfalz SL = Saarland
|
||||
HB = Bremen
|
||||
```
|
||||
|
||||
### Use Cases (RAG-Sammlungen)
|
||||
|
||||
| Use Case | Collection Pattern | Beschreibung |
|
||||
|----------|-------------------|--------------|
|
||||
| Klausurkorrektur | `bp_{bl}_klausur` | Erwartungshorizonte für Abitur |
|
||||
| Zeugnisgenerator | `bp_{bl}_zeugnis` | Textbausteine für Zeugnisse |
|
||||
| Lehrplan | `bp_{bl}_lehrplan` | Kerncurricula, Rahmenrichtlinien |
|
||||
|
||||
Beispiel: `bp_ni_klausur` = Niedersachsen Klausurkorrektur
|
||||
|
||||
## MinIO Bucket-Struktur
|
||||
|
||||
```
|
||||
breakpilot-rag/
|
||||
├── landes-daten/
|
||||
│ ├── ni/ # Niedersachsen
|
||||
│ │ ├── klausur/
|
||||
│ │ │ ├── 2016/
|
||||
│ │ │ │ ├── manifest.json
|
||||
│ │ │ │ └── *.pdf
|
||||
│ │ │ ├── 2017/
|
||||
│ │ │ ├── ...
|
||||
│ │ │ └── 2025/
|
||||
│ │ └── zeugnis/
|
||||
│ ├── by/ # Bayern
|
||||
│ └── .../
|
||||
│
|
||||
└── lehrer-daten/ # BYOEH - verschlüsselt
|
||||
└── {tenant_id}/
|
||||
└── {lehrer_id}/
|
||||
└── *.pdf.enc
|
||||
```
|
||||
|
||||
## Qdrant Schema
|
||||
|
||||
### Landes-Daten Collection (z.B. `bp_ni_klausur`)
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "uuid-v5-from-string",
|
||||
"vector": [384 dimensions],
|
||||
"payload": {
|
||||
"original_id": "nibis_2024_deutsch_ea_1_abc123_chunk_0",
|
||||
"doc_id": "nibis_2024_deutsch_ea_1_abc123",
|
||||
"chunk_index": 0,
|
||||
"text": "Der Erwartungshorizont...",
|
||||
"year": 2024,
|
||||
"subject": "Deutsch",
|
||||
"niveau": "eA",
|
||||
"task_number": 1,
|
||||
"doc_type": "EWH",
|
||||
"bundesland": "NI",
|
||||
"source": "nibis",
|
||||
"training_allowed": true,
|
||||
"minio_path": "landes-daten/ni/klausur/2024/2024_Deutsch_eA_I_EWH.pdf"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Lehrer-Daten Collection (`bp_eh`)
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"vector": [384 dimensions],
|
||||
"payload": {
|
||||
"tenant_id": "schule_123",
|
||||
"eh_id": "eh_abc",
|
||||
"chunk_index": 0,
|
||||
"subject": "deutsch",
|
||||
"encrypted_content": "base64...",
|
||||
"training_allowed": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Frontend-Komponenten
|
||||
|
||||
### 1. Sammlungen-Übersicht (`/admin/rag/collections`)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Daten & RAG │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Sammlungen [+ Neu] │
|
||||
│ ───────────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ 📚 Niedersachsen - Klausurkorrektur │ │
|
||||
│ │ bp_ni_klausur | 630 Docs | 4.521 Chunks | 2016-2025 │ │
|
||||
│ │ [Suchen] [Indexieren] [Details] │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ 📚 Niedersachsen - Zeugnisgenerator │ │
|
||||
│ │ bp_ni_zeugnis | 0 Docs | Leer │ │
|
||||
│ │ [Suchen] [Indexieren] [Details] │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2. Upload-Bereich (`/admin/rag/upload`)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Dokumente hochladen │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Ziel-Sammlung: [Niedersachsen - Klausurkorrektur ▼] │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ 📁 ZIP-Datei oder Ordner hierher ziehen │ │
|
||||
│ │ │ │
|
||||
│ │ oder [Dateien auswählen] │ │
|
||||
│ │ │ │
|
||||
│ │ Unterstützt: .zip, .pdf, Ordner │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Upload-Queue: │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ ✅ 2018.zip - 45 PDFs erkannt │ │
|
||||
│ │ ⏳ 2019.zip - Wird analysiert... │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ [Hochladen & Indexieren] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3. Ingestion-Status (`/admin/rag/ingestion`)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Ingestion Status │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Aktueller Job: Niedersachsen Klausur 2024 │
|
||||
│ ████████████████████░░░░░░░░░░ 65% (412/630 Docs) │
|
||||
│ Chunks: 2.891 | Fehler: 3 | ETA: 4:32 │
|
||||
│ [Pausieren] [Abbrechen] │
|
||||
│ │
|
||||
│ ───────────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
│ Letzte Jobs: │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ ✅ 09.01.2025 15:30 - NI Klausur 2024 - 128 Chunks │ │
|
||||
│ │ ✅ 09.01.2025 14:00 - NI Klausur 2017 - 890 Chunks │ │
|
||||
│ │ ❌ 08.01.2025 10:15 - BY Klausur - Fehler: Timeout │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4. Suche & Qualitätstest (`/admin/rag/search`)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ RAG Suche & Qualitätstest │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Sammlung: [Niedersachsen - Klausurkorrektur ▼] │
|
||||
│ │
|
||||
│ Query: [Analyse eines Gedichts von Rilke ] │
|
||||
│ │
|
||||
│ Filter: │
|
||||
│ Jahr: [Alle ▼] Fach: [Deutsch ▼] Niveau: [eA ▼] │
|
||||
│ │
|
||||
│ [🔍 Suchen] │
|
||||
│ │
|
||||
│ ───────────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
│ Ergebnisse (3): Latenz: 45ms │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ #1 | Score: 0.847 | 2024 Deutsch eA Aufgabe 2 │ │
|
||||
│ │ │ │
|
||||
│ │ "...Die Analyse des Rilke-Gedichts soll folgende │ │
|
||||
│ │ Aspekte berücksichtigen: Aufbau, Bildsprache..." │ │
|
||||
│ │ │ │
|
||||
│ │ Relevanz: [⭐⭐⭐⭐⭐] [⭐⭐⭐⭐] [⭐⭐⭐] [⭐⭐] [⭐] │ │
|
||||
│ │ Notizen: [Optional: Warum relevant/nicht relevant? ] │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 5. Metriken-Dashboard (`/admin/rag/metrics`)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ RAG Qualitätsmetriken │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Zeitraum: [Letzte 7 Tage ▼] Sammlung: [Alle ▼] │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Precision@5 │ │ Recall@10 │ │ MRR │ │
|
||||
│ │ 0.78 │ │ 0.85 │ │ 0.72 │ │
|
||||
│ │ ↑ +5% │ │ ↑ +3% │ │ ↓ -2% │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Avg Latency │ │ Bewertungen │ │ Fehlerrate │ │
|
||||
│ │ 52ms │ │ 127 │ │ 0.3% │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
│ ───────────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
│ Score-Verteilung: │
|
||||
│ 0.9+ ████████████████ 23% │
|
||||
│ 0.7+ ████████████████████████████ 41% │
|
||||
│ 0.5+ ████████████████████ 28% │
|
||||
│ <0.5 ██████ 8% │
|
||||
│ │
|
||||
│ [Export CSV] [Detailbericht] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Collections API
|
||||
|
||||
```
|
||||
GET /api/v1/admin/rag/collections
|
||||
POST /api/v1/admin/rag/collections
|
||||
GET /api/v1/admin/rag/collections/{id}
|
||||
DELETE /api/v1/admin/rag/collections/{id}
|
||||
GET /api/v1/admin/rag/collections/{id}/stats
|
||||
```
|
||||
|
||||
### Upload API
|
||||
|
||||
```
|
||||
POST /api/v1/admin/rag/upload
|
||||
Content-Type: multipart/form-data
|
||||
- file: ZIP oder PDF
|
||||
- collection_id: string
|
||||
- metadata: JSON (optional)
|
||||
|
||||
POST /api/v1/admin/rag/upload/folder
|
||||
- Für Ordner-Upload (WebKitDirectory)
|
||||
```
|
||||
|
||||
### Ingestion API
|
||||
|
||||
```
|
||||
POST /api/v1/admin/rag/ingest
|
||||
- collection_id: string
|
||||
- filters: {year?, subject?, doc_type?}
|
||||
|
||||
GET /api/v1/admin/rag/ingest/status
|
||||
GET /api/v1/admin/rag/ingest/history
|
||||
POST /api/v1/admin/rag/ingest/cancel
|
||||
```
|
||||
|
||||
### Search API
|
||||
|
||||
```
|
||||
POST /api/v1/admin/rag/search
|
||||
- query: string
|
||||
- collection_id: string
|
||||
- filters: {year?, subject?, niveau?}
|
||||
- limit: int
|
||||
|
||||
POST /api/v1/admin/rag/search/feedback
|
||||
- result_id: string
|
||||
- rating: 1-5
|
||||
- notes: string (optional)
|
||||
```
|
||||
|
||||
### Metrics API
|
||||
|
||||
```
|
||||
GET /api/v1/admin/rag/metrics
|
||||
- collection_id?: string
|
||||
- from_date?: date
|
||||
- to_date?: date
|
||||
|
||||
GET /api/v1/admin/rag/metrics/export
|
||||
- format: csv|json
|
||||
```
|
||||
|
||||
## Embedding-Konfiguration
|
||||
|
||||
```python
|
||||
# Default: Lokale Embeddings (kein API-Key nötig)
|
||||
EMBEDDING_BACKEND = "local"
|
||||
LOCAL_EMBEDDING_MODEL = "all-MiniLM-L6-v2"
|
||||
VECTOR_DIMENSIONS = 384
|
||||
|
||||
# Optional: OpenAI (für Produktion)
|
||||
EMBEDDING_BACKEND = "openai"
|
||||
EMBEDDING_MODEL = "text-embedding-3-small"
|
||||
VECTOR_DIMENSIONS = 1536
|
||||
```
|
||||
|
||||
## Datenpersistenz
|
||||
|
||||
### Docker Volumes (WICHTIG - nicht löschen!)
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
minio_data: # Alle hochgeladenen Dokumente
|
||||
qdrant_data: # Alle Vektoren und Embeddings
|
||||
postgres_data: # Metadaten, Bewertungen, History
|
||||
```
|
||||
|
||||
### Backup-Strategie
|
||||
|
||||
```bash
|
||||
# MinIO Backup
|
||||
docker exec breakpilot-pwa-minio mc mirror /data /backup
|
||||
|
||||
# Qdrant Backup
|
||||
curl -X POST http://localhost:6333/collections/bp_ni_klausur/snapshots
|
||||
|
||||
# Postgres Backup (bereits implementiert)
|
||||
# Läuft automatisch täglich um 2 Uhr
|
||||
```
|
||||
|
||||
## Implementierungsreihenfolge
|
||||
|
||||
1. ✅ Backend: Basis-Ingestion (nibis_ingestion.py)
|
||||
2. ✅ Backend: Lokale Embeddings (sentence-transformers)
|
||||
3. ✅ Backend: MinIO-Integration (minio_storage.py)
|
||||
4. ✅ Backend: Collections API (admin_api.py)
|
||||
5. ✅ Backend: Upload API mit ZIP-Support
|
||||
6. ✅ Backend: Metrics API mit PostgreSQL (metrics_db.py)
|
||||
7. ✅ Frontend: Sammlungen-Übersicht
|
||||
8. ✅ Frontend: Upload-Bereich (Drag & Drop)
|
||||
9. ✅ Frontend: Ingestion-Status
|
||||
10. ✅ Frontend: Suche & Qualitätstest (mit Stern-Bewertungen)
|
||||
11. ✅ Frontend: Metriken-Dashboard
|
||||
|
||||
## Technologie-Stack
|
||||
|
||||
- **Frontend**: Next.js 15 (`/website/app/admin/rag/page.tsx`)
|
||||
- **Backend**: FastAPI (`klausur-service/backend/`)
|
||||
- **Vector DB**: Qdrant v1.7.4 (384-dim Vektoren)
|
||||
- **Object Storage**: MinIO (S3-kompatibel)
|
||||
- **Embeddings**: sentence-transformers `all-MiniLM-L6-v2`
|
||||
- **Metrics DB**: PostgreSQL 16
|
||||
|
||||
## Entwickler-Dokumentation
|
||||
|
||||
### Projektstruktur
|
||||
|
||||
```
|
||||
klausur-service/
|
||||
├── backend/
|
||||
│ ├── main.py # FastAPI App + BYOEH Endpoints
|
||||
│ ├── admin_api.py # RAG Admin API (Upload, Search, Metrics)
|
||||
│ ├── nibis_ingestion.py # NiBiS Dokument-Ingestion Pipeline
|
||||
│ ├── eh_pipeline.py # Chunking, Embeddings, Encryption
|
||||
│ ├── qdrant_service.py # Qdrant Client + Search
|
||||
│ ├── minio_storage.py # MinIO S3 Storage
|
||||
│ ├── metrics_db.py # PostgreSQL Metrics
|
||||
│ ├── requirements.txt # Python Dependencies
|
||||
│ └── tests/
|
||||
│ └── test_rag_admin.py
|
||||
└── docs/
|
||||
└── RAG-Admin-Spec.md # Diese Datei
|
||||
```
|
||||
|
||||
### Schnellstart für Entwickler
|
||||
|
||||
```bash
|
||||
# 1. Services starten
|
||||
cd /path/to/breakpilot-pwa
|
||||
docker-compose up -d qdrant minio postgres
|
||||
|
||||
# 2. Dependencies installieren
|
||||
cd klausur-service/backend
|
||||
pip install -r requirements.txt
|
||||
|
||||
# 3. Service starten
|
||||
python -m uvicorn main:app --port 8086 --reload
|
||||
|
||||
# 4. RAG-Services initialisieren (erstellt Bucket + Tabellen)
|
||||
curl -X POST http://localhost:8086/api/v1/admin/rag/init
|
||||
```
|
||||
|
||||
### API-Referenz (Implementiert)
|
||||
|
||||
#### NiBiS Ingestion
|
||||
```
|
||||
GET /api/v1/admin/nibis/discover # Dokumente finden
|
||||
POST /api/v1/admin/nibis/ingest # Indexierung starten
|
||||
GET /api/v1/admin/nibis/status # Status abfragen
|
||||
GET /api/v1/admin/nibis/stats # Statistiken
|
||||
POST /api/v1/admin/nibis/search # Semantische Suche
|
||||
GET /api/v1/admin/nibis/collections # Qdrant Collections
|
||||
```
|
||||
|
||||
#### RAG Upload & Storage
|
||||
```
|
||||
POST /api/v1/admin/rag/upload # ZIP/PDF hochladen
|
||||
GET /api/v1/admin/rag/upload/history # Upload-Verlauf
|
||||
GET /api/v1/admin/rag/storage/stats # MinIO Statistiken
|
||||
```
|
||||
|
||||
#### Metrics & Feedback
|
||||
```
|
||||
GET /api/v1/admin/rag/metrics # Qualitätsmetriken
|
||||
POST /api/v1/admin/rag/search/feedback # Bewertung abgeben
|
||||
POST /api/v1/admin/rag/init # Services initialisieren
|
||||
```
|
||||
|
||||
### Umgebungsvariablen
|
||||
|
||||
```bash
|
||||
# Qdrant
|
||||
QDRANT_URL=http://localhost:6333
|
||||
|
||||
# MinIO
|
||||
MINIO_ENDPOINT=localhost:9000
|
||||
MINIO_ACCESS_KEY=breakpilot
|
||||
MINIO_SECRET_KEY=breakpilot123
|
||||
MINIO_BUCKET=breakpilot-rag
|
||||
|
||||
# PostgreSQL
|
||||
DATABASE_URL=postgres://breakpilot:breakpilot123@localhost:5432/breakpilot_db
|
||||
|
||||
# Embeddings
|
||||
EMBEDDING_BACKEND=local
|
||||
LOCAL_EMBEDDING_MODEL=all-MiniLM-L6-v2
|
||||
```
|
||||
|
||||
### Aktuelle Indexierungs-Statistik
|
||||
|
||||
- **Dokumente**: 579 Erwartungshorizonte (NiBiS)
|
||||
- **Chunks**: 7.352
|
||||
- **Jahre**: 2016, 2017, 2024, 2025
|
||||
- **Fächer**: Deutsch, Englisch, Mathematik, Physik, Chemie, Biologie, Geschichte, Politik-Wirtschaft, Erdkunde, Sport, Kunst, Musik, Latein, Informatik, Ev. Religion, Kath. Religion, Werte und Normen, etc.
|
||||
- **Collection**: `bp_nibis_eh`
|
||||
- **Vektor-Dimensionen**: 384
|
||||
293
klausur-service/docs/Vocab-Worksheet-Architecture.md
Normal file
293
klausur-service/docs/Vocab-Worksheet-Architecture.md
Normal file
@@ -0,0 +1,293 @@
|
||||
# Vokabel-Arbeitsblatt Generator - Architektur
|
||||
|
||||
**Version:** 1.0.0
|
||||
**Datum:** 2026-01-23
|
||||
**Status:** Produktiv
|
||||
|
||||
---
|
||||
|
||||
## 1. Uebersicht
|
||||
|
||||
Der Vokabel-Arbeitsblatt Generator ist ein DSGVO-konformes Tool fuer Lehrer, das Vokabeln aus Schulbuchseiten extrahiert und druckfertige Arbeitsblaetter generiert.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ Studio v2 (Next.js) │
|
||||
│ Port 3001 │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ /vocab-worksheet │ │
|
||||
│ │ - Session-Management (erstellen, fortsetzen, loeschen) │ │
|
||||
│ │ - PDF-Upload mit Seitenauswahl │ │
|
||||
│ │ - Vokabel-Bearbeitung (Grid-Editor) │ │
|
||||
│ │ - Arbeitsblatt-Konfiguration │ │
|
||||
│ │ - PDF-Export │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼ HTTP/REST
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ Klausur-Service (FastAPI) │
|
||||
│ Port 8086 │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ /api/v1/vocab/* │ │
|
||||
│ │ - Session CRUD │ │
|
||||
│ │ - PDF-Verarbeitung (PyMuPDF) │ │
|
||||
│ │ - Vokabel-Extraktion (Vision LLM / Hybrid OCR) │ │
|
||||
│ │ - Arbeitsblatt-Generierung (WeasyPrint) │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
┌───────────────┴───────────────┐
|
||||
▼ ▼
|
||||
┌───────────────────────────────┐ ┌───────────────────────────────────┐
|
||||
│ Ollama Vision LLM │ │ LLM Gateway │
|
||||
│ Port 11434 │ │ Port 8002 │
|
||||
│ ┌─────────────────────────┐ │ │ ┌─────────────────────────────┐ │
|
||||
│ │ qwen2.5vl:32b │ │ │ │ qwen2.5:14b │ │
|
||||
│ │ (Bild → Vokabeln) │ │ │ │ (OCR-Text → strukturiert) │ │
|
||||
│ └─────────────────────────┘ │ │ └─────────────────────────────┘ │
|
||||
└───────────────────────────────┘ └───────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Komponenten
|
||||
|
||||
### 2.1 Frontend (studio-v2)
|
||||
|
||||
**Datei:** `/studio-v2/app/vocab-worksheet/page.tsx`
|
||||
|
||||
| Aspekt | Details |
|
||||
|--------|---------|
|
||||
| Framework | Next.js 16.1.4 mit React 19.0.0 |
|
||||
| Styling | Tailwind CSS 3.4.17 |
|
||||
| Sprache | TypeScript 5.7.0 |
|
||||
| State | React Hooks (useState, useRef, useEffect) |
|
||||
|
||||
**Tab-basierter Workflow:**
|
||||
|
||||
1. **Upload** - Session benennen, Datei auswaehlen (Bild/PDF)
|
||||
2. **Pages** - Bei PDFs: Seiten mit Thumbnails auswaehlen
|
||||
3. **Vocabulary** - Extrahierte Vokabeln pruefen/bearbeiten
|
||||
4. **Worksheet** - Arbeitsblatt-Typ und Format waehlen
|
||||
5. **Export** - PDF herunterladen
|
||||
|
||||
**Datenstrukturen:**
|
||||
|
||||
```typescript
|
||||
interface VocabularyEntry {
|
||||
id: string
|
||||
english: string
|
||||
german: string
|
||||
example_sentence?: string
|
||||
word_type?: string
|
||||
source_page?: number
|
||||
}
|
||||
|
||||
interface Session {
|
||||
id: string
|
||||
name: string
|
||||
status: 'pending' | 'processing' | 'extracted' | 'completed'
|
||||
vocabulary_count: number
|
||||
}
|
||||
|
||||
type WorksheetType = 'en_to_de' | 'de_to_en' | 'copy' | 'gap_fill'
|
||||
```
|
||||
|
||||
### 2.2 Backend API
|
||||
|
||||
**Datei:** `/klausur-service/backend/vocab_worksheet_api.py`
|
||||
|
||||
| Aspekt | Details |
|
||||
|--------|---------|
|
||||
| Framework | FastAPI (async) |
|
||||
| Router-Prefix | `/api/v1/vocab` |
|
||||
| Storage | In-Memory (Dict) + Filesystem |
|
||||
|
||||
**Endpoints:**
|
||||
|
||||
| Methode | Pfad | Beschreibung |
|
||||
|---------|------|--------------|
|
||||
| POST | `/sessions` | Session erstellen |
|
||||
| GET | `/sessions` | Sessions auflisten |
|
||||
| GET | `/sessions/{id}` | Session-Details |
|
||||
| DELETE | `/sessions/{id}` | Session loeschen |
|
||||
| POST | `/sessions/{id}/upload` | Bild/PDF hochladen |
|
||||
| POST | `/sessions/{id}/upload-pdf-info` | PDF-Info abrufen |
|
||||
| GET | `/sessions/{id}/pdf-thumbnail/{page}` | Seiten-Thumbnail |
|
||||
| POST | `/sessions/{id}/process-single-page/{page}` | Einzelne Seite verarbeiten |
|
||||
| GET | `/sessions/{id}/vocabulary` | Vokabeln abrufen |
|
||||
| PUT | `/sessions/{id}/vocabulary` | Vokabeln aktualisieren |
|
||||
| POST | `/sessions/{id}/generate` | Arbeitsblatt generieren |
|
||||
| GET | `/worksheets/{id}/pdf` | Arbeitsblatt-PDF |
|
||||
| GET | `/worksheets/{id}/solution` | Loesungs-PDF |
|
||||
|
||||
### 2.3 Vokabel-Extraktion
|
||||
|
||||
**Zwei Modi verfuegbar:**
|
||||
|
||||
#### A. Vision LLM (Standard)
|
||||
|
||||
```python
|
||||
OLLAMA_URL = "http://host.docker.internal:11434"
|
||||
VISION_MODEL = "qwen2.5vl:32b"
|
||||
```
|
||||
|
||||
- Bild wird Base64-kodiert an Ollama gesendet
|
||||
- Prompt in Deutsch fuer bessere Erkennung
|
||||
- Timeout: 5 Minuten pro Seite
|
||||
- Confidence: ~85%
|
||||
|
||||
#### B. Hybrid OCR + LLM (Optional)
|
||||
|
||||
**Datei:** `/klausur-service/backend/hybrid_vocab_extractor.py`
|
||||
|
||||
```
|
||||
Bild → PaddleOCR → Text-Regionen → LLM Gateway → Strukturiertes JSON
|
||||
```
|
||||
|
||||
- PaddleOCR 3.x fuer Text-Erkennung
|
||||
- Automatische Spalten-Erkennung (2 oder 3 Spalten)
|
||||
- qwen2.5:14b fuer Strukturierung
|
||||
- ~4x schneller als Vision LLM
|
||||
|
||||
### 2.4 PDF-Verarbeitung
|
||||
|
||||
| Aufgabe | Bibliothek |
|
||||
|---------|------------|
|
||||
| PDF → PNG | PyMuPDF (fitz) |
|
||||
| Thumbnails | PyMuPDF mit Zoom 0.5 |
|
||||
| OCR-Bilder | PyMuPDF mit Zoom 2.0 |
|
||||
| PDF-Generierung | WeasyPrint |
|
||||
|
||||
---
|
||||
|
||||
## 3. Datenfluss
|
||||
|
||||
```
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│ Upload │───►│ OCR/ │───►│ Edit │───►│ Export │
|
||||
│ PDF │ │ Extract │ │ Vocab │ │ PDF │
|
||||
└──────────┘ └──────────┘ └──────────┘ └──────────┘
|
||||
│ │ │ │
|
||||
▼ ▼ ▼ ▼
|
||||
/upload /process- /vocabulary /generate
|
||||
single-page
|
||||
```
|
||||
|
||||
**Session-Status-Workflow:**
|
||||
|
||||
```
|
||||
PENDING → PROCESSING → EXTRACTED → COMPLETED
|
||||
│ │ │ │
|
||||
Upload Extraktion Bereit zum Worksheet
|
||||
erfolgt laeuft Bearbeiten generiert
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Arbeitsblatt-Typen
|
||||
|
||||
| Typ | Beschreibung |
|
||||
|-----|--------------|
|
||||
| `en_to_de` | Englisch → Deutsch uebersetzen |
|
||||
| `de_to_en` | Deutsch → Englisch uebersetzen |
|
||||
| `copy` | Woerter mehrfach abschreiben |
|
||||
| `gap_fill` | Lueckentext mit Beispielsaetzen |
|
||||
|
||||
**Optionen:**
|
||||
|
||||
- Zeilenhoehe: normal / large / extra-large
|
||||
- Loesungen: ja / nein
|
||||
- Wiederholungen (bei Copy): 1-5
|
||||
|
||||
---
|
||||
|
||||
## 5. Datenschutz (DSGVO)
|
||||
|
||||
| Aspekt | Umsetzung |
|
||||
|--------|-----------|
|
||||
| Verarbeitung | 100% lokal (Mac Mini) |
|
||||
| Externe APIs | Keine |
|
||||
| LLM | Ollama (lokal) |
|
||||
| Speicherung | Lokales Filesystem |
|
||||
| Datentransfer | Nur innerhalb LAN |
|
||||
|
||||
**Keine Daten werden an externe Server gesendet.**
|
||||
|
||||
---
|
||||
|
||||
## 6. Konfiguration
|
||||
|
||||
**Umgebungsvariablen:**
|
||||
|
||||
```bash
|
||||
# Ollama Vision LLM
|
||||
OLLAMA_URL=http://host.docker.internal:11434
|
||||
OLLAMA_VISION_MODEL=qwen2.5vl:32b
|
||||
|
||||
# LLM Gateway (Hybrid Mode)
|
||||
LLM_GATEWAY_URL=http://host.docker.internal:8002
|
||||
LLM_MODEL=qwen2.5:14b
|
||||
|
||||
# Storage
|
||||
VOCAB_STORAGE_PATH=/app/vocab-worksheets
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Abhaengigkeiten
|
||||
|
||||
### Backend (Python)
|
||||
|
||||
| Paket | Version | Zweck |
|
||||
|-------|---------|-------|
|
||||
| FastAPI | 0.123.9 | Web Framework |
|
||||
| PyMuPDF | 1.25.4 | PDF-Verarbeitung |
|
||||
| WeasyPrint | 66.0 | PDF-Generierung |
|
||||
| Pillow | 11.3.0 | Bildverarbeitung |
|
||||
| httpx | 0.28.1 | Async HTTP Client |
|
||||
| PaddleOCR | 3.x | OCR (optional) |
|
||||
|
||||
### Frontend (Node.js)
|
||||
|
||||
| Paket | Version | Zweck |
|
||||
|-------|---------|-------|
|
||||
| Next.js | 16.1.4 | Framework |
|
||||
| React | 19.0.0 | UI Library |
|
||||
| Tailwind CSS | 3.4.17 | Styling |
|
||||
| TypeScript | 5.7.0 | Type Safety |
|
||||
|
||||
---
|
||||
|
||||
## 8. Deployment
|
||||
|
||||
**Docker-Container:**
|
||||
|
||||
- `klausur-service` (Port 8086) - Backend API
|
||||
- `studio-v2` (Port 3001) - Frontend
|
||||
|
||||
**URLs:**
|
||||
|
||||
- Frontend: `http://macmini:3001/vocab-worksheet`
|
||||
- API: `http://macmini:8086/api/v1/vocab/`
|
||||
|
||||
---
|
||||
|
||||
## 9. Erweiterungsmoeglichkeiten
|
||||
|
||||
| Feature | Status |
|
||||
|---------|--------|
|
||||
| Weitere Sprachen (FR, ES) | Geplant |
|
||||
| Datenbank-Persistenz | Geplant |
|
||||
| Batch-Verarbeitung | Geplant |
|
||||
| Woerterbuch-Integration | Idee |
|
||||
| Audio-Ausspracheuebungen | Idee |
|
||||
|
||||
---
|
||||
|
||||
## 10. Verwandte Dokumentation
|
||||
|
||||
- [BYOEH-Architecture.md](./BYOEH-Architecture.md)
|
||||
- [OCR-Labeling-Spec.md](./OCR-Labeling-Spec.md)
|
||||
- [DSGVO-Audit-OCR-Labeling.md](./DSGVO-Audit-OCR-Labeling.md)
|
||||
425
klausur-service/docs/Vocab-Worksheet-Developer-Guide.md
Normal file
425
klausur-service/docs/Vocab-Worksheet-Developer-Guide.md
Normal file
@@ -0,0 +1,425 @@
|
||||
# Vokabel-Arbeitsblatt Generator - Entwicklerhandbuch
|
||||
|
||||
**Version:** 1.0.0
|
||||
**Datum:** 2026-01-23
|
||||
|
||||
---
|
||||
|
||||
## 1. Schnellstart
|
||||
|
||||
### 1.1 Lokale Entwicklung
|
||||
|
||||
```bash
|
||||
# Backend starten (klausur-service)
|
||||
cd /Users/benjaminadmin/Projekte/breakpilot-pwa/klausur-service/backend
|
||||
source venv/bin/activate
|
||||
uvicorn main:app --host 0.0.0.0 --port 8086 --reload
|
||||
|
||||
# Frontend starten (studio-v2)
|
||||
cd /Users/benjaminadmin/Projekte/breakpilot-pwa/studio-v2
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 1.2 URLs
|
||||
|
||||
| Umgebung | Frontend | Backend API |
|
||||
|----------|----------|-------------|
|
||||
| Lokal | http://localhost:3001/vocab-worksheet | http://localhost:8086/api/v1/vocab/ |
|
||||
| Mac Mini | http://macmini:3001/vocab-worksheet | http://macmini:8086/api/v1/vocab/ |
|
||||
|
||||
---
|
||||
|
||||
## 2. Projektstruktur
|
||||
|
||||
```
|
||||
breakpilot-pwa/
|
||||
├── klausur-service/
|
||||
│ ├── backend/
|
||||
│ │ ├── main.py # FastAPI App (inkl. Vocab-Router)
|
||||
│ │ ├── vocab_worksheet_api.py # Vocab-Worksheet Endpoints
|
||||
│ │ ├── hybrid_vocab_extractor.py # PaddleOCR + LLM Pipeline
|
||||
│ │ └── tests/
|
||||
│ │ └── test_vocab_worksheet.py # Unit Tests
|
||||
│ └── docs/
|
||||
│ ├── Vocab-Worksheet-Architecture.md
|
||||
│ └── Vocab-Worksheet-Developer-Guide.md
|
||||
│
|
||||
└── studio-v2/
|
||||
└── app/
|
||||
└── vocab-worksheet/
|
||||
└── page.tsx # Frontend (React/Next.js)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Backend API
|
||||
|
||||
### 3.1 Endpoints-Uebersicht
|
||||
|
||||
```
|
||||
POST /api/v1/vocab/sessions # Session erstellen
|
||||
GET /api/v1/vocab/sessions # Sessions auflisten
|
||||
GET /api/v1/vocab/sessions/{id} # Session abrufen
|
||||
DELETE /api/v1/vocab/sessions/{id} # Session loeschen
|
||||
|
||||
POST /api/v1/vocab/sessions/{id}/upload # Bild/PDF hochladen
|
||||
POST /api/v1/vocab/sessions/{id}/upload-pdf-info # PDF-Info abrufen
|
||||
GET /api/v1/vocab/sessions/{id}/pdf-thumbnail/{p} # Seiten-Thumbnail
|
||||
POST /api/v1/vocab/sessions/{id}/process-single-page/{p} # Seite verarbeiten
|
||||
|
||||
GET /api/v1/vocab/sessions/{id}/vocabulary # Vokabeln abrufen
|
||||
PUT /api/v1/vocab/sessions/{id}/vocabulary # Vokabeln aktualisieren
|
||||
|
||||
POST /api/v1/vocab/sessions/{id}/generate # Arbeitsblatt generieren
|
||||
GET /api/v1/vocab/worksheets/{id}/pdf # PDF herunterladen
|
||||
GET /api/v1/vocab/worksheets/{id}/solution # Loesungs-PDF
|
||||
```
|
||||
|
||||
### 3.2 Session erstellen
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8086/api/v1/vocab/sessions \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "Englisch Klasse 7 - Unit 3",
|
||||
"description": "Vokabeln aus Green Line",
|
||||
"source_language": "en",
|
||||
"target_language": "de"
|
||||
}'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"id": "15dce1f4-f587-4b80-8c3d-62b20e7b845c",
|
||||
"name": "Englisch Klasse 7 - Unit 3",
|
||||
"status": "pending",
|
||||
"vocabulary_count": 0,
|
||||
"created_at": "2026-01-23T10:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 Bild hochladen
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8086/api/v1/vocab/sessions/{session_id}/upload \
|
||||
-F "file=@vokabeln.png"
|
||||
```
|
||||
|
||||
### 3.4 PDF verarbeiten
|
||||
|
||||
```bash
|
||||
# 1. PDF hochladen und Info abrufen
|
||||
curl -X POST http://localhost:8086/api/v1/vocab/sessions/{id}/upload-pdf-info \
|
||||
-F "file=@schulbuch.pdf"
|
||||
|
||||
# Response: {"session_id": "...", "page_count": 5}
|
||||
|
||||
# 2. Einzelne Seiten verarbeiten (empfohlen)
|
||||
curl -X POST http://localhost:8086/api/v1/vocab/sessions/{id}/process-single-page/0
|
||||
curl -X POST http://localhost:8086/api/v1/vocab/sessions/{id}/process-single-page/1
|
||||
```
|
||||
|
||||
### 3.5 Vokabeln aktualisieren
|
||||
|
||||
```bash
|
||||
curl -X PUT http://localhost:8086/api/v1/vocab/sessions/{id}/vocabulary \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"vocabulary": [
|
||||
{
|
||||
"id": "uuid-1",
|
||||
"english": "achieve",
|
||||
"german": "erreichen",
|
||||
"example_sentence": "She achieved her goals."
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
### 3.6 Arbeitsblatt generieren
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8086/api/v1/vocab/sessions/{id}/generate \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"worksheet_types": ["en_to_de", "de_to_en"],
|
||||
"include_solutions": true,
|
||||
"line_height": "large"
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Frontend-Entwicklung
|
||||
|
||||
### 4.1 Komponenten-Struktur
|
||||
|
||||
Die gesamte UI ist in einer Datei (`page.tsx`) organisiert:
|
||||
|
||||
```typescript
|
||||
// Hauptkomponente
|
||||
export default function VocabWorksheetPage() {
|
||||
const [activeTab, setActiveTab] = useState<TabType>('upload')
|
||||
const [sessions, setSessions] = useState<Session[]>([])
|
||||
const [currentSession, setCurrentSession] = useState<Session | null>(null)
|
||||
const [vocabulary, setVocabulary] = useState<VocabularyEntry[]>([])
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
// Tabs
|
||||
type TabType = 'upload' | 'pages' | 'vocabulary' | 'worksheet' | 'export'
|
||||
```
|
||||
|
||||
### 4.2 API-Aufrufe
|
||||
|
||||
```typescript
|
||||
// API Base URL automatisch ermitteln
|
||||
const getApiBase = () => {
|
||||
if (typeof window === 'undefined') return 'http://localhost:8086'
|
||||
const host = window.location.hostname
|
||||
return `http://${host}:8086`
|
||||
}
|
||||
|
||||
// Session erstellen
|
||||
const createSession = async (name: string) => {
|
||||
const response = await fetch(`${getApiBase()}/api/v1/vocab/sessions`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ name })
|
||||
})
|
||||
return response.json()
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 Styling
|
||||
|
||||
Tailwind CSS mit Dark/Light Theme:
|
||||
|
||||
```typescript
|
||||
// Theme-aware Klassen
|
||||
className="bg-white dark:bg-gray-800 text-gray-900 dark:text-white"
|
||||
|
||||
// Gradient-Buttons
|
||||
className="bg-gradient-to-r from-purple-600 to-blue-600 hover:from-purple-700 hover:to-blue-700"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Vokabel-Extraktion
|
||||
|
||||
### 5.1 Vision LLM Modus (Standard)
|
||||
|
||||
```python
|
||||
# vocab_worksheet_api.py
|
||||
|
||||
OLLAMA_URL = os.getenv("OLLAMA_URL", "http://host.docker.internal:11434")
|
||||
VISION_MODEL = os.getenv("OLLAMA_VISION_MODEL", "qwen2.5vl:32b")
|
||||
|
||||
async def extract_vocabulary_from_image(image_data: bytes, filename: str):
|
||||
# Base64-kodiertes Bild an Ollama senden
|
||||
image_base64 = base64.b64encode(image_data).decode("utf-8")
|
||||
|
||||
payload = {
|
||||
"model": VISION_MODEL,
|
||||
"messages": [{
|
||||
"role": "user",
|
||||
"content": VOCAB_EXTRACTION_PROMPT,
|
||||
"images": [image_base64]
|
||||
}],
|
||||
"stream": False
|
||||
}
|
||||
|
||||
response = await client.post(f"{OLLAMA_URL}/api/chat", json=payload)
|
||||
# Parse JSON response...
|
||||
```
|
||||
|
||||
### 5.2 Hybrid OCR + LLM Modus (Optional)
|
||||
|
||||
```python
|
||||
# hybrid_vocab_extractor.py
|
||||
|
||||
async def extract_vocabulary_hybrid(image_bytes: bytes, page_number: int):
|
||||
# 1. PaddleOCR fuer Text-Erkennung
|
||||
regions, raw_text = run_paddle_ocr(image_bytes)
|
||||
|
||||
# 2. Text fuer LLM formatieren
|
||||
formatted_text = format_ocr_for_llm(regions)
|
||||
|
||||
# 3. LLM strukturiert die Daten
|
||||
vocabulary = await structure_vocabulary_with_llm(formatted_text)
|
||||
|
||||
return vocabulary, confidence, error
|
||||
```
|
||||
|
||||
### 5.3 Prompt Engineering
|
||||
|
||||
Der Extraktions-Prompt ist auf Deutsch fuer bessere Ergebnisse:
|
||||
|
||||
```python
|
||||
VOCAB_EXTRACTION_PROMPT = """Analysiere dieses Bild einer Vokabelliste aus einem Schulbuch.
|
||||
|
||||
AUFGABE: Extrahiere alle Vokabeleintraege in folgendem JSON-Format:
|
||||
|
||||
{
|
||||
"vocabulary": [
|
||||
{
|
||||
"english": "to improve",
|
||||
"german": "verbessern",
|
||||
"example": "I want to improve my English."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
REGELN:
|
||||
1. Erkenne das typische 3-Spalten-Layout: Englisch | Deutsch | Beispielsatz
|
||||
2. Behalte die exakte Schreibweise bei
|
||||
3. Bei fehlenden Beispielsaetzen: "example": null
|
||||
4. Ignoriere Seitenzahlen, Ueberschriften
|
||||
5. Gib NUR valides JSON zurueck
|
||||
"""
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Tests
|
||||
|
||||
### 6.1 Tests ausfuehren
|
||||
|
||||
```bash
|
||||
cd /Users/benjaminadmin/Projekte/breakpilot-pwa/klausur-service/backend
|
||||
source venv/bin/activate
|
||||
|
||||
# Alle Tests
|
||||
pytest tests/test_vocab_worksheet.py -v
|
||||
|
||||
# Mit Coverage
|
||||
pytest tests/test_vocab_worksheet.py --cov=vocab_worksheet_api --cov-report=html
|
||||
|
||||
# Einzelne Testklasse
|
||||
pytest tests/test_vocab_worksheet.py::TestSessionCRUD -v
|
||||
```
|
||||
|
||||
### 6.2 Test-Kategorien
|
||||
|
||||
| Klasse | Beschreibung |
|
||||
|--------|--------------|
|
||||
| `TestSessionCRUD` | Session erstellen, lesen, loeschen |
|
||||
| `TestVocabulary` | Vokabeln abrufen, aktualisieren |
|
||||
| `TestWorksheetGeneration` | Arbeitsblatt-Generierung |
|
||||
| `TestJSONParsing` | LLM-Response parsing |
|
||||
| `TestFileUpload` | Bild/PDF-Upload |
|
||||
| `TestSessionStatus` | Status-Workflow |
|
||||
| `TestEdgeCases` | Randfaelle |
|
||||
|
||||
---
|
||||
|
||||
## 7. Deployment
|
||||
|
||||
### 7.1 Docker Build
|
||||
|
||||
```bash
|
||||
# Klausur-Service neu bauen
|
||||
docker compose build klausur-service
|
||||
|
||||
# Studio-v2 neu bauen
|
||||
docker compose build studio-v2
|
||||
```
|
||||
|
||||
### 7.2 Sync zum Mac Mini
|
||||
|
||||
```bash
|
||||
# Source-Files synchronisieren
|
||||
rsync -avz --exclude 'node_modules' --exclude '.next' --exclude '__pycache__' \
|
||||
/Users/benjaminadmin/Projekte/breakpilot-pwa/ \
|
||||
macmini:/Users/benjaminadmin/Projekte/breakpilot-pwa/
|
||||
|
||||
# Container neu starten
|
||||
ssh macmini "cd /Users/benjaminadmin/Projekte/breakpilot-pwa && docker compose up -d"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Troubleshooting
|
||||
|
||||
### 8.1 Haeufige Probleme
|
||||
|
||||
| Problem | Loesung |
|
||||
|---------|---------|
|
||||
| Ollama nicht erreichbar | `docker exec -it ollama ollama list` pruefen |
|
||||
| PDF-Konvertierung schlaegt fehl | PyMuPDF installiert? `pip install PyMuPDF` |
|
||||
| Vision LLM Timeout | Timeout auf 300s erhoehen |
|
||||
| Leere Vokabel-Liste | Bild-Qualitaet pruefen, anderen LLM-Modus testen |
|
||||
|
||||
### 8.2 Logs pruefen
|
||||
|
||||
```bash
|
||||
# Backend-Logs
|
||||
docker logs klausur-service -f --tail 100
|
||||
|
||||
# Ollama-Logs
|
||||
docker logs ollama -f --tail 100
|
||||
```
|
||||
|
||||
### 8.3 Debug-Modus
|
||||
|
||||
```python
|
||||
# In vocab_worksheet_api.py
|
||||
import logging
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Zeigt detaillierte OCR/LLM-Ausgaben
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Erweiterung
|
||||
|
||||
### 9.1 Neue Sprache hinzufuegen
|
||||
|
||||
1. `source_language` und `target_language` in Session-Model erweitern
|
||||
2. Prompt anpassen fuer neue Sprachkombination
|
||||
3. Frontend-Dropdown erweitern
|
||||
|
||||
### 9.2 Neuer Arbeitsblatt-Typ
|
||||
|
||||
1. `WorksheetType` Enum erweitern:
|
||||
```python
|
||||
class WorksheetType(str, Enum):
|
||||
# ...
|
||||
CROSSWORD = "crossword" # Neu
|
||||
```
|
||||
|
||||
2. `generate_worksheet_html()` erweitern
|
||||
|
||||
3. Frontend-Checkbox hinzufuegen
|
||||
|
||||
### 9.3 Datenbank-Persistenz
|
||||
|
||||
Aktuell: In-Memory (`_sessions` Dict)
|
||||
|
||||
Fuer Produktion PostgreSQL hinzufuegen:
|
||||
|
||||
```python
|
||||
# models.py
|
||||
class VocabSession(Base):
|
||||
__tablename__ = "vocab_sessions"
|
||||
id = Column(UUID, primary_key=True)
|
||||
name = Column(String)
|
||||
status = Column(String)
|
||||
vocabulary = Column(JSON)
|
||||
# ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. API-Referenz
|
||||
|
||||
Vollstaendige OpenAPI-Dokumentation verfuegbar unter:
|
||||
|
||||
- **Swagger UI:** http://macmini:8086/docs
|
||||
- **ReDoc:** http://macmini:8086/redoc
|
||||
|
||||
Filter nach Tag `Vocabulary Worksheets` fuer alle Vocab-Endpoints.
|
||||
410
klausur-service/docs/Worksheet-Editor-Architecture.md
Normal file
410
klausur-service/docs/Worksheet-Editor-Architecture.md
Normal file
@@ -0,0 +1,410 @@
|
||||
# Visual Worksheet Editor - Architecture Documentation
|
||||
|
||||
**Version:** 1.0
|
||||
**Datum:** 2026-01-23
|
||||
**Status:** Implementiert
|
||||
|
||||
## 1. Übersicht
|
||||
|
||||
Der Visual Worksheet Editor ist ein Canvas-basierter Editor für die Erstellung und Bearbeitung von Arbeitsblättern. Er ermöglicht Lehrern, eingescannte Arbeitsblätter originalgetreu zu rekonstruieren oder neue Arbeitsblätter visuell zu gestalten.
|
||||
|
||||
### 1.1 Hauptfunktionen
|
||||
|
||||
- **Canvas-basiertes Editieren** mit Fabric.js
|
||||
- **Freie Positionierung** von Text, Bildern und Formen
|
||||
- **Typografie-Steuerung** (Schriftarten, Größen, Stile)
|
||||
- **Bilder & Grafiken** hochladen und einfügen
|
||||
- **KI-generierte Bilder** via Ollama/Stable Diffusion
|
||||
- **PDF/Bild-Export** für Druck und digitale Nutzung
|
||||
- **Mehrseitige Dokumente** mit Seitennavigation
|
||||
|
||||
### 1.2 Technologie-Stack
|
||||
|
||||
| Komponente | Technologie | Lizenz |
|
||||
|------------|-------------|--------|
|
||||
| Canvas-Bibliothek | Fabric.js 6.x | MIT |
|
||||
| PDF-Export | pdf-lib 1.17.x | MIT |
|
||||
| Frontend | Next.js / React | MIT |
|
||||
| Backend API | FastAPI | MIT |
|
||||
| KI-Bilder | Ollama + Stable Diffusion | Apache 2.0 / MIT |
|
||||
|
||||
## 2. Architektur
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────────┐
|
||||
│ Frontend (studio-v2 / Next.js) │
|
||||
│ /studio-v2/app/worksheet-editor/page.tsx │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌────────────────────────────┐ ┌────────────────┐ │
|
||||
│ │ Toolbar │ │ Fabric.js Canvas │ │ Properties │ │
|
||||
│ │ (Links) │ │ (Mitte - 60%) │ │ Panel │ │
|
||||
│ │ │ │ │ │ (Rechts) │ │
|
||||
│ │ - Select │ │ ┌──────────────────────┐ │ │ │ │
|
||||
│ │ - Text │ │ │ │ │ │ - Schriftart │ │
|
||||
│ │ - Formen │ │ │ A4 Arbeitsfläche │ │ │ - Größe │ │
|
||||
│ │ - Bilder │ │ │ mit Grid │ │ │ - Farbe │ │
|
||||
│ │ - KI-Bild │ │ │ │ │ │ - Position │ │
|
||||
│ │ - Tabelle │ │ └──────────────────────┘ │ │ - Ebene │ │
|
||||
│ └─────────────┘ └────────────────────────────┘ └────────────────┘ │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Seiten-Navigation | Zoom | Grid | Export PDF │ │
|
||||
│ └────────────────────────────────────────────────────────────────┘ │
|
||||
└──────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────────────────────┐
|
||||
│ klausur-service (FastAPI - Port 8086) │
|
||||
│ POST /api/v1/worksheet/ai-image → Bild via Ollama generieren │
|
||||
│ POST /api/v1/worksheet/save → Worksheet speichern │
|
||||
│ GET /api/v1/worksheet/{id} → Worksheet laden │
|
||||
│ POST /api/v1/worksheet/export-pdf → PDF generieren │
|
||||
└──────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────────────────────┐
|
||||
│ Ollama (Port 11434) │
|
||||
│ Model: stable-diffusion oder kompatibles Text-to-Image Modell │
|
||||
│ Text-to-Image für KI-generierte Grafiken │
|
||||
└──────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 3. Dateistruktur
|
||||
|
||||
### 3.1 Frontend (studio-v2)
|
||||
|
||||
```
|
||||
/studio-v2/
|
||||
├── app/
|
||||
│ └── worksheet-editor/
|
||||
│ ├── page.tsx # Haupt-Editor-Seite
|
||||
│ └── types.ts # TypeScript Interfaces
|
||||
│
|
||||
├── components/
|
||||
│ └── worksheet-editor/
|
||||
│ ├── index.ts # Exports
|
||||
│ ├── FabricCanvas.tsx # Fabric.js Canvas Wrapper
|
||||
│ ├── EditorToolbar.tsx # Werkzeugleiste (links)
|
||||
│ ├── PropertiesPanel.tsx # Eigenschaften-Panel (rechts)
|
||||
│ ├── AIImageGenerator.tsx # KI-Bild Generator Modal
|
||||
│ ├── CanvasControls.tsx # Zoom, Grid, Seiten
|
||||
│ ├── ExportPanel.tsx # PDF/Bild Export
|
||||
│ └── PageNavigator.tsx # Mehrseitige Dokumente
|
||||
│
|
||||
├── lib/
|
||||
│ └── worksheet-editor/
|
||||
│ ├── index.ts # Exports
|
||||
│ └── WorksheetContext.tsx # State Management
|
||||
```
|
||||
|
||||
### 3.2 Backend (klausur-service)
|
||||
|
||||
```
|
||||
/klausur-service/backend/
|
||||
├── worksheet_editor_api.py # API Endpoints
|
||||
└── main.py # Router-Registrierung
|
||||
```
|
||||
|
||||
## 4. API Endpoints
|
||||
|
||||
### 4.1 KI-Bild generieren
|
||||
|
||||
```http
|
||||
POST /api/v1/worksheet/ai-image
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"prompt": "Ein freundlicher Cartoon-Hund der ein Buch liest",
|
||||
"style": "cartoon",
|
||||
"width": 512,
|
||||
"height": 512
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"image_base64": "data:image/png;base64,...",
|
||||
"prompt_used": "...",
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
**Styles:**
|
||||
- `realistic` - Fotorealistisch
|
||||
- `cartoon` - Cartoon/Comic
|
||||
- `sketch` - Handgezeichnete Skizze
|
||||
- `clipart` - Einfache Clipart-Grafiken
|
||||
- `educational` - Bildungs-Illustrationen
|
||||
|
||||
### 4.2 Worksheet speichern
|
||||
|
||||
```http
|
||||
POST /api/v1/worksheet/save
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": "optional-existing-id",
|
||||
"title": "Englisch Vokabeln Unit 3",
|
||||
"pages": [
|
||||
{ "id": "page_1", "index": 0, "canvasJSON": "{...}" }
|
||||
],
|
||||
"pageFormat": {
|
||||
"width": 210,
|
||||
"height": 297,
|
||||
"orientation": "portrait"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 Worksheet laden
|
||||
|
||||
```http
|
||||
GET /api/v1/worksheet/{id}
|
||||
```
|
||||
|
||||
### 4.4 PDF exportieren
|
||||
|
||||
```http
|
||||
POST /api/v1/worksheet/{id}/export-pdf
|
||||
```
|
||||
|
||||
**Response:** PDF-Datei als Download
|
||||
|
||||
### 4.5 Worksheets auflisten
|
||||
|
||||
```http
|
||||
GET /api/v1/worksheet/list/all
|
||||
```
|
||||
|
||||
## 5. Komponenten
|
||||
|
||||
### 5.1 FabricCanvas
|
||||
|
||||
Die Kernkomponente für den Canvas-Bereich:
|
||||
|
||||
- **A4-Format**: 794 x 1123 Pixel (96 DPI)
|
||||
- **Grid-Overlay**: Optionales Raster mit Snap-Funktion
|
||||
- **Zoom/Pan**: Mausrad und Controls
|
||||
- **Selection**: Einzel- und Mehrfachauswahl
|
||||
- **Keyboard Shortcuts**: Del, Ctrl+C/V/Z/D
|
||||
|
||||
### 5.2 EditorToolbar
|
||||
|
||||
Werkzeuge für die Bearbeitung:
|
||||
|
||||
| Icon | Tool | Beschreibung |
|
||||
|------|------|--------------|
|
||||
| 🖱️ | Select | Elemente auswählen/verschieben |
|
||||
| T | Text | Text hinzufügen (IText) |
|
||||
| ▭ | Rechteck | Rechteck zeichnen |
|
||||
| ○ | Kreis | Kreis/Ellipse zeichnen |
|
||||
| ― | Linie | Linie zeichnen |
|
||||
| → | Pfeil | Pfeil zeichnen |
|
||||
| 🖼️ | Bild | Bild hochladen |
|
||||
| ✨ | KI-Bild | Bild mit KI generieren |
|
||||
| ⊞ | Tabelle | Tabelle einfügen |
|
||||
|
||||
### 5.3 PropertiesPanel
|
||||
|
||||
Eigenschaften-Editor für ausgewählte Objekte:
|
||||
|
||||
**Text-Eigenschaften:**
|
||||
- Schriftart (Arial, Times, Georgia, OpenDyslexic, Schulschrift)
|
||||
- Schriftgröße (8-120pt)
|
||||
- Schriftstil (Normal, Fett, Kursiv)
|
||||
- Zeilenhöhe, Zeichenabstand
|
||||
- Textausrichtung
|
||||
- Textfarbe
|
||||
|
||||
**Form-Eigenschaften:**
|
||||
- Füllfarbe
|
||||
- Rahmenfarbe und -stärke
|
||||
- Eckenradius
|
||||
|
||||
**Allgemein:**
|
||||
- Deckkraft
|
||||
- Löschen-Button
|
||||
|
||||
### 5.4 WorksheetContext
|
||||
|
||||
React Context für globalen State:
|
||||
|
||||
```typescript
|
||||
interface WorksheetContextType {
|
||||
canvas: Canvas | null
|
||||
document: WorksheetDocument | null
|
||||
activeTool: EditorTool
|
||||
selectedObjects: FabricObject[]
|
||||
zoom: number
|
||||
showGrid: boolean
|
||||
snapToGrid: boolean
|
||||
currentPageIndex: number
|
||||
canUndo: boolean
|
||||
canRedo: boolean
|
||||
isDirty: boolean
|
||||
// ... Methoden
|
||||
}
|
||||
```
|
||||
|
||||
## 6. Datenmodelle
|
||||
|
||||
### 6.1 WorksheetDocument
|
||||
|
||||
```typescript
|
||||
interface WorksheetDocument {
|
||||
id: string
|
||||
title: string
|
||||
description?: string
|
||||
pages: WorksheetPage[]
|
||||
pageFormat: PageFormat
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 WorksheetPage
|
||||
|
||||
```typescript
|
||||
interface WorksheetPage {
|
||||
id: string
|
||||
index: number
|
||||
canvasJSON: string // Serialisierter Fabric.js Canvas
|
||||
thumbnail?: string
|
||||
}
|
||||
```
|
||||
|
||||
### 6.3 PageFormat
|
||||
|
||||
```typescript
|
||||
interface PageFormat {
|
||||
width: number // in mm (Standard: 210)
|
||||
height: number // in mm (Standard: 297)
|
||||
orientation: 'portrait' | 'landscape'
|
||||
margins: { top, right, bottom, left: number }
|
||||
}
|
||||
```
|
||||
|
||||
## 7. Features
|
||||
|
||||
### 7.1 Undo/Redo
|
||||
|
||||
- History-Stack mit max. 50 Einträgen
|
||||
- Automatische Speicherung bei jeder Änderung
|
||||
- Keyboard: Ctrl+Z (Undo), Ctrl+Y (Redo)
|
||||
|
||||
### 7.2 Grid & Snap
|
||||
|
||||
- Konfigurierbares Raster (5mm, 10mm, 15mm, 20mm)
|
||||
- Snap-to-Grid beim Verschieben
|
||||
- Ein-/Ausblendbar
|
||||
|
||||
### 7.3 Export
|
||||
|
||||
- **PDF**: Mehrseitig, A4-Format
|
||||
- **PNG**: Hochauflösend (2x Multiplier)
|
||||
- **JPG**: Mit Qualitätseinstellung
|
||||
|
||||
### 7.4 Speicherung
|
||||
|
||||
- **Backend**: REST API mit JSON-Persistierung
|
||||
- **Fallback**: localStorage bei Offline-Betrieb
|
||||
|
||||
## 8. KI-Bildgenerierung
|
||||
|
||||
### 8.1 Ollama Integration
|
||||
|
||||
Der Editor nutzt Ollama für die KI-Bildgenerierung:
|
||||
|
||||
```python
|
||||
OLLAMA_URL = "http://host.docker.internal:11434"
|
||||
```
|
||||
|
||||
### 8.2 Placeholder-System
|
||||
|
||||
Falls Ollama nicht verfügbar ist, wird ein Placeholder-Bild generiert:
|
||||
- Farbcodiert nach Stil
|
||||
- Prompt-Text als Beschreibung
|
||||
- "KI-Bild (Platzhalter)"-Badge
|
||||
|
||||
### 8.3 Stil-Prompts
|
||||
|
||||
Jeder Stil fügt automatisch Modifikatoren zum Prompt hinzu:
|
||||
|
||||
```python
|
||||
STYLE_PROMPTS = {
|
||||
"realistic": "photorealistic, high detail",
|
||||
"cartoon": "cartoon style, colorful, child-friendly",
|
||||
"sketch": "pencil sketch, hand-drawn",
|
||||
"clipart": "clipart style, flat design",
|
||||
"educational": "educational illustration, textbook style"
|
||||
}
|
||||
```
|
||||
|
||||
## 9. Glassmorphism Design
|
||||
|
||||
Der Editor folgt dem Glassmorphism-Design des Studio v2:
|
||||
|
||||
```typescript
|
||||
// Dark Theme
|
||||
'backdrop-blur-xl bg-white/10 border border-white/20'
|
||||
|
||||
// Light Theme
|
||||
'backdrop-blur-xl bg-white/70 border border-black/10 shadow-xl'
|
||||
```
|
||||
|
||||
## 10. Internationalisierung
|
||||
|
||||
Unterstützte Sprachen:
|
||||
- 🇩🇪 Deutsch
|
||||
- 🇬🇧 English
|
||||
- 🇹🇷 Türkçe
|
||||
- 🇸🇦 العربية (RTL)
|
||||
- 🇷🇺 Русский
|
||||
- 🇺🇦 Українська
|
||||
- 🇵🇱 Polski
|
||||
|
||||
Translation Key: `nav_worksheet_editor`
|
||||
|
||||
## 11. Sicherheit
|
||||
|
||||
### 11.1 Bild-Upload
|
||||
|
||||
- Nur Bildformate (image/*)
|
||||
- Client-seitige Validierung
|
||||
- Base64-Konvertierung
|
||||
|
||||
### 11.2 CORS
|
||||
|
||||
Aktiviert für lokale Entwicklung und Docker-Umgebung.
|
||||
|
||||
## 12. Deployment
|
||||
|
||||
### 12.1 Frontend
|
||||
|
||||
```bash
|
||||
cd studio-v2
|
||||
npm install
|
||||
npm run dev # Port 3001
|
||||
```
|
||||
|
||||
### 12.2 Backend
|
||||
|
||||
Der klausur-service läuft auf Port 8086:
|
||||
|
||||
```bash
|
||||
cd klausur-service/backend
|
||||
python main.py
|
||||
```
|
||||
|
||||
### 12.3 Docker
|
||||
|
||||
Der Service ist Teil des docker-compose.yml.
|
||||
|
||||
## 13. Zukünftige Erweiterungen
|
||||
|
||||
- [ ] Tabellen-Tool mit Zellbearbeitung
|
||||
- [ ] Vorlagen-Bibliothek
|
||||
- [ ] Kollaboratives Editieren
|
||||
- [ ] Drag & Drop aus Dokumentenbibliothek
|
||||
- [ ] Integration mit Vocab-Worksheet
|
||||
480
klausur-service/docs/Worksheet-Editor-Developer-Guide.md
Normal file
480
klausur-service/docs/Worksheet-Editor-Developer-Guide.md
Normal file
@@ -0,0 +1,480 @@
|
||||
# Visual Worksheet Editor - Developer Guide
|
||||
|
||||
**Version:** 1.0
|
||||
**Datum:** 2026-01-23
|
||||
|
||||
## 1. Schnellstart
|
||||
|
||||
### 1.1 Dependencies installieren
|
||||
|
||||
```bash
|
||||
cd studio-v2
|
||||
npm install fabric@^6.0.0 pdf-lib@^1.17.1
|
||||
```
|
||||
|
||||
### 1.2 Entwicklungsserver starten
|
||||
|
||||
```bash
|
||||
# Frontend (Port 3001)
|
||||
cd studio-v2
|
||||
npm run dev
|
||||
|
||||
# Backend (Port 8086)
|
||||
cd klausur-service/backend
|
||||
source venv/bin/activate
|
||||
python main.py
|
||||
```
|
||||
|
||||
### 1.3 Editor öffnen
|
||||
|
||||
```
|
||||
http://localhost:3001/worksheet-editor
|
||||
```
|
||||
|
||||
## 2. Komponenten-Entwicklung
|
||||
|
||||
### 2.1 Neues Werkzeug hinzufügen
|
||||
|
||||
1. **Tool-Typ definieren** in `types.ts`:
|
||||
|
||||
```typescript
|
||||
export type EditorTool =
|
||||
| 'select'
|
||||
| 'text'
|
||||
// ... existierende Tools
|
||||
| 'neues-tool' // NEU
|
||||
```
|
||||
|
||||
2. **Button hinzufügen** in `EditorToolbar.tsx`:
|
||||
|
||||
```tsx
|
||||
<ToolButton
|
||||
tool="neues-tool"
|
||||
isActive={activeTool === 'neues-tool'}
|
||||
onClick={() => handleToolClick('neues-tool')}
|
||||
isDark={isDark}
|
||||
label="Neues Tool"
|
||||
icon={<svg>...</svg>}
|
||||
/>
|
||||
```
|
||||
|
||||
3. **Handler implementieren** in `FabricCanvas.tsx`:
|
||||
|
||||
```typescript
|
||||
case 'neues-tool': {
|
||||
// Canvas-Objekt erstellen
|
||||
const obj = new fabric.CustomObject({...})
|
||||
fabricCanvas.add(obj)
|
||||
fabricCanvas.setActiveObject(obj)
|
||||
setActiveTool('select')
|
||||
break
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 Eigenschaften-Panel erweitern
|
||||
|
||||
In `PropertiesPanel.tsx` neue Eigenschaften für einen Objekttyp hinzufügen:
|
||||
|
||||
```tsx
|
||||
{isMyType && (
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className={`block text-sm font-medium mb-2 ${labelStyle}`}>
|
||||
Neue Eigenschaft
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={myProperty}
|
||||
onChange={(e) => {
|
||||
setMyProperty(e.target.value)
|
||||
updateProperty('myProperty', e.target.value)
|
||||
}}
|
||||
className={`w-full px-3 py-2 rounded-xl border text-sm ${inputStyle}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
```
|
||||
|
||||
## 3. Context API
|
||||
|
||||
### 3.1 State abrufen
|
||||
|
||||
```tsx
|
||||
import { useWorksheet } from '@/lib/worksheet-editor/WorksheetContext'
|
||||
|
||||
function MyComponent() {
|
||||
const {
|
||||
canvas,
|
||||
activeTool,
|
||||
setActiveTool,
|
||||
selectedObjects,
|
||||
zoom,
|
||||
setZoom
|
||||
} = useWorksheet()
|
||||
|
||||
// Verwenden...
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 Canvas-Operationen
|
||||
|
||||
```typescript
|
||||
// Objekt hinzufügen
|
||||
canvas.add(newObject)
|
||||
canvas.setActiveObject(newObject)
|
||||
canvas.renderAll()
|
||||
|
||||
// Objekt entfernen
|
||||
canvas.remove(selectedObject)
|
||||
|
||||
// Alle Objekte abrufen (ohne Grid)
|
||||
const objects = canvas.getObjects().filter(obj => !obj.isGrid)
|
||||
|
||||
// Canvas exportieren
|
||||
const json = canvas.toJSON()
|
||||
const dataUrl = canvas.toDataURL({ format: 'png', multiplier: 2 })
|
||||
|
||||
// Canvas laden
|
||||
canvas.loadFromJSON(jsonData, () => {
|
||||
canvas.renderAll()
|
||||
})
|
||||
```
|
||||
|
||||
## 4. API-Integration
|
||||
|
||||
### 4.1 Worksheet speichern
|
||||
|
||||
```typescript
|
||||
const saveWorksheet = async () => {
|
||||
const host = window.location.hostname
|
||||
const apiBase = `http://${host}:8086`
|
||||
|
||||
const response = await fetch(`${apiBase}/api/v1/worksheet/save`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
id: worksheetId,
|
||||
title: 'Mein Arbeitsblatt',
|
||||
pages: [{
|
||||
id: 'page_1',
|
||||
index: 0,
|
||||
canvasJSON: JSON.stringify(canvas.toJSON())
|
||||
}]
|
||||
})
|
||||
})
|
||||
|
||||
const result = await response.json()
|
||||
console.log('Gespeichert:', result.id)
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 KI-Bild generieren
|
||||
|
||||
```typescript
|
||||
const generateAIImage = async (prompt: string) => {
|
||||
const host = window.location.hostname
|
||||
const apiBase = `http://${host}:8086`
|
||||
|
||||
const response = await fetch(`${apiBase}/api/v1/worksheet/ai-image`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
prompt,
|
||||
style: 'educational',
|
||||
width: 512,
|
||||
height: 512
|
||||
})
|
||||
})
|
||||
|
||||
const { image_base64, error } = await response.json()
|
||||
|
||||
if (image_base64) {
|
||||
// Bild zum Canvas hinzufügen
|
||||
fabric.Image.fromURL(image_base64, (img) => {
|
||||
canvas.add(img)
|
||||
canvas.setActiveObject(img)
|
||||
canvas.renderAll()
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 5. Fabric.js Patterns
|
||||
|
||||
### 5.1 Text-Objekt erstellen
|
||||
|
||||
```typescript
|
||||
const text = new fabric.IText('Text eingeben', {
|
||||
left: 100,
|
||||
top: 100,
|
||||
fontFamily: 'Arial',
|
||||
fontSize: 16,
|
||||
fill: '#000000',
|
||||
})
|
||||
canvas.add(text)
|
||||
text.enterEditing() // Bearbeitungsmodus
|
||||
```
|
||||
|
||||
### 5.2 Form erstellen
|
||||
|
||||
```typescript
|
||||
// Rechteck
|
||||
const rect = new fabric.Rect({
|
||||
left: 100,
|
||||
top: 100,
|
||||
width: 200,
|
||||
height: 100,
|
||||
fill: 'transparent',
|
||||
stroke: '#000000',
|
||||
strokeWidth: 2,
|
||||
rx: 5, // Eckenradius
|
||||
ry: 5,
|
||||
})
|
||||
|
||||
// Kreis
|
||||
const circle = new fabric.Circle({
|
||||
left: 100,
|
||||
top: 100,
|
||||
radius: 50,
|
||||
fill: '#ff6b6b',
|
||||
stroke: '#000000',
|
||||
strokeWidth: 2,
|
||||
})
|
||||
|
||||
// Linie
|
||||
const line = new fabric.Line([50, 50, 200, 50], {
|
||||
stroke: '#000000',
|
||||
strokeWidth: 2,
|
||||
})
|
||||
```
|
||||
|
||||
### 5.3 Bild laden
|
||||
|
||||
```typescript
|
||||
fabric.Image.fromURL(imageUrl, (img) => {
|
||||
// Skalierung auf max. Größe
|
||||
const maxWidth = 400
|
||||
const maxHeight = 300
|
||||
const scale = Math.min(maxWidth / img.width, maxHeight / img.height, 1)
|
||||
|
||||
img.set({
|
||||
left: 100,
|
||||
top: 100,
|
||||
scaleX: scale,
|
||||
scaleY: scale,
|
||||
})
|
||||
|
||||
canvas.add(img)
|
||||
}, { crossOrigin: 'anonymous' })
|
||||
```
|
||||
|
||||
### 5.4 Events
|
||||
|
||||
```typescript
|
||||
// Selection Events
|
||||
canvas.on('selection:created', (e) => {
|
||||
const selected = canvas.getActiveObjects()
|
||||
console.log('Ausgewählt:', selected.length)
|
||||
})
|
||||
|
||||
canvas.on('selection:cleared', () => {
|
||||
console.log('Auswahl aufgehoben')
|
||||
})
|
||||
|
||||
// Object Events
|
||||
canvas.on('object:modified', (e) => {
|
||||
console.log('Objekt geändert:', e.target)
|
||||
saveToHistory('modified')
|
||||
})
|
||||
|
||||
canvas.on('object:added', (e) => {
|
||||
console.log('Objekt hinzugefügt:', e.target)
|
||||
})
|
||||
|
||||
// Mouse Events
|
||||
canvas.on('mouse:down', (e) => {
|
||||
const pointer = canvas.getPointer(e.e)
|
||||
console.log('Klick bei:', pointer.x, pointer.y)
|
||||
})
|
||||
```
|
||||
|
||||
## 6. Testing
|
||||
|
||||
### 6.1 Unit Tests für Context
|
||||
|
||||
```typescript
|
||||
// __tests__/worksheet-context.test.tsx
|
||||
import { renderHook, act } from '@testing-library/react'
|
||||
import { WorksheetProvider, useWorksheet } from '../WorksheetContext'
|
||||
|
||||
describe('useWorksheet', () => {
|
||||
it('should initialize with default values', () => {
|
||||
const { result } = renderHook(() => useWorksheet(), {
|
||||
wrapper: WorksheetProvider,
|
||||
})
|
||||
|
||||
expect(result.current.activeTool).toBe('select')
|
||||
expect(result.current.zoom).toBe(1)
|
||||
expect(result.current.showGrid).toBe(true)
|
||||
})
|
||||
|
||||
it('should change tool', () => {
|
||||
const { result } = renderHook(() => useWorksheet(), {
|
||||
wrapper: WorksheetProvider,
|
||||
})
|
||||
|
||||
act(() => {
|
||||
result.current.setActiveTool('text')
|
||||
})
|
||||
|
||||
expect(result.current.activeTool).toBe('text')
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### 6.2 API Tests
|
||||
|
||||
```python
|
||||
# tests/test_worksheet_editor_api.py
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from main import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
def test_save_worksheet():
|
||||
response = client.post("/api/v1/worksheet/save", json={
|
||||
"title": "Test Worksheet",
|
||||
"pages": [{
|
||||
"id": "page_1",
|
||||
"index": 0,
|
||||
"canvasJSON": "{}"
|
||||
}]
|
||||
})
|
||||
assert response.status_code == 200
|
||||
assert "id" in response.json()
|
||||
|
||||
def test_get_worksheet():
|
||||
# Erst erstellen
|
||||
create_response = client.post("/api/v1/worksheet/save", json={
|
||||
"title": "Test",
|
||||
"pages": [{"id": "p1", "index": 0, "canvasJSON": "{}"}]
|
||||
})
|
||||
worksheet_id = create_response.json()["id"]
|
||||
|
||||
# Dann laden
|
||||
response = client.get(f"/api/v1/worksheet/{worksheet_id}")
|
||||
assert response.status_code == 200
|
||||
assert response.json()["title"] == "Test"
|
||||
|
||||
def test_ai_image_generation():
|
||||
response = client.post("/api/v1/worksheet/ai-image", json={
|
||||
"prompt": "A friendly dog",
|
||||
"style": "cartoon",
|
||||
"width": 256,
|
||||
"height": 256
|
||||
})
|
||||
# Kann 200 (Bild) oder 503 (Ollama nicht verfügbar) sein
|
||||
assert response.status_code in [200, 503]
|
||||
```
|
||||
|
||||
## 7. Styling
|
||||
|
||||
### 7.1 Glassmorphism Utilities
|
||||
|
||||
```typescript
|
||||
// Für Theme-aware Styling
|
||||
const glassCard = isDark
|
||||
? 'backdrop-blur-xl bg-white/10 border border-white/20'
|
||||
: 'backdrop-blur-xl bg-white/70 border border-black/10 shadow-xl'
|
||||
|
||||
const glassInput = isDark
|
||||
? 'bg-white/10 border-white/20 text-white placeholder-white/40'
|
||||
: 'bg-white/50 border-black/10 text-slate-900 placeholder-slate-400'
|
||||
|
||||
const labelStyle = isDark ? 'text-white/70' : 'text-slate-600'
|
||||
```
|
||||
|
||||
### 7.2 Button States
|
||||
|
||||
```typescript
|
||||
const buttonStyle = (active: boolean) => isDark
|
||||
? active
|
||||
? 'bg-purple-500/30 text-purple-300'
|
||||
: 'text-white/70 hover:bg-white/10 hover:text-white'
|
||||
: active
|
||||
? 'bg-purple-100 text-purple-700'
|
||||
: 'text-slate-600 hover:bg-slate-100 hover:text-slate-900'
|
||||
```
|
||||
|
||||
## 8. Best Practices
|
||||
|
||||
### 8.1 Performance
|
||||
|
||||
- Grid-Objekte mit `isGrid: true` markieren und vom Export ausschließen
|
||||
- Canvas-JSON nur bei tatsächlichen Änderungen speichern
|
||||
- History auf 50 Einträge limitieren
|
||||
- Bilder mit `multiplier: 2` für Retina-Export
|
||||
|
||||
### 8.2 Fehlerbehandlung
|
||||
|
||||
```typescript
|
||||
try {
|
||||
const response = await fetch(apiUrl)
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}`)
|
||||
}
|
||||
const data = await response.json()
|
||||
return data
|
||||
} catch (error) {
|
||||
console.error('API Error:', error)
|
||||
// Fallback auf localStorage
|
||||
return JSON.parse(localStorage.getItem(key) || '{}')
|
||||
}
|
||||
```
|
||||
|
||||
### 8.3 Hydration Safety
|
||||
|
||||
```typescript
|
||||
const [mounted, setMounted] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true)
|
||||
}, [])
|
||||
|
||||
if (!mounted) {
|
||||
return <LoadingSpinner />
|
||||
}
|
||||
```
|
||||
|
||||
## 9. Debugging
|
||||
|
||||
### 9.1 Canvas-State inspizieren
|
||||
|
||||
```typescript
|
||||
// Im Browser DevTools Console
|
||||
const canvas = document.querySelector('canvas')?.__fabric
|
||||
console.log('Objects:', canvas?.getObjects())
|
||||
console.log('Active:', canvas?.getActiveObject())
|
||||
console.log('JSON:', canvas?.toJSON())
|
||||
```
|
||||
|
||||
### 9.2 API-Calls überwachen
|
||||
|
||||
```bash
|
||||
# Backend-Logs
|
||||
tail -f /var/log/klausur-service.log
|
||||
|
||||
# Oder im Terminal wo main.py läuft
|
||||
```
|
||||
|
||||
## 10. Deployment Checklist
|
||||
|
||||
- [ ] Dependencies in package.json
|
||||
- [ ] Fabric.js und pdf-lib installiert
|
||||
- [ ] Backend-Router registriert
|
||||
- [ ] i18n-Übersetzungen vorhanden
|
||||
- [ ] Sidebar-Navigation aktualisiert
|
||||
- [ ] CORS für Produktions-Domain konfiguriert
|
||||
- [ ] Ollama-URL in Umgebungsvariablen
|
||||
58
klausur-service/docs/legal_corpus/AT_ABGB_AGB.txt
Normal file
58
klausur-service/docs/legal_corpus/AT_ABGB_AGB.txt
Normal file
@@ -0,0 +1,58 @@
|
||||
Allgemeines Buergerliches Gesetzbuch (ABGB) Oesterreich — Auszuege fuer Compliance (AGB-Recht)
|
||||
Quelle: https://www.ris.bka.gv.at/ (Gesetzesnr. 10001622)
|
||||
Amtliches Werk Oesterreich — PUBLIC DOMAIN
|
||||
|
||||
=== Relevante Bestimmungen fuer AGB-Kontrolle ===
|
||||
|
||||
§ 861 Entstehung und Inhalt von Vertraegen
|
||||
|
||||
Wer sich erklaert, er wolle einem Andern ein Recht einraeumen, oder fuer ihn eine Verbindlichkeit uebernehmen, der macht ein Versprechen; nimmt der Andere das Versprechen gueltig an, so kommt durch den uebereinstimmenden Willen beider Theile ein Vertrag zu Stande. So lange nur eine Seite das Versprechen gethan, die andere es aber noch nicht angenommen hat, ist es ein blosser Antrag (Offert).
|
||||
|
||||
§ 864 Annahme des Vertragsantrags
|
||||
|
||||
(1) Die Annahme kann ausdruecklich oder stillschweigend geschehen. Wenn der Antrag ohne Bestimmung einer Annahmefrist gemacht worden ist, so kann der Antragende zuruecktreten, wenn die Annahme nicht sogleich erfolgt.
|
||||
|
||||
§ 864a Ungewoehnliche Bestimmungen in Allgemeinen Geschaeftsbedingungen (Geltungskontrolle)
|
||||
|
||||
Eine in Allgemeinen Geschaeftsbedingungen oder Vertragsformblaettern enthaltene Vertragsbestimmung, die nicht eine der beiderseitigen Hauptleistungen festlegt, ist nicht Vertragsbestandteil, wenn sie unter Beruecksichtigung aller Umstaende des Falles, insbesondere des aeusseren Erscheinungsbildes der Urkunde, fuer den anderen Teil ueberraschend ist, es sei denn, der eine Teil hat den anderen besonders darauf hingewiesen.
|
||||
|
||||
§ 879 Nichtigkeit wegen Gesetzes- oder Sittenwidrigkeit
|
||||
|
||||
(1) Ein Vertrag, der gegen ein gesetzliches Verbot oder gegen die guten Sitten verstoesst, ist nichtig.
|
||||
|
||||
(2) Insbesondere sind folgende Vertraege nichtig:
|
||||
1. wenn jemand den Leichtsinn, die Zwangslage, Verstandesschwaeche, Unerfahrenheit oder Gemuetserregung eines andern dadurch ausbeutet, dass er sich oder einem Dritten fuer eine Leistung eine Gegenleistung versprechen oder gewaehren laesst, deren Vermoeggenswert zu dem Werte der Leistung in auffallendem Missverhaltnis steht;
|
||||
|
||||
(3) Eine in Allgemeinen Geschaeftsbedingungen oder Vertragsformblaettern enthaltene Vertragsbestimmung, die nicht eine der beiderseitigen Hauptleistungen festlegt, ist jedenfalls nichtig, wenn sie unter Beruecksichtigung aller Umstaende des Falles einen Teil gröblich benachteiligt.
|
||||
|
||||
§ 871 Irrtumsanfechtung
|
||||
|
||||
(1) War ein Teil ueber den Inhalt der von ihm abgegebenen oder an ihn gelangten Erklaerung in einem Irrtum befangen, so ist er an die Erklaerung nicht gebunden:
|
||||
1. wenn der Irrtum durch den anderen veranlasst war;
|
||||
2. wenn er dem anderen aus den Umstaenden offenbar auffallen musste;
|
||||
3. wenn er noch rechtzeitig aufgeklaert wurde.
|
||||
|
||||
§ 872 Rechtsfolgen des Irrtums
|
||||
|
||||
Ist der Irrtum so beschaffen, dass der Irrende den Vertrag bei Kenntnis des wahren Sachverhalts zu anderen Bedingungen geschlossen haette, so kann er nur eine Aenderung des Vertrags nach Massgabe des wahren Willens verlangen.
|
||||
|
||||
=== AGB-Kontrollmechanismen in Oesterreich (Zusammenfassung) ===
|
||||
|
||||
Das oesterreichische Recht kennt drei Stufen der AGB-Kontrolle:
|
||||
|
||||
1. Geltungskontrolle (§ 864a ABGB):
|
||||
- Ueberraschende Klauseln werden nicht Vertragsbestandteil
|
||||
- Pruefungsmassstab: aeusseres Erscheinungsbild, Ungewoehnlichkeit
|
||||
- Verwender muss auf ungewoehnliche Klauseln hinweisen
|
||||
|
||||
2. Inhaltskontrolle (§ 879 Abs. 3 ABGB):
|
||||
- Klauseln die gröblich benachteiligen sind nichtig
|
||||
- Gilt fuer Nebenbestimmungen (nicht Hauptleistungen)
|
||||
- Richterliche Einzelfallpruefung
|
||||
|
||||
3. Transparenzkontrolle (§ 6 Abs. 3 KSchG):
|
||||
- Klauseln muessen klar und verstaendlich formuliert sein
|
||||
- Intransparente Klauseln sind unwirksam
|
||||
- Verstaerkter Schutz bei Verbrauchervertraegen
|
||||
|
||||
Zusaetzlich: KSchG-Klauselverbote (§§ 6, 9 KSchG) fuer Verbrauchervertraege — siehe AT_KSCHG.
|
||||
71
klausur-service/docs/legal_corpus/AT_UGB_RET.txt
Normal file
71
klausur-service/docs/legal_corpus/AT_UGB_RET.txt
Normal file
@@ -0,0 +1,71 @@
|
||||
Unternehmensgesetzbuch (UGB) Oesterreich — Auszuege fuer Compliance (Retention / Aufbewahrung)
|
||||
Quelle: https://www.ris.bka.gv.at/ (Gesetzesnr. 10001702)
|
||||
Amtliches Werk Oesterreich — PUBLIC DOMAIN
|
||||
|
||||
=== Drittes Buch: Rechnungslegung (§§ 189-216 UGB) ===
|
||||
|
||||
§ 189 Rechnungslegungspflicht
|
||||
|
||||
(1) Die Rechnungslegungspflicht besteht fuer:
|
||||
1. Kapitalgesellschaften (AG, GmbH, SE);
|
||||
2. unternehmerisch taetige Personengesellschaften, bei denen kein unbeschraenkt haftender Gesellschafter eine natuerliche Person ist;
|
||||
3. alle anderen Unternehmer, die hinsichtlich der einzelnen einheitlichen Betriebe die Umsatzerloesschwelle des Abs. 2 ueberschreiten.
|
||||
|
||||
(2) Die Rechnungslegungspflicht besteht, wenn die Umsatzerloese in zwei aufeinander folgenden Geschaeftsjahren jeweils 700.000 Euro ueberschritten haben.
|
||||
|
||||
§ 190 Buchfuehrungspflicht
|
||||
|
||||
(1) Jeder rechnungslegungspflichtige Unternehmer hat Buecher zu fuehren und in diesen seine unternehmensbezogenen Geschaeftsfaelle und die Lage seines Vermoegens nach den Grundsaetzen ordnungsmaessiger Buchfuehrung ersichtlich zu machen.
|
||||
|
||||
(2) Die Buchfuehrung muss so beschaffen sein, dass sie einem sachverstaendigen Dritten innerhalb angemessener Zeit einen Ueberblick ueber die Geschaeftsfaelle und ueber die Lage des Unternehmens vermitteln kann.
|
||||
|
||||
§ 190a Fuehrung der Buecher
|
||||
|
||||
(1) Bei der Fuehrung der Buecher und bei den sonst erforderlichen Aufzeichnungen hat sich der Unternehmer einer lebenden Sprache zu bedienen.
|
||||
|
||||
(2) Die Eintragungen in Buechern und die sonst erforderlichen Aufzeichnungen muessen vollstaendig, richtig, zeitgerecht und geordnet vorgenommen werden.
|
||||
|
||||
(3) Eine Eintragung oder eine Aufzeichnung darf nicht in einer Weise veraendert werden, dass der urspruengliche Inhalt nicht mehr feststellbar ist.
|
||||
|
||||
(4) Die Buecher und die sonst erforderlichen Aufzeichnungen koennen auch auf Datentraegern gefuehrt werden, soweit diese Formen der Buchfuehrung einschliesslich des dabei angewandten Verfahrens den Grundsaetzen ordnungsmaessiger Buchfuehrung entsprechen.
|
||||
|
||||
§ 212 Aufbewahrung von Unterlagen
|
||||
|
||||
(1) Jeder rechnungslegungspflichtige Unternehmer ist verpflichtet, die folgenden Unterlagen geordnet aufzubewahren:
|
||||
1. Buecher (einschliesslich Journal- und Kontendaten), Inventare, Eroeffnungsbilanzen, Jahresabschluesse und Lageberichte, Konzernabschluesse und Konzernlageberichte, Nichtfinanzielle Berichte sowie die zu ihrem Verstaendnis erforderlichen Arbeitsanweisungen und sonstigen Organisationsunterlagen,
|
||||
2. die empfangenen und Wiedergaben der abgesandten Geschaeftsbriefe,
|
||||
3. Buchungsbelege.
|
||||
|
||||
(2) Die in Absatz 1 Nr. 1 und 3 aufgefuehrten Unterlagen sind sieben Jahre, die sonstigen in Absatz 1 aufgefuehrten Unterlagen sieben Jahre aufzubewahren.
|
||||
|
||||
(3) Die Aufbewahrungsfrist laeuft fuer Buecher und Aufzeichnungen vom Schluss des Kalenderjahres an, fuer das die letzte Eintragung vorgenommen worden ist; fuer alle anderen Unterlagen vom Schluss des Kalenderjahres an, in dem sie empfangen oder erstellt worden sind.
|
||||
|
||||
(4) Laengere Aufbewahrungsfristen aufgrund anderer Rechtsvorschriften bleiben unberuehrt.
|
||||
|
||||
(5) Bei Unterlagen, die fuer die Abgabenerhebung von Bedeutung sind, verlangert sich die Aufbewahrungsfrist auf die Dauer der Verjaehrung der Abgabenschuld. Bei Grundstuecken, die der Umsatzsteuer unterliegen, verlangert sich die Aufbewahrungsfrist um weitere 15 Jahre ab Beginn der Aufbewahrungsfrist gemaess Abs. 3.
|
||||
|
||||
=== AT BAO § 132 (Bundesabgabenordnung — Aufbewahrung) ===
|
||||
|
||||
§ 132 Aufbewahrung von Buechern und Aufzeichnungen
|
||||
|
||||
(1) Buecher und Aufzeichnungen sowie die zu den Buechern und Aufzeichnungen gehoerigen Belege sind sieben Jahre aufzubewahren; darueberhinaus sind sie so lange aufzubewahren, als sie fuer die Abgabenerhebung betreffende anhangige Verfahren von Bedeutung sind, in denen diejenigen Parteistellung haben, die fuer sie Buecher und Aufzeichnungen zu fuehren haben oder fuer die Buecher und Aufzeichnungen gefuehrt werden.
|
||||
|
||||
(2) Die Aufbewahrungsfrist laeuft fuer Buecher und Aufzeichnungen vom Schluss des Kalenderjahres an, fuer das die letzte Eintragung vorgenommen worden ist, fuer Belege und sonstige Unterlagen vom Schluss des Kalenderjahres an, auf das sie sich beziehen, oder in Ermangelung eines solchen Bezuges vom Schluss des Kalenderjahres an, in dem sie entstanden sind.
|
||||
|
||||
(3) Fuer Grundstuecke, die der Umsatzsteuer unterliegen, verlangert sich die Aufbewahrungsfrist fuer Unterlagen, die Grundstuecke im Sinne des § 2 des Grunderwerbsteuergesetzes 1987 betreffen, auf insgesamt 22 Jahre.
|
||||
|
||||
=== Zusammenfassung der oesterreichischen Aufbewahrungsfristen ===
|
||||
|
||||
Grundsatz Oesterreich: 7 Jahre Aufbewahrungspflicht (UGB und BAO)
|
||||
|
||||
UGB § 212:
|
||||
- 7 Jahre: Buecher, Inventare, Jahresabschluesse, Lageberichte, Buchungsbelege, Geschaeftsbriefe
|
||||
- Verlaengerung: Bei Grundstuecken mit Umsatzsteuer +15 Jahre (= 22 Jahre)
|
||||
- Verlaengerung: Bei anhaengigen Abgabenverfahren
|
||||
|
||||
BAO § 132:
|
||||
- 7 Jahre: Buecher, Aufzeichnungen und zugehoerige Belege
|
||||
- Verlaengerung: Solange anhaengige Abgabenverfahren laufen
|
||||
- Bei Grundstuecken: 22 Jahre
|
||||
|
||||
Vergleich mit Deutschland: DE hat 6 bzw. 10 Jahre (HGB/AO), AT hat einheitlich 7 Jahre.
|
||||
92
klausur-service/docs/legal_corpus/CH_OR_AGB.txt
Normal file
92
klausur-service/docs/legal_corpus/CH_OR_AGB.txt
Normal file
@@ -0,0 +1,92 @@
|
||||
Obligationenrecht (OR) Schweiz — Auszuege fuer Compliance (AGB-Recht und Aufbewahrung)
|
||||
Quelle: https://www.fedlex.admin.ch/eli/cc/27/317_321_377 (SR 220)
|
||||
Amtliches Werk Schweiz — PUBLIC DOMAIN
|
||||
|
||||
=== Teil 1: AGB-relevante Bestimmungen ===
|
||||
|
||||
Art. 1 Abschluss des Vertrages — Uebereinstimmende Willensaeusserung
|
||||
|
||||
(1) Zum Abschlusse eines Vertrages ist die uebereinstimmende gegenseitige Willensaeusserung der Parteien erforderlich.
|
||||
|
||||
(2) Sie kann eine ausdrueckliche oder stillschweigende sein.
|
||||
|
||||
Art. 8 Allgemeine Geschaeftsbedingungen
|
||||
|
||||
(1) Bestimmungen in Allgemeinen Geschaeftsbedingungen sind unwirksam, wenn sie fuer den anderen Teil nachteilig sind und in treuwidriger Weise:
|
||||
a. in erheblicher Weise von der gesetzlichen Ordnung abweichen; oder
|
||||
b. eine dem Vertragszweck unangemessene Einschraenkung von Rechten und Pflichten vorsehen.
|
||||
|
||||
(2) Die Unwirksamkeit wird auf Klage hin oder auf Einrede hin festgestellt.
|
||||
|
||||
(3) Allgemeine Geschaeftsbedingungen duerfen nicht dadurch wirksam werden, dass der andere Teil von ihrem Inhalt Kenntnis hatte.
|
||||
|
||||
Anmerkung: Art. 8 OR wurde durch das revidierte OR (AGB-Kontrolle) eingefuehrt. Diese Bestimmung fuehrt erstmals eine gesetzliche Inhaltskontrolle von AGB in der Schweiz ein.
|
||||
|
||||
Art. 19 Inhalt des Vertrages — Inhalt und Schranken
|
||||
|
||||
(1) Der Inhalt des Vertrages kann innerhalb der Schranken des Gesetzes beliebig festgestellt werden.
|
||||
|
||||
(2) Von den gesetzlichen Vorschriften abweichende Vereinbarungen sind nur zulaessig, wo das Gesetz nicht eine unabänderliche Vorschrift aufstellt oder die Abweichung nicht einen Verstoss gegen die oeffentliche Ordnung, gegen die guten Sitten oder gegen das Recht der Persoenlichkeit in sich schliesst.
|
||||
|
||||
Art. 20 Nichtigkeit
|
||||
|
||||
(1) Ein Vertrag, der einen unmoeglichen oder widerrechtlichen Inhalt hat oder gegen die guten Sitten verstoesst, ist nichtig.
|
||||
|
||||
(2) Betrifft aber der Mangel bloss einzelne Teile des Vertrages, so sind nur diese nichtig, sofern nicht anzunehmen ist, dass er ohne den nichtigen Teil ueberhaupt nicht geschlossen worden waere.
|
||||
|
||||
Art. 21 Uebervorteileung (laesio enormis)
|
||||
|
||||
(1) Wird ein offenbares Missverhaltnis zwischen der Leistung und der Gegenleistung durch einen Vertrag begruendet, dessen Abschluss von dem einen Teil durch Ausbeutung der Notlage, der Unerfahrenheit oder des Leichtsinns des anderen herbeigefuehrt worden ist, so kann der Verletzte innerhalb eines Jahres erklaeren, dass er den Vertrag nicht halte, und das bereits Geleistete zurueckverlangen.
|
||||
|
||||
Art. 31 Irrtumsanfechtung bei AGB
|
||||
|
||||
(1) Wenn der durch Irrtum, Taeuschung oder Furcht beeinflusste Teil binnen eines Jahres weder dem anderen die Absicht, den Vertrag nicht zu halten, erklaert, noch eine schon erfolgte Leistung zurueckfordert, so gilt der Vertrag als genehmigt.
|
||||
|
||||
=== Teil 2: Aufbewahrungspflichten (Geschaeftsbuecher) ===
|
||||
|
||||
Art. 957 Pflicht zur Buchfuehrung und Rechnungslegung
|
||||
|
||||
(1) Der Pflicht zur Buchfuehrung und Rechnungslegung gemaess den nachfolgenden Bestimmungen unterliegen:
|
||||
1. Einzelunternehmen und Personengesellschaften, die einen Umsatzerloes von mindestens 500.000 Franken im letzten Geschaeftsjahr erzielt haben;
|
||||
2. juristische Personen.
|
||||
|
||||
(2) Lediglich ueber die Einnahmen und Ausgaben sowie ueber die Vermoegensverhaeltnisse muessen Buch fuehren:
|
||||
1. Einzelunternehmen und Personengesellschaften mit weniger als 500.000 Franken Umsatzerloes im letzten Geschaeftsjahr;
|
||||
2. diejenigen Vereine und Stiftungen, die nicht verpflichtet sind, sich ins Handelsregister eintragen zu lassen;
|
||||
3. Stiftungen, die nach Artikel 83b Absatz 2 ZGB von der Pflicht zur Bezeichnung einer Revisionsstelle befreit sind.
|
||||
|
||||
Art. 957a Grundsaetze ordnungsmaessiger Buchfuehrung
|
||||
|
||||
(1) Die Buchfuehrung bildet die Grundlage der Rechnungslegung. Sie erfasst diejenigen Geschaeftsvorfaelle und Sachverhalte, die fuer die Darstellung der Vermoegens-, Finanzierungs- und Ertragslage des Unternehmens (wirtschaftliche Lage) notwendig sind.
|
||||
|
||||
(2) Die Buchfuehrung folgt den Grundsaetzen ordnungsmaessiger Buchfuehrung. Namentlich sind zu beachten:
|
||||
1. die vollstaendige, wahrheitsgetreue und systematische Erfassung der Geschaeftsvorfaelle und Sachverhalte;
|
||||
2. der Belegnachweis fuer die einzelnen Buchungsvorgaenge;
|
||||
3. die Klarheit;
|
||||
4. die Zweckmaessigkeit mit Blick auf die Art und Groesse des Unternehmens;
|
||||
5. die Nachpruefbarkeit.
|
||||
|
||||
Art. 958f Aufbewahrung
|
||||
|
||||
(1) Die Geschaeftsbuecher und die Buchungsbelege sowie der Geschaeftsbericht und der Revisionsbericht sind waehrend zehn Jahren aufzubewahren. Die Aufbewahrungsfrist beginnt mit dem Ablauf des Geschaeftsjahres.
|
||||
|
||||
(2) Der Geschaeftsbericht und der Revisionsbericht sind schriftlich und unterzeichnet aufzubewahren.
|
||||
|
||||
(3) Die Geschaeftsbuecher und die Buchungsbelege koennen auf Papier, elektronisch oder in vergleichbarer Weise aufbewahrt werden, soweit dadurch die Uebereinstimmung mit den zugrunde liegenden Geschaeftsvorfaellen und Sachverhalten gewaehrleistet ist und wenn sie jederzeit wieder lesbar gemacht werden koennen.
|
||||
|
||||
(4) Die Aufbewahrung im Ausland ist zulaessig, wenn die Buchfuehrung im Inland gefuehrt wird und die in der Schweiz gesetzlich vorgesehene Dokumentation im Inland aufbewahrt wird.
|
||||
|
||||
=== Zusammenfassung ===
|
||||
|
||||
Schweizer AGB-Recht:
|
||||
- Art. 8 OR: Gesetzliche Inhaltskontrolle von AGB
|
||||
- Unwirksamkeit bei treuwidriger Benachteiligung
|
||||
- Abweichung von gesetzlicher Ordnung ODER unangemessene Einschraenkung
|
||||
- Art. 19/20 OR: Allgemeine Vertragsfreiheitsschranken
|
||||
|
||||
Schweizer Aufbewahrungsfristen:
|
||||
- 10 Jahre: Geschaeftsbuecher und Buchungsbelege (Art. 958f OR)
|
||||
- 10 Jahre: Geschaeftsbericht und Revisionsbericht
|
||||
- Fristbeginn: Ablauf des Geschaeftsjahres
|
||||
- Elektronische Aufbewahrung zulaessig
|
||||
- Aufbewahrung im Ausland unter Bedingungen moeglich
|
||||
94
klausur-service/docs/legal_corpus/DE_AO_RET.txt
Normal file
94
klausur-service/docs/legal_corpus/DE_AO_RET.txt
Normal file
@@ -0,0 +1,94 @@
|
||||
Abgabenordnung (AO) — Auszuege fuer Compliance (Retention / Aufbewahrungspflichten)
|
||||
Quelle: https://www.gesetze-im-internet.de/ao_1977/
|
||||
Amtliches Werk — PUBLIC DOMAIN (§5 UrhG)
|
||||
|
||||
=== Vierter Abschnitt: Fuehrung von Buechern und Aufzeichnungen (§§ 140-148 AO) ===
|
||||
|
||||
§ 140 Buchfuehrungs- und Aufzeichnungspflichten nach anderen Gesetzen
|
||||
|
||||
Wer nach anderen Gesetzen als den Steuergesetzen Buecher und Aufzeichnungen zu fuehren hat, die fuer die Besteuerung von Bedeutung sind, hat die Verpflichtungen, die ihm nach den anderen Gesetzen obliegen, auch fuer die Besteuerung zu erfuellen.
|
||||
|
||||
§ 141 Buchfuehrungspflicht bestimmter Steuerpflichtiger
|
||||
|
||||
(1) Gewerbliche Unternehmer sowie Land- und Forstwirte, die nach den Feststellungen der Finanzverwaltung fuer den einzelnen Betrieb
|
||||
1. einen Gesamtumsatz im Sinne des § 19 Absatz 3 Satz 1 des Umsatzsteuergesetzes von mehr als 800.000 Euro im Kalenderjahr oder
|
||||
2. (weggefallen)
|
||||
3. selbstbewirtschaftete land- und forstwirtschaftliche Flaechen mit einem Wirtschaftswert von mehr als 25.000 Euro oder
|
||||
4. einen Gewinn aus Gewerbebetrieb von mehr als 80.000 Euro im Wirtschaftsjahr oder
|
||||
5. einen Gewinn aus Land- und Forstwirtschaft von mehr als 80.000 Euro im Kalenderjahr
|
||||
gehabt haben, sind auch dann verpflichtet, fuer diesen Betrieb Buecher zu fuehren und aufgrund jaehrlicher Bestandsaufnahmen Abschluesse zu machen, wenn sich eine Buchfuehrungspflicht nicht aus § 140 ergibt.
|
||||
|
||||
(2) Die §§ 238, 240 bis 242 Absatz 1 und die §§ 243 bis 256a des Handelsgesetzbuchs gelten sinngemaess.
|
||||
|
||||
§ 143 Aufzeichnung des Wareneingangs
|
||||
|
||||
(1) Gewerbliche Unternehmer muessen den Wareneingang gesondert aufzeichnen.
|
||||
|
||||
(2) Aufzuzeichnen sind alle Waren einschliesslich der Rohstoffe, unfertigen Erzeugnisse, Hilfsstoffe und Zubehoerteile, die der Unternehmer im Rahmen seines Gewerbebetriebes zur Weiterveraeusserung oder zum Verbrauch entgeltlich oder unentgeltlich, in Ausuebeung eines Rechts zum Bezug oder auf Grund einer aehnlichen Berechtigung erwirbt.
|
||||
|
||||
(3) Die Aufzeichnungen muessen die folgenden Angaben enthalten: Tag des Wareneingangs oder Datum der Rechnung, Name oder Firma und Anschrift des Lieferers, handelsübliche Bezeichnung der Ware, Preis der Ware, Hinweis auf den Beleg.
|
||||
|
||||
§ 144 Aufzeichnung des Warenausgangs
|
||||
|
||||
(1) Gewerbliche Unternehmer, die nach der Art ihres Geschaeftsbetriebes Waren regelmaessig an andere gewerbliche Unternehmer zur Weiterveraeusserung oder zum Verbrauch als Hilfsstoffe liefern, muessen den Warenausgang gesondert aufzeichnen.
|
||||
|
||||
(2) Die Aufzeichnungen muessen die folgenden Angaben enthalten: Tag des Warenausgangs oder Datum der Rechnung, Name oder Firma und Anschrift des Abnehmers, handelsübliche Bezeichnung der Ware, Preis der Ware, Hinweis auf den Beleg.
|
||||
|
||||
§ 145 Allgemeine Anforderungen an Buchfuehrung und Aufzeichnungen
|
||||
|
||||
(1) Die Buchfuehrung muss so beschaffen sein, dass sie einem sachverstaendigen Dritten innerhalb angemessener Zeit einen Ueberblick ueber die Geschaeftsvorfaelle und ueber die Lage des Unternehmens vermitteln kann. Die Geschaeftsvorfaelle muessen sich in ihrer Entstehung und Abwicklung verfolgen lassen.
|
||||
|
||||
(2) Aufzeichnungen sind so vorzunehmen, dass der Zweck, den sie fuer die Besteuerung erfuellen sollen, erreicht wird.
|
||||
|
||||
§ 146 Ordnungsvorschriften fuer die Buchfuehrung und fuer Aufzeichnungen
|
||||
|
||||
(1) Die Buchungen und die sonst erforderlichen Aufzeichnungen sind einzeln, vollstaendig, richtig, zeitgerecht und geordnet vorzunehmen. Kasseneinnahmen und Kassenausgaben sind taeglich festzuhalten.
|
||||
|
||||
(2) Buecher und die sonst erforderlichen Aufzeichnungen sind im Geltungsbereich dieses Gesetzes zu fuehren und aufzubewahren. Dies gilt nicht, soweit fuer Betriebsstaetten ausserhalb des Geltungsbereichs dieses Gesetzes nach dortigem Recht eine Verpflichtung besteht, Buecher und Aufzeichnungen zu fuehren, und diese Verpflichtung erfuellt wird.
|
||||
|
||||
(2a) Abweichend von Absatz 2 Satz 1 kann die zustaendige Finanzbehoerde auf schriftlichen oder elektronischen Antrag des Steuerpflichtigen bewilligen, dass elektronische Buecher und sonstige erforderliche elektronische Aufzeichnungen oder Teile davon ausserhalb des Geltungsbereichs dieses Gesetzes gefuehrt und aufbewahrt werden koennen. Voraussetzung ist, dass der Steuerpflichtige der zustaendigen Finanzbehoerde den Datenzugriff nach § 147 Absatz 6 in vollem Umfang ermoeglichen kann.
|
||||
|
||||
(2b) Kommt der Steuerpflichtige der Aufforderung zur Rueckverlagerung seiner elektronischen Buchfuehrung oder seiner elektronischen Aufzeichnungen in den Geltungsbereich dieses Gesetzes nicht innerhalb einer ihm bestimmten angemessenen Frist nach, so kann ein Verzoegerungsgeld von 2.500 Euro bis 250.000 Euro festgesetzt werden.
|
||||
|
||||
(4) Eine Eintragung oder eine Aufzeichnung darf nicht in einer Weise veraendert werden, dass der urspruengliche Inhalt nicht mehr feststellbar ist.
|
||||
|
||||
(5) Die Buecher und die sonst erforderlichen Aufzeichnungen koennen auch in der geordneten Ablage von Belegen bestehen oder auf Datentraegern gefuehrt werden, soweit diese Formen der Buchfuehrung einschliesslich des dabei angewandten Verfahrens den Grundsaetzen ordnungsmaessiger Buchfuehrung entsprechen.
|
||||
|
||||
§ 147 Ordnungsvorschriften fuer die Aufbewahrung von Unterlagen
|
||||
|
||||
(1) Die folgenden Unterlagen sind geordnet aufzubewahren:
|
||||
1. Buecher und Aufzeichnungen, Inventare, Jahresabschluesse, Lageberichte, die Eroeffnungsbilanz sowie die zu ihrem Verstaendnis erforderlichen Arbeitsanweisungen und sonstigen Organisationsunterlagen,
|
||||
2. die empfangenen Handels- oder Geschaeftsbriefe,
|
||||
3. Wiedergaben der abgesandten Handels- oder Geschaeftsbriefe,
|
||||
4. Buchungsbelege,
|
||||
4a. Unterlagen nach Artikel 15 Absatz 1 und Artikel 163 des Zollkodex der Union,
|
||||
5. sonstige Unterlagen, soweit sie fuer die Besteuerung von Bedeutung sind.
|
||||
|
||||
(2) Mit Ausnahme der Jahresabschluesse, der Eroeffnungsbilanzen und der Unterlagen nach Absatz 1 Nummer 4a, sofern es sich bei letzteren um amtliche Urkunden oder amtlich beglaubigte Abschriften handelt, koennen die in Absatz 1 aufgefuehrten Unterlagen auch als Wiedergabe auf einem Bildtraeger oder auf anderen Datentraegern aufbewahrt werden.
|
||||
|
||||
(3) Die in Absatz 1 Nummer 1, 4 und 4a aufgefuehrten Unterlagen sind zehn Jahre, die sonstigen in Absatz 1 aufgefuehrten Unterlagen sechs Jahre aufzubewahren, sofern nicht in anderen Steuergesetzen kuerzere Aufbewahrungsfristen zugelassen sind.
|
||||
|
||||
(4) Die Aufbewahrungsfrist beginnt mit dem Schluss des Kalenderjahrs, in dem die letzte Eintragung in das Buch gemacht, das Inventar, die Eroeffnungsbilanz, der Jahresabschluss oder der Lagebericht aufgestellt, der Handels- oder Geschaeftsbrief empfangen oder abgesandt worden oder der Buchungsbeleg entstanden ist, ferner die Aufzeichnung vorgenommen worden ist oder die sonstigen Unterlagen entstanden sind.
|
||||
|
||||
(5) Wer aufzubewahrende Unterlagen in der Form einer Wiedergabe auf einem Bildtraeger oder auf anderen Datentraegern vorlegt, ist verpflichtet, auf seine Kosten diejenigen Hilfsmittel zur Verfuegung zu stellen, die erforderlich sind, um die Unterlagen lesbar zu machen.
|
||||
|
||||
(6) Die Finanzbehoerde kann jederzeit verlangen, dass der Steuerpflichtige ihr die gespeicherten Unterlagen auf einem maschinell verwertbaren Datentraeger zur Verfuegung stellt oder dass die gespeicherten Daten nach ihren Vorgaben maschinell ausgewertet werden (Datenzugriff).
|
||||
|
||||
§ 148 Bewilligung von Erleichterungen
|
||||
|
||||
Die Finanzbehoerden koennen fuer einzelne Faelle oder fuer bestimmte Gruppen von Faellen Erleichterungen bewilligen, wenn die Einhaltung der durch die Steuergesetze begruendeten Buchfuehrungs-, Aufzeichnungs- und Aufbewahrungspflichten Haerten mit sich bringt und die Besteuerung durch die Erleichterung nicht beeintraechtigt wird.
|
||||
|
||||
=== Zusammenfassung der steuerlichen Aufbewahrungsfristen ===
|
||||
|
||||
10 Jahre Aufbewahrungspflicht:
|
||||
- Buecher und Aufzeichnungen
|
||||
- Inventare, Jahresabschluesse, Eroeffnungsbilanzen, Lageberichte
|
||||
- Buchungsbelege
|
||||
- Organisationsunterlagen
|
||||
|
||||
6 Jahre Aufbewahrungspflicht:
|
||||
- Empfangene Handels- oder Geschaeftsbriefe
|
||||
- Kopien abgesandter Handelsbriefe
|
||||
- Sonstige steuerrelevante Unterlagen
|
||||
|
||||
Wichtig: Elektronische Aufbewahrung ist zulaessig, aber Finanzbehoerden haben Recht auf Datenzugriff (§ 147 Abs. 6).
|
||||
167
klausur-service/docs/legal_corpus/DE_BGB_AGB.txt
Normal file
167
klausur-service/docs/legal_corpus/DE_BGB_AGB.txt
Normal file
@@ -0,0 +1,167 @@
|
||||
Buergerliches Gesetzbuch (BGB) — Auszuege fuer Compliance
|
||||
Quelle: https://www.gesetze-im-internet.de/bgb/
|
||||
Amtliches Werk — PUBLIC DOMAIN (§5 UrhG)
|
||||
|
||||
=== Abschnitt 1: AGB-Recht (§§ 305-310 BGB) ===
|
||||
|
||||
§ 305 Einbeziehung Allgemeiner Geschaeftsbedingungen in den Vertrag
|
||||
|
||||
(1) Allgemeine Geschaeftsbedingungen sind alle fuer eine Vielzahl von Vertraegen vorformulierten Vertragsbedingungen, die eine Vertragspartei (Verwender) der anderen Vertragspartei bei Abschluss eines Vertrags stellt. Gleichgueltig ist, ob die Bestimmungen einen aeusserlich gesonderten Bestandteil des Vertrags bilden oder in die Vertragsurkunde selbst aufgenommen werden, welchen Umfang sie haben, in welcher Schriftart sie verfasst sind und welche Form der Vertrag hat. Allgemeine Geschaeftsbedingungen liegen nicht vor, soweit die Vertragsbedingungen zwischen den Vertragsparteien im Einzelnen ausgehandelt sind.
|
||||
|
||||
(2) Allgemeine Geschaeftsbedingungen werden nur dann Bestandteil eines Vertrags, wenn der Verwender bei Vertragsschluss
|
||||
1. die andere Vertragspartei ausdruecklich oder, wenn ein ausdruecklicher Hinweis wegen der Art des Vertragsschlusses nur unter unverhaeltnismaessigen Schwierigkeiten moeglich ist, durch deutlich sichtbaren Aushang am Ort des Vertragsschlusses auf sie hinweist und
|
||||
2. der anderen Vertragspartei die Moeglichkeit verschafft, in zumutbarer Weise, die auch eine fuer den Verwender erkennbare koerperliche Behinderung der anderen Vertragspartei angemessen beruecksichtigt, von ihrem Inhalt Kenntnis zu nehmen,
|
||||
und wenn die andere Vertragspartei mit ihrer Geltung einverstanden ist.
|
||||
|
||||
(3) Die Vertragsparteien koennen fuer eine bestimmte Art von Rechtsgeschaeften die Geltung bestimmter Allgemeiner Geschaeftsbedingungen unter Beachtung der in Absatz 2 bezeichneten Erfordernisse im Voraus vereinbaren.
|
||||
|
||||
§ 305a Einbeziehung in besonderen Faellen
|
||||
|
||||
Auch ohne die in § 305 Absatz 2 Nr. 1 und 2 bezeichneten Erfordernisse werden einbezogen, wenn die andere Vertragspartei mit ihrer Geltung einverstanden ist,
|
||||
1. die mit Genehmigung der zustaendigen Verkehrsbehoerde oder aufgrund internationaler Uebereinkommen erlassenen Tarife und Ausfuehrungsbestimmungen der Eisenbahnen und die nach Massgabe des Personenbefoerderungsgesetzes genehmigten Befoerderungsbedingungen der Strassenbahnen, Obusse und Kraftfahrzeuge im Linienverkehr in den Befoerderungsvertrag,
|
||||
2. die im Amtsblatt der Bundesnetzagentur fuer Elektrizitaet, Gas, Telekommunikation, Post und Eisenbahnen veroeffentlichten und in den Geschaeftsraeumen des Verwenders bereitgehaltenen besonderen Bedingungen fuer den Zugang zu Telekommunikationsnetzen und fuer die Inanspruchnahme von Telekommunikationsdiensten in den Vertrag ueber die Inanspruchnahme der Leistungen.
|
||||
|
||||
§ 305b Vorrang der Individualabrede
|
||||
|
||||
Individuelle Vertragsabreden haben Vorrang vor Allgemeinen Geschaeftsbedingungen.
|
||||
|
||||
§ 305c Ueberraschende und mehrdeutige Klauseln
|
||||
|
||||
(1) Bestimmungen in Allgemeinen Geschaeftsbedingungen, die nach den Umstaenden, insbesondere nach dem aeusseren Erscheinungsbild des Vertrags, so ungewoehnlich sind, dass der Vertragspartner des Verwenders mit ihnen nicht zu rechnen braucht, werden nicht Vertragsbestandteil.
|
||||
|
||||
(2) Zweifel bei der Auslegung Allgemeiner Geschaeftsbedingungen gehen zu Lasten des Verwenders.
|
||||
|
||||
§ 306 Rechtsfolgen bei Nichteinbeziehung und Unwirksamkeit
|
||||
|
||||
(1) Sind Allgemeine Geschaeftsbedingungen ganz oder teilweise nicht Vertragsbestandteil geworden oder unwirksam, so bleibt der Vertrag im Uebrigen wirksam.
|
||||
|
||||
(2) Soweit die Bestimmungen nicht Vertragsbestandteil geworden oder unwirksam sind, richtet sich der Inhalt des Vertrags nach den gesetzlichen Vorschriften.
|
||||
|
||||
(3) Der Vertrag ist unwirksam, wenn das Festhalten an ihm auch unter Beruecksichtigung der nach Absatz 2 vorgesehenen Aenderung eine unzumutbare Haerte fuer eine Vertragspartei darstellen wuerde.
|
||||
|
||||
§ 306a Umgehungsverbot
|
||||
|
||||
Die Vorschriften dieses Abschnitts finden auch Anwendung, wenn sie durch anderweitige Gestaltungen umgangen werden.
|
||||
|
||||
§ 307 Inhaltskontrolle
|
||||
|
||||
(1) Bestimmungen in Allgemeinen Geschaeftsbedingungen sind unwirksam, wenn sie den Vertragspartner des Verwenders entgegen den Geboten von Treu und Glauben unangemessen benachteiligen. Eine unangemessene Benachteiligung kann sich auch daraus ergeben, dass die Bestimmung nicht klar und verstaendlich ist.
|
||||
|
||||
(2) Eine unangemessene Benachteiligung ist im Zweifel anzunehmen, wenn eine Bestimmung
|
||||
1. mit wesentlichen Grundgedanken der gesetzlichen Regelung, von der abgewichen wird, nicht zu vereinbaren ist oder
|
||||
2. wesentliche Rechte oder Pflichten, die sich aus der Natur des Vertrags ergeben, so einschraenkt, dass die Erreichung des Vertragszwecks gefaehrdet ist.
|
||||
|
||||
(3) Die Absaetze 1 und 2 sowie die §§ 308 und 309 gelten nur fuer Bestimmungen in Allgemeinen Geschaeftsbedingungen, durch die von Rechtsvorschriften abweichende oder diese ergaenzende Regelungen vereinbart werden. Andere Bestimmungen koennen nach Absatz 1 Satz 2 in Verbindung mit Absatz 1 Satz 1 unwirksam sein.
|
||||
|
||||
§ 308 Klauselverbote mit Wertungsmoeglichkeit
|
||||
|
||||
In Allgemeinen Geschaeftsbedingungen ist insbesondere unwirksam
|
||||
1. (Annahme- und Leistungsfrist) eine Bestimmung, durch die sich der Verwender unangemessen lange oder nicht hinreichend bestimmte Fristen fuer die Annahme oder Ablehnung eines Angebots oder die Erbringung einer Leistung vorbehalt; ausgenommen hiervon ist der Vorbehalt, erst nach Ablauf einer Widerrufsfrist zu leisten;
|
||||
1a. (Zahlung ohne Gegenleistung) eine Bestimmung, durch die der Verwender die Berechtigung erhaelt, eine Gegenleistung zu verlangen, ohne dass der Vertragspartner eine entsprechende Leistung des Verwenders erhaelt oder zu erwarten hat;
|
||||
1b. (Zahlung bei Nichtinanspruchnahme) eine Bestimmung, durch die der Verwender eine Vergütung fuer Leistungen verlangt, die er im Interesse des Vertragspartners erbringt und die der Vertragspartner weder beantragt hat noch beantragt haette;
|
||||
2. (Nachfrist) eine Bestimmung, durch die sich der Verwender fuer die von ihm zu bewirkende Leistung abweichend von Rechtsvorschriften eine unangemessen lange oder nicht hinreichend bestimmte Nachfrist vorbehalt;
|
||||
3. (Ruecktrittsvorbehalt) die Vereinbarung eines Rechts des Verwenders, sich ohne sachlich gerechtfertigten und im Vertrag angegebenen Grund von seiner Leistungspflicht zu loesen;
|
||||
4. (Aenderungsvorbehalt) die Vereinbarung eines Rechts des Verwenders, die versprochene Leistung zu aendern oder von ihr abzuweichen, wenn nicht die Vereinbarung der Aenderung oder Abweichung unter Beruecksichtigung der Interessen des Verwenders fuer den anderen Vertragsteil zumutbar ist;
|
||||
5. (Fingierte Erklaerungen) eine Bestimmung, wonach eine Erklaerung des Vertragspartners des Verwenders bei Vornahme oder Unterlassung einer bestimmten Handlung als von ihm abgegeben oder nicht abgegeben gilt, es sei denn, dass dem Vertragspartner eine angemessene Frist zur Abgabe einer ausdruecklichen Erklaerung eingeraeumt ist und der Verwender sich verpflichtet, den Vertragspartner bei Beginn der Frist auf die vorgesehene Bedeutung seines Verhaltens besonders hinzuweisen;
|
||||
6. (Fiktion des Zugangs) eine Bestimmung, die vorsieht, dass eine Erklaerung des Verwenders von besonderer Bedeutung dem anderen Vertragsteil als zugegangen gilt;
|
||||
7. (Abwicklung von Vertraegen) eine Bestimmung, nach der der Verwender fuer den Fall, dass eine Vertragspartei vom Vertrag zuruecktritt oder den Vertrag kuendigt, eine unangemessen hohe Vergütung fuer die Nutzung oder den Gebrauch einer Sache oder eines Rechts oder fuer erbrachte Leistungen oder einen unangemessen hohen Ersatz von Aufwendungen verlangen kann;
|
||||
8. (Nichtverfuegbarkeit der Leistung) die nach § 308 Nummer 3 zulaessige Vereinbarung eines Vorbehalts des Verwenders, sich von der Verpflichtung zur Erfuellung des Vertrags bei Nichtverfuegbarkeit der Leistung zu loesen, wenn sich der Verwender nicht verpflichtet, den Vertragspartner unverzueglich ueber die Nichtverfuegbarkeit zu informieren und Gegenleistungen des Vertragspartners unverzueglich zu erstatten.
|
||||
|
||||
§ 309 Klauselverbote ohne Wertungsmoeglichkeit
|
||||
|
||||
Auch soweit eine Abweichung von den gesetzlichen Vorschriften zulaessig ist, ist in Allgemeinen Geschaeftsbedingungen unwirksam
|
||||
1. (Kurzfristige Preiserhoehungen) eine Bestimmung, die die Erhoehung des Entgelts fuer Waren oder Leistungen vorsieht, die innerhalb von vier Monaten nach Vertragsschluss geliefert oder erbracht werden sollen;
|
||||
2. (Leistungsverweigerungsrechte) eine Bestimmung, durch die
|
||||
a) das Leistungsverweigerungsrecht, das dem Vertragspartner des Verwenders nach § 320 zusteht, ausgeschlossen oder eingeschraenkt wird oder
|
||||
b) ein dem Vertragspartner des Verwenders zustehendes Zurueckbehaltungsrecht, soweit es auf demselben Vertragsverhaltnis beruht, ausgeschlossen oder eingeschraenkt, insbesondere von der Anerkennung von Maengeln durch den Verwender abhaengig gemacht wird;
|
||||
3. (Aufrechnungsverbot) eine Bestimmung, durch die dem Vertragspartner des Verwenders die Befugnis genommen wird, mit einer unbestrittenen oder rechtskraeftig festgestellten Forderung aufzurechnen;
|
||||
4. (Mahnung, Fristsetzung) eine Bestimmung, durch die der Verwender von der gesetzlichen Obliegenheit freigestellt wird, den anderen Vertragsteil zu mahnen oder ihm eine Frist fuer die Leistung oder Nacherfuellung zu setzen;
|
||||
5. (Pauschalierung von Schadensersatzanspruechen) die Vereinbarung eines pauschalierten Anspruchs des Verwenders auf Schadensersatz oder Ersatz einer Wertminderung, wenn die Pauschale den in den geregelten Faellen nach dem gewoehnlichen Lauf der Dinge zu erwartenden Schaden oder die gewoehnlich eintretende Wertminderung uebersteigt oder wenn dem anderen Vertragsteil nicht ausdruecklich der Nachweis gestattet wird, ein Schaden oder eine Wertminderung sei ueberhaupt nicht entstanden oder wesentlich niedriger als die Pauschale;
|
||||
6. (Vertragsstrafe) eine Bestimmung, durch die dem Verwender fuer den Fall der Nichtabnahme oder verspaeteten Abnahme der Leistung, des Zahlungsverzugs oder fuer den Fall, dass der andere Vertragsteil sich vom Vertrag loest, Zahlung einer Vertragsstrafe versprochen wird;
|
||||
7. (Haftungsausschluss bei Verletzung von Leben, Koerper, Gesundheit und bei grobem Verschulden)
|
||||
a) ein Ausschluss oder eine Begrenzung der Haftung fuer Schaeden aus der Verletzung des Lebens, des Koerpers oder der Gesundheit, die auf einer fahrlaessigen Pflichtverletzung des Verwenders oder einer vorsaetzlichen oder fahrlaessigen Pflichtverletzung eines gesetzlichen Vertreters oder Erfuellungsgehilfen des Verwenders beruhen;
|
||||
b) ein Ausschluss oder eine Begrenzung der Haftung fuer sonstige Schaeden, die auf einer grob fahrlaessigen Pflichtverletzung des Verwenders oder auf einer vorsaetzlichen oder grob fahrlaessigen Pflichtverletzung eines gesetzlichen Vertreters oder Erfuellungsgehilfen des Verwenders beruhen;
|
||||
8. Sonstige Haftungsausschluesse bei Pflichtverletzung
|
||||
a) (Haftungsausschluss bei Pflichtverletzung) eine Bestimmung, durch die bei Verletzung einer Pflicht, die keine Kardinalspflicht ist, die Haftung fuer Schaeden, die auf einer leicht fahrlaessigen Pflichtverletzung des Verwenders oder eines seiner Erfuellungsgehilfen beruhen, ausgeschlossen oder eingeschraenkt wird,
|
||||
b) (Haftungsausschluss fuer Maengel) eine Bestimmung, durch die bei Vertraegen ueber Lieferungen neu hergestellter Sachen und ueber Werkleistungen die Ansprueche gegen den Verwender wegen eines Mangels insgesamt oder bezueglich einzelner Teile ausgeschlossen, auf die Einraeumung von Anspruechen gegen Dritte beschraenkt oder von der vorherigen gerichtlichen Inanspruchnahme Dritter abhaengig gemacht werden;
|
||||
9. (Laufzeit bei Dauerschuldverhaeltnissen) bei einem Vertragsverhaltnis, das die regelmaessige Lieferung von Waren oder die regelmaessige Erbringung von Dienst- oder Werkleistungen durch den Verwender zum Gegenstand hat, eine den anderen Vertragsteil fuer mehr als zwei Jahre bindende Laufzeit des Vertrags, eine den anderen Vertragsteil bindende stillschweigende Verlaengerung des Vertragsverhaeltnisses um jeweils mehr als ein Jahr oder eine zu Lasten des anderen Vertragsteils laengere Kuendigungsfrist als drei Monate vor Ablauf der zunaechst vorgesehenen oder stillschweigend verlaengerten Vertragsdauer;
|
||||
10. (Wechsel des Vertragspartners) eine Bestimmung, wonach bei Kauf-, Darlehens-, Dienst- oder Werkvertraegen ein Dritter anstelle des Verwenders in die sich aus dem Vertrag ergebenden Rechte und Pflichten eintritt oder eintreten kann, es sei denn, in der Bestimmung wird der Dritte namentlich bezeichnet oder dem anderen Vertragsteil das Recht eingeraeumt, sich vom Vertrag zu loesen;
|
||||
11. (Haftung des Abschlussvertreters) eine Bestimmung, durch die der Verwender einem Vertreter, der den Vertrag fuer den anderen Vertragsteil abschliesst, ohne hierzu von ihm bevollmaechtigt oder ohne eine Pflicht hierzu hat, eine eigene Haftung oder Einstandspflicht auferlegt.
|
||||
|
||||
§ 310 Anwendungsbereich
|
||||
|
||||
(1) § 305 Absatz 2 und 3, § 308 Nummer 1, 2 bis 8 und § 309 finden keine Anwendung auf Allgemeine Geschaeftsbedingungen, die gegenueber einem Unternehmer, einer juristischen Person des oeffentlichen Rechts oder einem oeffentlich-rechtlichen Sondervermoegen verwendet werden.
|
||||
|
||||
(2) Die §§ 308 und 309 finden keine Anwendung auf Vertraege der Elektrizitaets-, Gas-, Fernwaerme- und Wasserversorgungsunternehmen ueber die Versorgung von Sonderabnehmern mit elektrischer Energie, Gas, Fernwaerme und Wasser aus dem Versorgungsnetz, soweit die Versorgungsbedingungen nicht zum Nachteil der Abnehmer von Verordnungen ueber Allgemeine Bedingungen fuer die Versorgung von Tarifkunden mit elektrischer Energie, Gas, Fernwaerme und Wasser abweichen. § 307 findet in den Faellen des Satzes 1 auch insoweit Anwendung, als dies zur Unwirksamkeit von in den Faellen des Satzes 1 genannten Versorgungsbedingungen fuehrt.
|
||||
|
||||
(3) Bei Vertraegen zwischen einem Unternehmer und einem Verbraucher (Verbrauchervertraege) finden die Vorschriften dieses Abschnitts mit folgenden Massgaben Anwendung:
|
||||
1. Allgemeine Geschaeftsbedingungen gelten als vom Unternehmer gestellt, es sei denn, dass sie durch den Verbraucher in den Vertrag eingefuehrt wurden;
|
||||
2. § 305c Abs. 2 und die §§ 306 und 307 bis 309 dieses Gesetzes sowie Artikel 46b des Einfuehrungsgesetzes zum Buergerlichen Gesetzbuche finden auf vorformulierte Vertragsbedingungen auch dann Anwendung, wenn diese nur zur einmaligen Verwendung bestimmt sind und soweit der Verbraucher aufgrund der Vorformulierung auf ihren Inhalt keinen Einfluss nehmen konnte;
|
||||
3. bei der Beurteilung einer unangemessenen Benachteiligung nach § 307 Abs. 1 und 2 sind auch die den Vertragsschluss begleitenden Umstaende zu beruecksichtigen.
|
||||
|
||||
(4) Dieser Abschnitt findet keine Anwendung bei Vertraegen auf dem Gebiet des Erb-, Familien- und Gesellschaftsrechts sowie auf Tarifvertraege, Betriebs- und Dienstvereinbarungen. Bei der Anwendung auf Arbeitsvertraege sind die im Arbeitsrecht geltenden Besonderheiten angemessen zu beruecksichtigen; § 305 Abs. 2 und 3 ist nicht anzuwenden. Tarifvertraege, Betriebs- und Dienstvereinbarungen stehen Rechtsvorschriften im Sinne von § 307 Abs. 3 gleich.
|
||||
|
||||
=== Abschnitt 2: Fernabsatzvertraege und Verbraucherschutz im E-Commerce (§§ 312-312k BGB) ===
|
||||
|
||||
§ 312 Anwendungsbereich
|
||||
|
||||
(1) Die Vorschriften der §§ 312a bis 312k gelten fuer Verbrauchervertraege im Sinne des § 310 Absatz 3.
|
||||
|
||||
(2) Ausserhalb von Geschaeftsraeumen geschlossene Vertraege sind Vertraege,
|
||||
1. die bei gleichzeitiger koerperlicher Anwesenheit des Verbrauchers und des Unternehmers an einem Ort geschlossen werden, der kein Geschaeftsraum des Unternehmers ist,
|
||||
2. fuer die der Verbraucher unter den in Nummer 1 genannten Umstaenden ein Angebot abgegeben hat,
|
||||
3. die in den Geschaeftsraeumen des Unternehmers oder durch Fernkommunikationsmittel geschlossen werden, bei denen der Verbraucher jedoch unmittelbar zuvor ausserhalb der Geschaeftsraeume des Unternehmers bei gleichzeitiger koerperlicher Anwesenheit des Verbrauchers und des Unternehmers persoenlich und individuell angesprochen wurde, oder
|
||||
4. die auf einem Ausflug geschlossen werden, der von dem Unternehmer oder mit seiner Hilfe organisiert wurde, um beim Verbraucher fuer den Verkauf von Waren oder die Erbringung von Dienstleistungen zu werben und mit ihm entsprechende Vertraege abzuschliessen.
|
||||
|
||||
(3) Fernabsatzvertraege sind Vertraege, bei denen der Unternehmer oder eine in seinem Namen oder Auftrag handelnde Person und der Verbraucher fuer die Vertragsverhandlungen und den Vertragsschluss ausschliesslich Fernkommunikationsmittel verwenden, es sei denn, dass der Vertragsschluss nicht im Rahmen eines fuer den Fernabsatz organisierten Vertriebs- oder Dienstleistungssystems erfolgt.
|
||||
|
||||
§ 312a Allgemeine Pflichten und Grundsaetze bei Verbrauchervertraegen
|
||||
|
||||
(1) Der Unternehmer ist verpflichtet, den Verbraucher nach Massgabe des Artikels 246 des Einfuehrungsgesetzes zum Buergerlichen Gesetzbuche zu informieren.
|
||||
|
||||
(2) Eine Vereinbarung, die den Verbraucher verpflichtet, ein Entgelt dafuer zu zahlen, dass der Unternehmer die Verpflichtungen erfuellt, die ihm aufgrund des Vertragsschlusses oder aufgrund gesetzlicher Vorschriften obliegen, ist unwirksam. Die Vereinbarung eines Entgelts fuer die Nutzung eines Zahlungsmittels, das die Kosten uebersteigt, die dem Unternehmer durch die Nutzung des Zahlungsmittels entstehen, ist unwirksam.
|
||||
|
||||
(3) Eine Vereinbarung, durch die ein Verbraucher verpflichtet wird, ein Entgelt dafuer zu zahlen, dass der Verbraucher den Unternehmer wegen Fragen oder Erklaerungen zu einem zwischen ihnen geschlossenen Vertrag ueber eine Telefonnummer anruft, die der Unternehmer fuer solche Zwecke bereithalt, ist unwirksam, wenn das vereinbarte Entgelt das Entgelt fuer die blosse Nutzung des Telekommunikationsdienstes uebersteigt.
|
||||
|
||||
§ 312d Informationspflichten
|
||||
|
||||
(1) Bei ausserhalb von Geschaeftsraeumen geschlossenen Vertraegen und bei Fernabsatzvertraegen ist der Unternehmer verpflichtet, den Verbraucher nach Massgabe des Artikels 246a des Einfuehrungsgesetzes zum Buergerlichen Gesetzbuche zu informieren.
|
||||
|
||||
(2) Der Unternehmer kann seiner Informationspflicht bei ausserhalb von Geschaeftsraeumen geschlossenen Vertraegen dadurch genuegen, dass er dem Verbraucher die Informationen entsprechend den Anforderungen des Artikels 246a § 1 Absatz 2 Satz 2 des Einfuehrungsgesetzes zum Buergerlichen Gesetzbuche zur Verfuegung stellt.
|
||||
|
||||
§ 312f Button-Loesung / Bestellbutton
|
||||
|
||||
(1) Bei einem Verbrauchervertrag im elektronischen Geschaeftsverkehr, der eine entgeltliche Leistung des Unternehmers zum Gegenstand hat, muss der Unternehmer dem Verbraucher die Informationen gemaess Artikel 246a § 1 Absatz 1 Satz 1 Nummer 1, 5, 6, 8, 14 und 15 des Einfuehrungsgesetzes zum Buergerlichen Gesetzbuche unmittelbar bevor der Verbraucher seine Bestellung abgibt, klar und verstaendlich in hervorgehobener Weise zur Verfuegung stellen.
|
||||
|
||||
(2) Der Unternehmer hat die Bestellsituation so zu gestalten, dass der Verbraucher mit seiner Bestellung ausdruecklich bestaetigt, dass er sich zu einer Zahlung verpflichtet. Erfolgt die Bestellung ueber eine Schaltflaeche, ist die Pflicht des Unternehmers nur erfuellt, wenn diese Schaltflaeche gut lesbar mit nichts anderem als den Woertern "zahlungspflichtig bestellen" oder mit einer entsprechenden eindeutigen Formulierung beschriftet ist.
|
||||
|
||||
(3) Der Vertrag kommt nur zustande, wenn der Unternehmer seine Pflicht aus Absatz 2 erfuellt.
|
||||
|
||||
§ 312g Widerrufsrecht
|
||||
|
||||
(1) Dem Verbraucher steht bei ausserhalb von Geschaeftsraeumen geschlossenen Vertraegen und bei Fernabsatzvertraegen ein Widerrufsrecht gemaess § 355 zu.
|
||||
|
||||
(2) Das Widerrufsrecht besteht, soweit die Parteien nichts anderes vereinbart haben, nicht bei folgenden Vertraegen:
|
||||
1. Vertraegen zur Lieferung von Waren, die nicht vorgefertigt sind und fuer deren Herstellung eine individuelle Auswahl oder Bestimmung durch den Verbraucher massgeblich ist oder die eindeutig auf die persoenlichen Beduerfnisse des Verbrauchers zugeschnitten sind,
|
||||
2. Vertraegen zur Lieferung von Waren, die schnell verderben koennen oder deren Verfallsdatum schnell ueberschritten wuerde,
|
||||
3. Vertraegen zur Lieferung versiegelter Waren, die aus Gruenden des Gesundheitsschutzes oder der Hygiene nicht zur Rueckgabe geeignet sind, wenn ihre Versiegelung nach der Lieferung entfernt wurde.
|
||||
|
||||
§ 312i Allgemeine Pflichten im elektronischen Geschaeftsverkehr
|
||||
|
||||
(1) Der Unternehmer hat dem Kunden bei einem Vertrag im elektronischen Geschaeftsverkehr
|
||||
1. angemessene, wirksame und zugaengliche technische Mittel zur Verfuegung zu stellen, mit deren Hilfe der Kunde Eingabefehler vor Abgabe seiner Bestellung erkennen und berichtigen kann,
|
||||
2. die in Artikel 246c des Einfuehrungsgesetzes zum Buergerlichen Gesetzbuche bestimmten Informationen rechtzeitig vor Abgabe von dessen Bestellung klar und verstaendlich mitzuteilen,
|
||||
3. den Zugang von dessen Bestellung unverzueglich auf elektronischem Wege zu bestaetigen und
|
||||
4. die Moeglichkeit zu verschaffen, die Vertragsbestimmungen einschliesslich der Allgemeinen Geschaeftsbedingungen bei Vertragsschluss abzurufen und in wiedergabefaehiger Form zu speichern.
|
||||
|
||||
§ 312j Besondere Pflichten im elektronischen Geschaeftsverkehr gegenueber Verbrauchern
|
||||
|
||||
(1) Auf Webseiten fuer den elektronischen Geschaeftsverkehr mit Verbrauchern hat der Unternehmer zusaetzlich zu den Angaben nach § 312i Absatz 1 spaetestens bei Beginn des Bestellvorgangs klar und deutlich anzugeben, ob Lieferbeschraenkungen bestehen und welche Zahlungsmittel akzeptiert werden.
|
||||
|
||||
(2) Bei einem Verbrauchervertrag im elektronischen Geschaeftsverkehr, der eine entgeltliche Leistung des Unternehmers zum Gegenstand hat, muss der Unternehmer dem Verbraucher die Informationen gemaess Artikel 246a § 1 Absatz 1 Satz 1 Nummer 1, 5, 6, 8, 14 und 15 des Einfuehrungsgesetzes zum Buergerlichen Gesetzbuche unmittelbar bevor der Verbraucher seine Bestellung abgibt, klar und verstaendlich in hervorgehobener Weise zur Verfuegung stellen.
|
||||
|
||||
(3) Der Unternehmer hat die Bestellsituation bei einem Vertrag nach Absatz 2 so zu gestalten, dass der Verbraucher mit seiner Bestellung ausdruecklich bestaetigt, dass er sich zu einer Zahlung verpflichtet.
|
||||
|
||||
§ 312k Abweichende Vereinbarungen
|
||||
|
||||
Von den Vorschriften dieses Untertitels darf nicht zum Nachteil des Verbrauchers abgewichen werden. Die Vorschriften dieses Untertitels finden, soweit nicht ein anderes bestimmt ist, auch Anwendung, wenn sie durch anderweitige Gestaltungen umgangen werden.
|
||||
74
klausur-service/docs/legal_corpus/DE_EGBGB.txt
Normal file
74
klausur-service/docs/legal_corpus/DE_EGBGB.txt
Normal file
@@ -0,0 +1,74 @@
|
||||
Einfuehrungsgesetz zum Buergerlichen Gesetzbuche (EGBGB) — Auszuege Art. 246-248 fuer Compliance
|
||||
Quelle: https://www.gesetze-im-internet.de/bgbeg/
|
||||
Amtliches Werk — PUBLIC DOMAIN (§5 UrhG)
|
||||
|
||||
=== Artikel 246 — Informationspflichten bei Verbrauchervertraegen ===
|
||||
|
||||
§ 1 Informationspflichten bei Verbrauchervertraegen
|
||||
|
||||
(1) Der Unternehmer ist, sofern sich diese Informationen nicht aus den Umstaenden ergeben, nach § 312a Absatz 1 des Buergerlichen Gesetzbuchs verpflichtet, dem Verbraucher vor Abgabe von dessen Vertragserklaerung folgende Informationen in klarer und verstaendlicher Weise zur Verfuegung zu stellen:
|
||||
1. die wesentlichen Eigenschaften der Waren oder Dienstleistungen in dem fuer das Kommunikationsmittel und fuer die Waren oder Dienstleistungen angemessenen Umfang;
|
||||
2. seine Identitaet, beispielsweise seinen Handelsnamen und die Anschrift des Ortes, an dem er niedergelassen ist, sowie seine Telefonnummer;
|
||||
3. den Gesamtpreis der Waren oder Dienstleistungen einschliesslich aller Steuern und Abgaben oder in den Faellen, in denen der Preis aufgrund der Beschaffenheit der Waren oder Dienstleistungen vernuenftigerweise nicht im Voraus berechnet werden kann, die Art der Preisberechnung;
|
||||
4. gegebenenfalls die Zahlungs-, Liefer- und Leistungsbedingungen, den Termin, bis zu dem der Unternehmer die Waren liefern oder die Dienstleistung erbringen muss, und das Verfahren des Unternehmers zum Umgang mit Beschwerden;
|
||||
5. das Bestehen eines gesetzlichen Maengelgewaehrleistungsrechts fuer die Waren;
|
||||
6. gegebenenfalls das Bestehen und die Bedingungen von Kundendienstleistungen und Garantien;
|
||||
7. gegebenenfalls die Laufzeit des Vertrags oder die Kuendigungsbedingungen bei unbefristeten Vertraegen oder sich automatisch verlaengernden Vertraegen;
|
||||
8. gegebenenfalls die Funktionsfaehigkeit digitaler Inhalte, einschliesslich anwendbarer technischer Schutzmassnahmen;
|
||||
9. gegebenenfalls, soweit wesentlich, die Interoperabilitaet digitaler Inhalte mit Hard- und Software, soweit diese dem Unternehmer bekannt ist oder vernuenftigerweise bekannt sein muss.
|
||||
|
||||
=== Artikel 246a — Informationspflichten bei Fernabsatzvertraegen und ausserhalb von Geschaeftsraeumen geschlossenen Vertraegen ===
|
||||
|
||||
§ 1 Informationspflichten
|
||||
|
||||
(1) Der Unternehmer ist nach § 312d Absatz 1 des Buergerlichen Gesetzbuchs verpflichtet, dem Verbraucher folgende Informationen zur Verfuegung zu stellen:
|
||||
1. die wesentlichen Eigenschaften der Waren oder Dienstleistungen in dem fuer das Kommunikationsmittel und fuer die Waren und Dienstleistungen angemessenen Umfang;
|
||||
2. seine Identitaet, beispielsweise seinen Handelsnamen und die Anschrift des Ortes, an dem er niedergelassen ist, seine Telefonnummer und gegebenenfalls seine Telefaxnummer und E-Mail-Adresse sowie gegebenenfalls die Anschrift und die Identitaet des Unternehmers, in dessen Auftrag er handelt;
|
||||
3. die Anschrift des Ortes, an dem der Unternehmer niedergelassen ist, und gegebenenfalls die Anschrift des Unternehmers, in dessen Auftrag er handelt, an die sich der Verbraucher mit jeder Beschwerde wenden kann, falls diese Anschrift von der Anschrift unter Nummer 2 abweicht;
|
||||
4. den Gesamtpreis der Waren oder Dienstleistungen einschliesslich aller Steuern und Abgaben;
|
||||
5. gegebenenfalls die zusaetzlich anfallenden Liefer- und Versandkosten sowie einen Hinweis auf moegliche weitere Steuern oder Kosten, die nicht ueber den Unternehmer abgefuehrt oder von ihm in Rechnung gestellt werden;
|
||||
6. bei einem unbefristeten Vertrag oder einem Abonnement-Vertrag den Gesamtpreis, der die pro Abrechnungszeitraum anfallenden Gesamtkosten umfasst;
|
||||
7. die Kosten fuer den Einsatz des fuer den Vertragsschluss genutzten Fernkommunikationsmittels, sofern dem Verbraucher Kosten berechnet werden, die ueber die Kosten fuer die blosse Nutzung des Fernkommunikationsmittels hinausgehen;
|
||||
8. die Zahlungs-, Liefer- und Leistungsbedingungen, den Termin, bis zu dem der Unternehmer die Waren liefern oder die Dienstleistung erbringen muss, und gegebenenfalls das Verfahren des Unternehmers zum Umgang mit Beschwerden;
|
||||
9. das Bestehen eines gesetzlichen Maengelgewaehrleistungsrechts fuer die Waren;
|
||||
10. gegebenenfalls das Bestehen und die Bedingungen von Kundendienstleistungen, Garantien und Kulanzregelungen;
|
||||
11. gegebenenfalls bestehende einschlaegige Verhaltenskodizes und wie Exemplare davon erhalten werden koennen;
|
||||
12. die Laufzeit des Vertrags oder die Kuendigungsbedingungen bei unbefristeten Vertraegen oder sich automatisch verlaengernden Vertraegen;
|
||||
13. gegebenenfalls die Mindestdauer der Verpflichtungen, die der Verbraucher mit dem Vertrag eingeht;
|
||||
14. gegebenenfalls die Tatsache, dass der Unternehmer vom Verbraucher die Stellung einer Kaution oder die Leistung anderer finanzieller Sicherheiten verlangen kann, sowie deren Bedingungen;
|
||||
15. gegebenenfalls die Funktionsfaehigkeit digitaler Inhalte, einschliesslich anwendbarer technischer Schutzmassnahmen;
|
||||
16. gegebenenfalls, soweit wesentlich, die Interoperabilitaet digitaler Inhalte mit Hard- und Software, soweit diese dem Unternehmer bekannt ist oder vernuenftigerweise bekannt sein muss.
|
||||
|
||||
(2) Dem Verbraucher sind folgende Informationen zur Verfuegung zu stellen:
|
||||
1. die Bedingungen, die Fristen und das Verfahren fuer die Ausuebung des Widerrufsrechts nach § 355 Absatz 1 des Buergerlichen Gesetzbuchs sowie das Muster-Widerrufsformular;
|
||||
2. gegebenenfalls die Tatsache, dass der Verbraucher im Widerrufsfall die Kosten fuer die Ruecksendung der Waren zu tragen hat;
|
||||
3. gegebenenfalls die Tatsache, dass ein Widerrufsrecht nicht besteht oder die Umstaende, unter denen der Verbraucher sein Widerrufsrecht vorzeitig verliert.
|
||||
|
||||
=== Artikel 246b — Informationspflichten bei Teilzeit-Wohnrechtevertraegen ===
|
||||
|
||||
(fuer Compliance weniger relevant, hier nicht wiedergegeben)
|
||||
|
||||
=== Artikel 246c — Informationspflichten im elektronischen Geschaeftsverkehr ===
|
||||
|
||||
Der Unternehmer hat dem Kunden rechtzeitig vor Abgabe von dessen Vertragserklarung folgende Informationen klar und verstaendlich mitzuteilen:
|
||||
1. die einzelnen technischen Schritte, die zu einem Vertragsschluss fuehren;
|
||||
2. ob der Vertragstext nach dem Vertragsschluss von dem Unternehmer gespeichert wird und ob er dem Kunden zugaenglich ist;
|
||||
3. die technischen Mittel zur Erkennung und Berichtigung von Eingabefehlern vor Abgabe der Bestellung und
|
||||
4. die fuer den Vertragsschluss zur Verfuegung stehenden Sprachen.
|
||||
|
||||
=== Zusammenfassung fuer Compliance-Module ===
|
||||
|
||||
Relevant fuer AGB-Modul:
|
||||
- Art. 246 EGBGB: Vorvertragliche Informationspflichten bei allen Verbrauchervertraegen
|
||||
- Art. 246a EGBGB: Erweiterte Pflichten bei Fernabsatz und ausserhalb von Geschaeftsraeumen
|
||||
|
||||
Relevant fuer Impressum-Modul:
|
||||
- Identitaet, Anschrift, Telefon, E-Mail des Unternehmers
|
||||
- Beschwerdeadresse
|
||||
|
||||
Relevant fuer DSI-Modul (Digitale Services Informationspflichten):
|
||||
- Gesamtpreisangabe einschliesslich Steuern
|
||||
- Zahlungs-, Liefer- und Leistungsbedingungen
|
||||
- Widerrufsbelehrung
|
||||
- Button-Loesung
|
||||
- Technische Informationspflichten (Art. 246c)
|
||||
55
klausur-service/docs/legal_corpus/DE_HGB_RET.txt
Normal file
55
klausur-service/docs/legal_corpus/DE_HGB_RET.txt
Normal file
@@ -0,0 +1,55 @@
|
||||
Handelsgesetzbuch (HGB) — Auszuege fuer Compliance (Retention / Aufbewahrungspflichten)
|
||||
Quelle: https://www.gesetze-im-internet.de/hgb/
|
||||
Amtliches Werk — PUBLIC DOMAIN (§5 UrhG)
|
||||
|
||||
=== Dritter Abschnitt: Handelsbuecher (§§ 238-263) ===
|
||||
|
||||
§ 238 Buchfuehrungspflicht
|
||||
|
||||
(1) Jeder Kaufmann ist verpflichtet, Buecher zu fuehren und in diesen seine Handelsgeschaefte und die Lage seines Vermoegens nach den Grundsaetzen ordnungsmaessiger Buchfuehrung ersichtlich zu machen. Die Buchfuehrung muss so beschaffen sein, dass sie einem sachverstaendigen Dritten innerhalb angemessener Zeit einen Ueberblick ueber die Geschaeftsvorfaelle und ueber die Lage des Unternehmens vermitteln kann. Die Geschaeftsvorfaelle muessen sich in ihrer Entstehung und Abwicklung verfolgen lassen.
|
||||
|
||||
(2) Der Kaufmann ist verpflichtet, eine mit der Urschrift uebereinstimmende Wiedergabe der abgesandten Handelsbriefe (Kopie, Abdruck, Abschrift oder sonstige Wiedergabe des Wortlauts auf einem Schrift-, Bild- oder anderen Datentraeger) zurueckzubehalten.
|
||||
|
||||
§ 239 Fuehrung der Handelsbuecher
|
||||
|
||||
(1) Bei der Fuehrung der Handelsbuecher und bei den sonst erforderlichen Aufzeichnungen hat sich der Kaufmann einer lebenden Sprache zu bedienen. Werden Abkuerzungen, Ziffern, Buchstaben oder Symbole verwendet, muss im Einzelfall deren Bedeutung eindeutig festliegen.
|
||||
|
||||
(2) Die Eintragungen in Buechern und die sonst erforderlichen Aufzeichnungen muessen vollstaendig, richtig, zeitgerecht und geordnet vorgenommen werden.
|
||||
|
||||
(3) Eine Eintragung oder eine Aufzeichnung darf nicht in einer Weise veraendert werden, dass der urspruengliche Inhalt nicht mehr feststellbar ist. Auch solche Veraenderungen duerfen nicht vorgenommen werden, deren Beschaffenheit es ungewiss laesst, ob sie urspruenglich oder erst spaeter gemacht worden sind.
|
||||
|
||||
(4) Die Handelsbuecher und die sonst erforderlichen Aufzeichnungen koennen auch in der geordneten Ablage von Belegen bestehen oder auf Datentraegern gefuehrt werden, soweit diese Formen der Buchfuehrung einschliesslich des dabei angewandten Verfahrens den Grundsaetzen ordnungsmaessiger Buchfuehrung entsprechen. Bei der Fuehrung der Handelsbuecher und der sonst erforderlichen Aufzeichnungen auf Datentraegern muss insbesondere sichergestellt sein, dass die Daten waehrend der Dauer der Aufbewahrungsfrist verfuegbar sind und jederzeit innerhalb angemessener Frist lesbar gemacht werden koennen.
|
||||
|
||||
§ 257 Aufbewahrung von Unterlagen. Aufbewahrungsfristen
|
||||
|
||||
(1) Jeder Kaufmann ist verpflichtet, die folgenden Unterlagen geordnet aufzubewahren:
|
||||
1. Handelsbuecher, Inventare, Eroeffnungsbilanzen, Jahresabschluesse, Lageberichte, Konzernabschluesse, Konzernlageberichte sowie die zu ihrem Verstaendnis erforderlichen Arbeitsanweisungen und sonstigen Organisationsunterlagen,
|
||||
2. die empfangenen Handelsbriefe,
|
||||
3. Wiedergaben der abgesandten Handelsbriefe,
|
||||
4. Buchungsbelege,
|
||||
5. Unterlagen nach Artikel 15 Absatz 1 und Artikel 163 des Zollkodex der Union.
|
||||
|
||||
(2) Handelsbriefe sind nur Schriftstuecke, die ein Handelsgeschaeft betreffen.
|
||||
|
||||
(3) Mit Ausnahme der Eroeffnungsbilanzen, Abschluesse und der Unterlagen nach Absatz 1 Nummer 5 koennen die in Absatz 1 aufgefuehrten Unterlagen auch als Wiedergabe auf einem Bildtraeger oder auf anderen Datentraegern aufbewahrt werden, wenn dies den Grundsaetzen ordnungsmaessiger Buchfuehrung entspricht und sichergestellt ist, dass die Wiedergabe oder die Daten
|
||||
1. mit den empfangenen Handelsbriefen und den Buchungsbelegen bildlich und mit den anderen Unterlagen inhaltlich uebereinstimmen, wenn sie lesbar gemacht werden,
|
||||
2. waehrend der Dauer der Aufbewahrungsfrist verfuegbar sind und jederzeit innerhalb angemessener Frist lesbar gemacht werden koennen.
|
||||
|
||||
(4) Die in Absatz 1 Nr. 1, 4 und 5 aufgefuehrten Unterlagen sind zehn Jahre, die sonstigen in Absatz 1 aufgefuehrten Unterlagen sechs Jahre aufzubewahren, sofern nicht in anderen Vorschriften laengere Aufbewahrungsfristen bestimmt sind. Die Aufbewahrungsfrist beginnt mit dem Schluss des Kalenderjahrs, in dem die letzte Eintragung in das Buch gemacht, das Inventar, die Eroeffnungsbilanz, der Jahresabschluss oder der Lagebericht aufgestellt, der Handelsbrief empfangen oder abgesandt worden oder der Buchungsbeleg entstanden ist, ferner die Aufzeichnung vorgenommen worden ist oder die sonstigen Unterlagen entstanden sind.
|
||||
|
||||
(5) Wer aufzubewahrende Unterlagen nur in der Form einer Wiedergabe auf einem Bildtraeger oder auf anderen Datentraegern besitzt, ist verpflichtet, auf seine Kosten diejenigen Hilfsmittel zur Verfuegung zu stellen, die erforderlich sind, um die Unterlagen lesbar zu machen; soweit erforderlich, hat er die Unterlagen auf seine Kosten auszudrucken oder ohne Hilfsmittel lesbare Reproduktionen beizubringen.
|
||||
|
||||
=== Zusammenfassung der Aufbewahrungsfristen ===
|
||||
|
||||
Aufbewahrungspflicht 10 Jahre:
|
||||
- Handelsbuecher, Inventare, Eroeffnungsbilanzen
|
||||
- Jahresabschluesse und Lageberichte
|
||||
- Buchungsbelege
|
||||
- Organisationsunterlagen
|
||||
|
||||
Aufbewahrungspflicht 6 Jahre:
|
||||
- Empfangene Handelsbriefe
|
||||
- Kopien der abgesandten Handelsbriefe
|
||||
- Sonstige Geschaeftsunterlagen
|
||||
|
||||
Fristbeginn: Ende des Kalenderjahrs, in dem die Unterlage erstellt/empfangen wurde.
|
||||
27
klausur-service/docs/legal_corpus/DE_USTG_RET.txt
Normal file
27
klausur-service/docs/legal_corpus/DE_USTG_RET.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
Umsatzsteuergesetz (UStG) — Auszug § 14b fuer Compliance (Retention)
|
||||
Quelle: https://www.gesetze-im-internet.de/ustg_1980/
|
||||
Amtliches Werk — PUBLIC DOMAIN (§5 UrhG)
|
||||
|
||||
=== § 14b Aufbewahrung von Rechnungen ===
|
||||
|
||||
(1) Der Unternehmer hat ein Doppel der Rechnung, die er selbst oder ein Dritter in seinem Namen und fuer seine Rechnung ausgestellt hat, sowie alle Rechnungen, die er erhalten hat, aufzubewahren. Soweit der Unternehmer die Rechnung auf elektronischem Weg uebermittelt hat, muss das Doppel ebenfalls auf elektronischem Weg aufbewahrt werden; § 14 Absatz 2 gilt entsprechend. Bei Rechnungen im Sinne des § 14 Absatz 6 Satz 2 und Absatz 7 hat der Leistungsempfaenger ein Doppel der Rechnung aufzubewahren.
|
||||
|
||||
(2) Der nicht im Inland ansaessige Unternehmer hat der zustaendigen Finanzbehoerde auf Verlangen mitzuteilen, in welchem Mitgliedstaat oder in welchem Drittlandgebiet er die Rechnungen aufbewahrt. Hat der nicht im Inland ansaessige Unternehmer seinen Sitz in einem Drittlandgebiet, mit dem keine gegenseitige Amtshilfe besteht, ist er verpflichtet, die Rechnungen im Inland aufzubewahren.
|
||||
|
||||
(3) Der Unternehmer hat die in Absatz 1 bezeichneten Rechnungen waehrend der in § 147 Absatz 3 der Abgabenordnung bezeichneten Aufbewahrungsfrist aufzubewahren.
|
||||
|
||||
(4) Die in Absatz 1 bezeichneten Rechnungen muessen waehrend der gesamten Aufbewahrungsfrist die Echtheit der Herkunft, die Unversehrtheit des Inhalts und die Lesbarkeit gewaehrleisten.
|
||||
|
||||
(5) Die Aufbewahrungsfrist fuer Rechnungen ueber die Lieferung von oder den Einzelnachweis fuer Grundstuecke im Sinne des § 15a betraegt nicht zehn, sondern zwanzig Jahre.
|
||||
|
||||
=== Zusammenfassung ===
|
||||
|
||||
Aufbewahrungsfristen fuer Rechnungen nach UStG:
|
||||
- Grundregel: 10 Jahre (wie AO § 147 Abs. 3)
|
||||
- Grundstuecke: 20 Jahre (§ 14b Abs. 5 UStG i.V.m. § 15a UStG)
|
||||
|
||||
Formale Anforderungen:
|
||||
- Echtheit der Herkunft muss gewaehrleistet sein
|
||||
- Unversehrtheit des Inhalts
|
||||
- Lesbarkeit waehrend gesamter Aufbewahrungsfrist
|
||||
- Elektronische Rechnungen: elektronische Aufbewahrung Pflicht
|
||||
604
klausur-service/docs/legal_corpus/EPRIVACY.txt
Normal file
604
klausur-service/docs/legal_corpus/EPRIVACY.txt
Normal file
@@ -0,0 +1,604 @@
|
||||
ePrivacy-Richtlinie (Richtlinie 2002/58/EG)
|
||||
Datenschutz in der elektronischen Kommunikation
|
||||
|
||||
========================================
|
||||
GRUNDLAGEN
|
||||
========================================
|
||||
|
||||
Was ist die ePrivacy-Richtlinie?
|
||||
|
||||
Die ePrivacy-Richtlinie (Richtlinie 2002/58/EG) ist eine EU-Richtlinie, die spezifische Datenschutzregeln fuer den Bereich der elektronischen Kommunikation festlegt. Sie ergaenzt die DSGVO als "lex specialis" fuer diesen Bereich.
|
||||
|
||||
Offizieller Titel: "Richtlinie 2002/58/EG des Europaeischen Parlaments und des Rates vom 12. Juli 2002 ueber die Verarbeitung personenbezogener Daten und den Schutz der Privatsphaere in der elektronischen Kommunikation"
|
||||
|
||||
Die Richtlinie wurde mehrfach geaendert:
|
||||
- 2006 durch Richtlinie 2006/24/EG (Vorratsdatenspeicherung, spaeter aufgehoben)
|
||||
- 2009 durch Richtlinie 2009/136/EG ("Cookie-Richtlinie")
|
||||
|
||||
WICHTIG: Die ePrivacy-Verordnung (ePVO) soll die Richtlinie ersetzen, ist aber Stand 2026 noch nicht in Kraft getreten.
|
||||
|
||||
Anwendungsbereich der ePrivacy-Richtlinie
|
||||
|
||||
Die ePrivacy-Richtlinie gilt fuer:
|
||||
|
||||
1. ANBIETER OEFFENTLICHER KOMMUNIKATIONSDIENSTE
|
||||
- Telekommunikationsunternehmen
|
||||
- Internet Service Provider
|
||||
- E-Mail-Dienste
|
||||
- Messenger-Dienste (umstritten)
|
||||
|
||||
2. BETREIBER VON WEBSITES UND APPS
|
||||
- Cookies und aehnliche Technologien
|
||||
- Online-Tracking
|
||||
- Direktwerbung per E-Mail
|
||||
|
||||
3. JEDE VERARBEITUNG VON
|
||||
- Verkehrsdaten
|
||||
- Standortdaten
|
||||
- Kommunikationsinhalten
|
||||
|
||||
NICHT anwendbar auf:
|
||||
- Rein unternehmensinterne Kommunikationssysteme
|
||||
- Nationale Sicherheit und Strafverfolgung (Ausnahmen)
|
||||
|
||||
Verhaeltnis zur DSGVO
|
||||
|
||||
Die ePrivacy-Richtlinie steht in einem besonderen Verhaeltnis zur DSGVO:
|
||||
|
||||
GRUNDSATZ (Art. 95 DSGVO):
|
||||
Die DSGVO erlegt Anbietern oeffentlicher Kommunikationsdienste keine zusaetzlichen Pflichten auf, soweit die ePrivacy-Richtlinie dieselbe Zielsetzung verfolgt.
|
||||
|
||||
PRAKTISCHE BEDEUTUNG:
|
||||
|
||||
1. ePrivacy als "lex specialis"
|
||||
- Fuer elektronische Kommunikation gelten primaer ePrivacy-Regeln
|
||||
- DSGVO gilt ergaenzend, wo ePrivacy keine Regelung trifft
|
||||
|
||||
2. Cookie-Consent
|
||||
- Art. 5 Abs. 3 ePrivacy regelt Cookies VORRANGIG
|
||||
- DSGVO-Einwilligung gilt ZUSAETZLICH fuer personenbezogene Daten
|
||||
|
||||
3. Sanktionen
|
||||
- DSGVO-Bussgelder (bis 20 Mio. / 4% Umsatz) gelten NICHT direkt
|
||||
- Nationale Umsetzungsgesetze haben eigene Sanktionen
|
||||
|
||||
WICHTIG: Bei Cookies ist BEIDES erforderlich:
|
||||
- ePrivacy-Einwilligung (fuer Zugriff auf Geraet)
|
||||
- DSGVO-Rechtsgrundlage (fuer Verarbeitung personenbezogener Daten)
|
||||
|
||||
========================================
|
||||
COOKIES UND TRACKING (Art. 5 Abs. 3)
|
||||
========================================
|
||||
|
||||
Cookie-Einwilligungsregel (Art. 5 Abs. 3)
|
||||
|
||||
Art. 5 Abs. 3 der ePrivacy-Richtlinie regelt den Zugriff auf Endgeraete:
|
||||
|
||||
GRUNDSATZ:
|
||||
Die Speicherung von Informationen oder der Zugriff auf bereits gespeicherte Informationen im Endgeraet eines Nutzers ist NUR zulaessig, wenn:
|
||||
|
||||
1. Der Nutzer VORHER informiert wurde (Transparenz)
|
||||
2. Der Nutzer seine EINWILLIGUNG gegeben hat (Opt-In)
|
||||
|
||||
AUSNAHMEN (KEINE Einwilligung erforderlich):
|
||||
|
||||
a) TECHNISCH NOTWENDIGE COOKIES
|
||||
- Fuer die Uebertragung einer Nachricht erforderlich
|
||||
- Beispiel: Load Balancer Cookies
|
||||
|
||||
b) UNBEDINGT ERFORDERLICHE COOKIES
|
||||
- Vom Nutzer ausdruecklich gewuenscht
|
||||
- Fuer einen Dienst, den der Nutzer ausdruecklich angefordert hat
|
||||
- Beispiele:
|
||||
* Warenkorb-Cookies
|
||||
* Login-Session-Cookies
|
||||
* Spracheinstellungen
|
||||
* Cookie-Consent-Cookie selbst
|
||||
|
||||
WICHTIG: Die Ausnahmen sind ENG auszulegen!
|
||||
- Analytics-Cookies: KEINE Ausnahme, Einwilligung erforderlich
|
||||
- Marketing-Cookies: KEINE Ausnahme, Einwilligung erforderlich
|
||||
- Social Media Plugins: KEINE Ausnahme, Einwilligung erforderlich
|
||||
|
||||
Anforderungen an Cookie-Einwilligung
|
||||
|
||||
Die Einwilligung nach Art. 5 Abs. 3 ePrivacy muss den DSGVO-Standards entsprechen (Verweis auf Definition in DSGVO):
|
||||
|
||||
ANFORDERUNGEN:
|
||||
|
||||
1. FREIWILLIG
|
||||
- Keine Nachteile bei Ablehnung
|
||||
- Kein "Cookie Wall" (umstritten, nationale Unterschiede)
|
||||
- Gleichwertige Ablehnungsoption
|
||||
|
||||
2. INFORMIERT
|
||||
- Klare Information VORHER
|
||||
- Welche Cookies, welcher Zweck
|
||||
- Wer erhaelt Zugriff (Dritte)
|
||||
- Speicherdauer
|
||||
|
||||
3. AKTIVE HANDLUNG
|
||||
- Opt-In erforderlich (EuGH Planet49)
|
||||
- Vorausgewaehlte Checkboxen sind UNGUELTIG
|
||||
- Weitersurfen ist KEINE Einwilligung
|
||||
|
||||
4. SPEZIFISCH
|
||||
- Getrennte Einwilligung pro Zweck
|
||||
- "Alle akzeptieren" muss gleichwertig zu "Alle ablehnen" sein
|
||||
|
||||
5. WIDERRUFBAR
|
||||
- Jederzeitiger Widerruf muss moeglich sein
|
||||
- So einfach wie die Erteilung
|
||||
|
||||
CONSENT MANAGEMENT PLATFORM (CMP):
|
||||
Professionelle Cookie-Banner muessen:
|
||||
- Alle Kategorien einzeln anwaehlbar machen
|
||||
- "Ablehnen" gleichwertig prominent anbieten
|
||||
- Consent dokumentieren (Nachweis)
|
||||
- Widerruf ermoeglichen
|
||||
|
||||
Cookie-Kategorien und Einwilligungspflicht
|
||||
|
||||
Uebersicht der Cookie-Kategorien und Einwilligungspflicht:
|
||||
|
||||
KATEGORIE 1: TECHNISCH NOTWENDIG (KEINE Einwilligung)
|
||||
- Session-Cookies fuer Login
|
||||
- Warenkorb-Cookies
|
||||
- Load-Balancer-Cookies
|
||||
- CSRF-Token-Cookies
|
||||
- Cookie-Consent-Cookie
|
||||
- Spracheinstellungs-Cookies
|
||||
- Barrierefreiheits-Cookies
|
||||
|
||||
KATEGORIE 2: FUNKTIONAL (Einwilligung ERFORDERLICH)
|
||||
- Praeferenz-Cookies (Design, Layout)
|
||||
- Video-Player-Einstellungen
|
||||
- Chat-Widget-Cookies
|
||||
- Formular-Autofill-Cookies
|
||||
|
||||
KATEGORIE 3: ANALYTICS (Einwilligung ERFORDERLICH)
|
||||
- Google Analytics
|
||||
- Matomo/Piwik
|
||||
- Hotjar, Crazy Egg
|
||||
- Performance-Messung
|
||||
|
||||
SONDERFALL: Analytics ohne Einwilligung (UMSTRITTEN!)
|
||||
- Matomo ohne Cookies und mit IP-Anonymisierung
|
||||
- Serverseitige Analytics
|
||||
- Aggregierte Statistiken
|
||||
- Nationale Behoerden haben unterschiedliche Meinungen!
|
||||
|
||||
KATEGORIE 4: MARKETING/WERBUNG (Einwilligung ERFORDERLICH)
|
||||
- Retargeting-Cookies
|
||||
- Google Ads/Meta Pixel
|
||||
- Affiliate-Tracking
|
||||
- Cross-Site-Tracking
|
||||
|
||||
KATEGORIE 5: SOCIAL MEDIA (Einwilligung ERFORDERLICH)
|
||||
- Facebook Like Button
|
||||
- Twitter Widgets
|
||||
- LinkedIn Plugins
|
||||
- Embedded Content von Dritten
|
||||
|
||||
Szenario: Lokale KI-Anwendung (On-Premises)
|
||||
|
||||
Bei einer lokalen KI-Anwendung wie BreakPilot (On-Premises auf Mac Studio):
|
||||
|
||||
GRUNDSAETZLICH:
|
||||
|
||||
1. KEIN externer Cookie-Zugriff
|
||||
- Alle Verarbeitung lokal auf Schulserver
|
||||
- Keine Cookies an Dritte
|
||||
- Keine Tracking-Pixel
|
||||
|
||||
2. TECHNISCH NOTWENDIGE COOKIES
|
||||
- Session-Cookies fuer Login: KEINE Einwilligung
|
||||
- CSRF-Schutz: KEINE Einwilligung
|
||||
- Benutzereinstellungen (Sprache): Grauzone, besser Einwilligung
|
||||
|
||||
3. ANALYTICS
|
||||
- Interne Nutzungsstatistiken (serverseitig): Kein ePrivacy-Problem
|
||||
- Falls Cookie-basiert: Einwilligung erforderlich
|
||||
- Empfehlung: Serverseitige Logs statt Cookies
|
||||
|
||||
EMPFEHLUNG FUER BREAKPILOT:
|
||||
- Nur Session-Cookies fuer Login verwenden
|
||||
- Keine Analytics-Cookies
|
||||
- Keine Third-Party-Einbindungen
|
||||
- Einfaches Cookie-Banner mit Hinweis auf notwendige Cookies
|
||||
- Datenschutzerklaerung mit Cookie-Informationen
|
||||
|
||||
VORTEIL:
|
||||
Durch rein lokale Verarbeitung entfallen die meisten ePrivacy-Probleme automatisch!
|
||||
|
||||
========================================
|
||||
VERKEHRSDATEN (Art. 6)
|
||||
========================================
|
||||
|
||||
Was sind Verkehrsdaten?
|
||||
|
||||
Verkehrsdaten (Art. 2 lit. b) sind Daten, die zum Zwecke der Weiterleitung einer Nachricht oder zum Zwecke der Fakturierung verarbeitet werden:
|
||||
|
||||
BEISPIELE:
|
||||
|
||||
1. Bei TELEFONIE
|
||||
- Rufnummern (Anrufer und Angerufener)
|
||||
- Datum und Uhrzeit
|
||||
- Dauer des Gespraechs
|
||||
- Art des Dienstes (Sprache, SMS)
|
||||
|
||||
2. Bei INTERNET
|
||||
- IP-Adressen (dynamisch und statisch)
|
||||
- Zeitpunkt der Verbindung
|
||||
- Datenvolumen
|
||||
- Geraetekennungen (MAC-Adresse, IMEI)
|
||||
|
||||
3. Bei E-MAIL
|
||||
- E-Mail-Adressen (Sender, Empfaenger)
|
||||
- Zeitstempel
|
||||
- Betreffzeile (umstritten - eher Inhaltsdaten)
|
||||
|
||||
ABGRENZUNG:
|
||||
- INHALTSDATEN: Der eigentliche Inhalt der Kommunikation (strenger Schutz)
|
||||
- VERKEHRSDATEN: Metadaten der Kommunikation (weniger streng)
|
||||
- STANDORTDATEN: Geografische Position (gesondert geregelt)
|
||||
|
||||
Verarbeitung von Verkehrsdaten (Art. 6)
|
||||
|
||||
Die Verarbeitung von Verkehrsdaten ist streng geregelt:
|
||||
|
||||
GRUNDSATZ (Art. 6 Abs. 1):
|
||||
Verkehrsdaten muessen GELOESCHT oder ANONYMISIERT werden, sobald sie fuer die Uebertragung nicht mehr benoetigt werden.
|
||||
|
||||
AUSNAHMEN:
|
||||
|
||||
1. ABRECHNUNG (Art. 6 Abs. 2)
|
||||
- Verarbeitung fuer Rechnungsstellung zulaessig
|
||||
- Nur bis Ende der Frist fuer Rechnungsanfechtung
|
||||
- In Deutschland: 6 Monate
|
||||
|
||||
2. VERMARKTUNG VON DIENSTEN (Art. 6 Abs. 3)
|
||||
- Nur mit EINWILLIGUNG des Teilnehmers
|
||||
- Nur fuer Vermarktung von Telekommunikationsdiensten
|
||||
- Jederzeit widerrufbar
|
||||
|
||||
3. MEHRWERTDIENSTE (Art. 6 Abs. 4)
|
||||
- Mit Einwilligung fuer elektronische Mehrwertdienste
|
||||
- Nutzer muss informiert werden
|
||||
- Zeitlicher Rahmen definiert
|
||||
|
||||
WICHTIG FUER ANBIETER:
|
||||
- Technische Vorkehrungen zur automatischen Loeschung
|
||||
- Dokumentation der Loeschfristen
|
||||
- Keine Speicherung "auf Vorrat" ohne Rechtsgrundlage
|
||||
|
||||
========================================
|
||||
STANDORTDATEN (Art. 9)
|
||||
========================================
|
||||
|
||||
Verarbeitung von Standortdaten (Art. 9)
|
||||
|
||||
Standortdaten, die ueber Verkehrsdaten hinausgehen, unterliegen besonderen Regeln nach Art. 9:
|
||||
|
||||
DEFINITION (Art. 2 lit. c):
|
||||
Daten, die den geografischen Standort des Endgeraets eines Nutzers angeben.
|
||||
|
||||
GRUNDSATZ:
|
||||
Verarbeitung von Standortdaten NUR zulaessig wenn:
|
||||
- Anonymisiert, ODER
|
||||
- Mit EINWILLIGUNG des Nutzers
|
||||
|
||||
ANFORDERUNGEN BEI EINWILLIGUNG:
|
||||
|
||||
1. VOR der Verarbeitung einzuholen
|
||||
2. Umfang und Dauer der Verarbeitung angeben
|
||||
3. Zweck der Verarbeitung angeben
|
||||
4. Ob Daten an Dritte weitergegeben werden
|
||||
5. Widerruf jederzeit moeglich
|
||||
|
||||
PRAKTISCHE ANWENDUNG:
|
||||
|
||||
- Navigationsdienste: Einwilligung erforderlich
|
||||
- Standortbasierte Werbung: Einwilligung erforderlich
|
||||
- Flottenmanagement: Einwilligung der Fahrer
|
||||
- Find-my-Device: Einwilligung (oft Teil der Nutzungsbedingungen)
|
||||
|
||||
SONDERFALL: Notrufe
|
||||
Standortdaten duerfen fuer Notrufdienste ohne Einwilligung verarbeitet werden (Art. 10).
|
||||
|
||||
========================================
|
||||
UNERBETENE NACHRICHTEN - SPAM (Art. 13)
|
||||
========================================
|
||||
|
||||
E-Mail-Marketing und Direktwerbung (Art. 13)
|
||||
|
||||
Art. 13 regelt die Verwendung elektronischer Kommunikation fuer Direktwerbung:
|
||||
|
||||
GRUNDSATZ (Opt-In):
|
||||
Die Verwendung von E-Mail, SMS, Fax oder automatischen Anrufsystemen fuer Direktwerbung ist NUR zulaessig mit VORHERIGER EINWILLIGUNG.
|
||||
|
||||
AUSNAHME - BESTANDSKUNDEN (Art. 13 Abs. 2):
|
||||
E-Mail-Werbung OHNE Einwilligung ist zulaessig wenn ALLE Bedingungen erfuellt:
|
||||
|
||||
1. Der Absender hat die E-Mail-Adresse vom Kunden selbst erhalten
|
||||
2. Im Zusammenhang mit einem KAUF von Waren/Dienstleistungen
|
||||
3. Die Werbung bezieht sich auf AEHNLICHE Produkte/Dienstleistungen
|
||||
4. Der Kunde hatte bei Erhebung die Moeglichkeit zu widersprechen
|
||||
5. Bei JEDER weiteren Nachricht: Widerspruchsmoeglichkeit (Opt-Out)
|
||||
|
||||
WICHTIG: Die Ausnahme ist ENG auszulegen!
|
||||
- Newsletter: Einwilligung erforderlich (kein "aehnliches Produkt")
|
||||
- Werbung fuer Dritte: Einwilligung erforderlich
|
||||
- B2B-Kaltakquise per E-Mail: Umstritten, nationale Unterschiede
|
||||
|
||||
TELEFON-WERBUNG:
|
||||
- Automatische Anrufsysteme: Immer Einwilligung
|
||||
- Manuelle Anrufe: Nationale Regelung (in D: Einwilligung erforderlich)
|
||||
|
||||
ABSENDERKENNUNG:
|
||||
Die Identitaet des Absenders darf NICHT verschleiert werden!
|
||||
Eine gueltige Antwortadresse muss vorhanden sein.
|
||||
|
||||
Double Opt-In fuer Newsletter
|
||||
|
||||
Das Double Opt-In Verfahren ist Best Practice fuer Newsletter-Anmeldungen:
|
||||
|
||||
ABLAUF:
|
||||
|
||||
1. Nutzer gibt E-Mail-Adresse ein (Single Opt-In)
|
||||
2. System sendet Bestaetigungs-E-Mail mit Link
|
||||
3. Nutzer klickt Link zur Bestaetigung (Double Opt-In)
|
||||
4. Erst dann: Eintrag in Newsletter-Liste
|
||||
|
||||
VORTEILE:
|
||||
- Nachweis der Einwilligung
|
||||
- Schutz vor Missbrauch (fremde E-Mail-Adressen)
|
||||
- Reduziert Spam-Beschwerden
|
||||
- Bessere Zustellraten
|
||||
|
||||
ANFORDERUNGEN AN BESTAETIGUNGS-E-MAIL:
|
||||
- KEINE Werbung enthalten (nur Bestaetigung)
|
||||
- Klarer Hinweis auf den Zweck
|
||||
- Bestaetigung muss aktiv erfolgen
|
||||
- Protokollierung: IP, Zeitstempel, User-Agent
|
||||
|
||||
RECHTLICHE EINORDNUNG:
|
||||
- Die Bestaetigungs-E-Mail selbst ist KEINE Werbung
|
||||
- Aber: Nur EINE Erinnerung zulaessig
|
||||
- Nach Nicht-Bestaetigung: Adresse loeschen
|
||||
|
||||
SPEICHERDAUER NACHWEIS:
|
||||
- Einwilligungsnachweis aufbewahren
|
||||
- Mindestens bis Widerruf + Verjaehrungsfrist
|
||||
- In Deutschland: 3 Jahre empfohlen
|
||||
|
||||
========================================
|
||||
KOMMUNIKATIONSGEHEIMNIS (Art. 5)
|
||||
========================================
|
||||
|
||||
Vertraulichkeit der Kommunikation (Art. 5 Abs. 1)
|
||||
|
||||
Art. 5 Abs. 1 schuetzt die Vertraulichkeit elektronischer Kommunikation:
|
||||
|
||||
GRUNDSATZ:
|
||||
Die Mitgliedstaaten stellen die Vertraulichkeit der mit oeffentlichen Kommunikationsnetzen uebertragenen Nachrichten sicher.
|
||||
|
||||
VERBOTEN IST:
|
||||
- Abhoeren von Nachrichten
|
||||
- Anzapfen von Leitungen
|
||||
- Speicherung von Kommunikation durch Unbefugte
|
||||
- Jede andere Art des Abfangens
|
||||
|
||||
AUSNAHMEN:
|
||||
- Mit Einwilligung der betroffenen Nutzer
|
||||
- Gesetzlich erlaubte Ueberwachung (Strafverfolgung)
|
||||
- Technische Speicherung fuer Uebertragungszwecke
|
||||
|
||||
PRAKTISCHE BEDEUTUNG:
|
||||
|
||||
1. ARBEITGEBER
|
||||
- Abhoeren von Mitarbeiter-E-Mails problematisch
|
||||
- Private Nutzung verboten = mehr Spielraum
|
||||
- Betriebsvereinbarung empfohlen
|
||||
|
||||
2. E-MAIL-PROVIDER
|
||||
- Automatische Spam-Filter: Zulaessig (technisch notwendig)
|
||||
- Werbefinanzierte Analyse: Einwilligung erforderlich
|
||||
|
||||
3. MESSENGER-DIENSTE
|
||||
- Ende-zu-Ende-Verschluesselung schuetzt Vertraulichkeit
|
||||
- "Client-Side Scanning" (geplant) hochumstritten
|
||||
|
||||
========================================
|
||||
NATIONALE UMSETZUNG (DEUTSCHLAND)
|
||||
========================================
|
||||
|
||||
Umsetzung in Deutschland: TTDSG
|
||||
|
||||
In Deutschland wurde die ePrivacy-Richtlinie durch das Telekommunikation-Telemedien-Datenschutz-Gesetz (TTDSG) umgesetzt.
|
||||
|
||||
TTDSG (seit 01.12.2021):
|
||||
|
||||
Paragraph 25 TTDSG - COOKIES UND AEHNLICHE TECHNOLOGIEN:
|
||||
Entspricht Art. 5 Abs. 3 ePrivacy-Richtlinie
|
||||
- Einwilligung erforderlich fuer nicht-notwendige Cookies
|
||||
- Ausnahme: Technisch notwendige Speicherung/Zugriff
|
||||
|
||||
Paragraph 26 TTDSG - ANERKANNTE DIENSTE (PIMS):
|
||||
Personal Information Management Services
|
||||
- Nutzer kann zentral Einstellungen verwalten
|
||||
- Websites muessen PIMS-Signale beachten
|
||||
- Noch kaum praktische Umsetzung
|
||||
|
||||
WEITERE RELEVANTE GESETZE:
|
||||
|
||||
TKG (Telekommunikationsgesetz):
|
||||
- Paragraph 88 TKG: Fernmeldegeheimnis
|
||||
- Paragraph 96ff TKG: Verkehrsdaten
|
||||
|
||||
UWG (Gesetz gegen unlauteren Wettbewerb):
|
||||
- Paragraph 7 UWG: Unzumutbare Belaestigungen
|
||||
- Spam-Verbot, Telefon-Werbung
|
||||
|
||||
SANKTIONEN (Paragraph 28 TTDSG):
|
||||
- Verstoss gegen Paragraph 25: Bussgeld bis 300.000 EUR
|
||||
- Verstoss gegen Paragraph 26: Bussgeld bis 50.000 EUR
|
||||
|
||||
DSK Orientierungshilfe zu Telemedien
|
||||
|
||||
Die Datenschutzkonferenz (DSK) hat eine Orientierungshilfe fuer Anbieter von Telemedien veroeffentlicht:
|
||||
|
||||
KERNAUSSAGEN:
|
||||
|
||||
1. EINWILLIGUNG
|
||||
- Muss VOR dem Setzen von Cookies eingeholt werden
|
||||
- Vorausgewaehlte Checkboxen sind unwirksam
|
||||
- "Nur notwendige akzeptieren" muss gleichwertig sein
|
||||
|
||||
2. TECHNISCH NOTWENDIG
|
||||
- Enger Auslegung
|
||||
- Session-Cookies: Ja
|
||||
- Persistente Praeferenz-Cookies: Nein
|
||||
|
||||
3. INFORMATIONSPFLICHTEN
|
||||
- Zweck jedes Cookies angeben
|
||||
- Speicherdauer angeben
|
||||
- Dritte benennen
|
||||
|
||||
4. DOKUMENTATION
|
||||
- Einwilligungen dokumentieren
|
||||
- Mindestens: Zeitstempel, Umfang, Version
|
||||
|
||||
5. WIDERRUF
|
||||
- Jederzeit moeglich
|
||||
- So einfach wie Erteilung
|
||||
- Link im Footer oder Cookie-Banner
|
||||
|
||||
PRAXISTIPP:
|
||||
Die DSK-Orientierungshilfe ist nicht rechtlich bindend, wird aber von Aufsichtsbehoerden als Massstab herangezogen.
|
||||
|
||||
========================================
|
||||
EPRIVACY-VERORDNUNG (AUSBLICK)
|
||||
========================================
|
||||
|
||||
ePrivacy-Verordnung (ePVO) - Ausblick
|
||||
|
||||
Die ePrivacy-Verordnung (ePVO) soll die Richtlinie 2002/58/EG ersetzen:
|
||||
|
||||
STATUS (Stand 2026):
|
||||
- Kommissionsvorschlag: Januar 2017
|
||||
- Rat: Kein Konsens erreicht
|
||||
- Mehrere Kompromissvorschlaege gescheitert
|
||||
- Inkrafttreten: Weiterhin unklar
|
||||
|
||||
GEPLANTE AENDERUNGEN:
|
||||
|
||||
1. VERORDNUNG STATT RICHTLINIE
|
||||
- Direkt anwendbar in allen Mitgliedstaaten
|
||||
- Keine Umsetzung erforderlich
|
||||
- Einheitliche Regeln in der EU
|
||||
|
||||
2. ERWEITERTER ANWENDUNGSBEREICH
|
||||
- Auch OTT-Dienste (WhatsApp, Zoom, etc.)
|
||||
- Auch Maschine-zu-Maschine-Kommunikation (IoT)
|
||||
|
||||
3. COOKIE-WALLS
|
||||
- Verschiedene Positionen
|
||||
- Evtl. unter bestimmten Bedingungen zulaessig
|
||||
|
||||
4. BROWSER-EINSTELLUNGEN
|
||||
- "Privacy by Default" im Browser
|
||||
- Zentrale Einwilligungsverwaltung
|
||||
|
||||
5. HARMONISIERTE SANKTIONEN
|
||||
- DSGVO-aehnliche Bussgelder
|
||||
|
||||
BIS ZUR EPVO:
|
||||
Die Richtlinie 2002/58/EG und nationale Umsetzungen bleiben in Kraft!
|
||||
|
||||
========================================
|
||||
PRAKTISCHE CHECKLISTEN
|
||||
========================================
|
||||
|
||||
ePrivacy-Checkliste fuer Websites
|
||||
|
||||
COOKIES:
|
||||
- Cookie-Audit durchgefuehrt (alle Cookies identifiziert)
|
||||
- Kategorisierung (technisch notwendig vs. einwilligungspflichtig)
|
||||
- Cookie-Banner implementiert
|
||||
- Opt-In vor Setzen von nicht-notwendigen Cookies
|
||||
- "Ablehnen" gleichwertig zu "Akzeptieren"
|
||||
- Granulare Auswahlmoeglichkeit (Kategorien)
|
||||
- Speicherdauer dokumentiert
|
||||
- Einwilligungen protokolliert
|
||||
- Widerruf jederzeit moeglich
|
||||
|
||||
DATENSCHUTZERKLAERUNG:
|
||||
- Cookie-Informationen enthalten
|
||||
- Alle Cookies mit Zweck aufgelistet
|
||||
- Drittanbieter benannt
|
||||
- Speicherdauer angegeben
|
||||
|
||||
E-MAIL-MARKETING:
|
||||
- Double Opt-In implementiert
|
||||
- Abmelde-Link in jeder E-Mail
|
||||
- Einwilligungen dokumentiert
|
||||
- Bei Bestandskunden: Widerspruchsmoeglichkeit
|
||||
|
||||
TRACKING/ANALYTICS:
|
||||
- Nur mit Einwilligung aktiv
|
||||
- Oder: Einwilligungsfreie Alternative (z.B. serverseitig)
|
||||
- IP-Anonymisierung aktiviert
|
||||
- Datenverarbeitung dokumentiert
|
||||
|
||||
ePrivacy-Checkliste fuer lokale Anwendungen
|
||||
|
||||
GRUNDSAETZE:
|
||||
- Alle Daten bleiben lokal
|
||||
- Keine Cloud-Anbindung fuer Nutzerdaten
|
||||
- Keine Third-Party-Tracker
|
||||
|
||||
COOKIES/LOKALE SPEICHERUNG:
|
||||
- Nur Session-Cookies fuer Login
|
||||
- Keine persistenten Tracking-Cookies
|
||||
- Keine Local Storage fuer Tracking
|
||||
- Kein Fingerprinting
|
||||
|
||||
ANALYTICS:
|
||||
- Serverseitige Logs statt Cookies
|
||||
- Keine personenbezogenen Daten in Logs
|
||||
- Oder: Einwilligung fuer Cookie-Analytics
|
||||
|
||||
KOMMUNIKATION:
|
||||
- Keine automatisierten Werbe-E-Mails ohne Einwilligung
|
||||
- Abmelde-Moeglichkeit bei Benachrichtigungen
|
||||
- Push-Benachrichtigungen nur mit Zustimmung
|
||||
|
||||
DOKUMENTATION:
|
||||
- Datenschutzerklaerung aktuell
|
||||
- Cookie-Informationen (falls Cookies)
|
||||
- Technische Dokumentation der Datenverarbeitung
|
||||
|
||||
VORTEIL LOKALER VERARBEITUNG:
|
||||
Die meisten ePrivacy-Anforderungen entfallen bei rein lokaler Verarbeitung ohne externe Dienste!
|
||||
|
||||
========================================
|
||||
RECHTLICHE REFERENZEN
|
||||
========================================
|
||||
|
||||
EU-Recht:
|
||||
- Richtlinie 2002/58/EG (ePrivacy-Richtlinie)
|
||||
- Richtlinie 2009/136/EG (Cookie-Richtlinie)
|
||||
- DSGVO Art. 95 (Verhaeltnis zu ePrivacy)
|
||||
- EuGH Planet49 (C-673/17)
|
||||
|
||||
Deutsches Recht:
|
||||
- TTDSG (Telekommunikation-Telemedien-Datenschutz-Gesetz)
|
||||
- Paragraph 25 TTDSG (Cookies)
|
||||
- Paragraph 7 UWG (Unzumutbare Belaestigungen)
|
||||
- Paragraph 88 TKG (Fernmeldegeheimnis)
|
||||
|
||||
Behoerdenpraxis:
|
||||
- DSK Orientierungshilfe fuer Anbieter von Telemedien (2022)
|
||||
- DSK Beschluss zu Tracking (2021)
|
||||
- CNIL Guidelines on Cookies (2020)
|
||||
Reference in New Issue
Block a user