Commit Graph
48 Commits
Author SHA1 Message Date
ClaudeandClaude Opus 5.5 531ee2a02b Gitea-Client herausgelöst, Konfiguration für Organisation und System-Konto, Test-Nachbauten
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 10:21:34 +00:00
ClaudeandClaude Opus 5.5 ea71b3f1c3 Sperren: Timeout eines Wartenden hebt die Sperre nicht auf
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 10:21:34 +00:00
ClaudeandClaude Opus 5.5 679f996597 Bausteine: slugify mit Umlauten, deutsche Zeit, Sperren
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 10:21:34 +00:00
ClaudeandClaude Opus 5.5 e4efdac226 Hosting-Abo: Preis 15 € -> 20 € pro Monat (Vertragsbedingungen v4, Katalog, Leitfaden)
- server/config.js: amountCents 2000, lookup_key webklar_hosting_monatlich_2000
- ensurePrice haengt einen neuen Preis an das vorhandene Stripe-Produkt (metadata.webklar),
  statt ein zweites "WEBklar Hosting-Abo" anzulegen
- abo-bedingungen.html (Uebersicht, Preise, Leistungsbeschreibung) + PDF, Leitfaden + PDF
- Tests auf 20 € umgestellt (399/399)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 16:29:01 +00:00
ClaudeandClaude Opus 5.5 78b4d7b7fe Livegang: Vertragsbedingungen Version 4 und Datenschutzerklärung Stand 30.09.2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 16:03:39 +00:00
ClaudeandClaude Sonnet 5.5 36b54f6dab Löschfristen: bei abgeschnittenen Listen abbrechen, Teilfehler melden, Randfälle
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-29 14:54:43 +00:00
ClaudeandClaude Opus 5.5 6c8e7703ae Vertragsbedingungen Version 4: Datenverlust-Klausel § 13 Abs. 3 mit Ausnahme für Absatz 1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 14:52:38 +00:00
ClaudeandClaude Sonnet 5.5 9342ba10c8 Löschfristen: Probelauf, Bericht ans Team, Löschen nach drei Jahren
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-29 14:51:50 +00:00
ClaudeandClaude Sonnet 5.5 cc42ab16c1 Admin E-Mail-Speicher: belegter Speicher wie in konsoleH, klare Vorgabe je Kunde
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-29 14:48:49 +00:00
ClaudeandClaude Fable 5.1 12a24514a4 Mails: Vertragsbestätigung je Fassung, Zustimmung zum AVV, kleinere Textkorrekturen
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-29 14:46:41 +00:00
ClaudeandClaude Fable 5.1 63d3bb11bf Admin: Reiter E-Mail-Speicher, Abo mit Produkt; Schnittstelle fürs Ticketsystem
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-29 14:37:42 +00:00
ClaudeandClaude Fable 5.1 19f9c747a2 Mails: Produktname statt fest Wartungs-Abo, neue Mails für Wechsel und Zusatzspeicher, UptimeRobot-Hinweis
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-29 10:38:43 +00:00
ClaudeandClaude Fable 5.1 0d2254ca20 Kündigung und Widerruf: Paketzahl in jeder Bestätigung, klare Hinweise fürs Team, Tests
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-29 10:15:51 +00:00
ClaudeandClaude Sonnet 5 e5cc2f3c82 Abo-Angebote: für Hosting- oder Wartungs-Abo
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 10:08:59 +00:00
ClaudeandClaude Fable 5.1 7ffe95f24a Kündigung und Widerruf: Vertrag bzw. Bestellung auswählbar (§ 312k, § 356a BGB)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-29 09:52:37 +00:00
ClaudeandClaude Fable 5.1 f66a713531 Zusatzspeicher: Plan nach Stripe-Abgleich erneut prüfen, Aufgabenliste unter Sperre, K13 ohne Kosten
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-29 09:31:28 +00:00
ClaudeandClaude Opus 5.5 662f8d8144 Wechsel: Lastschrift-Fehler nur für den echten Wechsel, Abgleich ohne Webhook, Gutschrift netto, Skript prüft Stripe
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 09:24:02 +00:00
ClaudeandClaude Fable 5.1 bc20ce0673 Zusatzspeicher: Vorschau im flexiblen Abrechnungsmodus, Aufgaben nach Zeitpunkt, keine stillen Abbrüche
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-29 09:16:07 +00:00
ClaudeandClaude Opus 5.5 188db4b3c1 Wechsel Hosting → Wartung: neuer Abbuchungstag, Gutschrift, 12 neue Monate
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 11:30:21 +00:00
ClaudeandClaude Fable 5.1 379cc26dcd Zusatzspeicher: Plus sofort anteilig, Minus zum Monatsende, Aufgaben für konsoleH
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-28 10:48:29 +00:00
ClaudeandClaude Fable 5.1 887e1e54a0 Abo-API: Nachweis-ID nach Appwrite-Regeln, Webhook bei dauerhaften Fehlern, Tests
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-28 10:19:05 +00:00
ClaudeandClaude Opus 5.5 7df0b72019 Stripe: Testrabatt-Namen, Produktbild, Hosting-Leistungen, Tests für Bestandskunden
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 10:02:03 +00:00
ClaudeandClaude Fable 5.1 c4607e9c43 Abo-API: Bestellung je Produkt, Katalog, Speicherstand, Wechsel-Möglichkeit
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-28 09:43:09 +00:00
ClaudeandClaude Opus 5.5 05363d06ad Vertragsereignisse: Speicher-Aufgaben mit gelesenen Details
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 09:25:16 +00:00
ClaudeandClaude Opus 5.5 e5cc57cefd Stripe: Preise je Produkt, Testrabatt Hosting, Kundenportal „Abo verwalten“, Mindestlaufzeit ab termStartAt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 09:21:25 +00:00
ClaudeandClaude Opus 5.5 7799d7c4de Vertragsereignisse: Nachweise, Widerrufsfristen, Speicher-Aufgaben
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 08:59:30 +00:00
ClaudeandClaude Opus 5.5 7e869280f3 Rechtsrunde: Wartung ab wirksamem Wechsel, Wortlaut § 9, Aufbewahrung bis Jahresende
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 08:45:40 +00:00
ClaudeandClaude Opus 5.5 478fbae3aa Rechtsrunde: Wechsel erst mit Zahlung, Zusatzspeicher teilweise kündbar, Aufbewahrung nach dem letzten Abo
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 08:19:29 +00:00
ClaudeandClaude Fable 5.1 e456c3de69 Übernahmegutschrift: Verrechnung nach Wechsel, Mail K09, Leitfaden, Admin zeigt das Abo, Tests
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-28 07:49:51 +00:00
ClaudeandClaude Opus 5.5 0c2e50fc20 Vertragsbedingungen Version 4: Webmail, Übersicht, Löschung bei Vertragsende, Hinweise zum Widerruf, Tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 20:45:29 +00:00
ClaudeandClaude Fable 5.1 6f7daf757f Datenschutz (Entwurf): Übermittlung an UptimeRobot, Bestellungen im Portal, Formulare, Tests
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-27 20:37:06 +00:00
ClaudeandClaude Fable 5.1 a2c1f0d81c Übernahmegutschrift und Leitfaden: für beide Abos (Entwurf)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-27 20:23:44 +00:00
ClaudeandClaude Fable 5.1 0098899ac6 Datenschutz (Entwurf): unsere Abos, Überwachung mit UptimeRobot
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-27 20:05:34 +00:00
ClaudeandClaude Opus 5.5 fead8fdd5a Vertragsbedingungen Version 4: Korrekturen aus der Prüfung (Widerrufsfrist, Kündigung, Bestellübersicht, Postfächer, AVV, § 19 UStG)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 19:41:22 +00:00
ClaudeandClaude Opus 5.5 f19187cc16 Vertragsbedingungen Version 4 (Entwurf): Hosting- und Wartungs-Abo, Postfächer, Zusatzspeicher, Wechsel; Fassung 3 archiviert
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 16:17:31 +00:00
ClaudeandClaude Opus 5.5 47c1af7015 Stripe: Testadresse STRIPE_API_BASE nur für 127.0.0.1/localhost
Ein verirrter Wert in Produktion kann den Live-Schlüssel so nie an einen
fremden Server schicken; getStripe() bricht mit klarer Meldung ab.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 15:46:26 +00:00
ClaudeandClaude Opus 5.5 2694ef18d6 Abo-Spiegel: fehlt ein neues Feld in Appwrite, wird ohne dieses Feld gespiegelt
Schützt Webhooks und den öffentlichen Kündigungs-/Widerrufsknopf, falls das
Setup-Skript erst nach dem Deploy läuft; der Fehler steht laut im Log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 15:45:54 +00:00
ClaudeandClaude Opus 5.5 dc61649228 Stundenkonto: Abos ohne bekannten Preis bekommen als Altbestand weiter ihre Stunde
Wie im Abo-Spiegel gelten Rechnungen ohne jeden bekannten Abo-Preis als
Wartung. Ein unbekannter Preis neben einem bekannten (z. B. Hosting) bringt
weiterhin keine Stunde.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 15:45:09 +00:00
ClaudeandClaude Opus 5.5 51fc2434e5 Stundenkonto: Arbeitszeit nur für bezahlte Wartungs-Monate, nicht für andere Abo-Rechnungen
Die Rechnung wird frisch geladen; eine Stunde bringt nur eine reguläre
(nicht anteilige) Wartungs-Zeile über 0 €. Preis-IDs werden einmal bei
Stripe nachgeschlagen und zwischengespeichert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 15:33:33 +00:00
ClaudeandClaude Opus 5.5 d097704d49 Abo-Spiegel: Produkt und tatsächlicher Preis aus den Stripe-Positionen
Neues Appwrite-Feld subscriptions.productKey (Setup-Skript). Ohne bekannten
Abo-Preis gilt ein Abo weiter als Wartungs-Abo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 15:31:56 +00:00
ClaudeandClaude Opus 5.5 54defb75c4 Tests: Stripe- und Appwrite-Nachbau im Testprozess
getStripe() nutzt in Tests über STRIPE_API_BASE den Nachbau auf 127.0.0.1;
in Produktion ist der Wert leer und nichts ändert sich.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 15:30:56 +00:00
ClaudeandClaude Opus 5.5 877fde7a6f Abo-Katalog: Wartung, Hosting und Zusatzspeicher als Produkte (noch ohne Verwendung)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 15:29:16 +00:00
ClaudeandClaude Opus 5.5 18c3cdf3e5 Automatische Mails im neuen Design (HTML mit Textfassung)
Alle 22 automatischen Mails gehen jetzt als HTML nach den Vorlagen aus
server/mail-templates raus, dazu eine aus dem HTML erzeugte Textfassung
(multipart/alternative). Werte werden HTML-sicher eingesetzt, optionale
Blöcke (WENN/ENDE) je nach Fall ein- oder ausgeblendet.

