shinkan-jinkendo/docs/p06-upload-rights-spec.md
Lars 34235ef46d
Some checks failed
Deploy Development / deploy (push) Successful in 39s
Test Suite / pytest-backend (push) Successful in 34s
Test Suite / lint-backend (push) Successful in 1s
Test Suite / build-frontend (push) Successful in 11s
Test Suite / playwright-tests (push) Failing after 1m23s
feat(compliance): P-06 Upload-Einwilligungsdialog v1-conservative
Implementiert server-seitige Rechteerklärungspflicht für alle Medien-Uploads
und Sichtbarkeits-Promotions (konservative Erstannahme: alle Uploads).

Backend:
- backend/media_rights.py (NEU): Kernmodul — validate_rights_declaration,
  check_rights_coverage, assert_rights_for_promotion, assert_rights_for_exercise_link,
  write_rights_declaration, update_rights_quick_fields
- backend/migrations/048_media_rights_declarations.sql (NEU): Tabelle
  media_asset_rights_declarations (Append-only Audit-Log), Felder
  rights_status/rights_visibility_level in media_assets
- backend/routers/media_assets.py: P-06-Pflichtprüfung in PATCH (single + bulk),
  POST /api/media-assets/{id}/rights-declarations (Re-Deklaration),
  GET /api/admin/media-rights/legacy-summary|legacy-assets (Admin-Endpoints)
- backend/routers/exercises.py: P-06-Felder in upload_exercise_media,
  assert_rights_for_exercise_link in attach_exercise_media_from_asset
- backend/main.py: admin_rights_router registriert

Frontend:
- frontend/src/components/RightsDeclarationDialog.jsx (NEU): 9-Felder-Dialog
  (konservativ: immer alle Fragen), Client-Validierung, VORLÄUFIG-Hinweis
- frontend/src/pages/MediaLibraryPage.jsx: Dialog-Intercept vor Upload,
  Altbestand-Indikator (legacy_unreviewed)
- frontend/src/utils/api.js: P-06-Felder in bulkUploadMediaAssets weitergeleitet

Tests:
- backend/tests/test_media_rights_declaration.py (NEU): 28 Unit-/Integrationstests
- backend/tests/test_media_assets_archive.py: P-06 fetchone-Slots + Mock ergänzt
- backend/tests/test_media_assets_copyright_promotion.py: check_rights_coverage gemockt
- tests/dev-smoke-test.spec.js: 5 P-06 E2E-Tests ergänzt

Dokumentation:
- docs/compliance-implementation.md: P-06-Abschnitt
- docs/compliance-package-register.md: Status ⚠️ teilweise umgesetzt (KRIT-04 offen)
- docs/compliance-roadmap.md: P-06 im Freigaben-Log

Offen: KRIT-04 (rechtliche Finalisierung Einwilligungsformulierung) — technisch
vollständig, Rechtstext VORLÄUFIG.

version: 0.8.75
module: media_rights 1.0.0, media_assets 1.13.0, exercises 2.20.0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 08:12:44 +02:00

49 KiB
Raw Blame History

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.28.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:

  1. Jeder Medien-Upload mit einer strukturierten, gespeicherten Rechteerklärung verknüpft ist
  2. Die Erklärung nach Sichtbarkeitsstufe gestuft wird (private minimal, official vollständig)
  3. Bestehende Prüfungen aus P-04 (copyright_notice) komplementär erhalten bleiben
  4. Juristische Textanpassungen ohne Codeänderungen möglich sind (Versionierung)
  5. Altmedien ohne rückwirkenden Zwang behandelt werden können
  6. 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 1n 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.

P-04 erzwingt copyright_notice bei Promotion zu club oder official:

  • patch_media_asset(): HTTP 400 wenn copyright_notice leer bei Ziel club/official
  • bulk_media_patch(): Asset in failed-Liste wenn copyright fehlt
  • apply_official_exercise_media_rules(): HTTP 422 OFFICIAL_MEDIA_CONFIRM_REQUIRED wenn 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=club oder visibility=official existieren 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:

  1. Nutzer öffnet Upload-Dialog (Exercise oder Archiv)
  2. Dateiauswahl
  3. 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]
  4. Upload-Button aktiv erst wenn Pflicht-Checkbox gesetzt

Backend:

  • Empfängt neue Felder: rights_holder_confirmed, optional contains_identifiable_persons, person_consent_confirmed, contains_minors
  • Prüft: rights_holder_confirmed == true — sonst HTTP 400 RIGHTS_DECLARATION_REQUIRED
  • INSERT in media_assets mit rights_status = 'declared', rights_declared_for_visibility = 'private', rights_declared_at = NOW()
  • INSERT in media_asset_rights_declarations mit action_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 = club im 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_declarations mit action_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:

  1. Nutzer ändert Sichtbarkeit eines Mediums zu club (im Archiv oder via Übungssichtbarkeit)
  2. Frontend erkennt Sichtbarkeitserhöhung
  3. 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]
  4. 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_visibility in media_assets auf 'club' setzen

