test: Geldpfade absichern und Go-Live-Pruefung ehrlich machen

Die beiden Dateien, in denen Geld und Lagerbestand zusammenlaufen, hatten
bisher keinen einzigen Test. Dazu meldete die Go-Live-Pruefung gruene
Haken fuer Werte, die gar nicht gesetzt waren.

Tests fuer api/checkout/route.ts (10 Faelle)
  Torwaechter (fremder Origin, Turnstile, Rate-Limit), deaktiviertes
  Produkt, Preis 0, ausverkaufte Ware, Sitzungslebensdauer — und die
  beiden Regressionen: scheitert die Stripe-Sitzung, wird die Bestellung
  aufgeloest und OHNE orderNumber geantwortet; laesst sich die
  Sitzungs-ID nicht speichern, wird die Sitzung geschlossen. Per
  Mutationstest geprueft, dass der zweite Fall ohne den Fix rot wird.

Tests fuer api/checkout/webhook/route.ts (12 Faelle)
  Signaturpruefung, verzoegerte Zahlung (SEPA), Auslieferung samt
  Rechnung und Anhang, mehrfach zugestelltes Ereignis (Gutschein und
  Rechnungsnummer duerfen sich nicht wiederholen), Zahlung auf eine
  stornierte Bestellung, Betragsabweichung, abgelaufene Sitzung,
  fehlgeschlagener Einzug, volle und teilweise Erstattung, Rueckbuchung.

Datenbank und Stripe sind in beiden Dateien vollstaendig ersetzt.

Go-Live-Pruefung: falsch-positive Haken beseitigt
  Regeln, die einen Wert voraussetzen, bestanden bei fehlendem Wert
  einfach — eine leere Zeichenkette enthaelt nun einmal kein
  "example.com". Der Bericht meldete deshalb "NEXT_PUBLIC_SITE_URL ist
  die echte Domain" als bestanden, direkt neben dem Blocker
  "NEXT_PUBLIC_SITE_URL gesetzt". Ohne jeden Stripe-Schluessel galt
  sogar der Live-Modus als bestaetigt. Das ist die gefaehrlichste
  Fehlmeldung, die eine solche Pruefung machen kann: sie beruhigt ueber
  genau den Punkt, der offen ist. mustWhenSet/shouldWhenSet lassen
  Folgeregeln bei fehlendem Wert entfallen.

  Ausserdem sagt der Bericht jetzt ausdruecklich, dass er die Umgebung
  prueft, in der er LAEUFT. Lokal meldet er Blocker, die in der
  ConfigMap des Clusters laengst erledigt sind; wer das ein paarmal
  erlebt, liest ueber den Bericht hinweg. Das README nennt den Aufruf
  im Pod.

tsc: 0 Fehler. vitest: 316/316 gruen (zuvor 294). eslint: 0 Warnungen.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Opus 5 committed 2026-09-18 17:50:38 +02:00
1 parent 1fa8dc9ce2
commit dbf146c19f
4 files changed
+732 -12

No files matched your search

+10
View File
@@ -308,6 +308,16 @@ Die App läuft danach hinter [Caddy](https://caddyserver.com/) unter `http://loc
pnpm preflight
```
**Geprüft wird die Umgebung, in der der Befehl läuft — nicht „das Projekt".** Auf einem Entwicklungsrechner liest er die lokale `.env`, und die enthält absichtlich einen `sk_test`-Schlüssel, kein SMTP und keine echte Domain. Er meldet dort also Blocker, die für den Live-Betrieb längst erledigt sind: `NEXT_PUBLIC_SITE_URL`, `SMTP_FROM` und die Steuersätze stehen in `k8s/01-configmap.yaml`, die Geheimnisse in `k8s/02-secret.yaml`. Wer das ein paarmal erlebt, gewöhnt sich an, über den Bericht hinwegzulesen — und übersieht dann den einen Blocker, der echt ist.
Für eine belastbare Aussage deshalb **im laufenden Pod** ausführen, wo ConfigMap und Secret tatsächlich anliegen:
```bash
kubectl exec -n wabenhain deploy/wabenhain-app -- pnpm preflight
```
Der Exit-Code ist dabei derselbe (1, solange ein Blocker offen ist), der Aufruf lässt sich also unverändert als letzter Schritt in die Deploy-Pipeline hängen.
Prüft die Konfiguration gegen alles, was einen öffentlichen Shop still unbrauchbar machen kann, und beendet sich mit Exit-Code 1, solange ein Blocker offen ist — dadurch lässt sich der Aufruf unverändert als Schritt in die Deploy-Pipeline hängen. Geprüft werden unter anderem:
- `SESSION_SECRET`, `ADMIN_EMAIL` und `ADMIN_PASSWORD` auf Länge und darauf, dass noch der Beispielwert aus `.env.example` darin steht (ein bekanntes Signiergeheimnis macht jede Sitzung fälschbar).