Commit graph

19 commits

Author SHA1 Message Date
Daniel Michelberger
247ac8ec6b feat: Stores für Trails und GPX-Versionen
TrailStore verwaltet Trail-Datensätze mit Team-Filterung und Edit-Berechtigungen
für Trail-Paten, Team-Owner und Admins. TrailVersionStore verwaltet GPX-Versionen
mit Upload und Aktivierung (mit Prüfung auf Trail-Zugehörigkeit).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 17:37:50 +02:00
Daniel Michelberger
efadbab48a docs: fehlerhaften Höhenmeter-Test im Plan korrigieren
Der Test "ignoriert Höhenschwankungen unter 3 m" nutzte 300->301->302->303
und erwartete 0 Höhenmeter. Das ist aber ein echter Anstieg von 3 m, nur fein
aufgezeichnet — bei einem langen gleichmäßigen Berganstieg hätte der Parser
die Höhenmeter systematisch verschluckt.

Jetzt zwei Tests, die die Fälle trennen: gleichmäßiger Anstieg in 1-m-Schritten
ergibt 3 hm, Schwanken um denselben Wert ergibt 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 17:35:54 +02:00
Daniel Michelberger
1eb25cd7e4 fix: Rausch-Schwelle auf >= und <=, Tests korrigiert, Fehlertext angepasst
- Operator auf >= und <= geändert (kumulativ zählen)
- Test "ignoriert Höhenschwankungen" ersetzt durch zwei separate Tests:
  * "erfasst einen gleichmäßigen Anstieg auch in feinen Schritten" (300→303 in 1m Schritten = 3m)
  * "ignoriert Rauschen, das um denselben Wert schwankt" (auf/ab ohne Gewinn = 0m)
- Fehlertext auf Brief-Fassung: "Die Datei ist kein gültiges XML."
- Test-Regex angepasst zum neuen Fehlertext

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 17:34:16 +02:00
Daniel Michelberger
f89f163e22 fix: Punkte ohne Koordinaten, Fehlertext, neuer Test für Null-Island
- Prüfe lat/lon auf null vor Number-Konvertierung (Number(null) ist 0, nicht NaN)
- Ergänze Test für übersprungene Punkte ohne Koordinaten
- Bessere Fehlermeldung für ungültiges XML

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 17:30:20 +02:00
Daniel Michelberger
ef8c05bd7c style: TeamSwitcher und Design-Umschalter nach links vor die Navigation 2026-08-06 17:21:03 +02:00
Daniel Michelberger
64c5139d71 feat: GPX-Parser mit Länge, Höhenmetern und Streckenvereinfachung
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 17:19:02 +02:00
Daniel Michelberger
f576550429 fix: Präzedenzfehler in trail_flags.deleteRule beheben
&& bindet stärker als || — ohne Klammern galt die
Marker-Referenzprüfung nur für den admins-Zweig. Ein Team-Owner konnte
dadurch einen noch von Markern referenzierten Flag-Typ löschen und
verwaiste Marker hinterlassen.

Klammerung in 1754500000_created_trails.js korrigiert, damit ein
Neuaufbau der Datenbank die richtige Regel von Anfang an bekommt.
1754500200_trail_flags_delete_rule.js (bereits mit der fehlerhaften
Regel angewendet) inhaltlich ebenfalls korrigiert, und eine neue
Migration 1754500300_trail_flags_delete_rule_precedence.js trägt die
Korrektur für bestehende Instanzen nach. Snapshot aktualisiert.
2026-08-06 17:13:35 +02:00
Daniel Michelberger
55f25fae0c fix: verwaiste trail_markers beim Löschen von trail_flags verhindern
trail_markers.flag ist required, hatte aber cascadeDelete: false — beim
Löschen eines Flag-Typs blieben Marker mit toter Referenz zurück. Die
deleteRule von trail_flags verbietet das Löschen jetzt, solange noch
Marker den Typ referenzieren.