- Neu: services/mailTemplates.js (Vorlagen lesen, Platzhalter, Blöcke,
  Textfassung); mailer.js nimmt { template, values, blocks }.
- K11 "Passwort geändert" war nicht im Design-Export: aus den Bausteinen
  von K02 zusammengesetzt.
- T09 (Widerruf, intern): Fälle "kein Abo gefunden" und "Stripe-Kündigung
  fehlgeschlagen" ergänzt; bisher stand dort immer "auf Kündigung gesetzt".
- Einheitlich: Datum TT.MM.JJJJ, Beträge deutsch (T04 "50,00 €"),
  "WEBklar" statt "Webklar", Anrede mit Kundennamen, Team-Absender
  "WEBklar Kundenportal", Betreff T05 "Kündigung (Stripe)".
- Logo für die Mails: public/webklar-logo.png (192 px, aus dem Design-SVG).

Tests: 52 neue (jede Vorlage: Kopf, Platzhalter, Blöcke, Rendern,
Escaping, Textfassung), npm test 97/97 auf Node 20.19.5; alle 40 Auslöser
einmal durch den Server geschickt (Appwrite-Mock, Stripe-Double,
SMTP-Falle mit STARTTLS).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 14:37:50 +00:00
ClaudeandClaude Opus 5.5 32e441c8bc Abo-Angebote: Mail-Status in der Liste und E-Mail erneut senden
Bisher sah man nirgends, ob die Angebots-Mail rausging, Fehler landeten
nicht im Log, und senden ließ sie sich nur beim Anlegen.
- Angebotsliste: Kunden-Adresse unter dem Namen, im Status "E-Mail
  gesendet <Zeitpunkt>" bzw. "E-Mail nicht verschickt" / "Keine
  E-Mail-Adresse hinterlegt"
