Update CLAUDE.md, MkDocs, nginx docs proxy, .claude/rules

- CLAUDE.md: Comprehensive documentation for core infrastructure
- docs-src: Cleaned 316MB junk, kept only markdown docs
- mkdocs.yml: Updated nav for core-only content
- nginx: Docs proxy targets split (3002->lehrer, 3007->compliance)
- docker-compose: Fixed docs port mapping (8009:80), added INSTALL_LOCK
- .claude/rules: testing, documentation, open-source-policy, night-scheduler

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Boenisch
2026-02-12 00:49:21 +01:00
parent ad111d5e69
commit 2498b0eb1f
54 changed files with 953 additions and 19290 deletions

View File

@@ -0,0 +1,91 @@
# Dokumentations-Regeln
## Automatische Dokumentations-Aktualisierung
**WICHTIG:** Bei JEDER Code-Änderung muss die entsprechende Dokumentation aktualisiert werden!
## Wann Dokumentation aktualisieren?
### API-Änderungen
Wenn du einen Endpoint änderst, hinzufügst oder entfernst:
- Aktualisiere `/docs/api/consent-service-api.md` (Go Endpoints)
- Aktualisiere `/docs/api/backend-api.md` (Python Endpoints)
### Neue Funktionen/Klassen
Wenn du neue Funktionen, Klassen oder Module erstellst:
- Aktualisiere `/docs/consent-service/README.md` (für Go)
- Aktualisiere `/docs/backend/README.md` (für Python)
### Architektur-Änderungen
Wenn du die Systemarchitektur änderst:
- Aktualisiere `/docs/architecture/system-architecture.md`
- Aktualisiere `/docs/architecture/data-model.md` (bei DB-Änderungen)
### Neue Konfigurationsoptionen
Wenn du neue Umgebungsvariablen oder Konfigurationen hinzufügst:
- Aktualisiere die entsprechende README
- Füge zur `guides/local-development.md` hinzu
## Dokumentations-Format
### API-Endpoints dokumentieren
```markdown
### METHOD /path/to/endpoint
Kurze Beschreibung.
**Request Body:**
\`\`\`json
{
"field": "value"
}
\`\`\`
**Response (200):**
\`\`\`json
{
"result": "value"
}
\`\`\`
**Errors:**
- `400`: Beschreibung
- `401`: Beschreibung
```
### Funktionen dokumentieren
```markdown
### FunctionName (file.go:123)
\`\`\`go
func FunctionName(param Type) ReturnType
\`\`\`
**Beschreibung:** Was macht die Funktion?
**Parameter:**
- `param`: Beschreibung
**Rückgabe:** Beschreibung
```
## Checkliste nach Code-Änderungen
Vor dem Abschluss einer Aufgabe prüfe:
- [ ] Wurden neue API-Endpoints hinzugefügt? → API-Docs aktualisieren
- [ ] Wurden Datenmodelle geändert? → data-model.md aktualisieren
- [ ] Wurden neue Konfigurationen hinzugefügt? → README aktualisieren
- [ ] Wurden neue Abhängigkeiten hinzugefügt? → requirements.txt/go.mod UND Docs
- [ ] Wurde die Architektur geändert? → architecture/ aktualisieren
## Beispiel: Vollständige Dokumentation einer neuen Funktion
Wenn du z.B. `GetUserStats()` im Go Service hinzufügst:
1. **Code schreiben** in `internal/services/stats_service.go`
2. **API-Doc aktualisieren** in `docs/api/consent-service-api.md`
3. **Service-Doc aktualisieren** in `docs/consent-service/README.md`
4. **Test schreiben** (siehe testing.md)

View File

