stammtisch-hersbruck/TODO.md
Daniel Michelberger fae50d3209 feat: Fahrer werden zum Kader, Events bekommen Teilnehmer und Serien
Damit sind alle offenen Punkte aus TODO.md gebaut.

Fahrer gehoeren ab jetzt dem Team, nicht mehr einem Event. Wer bei einem
Termin dabei ist, steht in event_participants - dort haengt auch die
Startnummer, denn die gilt je Event: Derselbe Fahrer kann in zwei Rennen
zwei Nummern haben und beim Stammtisch gar keine. Die vorhandenen Daten
wandern in der Migration mit.

Events tragen zwei Schalter. timing blendet Runs und Zeitnahme ein - der
woechentliche Stammtisch braucht sie nicht. participation regelt, wie man
dazukommt: offen (jeder traegt sich selbst ein), bestaetigung (Anmeldung,
Ersteller oder Team-Admin bestaetigt) oder geschlossen. Durchgesetzt wird
das serverseitig, nicht nur im Formular.

Serien erzeugen echte Einzeltermine statt einer Wiederholungsregel, aus der
Termine nur gerechnet werden. Nur so laesst sich beantworten, wer am 12.
kommt, und nur so faellt eine einzelne Woche aus. Gerechnet wird auf
Kalendertagen: ueber die Zeitumstellung hinweg kippte ein Termin sonst auf
den Vortag - dafuer gibt es einen Test.

Ausserdem: Teammitglieder duerfen den Zustand eines Trails melden. Die Regel
gibt genau die drei Statusfelder frei und schliesst jedes andere aus; ohne
das haette man Mitgliedern das ganze Objekt oeffnen muessen. Und bestehende
Konten lassen sich wieder per E-Mail ins Team holen, wofuer users.listRule
sich oeffnet.

Die neuen Regeln sind ungetestet - weder Docker noch eine lokale
PocketBase-Instanz standen zur Verfuegung. TODO.md sagt, was nach dem Deploy
durchzuspielen ist.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014dh9W1i7aLSdPYJzQPid5o
2026-09-02 16:03:17 +02:00

106 lines
5.2 KiB
Markdown

