All checks were successful
Deploy Development / deploy (push) Successful in 37s
Test Suite / pytest-backend (push) Successful in 31s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 7s
Test Suite / playwright-tests (push) Successful in 27s
- Added compliance implementation report detailing the status of various packages (P-03, P-04, P-05, P-07, P-23, P-24) and their technical changes, tests, and notes. - Introduced a new workspace configuration file for the project to streamline development setup.
155 lines
6.2 KiB
Markdown
155 lines
6.2 KiB
Markdown
# Compliance-Implementierung – Umsetzungsbericht
|
||
|
||
**Erstellt:** 2026-05-09
|
||
**Audit-Basis:** `docs/compliance-audit.md`
|
||
**App-Version nach Umsetzung:** 0.8.66
|
||
|
||
---
|
||
|
||
## Freigegebene Pakete und Umsetzungsstatus
|
||
|
||
### P-03 – Papierkorb-Retention-Job aktivieren ✅
|
||
|
||
**Status:** Umgesetzt
|
||
|
||
**Betroffene Dateien:**
|
||
- `docker-compose.yml` – neuer Service `retention-cron`
|
||
|
||
**Technische Änderung:**
|
||
Neuer Docker-Service `retention-cron` nutzt dasselbe Backend-Image und führt `scripts/media_retention_job.py` täglich um 03:00 Uhr aus. Der Service startet beim ersten Hochfahren sofort und schläft bis zum nächsten 3 AM (Python-basierter Loop ohne externe Cron-Abhängigkeit). Zugriff auf DB und Media-Volume identisch zur Backend-Konfiguration.
|
||
|
||
**Tests:** Keine automatisierten Tests möglich (Runtime-Verhalten); operativ über Container-Logs (`docker logs shinkan-retention-cron`) überprüfbar.
|
||
|
||
**Anmerkungen:**
|
||
- Retention-Zeiten über Env-Variablen konfigurierbar: `MEDIA_TRASH_SOFT_TO_HIDDEN_DAYS` (Default 30), `MEDIA_TRASH_HIDDEN_TO_PURGE_DAYS` (Default 90)
|
||
- Das Skript selbst (`scripts/media_retention_job.py`) war bereits korrekt implementiert; nur der Scheduler fehlte
|
||
|
||
---
|
||
|
||
### P-04 – Copyright-Pflicht bei Archiv-Promotion vereinheitlichen ✅
|
||
|
||
**Status:** Umgesetzt
|
||
|
||
**Betroffene Dateien:**
|
||
- `backend/routers/media_assets.py` – `patch_media_asset()` und `bulk_media_patch()`
|
||
|
||
**Technische Änderung:**
|
||
Beide Endpoints prüfen nun, ob `copyright_notice` vorhanden ist, wenn `visibility` auf `club` oder `official` gewechselt wird. Priorität: Wert aus dem Request-Body > bestehender Wert in der DB. Ist beides leer, wird HTTP 400 zurückgegeben.
|
||
|
||
Single PATCH: `raise HTTPException(status_code=400, ...)`
|
||
Bulk PATCH: Asset wird in die `failed`-Liste eingetragen und übersprungen, Gesamtoperation läuft weiter.
|
||
|
||
**Tests:** `backend/tests/test_media_assets_copyright_promotion.py` (7 Tests, alle grün):
|
||
- Promotion zu `club` ohne Copyright → 400
|
||
- Promotion zu `official` ohne Copyright → 400
|
||
- Promotion zu `club` mit Copyright im Body → nicht 400
|
||
- Promotion zu `club`, Copyright bereits auf Asset → nicht 400
|
||
- Kein Visibility-Wechsel → keine Copyright-Prüfung → 200
|
||
- Bulk: ohne Copyright → in `failed`, `updated_count == 0`
|
||
- Bulk: mit Copyright → in `updated`, `updated_count == 1`
|
||
|
||
---
|
||
|
||
### P-05 – Passwort-Mindestlänge angleichen ✅
|
||
|
||
**Status:** Umgesetzt
|
||
|
||
**Betroffene Dateien:**
|
||
- `backend/routers/auth.py:101` – `PUT /api/auth/pin`
|
||
- `frontend/src/pages/LoginPage.jsx:175` – Registrierungs-/Login-Formular
|
||
- `frontend/src/pages/AccountSettingsPage.jsx:403` – Passwort-Änderungsformular
|
||
|
||
**Technische Änderung:**
|
||
- Backend: `if len(new_pin) < 4` → `if len(new_pin) < 8` (Fehlermeldung angepasst)
|
||
- Frontend LoginPage: `minLength="6"` → `minLength="8"`
|
||
- Frontend AccountSettingsPage: `minLength={4}` → `minLength={8}`
|
||
|
||
Alle drei Stellen sind jetzt konsistent mit dem bereits korrekten `POST /api/auth/register` (war schon `< 8`).
|
||
|
||
**Tests:** Keine neuen Tests; Änderung ist trivial und durch bestehende Auth-Tests (Register) indirekt abgedeckt.
|
||
|
||
---
|
||
|
||
### P-07 – ALLOW_PUBLIC_MEDIA_STATIC dokumentieren + Release-Test ✅
|
||
|
||
**Status:** Umgesetzt
|
||
|
||
**Betroffene Dateien:**
|
||
- `backend/tests/test_security_release.py` – 2 neue Tests
|
||
|
||
**Technische Änderung:**
|
||
Zwei neue Tests in der bestehenden Release-Test-Suite:
|
||
|
||
1. `test_public_media_static_not_mounted_by_default`: Verifiziert, dass `/media`-Mount ohne `ALLOW_PUBLIC_MEDIA_STATIC` in der App-Route-Liste nicht vorhanden ist (sicherer Standardzustand in Production).
|
||
|
||
2. `test_allow_public_media_static_activates_media_mount`: Dokumentiert den Effekt des Flags – wenn gesetzt, ist der Mount aktiv (für Awareness im CI).
|
||
|
||
**Tests:** Beide Tests grün (16/16 in `test_security_release.py`).
|
||
|
||
---
|
||
|
||
### P-23 – LoginPage: minLength + Versionsstring ✅
|
||
|
||
**Status:** Umgesetzt (zusammen mit P-05)
|
||
|
||
**Betroffene Dateien:**
|
||
- `frontend/src/pages/LoginPage.jsx`
|
||
|
||
**Technische Änderung:**
|
||
- `minLength="6"` → `minLength="8"` (deckungsgleich mit P-05)
|
||
- Hardcodierter Versionsstring `v0.1.0 • Development` aus dem Footer der LoginPage entfernt. Kein Ersatz: Die Versionsinformation ist nur im eingeloggten Bereich unter Einstellungen sichtbar.
|
||
|
||
---
|
||
|
||
### P-24 – CORS allow_methods und allow_headers einschränken ✅
|
||
|
||
**Status:** Umgesetzt
|
||
|
||
**Betroffene Dateien:**
|
||
- `backend/main.py:85-86` – CORSMiddleware-Konfiguration
|
||
|
||
**Technische Änderung:**
|
||
```python
|
||
# Vorher:
|
||
allow_methods=["*"],
|
||
allow_headers=["*"],
|
||
|
||
# Nachher:
|
||
allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
|
||
allow_headers=["Content-Type", "X-Auth-Token", "X-Active-Club-Id"],
|
||
```
|
||
|
||
Die drei erlaubten Header entsprechen den tatsächlich genutzten Headers (Auth-Token, Tenant-Header, Content-Type). Alle API-Funktionen bleiben unverändert erreichbar.
|
||
|
||
---
|
||
|
||
## Test-Zusammenfassung
|
||
|
||
```
|
||
tests/test_security_release.py 9 passed (inkl. 2 neue P-07 Tests)
|
||
tests/test_media_assets_copyright_promotion.py 7 passed (neue P-04 Tests)
|
||
Gesamt neue Tests: 11
|
||
Gesamt bestehende Tests: 104 → 103 passed, 1 failed (pre-existing, DB nicht erreichbar)
|
||
```
|
||
|
||
Der vorhandene Fehler (`test_list_media_assets_invalid_lifecycle_400`) war bereits vor dieser Implementierung vorhanden (verifiziert per `git stash`). Er tritt nur lokal auf, wenn kein PostgreSQL-Container mit Hostname `postgres` läuft, und besteht in der CI/Docker-Umgebung nicht.
|
||
|
||
---
|
||
|
||
## Nicht umgesetzte Pakete (laut Freigabe ausgeschlossen)
|
||
|
||
P-01, P-02, P-06, P-09, P-10, P-11, P-13–P-16 und alle weiteren Findings bleiben offen.
|
||
Vollständige Liste und Begründungen: `docs/compliance-audit.md`.
|
||
|
||
---
|
||
|
||
## Re-Audit-Empfehlung
|
||
|
||
Nach Deployment der Version 0.8.66 sollten folgende Punkte operativ verifiziert werden:
|
||
|
||
1. **P-03**: `docker logs shinkan-retention-cron` prüfen — Job läuft einmalig beim Start und danach täglich um 03:00 Uhr
|
||
2. **P-04**: Manuelle Stichprobe: PATCH eines privaten Mediums auf `official` ohne `copyright_notice` → muss 400 zurückgeben
|
||
3. **P-24**: Browser DevTools → Network → Preflight-Request auf `/api/exercises` → `Access-Control-Allow-Headers` darf nur `content-type, x-auth-token, x-active-club-id` enthalten
|
||
|
||
Nächster vollständiger Re-Audit empfohlen nach Umsetzung der kritischen Findings (P-01: Impressum/Datenschutz, P-02: Löschkonzept/DSGVO-Request-Workflow).
|