No description
  • TypeScript 59.2%
  • Svelte 39.6%
  • CSS 0.7%
  • JavaScript 0.2%
  • Dockerfile 0.2%
  • Other 0.1%
Find a file
Claude c855e72693
All checks were successful
CI / test (push) Successful in 1m0s
Release / build-image (push) Successful in 1m20s
Vorsitz nimmt auch die Hinweise mit
- Beim Einteilen des Vorsitzes werden neben einleitenden Worten und
  Schlussworten jetzt auch die „Hinweise"-Punkte mitgesetzt (gilt für
  manuelle Zuteilung und Auto-Assign)
- Bereits abweichend besetzte Punkte werden weiterhin nicht überschrieben;
  beim Wechsel des Vorsitzenden wandern nur seine eigenen Punkte mit
- Prüf-Logik als belongsToChairman ausgelagert und getestet (134 grün)
2026-08-03 20:00:27 +00:00
.forgejo/workflows ci: forgejo-release-Action durch API-Aufruf ersetzen (ambiguous-redirect-Bug) 2026-07-29 00:48:54 +02:00
docker fix: Upload-Limit für Arbeitshefte anheben (413 Payload Too Large) 2026-07-29 11:07:26 +02:00
docs Empfängerkreise für Schwarzes Brett und Ereignisse 2026-08-03 17:22:08 +00:00
drizzle Sonderwochen: abweichender Tag, eigener Beginn, keine Soll-Endzeit 2026-08-03 17:59:21 +00:00
scripts feat: Projektfundament (Meilenstein 1) 2026-07-29 00:04:00 +02:00
src Vorsitz nimmt auch die Hinweise mit 2026-08-03 20:00:27 +00:00
static refactor: App in Reso umbenennen (Branding, DB-Name, Manifest, Stack) 2026-07-29 00:14:57 +02:00
tests Vorsitz nimmt auch die Hinweise mit 2026-08-03 20:00:27 +00:00
.env.example fix: Upload-Limit für Arbeitshefte anheben (413 Payload Too Large) 2026-07-29 11:07:26 +02:00
.gitignore feat: Projektfundament (Meilenstein 1) 2026-07-29 00:04:00 +02:00
docker-compose.dev.yml fix(compose): Build-Block entfernen – Portainer zieht Image aus Registry; dev-Override ergänzt 2026-07-29 00:43:38 +02:00
docker-compose.yml fix: Upload-Limit für Arbeitshefte anheben (413 Payload Too Large) 2026-07-29 11:07:26 +02:00
drizzle.config.ts refactor: App in Reso umbenennen (Branding, DB-Name, Manifest, Stack) 2026-07-29 00:14:57 +02:00
package-lock.json feat: Liederbuch per Excel/CSV importieren, CSV-Export 2026-07-29 16:13:58 +02:00
package.json feat: Liederbuch per Excel/CSV importieren, CSV-Export 2026-07-29 16:13:58 +02:00
README.md fix: Dienste im Wochenplan sichtbar, Notizen fuer den Vorsitz 2026-07-29 18:24:56 +02:00
svelte.config.js fix: PDF-Vorschau am schwarzen Brett wurde von den eigenen Headern blockiert 2026-07-29 14:15:05 +02:00
tsconfig.json feat: Projektfundament (Meilenstein 1) 2026-07-29 00:04:00 +02:00
vite.config.ts feat: Projektfundament (Meilenstein 1) 2026-07-29 00:04:00 +02:00

Reso

Sichere, selbst gehostete Web-App (PWA) zur Verwaltung der Versammlung. Siehe docs/Anforderungsdokument.md und docs/Architekturdokument.md.

Entwicklung

npm install
cp .env.example .env        # Werte anpassen (openssl rand -base64 32 für Schlüssel)
docker compose up db -d     # lokale PostgreSQL
npm run db:migrate          # Migrationen anwenden
npm run dev

Beim ersten Aufruf leitet die App auf /setup dort wird das Admin-Konto angelegt.

Produktion (Docker Compose / Portainer)

cp .env.example .env        # alle CHANGE_ME-Werte setzen!
docker compose up -d --build

