Merge pull request #246 from trails-cool/docs/legal-rewrite

Rewrite legal pages per legal review feedback
This commit is contained in:
Ullrich Schäfer 2026-04-18 03:00:39 +02:00 committed by GitHub
commit c9758a65d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 628 additions and 375 deletions

View file

@ -10,84 +10,141 @@ export function meta() {
export default function ImprintPage() {
return (
<div className="mx-auto max-w-2xl px-4 py-12">
<h1 className="text-3xl font-bold text-gray-900">Impressum</h1>
<h1 className="text-3xl font-bold text-gray-900">Impressum / Legal Notice</h1>
<p className="mt-2 text-xs text-gray-500">
Die deutsche Fassung ist maßgeblich. / The German version is authoritative.
</p>
<section className="mt-8 space-y-4 text-gray-700">
<h2 className="text-lg font-semibold text-gray-900">
Angaben gemäß § 5 TMG
</h2>
<address className="not-italic">
{operator.name}
<br />
{operator.address.street}
<br />
{operator.address.postalCode} {operator.address.city}
<br />
{operator.address.country}
</address>
{/* ------------------------------------------------------------------
Deutsche Fassung
------------------------------------------------------------------ */}
<h2 className="text-lg font-semibold text-gray-900">Kontakt</h2>
<p>
E-Mail:{" "}
<a
className="text-blue-600 hover:underline"
href={`mailto:${operator.email}`}
>
{operator.email}
</a>
</p>
<section className="mt-10 space-y-6 text-gray-700">
<div>
<h2 className="text-lg font-semibold text-gray-900">
Anbieter nach § 5 TMG
</h2>
<address className="mt-2 not-italic">
{operator.name}
<br />
{operator.address.street}
<br />
{operator.address.postalCode} {operator.address.city}
<br />
{operator.address.country}
</address>
</div>
<h2 className="text-lg font-semibold text-gray-900">
Verantwortlich für den Inhalt nach § 18 Abs. 2 MStV
</h2>
<address className="not-italic">
{operator.responsiblePerson}
<br />
{operator.address.street}
<br />
{operator.address.postalCode} {operator.address.city}
</address>
<div>
<h2 className="text-lg font-semibold text-gray-900">Kontakt</h2>
<p className="mt-2">
E-Mail:{" "}
<a className="text-blue-600 hover:underline" href={`mailto:${operator.email}`}>
{operator.email}
</a>
</p>
</div>
<h2 className="text-lg font-semibold text-gray-900">Haftungsausschluss</h2>
<p className="text-sm">
Die Inhalte dieser Seiten wurden mit größtmöglicher Sorgfalt erstellt.
Für die Richtigkeit, Vollständigkeit und Aktualität der Inhalte
können wir jedoch keine Gewähr übernehmen. trails.cool befindet sich
in aktiver Entwicklung (Alpha) Inhalte, Funktionen und Daten können
sich jederzeit ändern oder entfallen.
</p>
<div>
<h2 className="text-lg font-semibold text-gray-900">
Inhaltlich verantwortlich nach § 18 Abs. 2 MStV
</h2>
<address className="mt-2 not-italic">
{operator.responsiblePerson}
<br />
{operator.address.street}, {operator.address.postalCode}{" "}
{operator.address.city}
</address>
</div>
<p className="text-sm">
Als Diensteanbieter sind wir gemäß § 7 Abs. 1 TMG für eigene Inhalte
auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach
§§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht
verpflichtet, übermittelte oder gespeicherte fremde Informationen zu
überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige
Tätigkeit hinweisen.
</p>
<div>
<h2 className="text-lg font-semibold text-gray-900">Streitbeilegung</h2>
<p className="mt-2 text-sm">
Die Europäische Kommission stellt eine Plattform zur
Online-Streitbeilegung (OS) bereit:{" "}
<a
className="text-blue-600 hover:underline"
href="https://ec.europa.eu/consumers/odr"
>
https://ec.europa.eu/consumers/odr
</a>
.
</p>
<p className="mt-2 text-sm">
Wir sind nicht bereit oder verpflichtet, an
Streitbeilegungsverfahren vor einer Verbraucherschlichtungsstelle
teilzunehmen.
</p>
</div>
<div>
<h2 className="text-lg font-semibold text-gray-900">Alpha-Status</h2>
<p className="mt-2 text-sm">
trails.cool befindet sich in aktiver Entwicklung (Alpha). Inhalte,
Funktionen und Daten können sich jederzeit ändern oder entfallen.
</p>
</div>
</section>
<hr className="my-12 border-gray-200" />
<section className="space-y-4 text-gray-700">
<h2 className="text-lg font-semibold text-gray-900">
Legal notice (English summary)
</h2>
<p className="text-sm">
trails.cool is operated from Germany by {operator.name}, reachable at
the address above and at{" "}
<a
className="text-blue-600 hover:underline"
href={`mailto:${operator.email}`}
>
{operator.email}
</a>
. The service is currently in alpha see the{" "}
<a className="text-blue-600 hover:underline" href="/legal/terms">
Terms of Service
</a>{" "}
for details.
</p>
{/* ------------------------------------------------------------------
English version
------------------------------------------------------------------ */}
<section className="space-y-6 text-gray-700">
<h2 className="text-xl font-semibold text-gray-900">English version</h2>
<div>
<h3 className="text-base font-semibold text-gray-900">
Service provider (§ 5 TMG)
</h3>
<address className="mt-2 not-italic text-sm">
{operator.name}, {operator.address.street},{" "}
{operator.address.postalCode} {operator.address.city},{" "}
{operator.address.country}
</address>
</div>
<div>
<h3 className="text-base font-semibold text-gray-900">Contact</h3>
<p className="mt-2 text-sm">
Email:{" "}
<a className="text-blue-600 hover:underline" href={`mailto:${operator.email}`}>
{operator.email}
</a>
</p>
</div>
<div>
<h3 className="text-base font-semibold text-gray-900">
Content responsibility (§ 18 (2) MStV)
</h3>
<p className="mt-2 text-sm">{operator.responsiblePerson}, address as above.</p>
</div>
<div>
<h3 className="text-base font-semibold text-gray-900">Dispute resolution</h3>
<p className="mt-2 text-sm">
The European Commission provides an online dispute resolution platform at{" "}
<a
className="text-blue-600 hover:underline"
href="https://ec.europa.eu/consumers/odr"
>
https://ec.europa.eu/consumers/odr
</a>
. We are not willing or obliged to participate in dispute resolution
proceedings before a consumer arbitration board.
</p>
</div>
<div>
<h3 className="text-base font-semibold text-gray-900">Alpha status</h3>
<p className="mt-2 text-sm">
trails.cool is under active development (alpha). Features and data
may change or be removed at any time.
</p>
</div>
</section>
</div>
);

View file

@ -13,16 +13,21 @@ export default function PrivacyPage() {
<h1 className="text-3xl font-bold text-gray-900">
Datenschutzerklärung / Privacy Policy
</h1>
<p className="mt-2 text-sm text-gray-500">Last updated: 2026-04-18</p>
<p className="mt-2 text-sm text-gray-500">
Stand / Last updated: 2026-04-18. Die deutsche Fassung ist maßgeblich.
The German version is authoritative; English summaries follow each
section.
</p>
{/* GDPR formal sections */}
{/* ================================================================
1. Verantwortlicher / Data controller
================================================================ */}
<section className="mt-10">
<h2 className="text-xl font-semibold text-gray-900">
1. Verantwortliche Stelle / Data Controller
1. Verantwortlicher
</h2>
<p className="mt-2 text-gray-600">
Verantwortlich für die Datenverarbeitung auf dieser Website im Sinne
der DSGVO ist:
<p className="mt-2 text-gray-700">
Verantwortlich für die Datenverarbeitung im Sinne der DSGVO ist:
</p>
<address className="mt-2 not-italic text-gray-700">
{operator.name}
@ -38,69 +43,264 @@ export default function PrivacyPage() {
{operator.email}
</a>
</address>
<p className="mt-3 text-sm text-gray-600">
<em>English.</em> Data controller under GDPR is the party named
above. Contact for any data-protection matter: {operator.email}.
</p>
</section>
{/* ================================================================
2. Erhobene Daten & Zwecke / Data categories & purposes
================================================================ */}
<section className="mt-10">
<h2 className="text-xl font-semibold text-gray-900">
2. Rechtsgrundlagen / Legal Basis
2. Erhobene Daten und Zwecke
</h2>
<p className="mt-2 text-gray-600">
Wir verarbeiten personenbezogene Daten auf Grundlage folgender
Rechtsgrundlagen:
<p className="mt-2 text-gray-700">
Wir verarbeiten nur die Daten, die für den Betrieb der jeweiligen
Funktion erforderlich sind. trails.cool besteht aus zwei Teilen:
dem <strong>Journal</strong> (trails.cool, mit Konto) und dem{" "}
<strong>Planner</strong> (planner.trails.cool, anonym).
</p>
<ul className="mt-3 list-disc pl-6 text-gray-600 space-y-1">
<ul className="mt-3 list-disc pl-6 text-gray-700 space-y-2">
<li>
<strong>Vertragserfüllung (Art. 6 Abs. 1 lit. b DSGVO)</strong>:
Kontoverwaltung, Speicherung von Routen und Aktivitäten, Anmeldung
via Passkey / Magic Link.
<strong>Kontodaten (Journal):</strong> E-Mail-Adresse,
Benutzername, Anzeigename, Passkey-Public-Key. Zweck:
Kontoverwaltung und Anmeldung.
</li>
<li>
<strong>Berechtigte Interessen (Art. 6 Abs. 1 lit. f DSGVO)</strong>:
Fehlerüberwachung (Sentry) zur Sicherstellung der
Funktionsfähigkeit des Dienstes.
<strong>Nutzerinhalte (Journal):</strong> Routen (GPX-Daten,
Geometrie, Titel, Beschreibung) und Aktivitäten (Titel,
Beschreibung, Datum, Verknüpfung zu Routen). Zweck: Speicherung
und Anzeige innerhalb des Dienstes.
</li>
<li>
<strong>Einwilligung (Art. 6 Abs. 1 lit. a DSGVO)</strong>: Bei
ausdrücklicher Zustimmung zu den Nutzungsbedingungen während der
Registrierung.
<strong>Anmeldedaten (Journal):</strong> kurzlebige Magic-Link-Token
(zur E-Mail-basierten Anmeldung). Zweck: Authentifizierung.
</li>
<li>
<strong>Sitzungscookie (Journal):</strong> eine zufällige
Sitzungs-ID nach dem Einloggen. Zweck: Authentifizierung während
der Sitzung.
</li>
<li>
<strong>Planner-Sitzungsdaten:</strong> anonyme Sitzungs-ID,
kollaborativer Zustand (Wegpunkte, Notizen). Keine Zuordnung zu
einer Person. Zweck: gemeinsames Planen von Routen.
</li>
<li>
<strong>Server-Logfiles:</strong> IP-Adresse, Zeitstempel,
HTTP-Methode, Pfad, Statuscode, User-Agent. Zweck: Sicherheit,
Betrieb, Fehlersuche. Details siehe Abschnitt 4.
</li>
<li>
<strong>Fehlerdaten (Sentry):</strong> Stacktraces,
Fehlermeldungen, Browser-/OS-Information aus dem User-Agent,
Performance-Metriken. Bei eingeloggten Journal-Nutzer:innen
zusätzlich die Nutzer-ID (keine E-Mail, kein Benutzername).
Keine IP-Adressen, keine Cookies, keine Formulareingaben.
</li>
</ul>
<p className="mt-3 text-sm text-gray-600">
<em>English.</em> The Journal stores only what you provide (account
details and your own routes/activities) plus short-lived auth
artefacts. The Planner is anonymous and holds only ephemeral
session state. Server logs and Sentry error data are covered
separately below.
</p>
</section>
{/* ================================================================
3. Rechtsgrundlagen / Legal bases
================================================================ */}
<section className="mt-10">
<h2 className="text-xl font-semibold text-gray-900">
3. Ihre Rechte / Your Rights
</h2>
<p className="mt-2 text-gray-600">
Als betroffene Person stehen Ihnen folgende Rechte nach DSGVO zu:
</p>
<ul className="mt-3 list-disc pl-6 text-gray-600 space-y-1">
<li>Recht auf Auskunft (Art. 15 DSGVO)</li>
<li>Recht auf Berichtigung (Art. 16 DSGVO)</li>
<li>Recht auf Löschung (Art. 17 DSGVO)</li>
<li>Recht auf Einschränkung der Verarbeitung (Art. 18 DSGVO)</li>
<li>Recht auf Datenübertragbarkeit (Art. 20 DSGVO)</li>
<li>Widerspruchsrecht (Art. 21 DSGVO)</li>
<li>Recht auf Widerruf einer Einwilligung (Art. 7 Abs. 3 DSGVO)</li>
<h2 className="text-xl font-semibold text-gray-900">3. Rechtsgrundlagen</h2>
<ul className="mt-3 list-disc pl-6 text-gray-700 space-y-2">
<li>
<strong>Art. 6 Abs. 1 lit. b DSGVO (Vertragserfüllung):</strong>{" "}
Kontoführung, Anmeldung per Passkey oder Magic Link, Speicherung
und Anzeige der von Ihnen erstellten Routen und Aktivitäten,
Versand notwendiger Transaktions-E-Mails, Bereitstellung anonymer
Planner-Sitzungen. Ein Konto sowie die Bestätigung der
Nutzungsbedingungen sind Bestandteil dieses Nutzungsvertrags
sie sind <em>keine</em> Einwilligung im Sinne von Art. 6 Abs. 1
lit. a DSGVO.
</li>
<li>
<strong>Art. 6 Abs. 1 lit. f DSGVO (berechtigte Interessen):</strong>{" "}
kurzzeitige Server-Logfiles zur Sicherung des Betriebs und zur
Missbrauchsabwehr, Rate-Limiting, Fehlermonitoring über Sentry
zur Sicherstellung der Funktionsfähigkeit des Dienstes.
</li>
</ul>
<p className="mt-3 text-gray-600">
Zur Ausübung dieser Rechte wenden Sie sich bitte an{" "}
<p className="mt-3 text-sm text-gray-600">
<em>English.</em> Contract (Art. 6(1)(b)) covers everything
account- and content-related; legitimate interests (Art. 6(1)(f))
cover short-lived server logs, rate-limiting, and error monitoring.
We do <strong>not</strong> rely on consent for any of this.
</p>
</section>
{/* ================================================================
4. Server-Logfiles / Server logs
================================================================ */}
<section className="mt-10">
<h2 className="text-xl font-semibold text-gray-900">4. Server-Logfiles</h2>
<p className="mt-2 text-gray-700">
Beim Aufruf der Dienste werden automatisch technische Informationen
protokolliert:
</p>
<ul className="mt-3 list-disc pl-6 text-gray-700 space-y-1">
<li>IP-Adresse</li>
<li>Zeitstempel</li>
<li>HTTP-Methode, Pfad, Statuscode</li>
<li>User-Agent (Browser, Betriebssystem)</li>
</ul>
<p className="mt-3 text-gray-700">
<strong>Zweck:</strong> Sicherheit, Betrieb und Fehlersuche.{" "}
<strong>Rechtsgrundlage:</strong> Art. 6 Abs. 1 lit. f DSGVO.{" "}
<strong>Speicherdauer:</strong> maximal 14 Tage, danach automatische
Löschung. Eine Zusammenführung dieser Daten mit anderen Datenquellen
findet nicht statt.
</p>
<p className="mt-3 text-sm text-gray-600">
<em>English.</em> HTTP requests to our servers are logged (IP,
timestamp, method, path, status, user-agent) for up to 14 days for
operational and security purposes under Art. 6(1)(f), then deleted.
</p>
</section>
{/* ================================================================
5. Speicherdauer / Storage durations
================================================================ */}
<section className="mt-10">
<h2 className="text-xl font-semibold text-gray-900">5. Speicherdauer</h2>
<ul className="mt-3 list-disc pl-6 text-gray-700 space-y-1">
<li>Konto und zugehörige Inhalte: bis zur Löschung durch Sie</li>
<li>Planner-Sitzungen: automatische Löschung nach 7 Tagen Inaktivität</li>
<li>Magic-Link-Token: 15 Minuten</li>
<li>Server-Logfiles: maximal 14 Tage</li>
<li>Fehlerdaten (Sentry): 90 Tage</li>
</ul>
<p className="mt-3 text-sm text-gray-600">
<em>English.</em> Account and content kept until you delete them.
Ephemeral data (sessions, magic-link tokens, logs, Sentry events)
deleted automatically on the schedules above.
</p>
</section>
{/* ================================================================
6. Empfänger / Third parties
================================================================ */}
<section className="mt-10">
<h2 className="text-xl font-semibold text-gray-900">6. Empfänger und Drittanbieter</h2>
<p className="mt-2 text-gray-700">
Wir geben personenbezogene Daten nur an die unten genannten
Auftragsverarbeiter und Dritten weiter, und auch dort nur im
jeweils notwendigen Umfang.
</p>
<ul className="mt-3 list-disc pl-6 text-gray-700 space-y-3">
<li>
<strong>Sentry</strong> (Functional Software Inc.) Fehler- und
Performance-Monitoring. Was übermittelt wird: Stacktraces,
Fehlertext, Browser-/OS-Informationen aus dem User-Agent,
Performance-Daten; bei eingeloggten Journal-Nutzer:innen
zusätzlich die Nutzer-ID. <strong>Nicht</strong> übermittelt:
IP-Adresse, Cookies, vollständige HTTP-Header
(<code>sendDefaultPii</code> ist deaktiviert). Keine
Session-Replays. Hosting innerhalb der EU (Frankfurt).
</li>
<li>
<strong>OpenStreetMap</strong> Kartenkacheln werden beim Anzeigen
der Karten direkt vom Browser von OSM-Tile-Servern geladen. Dabei
werden <strong>IP-Adresse und User-Agent</strong> an OSM übertragen.
Dies ist notwendig, um überhaupt eine Karte darzustellen; es gilt
die{" "}
<a
className="text-blue-600 hover:underline"
href="https://wiki.osmfoundation.org/wiki/Privacy_Policy"
>
OSM Foundation Privacy Policy
</a>
.
</li>
<li>
<strong>Overpass API</strong> (POI-Daten) POI-Abfragen laufen
serverseitig über unsere eigene Route <code>/api/overpass</code>.
Der Upstream-Dienst sieht nur unsere Server-IP, nicht die Ihrer
Nutzer:innen. Aktueller Upstream: <code>overpass.private.coffee</code>
, der ohne Query-Logs arbeitet. Eine selbst gehostete Instanz ist
geplant.
</li>
<li>
<strong>BRouter</strong> Routenberechnung läuft auf einer von uns
selbst gehosteten Instanz. Keine Weitergabe an Dritte.
</li>
<li>
<strong>SMTP-Versand</strong> Transaktions-E-Mails (Magic Link,
Willkommensnachricht) werden über einen SMTP-Dienst versendet.
Dabei wird die E-Mail-Adresse der Empfänger:in an den SMTP-Dienst
übergeben.
</li>
<li>
<strong>Hosting</strong> Die Dienste werden in Rechenzentren
innerhalb der EU betrieben. Ein Auftragsverarbeitungsvertrag mit
dem Hoster besteht.
</li>
</ul>
<p className="mt-3 text-sm text-gray-600">
<em>English.</em> Third parties and what they receive: Sentry (error
details, no IPs/cookies, EU-hosted); OpenStreetMap tile servers
(your IP and user-agent, directly from your browser, to load map
tiles); Overpass (via our server-side proxy, so upstream only sees
our server); BRouter (self-hosted, no third party involved); SMTP
provider (your email address for magic link / welcome mail);
hosting provider in the EU under a DPA.
</p>
</section>
{/* ================================================================
7. Ihre Rechte / Rights
================================================================ */}
<section className="mt-10">
<h2 className="text-xl font-semibold text-gray-900">7. Ihre Rechte</h2>
<p className="mt-2 text-gray-700">
Als betroffene Person stehen Ihnen die folgenden Rechte zu:
</p>
<ul className="mt-3 list-disc pl-6 text-gray-700 space-y-1">
<li>Auskunft (Art. 15 DSGVO)</li>
<li>Berichtigung (Art. 16 DSGVO)</li>
<li>Löschung (Art. 17 DSGVO)</li>
<li>Einschränkung der Verarbeitung (Art. 18 DSGVO)</li>
<li>Datenübertragbarkeit (Art. 20 DSGVO)</li>
<li>Widerspruch gegen Verarbeitung auf Basis berechtigter Interessen (Art. 21 DSGVO)</li>
</ul>
<p className="mt-3 text-gray-700">
Zur Ausübung dieser Rechte genügt eine formlose E-Mail an{" "}
<a className="text-blue-600 hover:underline" href={`mailto:${operator.email}`}>
{operator.email}
</a>
. Ein vollständiger Export Ihrer Daten ist jederzeit direkt über die
Einstellungen Ihres Kontos möglich (Routen als GPX, Aktivitäten als
GPX/JSON). Sie können Ihr Konto jederzeit selbst löschen.
. Einen vollständigen Export Ihrer Routen und Aktivitäten können Sie
jederzeit direkt in den Kontoeinstellungen herunterladen (GPX bzw.
JSON). Ihr Konto samt Inhalten können Sie dort ebenfalls selbst
löschen.
</p>
<p className="mt-3 text-sm text-gray-600">
<em>English.</em> You have the standard GDPR rights (access,
rectification, erasure, restriction, portability, objection). Email
us to exercise them. Data exports and account deletion are also
available directly in your account settings.
</p>
</section>
{/* ================================================================
8. Beschwerderecht / Complaint authority
================================================================ */}
<section className="mt-10">
<h2 className="text-xl font-semibold text-gray-900">
4. Beschwerderecht / Right to Complain
</h2>
<p className="mt-2 text-gray-600">
<h2 className="text-xl font-semibold text-gray-900">8. Beschwerderecht</h2>
<p className="mt-2 text-gray-700">
Sie haben das Recht, sich bei einer Datenschutzaufsichtsbehörde zu
beschweren. Zuständig für uns ist:
beschweren. Für uns zuständig ist:
</p>
<address className="mt-2 not-italic text-gray-700">
Berliner Beauftragte für Datenschutz und Informationsfreiheit
@ -116,135 +316,89 @@ export default function PrivacyPage() {
www.datenschutz-berlin.de
</a>
</address>
<p className="mt-3 text-sm text-gray-600">
<em>English.</em> You have the right to lodge a complaint with a
supervisory authority; ours is the Berlin data-protection
commissioner (address above).
</p>
</section>
<hr className="my-10 border-gray-200" />
<hr className="my-12 border-gray-200" />
{/* Existing privacy manifest (plain-language) */}
{/* ================================================================
Privacy Manifest (developer-friendly, plain language)
================================================================ */}
<h2 className="text-2xl font-bold text-gray-900">Privacy Manifest</h2>
<p className="mt-4 text-gray-600">
trails.cool is committed to privacy by design. This manifest documents
everything we collect, why, and how you can control it.
<p className="mt-4 text-gray-700">
A plain-language summary of what we do, for readers who prefer
behaviour over paragraphs. Binding text is above.
</p>
<section className="mt-10">
<section className="mt-8">
<h3 className="text-xl font-semibold text-gray-900">Planner (planner.trails.cool)</h3>
<p className="mt-2 text-gray-600">
The Planner collects <strong>no personal data</strong>. Sessions are anonymous
there are no user accounts, no tracking, and no analytics on your routes.
<p className="mt-2 text-gray-700">
Anonymous by design. No account, no identifier, nothing persisted
past the session.
</p>
<ul className="mt-3 list-disc pl-6 text-gray-600 space-y-1">
<ul className="mt-3 list-disc pl-6 text-gray-700 space-y-1">
<li>No cookies, no localStorage, no sessionStorage</li>
<li>No user accounts or login</li>
<li>No browser-side error tracking (Sentry is not loaded in the Planner)</li>
<li>No route data is stored permanently without your action</li>
<li>Session data is automatically deleted after 7 days of inactivity</li>
<li>No browser-side error tracking (Sentry is not loaded)</li>
<li>Session data is deleted automatically after 7 days of inactivity</li>
</ul>
</section>
<section className="mt-10">
<section className="mt-8">
<h3 className="text-xl font-semibold text-gray-900">Journal (trails.cool)</h3>
<p className="mt-2 text-gray-600">
The Journal stores the data you explicitly provide:
<p className="mt-2 text-gray-700">
Holds only what you put in. Exportable any time, deletable any time.
</p>
<ul className="mt-3 list-disc pl-6 text-gray-600 space-y-1">
<li><strong>Account data</strong>: email, username, display name, passkey credentials</li>
<li><strong>Routes</strong>: name, description, GPX data, geometry</li>
<li><strong>Activities</strong>: title, description, date, linked routes</li>
<ul className="mt-3 list-disc pl-6 text-gray-700 space-y-1">
<li>Account: email, username, display name, passkey public key</li>
<li>Routes: GPX, geometry, title, description</li>
<li>Activities: title, description, date, linked route</li>
<li>GPX / JSON export available per object and overall</li>
</ul>
<p className="mt-3 text-gray-600">
All your data is exportable at any time in open formats (GPX, JSON).
You can self-host your own instance and migrate your data completely.
</p>
</section>
<section className="mt-10">
<h3 className="text-xl font-semibold text-gray-900">Error Tracking (Sentry)</h3>
<p className="mt-2 text-gray-600">
We use <a href="https://sentry.io" className="text-blue-600 hover:underline">Sentry</a> for
error monitoring, scoped narrowly by design.
</p>
<h4 className="mt-4 font-medium text-gray-800">Where Sentry runs:</h4>
<ul className="mt-2 list-disc pl-6 text-gray-600 space-y-1">
<li><strong>Journal, logged-out</strong>: server-side only. The browser-side Sentry SDK is not loaded until you log in.</li>
<li><strong>Journal, logged-in</strong>: Sentry initialises in the browser after login and is torn down on logout.</li>
<li><strong>Planner</strong>: server-side only. The browser-side Planner does not load Sentry at all.</li>
<section className="mt-8">
<h3 className="text-xl font-semibold text-gray-900">Sentry</h3>
<ul className="mt-3 list-disc pl-6 text-gray-700 space-y-1">
<li>Journal server: always on</li>
<li>Journal browser: only after login, torn down on logout</li>
<li>Planner: server only; the browser never loads Sentry</li>
<li>No IPs, no cookies, no headers (<code>sendDefaultPii: false</code>)</li>
<li>No replays (replay integration not installed, sample rates 0)</li>
<li>User ID only (no email/username) on Journal-logged-in events</li>
</ul>
<h4 className="mt-4 font-medium text-gray-800">What Sentry collects:</h4>
<ul className="mt-2 list-disc pl-6 text-gray-600 space-y-1">
<li><strong>Error details</strong>: stack traces, error messages, browser/OS info derived from the User-Agent</li>
<li><strong>Performance traces</strong>: page load times, route navigation timing</li>
<li><strong>User ID</strong> (Journal, logged-in only): just the user ID not username, email, or IP</li>
</ul>
<h4 className="mt-4 font-medium text-gray-800">What Sentry does NOT collect:</h4>
<ul className="mt-2 list-disc pl-6 text-gray-600 space-y-1">
<li>Session replays or DOM recordings replay integration is not installed and sample rates are 0</li>
<li>IP addresses, cookies, or full HTTP headers <code>sendDefaultPii</code> is set to <code>false</code> everywhere</li>
<li>Route or GPX data</li>
<li>Passwords or passkey credentials</li>
<li>Form input contents</li>
</ul>
<h4 className="mt-4 font-medium text-gray-800">Data retention:</h4>
<p className="mt-2 text-gray-600">
Sentry data is retained for 90 days and then automatically deleted.
Sentry&apos;s servers are hosted in the EU (Frankfurt).
</p>
</section>
<section className="mt-10">
<h3 className="text-xl font-semibold text-gray-900">Email</h3>
<p className="mt-2 text-gray-600">
The Journal sends transactional emails for magic link login and welcome messages
via SMTP. On the official instance, emails are sent through our own mail server.
</p>
<h4 className="mt-4 font-medium text-gray-800">What is sent via email:</h4>
<ul className="mt-2 list-disc pl-6 text-gray-600 space-y-1">
<li><strong>Magic link</strong>: a one-time login link sent to your email address</li>
<li><strong>Welcome email</strong>: a greeting after registration</li>
<section className="mt-8">
<h3 className="text-xl font-semibold text-gray-900">What we don&apos;t do</h3>
<ul className="mt-3 list-disc pl-6 text-gray-700 space-y-1">
<li>Sell data</li>
<li>Show ads</li>
<li>Build user profiles</li>
<li>Run tracking pixels, analytics, or A/B tests</li>
</ul>
<p className="mt-3 text-gray-600">
Self-hosted instances can configure their own SMTP server. No email content
is stored beyond what your mail server retains.
</p>
</section>
<section className="mt-10">
<h3 className="text-xl font-semibold text-gray-900">Third Parties</h3>
<ul className="mt-3 list-disc pl-6 text-gray-600 space-y-1">
<li><strong>Sentry</strong> (Functional Software Inc.) error tracking, as described above</li>
<li><strong>OpenStreetMap</strong> map tiles are loaded from OSM tile servers. OSM&apos;s <a href="https://wiki.osmfoundation.org/wiki/Privacy_Policy" className="text-blue-600 hover:underline">privacy policy</a> applies to tile requests.</li>
<li><strong>BRouter</strong> routing requests are processed by our self-hosted BRouter instance. No data is sent to third parties for routing.</li>
<section className="mt-8">
<h3 className="text-xl font-semibold text-gray-900">Security</h3>
<ul className="mt-3 list-disc pl-6 text-gray-700 space-y-1">
<li>Auth via passkey (WebAuthn) or magic link no passwords stored</li>
<li>HTTPS + HSTS preload on all origins; session cookies httpOnly + Secure</li>
<li>CSP, X-Frame-Options, X-Content-Type-Options on every response</li>
<li>Containers run non-root; host firewall restricts to HTTP/HTTPS/SSH</li>
<li>Gitleaks + dependency audit on every PR</li>
<li>
<strong>Overpass API</strong> POI overlay data is fetched via the Overpass API. Requests are proxied
through our own server (<code>/api/overpass</code>), so the upstream Overpass host sees our server rather
than end users&apos; IP addresses or browsers. The current upstream is{" "}
<a href="https://private.coffee" className="text-blue-600 hover:underline">overpass.private.coffee</a>,
which operates without query logging. A self-hosted Overpass instance is planned.
Vulnerability reports:{" "}
<a
className="text-blue-600 hover:underline"
href="https://github.com/trails-cool/trails/blob/main/SECURITY.md"
>
SECURITY.md
</a>
</li>
<li><strong>SMTP provider</strong> transactional emails (magic link, welcome) are delivered via SMTP. Self-hosters configure their own provider.</li>
</ul>
</section>
<section className="mt-10">
<h3 className="text-xl font-semibold text-gray-900">What We Don&apos;t Do</h3>
<ul className="mt-3 list-disc pl-6 text-gray-600 space-y-1">
<li>We don&apos;t sell data</li>
<li>We don&apos;t show ads</li>
<li>We don&apos;t build user profiles</li>
<li>We don&apos;t use tracking pixels or analytics</li>
<li>We don&apos;t share data with anyone except as listed above</li>
</ul>
</section>
<section className="mt-10">
<h3 className="text-xl font-semibold text-gray-900">Security Practices</h3>
<ul className="mt-3 list-disc pl-6 text-gray-600 space-y-1">
<li><strong>Authentication</strong>: Passkey (WebAuthn) and magic link login. No passwords stored.</li>
<li><strong>Encryption</strong>: All traffic over HTTPS with HSTS preload. Cookies are httpOnly and secure.</li>
<li><strong>Headers</strong>: Content-Security-Policy, X-Frame-Options, X-Content-Type-Options on all responses.</li>
<li><strong>Infrastructure</strong>: Docker containers run as non-root. Firewall restricts to HTTP/HTTPS/SSH only.</li>
<li><strong>CI/CD</strong>: Gitleaks secret scanning and dependency auditing on every pull request.</li>
<li><strong>Vulnerability reporting</strong>: See our <a href="https://github.com/trails-cool/trails/blob/main/SECURITY.md" className="text-blue-600 hover:underline">SECURITY.md</a> for responsible disclosure.</li>
</ul>
</section>
</div>

View file

@ -1,6 +1,6 @@
export function meta() {
return [
{ title: "Terms of Service — trails.cool" },
{ title: "Nutzungsbedingungen — trails.cool" },
{ name: "robots", content: "noindex" },
];
}
@ -12,175 +12,217 @@ export default function TermsPage() {
Nutzungsbedingungen / Terms of Service
</h1>
<p className="mt-2 text-sm text-gray-500">
Last updated: 2026-04-17 Alpha version subject to change
Stand / Last updated: 2026-04-18 Alpha subject to change. Die
deutsche Fassung ist maßgeblich. The German version is authoritative;
English summaries follow each section.
</p>
{/* Deutsche Fassung (maßgebend) */}
<section className="mt-10 space-y-4 text-gray-700">
<h2 className="text-xl font-semibold text-gray-900">Deutsche Fassung</h2>
<section className="mt-10 space-y-6 text-gray-700">
<div>
<h2 className="text-lg font-semibold text-gray-900">
1. Gegenstand und Alpha-Status
</h2>
<p className="mt-2 text-sm">
trails.cool ist ein experimenteller, kostenloser Dienst zur Planung
und Dokumentation von Outdoor-Aktivitäten. Der Dienst befindet sich
in aktiver Entwicklung (Alpha). Funktionen, Schnittstellen und
gespeicherte Daten können jederzeit ohne Vorankündigung geändert,
unterbrochen, gelöscht oder eingestellt werden. Eine
Verfügbarkeitsgarantie besteht nicht.
</p>
<p className="mt-2 text-xs text-gray-600">
<em>English.</em> trails.cool is an experimental, free service in
active alpha development. Features, data, and availability can
change at any time without notice. No availability is guaranteed.
</p>
</div>
<h3 className="mt-6 text-base font-semibold text-gray-900">
1. Gegenstand und Alpha-Status
</h3>
<p className="text-sm">
trails.cool ist ein experimenteller Dienst zur Planung und Dokumentation
von Outdoor-Aktivitäten. Der Dienst befindet sich in aktiver Entwicklung
(Alpha). Funktionen, Schnittstellen und gespeicherte Daten können
jederzeit ohne Vorankündigung geändert, gelöscht oder eingestellt
werden. Eine Verfügbarkeitsgarantie besteht nicht.
</p>
<div>
<h2 className="text-lg font-semibold text-gray-900">
2. Mindestalter
</h2>
<p className="mt-2 text-sm">
Die Nutzung eines Journal-Kontos ist erst ab einem Alter von 16
Jahren zulässig. Anonyme Nutzung des Planners unterliegt keiner
Altersbeschränkung.
</p>
<p className="mt-2 text-xs text-gray-600">
<em>English.</em> A Journal account is available only to users
aged 16 or older. Anonymous use of the Planner has no age
requirement.
</p>
</div>
<h3 className="mt-6 text-base font-semibold text-gray-900">
2. Zurücksetzen der Datenbank
</h3>
<p className="text-sm">
Während der Alpha-Phase behält sich der Betreiber ausdrücklich das Recht
vor, die gesamte Datenbank zurückzusetzen oder einzelne Datensätze ohne
vorherige Benachrichtigung zu löschen. Nutzer:innen sollten wichtige
Routen und Aktivitäten selbstständig über die Export-Funktion (GPX)
sichern.
</p>
<div>
<h2 className="text-lg font-semibold text-gray-900">
3. Dienstverfügbarkeit
</h2>
<p className="mt-2 text-sm">
Der Betreiber kann den Dienst jederzeit ändern, einschränken,
unterbrechen oder einstellen, auch einzelne Funktionen oder
einzelne Konten. Wartungs- und Ausfallzeiten sind möglich.
</p>
<p className="mt-2 text-xs text-gray-600">
<em>English.</em> The operator may modify, limit, interrupt, or
discontinue the service (or parts of it, or individual accounts)
at any time. Downtime and maintenance windows may occur.
</p>
</div>
<h3 className="mt-6 text-base font-semibold text-gray-900">
3. Haftungsausschluss
</h3>
<p className="text-sm">
Der Dienst wird ohne jegliche Gewährleistung bereitgestellt. Eine Haftung
für Schäden, die durch die Nutzung oder Nichtverfügbarkeit des Dienstes
entstehen, ist ausgeschlossen, soweit dies gesetzlich zulässig ist. Bei
Vorsatz und grober Fahrlässigkeit sowie bei Verletzung von Leben, Körper
und Gesundheit gelten die gesetzlichen Vorschriften.
</p>
<div>
<h2 className="text-lg font-semibold text-gray-900">
4. Zurücksetzen der Datenbank
</h2>
<p className="mt-2 text-sm">
Während der Alpha-Phase behält sich der Betreiber ausdrücklich das
Recht vor, die gesamte Datenbank zurückzusetzen oder einzelne
Datensätze ohne vorherige Benachrichtigung zu löschen.
Nutzer:innen sollten wichtige Routen und Aktivitäten selbstständig
über die Export-Funktion (GPX bzw. JSON) sichern.
</p>
<p className="mt-2 text-xs text-gray-600">
<em>English.</em> During alpha, the operator may reset the entire
database or delete individual records without notice. Back up
anything important via the GPX / JSON export.
</p>
</div>
<h3 className="mt-6 text-base font-semibold text-gray-900">
4. Nutzungsregeln
</h3>
<ul className="ml-6 list-disc space-y-1 text-sm">
<li>Keine Verbreitung rechtswidriger Inhalte</li>
<li>Keine missbräuchliche Nutzung (Spam, automatisierte Abfragen in
hoher Frequenz, Denial-of-Service)
</li>
<li>Kein Umgehen technischer Schutzmaßnahmen</li>
</ul>
<div>
<h2 className="text-lg font-semibold text-gray-900">
5. Eigenverantwortung für Daten
</h2>
<p className="mt-2 text-sm">
Nutzer:innen sind für die Sicherung ihrer Inhalte selbst
verantwortlich. GPX- und JSON-Exporte sind im Journal jederzeit
für jede Route und Aktivität verfügbar. Der Betreiber schuldet
keine Datenwiederherstellung.
</p>
<p className="mt-2 text-xs text-gray-600">
<em>English.</em> You are responsible for backing up your own
content. Exports are always available in the Journal; the
operator owes no data recovery.
</p>
</div>
<h3 className="mt-6 text-base font-semibold text-gray-900">
5. Eigenverantwortung für Daten
</h3>
<p className="text-sm">
Nutzer:innen sind dafür verantwortlich, regelmäßig Sicherungskopien ihrer
Routen und Aktivitäten anzufertigen. GPX-Exporte sind im Journal für
jede Route und Aktivität verfügbar.
</p>
<div>
<h2 className="text-lg font-semibold text-gray-900">
6. Inhalte und Nutzungsrechte
</h2>
<p className="mt-2 text-sm">
Die von Ihnen eingestellten Inhalte (Routen, Aktivitäten,
Beschreibungen, GPX-Dateien) bleiben Ihr Eigentum. Sie räumen dem
Betreiber lediglich das einfache, nicht übertragbare Recht ein,
diese Inhalte zum Zweck des Betriebs des Dienstes zu speichern,
zu verarbeiten und Ihnen wieder anzuzeigen. Eine darüber
hinausgehende Nutzung, Veröffentlichung oder Weitergabe findet
nicht statt.
</p>
<p className="mt-2 text-xs text-gray-600">
<em>English.</em> You retain ownership of everything you upload.
You grant the operator a limited, non-transferable licence to
store, process, and display your content solely for operating the
service; no other use, publication, or sharing.
</p>
</div>
<h3 className="mt-6 text-base font-semibold text-gray-900">
6. Beendigung
</h3>
<p className="text-sm">
Nutzer:innen können ihr Konto jederzeit über die Einstellungen löschen.
Der Betreiber kann Konten bei Verstößen gegen diese Bedingungen sperren
oder löschen.
</p>
<div>
<h2 className="text-lg font-semibold text-gray-900">
7. Nutzungsregeln
</h2>
<ul className="mt-2 ml-6 list-disc space-y-1 text-sm">
<li>Keine Verbreitung rechtswidriger Inhalte</li>
<li>
Keine missbräuchliche Nutzung (Spam, hochfrequente automatisierte
Abfragen, Denial-of-Service)
</li>
<li>Kein Umgehen technischer Schutzmaßnahmen</li>
<li>
Keine Verwendung des Dienstes zum Aufbau konkurrierender
Angebote durch massenhaftes Abziehen von Daten
</li>
</ul>
<p className="mt-2 text-xs text-gray-600">
<em>English.</em> No illegal content, no abuse (spam, flooding,
DoS), no circumvention of technical protections, no bulk scraping
to build competing services.
</p>
</div>
<h3 className="mt-6 text-base font-semibold text-gray-900">
7. Änderungen
</h3>
<p className="text-sm">
Diese Nutzungsbedingungen können sich während der Alpha-Phase ändern. Bei
wesentlichen Änderungen werden registrierte Nutzer:innen per E-Mail
informiert und müssen die neuen Bedingungen erneut bestätigen.
</p>
<div>
<h2 className="text-lg font-semibold text-gray-900">
8. Kontobeendigung
</h2>
<p className="mt-2 text-sm">
Sie können Ihr Konto jederzeit über die Einstellungen löschen;
damit werden auch die zugehörigen Inhalte gelöscht. Der Betreiber
kann Konten bei Verstößen gegen diese Bedingungen nach
angemessener Interessenabwägung sperren oder löschen.
</p>
<p className="mt-2 text-xs text-gray-600">
<em>English.</em> Delete your account (and its content) any time
via settings. The operator may suspend or delete accounts that
violate these terms, balancing interests reasonably.
</p>
</div>
<h3 className="mt-6 text-base font-semibold text-gray-900">
8. Anwendbares Recht
</h3>
<p className="text-sm">
Es gilt deutsches Recht unter Ausschluss des UN-Kaufrechts. Verbraucher:innen
mit gewöhnlichem Aufenthalt in der EU genießen den zwingenden Schutz
ihres nationalen Verbraucherrechts.
</p>
</section>
<div>
<h2 className="text-lg font-semibold text-gray-900">
9. Haftung
</h2>
<p className="mt-2 text-sm">
Der Dienst wird ohne Gewährleistung bereitgestellt. Der Betreiber
haftet uneingeschränkt bei Vorsatz und grober Fahrlässigkeit sowie
bei Verletzung von Leben, Körper oder Gesundheit. Im Übrigen ist
die Haftung für leicht fahrlässige Pflichtverletzungen auf den
vertragstypischen, vorhersehbaren Schaden bei Verletzung
wesentlicher Vertragspflichten (Kardinalpflichten) begrenzt. Eine
darüber hinausgehende Haftung insbesondere für Datenverlust
ist ausgeschlossen, soweit gesetzlich zulässig.
</p>
<p className="mt-2 text-xs text-gray-600">
<em>English.</em> No warranty. Unlimited liability for intent,
gross negligence, and injury to life, body, or health. For
slight negligence, liability is limited to foreseeable damages
arising from breach of material contractual duties. Liability
beyond that in particular for data loss is excluded to the
extent permitted by law.
</p>
</div>
<hr className="my-12 border-gray-200" />
<div>
<h2 className="text-lg font-semibold text-gray-900">
10. Änderungen der Bedingungen
</h2>
<p className="mt-2 text-sm">
Diese Nutzungsbedingungen können sich während der Alpha-Phase
ändern. Bei wesentlichen Änderungen werden registrierte
Nutzer:innen per E-Mail informiert und müssen die neuen
Bedingungen erneut bestätigen.
</p>
<p className="mt-2 text-xs text-gray-600">
<em>English.</em> These terms may change during alpha. Registered
users will be emailed about material changes and prompted to
re-accept.
</p>
</div>
{/* English translation (informational) */}
<section className="space-y-4 text-gray-700">
<h2 className="text-xl font-semibold text-gray-900">English version</h2>
<p className="text-xs text-gray-500">
The German version is authoritative. This English text is a translation
for convenience.
</p>
<h3 className="mt-6 text-base font-semibold text-gray-900">
1. Alpha status
</h3>
<p className="text-sm">
trails.cool is an experimental service for planning and documenting
outdoor activities. It is under active development (alpha). Features,
APIs, and stored data may change, be deleted, or be discontinued at any
time without notice. No availability is guaranteed.
</p>
<h3 className="mt-6 text-base font-semibold text-gray-900">
2. Database resets
</h3>
<p className="text-sm">
During alpha, the operator expressly reserves the right to reset the
entire database or delete individual records without prior notice. Users
should back up important routes and activities via the GPX export.
</p>
<h3 className="mt-6 text-base font-semibold text-gray-900">
3. No warranty
</h3>
<p className="text-sm">
The service is provided without any warranty. Liability for damages
arising from use or unavailability is excluded to the maximum extent
permitted by law. Statutory provisions apply for intent, gross
negligence, and injury to life, body, or health.
</p>
<h3 className="mt-6 text-base font-semibold text-gray-900">
4. Acceptable use
</h3>
<ul className="ml-6 list-disc space-y-1 text-sm">
<li>No illegal content</li>
<li>No abusive use (spam, high-frequency automated requests, denial of service)</li>
<li>No circumvention of technical protections</li>
</ul>
<h3 className="mt-6 text-base font-semibold text-gray-900">
5. Data responsibility
</h3>
<p className="text-sm">
Users are responsible for regularly backing up their routes and
activities. GPX exports are available in the Journal for every route
and activity.
</p>
<h3 className="mt-6 text-base font-semibold text-gray-900">
6. Termination
</h3>
<p className="text-sm">
Users can delete their account at any time via settings. The operator
may suspend or delete accounts that violate these terms.
</p>
<h3 className="mt-6 text-base font-semibold text-gray-900">
7. Changes
</h3>
<p className="text-sm">
These terms may change during alpha. Registered users will be notified
by email of material changes and must re-accept the updated terms.
</p>
<h3 className="mt-6 text-base font-semibold text-gray-900">
8. Governing law
</h3>
<p className="text-sm">
German law applies, excluding the UN Convention on Contracts for the
International Sale of Goods. Consumers habitually residing in the EU
retain the mandatory protection of their national consumer law.
</p>
<div>
<h2 className="text-lg font-semibold text-gray-900">
11. Anwendbares Recht
</h2>
<p className="mt-2 text-sm">
Es gilt deutsches Recht unter Ausschluss des UN-Kaufrechts. Für
Verbraucher:innen mit gewöhnlichem Aufenthalt in einem Mitgliedstaat
der Europäischen Union bleibt der zwingende Schutz des Rechts ihres
Aufenthaltslandes unberührt.
</p>
<p className="mt-2 text-xs text-gray-600">
<em>English.</em> German law applies, excluding the UN Convention
on Contracts for the International Sale of Goods. Consumers
habitually residing in an EU member state retain the mandatory
protection of their national law.
</p>
</div>
</section>
</div>
);