diff --git a/.claude/commands/release.md b/.claude/commands/release.md index b30cd15..91dbd29 100644 --- a/.claude/commands/release.md +++ b/.claude/commands/release.md @@ -4,6 +4,7 @@ argument-hint: --- Bereite Release $ARGUMENTS vor: +0. `docs/release-checkliste.md` nur lesen und den Status erheben (was ist erledigt, was offen). Keine Prüfbefehle gegen Staging/Prod ohne Freigabe von Chris. Offene Release-Blocker (Abschnitte 2 bis 5) halten Schritt 1 nicht auf (Version und Changelog dürfen vorbereitet werden), verhindern aber den Tag-Vorschlag in Schritt 4; Chris entscheidet. 1. `devops`: prüft, dass `main` grün ist, setzt `version:` in `app/pubspec.yaml` (Build-Nummer +1) auf einem Branch `release/$ARGUMENTS` und erstellt einen PR. 2. `docs-writer`: ergänzt `CHANGELOG.md` aus den gemergten PRs seit dem letzten Tag und diff --git a/README.md b/README.md index c366734..b0c6121 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Die vollständige Schritt-für-Schritt-Anleitung liegt als separates Dokument be | `.claude/hooks/` | Auto-Format für Dart, Schutz bestehender Migrationen | | `.mcp.json` | MCP-Server: Forgejo, Outline, Dart, Playwright | | `.forgejo/` | CI-Pipeline, Issue- und PR-Vorlagen | -| `docs/` | ADR-0001 (Tech-Stack-Vorschlag), Vorlagen für Specs und ADRs | +| `docs/` | ADR-0001 (Tech-Stack-Vorschlag), Vorlagen für Specs und ADRs, [Release-Checkliste](docs/release-checkliste.md) | | `requirements/` | Ablage für deine fachlichen Anforderungen | | `supabase/` | R1-Datenbank: Migrationen, RLS-Policies, pgTAP-Tests, Seed | | `scripts/` | Setup-Check, Forgejo-Labels | diff --git a/docs/auth-konfiguration.md b/docs/auth-konfiguration.md index 5096816..ca96abb 100644 --- a/docs/auth-konfiguration.md +++ b/docs/auth-konfiguration.md @@ -148,7 +148,7 @@ Mit der committeten `config.toml` geprüft (Mailpit-API): Registrierung mit `loc ## 5. Release-Checkliste (vor jedem Release auf Staging/Produktion) -Automatisiert nicht abdeckbar (Spec § 7.1); vor dem Release abhaken: +Zentrale Liste über alle Bereiche (Katalog, Zugang, Runner): [`release-checkliste.md`](release-checkliste.md). Automatisiert nicht abdeckbar (Spec § 7.1); vor dem Release abhaken: - [ ] GoTrue-Image ist `supabase/gotrue:v2.197.0` (oder bewusst aktualisiert, dann Spike-Punkte (c), (d), (f) wiederholen). - [ ] Env-Block aus Abschnitt 2 ist vollständig gesetzt; `GOTRUE_PASSWORD_HIBP_ENABLED=false` (AUTH-CFG-21). @@ -160,6 +160,7 @@ Automatisiert nicht abdeckbar (Spec § 7.1); vor dem Release abhaken: - [ ] `GOTRUE_RATE_LIMIT_EMAIL_SENT=30` gesetzt und Monitoring auf 429 `over_email_send_rate_limit` aktiv (AUTH-CFG-09, R3). - [ ] Nach Passwortänderung kommt keine Benachrichtigungs-Mail (AUTH-CFG-19). - [ ] **Monitoring/Alarm auf SMTP-Fehler** (Release-Blocker, D1, Issue #37/F13): GoTrue-Logs mit `unexpected_failure`/HTTP 500 bei `/recover`, `/resend` und `/signup` alarmieren. Die App zeigt bei einem SMTP-Ausfall bewusst die neutrale „Prüfe dein Postfach“-Seite (Konten-Schutz); Nutzer bekommen keinen Hinweis und keine Mail, nur der Betrieb sieht den Ausfall. Die App loggt zusätzlich Operation, Fehlerart, Status und Code (ohne E-Mail). +- [ ] **#46:** Gateway-/Proxy- und GoTrue-SMTP-Timeouts festgelegt (bei hängendem SMTP kommt ein 504 mit Status vor dem Client-Timeout); Monitoring zusätzlich auf Gateway-5xx/504 für `/recover`, `/resend`, `/signup`. - [ ] SMTP-Anbieter mit AVV und Absender-Domain entschieden und eingerichtet (AUTH-CFG-22, F7). - [ ] SPA-Rewrite: `/auth/confirm` wird von der Web-App ausgeliefert. - [ ] Rechtstexte-URLs und `TERMS_VERSION` final (R11); Bundle-/Application-ID final (R15). diff --git a/docs/katalog-pflege.md b/docs/katalog-pflege.md index ea3d551..48046fe 100644 --- a/docs/katalog-pflege.md +++ b/docs/katalog-pflege.md @@ -9,7 +9,7 @@ Stand: PR 2a (Datenmodell, Startbestand, Ausblenden). Die Abschnitte **Zusammenf ## 1. Zugang - Studio läuft als Datenbankrolle `postgres` (bzw. `supabase_admin`) und **umgeht Row Level Security**. Wer Studio erreicht, kann alles lesen und ändern, auch private Nutzerdaten. Mit `select current_user;` im SQL-Editor prüfen, unter welcher Rolle man arbeitet. -- **Nicht öffentlich erreichbar** sein dürfen: Studio, der Postgres-Port 5432, der Pooler (Supavisor, Standard 6543) und die Kong-Route `/pg/` (pg-meta). Zugriff nur über SSH-Tunnel oder VPN; die Basic-Auth des Gateways (`DASHBOARD_USERNAME`/`DASHBOARD_PASSWORD`) bleibt mit starkem Passwort als zweite Schicht. Gilt ebenso für Staging. (Einrichtung und Bestätigung: Aufgabe D1, devops.) +- **Nicht öffentlich erreichbar** sein dürfen: Studio, der Postgres-Port 5432, der Pooler (Supavisor, Standard 6543) und die Kong-Route `/pg/` (pg-meta). Zugriff nur über SSH-Tunnel oder VPN; die Basic-Auth des Gateways (`DASHBOARD_USERNAME`/`DASHBOARD_PASSWORD`) bleibt mit starkem Passwort als zweite Schicht. Gilt ebenso für Staging. (Einrichtung und Bestätigung: Aufgabe D1, devops; Prüfschritte in [`release-checkliste.md`](release-checkliste.md) Abschnitt 4.) - **Immer in einer Transaktion arbeiten:** `begin; … commit;` (bei Fehler `rollback;`). Vor größeren Änderungen den Stand des Backups prüfen. - **Niemals `set …` ohne `local` verwenden** (zum Beispiel `set shuffle.catalog_import`): Ohne `local` gilt die Einstellung für die ganze Sitzung. Der Import-Schalter `shuffle.catalog_import` ist ohnehin nur für die Rolle `catalog_importer` wirksam und gehört nicht ins Studio. Hinweis: `set local` statt `set` ist eine Konvention des Imports; ein sitzungsweites `set` bleibt hinter einem Pooler bis zum Ende der Verbindung bestehen und kann auf die nächste Anfrage durchschlagen. - Die Rolle `app_metadata.role = 'admin'` (JWT) wird in R1 **niemandem vergeben** (siehe 7). @@ -100,7 +100,7 @@ git add supabase/catalog supabase/tests/support && git commit psql "$DB_URL" -f supabase/catalog/checks.sql # oder Inhalt im Studio-SQL-Editor ``` -Je Regel eine Zeile (Soll, Ist, Status `ok`/`Verstoß`/`Information`). **Abnahme (Krit. 7 und 10):** SB1 meldet mindestens 180 sichtbare Spiele, SB2, SB4 und SB6 melden 0. Die Abfrage betrachtet nur Spiele aus `startbestand-keys.csv`; im Studio angelegte Spiele und das Beispielspiel aus `seed.sql` (nur lokal) zählen nicht. Lokal und in CI ist SB1 nur eine Information, solange noch eingepflegt wird. Die Herkunft der Fakten (SB3) und der Kurztexte (SB4) bestätigt Chris selbst; die rechtliche Prüfung folgt vor dem Release. +Je Regel eine Zeile (Soll, Ist, Status `ok`/`Verstoß`/`Information`). **Abnahme (Krit. 7 und 10):** SB1 meldet mindestens 180 sichtbare Spiele, SB2, SB4 und SB6 melden 0. Die Abfrage betrachtet nur Spiele aus `startbestand-keys.csv`; im Studio angelegte Spiele und das Beispielspiel aus `seed.sql` (nur lokal) zählen nicht. Lokal und in CI ist SB1 nur eine Information, solange noch eingepflegt wird. Vor dem Go-live ist `checks.sql` Teil der [Release-Checkliste](release-checkliste.md) (Abschnitt 2). Die Herkunft der Fakten (SB3) und der Kurztexte (SB4) bestätigt Chris selbst; die rechtliche Prüfung folgt vor dem Release. ### 2.7 Ergebnis der Prüfung der CLI-Annahmen (Spec R11, Supabase CLI 3.0.0, geprüft am 2026-11-03) @@ -113,7 +113,7 @@ Je Regel eine Zeile (Soll, Ist, Status `ok`/`Verstoß`/`Information`). **Abnahme | Pfad ohne Treffer in `sql_paths` | Nur die Warnung `no files matched pattern: …`, **kein Fehler**, Exit-Code 0. Ein Tippfehler im Pfad überspringt die Datei also still; nach dem Reset `checks.sql` bzw. die Zeilenzahlen ansehen. | | Datei, die nur Kommentare enthält | läuft ohne Fehler | | psql-Metabefehle (`\i` …) in Seed-Dateien | nicht nutzbar (die Datei wird als SQL-Batch gesendet) | -| `supabase start` lädt Seeds nur beim ersten Start einer leeren Datenbank | **nicht geprüft** (hätte Chris' laufenden lokalen Stack stoppen müssen). Nicht darauf verlassen: nach Änderungen an Migrationen oder Seeds immer `supabase db reset`. | +| `supabase start` lädt Seeds nur beim ersten Start einer leeren Datenbank | **nicht geprüft** (hätte Chris' laufenden lokalen Stack stoppen müssen). Nicht darauf verlassen: nach Änderungen an Migrationen oder Seeds immer `supabase db reset`. Nur lokal relevant. `supabase db reset` niemals gegen Staging/Prod (löscht alle Daten); Seeds dort ausschließlich per `psql` (2.5, [Release-Checkliste](release-checkliste.md) Abschnitt 2). | ## 3. Spiel anlegen und bearbeiten diff --git a/docs/release-checkliste.md b/docs/release-checkliste.md new file mode 100644 index 0000000..f42f9bf --- /dev/null +++ b/docs/release-checkliste.md @@ -0,0 +1,122 @@ +# Release-Checkliste (Staging und Produktion) + +| | | +|---|---| +| Gilt für | jedes Release auf Staging/Produktion; **Go-live** (erster Release mit echten Nutzern) zusätzlich die Punkte mit „Go-live“ | +| Stand | 2026-11-03 | +| Quellen | `docs/specs/2-katalog-daten.md` (§ 4.2, § 8.1 Aufgabe D1), `docs/auth-konfiguration.md` (§ 3, § 5), `docs/katalog-pflege.md` (§ 1, § 2), ADR-0002, ADR-0003, Issue #46 | +| Bezug | Refs #2 (Katalog), Refs #1 (Auth), Refs #46 (SMTP-Timeouts), Refs #43 (CI-Runner) | + +Diese Datei ist die zentrale Stelle. Die ausführliche Auth-Liste bleibt in `docs/auth-konfiguration.md` § 5; die Release-Blocker daraus stehen hier, damit nichts übersehen wird. **Auth § 5 und Abschnitt 3 dieser Datei beide pflegen.** + +**Grundregeln (CLAUDE.md, Rolle devops):** Kein Tag, kein Deployment, kein Store-Upload ohne ausdrückliche Freigabe von Chris. Infrastruktur (Server, DNS, Reverse Proxy, Firewall) richtet Chris ein bzw. gibt sie frei; devops liefert Anleitung und Prüfschritte. Secrets nie in Logs, Tickets oder dieser Datei. In den Prüfbefehlen stehen Platzhalter in `<…>`; echte Werte stehen nicht im Repo. + +**Wer:** `Chris` = Entscheidung, Freigabe, Eingriff in die Infrastruktur; `devops` = Prüfung und Dokumentation. + +Ergebnis je Punkt mit Datum und Umgebung (Staging/Prod) im Release-PR oder als Kommentar zu #2 festhalten. + +## 1. Vor jedem Release + +| ☐ | Punkt | Wer | Prüfung | +|---|---|---|---| +| ☐ | `main` ist grün (Format, Analyse, Tests, Web-Build, pgTAP, `e2e`, Deno-Schritte) | devops | Forgejo Actions, letzter Lauf auf `main` | +| ☐ | Version in `app/pubspec.yaml` gesetzt (`x.y.z+build`), Changelog und Release Notes erstellt | devops, docs-writer | `.claude/commands/release.md` | +| ☐ | Migrationen auf Staging eingespielt und geprüft; Produktion erst nach Freigabe | Chris | Verfahren **offen**, siehe 8 | +| ☐ | **ADR-0002-Pflichtbausteine vor dem ersten echten Nutzer (Go-live):** automatisierte Backups (DB + Storage) an getrenntem Ort, **getesteter** Restore, TLS und Reverse Proxy, Firewall (nur nötige Ports), Update-Routine, Monitoring und Alarm, Secrets nicht im Repo | Chris | je Baustein Nachweis (z. B. Restore-Test mit Datum); Umsetzung und Verfahren **offen**, siehe 8 | + +## 2. Katalog und Startbestand (Spec #2, KAT-05) + +Reihenfolge: Migrationen, `vocabulary.sql`, `startbestand.sql` (Runbook `docs/katalog-pflege.md` § 2.5). **`startbestand.sql` wird nur bis einschließlich Go-live eingespielt**; danach ist es eingefroren, weil es Korrekturen aus dem Studio überschreiben würde (Spec § 4.3, Spec-F6). Danach bei Bedarf nur noch `vocabulary.sql` (idempotent). + +| ☐ | Punkt | Wer | Prüfung | +|---|---|---|---| +| ☐ | **C0:** Vokabular (`supabase/catalog/vocabulary.csv`, Genres und Mechaniken) von Chris freigegeben oder korrigiert; `vocabulary.sql` ist aus der freigegebenen CSV erzeugt | Chris | Freigabe als Kommentar in #2 oder im PR; CI-Schritt „Erzeugte Katalogdateien aktuell?“ grün | +| ☐ | Startbestand in `startbestand.csv` gepflegt (mindestens 180, Ziel ca. 200), `startbestand.sql` und `startbestand-keys.csv` erzeugt und committet (C1) | Chris | Ablauf Runbook § 2.4; CI grün | +| ☐ | Herkunft der Fakten (SB3) und der Kurztexte (SB4) bestätigt; **rechtliche Prüfung** vor dem Release | Chris | schriftliche Bestätigung in #2 | +| ☐ | Vokabular und Startbestand auf der Zielumgebung eingespielt (nur per Tunnel/VPN, siehe 4; `startbestand.sql` nur bis Go-live) | Chris | `psql "$DB_URL" -v ON_ERROR_STOP=1 --single-transaction -f supabase/catalog/vocabulary.sql -f supabase/catalog/startbestand.sql` | +| ☐ | **Seeds nur per `psql`:** `supabase db reset` niemals gegen Staging/Prod (löscht alle Daten); Seeds dort ausschließlich per `psql` (Runbook § 2.5). Das Verhalten von `supabase start` mit Seeds (nur beim ersten Start einer leeren DB) ist **nicht geprüft** (Runbook § 2.7) und nur lokal relevant | Chris, devops | Zeile oben plus nächster Punkt | +| ☐ | **`checks.sql` (SB1, Go-live-Kriterium):** mindestens 180 sichtbare Startbestandsspiele; SB2, SB4 und SB6 melden 0 Verstöße. `checks.sql` muss aus **demselben Commit** stammen wie das eingespielte `startbestand.sql` (die committete Fassung ohne Startbestand enthält eine leere ID-Liste `'[]'`, dann sind SB2/SB4/SB6 aussagelos). Zusätzlich SB0 (Istwert = Soll „alle N“) und die Informationszeile zu abweichenden Vokabular-IDs ansehen | Chris (Abnahme C1) | `psql "$DB_URL" -v ON_ERROR_STOP=1 -f supabase/catalog/checks.sql` oder Inhalt im Studio-SQL-Editor. Erwartung: Status `ok` bei SB0/SB1/SB2/SB4/SB6, SB1-Istwert >= 180. Bei < 180 zeigt `checks.sql` „Verstoß“; nur der CI-Schritt wertet SB1 lokal als Information | +| ☐ | Das lokale Beispielspiel aus `seed.sql` ist auf Produktion nicht vorhanden (reiner Sicherheitsnetz-Check; `checks.sql` zählt es nicht mit) | devops | `select count(*) from public.games where title = 'Beispielspiel';` erwartet 0 | +| ☐ | **Go-live:** `startbestand.sql` ist ab jetzt eingefroren und wird nicht mehr eingespielt (Korrekturen nur im Studio, Spec-F6); dieser Schritt kommt **nach** dem Einspielen und der `checks.sql`-Abnahme | Chris | Hinweis im Release-PR | + +Issue #2 wird erst nach der Abnahme von `checks.sql` auf Produktion (C1) und nach Fertigstellung von #4 (KAT-02) geschlossen, und nur von Chris. + +## 3. Auth, SMTP und Gateway (Spec #1, D1, Issue #46) + +Vollständige Liste mit AUTH-CFG-Verweisen: `docs/auth-konfiguration.md` § 5; Gateway-Vorgaben § 3. Release-Blocker: + +| ☐ | Punkt | Wer | Prüfung | +|---|---|---|---| +| ☐ | GoTrue-Image gepinnt auf `supabase/gotrue:v2.197.0` (oder bewusst aktualisiert, dann Spike-Punkte wiederholen); Env-Block aus Auth § 2 vollständig; `GOTRUE_PASSWORD_HIBP_ENABLED=false` | Chris, devops | Auth § 5, erste Punkte; Env-Werte prüfen, ohne Secrets zu posten | +| ☐ | `GOTRUE_SMS_AUTOCONFIRM=false` bzw. `ENABLE_PHONE_AUTOCONFIRM=false` (die Self-Hosting-Vorlage setzt `true`): Enumerationsschutz | devops | Signup mit bereits bestätigter Adresse liefert 200 mit leeren `identities`, nicht 422 `user_already_exists` (AUTH-CFG-24) | +| ☐ | **Proxy vor GoTrue mit `GOTRUE_RATE_LIMIT_HEADER=X-Forwarded-For`** (AUTH-CFG-13): Proxy **überschreibt** den Header, GoTrue ist von außen nicht direkt erreichbar | Chris (Einrichtung), devops (Test) | **Nur auf Staging testen** (der Test sperrt die eigene IP für ca. 5 Minuten). 31 Fehllogins derselben IP gegen `https:///auth/v1/token?grant_type=password` mit Header `-H "apikey: "` (Platzhalter; ohne Key antwortet das Gateway mit 401 und der Test sagt nichts) und einem Testkonto: Nr. 31 liefert 429 `over_request_rate_limit`. Zweiter Test mit gefälschtem Header `X-Forwarded-For: 203.0.113.7`: darf die Drosselung nicht umgehen. Direktzugriff auf den GoTrue-Port von außen muss scheitern | +| ☐ | **Gateway sperrt `POST /auth/v1/otp` und `POST /auth/v1/magiclink`** (AUTH-CFG-20; `/otp` legt sonst Konten an) | Chris (Einrichtung), devops (Test) | `curl -s -i -X POST https:///auth/v1/otp -H "apikey: " -H 'Content-Type: application/json' -d '{}'`, ebenso für `/auth/v1/magiclink` (der `apikey`-Header ist nötig, sonst kommt 401 und der Test ist wertlos). Erwartet: Ablehnung durch das Gateway (z. B. 403/404) **ohne** GoTrue-JSON (kein `code`/`error_code`/`msg` im Body); ein 400/422 mit GoTrue-Fehlerbody heißt: nicht gesperrt | +| ☐ | **SPA-Rewrite:** `/auth/confirm` wird von der Web-App ausgeliefert (alle Pfade auf `index.html`) | Chris (Einrichtung), devops (Test) | `curl -s -o /dev/null -w '%{http_code}\n' 'https:///auth/confirm?token_hash=x&type=email'` erwartet 200 und HTML der App | +| ☐ | **Mailvorlagen-URL** erreichbar (GoTrue lädt Vorlagen per URL und fällt bei Fehlern **still** auf Englisch zurück, Spec #1 Risiko R5); URL im Health-Check | Chris, devops | URL aus dem Env-Block per `curl -I` vom Server aus. **Testmail de und en** (Bestätigung und Reset) auf Staging: Betreff und Text in der richtigen Sprache, Link `/auth/confirm?token_hash=…` | +| ☐ | SMTP-Anbieter mit AVV und Absender-Domain entschieden und eingerichtet (AUTH-CFG-22, F7, bisher **vertagt**) | Chris | echter Versand auf Staging | +| ☐ | **Alarm auf SMTP-Fehler:** GoTrue-Logs mit `unexpected_failure`/HTTP 500 bei `/recover`, `/resend`, `/signup` lösen einen Alarm aus (die App zeigt bei SMTP-Ausfall bewusst die neutrale „Prüfe dein Postfach“-Seite, Nutzer merken nichts) | Chris (Einrichtung), devops (Test) | Alarm einmal auslösen (z. B. SMTP-Host auf Staging kurz falsch setzen) und Eingang bestätigen | +| ☐ | **#46 Timeouts und Monitoring:** Gateway-/Proxy-Timeout und GoTrue-SMTP-Timeout so gesetzt, dass bei hängendem SMTP ein 504 **mit Status** vor dem Client-Timeout kommt (Werte noch nicht festgelegt, Spike aus #46 offen); Monitoring umfasst zusätzlich **Gateway-5xx/504** für `/recover`, `/resend`, `/signup`, nicht nur `unexpected_failure`/500 | Chris, devops | Spike aus #46 nur auf Staging und **nur mit Freigabe von Chris** (`GOTRUE_SMTP_HOST=10.255.255.1`, nicht routbar): Status und Dauer für bekannte und unbekannte Adresse; Ergebnis in `docs/auth-konfiguration.md` eintragen. **Solange #46 offen ist, nicht abhakbar** | +| ☐ | `GOTRUE_RATE_LIMIT_EMAIL_SENT=30` und Monitoring auf 429 `over_email_send_rate_limit`; Mindestabstand 60 s (AUTH-CFG-08); Link-Gültigkeit 1 h (AUTH-CFG-07) | devops | Auth § 5 | +| ☐ | Nach Passwortänderung geht keine Benachrichtigungs-Mail aus (AUTH-CFG-19) | devops | Testkonto auf Staging, Postfach prüfen | +| ☐ | Rechtstexte-URLs und `TERMS_VERSION` final (R11); Bundle-/Application-ID final (R15) | Chris | vor dem Store-Release | + +## 4. Zugang zu Studio, Datenbank, Pooler und `/pg/` (Spec #2 § 4.2, Spec #2 Risiko R1) + +**Herleitung:** Die Routen und Ports stammen aus der Supabase-Self-Hosting-Vorlage (`kong.yml`, `docker-compose.yml`); diese Dateien liegen nicht im Repo und wurden nicht gelesen. Die Prüfungen unten sind daraus abgeleitet und am echten Setup zu bestätigen. + +Studio läuft als Rolle `postgres` bzw. `supabase_admin` und **umgeht RLS**; im Self-Hosting gibt es in Studio keine Benutzerverwaltung. Wer Studio, 5432, den Pooler oder `/pg/` erreicht, kann alle Daten lesen und ändern. Gilt für **Staging und Produktion**. + +| ☐ | Punkt | Wer | Prüfung | +|---|---|---|---| +| ☐ | Studio nicht öffentlich erreichbar, nur per SSH-Tunnel oder VPN | Chris (Einrichtung), devops (Prüfung) | Von einem Rechner **außerhalb** von Tunnel/VPN: `curl -s -o /dev/null -m 5 -w '%{http_code}\n' https:///` darf keine Studio-Seite liefern (Timeout, 403/404 oder Verbindungsfehler). Auch **401 (Basic-Auth-Abfrage) von außen gilt als Verstoß**: Studio ist nur über Tunnel/VPN erreichbar, Basic-Auth ist nur die zweite Schicht | +| ☐ | Postgres-Port 5432 nicht öffentlich (IPv4 **und** IPv6) | Chris, devops | von außen: `nc -zv -w 5 5432` und `nc -6zv -w 5 5432` schlagen fehl. Zusätzlich allgemeiner Port-Scan der öffentlichen Adressen (z. B. `nmap -Pn -p- `, nur gegen eigene Server): nur die gewollten Ports (443, ggf. 80) offen | +| ☐ | Pooler (Supavisor, Standard 6543; auch 5432 kann der Pooler belegen) nicht öffentlich (IPv4 und IPv6) | Chris, devops | von außen: `nc -zv -w 5 6543` schlägt fehl; abgedeckt durch den Port-Scan oben (tatsächlicher Port **offen**, siehe 8) | +| ☐ | Kong-Route `/pg/` (pg-meta) von außen gar nicht erreichbar | Chris, devops | `curl -s -i https:///pg/tables -H "apikey: "` von außen: erwartet 403/404 oder Verbindungsfehler. **401 oder 200 gilt als Verstoß** (die Vorlage schützt `/pg/` per Key-Auth und Admin-ACL, das reicht hier nicht). Ohne `apikey` ist ein 401 wertlos | +| ☐ | **Basic-Auth** des Gateways gesetzt (`DASHBOARD_USERNAME`/`DASHBOARD_PASSWORD`, starkes Passwort, Standardwerte der Vorlage ersetzt) als zweite Schicht | Chris | Dashboard (per Tunnel) ohne Zugangsdaten liefert 401. Passwort nie ins Repo oder in Logs | +| ☐ | **Studio-Rolle bestätigt:** im Studio-SQL-Editor `select current_user;` ausführen; Ergebnis `postgres` oder `supabase_admin` (die Admin-Funktionen akzeptieren genau diese beiden Rollen, Spec § 4.2) | Chris | Ergebnis im Release-PR oder in #2 festhalten; bei anderer Rolle melden und Spec § 4.2 anpassen | +| ☐ | Im Studio nie `set …` ohne `local`, immer in einer Transaktion (Runbook § 1) | Chris | Dauerregel, kein Prüfbefehl | + +Eingriffe an Firewall, Reverse Proxy und DNS führt Chris aus; devops liefert nur Anleitung und die Außen-Tests oben. + +## 5. CI-Runner (ADR-0003, Issue #43, manuelle Schritte) + +ADR-0003 hat den Status „Vorgeschlagen“. Solange die Schritte offen sind, gilt `docker-host` als nicht für externe Beiträge geeignet; **vor dem ersten externen Beitrag, spätestens vor Release**, Schritt B umsetzen oder das Repo privat stellen (dann entfallen die B-Zeilen weitgehend). Issue #43 erst danach schließen. + +| ☐ | Punkt (ADR-0003, Abschnitt) | Wer | Prüfung | +|---|---|---|---| +| ☐ | **A. Verhalten prüfen:** Test-Fork-PR mit manipulierter `ci.yml`: Lauf wartet auf Freigabe; zweiter Push läuft ohne erneute Freigabe; danach Testkonto und Fork löschen | Chris | Ergebnis in #43 notieren; startet der Lauf ohne Freigabe: Repo sofort privat stellen und Runner pausieren (B.3) | +| ☐ | **B.1** Erreichbarkeit des dind aus `docker`-Jobs prüfen | Chris | `curl -s -m 3 http://:2375/version` im Job (Gateway wie in `ci.yml`). Antwortet der dind, gilt die Warnung für alle Jobs des Runners | +| ☐ | **B.2** Runner in Wegwerf-VM bzw. separaten Host ohne Host-Mounts, ohne LAN-Zugriff, ohne Zugangsdaten und ohne persönliche Daten verlagern | Chris | Beschreibung des Setups in #43 | +| ☐ | **B.3** Notbremse (Runner stoppen) bekannt und einmal geprobt | Chris | Weg laut ADR **unverifiziert** | +| ☐ | **B.4 / C.1** Runner nur für dieses Repo registriert; Fork-PR-Läufe werden nicht freigegeben, solange nicht isoliert | Chris | Forgejo: Einstellungen, Actions, Runner | +| ☐ | **C.5** Runner-Token rotiert (Vorschlag: alle 3 Monate, sofort bei Verdacht) | Chris | Datum der letzten Rotation notieren | + +## 6. Mobile Stores (nur bei Store-Release) + +Android-AAB und iOS-Build: Upload nur nach ausdrücklicher Freigabe von Chris. iOS benötigt einen macOS-Runner oder lokalen Mac. Signierung und Zugänge liegen bei Chris (nicht im Repo). Details sind noch nicht festgelegt (siehe 8). + +## 7. Nach dem Deployment + +| ☐ | Punkt | Wer | Prüfung | +|---|---|---|---| +| ☐ | Smoke-Test Web: Start, Registrierung, Bestätigungs-Link, Anmeldung, Katalog zeigt Spiele | Chris | manuell auf der Zielumgebung | +| ☐ | Tag `v` erst nach Freigabe. Ein Release-/Deploy-Workflow existiert noch nicht (`.forgejo/workflows/` enthält nur `ci.yml`), siehe 8 | Chris | `.claude/commands/release.md`, Schritt 4 | + +## 8. Offene Punkte für Chris (fehlende Angaben, nichts davon wurde erfunden) + +1. Adressen von Staging und Produktion (Domain, Studio-Adresse, Server-IP) und der Zugangsweg (SSH-Tunnel oder VPN, welches). +2. Welcher Reverse Proxy sitzt vor Kong/GoTrue; wie wird `X-Forwarded-For` dort gesetzt; wo werden `/auth/v1/otp` und `/magiclink` gesperrt (Proxy oder Kong). +3. Port des Pooler im tatsächlichen Setup; ob `/pg/` über Kong erreichbar ist. +4. Logging und Alarmierung: welches Werkzeug soll SMTP-Fehler, Gateway-5xx/504 und 429 `over_email_send_rate_limit` melden. +5. SMTP-Anbieter und Absender-Domain (F7 vertagt); Hosting der Mailvorlagen (URL). +6. Konkrete Timeout-Werte (GoTrue-SMTP, Proxy, Client) und Ergebnis des Spikes aus #46. +7. Verfahren für Migrationen auf Staging/Prod, Backup-/Restore-Runbook und Nachweis des Restore-Tests (ADR-0002; ein Betriebs-Runbook in `docs/` existiert noch nicht). +8. Ob Staging und Produktion auf demselben Server laufen (ADR-0002: getrennt, sobald echte Nutzer da sind). +9. Wie `DB_URL` für `psql` gebildet wird (Tunnel, Rolle); nicht ins Repo. +10. Entscheidung über ADR-0003 (Status „Vorgeschlagen“, Maßnahmen A/B/C). +11. Release-/Deploy-Workflow (Web-Deployment, Tag `v*`) existiert noch nicht; Ziel, Verfahren und Freigabe-Schritt sind festzulegen. +12. Store-Release: Signierung, Bundle-/Application-ID (R15), Rechtstexte (R11). + +## 9. Nicht geprüft (Stand dieser Datei) + +Reine Dokumentation, erstellt ohne Zugriff auf Staging/Prod. Die Prüfbefehle wurden **nicht** ausgeführt; erwartete Ergebnisse (z. B. 403/404 bei gesperrten Routen) sind aus den Quellen abgeleitet. Ebenfalls nicht geprüft: das Verhalten von `supabase start` mit Seeds (Runbook § 2.7), das Verhalten von GoTrue bei hängendem SMTP (#46) und die Aussagen aus ADR-0003 zu Runner und Forgejo (laut ADR teils unverifiziert). diff --git a/supabase/README.md b/supabase/README.md index 3a4af99..7fd7c6d 100644 --- a/supabase/README.md +++ b/supabase/README.md @@ -20,7 +20,7 @@ supabase test db # alle pgTAP-Tests ausführen - 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, Release-Checkliste und bekannte Grenzen: [`docs/auth-konfiguration.md`](../docs/auth-konfiguration.md). +- Auth-Einstellungen (`AUTH-CFG-nn` in `config.toml`), Env-Block für Staging/Produktion, Auth-Checkliste und bekannte Grenzen: [`docs/auth-konfiguration.md`](../docs/auth-konfiguration.md). Zentrale Release-Checkliste (Katalog, `checks.sql`, Zugang, Auth/SMTP, Runner): [`docs/release-checkliste.md`](../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)