Der Stack enthält App (Port 3000), PostgreSQL 17 und einen täglichen, verschlüsselten Backup-Job (openssl enc -aes-256-cbc, 30 Tage Aufbewahrung). Ein HTTPS-Reverse-Proxy (Caddy/Traefik/NPM) davor ist Pflicht PWA und Web Push funktionieren nur über HTTPS.

Upload-Größe: Arbeitshefte sind mehrere MB groß. BODY_SIZE_LIMIT ist auf 32M voreingestellt (ohne diesen Wert würde der Node-Adapter bei 512 KB mit 413 Payload Too Large abbrechen). Der Reverse Proxy muss ebenfalls genug erlauben:

  • nginx / Nginx Proxy Manager: client_max_body_size 32m;
  • Caddy und Traefik: standardmäßig unbegrenzt

Backup wiederherstellen:

openssl enc -d -aes-256-cbc -pbkdf2 -pass env:BACKUP_PASSPHRASE \
  -in reso_DATUM.sql.gz.enc | gunzip | psql "$DATABASE_URL"

CI/CD (Forgejo Actions)

  • ci.yml: Typecheck, Tests, Build bei jedem Push/PR
  • release.yml: bei Tag v* Multi-Arch-Image (amd64/arm64) → Forgejo-Registry
    • Release mit Stack-Paket (docker-compose.yml + .env.example)

Benötigte Repo-Einstellungen: Variablen REGISTRY, REGISTRY_USER, Secrets REGISTRY_TOKEN, RELEASE_TOKEN.

Sicherheit (Kurzfassung)

  • Argon2id-Passwort-Hashing, Richtlinie 12+ Zeichen
  • DB-Sessions (HttpOnly/Secure/SameSite), Login-Lockout, Audit-Log
  • TOTP-2FA (Grundlage vorhanden, UI folgt in Meilenstein 2)
  • Feldverschlüsselung AES-256-GCM für sensible Daten (FIELD_ENCRYPTION_KEY)
  • Security-Header (CSP, HSTS, X-Frame-Options) via hooks.server.ts
  • Container läuft als non-root

Struktur

src/lib/server/db       Drizzle-Schema + Client
src/lib/server/auth     Sessions, Passwort, TOTP, RBAC
src/lib/server/crypto   Feldverschlüsselung
src/routes/(auth)       Login, Ersteinrichtung
src/routes/(app)        eingeloggter Bereich (App-Shell, Dark Mode)
drizzle/                SQL-Migrationen
docker/                 Dockerfile + Entrypoint (führt Migrationen aus)
.forgejo/workflows/     CI + Release

Meilensteine

  1. Fundament: Auth, RBAC, Schema, Docker, CI
  2. Mitglieder: Personen, Gruppen, Notfallkontakte, individuelle Felder
  3. Sekretär: Berichte, Statusberechnung, Auswertung, S-21-Druck, Anwesenheit
  4. LuD: Wochenplanung, Empfehlung + Auto-Assign, S-140/S-89-Druckansichten
  5. PWA/Push: Service Worker, Mein-Bereich mit Berichtsabgabe, Push bei Zuteilung
  6. 🔶 Härtung: Benutzerverwaltung, TOTP-2FA-Setup, Audit-Ansicht (DSGVO-Export, Pentest-Checkliste ausstehend)

