Shuffle/supabase
cschlaefke 154e5e4bb5 fix(db): Jahr-Grenzen in find_similar_catalog_games, Tests für Tagesgrenze und Trimmen (Refs #13)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-04 19:44:02 +01:00
..
catalog fix(db): single filter set, filter tests with query, perf guards, evidence docs (KAT-01, 3a review) 2026-11-04 10:39:02 +01:00
migrations fix(db): Jahr-Grenzen in find_similar_catalog_games, Tests für Tagesgrenze und Trimmen (Refs #13) 2026-11-04 19:44:02 +01:00
perf fix(db): single filter set, filter tests with query, perf guards, evidence docs (KAT-01, 3a review) 2026-11-04 10:39:02 +01:00
templates fix(db): trim all Unicode whitespace in display name, harden templates 2026-11-02 23:48:01 +01:00
tests fix(db): Jahr-Grenzen in find_similar_catalog_games, Tests für Tagesgrenze und Trimmen (Refs #13) 2026-11-04 19:44:02 +01:00
.gitignore chore(supabase): add config.toml and ignore app env files 2026-11-02 20:12:09 +01:00
config.toml feat(catalog): add starting-stock tool, vocabulary proposal and CI checks 2026-11-03 15:38:28 +01:00
README.md docs(db): Meldungen (KAT-04) in Datenmodell, Katalogpflege, README und Umsetzungs-Nachtrag 2026-11-04 19:16:31 +01:00
seed.sql feat(catalog): add starting-stock tool, vocabulary proposal and CI checks 2026-11-03 15:38:28 +01:00

Supabase – Datenbank für Shuffle

Inhalt

Pfad Zweck
migrations/ Schema, Trigger und RLS-Policies für R1 (22 Tabellen, 3 Views). Nur additiv ändern, nie bestehende Dateien editieren.
tests/database/ pgTAP-Tests: Struktur-Regeln und Zugriffsrechte je Bereich.
perf/ Messskript für die Katalogsuche (kein Test, läuft nicht in supabase test db).
templates/ Auth-Mailvorlagen (HTML, Go-Template) für Bestätigung und Passwort-Reset.
seed.sql Beispieldaten nur für die lokale Entwicklung.
catalog/ Katalog-Vokabular und Startbestand (CSV, Werkzeug build_startbestand.ts, erzeugte SQL-Dateien), siehe unten.

Lokal starten und testen

supabase start          # lokales Backend
supabase db reset       # Migrationen + Seed einspielen
supabase test db        # alle pgTAP-Tests ausführen

Registrierung (KTO-01)

  • Der Trigger handle_new_user erzwingt Altersbestätigung, Zustimmung, terms_version und Anzeigename (1–30 Zeichen). Fehlertexte: siehe docs/datenmodell-r1.md. Clients senden diese Werte als user_metadata bei signUp.
  • pgTAP-Fixtures, die auth.users direkt füllen, brauchen daher age_confirmed, terms_accepted, terms_version und display_name in raw_user_meta_data.
  • Ergebnisse der GoTrue-Prüfung: docs/specs/1-auth-spike-ergebnisse.md.
  • Auth-Einstellungen (AUTH-CFG-nn in config.toml), Env-Block für Staging/Produktion, Auth-Checkliste und bekannte Grenzen: docs/auth-konfiguration.md. Zentrale Release-Checkliste (Katalog, checks.sql, Zugang, Auth/SMTP, Runner): docs/release-checkliste.md.
  • Mailvorlagen (Bestätigung, Passwort-Reset; de/en nach user_metadata.locale): templates/. Lokal landen Mails in Mailpit (http://127.0.0.1:54324).

E2E-Tests (Playwright)

  • e2e/ testet GoTrue über Kong (api), die gebaute Web-App (web), die IP-Drosselung (throttle) und den SMTP-Ausfall (spike). Voraussetzung: supabase start mit Mailpit und Postgres (Ports 54321, 54322, 54324).
  • e2e/support/db.ts verbindet sich direkt mit dem lokalen Postgres (Rolle postgres) und setzt recovery_sent_at/confirmation_sent_at für die Ablauftests; es bricht bei nicht-lokalem Host ab.
  • Der Extra-Container für throttle/spike startet mit e2e/support/start-throttle-gotrue.sh. Details: e2e/README.md.
  • CI: Job e2e in .forgejo/workflows/ci.yml (Runner docker-host, dind); Ablauf in docs/auth-konfiguration.md Abschnitt 7.

Katalog (KAT-05)

  • Pflege in R1 nur über Studio bzw. psql (Rolle postgres), Ablauf und Regeln: docs/katalog-pflege.md. Spec: docs/specs/2-katalog-daten.md.
  • Suche und Entdecken lesen nur die View catalog_games (ohne ausgeblendete und zusammengeführte Spiele). Geänderte Fakten trägt ein Trigger in games.manual_fields ein.
  • Zusammenführen von Duplikaten nur über die Funktion public.admin_merge_games(quelle, ziel) (nur Datenbankrolle postgres/supabase_admin, nicht über die API aufrufbar); Ablauf in docs/katalog-pflege.md, Abschnitt 5. Jede neue Tabelle mit Verweis auf games muss dort behandelt werden (Wächter in tests/database/07_catalog_merge.test.sql und 08_game_reports.test.sql).
  • Meldungen fehlender Spiele (game_reports) bearbeitet der Admin nur über public.admin_resolve_report(meldung, status, ziel) (nur Datenbankrolle postgres/supabase_admin); Ablauf in docs/katalog-pflege.md, Abschnitt 6. visibility und owner_id eines Spiels sind unveränderlich (Trigger games_visibility_immutable).
  • db reset spielt seed.sql, catalog/vocabulary.sql und catalog/startbestand.sql ein ([db.seed] sql_paths in config.toml). Die SQL-Dateien in catalog/ sind erzeugt; Quellen sind die CSV-Dateien. Neu erzeugen und testen (Deno, brew install deno):
    deno run --allow-read=supabase --allow-write=supabase supabase/catalog/build_startbestand.ts
    deno test --allow-read=supabase supabase/catalog/
    
  • Ein Pfad in sql_paths, der nicht existiert, wird von der CLI nur mit Warnung übersprungen (kein Fehler). Genauere CLI-Ergebnisse: docs/katalog-pflege.md, Abschnitt 2.7.
  • pgTAP-Tests, die Include-Dateien brauchen, nutzen \ir ../support/…; die Dateien in tests/support/ sind erzeugt (gleiches Werkzeug) und keine Tests.

Katalogsuche (KAT-01)

  • public.search_normalize(text) (Normalisierung für Suche und Titelvergleich) und die RPC public.search_catalog_games(…) sind für API-Rollen ausführbar (search_normalize: anon, authenticated, service_role, weil generierte Spalten mit den Rechten des Schreibenden rechnen; search_catalog_games: anon, authenticated). Beides ist die Ausnahme von der Regel „Funktionen sind für niemanden aufrufbar“; die Rechte prüft tests/database/09_catalog_search.test.sql.
  • Fehlendes Spiel melden (KAT-04, tests/database/10_game_reports_user.test.sql): public.find_similar_catalog_games(titel, jahr), public.report_missing_game(...) und public.adopt_report_target(meldung) sind nur für authenticated ausführbar (anon und service_role nicht); ebenso die Hilfsfunktionen strip_leading_article, normalize_game_title und report_day. adopt_report_target ist die einzige security definer-Funktion dieser Gruppe (Eigentümer postgres, search_path leer, Aufrufer nur über auth.uid(), ruft keine admin_*-Funktion auf). authenticated darf in game_reports nur owner_id, title, publisher_name, year, link, provisional_game_id einfügen und nur result_seen_at ändern. Das Tageslimit (10 Nutzer-Meldungen je Berliner Tag) setzt ein Trigger durch, der unter READ COMMITTED (Standard bei PostgREST) wirkt; er gilt für jede Rolle, auch postgres. Vertrag und Fehlercodes: docs/datenmodell-r1.md, Abschnitt „Meldungen (KAT-04)“.
  • Alternative Titel (game_alt_titles) sind für API-Rollen nur lesbar; Pflege über Studio (docs/katalog-pflege.md, Abschnitt 3.1) und die CSV-Spalte alt_titles (de:Titel;en:Title, ; im Titel nicht erlaubt).
  • Nach einem Image-Upgrade der Datenbank die Normalisierung prüfen (docs/katalog-pflege.md, Abschnitt 8).
  • Messskript für das Zeitbudget der Suche (nur lokal, nie gegen Staging/Produktion, bewusst nicht unter tests/): perf/catalog_search_perf.sql, Aufruf im Kopfkommentar.

Regeln

  • Jede Tabelle hat id (uuid, PK), created_at, updated_at und Row Level Security.
  • updated_at setzt ein Trigger; id und created_at sind nach dem Anlegen unveränderlich.
  • Fremdschlüssel nur dort, wo Tabellen in Beziehung stehen, benannt <Zieltabelle>_id.
  • Rechte werden explizit vergeben (erst alles entziehen, dann gezielt gewähren).
  • Admin-Rolle kommt aus app_metadata.role = 'admin' im JWT, nie aus user_metadata; in R1 niemandem vergeben, Pflege über Studio (KAT-05 E10).

Noch nicht enthalten

  • Storage-Buckets und -Policies für Avatare und Spielbilder.
  • Edge Functions (BGG-Import, Konto löschen).
  • Selbst-Hosting-Setup auf Hetzner (ADR-0002, Aufgabe für devops).