Webdesign-Bereich: Fundament, oeffentliche Seiten, Zugangsschutz, PayPal

Umsetzung des "Website Masterplan" (16 Seiten) unter /webdesign.

Zugangsschutz mit EIGENER Schranke (server/webdesign-gate.js) statt gate.js:
gate.js laesst seit dem oeffentlichen Start am 21.08.2026 jeden durch, weil
die Pruefung auf SITE_PUBLIC_LAUNCH_AT als allererste Zeile steht. Haette man
/webdesign dahintergehaengt, waere der ausdruecklich nicht-oeffentliche Bereich
inklusive Preisen und spaeteren Kundendaten ab der ersten Sekunde fuer jeden
lesbar gewesen. Eigenes Sitzungs-Cookie, bereich="webdesign" im Token, damit
ein gueltiges Universe-Cookie hier NICHT gilt. 37/37 Tests.

Sieben oeffentliche Seiten in fuenf Sprachen (de, de-CH mit echtem Dialekt, en,
fr, pt). Preise, Zeitrahmen, Paketnamen und die 30-%-Regel stehen an genau
EINER Stelle in wd-core.js -- der Masterplan verlangt "ueberall
widerspruchsfrei", und vier Kopien laufen bei der ersten Preisaenderung
auseinander.

Als App installierbar auf Handy und PC. Der Service Worker speichert bewusst
KEINE HTML-Seite zwischen: nach dem Abmelden wuerden sonst geschuetzte Seiten
weiter ausgeliefert, ohne dass der Server je gefragt wird. 18/18 Tests.

Handy-Abnahme ueber alle Seiten in fuenf Breiten (320-1440) und fuenf Sprachen:
40/40. Der Test fand 35 echte Fehler (Touch-Ziele unter 44px), behoben im
Designsystem statt einzeln pro Seite.

PayPal (Wunsch 22.08.2026 "sofort auf meinem paypal"): Orders API mit
intent=CAPTURE, also sofortiger Einzug statt blosser Reservierung. Gebuehr und
Nettobetrag getrennt gespeichert. Betraege durchgehend als Ganzzahl in Cent.
Gefaelschte Webhooks werden abgewiesen. Fail closed solange Zugangsdaten
fehlen. 28/28 Tests gegen einen nachgebauten PayPal-Server.

Datenbank: 15 Tabellen mit Praefix wd_, fachlich vollstaendig vom Universe
getrennt.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-08-22 18:06:52 +02:00
co-authored by Claude Opus 5
parent 2010b5ec33
commit 4b3ec450d5
50 changed files with 8264 additions and 0 deletions
+19
View File
@@ -78,6 +78,14 @@ import {
getTeamPublic, getTeamAdmin, saveTeamMember, importLegacyMember, deleteTeamMember, uploadTeamPhoto,
} from "./routes/team.js";
import { getSiteTextsPublic, saveSiteText } from "./routes/site-texts.js";
/* Webdesign-Bereich (22.08.2026). Die Rechteprüfung sitzt bewusst IN den
Handlern statt in einer Middleware davor: die Endpunkte brauchen
unterschiedliche Rechte (ansehen vs. bearbeiten), und ein einzelnes
requireTeamSession davor würde diesen Unterschied verwischen. */
import {
anfrageAbsenden, anfragenListe, anfrageDetail,
anfrageStatus, anfrageArchivieren, anfrageNotiz,
} from "./routes/webdesign-anfragen.js";
initDb();
@@ -208,6 +216,17 @@ app.get("/testimonials", wrap(getApprovedTestimonialsPublic));
app.get("/team", wrap(getTeamPublic));
app.get("/site-texts", wrap(getSiteTextsPublic));
/* ---------- Webdesign-Bereich (22.08.2026) ----------
Genau EIN öffentlicher Endpunkt: das Anfrageformular. Alles Weitere
verlangt eine Team-Anmeldung, die in den Handlern selbst geprüft wird
(unterschiedliche Rechte je Endpunkt, siehe Import oben). */
app.post("/webdesign/anfrage", wrap(anfrageAbsenden));
app.get("/webdesign/admin/anfragen", wrap(anfragenListe));
app.get("/webdesign/admin/anfragen/:id", wrap(anfrageDetail));
app.post("/webdesign/admin/anfragen/:id/status", wrap(anfrageStatus));
app.post("/webdesign/admin/anfragen/:id/archivieren", wrap(anfrageArchivieren));
app.post("/webdesign/admin/anfragen/:id/notiz", wrap(anfrageNotiz));
app.post("/supporter/register", wrap(registerSupporter));
app.post("/supporter/verify-email", wrap(verifySupporterEmail));
// Normaler Login seit 21.08.2026: E-Mail + selbst gewählter Zugangscode.