Module

  • Wochenplan (/wochenplan): die ganze Woche in einer Ansicht und in dieser Reihenfolge zuerst die Zusammenkunft unter der Woche mit Programm und Uhrzeiten, darunter die Zusammenkunft am Wochenende (fester Ablauf: Lied und Gebet, öffentlicher Vortrag, Lied, Wachtturm-Studium, Lied und Gebet; berechnet in src/lib/domain/weekend.ts), darunter der Rest der Woche: Dienste je Dienstart (Ordner, Mischpult, Medien …) mit den eingeteilten Personen, offene Dienste erscheinen mit „offen"; gilt dieselbe Besetzung an beiden Tagen, steht sie einmal mit dem Vermerk „ganze Woche", sonst getrennt nach „unter der Woche" und „Wochenende". Dazu Predigtdienst, Reinigung und Ereignisse. Jeder Abschnitt hängt an seinem eigenen Leserecht; Notizen für den Vorsitz und „Hinweise" erscheinen hier nicht. Eigene Zuteilungen sind hervorgehoben (farbiger Balken und Stern) auch Wochenend-Rollen, Dienste, Predigtdienst und Reinigungen der eigenen Gruppe.

  • Pläne (/plaene): die einzelnen Pläne als einfache Listen in vier Reitern Redner, Dienste, Reinigung und Predigtdienst. Kein Bearbeiten, eigene Zuteilungen mit Stern markiert; jeder Reiter hängt an seinem Leserecht und erscheint nur, wenn es vorhanden ist.

  • Schwarzes Brett (/schwarzes-brett): Bekanntmachungen mit Rich-Text-Editor (fett, kursiv, unterstrichen, Überschriften, Listen, Zitat, Links) und/oder PDF-Anhängen. PDFs werden in der App angezeigt (eingebettet per iframe, Content-Disposition: inline), nicht als Download; daneben ein Knopf zum Öffnen in neuem Tab. Damit die Vorschau funktioniert, erlauben X-Frame-Options: SAMEORIGIN und die CSP-Direktiven frame-src/object-src/frame-ancestors das Einbetten von der eigenen Domain fremdes Einbetten bleibt blockiert. Einträge lassen sich anpinnen und mit einem Sichtbarkeitsende versehen. Der Editor liefert HTML, das serverseitig mit sanitize-html gegen eine strenge Positivliste bereinigt wird (keine Skripte, Stile, Event-Attribute oder iframes) sonst wäre ein Eintrag ein Einfallstor für XSS. Anhänge liegen als bytea in der Datenbank und sind damit Teil der verschlüsselten Backups; je Datei bis 10 MB, nur PDF.

  • Ereignisse (/ereignisse): Termine mit Datum, Uhrzeit, mehrtägigem Zeitraum, Ort und Beschreibung; getrennt in kommende und vergangene.

  • Beide erscheinen als Karten auf dem Dashboard das schwarze Brett mit den vier neuesten Einträgen, die Ereignisse mit den fünf nächsten Terminen.

  • Zuteilungen je Person (/personen/<id>): für jede Aufgabe der Zusammenkunft und jeden Dienst einzeln ein-/ausschaltbar

  • Berichte (/berichte): Monats-Erfassung je Verkündiger, Status aktiv/unregelmäßig/inaktiv, fehlende Berichte hervorgehoben; Auswertung mit 6/12-Monats-Durchschnitten und Pionierstunden

  • Zusammenkunft (/zusammenkunft): Wochen mit Standardprogramm, Zuteilung mit Empfehlung (längste Pause, Abwesenheiten, Doppelbelegung), Auto-Assign, Druckansicht inkl. Aufgabenzettel

  • Anwesenheit (/anwesenheit): Erfassung + Durchschnitte

  • Startseite: Karte „Als nächstes" mit den vier nächsten eigenen Zuteilungen und Link auf die vollständige Liste; dazu Berichts-Erinnerung, Abwesenheitskonflikte für Planer, schwarzes Brett und Ereignisse

  • Mein Bereich (/meine) als Selbstbedienung, gegliedert in die Reiter Aufgaben, Meine Daten und Abwesenheiten ohne Bereichsrechte nutzbar: eigene Kontaktdaten (Telefon, Mobil, E-Mail, Adresse) und Notfallkontakte pflegen, Abwesenheiten für sich und die Familie eintragen, Bericht abgeben, Push-Benachrichtigungen ein- und ausschalten, Kalender-Abo einrichten. Name, Stellung und Gruppe bleiben dem Sekretär vorbehalten. Dazu alle kommenden eigenen Zuteilungen aus allen Bereichen Zusammenkunft, Wochenende, Dienste, Predigtdienst und Reinigung , farblich unterschieden und nach Datum und Uhrzeit sortiert; dazu Berichtsabgabe und Push-Benachrichtigungen. Reinigungen der eigenen Predigtdienstgruppe erscheinen mit dem Hinweis „mit der Gruppe". Beide Ansichten nutzen dasselbe Modul (src/lib/server/domain/myAssignments.ts) und dieselben Farbcodes (src/lib/shared/assignmentKinds.ts), damit sie nicht auseinanderlaufen.

  • Berichts-Erinnerung: Zum Monatsende erscheint auf dem Dashboard und in „Mein Bereich" eine Karte zur Abgabe des eigenen Predigtdienstberichts für alle ab „ungetaufter Verkündiger". Nach der Abgabe bleibt nur ein Hinweis stehen. Zeitfenster (src/lib/domain/reportWindow.ts): ab dem 28. für den laufenden Monat, vom 1. bis 20. für den zurückliegenden; dazwischen wird nichts angezeigt. Wer direkt ans Zweigbüro berichtet, wird nicht erinnert.

  • Vorträge (/vortraege): Wochenend-Zusammenkünfte mit Redner, Thema, Vorsitz, WT-Leser, Gastfreundschaft; Redner- und Nachbarversammlungs-Verwaltung

  • Dienste (/dienste): frei definierbare Dienste (Ton, Mikrofone, Ordner …) als Matrix je Zusammenkunft

  • Predigtdienst (/predigtdienst): Treffpunkte mit Datum, Uhrzeit, Ort, Karten-Link, Leiter und Gebet

  • Reinigung (/reinigung): wochenweise Zuteilung je Arbeit (Zwischen-, Wochen-, Monats-, Jahresreinigung, Garten, Rasen) an eine Gruppe oder eine einzelne Person

  • Programmimport (/zusammenkunft/import): Arbeitsheft als EPUB (empfohlen) oder PDF hochladen importiert werden ausschließlich Datum, Titel und Zeiten der Programmpunkte. Vorschau vor dem Import, Wochentag wählbar, Vorsitz/Gebete optional ergänzbar, vorhandene Termine werden übersprungen. Alternativ Programmtext einfügen.

  • E-Mail: Aufgabenzettel je Zusammenkunft per Knopfdruck an Studierende (SMTP_URL/MAIL_FROM nötig)

  • DSGVO: Datenauskunft je Person als JSON-Export

  • Einstellungen → Versammlung: Wochentag und Beginn beider Zusammenkünfte, Gesamtdauer der Zusammenkunft sowie die Dauern für „Lied und Gebet" und die „Hinweise". Diese Werte gelten dauerhaft: der Arbeitsheft-Import berechnet daraus die Termine, und alle Programmansichten zeigen daraus die Uhrzeiten

  • Einstellungen: individuelle Felder, Benutzerkonten + Rollen, 2FA, Audit-Log

