Der Name "Tages-Code" konnte fälschlich als sich täglich änderndem/rotierendem Code
verstanden werden. Tatsächlich bleibt der Code dauerhaft gleich (6GAM4AST) — nur die
24h-Sitzung läuft ab, wodurch derselbe Code einmal pro Tag erneut eingegeben werden
muss. Reine Text-/Kommentar-Korrektur, keine Verhaltensänderung.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Auf ausdrücklichen Wunsch: /verwaltung/ + /api/verwaltung/* verlangen jetzt ZUSÄTZLICH zum
normalen 90-Tage-Seitenzugang einen zweiten, eigenen Code, den nur qciga und VanVan kennen —
und der nach 24 Stunden automatisch abläuft (muss also einmal täglich neu eingegeben werden).
Der Rest der Seite ist davon unberührt, nur die Bestellübersicht ist betroffen.
Bewusst als eigenständiges System (eigenes Cookie vandiy_verwaltung_session, eigenes Geheimnis
VERWALTUNG_SESSION_SECRET, eigener HMAC-Signaturcode statt geteiltem mit dem normalen
Seitenzugang) — gleiches Trennungsprinzip wie bei den Kundenkonten: ein Leck bei einer
Sitzungsart darf nie die andere gefährden.
Neue Dateien: functions/_shared/verwaltung-auth.js (Session-Logik), public/verwaltung-code.html
(Eingabemaske im selben Stil wie die Haupt-Zugangsseite). functions/_middleware.js prüft nach
erfolgreicher Haupt-Sitzung zusätzlich diese zweite Sitzung für /verwaltung*-Pfade. Beide
API-Routen (orders.js, orders/[id].js) prüfen die zweite Schranke zusätzlich eigenständig,
nach demselben Verteidigungs-in-der-Tiefe-Prinzip wie die bestehende Haupt-Prüfung.
Lokal vollständig durchgetestet (wrangler pages dev): kompletter Ablauf ohne jeden Zugang ->
Haupt-Gate -> Redirect zum Tages-Code -> falscher Code abgelehnt -> richtiger Code setzt
24-Stunden-Cookie -> Seite und API danach erreichbar. Bestätigt: der Rest der Seite bleibt
unberührt (kein Tages-Code nötig), UND dass VanVan mit nur dem Haupt-Zugang (ohne Tages-Code)
ebenfalls noch ausgesperrt bleibt, wie gewünscht.
Zwei neue Cloudflare-Secrets in Produktion gesetzt: VERWALTUNG_SESSION_SECRET (zufällig
erzeugt) und VERWALTUNG_ACCESS_CODE (der eigentliche Tages-Code, an qciga und VanVan zu
verteilen).
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Kundenkonten sind jetzt genauso echt wie die PayPal-Zahlung: server-geprüftes OAuth 2.0 mit
PKCE für Google und "Log in with PayPal" (functions/_shared/oauth.js, oauth-handlers.js),
neue D1-Tabelle "customers" (bewusst ohne Passwort-Feld), eigene von der Zugangscode-Schranke
getrennte Sitzungs-Logik (customer-auth.js). Echte DSGVO-Rechte direkt im Kontobereich:
Daten herunterladen (Art. 15/20) und Konto unwiderruflich löschen (Art. 17), Bestellungen
bleiben aus gesetzlichen Gründen erhalten. Datenschutzerklärung entsprechend ergänzt.
Ohne echte Google-/PayPal-Zugangsdaten zeigt der Login-Button ehrlich einen
"noch nicht eingerichtet"-Hinweis statt eine Anmeldung vorzutäuschen.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Auf ausdrücklichen Wunsch, mit Fokus auf rechtliche Absicherung:
- Klarna komplett entfernt (hätte eigene Händlerprüfung + Bonitätsprüfungs-
Pflichten nach der neuen EU-Verbraucherkreditrichtlinie vorausgesetzt).
- Eigene Kreditkarten-Eingabemaske komplett entfernt (wäre PCI-DSS-pflichtig
gewesen — für einen kleinen Shop praktisch nicht stemmbar). Kartenzahlung
bleibt möglich: PayPals eigener, PCI-zertifizierter Gast-Checkout bietet
Kredit-/Debitkarte an, ohne dass Kartendaten je unsere Seite berühren.
- PayPal ist jetzt ECHT server-seitig verifiziert statt dem Browser blind zu
vertrauen: eigener Cloudflare-Function-Flow (functions/_shared/paypal.js +
functions/api/paypal/) legt die PayPal-Bestellung server-seitig an, zieht
die Zahlung nach Bestätigung server-seitig ein und prüft den eingezogenen
Betrag gegen die Bestellsumme — die Bestellung wird ausschließlich bei
bestätigter, betragsgleicher Zahlung angelegt. /api/orders lehnt direkte
PayPal-Bestellungen jetzt ausdrücklich ab (verhindert vorgetäuschte
"bezahlte" Bestellungen ohne echte Zahlung).
- Neuer, ehrlicherer Bestellstatus "zahlungOffen": Überweisungs-Bestellungen
starten jetzt so (Geld noch nicht da) statt fälschlich sofort "bezahlt" zu
heißen — Schutz vor Warenversand, bevor das Geld wirklich angekommen ist.
Eigene Kachel/Filter/Badge-Farbe in der Verwaltung, Umsatz-/Auswertungs-
Zahlen zählen "zahlungOffen" bewusst nicht mit.
- Rechtstexte (AGB, Datenschutzerklärung, FAQ, Versand & Zahlung) auf allen
4 Sprachen aktualisiert: nur noch PayPal + Überweisung erwähnt, inkl. DSGVO-
Hinweis zur internationalen Datenübertragung an PayPal (Data Privacy
Framework-Zertifizierung).
- D1-Migration 0003: neue Spalte paypal_order_id (Zahlungsbeleg) + erweiterter
Status-Wertebereich, auf Live-Datenbank angewendet, bestehende Daten intakt.
Mit echten Testbestellungen lokal verifiziert: Überweisung legt korrekt
"zahlungOffen" an, direkter PayPal-Bypass-Versuch an /api/orders wird
abgelehnt, PayPal-Route meldet sauber "noch nicht eingerichtet" ohne
Zugangsdaten. Checkout-UI zeigt nur noch 2 Zahlungsarten, Bestellknopf ist bei
PayPal ausgeblendet (Zahlung läuft exklusiv über den echten PayPal-Button).
Für den echten Zahlungseingang fehlt noch VanVans eigenes PayPal-Business-
Konto (Client-ID + Secret) — Details in der Vault-Dokumentation.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
context.waitUntil() lief in dieser Pages-Functions-Umgebung nicht zuverlässig zu
Ende, bevor die Anfrage beendet wurde - Bestellungen wurden korrekt gespeichert,
aber die Benachrichtigungs-Mail an [email protected] kam nie an.
Mit echten Live-Bestellungen verifiziert: mit waitUntil kam nichts bei Resend an,
mit await kam die Mail sofort und zuverlässig an.
Außerdem: "Auf Lager"-Feld im Produkt-Formular (Admin) steht jetzt über "Kategorie"
statt darunter, wie gewünscht.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
1) Gutscheincodes können jetzt im Adminbereich auf "nur einmal pro Person einlösbar"
gestellt werden. Wird serverseitig durchgesetzt (neue Spalte orders.gutschein_code +
Prüfung in functions/api/orders.js gegen die echte Bestelldatenbank, case-insensitiv
nach E-Mail-Adresse) — kann also NICHT durch Löschen von localStorage/einen anderen
Browser umgangen werden, anders als die bisherige rein clientseitige Rabattlogik.
Stornierte Bestellungen zählen nicht als "schon benutzt". Ausführlich getestet: echter
Browser-Checkout mit Einmal-Code funktioniert beim ersten Versuch, wird beim zweiten
Versuch (gleiche E-Mail) korrekt mit klarer Fehlermeldung abgelehnt, mit anderer E-Mail
weiterhin nutzbar.
2) Bestell-E-Mail-Benachrichtigung an [email protected]: recherchiert und
vorbereitet (existierte vorher nirgends im Code). Läuft über Resend (kostenlos bis
3.000 E-Mails/Monat), im Hintergrund per context.waitUntil() nach jeder neuen
Bestellung — verzögert nie die Antwort an die Kundschaft und kann eine Bestellung
niemals zum Scheitern bringen, selbst wenn der Versand fehlschlägt (mit ungültigem
Testschlüssel verifiziert: Bestellung bleibt trotzdem erfolgreich gespeichert). Wird
automatisch aktiv, sobald ein RESEND_API_KEY als Secret hinterlegt wird.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Ersetzt die Phase-1-Beispieldaten in /verwaltung/ durch ein echtes, funktionierendes
Bestellsystem:
- Neue D1-Datenbank (vans-diy-bastelbedarf-db) mit orders/order_items-Tabellen,
an das Pages-Projekt gebunden (wrangler.toml).
- Neue API-Routen (Pages Functions): POST /api/orders legt beim Checkout eine echte
Bestellung an (mit Validierung); GET/PATCH /api/verwaltung/orders(/:id) listen bzw.
ändern Bestellungen — beide zusätzlich zur Middleware nochmal eigenständig gegen die
Zugangscode-Sitzung geprüft (Verteidigung in der Tiefe). Gemeinsame Auth-Logik aus
_middleware.js nach functions/_shared/auth.js ausgelagert.
- Checkout (4 Sprachen) sendet beim Absenden die echte Bestellung an die API, zeigt bei
einem Fehler eine klare Meldung statt einfach auf die Danke-Seite weiterzuleiten.
- /verwaltung/ lädt Bestellungen jetzt live per fetch(), mit Lade-/Fehlerzustand, und
erlaubt direktes Ändern des Bestellstatus per Dropdown (sofort in der Datenbank
gespeichert). Neuer Status "storniert" (zählt nicht in Umsatz/Auswertung mit).
Vollständig lokal end-to-end getestet (wrangler pages dev + lokale D1): echter
Browser-Checkout -> Bestellung landet in der Datenbank -> erscheint sofort in der
Verwaltung -> Status ändern bleibt nach Neuladen bestehen.
Co-Authored-By: Claude Sonnet 5 <[email protected]>