docs(auth): document E2E setup and SMTP outage spike result

Refs #38

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
cschlaefke 2026-11-03 10:42:28 +01:00
parent d390b60bd6
commit ec2d45c319
4 changed files with 89 additions and 0 deletions

4
.gitignore vendored
View file

@ -28,6 +28,10 @@ app/coverage/
node_modules/
test-results/
playwright-report/
blob-report/
playwright/.cache/
.playwright-mcp/
e2e/.auth/
# OS
.DS_Store

View file

@ -176,3 +176,28 @@ Automatisiert nicht abdeckbar (Spec § 7.1); vor dem Release abhaken:
- **Magic Link / OTP** sind nicht abschaltbar, nur am Gateway sperrbar (R4).
- **Vorlagen-Rückfall:** Unerreichbare Vorlagen-URL → stille englische Standardvorlage (R5).
- **Plain-Text-Teil der Mails:** GoTrue sendet nur HTML. Die Vorlagen zeigen den Link deshalb zusätzlich als Klartext; Mailpit erzeugt lokal einen Text-Teil.
## 7. E2E-Tests und SMTP-Ausfall (Issue #38, Spike #37)
Die Playwright-Tests unter `e2e/` (Projekte `api`, `web`, `throttle`, `spike`; Anleitung `e2e/README.md`) sichern diese Konfiguration ab. Konstanten stehen in `e2e/support/auth-config.ts`; `tests/api/config.spec.ts` prüft sie gegen `supabase/config.toml` und diese Datei (alle IDs AUTH-CFG-01 bis -25 müssen in Abschnitt 1 vorkommen).
| ID | Absichernder Test |
|---|---|
| AUTH-CFG-04, -24 | `tests/api/krit04-enumeration.spec.ts` (Signup mit bestätigter Adresse → 200, `identities` leer, keine Mail, altes Passwort gilt) |
| AUTH-CFG-05 | `krit02-03-validierung.spec.ts` (9 Zeichen → 422 `weak_password`) |
| AUTH-CFG-07 | `krit08-reset-link.spec.ts` und `web/krit08-reset.spec.ts` (Link nach 1 h + 1 s abgelaufen, 60 s vor Ablauf gültig) |
| AUTH-CFG-10, -13 | `tests/throttle/krit07-drosselung.spec.ts` (Login #31 → 429, zweite IP unbeeinflusst, kein `Retry-After`, ohne Header keine Drosselung) |
| AUTH-CFG-14, -15, -16 | `krit05-sitzung.spec.ts`, `config.spec.ts` |
| AUTH-CFG-17, -18, -19 | `krit11-sprache-benachrichtigungen.spec.ts` |
### SMTP-Ausfall (Spike #37, Stand 2026-11-03, GoTrue `v2.197.0`)
Messung gegen einen zusätzlichen GoTrue-Container, dessen SMTP-Port 1 die Verbindung ablehnt (`e2e/support/start-throttle-gotrue.sh start smtp-down`, Test `e2e/tests/spike/smtp-down.spec.ts`). Mailpit bleibt für die anderen Tests unberührt. Die Tests prüfen nichts, sie protokollieren.
| Aufruf | bekannte Adresse | unbekannte Adresse |
|---|---|---|
| `POST /recover` | **500** `unexpected_failure` „Error sending recovery email“ | **200** |
| `POST /resend` (signup) | unbestätigt: **500** „Error sending confirmation email“ | **200** |
| `POST /signup` | unbestätigt: **500**; bestätigt: **200** (erfundener Nutzer, kein Versand) | neu: **500** „Error sending confirmation email“, Nutzer wird **nicht** angelegt (Rollback) |
Antwortzeiten liegen alle im einstelligen bis niedrigen zweistelligen Millisekundenbereich (Verbindung wird sofort abgelehnt), also kein Zeit-Seitenkanal. **Befund:** Bei nicht erreichbarem SMTP unterscheiden sich die Antworten von `/recover`, `/resend` und `/signup` je nach Existenz des Kontos (500 vs. 200), und zwar nicht nur bei erschöpftem Mail-Limit (R3, F12). Die rohe API verrät dann die Existenz; laut Mapping 4.4 (nicht getestet) würde die App bei Reset 500 als `unexpected`, bei Registrierung als `registrationRejected` anzeigen, also einen Fehler statt des neutralen Bildschirms. Ob die App bei HTTP 500 aus Sendefehlern neutral bleiben soll (wie bei `over_email_send_rate_limit`), ist offen (Issue #37). Nicht untersucht: ein SMTP-Server, der die Verbindung annimmt, aber nicht antwortet (Timeout), und GoTrue hinter dem Produktions-Gateway. Dafür den Container mit einer nicht routbaren SMTP-Adresse (z. B. `GOTRUE_SMTP_HOST=10.255.255.1`) starten und `GOTRUE_SMTP_PORT` bis zum Timeout beobachten.

55
e2e/README.md Normal file
View file

@ -0,0 +1,55 @@
# E2E-Tests (Playwright)
Auth-Tests für KTO-01 (Spec `docs/specs/1-auth-registrierung-anmeldung.md` § 7, Issue #38). Jeder Test
nutzt zufällige E-Mail-Adressen und filtert Mails je Adresse (Mailpit wird nie global geleert),
die Tests laufen deshalb parallel.
## Projekte
| Projekt | Ziel | Voraussetzung | Tests |
|---|---|---|---|
| `api` | GoTrue über Kong (`:54321`) + Mailpit (`:54324`) + Postgres (`:54322`) | `supabase start` | 52 |
| `web` | gebaute Flutter-Web-App auf `http://localhost:3000` | zusätzlich `flutter build web` | 21 |
| `throttle` | Extra-GoTrue-Container mit `GOTRUE_RATE_LIMIT_HEADER` (AUTH-CFG-13) | `THROTTLE_GOTRUE_URL` | 4 |
| `spike` | GoTrue mit unerreichbarem SMTP (Issue #37), nicht blockierend | `SPIKE_GOTRUE_URL` | 3 |
`throttle` und `spike` werden nur registriert, wenn die jeweilige Variable gesetzt ist.
## Lokal ausführen
```bash
supabase start -x studio,imgproxy,vector,logflare,edge-runtime,postgres-meta,realtime,storage-api
supabase db reset
# Web-Build gegen die lokale CLI (echten Anon-Key aus `supabase status -o env` eintragen)
cd app && flutter build web --dart-define-from-file=env/ci.example.json # SUPABASE_URL/ANON_KEY anpassen
cd ../e2e && npm ci && npx playwright install chromium
npx playwright test --project=api
npx playwright test --project=web # startet `serve -s ../app/build/web -l 3000` selbst
# Drosselung (Krit. 7) und SMTP-Spike
./support/start-throttle-gotrue.sh start throttle # :9998
./support/start-throttle-gotrue.sh start smtp-down # :9997
THROTTLE_GOTRUE_URL=http://127.0.0.1:9998 SPIKE_GOTRUE_URL=http://127.0.0.1:9997 npx playwright test
./support/start-throttle-gotrue.sh stop throttle; ./support/start-throttle-gotrue.sh stop smtp-down
```
Umgebungsvariablen (Standard = lokale CLI-Demo-Werte, keine Secrets): `SUPABASE_URL`,
`SUPABASE_ANON_KEY`, `SUPABASE_SERVICE_ROLE_KEY`, `MAILPIT_URL`, `E2E_DB_URL`, `WEB_URL`,
`TERMS_VERSION`.
## Aufbau
- `support/auth-config.ts` – Konstanten mit `AUTH-CFG-nn`-Bezug; `tests/api/config.spec.ts` prüft sie gegen `supabase/config.toml` und `docs/auth-konfiguration.md`.
- `support/gotrue.ts`, `support/mailpit.ts` – REST-Client und Mailfänger-Helfer.
- `support/db.ts` – direkter Postgres-Zugriff, **nur lokal/CI** (bricht bei anderem Host ab); setzt `recovery_sent_at`/`confirmation_sent_at` für Ablauftests.
- `support/web.ts` – Flutter-Web-Helfer (Semantics einschalten, Felder füllen, Uhr verschieben).
- `support/start-throttle-gotrue.sh` – zweiter GoTrue-Container (Profile `throttle`, `smtp-down`).
## Hinweise zum Web-Projekt
- Flutter zeichnet auf Canvas. Der Semantics-Baum wird über `flt-semantics-placeholder` eingeschaltet (`enableSemantics`).
- Eingabefelder werden mit `click` + `pressSequentially` gefüllt; `fill` allein geht gelegentlich verloren.
- Immer `localhost` (nicht `127.0.0.1`): Die Mail-Links nutzen die Site-URL (AUTH-CFG-01), sonst liegt die Sitzung in einem anderen `localStorage`.
- Gegen die gemeinsame CLI-Instanz werden nie `X-Forwarded-For`-Header gesendet (R13).

View file

@ -22,6 +22,11 @@ supabase test db # alle pgTAP-Tests ausführen
- 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).
- 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`](../e2e/README.md).
## 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.