Arbeitsheft-Import: technische Hinweise

Es werden drei Quellen unterstützt. Empfohlen ist das EPUB.

EPUB (empfohlen)

src/lib/domain/workbookEpub.ts. Das EPUB ist ein unverschlüsseltes ZIP mit einem XHTML-Dokument pro Woche und semantischer Auszeichnung:

Element Inhalt
<h1> Datumsbereich der Woche
<h2> Bibellesestoff bzw. Abschnitt (SCHÄTZE AUS GOTTES WORT …)
<h3> Programmpunkt
<p> Details, beginnend mit der Zeitangabe

Die Teil-Typen werden aus dem Abschnitt abgeleitet, nicht aus dem Titel das ist verlässlicher als jede Heuristik. Weiche Trennstriche (U+00AD) werden entfernt.

PDF (Rückfalloption)

src/lib/server/import/pdfText.ts behandelt drei Eigenheiten der PDFs: zweispaltiges Layout, Umlaute als separat gezeichnete Akzent-Glyphen und unbrauchbare Leerzeichen-Items (Wortabstände kommen aus den X-Lücken). Die Segmentierung in Wochen erfolgt über die Nummerierung der Programmpunkte, nicht über die Dokumentreihenfolge eine Seite kann das Ende einer Woche und den Anfang der nächsten enthalten.

Text einfügen

Für einzelne Wochen, wenn keine Datei zur Hand ist.

