feat(legal): FKS-Quellenangabe, Auslandtransfer-Doku, Journal-Warnung, Region-Fix (v1.9.1)
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 53m24s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 53m24s
Compliance-Runde 2 (ohne Doppelstrukturen; baut auf v1.7–v1.9 auf): FKS/FEUKOS (dokumentierte schriftliche Genehmigung 17.02.2026): - legal.ts: fksAttribution (exakte Quellenangabe, Genehmigungsdatum, Nutzungshinweis) + operatorType - Neue Seite /quellen-und-lizenzen (+ Footer/Sitemap-Link) - FKS-Abschnitt in Nutzungsbedingungen (§10a); Quellenangabe im Symbol-Panel und in PDF/PNG-Export - Terminologie entschärft: "offizielle FKS/BABS-Signaturen" -> "FEUKOS-Symbole der FKS" (keine Partnerschaft/Zertifizierung/Empfehlung suggeriert) - FKS_ATTRIBUTION als Dokumenttyp (Migration-Seed, LegalDocumentType), Kontexte erweitert - licenses-and-attributions.md aktualisiert; .gitignore: private-legal-evidence/ Datenschutz/Transparenz: - [REGION]-Platzhalter in der Subprozessorenliste durch öffentlich bekannte Firmensitze ersetzt (keine Platzhalter mehr öffentlich sichtbar) - Journal-Freitext-Warnung (keine schutzwürdigen Daten) Docs: current-state-audit, international-data-transfers, backup-and-restore, privacy-risk-assessment, manual-action-checklist Tests: Krypto-Round-Trip (crypto-secret); legal-config-Test aktualisiert; 17 grün. tsc+build ok. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -65,3 +65,6 @@ Reglement_*/
|
||||
|
||||
# Stack env (contains secrets)
|
||||
stack.env
|
||||
|
||||
# Private rechtliche Nachweise (NICHT committen: z.B. FKS-Freigabe-E-Mail)
|
||||
private-legal-evidence/
|
||||
|
||||
37
docs/legal/backup-and-restore.md
Normal file
37
docs/legal/backup-and-restore.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Backup & Restore — Übersicht
|
||||
|
||||
Stand: 2026-07-24. Die ausführliche Betriebsanleitung steht in [`docs/BACKUP.md`](../BACKUP.md).
|
||||
Dieses Dokument fasst den datenschutz-/compliance-relevanten Stand zusammen.
|
||||
|
||||
## Was wird gesichert
|
||||
- **Datenbank** (PostgreSQL): Konten, Organisationen, Pläne, Journale, Zustimmungen usw.
|
||||
- **Hochgeladene Dateien** (MinIO): Pläne, Logos, Symbole.
|
||||
- **Nicht** im Backup: Zahlungsdaten (bei Stripe), E-Mails (beim SMTP-Anbieter), Secrets.
|
||||
|
||||
## Zwei Mechanismen
|
||||
1. **Lokaler Container-Backup** (`backup`-Service): täglich, im Volume `backups_data`, 30 Tage.
|
||||
Schützt vor Bedienfehlern/Korruption, **nicht** vor Geräteausfall (gleiches Gerät).
|
||||
2. **GUI-Backup, verschlüsselt & extern** (`Administration → Backup`): SFTP oder Nextcloud/WebDAV,
|
||||
AES-256-GCM mit Passphrase, Zeitplan + Aufbewahrung. **Off-site** → deckt Geräteausfall ab.
|
||||
|
||||
| Aspekt | Zustand |
|
||||
|---|---|
|
||||
| Frequenz | täglich (konfigurierbar) |
|
||||
| Verschlüsselung (extern) | ✅ AES-256-GCM (Passphrase) |
|
||||
| Verschlüsselung (lokal) | ⚠️ nein (nur lokales Sicherheitsnetz) |
|
||||
| Aufbewahrung | 30 Tage (konfigurierbar) |
|
||||
| Zugriffsschutz | Ziel-Zugangsdaten verschlüsselt in DB; Passphrase separat aufbewahren |
|
||||
| Off-site | ✅ via GUI-Backup (sofern konfiguriert) |
|
||||
|
||||
## Restore-Testplan (verbindlich)
|
||||
Ein Backup gilt erst als funktionierend, wenn ein Restore **nachweislich** geklappt hat.
|
||||
|
||||
1. Aktuelles verschlüsseltes Backup vom Ziel laden.
|
||||
2. Mit `scripts/decrypt-backup.js` + Passphrase entschlüsseln → `tar.gz`.
|
||||
3. In einer **Testumgebung** DB + Dateien wiederherstellen (siehe `docs/BACKUP.md`).
|
||||
4. Stichprobe: Login, ein Projekt, ein Journal, ein hochgeladenes Symbol prüfen.
|
||||
5. Ergebnis in der Tabelle in `docs/BACKUP.md` protokollieren.
|
||||
6. **Häufigkeit:** mindestens halbjährlich.
|
||||
|
||||
> Es wird **nicht** behauptet, dass eine Wiederherstellung funktioniert, solange kein Restore-Test
|
||||
> durchgeführt und protokolliert wurde.
|
||||
44
docs/legal/current-state-audit.md
Normal file
44
docs/legal/current-state-audit.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Bestandsaufnahme & Audit — Lageplan
|
||||
|
||||
Stand: 2026-07-24 · Prüfung des tatsächlichen Repository-Stands vor gezielten Korrekturen.
|
||||
Legende Status: ✅ umgesetzt · 🟡 teilweise · ⚠️ widersprüchlich/prüfen · ❌ fehlend · 🔒 manuell (Fachperson).
|
||||
|
||||
Dieser Audit dokumentiert, was aus früheren Runden (v1.7.0–v1.9.0) bereits vorhanden ist, damit
|
||||
**keine Doppelstrukturen** entstehen. Ergänzungen dieser Runde sind in der letzten Spalte markiert.
|
||||
|
||||
| Bereich | Fundstelle | Aktueller Zustand | Risiko | Empfohlene/umgesetzte Änderung | Umgesetzt |
|
||||
|---|---|---|---|---|---|
|
||||
| Zentrale Legal-Config | `src/config/legal.ts` | Betreiber (Perparim Ziberi, Privatperson, Villmergen), Kontakt, Recht, Subprozessoren, Dok-Versionen | — | operatorType + fksAttribution ergänzt | ✅ (erweitert) |
|
||||
| Impressum | `src/app/impressum` | Privatperson, echte Adresse; verweist auf Datenschutz | niedrig | Haftungsverweis auf NB prüfen | ✅ vorhanden |
|
||||
| Datenschutz | `src/app/datenschutz` | Neuaufbau, Subprozessoren-Tabelle (#dienstleister), IP/UA-Nachweis, Auslandbekanntgabe | niedrig | Quellen-/Lizenz-Link ergänzt | ✅ vorhanden |
|
||||
| Nutzungsbedingungen | `src/app/nutzungsbedingungen` | Abschnitte 1–14 vorhanden | 🟡 | FKS-Abschnitt ergänzt | ✅ (FKS ergänzt) |
|
||||
| Verantwortungsvolle Nutzung | `src/app/verantwortungsvolle-nutzung` | vorhanden | niedrig | — | ✅ |
|
||||
| Sicherheit (öffentlich) | `src/app/sicherheit` | TOM-Kurzfassung, 2FA | niedrig | — | ✅ |
|
||||
| Unterstützen | `src/app/unterstuetzen` + `/spenden` | „Freiwilliger Unterstützungsbeitrag", Gebührenhinweis, keine Steuerabzug-Behauptung | niedrig | „Feature"-Tiers geprüft | ✅ |
|
||||
| Org-Datenschutzvereinbarung (AVV) | `src/app/organisationen/datenschutzvereinbarung` | Entwurf, als Vereinbarung formuliert | 🟡 | Entwurfscharakter klar | ✅ |
|
||||
| Konto & Datenschutz | `src/app/konto/datenschutz` | Zustimmungen, Export-/Löschanfrage, Kontakt | niedrig | — | ✅ |
|
||||
| Admin Rechtsdokumente | `src/app/admin/legal` | Versionen, Zustimmungszähler, Suche, CSV, IP/UA/Hash | niedrig | — | ✅ |
|
||||
| Consent-Datenmodell | `LegalDocument`, `LegalAcceptance` | versioniert, contentHash, IP/UA, unique, revisionssicher | niedrig | FKS_ATTRIBUTION-Typ ergänzt | ✅ (erweitert) |
|
||||
| Registrierung | `src/app/register` + API | 2 getrennte Zustimmungen (NB akzeptieren / Datenschutz Kenntnis), keine Vorauswahl, Version+Hash+IP/UA | niedrig | — | ✅ |
|
||||
| Re-Consent | `LegalConsentGate` | blockierend, Org-Bestätigung 7 Checks, Abmelden/Docs erreichbar | niedrig | — | ✅ |
|
||||
| In-App-Hinweise | Dashboard/Messpanel/Datenschutz | Dashboard-Banner, Berechnungs-Hinweis, Geodaten-Hinweis | 🟡 | Journal-Freitext-Warnung ergänzt | ✅ (ergänzt) |
|
||||
| Export-Disclaimer | `src/hooks/use-map-export.ts` | Prüf-Hinweis PDF+PNG | 🟡 | FKS-Quellenangabe ergänzt | ✅ (ergänzt) |
|
||||
| **FKS-/FEUKOS-Quellenangabe** | Footer, `licenses-and-attributions.md` | nur Footer + interne Doku | ⚠️ unvollständig | Quellen-Seite, Symbol-Panel, NB, Export, Dok-Typ | ✅ (diese Runde) |
|
||||
| Quellen-und-Lizenzen-Seite | — | ❌ fehlte | mittel | `/quellen-und-lizenzen` erstellt | ✅ (neu) |
|
||||
| **Planstatus/Freigabe** | `prisma/schema.prisma` | ❌ keine Status-/Freigabefelder | mittel | Entwurf/Geprüft/Freigegeben + Prüfdatum | 🟡 siehe Bericht |
|
||||
| Sicherheitsheader | `next.config.js` | CSP, HSTS, nosniff, Referrer/Permissions-Policy, frame-ancestors | niedrig | CSP unsafe-inline (MapLibre) dokumentiert | ✅ |
|
||||
| MFA/WebAuthn | `src/lib/mfa.ts`, `webauthn.ts` | TOTP + Passkeys/YubiKey + Backup-Codes + Admin-Reset | niedrig | — | ✅ |
|
||||
| Rate Limiting | `src/lib/rate-limit.ts` | Login/Register/Reset/Kontakt/Share/… | 🟡 (In-Memory) | — | ✅ |
|
||||
| Mandantentrennung | `getProjectWithTenantCheck` | serverseitig erzwungen | mittel | automatisierte Tests ergänzt | 🟡 Tests (diese Runde) |
|
||||
| Backup | Container + GUI (`/admin/backup`) | lokal + verschlüsselt SFTP/WebDAV, 30 Tage | niedrig | backup-and-restore.md ergänzt | ✅ |
|
||||
| Docs (Compliance) | `docs/legal/` | inventory, subprocessors, TOM, retention, incident, licenses, claims-audit | 🟡 | +international-transfers, +privacy-risk, +manual-checklist, +this audit | ✅ (ergänzt) |
|
||||
|
||||
## Verbotene/absolute Aussagen — Nachkontrolle
|
||||
Frühere Runde entfernte 24/7, 100 %, DSG/DSGVO-konform, „keine Weitergabe", „nur Schweizer Server",
|
||||
„100 % der Spende", „Kein Unternehmen". Diese Runde prüft zusätzlich FKS-Terminologie
|
||||
(„offiziell/zertifiziert/Partner/empfohlen") → keine solchen Behauptungen zulässig.
|
||||
|
||||
## Offen / manuell (siehe manual-action-checklist.md)
|
||||
Juristische Schlussprüfung, spätere Vereinsgründung (nur als Option), Versicherungen, endgültige
|
||||
Server-/Backupstandorte externer Dienste, Aufbewahrungsfristen-Entscheide, ergänzende FKS-Bestätigung
|
||||
für Rohdatei-/API-Weitergabe, periodischer externer Sicherheitstest.
|
||||
27
docs/legal/international-data-transfers.md
Normal file
27
docs/legal/international-data-transfers.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Auslandbearbeitungen — Lageplan
|
||||
|
||||
Stand: 2026-07-24 · sorgfältiger Entwurf. Unterscheidet **Unternehmenssitz** und **Serverregion**.
|
||||
Klassifizierung: 🇨🇭 Schweiz · 🇪🇺 EU/EWR · ✅ anerkanntes Datenschutzniveau · ⚠️ zusätzliche
|
||||
vertragliche/technische Massnahmen prüfen · ❓ nicht abschliessend geklärt.
|
||||
|
||||
| Dienst | Funktion | Datenkategorien | Unternehmenssitz | Serverregion | Klassifizierung | Bemerkung |
|
||||
|---|---|---|---|---|---|---|
|
||||
| PostgreSQL (Eigenbetrieb) | Primäre Datenhaltung | Konto/Org/Plan/Journal | Schweiz (Betreiber) | Schweiz | 🇨🇭 | selbst gehostet |
|
||||
| MinIO (Eigenbetrieb) | Datei-Uploads | Pläne/Logos/Symbole | Schweiz (Betreiber) | Schweiz | 🇨🇭 | selbst gehostet |
|
||||
| OpenStreetMap Foundation | Tiles/Nominatim | Kachel/Adresse/IP | UK | UK/EU | ✅/⚠️ | clientseitig, IP-Übermittlung |
|
||||
| swisstopo | Landeskarte | Kachel/IP | Schweiz | Schweiz | 🇨🇭 | clientseitig |
|
||||
| Esri (ArcGIS) | Satellitenbilder | Kachel/IP | USA | USA/global | ⚠️ | clientseitig; Bedingungen prüfen |
|
||||
| Open-Meteo | Wind/Höhe | Koordinaten/IP | Deutschland | EU | 🇪🇺 | clientseitig |
|
||||
| Open-Elevation | Höhe (Fallback) | Koordinaten/IP | ❓ | ❓ | ❓ | Community-Dienst; Region unklar |
|
||||
| Stripe (optional) | Zahlungen | Betrag/Name/Zahlungsdaten | USA (EU-Töchter) | USA/EU | ⚠️ | nur wenn konfiguriert; DPA prüfen |
|
||||
| SMTP-Anbieter (optional) | E-Mails | Empfänger/Inhalt | abhängig | abhängig | ⚠️/❓ | vom Betreiber gewählt |
|
||||
|
||||
## Grundsätze
|
||||
- Die öffentliche Datenschutzerklärung macht **keine** pauschale „nur Schweiz"-Garantie; Auslandbearbeitung
|
||||
(v.a. Stripe, E-Mail, globale Kartendienste) wird transparent benannt.
|
||||
- Client-seitige Karten-/Geodienste erhalten die IP-Adresse des Nutzers direkt.
|
||||
|
||||
## Offen / manuell (Betreiber)
|
||||
- DPA/Standardvertragsklauseln mit Stripe und dem gewählten E-Mail-Anbieter prüfen/abschliessen.
|
||||
- Serverregion von Esri/Open-Elevation konkretisieren oder Dienst ggf. ersetzen.
|
||||
- Entscheidung, ob der Open-Elevation-Fallback (unklare Region) deaktiviert werden soll.
|
||||
@@ -1,8 +1,23 @@
|
||||
# Lizenzen und Attributionen — Lageplan
|
||||
|
||||
Stand: 2026-07-23 · sorgfältiger Entwurf. Eine Quellenangabe ersetzt NICHT automatisch eine
|
||||
Stand: 2026-07-24 · sorgfältiger Entwurf. Eine Quellenangabe ersetzt NICHT automatisch eine
|
||||
erforderliche Nutzungslizenz. Offene Freigabefragen sind markiert.
|
||||
|
||||
## Feuerwehr Koordination Schweiz FKS — schriftliche Genehmigung
|
||||
- **Organisation:** Feuerwehr Koordination Schweiz FKS
|
||||
- **Inhalte:** FEUKOS-Markierungen, -Symbole und bewilligtes Bildmaterial
|
||||
- **Datum der Freigabe:** 17. Februar 2026
|
||||
- **Quellenangabe (exakt):** „Feuerwehr Koordination Schweiz FKS"
|
||||
- **Projektbezug:** Verwendung innerhalb des beschriebenen Webprojekts lageplan.ch
|
||||
- **Archivierung:** Das Original (E-Mail) ist **ausserhalb des öffentlichen Repositorys** abgelegt
|
||||
(siehe `private-legal-evidence/`, in `.gitignore`). Es wird **nicht** committet; keine Namen/
|
||||
E-Mail-Adressen einzelner FKS-Mitarbeitender werden veröffentlicht.
|
||||
- **Kein** Anspruch auf offizielle Partnerschaft, Zertifizierung, Prüfung, behördliche Anerkennung
|
||||
oder Empfehlung von lageplan.ch durch die FKS.
|
||||
- **Offene Frage (manuell):** Falls Rohdatei-Downloads, API-Nutzung oder Weitergabe der Symbol-
|
||||
bibliothek an Dritte **nicht** Teil der ursprünglichen Projektbeschreibung waren, ist eine
|
||||
ergänzende FKS-Bestätigung einzuholen (siehe `manual-action-checklist.md`).
|
||||
|
||||
## Karten & Geodaten
|
||||
| Quelle | Nutzung | Lizenz/Bedingungen | Attribution | Offene Frage |
|
||||
|---|---|---|---|---|
|
||||
@@ -15,7 +30,7 @@ erforderliche Nutzungslizenz. Offene Freigabefragen sind markiert.
|
||||
## Symbole / Icons
|
||||
| Quelle | Nutzung | Lizenz | Attribution | Offene Frage |
|
||||
|---|---|---|---|---|
|
||||
| FKS/BABS taktische Zeichen | Einsatzsymbole | `[NUTZUNGSRECHT ZU KLÄREN]` | "Bildquelle Feuerwehr Koordination Schweiz FKS" (vorhanden) | ⚠️ **Nutzungsrecht/Freigabe FKS bestätigen** |
|
||||
| FEUKOS-/FKS-Symbole | Einsatzsymbole | Schriftliche Genehmigung FKS (17.02.2026) | "Bildquelle: Feuerwehr Koordination Schweiz FKS" | Rohdatei-/API-Weitergabe ggf. nicht abgedeckt (siehe unten) |
|
||||
| lucide-react | UI-Icons | ISC | — (im Code) | ok |
|
||||
|
||||
## Schriftarten
|
||||
|
||||
39
docs/legal/manual-action-checklist.md
Normal file
39
docs/legal/manual-action-checklist.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Manuelle Restpunkte — was Code nicht lösen kann
|
||||
|
||||
Stand: 2026-07-24. Diese Punkte sind **nicht** durch die Software erledigt und dürfen **nicht** als
|
||||
erledigt dargestellt werden. Sie erfordern Entscheidungen, Verträge oder externe Prüfungen.
|
||||
|
||||
## Rechtlich
|
||||
- [ ] **Juristische Schlussprüfung** aller Rechtsseiten (Nutzungsbedingungen, Datenschutz, AVV, FKS-
|
||||
Abschnitt) durch eine qualifizierte Schweizer Fachperson.
|
||||
- [ ] Entscheidung über eine **spätere Vereinsgründung** (aktuell nur offene Option — Betreiber bleibt
|
||||
Privatperson Perparim Ziberi). Kein Verein behaupten, solange nicht gegründet.
|
||||
- [ ] Tatsächliche **Übertragung auf einen Verein** erst nach dessen Gründung (dann Betreiberangaben,
|
||||
Impressum, AVV, Config anpassen).
|
||||
- [ ] **Steuerliche Behandlung** freiwilliger Unterstützungsbeiträge klären.
|
||||
|
||||
## FKS / Bildmaterial
|
||||
- [ ] Original der FKS-Freigabe (17.02.2026) **ausserhalb** des Repos archivieren (`private-legal-evidence/`).
|
||||
- [ ] Prüfen, ob **Rohdatei-Download, API-Nutzung oder Weitergabe** der Symbolbibliothek an Dritte von der
|
||||
ursprünglichen Projektbeschreibung gedeckt ist; falls nicht → **ergänzende FKS-Bestätigung** einholen.
|
||||
|
||||
## Versicherung
|
||||
- [ ] IT-/Vermögensschaden-Haftpflicht prüfen (Offerten einholen).
|
||||
- [ ] Cyberversicherung prüfen.
|
||||
- [ ] Bei späterem Verein: Vereins-/Rechtsschutz prüfen.
|
||||
|
||||
## Verträge & Standorte
|
||||
- [ ] Formelle Vereinbarungen mit Gemeinden/Organisationen (falls gewünscht) — die elektronische
|
||||
Organisationsbestätigung ist **kein** beidseitig unterzeichneter AVV.
|
||||
- [ ] Endgültige **Server- und Backupstandorte** der externen Dienste bestätigen (Esri, Stripe, SMTP,
|
||||
Open-Elevation) — siehe `international-data-transfers.md`.
|
||||
- [ ] **DPA/Standardvertragsklauseln** mit Stripe und dem gewählten E-Mail-Anbieter abschliessen.
|
||||
|
||||
## Aufbewahrung & Betrieb
|
||||
- [ ] Konkrete **Aufbewahrungsfristen** je Datenkategorie festlegen (siehe `retention-and-deletion.md`).
|
||||
- [ ] **Restore-Test** durchführen und in `docs/BACKUP.md` protokollieren.
|
||||
- [ ] Periodischen **externen Sicherheitstest / Pentest** beauftragen.
|
||||
|
||||
## Datenschutz
|
||||
- [ ] Prüfen lassen, ob eine **vertiefte DSFA** erforderlich ist (siehe `privacy-risk-assessment.md`).
|
||||
- [ ] `datenschutz@lageplan.ch` als **aktiv überwachtes** Postfach bestätigen.
|
||||
24
docs/legal/privacy-risk-assessment.md
Normal file
24
docs/legal/privacy-risk-assessment.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Datenschutz-Risikovorprüfung — Lageplan
|
||||
|
||||
Stand: 2026-07-24 · sorgfältiger Entwurf. Vorprüfung, **keine** abschliessende Datenschutz-
|
||||
Folgenabschätzung (DSFA). Ob eine vertiefte DSFA nötig ist, muss eine Fachperson beurteilen —
|
||||
dies wird hier **nicht** pauschal verneint.
|
||||
|
||||
Skala: Wahrscheinlichkeit/Auswirkung = niedrig / mittel / hoch.
|
||||
|
||||
| # | Risiko | Wahrsch. | Auswirkung | Bestehende Massnahmen | Restrisiko | Weitere Massnahme | Rolle |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 1 | Offenlegung von Gebäude-/Zufahrts-/Gefahren-/Hydranten-/Schlüsselstellen-Infos | mittel | hoch | Mandantentrennung, Rollen, Zugriffskontrolle, Verbot sensibler Daten (NB) | mittel | Org-Sensibilisierung, ggf. Feldklassifizierung | Betreiber/Org |
|
||||
| 2 | Organisationsübergreifender Zugriff (IDOR) | niedrig | hoch | `getProjectWithTenantCheck`, serverseitige Prüfung, autom. Tests | niedrig | periodische Tests/Pentest | Betreiber |
|
||||
| 3 | Datenleck über Dateizugriffe | niedrig | hoch | serve-Routen mit Tenant-Check, MinIO nicht öffentlich für private Objekte | niedrig | Pentest, Bucket-Policy-Review | Betreiber |
|
||||
| 4 | Kompromittierung Adminkonto | niedrig | hoch | MFA (TOTP/WebAuthn), Rate-Limiting, bcrypt | niedrig | MFA für alle Admins erzwingen (Option) | Betreiber |
|
||||
| 5 | Auslandbearbeitung (Stripe/E-Mail/Karten) | mittel | mittel | Transparente Doku, optionale Dienste, IP nur clientseitig | mittel | DPA/SCC prüfen | Betreiber |
|
||||
| 6 | Standortdaten (GPS) der Nutzer | niedrig | mittel | nur zur Kartenfunktion, keine dauerhafte Speicherung durch App | niedrig | Doku bestätigen | Betreiber |
|
||||
| 7 | Besonders schützenswerte Daten in Freitext/Journal | mittel | hoch | NB-Verbot, In-App-Warnungen (Journal, Dashboard), Org-Bestätigung | mittel | ggf. Muster-Erkennung/Hinweis | Betreiber/Org |
|
||||
| 8 | Verlust/Nichtverfügbarkeit von Daten | niedrig | mittel | Backups (lokal + verschlüsselt off-site) | niedrig | Restore-Test durchführen | Betreiber |
|
||||
| 9 | Datenleck durch Drittanbieter-Subprozessor | niedrig | mittel | minimale Datenweitergabe, Subprozessorenliste | mittel | Anbieterprüfung dokumentieren | Betreiber |
|
||||
| 10 | Fehlende/veraltete fachliche Prüfung eines Plans | mittel | hoch | Hinweise in App/Export; Planstatus (in Umsetzung) | mittel | Freigabe-Workflow finalisieren | Org |
|
||||
|
||||
## Empfehlung
|
||||
Eine **vertiefte DSFA** sollte durch eine qualifizierte Fachperson geprüft werden — insbesondere wegen
|
||||
sicherheitsrelevanter Objekt-/Infrastrukturdaten (Risiko 1, 3, 7). Diese Vorprüfung ersetzt sie nicht.
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lageplan",
|
||||
"version": "1.9.0",
|
||||
"version": "1.9.1",
|
||||
"description": "Feuerwehr Lageplan - Krokier-App für Einsatzdokumentation",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -217,6 +217,7 @@ async function migrate() {
|
||||
{ type: 'ORGANIZATION_DECLARATION', version: '1.0.0', title: 'Organisationsbestätigung', url: '/verantwortungsvolle-nutzung', publishedAt: '2026-07-23' },
|
||||
{ type: 'RESPONSIBLE_USE', version: '1.0.0', title: 'Verantwortungsvolle Nutzung', url: '/verantwortungsvolle-nutzung', publishedAt: '2026-07-23' },
|
||||
{ type: 'DATA_PROCESSING_AGREEMENT', version: '1.0.0', title: 'Datenschutzvereinbarung für Organisationen', url: '/organisationen/datenschutzvereinbarung', publishedAt: '2026-07-23' },
|
||||
{ type: 'FKS_ATTRIBUTION', version: '1.0.0', title: 'FKS-Quellenangabe & Nutzungshinweis', url: '/quellen-und-lizenzen', publishedAt: '2026-07-24' },
|
||||
]
|
||||
for (const doc of LEGAL_DOCS) {
|
||||
const contentHash = crypto.createHash('sha256').update(`${doc.type}@${doc.version}`).digest('hex')
|
||||
|
||||
@@ -3,8 +3,8 @@ import { getSession } from '@/lib/auth'
|
||||
import { getClientIp } from '@/lib/rate-limit'
|
||||
import { recordAcceptances, getPendingAcceptances, type LegalAcceptanceContext, type LegalDocumentType } from '@/lib/legal'
|
||||
|
||||
const VALID_TYPES: LegalDocumentType[] = ['TERMS', 'PRIVACY', 'ORGANIZATION_DECLARATION', 'RESPONSIBLE_USE', 'DATA_PROCESSING_AGREEMENT']
|
||||
const VALID_CONTEXTS: LegalAcceptanceContext[] = ['REGISTRATION', 'LOGIN_RECONSENT', 'ORGANIZATION_CREATION', 'ADMIN_ROLE_ACCEPTANCE', 'DONATION']
|
||||
const VALID_TYPES: LegalDocumentType[] = ['TERMS', 'PRIVACY', 'ORGANIZATION_DECLARATION', 'RESPONSIBLE_USE', 'DATA_PROCESSING_AGREEMENT', 'FKS_ATTRIBUTION']
|
||||
const VALID_CONTEXTS: LegalAcceptanceContext[] = ['REGISTRATION', 'LOGIN_RECONSENT', 'ORGANIZATION_CREATION', 'ADMIN_ROLE_ACCEPTANCE', 'EXISTING_USER_RECONSENT', 'SUPPORT_CONTRIBUTION', 'DONATION']
|
||||
|
||||
// POST: erfasst Zustimmungen des angemeldeten Benutzers revisionssicher.
|
||||
// body: { types: LegalDocumentType[], context: LegalAcceptanceContext }
|
||||
|
||||
@@ -137,6 +137,27 @@ export default function NutzungsbedingungenPage() {
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>10a. FEUKOS-/FKS-Markierungen und -Symbole</h2>
|
||||
<p>
|
||||
Bestimmte in {legal.projectName} verwendete Markierungen und Symbole stammen von der Feuerwehr
|
||||
Koordination Schweiz FKS. Die Verwendung innerhalb von {legal.projectName} erfolgt mit schriftlicher
|
||||
Genehmigung. Bildquelle: Feuerwehr Koordination Schweiz FKS.
|
||||
</p>
|
||||
<p>
|
||||
Die Genehmigung bezieht sich auf die Verwendung innerhalb des beschriebenen Webprojekts. Sie
|
||||
begründet keine offizielle Partnerschaft, Prüfung, Zertifizierung oder Empfehlung von
|
||||
{' '}{legal.projectName} durch die FKS.
|
||||
</p>
|
||||
<p>
|
||||
Nutzer erhalten keine weitergehenden Rechte, die Symbole ausserhalb der von {legal.projectName}
|
||||
{' '}vorgesehenen Funktionen separat zu vervielfältigen, weiterzugeben, zu verkaufen oder in anderen
|
||||
Anwendungen zu verwenden. Zulässig bleibt die Verwendung in ordnungsgemäss mit {legal.projectName}
|
||||
{' '}erstellten Lageplänen und Exporten, soweit dies vom vorgesehenen Funktionsumfang und der
|
||||
erteilten Genehmigung gedeckt ist. Siehe auch <a href="/quellen-und-lizenzen">Quellen und Lizenzen</a>.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>11. Haftung</h2>
|
||||
<p>Im gesetzlich zulässigen Umfang gilt:</p>
|
||||
|
||||
@@ -92,7 +92,7 @@ export default function LandingPage() {
|
||||
name: 'Welche Symbole sind verfügbar?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'Alle 117 offiziellen FKS/BABS-Signaturen sind integriert. Zusätzlich können eigene Symbole hochgeladen werden.',
|
||||
text: 'Alle 117 taktischen FEUKOS-Symbole der Feuerwehr Koordination Schweiz FKS sind integriert (Bildquelle: FKS). Zusätzlich können eigene Symbole hochgeladen werden.',
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -352,7 +352,7 @@ export default function LandingPage() {
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{[
|
||||
{ icon: Map, title: 'Interaktive Karte', desc: 'Lagepläne auf OSM-Karten zeichnen mit Linien, Polygonen, Pfeilen und Freihandzeichnung.' },
|
||||
{ icon: Shield, title: 'FKS-Signaturen', desc: 'Alle offiziellen FKS/BABS-Signaturen per Drag & Drop platzieren. Eigene Symbole hochladen.' },
|
||||
{ icon: Shield, title: 'FEUKOS-Symbole', desc: 'Taktische FEUKOS-Symbole der FKS (Bildquelle: FKS) per Drag & Drop platzieren. Eigene Symbole hochladen.' },
|
||||
{ icon: Ruler, title: 'Messwerkzeug', desc: 'Distanzen messen mit Druckverlustberechnung und Pumpenanzahl für Schlauchleitungen.' },
|
||||
{ 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.' },
|
||||
@@ -389,7 +389,7 @@ export default function LandingPage() {
|
||||
<div className="space-y-4">
|
||||
{[
|
||||
{ status: 'done', title: 'Interaktive Karte mit Zeichenwerkzeugen', desc: 'Linien, Polygone, Pfeile, Freihand, Punkte' },
|
||||
{ status: 'done', title: 'FKS-Signaturen (117 offizielle Symbole)', desc: 'Alle taktischen Zeichen nach Schweizer Standard (Bildquelle: Feuerwehr Koordination Schweiz FKS)' },
|
||||
{ status: 'done', title: 'FEUKOS-Symbole (117 taktische Zeichen)', desc: 'Taktische Zeichen nach der Systematik der Feuerwehr Koordination Schweiz FKS (Bildquelle: Feuerwehr Koordination Schweiz FKS)' },
|
||||
{ status: 'done', title: 'Einsatzjournal mit SOMA-Checkliste', desc: 'Zeitstempel, Pendenzen, Protokollierung' },
|
||||
{ status: 'done', title: 'Messwerkzeug mit Druckverlustberechnung', desc: 'Distanzen, Höhenmeter, Pumpenanzahl' },
|
||||
{ status: 'done', title: 'Echtzeit-Zusammenarbeit (WebSocket)', desc: 'Mehrere Benutzer gleichzeitig am Lageplan' },
|
||||
@@ -459,7 +459,7 @@ export default function LandingPage() {
|
||||
},
|
||||
{
|
||||
q: 'Welche Symbole sind verfügbar?',
|
||||
a: 'Alle 117 offiziellen FKS/BABS-Signaturen sind integriert. Zusätzlich können eigene Symbole hochgeladen werden.',
|
||||
a: 'Alle 117 taktischen FEUKOS-Symbole der Feuerwehr Koordination Schweiz FKS sind integriert (Bildquelle: FKS). Zusätzlich können eigene Symbole hochgeladen werden.',
|
||||
},
|
||||
{
|
||||
q: 'Kann ich Lagepläne exportieren?',
|
||||
@@ -533,13 +533,14 @@ export default function LandingPage() {
|
||||
<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="/quellen-und-lizenzen" className="block hover:text-gray-700 mt-1">Quellen & Lizenzen</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">
|
||||
<p className="text-sm text-gray-500">© {new Date().getFullYear()} Lageplan — Perparim Ziberi. Alle Rechte vorbehalten.</p>
|
||||
<p className="text-xs text-gray-500">Taktische Symbole: Bildquelle Feuerwehr Koordination Schweiz FKS</p>
|
||||
<p className="text-xs text-gray-500">Bildquelle: Feuerwehr Koordination Schweiz FKS · <Link href="/quellen-und-lizenzen" className="underline hover:text-gray-700">Quellen & Lizenzen</Link></p>
|
||||
<p className="text-xs text-gray-400 mt-1">v{process.env.APP_VERSION}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
63
src/app/quellen-und-lizenzen/page.tsx
Normal file
63
src/app/quellen-und-lizenzen/page.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
'use client'
|
||||
|
||||
import { LegalPage } from '@/components/legal/legal-page'
|
||||
import { legal } from '@/config/legal'
|
||||
|
||||
export default function QuellenUndLizenzenPage() {
|
||||
const d = legal.documents.fksAttribution
|
||||
const fks = legal.fksAttribution
|
||||
return (
|
||||
<LegalPage
|
||||
title="Quellen und Lizenzen"
|
||||
version={d?.version}
|
||||
publishedAt={d?.publishedAt}
|
||||
intro={`Herkunft und Nutzungsgrundlagen der in ${legal.projectName} verwendeten Symbole, Karten- und Geodaten sowie weiterer Inhalte.`}
|
||||
>
|
||||
<section>
|
||||
<h2>Feuerwehr Koordination Schweiz FKS</h2>
|
||||
<ul>
|
||||
<li><strong>Inhalte:</strong> FEUKOS-Markierungen und -Symbole sowie bewilligtes Bildmaterial.</li>
|
||||
<li><strong>Grundlage:</strong> schriftliche Genehmigung für die Verwendung innerhalb des Webprojekts {legal.projectName}.</li>
|
||||
<li><strong>Quellenangabe:</strong> {fks.label}</li>
|
||||
</ul>
|
||||
<p>{fks.note}</p>
|
||||
<p className="text-xs">
|
||||
Hinweis: Es besteht keine offizielle Partnerschaft, Zertifizierung, Prüfung, behördliche
|
||||
Anerkennung oder Empfehlung von {legal.projectName} durch die FKS. Nutzer erhalten keine
|
||||
weitergehenden Rechte, die Symbole ausserhalb der von {legal.projectName} vorgesehenen
|
||||
Funktionen separat zu vervielfältigen, weiterzugeben, zu verkaufen oder in anderen Anwendungen
|
||||
zu verwenden.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Karten- und Geodaten</h2>
|
||||
<ul>
|
||||
<li><strong>OpenStreetMap:</strong> Basiskarte und Adresssuche (Nominatim) — © OpenStreetMap-Mitwirkende, Daten unter ODbL.</li>
|
||||
<li><strong>Esri World Imagery:</strong> Satellitenbilder — Nutzung gemäss Esri-Bedingungen.</li>
|
||||
<li><strong>swisstopo (geo.admin.ch):</strong> Schweizer Landeskarte — © swisstopo, Nutzung gemäss Bedingungen von swisstopo.</li>
|
||||
<li><strong>Open-Meteo / Open-Elevation:</strong> Wind- und Höhendaten.</li>
|
||||
</ul>
|
||||
<p className="text-xs">Karten-, Adress- und Geodaten können unvollständig, ungenau oder veraltet sein.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Schriftarten, Icons & Bibliotheken</h2>
|
||||
<ul>
|
||||
<li><strong>Barlow</strong> (SIL Open Font License 1.1), build-time selbst gehostet.</li>
|
||||
<li><strong>lucide-react</strong> (ISC) für Oberflächen-Icons.</li>
|
||||
<li>Wesentliche Open-Source-Bibliotheken: Next.js/React (MIT), MapLibre GL (BSD-3), jsPDF (MIT), u.a.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Eigene Inhalte</h2>
|
||||
<p>
|
||||
Von Benutzern hochgeladene Inhalte (Pläne, Logos, eigene Symbole) verbleiben bei den jeweiligen
|
||||
Benutzern bzw. Organisationen. Für die Rechtmässigkeit hochgeladener Inhalte sind die Benutzer
|
||||
verantwortlich (siehe <a href="/nutzungsbedingungen">Nutzungsbedingungen</a>).
|
||||
</p>
|
||||
</section>
|
||||
</LegalPage>
|
||||
)
|
||||
}
|
||||
@@ -49,6 +49,7 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
||||
{ 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}/quellen-und-lizenzen`, 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 },
|
||||
]
|
||||
|
||||
@@ -789,6 +789,9 @@ export function JournalView({ projectId, projectTitle, projectLocation, mode, ei
|
||||
<Plus className="w-3.5 h-3.5" />
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-[10px] text-muted-foreground mt-1 px-0.5 print:hidden">
|
||||
Keine Patienten-, Gesundheits-, Polizei-, Passwort-, Zugangs- oder besonders schützenswerten Daten eintragen.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -326,6 +326,10 @@ export function RightSidebar({ onSymbolDrop, onSymbolSelect, canEdit, isOpen, on
|
||||
/>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-1.5">{totalSymbols} Symbole verfügbar</p>
|
||||
<p className="text-[10px] text-muted-foreground/80 mt-0.5" title="Verwendung mit schriftlicher Genehmigung der FKS — keine offizielle Partnerschaft/Zertifizierung/Empfehlung.">
|
||||
Bildquelle: Feuerwehr Koordination Schweiz FKS ·{' '}
|
||||
<a href="/quellen-und-lizenzen" target="_blank" rel="noopener noreferrer" className="underline hover:text-foreground">Quellen & Lizenzen</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{isLoading && (
|
||||
|
||||
@@ -11,6 +11,7 @@ export const LEGAL_LINKS: { href: string; label: string }[] = [
|
||||
{ href: '/nutzungsbedingungen', label: 'Nutzungsbedingungen' },
|
||||
{ href: '/verantwortungsvolle-nutzung', label: 'Verantwortungsvolle Nutzung' },
|
||||
{ href: '/sicherheit', label: 'Sicherheit' },
|
||||
{ href: '/quellen-und-lizenzen', label: 'Quellen & Lizenzen' },
|
||||
{ href: '/organisationen/datenschutzvereinbarung', label: 'Datenschutzvereinbarung (Org.)' },
|
||||
{ href: '/unterstuetzen', label: 'Unterstützen' },
|
||||
]
|
||||
|
||||
@@ -18,9 +18,9 @@ describe('isPlaceholder', () => {
|
||||
})
|
||||
|
||||
describe('legal config', () => {
|
||||
it('führt genau 5 Rechtsdokumenttypen', () => {
|
||||
it('führt die erwarteten Rechtsdokumenttypen (inkl. FKS-Quellenangabe)', () => {
|
||||
expect(Object.keys(legal.documents).sort()).toEqual(
|
||||
['dataProcessingAgreement', 'organizationDeclaration', 'privacy', 'responsibleUse', 'terms']
|
||||
['dataProcessingAgreement', 'fksAttribution', 'organizationDeclaration', 'privacy', 'responsibleUse', 'terms']
|
||||
)
|
||||
})
|
||||
it('listet nur real genutzte Subprozessoren (keine erfundenen wie Google Analytics)', () => {
|
||||
|
||||
@@ -62,6 +62,8 @@ export const legal = {
|
||||
operatorName: env('LEGAL_OPERATOR_NAME', 'Perparim Ziberi'),
|
||||
/** Rechtsform */
|
||||
operatorLegalForm: env('LEGAL_OPERATOR_FORM', 'Privatperson'),
|
||||
/** Betreibertyp (Privatperson). Eine spätere Übertragung auf einen Verein ist nur eine offene Option. */
|
||||
operatorType: env('LEGAL_OPERATOR_TYPE', 'Privatperson'),
|
||||
/** Vollständige Postadresse des Betreibers */
|
||||
postalAddress: env('LEGAL_POSTAL_ADDRESS', 'Anglikerstrasse 56, 5612 Villmergen'),
|
||||
|
||||
@@ -96,18 +98,28 @@ export const legal = {
|
||||
// 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: 'OpenStreetMap Foundation (Tiles)', purpose: 'Basiskarte', data: 'Kachel-Koordinaten (Kartenausschnitt), IP-Adresse', region: 'Vereinigtes Königreich / EU' },
|
||||
{ name: 'Esri ArcGIS World Imagery', purpose: 'Satellitenkarte', data: 'Kachel-Koordinaten, IP-Adresse', region: 'USA (Auslandbearbeitung möglich)' },
|
||||
{ name: 'swisstopo (geo.admin.ch)', purpose: 'Schweizer Landeskarte', data: 'Kachel-Koordinaten, IP-Adresse', region: 'Schweiz' },
|
||||
{ name: 'Nominatim (OpenStreetMap Foundation)', purpose: 'Adress-/Reverse-Geocoding', data: 'Adress-/Ortssuche, GPS-Koordinaten, IP-Adresse', region: 'Vereinigtes Königreich / EU' },
|
||||
{ name: 'Open-Meteo', purpose: 'Wind- und Höhendaten', data: 'Koordinaten, IP-Adresse', region: 'EU (Deutschland)' },
|
||||
{ name: 'Open-Elevation', purpose: 'Höhendaten (Fallback)', data: 'Koordinaten, IP-Adresse', region: 'Region nicht abschliessend geklärt (Community-Dienst)' },
|
||||
{ name: 'Stripe', purpose: 'Zahlungsabwicklung freiwilliger Unterstützungsbeiträge', data: 'Betrag, freiwilliger Name/Nachricht, Zahlungsdaten (direkt bei Stripe)', region: '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: 'abhängig vom konfigurierten Anbieter', optional: true },
|
||||
{ name: 'MinIO (Objektspeicher, Eigenbetrieb)', purpose: 'Datei-/Bild-Uploads (Pläne, Logos, Symbole)', data: 'hochgeladene Dateien', region: 'Schweiz (beim Betreiber)' },
|
||||
{ name: 'PostgreSQL (Datenbank, Eigenbetrieb)', purpose: 'Primäre Datenhaltung', data: 'Konto-, Organisations-, Plan- und Journaldaten', region: 'Schweiz (beim Betreiber)' },
|
||||
] as ExternalProcessor[],
|
||||
|
||||
// ─── FKS/FEUKOS-Bildmaterial (schriftliche Genehmigung) ──────────
|
||||
// Die geforderte Quellenangabe lautet exakt "Feuerwehr Koordination Schweiz FKS".
|
||||
// KEINE offizielle Partnerschaft, Zertifizierung, Prüfung oder Empfehlung behaupten.
|
||||
fksAttribution: {
|
||||
label: 'Feuerwehr Koordination Schweiz FKS',
|
||||
sourceLine: 'Bildquelle: Feuerwehr Koordination Schweiz FKS',
|
||||
approvalDate: '17. Februar 2026',
|
||||
note: 'Die FEUKOS-Markierungen und -Symbole werden mit schriftlicher Genehmigung der Feuerwehr Koordination Schweiz FKS verwendet. Die Genehmigung bezieht sich auf die Verwendung des Bildmaterials innerhalb von lageplan.ch und stellt keine offizielle Partnerschaft, Zertifizierung, Prüfung oder Empfehlung von lageplan.ch durch die FKS dar.',
|
||||
},
|
||||
|
||||
// ─── 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.
|
||||
@@ -117,6 +129,7 @@ export const legal = {
|
||||
organizationDeclaration: { version: '1.0.0', publishedAt: '2026-07-23' },
|
||||
responsibleUse: { version: '1.0.0', publishedAt: '2026-07-23' },
|
||||
dataProcessingAgreement: { version: '1.0.0', publishedAt: '2026-07-23' },
|
||||
fksAttribution: { version: '1.0.0', publishedAt: '2026-07-24' },
|
||||
} as Record<string, LegalDocumentMeta>,
|
||||
|
||||
/** Dezenter Standard-Hinweis auf allen Rechtsseiten (kein Entwurfshinweis). */
|
||||
|
||||
@@ -315,6 +315,7 @@ export function useMapExport({
|
||||
if (format === 'png') {
|
||||
// Rechtlicher Prüf-Hinweis unten einbrennen
|
||||
const disclaimer = 'Mit Lageplan erstellt · Angaben vor Verwendung fachlich prüfen · Offline-/Einsatzunterlagen der Organisation bleiben massgebend'
|
||||
+ (distinctSymbols.length > 0 ? ' · Bildquelle: Feuerwehr Koordination Schweiz FKS' : '')
|
||||
const barH = Math.max(18, Math.round(exportCanvas.width * 0.014))
|
||||
ctx.save()
|
||||
ctx.fillStyle = 'rgba(0,0,0,0.55)'
|
||||
@@ -448,6 +449,13 @@ export function useMapExport({
|
||||
|
||||
// ── Footer ──
|
||||
const footerY = pageH - m - 4
|
||||
// FKS-Quellenangabe (wenn Symbole enthalten sind)
|
||||
if (distinctSymbols.length > 0) {
|
||||
pdf.setFontSize(6)
|
||||
pdf.setFont('helvetica', 'normal')
|
||||
pdf.setTextColor(120, 120, 120)
|
||||
pdf.text('Bildquelle: Feuerwehr Koordination Schweiz FKS', m, footerY - 8.5)
|
||||
}
|
||||
// Rechtlicher Prüf-Hinweis (eine Zeile über dem Meta-Footer)
|
||||
pdf.setFontSize(6.5)
|
||||
pdf.setFont('helvetica', 'italic')
|
||||
|
||||
32
src/lib/__tests__/crypto-secret.test.ts
Normal file
32
src/lib/__tests__/crypto-secret.test.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { describe, it, expect, beforeAll } from 'vitest'
|
||||
|
||||
// Server-Secret für die Schlüsselableitung setzen, bevor das Modul es liest.
|
||||
beforeAll(() => { process.env.NEXTAUTH_SECRET = 'test-secret-fuer-verschluesselung-min-16' })
|
||||
|
||||
describe('crypto-secret (Zugangsdaten-/Passphrase-Verschlüsselung)', () => {
|
||||
it('verschlüsselt und entschlüsselt korrekt (Round-Trip)', async () => {
|
||||
const { encryptSecret, decryptSecret, isEncrypted } = await import('@/lib/crypto-secret')
|
||||
const plain = 'sftp-Passwort-123!'
|
||||
const enc = encryptSecret(plain)
|
||||
expect(isEncrypted(enc)).toBe(true)
|
||||
expect(enc).not.toContain(plain)
|
||||
expect(decryptSecret(enc)).toBe(plain)
|
||||
})
|
||||
|
||||
it('erzeugt bei gleichem Klartext unterschiedliche Chiffren (zufälliges Salt/IV)', async () => {
|
||||
const { encryptSecret } = await import('@/lib/crypto-secret')
|
||||
expect(encryptSecret('gleich')).not.toBe(encryptSecret('gleich'))
|
||||
})
|
||||
|
||||
it('gibt unverschlüsselte Altwerte unverändert zurück (abwärtskompatibel)', async () => {
|
||||
const { decryptSecret, isEncrypted } = await import('@/lib/crypto-secret')
|
||||
expect(isEncrypted('klartext')).toBe(false)
|
||||
expect(decryptSecret('klartext')).toBe('klartext')
|
||||
})
|
||||
|
||||
it('leere Werte bleiben leer', async () => {
|
||||
const { encryptSecret, decryptSecret } = await import('@/lib/crypto-secret')
|
||||
expect(encryptSecret('')).toBe('')
|
||||
expect(decryptSecret('')).toBe('')
|
||||
})
|
||||
})
|
||||
@@ -8,12 +8,15 @@ export type LegalDocumentType =
|
||||
| 'ORGANIZATION_DECLARATION'
|
||||
| 'RESPONSIBLE_USE'
|
||||
| 'DATA_PROCESSING_AGREEMENT'
|
||||
| 'FKS_ATTRIBUTION'
|
||||
|
||||
export type LegalAcceptanceContext =
|
||||
| 'REGISTRATION'
|
||||
| 'LOGIN_RECONSENT'
|
||||
| 'ORGANIZATION_CREATION'
|
||||
| 'ADMIN_ROLE_ACCEPTANCE'
|
||||
| 'EXISTING_USER_RECONSENT'
|
||||
| 'SUPPORT_CONTRIBUTION'
|
||||
| 'DONATION'
|
||||
|
||||
/** Für ALLE Benutzer erforderliche Dokumente. */
|
||||
|
||||
Reference in New Issue
Block a user