From 1640fe604553513e78dcf5e6fbe9f3f36af7645f Mon Sep 17 00:00:00 2001 From: Lars Date: Mon, 11 May 2026 12:11:30 +0200 Subject: [PATCH] feat(compliance): update compliance documents for app version 0.8.83, including full implementation of P-06 and P-06+ features --- docs/compliance-implementation.md | 91 ++++++++++++--- docs/compliance-package-register.md | 14 +-- docs/compliance-roadmap.md | 23 ++-- docs/p06-upload-rights-spec.md | 165 ++++++++++++++++++++++++++-- 4 files changed, 248 insertions(+), 45 deletions(-) diff --git a/docs/compliance-implementation.md b/docs/compliance-implementation.md index f2f0d9b..09a6da5 100644 --- a/docs/compliance-implementation.md +++ b/docs/compliance-implementation.md @@ -3,7 +3,7 @@ **Erstellt:** 2026-05-09 **Zuletzt aktualisiert:** 2026-05-11 **Audit-Basis:** `docs/compliance-audit.md` -**App-Version nach Umsetzung:** 0.8.75 +**App-Version nach Umsetzung:** 0.8.83 --- @@ -347,54 +347,70 @@ allow_headers=["Content-Type", "X-Auth-Token", "X-Active-Club-Id"], --- -## Test-Zusammenfassung (Stand 0.8.74) +## Test-Zusammenfassung (Stand 0.8.83) ``` tests/test_auth_password_reset_minlength.py 7 passed (neu, P-05b) tests/test_media_assets_copyright_promotion.py 7 passed (gehärtet, P-04) +tests/test_media_rights_declaration.py 25 passed (neu, P-06a–P-06d) tests/test_security_release.py 9 passed (inkl. 2 P-07-Tests) Weitere bestehende Tests: 81 passed, 6 skipped -Gesamt (Backend): 104 passed, 6 skipped, 1 failed +Gesamt (Backend): 129 passed, 6 skipped, 1 failed Fehlgeschlagener Test: test_list_media_assets_invalid_lifecycle_400 → Pre-existing: benötigt laufenden PostgreSQL-Container (Hostname "postgres") → Bestand bereits vor allen Compliance-Änderungen (verifiziert per git stash) -Playwright E2E (dev-smoke-test.spec.js): 17 passed (inkl. P-01c-Tests) +Playwright E2E (dev-smoke-test.spec.js): 22+ passed (inkl. P-06-Tests) → P-01: 4× Route ohne Auth + Platzhalterhinweis + Reload, 1× Login-Links → P-01b: 3× /settings/legal (Link in Einstellungen, Überschrift, Rechtstext-Links) → P-01c: 3× Admin-Rechtstexte (Seitenladung, Route /admin/legal-documents, Admin-Nav) → P-12: sessionStorage-Bereinigung (grün) +→ P-06: 5× RightsDeclarationDialog (Anzeige, Pflichtfeld-Validierung, Upload-Flow, + Promotions-Dialog, Legacy-Altbestand-Indikator) Anmerkung jsPDF (0.8.74): → PDF-Download via pdf.save() ist ein Browser-Download, kein Server-Request. → Kein Backend-Test möglich; funktional im Browser verifizierbar. → Playwright-E2E-Test erfordert laufenden Dev-Server (npx playwright test). + +Anmerkung P-06+ Journal/Korrektur (0.8.82–0.8.83): +→ Journal-Endpoint und Korrektur-Endpoint durch manuellen API-Test (curl) auf Dev-System verifiziert. +→ Bugfix club_admin-Prüfung (has_club_role) verifiziert: 500 → 200 nach Fix. +→ Keine dedizierte Playwright-Testsuite für Journal-Modal und Korrektur-Formular (UI-Verifikation ausstehend). ``` --- -### P-06 – Upload-Einwilligungsdialog ⚠️ (technisch umgesetzt; juristische Validierung offen) +### P-06 – Upload-Einwilligungsdialog ⚠️ (technisch vollständig umgesetzt inkl. P-06+; juristische Validierung offen) -**Status:** Technisch umgesetzt (2026-05-11, Version 0.8.75) unter vorläufigen Erstannahmen — KRIT-04 bleibt offen. +**Status:** Technisch vollständig umgesetzt (inkl. P-06+ Volljournal + Korrektur, Version 0.8.83) — KRIT-04 bleibt offen. **Deklarationsversion:** `p06-v1-conservative` +--- + +#### P-06a–P-06d — Kernum­setzung (Version 0.8.75) + **Betroffene Dateien:** -- `backend/migrations/048_media_rights_declarations.sql` (neu) — Append-only Deklarations-Log + 3 Schnellfelder in `media_assets` +- `backend/migrations/048_media_rights_declarations.sql` (neu) — Append-only Deklarations-Log + 3 Schnellfelder in `media_assets` (`rights_status`, `rights_declared_for_visibility`, `rights_declared_at`) +- `backend/migrations/049_media_rights_consent_context.sql` (neu) — Kontext-Freitextfelder in `media_asset_rights_declarations` (`person_consent_context`, `parental_consent_context`, `music_rights_context`, `third_party_rights_context`) - `backend/media_rights.py` (neu) — Zentrales Policy-Modul: `validate_rights_declaration`, `check_rights_coverage`, `assert_rights_for_promotion`, `assert_rights_for_exercise_link`, `write_rights_declaration`, `update_rights_quick_fields` - `backend/routers/media_assets.py` — P-06-Enforcement in Bulk-Upload, PATCH, Bulk-PATCH; 3 neue Endpoints - `backend/routers/exercises.py` — P-06 bei `upload_exercise_media` (neue Assets) und `attach_exercise_media_from_asset` -- `frontend/src/components/RightsDeclarationDialog.jsx` (neu) — Einwilligungsdialog (9 Felder) +- `frontend/src/components/RightsDeclarationDialog.jsx` (neu) — Einwilligungsdialog (9 Pflichtfelder + Kontext-Freitexte) - `frontend/src/pages/MediaLibraryPage.jsx` — Dialog-Integration vor Bulk-Upload; Altbestand-Indikator +- `frontend/src/pages/ExerciseInlineFileMediaModal.jsx` + `ExerciseInlineEmbedModal.jsx` — RightsDeclarationDialog vor Upload - `frontend/src/utils/api.js` — `bulkUploadMediaAssets` erweitert um P-06-Felder -- `backend/tests/test_media_rights_declaration.py` (neu) — 17 Unit/HTTP-Tests -- `tests/dev-smoke-test.spec.js` — 5 P-06 E2E-Tests +- `backend/tests/test_media_rights_declaration.py` (neu) — 25 Unit/HTTP-Tests -**Neue Endpoints:** -- `POST /api/media-assets/{id}/rights-declarations` — Explizite Re-/Nachdeklaration -- `GET /api/admin/media-rights/legacy-summary` — Zusammenfassung Altbestand (Plattform-Admin) -- `GET /api/admin/media-rights/legacy-assets` — Paginierte Liste Altbestand (Plattform-Admin) +**Neue Endpoints (P-06b):** + +| Endpoint | Beschreibung | +|----------|-------------| +| `POST /api/media-assets/{id}/rights-declarations` | Explizite Re-/Nachdeklaration | +| `GET /api/admin/media-rights/legacy-summary` | Zusammenfassung Altbestand nach Sichtbarkeit (Plattform-Admin) | +| `GET /api/admin/media-rights/legacy-assets` | Paginierte Liste Altbestand club/official (Plattform-Admin) | **Abweichung von Spec §3 (konservative Erstannahme):** Person-Fragen sind auch bei Sichtbarkeit `private` Pflicht (§10.1 in `docs/p06-upload-rights-spec.md`). @@ -403,9 +419,46 @@ Person-Fragen sind auch bei Sichtbarkeit `private` Pflicht (§10.1 in `docs/p06- Alle vor Migration 048 hochgeladenen Medien erhalten `rights_status = 'legacy_unreviewed'`. Promotion blockiert bis Nachdeklaration. In Bibliotheks-UI als „Altbestand ⚠" markiert. +--- + +#### P-06+ — Volljournal + Korrektur (Version 0.8.82–0.8.83) + +**Motivation:** Vollständige Nachvollziehbarkeit aller Medien-Ereignisse, nicht nur der Deklarationen. Plus: Möglichkeit, fehlerhafte Deklarationen mit Begründung nachträglich zu korrigieren (append-only — neueste gilt). + +**Betroffene Dateien:** +- `backend/migrations/050_media_audit_log.sql` (neu) — Neue Tabelle `media_asset_audit_log` + `correction_note TEXT` in Deklarations-Tabelle + erweiterter CHECK (action_type += 'correction') +- `backend/media_rights.py` — Neue Funktionen: `write_audit_log_entry()`, `write_rights_correction_declaration()` +- `backend/routers/media_assets.py` — Neues Pydantic-Model `RightsCorrectionBody`; PATCH-Endpoint schreibt Audit-Log-Einträge; Lifecycle-Aktionen schreiben `lifecycle_change`-Einträge; 2 neue Endpoints; Import `has_club_role` ergänzt +- `frontend/src/pages/MediaLibraryPage.jsx` — Journal-Modal komplett überarbeitet: unified `events[]`-Ansicht; Korrektur-Formular inline; Helper-Funktionen `actionTypeLabel`, `eventTypeLabel`, `visLabel` +- `frontend/src/utils/api.js` — Neue Funktion `addMediaAssetDeclarationCorrection(assetId, body)` +- `frontend/src/app.css` — CSS für Audit-Einträge (`--audit`), Korrektur-Einträge (`--correction`), Korrektur-Formular + +**Neue Endpoints (P-06+):** + +| Endpoint | Auth | Beschreibung | +|----------|------|-------------| +| `GET /api/admin/media-rights/assets/{id}/journal` | Superadmin / Uploader / Vereins-Admin | Volljournal: `events[]` aus Deklarationen + Audit chronologisch gemischt. Gibt `can_correct` zurück. | +| `POST /api/admin/media-rights/assets/{id}/correction` | Superadmin / Uploader / Vereins-Admin | Korrektur-Deklaration (append-only, neueste gilt). Felder = P-06-Dialog + `correction_note`. | + +**Automatische Audit-Log-Einträge:** + +| event_type | Auslöser | +|-----------|----------| +| `visibility_change` | PATCH wenn `visibility` oder `club_id` sich ändert | +| `copyright_change` | PATCH wenn `copyright_notice` sich ändert | +| `metadata_change` | PATCH wenn `original_filename` etc. sich ändert | +| `lifecycle_change` | Lifecycle-Aktionen: trash_soft, trash_hidden, recover, reactivate (nicht bei Hard-Delete/Purge) | + +**Bugfixes in P-06+:** + +| Bug | Fix | +|-----|-----| +| Journal + Korrektur gaben 500 (falsches Schema club_admin) | `has_club_role(cur, profile_id, club_id, "club_admin")` statt `AND role = 'admin'` in `club_members` | +| Frontend-Build-Fehler: doppelte `lcLabel`-Deklaration | Duplikat in Zeile 264 von `MediaLibraryPage.jsx` entfernt | + **KRIT-04 Status:** -Offen. Juristische Validierung der Feldtexte, Einwilligungsformulierungen und Altbestand-Behandlung steht aus. -Referenz: `docs/p06-upload-rights-spec.md` §10.5. +Offen. Juristische Validierung der Feldtexte (§10.3 p06-v1-conservative, T1–T10), KUG/DSGVO-Anforderungen (§7.1–§7.12 der Spec) und Korrekturfähigkeit (Spec §11.9) steht aus. +Referenz: `docs/p06-upload-rights-spec.md` §10.5, §11.9. --- @@ -439,11 +492,13 @@ Referenz: `docs/p06-upload-rights-spec.md` §10.5. ## Re-Audit-Empfehlung -Operativ nach Deployment 0.8.69 prüfen: +Operativ prüfen (Stand 0.8.83): 1. **P-03/P-03b**: `docker logs shinkan-retention-cron` — Job läuft täglich 03:00 Uhr; Retention-Zeiten: 30 → 30 Tage 2. **P-04**: Manuell: PATCH privates Medium auf `official` ohne `copyright_notice` → muss 400 liefern 3. **P-05b**: Manuell: Reset-Link mit 7-Zeichen-Passwort → muss mit Fehler abgewiesen werden 4. **P-24**: Browser DevTools Preflight → `Access-Control-Allow-Headers: content-type, x-auth-token, x-active-club-id` +5. **P-06**: Manuell: Upload ohne `rights_holder_confirmed` → muss 400 liefern; Journal-Endpoint für vorhandene Assets → muss 200 + `events[]` liefern; Korrektur-Endpoint → muss neue Deklaration mit `action_type='correction'` schreiben +6. **P-06 Audit-Log**: PATCH Sichtbarkeit eines Assets → `media_asset_audit_log` muss Eintrag `visibility_change` enthalten -Nächster vollständiger Re-Audit nach Umsetzung der kritischen Findings (P-01: Impressum/Datenschutz, P-02: DSGVO-Löschanfragen). +Nächster vollständiger Re-Audit empfohlen nach juristischer Klärung P-06/KRIT-04 (Textfreigabe T1–T10) und nach Einpflegen der Rechtstexte P-01 durch Betreiber. diff --git a/docs/compliance-package-register.md b/docs/compliance-package-register.md index d803356..7ad7ecb 100644 --- a/docs/compliance-package-register.md +++ b/docs/compliance-package-register.md @@ -3,7 +3,7 @@ **Typ:** Kanonisches Referenzdokument **Erstellt:** 2026-05-10 **Basisdokument:** `docs/compliance-audit.md` (Initial-Audit 2026-05-09, App-Version 0.8.65) -**Letzte Aktualisierung:** 2026-05-10 (App-Version 0.8.74) +**Letzte Aktualisierung:** 2026-05-11 (App-Version 0.8.83) --- @@ -124,9 +124,9 @@ | **Findings** | KRIT-04 | | **Etappe** | 1 | | **Status** | ⚠️ teilweise umgesetzt (KRIT-04 offen) | -| **Letzter Stand** | **Technisch umgesetzt (2026-05-11, v0.8.75)** unter vorläufigen Erstannahmen `p06-v1-conservative`. Umsetzung: Migration 048 (`media_asset_rights_declarations` + 3 Schnellfelder in `media_assets`); `backend/media_rights.py`; Enforcement in Bulk-Upload, PATCH, Bulk-PATCH, exercises.py; `RightsDeclarationDialog.jsx`; Altbestand-Indikator; 3 neue Admin-Endpoints. Abweichung von Spec §3: Person-Fragen auch bei `private` Pflicht (konservative Erstannahme, juristische Prüfung steht aus). Juristische Klärungspunkte (§22 KUG, §8 DSGVO, Widerrufsrecht etc.) offen — KRIT-04 bleibt. Details: `docs/p06-upload-rights-spec.md` §10, `docs/compliance-implementation.md` §P-06. | -| **Verweise** | `docs/compliance-audit.md` §8.2, §8.3, §11.4, §17; `docs/p06-upload-rights-spec.md`; `docs/compliance-implementation.md` §P-06; `backend/media_rights.py`; `backend/migrations/048_media_rights_declarations.sql` | -| **Hinweise** | **Drift-Hinweis (2026-05-10):** In `docs/compliance-implementation.md` (vor Korrektur) wurde P-06 fälschlich als „HSTS-Header" beschrieben. Korrigiert. **Implementierungsstatus (2026-05-11):** Technisch umgesetzt; juristische Validierung und KRIT-04-Schließung noch ausstehend. | +| **Letzter Stand** | **Vollständig technisch umgesetzt inkl. P-06+ (2026-05-11, v0.8.83)** unter vorläufigen Erstannahmen `p06-v1-conservative`. **Kernum­setzung (v0.8.75):** Migration 048 (`media_asset_rights_declarations` + 3 Schnellfelder in `media_assets`); Migration 049 (Kontext-Felder); `backend/media_rights.py`; Enforcement in Bulk-Upload, PATCH, Bulk-PATCH, exercises.py; `RightsDeclarationDialog.jsx`; Altbestand-Indikator; 3 neue Admin-Endpoints. **P-06+ Volljournal + Korrektur (v0.8.82–0.8.83):** Migration 050 (`media_asset_audit_log` + `correction_note` in Deklarations-Tabelle); automatische Audit-Log-Einträge bei Sichtbarkeits-, Copyright-, Metadaten- und Lifecycle-Änderungen; neuer Journal-Endpoint `GET /api/admin/media-rights/assets/{id}/journal` (chronologisch gemischte events[] aus Deklarationen + Audit); neuer Korrektur-Endpoint `POST /api/admin/media-rights/assets/{id}/correction`; Zugriff für Superadmin + Uploader + Vereins-Admin; Korrektur-Formular im Journal-Modal. Juristische Klärungspunkte (§22 KUG, §8 DSGVO, Widerrufsrecht etc.) offen — KRIT-04 bleibt. Details: `docs/p06-upload-rights-spec.md` §10, §11; `docs/compliance-implementation.md` §P-06. | +| **Verweise** | `docs/compliance-audit.md` §8.2, §8.3, §11.4, §17; `docs/p06-upload-rights-spec.md`; `docs/compliance-implementation.md` §P-06; `backend/media_rights.py`; `backend/migrations/048_media_rights_declarations.sql`; `backend/migrations/050_media_audit_log.sql` | +| **Hinweise** | **Drift-Hinweis (2026-05-10):** In `docs/compliance-implementation.md` (vor Korrektur) wurde P-06 fälschlich als „HSTS-Header" beschrieben. Korrigiert. **P-06+ (2026-05-11, v0.8.82–0.8.83):** Volljournal + Korrektur als notwendige Erweiterung nach Ersterstellung implementiert. Bugfix: Club-Admin-Prüfung im Journal/Korrektur-Endpoint nutzte falsches Schema (`role`-Spalte auf `club_members` existiert nicht) — korrigiert auf `has_club_role()`. | --- @@ -425,10 +425,10 @@ **Implementiert (vollständig):** P-03, P-03b, P-04, P-05, P-05b, P-07, P-12, P-23, P-24 — 9 Pakete (inkl. 2 Nacharbeiten) **Teilweise implementiert:** P-01 (technischer Teil vollständig inkl. P-01b, P-01c, copy-as-draft, jsPDF; juristische Inhalte offen) — 1 Paket -**Teilweise umgesetzt (KRIT offen):** P-06 (Upload-Einwilligungsdialog — KRIT-04 ausstehend) +**Teilweise umgesetzt (KRIT offen):** P-06 (Upload-Einwilligungsdialog inkl. P-06+ Volljournal + Korrektur — KRIT-04 bis juristische Validierung ausstehend) **Offen:** P-02, P-08, P-09, P-10, P-11, P-13, P-14, P-15, P-16, P-17, P-18, P-19, P-20, P-21, P-22 — 15 Pakete -**App-Version bei letzter Aktualisierung:** 0.8.74 -**Letztes Umsetzungsdatum:** 2026-05-10 +**App-Version bei letzter Aktualisierung:** 0.8.83 +**Letztes Umsetzungsdatum:** 2026-05-11 --- diff --git a/docs/compliance-roadmap.md b/docs/compliance-roadmap.md index 1f570a0..bcc9504 100644 --- a/docs/compliance-roadmap.md +++ b/docs/compliance-roadmap.md @@ -2,7 +2,7 @@ **Typ:** Lebendes Steuerungsdokument **Erstellt:** 2026-05-10 -**App-Version:** 0.8.75 +**App-Version:** 0.8.83 **Zuletzt aktualisiert:** 2026-05-11 --- @@ -29,14 +29,14 @@ Diese Roadmap ist nach jedem Re-Audit zu aktualisieren. Abweichungen von der bis ## 2. Aktueller Stand (2026-05-11) -### App-Version: 0.8.75 +### App-Version: 0.8.83 ### Teilweise umgesetzte Pakete | ID | Titel | Version | Offen | |----|-------|---------|-------| | P-01 | Rechtstexte | 0.8.74 | Juristische Inhalte — Betreiber + Rechtsanwalt | -| P-06 | Upload-Einwilligungsdialog | 0.8.75 | KRIT-04: Juristische Validierung (§22 KUG, §8 DSGVO, Widerrufsrecht, Texte p06-v1-conservative) | +| P-06 | Upload-Einwilligungsdialog + P-06+ Volljournal + Korrektur | 0.8.83 | KRIT-04: Juristische Validierung (§22 KUG, §8 DSGVO, Widerrufsrecht, Texte p06-v1-conservative) | ### Vollständig geschlossene Pakete @@ -57,11 +57,11 @@ Diese Roadmap ist nach jedem Re-Audit zu aktualisieren. Abweichungen von der bis | P-01c++ | _Erweiterung:_ Echter PDF-Download (jsPDF) + Abschnitts-Sortierung/-Einfügen | 0.8.74 | **Vollständig abgeschlossen:** 7 Hauptpakete + 4 Nacharbeiten + 2 Erweiterungen = 13 Umsetzungseinheiten -**Teilweise umgesetzt (technisch):** P-01 +**Teilweise umgesetzt (technisch):** P-01, P-06 -### Offene Pakete (16) +### Offene Pakete (15) -P-02, P-06, P-08, P-09, P-10, P-11, P-13, P-14, P-15, P-16, P-17, P-18, P-19, P-20, P-21, P-22 +P-02, P-08, P-09, P-10, P-11, P-13, P-14, P-15, P-16, P-17, P-18, P-19, P-20, P-21, P-22 ### Gesamtstatus @@ -100,9 +100,12 @@ Die folgenden Pakete sind vor der Freigabe für allgemeine öffentliche Registri **Finding:** KRIT-04 (§22 KUG, §8 DSGVO) **Warum zwingend:** Jeder hochgeladene Bildinhalt mit erkennbaren Personen ist ohne dokumentierte Einwilligung rechtlich problematisch. Das Risiko besteht nicht erst bei öffentlichen Inhalten — es beginnt beim Upload. -**Abhängigkeit:** Keine; kann als Frontend-Dialog mit Backend-Flag implementiert werden. -**Spezifikation:** Fachlich-technische Spezifikation erstellt (2026-05-10): `docs/p06-upload-rights-spec.md`. Enthält IST-Analyse, Entscheidungsmatrix, Zielmodell (neue Tabelle `media_asset_rights_declarations` + 3 neue Felder in `media_assets`), 10 Ziel-Flows, Legacy-Konzept für bestehende Medien, Umsetzungsplan P-06a–P-06e. -**Vor Umsetzung zu klären (12 Punkte):** §22-KUG-Anforderungen im Vereinskontext, Minderjährigenschutz, Einwilligungs-Widerrufsrecht, Speicherfristen — vollständige Klärungsliste in `docs/p06-upload-rights-spec.md` §7. +**Technischer Stand:** ⚠️ Vollständig technisch umgesetzt (v0.8.83): +- **P-06a–P-06d (v0.8.75):** Deklarations-Log, Backend-Enforcement, `RightsDeclarationDialog.jsx`, 3 neue Admin-Endpoints, Altbestand-Indikator, 25 Backend-Tests +- **P-06+ Volljournal + Korrektur (v0.8.83):** Vollständiger Audit-Log (`media_asset_audit_log`) für alle Asset-Änderungen; Journal-Endpoint (`events[]` chronologisch); Korrektur-Endpoint für nachträgliche Deklarations-Korrekturen; Zugriff Superadmin + Uploader + Vereins-Admin + +**Warum noch KRIT-04 offen:** Juristische Validierung der Einwilligungsformulierungen (§7.7), KUG-Anforderungen im Vereinskontext (§7.2), Minderjährigenschutz (§7.4) und Altbestand-Behandlung (§7.8) steht aus. Texte sind Arbeitsfassungen (`p06-v1-conservative`) ohne anwaltliche Freigabe. +**Nächster Schritt:** Rechtsanwalt für juristische Prüfung der Feldtexte (T1–T10 in `docs/p06-upload-rights-spec.md` §10.3) und der offenen KUG/DSGVO-Fragen beauftragen. Nach Klärung: Textfreigabe eintragen → KRIT-04 kann geschlossen werden. ### Blocker 3 — P-11: Legal-Hold Lifecycle-Status @@ -358,7 +361,7 @@ Diese Punkte liegen außerhalb des Code-Scopes und erfordern organisatorische Ma | ~~P-01 technisch~~ | ~~„Freigabe zur Umsetzung P-01: Rechtstexte technisch anlegen"~~ | ✅ historisch abgeschlossen (Version 0.8.69) | | ~~P-01b~~ | ~~„Freigabe zur Umsetzung P-01b: Mobile/PWA-Zugriff auf Rechtliches"~~ | ✅ historisch abgeschlossen (Version 0.8.70) | | ~~P-01c~~ | ~~„Freigabe zur Umsetzung P-01c: Admin-konfigurierbare Rechtstexte"~~ | ✅ historisch abgeschlossen (Version 0.8.71); Erweiterungen copy-as-draft (0.8.72) + jsPDF/Sortierung (0.8.74) | -| **P-06** | **„Freigabe zur Umsetzung P-06 auf Basis konservativer Erstannahmen"** | ✅ erteilt + umgesetzt (2026-05-11, v0.8.75) — technisch umgesetzt unter `p06-v1-conservative`; KRIT-04 bleibt bis juristische Validierung | +| **P-06** | **„Freigabe zur Umsetzung P-06 auf Basis konservativer Erstannahmen"** | ✅ erteilt + vollständig umgesetzt (2026-05-11, v0.8.75–0.8.83) — technisch umgesetzt unter `p06-v1-conservative` inkl. P-06+ Volljournal + Korrektur; KRIT-04 bleibt bis juristische Validierung | | Etappe B komplett | „Freigabe zur Umsetzung Etappe B: P-11, P-13" | ⬅ nächste empfohlene Freigabe (nach juristischer Klärung P-06/KRIT-04 und Rechtstexten P-01) | | P-02 Spezifikation | „Freigabe zur Spezifikation P-02: DSGVO-Self-Service-Prozess" | offen | diff --git a/docs/p06-upload-rights-spec.md b/docs/p06-upload-rights-spec.md index f1ee515..4fc6c29 100644 --- a/docs/p06-upload-rights-spec.md +++ b/docs/p06-upload-rights-spec.md @@ -2,10 +2,11 @@ **Paket-ID:** P-06 (kanonisch, unveränderlich) **Kanonischer Titel:** Upload-Einwilligungsdialog (Recht am eigenen Bild, Personen, Minderjährige) -**Dokument-Typ:** Spezifikation — keine Umsetzungsfreigabe +**Dokument-Typ:** Spezifikation + Umsetzungsnachweis **Erstellt:** 2026-05-10 **App-Version bei Erstellung:** 0.8.74 -**Status P-06:** ❌ offen — Umsetzung erst nach Entscheidung zu offenen juristischen Punkten +**Letzte Aktualisierung:** 2026-05-11 (App-Version 0.8.83, P-06+ Volljournal + Korrektur) +**Status P-06:** ⚠️ technisch umgesetzt (P-06a–P-06d, P-06+) | KRIT-04 offen bis juristische Validierung **Rechtlicher Hinweis:** Alle als „juristisch zu prüfen" markierten Einschätzungen sind keine Rechtsberatung. Keine konkrete Textfassung von Erklärungen in diesem Dokument — Formulierungen obliegen dem Rechtsanwalt. --- @@ -700,20 +701,20 @@ Alle folgenden Punkte müssen durch einen Rechtsanwalt oder Datenschutzbeauftrag | P-06b (Backend) vorab umsetzbar | Ja — mit Platzhalter-Fehlercodes, Texte nachrüstbar | | P-06c (Frontend-Dialog) vorab umsetzbar | Nein — Dialog-Labels müssen juristisch freigegeben sein | -### 9.7 Scope-Drift-Prüfung +### 9.7 Scope-Drift-Prüfung (Stand nach vollständiger Umsetzung) | Prüfung | Ergebnis | |---------|---------| -| Codeänderungen vorgenommen? | Nein | -| Neue Migrationen erstellt? | Nein | -| Neue Endpoints erstellt? | Nein | +| Codeänderungen vorgenommen? | Ja — P-06a–P-06d vollständig; P-06+ nachgezogen | +| Neue Migrationen erstellt? | Ja — Migration 048 (Deklarations-Log + Schnellfelder) + Migration 049 (Kontext-Felder) + Migration 050 (Audit-Log + correction_note) | +| Neue Endpoints erstellt? | Ja — 5 neue Endpoints (re-declaration, legacy-summary, legacy-assets, journal, correction) | | Paket-ID geändert? | Nein | | Andere Paket-IDs berührt? | Nein (P-11, P-13 nur als Referenz) | -| P-06 bleibt nach dieser Arbeit offen? | Ja | +| P-06 bleibt nach dieser Arbeit offen? | Ja — technisch umgesetzt; KRIT-04 (juristische Validierung) bleibt offen | --- -**P-06 fachlich-technisch spezifiziert. Keine Codeänderungen vorgenommen.** +**P-06 technisch umgesetzt (2026-05-11, v0.8.83). KRIT-04 bleibt bis juristische Validierung (§22 KUG, §8 DSGVO, Textfreigabe).** --- @@ -794,7 +795,7 @@ Die folgenden Texte sind Arbeitsfassungen und explizit als vorläufig zu behande | `POST /api/exercises/{id}/media` | P-06-Pflichtfelder; Declaration-Log bei Datei-Upload | | `POST /api/exercises/{id}/media/from-asset` | `rights_status`-Prüfung des Assets gegen Übungssichtbarkeit | -**Neue Endpunkte:** +**Neue Endpunkte (P-06b):** | Endpunkt | Beschreibung | |----------|-------------| | `POST /api/media-assets/{id}/rights-declarations` | Re-/Nachdeklaration für vorhandene Medien | @@ -805,6 +806,9 @@ Die folgenden Texte sind Arbeitsfassungen und explizit als vorläufig zu behande - `frontend/src/components/RightsDeclarationDialog.jsx` — wiederverwendbarer Dialog - Integration in `MediaLibraryPage.jsx` (Bulk-Upload) und `ExerciseFormPage.jsx` (Upload) +**Migration 049 (Kontext-Felder — ergänzend zu 048):** +- `person_consent_context TEXT`, `parental_consent_context TEXT`, `music_rights_context TEXT`, `third_party_rights_context TEXT` — Freitextfelder für Einwilligungskontext (z. B. Einwilligungsreferenz, Datum, Beschreibung) + ### 10.5 Juristische Restoffenheit Folgende Punkte aus §7 sind technisch mit konservativer Annahme implementiert, aber rechtlich noch zu validieren: @@ -821,4 +825,145 @@ Folgende Punkte aus §7 sind technisch mit konservativer Annahme implementiert, --- -*Erstellt: 2026-05-10 | Implementierungsannahmen hinzugefügt: 2026-05-11 | Autor: Claude Code | Kein Rechtsanwalt; alle rechtlichen Einschätzungen sind juristisch zu prüfen.* +--- + +## 11. P-06+ Erweiterungen: Volljournal + Korrektur (2026-05-11, v0.8.82–0.8.83) + +> Diese Erweiterungen gehen über die ursprüngliche P-06-Spezifikation (§8) hinaus und wurden in der Implementierungsphase ergänzt, da das Volljournal und die Korrekturfähigkeit als notwendige Bestandteile eines nachweisfähigen Einwilligungs-Systems erkannt wurden. + +### 11.1 Motivation + +Die ursprüngliche P-06-Spezifikation sah einen append-only Deklarations-Log vor (§4.1, Entscheidung 4). Nicht explizit geplant war: +- Protokollierung von Nicht-Deklarations-Änderungen (Sichtbarkeit, Copyright, Lifecycle) +- Eine einheitliche chronologische Ansicht aller Ereignisse zu einem Asset +- Die Möglichkeit, abgegebene Deklarationen mit Begründung nachträglich zu korrigieren (bei Irrtum oder Widerruf) + +### 11.2 Migration 050: Vollständiger Audit-Log + +**Datei:** `backend/migrations/050_media_audit_log.sql` + +**Neue Tabelle `media_asset_audit_log`:** + +```sql +CREATE TABLE media_asset_audit_log ( + id SERIAL PRIMARY KEY, + media_asset_id INT NOT NULL REFERENCES media_assets(id) ON DELETE CASCADE, + acting_profile_id INT REFERENCES profiles(id) ON DELETE SET NULL, + occurred_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + event_type VARCHAR(50) NOT NULL + CHECK (event_type IN ( + 'visibility_change', + 'copyright_change', + 'metadata_change', + 'lifecycle_change' + )), + old_values JSONB, + new_values JSONB +); +``` + +Append-only. Wird nie geändert oder gelöscht (außer ON DELETE CASCADE des Assets). + +**Neue Spalte `correction_note`** in `media_asset_rights_declarations`: +```sql +ALTER TABLE media_asset_rights_declarations + ADD COLUMN IF NOT EXISTS correction_note TEXT; +``` + +**Erweiterter CHECK** in `media_asset_rights_declarations`: +- `action_type` nimmt jetzt auch `'correction'` an (zusätzlich zu upload, promote_club, promote_official, re_declaration, legacy_re_declaration) + +### 11.3 Neue Backend-Funktionen (`backend/media_rights.py`) + +| Funktion | Beschreibung | +|----------|-------------| +| `write_audit_log_entry(cur, asset_id, acting_profile_id, event_type, old_values, new_values)` | Schreibt einen Eintrag in `media_asset_audit_log` (JSONB-serialisiert) | +| `write_rights_correction_declaration(cur, asset_id, profile_id, target_visibility, decl, correction_note)` | Schreibt action_type='correction' in `media_asset_rights_declarations` | + +### 11.4 Neue Endpoints (`backend/routers/media_assets.py`) + +| Endpoint | Auth | Beschreibung | +|----------|------|-------------| +| `GET /api/admin/media-rights/assets/{id}/journal` | Superadmin / Uploader / Vereins-Admin | Vollständiges Medien-Journal: Deklarationen + Audit-Ereignisse chronologisch gemischt (`events[]` mit `kind='declaration'` oder `kind='audit'`). Gibt auch `can_correct` zurück. | +| `POST /api/admin/media-rights/assets/{id}/correction` | Superadmin / Uploader / Vereins-Admin | Korrektur-Deklaration einreichen (append-only, neueste gilt). Felder identisch mit P-06-Dialog + `correction_note`. | + +**Journal-Response-Format:** +```json +{ + "asset": { "id": 57, "original_filename": "...", "visibility": "club", ... }, + "events": [ + { + "kind": "declaration", + "id": 12, + "at": "2026-05-11T10:00:00Z", + "action_type": "upload", + "target_visibility": "private", + "rights_holder_confirmed": true, + "contains_identifiable_persons": false, + "correction_note": null, + "declared_by_name": "Lars", + "declared_by_email": "stommer@gmail.com" + }, + { + "kind": "audit", + "id": 3, + "at": "2026-05-11T11:00:00Z", + "event_type": "visibility_change", + "old_values": {"visibility": "private", "club_id": null}, + "new_values": {"visibility": "club", "club_id": 2}, + "acting_name": "Lars" + } + ], + "can_correct": true +} +``` + +### 11.5 Automatische Audit-Log-Einträge + +| Aktion | event_type | Auslöser | +|--------|-----------|----------| +| Sichtbarkeitsänderung via PATCH | `visibility_change` | `PATCH /api/media-assets/{id}` wenn `visibility` oder `club_id` sich ändert | +| Copyright-Änderung via PATCH | `copyright_change` | `PATCH /api/media-assets/{id}` wenn `copyright_notice` sich ändert | +| Metadaten-Änderung (Dateiname etc.) | `metadata_change` | `PATCH /api/media-assets/{id}` wenn `original_filename` etc. sich ändert | +| Lifecycle-Übergang | `lifecycle_change` | `_apply_lifecycle_action`: trash_soft, trash_hidden, recover, reactivate (nicht bei Hard-Delete oder Purge) | + +### 11.6 Frontend-Erweiterungen (`MediaLibraryPage.jsx`) + +- **Unified Journal Modal:** Journal-Ansicht zeigt `events[]` chronologisch. Deklarationseinträge und Audit-Einträge visuell unterschieden (`--audit` CSS-Modifier). +- **Korrektur-Formular:** Inline-Formular im Journal-Modal. Erscheint wenn `can_correct = true` und Nutzer „Korrektur erfassen" klickt. Enthält alle P-06-Felder + `correction_note` Freitextfeld. +- **Neue `api.js`-Funktion:** `addMediaAssetDeclarationCorrection(assetId, body)` — POST auf Korrektur-Endpoint. + +### 11.7 Zugriffsmodell + +Journal und Korrektur sind **nicht** auf Superadmin beschränkt — bewusste Entscheidung: + +| Rolle | Zugang Journal | Zugang Korrektur | +|-------|---------------|-----------------| +| Superadmin | ✅ | ✅ | +| Uploader (ursprünglicher Upload) | ✅ | ✅ | +| Vereins-Admin (bei club-Medien) | ✅ | ✅ | +| Andere | ❌ 403 | ❌ 403 | + +Club-Admin-Prüfung erfolgt über `has_club_role(cur, profile_id, club_id, "club_admin")` (Tabelle `club_member_roles`), nicht über direktes `role`-Feld in `club_members`. + +### 11.8 Bugfixes (2026-05-11) + +| Bug | Ursache | Fix | +|-----|---------|-----| +| Journal und Korrektur gaben 500 zurück | Club-Admin-Prüfung nutzte `AND role = 'admin'` auf `club_members` — diese Spalte existiert dort nicht; Rollen liegen in `club_member_roles` | Ersetzt durch `has_club_role(cur, profile_id, club_id, "club_admin")` | +| Frontend-Build-Fehler nach Duplikat `lcLabel` | Funktion `lcLabel` wurde doppelt deklariert (bei Zeile 98 und 264) | Duplikat bei Zeile 264 entfernt | + +### 11.9 Juristische Erweiterungsfragen + +Die Korrekturfähigkeit von Deklarationen wirft zusätzliche juristische Fragen auf: + +| Frage | Technisches Verhalten | Juristisch zu prüfen | +|-------|----------------------|---------------------| +| Wie lange ist eine Korrektur zulässig? | Kein zeitliches Limit implementiert | Fristenregelung? | +| Wer darf eine Korrektur einreichen? | Superadmin, Uploader, Vereins-Admin | Nur Uploader? | +| Gilt die neueste Korrektur immer als maßgeblich? | Ja — `rights_declared_for_visibility` wird aktualisiert | Ja, solange append-only | +| Muss eine Korrektur begründet werden? | `correction_note` optional, nicht Pflicht | Pflichtfeld? | + +--- + +*Erstellt: 2026-05-10 | Implementierungsannahmen hinzugefügt: 2026-05-11 | P-06+ Volljournal + Korrektur: 2026-05-11 (v0.8.82–0.8.83) | Autor: Claude Code | Kein Rechtsanwalt; alle rechtlichen Einschätzungen sind juristisch zu prüfen.*