Umfang und JWPUB

Importiert werden Datum, Titel, Zeiten und Lieder. Lieder werden als Programmpunkte angelegt („Lied 123 und Gebet"); da im Arbeitsheft keine Dauer dafür steht, wird der Wert aus den Einstellungen verwendet, damit die Uhrzeiten stimmen. Bibelstellen und Publikationsverweise bleiben außen vor.

Die Uhrzeit jedes Programmpunkts wird nicht gespeichert, sondern aus Beginn und Dauern berechnet (src/lib/domain/schedule.ts). Ändert sich der Beginn in den Einstellungen, stimmen alle Pläne sofort auch die bereits importierten.

Feste Gesamtdauer: Die Zusammenkunft soll immer gleich lang sein (Standard 105 Minuten). Der letzte Programmpunkt wird deshalb so gelegt, dass die Zusammenkunft genau dann endet; bei Beginn 19:00 startet „Lied und Gebet" also um 20:40. Der Puffer liegt damit vor dem Schlusslied, typischerweise bei den Schlussworten. Läuft ein Programm einmal länger als vorgesehen, wird nicht nach vorn verschoben, sondern fortlaufend weitergerechnet und in der Planung als Überziehung angezeigt.

Abschnitte und „Hinweise"

Jeder Programmpunkt kennt seinen Abschnitt (Schätze aus Gottes Wort, Uns im Dienst verbessern, Unser Leben als Christ). Die Abschnitte werden in Planung und Druckansicht als Überschriften dargestellt; Lieder und Schlussworte stehen dabei unter dem jeweiligen Abschnitt, so wie im Arbeitsheft.

Nach der Bibellesung und nach jeder Aufgabe in „Uns im Dienst verbessern" ergänzt der Import einen Punkt „Hinweise" (src/lib/domain/counsel.ts) für die Rückmeldung des Vorsitzenden. Er steht nicht im Arbeitsheft, folgt aber immer demselben Muster. Diese Punkte sind mit chairman_only markiert:

  • sie zählen in den Zeitplan, verschieben also alle Folgezeiten
  • sie erscheinen nur im Vorsitzenden-Plan (/zusammenkunft/<id>/drucken?vorsitz=1), nicht im öffentlichen Plan und nicht im Verkündiger-Bereich

Die Uhrzeiten werden immer über alle Punkte gerechnet und erst danach für die Anzeige gefiltert dadurch stimmen die Zeiten im öffentlichen Plan trotz ausgeblendeter Zeilen.

Vorsitz: Wer den Vorsitz erhält, wird automatisch auch den einleitenden Worten und den Schlussworten zugeteilt beim manuellen Zuteilen wie beim Auto-Assign. Ist dort schon jemand anderes eingetragen, bleibt das unangetastet.

Notizen für den Vorsitz: Zu jedem Programmpunkt kann in der Planung eine Notiz hinterlegt werden (meeting_part.chairman_note). Sie erscheint ausschließlich im Vorsitzenden-Plan nicht im öffentlichen Plan, nicht auf den Aufgabenzetteln und nicht im Verkündiger-Bereich.

Die .jwpub ist als Quelle nicht nutzbar: Sie ist ein ZIP mit manifest.json und contents (wiederum ein ZIP mit einer SQLite-Datenbank). Im Klartext liegen dort Wochentitel mit exakten Datumsbereichen sowie Lied- und Publikationsverweise die Programminhalte selbst sind jedoch verschlüsselt (AES, contentFormat: "z-a"). Geprüft wurden alle Inhalts-Spalten (Document, DatedText, Extract): kein Blob liegt im Klartext. Titel und Zeiten sind daraus also nicht zu gewinnen. Das EPUB liefert dieselben Daten vollständig und ohne Umgehung eines Schutzmechanismus.

Zuteilbarkeit je Person

Unter Personen → (Person) → Zuteilen wird festgelegt, wofür eine Person eingeteilt werden darf. Die Freigaben sind nach Bereichen gegliedert, jeder Bereich hat einen „Alle"-Schalter:

Bereich Inhalt
Schätze aus Gottes Wort Vorsitz, Gebete, Schätze, Geistige Schätze, Bibellesung, Ratgeber
Uns im Dienst verbessern Gespräche beginnen, Interesse fördern, Jünger machen, Glaubensansichten, Partner, Vortrag
Unser Leben als Christ Aufgaben, Versammlungsbibelstudium, Leser, Schlussgebet
Zusammenkunft am Wochenende Redner lokal/auswärtig, Vorsitz, Wachtturm-Leser, Schlussgebet, Gastfreundschaft
Predigtdienst Treffpunkt leiten, Gebet, öffentliches Zeugnisgeben, Hauptansprechpartner
Reinigung und Gartenpflege Zwischen-, Wochen-, Monats-, Jahresreinigung, Garten, Rasen
Dienste alle unter Dienste angelegten Einträge

Modell und Vorrang (src/lib/shared/capabilities.ts, src/lib/server/domain/capabilities.ts):

  • Gespeichert wird je Person und Schlüssel ein Eintrag in person_capability. Schlüssel sind der Programmpunkt-Typ (bible_reading), duty:<id> für Dienste oder ein sprechender Name (weekend_chairman).
  • Ein gespeicherter Eintrag gilt immer. Fehlt er, greift die Voreinstellung aus dem Katalog (defaultFor: nur Älteste, nur Ernannte, nur Brüder oder alle Verkündiger). Die Oberfläche zeigt damit sofort den wirksamen Zustand; beim Speichern werden alle Werte festgeschrieben.

Wirksam werden die Freigaben in allen Planungsmodulen:

Modul gefilterte Auswahl
Zusammenkunft unter der Woche alle Programmpunkte, auch im Auto-Assign
Vorträge (Wochenende) Vorsitz, Wachtturm-Leser, Schlussgebet
Dienste je Dienst nur zugelassene Personen
Predigtdienst Leiter, Gebet am Treffpunkt
Reinigung je Arbeit nur zugelassene Personen

Eine bereits eingeteilte Person bleibt in ihrer Auswahlliste sichtbar, auch wenn sie später abgeschaltet wird so verschwindet keine bestehende Zuteilung unbemerkt.

Abwesenheiten und Familienverbünde

Familienverbünde (/familien) fassen Angehörige zusammen unabhängig von den Predigtdienstgruppen. Sie dienen dazu, Abwesenheiten gemeinsam einzutragen: dabei entsteht je Person eine Zeile mit gemeinsamer batch_id, sodass die Zeit später auch gesammelt wieder entfernt werden kann.

Eigene Abwesenheiten kann jeder in Mein Bereich selbst pflegen unabhängig von den Bereichsrechten, ebenso für Angehörige des eigenen Familienverbunds. Serverseitig wird geprüft, dass nur die eigene Person und Mitglieder derselben Familie betroffen sind; gelöscht werden können nur eigene Einträge.

Wirkung auf die Planung (src/lib/server/domain/absences.ts):

  • In den Auswahllisten der Zusammenkunft sind abwesende Personen deaktiviert; wer bereits eingeteilt ist, bleibt sichtbar, damit die bestehende Zuteilung nicht verschwindet.
  • Das Speichern einer Zuteilung wird serverseitig abgewiesen, wenn die Person an dem Tag abwesend ist die Prüfung hängt also nicht an der Oberfläche.
  • Auto-Assign überspringt Abwesende grundsätzlich.
  • Wird ein Urlaub nach der Planung eingetragen, erscheint der Konflikt an drei Stellen: auf dem Dashboard der Planer, als Banner auf der betroffenen Zusammenkunft und im Abwesenheiten-Reiter der Person. Geprüft werden Zusammenkunft, Vorträge, Dienste, Predigtdienst und Reinigung.

Navigation

Das Menü ist in drei Abschnitte gegliedert, jeweils nach Rechten gefiltert:

  • Übersicht Start, Wochenplan, Schwarzes Brett, Ereignisse, Mein Bereich
  • Planung Zusammenkunft, Vorträge, Dienste, Predigtdienst, Reinigung
  • Verwaltung Personen, Gruppen, Berichte, Anwesenheit, Einstellungen

Wer nur informiert werden will, braucht ausschließlich den Abschnitt Übersicht; Planer nutzen zusätzlich die Bearbeitungsansichten, können sich aber ebenso über den Wochenplan informieren.

Mobil liegt am unteren Rand eine Leiste mit den wichtigsten Zielen als Symbol Start, Wochenplan, Pläne, Mein Bereich dazu „Mehr", das das vollständige Menü als Blatt öffnet. Die Einträge der Leiste richten sich nach den Leserechten. Am Schreibtisch bleibt die Seitenleiste.

Rechteverwaltung

Der Zugriff wird je Benutzerkonto und Bereich in drei Stufen gesetzt: kein Zugriff, ansehen, bearbeiten (Einstellungen → Rechte). Bereiche sind nach Versammlung, Personen und Planen gegliedert (src/lib/shared/permissions.ts). Pläne ansehen und Planen bearbeiten sind dabei getrennte Gruppen: view_midweek, view_weekend, view_duties, view_field_service und view_cleaning steuern das Lesen, plan_* das Bearbeiten. Wer bearbeiten darf, darf immer auch lesen (canReadPlan), sodass Planern nicht beide Rechte einzeln gegeben werden müssen. Neue Bereiche werden beim Start in den mitgelieferten Rollenvorlagen nachgetragen, ohne bestehende Einstellungen zu verändern.

Durchsetzung (src/lib/server/auth/permissions.ts):

  • hooks.server.ts lädt die Rechte einmal pro Anfrage nach locals.permissions.
  • Jede load- und action-Funktion ruft requirePermission(...) auf lesende Zugriffe mit view, schreibende mit edit. Ohne Recht antwortet der Server mit 403.
  • Bereiche mit dem Recht ansehen zeigen einen Hinweis „Nur Ansicht" und legen alle Formulare der Seite mit inert still umgesetzt auf allen Planungs-, Personen-, Verwaltungs- und Einstellungsseiten so tippt niemand ins Leere und kassiert beim Speichern eine Fehlermeldung. Der Schutz bleibt die serverseitige Prüfung.
  • Die Navigation blendet Bereiche ohne Recht aus. Das ist nur Bequemlichkeit: der Schutz liegt ausschließlich in der serverseitigen Prüfung, ein direkter Aufruf der URL wird ebenso abgewiesen.
  • Konten mit der Rolle admin haben immer vollen Zugriff, damit sich niemand aus der Verwaltung aussperren kann.
  • Der persönliche Bereich (/meine, /benachrichtigungen, Einstellungen → Sicherheit) ist ohne Bereichsrecht erreichbar dort sieht jeder ausschließlich seine eigenen Daten.

Passwort zurücksetzen: Unter Einstellungen → Benutzer kann jedes Konto mit dem Recht settings: bearbeiten das Passwort eines anderen Kontos zurücksetzen. Es wird wie beim Anlegen ein Einmal-Passwort erzeugt und einmalig angezeigt; gleichzeitig werden alle bestehenden Anmeldungen dieses Kontos beendet und der Login-Zähler zurückgesetzt. Der Vorgang steht im Audit-Log.

Rollenvorlagen: Die gängigen Ämter (Koordinator der Ältestenschaft, Sekretär, Dienstaufseher, Aufseher der Leben-und-Dienst-Zusammenkunft, Vortragskoordinator, Gruppenaufseher, Ordner, Gebietsdiener, Literaturdiener, Diener des Königreichssaals, Koordinator für Audio/Video, Ältester, Dienstamtgehilfe, Verkündiger) werden beim ersten Start angelegt und sind frei bearbeitbar; eigene Vorlagen lassen sich ergänzen. Eine Vorlage setzt die Matrix eines Kontos, die anschließend noch angepasst werden kann.

Benachrichtigungen

Benachrichtigungen hängen am Benutzerkonto, nicht an der Person nur der Empfänger kann sie abrufen (src/lib/server/notifications.ts). Sie erscheinen über die Glocke im Header mit Zähler für Ungelesene und zusätzlich als Web Push, sofern das Gerät dafür angemeldet ist. Ausgelöst werden sie bei neuen Zuteilungen; weitere Anlässe lassen sich über notifyPerson() ergänzen.

Der persönliche Bereich ist über das Profilbild im Header erreichbar (Mein Bereich, Sicherheit, Abmelden).

Kalender-Abo

Jeder kann sich in Mein Bereich eine persönliche Kalender-Adresse erzeugen und im eigenen Kalender als Abo eintragen (/kalender/<token>.ics). Ausgeliefert werden ausschließlich die eigenen Zuteilungen; Termine mit Uhrzeit als Zeitpunkt, wochenbezogene wie die Reinigung als ganztägiger Eintrag.

Kalender-Apps können sich nicht anmelden, deshalb steckt die Berechtigung im Token der Adresse (user_account.calendar_token). Entsprechend gilt: nicht weitergeben. Über Neue Adresse erzeugen lässt sich das Token jederzeit austauschen, wodurch alte Abos ungültig werden. Die Route ist von der Anmeldepflicht ausgenommen, liefert aber nur bei gültigem Token Daten und ist für Suchmaschinen gesperrt.

Rückmeldung zu Zuteilungen

In Mein Bereich → Aufgaben kann jeder zu seinen Programmpunkten der Zusammenkunft antworten: Passt oder Geht nicht (mit optionalem Grund). Der Stand steht in meeting_part.confirmed_at / declined_at / decline_note.

  • Eine Absage benachrichtigt alle, die plan_midweek bearbeiten dürfen, sowie Administratoren (notifyEditorsOf) Zusagen erzeugen bewusst keine Benachrichtigung, sonst würde die Glocke im Alltag zulaufen.
  • Die Planungsansicht zeigt je Programmpunkt „zugesagt" bzw. „abgesagt" samt Grund.
  • Wird ein Punkt neu besetzt, wird die alte Rückmeldung verworfen sonst stünde bei der neuen Person die Zusage des Vorgängers.
  • Serverseitig wird geprüft, dass nur eigene Zuteilungen beantwortet werden können.

Daten: Import und Export

Einstellungen → Daten (settings-Recht):

  • Liederbuch importieren aus .xlsx oder .csv mit zwei Spalten (Nummer, Titel). Eine Kopfzeile wird erkannt, bestehende Nummern werden aktualisiert, ungültige Zeilen gemeldet statt still verworfen. Danach erscheint überall „Lied 123 Titel": Wochenplan, Wochenend-Plan und Druckansicht (src/lib/server/songs.ts).
  • Personen importieren aus .xlsx oder .csv. Die Spalten werden über die Kopfzeile erkannt (Vorname, Nachname, Geschlecht, Geburtsdatum, Taufdatum, Telefon, Mobil, E-Mail, Adresse, Stellung, Gruppe, Familie); ohne Kopfzeile gilt die Reihenfolge des Exports, sodass Export → Bearbeiten in Excel → Import zusammenpasst. Datumsangaben werden deutsch und in ISO-Form verstanden, die Stellung aus Klartext („Ältester, Allgemeiner Pionier"). Vorhandene Personen werden über Vor- und Nachnamen erkannt und aktualisiert. Ein Testlauf ist voreingestellt: er zeigt, wie viele Einträge neu und wie viele aktualisiert würden, ohne zu speichern. Zeilen mit Problemen werden einzeln gemeldet, nicht still verworfen. Verlangt das Bearbeitungsrecht auf Personendaten.
  • Export als CSV für Lieder und Personen mit Semikolon und BOM, damit Excel die Datei ohne Zwischenschritte richtig öffnet. Der Personen-Export verlangt zusätzlich das Leserecht auf Personendaten.

Der Tabellen-Leser (src/lib/server/import/tabular.ts) versteht .xlsx über ExcelJS und CSV über einen eigenen Parser, der Semikolon oder Komma erkennt und Anführungszeichen korrekt behandelt.

Für die Datenbank-Sicherung bleibt der Backup-Dienst des Compose-Stacks zuständig: täglich ein verschlüsselter pg_dump, 30 Tage Aufbewahrung.