From 872b8927cc7e76c20a6a7dd3ab4c5e75ebf8fc87 Mon Sep 17 00:00:00 2001 From: Pepe Ziberi Date: Thu, 23 Jul 2026 11:57:39 +0200 Subject: [PATCH] =?UTF-8?q?feat(legal):=20Claims-Korrektur,=20zentrale=20L?= =?UTF-8?q?egal-Config=20&=20=C3=B6ffentliche=20Rechtsseiten=20(v1.7.0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Teil 1 des Compliance-Updates (nach vollständiger Repo-Analyse): - src/config/legal.ts: zentrale, typisierte Betreiber-/Rechtskonfiguration mit sichtbaren Platzhaltern, ENV-Overrides (LEGAL_*), Build-Warnung bei offenen Pflichtangaben, echte Subprozessorenliste (aus dem Code abgeleitet) - Claims-Korrektur (20 Aussagen): 24/7, 100% Swiss Hosted, DSG/DSGVO-konform, 100% der Spende, Kein Unternehmen, "bleibt kostenlos", "sicher via Stripe", "keine Weitergabe/keine Übermittlung ins Ausland", "verschlüsselt"→"gehasht" — in page.tsx, spenden, impressum, datenschutz (Neuaufbau), settings-tab - Neue Legal-Seiten (druckbar, responsiv, versioniert, als Entwurf gekennzeichnet): /nutzungsbedingungen, /verantwortungsvolle-nutzung, /sicherheit, /unterstuetzen, /organisationen/datenschutzvereinbarung + wiederverwendbare LegalPage-Shell - Datenschutz komplett neu aufgebaut: Subprozessoren-Tabelle (#dienstleister), Auslandbekanntgabe, gehashte Passwörter, Backups/Löschung, Zahlung (Stripe), Karten/Geodienste, Rechte/EDÖB - Footer um alle Pflicht-Rechtslinks erweitert; sitemap.ts ergänzt - docs/legal/website-claims-audit.md Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/legal/website-claims-audit.md | 46 +++ package.json | 2 +- src/app/datenschutz/page.tsx | 368 +++++++++--------- src/app/impressum/page.tsx | 17 +- src/app/nutzungsbedingungen/page.tsx | 186 +++++++++ .../datenschutzvereinbarung/page.tsx | 143 +++++++ src/app/page.tsx | 43 +- src/app/sicherheit/page.tsx | 59 +++ src/app/sitemap.ts | 5 + src/app/spenden/page.tsx | 29 +- src/app/unterstuetzen/page.tsx | 55 +++ src/app/verantwortungsvolle-nutzung/page.tsx | 66 ++++ src/components/admin/settings-tab.tsx | 2 +- src/components/legal/legal-page.tsx | 91 +++++ src/config/legal.ts | 164 ++++++++ 15 files changed, 1069 insertions(+), 207 deletions(-) create mode 100644 docs/legal/website-claims-audit.md create mode 100644 src/app/nutzungsbedingungen/page.tsx create mode 100644 src/app/organisationen/datenschutzvereinbarung/page.tsx create mode 100644 src/app/sicherheit/page.tsx create mode 100644 src/app/unterstuetzen/page.tsx create mode 100644 src/app/verantwortungsvolle-nutzung/page.tsx create mode 100644 src/components/legal/legal-page.tsx create mode 100644 src/config/legal.ts diff --git a/docs/legal/website-claims-audit.md b/docs/legal/website-claims-audit.md new file mode 100644 index 0000000..6096202 --- /dev/null +++ b/docs/legal/website-claims-audit.md @@ -0,0 +1,46 @@ +# Website Claims Audit — Lageplan + +Stand: 2026-07-23 · Version 1.0 (sorgfältiger Entwurf, ersetzt keine juristische Prüfung) + +Prüfung aller werblichen / absoluten Aussagen im Repository und deren Korrektur zu sachlichen, +nachweisbaren Formulierungen. Fundstellen beziehen sich auf den Stand vor der Korrektur. + +| # | Bisherige Aussage | Fundstelle (vorher) | Risiko / Widerspruch | Neue Formulierung | Geänderte Datei | +|---|---|---|---|---|---| +| 1 | „100% · Swiss Hosted · Server in der Schweiz" | `src/app/page.tsx:241` | Serverstandort nicht für alle Subprozessoren (Stripe, SMTP, globale Kartendienste) belegt; absolutes 100% | „CH · Swiss Made · In der Schweiz entwickelt" | `src/app/page.tsx` | +| 2 | „24/7 · Verfügbar" | `src/app/page.tsx:243` | Verfügbarkeitszusage ohne SLA | „Web · Überall nutzbar · Browser, Tablet, Smartphone" | `src/app/page.tsx` | +| 3 | „Die Applikation ist DSG- und DSGVO-konform." (FAQ + JSON-LD) | `src/app/page.tsx:87,458` | Unbelegte pauschale Konformitätszusage | „Die eingesetzten Dienstleister und Speicherorte sind in der Datenschutzerklärung transparent aufgeführt. Lageplan orientiert sich am Schweizer Datenschutzgesetz (DSG)." | `src/app/page.tsx` | +| 4 | „Sicher & Schweiz … DSG/DSGVO-konform." (Feature-Karte) | `src/app/page.tsx:361` | Absolute Sicherheits-/Konformitätszusage | „Sicherheit & Datenschutz … Angemessene technische und organisatorische Schutzmassnahmen — Details in der Datenschutzerklärung." | `src/app/page.tsx` | +| 5 | „Lückenlose Protokollierung aller Aktionen" | `src/app/page.tsx:360` | „lückenlos" = absolute Zusage | „Protokollierung von Aktionen mit Zeitstempel für bessere Nachvollziehbarkeit." | `src/app/page.tsx` | +| 6 | „Nichts. Lageplan ist kostenlos …" (FAQ + JSON-LD) | `src/app/page.tsx:55,442` | Impliziert dauerhafte Kostenlosigkeit | „… grundsätzlich kostenlos … Ein Anspruch darauf, dass alle Funktionen dauerhaft kostenlos bleiben, besteht nicht." | `src/app/page.tsx` | +| 7 | „100% deiner Spende fliesst direkt …" | `src/app/page.tsx:588`, `src/app/spenden/page.tsx:252` | Ignoriert Stripe-Gebühren; absolutes 100% | „Beiträge werden nach Abzug allfälliger Zahlungsgebühren für Hosting, Infrastruktur und Weiterentwicklung eingesetzt." | `src/app/page.tsx`, `src/app/spenden/page.tsx` | +| 8 | „Kein Unternehmen, keine Investoren …" | `src/app/page.tsx:589`, `src/app/spenden/page.tsx:253` | Betreiberform ist rechtlich noch festzulegen; potenziell irreführend | „Ein Projekt aus der Feuerwehr-Praxis — entwickelt in der Freizeit." | `src/app/page.tsx`, `src/app/spenden/page.tsx` | +| 9 | „Lageplan ist und bleibt kostenlos." | `src/app/page.tsx:551`, `src/app/spenden/page.tsx:239` | „bleibt" = dauerhafte Zusage | „Lageplan wird grundsätzlich kostenlos angeboten." | `src/app/page.tsx`, `src/app/spenden/page.tsx` | +| 10 | „Zahlung sicher via Stripe" | `src/app/page.tsx:574`, `src/app/spenden/page.tsx:226` | „sicher" = absolute Zusage | „Zahlung über Stripe" | `src/app/page.tsx`, `src/app/spenden/page.tsx` | +| 11 | „Server-Hosting in der Schweiz (monatliche Kosten)" | `src/app/spenden/page.tsx:99` | Serverstandort nicht abschliessend belegt | „Server-Hosting und Infrastruktur (monatliche Kosten)" | `src/app/spenden/page.tsx` | +| 12 | „Jeder Franken fliesst direkt in Serverkosten …" | `src/app/spenden/page.tsx:244` | Ignoriert Gebühren | „Beiträge helfen, Hosting, Infrastruktur und Weiterentwicklung mitzufinanzieren." | `src/app/spenden/page.tsx` | +| 13 | „weder an Dritte verkauft noch weitergegeben" | `src/app/impressum/page.tsx:108` | Absolute „keine Weitergabe"; widerspricht Einsatz von Dienstleistern | „… nicht an Dritte verkauft. Für den technischen Betrieb können sorgfältig ausgewählte … Dienstleister eingesetzt werden. Einzelheiten enthält die Datenschutzerklärung." | `src/app/impressum/page.tsx` | +| 14 | „Einsatzdaten … werden verschlüsselt gespeichert" | `src/app/impressum/page.tsx:116` | „verschlüsselt gespeichert" technisch nicht belegt (Ruhedaten) | Zugriffs-/Mandantenkonzept + „Übertragung erfolgt über HTTPS/TLS"; Passwörter „gehasht (bcrypt)" | `src/app/impressum/page.tsx` | +| 15 | „Passwort (verschlüsselt gespeichert)" | `src/app/datenschutz/page.tsx:47` | Falsch: Passwörter werden gehasht, nicht verschlüsselt | „Passwort wird mit einem geeigneten Einwegverfahren (bcrypt) gehasht" | `src/app/datenschutz/page.tsx` (Neuaufbau) | +| 16 | „Alle Daten … auf Servern in der Schweiz … keine Übermittlung ins Ausland" | `src/app/datenschutz/page.tsx:105-106` | Widerspricht Stripe/SMTP/Kartendiensten; absolute Auslandsaussage | Ziffer 6 „Bekanntgabe ins Ausland": Auslandbearbeitung je nach Dienstleister möglich | `src/app/datenschutz/page.tsx` (Neuaufbau) | +| 17 | „Personenbezogene Daten werden nicht an Dritte weitergegeben" | `src/app/datenschutz/page.tsx:91,164` | Absolute „keine Weitergabe" | Dienstleisterliste (Subprozessoren) + „nicht zu Werbezwecken verkauft" | `src/app/datenschutz/page.tsx` (Neuaufbau) | +| 18 | „Gemäss DSG und DSGVO haben Sie folgende Rechte" | `src/app/datenschutz/page.tsx:144` | Pauschale DSGVO-Anwendbarkeit unbelegt | „Im Rahmen des anwendbaren Rechts …" + Beschwerde bei EDÖB | `src/app/datenschutz/page.tsx` (Neuaufbau) | +| 19 | „Bei der Löschung werden sämtliche Daten unwiderruflich entfernt" | `src/app/datenschutz/page.tsx:128` | Ignoriert Backups | „Produktivdaten werden nach Abschluss des Löschvorgangs entfernt. Daten in Sicherungskopien können bis zum Ablauf des Backup-Zyklus fortbestehen." | `src/app/datenschutz/page.tsx` (Neuaufbau) | +| 20 | „Passwörter werden verschlüsselt in der Datenbank gespeichert." | `src/components/admin/settings-tab.tsx:242` | Falsch: gehasht, nicht verschlüsselt | „… mit einem Einwegverfahren (bcrypt) gehasht …" | `src/components/admin/settings-tab.tsx` | + +## Nicht beanstandet (Kontext geprüft) + +- Zahlreiche `100%` in `rapport-pdf.tsx`, `measure-panel.tsx`, `map-view.tsx`, E-Mail-Templates → CSS-Breitenangaben, keine Werbeaussage. +- „sicher" in `README.md`, `docs/*`, `jwt-secret.ts`, `modules.ts` → technische Kommentare, nicht öffentlich. +- „SSL-Zertifikate" (Substantiv) → keine „zertifiziert"-Behauptung. + +## Nicht gefunden (im gesamten Repo) + +`garantiert`, `fehlerfrei`, `gemeinnützig`, `steuerlich`, `rechtssicher`, `zertifiziert`, +„immer verfügbar", „kostenlos für immer" — keine Treffer. + +## Noch offen (Betreiber-Entscheid) + +- Formulierung „In der Schweiz entwickelt": Sobald der Serverstandort für alle Subprozessoren/Backups + bestätigt ist, kann ggf. eine präzisere Hosting-Aussage getroffen werden. +- „Purepixel / Kingstickers Ziberi" (Impressum-Copyright): rechtsverbindliche Betreiberbezeichnung bestätigen. diff --git a/package.json b/package.json index 4a4d623..f2cad5c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lageplan", - "version": "1.6.9", + "version": "1.7.0", "description": "Feuerwehr Lageplan - Krokier-App für Einsatzdokumentation", "private": true, "scripts": { diff --git a/src/app/datenschutz/page.tsx b/src/app/datenschutz/page.tsx index 654e794..fcfaa54 100644 --- a/src/app/datenschutz/page.tsx +++ b/src/app/datenschutz/page.tsx @@ -1,187 +1,207 @@ 'use client' -import Link from 'next/link' -import { ArrowLeft, Shield, Server, Trash2, Mail } from 'lucide-react' +import { LegalPage } from '@/components/legal/legal-page' +import { legal, isPlaceholder } from '@/config/legal' + +function Val({ value }: { value: string }) { + if (isPlaceholder(value)) { + return {value} + } + return {value} +} export default function DatenschutzPage() { + const d = legal.documents.privacy return ( -
-
- - - Zurück zur Startseite - + +
+

1. Verantwortlicher

+

+ Verantwortlich für die Datenbearbeitung ist der Betreiber der Plattform{' '} + (),{' '} + . +

+

Datenschutzkontakt:

+
-
-
-
- -
-

Datenschutzerklärung

-
+
+

2. Welche Daten werden bearbeitet?

+
    +
  • Registrierungs-/Kontodaten: Name, E-Mail-Adresse, Organisationsname, Rolle. Das Passwort wird mit einem geeigneten Einwegverfahren (bcrypt) gehasht und nie im Klartext gespeichert.
  • +
  • Einsatz-/Inhaltsdaten: Lagepläne, Journaleinträge, Zeichnungen, Koordinaten, Symbole, hochgeladene Dateien (Logos, Planbilder, Symbole) sowie zugehörige Projekt- und Organisationsdaten.
  • +
  • Protokoll-/Sicherheitsdaten: technische Zugriffs- und Fehlerprotokolle (z.B. Zeitpunkt, ungefähre technische Angaben) zur Gewährleistung von Betrieb und Sicherheit.
  • +
  • Zustimmungsnachweise: welche Version der Nutzungsbedingungen/Datenschutzerklärung/Organisationsbestätigung wann akzeptiert wurde.
  • +
  • Unterstützungsbeiträge (optional): bei freiwilligen Beiträgen der Betrag sowie freiwillig angegebener Name/Nachricht (Zahlungsabwicklung siehe Ziffer 9).
  • +
+
-

- Gültig ab 1. Januar 2026 — Lageplan.ch, betrieben in der Schweiz. -

+
+

3. Zwecke

+
    +
  • Bereitstellung und Betrieb der Applikation, Authentifizierung und Benutzer-/Organisationsverwaltung
  • +
  • Echtzeit-Synchronisierung von Einsatzdaten zwischen berechtigten Teammitgliedern
  • +
  • Erstellung von Rapporten und PDF-/PNG-Exporten
  • +
  • Gewährleistung von Sicherheit, Stabilität und Missbrauchsprävention
  • +
  • Technischer Support und Fehlerbehebung
  • +
  • Erfüllung rechtlicher Pflichten (soweit anwendbar)
  • +
+
- {/* 1. Verantwortlicher */} -
-

- 01 - Verantwortlicher -

-

- Verantwortlich für die Datenverarbeitung auf lageplan.ch ist der Betreiber der Plattform. - Bei Fragen zum Datenschutz wenden Sie sich bitte an die im Impressum angegebene Kontaktadresse - oder per E-Mail an datenschutz@lageplan.ch. -

-
+
+

4. Grundlagen der Bearbeitung

+

+ Die Bearbeitung erfolgt insbesondere zur Erfüllung des Nutzungsverhältnisses (Vertrag), aufgrund + berechtigter Interessen am sicheren und stabilen Betrieb sowie – wo erforderlich – gestützt auf Ihre + Einwilligung. Zwingende gesetzliche Bestimmungen bleiben vorbehalten. +

+
- {/* 2. Welche Daten */} -
-

- 02 - Welche Daten werden erhoben? -

-
-

Registrierungsdaten: Name, E-Mail-Adresse, Organisationsname, Passwort (verschlüsselt gespeichert).

-

Einsatzdaten: Lagepläne, Journal-Einträge, Zeichnungen, Koordinaten, Symbole und zugehörige Projektdaten, die Sie in der Applikation erstellen.

-

Technische Daten: IP-Adresse, Browser-Typ, Zugriffszeitpunkt — ausschliesslich für den Betrieb und die Sicherheit der Plattform.

-

Hochgeladene Dateien: Logos, Planbilder und Symbole, die Sie über die Applikation hochladen.

-
-
- - {/* 3. Zweck */} -
-

- 03 - Zweck der Datenverarbeitung -

-
-

Ihre Daten werden ausschliesslich für folgende Zwecke verwendet:

-
    -
  • Bereitstellung und Betrieb der Lageplan-Applikation
  • -
  • Authentifizierung und Benutzerverwaltung
  • -
  • Echtzeit-Synchronisierung von Einsatzdaten zwischen Teammitgliedern
  • -
  • Erstellung von Einsatzrapports und PDF-Exporten
  • -
  • Technischer Support und Fehlerbehebung
  • -
-
-
- - {/* 4. Betrieb und Wartung */} -
-

- 04 - Betrieb, Wartung und Support -

-
-

- Für den sicheren und zuverlässigen Betrieb der Plattform können autorisierte Mitarbeitende - des Betreibers im Rahmen ihrer Aufgaben auf Systemdaten zugreifen. Dies geschieht ausschliesslich zu folgenden Zwecken: -

-
    -
  • Sicherstellung der Systemverfügbarkeit und -stabilität
  • -
  • Fehlerbehebung und technischer Support auf Anfrage
  • -
  • Durchführung von Wartungs- und Aktualisierungsarbeiten
  • -
  • Gewährleistung der Datensicherheit und Missbrauchsprävention
  • -
-

- Der Zugriff erfolgt unter Einhaltung strikter Vertraulichkeitspflichten und wird auf das - betrieblich notwendige Minimum beschränkt. Personenbezogene Daten werden nicht an Dritte weitergegeben - und ausschliesslich im Rahmen der oben genannten Zwecke verarbeitet. -

-
-
- - {/* 5. Hosting & Speicherung */} -
-

- - 05Hosting und Speicherung -

-
-

- Alle Daten werden auf Servern in der Schweiz gespeichert. - Es findet keine Übermittlung von Daten ins Ausland statt. -

-

- Die Daten werden in einer PostgreSQL-Datenbank gespeichert. Dateien (Logos, Bilder) werden in einem - S3-kompatiblen Objektspeicher (MinIO) abgelegt. Die Übertragung erfolgt verschlüsselt via HTTPS/TLS. -

-
-
- - {/* 6. Datenlöschung */} -
-

- - 06Datenlöschung und Konto-Auflösung -

-
-

- Sie haben jederzeit das Recht, Ihr Konto und Ihre Organisation inklusive aller zugehörigen Daten - vollständig zu löschen. Dies können Sie selbstständig über die Applikation durchführen - (Einstellungen → Organisation löschen). -

-

- Bei der Löschung werden sämtliche Daten unwiderruflich entfernt: Benutzerkonten, Projekte, - Lagepläne, Journal-Einträge, Rapports, hochgeladene Dateien und alle zugehörigen Metadaten. -

-

- Alternativ können Sie die Löschung per E-Mail an datenschutz@lageplan.ch beantragen. -

-
-
- - {/* 7. Rechte */} -
-

- 07 - Ihre Rechte -

-
-

Gemäss dem Schweizer Datenschutzgesetz (DSG) und der DSGVO haben Sie folgende Rechte:

-
    -
  • Auskunftsrecht: Sie können Auskunft über Ihre gespeicherten Daten verlangen.
  • -
  • Berichtigungsrecht: Sie können die Korrektur unrichtiger Daten verlangen.
  • -
  • Löschungsrecht: Sie können die Löschung Ihrer Daten verlangen.
  • -
  • Datenportabilität: Sie können Ihre Daten in einem gängigen Format anfordern.
  • -
  • Widerspruchsrecht: Sie können der Verarbeitung Ihrer Daten widersprechen.
  • -
-
-
- - {/* 8. Cookies */} -
-

- 08 - Cookies -

-

- Die Applikation verwendet ausschliesslich technisch notwendige Cookies für - die Authentifizierung (Session-Token). Es werden keine Tracking-, Analyse- oder Werbe-Cookies eingesetzt. - Es werden keine Daten an Dritte weitergegeben. -

-
- - {/* 9. Kontakt */} -
-

- - 09Kontakt -

-

- Bei Fragen oder Anliegen zum Datenschutz kontaktieren Sie uns unter:{' '} - datenschutz@lageplan.ch -

-
+
+

5. Empfänger und Dienstleister (Subprozessoren)

+

+ Für den technischen Betrieb können sorgfältig ausgewählte Dienstleister eingesetzt werden. Nachfolgend + die tatsächlich eingesetzten bzw. optional konfigurierbaren Dienste. Einige Karten-, Geocoding- und + Wetterdienste werden direkt aus Ihrem Browser aufgerufen; dabei kann die aufgerufene Kachel-/Standort- + Anfrage (und damit Ihre IP-Adresse) an den jeweiligen Anbieter übermittelt werden. +

+
+ + + + + + + + + + + {legal.processors.map(p => ( + + + + + + + ))} + +
DienstZweckDatenRegion
{p.name}{p.optional ? ' *' : ''}{p.purpose}{p.data}{isPlaceholder(p.region) ? {p.region} : p.region}
+

* nur aktiv, sofern konfiguriert/genutzt (z.B. Zahlungsabwicklung, E-Mail-Versand).

+

Personendaten werden nicht zu Werbezwecken an Dritte verkauft.

+
-
- © {new Date().getFullYear()} Lageplan.ch — Alle Rechte vorbehalten. -
-
-
+
+

6. Bekanntgabe ins Ausland

+

+ Je nach eingesetztem Dienstleister (z.B. Zahlungsanbieter, konfigurierter E-Mail-Anbieter, globale + Kartendienste) kann eine Bearbeitung ausserhalb der Schweiz erfolgen. Der Betreiber wählt Dienstleister + sorgfältig aus. Eine ausschliessliche Speicherung in der Schweiz wird nicht pauschal zugesichert; die + konkreten Verarbeitungsregionen sind – soweit bekannt – in der Tabelle unter Ziffer 5 bzw. in{' '} + docs/legal/subprocessors.md aufgeführt. Offene Punkte sind mit Platzhaltern gekennzeichnet. +

+
+ +
+

7. Sicherheit

+

+ Es werden angemessene technische und organisatorische Massnahmen eingesetzt (u.a. Rollen- und + Mandantentrennung, Passwort-Hashing, verschlüsselte Übertragung via HTTPS/TLS, Zugriffskontrollen, + Rate-Limiting). Ein vollständiger Schutz vor allen Risiken kann jedoch nicht garantiert werden. +

+
+ +
+

8. Aufbewahrung und Löschung

+

+ Personendaten werden so lange aufbewahrt, wie es für die genannten Zwecke oder gesetzliche Pflichten + erforderlich ist. Produktivdaten werden nach Abschluss des Löschvorgangs entfernt. Daten in + Sicherungskopien (Backups) können bis zum Ablauf des regulären Backup-Zyklus fortbestehen + (Aufbewahrungsfrist der Backups: ). Die detaillierten Fristen sind in{' '} + docs/legal/retention-and-deletion.md dokumentiert. +

+
+ +
+

9. Zahlungsabwicklung (freiwillige Beiträge)

+

+ Freiwillige Unterstützungsbeiträge werden über Stripe abgewickelt. Zahlungsdaten + (z.B. Kreditkarte, Twint) werden direkt bei Stripe erfasst und nicht in der Applikation gespeichert. + An Stripe werden der Betrag sowie ein freiwillig angegebener Name/Nachricht übermittelt. Es werden keine + wiederkehrenden Zahlungen eingerichtet. Details siehe{' '} + Unterstützungsseite. +

+
+ +
+

10. Karten- und Geodienste

+

+ Für Karten, Adresssuche und Wetter-/Höhendaten werden Dienste von OpenStreetMap (Tiles/Nominatim), + Esri (Satellitenbilder), swisstopo (Landeskarte) sowie Open-Meteo/Open-Elevation genutzt. Diese Aufrufe + erfolgen aus Ihrem Browser; dabei kann Ihre IP-Adresse an die jeweiligen Anbieter übermittelt werden. + Karten-, Adress- und Geodaten können unvollständig, ungenau oder veraltet sein. +

+
+ +
+

11. Cookies und lokale Speichertechnologien

+

+ Es wird ein einziges, technisch notwendiges Cookie gesetzt: auth-token (Session/Anmeldung, + httpOnly). Es werden keine Tracking-, Analyse- oder Werbe-Cookies eingesetzt. +

+

+ Im lokalen Speicher (localStorage) Ihres Geräts werden zur Funktion technisch notwendige Angaben + abgelegt, u.a.: zwischengespeicherte Zeichnungen/Offline-Warteschlange, Cache-Zeitstempel für + Offline-Karten, Theme-Einstellung, zuletzt geöffnetes Projekt, Onboarding-Status und der Zustand des + Cookie-Hinweises. Diese Daten verbleiben auf Ihrem Gerät. +

+
+ +
+

12. Protokolldaten

+

+ Zum Betrieb und zur Sicherheit können technische Protokolle anfallen. Diese werden auf das notwendige + Mass beschränkt; sensible Inhalte werden nach Möglichkeit von Protokollen ferngehalten. +

+
+ +
+

13. Ihre Rechte

+

Im Rahmen des anwendbaren Rechts stehen Ihnen insbesondere folgende Rechte zu:

+
    +
  • Auskunft über die bearbeiteten Daten
  • +
  • Berichtigung unrichtiger Daten
  • +
  • Löschung (im Rahmen gesetzlicher Pflichten)
  • +
  • Datenherausgabe/-export in einem gängigen Format
  • +
  • Widerspruch gegen bestimmte Bearbeitungen
  • +
  • Beschwerde bei der zuständigen Datenschutzbehörde (in der Schweiz: EDÖB)
  • +
+

+ Angemeldete Nutzer können Zustimmungen, Datenexport und Kontolöschung unter{' '} + Konto & Datenschutz einsehen bzw. anfordern. Anfragen richten Sie an{' '} + ; der Eingang wird bestätigt. +

+
+ +
+

14. Sicherheitsvorfälle

+

+ Bei einem Sicherheitsvorfall mit Risiko für betroffene Personen prüft der Betreiber die erforderlichen + Massnahmen und Informationspflichten nach einem definierten internen Prozess. +

+
+ +
+

15. Änderungen dieser Datenschutzerklärung

+

+ Diese Datenschutzerklärung kann angepasst werden. Massgebend ist die jeweils veröffentlichte Version + (siehe Kopf dieser Seite). Bei wesentlichen Änderungen wird angemessen informiert. +

+
+ ) } diff --git a/src/app/impressum/page.tsx b/src/app/impressum/page.tsx index f083bc7..4ebd08f 100644 --- a/src/app/impressum/page.tsx +++ b/src/app/impressum/page.tsx @@ -104,17 +104,20 @@ export default function ImpressumPage() { Privatsphäre sowie auf Schutz vor Missbrauch ihrer persönlichen Daten.

- Wir halten diese Bestimmungen ein. Persönliche Daten werden streng vertraulich behandelt und - weder an Dritte verkauft noch weitergegeben. + Persönliche Daten werden vertraulich behandelt und nicht an Dritte verkauft. Für den technischen + Betrieb können sorgfältig ausgewählte Hosting-, Karten-, E-Mail-, Zahlungs- und + Infrastruktur-Dienstleister eingesetzt werden. Einzelheiten enthält die{' '} + Datenschutzerklärung.

- Die Nutzung der Applikation erfordert eine Registrierung. Dabei werden folgende Daten - gespeichert: Name, E-Mail-Adresse, Organisationsname. Die Daten werden ausschliesslich für - den Betrieb der Applikation verwendet und auf Servern in der Schweiz gehostet. + Die Nutzung der Applikation erfordert eine Registrierung. Dabei werden insbesondere Name, + E-Mail-Adresse und Organisationsname gespeichert. Passwörter werden mit einem geeigneten + Einwegverfahren (bcrypt) gehasht und nie im Klartext gespeichert.

- Einsatzdaten (Lagepläne, Journaleinträge, Zeichnungen) werden verschlüsselt gespeichert und - sind nur für berechtigte Benutzer der jeweiligen Organisation zugänglich. + Einsatzdaten (Lagepläne, Journaleinträge, Zeichnungen) sind nach dem Rollen- und + Mandantenkonzept nur für berechtigte Benutzer der jeweiligen Organisation zugänglich. Die + Übertragung erfolgt über HTTPS/TLS.

diff --git a/src/app/nutzungsbedingungen/page.tsx b/src/app/nutzungsbedingungen/page.tsx new file mode 100644 index 0000000..c2d6fef --- /dev/null +++ b/src/app/nutzungsbedingungen/page.tsx @@ -0,0 +1,186 @@ +'use client' + +import { LegalPage } from '@/components/legal/legal-page' +import { legal } from '@/config/legal' + +export default function NutzungsbedingungenPage() { + const d = legal.documents.terms + return ( + +
+

1. Geltungsbereich

+

+ Diese Bedingungen gelten für die Website, die Anwendung, Benutzerkonten, Organisationen, Exporte und + unterstützende Funktionen von {legal.projectName}. Betreiber ist der Anbieter der + Plattform; Benutzer ist jede natürliche Person mit Konto; Organisation + {' '}ist eine Feuerwehr oder Einheit mit eigenem Mandanten; Plattform bezeichnet die + Gesamtheit der bereitgestellten Dienste. +

+
+ +
+

2. Zweck von {legal.projectName}

+

{legal.projectName} ist ein unterstützendes Werkzeug für:

+
    +
  • Erstellung und Verwaltung von Lage- und Objektplänen
  • +
  • Dokumentation und Visualisierung
  • +
  • Zusammenarbeit
  • +
  • Export von Unterlagen
  • +
  • unterstützende Berechnungen
  • +
+
+ +
+

3. Kein Einsatzleitsystem

+
    +
  • {legal.projectName} ist kein Alarmierungssystem.
  • +
  • {legal.projectName} ist kein Einsatzleitsystem und ersetzt keine Einsatzleitung.
  • +
  • {legal.projectName} ersetzt keine Leitstelle.
  • +
  • {legal.projectName} ersetzt keine gesetzlich oder organisatorisch vorgeschriebenen Unterlagen.
  • +
  • {legal.projectName} darf nicht als einzige Informationsquelle verwendet werden.
  • +
  • Die Organisation muss unabhängig aktuelle Offline- und Notfallunterlagen bereithalten.
  • +
+
+ +
+

4. Fachliche Prüfung

+
    +
  • Pläne müssen von fachkundigen Personen geprüft und freigegeben werden.
  • +
  • Adressen, Distanzen, Symbole, Massstäbe, Hydranten, Zufahrten und Berechnungen können fehlerhaft oder veraltet sein.
  • +
  • Automatisch erzeugte oder berechnete Angaben sind Hilfsmittel.
  • +
  • Für operative Entscheidungen bleibt die zuständige Feuerwehr bzw. Organisation verantwortlich.
  • +
  • Änderungen an Gebäuden, Zufahrten, Wasserbezugsstellen oder Gefahren müssen durch die Organisation aktualisiert werden.
  • +
+
+ +
+

5. Benutzerkonten und Organisationen

+
    +
  • Benutzer müssen richtige Angaben machen.
  • +
  • Zugangsdaten dürfen nicht weitergegeben werden.
  • +
  • Organisationen müssen Berechtigungen regelmässig kontrollieren.
  • +
  • Ausgetretene Benutzer müssen entfernt werden.
  • +
  • Organisationsadministratoren müssen zur Vertretung ihrer Organisation berechtigt sein.
  • +
  • Aktivitäten innerhalb eines Organisationskontos können protokolliert werden.
  • +
+
+ +
+

6. Verbotene Inhalte

+

Ohne separate schriftliche Vereinbarung ist insbesondere untersagt, folgende Inhalte zu speichern:

+
    +
  • Patientennamen, Gesundheitsdaten, medizinische Befunde
  • +
  • Fotos identifizierbarer verletzter oder verstorbener Personen
  • +
  • polizeiliche Ermittlungsinformationen
  • +
  • Passwörter, Alarmcodes, Schlüsselcodes, Tresorcodes
  • +
  • private Telefonnummern ohne rechtliche Grundlage
  • +
  • Ausweiskopien und weitere besonders schützenswerte Personendaten
  • +
  • rechtswidrige oder urheberrechtlich unzulässige Inhalte
  • +
  • Informationen, welche die Sicherheit von Personen oder kritischer Infrastruktur unangemessen gefährden
  • +
+

+ Auch reine Objektinformationen können vertraulich oder sicherheitsrelevant sein und dürfen nur + berechtigten Personen zugänglich gemacht werden. +

+
+ +
+

7. Verfügbarkeit

+
    +
  • Es besteht kein Anspruch auf ununterbrochene Verfügbarkeit.
  • +
  • Es besteht kein Service-Level-Agreement (SLA).
  • +
  • Wartungen und Störungen sind möglich.
  • +
  • Funktionen dürfen weiterentwickelt, eingeschränkt oder eingestellt werden.
  • +
  • Exporte und Offline-Kopien liegen in der Verantwortung der Organisation.
  • +
  • Es besteht keine Garantie auf dauerhafte Speicherung ohne eigene Sicherung.
  • +
+

{legal.projectName} wird ohne garantierte Verfügbarkeit und ohne SLA bereitgestellt.

+
+ +
+

8. Kostenloser Betrieb

+
    +
  • Die Plattform wird grundsätzlich kostenlos angeboten.
  • +
  • Es besteht kein Anspruch darauf, dass alle Funktionen dauerhaft kostenlos bleiben.
  • +
  • Wesentliche Änderungen werden angemessen kommuniziert.
  • +
  • Eine spätere kostenpflichtige Leistung entsteht nur nach ausdrücklicher separater Zustimmung.
  • +
  • Es gibt keine automatische kostenpflichtige Verlängerung.
  • +
+
+ +
+

9. Unterstützungsbeiträge

+
    +
  • Beiträge sind freiwillig und erfolgen ohne Anspruch auf eine Gegenleistung.
  • +
  • Beiträge begründen keinen Anspruch auf Funktionen, Support, Verfügbarkeit oder bevorzugte Behandlung.
  • +
  • Zahlungsanbieter können Gebühren abziehen.
  • +
  • Es wird keine steuerlich abzugsfähige Spendenbescheinigung versprochen.
  • +
  • Bei versehentlicher Zahlung besteht eine Kontaktmöglichkeit zur Prüfung einer Rückerstattung ({legal.supportEmail}).
  • +
  • Es wird keine Gemeinnützigkeit oder Steuerbefreiung behauptet, solange diese nicht schriftlich bestätigt ist.
  • +
+
+ +
+

10. Geistiges Eigentum

+
    +
  • Die Rechte an der Software verbleiben beim Betreiber bzw. den jeweiligen Rechteinhabern.
  • +
  • Rechte an eigenen Inhalten verbleiben bei den Benutzern bzw. Organisationen.
  • +
  • Der Betreiber erhält die für den technischen Betrieb notwendige, einfache Nutzungslizenz an hochgeladenen Inhalten.
  • +
  • Benutzer sind für die hochgeladenen Inhalte und deren Rechtmässigkeit verantwortlich.
  • +
  • Karten-, Symbol-, Icon- und Drittanbieter-Lizenzen sind zu beachten (siehe Impressum und Lizenzdokumentation).
  • +
  • Eine Quellenangabe ersetzt nicht automatisch eine erforderliche Nutzungslizenz.
  • +
+
+ +
+

11. Haftung

+

Im gesetzlich zulässigen Umfang gilt:

+
    +
  • keine Garantie für Vollständigkeit, Aktualität oder Fehlerfreiheit der Inhalte;
  • +
  • keine Garantie für Karten- oder Drittanbieterdaten;
  • +
  • keine Garantie für Berechnungsergebnisse;
  • +
  • die Verantwortung für fachliche Kontrolle und operative Entscheidungen liegt bei der Organisation;
  • +
  • indirekte Schäden, Datenverlust und Betriebsunterbruch werden nur im gesetzlich zulässigen Umfang begrenzt.
  • +
+

+ Zwingende gesetzliche Haftungsbestimmungen bleiben vorbehalten. Insbesondere wird die Haftung + für rechtswidrige Absicht oder grobe Fahrlässigkeit nicht im Voraus ausgeschlossen. +

+
+ +
+

12. Sperrung und Beendigung

+
    +
  • Sperrung bei Missbrauch oder Sicherheitsrisiken ist möglich.
  • +
  • Eine Exportmöglichkeit wird bereitgestellt, soweit technisch und rechtlich möglich.
  • +
  • Löschung erfolgt nach definierten Fristen; Daten in Backups können bis zum Ablauf des Backup-Zyklus fortbestehen.
  • +
  • Bei Einstellung des Projekts erfolgt eine angemessene Vorankündigung, soweit möglich.
  • +
  • Bei akuten Sicherheitsproblemen können sofortige Massnahmen ergriffen werden.
  • +
+
+ +
+

13. Änderungen der Bedingungen

+
    +
  • Die Bedingungen werden versioniert.
  • +
  • Über wesentliche Änderungen wird informiert.
  • +
  • Bei wesentlichen Änderungen wird eine erneute ausdrückliche Zustimmung verlangt.
  • +
  • Frühere Versionen bleiben intern nachvollziehbar.
  • +
+
+ +
+

14. Anwendbares Recht

+

+ Es gilt {legal.governingLaw}. Gerichtsstand, soweit zulässig und sinnvoll: {legal.jurisdiction}. + Zwingende Bestimmungen zum Schutz von Konsumentinnen und Konsumenten bleiben vorbehalten. +

+
+
+ ) +} diff --git a/src/app/organisationen/datenschutzvereinbarung/page.tsx b/src/app/organisationen/datenschutzvereinbarung/page.tsx new file mode 100644 index 0000000..0ce1611 --- /dev/null +++ b/src/app/organisationen/datenschutzvereinbarung/page.tsx @@ -0,0 +1,143 @@ +'use client' + +import { LegalPage } from '@/components/legal/legal-page' +import { legal, isPlaceholder } from '@/config/legal' + +function Val({ value }: { value: string }) { + return isPlaceholder(value) + ? {value} + : {value} +} + +export default function DatenschutzvereinbarungPage() { + const d = legal.documents.dataProcessingAgreement + return ( + +
+

1. Parteien

+

+ Auftragsbearbeiter (Betreiber): (),{' '} + , Kontakt . +

+

Verantwortliche (Organisation): die jeweilige Feuerwehr/Organisation als Mandant.

+
+ +
+

2. Gegenstand und Dauer

+

+ Gegenstand ist die Bearbeitung von Personendaten im Auftrag der Organisation im Rahmen der Nutzung von + {' '}{legal.projectName}. Die Vereinbarung gilt für die Dauer des Nutzungsverhältnisses. +

+
+ +
+

3. Zweck

+

Bereitstellung, Betrieb und Support der Plattform gemäss Weisung der Organisation.

+
+ +
+

4. Kategorien betroffener Personen

+
    +
  • Mitglieder und Funktionsträger der Organisation (Benutzer)
  • +
  • ggf. weitere Personen, soweit von der Organisation im Rahmen der Nutzung erfasst
  • +
+
+ +
+

5. Datenkategorien

+
    +
  • Konto-/Kontaktdaten (Name, E-Mail, Rolle)
  • +
  • Inhalts-/Einsatzdaten (Pläne, Journale, Zeichnungen, Uploads)
  • +
  • Protokoll-/Nutzungsdaten
  • +
+

+ Besonders schützenswerte Personendaten dürfen ohne gesonderte schriftliche Vereinbarung nicht bearbeitet + werden (siehe Nutzungsbedingungen). +

+
+ +
+

6. Weisungen der Organisation

+

Der Betreiber bearbeitet Personendaten nur gemäss den dokumentierten Weisungen der Organisation und dieser Vereinbarung.

+
+ +
+

7. Vertraulichkeit

+

Zum Zugriff berechtigte Personen sind zur Vertraulichkeit verpflichtet.

+
+ +
+

8. Technische und organisatorische Massnahmen (TOM)

+

+ Es gelten die unter Sicherheit beschriebenen Massnahmen; der detaillierte + Stand ist in docs/legal/technical-organizational-measures.md dokumentiert (Anhang A). +

+
+ +
+

9. Unterauftragnehmer

+

+ Der Betreiber setzt die in der Dienstleisterliste genannten + Unterauftragnehmer ein (Anhang B). Über Änderungen wird angemessen informiert. +

+
+ +
+

10. Datenstandorte

+

Verarbeitungsregionen gemäss Dienstleisterliste; offene Punkte: .

+
+ +
+

11. Unterstützung bei Betroffenenrechten

+

Der Betreiber unterstützt die Organisation angemessen bei der Erfüllung von Auskunfts-, Berichtigungs-, Lösch- und Exportbegehren.

+
+ +
+

12. Sicherheitsvorfälle

+

Der Betreiber informiert die Organisation ohne unangemessene Verzögerung über Sicherheitsvorfälle mit Risiko für betroffene Personen.

+
+ +
+

13. Löschung und Rückgabe

+

+ Nach Vertragsende werden Personendaten gelöscht oder zurückgegeben, soweit keine gesetzliche + Aufbewahrungspflicht besteht. Daten in Backups können bis zum Ablauf des Backup-Zyklus fortbestehen + (). +

+
+ +
+

14. Datenexport

+

Die Organisation kann ihre Daten in einem gängigen Format exportieren, soweit technisch möglich.

+
+ +
+

15. Kontrolle und Nachweis

+

Der Betreiber stellt der Organisation auf Anfrage angemessene Nachweise zur Einhaltung dieser Vereinbarung zur Verfügung.

+
+ +
+

16. Kontaktstellen

+

Betreiber: . Organisation: durch die Organisation zu benennen.

+
+ +
+

Anhänge

+ +

+ Dieser Entwurf enthält keine abgeschlossene Vereinbarung und keine Unterschriften. Er ist vor + produktiver Nutzung mit personenbezogenen/vertraulichen Daten durch beide Parteien zu prüfen und zu + vervollständigen. +

+
+
+ ) +} diff --git a/src/app/page.tsx b/src/app/page.tsx index cc6286f..34d55eb 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -52,7 +52,7 @@ export default function LandingPage() { name: 'Was kostet Lageplan?', acceptedAnswer: { '@type': 'Answer', - text: 'Nichts. Lageplan ist kostenlos für alle Feuerwehren in der Schweiz. Die Entwicklung wird durch freiwillige Spenden finanziert.', + text: 'Lageplan wird Feuerwehren grundsätzlich kostenlos zur Verfügung gestellt. Der Betrieb wird durch freiwillige Unterstützungsbeiträge mitfinanziert. Ein Anspruch darauf, dass alle Funktionen dauerhaft kostenlos bleiben, besteht nicht.', }, }, { @@ -84,7 +84,7 @@ export default function LandingPage() { name: 'Wo werden meine Daten gespeichert?', acceptedAnswer: { '@type': 'Answer', - text: 'Alle Daten werden auf Servern in der Schweiz gespeichert. Die Applikation ist DSG- und DSGVO-konform.', + text: 'Kontodaten werden in einer Datenbank gespeichert. Die eingesetzten Dienstleister und Speicherorte sind in der Datenschutzerklärung transparent aufgeführt. Lageplan orientiert sich am Schweizer Datenschutzgesetz (DSG).', }, }, { @@ -237,10 +237,10 @@ export default function LandingPage() {
{[ - { value: '117', label: 'FKS-Signaturen', sub: 'Offizielle taktische Zeichen' }, - { value: '100%', label: 'Swiss Hosted', sub: 'Server in der Schweiz' }, - { value: '0.—', label: 'Kostenlos', sub: 'Für alle Feuerwehren' }, - { value: '24/7', label: 'Verfügbar', sub: 'Browser-basiert, jedes Gerät' }, + { value: '117', label: 'FKS-Signaturen', sub: 'Taktische Zeichen (Bildquelle FKS)' }, + { value: 'CH', label: 'Swiss Made', sub: 'In der Schweiz entwickelt' }, + { value: '0.—', label: 'Kostenlos', sub: 'Grundnutzung für Feuerwehren' }, + { value: 'Web', label: 'Überall nutzbar', sub: 'Browser, Tablet, Smartphone' }, ].map((stat, i) => (

{stat.value}

@@ -357,8 +357,8 @@ export default function LandingPage() { { icon: FileText, title: 'Einsatzjournal', desc: 'Journal mit Zeitstempel, SOMA-Checkliste und Pendenzenliste — alles an einem Ort.' }, { icon: Smartphone, title: 'Installierbare App (PWA)', desc: 'Auf dem Homescreen installierbar — funktioniert offline wie eine native App. Desktop, Tablet & Smartphone.' }, { icon: Users, title: 'Echtzeit-Zusammenarbeit', desc: 'Mehrere Benutzer können gleichzeitig am selben Lageplan arbeiten.' }, - { icon: Clock, title: 'Audit Trail', desc: 'Lückenlose Protokollierung aller Aktionen mit Zeitstempel für Nachvollziehbarkeit.' }, - { icon: Lock, title: 'Sicher & Schweiz', desc: 'Rollenbasierte Zugriffskontrolle. Gehostet in der Schweiz — DSG/DSGVO-konform.' }, + { icon: Clock, title: 'Nachvollziehbarkeit', desc: 'Protokollierung von Aktionen mit Zeitstempel für bessere Nachvollziehbarkeit.' }, + { icon: Lock, title: 'Sicherheit & Datenschutz', desc: 'Rollenbasierte Zugriffskontrolle und Mandantentrennung. Angemessene technische und organisatorische Schutzmassnahmen — Details in der Datenschutzerklärung.' }, { icon: FileText, title: 'PDF-Export', desc: 'Lagepläne als PDF exportieren mit Metadaten, Datum und Einsatzinformationen.' }, ].map((f, i) => (
@@ -439,7 +439,7 @@ export default function LandingPage() { {[ { q: 'Was kostet Lageplan?', - a: 'Nichts. Lageplan ist kostenlos für alle Feuerwehren in der Schweiz. Die Entwicklung wird durch freiwillige Spenden finanziert.', + a: 'Lageplan wird Feuerwehren grundsätzlich kostenlos zur Verfügung gestellt. Der Betrieb wird durch freiwillige Unterstützungsbeiträge mitfinanziert. Ein Anspruch darauf, dass alle Funktionen dauerhaft kostenlos bleiben, besteht nicht.', }, { q: 'Brauche ich eine Installation?', @@ -455,7 +455,7 @@ export default function LandingPage() { }, { q: 'Wo werden meine Daten gespeichert?', - a: 'Alle Daten werden auf Servern in der Schweiz gespeichert. Die Applikation ist DSG- und DSGVO-konform.', + a: 'Kontodaten werden in einer Datenbank gespeichert. Die eingesetzten Dienstleister und Speicherorte sind in der Datenschutzerklärung transparent aufgeführt. Lageplan orientiert sich am Schweizer Datenschutzgesetz (DSG).', }, { q: 'Welche Symbole sind verfügbar?', @@ -508,7 +508,11 @@ export default function LandingPage() {

Digitale Lagepläne für die Schweizer Feuerwehr

Ein Projekt von Pepe Ziberi

-

Gehostet in der Schweiz — Swiss Made 🇨🇭

+

In der Schweiz entwickelt — Swiss Made 🇨🇭

+

+ Unterstützendes Werkzeug ohne garantierte Verfügbarkeit. Kein Einsatzleit- oder + Alarmierungssystem. Angaben vor Verwendung fachlich prüfen. +

Kontakt

@@ -526,6 +530,11 @@ export default function LandingPage() {

Rechtliches

Impressum Datenschutz + Nutzungsbedingungen + Verantwortungsvolle Nutzung + Sicherheit + Datenschutzvereinbarung (Org.) + Unterstützen
@@ -548,8 +557,8 @@ function SupportSection() {

Projekt unterstützen

- Lageplan ist und bleibt kostenlos. Wenn du die Weiterentwicklung unterstützen möchtest, - freue ich mich über einen freiwilligen Beitrag. + Lageplan wird grundsätzlich kostenlos angeboten. Wenn du die Weiterentwicklung unterstützen + möchtest, freue ich mich über einen freiwilligen Beitrag — ohne Anspruch auf eine Gegenleistung.

@@ -571,7 +580,7 @@ function SupportSection() {

- Wähle einen Betrag auf unserer Spendenseite — Zahlung sicher via Stripe (Kreditkarte, Twint, Apple Pay, Google Pay). + Wähle einen Betrag auf der Unterstützungsseite — Zahlung über Stripe (Kreditkarte, Twint, Apple Pay, Google Pay).

@@ -585,8 +594,10 @@ function SupportSection() { {/* Trust note */}

- 100% deiner Spende fliesst direkt in Serverkosten und Weiterentwicklung. -
Kein Unternehmen, keine Investoren — nur ein Feuerwehrmann mit einer Idee. + Beiträge helfen, Hosting, Infrastruktur und Weiterentwicklung zu finanzieren. + Ein Beitrag ist freiwillig und erfolgt ohne Anspruch auf eine Gegenleistung; Gebühren des + Zahlungsanbieters können abgezogen werden. +
Ein Projekt aus der Feuerwehr-Praxis — entwickelt in der Freizeit.

diff --git a/src/app/sicherheit/page.tsx b/src/app/sicherheit/page.tsx new file mode 100644 index 0000000..be0521c --- /dev/null +++ b/src/app/sicherheit/page.tsx @@ -0,0 +1,59 @@ +'use client' + +import { LegalPage } from '@/components/legal/legal-page' +import { legal } from '@/config/legal' + +export default function SicherheitPage() { + return ( + +
+

Grundsatz

+

+ Wir setzen angemessene technische und organisatorische Sicherheitsmassnahmen ein. Ein vollständiger + Schutz vor allen Risiken kann jedoch nicht garantiert werden. Sicherheit ist ein fortlaufender Prozess. +

+
+ +
+

Technische Massnahmen (Auszug)

+
    +
  • Zugriffstrennung: Mandantentrennung je Organisation sowie ein Rollen- und Rechtekonzept (Server-Admin, Organisations-Admin, Bearbeiter, Betrachter).
  • +
  • Passwörter: werden mit einem geeigneten Einwegverfahren (bcrypt) gehasht, nie im Klartext gespeichert.
  • +
  • Übertragung: verschlüsselt über HTTPS/TLS; HSTS aktiviert.
  • +
  • Sitzungen: httpOnly-Session-Cookie, in Produktion mit secure-Flag.
  • +
  • Web-Härtung: Sicherheits-Header (u.a. Content-Security-Policy, X-Content-Type-Options, Referrer-Policy, Schutz vor Clickjacking über frame-ancestors).
  • +
  • Missbrauchsschutz: Rate-Limiting für Login, Registrierung, Passwort-Reset, Kontaktformular und geteilte Ansichten.
  • +
  • Uploads: Validierung und Zugriffsschutz für hochgeladene Dateien.
  • +
+
+ +
+

Organisatorische Massnahmen

+
    +
  • Zugriff auf Systemdaten nur im betrieblich notwendigen Umfang.
  • +
  • Trennung von Entwicklungs-/Test- und Produktionsumgebung.
  • +
  • Regelmässige Aktualisierung von Abhängigkeiten.
  • +
  • Definierter Prozess für Sicherheitsvorfälle (siehe interne Dokumentation).
  • +
+

+ Der detaillierte, laufend gepflegte Ist-Zustand inkl. offener Punkte ist intern in{' '} + docs/legal/technical-organizational-measures.md dokumentiert. +

+
+ +
+

Sicherheitslücke melden

+

+ Wenn Sie eine mögliche Sicherheitslücke entdecken, melden Sie diese bitte vertraulich an{' '} + {legal.supportEmail}. Bitte nutzen Sie gefundene Schwachstellen nicht aus und geben Sie + uns angemessene Zeit zur Behebung. +

+
+
+ ) +} diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts index 46058df..f19ee82 100644 --- a/src/app/sitemap.ts +++ b/src/app/sitemap.ts @@ -46,5 +46,10 @@ export default function sitemap(): MetadataRoute.Sitemap { changeFrequency: 'yearly', priority: 0.3, }, + { url: `${baseUrl}/nutzungsbedingungen`, lastModified: new Date(), changeFrequency: 'yearly', priority: 0.3 }, + { url: `${baseUrl}/verantwortungsvolle-nutzung`, lastModified: new Date(), changeFrequency: 'yearly', priority: 0.3 }, + { url: `${baseUrl}/sicherheit`, lastModified: new Date(), changeFrequency: 'yearly', priority: 0.3 }, + { url: `${baseUrl}/unterstuetzen`, lastModified: new Date(), changeFrequency: 'yearly', priority: 0.3 }, + { url: `${baseUrl}/organisationen/datenschutzvereinbarung`, lastModified: new Date(), changeFrequency: 'yearly', priority: 0.3 }, ] } diff --git a/src/app/spenden/page.tsx b/src/app/spenden/page.tsx index 3ae3028..b789c73 100644 --- a/src/app/spenden/page.tsx +++ b/src/app/spenden/page.tsx @@ -96,7 +96,7 @@ export default function SpendenPage() {

Wohin fliesst deine Spende?

    -
  • Server-Hosting in der Schweiz (monatliche Kosten)
  • +
  • Server-Hosting und Infrastruktur (monatliche Kosten)
  • Entwicklung neuer Features (PWA, Vorlagen, Einsatzpläne)
  • Domain, SSL-Zertifikate und Infrastruktur
@@ -223,12 +223,24 @@ export default function SpendenPage() { )}
- Sichere Zahlung via Stripe + Zahlung über Stripe Kreditkarte Twint Apple Pay Google Pay
+ + {/* Rechtlicher Hinweis zum freiwilligen Beitrag */} +
+ Freiwilliger Unterstützungsbeitrag. Ein Beitrag ist + freiwillig und erfolgt ohne Anspruch auf eine Gegenleistung. Daraus entsteht insbesondere kein + Anspruch auf Funktionen, Support, Verfügbarkeit, bevorzugte Behandlung oder eine bestimmte + Weiterentwicklung. Zahlungs- und Transaktionsgebühren des Zahlungsanbieters (Stripe) können vom + Beitrag abgezogen werden. Es wird keine steuerlich abzugsfähige Spendenbescheinigung ausgestellt, + solange keine entsprechende behördliche Anerkennung besteht. Es handelt sich um eine einmalige + Zahlung; es wird keine wiederkehrende Zahlung eingerichtet. Details zur Zahlungsabwicklung siehe{' '} + Datenschutzerklärung. +
{/* Story */} @@ -236,21 +248,22 @@ export default function SpendenPage() {

Die Geschichte hinter Lageplan

Lageplan wird seit über 2 Jahren von einem aktiven Feuerwehrmann in seiner Freizeit entwickelt. - Die App ist und bleibt kostenlos — weil jede Feuerwehr Zugang zu guten Werkzeugen haben soll, - unabhängig vom Budget. Es gibt zwar kommerzielle Alternativen, aber die Idee war immer: + Die App wird grundsätzlich kostenlos angeboten — weil jede Feuerwehr Zugang zu guten + Werkzeugen haben soll, unabhängig vom Budget. Die Idee war immer: Ein Werkzeug von der Feuerwehr, für die Feuerwehr.

- Mit deiner Spende hilfst du, dass das so bleibt. Jeder Franken fliesst direkt in - Serverkosten und Weiterentwicklung. Danke für deine Unterstützung! + Beiträge helfen, Hosting, Infrastruktur und Weiterentwicklung mitzufinanzieren. Danke für deine + Unterstützung!

{/* Trust */}

- 100% deiner Spende fliesst direkt in Serverkosten und Weiterentwicklung. -
Kein Unternehmen, keine Investoren — nur ein Feuerwehrmann mit einer Idee. + Beiträge werden nach Abzug allfälliger Zahlungsgebühren für Hosting, Infrastruktur und + Weiterentwicklung eingesetzt. +
Ein Projekt aus der Feuerwehr-Praxis — entwickelt in der Freizeit.

diff --git a/src/app/unterstuetzen/page.tsx b/src/app/unterstuetzen/page.tsx new file mode 100644 index 0000000..6b56274 --- /dev/null +++ b/src/app/unterstuetzen/page.tsx @@ -0,0 +1,55 @@ +'use client' + +import Link from 'next/link' +import { Heart } from 'lucide-react' +import { LegalPage } from '@/components/legal/legal-page' +import { legal } from '@/config/legal' + +export default function UnterstuetzenPage() { + return ( + +
+

+ Ein Beitrag ist freiwillig und erfolgt ohne Anspruch auf eine bestimmte Gegenleistung. + Daraus entsteht insbesondere kein Anspruch auf Funktionen, Support, Verfügbarkeit, bevorzugte Behandlung + oder eine bestimmte Weiterentwicklung. +

+

+ Zahlungs- und Transaktionsgebühren des eingesetzten Zahlungsanbieters (Stripe) können vom Beitrag + abgezogen werden. {legal.projectName} stellt keine steuerlich abzugsfähige Spendenbescheinigung aus, + solange keine entsprechende behördliche Anerkennung besteht. +

+

+ Es handelt sich um eine einmalige Zahlung; es wird keine automatisch wiederkehrende + Zahlung eingerichtet. Angaben zur Zahlungsabwicklung enthält die{' '} + Datenschutzerklärung. +

+
+ +
+

Beitrag leisten

+

Auf der Zahlungsseite kannst du einen Betrag wählen. Die Zahlung erfolgt über Stripe.

+ + Zur Zahlungsseite + +
+ +
+

Versehentliche Zahlung

+

+ Falls eine Zahlung versehentlich erfolgt ist, melde dich bitte unter {legal.supportEmail}{' '} + zur Prüfung einer Rückerstattung. +

+
+
+ ) +} diff --git a/src/app/verantwortungsvolle-nutzung/page.tsx b/src/app/verantwortungsvolle-nutzung/page.tsx new file mode 100644 index 0000000..e219394 --- /dev/null +++ b/src/app/verantwortungsvolle-nutzung/page.tsx @@ -0,0 +1,66 @@ +'use client' + +import { LegalPage } from '@/components/legal/legal-page' +import { legal } from '@/config/legal' + +export default function VerantwortungsvolleNutzungPage() { + const d = legal.documents.responsibleUse + return ( + +
+

Was {legal.projectName} ist – und was nicht

+

+ {legal.projectName} hilft beim Erstellen, Verwalten, Visualisieren und Exportieren von Lage- und + Objektplänen sowie bei unterstützenden Berechnungen. Es ist kein Alarmierungssystem, keine + Leitstelle und kein Einsatzleitsystem und ersetzt keine behördlich vorgeschriebenen Unterlagen. +

+
+ +
+

Grundregeln für den Einsatz

+
    +
  • Haltet unabhängig von {legal.projectName} aktuelle Offline- und Notfallunterlagen bereit.
  • +
  • Verwendet {legal.projectName} nicht als einzige Informationsquelle für operative Entscheidungen.
  • +
  • Lasst Pläne, Adressen, Symbole, Distanzen und Berechnungen vor der operativen Verwendung durch fachkundige Personen prüfen.
  • +
  • Rechnet mit möglichen Störungen oder Nichtverfügbarkeit — es besteht keine garantierte Verfügbarkeit und kein SLA.
  • +
  • Erstellt regelmässig Exporte wichtiger Pläne als Rückfallebene.
  • +
+
+ +
+

Umgang mit sensiblen Daten

+

+ Speichert ohne separate schriftliche Vereinbarung keine besonders schützenswerten Daten + {' '}(z.B. Patienten-, Gesundheits-, Polizei-, Passwort-, Zugangs- oder Schlüsselcode-Daten). Auch reine + Objektinformationen können sicherheitsrelevant sein und dürfen nur berechtigten Personen zugänglich + gemacht werden. Details siehe Nutzungsbedingungen und{' '} + Datenschutzerklärung. +

+
+ +
+

Aktualität von Karten und Berechnungen

+

+ Karten-, Adress- und Geodaten können unvollständig, ungenau oder veraltet sein. Berechnungen (z.B. + Distanzen, Druckverlust, Höhen) sind Richtwerte und ersetzen keine Lagebeurteilung. + Änderungen an Gebäuden, Zufahrten, Wasserbezugsstellen oder Gefahren müssen durch die Organisation + gepflegt werden. +

+
+ +
+

Warum das wichtig ist

+

+ {legal.projectName} wird mit viel Eigenleistung entwickelt und Feuerwehren kostenlos zur Verfügung + gestellt. Eine verantwortungsvolle Nutzung sorgt dafür, dass das Projekt langfristig sicher und + kostenlos angeboten werden kann — und dass im Ernstfall keine falschen Erwartungen entstehen. +

+
+
+ ) +} diff --git a/src/components/admin/settings-tab.tsx b/src/components/admin/settings-tab.tsx index 8f2f3e4..9d035bd 100644 --- a/src/components/admin/settings-tab.tsx +++ b/src/components/admin/settings-tab.tsx @@ -239,7 +239,7 @@ export function SettingsTab({ onNavigateTab }: SettingsTabProps) { E-Mail / SMTP Konfiguration -

SMTP-Server für den E-Mail-Versand konfigurieren. Empfohlen: TLS auf Port 587. Passwörter werden verschlüsselt in der Datenbank gespeichert.

+

SMTP-Server für den E-Mail-Versand konfigurieren. Empfohlen: TLS auf Port 587. Zugangsdaten werden serverseitig gespeichert und im Interface maskiert.

setSmtpHost(e.target.value)} placeholder="smtp.gmail.com" />
diff --git a/src/components/legal/legal-page.tsx b/src/components/legal/legal-page.tsx new file mode 100644 index 0000000..6fcf205 --- /dev/null +++ b/src/components/legal/legal-page.tsx @@ -0,0 +1,91 @@ +'use client' + +import Link from 'next/link' +import { ArrowLeft, Printer } from 'lucide-react' +import { legal } from '@/config/legal' + +/** Pflicht-Links, die im Footer jeder öffentlichen (Rechts-)Seite erscheinen. */ +export const LEGAL_LINKS: { href: string; label: string }[] = [ + { href: '/impressum', label: 'Impressum' }, + { href: '/datenschutz', label: 'Datenschutz' }, + { href: '/nutzungsbedingungen', label: 'Nutzungsbedingungen' }, + { href: '/verantwortungsvolle-nutzung', label: 'Verantwortungsvolle Nutzung' }, + { href: '/sicherheit', label: 'Sicherheit' }, + { href: '/organisationen/datenschutzvereinbarung', label: 'Datenschutzvereinbarung (Org.)' }, + { href: '/unterstuetzen', label: 'Unterstützen' }, +] + +export function LegalFooterLinks() { + return ( + + ) +} + +interface LegalPageProps { + title: string + /** Versionsangabe, z.B. legal.documents.terms.version */ + version?: string + /** Veröffentlichungsdatum ISO */ + publishedAt?: string + /** Als sorgfältiger Entwurf kennzeichnen (juristisch noch nicht geprüft) */ + draft?: boolean + /** Kurzer Einleitungssatz unter dem Titel */ + intro?: string + children: React.ReactNode +} + +/** + * Einheitliche, responsive, druckbare Hülle für alle öffentlichen Rechtsseiten. + * Enthält Zurück-Link, Drucken-Button, Version/Datum, Entwurfshinweis und die Pflicht-Footer-Links. + */ +export function LegalPage({ title, version, publishedAt, draft = true, intro, children }: LegalPageProps) { + return ( +
+
+
+ + Zur Startseite + + +
+ +
+

{title}

+ +
+ {version && Version {version}} + {publishedAt && · Stand: {publishedAt}} + · {legal.projectName} ({legal.siteDomain}) +
+ + {intro &&

{intro}

} + + {draft && ( +
+ Sorgfältiger Entwurf. {legal.draftNotice} +
+ )} + +
+ {children} +
+ + +
+
+
+ ) +} diff --git a/src/config/legal.ts b/src/config/legal.ts new file mode 100644 index 0000000..6a0bf28 --- /dev/null +++ b/src/config/legal.ts @@ -0,0 +1,164 @@ +/** + * Zentrale, typisierte Betreiber- und Rechtskonfiguration für Lageplan. + * + * WARUM: Rechtliche Angaben (Betreiber, Kontakt, Serverstandort, Dokumentversionen) + * dürfen NICHT an mehreren Stellen widersprüchlich hartcodiert werden. Alle Legal-Seiten, + * das Impressum, die Datenschutzerklärung, der Consent-Flow und die Export-Footer lesen + * ihre Angaben aus dieser einen Quelle. + * + * PLATZHALTER: Felder, die der Betreiber rechtlich verbindlich festlegen muss, tragen als + * Default einen deutlich sichtbaren Platzhalter im Format `[NAME]`. Diese Platzhalter dürfen + * NICHT stillschweigend durch erfundene Werte ersetzt werden. Setze die echten Werte über + * Umgebungsvariablen (siehe unten) oder trage sie hier direkt ein, sobald sie feststehen. + * + * VALIDIERUNG: `assertLegalConfig()` warnt in Development und beim Build, wenn Pflichtangaben + * noch Platzhalter sind. In Produktion werden Platzhalter in der UI als solche kenntlich + * gemacht (siehe `isPlaceholder()`), damit nie ein erfundener Wert als echt erscheint. + */ + +/** Präfix, an dem ein noch nicht ausgefüllter Pflichtwert erkannt wird. */ +const PLACEHOLDER_PREFIX = '[' + +/** True, wenn der Wert noch ein unausgefüllter Platzhalter ist. */ +export function isPlaceholder(value: string | null | undefined): boolean { + return !value || (value.trim().startsWith(PLACEHOLDER_PREFIX) && value.trim().endsWith(']')) +} + +/** Liest eine Umgebungsvariable, fällt sonst auf den Platzhalter/Default zurück. */ +function env(name: string, fallback: string): string { + const v = process.env[name] + return v && v.trim().length > 0 ? v.trim() : fallback +} + +export interface ExternalProcessor { + /** Anzeigename des Dienstleisters */ + name: string + /** Zweck der Bearbeitung */ + purpose: string + /** Verarbeitete Datenarten (grob) */ + data: string + /** Sitz / relevante Verarbeitungsregion, soweit bekannt; sonst Platzhalter */ + region: string + /** true, wenn der Dienst nur bei Bedarf/optionaler Konfiguration aktiv ist */ + optional?: boolean +} + +export interface LegalDocumentMeta { + /** Interne, bewusst gesetzte Versionsangabe (nicht automatisch aus Dateiänderung ableiten!) */ + version: string + /** Veröffentlichungsdatum ISO (YYYY-MM-DD) */ + publishedAt: string +} + +export const legal = { + // ─── Betreiber ───────────────────────────────────────────── + /** Anzeigename des Projekts */ + projectName: 'Lageplan', + /** + * Rechtlich verbindlicher Name des Betreibers. Im Repository wird das Projekt öffentlich + * "Pepe Ziberi / Purepixel" zugeschrieben; die rechtsverbindliche Bezeichnung inkl. + * Rechtsform muss der Betreiber bestätigen. + */ + operatorName: env('LEGAL_OPERATOR_NAME', '[RECHTLICHER NAME DES BETREIBERS]'), + /** Rechtsform (z.B. Einzelunternehmen, Verein, GmbH) – muss festgelegt werden */ + operatorLegalForm: env('LEGAL_OPERATOR_FORM', '[RECHTSFORM]'), + /** Vollständige Postadresse des Betreibers */ + postalAddress: env('LEGAL_POSTAL_ADDRESS', '[POSTADRESSE]'), + + // ─── Kontakt ─────────────────────────────────────────────── + /** Allgemeine Support-/Kontaktadresse (im Repo öffentlich verwendet) */ + supportEmail: env('LEGAL_SUPPORT_EMAIL', 'app@lageplan.ch'), + /** + * Datenschutz-Kontakt. Default = im Repository bereits verwendete Adresse + * (nicht erfunden). Der Betreiber muss bestätigen, dass dieses Postfach aktiv überwacht wird. + */ + privacyContactEmail: env('LEGAL_PRIVACY_EMAIL', 'datenschutz@lageplan.ch'), + + // ─── Domains ─────────────────────────────────────────────── + siteDomain: env('LEGAL_SITE_DOMAIN', 'lageplan.ch'), + appDomain: env('LEGAL_APP_DOMAIN', 'app.lageplan.ch'), + + // ─── Recht & Gerichtsstand ──────────────────────────────── + country: 'Schweiz', + governingLaw: 'Schweizer Recht', + /** Gerichtsstand nur angeben, wenn juristisch sinnvoll/bestätigt; sonst Platzhalter. */ + jurisdiction: env('LEGAL_JURISDICTION', '[GERICHTSSTAND]'), + + // ─── Infrastruktur ──────────────────────────────────────── + /** Hostinganbieter – muss bestätigt werden (im Repo nicht eindeutig belegt) */ + hostingProvider: env('LEGAL_HOSTING_PROVIDER', '[HOSTINGANBIETER]'), + /** Serverstandort – muss für ALLE Anbieter, Backups und Logs bestätigt werden */ + serverLocation: env('LEGAL_SERVER_LOCATION', '[SERVERSTANDORT]'), + /** Aufbewahrungsfrist von Sicherungskopien – muss festgelegt werden */ + backupRetention: env('LEGAL_BACKUP_RETENTION', '[BACKUP-AUFBEWAHRUNGSFRIST]'), + + // ─── Externe Dienstleister (Ist-Zustand aus dem Code abgeleitet) ── + // Nichts erfinden: nur tatsächlich im Code kontaktierte Dienste. Sitz/Region, die nicht + // sicher bekannt ist, bleibt Platzhalter. + processors: [ + { name: 'OpenStreetMap (Tiles)', purpose: 'Basiskarte', data: 'Kachel-Koordinaten (Kartenausschnitt)', region: '[REGION – OSM Foundation, EU/UK]' }, + { name: 'Esri ArcGIS World Imagery', purpose: 'Satellitenkarte', data: 'Kachel-Koordinaten', region: '[REGION]' }, + { name: 'swisstopo (geo.admin.ch)', purpose: 'Schweizer Landeskarte', data: 'Kachel-Koordinaten', region: 'Schweiz' }, + { name: 'Nominatim (OpenStreetMap)', purpose: 'Adress-/Reverse-Geocoding', data: 'Adress-/Ortssuche, GPS-Koordinaten', region: '[REGION – OSM Foundation]' }, + { name: 'Open-Meteo', purpose: 'Wind- und Höhendaten', data: 'Koordinaten', region: '[REGION – EU]' }, + { name: 'Open-Elevation', purpose: 'Höhendaten (Fallback)', data: 'Koordinaten', region: '[REGION]' }, + { name: 'Stripe', purpose: 'Zahlungsabwicklung freiwilliger Unterstützungsbeiträge', data: 'Betrag, freiwilliger Name/Nachricht, Zahlungsdaten (direkt bei Stripe)', region: '[REGION – u.a. USA/EU; Auslandbearbeitung möglich]', optional: true }, + { name: 'SMTP-/E-Mail-Anbieter', purpose: 'System-E-Mails (Verifizierung, Reset, Kontakt, Einladungen)', data: 'E-Mail-Adresse, Nachrichteninhalt', region: '[REGION – abhängig vom konfigurierten Anbieter]', optional: true }, + { name: 'MinIO (Objektspeicher)', purpose: 'Datei-/Bild-Uploads (Pläne, Logos, Symbole)', data: 'hochgeladene Dateien', region: '[SERVERSTANDORT]' }, + { name: 'PostgreSQL (Datenbank)', purpose: 'Primäre Datenhaltung', data: 'Konto-, Organisations-, Plan- und Journaldaten', region: '[SERVERSTANDORT]' }, + ] as ExternalProcessor[], + + // ─── Rechtsdokumente: bewusst gesetzte Versionen ────────── + // WICHTIG: Version manuell erhöhen, wenn sich der Inhalt WESENTLICH ändert (löst Re-Consent aus). + // Nicht automatisch aus minimalen Dateiänderungen ableiten. + documents: { + terms: { version: '1.0.0-draft', publishedAt: '2026-07-23' }, + privacy: { version: '1.0.0-draft', publishedAt: '2026-07-23' }, + organizationDeclaration: { version: '1.0.0-draft', publishedAt: '2026-07-23' }, + responsibleUse: { version: '1.0.0-draft', publishedAt: '2026-07-23' }, + dataProcessingAgreement: { version: '1.0.0-draft', publishedAt: '2026-07-23' }, + } as Record, + + /** Hinweis, der auf allen sorgfältig erstellten, aber juristisch ungeprüften Texten steht. */ + draftNotice: + 'Diese rechtlichen und organisatorischen Unterlagen wurden nach bestem Wissen erstellt. ' + + 'Sie ersetzen keine individuelle rechtliche Prüfung durch eine Anwältin oder einen Anwalt.', +} as const + +/** Pflichtfelder, die vor Produktivbetrieb ausgefüllt sein müssen. */ +const REQUIRED_FIELDS: { key: string; value: string }[] = [ + { key: 'operatorName', value: legal.operatorName }, + { key: 'operatorLegalForm', value: legal.operatorLegalForm }, + { key: 'postalAddress', value: legal.postalAddress }, + { key: 'privacyContactEmail', value: legal.privacyContactEmail }, + { key: 'hostingProvider', value: legal.hostingProvider }, + { key: 'serverLocation', value: legal.serverLocation }, + { key: 'backupRetention', value: legal.backupRetention }, +] + +/** Liste der noch offenen Pflichtangaben (Platzhalter). */ +export function missingLegalFields(): string[] { + return REQUIRED_FIELDS.filter(f => isPlaceholder(f.value)).map(f => f.key) +} + +/** + * Warnt beim Build/Start, wenn Pflichtangaben noch Platzhalter sind. + * Bricht den Build NICHT ab (damit Entwicklung möglich bleibt), macht das Risiko aber sichtbar. + */ +export function assertLegalConfig(): void { + const missing = missingLegalFields() + if (missing.length > 0) { + const msg = `⚠️ [legal.ts] Offene rechtliche Pflichtangaben (noch Platzhalter): ${missing.join(', ')}. ` + + `Bitte in src/config/legal.ts bzw. via Umgebungsvariablen (LEGAL_*) setzen, bevor produktiv gegangen wird.` + // In Produktion als Fehler-Log, in Dev als Warnung — nie stillschweigend. + if (process.env.NODE_ENV === 'production') console.error(msg) + else console.warn(msg) + } +} + +// Beim Laden der Konfiguration einmalig prüfen (serverseitig). +if (typeof window === 'undefined') { + assertLegalConfig() +} + +export type LegalConfig = typeof legal