1754500000_created_trails.js wurde direkt angepasst, damit ein Neuaufbau
der DB die Regel von Anfang an enthält. Da die Migration lokal bereits
angewendet war, trägt 1754500200_trail_flags_delete_rule.js dieselbe
Änderung für bestehende Instanzen nach. Snapshot in
1754400000_init_schema.js entsprechend aktualisiert.
2026-08-06 17:08:40 +02:00
Daniel Michelberger
9948073b25 fix: Avatar-Upload auf 5 MB begrenzen
users.avatar.maxSize stand auf 0 (unbegrenzt) — Ressourcenrisiko durch
beliebig große Uploads. Migration setzt das ursprüngliche Limit zurück.
2026-08-06 17:08:21 +02:00
Daniel Michelberger
c41a6cb056 feat: Collections für Trails, Versionen, Flags, Marker und Kommentare 2026-08-06 16:57:23 +02:00
Daniel Michelberger
ced89ed9d2 style: Titel "Zeitnahme" aus dem App-Header entfernen 2026-08-06 16:53:52 +02:00
Daniel Michelberger
2e8f92b6f6 docs: Umsetzungsplan für Trails 2026-08-06 16:42:18 +02:00
Daniel Michelberger
564632522e docs: Begründung für trails.current statt active-Flag ergänzen
Die Alternative (bool active auf trail_versions) käme ohne Zirkelbezug aus,
verlagert die Wahrheit aber in N Datensätze: zwei Schreibvorgänge beim
Umschalten, ohne Transaktion kurzzeitig zwei aktive Versionen möglich.
trails.current ändert genau ein Feld und kennt keinen ungültigen Zustand.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 16:33:58 +02:00
Daniel Michelberger
f11f7b4dff docs: Spec für Trails mit GPX, Markern und Kommentaren
Trail-Katalog pro Team: GPX hochladen, auf Karte anzeigen, verortete
Meldungen setzen, kommentieren. Neue Uploads legen Versionen an statt zu
überschreiben; Marker und Kommentare hängen am Trail und überleben damit
einen Track-Austausch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 16:31:08 +02:00
Daniel Michelberger
f316058367 fix: Deployment reparieren — adapter-node und Node-Anforderung festschreiben
Das Coolify-Deployment scheiterte an zwei Stellen:

1. npm ci brach mit EBADENGINE ab. Coolify baute mit Node 22.11.0, vite und
   @sveltejs/vite-plugin-svelte verlangen aber >=22.12; engine-strict=true
   aus der .npmrc macht daraus einen Abbruch statt einer Warnung. Das
   engines-Feld schreibt die Anforderung jetzt im Repo fest, statt sie einer
   Einstellung in der Coolify-UI zu überlassen.