@@ -0,0 +1,297 @@
# Night Scheduler - Entwicklerdokumentation
**Status:** Produktiv
**Letzte Aktualisierung:** 2026-02-09
**URL:** https://macmini:3002/infrastructure/night-mode
**API:** http://macmini:8096
---
## Uebersicht
Der Night Scheduler ermoeglicht die automatische Nachtabschaltung der Docker-Services:
- Zeitgesteuerte Abschaltung (Standard: 22:00)
- Zeitgesteuerter Start (Standard: 06:00)
- Manuelle Sofortaktionen (Start/Stop)
- Dashboard-UI zur Konfiguration
---
## Architektur
```
┌─────────────────────────────────────────────────────────────┐
│ Admin Dashboard (Port 3002) │
│ /infrastructure/night-mode │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ API Proxy: /api/admin/night-mode │
│ - GET: Status abrufen │
│ - POST: Konfiguration speichern │
│ - POST /execute: Sofortaktion (start/stop) │
│ - GET /services: Service-Liste │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ night-scheduler (Port 8096) │
│ - Python/FastAPI Container │
│ - Prueft jede Minute ob Aktion faellig │
│ - Fuehrt docker compose start/stop aus │
│ - Speichert Config in /config/night-mode.json │
└─────────────────────────────────────────────────────────────┘
```
---
## Dateien
| Pfad | Beschreibung |
|------|--------------|
| `night-scheduler/scheduler.py` | Python Scheduler mit FastAPI |
| `night-scheduler/Dockerfile` | Container mit Docker CLI |
| `night-scheduler/requirements.txt` | Dependencies |
| `night-scheduler/config/night-mode.json` | Konfigurationsdatei |
| `night-scheduler/tests/test_scheduler.py` | Unit Tests |
| `admin-v2/app/api/admin/night-mode/route.ts` | API Proxy |
| `admin-v2/app/api/admin/night-mode/execute/route.ts` | Execute Endpoint |
| `admin-v2/app/api/admin/night-mode/services/route.ts` | Services Endpoint |
| `admin-v2/app/(admin)/infrastructure/night-mode/page.tsx` | UI Seite |
---
## API Endpoints
### GET /api/night-mode
Status und Konfiguration abrufen.
**Response:**
```json
{
"config": {
"enabled": true,
"shutdown_time": "22:00",
"startup_time": "06:00",
"last_action": "startup",
"last_action_time": "2026-02-09T06:00:00",
"excluded_services": ["night-scheduler", "nginx"]
},
"current_time": "14:30:00",
"next_action": "shutdown",
"next_action_time": "22:00",
"time_until_next_action": "7h 30min",
"services_status": {
"backend": "running",
"postgres": "running"
}
}
```
### POST /api/night-mode
Konfiguration aktualisieren.
**Request:**
```json
{
"enabled": true,
"shutdown_time": "23:00",
"startup_time": "07:00",
"excluded_services": ["night-scheduler", "nginx", "vault"]
}
```
### POST /api/night-mode/execute
Sofortige Aktion ausfuehren.
**Request:**
```json
{
"action": "stop" // oder "start"
}
```
**Response:**
```json
{
"success": true,
"message": "Aktion 'stop' erfolgreich ausgefuehrt fuer 25 Services"
}
```
### GET /api/night-mode/services
Liste aller Services abrufen.
**Response:**
```json
{
"all_services": ["backend", "postgres", "valkey", ...],
"excluded_services": ["night-scheduler", "nginx"],
"status": {
"backend": "running",
"postgres": "running"
}
}
```
---
## Konfiguration
### Config-Format (night-mode.json)
```json
{
"enabled": true,
"shutdown_time": "22:00",
"startup_time": "06:00",
"last_action": "startup",
"last_action_time": "2026-02-09T06:00:00",
"excluded_services": ["night-scheduler", "nginx"]
}
```
### Umgebungsvariablen
| Variable | Default | Beschreibung |
|----------|---------|--------------|
| `COMPOSE_PROJECT_NAME` | `breakpilot-pwa` | Docker Compose Projektname |
---
## Ausgeschlossene Services
Diese Services werden NICHT gestoppt:
1. **night-scheduler** - Muss laufen, um Services zu starten
2. **nginx** - Optional, fuer HTTPS-Zugriff
Weitere Services koennen ueber die Konfiguration ausgeschlossen werden.
---
## Docker Compose Integration
```yaml
night-scheduler:
build: ./night-scheduler
container_name: breakpilot-pwa-night-scheduler
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./night-scheduler/config:/config
- ./docker-compose.yml:/app/docker-compose.yml:ro
environment:
- COMPOSE_PROJECT_NAME=breakpilot-pwa
ports:
- "8096:8096"
networks:
- breakpilot-pwa-network
restart: unless-stopped
```
---
## Tests ausfuehren
```bash
# Im Container
docker exec -it breakpilot-pwa-night-scheduler pytest -v
# Lokal (mit Dependencies)
cd night-scheduler
pip install -r requirements.txt
pytest -v tests/
```
---
## Deployment
```bash
# 1. Dateien synchronisieren
rsync -avz night-scheduler/ macmini:.../night-scheduler/
# 2. Container bauen
ssh macmini "docker compose -f .../docker-compose.yml build --no-cache night-scheduler"
# 3. Container starten
ssh macmini "docker compose -f .../docker-compose.yml up -d night-scheduler"
# 4. Testen
curl http://macmini:8096/health
curl http://macmini:8096/api/night-mode
```
---
## Troubleshooting
### Problem: Services werden nicht gestoppt/gestartet
1. Pruefen ob Docker Socket gemountet ist:
```bash
docker exec breakpilot-pwa-night-scheduler ls -la /var/run/docker.sock
```
2. Pruefen ob docker compose CLI verfuegbar ist:
```bash
docker exec breakpilot-pwa-night-scheduler docker compose version
```
3. Logs pruefen:
```bash
docker logs breakpilot-pwa-night-scheduler
```
### Problem: Konfiguration wird nicht gespeichert
1. Pruefen ob /config beschreibbar ist:
```bash
docker exec breakpilot-pwa-night-scheduler touch /config/test
```
2. Volume-Mount pruefen in docker-compose.yml
### Problem: API nicht erreichbar
1. Container-Status pruefen:
```bash
docker ps | grep night-scheduler
```
2. Health-Check pruefen:
```bash
curl http://localhost:8096/health
```
---
## Sicherheitshinweise
- Der Container benoetigt Zugriff auf den Docker Socket
- Nur interne Services koennen gestoppt/gestartet werden
- Keine Authentifizierung (internes Netzwerk)
- Keine sensitiven Daten in der Konfiguration
---
## Dependencies (SBOM)
| Package | Version | Lizenz |
|---------|---------|--------|
| FastAPI | 0.109.0 | MIT |
| Uvicorn | 0.27.0 | BSD-3-Clause |
| Pydantic | 2.5.3 | MIT |
| pytest | 8.0.0 | MIT |
| pytest-asyncio | 0.23.0 | Apache-2.0 |
| httpx | 0.26.0 | BSD-3-Clause |
---
## Aenderungshistorie
| Datum | Aenderung |
|-------|-----------|
| 2026-02-09 | Initiale Implementierung |

