Zwei schnell aufeinanderfolgende Klicks auf "DHL-Versandmarke
erstellen" konnten beide den findUnique-Check bestehen und zwei
echte, kostenpflichtige DHL-Sendungen anlegen (gleiche Race-Condition
wie beim zuvor gefixten Retouren-Erstattungs-Bug). Ein reines
create()-mit-Unique-Constraint waere hier nicht ausreichend gewesen,
da Shipment-Datensaetze bereits ohne DHL existieren koennen
(automatisch bei Statuswechsel auf VERSENDET, oder manuell erfasst).
Fix: Serializable-Transaktion claimt den Datensatz atomar mit einem
Sentinel-Wert, bevor der DHL-Aufruf ueberhaupt startet; bei einem
fehlschlagenden DHL-Aufruf wird der Sentinel wieder entfernt.
Gefunden bei eigener Nachpruefung der neuen Admin-Actions dieser
Session (apicore-sync.ts war bereits sauber idempotent, kein Fix
noetig).
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Keine der in dieser Session neu hinzugefuegten sicherheitskritischen
Module (lib/csrf.ts, lib/entra.ts, lib/dhl.ts) hatte bisher Tests.
- csrf.test.ts: Same-Origin-Erkennung, Ablehnung gefaelschter
Cross-Origin-Requests, tolerantes Verhalten bei fehlendem/kaputtem
Origin-Header.
- entra.test.ts: PKCE-Paar-Erzeugung (RFC 7636), Authorize-URL-Aufbau,
Extraktion des verifizierten E-Mail-Claims (nie ein unplausibles
Feld raten).
- dhl.test.ts: Adress-Mapping (Strasse/Hausnummer-Trennung,
ISO2->ISO3-Laendercode), Fehlerbehandlung bei nicht unterstuetztem
Land, DHL-Validierungsfehlern und HTTP-Fehlern, statt einen falschen
Erfolg vorzutaeuschen.
Alle 118 Tests (13 Dateien) gruen, tsc --noEmit clean.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
- Checkout: Gutscheincode-Nutzungslimit wird jetzt innerhalb derselben
Serializable-Transaktion wie die Bestellanlage frisch nachgeprueft, statt
nur einmalig vorab. Zwei gleichzeitige Checkouts mit demselben
maxUses:1-Code konnten sich sonst beide durchsetzen.
- Admin/Retouren: Erstattungsstatus wird jetzt atomar (bedingtes Update,
ANGENOMMEN -> ERSTATTET) VOR dem Stripe-Aufruf gesetzt statt danach. Ein
Doppelklick auf "Erstatten" konnte sonst zwei echte Stripe-Erstattungen
ausloesen. Bei einem fehlschlagenden Stripe-Aufruf wird der Status wieder
zurueckgesetzt, damit erneut versucht werden kann.
Beide Luecken kamen aus dem Security-Assessment dieser Session.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
CSRF-Schutz, DHL-Versandmarken, Entra-ID-SSO, ApiCore-Sync und die
Harvest-isPublished-Migration waren gestaged aber nicht im letzten
Commit enthalten — Gitea-Actions-Build brach mit "Module not found"
fuer genau diese Dateien ab.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
gitea.server_url ist in manchen Gitea-Versionen leer (go-gitea/gitea#23276)
und liefert selbst im Erfolgsfall eine volle URL mit https://-Schema statt
des fuer docker login/Image-Tags benoetigten reinen Hostnamens. Registry
jetzt fest als git.encry.de hinterlegt, k8s-Manifeste entsprechend
vorausgefuellt.
Dockerfile (Multi-Stage, "output: standalone"), docker-compose.yml mit
Caddy als einzigem nach aussen offenem Reverse-Proxy (verhindert
X-Forwarded-For-Faelschung fuer das App-eigene Rate-Limiting), Gitea
Actions Workflow der bei jedem Push zwei Image-Tags in die Gitea-
Container-Registry baut (schlankes Laufzeit-Image + ein Migrations-
Image mit Prisma-CLI), sowie rohe Kubernetes-Manifeste (Namespace,
ConfigMap, Secret-Vorlage, Postgres-/MySQL-StatefulSet, Migrations-Job,
App-Deployment, Ingress) fuer den Cluster-Betrieb. Siehe k8s/README.md
fuer den vollstaendigen Einrichtungs-/Deployment-Ablauf.