- TypeScript 59.2%
- Svelte 39.6%
- CSS 0.7%
- JavaScript 0.2%
- Dockerfile 0.2%
- Other 0.1%
- 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) |
||
|---|---|---|
| .forgejo/workflows | ||
| docker | ||
| docs | ||
| drizzle | ||
| scripts | ||
| src | ||
| static | ||
| tests | ||
| .env.example | ||
| .gitignore | ||
| docker-compose.dev.yml | ||
| docker-compose.yml | ||
| drizzle.config.ts | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| svelte.config.js | ||
| tsconfig.json | ||
| vite.config.ts | ||
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/PRrelease.yml: bei Tagv*Multi-Arch-Image (amd64/arm64) → Forgejo-Registry- Release mit Stack-Paket (
docker-compose.yml+.env.example)
- Release mit Stack-Paket (
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
- ✅ Fundament: Auth, RBAC, Schema, Docker, CI
- ✅ Mitglieder: Personen, Gruppen, Notfallkontakte, individuelle Felder
- ✅ Sekretär: Berichte, Statusberechnung, Auswertung, S-21-Druck, Anwesenheit
- ✅ LuD: Wochenplanung, Empfehlung + Auto-Assign, S-140/S-89-Druckansichten
- ✅ PWA/Push: Service Worker, Mein-Bereich mit Berichtsabgabe, Push bei Zuteilung
- 🔶 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 insrc/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 periframe,Content-Disposition: inline), nicht als Download; daneben ein Knopf zum Öffnen in neuem Tab. Damit die Vorschau funktioniert, erlaubenX-Frame-Options: SAMEORIGINund die CSP-Direktivenframe-src/object-src/frame-ancestorsdas 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 mitsanitize-htmlgegen 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 alsbyteain 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.tslädt die Rechte einmal pro Anfrage nachlocals.permissions.- Jede
load- undaction-Funktion ruftrequirePermission(...)auf – lesende Zugriffe mitview, schreibende mitedit. Ohne Recht antwortet der Server mit 403. - Bereiche mit dem Recht ansehen zeigen einen Hinweis „Nur Ansicht" und legen alle Formulare
der Seite mit
inertstill – 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
adminhaben 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_midweekbearbeiten 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
.xlsxoder.csvmit 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
.xlsxoder.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.