View File

@@ -0,0 +1,99 @@
# Open Source Policy
## Lizenzprüfung (AUTOMATISCH BEI JEDER DEPENDENCY)
### Erlaubte Lizenzen ✅
| Lizenz | Typ | Kommerziell OK |
|--------|-----|----------------|
| MIT | Permissive | ✅ |
| Apache-2.0 | Permissive | ✅ |
| BSD-2-Clause | Permissive | ✅ |
| BSD-3-Clause | Permissive | ✅ |
| ISC | Permissive | ✅ |
| MPL-2.0 | Weak Copyleft | ✅ |
| LGPL-2.1 / LGPL-3.0 | Weak Copyleft | ✅ (nur linking) |
| CC0-1.0 | Public Domain | ✅ |
| Unlicense | Public Domain | ✅ |
### Verbotene Lizenzen ❌
| Lizenz | Grund |
|--------|-------|
| GPL-2.0 / GPL-3.0 | Copyleft - infiziert Projekt |
| AGPL-3.0 | Network Copyleft - SaaS-Killer |
| SSPL | Server Side Public License |
| BSL | Business Source License |
| "Non-Commercial" | Keine kommerzielle Nutzung |
| "Educational Only" | Nur für Bildung |
| Proprietary | Keine OSS |
---
## Workflow bei neuer Dependency
### 1. Vor dem Hinzufügen prüfen
```bash
# NPM Package
npm view <package> license
# Python Package
pip show <package> | grep License
# Go Module
go-licenses check <module>
```
### 2. Bei Unklarheit
- README.md des Projekts lesen
- LICENSE-Datei prüfen
- SPDX-Identifier suchen
- Im Zweifel: **NICHT verwenden**
### 3. Nach dem Hinzufügen
**SBOM aktualisieren:** https://macmini:3002/infrastructure/sbom
```bash
# SBOM generieren
cd /Users/benjaminadmin/Projekte/breakpilot-pwa
# Python
pip-licenses --format=json > sbom/python-licenses.json
# Node.js
npx license-checker --json > sbom/node-licenses.json
# Go
go-licenses csv ./... > sbom/go-licenses.csv
```
---
## Grenzfälle
### Dual-Licensed Packages
- Wenn MIT **oder** GPL angeboten wird → MIT wählen
- Dokumentieren welche Lizenz gewählt wurde
### Transitive Dependencies
- Auch indirekte Abhängigkeiten prüfen
- `npm ls`, `pip-tree`, `go mod graph`
### Fonts & Assets
- Google Fonts: ✅ (OFL)
- Font Awesome Free: ✅ (CC BY 4.0 / OFL / MIT)
- Icons8: ❌ (Attribution required, kompliziert)
---
## Checkliste bei PR/Commit
Wenn neue Dependencies hinzugefügt wurden:
- [ ] Lizenz ist in der Whitelist
- [ ] SBOM wurde aktualisiert
- [ ] Keine GPL/AGPL-Abhängigkeiten eingeschleppt
- [ ] Bei Dual-License: MIT/Apache gewählt

202
.claude/rules/testing.md Normal file
View File

