feat(legal): Claims-Korrektur, zentrale Legal-Config & öffentliche Rechtsseiten (v1.7.0)
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) <noreply@anthropic.com>
This commit is contained in:
46
docs/legal/website-claims-audit.md
Normal file
46
docs/legal/website-claims-audit.md
Normal file
@@ -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.
|
||||
@@ -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": {
|
||||
|
||||
@@ -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 <span className="text-amber-600 dark:text-amber-400 font-medium">{value}</span>
|
||||
}
|
||||
return <span className="text-foreground font-medium">{value}</span>
|
||||
}
|
||||
|
||||
export default function DatenschutzPage() {
|
||||
const d = legal.documents.privacy
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900 px-4 py-12">
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<Link href="/" className="text-sm text-gray-400 hover:text-gray-300 inline-flex items-center gap-1 mb-8">
|
||||
<ArrowLeft className="w-3.5 h-3.5" />
|
||||
Zurück zur Startseite
|
||||
</Link>
|
||||
|
||||
<div className="bg-card rounded-xl shadow-2xl p-8 md:p-12 border border-border">
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="w-10 h-10 bg-red-600 rounded-full flex items-center justify-center">
|
||||
<Shield className="w-5 h-5 text-white" />
|
||||
</div>
|
||||
<h1 className="text-3xl font-bold text-foreground">Datenschutzerklärung</h1>
|
||||
</div>
|
||||
|
||||
<p className="text-muted-foreground mb-8">
|
||||
Gültig ab 1. Januar 2026 — Lageplan.ch, betrieben in der Schweiz.
|
||||
</p>
|
||||
|
||||
{/* 1. Verantwortlicher */}
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-foreground mb-3 flex items-center gap-2">
|
||||
<span className="text-red-500 font-mono text-sm">01</span>
|
||||
Verantwortlicher
|
||||
</h2>
|
||||
<p className="text-muted-foreground text-sm leading-relaxed">
|
||||
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 <span className="text-foreground font-medium">datenschutz@lageplan.ch</span>.
|
||||
<LegalPage
|
||||
title="Datenschutzerklärung"
|
||||
version={d.version}
|
||||
publishedAt={d.publishedAt}
|
||||
intro={`Diese Erklärung informiert transparent darüber, welche Personendaten ${legal.projectName} bearbeitet, zu welchem Zweck und wer daran beteiligt ist. Sie orientiert sich am Schweizer Datenschutzgesetz (DSG).`}
|
||||
>
|
||||
<section>
|
||||
<h2>1. Verantwortlicher</h2>
|
||||
<p>
|
||||
Verantwortlich für die Datenbearbeitung ist der Betreiber der Plattform{' '}
|
||||
<Val value={legal.operatorName} /> (<Val value={legal.operatorLegalForm} />),{' '}
|
||||
<Val value={legal.postalAddress} />.
|
||||
</p>
|
||||
<p><strong>Datenschutzkontakt:</strong> <Val value={legal.privacyContactEmail} /></p>
|
||||
</section>
|
||||
|
||||
{/* 2. Welche Daten */}
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-foreground mb-3 flex items-center gap-2">
|
||||
<span className="text-red-500 font-mono text-sm">02</span>
|
||||
Welche Daten werden erhoben?
|
||||
</h2>
|
||||
<div className="space-y-3 text-sm text-muted-foreground leading-relaxed">
|
||||
<p><strong className="text-foreground">Registrierungsdaten:</strong> Name, E-Mail-Adresse, Organisationsname, Passwort (verschlüsselt gespeichert).</p>
|
||||
<p><strong className="text-foreground">Einsatzdaten:</strong> Lagepläne, Journal-Einträge, Zeichnungen, Koordinaten, Symbole und zugehörige Projektdaten, die Sie in der Applikation erstellen.</p>
|
||||
<p><strong className="text-foreground">Technische Daten:</strong> IP-Adresse, Browser-Typ, Zugriffszeitpunkt — ausschliesslich für den Betrieb und die Sicherheit der Plattform.</p>
|
||||
<p><strong className="text-foreground">Hochgeladene Dateien:</strong> Logos, Planbilder und Symbole, die Sie über die Applikation hochladen.</p>
|
||||
</div>
|
||||
<section>
|
||||
<h2>2. Welche Daten werden bearbeitet?</h2>
|
||||
<ul>
|
||||
<li><strong>Registrierungs-/Kontodaten:</strong> Name, E-Mail-Adresse, Organisationsname, Rolle. Das Passwort wird mit einem geeigneten Einwegverfahren (bcrypt) gehasht und nie im Klartext gespeichert.</li>
|
||||
<li><strong>Einsatz-/Inhaltsdaten:</strong> Lagepläne, Journaleinträge, Zeichnungen, Koordinaten, Symbole, hochgeladene Dateien (Logos, Planbilder, Symbole) sowie zugehörige Projekt- und Organisationsdaten.</li>
|
||||
<li><strong>Protokoll-/Sicherheitsdaten:</strong> technische Zugriffs- und Fehlerprotokolle (z.B. Zeitpunkt, ungefähre technische Angaben) zur Gewährleistung von Betrieb und Sicherheit.</li>
|
||||
<li><strong>Zustimmungsnachweise:</strong> welche Version der Nutzungsbedingungen/Datenschutzerklärung/Organisationsbestätigung wann akzeptiert wurde.</li>
|
||||
<li><strong>Unterstützungsbeiträge (optional):</strong> bei freiwilligen Beiträgen der Betrag sowie freiwillig angegebener Name/Nachricht (Zahlungsabwicklung siehe Ziffer 9).</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
{/* 3. Zweck */}
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-foreground mb-3 flex items-center gap-2">
|
||||
<span className="text-red-500 font-mono text-sm">03</span>
|
||||
Zweck der Datenverarbeitung
|
||||
</h2>
|
||||
<div className="space-y-2 text-sm text-muted-foreground leading-relaxed">
|
||||
<p>Ihre Daten werden ausschliesslich für folgende Zwecke verwendet:</p>
|
||||
<ul className="list-disc pl-5 space-y-1">
|
||||
<li>Bereitstellung und Betrieb der Lageplan-Applikation</li>
|
||||
<li>Authentifizierung und Benutzerverwaltung</li>
|
||||
<li>Echtzeit-Synchronisierung von Einsatzdaten zwischen Teammitgliedern</li>
|
||||
<li>Erstellung von Einsatzrapports und PDF-Exporten</li>
|
||||
<section>
|
||||
<h2>3. Zwecke</h2>
|
||||
<ul>
|
||||
<li>Bereitstellung und Betrieb der Applikation, Authentifizierung und Benutzer-/Organisationsverwaltung</li>
|
||||
<li>Echtzeit-Synchronisierung von Einsatzdaten zwischen berechtigten Teammitgliedern</li>
|
||||
<li>Erstellung von Rapporten und PDF-/PNG-Exporten</li>
|
||||
<li>Gewährleistung von Sicherheit, Stabilität und Missbrauchsprävention</li>
|
||||
<li>Technischer Support und Fehlerbehebung</li>
|
||||
<li>Erfüllung rechtlicher Pflichten (soweit anwendbar)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* 4. Betrieb und Wartung */}
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-foreground mb-3 flex items-center gap-2">
|
||||
<span className="text-red-500 font-mono text-sm">04</span>
|
||||
Betrieb, Wartung und Support
|
||||
</h2>
|
||||
<div className="space-y-3 text-sm text-muted-foreground leading-relaxed">
|
||||
<section>
|
||||
<h2>4. Grundlagen der Bearbeitung</h2>
|
||||
<p>
|
||||
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:
|
||||
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.
|
||||
</p>
|
||||
<ul className="list-disc pl-5 space-y-1">
|
||||
<li>Sicherstellung der Systemverfügbarkeit und -stabilität</li>
|
||||
<li>Fehlerbehebung und technischer Support auf Anfrage</li>
|
||||
<li>Durchführung von Wartungs- und Aktualisierungsarbeiten</li>
|
||||
<li>Gewährleistung der Datensicherheit und Missbrauchsprävention</li>
|
||||
</section>
|
||||
|
||||
<section id="dienstleister" className="scroll-mt-20">
|
||||
<h2>5. Empfänger und Dienstleister (Subprozessoren)</h2>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-xs border-collapse mt-2">
|
||||
<thead>
|
||||
<tr className="text-left text-foreground border-b border-border">
|
||||
<th className="py-1.5 pr-3">Dienst</th>
|
||||
<th className="py-1.5 pr-3">Zweck</th>
|
||||
<th className="py-1.5 pr-3">Daten</th>
|
||||
<th className="py-1.5">Region</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{legal.processors.map(p => (
|
||||
<tr key={p.name} className="border-b border-border/50 align-top">
|
||||
<td className="py-1.5 pr-3 text-foreground font-medium">{p.name}{p.optional ? ' *' : ''}</td>
|
||||
<td className="py-1.5 pr-3">{p.purpose}</td>
|
||||
<td className="py-1.5 pr-3">{p.data}</td>
|
||||
<td className="py-1.5">{isPlaceholder(p.region) ? <span className="text-amber-600 dark:text-amber-400">{p.region}</span> : p.region}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p className="text-xs">* nur aktiv, sofern konfiguriert/genutzt (z.B. Zahlungsabwicklung, E-Mail-Versand).</p>
|
||||
<p>Personendaten werden nicht zu Werbezwecken an Dritte verkauft.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>6. Bekanntgabe ins Ausland</h2>
|
||||
<p>
|
||||
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{' '}
|
||||
<code>docs/legal/subprocessors.md</code> aufgeführt. Offene Punkte sind mit Platzhaltern gekennzeichnet.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>7. Sicherheit</h2>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>8. Aufbewahrung und Löschung</h2>
|
||||
<p>
|
||||
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: <Val value={legal.backupRetention} />). Die detaillierten Fristen sind in{' '}
|
||||
<code>docs/legal/retention-and-deletion.md</code> dokumentiert.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>9. Zahlungsabwicklung (freiwillige Beiträge)</h2>
|
||||
<p>
|
||||
Freiwillige Unterstützungsbeiträge werden über <strong>Stripe</strong> 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{' '}
|
||||
<a href="/unterstuetzen">Unterstützungsseite</a>.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>10. Karten- und Geodienste</h2>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>11. Cookies und lokale Speichertechnologien</h2>
|
||||
<p>
|
||||
Es wird ein einziges, technisch notwendiges Cookie gesetzt: <code>auth-token</code> (Session/Anmeldung,
|
||||
httpOnly). Es werden keine Tracking-, Analyse- oder Werbe-Cookies eingesetzt.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>12. Protokolldaten</h2>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>13. Ihre Rechte</h2>
|
||||
<p>Im Rahmen des anwendbaren Rechts stehen Ihnen insbesondere folgende Rechte zu:</p>
|
||||
<ul>
|
||||
<li><strong>Auskunft</strong> über die bearbeiteten Daten</li>
|
||||
<li><strong>Berichtigung</strong> unrichtiger Daten</li>
|
||||
<li><strong>Löschung</strong> (im Rahmen gesetzlicher Pflichten)</li>
|
||||
<li><strong>Datenherausgabe/-export</strong> in einem gängigen Format</li>
|
||||
<li><strong>Widerspruch</strong> gegen bestimmte Bearbeitungen</li>
|
||||
<li><strong>Beschwerde</strong> bei der zuständigen Datenschutzbehörde (in der Schweiz: EDÖB)</li>
|
||||
</ul>
|
||||
<p>
|
||||
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.
|
||||
Angemeldete Nutzer können Zustimmungen, Datenexport und Kontolöschung unter{' '}
|
||||
<a href="/konto/datenschutz">Konto & Datenschutz</a> einsehen bzw. anfordern. Anfragen richten Sie an{' '}
|
||||
<Val value={legal.privacyContactEmail} />; der Eingang wird bestätigt.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* 5. Hosting & Speicherung */}
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-foreground mb-3 flex items-center gap-2">
|
||||
<Server className="w-4 h-4 text-red-500" />
|
||||
<span><span className="text-red-500 font-mono text-sm mr-2">05</span>Hosting und Speicherung</span>
|
||||
</h2>
|
||||
<div className="space-y-2 text-sm text-muted-foreground leading-relaxed">
|
||||
<section>
|
||||
<h2>14. Sicherheitsvorfälle</h2>
|
||||
<p>
|
||||
Alle Daten werden auf Servern in der <strong className="text-foreground">Schweiz</strong> gespeichert.
|
||||
Es findet keine Übermittlung von Daten ins Ausland statt.
|
||||
Bei einem Sicherheitsvorfall mit Risiko für betroffene Personen prüft der Betreiber die erforderlichen
|
||||
Massnahmen und Informationspflichten nach einem definierten internen Prozess.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>15. Änderungen dieser Datenschutzerklärung</h2>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* 6. Datenlöschung */}
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-foreground mb-3 flex items-center gap-2">
|
||||
<Trash2 className="w-4 h-4 text-red-500" />
|
||||
<span><span className="text-red-500 font-mono text-sm mr-2">06</span>Datenlöschung und Konto-Auflösung</span>
|
||||
</h2>
|
||||
<div className="space-y-2 text-sm text-muted-foreground leading-relaxed">
|
||||
<p>
|
||||
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).
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
Alternativ können Sie die Löschung per E-Mail an <span className="text-foreground font-medium">datenschutz@lageplan.ch</span> beantragen.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* 7. Rechte */}
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-foreground mb-3 flex items-center gap-2">
|
||||
<span className="text-red-500 font-mono text-sm">07</span>
|
||||
Ihre Rechte
|
||||
</h2>
|
||||
<div className="space-y-2 text-sm text-muted-foreground leading-relaxed">
|
||||
<p>Gemäss dem Schweizer Datenschutzgesetz (DSG) und der DSGVO haben Sie folgende Rechte:</p>
|
||||
<ul className="list-disc pl-5 space-y-1">
|
||||
<li><strong className="text-foreground">Auskunftsrecht:</strong> Sie können Auskunft über Ihre gespeicherten Daten verlangen.</li>
|
||||
<li><strong className="text-foreground">Berichtigungsrecht:</strong> Sie können die Korrektur unrichtiger Daten verlangen.</li>
|
||||
<li><strong className="text-foreground">Löschungsrecht:</strong> Sie können die Löschung Ihrer Daten verlangen.</li>
|
||||
<li><strong className="text-foreground">Datenportabilität:</strong> Sie können Ihre Daten in einem gängigen Format anfordern.</li>
|
||||
<li><strong className="text-foreground">Widerspruchsrecht:</strong> Sie können der Verarbeitung Ihrer Daten widersprechen.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* 8. Cookies */}
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-foreground mb-3 flex items-center gap-2">
|
||||
<span className="text-red-500 font-mono text-sm">08</span>
|
||||
Cookies
|
||||
</h2>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed">
|
||||
Die Applikation verwendet ausschliesslich <strong className="text-foreground">technisch notwendige Cookies</strong> für
|
||||
die Authentifizierung (Session-Token). Es werden keine Tracking-, Analyse- oder Werbe-Cookies eingesetzt.
|
||||
Es werden keine Daten an Dritte weitergegeben.
|
||||
Diese Datenschutzerklärung kann angepasst werden. Massgebend ist die jeweils veröffentlichte Version
|
||||
(siehe Kopf dieser Seite). Bei wesentlichen Änderungen wird angemessen informiert.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{/* 9. Kontakt */}
|
||||
<section className="mb-4">
|
||||
<h2 className="text-xl font-semibold text-foreground mb-3 flex items-center gap-2">
|
||||
<Mail className="w-4 h-4 text-red-500" />
|
||||
<span><span className="text-red-500 font-mono text-sm mr-2">09</span>Kontakt</span>
|
||||
</h2>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed">
|
||||
Bei Fragen oder Anliegen zum Datenschutz kontaktieren Sie uns unter:{' '}
|
||||
<span className="text-foreground font-medium">datenschutz@lageplan.ch</span>
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div className="text-center mt-6 text-xs text-gray-500">
|
||||
© {new Date().getFullYear()} Lageplan.ch — Alle Rechte vorbehalten.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LegalPage>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -104,17 +104,20 @@ export default function ImpressumPage() {
|
||||
Privatsphäre sowie auf Schutz vor Missbrauch ihrer persönlichen Daten.
|
||||
</p>
|
||||
<p className="mt-2">
|
||||
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{' '}
|
||||
<a href="/datenschutz" className="text-red-600 hover:text-red-500">Datenschutzerklärung</a>.
|
||||
</p>
|
||||
<p className="mt-2">
|
||||
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.
|
||||
</p>
|
||||
<p className="mt-2">
|
||||
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.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
||||
186
src/app/nutzungsbedingungen/page.tsx
Normal file
186
src/app/nutzungsbedingungen/page.tsx
Normal file
@@ -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 (
|
||||
<LegalPage
|
||||
title="Nutzungsbedingungen"
|
||||
version={d.version}
|
||||
publishedAt={d.publishedAt}
|
||||
intro={`Diese Nutzungsbedingungen regeln die Nutzung von ${legal.projectName} (Website, Anwendung, Benutzerkonten, Organisationen, Exporte und unterstützende Funktionen).`}
|
||||
>
|
||||
<section>
|
||||
<h2>1. Geltungsbereich</h2>
|
||||
<p>
|
||||
Diese Bedingungen gelten für die Website, die Anwendung, Benutzerkonten, Organisationen, Exporte und
|
||||
unterstützende Funktionen von {legal.projectName}. <strong>Betreiber</strong> ist der Anbieter der
|
||||
Plattform; <strong>Benutzer</strong> ist jede natürliche Person mit Konto; <strong>Organisation</strong>
|
||||
{' '}ist eine Feuerwehr oder Einheit mit eigenem Mandanten; <strong>Plattform</strong> bezeichnet die
|
||||
Gesamtheit der bereitgestellten Dienste.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>2. Zweck von {legal.projectName}</h2>
|
||||
<p>{legal.projectName} ist ein unterstützendes Werkzeug für:</p>
|
||||
<ul>
|
||||
<li>Erstellung und Verwaltung von Lage- und Objektplänen</li>
|
||||
<li>Dokumentation und Visualisierung</li>
|
||||
<li>Zusammenarbeit</li>
|
||||
<li>Export von Unterlagen</li>
|
||||
<li>unterstützende Berechnungen</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>3. Kein Einsatzleitsystem</h2>
|
||||
<ul>
|
||||
<li>{legal.projectName} ist <strong>kein Alarmierungssystem</strong>.</li>
|
||||
<li>{legal.projectName} ist <strong>kein Einsatzleitsystem</strong> und ersetzt keine Einsatzleitung.</li>
|
||||
<li>{legal.projectName} ersetzt keine Leitstelle.</li>
|
||||
<li>{legal.projectName} ersetzt keine gesetzlich oder organisatorisch vorgeschriebenen Unterlagen.</li>
|
||||
<li>{legal.projectName} darf <strong>nicht als einzige Informationsquelle</strong> verwendet werden.</li>
|
||||
<li>Die Organisation muss unabhängig aktuelle <strong>Offline- und Notfallunterlagen</strong> bereithalten.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>4. Fachliche Prüfung</h2>
|
||||
<ul>
|
||||
<li>Pläne müssen von fachkundigen Personen geprüft und freigegeben werden.</li>
|
||||
<li>Adressen, Distanzen, Symbole, Massstäbe, Hydranten, Zufahrten und Berechnungen können fehlerhaft oder veraltet sein.</li>
|
||||
<li>Automatisch erzeugte oder berechnete Angaben sind Hilfsmittel.</li>
|
||||
<li>Für operative Entscheidungen bleibt die zuständige Feuerwehr bzw. Organisation verantwortlich.</li>
|
||||
<li>Änderungen an Gebäuden, Zufahrten, Wasserbezugsstellen oder Gefahren müssen durch die Organisation aktualisiert werden.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>5. Benutzerkonten und Organisationen</h2>
|
||||
<ul>
|
||||
<li>Benutzer müssen richtige Angaben machen.</li>
|
||||
<li>Zugangsdaten dürfen nicht weitergegeben werden.</li>
|
||||
<li>Organisationen müssen Berechtigungen regelmässig kontrollieren.</li>
|
||||
<li>Ausgetretene Benutzer müssen entfernt werden.</li>
|
||||
<li>Organisationsadministratoren müssen zur Vertretung ihrer Organisation berechtigt sein.</li>
|
||||
<li>Aktivitäten innerhalb eines Organisationskontos können protokolliert werden.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>6. Verbotene Inhalte</h2>
|
||||
<p>Ohne separate schriftliche Vereinbarung ist insbesondere untersagt, folgende Inhalte zu speichern:</p>
|
||||
<ul>
|
||||
<li>Patientennamen, Gesundheitsdaten, medizinische Befunde</li>
|
||||
<li>Fotos identifizierbarer verletzter oder verstorbener Personen</li>
|
||||
<li>polizeiliche Ermittlungsinformationen</li>
|
||||
<li>Passwörter, Alarmcodes, Schlüsselcodes, Tresorcodes</li>
|
||||
<li>private Telefonnummern ohne rechtliche Grundlage</li>
|
||||
<li>Ausweiskopien und weitere besonders schützenswerte Personendaten</li>
|
||||
<li>rechtswidrige oder urheberrechtlich unzulässige Inhalte</li>
|
||||
<li>Informationen, welche die Sicherheit von Personen oder kritischer Infrastruktur unangemessen gefährden</li>
|
||||
</ul>
|
||||
<p>
|
||||
Auch reine Objektinformationen können vertraulich oder sicherheitsrelevant sein und dürfen nur
|
||||
berechtigten Personen zugänglich gemacht werden.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>7. Verfügbarkeit</h2>
|
||||
<ul>
|
||||
<li>Es besteht kein Anspruch auf ununterbrochene Verfügbarkeit.</li>
|
||||
<li>Es besteht kein Service-Level-Agreement (SLA).</li>
|
||||
<li>Wartungen und Störungen sind möglich.</li>
|
||||
<li>Funktionen dürfen weiterentwickelt, eingeschränkt oder eingestellt werden.</li>
|
||||
<li>Exporte und Offline-Kopien liegen in der Verantwortung der Organisation.</li>
|
||||
<li>Es besteht keine Garantie auf dauerhafte Speicherung ohne eigene Sicherung.</li>
|
||||
</ul>
|
||||
<p>{legal.projectName} wird ohne garantierte Verfügbarkeit und ohne SLA bereitgestellt.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>8. Kostenloser Betrieb</h2>
|
||||
<ul>
|
||||
<li>Die Plattform wird grundsätzlich kostenlos angeboten.</li>
|
||||
<li>Es besteht kein Anspruch darauf, dass alle Funktionen dauerhaft kostenlos bleiben.</li>
|
||||
<li>Wesentliche Änderungen werden angemessen kommuniziert.</li>
|
||||
<li>Eine spätere kostenpflichtige Leistung entsteht nur nach ausdrücklicher separater Zustimmung.</li>
|
||||
<li>Es gibt keine automatische kostenpflichtige Verlängerung.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>9. Unterstützungsbeiträge</h2>
|
||||
<ul>
|
||||
<li>Beiträge sind freiwillig und erfolgen ohne Anspruch auf eine Gegenleistung.</li>
|
||||
<li>Beiträge begründen keinen Anspruch auf Funktionen, Support, Verfügbarkeit oder bevorzugte Behandlung.</li>
|
||||
<li>Zahlungsanbieter können Gebühren abziehen.</li>
|
||||
<li>Es wird keine steuerlich abzugsfähige Spendenbescheinigung versprochen.</li>
|
||||
<li>Bei versehentlicher Zahlung besteht eine Kontaktmöglichkeit zur Prüfung einer Rückerstattung ({legal.supportEmail}).</li>
|
||||
<li>Es wird keine Gemeinnützigkeit oder Steuerbefreiung behauptet, solange diese nicht schriftlich bestätigt ist.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>10. Geistiges Eigentum</h2>
|
||||
<ul>
|
||||
<li>Die Rechte an der Software verbleiben beim Betreiber bzw. den jeweiligen Rechteinhabern.</li>
|
||||
<li>Rechte an eigenen Inhalten verbleiben bei den Benutzern bzw. Organisationen.</li>
|
||||
<li>Der Betreiber erhält die für den technischen Betrieb notwendige, einfache Nutzungslizenz an hochgeladenen Inhalten.</li>
|
||||
<li>Benutzer sind für die hochgeladenen Inhalte und deren Rechtmässigkeit verantwortlich.</li>
|
||||
<li>Karten-, Symbol-, Icon- und Drittanbieter-Lizenzen sind zu beachten (siehe <a href="/impressum">Impressum</a> und Lizenzdokumentation).</li>
|
||||
<li>Eine Quellenangabe ersetzt nicht automatisch eine erforderliche Nutzungslizenz.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>11. Haftung</h2>
|
||||
<p>Im gesetzlich zulässigen Umfang gilt:</p>
|
||||
<ul>
|
||||
<li>keine Garantie für Vollständigkeit, Aktualität oder Fehlerfreiheit der Inhalte;</li>
|
||||
<li>keine Garantie für Karten- oder Drittanbieterdaten;</li>
|
||||
<li>keine Garantie für Berechnungsergebnisse;</li>
|
||||
<li>die Verantwortung für fachliche Kontrolle und operative Entscheidungen liegt bei der Organisation;</li>
|
||||
<li>indirekte Schäden, Datenverlust und Betriebsunterbruch werden nur im gesetzlich zulässigen Umfang begrenzt.</li>
|
||||
</ul>
|
||||
<p>
|
||||
<strong>Zwingende gesetzliche Haftungsbestimmungen bleiben vorbehalten. Insbesondere wird die Haftung
|
||||
für rechtswidrige Absicht oder grobe Fahrlässigkeit nicht im Voraus ausgeschlossen.</strong>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>12. Sperrung und Beendigung</h2>
|
||||
<ul>
|
||||
<li>Sperrung bei Missbrauch oder Sicherheitsrisiken ist möglich.</li>
|
||||
<li>Eine Exportmöglichkeit wird bereitgestellt, soweit technisch und rechtlich möglich.</li>
|
||||
<li>Löschung erfolgt nach definierten Fristen; Daten in Backups können bis zum Ablauf des Backup-Zyklus fortbestehen.</li>
|
||||
<li>Bei Einstellung des Projekts erfolgt eine angemessene Vorankündigung, soweit möglich.</li>
|
||||
<li>Bei akuten Sicherheitsproblemen können sofortige Massnahmen ergriffen werden.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>13. Änderungen der Bedingungen</h2>
|
||||
<ul>
|
||||
<li>Die Bedingungen werden versioniert.</li>
|
||||
<li>Über wesentliche Änderungen wird informiert.</li>
|
||||
<li>Bei wesentlichen Änderungen wird eine erneute ausdrückliche Zustimmung verlangt.</li>
|
||||
<li>Frühere Versionen bleiben intern nachvollziehbar.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>14. Anwendbares Recht</h2>
|
||||
<p>
|
||||
Es gilt {legal.governingLaw}. Gerichtsstand, soweit zulässig und sinnvoll: {legal.jurisdiction}.
|
||||
Zwingende Bestimmungen zum Schutz von Konsumentinnen und Konsumenten bleiben vorbehalten.
|
||||
</p>
|
||||
</section>
|
||||
</LegalPage>
|
||||
)
|
||||
}
|
||||
143
src/app/organisationen/datenschutzvereinbarung/page.tsx
Normal file
143
src/app/organisationen/datenschutzvereinbarung/page.tsx
Normal file
@@ -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)
|
||||
? <span className="text-amber-600 dark:text-amber-400 font-medium">{value}</span>
|
||||
: <span className="text-foreground font-medium">{value}</span>
|
||||
}
|
||||
|
||||
export default function DatenschutzvereinbarungPage() {
|
||||
const d = legal.documents.dataProcessingAgreement
|
||||
return (
|
||||
<LegalPage
|
||||
title="Datenschutzvereinbarung für Organisationen"
|
||||
version={d.version}
|
||||
publishedAt={d.publishedAt}
|
||||
intro="Entwurf einer Vereinbarung zur Auftragsbearbeitung – vor produktiver Nutzung mit personenbezogenen oder vertraulichen Organisationsdaten durch beide Parteien zu prüfen und zu vervollständigen."
|
||||
>
|
||||
<section>
|
||||
<h2>1. Parteien</h2>
|
||||
<p>
|
||||
<strong>Auftragsbearbeiter (Betreiber):</strong> <Val value={legal.operatorName} /> (<Val value={legal.operatorLegalForm} />),{' '}
|
||||
<Val value={legal.postalAddress} />, Kontakt <Val value={legal.privacyContactEmail} />.
|
||||
</p>
|
||||
<p><strong>Verantwortliche (Organisation):</strong> die jeweilige Feuerwehr/Organisation als Mandant.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>2. Gegenstand und Dauer</h2>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>3. Zweck</h2>
|
||||
<p>Bereitstellung, Betrieb und Support der Plattform gemäss Weisung der Organisation.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>4. Kategorien betroffener Personen</h2>
|
||||
<ul>
|
||||
<li>Mitglieder und Funktionsträger der Organisation (Benutzer)</li>
|
||||
<li>ggf. weitere Personen, soweit von der Organisation im Rahmen der Nutzung erfasst</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>5. Datenkategorien</h2>
|
||||
<ul>
|
||||
<li>Konto-/Kontaktdaten (Name, E-Mail, Rolle)</li>
|
||||
<li>Inhalts-/Einsatzdaten (Pläne, Journale, Zeichnungen, Uploads)</li>
|
||||
<li>Protokoll-/Nutzungsdaten</li>
|
||||
</ul>
|
||||
<p>
|
||||
Besonders schützenswerte Personendaten dürfen ohne gesonderte schriftliche Vereinbarung nicht bearbeitet
|
||||
werden (siehe <a href="/nutzungsbedingungen">Nutzungsbedingungen</a>).
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>6. Weisungen der Organisation</h2>
|
||||
<p>Der Betreiber bearbeitet Personendaten nur gemäss den dokumentierten Weisungen der Organisation und dieser Vereinbarung.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>7. Vertraulichkeit</h2>
|
||||
<p>Zum Zugriff berechtigte Personen sind zur Vertraulichkeit verpflichtet.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>8. Technische und organisatorische Massnahmen (TOM)</h2>
|
||||
<p>
|
||||
Es gelten die unter <a href="/sicherheit">Sicherheit</a> beschriebenen Massnahmen; der detaillierte
|
||||
Stand ist in <code>docs/legal/technical-organizational-measures.md</code> dokumentiert (Anhang A).
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>9. Unterauftragnehmer</h2>
|
||||
<p>
|
||||
Der Betreiber setzt die in der <a href="/datenschutz#dienstleister">Dienstleisterliste</a> genannten
|
||||
Unterauftragnehmer ein (Anhang B). Über Änderungen wird angemessen informiert.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>10. Datenstandorte</h2>
|
||||
<p>Verarbeitungsregionen gemäss Dienstleisterliste; offene Punkte: <Val value={legal.serverLocation} />.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>11. Unterstützung bei Betroffenenrechten</h2>
|
||||
<p>Der Betreiber unterstützt die Organisation angemessen bei der Erfüllung von Auskunfts-, Berichtigungs-, Lösch- und Exportbegehren.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>12. Sicherheitsvorfälle</h2>
|
||||
<p>Der Betreiber informiert die Organisation ohne unangemessene Verzögerung über Sicherheitsvorfälle mit Risiko für betroffene Personen.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>13. Löschung und Rückgabe</h2>
|
||||
<p>
|
||||
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
|
||||
(<Val value={legal.backupRetention} />).
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>14. Datenexport</h2>
|
||||
<p>Die Organisation kann ihre Daten in einem gängigen Format exportieren, soweit technisch möglich.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>15. Kontrolle und Nachweis</h2>
|
||||
<p>Der Betreiber stellt der Organisation auf Anfrage angemessene Nachweise zur Einhaltung dieser Vereinbarung zur Verfügung.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>16. Kontaktstellen</h2>
|
||||
<p>Betreiber: <Val value={legal.privacyContactEmail} />. Organisation: durch die Organisation zu benennen.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Anhänge</h2>
|
||||
<ul>
|
||||
<li><strong>Anhang A – TOM:</strong> <a href="/sicherheit">Sicherheit</a> / interne TOM-Dokumentation</li>
|
||||
<li><strong>Anhang B – Unterauftragnehmer:</strong> <a href="/datenschutz#dienstleister">Dienstleisterliste</a></li>
|
||||
</ul>
|
||||
<p className="text-xs">
|
||||
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.
|
||||
</p>
|
||||
</section>
|
||||
</LegalPage>
|
||||
)
|
||||
}
|
||||
@@ -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() {
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-6 md:gap-8">
|
||||
{[
|
||||
{ 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) => (
|
||||
<div key={i} className="text-center">
|
||||
<p className="text-3xl sm:text-4xl font-extrabold text-red-600">{stat.value}</p>
|
||||
@@ -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) => (
|
||||
<div key={i} className="bg-white rounded-xl p-6 border border-gray-100 hover:shadow-lg transition-shadow">
|
||||
@@ -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() {
|
||||
</div>
|
||||
<p className="text-sm text-gray-500">Digitale Lagepläne für die Schweizer Feuerwehr</p>
|
||||
<p className="text-sm text-gray-500 mt-1">Ein Projekt von Pepe Ziberi</p>
|
||||
<p className="text-sm text-gray-500">Gehostet in der Schweiz — Swiss Made 🇨🇭</p>
|
||||
<p className="text-sm text-gray-500">In der Schweiz entwickelt — Swiss Made 🇨🇭</p>
|
||||
<p className="text-xs text-gray-400 mt-2 max-w-xs">
|
||||
Unterstützendes Werkzeug ohne garantierte Verfügbarkeit. Kein Einsatzleit- oder
|
||||
Alarmierungssystem. Angaben vor Verwendung fachlich prüfen.
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-sm text-gray-500">
|
||||
<p className="font-medium text-gray-700 mb-2">Kontakt</p>
|
||||
@@ -526,6 +530,11 @@ export default function LandingPage() {
|
||||
<p className="font-medium text-gray-700 mb-2">Rechtliches</p>
|
||||
<Link href="/impressum" className="block hover:text-gray-700">Impressum</Link>
|
||||
<Link href="/datenschutz" className="block hover:text-gray-700 mt-1">Datenschutz</Link>
|
||||
<Link href="/nutzungsbedingungen" className="block hover:text-gray-700 mt-1">Nutzungsbedingungen</Link>
|
||||
<Link href="/verantwortungsvolle-nutzung" className="block hover:text-gray-700 mt-1">Verantwortungsvolle Nutzung</Link>
|
||||
<Link href="/sicherheit" className="block hover:text-gray-700 mt-1">Sicherheit</Link>
|
||||
<Link href="/organisationen/datenschutzvereinbarung" className="block hover:text-gray-700 mt-1">Datenschutzvereinbarung (Org.)</Link>
|
||||
<Link href="/unterstuetzen" className="block hover:text-gray-700 mt-1">Unterstützen</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-t border-gray-100 mt-8 pt-6 text-center space-y-1">
|
||||
@@ -548,8 +557,8 @@ function SupportSection() {
|
||||
<Coffee className="w-10 h-10 text-red-600 mx-auto mb-4" />
|
||||
<h2 className="text-3xl font-bold text-gray-900">Projekt unterstützen</h2>
|
||||
<p className="mt-3 text-lg text-gray-500 max-w-xl mx-auto">
|
||||
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.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -571,7 +580,7 @@ function SupportSection() {
|
||||
</div>
|
||||
|
||||
<p className="text-gray-500 mb-6">
|
||||
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).
|
||||
</p>
|
||||
|
||||
<Link href="/spenden">
|
||||
@@ -585,8 +594,10 @@ function SupportSection() {
|
||||
{/* Trust note */}
|
||||
<div className="mt-8 text-center">
|
||||
<p className="text-sm text-gray-500">
|
||||
100% deiner Spende fliesst direkt in Serverkosten und Weiterentwicklung.
|
||||
<br />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.
|
||||
<br />Ein Projekt aus der Feuerwehr-Praxis — entwickelt in der Freizeit.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
59
src/app/sicherheit/page.tsx
Normal file
59
src/app/sicherheit/page.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
'use client'
|
||||
|
||||
import { LegalPage } from '@/components/legal/legal-page'
|
||||
import { legal } from '@/config/legal'
|
||||
|
||||
export default function SicherheitPage() {
|
||||
return (
|
||||
<LegalPage
|
||||
title="Sicherheit"
|
||||
version={legal.documents.privacy.version}
|
||||
publishedAt={legal.documents.privacy.publishedAt}
|
||||
intro={`Übersicht über die technischen und organisatorischen Sicherheitsmassnahmen von ${legal.projectName}. Diese Darstellung ist allgemein gehalten; ein vollständiger Schutz vor allen Risiken kann nicht garantiert werden.`}
|
||||
>
|
||||
<section>
|
||||
<h2>Grundsatz</h2>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Technische Massnahmen (Auszug)</h2>
|
||||
<ul>
|
||||
<li><strong>Zugriffstrennung:</strong> Mandantentrennung je Organisation sowie ein Rollen- und Rechtekonzept (Server-Admin, Organisations-Admin, Bearbeiter, Betrachter).</li>
|
||||
<li><strong>Passwörter:</strong> werden mit einem geeigneten Einwegverfahren (bcrypt) gehasht, nie im Klartext gespeichert.</li>
|
||||
<li><strong>Übertragung:</strong> verschlüsselt über HTTPS/TLS; HSTS aktiviert.</li>
|
||||
<li><strong>Sitzungen:</strong> httpOnly-Session-Cookie, in Produktion mit <code>secure</code>-Flag.</li>
|
||||
<li><strong>Web-Härtung:</strong> Sicherheits-Header (u.a. Content-Security-Policy, <code>X-Content-Type-Options</code>, Referrer-Policy, Schutz vor Clickjacking über <code>frame-ancestors</code>).</li>
|
||||
<li><strong>Missbrauchsschutz:</strong> Rate-Limiting für Login, Registrierung, Passwort-Reset, Kontaktformular und geteilte Ansichten.</li>
|
||||
<li><strong>Uploads:</strong> Validierung und Zugriffsschutz für hochgeladene Dateien.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Organisatorische Massnahmen</h2>
|
||||
<ul>
|
||||
<li>Zugriff auf Systemdaten nur im betrieblich notwendigen Umfang.</li>
|
||||
<li>Trennung von Entwicklungs-/Test- und Produktionsumgebung.</li>
|
||||
<li>Regelmässige Aktualisierung von Abhängigkeiten.</li>
|
||||
<li>Definierter Prozess für Sicherheitsvorfälle (siehe interne Dokumentation).</li>
|
||||
</ul>
|
||||
<p className="text-xs">
|
||||
Der detaillierte, laufend gepflegte Ist-Zustand inkl. offener Punkte ist intern in{' '}
|
||||
<code>docs/legal/technical-organizational-measures.md</code> dokumentiert.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Sicherheitslücke melden</h2>
|
||||
<p>
|
||||
Wenn Sie eine mögliche Sicherheitslücke entdecken, melden Sie diese bitte vertraulich an{' '}
|
||||
<strong>{legal.supportEmail}</strong>. Bitte nutzen Sie gefundene Schwachstellen nicht aus und geben Sie
|
||||
uns angemessene Zeit zur Behebung.
|
||||
</p>
|
||||
</section>
|
||||
</LegalPage>
|
||||
)
|
||||
}
|
||||
@@ -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 },
|
||||
]
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ export default function SpendenPage() {
|
||||
<div>
|
||||
<h3 className="font-bold text-gray-900 mb-2">Wohin fliesst deine Spende?</h3>
|
||||
<ul className="space-y-2 text-sm text-gray-600">
|
||||
<li className="flex items-center gap-2"><Shield className="w-4 h-4 text-red-500 shrink-0" /> Server-Hosting in der Schweiz (monatliche Kosten)</li>
|
||||
<li className="flex items-center gap-2"><Shield className="w-4 h-4 text-red-500 shrink-0" /> Server-Hosting und Infrastruktur (monatliche Kosten)</li>
|
||||
<li className="flex items-center gap-2"><Sparkles className="w-4 h-4 text-red-500 shrink-0" /> Entwicklung neuer Features (PWA, Vorlagen, Einsatzpläne)</li>
|
||||
<li className="flex items-center gap-2"><Coffee className="w-4 h-4 text-red-500 shrink-0" /> Domain, SSL-Zertifikate und Infrastruktur</li>
|
||||
</ul>
|
||||
@@ -223,12 +223,24 @@ export default function SpendenPage() {
|
||||
)}
|
||||
|
||||
<div className="mt-4 flex flex-wrap items-center justify-center gap-3 text-xs text-gray-400">
|
||||
<span className="flex items-center gap-1"><Shield className="w-3.5 h-3.5" /> Sichere Zahlung via Stripe</span>
|
||||
<span className="flex items-center gap-1"><Shield className="w-3.5 h-3.5" /> Zahlung über Stripe</span>
|
||||
<span className="flex items-center gap-1"><Check className="w-3.5 h-3.5" /> Kreditkarte</span>
|
||||
<span className="flex items-center gap-1"><Check className="w-3.5 h-3.5" /> Twint</span>
|
||||
<span className="flex items-center gap-1"><Check className="w-3.5 h-3.5" /> Apple Pay</span>
|
||||
<span className="flex items-center gap-1"><Check className="w-3.5 h-3.5" /> Google Pay</span>
|
||||
</div>
|
||||
|
||||
{/* Rechtlicher Hinweis zum freiwilligen Beitrag */}
|
||||
<div className="mt-5 rounded-lg bg-gray-50 border border-gray-100 p-4 text-xs text-gray-500 leading-relaxed">
|
||||
<strong className="text-gray-700">Freiwilliger Unterstützungsbeitrag.</strong> 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{' '}
|
||||
<Link href="/datenschutz" className="text-red-600 underline">Datenschutzerklärung</Link>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Story */}
|
||||
@@ -236,21 +248,22 @@ export default function SpendenPage() {
|
||||
<h3 className="font-bold text-gray-900 mb-3">Die Geschichte hinter Lageplan</h3>
|
||||
<p className="text-sm text-gray-600 leading-relaxed">
|
||||
Lageplan wird seit über 2 Jahren von einem aktiven Feuerwehrmann in seiner Freizeit entwickelt.
|
||||
Die App ist und bleibt <strong>kostenlos</strong> — 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 <strong>grundsätzlich kostenlos</strong> angeboten — weil jede Feuerwehr Zugang zu guten
|
||||
Werkzeugen haben soll, unabhängig vom Budget. Die Idee war immer:
|
||||
Ein Werkzeug <em>von der Feuerwehr, für die Feuerwehr</em>.
|
||||
</p>
|
||||
<p className="text-sm text-gray-600 leading-relaxed mt-3">
|
||||
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!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Trust */}
|
||||
<div className="mt-8 text-center">
|
||||
<p className="text-sm text-gray-500">
|
||||
100% deiner Spende fliesst direkt in Serverkosten und Weiterentwicklung.
|
||||
<br />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.
|
||||
<br />Ein Projekt aus der Feuerwehr-Praxis — entwickelt in der Freizeit.
|
||||
</p>
|
||||
<div className="mt-6">
|
||||
<Link href="/">
|
||||
|
||||
55
src/app/unterstuetzen/page.tsx
Normal file
55
src/app/unterstuetzen/page.tsx
Normal file
@@ -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 (
|
||||
<LegalPage
|
||||
title="Freiwilliger Unterstützungsbeitrag"
|
||||
version={legal.documents.terms.version}
|
||||
publishedAt={legal.documents.terms.publishedAt}
|
||||
draft={false}
|
||||
intro={`${legal.projectName} wird grundsätzlich kostenlos angeboten. Freiwillige Beiträge helfen bei der Finanzierung von Hosting, Infrastruktur und Weiterentwicklung.`}
|
||||
>
|
||||
<section>
|
||||
<p>
|
||||
Ein Beitrag ist <strong>freiwillig</strong> und erfolgt ohne Anspruch auf eine bestimmte Gegenleistung.
|
||||
Daraus entsteht insbesondere kein Anspruch auf Funktionen, Support, Verfügbarkeit, bevorzugte Behandlung
|
||||
oder eine bestimmte Weiterentwicklung.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
Es handelt sich um eine <strong>einmalige Zahlung</strong>; es wird keine automatisch wiederkehrende
|
||||
Zahlung eingerichtet. Angaben zur Zahlungsabwicklung enthält die{' '}
|
||||
<a href="/datenschutz">Datenschutzerklärung</a>.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Beitrag leisten</h2>
|
||||
<p>Auf der Zahlungsseite kannst du einen Betrag wählen. Die Zahlung erfolgt über Stripe.</p>
|
||||
<Link
|
||||
href="/spenden"
|
||||
className="not-prose inline-flex items-center gap-2 rounded-lg bg-red-600 hover:bg-red-700 text-white px-5 py-2.5 font-semibold no-underline print:hidden"
|
||||
>
|
||||
<Heart className="w-4 h-4" /> Zur Zahlungsseite
|
||||
</Link>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Versehentliche Zahlung</h2>
|
||||
<p>
|
||||
Falls eine Zahlung versehentlich erfolgt ist, melde dich bitte unter <strong>{legal.supportEmail}</strong>{' '}
|
||||
zur Prüfung einer Rückerstattung.
|
||||
</p>
|
||||
</section>
|
||||
</LegalPage>
|
||||
)
|
||||
}
|
||||
66
src/app/verantwortungsvolle-nutzung/page.tsx
Normal file
66
src/app/verantwortungsvolle-nutzung/page.tsx
Normal file
@@ -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 (
|
||||
<LegalPage
|
||||
title="Verantwortungsvolle Nutzung"
|
||||
version={d.version}
|
||||
publishedAt={d.publishedAt}
|
||||
intro={`${legal.projectName} ist ein unterstützendes Werkzeug. Diese Seite erklärt, wie es sicher und verantwortungsvoll eingesetzt wird — damit es im Einsatz zu keinen Missverständnissen kommt.`}
|
||||
>
|
||||
<section>
|
||||
<h2>Was {legal.projectName} ist – und was nicht</h2>
|
||||
<p>
|
||||
{legal.projectName} hilft beim Erstellen, Verwalten, Visualisieren und Exportieren von Lage- und
|
||||
Objektplänen sowie bei unterstützenden Berechnungen. Es ist <strong>kein Alarmierungssystem, keine
|
||||
Leitstelle und kein Einsatzleitsystem</strong> und ersetzt keine behördlich vorgeschriebenen Unterlagen.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Grundregeln für den Einsatz</h2>
|
||||
<ul>
|
||||
<li>Haltet unabhängig von {legal.projectName} <strong>aktuelle Offline- und Notfallunterlagen</strong> bereit.</li>
|
||||
<li>Verwendet {legal.projectName} <strong>nicht als einzige Informationsquelle</strong> für operative Entscheidungen.</li>
|
||||
<li>Lasst Pläne, Adressen, Symbole, Distanzen und Berechnungen vor der operativen Verwendung durch <strong>fachkundige Personen prüfen</strong>.</li>
|
||||
<li>Rechnet mit möglichen Störungen oder Nichtverfügbarkeit — es besteht keine garantierte Verfügbarkeit und kein SLA.</li>
|
||||
<li>Erstellt regelmässig <strong>Exporte</strong> wichtiger Pläne als Rückfallebene.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Umgang mit sensiblen Daten</h2>
|
||||
<p>
|
||||
Speichert ohne separate schriftliche Vereinbarung <strong>keine besonders schützenswerten Daten</strong>
|
||||
{' '}(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 <a href="/nutzungsbedingungen">Nutzungsbedingungen</a> und{' '}
|
||||
<a href="/datenschutz">Datenschutzerklärung</a>.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Aktualität von Karten und Berechnungen</h2>
|
||||
<p>
|
||||
Karten-, Adress- und Geodaten können unvollständig, ungenau oder veraltet sein. Berechnungen (z.B.
|
||||
Distanzen, Druckverlust, Höhen) sind <strong>Richtwerte</strong> und ersetzen keine Lagebeurteilung.
|
||||
Änderungen an Gebäuden, Zufahrten, Wasserbezugsstellen oder Gefahren müssen durch die Organisation
|
||||
gepflegt werden.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Warum das wichtig ist</h2>
|
||||
<p>
|
||||
{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.
|
||||
</p>
|
||||
</section>
|
||||
</LegalPage>
|
||||
)
|
||||
}
|
||||
@@ -239,7 +239,7 @@ export function SettingsTab({ onNavigateTab }: SettingsTabProps) {
|
||||
<Mail className="w-5 h-5 text-primary" />
|
||||
E-Mail / SMTP Konfiguration
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground mb-4">SMTP-Server für den E-Mail-Versand konfigurieren. Empfohlen: TLS auf Port 587. Passwörter werden verschlüsselt in der Datenbank gespeichert.</p>
|
||||
<p className="text-sm text-muted-foreground mb-4">SMTP-Server für den E-Mail-Versand konfigurieren. Empfohlen: TLS auf Port 587. Zugangsdaten werden serverseitig gespeichert und im Interface maskiert.</p>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div><Label>SMTP Host</Label><Input value={smtpHost} onChange={e => setSmtpHost(e.target.value)} placeholder="smtp.gmail.com" /></div>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
|
||||
91
src/components/legal/legal-page.tsx
Normal file
91
src/components/legal/legal-page.tsx
Normal file
@@ -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 (
|
||||
<nav aria-label="Rechtliche Seiten" className="mt-10 border-t border-border pt-6 print:hidden">
|
||||
<ul className="flex flex-wrap gap-x-4 gap-y-2 text-sm text-muted-foreground">
|
||||
{LEGAL_LINKS.map(l => (
|
||||
<li key={l.href}>
|
||||
<Link href={l.href} className="hover:text-foreground underline underline-offset-2">{l.label}</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
|
||||
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 (
|
||||
<div className="min-h-screen bg-background px-4 py-10 print:py-0 print:bg-white">
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<div className="flex items-center justify-between mb-6 print:hidden">
|
||||
<Link href="/" className="text-sm text-muted-foreground hover:text-foreground inline-flex items-center gap-1">
|
||||
<ArrowLeft className="w-3.5 h-3.5" /> Zur Startseite
|
||||
</Link>
|
||||
<button
|
||||
onClick={() => window.print()}
|
||||
className="text-sm text-muted-foreground hover:text-foreground inline-flex items-center gap-1"
|
||||
>
|
||||
<Printer className="w-3.5 h-3.5" /> Drucken
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<article className="bg-card rounded-xl border border-border shadow-sm p-6 md:p-10 print:border-0 print:shadow-none print:p-0">
|
||||
<h1 className="text-3xl font-bold text-foreground">{title}</h1>
|
||||
|
||||
<div className="mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground">
|
||||
{version && <span>Version {version}</span>}
|
||||
{publishedAt && <span>· Stand: {publishedAt}</span>}
|
||||
<span>· {legal.projectName} ({legal.siteDomain})</span>
|
||||
</div>
|
||||
|
||||
{intro && <p className="mt-4 text-sm text-muted-foreground leading-relaxed">{intro}</p>}
|
||||
|
||||
{draft && (
|
||||
<div className="mt-4 rounded-lg border border-amber-300 bg-amber-50 dark:bg-amber-950/30 dark:border-amber-800 px-4 py-3 text-sm text-amber-800 dark:text-amber-300">
|
||||
<strong>Sorgfältiger Entwurf.</strong> {legal.draftNotice}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="legal-prose mt-6 space-y-6 text-sm leading-relaxed text-muted-foreground [&_h2]:text-lg [&_h2]:font-semibold [&_h2]:text-foreground [&_h2]:mb-2 [&_h2]:mt-2 [&_h3]:font-semibold [&_h3]:text-foreground [&_strong]:text-foreground [&_a]:text-red-600 [&_a]:underline [&_ul]:list-disc [&_ul]:pl-5 [&_ul]:space-y-1 [&_ol]:list-decimal [&_ol]:pl-5 [&_ol]:space-y-1">
|
||||
{children}
|
||||
</div>
|
||||
|
||||
<LegalFooterLinks />
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
164
src/config/legal.ts
Normal file
164
src/config/legal.ts
Normal file
@@ -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<string, LegalDocumentMeta>,
|
||||
|
||||
/** 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
|
||||
Reference in New Issue
Block a user