# Architektur ## Systemgrenze Sendewerk ist ein einzelner SvelteKit-Prozess. Browserseiten, serverseitige Actions, spätere REST-Endpunkte und Hintergrundaufgaben verwenden dieselbe Geschäftslogik. SQLite und ein lokales Upload-Verzeichnis sind die einzigen persistenten Laufzeitabhängigkeiten. Externe Mail-, RSS- oder KI-Dienste sind nicht Voraussetzung für Kernfunktionen. ```text Browser -> SvelteKit-Routen -> Anwendungsdienste -> SQLite | -> Upload-Verzeichnis +-> später: Mail/RSS über Adapter ``` Servercode lebt unter `src/lib/server` und darf nicht in Browser-Bundles gelangen. Routen liefern nur die für ihre Ansicht erlaubten Daten. Fachlogik wird nicht an Svelte-Komponenten gebunden, damit Browseraktionen und die spätere API dieselben Regeln verwenden. ## Laufzeit und Speicher - Lokal: `.data/sendewerk.sqlite` und `.data/uploads`, jeweils konfigurierbar. - Tests: pro Lauf ein temporäres Verzeichnis unter dem Betriebssystem-Tempdir. - Cloudron: `/app/data/sendewerk.sqlite` und `/app/data/uploads`. - Migrationen liegen nummeriert unter `migrations/`, laufen in Transaktionen und werden in `schema_migrations` protokolliert. - Der Seed nutzt stabile IDs und Transaktionen. Wiederholung liefert denselben fachlichen Ausgangsbestand, ohne Migrationstabellen anzutasten. - Zeitpunkte werden als ISO-8601-UTC-Text gespeichert. Dauern sind nichtnegative ganze Sekunden. Zeitzonendarstellung ist `Europe/Berlin`. ## Geplantes Gesamtdatenmodell Etappe 1 materialisiert nur den für echte Vorschau- und Seed-Daten benötigten Kern. Folgende Grenzen sind für spätere Migrationen bereits festgelegt. | Bereich | Geplante Entitäten und Beziehungen | | ----------- | ---------------------------------------------------------------------------------------------------------------------------- | | Identität | `users`, Rollen, Sessions, Einladungen, Reset-Tokens und Sperren sind umgesetzt; technische Zugänge folgen später | | Taxonomie | getrennte `section_categories`, `formats`, `topics`; Pieces und Vorschläge über Zuordnungstabellen mehrfach verknüpft | | Inhalt | `pieces` mit Status und Dauer; Quellen, Medien, private Recherche, Moderation, Präsentation und Vorlagen als getrennte Daten | | Sendungsbau | `shows`, geordnete `show_sections`, kopierte `piece_usages`, Reservebank und Sendungsvorlagen; Original-ID bleibt Referenz | | Live | expliziter Live-Stand, aktuelles Element, Status je Verwendung, tatsächliche Zeiten und getrennte Präsentationsausgabe | | Historie | unveränderliche Abschluss-Snapshots und Verwendungshistorie; Übersprungenes zählt nicht als gesendet | | Freigaben | widerrufbare, gehashte Lesetokens mit Sendung, Umfang, Passwortoption und Ablaufzeit | | RSS | Feedquellen, Abrufläufe und externe Einträge mit stabiler Herkunfts-ID sowie Status neu/übernommen/verworfen | | API/Audit | technische Berechtigungen, Idempotenzschlüssel und Audit-Ereignisse mit Akteur, Aktion und Ziel | | Betrieb | Anwendungseinstellungen und spätere Job-Zustände, keine Geheimnisse im Klartext ohne begründete Schutzstrategie | ### Historien- und Kopierregel Beim Einplanen entsteht eine bearbeitbare `piece_usage`-Kopie der sendungsrelevanten Texte und Dauer. Das Original bleibt verknüpft, wird aber nicht live gespiegelt. Beim Abschluss wird der damalige Sendungsinhalt stabil eingefroren. Eine historische Sendung wird dupliziert, nie weiterbearbeitet. ### Dauerregel Eine Abschnittsdauer ist entweder die Summe ihrer eingeplanten Verwendungen oder eine explizite Abschnittsdauer. Beides wird nie addiert. Reserveelemente zählen erst nach dem Einplanen. Geplante und tatsächliche Dauer bleiben getrennt. ## Anmeldung und Rechte Etappe 2 ergänzt lokale Konten mit den festen Rollen `barkeeper` und `thekencrew`. Passwörter werden mit Argon2id gespeichert. Sitzungs-, Einladungs- und Reset-Tokens entstehen aus kryptografischem Zufall; in SQLite liegt jeweils nur ihr SHA-256-Hash. Der Browser erhält ausschließlich das rohe Sitzungstoken in einem `HttpOnly`-, `SameSite=Lax`-Cookie. `hooks.server.ts` löst die Sitzung für jeden Request auf. Die Datenbankabfrage verbindet die Session immer mit dem aktuellen Nutzerzustand, sodass Sperren und Rollenwechsel ohne verzögerte Token-Erneuerung wirken. Geschützte Routen erfordern eine Anmeldung; Verwaltungs-Loads und jede Verwaltungs-Action prüfen zusätzlich die Barkeeper-Rolle. Sperrung und Passwortwechsel löschen bestehende Sessions transaktional. Der Erstadmin benötigt sowohl eine leere Nutzertabelle als auch ein extern konfiguriertes Setup-Token. Einladungs- und Reset-Links sind 24 Stunden gültig, werden erst beim bestätigenden POST verbraucht und sind genau einmal nutzbar. Fehlgeschlagene Loginversuche werden pro E-Mail-Schlüssel und Clientadresse in einem Zeitfenster begrenzt, ohne das Konto dauerhaft zu sperren. Mail verwendet einen Adapter: `local` schreibt geschützte Dateien in den konfigurierten Outbox-Pfad, `smtp` nutzt Nodemailer nur nach expliziter Auswahl. Die feste Anwendungs-Origin erzeugt Links und bestimmt den `Secure`-Status der Cookies; sie wird nicht aus ungeprüften Request-Headern übernommen. ## Oberflächenstruktur Die Hauptnavigation umfasst Eingang, Fundus, Sendungen, Archiv und Verwaltung. Auf dem Desktop bleibt eine feste Seitenleiste sichtbar; Verwaltung liegt an ihrem unteren Ende. Bis einschließlich `52rem` ersetzen eine obere Leiste und die untere Hauptnavigation die Seitenleiste vollständig. Auf breiten Ansichten stehen Fundus und Ablauf nebeneinander. Bis einschließlich `72rem` werden sie über eine gut erreichbare Umschaltung einzeln gezeigt, damit auch schmale Desktopfenster ohne horizontalen Überlauf bedienbar bleiben. Der Live-Modus ist eine eigene, fokussierte Ansicht; die spätere Präsentationsausgabe erhält eine separate, strikt reduzierte Datenansicht. Etappe 1 zeigt Fundus, Sendungsbau und Live-Modus als sichtbare `Gestaltungsvorschau`. Die Daten kommen bereits aus SQLite, mutierende Fachabläufe werden jedoch nicht vorgetäuscht. ## Sicherheitsgrenzen ab den Folgeetappen Authentifizierung und Autorisierung werden seit Etappe 2 serverseitig an jeder betroffenen Route und Action geprüft. Markdown und fremdes HTML werden vor Ausgabe bereinigt. Uploadzugriff folgt denselben Rechten. Netzwerkabrufe erhalten Schutz gegen interne Ziele, Größen-/Zeitlimits und kontrollierte Redirects. Diese Regeln sind geplant, aber nicht Bestandteil der Etappe-1-Vorschauen.