- Knopf "E-Mail senden" / "Erneut senden" mit Rückfrage (Adresse, letzter
  Versand), solange das Angebot offen und gültig ist; bei laufendem Abo,
  solange die erste rabattierte Abbuchung noch bevorsteht (die Mail
  nennt sie). POST /api/portal-admin/offers/:id/notify setzt notifiedAt.
- Server-Log: "[offers] Angebots-Mail <Ref> vom Mailserver angenommen:
  <Message-ID> 250 … queued as …" bzw. "… fehlgeschlagen: <Grund>"
- Lehnt der Mailserver nur den Kunden ab (die BCC-Kopie ans Team geht
  trotzdem raus), gilt die Mail als nicht verschickt
- sendCustomerMail gibt die nodemailer-Info zurück

Tests: npm test (40), Server-Durchlauf gegen Appwrite-Mock, SMTP-Sink
und Stripe-Double (28 Prüfungen), Oberfläche (18 Prüfungen).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 11:12:39 +00:00
ClaudeandClaude Opus 5.5 81119c19bc Kundenbereich: Passwort selbst ändern
Im Konto-Menü (Profilbild) gibt es unter "Konto" jetzt "Passwort
ändern". Die Seite fragt aktuelles Passwort, neues Passwort und
Wiederholung ab (mindestens 8 Zeichen, "Passwörter anzeigen"). Am
Handy ist sie eine Unterseite des Tabs, aus dem man kam; Direktlink
/dashboard.html#passwort. Im Ansichtsmodus ist sie gesperrt.