2. Selbst nach erfolgreichem npm ci wäre der Start gescheitert: adapter-auto
   erkennt Coolify nicht ("Could not detect a supported production
   environment") und erzeugt gar kein build/ — der Startbefehl "node build"
   findet dann nichts. Jetzt adapter-node, adapter-auto entfällt.

Verifiziert in einer frischen Kopie ohne node_modules, mit derselben Kette
wie im Deployment: npm ci läuft durch, npm run build erzeugt build/index.js,
node build antwortet auf / und /login mit HTTP 200.

Dabei fiel ein dritter Punkt auf, der keine Code-Änderung braucht, aber im
Deployment gesetzt sein muss: PUBLIC_PB_URL wird zur Buildzeit eingesetzt.
Fehlt sie, bricht der Build mit "PUBLIC_PB_URL is not exported by
virtual:env/static/public" ab. Steht jetzt in frontend/README.md und CLAUDE.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 14:52:00 +02:00
Daniel Michelberger
2540666e1a feat: Typen aus der Schema-Migration erzeugen statt aus einer Instanz
npm run generate-pocketbase-types liest das Collections-Array jetzt direkt
aus backend/pb_migrations/ (scripts/schema-to-json.mjs) und speist es über
pocketbase-typegen --json ein. Keine laufende Instanz, kein Token, kein
Netzwerkzugriff mehr nötig.

Damit stammen Schema und Typen aus derselben versionierten Quelle und können
nicht auseinanderlaufen. Vorher zeigten sie auf eine Remote-Instanz, deren
Stand niemand garantieren konnte — nach dem Neu-Deployment lieferte sie
prompt Typen ohne die fachlichen Collections.

frontend/.env enthält dadurch nur noch PUBLIC_PB_URL. PB_TYPEGEN_URL und
PB_TYPEGEN_TOKEN entfallen (letztere wurde ohnehin nirgends gelesen),
PB_SUPERUSER_TOKEN wird nicht mehr gebraucht. Die Datei enthält damit kein
Geheimnis mehr.

Verifiziert: ohne .env, ohne Token und ohne laufende Instanz entstehen alle
sechs Collections, svelte-check meldet 0 Fehler und 0 Warnungen.

Die System-Collections (_superusers, _mfas, ...) fehlen in den Typen, weil
sie bewusst nicht in der Migration stehen. Die Anwendung verwendet sie nicht.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 14:20:15 +02:00
Daniel Michelberger
132ce04e0c fix: pb_migrations nicht mounten — Deployment startete ohne Collections
Der in 22cd427 ergänzte Bind-Mount ./pb_migrations:/pb/pb_migrations
überdeckt das Verzeichnis aus dem Image. Auf einem Deployment-Host, neben
dessen compose-Datei kein ausgechecktes Repo liegt, legt Docker dort ein
leeres Verzeichnis an: PocketBase findet keine Migration und startet mit
einer Datenbank ohne Collections. Genau das ist auf der neu deployten
Instanz passiert — users war da (legt PocketBase selbst an), events, teams,
riders, runs und times fehlten.

Reproduziert und beide Richtungen verifiziert: mit leerem Mount 404 auf
allen fünf Collections, ohne Mount kommen alle sechs aus dem Image.

Die Migrationen kommen damit wieder ausschließlich über COPY ins Image. Der
Preis ist der Weg zurück: Im Admin-UI erzeugte Migrationen liegen nur im
Container und müssen mit "docker compose cp" ins Repo geholt werden. Das
steht jetzt in backend/README.md und CLAUDE.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 14:06:30 +02:00
Daniel Michelberger
5658ef7bcc chore: veraltete Scripts unter frontend/scripts entfernen
Alle vier Scripts setzten auf einem Schema auf, das es nicht mehr gibt:

- seed-test-data.ts schrieb in stages und results (heute: runs und times)
  und kannte users.role, riders.email/birthday sowie events.created_by/
  timekeepers -- alles nicht mehr vorhanden. Teams kannte es gar nicht,
  ohne Team-Zuordnung greifen sämtliche API-Rules und die Daten wären
  unsichtbar geblieben.
- migrate-schema.ts und migrate-teams.ts waren Einmal-Migrationen. Ihr
  Ergebnis steckt längst im Schema (events.status, riders.number, times.
  correction, die teams-Collection, die team-Felder). Ein erneuter Lauf
  gegen die produktive Instanz wäre bestenfalls wirkungslos.
- test-token.ts war ein Wegwerf-Prüfscript für den Superuser-Token.

Das Schema ist jetzt in backend/pb_migrations/ versioniert; das ist der
Weg für Änderungen. tsx entfällt als Abhängigkeit, es wurde nur von
diesen Scripts benutzt.

PB_SUPERUSER_TOKEN bleibt in .env -- generate-pocketbase-types braucht ihn.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 13:42:24 +02:00
Daniel Michelberger
1061a8b9ad chore: Repo-Struktur mit frontend/ und backend/ aufsetzen
Die SvelteKit-App liegt unter frontend/, das Backend unter backend/ als
eigenständige PocketBase-Instanz mit Dockerfile, docker-compose und
versioniertem Schema.

- PocketBase-URL über PUBLIC_PB_URL konfigurierbar, Default bleibt die
  produktive Instanz https://api.stammtisch-hersbruck.de
- Schema als Snapshot-Migration der sechs fachlichen Collections
  (users, teams, events, runs, riders, times), abgezogen von der
  produktiven Instanz. Verifiziert: ein Erststart gegen leere pb_data
  legt alle sechs an, Felder und API-Rules stimmen überein.
- pb_data und pb_migrations als Bind-Mounts, damit Daten persistieren und
  im Admin-UI erzeugte Migrationen im Repo landen
- Veraltete Dokumentation entfernt: pocketbase_schema.json nannte
  Collections (stages, results, organizers), die es nicht gibt

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 13:16:43 +02:00