@@ -0,0 +1,202 @@
# Test-Regeln
## Automatische Test-Erweiterung
**WICHTIG:** Bei JEDER Code-Änderung müssen entsprechende Tests erstellt oder aktualisiert werden!
## Wann Tests schreiben?
### IMMER wenn du:
1. **Neue Funktionen** erstellst → Unit Test
2. **Neue API-Endpoints** hinzufügst → Handler Test
3. **Bugs fixst** → Regression Test (der Bug sollte nie wieder auftreten)
4. **Bestehenden Code änderst** → Bestehende Tests anpassen
## Test-Struktur
### Go Tests (Consent Service)
**Speicherort:** Im gleichen Verzeichnis wie der Code
```
internal/
├── services/
│ ├── auth_service.go
│ └── auth_service_test.go ← Test hier
├── handlers/
│ ├── handlers.go
│ └── handlers_test.go ← Test hier
└── middleware/
├── auth.go
└── middleware_test.go ← Test hier
```
**Test-Namenskonvention:**
```go
func TestFunctionName_Scenario_ExpectedResult(t *testing.T)
// Beispiele:
func TestHashPassword_ValidPassword_ReturnsHash(t *testing.T)
func TestLogin_InvalidCredentials_Returns401(t *testing.T)
func TestCreateDocument_MissingTitle_ReturnsError(t *testing.T)
```
**Test-Template:**
```go
func TestFunctionName(t *testing.T) {
// Arrange
service := &MyService{}
input := "test-input"
// Act
result, err := service.DoSomething(input)
// Assert
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if result != expected {
t.Errorf("Expected %v, got %v", expected, result)
}
}
```
**Table-Driven Tests bevorzugen:**
```go
func TestValidateEmail(t *testing.T) {
tests := []struct {
name string
email string
expected bool
}{
{"valid email", "test@example.com", true},
{"missing @", "testexample.com", false},
{"empty", "", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := ValidateEmail(tt.email)
if result != tt.expected {
t.Errorf("Expected %v, got %v", tt.expected, result)
}
})
}
}
```
### Python Tests (Backend)
**Speicherort:** `/backend/tests/`
```
backend/
├── consent_client.py
├── gdpr_api.py
└── tests/
├── __init__.py
├── test_consent_client.py ← Tests für consent_client.py
└── test_gdpr_api.py ← Tests für gdpr_api.py
```
**Test-Namenskonvention:**
```python
class TestClassName:
def test_method_scenario_expected_result(self):
pass
# Beispiele:
class TestConsentClient:
def test_check_consent_valid_token_returns_status(self):
pass
def test_check_consent_expired_token_raises_error(self):
pass
```
**Test-Template:**
```python
import pytest
from unittest.mock import AsyncMock, patch, MagicMock
class TestMyFeature:
def test_sync_function(self):
# Arrange
input_data = "test"
# Act
result = my_function(input_data)
# Assert
assert result == expected
@pytest.mark.asyncio
async def test_async_function(self):
# Arrange
client = MyClient()
# Act
with patch("httpx.AsyncClient") as mock:
mock_instance = AsyncMock()
mock.return_value = mock_instance
result = await client.fetch_data()
# Assert
assert result is not None
```
## Test-Kategorien
### 1. Unit Tests (Höchste Priorität)
- Testen einzelne Funktionen/Methoden
- Keine externen Abhängigkeiten (Mocks verwenden)
- Schnell ausführbar
### 2. Integration Tests
- Testen Zusammenspiel mehrerer Komponenten
- Können echte DB verwenden (Test-DB)
### 3. Security Tests
- Auth/JWT Validierung
- Passwort-Hashing
- Berechtigungsprüfung
## Checkliste vor Abschluss
Vor dem Abschluss einer Aufgabe:
- [ ] Gibt es Tests für alle neuen Funktionen?
- [ ] Gibt es Tests für alle Edge Cases?
- [ ] Gibt es Tests für Fehlerfälle?
- [ ] Laufen alle bestehenden Tests noch? (`go test ./...` / `pytest`)
- [ ] Ist die Test-Coverage angemessen?
## Tests ausführen
```bash
# Go - Alle Tests
cd consent-service && go test -v ./...
# Go - Mit Coverage
cd consent-service && go test -cover ./...
# Python - Alle Tests
cd backend && source venv/bin/activate && pytest -v
# Python - Mit Coverage
cd backend && pytest --cov=. --cov-report=html
```
## Beispiel: Vollständiger Test-Workflow
Wenn du z.B. eine neue `GetUserStats()` Funktion im Go Service hinzufügst:
1. **Funktion schreiben** in `internal/services/stats_service.go`
2. **Test erstellen** in `internal/services/stats_service_test.go`:
```go
func TestGetUserStats_ValidUser_ReturnsStats(t *testing.T) {...}
func TestGetUserStats_InvalidUser_ReturnsError(t *testing.T) {...}
func TestGetUserStats_NoConsents_ReturnsEmptyStats(t *testing.T) {...}
```
3. **Tests ausführen**: `go test -v ./internal/services/...`
4. **Dokumentation aktualisieren** (siehe documentation.md)