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:
Benjamin Boenisch
2026-02-11 23:47:26 +01:00
commit 5a31f52310
1224 changed files with 425430 additions and 0 deletions

View 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)

View 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.

View 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*

View 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)

View 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
```

View 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

View 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)

View 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.

View 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

View 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

View 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.

View 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.

View 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

View 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).

View 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.

View 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)

View 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.

View 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

View 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)