Notiz-Medien & Sprachnachrichten: Fotos/Videos/Dateien + Audio an Notizen

Wiederverwendbarer UI.noteMediaAttacher für beide Notiz-Stellen (UI.noteModal
+ Notizblock-Seite). note_media-Tabelle + POST/DELETE /api/notes/{id}/media
(vor der gierigen /{parent_type}/{parent_id}-Route). Audio per MediaRecorder,
serverseitig nach m4a/AAC transkodiert (ffmpeg) — iOS spielt Chrome-Opus-webm
nicht ab. UI.lightbox global eingeführt. Mikrofon-Policy microphone=(self) +
CSP media-src 'self' blob:, Datenschutz v6. Disk-Cleanup für note_media bei
Notiz-, Account- und Admin-User-Delete. Reine Medien-Notiz ohne Text erlaubt.
noteModal-Bug gefixt: notes.get() liefert Array -> existing[0] statt
existing?.id (verhinderte Bearbeiten, erzeugte Duplikate). 12 neue Tests.

admin.py enthält außerdem KI-Vision-Statusfelder aus paralleler Arbeit
(nicht sauber trennbar ohne interaktives Staging).
This commit is contained in:
rene 2026-06-14 20:22:35 +02:00
parent 203da50e1d
commit e86d89f3d9
12 changed files with 947 additions and 59 deletions

View file

@ -106,7 +106,7 @@ class SecurityHeadersMiddleware(BaseHTTPMiddleware):
response = await call_next(request)
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
response.headers["Permissions-Policy"] = "camera=(), microphone=(), geolocation=(self)"
response.headers["Permissions-Policy"] = "camera=(), microphone=(self), geolocation=(self)"
response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
response.headers["Content-Security-Policy"] = (
"default-src 'self'; "
@ -114,6 +114,7 @@ class SecurityHeadersMiddleware(BaseHTTPMiddleware):
"worker-src 'self' blob:; " # 'self' = Service Worker (sw.js); blob: = MapLibre-GL-Worker
"style-src 'self' 'unsafe-inline'; " # Inline-Styles bleiben (zu viele Fundstellen für jetzt)
"img-src 'self' data: blob: https:; "
"media-src 'self' blob:; " # Audio/Video-Wiedergabe + lokale blob:-Vorschau (Sprachnotizen)
"connect-src 'self' https:; "
"frame-ancestors 'none'; "
"base-uri 'self'; "