- docs/p06-upload-rights-spec.md (neu): vollständige Spezifikation für Upload-Einwilligungsdialog (§22 KUG, §8 DSGVO, Minderjährigenschutz) — IST-Analyse, Entscheidungsmatrix, Zielmodell (media_asset_rights_declarations + 3 neue Felder in media_assets), 10 Ziel-Flows, Legacy-Konzept, 12 juristische Klärungspunkte, Umsetzungsplan P-06a–P-06e - compliance-roadmap.md: Blocker 2 (P-06) mit Spec-Hinweis und juristischer Klärungsliste; §6 Freigabe-Empfehlung aktualisiert - compliance-package-register.md: P-06 Letzter Stand mit Spec-Verweis und Zielmodell-Zusammenfassung ergänzt - compliance-implementation.md: P-06 in Tabelle mit Spec-Hinweis Keine Code-Umsetzung; Umsetzung erst nach juristischer Klärung. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
42 KiB
P-06 – Fachlich-technische Spezifikation: Upload-Einwilligungsdialog
Paket-ID: P-06 (kanonisch, unveränderlich)
Kanonischer Titel: Upload-Einwilligungsdialog (Recht am eigenen Bild, Personen, Minderjährige)
Dokument-Typ: Spezifikation — keine Umsetzungsfreigabe
Erstellt: 2026-05-10
App-Version bei Erstellung: 0.8.74
Status P-06: ❌ offen — Umsetzung erst nach Entscheidung zu offenen juristischen Punkten
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.
1. Kontext und Ziel
1.1 Ausgangslage (Initial-Audit-Befund)
Das Initial-Audit (docs/compliance-audit.md, §8.2–8.3) identifiziert folgende Lücken:
- Keine verbindliche Rechteerklärung beim Medienupload
- Keine Abfrage, ob erkennbare Personen enthalten sind
- Keine Abfrage, ob Minderjährige abgebildet sind
- Keine Abfrage, ob erforderliche Einwilligungen abgebildeter Personen vorliegen
- Keine Dokumentation, wer wann welche Erklärung abgegeben hat
1.2 Regulatorische Prüfanker (technische Modellierung)
| Norm | Relevanz für Datenmodell | Juristisch zu prüfen |
|---|---|---|
| § 22 KUG | Bildnisse erkennbarer Personen erfordern Einwilligung vor Verbreitung/Zurschaustellung | Gilt auch für vereinsinterne Sichtbarkeit? |
| Art. 8 DSGVO | Bei Minderjährigen ggf. Einwilligung Erziehungsberechtigter | Ab welchem Alter? Welche Mechanismen? |
| § 19a UrhG | Öffentliche Zugänglichmachung = eigener Nutzungstatbestand | Ab wann gilt official als „öffentlich zugänglich"? |
| DSGVO Art. 5(1)(e) | Datenminimierung — welche Nachweisdaten dürfen gespeichert werden? | Was ist verhältnismäßig? |
1.3 Ziel dieser Spezifikation
P-06 soll sicherstellen, dass:
- Jeder Medien-Upload mit einer strukturierten, gespeicherten Rechteerklärung verknüpft ist
- Die Erklärung nach Sichtbarkeitsstufe gestuft wird (private minimal, official vollständig)
- Bestehende Prüfungen aus P-04 (copyright_notice) komplementär erhalten bleiben
- Juristische Textanpassungen ohne Codeänderungen möglich sind (Versionierung)
- Altmedien ohne rückwirkenden Zwang behandelt werden können
- Backend-Erzwingung (keine reine Frontend-Kosmetik) besteht
2. IST-Analyse
2.1 Upload-Pfade (vollständige Bestandsaufnahme)
| # | Endpoint | Datei | Upload-Typ | Sichtbarkeit wählbar | Copyright bei Upload |
|---|---|---|---|---|---|
| U1 | POST /api/exercises/{id}/media |
routers/exercises.py:2518 |
Einzeldatei oder Embed-URL | Folgt Übungssichtbarkeit (implizit) | Nicht abgefragt |
| U2 | POST /api/media-assets/bulk-upload |
routers/media_assets.py:787 |
1–n Dateien | visibility + club_id als Form-Parameter |
Optional (copyright_notice fehlt im POST-Body, nur via PATCH nachträglich) |
Kein weiterer Upload-Endpoint vorhanden (geprüft über Codebase-Suche nach UploadFile).
Weitere indirekte Upload-Pfade:
POST /api/exercises/{id}/media/from-asset(exercises.py) — verknüpft ein bestehendes Archiv-Asset mit einer Übung; kein Upload, kein neues Medium- Embed-URL (
embed_url,embed_platform) — keine Datei, keine Rechteerklärung für Dateiinhalte; externe Plattform verantwortlich
2.2 Promotionspfade (Sichtbarkeitsänderung)
| # | Endpoint | Datei | Mögliche Promotion |
|---|---|---|---|
| PR1 | PATCH /api/media-assets/{id} |
routers/media_assets.py:1223 |
private→club, private→official, club→official, auch Rückstufung |
| PR2 | POST /api/media-assets/bulk-patch |
routers/media_assets.py:1094 |
Massenpromotion, gleiche Richtungen |
| PR3 | Implizit bei PUT /api/exercises/{id} |
routers/exercises.py |
Übungssichtbarkeit→club/official löst apply_official_exercise_media_rules() oder apply_club_exercise_media_copyright_rules() aus |
Rückstufungen (official→club, club→private) werden nicht gesperrt — juristisch zu prüfen, ob Rückstufung Rechte-Konsequenzen hat.
2.3 Datenmodell media_assets (Migration 045 + 046)
media_assets
├── id SERIAL PK
├── mime_type VARCHAR(100)
├── byte_size INT
├── sha256 CHAR(64) NOT NULL
├── original_filename VARCHAR(300)
├── visibility VARCHAR(32) NOT NULL DEFAULT 'private' ← Sichtbarkeitsstufe
├── club_id INT REFERENCES clubs(id) ← Vereinszuordnung
├── uploaded_by_profile_id INT REFERENCES profiles(id) ← Uploader
├── copyright_notice TEXT ← Urheberrechtshinweis (P-04)
├── storage_backend VARCHAR(32)
├── storage_key TEXT NOT NULL UNIQUE
├── lifecycle_state VARCHAR(32) DEFAULT 'active'
├── trash_soft_at, trash_hidden_at, purge_after_at TIMESTAMP
├── created_at, updated_at TIMESTAMP
└── tags TEXT[] DEFAULT '{}'
Fehlende P-06-Felder: Keine Einwilligungsfelder vorhanden. Keine Personenabbildungsmarkierung. Keine Deklarations-Versionierung.
2.4 Rollen und Berechtigungen (Zusammenfassung _item_permissions())
| Aktion | private | club | official |
|---|---|---|---|
| Upload (neu) | Jeder authentifizierte Nutzer | Vereinsmitglied + club_id | Nur Superadmin |
edit_metadata |
Superadmin, Plattform-Admin, Uploader | Superadmin, Plattform-Admin, Club-Admin | Nur Superadmin |
| Promotion zu club | Eigener Upload: Uploader; Club-Asset: Club-Admin | — | — |
| Promotion zu official | Nur Superadmin | Nur Superadmin | — |
| Lifecycle (trash) | Uploader, Plattform-Admin, Superadmin | Club-Admin, Plattform-Admin, Superadmin | Nur Superadmin |
2.5 Bestehende Frontend-Dialoge
| Stelle | Datei | Aktuelles Verhalten |
|---|---|---|
| Übungsformular Medienupload | ExerciseFormPage.jsx |
Datei-Picker, kein Einwilligungsdialog |
| Archiv Bulk-Upload | MediaLibraryPage.jsx |
Datei-Picker + optional copyright_notice im Editmodal, kein Pflichtdialog |
| Übung → official (API-Error) | ExerciseFormPage.jsx:624 |
window.prompt() für copyright_notice nach 422-Fehler — reaktiv, kein proaktiver Dialog |
| Archiv PATCH Sichtbarkeit | MediaLibraryPage.jsx |
Backend wirft 400 wenn copyright fehlt; Frontend-Feedback unklar |
Ergebnis: Kein proaktiver strukturierter Einwilligungsdialog vorhanden. Alle Copyright-Abfragen sind reaktiv (nach API-Fehler) oder optional.
2.6 Bestehende Copyright-Prüfungen P-04 (Referenz)
P-04 erzwingt copyright_notice bei Promotion zu club oder official:
patch_media_asset(): HTTP 400 wenncopyright_noticeleer bei Ziel club/officialbulk_media_patch(): Asset infailed-Liste wenn copyright fehltapply_official_exercise_media_rules(): HTTP 422OFFICIAL_MEDIA_CONFIRM_REQUIREDwenn Assets kein copyright- Mindestlänge: 3 Zeichen (
_MIN_OFFICIAL_MEDIA_COPYRIGHT_LEN = 3)
Verhältnis zu P-06: P-04 (copyright_notice) = Attribution für Dritte (wer besitzt das Recht). P-06 = Selbsterklärung des Uploaders (habe ich das Recht, dieses Medium hochzuladen). Ergänzend, nicht konkurrierend.
2.7 IST-Lücken (P-06-spezifisch)
| Lücke | Schwere |
|---|---|
| Kein Pflichtfeld „Ich bin Rechteinhaber" beim Upload | Kritisch (Grundlage aller Uploads) |
| Keine Abfrage „erkennbare Personen enthalten?" | Hoch (§ 22 KUG-Risiko bei club/official) |
| Keine Abfrage „Minderjährige enthalten?" | Hoch (Art. 8 DSGVO, besonderer Schutz) |
| Keine Speicherung von Einwilligungszeitpunkt und -version | Hoch (Nachweisbarkeit) |
| Keine Erzwingung im Backend (nur Frontend-Checkbox wäre zu wenig) | Kritisch |
| Kein Einwilligungslog (wer hat wann welche Version bestätigt?) | Hoch |
| copyright_notice beim Erstupload nicht abgefragt | Mittel (P-04 fragt erst bei Promotion) |
2.8 Altbestandsrisiken
- Alle bestehenden
media_assets-Zeilen haben keine Einwilligungsmetadaten - Unbekannt, ob bei bestehenden Medien erkennbare Personen/Minderjährige abgebildet sind
- Medien mit
visibility=clubodervisibility=officialexistieren ohne dokumentierte Einwilligung - Superadmin kann bestehende official-Medien weiter sehen/nutzen ohne Nachdeklaration
- Bei Neuzuweisung zu einer anderen Übung werden bestehende Medien ohne Prüfung verknüpft
3. Entscheidungsmatrix
Anforderungen nach Sichtbarkeitsstufe (Zeilen) × Aktion (Spalten). „Pflicht" = Backend-Sperre wenn fehlend. „Optional" = abfragen aber nicht erzwingen.
| Aktion → | Erstupload | Promotion club | Promotion official | Metadaten-Edit | Reuse in neuer Übung |
|---|---|---|---|---|---|
| private | rights_holder: Pflicht; Personen-Fragen: optional |
— | — | Keine P-06-Pflicht | Keine P-06-Pflicht |
| club | rights_holder: Pflicht; contains_persons: Pflicht; person_consent: Pflicht wenn Personen |
contains_persons + person_consent: Pflicht; contains_minors: Pflicht |
— | Keine P-06-Pflicht | Keine P-06-Pflicht |
| official | Alles Pflicht | Alles Pflicht | Alle Felder Pflicht + copyright_notice (P-04) | Keine P-06-Pflicht | Keine P-06-Pflicht |
B: Medieninhalt — Konsequenzen:
| Inhalt | private | club | official |
|---|---|---|---|
| Keine erkennbaren Personen | person_consent entfällt |
person_consent entfällt |
person_consent entfällt |
| Erkennbare Erwachsene | Optional zu deklarieren | Einwilligung Pflicht (juristisch zu prüfen) | Einwilligung Pflicht |
| Erkennbare Minderjährige | Optional zu deklarieren | Einwilligung Erziehungsberechtigter Pflicht (juristisch zu prüfen) | Einwilligung Pflicht |
| Unklar / nicht beantwortet | Zulässig bei private | Blockiert bei club/official | Blockiert |
C: Rechteinhalt — Konsequenzen:
| Inhalt | Konsequenz |
|---|---|
| Nutzer ist selbst Urheber | rights_holder_confirmed = true genügt |
| Nutzer hat Nutzungsrechte | rights_holder_confirmed = true genügt; copyright_notice sollte Rechteinhaber nennen |
| Drittmaterial enthalten | rights_holder_confirmed = true nur wenn Lizenz vorhanden; copyright_notice Pflicht bei club/official |
| Musik enthalten | contains_music = true; music_rights_confirmed Pflicht (juristisch zu prüfen) |
| Logos/Marken/sonstige Fremdinhalte | Fällt unter rights_holder_confirmed; juristisch zu prüfen |
D: Aktion — Blockierungslogik:
| Aktion | Fehlendes Pflichtfeld | Verhalten Backend |
|---|---|---|
| Upload | rights_holder_confirmed fehlt | HTTP 400 RIGHTS_DECLARATION_REQUIRED |
| Promotion club | contains_persons / person_consent fehlt | HTTP 400 CONSENT_REQUIRED_FOR_CLUB |
| Promotion official | Beliebiges Pflichtfeld fehlt | HTTP 400 CONSENT_REQUIRED_FOR_OFFICIAL |
| Promotion mit Altmedium (legacy) | rights_status = legacy_unreviewed | HTTP 400 LEGACY_REDECLARATION_REQUIRED |
4. Empfohlenes Zielmodell
4.1 Neue Tabelle: media_asset_rights_declarations
Append-only Audit-Log. Jede Erklärung (Upload, Promotion, Nachdeklaration) erzeugt einen neuen Eintrag. Bestehende Einträge werden nie geändert.
CREATE TABLE media_asset_rights_declarations (
id SERIAL PRIMARY KEY,
media_asset_id INT NOT NULL REFERENCES media_assets(id) ON DELETE CASCADE,
declared_by_profile_id INT REFERENCES profiles(id) ON DELETE SET NULL,
declared_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
-- Kontext
action_type VARCHAR(50) NOT NULL
CHECK (action_type IN (
'upload', -- Erstupload
'promote_club', -- Promotion zu club
'promote_official', -- Promotion zu official
're_declaration', -- Nachdeklaration (auf Aufforderung)
'legacy_re_declaration' -- Altmedium: erste Deklaration nachgereicht
)),
target_visibility VARCHAR(32) NOT NULL, -- Sichtbarkeit für die erklärt wird
declaration_version VARCHAR(20) NOT NULL DEFAULT 'p06-v1.0', -- Textversion der Erklärung
-- Pflichtfeld (alle Sichtbarkeiten)
rights_holder_confirmed BOOLEAN NOT NULL,
-- Personenrechte (Pflicht ab club)
contains_identifiable_persons BOOLEAN,
person_consent_confirmed BOOLEAN, -- Pflicht wenn contains_identifiable_persons = true
contains_minors BOOLEAN,
parental_consent_confirmed BOOLEAN, -- Pflicht wenn contains_minors = true (juristisch zu prüfen)
-- Drittmaterial (optional MVP, Pflicht später)
contains_music BOOLEAN,
music_rights_confirmed BOOLEAN,
third_party_content_confirmed BOOLEAN,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_mar_declarations_asset ON media_asset_rights_declarations (media_asset_id);
CREATE INDEX idx_mar_declarations_profile ON media_asset_rights_declarations (declared_by_profile_id);
4.2 Neue Felder in media_assets
Drei neue Schnellzugriffs-Felder (kein Ersatz für den Log, nur für performante Abfragen):
ALTER TABLE media_assets
ADD COLUMN rights_status VARCHAR(32)
NOT NULL DEFAULT 'legacy_unreviewed'
CHECK (rights_status IN ('pending', 'declared', 'legacy_unreviewed', 'blocked')),
ADD COLUMN rights_declared_for_visibility VARCHAR(32), -- Höchste Stufe, für die erklärt wurde
ADD COLUMN rights_declared_at TIMESTAMP WITH TIME ZONE; -- Zeitpunkt der aktuellsten Erklärung
Status-Semantik:
| rights_status | Bedeutung |
|---|---|
legacy_unreviewed |
Bestehendes Medium ohne P-06-Daten — Altbestand |
pending |
Neues Medium, Upload noch ohne Deklaration (Zwischenzustand, darf nie persistent sein) |
declared |
Gültige Deklaration vorhanden für rights_declared_for_visibility |
blocked |
Deklaration widerrufen oder durch Admin gesperrt (→ P-11/P-13 Schnittstelle) |
Visibility-Hierarchie für Prüfung:
private (1) < club (2) < official (3)
Promotion ist erlaubt wenn: rights_declared_for_visibility ≥ Ziel-Visibility. Sonst ist neue Deklaration erforderlich.
4.3 Feld-Bewertung: MVP vs. später
| Feld | MVP-Pflicht | Sinnvoll später | Unnötig / zu früh | Juristisch abhängig |
|---|---|---|---|---|
rights_holder_confirmed |
✅ | — | — | Nein |
contains_identifiable_persons |
✅ ab club | — | — | Nein |
person_consent_confirmed |
✅ wenn Personen + ≥ club | — | — | Teilweise |
contains_minors |
✅ ab official | ✅ auch club | — | Ja (Schwelle) |
parental_consent_confirmed |
— | ✅ | — | Ja (juristisch zu klären) |
contains_music |
— | ✅ | — | Ja |
music_rights_confirmed |
— | ✅ | — | Ja |
third_party_content_confirmed |
— | ✅ | — | Teilweise |
declaration_version |
✅ | — | — | Nein |
action_type |
✅ | — | — | Nein |
rights_status in media_assets |
✅ | — | — | Nein |
rights_declared_for_visibility |
✅ | — | — | Nein |
| Separates Upload von Einwilligungsdokumenten | — | — | Zu früh | Ja |
may_be_embedded_in_exercises |
— | — | Unnötig (exercise_media-Tabelle reicht) | — |
declaration_scope_* als einzelne Booleans |
— | — | Unnötig (visibility-String reicht) | — |
4.4 Designentscheidungen (mit Begründung)
Entscheidung 1: Gestufte Erklärungen je Sichtbarkeitsstufe
Nicht eine universale Erklärung für alle Stufen, sondern Promotion auf höhere Stufe erfordert neue Erklärung.
Begründung: Rechtliche Anforderungen steigen mit Sichtbarkeit. Private Medien: nur Eigentümer sieht sie. Official-Medien: plattformweit sichtbar (ggf. öffentlich). Stufenmodell ist rechtsanschlussfähig — spätere juristische Textanpassungen pro Stufe ohne Systemwechsel möglich.
Entscheidung 2: Minimalset beim Erstupload
Pflicht beim privaten Upload: nur rights_holder_confirmed. Personen-Fragen: optional beim Upload, Pflicht erst bei Promotion zu club/official.
Begründung: Die meisten Uploads bleiben privat und werden nie promoted. Volle Fragebogenbelastung beim Upload würde Nutzung hemmen ohne rechtlichen Mehrwert. Personen-Fragen werden erzwungen sobald der Upload für andere sichtbar wird.
Entscheidung 3: Keine globale Nutzer-Einwilligung (pro Upload)
Erklärung wird pro Upload abgegeben, nicht einmalig pro Nutzer.
Begründung: Jedes Medium ist inhaltlich unterschiedlich. Eine pauschale Einwilligung beim Registrieren oder einmalig je Nutzer deckt nicht ab, ob bei diesem konkreten Video Minderjährige abgebildet sind.
Entscheidung 4: Append-only Audit-Log
Einmal abgegebene Erklärungen werden nie geändert oder gelöscht. Neue Erklärung = neuer Eintrag.
Begründung: Nachweisbarkeit. Bei späterem Streit muss belegbar sein, was wann erklärt wurde.
Entscheidung 5: Versionierung via declaration_version-String
Wenn Rechtsanwalt Erklärungstexte ändert, wird die neue Version als "p06-v1.1" deklariert. Keine Datenbank-FK auf eine Textversion-Tabelle (zu komplex für MVP).
Begründung: Einfach nachvollziehbar. Ob bei Versionswechsel alle Altdeklarationen erneuert werden müssen, ist juristisch zu entscheiden — technisch ermöglicht das System beides.
Entscheidung 6: copyright_notice bleibt separat (P-04 unberührt)
P-06 führt keine copyright_notice-Redundanz ein. copyright_notice (P-04) = Attribution. rights_holder_confirmed (P-06) = Berechtigung. Beide sind Pflicht bei official.
5. Ziel-Flows
Flow 1: Erstupload eines privaten Mediums (Übung oder Archiv)
Frontend:
- Nutzer öffnet Upload-Dialog (Exercise oder Archiv)
- Dateiauswahl
- P-06-Dialog erscheint vor Upload-Button-Aktivierung:
- ☑ „Ich bin der Rechteinhaber oder besitze die erforderlichen Nutzungsrechte an diesem Medium." [Pflicht]
- ☐ „Das Medium enthält erkennbare Personen." [optional]
- → wenn ja: ☑ „Alle abgebildeten Personen haben der Nutzung zugestimmt." [optional bei private, Pflicht bei Promotion]
- ☐ „Das Medium enthält Minderjährige." [optional]
- Upload-Button aktiv erst wenn Pflicht-Checkbox gesetzt
Backend:
- Empfängt neue Felder:
rights_holder_confirmed, optionalcontains_identifiable_persons,person_consent_confirmed,contains_minors - Prüft:
rights_holder_confirmed == true— sonst HTTP 400RIGHTS_DECLARATION_REQUIRED - INSERT in
media_assetsmitrights_status = 'declared',rights_declared_for_visibility = 'private',rights_declared_at = NOW() - INSERT in
media_asset_rights_declarationsmitaction_type = 'upload',declaration_version = 'p06-v1.0', alle Felder
Fehlermeldungen:
RIGHTS_DECLARATION_REQUIRED: "Bitte bestätige, dass du die erforderlichen Rechte an diesem Medium besitzt."
Tests:
- Upload ohne
rights_holder_confirmed→ 400 - Upload mit
rights_holder_confirmed=true→ 201,rights_status='declared'in DB - Declaration-Log-Eintrag vorhanden mit korrektem
action_type='upload'
Offene juristische Fragen: Reicht Selbsterklärung oder muss der Betreiber den Upload ansonsten ablehnen? (→ §7.1)
Flow 2: Erstupload direkt als club-Medium (Archiv-Bulk-Upload)
Frontend:
- Nutzer wählt
visibility = clubim Bulk-Upload-Dialog - P-06-Dialog erweitert (zusätzlich zur privaten Pflicht-Checkbox):
- ☑ „Das Medium enthält erkennbare Personen." [Antwort Pflicht bei club]
- → wenn ja: ☑ „Alle abgebildeten Personen haben der vereinsinternen Nutzung zugestimmt." [Pflicht]
- ☑ „Das Medium enthält Minderjährige." [Antwort Pflicht]
- → wenn ja: ☑ „Einwilligung der Erziehungsberechtigten liegt vor." [Pflicht, juristisch zu prüfen]
Backend:
- Prüft alle Pflichtfelder für club:
rights_holder_confirmed,contains_identifiable_persons(must be answered),person_consent_confirmed(wenn contains_persons=true) rights_declared_for_visibility = 'club'- Eintrag in
media_asset_rights_declarationsmitaction_type = 'upload',target_visibility = 'club'
Flow 3: Bulk-Upload durch Admin (Plattform-Admin / Superadmin)
Besonderheit: Admin lädt oft viele Dateien auf einmal. Dialog-Design muss batch-fähig sein.
Empfehlung: Eine Einwilligungserklärung für den gesamten Batch (nicht je Datei). Alle Dateien des Batches erhalten den gleichen Declarations-Record, jedoch referenziert je media_asset_id.
Frontend:
- Vor Upload: Batch-Deklaration (gilt für alle Dateien des Batches)
- Alternativ: Je Datei separate Deklaration (aufwändiger aber präziser) — juristisch zu prüfen welche Variante ausreichend ist
Backend:
action_type = 'upload'für alle Dateien des Batches- Wenn Batch-Deklaration: eine Deklarations-Transaktion, n Einträge in Log (je asset_id)
Offene juristische Fragen: Genügt eine Sammelbestätigung für Batches? (→ §7.6)
Flow 4: Promotion private → club
Frontend:
- Nutzer ändert Sichtbarkeit eines Mediums zu
club(im Archiv oder via Übungssichtbarkeit) - Frontend erkennt Sichtbarkeitserhöhung
- P-06-Promotions-Dialog:
- ☑ „Das Medium enthält erkennbare Personen." [Pflicht — Antwort erforderlich]
- → wenn ja: ☑ „Alle abgebildeten Personen haben der vereinsinternen Nutzung zugestimmt." [Pflicht]
- ☑ „Das Medium enthält Minderjährige." [Pflicht — Antwort erforderlich]
- → wenn ja: ☑ „Einwilligung der Erziehungsberechtigten liegt vor." [Pflicht, juristisch zu prüfen]
- Bestehende copyright_notice-Abfrage (P-04) bleibt erhalten — läuft parallel oder im gleichen Dialog
Backend:
- PATCH
/api/media-assets/{id}empfängt:visibility='club', P-06-Felder,copyright_notice - Prüft: rights_status='declared' AND rights_declared_for_visibility ≥ 'club' — wenn ja, keine neue Deklaration nötig (z. B. bereits als club hochgeladen)
- Wenn nicht: neue Pflichtfelder prüfen, INSERT in Declarations-Log mit
action_type='promote_club' - Bestehende P-04-Prüfung: copyright_notice weiterhin Pflicht
rights_declared_for_visibilityin media_assets auf 'club' setzen
Backend-Fehler:
CONSENT_REQUIRED_FOR_CLUB: Personenfragen nicht beantwortetLEGACY_REDECLARATION_REQUIRED: Altmedium, muss Nachdeklaration abgebenRIGHTS_DECLARATION_REQUIRED(P-04): copyright_notice fehlt (bestehend)
Flow 5: Promotion private/club → official
Frontend:
- Nur Superadmin kann zu official promoten
- Dialog zeigt vollständige Erklärung:
- Alle Felder aus Flow 4 (Pflicht)
- ☑ zusätzlich: „Das Medium enthält Musik oder sonstige Fremdinhalte." [Pflicht — Antwort erforderlich]
- → wenn ja: ☑ „Ich besitze die erforderlichen Lizenzen für die öffentliche Nutzung." [Pflicht]
- copyright_notice (P-04) weiterhin Pflicht (bestehende Logik)
Backend:
- Prüft alle Felder + copyright_notice
action_type = 'promote_official',target_visibility = 'official'rights_declared_for_visibility = 'official'
Offene juristische Fragen: Reicht Selbstdeklaration oder muss Superadmin bei official höhere Sorgfalt nachweisen? (→ §7.3)
Flow 6: Nachbearbeitung von Metadaten (ohne Sichtbarkeitsänderung)
Szenario: Nutzer ändert nur copyright_notice, original_filename, tags — keine Sichtbarkeitsänderung.
P-06-Anforderung: Keine neue Deklaration erforderlich (Metadaten-Edit ist kein Promotions-Schritt).
Ausnahme: Wenn rights_status = 'blocked' (durch P-11/P-13 gesetzt) → Metadaten-Edit erlaubt, aber Sichtbarkeitsänderungen bleiben gesperrt.
Flow 7: Verwendung bestehender Medien in neuer Übung (from-asset)
Szenario: Trainer verknüpft ein bereits im Archiv liegendes Medium mit einer neuen Übung über POST /api/exercises/{id}/media/from-asset.
P-06-Anforderung: Keine neue Deklaration erforderlich. Die Deklaration gilt für das Medium selbst, nicht für die Verknüpfung. Voraussetzung: rights_status des Assets ist 'declared' für die Sichtbarkeit der Übung.
Backend-Prüfung (neu):
- Asset-Sichtbarkeit ≥ Übungs-Sichtbarkeit? Bestehende Prüfung.
rights_declared_for_visibility≥ Übungs-Sichtbarkeit? → Neue Prüfung durch P-06- Wenn nicht: HTTP 400
RIGHTS_DECLARATION_REQUIRED_FOR_TARGET_VISIBILITY
Flow 8: Behandlung von Altmedien ohne P-06-Metadaten
Strategie: Soft-Block bei Promotion, kein Rückwirkungs-Zwang für private Altmedien
| Situation | Verhalten |
|---|---|
| Altmedium private → weiterhin privat | Unverändert zugänglich; keine Zwangs-Nachdeklaration |
| Altmedium privat → Anzeige in Übung (private) | Unverändert; keine neue Deklaration |
| Altmedium privat → Promotion zu club | Blocked: LEGACY_REDECLARATION_REQUIRED; Nutzer muss Nachdeklaration abgeben |
| Altmedium club → Promotion zu official | Blocked; Superadmin muss Nachdeklaration abgeben |
Altmedium mit rights_status = 'legacy_unreviewed' |
Einsehbar, nicht promotable |
Nachdeklarations-Flow:
- Nutzer versucht Promotion eines Altmediums
- Backend gibt HTTP 400
LEGACY_REDECLARATION_REQUIREDzurück - Frontend zeigt Hinweis und Deklarations-Dialog (analog zu neuem Upload-Dialog)
- Nutzer füllt Deklaration aus
- PATCH mit
legacy_re_declaration=true+ alle Pflichtfelder +visibility - Backend: INSERT in Declarations-Log mit
action_type='legacy_re_declaration', aktualisiertrights_status,rights_declared_for_visibility
Migrationsstrategie für bestehende Daten:
- Alle bestehenden
media_assets-Zeilen bleiben mitrights_status = 'legacy_unreviewed'(Default in Migration) - Keine rückwirkende Sperrung
- Bestehende club/official-Medien:
rights_status = 'legacy_unreviewed'— die historische Sichtbarkeit bleibt erhalten, spätere Änderungen erfordern aber Nachdeklaration
Juristisch zu prüfen: Muss der Betreiber aktiv alle Altmedien auf club/official sperren bis zur Nachdeklaration? (→ §7.8)
Flow 9: Widerruf / nachträglich fehlende Rechte erkannt
Szenario: Abgebildete Person widerruft Einwilligung oder Uploader erkennt, dass er keine Rechte hatte.
P-06 implementiert keinen Widerrufsmechanismus direkt. Anschluss an spätere Pakete:
- P-11 (Legal-Hold): Superadmin kann
rights_status = 'blocked'setzen → Medium sofort aus allen öffentlichen Abfragen entfernt - P-13 (Content-Melde-Backend): Dritte können Rechtsverletzung melden → Moderationsqueue → Superadmin entscheidet über Sperrung
P-06-Schnittstelle: Das Feld rights_status = 'blocked' in media_assets ist die technische Brücke zu P-11 und P-13.
Empfehlung: Declaration-Log-Tabelle hat ON DELETE CASCADE auf media_assets.id — wenn ein Medium purged wird, werden auch alle Deklarationseinträge entfernt. Juristisch zu prüfen, ob Deklarationslog nach Löschung aufbewahrt werden muss (Rechenschaftspflicht Art. 5 Abs. 2 DSGVO).
Flow 10: Zusammenspiel mit späterem P-11 und P-13
| P-06-Element | P-11-Anschluss | P-13-Anschluss |
|---|---|---|
rights_status = 'blocked' |
P-11 setzt diesen Status (Legal-Hold) | P-13-Moderator triggert P-11-Sperre |
| Declaration-Log | Zeigt, welche Version bei Sperrung galt | Kontext für Moderationsentscheidung |
contains_identifiable_persons |
Relevant für Löschbegründung (KUG) | Relevanzmerkmal für Meldekategorie |
contains_minors |
Höchste Priorität bei P-11-Sofortsperrung | CSAM-Eskalationspfad in P-13 |
P-06 darf nicht im Widerspruch zu den späteren Paketen implementiert werden. Der rights_status-Enum muss 'blocked' bereits in P-06a (Migration) enthalten.
6. Legacy- und Migrationskonzept
6.1 Fragen und Antworten
| Frage | Empfehlung | Juristisch zu prüfen |
|---|---|---|
| Dürfen Altmedien sichtbar bleiben? | Ja — keine rückwirkende Sperrung | Ja — insb. club/official ohne Einwilligung |
| Dürfen Altmedien in neuen Übungen verwendet werden? | Ja, wenn Sichtbarkeit kompatibel | Ja — falls keine Rechte vorhanden |
| Dürfen Altmedien zu club promoted werden? | Nein — Nachdeklaration erforderlich | Ja — ob Selbstdeklaration genügt |
| Dürfen Altmedien zu official promoted werden? | Nein — vollständige Nachdeklaration | Ja — höhere Anforderungen |
| Muss bei erster Bearbeitung Nachdeklaration erzwungen werden? | Nein (nur bei Promotion) | Ja — Betreiber-Ermessen |
6.2 Migration-Schritte
- Migration (P-06a): Neue Spalten in
media_assetsmitDEFAULT 'legacy_unreviewed'→ alle bestehenden Zeilen erhalten automatisch Statuslegacy_unreviewed - Neue Uploads nach P-06: Code setzt
rights_status = 'declared'nach erfolgreicher Deklaration - Altmedien-Promotion: Backend blockiert mit
LEGACY_REDECLARATION_REQUIRED; Nutzer muss Nachdeklaration abgeben - Keine automatische Batch-Re-Deklaration durch Betreiber (wäre fachlich falsch — Betreiber kann nicht für Uploader erklären)
6.3 Empfohlene Übergangsstrategie (Minimales Risiko)
private Altmedien: weiter sichtbar und nutzbar | Promotion blockiert
club Altmedien: weiter sichtbar | Sichtbarkeitsänderung blockiert
official Altmedien: weiter sichtbar | Sichtbarkeitsänderung blockiert
Begründung: Vollständige Sperrung aller Altmedien würde Betrieb lahmlegen. Die Blockierung bei Promotion schützt vor Eskalation ohne existierende Nutzung zu zerstören. Juristisch bleibt das Risiko bei bereits exponierten Medien — das ist ein organisatorisches Problem, kein technisches.
7. Juristische Klärungsliste
Alle folgenden Punkte müssen durch einen Rechtsanwalt oder Datenschutzbeauftragten bewertet werden. Keine der folgenden Einschätzungen ist rechtlich bindend.
| # | Frage | Technische Relevanz | Dringlichkeit |
|---|---|---|---|
| 7.1 | Welche Erklärung ist für private Medien (nur Uploader sieht sie) erforderlich? Reicht rights_holder_confirmed oder ist auch ohne Sichtbarkeit Dritter eine Personeneinwilligung nötig? |
Ob Personen-Fragen bei private Pflicht werden | Vor MVP |
| 7.2 | Welche Erklärung ist für club-interne Sichtbarkeit (Vereinsmitglieder) erforderlich? Gilt § 22 KUG für vereinsintern? Reicht Selbsterklärung des Uploaders? | Pflichtfelder bei Promotion zu club | Vor MVP |
| 7.3 | Welche Erklärung ist für official (plattformweit, ggf. öffentlich) erforderlich? Reicht Selbsterklärung oder muss Einwilligung nachgewiesen werden? | Pflichtfelder bei Promotion zu official | Vor MVP |
| 7.4 | Wie ist mit erkennbaren Minderjährigen zu verfahren? Ab welchem Alter benötigen Minderjährige elterliche Einwilligung? Welche Einwilligungsform ist rechtssicher? | contains_minors + parental_consent_confirmed — Pflicht ab welcher Stufe? |
Vor MVP |
| 7.5 | Reicht eine Selbsterklärung des Uploaders oder müssen Einwilligungs-Dokumente (Scan, Upload) archiviert werden? | Dateiupload für Einwilligungs-Scan nötig? (MVP oder später?) | Vor MVP |
| 7.6 | Ist eine Batch-Deklaration (eine Erklärung für mehrere Dateien des Uploads) rechtlich ausreichend? | Flow 3: Bulk-Upload-Design | Vor MVP |
| 7.7 | Muss die Textfassung der Erklärungen (Checkbox-Labels) durch Rechtsanwalt freigegeben werden? Welche konkreten Formulierungen sind erforderlich? | declaration_version Textbasis |
Vor MVP |
| 7.8 | Wie sind Altmedien zu behandeln, die bereits mit club/official-Sichtbarkeit in der DB stehen? Muss der Betreiber diese sperren bis zur Nachdeklaration? | Migrationsstrategie §6.3 | Zeitnah |
| 7.9 | Wie ist bei Widerruf einer Einwilligung vorzugehen? Welche Fristen gelten? Muss das Medium sofort gelöscht oder nur gesperrt werden? | rights_status='blocked', Schnittstelle P-11 | Vor P-11 |
| 7.10 | Welche Nachweisdaten dürfen/sollen gespeichert werden (Datensparsamkeit vs. Rechenschaftspflicht)? Wie lange muss der Declaration-Log aufbewahrt werden? | Retention-Policy für media_asset_rights_declarations |
Vor MVP |
| 7.11 | Welche Anforderungen gelten für Trainingsvideos mit mehreren Personen? Muss jede Person einzeln einwilligen oder reicht eine kollektive Erklärung? | person_consent_confirmed als Boolean vs. Mehrfach-Einwilligung |
Vor MVP |
| 7.12 | Welche Anforderungen gelten für Musik, Logos, Marken, Grafiken von Dritten im Video/Bild? Ab wann ist eine separate Lizenz nötig? Reicht music_rights_confirmed als Selbsterklärung? |
contains_music, music_rights_confirmed — MVP oder Pflicht? |
Mittel |
8. Umsetzungsplan (für spätere Codephase — keine Umsetzungsfreigabe)
P-06a – Datenmodell / Migration
| Feld | Wert |
|---|---|
| Ziel | Neue Tabelle media_asset_rights_declarations anlegen; drei neue Spalten in media_assets |
| Betroffene Dateien | backend/migrations/048_media_rights_declarations.sql (neu) |
| Migrationsbedarf | Neue Migration; DEFAULT 'legacy_unreviewed' automatisch für bestehende Zeilen |
| Abhängigkeiten | Keine (neue Tabelle) |
| Testbedarf | Migration idempotent; bestehende media_assets-Zeilen haben rights_status='legacy_unreviewed' nach Migration; neue Zeilen haben rights_status='declared' nach P-06b |
| Akzeptanzkriterien | Tabelle angelegt, alle Spalten korrekt typisiert, Indizes vorhanden, ALTER-Migration ohne Downtime anwendbar |
| Risiko | Niedrig (neue Tabelle + ALTER mit DEFAULT ohne Table-Lock in PostgreSQL 16) |
| Rollback | DROP TABLE media_asset_rights_declarations; ALTER TABLE media_assets DROP COLUMN rights_status, rights_declared_for_visibility, rights_declared_at |
P-06b – Backend-Erzwingung
| Feld | Wert |
|---|---|
| Ziel | Backend blockiert Upload und Promotion wenn Pflichtfelder fehlen; schreibt Declarations-Log |
| Betroffene Dateien | backend/routers/media_assets.py (bulk-upload + patch + bulk-patch), backend/routers/exercises.py (upload_exercise_media, from-asset), neues Modul backend/media_rights.py (Hilfslogik) |
| Neue Pydantic-Models | RightsDeclaration (Pflichtfelder + optionale Felder); Integration in MediaAssetPatch + Upload-Endpoints |
| Neue Fehlercodes | RIGHTS_DECLARATION_REQUIRED, CONSENT_REQUIRED_FOR_CLUB, CONSENT_REQUIRED_FOR_OFFICIAL, LEGACY_REDECLARATION_REQUIRED, RIGHTS_DECLARATION_REQUIRED_FOR_TARGET_VISIBILITY |
| Abhängigkeiten | P-06a (Migration) muss abgeschlossen sein |
| Testbedarf | Unit-Tests für jeden neuen Fehlercode; Integrationstests Upload → Deklarationslog; Promotion ohne/mit Deklaration; Legacy-Block |
| Akzeptanzkriterien | Upload ohne rights_holder_confirmed → 400; promotion ohne Personen-Deklaration → 400; gültige Deklaration → Eintrag in DB vorhanden; bestehender P-04-Test weiterhin grün |
| Risiko | Mittel (Breaking Change für alle Upload-Clients); Feature-Flag zum schrittweisen Rollout empfohlen |
| Rollback | Feature-Flag deaktivieren; kein DB-Rollback nötig |
P-06c – Frontend-Dialoge
| Feld | Wert |
|---|---|
| Ziel | Einwilligungsdialog in allen Upload-Pfaden; Promotions-Dialog bei Sichtbarkeitsänderung |
| Betroffene Dateien | frontend/src/components/RightsDeclarationDialog.jsx (neu, wiederverwendbar), frontend/src/pages/ExerciseFormPage.jsx, frontend/src/pages/MediaLibraryPage.jsx, frontend/src/utils/api.js |
| Dialog-Typen | Upload-Dialog (privat/club/official je nach Kontext), Promotions-Dialog (erkennt Sichtbarkeitserhöhung), Nachdeklarations-Dialog (für Legacy) |
| Abhängigkeiten | P-06b (Backend-Codes müssen definiert sein); juristische Textfreigabe für Checkbox-Labels |
| Testbedarf | Playwright E2E: Dialog erscheint; Upload ohne Checkbox → deaktivierter Button; Dialog mit allem ausgefüllt → erfolgreicher Upload; Backend-Fehler → korrekte Fehlermeldung |
| Akzeptanzkriterien | Dialog erscheint bei allen Upload-Pfaden; Checkbox-State korrekt; Labels entsprechen juristisch geprüften Formulierungen; Promotions-Dialog erkennt Sichtbarkeitserhöhung |
| Risiko | Mittel (UX-Änderung an häufig genutzten Pfaden) |
| Rollback | Feature-Flag; Dialoge können ohne Backend-Änderung deaktiviert werden |
P-06d – Tests / Dokumentation
| Feld | Wert |
|---|---|
| Ziel | Vollständige Testabdeckung für P-06 + Doku-Update |
| Betroffene Dateien | backend/tests/test_media_rights_declaration.py (neu), tests/dev-smoke-test.spec.js (neue P-06-Tests), docs/compliance-implementation.md, docs/compliance-package-register.md, Access-Layer-Audit aktualisieren |
| Backend-Tests | Upload-Flows, Promotions-Flows, Legacy-Block, Declaration-Log, alle Fehlercodes |
| Playwright-Tests | Dialog erscheint, Checkbox-Validierung, vollständiger Upload-Flow, Promotions-Dialog |
| Abhängigkeiten | P-06a, P-06b, P-06c abgeschlossen |
| Akzeptanzkriterien | Alle neuen Tests grün; bestehende Tests unverändert grün; ACCESS_LAYER_STRICT=1 grün |
| Risiko | Niedrig |
P-06e – Legacy-Nacharbeit (optional, nach juristischer Klärung)
| Feld | Wert |
|---|---|
| Ziel | Massenprüfung und ggf. Sperrung bestehender club/official-Medien ohne Deklaration, falls juristisch notwendig |
| Betroffene Dateien | backend/scripts/media_rights_audit.py (neu), evtl. Admin-UI |
| Inhalt | Script listet alle visibility IN ('club', 'official') mit rights_status='legacy_unreviewed'; Superadmin kann Massenmarkierung oder individuelle Überprüfung anstoßen |
| Abhängigkeiten | P-06a–d; juristische Klärung §7.8 |
| Akzeptanzkriterien | Script läuft ohne Fehler; erzeugt CSV-Report mit betroffenen Assets |
| Risiko | Mittel (wenn Sperrung aktiv: Betriebsunterbrechung für Vereinsmedien) |
| Hinweis | Erst nach juristischer Entscheidung über Altbestand-Behandlung umsetzen |
9. Abschlussbewertung
9.1 Neue / geänderte Dokumente
| Dokument | Änderung |
|---|---|
docs/p06-upload-rights-spec.md |
Neu erstellt (dieses Dokument) |
docs/compliance-roadmap.md |
P-06: Spezifikation erstellt vermerkt; nächste Freigabe angepasst |
docs/compliance-implementation.md |
Kurzer P-06-Eintrag: Spezifikation erstellt, keine Umsetzung |
docs/compliance-package-register.md |
P-06 Letzter Stand: Spezifikation vorhanden |
9.2 Empfohlene P-06-Zielarchitektur (Kurzfassung)
- Append-only Log-Tabelle
media_asset_rights_declarations(Wer, Wann, Was, Welche Version) - Drei Status-Felder in
media_assets:rights_status/rights_declared_for_visibility/rights_declared_at - Gestufte Erklärungen: Upload = Minimalset; Promotion club = Personen-Pflicht; Promotion official = vollständig
- Backend-Erzwingung über neue Fehlercodes; keine reine Frontend-Checkbox
- Versionierung über
declaration_version-String; kein FK auf Texttabelle - Legacy:
rights_status = 'legacy_unreviewed'; Promotion blockiert; Nachdeklarations-Flow
9.3 Kritische Designentscheidungen
| Entscheidung | Begründung |
|---|---|
| Gestufte Erklärungen je Sichtbarkeitsstufe | Rechtsrisiko steigt mit Sichtbarkeit; Rechtsanschlussfähigkeit |
| Minimalset beim Erstupload | Nutzbarkeit vs. Compliance; Pflicht-Erweiterung bei Promotion |
| Append-only Log (nie löschen/ändern) | Nachweisbarkeit; Audit-Integrität |
| rights_status = 'legacy_unreviewed' per Default | Keine rückwirkende Sperrung; kontrollierbarer Übergang |
| Kein Einwilligungs-Datei-Upload (MVP) | Aufwand vs. Mehrwert; spätere Nachrüstung möglich |
rights_status = 'blocked' als P-11-Schnittstelle |
Zukunftssicherheit; P-11/P-13 können sofort anschließen |
9.4 Offene juristische Fragen (Priorisiert)
| Priorität | Frage | Paket-Impact |
|---|---|---|
| Vor MVP | §7.7 Textfassung der Erklärungen | P-06c (Dialog-Labels) |
| Vor MVP | §7.1 Private: Reicht rights_holder allein? | Pflichtfeld-Definition |
| Vor MVP | §7.2 Club: § 22 KUG vereinsintern? | contains_persons bei club Pflicht? |
| Vor MVP | §7.4 Minderjährige: Schwelle und Form | parental_consent MVP oder später |
| Vor MVP | §7.5 Selbsterklärung oder Dokumenten-Upload? | Scope P-06c |
| Zeitnah | §7.8 Altmedien club/official: Sperrpflicht? | P-06e Scope |
| Vor P-11 | §7.9 Widerruf: Fristen und Mechanismus | P-11-Design |
| Mittel | §7.10 Aufbewahrung Declaration-Log | Retention-Policy |
9.5 Empfohlene spätere Umsetzungsschritte
- Rechtsanwalt beauftragt für §7.7 (Texte) und §7.1–7.3 (Anforderungen je Stufe)
- Nach Klärung §7.7: Freigabe P-06a + P-06b parallel (kein Frontend-Merge nötig)
- Nach §7.7 Textfreigabe: Freigabe P-06c (Frontend-Dialoge)
- P-06d: Tests + Doku beim gleichen Merge wie P-06b/P-06c
- Nach §7.8-Klärung: ggf. P-06e (Legacy-Massenprüfung)
9.6 Implementierungsbereitschaft
| Kriterium | Einschätzung |
|---|---|
| P-06 implementierungsreif | Teilweise — Datenmodell und Backend-Logik spezifizierbar; Dialog-Labels nicht ohne juristische Textfreigabe |
| Juristische Vorabklärung erforderlich | Ja — §7.7 (Textfassung) blockiert P-06c; §7.1–7.3 bestimmen Pflichtfelder |
| P-06a (Migration) vorab umsetzbar | Ja — unabhängig von juristischen Texten |
| 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
| Prüfung | Ergebnis |
|---|---|
| Codeänderungen vorgenommen? | Nein |
| Neue Migrationen erstellt? | Nein |
| Neue Endpoints erstellt? | Nein |
| 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 fachlich-technisch spezifiziert. Keine Codeänderungen vorgenommen.
Erstellt: 2026-05-10 | Autor: Claude Code | Kein Rechtsanwalt; alle rechtlichen Einschätzungen sind juristisch zu prüfen.