Server (POST /api/auth/password):
- Das aktuelle Passwort wird über eine kurze Appwrite-Session geprüft,
  die gleich wieder gelöscht wird. Tippfehler lösen nicht die globale
  Login-Sperre aus. Es gibt höchstens 5 Prüfungen je Kunde und Stunde,
  das bleibt unter Appwrites Grenze (10 Anmeldungen je E-Mail und
  Stunde).
- Das neue Passwort wird über die Users-API gesetzt. Fehler von
  Appwrite (zuletzt benutzt, zu häufig, persönliche Daten) kommen als
  verständliche Meldung.
- Die Klartext-Kopie in customers.portalPassword und ein Alt-Eintrag
  in den Notizen werden geleert. Ein selbst gewähltes Passwort wird
  nie im Klartext gespeichert; das Ticketsystem zeigt dann "–".
- Der Kunde bekommt eine Bestätigungsmail (Kopie an die Admins wie
  bei allen Kundenmails).

Andere Geräte werden abgemeldet: Kunden-Sessions merken sich beim
Login den Passwortstand (Appwrite passwordUpdate, pwv).
requireSession und /api/auth/me prüfen ihn, 60 s zwischengespeichert.
Das gilt auch, wenn wir im Ticketsystem ein neues Passwort setzen. Ist
Appwrite nicht erreichbar, bleibt die Session gültig. Sessions von
vor diesem Update haben keinen Stand und laufen normal aus (höchstens
7 Tage).