Backend-Fehler:

  • CONSENT_REQUIRED_FOR_CLUB: Personenfragen nicht beantwortet
  • LEGACY_REDECLARATION_REQUIRED: Altmedium, muss Nachdeklaration abgeben
  • RIGHTS_DECLARATION_REQUIRED (P-04): copyright_notice fehlt (bestehend)

Flow 5: Promotion private/club → official

Frontend:

  1. Nur Superadmin kann zu official promoten
  2. 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]
  3. 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:

  1. Nutzer versucht Promotion eines Altmediums
  2. Backend gibt HTTP 400 LEGACY_REDECLARATION_REQUIRED zurück
  3. Frontend zeigt Hinweis und Deklarations-Dialog (analog zu neuem Upload-Dialog)
  4. Nutzer füllt Deklaration aus
  5. PATCH mit legacy_re_declaration=true + alle Pflichtfelder + visibility
  6. Backend: INSERT in Declarations-Log mit action_type='legacy_re_declaration', aktualisiert rights_status, rights_declared_for_visibility

Migrationsstrategie für bestehende Daten:

  • Alle bestehenden media_assets-Zeilen bleiben mit rights_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

  1. Migration (P-06a): Neue Spalten in media_assets mit DEFAULT 'legacy_unreviewed' → alle bestehenden Zeilen erhalten automatisch Status legacy_unreviewed
  2. Neue Uploads nach P-06: Code setzt rights_status = 'declared' nach erfolgreicher Deklaration
  3. Altmedien-Promotion: Backend blockiert mit LEGACY_REDECLARATION_REQUIRED; Nutzer muss Nachdeklaration abgeben
  4. 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-06ad; 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

  1. Rechtsanwalt beauftragt für §7.7 (Texte) und §7.17.3 (Anforderungen je Stufe)
  2. Nach Klärung §7.7: Freigabe P-06a + P-06b parallel (kein Frontend-Merge nötig)
  3. Nach §7.7 Textfreigabe: Freigabe P-06c (Frontend-Dialoge)
  4. P-06d: Tests + Doku beim gleichen Merge wie P-06b/P-06c
  5. 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.17.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.


10. Vorläufige Implementierungsannahmen (2026-05-11)

Wichtiger Hinweis: Die folgenden Annahmen gelten als vorläufige Erstfassung. Sie wurden bewusst konservativ gewählt. Die juristische Validierung (insb. §7.1§7.7 dieser Spec) steht weiterhin aus. Texte, Pflichtfelder und Stufenlogik können nach juristischer Prüfung gelockert oder präzisiert werden. P-06 gilt nach dieser technischen Umsetzung als technisch umgesetzt unter vorläufigen Annahmen — nicht als rechtlich endgültig abgeschlossen. KRIT-04 bleibt bis zur anwaltlichen Prüfung als rechtlicher Blocker offen.

10.1 Abweichung gegenüber ursprünglicher Matrix (§3)

Die Entscheidungsmatrix in §3 sah vor:

  • private Upload: Personenfragen optional
  • club/official Upload: Personenfragen Pflicht

Geändert für conservative Erstannahme:

  • Personenfragen sind bei allen Uploads (auch private) Pflicht zu beantworten
  • Begründung: lieber zunächst strenger und nach juristischer Klärung gezielt lockern; ein bereits gesammeltes „Nein, keine erkennbaren Personen" ist besser als gar kein Datenpunkt
  • Diese Verschärfung ist als declaration_version = 'p06-v1-conservative' dokumentiert
  • Spätere Lockerung auf 'p06-v1.1' o. ä. möglich ohne Datenverlust

10.2 Verbindliche Erstannahmen

Annahme Technisch umgesetzt als
Jeder Upload (auch private) erfordert Rechteerklärung rights_holder_confirmed = true Pflicht bei allen Uploads
Personenfragen bei allen Uploads Pflicht contains_identifiable_persons muss beantwortet sein
Personeneinwilligung Pflicht wenn Personen vorhanden person_consent_confirmed = true wenn contains_identifiable_persons = true
Minderjährigenfrage bei allen Uploads Pflicht contains_minors muss beantwortet sein
Elterneinwilligung Pflicht wenn Minderjährige vorhanden parental_consent_confirmed = true wenn contains_minors = true
Musikfrage Pflicht contains_music muss beantwortet sein
Musikrechte Pflicht wenn Musik vorhanden music_rights_confirmed = true wenn contains_music = true
Fremdmaterial-Frage Pflicht contains_third_party_content muss beantwortet sein
Fremdmaterialrechte Pflicht wenn Fremdmaterial vorhanden third_party_rights_confirmed = true wenn contains_third_party_content = true
Erklärung gilt für konkrete Zielsichtbarkeit target_visibility = private / club / official
Promotion zu höherer Sichtbarkeit erfordert neue Erklärung Backend blockiert ohne passende neue Declaration
Altmedien bleiben sichtbar rights_status = 'legacy_unreviewed' per Migration-Default
Altmedien-Promotion blockiert HTTP 400 LEGACY_REDECLARATION_REQUIRED
Selbsterklärung genügt (MVP) Kein Dokumenten-Upload erforderlich
Deklarationsversion declaration_version = 'p06-v1-conservative'

