Files
FireAdministration/.env.example
T

445 lines
22 KiB
Bash

# =============================================================================
# FLORIAN — Feuerwehr-Verwaltungsplattform
# Kopiere diese Datei nach ".env" und passe die Werte an:
# cp .env.example .env
# Alles, was hier steht, wird von docker-compose.yml und von lib/env.ts gelesen.
# lib/env.ts validiert beim Start mit Zod — fehlt eine Pflichtvariable, startet
# die App gar nicht erst, statt später halb zu funktionieren.
# =============================================================================
# -----------------------------------------------------------------------------
# Allgemein
# -----------------------------------------------------------------------------
# development | production | test — steuert Logging, Fehlerseiten und Caching.
NODE_ENV=development
# Öffentliche Basis-URL der Anwendung, ohne abschließenden Schrägstrich.
# Muss exakt der Adresse entsprechen, unter der Nutzer die App aufrufen —
# Auth.js baut daraus die OIDC-Redirect-URI.
APP_URL=http://localhost:3100
# Zeitzone für alle serverseitigen Fristen- und Terminberechnungen.
# Nicht ändern, außer die Wehr liegt außerhalb Deutschlands.
TZ=Europe/Berlin
# Host-Ports fuer die Entwicklung. Bewusst nicht die Standardports,
# damit FLORIAN neben anderen lokalen Stacks laufen kann.
APP_PORT=3100
GOTENBERG_PORT=3101
MAILPIT_UI_PORT=8125
MAILPIT_SMTP_PORT=1125
ADMINER_PORT=8081
# -----------------------------------------------------------------------------
# Traefik / Domains (nur für den Produktionsbetrieb relevant)
# In der Entwicklung greift docker-compose.override.yml und veröffentlicht die
# Dienste direkt auf localhost — Traefik wird dort nicht gebraucht.
# -----------------------------------------------------------------------------
# Hostname der Anwendung hinter Traefik, z. B. florian.beispielwehr.de
APP_DOMAIN=florian.localhost
# Hostname der MinIO-S3-API (Datei-Uploads, presignte URLs).
MINIO_DOMAIN=s3.florian.localhost
# Hostname der MinIO-Weboberfläche (Administration der Buckets).
MINIO_CONSOLE_DOMAIN=minio.florian.localhost
# Hostname des Traefik-Dashboards. Leer lassen, um es nicht zu veröffentlichen.
TRAEFIK_DASHBOARD_DOMAIN=traefik.florian.localhost
# E-Mail-Adresse für die ACME-Zertifikate (Let us Encrypt).
ACME_EMAIL=kommandant@beispielwehr.de
# Traefik-Entrypoint für HTTPS. "websecure" ist der Standard aus dieser Datei.
TRAEFIK_ENTRYPOINT=websecure
# -----------------------------------------------------------------------------
# PostgreSQL 17 + PostGIS
# -----------------------------------------------------------------------------
POSTGRES_USER=florian
# Vor dem ersten Start ersetzen: openssl rand -base64 24
POSTGRES_PASSWORD=bitte_aendern_postgres
POSTGRES_DB=florian
# Port, unter dem Postgres auf dem Host erreichbar ist (nur Entwicklung).
POSTGRES_PORT=5442
# Verbindungszeichenfolge der Anwendung. Läuft über den Datenbankbenutzer
# "florian_app", für den Row Level Security AKTIV ist — dieser Zugang sieht nur
# Daten der Organisation, die per SET LOCAL app.current_organisation gesetzt
# wurde (siehe src/lib/db.ts).
DATABASE_URL=postgresql://florian_app:bitte_aendern_app@postgres:5432/florian?schema=public
# Passwort des Anwendungsbenutzers. Muss zu DATABASE_URL passen und wird beim
# ersten Start von docker/postgres/10-init-app-role.sh gesetzt.
POSTGRES_APP_PASSWORD=bitte_aendern_app
# Verbindung für Migrationen und Seed. Nutzt den Eigentümer-Zugang, der RLS
# umgehen darf. Niemals im Anwendungscode verwenden.
DIRECT_DATABASE_URL=postgresql://florian:bitte_aendern_postgres@postgres:5432/florian?schema=public
# -----------------------------------------------------------------------------
# Redis (Warteschlangen für BullMQ, Rate-Limiting)
# -----------------------------------------------------------------------------
# Vor dem ersten Start ersetzen: openssl rand -base64 24
REDIS_PASSWORD=bitte_aendern_redis
REDIS_URL=redis://:bitte_aendern_redis@redis:6379
# Port auf dem Host (nur Entwicklung).
REDIS_PORT=6389
# Anzahl paralleler Jobs je Worker-Prozess.
WORKER_CONCURRENCY=5
# -----------------------------------------------------------------------------
# MinIO (S3-kompatibler Objektspeicher — ALLE Dateien liegen hier, nie im FS)
# -----------------------------------------------------------------------------
MINIO_ROOT_USER=florian
# Mindestens 8 Zeichen, vor dem ersten Start ersetzen.
MINIO_ROOT_PASSWORD=bitte_aendern_minio
# Endpunkt, den App und Worker intern ansprechen — im Compose-Netz der
# Dienstname, außerhalb der externe Hostname.
S3_ENDPOINT=minio
S3_PORT=9000
# true, sobald MinIO hinter Traefik mit TLS läuft.
S3_USE_SSL=false
S3_ACCESS_KEY=florian
S3_SECRET_KEY=bitte_aendern_minio
S3_REGION=eu-central-1
# Bucket für alle Nutzdateien (Prüfprotokolle, Fotos, Rechnungen, Exporte).
S3_BUCKET=florian
# Öffentlich erreichbare Basis-URL für presignte Download-Links. In der
# Entwicklung http://localhost:9010, in Produktion https://$MINIO_DOMAIN
S3_PUBLIC_URL=http://localhost:9010
# Gültigkeitsdauer presignter Links in Sekunden (Standard: 15 Minuten).
S3_URL_TTL=900
# Ports auf dem Host (nur Entwicklung): API und Weboberfläche.
MINIO_API_PORT=9010
MINIO_CONSOLE_PORT=9011
# -----------------------------------------------------------------------------
# Gotenberg (PDF-Erzeugung für Prüfprotokolle, Berichte, Rechnungen)
# -----------------------------------------------------------------------------
GOTENBERG_URL=http://gotenberg:3000
# Zeitlimit je PDF-Auftrag in Sekunden.
GOTENBERG_TIMEOUT=30
# -----------------------------------------------------------------------------
# Auth.js — Sitzungsverwaltung
# -----------------------------------------------------------------------------
# Signiert die Sitzungs-Cookies. Zwingend erforderlich, pro Installation neu:
# openssl rand -base64 32
AUTH_SECRET=bitte_aendern_mindestens_32_zeichen_lang
# Muss hinter einem Reverse Proxy (Traefik) auf true stehen, damit Auth.js die
# X-Forwarded-Header auswertet und korrekte Redirect-URIs erzeugt.
AUTH_TRUST_HOST=true
# Lebensdauer einer Sitzung in Sekunden (Standard: 8 Stunden).
AUTH_SESSION_MAX_AGE=28800
# -----------------------------------------------------------------------------
# OIDC gegen authentik
# Die authentik-Instanz wird SEPARAT betrieben und ist nicht Teil dieses Stacks.
# In authentik anzulegen: Provider "OAuth2/OpenID" (Client-Typ: confidential),
# Redirect-URI exakt $APP_URL/api/auth/callback/authentik
# Scopes: openid profile email — plus einen Gruppen-Scope, wenn Rollen aus
# authentik-Gruppen vorbelegt werden sollen (siehe AUTH_OIDC_GROUP_CLAIM).
# -----------------------------------------------------------------------------
# false blendet den OIDC-Knopf aus; dann bleibt nur der lokale Login. Sinnvoll
# für den Erststart, bevor authentik konfiguriert ist.
AUTH_OIDC_ENABLED=false
# Issuer-URL des Providers, OHNE /.well-known/openid-configuration.
# Bei authentik: https://<authentik-host>/application/o/<application-slug>/
AUTH_OIDC_ISSUER=https://auth.beispiel.de/application/o/florian/
AUTH_OIDC_CLIENT_ID=
AUTH_OIDC_CLIENT_SECRET=
# Beschriftung des Anmeldeknopfes in der Oberfläche.
AUTH_OIDC_NAME=Anmeldung über authentik
# Claim, aus dem die Gruppenzugehörigkeit gelesen wird. In authentik über ein
# Scope-Mapping bereitzustellen. Leer lassen, um das Mapping abzuschalten —
# dann werden Rollen ausschließlich in FLORIAN gepflegt.
AUTH_OIDC_GROUP_CLAIM=groups
# Zuordnung authentik-Gruppe -> FLORIAN-Rolle, kommagetrennt als "gruppe:ROLLE".
# Wirkt nur als VORBELEGUNG beim ersten Login; danach ist die in FLORIAN
# gepflegte Rolle führend und wird nicht mehr überschrieben.
AUTH_OIDC_GROUP_MAPPING=feuerwehr-kommandant:KOMMANDANT,feuerwehr-geraetewart:GERAETEWART,feuerwehr-atemschutz:ATEMSCHUTZGERAETEWART,feuerwehr-kassier:KASSIER,feuerwehr-schriftfuehrer:SCHRIFTFUEHRER,feuerwehr-ausbilder:AUSBILDER,feuerwehr-mitglied:MITGLIED
# true legt einen in authentik bekannten Nutzer beim ersten Login automatisch
# als Person an. false verlangt, dass die Person vorher in FLORIAN existiert
# und über die E-Mail-Adresse verknüpft wird.
AUTH_OIDC_AUTO_PROVISION=true
# Organisation (Slug), der automatisch angelegte Personen zugeordnet werden.
AUTH_OIDC_STANDARD_ORGANISATION=ff-musterhausen
# -----------------------------------------------------------------------------
# Lokaler E-Mail/Passwort-Login (Rückfalloption für Erststart und Notbetrieb)
# -----------------------------------------------------------------------------
# Nach der Einrichtung von authentik auf false setzen, damit nur noch OIDC geht.
AUTH_LOCAL_ENABLED=true
# Zugangsdaten des ersten Administrators, angelegt vom Seed-Skript.
# Nach dem ersten Login das Passwort in der Oberfläche ändern.
SEED_ADMIN_EMAIL=admin@beispielwehr.de
SEED_ADMIN_PASSWORT=Feuerwehr2026
# Das Konto der Kreisebene aus dem Beispielbestand (Phase 10): Mitglied in der
# eigenen Wehr, Aufsicht in der Nachbarwehr. Vorgabe leitet sich aus der
# Wehrkennung ab, also kbi@ff-musterhausen.de.
# SEED_KBI_EMAIL=
# SEED_KBI_PASSWORT=Feuerwehr2026
# bcrypt-Kostenfaktor. 12 ist ein guter Kompromiss aus Sicherheit und Tempo.
AUTH_BCRYPT_ROUNDS=12
# -----------------------------------------------------------------------------
# Terminal-/Kiosk-Anmeldung im Gerätehaus (PIN und RFID)
# -----------------------------------------------------------------------------
# Schaltet den Kiosk-Modus samt Terminal-Login frei.
KIOSK_ENABLED=true
# Gemeinsames Geheimnis, mit dem sich ein Terminal-Gerät gegenüber dem Server
# ausweist, bevor überhaupt eine PIN oder ein Token akzeptiert wird:
# openssl rand -hex 32
KIOSK_DEVICE_SECRET=bitte_aendern_kiosk_geheimnis
# Länge der Personen-PIN. 4 ist bequem, 6 ist sicherer.
KIOSK_PIN_LAENGE=6
# Nach wie vielen Fehlversuchen eine PIN gesperrt wird.
KIOSK_MAX_FEHLVERSUCHE=5
# Sperrdauer nach zu vielen Fehlversuchen, in Sekunden.
KIOSK_SPERRDAUER=300
# Automatische Abmeldung am Terminal nach Untätigkeit, in Sekunden.
KIOSK_IDLE_TIMEOUT=120
# -----------------------------------------------------------------------------
# Kartenmodule (Phase 6)
# -----------------------------------------------------------------------------
# FLORIAN laedt keine Kacheln aus dem Netz. Wo eine Wehr ausrueckt und wo ihre
# Hydranten liegen, ist niemandes Geschaeft — der Kartenserver laeuft selbst:
#
# docker compose --profile karte up -d
#
# Dafuer wird eine MBTiles-Datei des Ausrueckegebiets gebraucht (siehe README).
# Ohne KARTE_STIL_URL zeigt die Karte einen leeren Hintergrund mit Gitternetz;
# Hydranten, Objekte und Lagekarte funktionieren trotzdem.
KARTE_STIL_URL=http://localhost:8085/styles/basic/style.json
# Kartenmittelpunkt beim Oeffnen (Musterhausen).
KARTE_BREITENGRAD=48.5
KARTE_LAENGENGRAD=12.15
KARTE_ZOOM=13
# -----------------------------------------------------------------------------
# Atemschutz nach FwDV 7 (Phase 5)
# -----------------------------------------------------------------------------
# Der Sicherheitshinweis ueber jeder Ansicht der Atemschutzueberwachung:
# "Ergaenzendes System — die analoge Atemschutzueberwachung bleibt fuehrend."
# Er gehoert dorthin. Auf false setzen darf ihn nur, wer eine schriftliche
# Freigabe des Kommandanten hat — und deren Fundstelle gehoert in
# ATEMSCHUTZ_FREIGABE, sonst bleibt der Hinweis stehen.
ATEMSCHUTZ_HINWEIS=true
# Aktenzeichen oder Fundstelle der Freigabe, z. B. "Kommandantenbeschluss vom 12.03.2026".
ATEMSCHUTZ_FREIGABE=
# Abstand der Druckabfrage in Sekunden. FwDV 7 nennt keinen festen Wert;
# zehn Minuten sind die uebliche Praxis.
ATEMSCHUTZ_ABFRAGE_INTERVALL=600
# Ansprechdruck der Warneinrichtung in bar. Je nach Baujahr 50 bis 60.
ATEMSCHUTZ_WARNDRUCK=55
# Sicherheitszuschlag auf den errechneten Rueckzugsdruck, in bar.
ATEMSCHUTZ_ZUSCHLAG=10
# -----------------------------------------------------------------------------
# Wetterwarnungen auf dem Hallenmonitor (optional, DWD)
# Die einzige Verbindung nach draussen, die FLORIAN von sich aus aufbaut —
# deshalb standardmaessig aus. Ohne WETTER_ENABLED=true wird nichts abgerufen.
# -----------------------------------------------------------------------------
WETTER_ENABLED=false
# Warnzellen-Nummer der eigenen Gemeinde aus der DWD-Warnzellenliste:
# https://www.dwd.de/DE/leistungen/opendata/help/warnungen/cap_warncellids_csv.csv
DWD_WARNCELL=
DWD_WARNUNGEN_URL=https://www.dwd.de/DWD/warnungen/warnapp/json/warnings.json
# Zeitlimit fuer den Abruf, in Sekunden. Der Monitor darf davon nicht haengen.
WETTER_TIMEOUT=5
# Wie lange eine Antwort gilt, bevor neu gefragt wird, in Sekunden.
WETTER_ZWISCHENSPEICHER=300
# -----------------------------------------------------------------------------
# E-Mail-Versand (optional, hinter lib/integrations/mail.ts abstrahiert)
# Ohne MAIL_ENABLED=true wird nur ins Log geschrieben — praktisch für Tests.
# -----------------------------------------------------------------------------
MAIL_ENABLED=false
MAIL_HOST=smtp.beispiel.de
MAIL_PORT=587
MAIL_SECURE=false
MAIL_USER=
MAIL_PASSWORD=
MAIL_FROM=FLORIAN <florian@beispielwehr.de>
# -----------------------------------------------------------------------------
# Telegram-Benachrichtigungen (optional, abschaltbar)
# -----------------------------------------------------------------------------
TELEGRAM_ENABLED=false
TELEGRAM_BOT_TOKEN=
TELEGRAM_CHAT_ID=
# -----------------------------------------------------------------------------
# Push über ntfy (Phase 7, optional)
#
# ntfy ist ein winziger Push-Dienst, den man selbst betreibt: ein Container,
# eine App im Store, fertig. Man abonniert ein "Thema" (einen frei gewählten
# Namen) und bekommt Meldungen darauf — ohne Konto, ohne Telefonnummer.
#
# Läuft der Server im eigenen Netz, verlässt keine Nachricht das Gerätehaus.
# Deshalb gilt ntfy in FLORIAN als INTERNER Kanal und bekommt die
# ausführlichen Texte. Wer stattdessen das öffentliche ntfy.sh einträgt, macht
# ihn zu einem externen Dienst wie jeden anderen.
#
# ACHTUNG: Ein Thema ist nur so geheim wie sein Name. Wer ihn kennt, liest mit.
# FLORIAN schlägt deshalb Namen mit Zufallsanteil vor.
# -----------------------------------------------------------------------------
NTFY_ENABLED=false
# NTFY_URL=http://ntfy:80
# Nur nötig, wenn der eigene ntfy Zugriffsschutz eingeschaltet hat.
NTFY_TOKEN=
NTFY_TIMEOUT=10
# -----------------------------------------------------------------------------
# Web-Push in den Browser (Phase 7, optional)
#
# Der Weg, der ohne App auskommt. Die Meldung läuft über den Push-Dienst des
# Browserherstellers (Mozilla, Google, Apple) — verschlüsselt, aber sie
# verlässt das Netz der Wehr. Deshalb ist Web-Push ein EXTERNER Kanal und
# bekommt nur Kurzfassungen: "3 Prüfungen fällig", nicht welche.
#
# Schlüsselpaar erzeugen mit: npm run vapid
#
# ACHTUNG: Beide Schlüssel gehören ins Backup. Ein neuer öffentlicher Schlüssel
# macht alle bestehenden Push-Abos wertlos — jeder müsste Push neu erlauben,
# und niemand merkt es, die Meldungen bleiben einfach aus.
# -----------------------------------------------------------------------------
WEBPUSH_ENABLED=false
WEBPUSH_PUBLIC_KEY=
WEBPUSH_PRIVATE_KEY=
# Kontaktweg für den Push-Dienst, "mailto:..." oder eine Adresse.
WEBPUSH_KONTAKT=
# -----------------------------------------------------------------------------
# WhatsApp: bewusst NICHT.
#
# Es gibt keine WHATSAPP_-Variablen, und das ist eine Entscheidung, keine Lücke.
# Die Begründung steht im README unter "Warum kein WhatsApp" — kurz: die
# Business-Plattform kostet je Konversation, verlangt einen Vertrag mit Meta
# als Auftragsverarbeiter, und die App gleicht das Telefonbuch ab. Für eine
# Wehr, deren Daten im Gerätehaus bleiben sollen, ist das der falsche Weg.
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Benachrichtigungen und Termine (Phase 7)
# -----------------------------------------------------------------------------
# Wann der Worker die Erinnerungen anlegt und verschickt (cron, Europe/Berlin).
# Bewusst am frühen Morgen und nicht nachts: eine Push-Meldung um drei Uhr
# weckt Leute, die am nächsten Tag arbeiten müssen.
BENACHRICHTIGUNG_LAUF=0 7 * * *
# Wie viele Tage vor einem Termin erinnert wird (kommagetrennt).
# "7,1": einmal in der Woche davor, damit man den Abend freihalten kann, und
# einmal am Vortag, weil man es bis dahin wieder vergessen hat.
TERMIN_ERINNERUNG_TAGE=7,1
# Wie oft eine fehlgeschlagene Zustellung wiederholt wird, bevor sie als
# fehlgeschlagen stehen bleibt. Stehen bleiben ist Absicht: eine still
# verschluckte Benachrichtigung ist schlimmer als eine sichtbar gescheiterte.
BENACHRICHTIGUNG_VERSUCHE=3
# Wie lange ZUGESTELLTE Benachrichtigungen aufgehoben werden.
# Fehlgeschlagene bleiben — sie zeigen einen kaputten Kanal an.
BENACHRICHTIGUNG_AUFBEWAHRUNG_TAGE=90
# -----------------------------------------------------------------------------
# LLM-Anbindung (optional; nur selbstgehostete Endpunkte, kein Cloud-Zwang)
# -----------------------------------------------------------------------------
# ES GIBT KEINEN RUECKFALL AUF EINEN ANBIETER. Laeuft der eigene Endpunkt
# nicht, fehlen die KI-Funktionen — sie werden nicht durch einen fremden
# Dienst ersetzt. Ein Einsatzbericht spricht ueber Menschen in ihrer
# schlechtesten Stunde; solche Texte gehoeren nirgendwo anders hin.
#
# Container starten: docker compose --profile ki up -d
# Modelle holen: docker compose exec ollama ollama pull <modell>
LLM_ENABLED=false
# OpenAI-kompatibler Endpunkt, z. B. eine lokale Ollama- oder vLLM-Instanz.
LLM_BASE_URL=http://ollama:11434/v1
LLM_API_KEY=
LLM_MODELL=qwen2.5:14b
# Zeitlimit fuer eine Antwort. Ein Bericht darf dauern, aber nicht ewig.
LLM_TIMEOUT=120
# Modell fuer Einbettungen (semantische Suche im Wiki).
#
# ACHTUNG: Die Spalte wikiabschnitt.einbettung ist auf 768 Dimensionen
# festgelegt — das liefert nomic-embed-text. Ein Modell mit anderer Laenge
# braucht eine Migration; wie, steht im README unter Phase 8.
LLM_EINBETTUNG_MODELL=nomic-embed-text
LLM_EINBETTUNG_DIMENSIONEN=768
# Modell, das Bilder lesen kann — fuer die Belegerfassung. Ohne dieses Modell
# werden Belege trotzdem abgelegt, die Angaben nur von Hand eingetragen.
# LLM_VISION_MODELL=llama3.2-vision
# -----------------------------------------------------------------------------
# Spracherkennung fuers Diktat (Phase 8, optional)
#
# Selbst betriebener faster-whisper im Compose-Profil "ki". Groesse ueber
# WHISPER_MODELL: "tiny" laeuft auf jedem Buerorechner, "base" ist der
# brauchbare Kompromiss, "small" erkennt Fachbegriffe merklich besser und
# will dafuer Zeit oder eine Grafikkarte.
# -----------------------------------------------------------------------------
WHISPER_ENABLED=false
WHISPER_URL=http://whisper:8000
WHISPER_MODELL=base
WHISPER_SPRACHE=de
# Zeitlimit fuer eine Aufnahme. Zehn Minuten Sprache brauchen Zeit.
WHISPER_TIMEOUT=300
# Hoechstlaenge einer Aufnahme in Sekunden.
DIKTAT_MAX_SEKUNDEN=600
# -----------------------------------------------------------------------------
# Einsätze und Übungen (Phase 3)
# -----------------------------------------------------------------------------
# Adressen zu Koordinaten auflösen. Vorgesehen ist ein SELBST betriebener
# Nominatim — Einsatzadressen gehören nicht an einen öffentlichen Dienst, und
# dessen Nutzungsbedingungen erlauben es ohnehin nicht.
GEOCODING_ENABLED=false
# NOMINATIM_URL=http://nominatim:8080
GEOCODING_TIMEOUT=5
# Auf welche Länder die Suche eingegrenzt wird (ISO-Codes, kommagetrennt).
GEOCODING_LAENDER=de,at,ch
# Einsatzportal für Fremdwehren: ein signierter Link ohne Anmeldung, über den
# eine Nachbarwehr den Stand sieht und Lagemeldungen absetzen kann.
PORTAL_ENABLED=true
# Wie lange ein neu erzeugter Link gilt.
PORTAL_GUELTIGKEIT_STUNDEN=24
# Höchstzahl Zugriffe je Link und Stunde.
PORTAL_MAX_ZUGRIFFE=120
# -----------------------------------------------------------------------------
# Wartung und Prüfung (Phase 2)
# -----------------------------------------------------------------------------
# Wann der nächtliche Lauf Prüftermine plant. Cron-Syntax, Zeitzone
# Europe/Berlin. Der Worker trägt den Zeitplan beim Start je Wehr selbst ein.
WARTUNG_NACHTLAUF=15 3 * * *
# Wann die Erinnerungen verschickt werden. Bewusst nach der Planung: sonst
# erinnert der Lauf an Termine, die es noch gar nicht gibt.
WARTUNG_ERINNERUNG_LAUF=45 3 * * *
# Wie weit im Voraus Termine angelegt werden. Ohne Horizont stünden Termine für
# die nächsten zehn Jahre im Dashboard.
WARTUNG_PLANUNGSHORIZONT_TAGE=180
# -----------------------------------------------------------------------------
# Datenschutz und Aufbewahrung (DSGVO)
# -----------------------------------------------------------------------------
# Aufbewahrungsfrist für Einsatz- und Prüfdokumentation in Jahren.
AUFBEWAHRUNG_JAHRE=10
# Aufbewahrungsfrist für den Audit-Log in Tagen. Der Log ist append-only;
# Älteres wird vom Worker exportiert, bevor es entfernt wird.
AUDIT_AUFBEWAHRUNG_TAGE=3650
# Frist in Tagen, nach der ein ausgetretenes Mitglied anonymisiert wird.
PERSON_ANONYMISIERUNG_TAGE=365
# -----------------------------------------------------------------------------
# Telemetrie bleibt aus. Nicht ändern.
# -----------------------------------------------------------------------------
NEXT_TELEMETRY_DISABLED=1
CHECKPOINT_DISABLE=1
# -----------------------------------------------------------------------------
# Testwehr fuer die E2E-Tests
#
# Die Playwright-Tests laufen gegen eine EIGENE Wehr, nicht gegen die
# Beispielwehr aus der Anleitung. Sonst wachsen deren Listen bei jedem Lauf,
# und die Bildschirmfotos aendern sich, ohne dass sich die Oberflaeche
# geaendert haette.
#
# Vor dem Lauf einmal: npm run db:test-reset
# -----------------------------------------------------------------------------
E2E_SLUG=ff-teststelle
E2E_NAME=Freiwillige Feuerwehr Teststelle
E2E_KURZNAME=FF Teststelle
E2E_ADMIN_EMAIL=e2e@teststelle.de
E2E_ADMIN_PASSWORT=Feuerwehr2026