# Offene Punkte
Stand: 2026-09-02. Die fachlichen Entscheidungen sind gefallen und gebaut; was
hier steht, passiert außerhalb des Repos oder wartet auf den nächsten Deploy.
## Vor dem nächsten Deploy
### `PUBLIC_CARTO_API_KEY` in Coolify setzen
Die Kartenkacheln kommen von CARTO. Der Schlüssel muss den Browser erreichen,
deshalb das `PUBLIC_`-Präfix — ohne das reicht SvelteKit ihn nicht weiter.
Gelesen wird er über `$env/dynamic/public`, das heißt: Die Variable muss in der
**Laufzeitumgebung** des `node build`-Prozesses stehen, nicht nur zur Buildzeit.
In Coolify als normale Umgebungsvariable eintragen genügt. Fehlt sie, laufen die
Kacheln ohne Schlüssel weiter — die Karte bleibt also sichtbar.
### Migrationen greifen beim nächsten Start
Elf neue Migrationen liegen in `backend/pb_migrations/`:
| Datei | Was sie tut |
|---|---|
| `1754500500_riders_user_and_admin_rules` | `riders.user`, Fahrerpflege nur noch Teamleitung, `users.viewRule`/`createRule` gelockert |
| `1754500600_events_dates_instead_of_status` | `events.status` **raus**, `starts`/`ends` rein |
| `1754500700_trail_status_meta` | `trails.status_changed`, `trails.status_by` |
| `1754500800_trail_markers_custom` | `trail_markers.label`/`icon`, `flag` nicht mehr Pflicht |
| `1754500900_users_superadmin` | `users.superadmin`, gesetzt für stammtisch@dne.name |
| `1754501000_teams_logo` | `teams.logo` |
| `1754501100_trails_status_report` | Mitglieder dürfen den Trail-Zustand melden |
| `1754501200_users_list_for_invites` | `users.listRule` gelockert (Kontosuche) |
| `1754501300_event_participants` | neue Collection, **verschiebt Daten**, entfernt `riders.event`/`riders.number` |
| `1754501400_events_timing_participation` | `events.timing`/`participation`, Regeln für Selbsteintrag |
| `1754501500_event_series` | neue Collection `event_series`, `events.series` |
Solange sie nicht gelaufen sind, scheitert alles, was auf den neuen Regeln
aufbaut. Am deutlichsten beim Anlegen eines Mitglieds oder eines Fahrer-Logins:
**„Only superusers can perform this action"** — genau das sagt die noch
unveränderte `users.createRule` (null = nur Superuser).
**Drei Dinge sind nicht zurückzunehmen:**
1. `events.status` verschwindet samt seiner Werte.
2. `1754501300` legt für jeden Fahrer mit Event einen Teilnehmer an und
entfernt danach `riders.event` und `riders.number`. Eine Startnummer an
einem Fahrer **ohne** Event hat danach keinen Platz mehr und geht verloren —
sie war ohnehin nirgends sichtbar, weil alle Listen nach Event filterten.
3. Bestehende Events werden auf `timing = true` und `participation =
geschlossen` gesetzt. Genau so wurden sie bisher benutzt; wer einen
Stammtisch daraus machen will, schaltet die Zeitnahme im Dialog ab.
Ebenfalls neu und bewusst so: Jeder Eingeloggte kann Konten auflisten
(`users.listRule`), damit sich bestehende Konten wieder per E-Mail ins Team
holen lassen. E-Mail-Adressen bleiben über `emailVisibility` verborgen.
### Typen einmal neu erzeugen
`frontend/src/lib/types.d.ts` wurde bei allen Schema-Änderungen von Hand
gepflegt. Grund: `pocketbase-typegen` braucht native sqlite3-Bindings, die in
der Arbeitsumgebung nicht gebaut werden durften.
```bash
cd frontend && npm run generate-pocketbase-types
```
Die Datei sollte danach unverändert bleiben. Tut sie es nicht, gilt das Ergebnis
des Generators.
### Regeln einmal durchspielen
Die Zugriffsregeln der neuen Collections konnten nirgends laufen — weder Docker
noch eine lokale PocketBase-Instanz standen zur Verfügung. Sie sind nach dem
Muster der vorhandenen Collections geschrieben, aber ungetestet. Nach dem Deploy
einmal ausprobieren:
- Ein einfaches Teammitglied trägt sich bei einem **offenen** Event selbst ein.
- Dasselbe bei einem Event **mit Bestätigung** — es muss als „Angefragt"
landen, nicht als „Dabei".
- Bei einem **geschlossenen** Event darf es gar nicht gehen.
- Ein Mitglied meldet einen Trail-Zustand (muss gehen) und versucht, den Namen
des Trails zu ändern (darf nicht gehen).
Der Selbsteintrag setzt außerdem voraus, dass das Konto der Person mit einem
Fahrer verknüpft ist (Einstellungen → Fahrer → Konto). Ohne Verknüpfung
erscheint der Knopf gar nicht erst.
### Logo des Stammtischs zuordnen
`teams.logo` gibt es ab `1754501000`. Solange nichts hinterlegt ist, zeigt die
App weiterhin das Wappen aus `static/` — für den Stammtisch Hersbruck sieht es
also unverändert aus. Wer es als Datei am Team haben will, lädt es nach dem
Deploy unter Einstellungen → Team → Logo hoch.
## Kleinigkeiten
- Die Rolle **Superadmin** ist gesetzt, gibt in der App aber noch keine
besonderen Rechte. Sie ist bewusst nur in PocketBase vergebbar: Die
`updateRule` der users-Collection schließt `superadmin` vom Selbstsetzen aus.
Sobald klar ist, was sie dürfen soll, kommen die Regeln dazu.
- Flag-Typen sind **teamspezifisch**. Ein neues Team bekommt beim Anlegen den
hartkodierten Standardsatz aus `trailFlags.svelte.ts` und kann ihn frei
ändern.
- Serien erzeugen bis zu zwölf Termine je Klick und überspringen, was schon
angelegt ist. Ein Termin, der ausfällt, wird als Event gelöscht oder
verschoben — die Serie bleibt davon unberührt.
- `NAMING.md` und `frontend/static/pedaler.svg` liegen bewusst nur lokal.