10.3 Vorläufige Dialogtexte (Arbeitsfassung — juristisch nicht geprüft)

Die folgenden Texte sind Arbeitsfassungen und explizit als vorläufig zu behandeln. Sie werden in der UI mit einem entsprechenden Hinweis angezeigt. Alle Labels sind in der Frontend-Komponente zentral definiert und ohne Code-Änderung austauschbar.

# Label Text (Vorläufig)
T1 Rechteinhaber-Bestätigung „Ich bestätige, dass ich berechtigt bin, dieses Medium hochzuladen und in der gewählten Sichtbarkeitsstufe zu verwenden, und dass ich über die dafür erforderlichen Rechte verfüge."
T2 Personen-Frage „Sind auf diesem Medium Personen eindeutig erkennbar?"
T3 Personen-Einwilligung „Ich bestätige, dass mir für alle erkennbaren Personen die für diese Nutzung erforderlichen Einwilligungen vorliegen."
T4 Minderjährigen-Frage „Sind auf diesem Medium Minderjährige eindeutig erkennbar?"
T5 Minderjährigen-Einwilligung „Ich bestätige, dass mir die für diese Nutzung erforderlichen Einwilligungen der Sorgeberechtigten vorliegen."
T6 Musik-Frage „Enthält das Medium Musik?"
T7 Musik-Rechte „Ich bestätige, dass ich für die enthaltene Musik die für diese Nutzung erforderlichen Rechte habe."
T8 Fremdmaterial-Frage „Enthält das Medium Logos, Grafiken oder sonstige fremde geschützte Inhalte?"
T9 Fremdmaterial-Rechte „Ich bestätige, dass ich für alle enthaltenen fremden Inhalte die für diese Nutzung erforderlichen Rechte habe."
T10 Hinweis „Diese Erklärung wird protokolliert. Die konkrete rechtliche Ausgestaltung wird noch abschließend geprüft."

10.4 Tatsächlich implementierte Endpunkte und Felder

Migration 048: backend/migrations/048_media_rights_declarations.sql

  • Neue Tabelle: media_asset_rights_declarations (append-only, alle Felder aus §4.1)
  • Neues Feld rights_status in media_assets (DEFAULT 'legacy_unreviewed')
  • Neues Feld rights_declared_for_visibility in media_assets
  • Neues Feld rights_declared_at in media_assets

Neues Backend-Modul: backend/media_rights.py

  • VISIBILITY_LEVELS: Hierarchie private(1) < club(2) < official(3)
  • validate_rights_declaration(): Prüft vollständige Deklaration je Sichtbarkeit
  • check_rights_coverage(): Prüft ob vorhandene Erklärung Zielsichtbarkeit abdeckt
  • write_rights_declaration(): Schreibt append-only Declaration-Log
  • update_rights_quick_fields(): Aktualisiert Schnellfelder in media_assets

Angepasste Endpunkte:

Endpunkt Änderung
POST /api/media-assets/bulk-upload P-06-Pflichtfelder als Form-Parameter; Declaration-Log bei Erfolg
PATCH /api/media-assets/{id} Rechte-Prüfung bei Promotion; Declaration-Log wenn neue Erklärung
POST /api/media-assets/bulk-patch Rechte-Prüfung bei Promotion per Asset
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:

Endpunkt Beschreibung
POST /api/media-assets/{id}/rights-declarations Re-/Nachdeklaration für vorhandene Medien
GET /api/admin/media-rights/legacy-summary Auswertung legacy_unreviewed nach Sichtbarkeit
GET /api/admin/media-rights/legacy-assets Liste legacy_unreviewed club/official-Medien

Frontend-Komponente:

  • frontend/src/components/RightsDeclarationDialog.jsx — wiederverwendbarer Dialog
  • Integration in MediaLibraryPage.jsx (Bulk-Upload) und ExerciseFormPage.jsx (Upload)

10.5 Juristische Restoffenheit

Folgende Punkte aus §7 sind technisch mit konservativer Annahme implementiert, aber rechtlich noch zu validieren:

§7-Punkt Konservative Annahme Juristisch offen
§7.1 private: Reicht rights_holder allein? Nein — alle Fragen Pflicht Ja
§7.2 club: KUG vereinsintern? Ja — volle Erklärung Pflicht Ja
§7.4 Minderjährige: Schwelle, Form? Pflichtfeld ab Upload Ja
§7.5 Selbsterklärung genügt? Ja (MVP) Ja
§7.6 Batch-Deklaration genügend? Ja — eine Erklärung gilt für alle Batch-Dateien Ja
§7.7 Textfassung der Erklärungen Vorläufige Arbeitsfassung (T1T10) Ja — anwaltliche Freigabe nötig
§7.10 Aufbewahrung Declaration-Log ON DELETE SET NULL für declared_by; CASCADE auf media_asset_id Ja

Erstellt: 2026-05-10 | Implementierungsannahmen hinzugefügt: 2026-05-11 | Autor: Claude Code | Kein Rechtsanwalt; alle rechtlichen Einschätzungen sind juristisch zu prüfen.