Login-Seite: Hinweis auf "Passwort ändern" statt "über das
Ticketsystem", dazu "Passwort vergessen?" mit support@webklar.com.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 09:22:37 +00:00
ClaudeandClaude Opus 5.5 054b04d5b6 Abo-Angebote: Admin sieht, bis wann der Rabatt läuft
"Gültig bis" ist nur die Frist zum Annehmen. Jetzt steht auch das
Rabattende da:
- Formular "Neues Angebot", Kunde ohne Abo: Schätzung "Rabatt läuft
  N Monate ab Abschluss und endet voraussichtlich zwischen <heute + N>
  und <gültig bis + N>", mit Hinweis auf den späteren Start nach der
  Widerrufsfrist (gut 2 Wochen)
- Formular, laufendes Abo: genaues Ende aus den nächsten Abbuchungen
  (Anker = Leistungsbeginn, Monatsende wie bei Stripe), auch in der
  Erfolgsmeldung
- Angebotsliste: offen -> Schätzung, aktiv -> "Rabatt endet am ..."
  aus dem Abo-Dokument (bzw. "endete", "endet mit dem Abo am ...",
  "unbekannt (Abo nicht gefunden)")

Rechnung in server/services/offerDiscount.js: Der Coupon deckt die
N Abbuchungen ab dem Anwenden. Beim Checkout ist das der Abo-Start, bei
laufendem Abo und Testkonto (Coupon per Webhook) der Zeitpunkt des
Anhängens; Testkonten laufen deshalb einen Monat länger.

Tests: npm test (37 Fälle, davon 8 neu).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 23:01:45 +00:00
ClaudeandClaude Opus 5.5 d5eb908cb6 Preview-Router: öffentliche Seiten überstehen Server-Neustart
Nach einem Neustart startet der Kundenbereich oft vor Appwrite. Bisher
lieferte getPublicSubdomains dann ein leeres Set, syncPreviewTls setzte
alle Preview-Hosts hinter die Login-Weiche (preview-chain) und wiederholte
das nie. Öffentliche Seiten wie anelia-wolf und emmas-schatzkiste waren
bis zum nächsten Deploy nur noch mit Login erreichbar bzw. 403.

- Antwortet Appwrite nicht, übernimmt syncPreviewTls die öffentlichen
  Seiten aus der zuletzt geschriebenen preview-hosts.yml. Neue Subdomains
  bleiben login-geschützt, ohne alte Datei ist alles geschützt.
- Beim Start wird der Abgleich alle 15 s wiederholt (max. 10 min), bis er
  mit Appwrite-Daten geklappt hat.
- Tests: Datei lesen, Abgleich mit/ohne Appwrite, Startup-Wiederholung.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 22:19:33 +00:00
ClaudeandClaude Opus 5.5 ba9916cfe6 Projektdetails und Fortschritt kundenverständlich
Der Server bereitet Commits, Tickets und Arbeitseinträge für Kunden auf
(server/services/customerProjectView.js), die Rohdaten bleiben intern:
- keine Co-Authored-By-/Signed-off-by-Zeilen und KI-Hinweise, keine
  Commit-Kürzel, Kontonamen, Git-Links oder Branch
- technische Commits (Preview-Config, Merges) ausgeblendet, bekannte
  Automatik-Texte übersetzt, "fix"/"upload" -> "Website aktualisiert"
- Ticketstatus und Arbeitsarten auf Deutsch (Open -> Eingegangen,
  Remote -> Online erledigt, ...), Fortschritt in 4 Schritten
- Akquise-Tickets auch in den Projektdetails verborgen
- /api/projects ohne Gitea-URL, Repo- und Vorlagennamen

Darstellung: Auftragskarte mit Status und Fortschrittsleiste, Zeitleiste
"Letzte Änderungen" nach Tagen, Arbeiten mit Farbe/Symbol je Art und
Arbeitszeit; der Tab "Fortschritt" nutzt dieselben Bausteine. In der
App-Ansicht öffnen sich die Projektdetails als eigene Seite mit Zurück
zu "Projekte".

Tests: npm test (node --test, 22 Fälle).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 18:46:22 +00:00