sorted markdown and added favicon
Sonarqube Scanner / Prepare environment (push) Successful in 13s
Sonarqube Scanner / Build and test (push) Successful in 33s
Sonarqube Scanner / SonarQube analysis (push) Successful in 1m38s
Sonarqube Scanner / Deploy to Server (push) Successful in 7s

This commit is contained in:
Florian Zumpe
2026-10-04 09:06:48 +02:00
parent 497b7b8050
commit 74090723c4
22 changed files with 1133 additions and 5 deletions
+85
View File
@@ -0,0 +1,85 @@
# Agent-Anweisungen für Wegwichtel
Diese Datei vor jeder Änderung am Projekt lesen. Sie gilt für das gesamte
Repository. Da sie unter `docs/agents/` liegt, muss ihr Pfad in Übergaben und
Agent-Aufträgen ausdrücklich genannt werden; eine automatische Suche nach
einer `AGENTS.md` im Projektverzeichnis findet sie dort nicht.
## Ablage der Dokumentation
- Markdown mit Agent-Anweisungen, Entwicklungsvorgaben und offenen
Entwicklungsaufgaben ausschließlich unter `docs/agents/` ablegen.
- Markdown für Anwender und Betrieb ausschließlich direkt unter `docs/` ablegen.
- Keine eigenen Markdown-Dateien im Projektverzeichnis oder neben Werkzeugen
und ausgelieferten Bibliotheken anlegen. Links nach Umzügen aktualisieren.
- Bei Übergaben die relevanten Markdown-Dateien im Repository mit ihren
aktuellen Pfaden ausdrücklich nennen, insbesondere diese Datei sowie
`docs/agents/I18N.md`, `docs/agents/GPX-Aufzeichnung.md` und
`docs/agents/TODO-MODERATION.md`.
# Wegwichtel: Sprache der App
GPX-Änderungen berücksichtigen `GPX-Aufzeichnung.md`: Stationen sind `wpt`,
Aufzeichnungen sind `trkpt`, der Server normalisiert zu `rtept`. Fehlende
Koordinaten bleiben gespeichert und bearbeitbar; keine Ersatzkoordinaten erfinden.
Die GPX-Dateien sind die einzige Quelle der Routenpunkte und berechneten
Routenwerte. SQLite speichert davon nur Min-/Max-Grenzen für die Näheresuche.
Schemaänderungen immer auch mit der Startprüfung an einer vorhandenen,
frisch erzeugten Testdatenbank prüfen.
Diese Vorgabe des Nutzers gilt für alle künftigen Änderungen an der Oberfläche.
Die App richtet sich an Grundschulkinder und Menschen ohne technische Vorkenntnisse.
- Schreibe kurze, verständliche Sätze. Sprich die Nutzer mit „du“ an.
- Erkläre, was eine Aktion bewirkt und was als Nächstes zu tun ist.
- Verwende durchgängig „Strecke“, „Station“, „Meine Entwürfe“ und „für unterwegs speichern“.
- Technische Begriffe wie GPX, JSON, Cache, API, OPFS, IndexedDB, Local Storage,
Server, Token oder interne Feldnamen gehören nicht in Bedienungstexte,
Hilfe, Statusmeldungen, Dateiauswahl-Beschreibungen oder vorgelesene Beschriftungen.
- Bezeichne einen Wegexport als „Weg als Datei herunterladen“. Erkläre bei Bedarf,
dass die Datei für eine andere Wander-App gedacht ist und keine Bilder oder Ton enthält.
- Verwende „Bilder und Tonaufnahmen“ statt „Medien“, „Zur Prüfung senden“ statt „Upload“
und „auf diesem Gerät“ statt „lokal im Browser“.
- Fehlermeldungen nennen das Problem und einen verständlichen nächsten Schritt.
Zeige keine rohen Fehler aus dem Betriebssystem, Netzwerkantworten oder Dateipfade.
- Vereinfache auch Hilfen zu Daten und Speicher. Behalte wichtige Angaben zu
Löschung, Erlaubnissen, Grenzen und Speicher-Schätzungen bei. Mache keine
Zusicherungen, die die App nicht einhalten kann.
- Rechtliche Texte dürfen notwendige Rechtsbegriffe behalten. Erkläre sie einfach;
ändere dabei nicht die Bedeutung, Verantwortlichen oder Kontaktdaten.
- Fachliche Details für Entwicklung und Betrieb gehören in Projekt-Dokumentation
und Code-Kommentare. Code-Bezeichner, Dateiformate und Schnittstellen bleiben fachlich präzise.
- Prüfe neue Texte und angepasste Text-Erwartungen in den vorhandenen Tests.
## Texte und Übersetzungen
- Alle eigenen Bedienungstexte liegen zentral in der Klasse `WegwichtelTexts`
in `public/js/texts-de.js`. Keine neuen sichtbaren Texte direkt in HTML oder
Funktionscode schreiben.
- Ausnahme: Impressum und Datenschutzerklärung bleiben ausschließlich statisch
auf Deutsch in `public/index.html` und tragen `lang="de"`. Ihre Texte und
Kontaktangaben gehören nicht in Sprachdateien und erhalten keine i18n-Attribute.
Auch ihre Dialogüberschriften bleiben beim Sprachwechsel auf Deutsch.
- Das HTML enthält daraus erzeugte deutsche Standardtexte, damit Beschriftungen
vor dem Laden der Skripte vorhanden sind. Nach Änderungen am Textkatalog
`node scripts/localize-html.js` ausführen und `public/index.html` mit ablegen.
Diese erzeugten Texte nicht von Hand ändern; die i18n-Attribute bleiben erhalten.
- JavaScript bezieht Texte über `Wegwichtel.I18n.t(textKey, variables)`.
HTML verwendet `data-i18n` bzw. `data-i18n-aria-label`, `data-i18n-title`,
`data-i18n-placeholder` und `data-i18n-alt`.
- Zahlen und Namen sind Platzhalter; ganze Sätze übersetzen, keine Sätze aus
deutschen Wortteilen zusammensetzen. Für Mengen Einzahl und Mehrzahl verwenden.
- Nutzerinhalte wie Streckennamen, Beschreibungen und Aufnahmen nicht automatisch
übersetzen oder verändern. Interne Fehlerdiagnosen dürfen technisch bleiben;
die sichtbare Meldung muss verständlich sein.
- Sprachdateien heißen `public/js/texts-<Sprache>.js` und verwenden dieselbe
generische Klasse `WegwichtelTexts`. Sie registrieren sich in `TextCatalogs`.
Die App lädt Deutsch und Englisch und wählt anhand von `navigator.languages`
bzw. `navigator.language`. Fehlende Übersetzungen fallen auf den ersten
geladenen Katalog zurück (in der App Deutsch).
- Verwende kurze, stabile englische Funktionsschlüssel wie `app.no-route` oder
`bootstrap-loader.error.start-error`. Schlüssel nicht aus dem deutschen Text
ableiten. Startmeldungen in `bootstrap-loader.steps` nach Schritt gruppieren.
- Deutsch und Englisch enthalten dieselben Schlüssel, Platzhalter und Pluralformen.
Texte in beiden Sprachen einfach und sinngemäß schreiben. Sprachwechsel aktualisieren feste Beschriftungen;
bereits erzeugte dynamische Ansichten bei Bedarf neu rendern.
+99
View File
@@ -0,0 +1,99 @@
# GPX und Wegaufzeichnung
## Stationen und Weg getrennt speichern
- Stationen mit Koordinaten stehen als `wpt` unmittelbar unter `gpx`.
- Beim ersten Speichern eines neuen Entwurfs startet während der Bearbeitung eine Aufzeichnung:
sofort eine Position, danach alle 30 Sekunden eine neue GPS-Abfrage.
Schließen, Abbrechen, Rückkehr zur Streckenliste oder Wechsel der Strecke
beendet die Aufzeichnung. Nach einem Neustart ist sie inaktiv. Beim erneuten
Öffnen eines lokalen Entwurfs zur Bearbeitung beginnt eine neue Sitzung.
Speichern innerhalb derselben Sitzung hebt Pause oder bewusstes Stoppen nicht auf.
- Die sichtbaren Schaltflächen erlauben Pausieren, Fortsetzen und Beenden.
Beim Löschen des Entwurfs endet die Aufzeichnung ebenfalls.
- Tatsächliche Positionen stehen als `trk/trkseg/trkpt` mit Zeitstempel und,
falls vorhanden, Höhe in der Datei des Entwurfs.
- Ohne Standort entsteht eine Erweiterung `wegwichtel:gpsGap` mit Zeitstempel.
Eine Station ohne Standort steht als `wegwichtel:pendingWaypoint` in den
Erweiterungen. Es werden keine Koordinaten wie `0,0` erfunden. Leere GPX-
`wpt` oder `trkpt` wären ungültig, daher werden Erweiterungen verwendet.
Die Aufzeichnung speichert immer die neueste Fassung des Entwurfs, damit
gleichzeitige Änderungen an Stationen erhalten bleiben. Auch eine manuelle
Bearbeitung ergänzt die neueste Aufzeichnung und bewahrt inzwischen hinzugekommene
Positionen. Speicherfehler pausieren die Aufzeichnung und zeigen einen Hinweis.
## Später Koordinaten ergänzen
Entwürfe und Stationen dürfen ohne GPS erstellt und gespeichert werden.
In der Streckenbearbeitung können unter „Orte auf dem Weg ergänzen“ fehlende
Positionen ergänzt, vorhandene geändert und weitere hinzugefügt werden.
Breiten- und Längengrad müssen gemeinsam angegeben werden oder beide leer bleiben.
Stationen haben eigene Felder unter „Ort ergänzen“.
Die Serverdatenbank erlaubt `NULL` in `pois.lat` und `pois.lon`.
Die Tabelle `route_points` entfällt. Routenpunkte, Start und Mittelpunkt,
Weglänge, Höhengewinn und Punktzahl werden aus der gespeicherten GPX-Datei
gelesen beziehungsweise berechnet. Die Änderung ist in
`database/schema.sql` enthalten; eine bestehende Datenbank bekommt sie nicht
allein durch das Kopieren des Codes. Das Projekt verwendet beim Deployment
die vereinbarte Neuerstellung der Datenbank, keine automatische Migration.
SQLite enthält weiterhin Verwaltungseinträge, Freigaben sowie Stations- und
Medienangaben. Von den berechneten Routenwerten bleiben dort ausschließlich
`min_lat`, `min_lon`, `max_lat` und `max_lon` als Suchwerte erhalten. Die
Näheresuche verwendet diese Grenzen zur Vorauswahl und berechnet anschließend
den Abstand zum Start aus der GPX-Datei. Anlegen, Ersetzen, Anhängen und Änderungen
an Stationen aktualisieren die Grenzen. Ohne Koordinaten bleiben alle vier leer.
Die Startprüfung erwartet dasselbe Schema einschließlich der optionalen
Stationskoordinaten, lehnt die entfernte Tabelle und Routenspalten ab und prüft
die Suchgrenzen gegen die GPX-Dateien. Ein zusätzlicher Test führt die Prüfung
in einem getrennten Prozess mit einer echten temporären Datenbank und Dateien
aus. Damit wird der Fall einer vorhandenen Datenbank auch beim normalen
Coverage-Lauf geprüft.
## Normalisierung auf dem Server
Beim Einreichen oder Ersetzen einer GPX-Datei normalisiert der Node-Dienst den
aufgezeichneten Weg zu `rte/rtept`. Bereits vorhandene Routenpunkte haben Vorrang.
Aufeinanderfolgende Trackpunkte innerhalb des eingestellten Abstands werden
zusammengefasst. Der erste Punkt bleibt der Vertreter; der nächste wird erst
übernommen, wenn er weiter entfernt liegt. So werden kleine Schwankungen
während einer Pause nicht fortlaufend zur Weglänge addiert.
`GPX_CLUSTER_METERS` in `.env` steuert den Abstand, standardmäßig 20 Meter.
Das Verfahren ist eine geometrische Vereinfachung ohne externen Routingdienst.
Es berechnet keine Wege auf einer Straßenkarte. GPS-Lücken werden bei der
Routenberechnung übersprungen; zwischen gültigen Nachbarpunkten entsteht eine
direkte Verbindung. Die Lücken bleiben für spätere Bearbeitung als Erweiterungen
erhalten. Gibt es keine gültigen Wegpositionen, bleiben Weglänge und Punktzahl
bei 0 Metern und 0 Punkten; Stationen bleiben trotzdem gespeichert.
Die gespeicherte Serverdatei enthält den normalisierten Weg. Änderungen an
Stationen synchronisieren die `wpt` und die noch unvollständigen Stationen in
dieser Datei. GPX verwendet unverändert den Namespace
`http://www.topografix.com/GPX/1/1`; das ist eine Kennung, kein Netzwerkabruf.
## Anzeige beim Abspielen
Zwei Pfeile zeigen gleichzeitig die Richtung:
- zum nächsten Routenpunkt, ohne Entfernungsangabe;
- zur nächsten noch offenen Station mit Koordinaten, mit Metern.
Bei einer Strecke mit ausschließlich Stationen fehlt nur die Wegführung.
Stationen ohne Koordinaten lösen keine Standort-Erkennung aus. Während einer
Pause werden die Pfeile verborgen.
## Grenzen und Prüfung
Die Aufzeichnung läuft nur im geöffneten App-Fenster. Neuladen beendet sie;
bereits gespeicherte Positionen bleiben erhalten. Browser und Betriebssystem
können Zeitgeber und Standort-Abfragen im Hintergrund oder bei gesperrtem
Bildschirm verzögern. Ein verlässlicher Hintergrunddienst wird nicht zugesichert.
Bei verweigerter Standort-Erlaubnis bleiben die Einträge leer und bearbeitbar.
Die Tests prüfen Aufzeichnung, Pause/Fortsetzen/Ende, verspätete GPS-Antworten,
Speicherfehler, GPS-Lücken, manuelle Ergänzungen, getrennte Pfeile,
Servernormalisierung sowie Stationen ohne Koordinaten über die API.
+56
View File
@@ -0,0 +1,56 @@
# Texte und Sprachen
Die Sprachdateien `public/js/texts-de.js` und `public/js/texts-en.js` enthalten
jeweils die generische Klasse `WegwichtelTexts`. Beide Dateien verwenden dieselben
Schlüssel und registrieren ihren Katalog mit der eigenen Sprachkennung in
`Wegwichtel.TextCatalogs`. Es gibt keine sprachabhängigen Klassennamen.
Die App lädt beide Kataloge vor `i18n.js`. Beim Start wird die erste unterstützte
Sprache aus `navigator.languages` gewählt; ohne diese Liste wird
`navigator.language` verwendet. Regionale Varianten wie `en-GB` oder `de-DE`
verwenden den passenden Grundkatalog. Passt keine Sprache, wird der erste
geladene Katalog verwendet: in der App Deutsch. Einzelne fehlende Übersetzungen
fallen ebenfalls auf diesen Katalog zurück. Wird nur eine Sprachdatei eingebunden,
funktioniert sie allein und bildet den Fallback.
## Verwendung
Schlüssel beschreiben die Funktion, nicht den Wortlaut. Zusammengehörige Texte
liegen in verschachtelten Abschnitten; der Aufruf verwendet Punkte als Trennung.
```js
Wegwichtel.I18n.t('app.no-route');
Wegwichtel.I18n.t('bootstrap-loader.error.start-error');
Wegwichtel.I18n.t(`bootstrap-loader.steps.${step}`);
Wegwichtel.I18n.t('media.image.count', { count: 2 });
```
`bootstrap-loader.steps` ist nach den stabilen Schrittkennungen aufgebaut:
`storage`, `jquery`, `jquery-ui`, `modules`, `server`, `routes` und `location`.
Die Zuordnung benötigt keine zusätzliche Liste von Nachrichtenschlüsseln.
HTML verwendet `data-i18n`, `data-i18n-title`, `data-i18n-aria-label`,
`data-i18n-placeholder` und `data-i18n-alt`. Deutsche Standardtexte werden mit
`node scripts/localize-html.js` aus dem Katalog ins HTML übernommen. Dadurch
stehen Beschriftungen bereits vor dem Laden der Skripte bereit. Nach Änderungen
die erzeugte `public/index.html` mit ins Repository übernehmen.
Impressum und Datenschutzerklärung sind davon ausgenommen. Ihre rechtlichen
Texte und Kontaktangaben stehen ausschließlich statisch auf Deutsch in
`public/index.html`, ohne i18n-Attribute und mit `lang="de"` an beiden Artikeln.
Änderungen an diesen Angaben direkt im HTML vornehmen. Auch die zugehörigen
Dialogüberschriften bleiben auf Deutsch. Die Menüeinträge und die übrige
Bedienoberfläche werden weiterhin übersetzt.
Zum gezielten Prüfen kann `Wegwichtel.I18n.setLanguage('en')` aufgerufen werden.
Das aktualisiert feste Beschriftungen. Bereits aufgebaute dynamische Ansichten
müssen neu aufgebaut werden; die automatische Startauswahl erfolgt vor ihrem
ersten Aufbau. Ein sichtbarer Sprachschalter ist nicht enthalten.
Die Tests prüfen beide Kataloge, Platzhalter und Pluralformen, Browserpräferenzen,
den Betrieb mit nur einer Sprachdatei, deutsche HTML-Standardtexte und englische
App-Meldungen. Nutzerinhalte wie Streckennamen werden nicht übersetzt.
SonarQube prüft auch die Sprachdateien auf Probleme und Testabdeckung. Nur die
Duplikaterkennung nimmt `public/js/texts-*.js` aus: Übersetzungskataloge müssen
dieselbe Struktur haben und sind keine mehrfach implementierte Programmlogik.
+53
View File
@@ -0,0 +1,53 @@
# SonarQube-Auswertung vom 3. Oktober 2026
Basis: Export `Wegwichtel-sonarqube-export(17).json`, Repository `cf4170f`.
Von 119 exportierten Issues sind fünf offen; die übrigen sind bereits geschlossen.
## Code-Korrekturen
- `javascript:S7773`, `public/js/local-routes.js`: beide globalen `NaN` durch
`Number.NaN` ersetzt. Fehlende Positionen bleiben weiterhin ungültige Zahlen
und werden als GPS-Lücken gespeichert.
- `javascript:S3358`, `src/services/gpx.js`: Auswahl der Punkte für die
Metrikberechnung in eine eigene Variable ausgelagert. Keine verschachtelte
bedingte Operation mehr; die bisherigen Fälle bleiben erhalten.
- `javascript:S1481`, `src/services/gpx.js`: die beiden unbenutzten Variablen
`_oldWaypoints` und `_oldPending` entfernt. Alte Wegpunkte und unvollständige
Stationen werden gezielt entfernt, bevor die aktuelle Stationsliste entsteht.
Andere Erweiterungen bleiben erhalten.
Das bereits korrigierte Moderationsskript bleibt unverändert.
## Security-Hotspot mit notwendiger Bewertung in SonarQube
- Schlüssel: `7854386c-ec53-4e14-b374-d7d356accf23`
- Datei: `src/services/gpx.js`
- Regel: `javascript:S5332`
- Meldung: Verwendung des HTTP-Protokolls
- Empfohlene Bewertung nach Prüfung: **Safe**
Begründung zum Einfügen in SonarQube:
> Die Zeichenfolge `http://www.topografix.com/GPX/1/1` ist der offizielle
> XML-Namespace von GPX 1.1. Die Funktion schreibt sie als xmlns-Attribut in die
> erzeugte GPX-Datei. Sie stellt keine HTTP-Verbindung her und überträgt keine
> Daten an diese Adresse. Ein Wechsel zu https würde einen anderen Namespace
> erzeugen und die GPX-Kompatibilität beeinträchtigen. Daher besteht an dieser
> Stelle kein unverschlüsselter Datentransport.
Offizielle Referenz: https://www.topografix.com/GPX/1/1/
Der gleiche Namespace in `public/js/local-routes.js` wurde laut Export bereits
als **Safe** bewertet. Der neue Hotspot ist weiterhin **TO_REVIEW**; ein
Code-Kommentar oder dieses Dokument ändert seinen Status in SonarQube nicht.
Es wurden keine Regeln deaktiviert und keine Findings per Suppression verborgen.
## Quality Gate laut Export
- Neue Coverage: 87,8 %, bestanden (mindestens 80 %).
- Neue Duplikate: rund 0,35 %, bestanden (höchstens 3 %).
- Neue offene Findings: fünf, durch die Code-Korrekturen adressiert.
- Geprüfte Security-Hotspots: 50 %, noch nicht bestanden (erforderlich 100 %).
Die abschließende Bewertung des Quality Gates benötigt einen neuen Scan und
die Bewertung des genannten Hotspots in SonarQube.
+20
View File
@@ -0,0 +1,20 @@
# Moderation: Ersteller und Gerätekennung
Umgesetzt: dauerhafte, zufällige 256-Bit-Gerätekennung im getrennten Local Storage,
`creator_id` in lokalen Entwürfen und Server-Strecken, Anzeige im Moderationsskript,
gezieltes Löschen nur nach ausdrücklicher Bestätigung und erneutes Einsenden noch
nicht freigegebener Strecken. Beschreibung: [CREATOR-ID.md](../CREATOR-ID.md).
Das GPX-Attribut `creator="Wegwichtel"` bezeichnet weiterhin nur das Programm.
Noch offen für gemeinsame Bearbeitung:
- Authentifizierte Eigentumszuordnung und Einladungen für Mitbearbeiter entwickeln.
Eine frei übermittelte Gerätekennung allein beweist kein Eigentum.
- Wiederherstellung nach verlorenen Browserdaten und bewussten Gerätewechsel planen.
- Gleichzeitige Änderungen und Versionskonflikte erkennen; der derzeitige lokale
Entwurf wird beim Einsenden als vollständiger Stand behandelt.
- Idempotente POSTs auch bei verlorenem HTTP-Erfolg und Gesamtübertragungen mit
mehreren Dateien absichern.
Die Ersteller-ID ersetzt keine Anmeldung. Der Moderationszugang ist separat
über Nginx und eine Passwortdatei geschützt (siehe [MODERATION-MEDIEN.md](../MODERATION-MEDIEN.md)).
+47
View File
@@ -0,0 +1,47 @@
# Wegwichtel Editor v5
Dieses Paket bereinigt den einfachen Streckeneditor nach dem grünen SonarQube-Lauf weiter.
## Status
Der zuletzt geprüfte SonarQube-Export meldet ein bestandenes Quality Gate, keine Bugs, keine Vulnerabilities, keine Code Smells und keine Security Hotspots. Die New-Coverage lag bei 85,1 %.
## Fachliche Optimierungen gegenüber v4
- Der Editor sendet `activated_at` nicht mehr beim Speichern von Strecken.
- Neue Strecken bleiben durch den DB-Default unveröffentlicht.
- Bereits manuell aktivierte Strecken werden durch spätere Editor-Änderungen nicht versehentlich deaktiviert.
- Der Plus-Button besitzt `aria-haspopup="dialog"`, `aria-expanded` und `aria-controls`; beim Öffnen und Schließen wird `aria-expanded` synchronisiert.
- POI-Sortierpfeile sind am Listenanfang beziehungsweise Listenende deaktiviert.
- Das Initialschema enthält zusätzlich `idx_routes_activation` für spätere veröffentlichte Listenabfragen nach `status` und `activated_at`.
- POIs erhalten analog zu Strecken einen `pois_updated_at`-Trigger, damit `updated_at` bei Bearbeitungen automatisch aktualisiert wird.
- Die Dokumentation verwendet durchgehend `TEXT DEFAULT NULL` statt des für SQLite-STRICT falschen `DATETIME`.
## Datenbankschema
Für neu erzeugte Datenbanken steht die Spalte direkt in `database/schema.sql`:
```sql
activated_at TEXT DEFAULT NULL
```
Für bestehende SQLite-Datenbanken liegt weiterhin eine Migration vor:
```bash
sqlite3 <pfad-zur-wegwichtel-db> < database/migrations/20260901_add_route_activated_at.sql
```
Die Migration darf nur auf Bestandsdatenbanken ohne `activated_at` ausgeführt werden. Auf einer frischen Datenbank, die schon mit dem aktuellen `database/schema.sql` erstellt wurde, ist sie nicht nötig.
## Tests
```bash
node --check public/js/editor-ui.js
npm test -- test/editor-ui.test.js
npm test -- test/editor-database-schema.test.js
npm run test:coverage
```
## Optionaler Cleanup
`scripts/apply-editor-schema.mjs` war nur als Übergangshilfe gedacht. Nach diesem Paket ist das Initialschema direkt enthalten. Die Datei wird nicht mehr benötigt und kann entfernt werden, falls sie aus v3/v4 noch im Repository vorhanden ist.