Commit Graph
57 Commits
Author SHA1 Message Date
ClaudeandClaude Sonnet 5.5 8e0d2b2736 Kundenansicht P5: gesammelte Widerrufsfristen (sammleFristen, GET /api/fristen)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-16 15:53:29 +00:00
ClaudeandClaude Sonnet 5.5 f2c9eb107a Kundenansicht neu: Dashboard-Weiche vor den statischen Dateien, Platzhalter-Seite
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-16 12:59:48 +00:00
knsoandClaude Opus 5.5 fd971309a8 Buchungskalender: origin/main (Aufträge) zusammenführen
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 15:46:31 +00:00
ClaudeandClaude Opus 5.5 8627ed1124 Aufträge: Router-Gerüste und Einbindung in server/index.js und Team-Router
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:08:37 +00:00
knsoandClaude Opus 5.5 a68baf10d9 Buchungskalender: Verdrahtung, Router-Gerüste und API-Vertrag
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:59:38 +00:00
ClaudeandClaude Opus 5.5 e87140e5ba Merge remote-tracking branch 'origin/main' into feature/oeffnungszeiten
Zusammenführung von TP2-Abschluss und Webshop (origin/main cab9c33) mit Öffnungszeiten live. Beide
Funktionen bleiben vollständig: jeder Konflikt ist als Vereinigung gelöst, Reihenfolge der Funktionsschlüssel
überall news, termine, shop, zeiten.

Konfliktdateien (28): public/app.js, dashboard.html, funktionen.js, widerrufen.html; scripts/stripe-products.mjs;
server/config.js, index.js, middleware/kundenansichtGuard.js, routes/abo.js, routes/admin/funktionenAdmin.js,
routes/funktionen.js, services/customerAdmin.js, customerViewLog.js, featureRegistry.js, retention.js,
siteFeatures.js, stripeBilling.js; test/customerViewLog, featureFreischaltung, featureRegistry, funktionenRoutes,
funktionenTermine, kundenansichtGuard, mailTemplates, publicForms, siteFeatures, stripeProductsScript (je
.test.js) und test/support/schema.js.

Entscheidungen: Mailvorlagen G01–G15, K01–K30, T01–T21 lückenlos (K24–K26 Webshop, K27–K30 Öffnungszeiten);
Stripe-Katalog mit shopSetup und zeitenSetup; Widerruf kennt shop und zeiten; ABO_FUNKTIONEN bleibt analyse
und termine (kein zeiten); activate() schreibt die Zeiten-Felder nur über extra; kein Halter von
feature-activate:<id> ruft disable() auf; die Aufbewahrungs-Löschung löscht Zeiten-Daten vor dem Abschalten und
hält den Kunden bei einem Fehler (held); die Admin-Antwort trägt ersatzTicket und warnung; Hash-Routen webshop
und zeiten, Ansichten view-webshop und view-zeiten; assertOwnProject behält die Meldung von main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 06:12:23 +00:00
ClaudeandClaude Opus 5.5 b8055b336c Shop J3: Tagesjob und Stundenjob, Löschfristen, Kundenlöschung
- shop/jobs.js: taeglicherJob (Käuferdaten bezahlter Bestellungen und Widerrufe 3 Jahre nach Ende des Bestelljahres anonymisieren, Grenze 1. Januar Berlin; unbezahlte/stornierte Bestellungen nach 30 Tagen löschen; Shops seit 90 Tagen disabled samt Artikeln, Bestellungen, Widerrufen, Bildern und shopConfig löschen, Funktionsdokument bleibt disabled mit Vermerk), seitenweise mit Deckel je Lauf, Schritte und Dokumente einzeln abgesichert; stuendlicherJob räumt nie beanspruchte Bilder auf
- shop/loeschen.js: gemeinsamer Baustein zum Löschen aller Daten eines Shops (Tagesjob und Löschfristen)
- shop/kundenLoeschung.js + customerAdmin.js: Kundenlöschung schaltet den Webshop ab (kunde_geloescht) und schließt die Shops
- retention.js: fällige Kunden verlieren auch ihre Shopdaten (vor den Abo-Dokumenten, bei Fehler held)
- server/index.js: Minuten- (75 s), Stunden- (130 s) und Tagesjob (200 s) registriert
- Tests: shopJobs.test.js, retention.test.js erweitert

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:15:20 +00:00
ClaudeandClaude Opus 5.5 eb616ddbe8 Shop H2: Standalone-Seiten GET /shop/:siteKey und /shop/:siteKey/widerruf mit neutraler Seite, Schutz-Headern und Route-Test
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:07:48 +00:00
ClaudeandClaude Opus 5.5 7464a4ef55 Shop D3: Connect-Webhook (account.updated, Checkout-Abschluss/Verwerfen, charge.refunded nachtragen)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:04:47 +00:00
ClaudeandClaude Opus 5.5 98d1e6613d Shop F1: öffentliche Schnittstelle zum Lesen (Konfiguration mit Artikeln, Artikelbilder, Grenzen, Formular-Token)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 08:54:06 +00:00
ClaudeandClaude Opus 5.5 83605975b0 Webshop B1: Anfrage-Dienst, Kundenroute /api/shop und Team-Mail T21
Anfrage stellen, zurückziehen und Stand lesen (ensureShopConfig, normalisiereAnfrage,
stelleAnfrage, zieheZurueck, anfrageAnsicht), Router /api/shop mit Rate-Limit 20/h und
Sperre in der Kundenansicht, Vorlage T21 Neue Webshop-Anfrage mit Tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 08:40:24 +00:00
ClaudeandClaude Opus 5.5 1d5a565e9f Merge feature/terminplaner-tp2 (a629b25) in feature/oeffnungszeiten
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 04:42:31 +00:00
ClaudeandClaude Opus 5.5 a198c472bd Öffnungszeiten: Feiertags-Erinnerung und Jobs
erinnereFeiertage(now): stündlich, nur bei Schalter pilot/on (pilot: nur
freigegebene Kunden) und nur 08:00 bis 20:00 Berliner Zeit; je Funktion in
setup/active zuerst der Merker sha1(featureId|datum) je Tag (409 = schon
erinnert), danach eine Mail K25 mit allen neuen Tagen ohne BCC ans Team;
Merker älter als 30 Tage werden gelöscht. zeitenAboJob (täglich) und
zeitenErinnerungsJob (stündlich) mit eigener Überlappsperre, ohne Wurf;
in server/index.js nach 240 s bzw. 300 s gestartet, mit unref.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 03:40:07 +00:00
ClaudeandClaude Sonnet 5.5 b20d0464c4 Rechtstexte: Dokument-Registry und Fassungskonstante des Terminplaners
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 02:24:42 +00:00
ClaudeandClaude Opus 5.5 d1f9176c99 Öffnungszeiten: öffentliche Route
GET /api/public/zeiten/v1/:siteKey mit CORS *, OPTIONS 204, 405, weichem ETag
ohne stand, Cache-Control max-age=60, Expose-Headers Date, Grenze 120 je Minute
und IP (zeiten/limits.js), 503 ohne Details und 404 für unbekannte Pfade.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 01:19:43 +00:00
ClaudeandClaude Opus 5.5 7bf2ad2665 Öffnungszeiten: Kundenschnittstelle zum Bearbeiten
GET/PUT /api/zeiten/:projectId und GET .../vorschau für den Editor im Portal.
Zugang nach Funktionszustand (ordered/setup/active lesen und speichern,
disabled mit Daten nur lesen), Version 0 vor dem ersten Speichern, 409
ZEITEN_VERALTET, 60 Speichervorgänge je Kunde und Stunde. Die Kundenansicht darf
speichern (Protokoll zeiten_gespeichert), den WhatsApp-Haken setzt nur der
Kunde selbst: bestaetigtAt kommt vom Server (R12), in der Kundenansicht 403.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 01:01:24 +00:00
ClaudeandClaude Sonnet 5.5 e3e198fb1a Terminplaner: Kunden-Schnittstelle
/api/termine: Einstellungen (Vorlage, PATCH mit Version, Feed-Link), Buchungen
(Liste, Zeiten, von Hand, Sperre, Aktionen), CSV-Export, Protokoll der
Kundenansicht. Pflichtangaben fuer Gaeste (Telefon immer, Anschrift bei
Widerrufsbelehrung) in normalisiereEinstellung, Entwurf aus Vorlagen,
kontextPerSiteKey ohne Pflichtangaben nicht buchbar; speichereEinstellung
nimmt eine Funktion unter der Sperre.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:43 +00:00
ClaudeandClaude Sonnet 5.5 2b0c05b8e9 Terminplaner: oeffentliche Schnittstelle v1 mit Missbrauchsschutz
Router /api/public/termine/v1 (config, tage, zeiten, buchungen, widerruf, Token-Seiten /termin/*, Kalender-Abo) mit
eigenem 16-KB-Parser und Fehlermiddleware, CORS nach Herkunft, Honeypot und Formular-Token, Grenzen je IP (IPv6 je /64),
siteKey und Adresse in limits.js, Mindestantwortzeit (TERMINE_MIN_ANTWORT_MS) und 10-Sekunden-Cache fuer tage/zeiten.
Vor dem globalen express.json eingehaengt; /api/public/ ist vom Kundenansicht-Waechter ausgenommen.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:43 +00:00
ClaudeandClaude Sonnet 5.5 43ac05aa06 Terminplaner: Jobs lesen abgeschaltete Funktionen vor dem Löschen neu, Tagesbericht im Log
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:43 +00:00
ClaudeandClaude Sonnet 5.5 485ff3bc15 Terminplaner: Hintergrund-Jobs
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:43 +00:00
ClaudeandClaude Opus 5.5 df8b952b81 Alte Mail-Links aufs Admin-Panel leiten ins Ticketsystem (Antrag direkt geoeffnet)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 04:05:17 +00:00
ClaudeandClaude Opus 5.5 7c00633db0 Portal: Admin-Panel, Rechnungsanalyse und alte Admin-Schnittstellen entfernt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 03:50:14 +00:00
ClaudeandClaude Opus 5.5 25f3c1df4d Kundenansicht: zentraler Waechter (2 h, Verwechslungsschutz, Schreibsperre ausser News)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 19:29:47 +00:00
ClaudeandClaude Opus 5.5 fdf594706d Kundenansicht: Protokoll-Collection customerViewLog mit Schreiben, Lesen und Loeschen nach 12 Monaten
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 19:25:26 +00:00
ClaudeandClaude Opus 5.5 772095ab19 Team-Eingang: /api/team mit Appwrite-JWT fuer alle Mitarbeiter, CORS-Header fuer Uploads
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 19:23:57 +00:00
ClaudeandClaude Opus 5.5 78170567b4 Analyse: alle Beendigungswege schalten den Messdienst ab (Kunde/Projekt weg, Domain, Löschfrist, Widerruf Wechsel)
Messdienst: POST /a/admin/sites/:key/off setzt active=0 und offSince einmalig; Portal-Client stopSite.
analyse.js: endAnalyse als gemeinsamer Kern, endAnalyseForCustomer, analyseOnProjectChanged,
analyseDisabled (Sperre/Löschfrist) und täglicher Abgleich runAnalyseReconcile (Projekt/Kunde weg,
Domains nachziehen, K18-Wiederholung, Messdienst für off/disabled, fehlende Entfernen-Tickets nachholen).
Entfernen-Ticket je Abschaltung gekennzeichnet (kein Doppelticket, auch wenn das Speichern der ID scheiterte).
Hooks: Kunde löschen, updateWebsiteProject, withdrawOrder (Wechsel), siteFeatures.disable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 18:50:36 +00:00
ClaudeandClaude Opus 5.5 ddb91a9950 Analyse: geprüfte Rechtstexte Fassung 2026-10-02 veröffentlichen (HTML, PDF, Zusatzseiten-Vorlage, Archiv)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 18:50:36 +00:00
ClaudeandClaude Sonnet 5.5 ef2ce49669 Finanzen: Start-Abruf nur bei altem Stand, unlesbare Buchungen ueberspringen, Mail bei Widerruf des Bankzugangs
I1: shouldRunStartupSync; der Abruf 2 Minuten nach dem Start entfaellt, wenn der letzte erfolgreiche
Abruf weniger als 5,5 Stunden her ist (Deployments verbrauchten das Tageslimit der Bank).
M4: eine unlesbare Buchung wird uebersprungen und gezaehlt, der Abruf endet ok.
M10: 401/403 beim Abruf sendet T18 einmal (Stufe 0 in warnedThresholds).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 15:42:06 +00:00
ClaudeandClaude Sonnet 5.5 6af9834293 Finanzen: Admin-Routen fuer Bankstatus, Abruf, Neuverbindung und Buchungen
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 15:42:06 +00:00
ClaudeandClaude Sonnet 5.5 7b35ed67a5 Finanzen: Warnung vor Ablauf des Bankzugangs (T18) und Abruf-Jobs
checkBankConsent mailt bei 30, 14, 3 Tagen und am Ablauftag (Berliner Kalendertage),
merkt sich die erreichten Stufen in warnedThresholds und holt eine nicht versandte
Mail beim naechsten Lauf nach. Jobs nur mit Enable Banking: Abruf nach 2 Minuten und
alle 6 Stunden, Pruefung nach 3 Minuten und taeglich.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 15:42:01 +00:00
ClaudeandClaude Sonnet 5.5 714687fe3b Website-Analyse: AVV als Seite, www/Apex-Domains, Abo-Check unabhängig vom Schalter, Dev-Hinweis
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 11:04:50 +00:00
ClaudeandClaude Sonnet 5.5 f4c8b291d7 Analyse: Routen fuer Portal und WOMS
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 10:19:37 +00:00
ClaudeandClaude Sonnet 5.5 f0eee196ed Analyse: Freischalten, Abschalten, Abo-Pruefung
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 10:10:39 +00:00
ClaudeandClaude Sonnet 5.5 b7cbe3aa38 fix(preview): Status bleibt bei Runner-Builds, dev-Label, Abgleich mit dem Runner, Längenkürzung
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 21:54:01 +00:00
ClaudeandClaude Sonnet 5.5 07bef6971c Preview: Admin-API und Modus-Vorgabe
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 21:54:01 +00:00
ClaudeandClaude Sonnet 5.5 1f1ffb5275 Projektarten: neue Repos erkennen und Zuordnungs-Mail senden
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 18:31:20 +00:00
ClaudeandClaude Sonnet 5.5 08958dee77 Projektarten: Services-Uebersicht fuer WOMS
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 18:30:53 +00:00
knsoandClaude Opus 5.5 035d1d5517 Einbau-Skript news.js für Kundenwebsites
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:16:37 +00:00
knsoandClaude Opus 5.5 319f8937aa News: Kunden-API und öffentliche Lese-API
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:49:39 +00:00
knsoandClaude Opus 5.5 0cc35bf1a5 Funktionen: Buchung per Stripe, Webhook, Mails und Freischalt-Job
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:33:48 +00:00
ClaudeandClaude Opus 5.5 a28ae21389 Push-Zeitmail: Bestätigungsseite /zeit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:41:57 +00:00
ClaudeandClaude Opus 5.5 0555a2274d Wechsel Ticketsystem → Projekt-Admin per Einmal-Link, Rückweg-Button
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 10:31:10 +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 35d98da977 Chat: Bilder, Kamerafoto, Dateien und Sprachnachrichten
- Kundenbereich und Admin-Chat: Bueroklammer-Menue (Bild, Kamera, Datei),
  Mikrofon fuer Sprachnachrichten, Vorschau vor dem Senden mit
  Upload-Fortschritt, Einfuegen (Strg+V) und Hineinziehen von Dateien
- Kamera: am Handy/Tablet die Kamera-App, am Rechner die Kamera im Browser
  mit Vorschau, Kamerawechsel und "Nochmal"
- Sprachnachricht: Aufnahme mit Zeit und Pegel, vorher anhoerbar oder
  direkt senden, hoechstens 5 Minuten
- Verlauf: Bilder (einzeln bzw. Raster, Grossansicht), Player fuer
  Sprachnachrichten, Datei-Kacheln mit Download
- Server: jede Datei einzeln roh hochgeladen (max. 25 MB, 10 je Nachricht,
  max. 3 gleichzeitig), Typ aus dem Inhalt, nur erlaubte Endungen, keine
  Programme; Ablage unter upload-data/chat/<Kunde>/ ausserhalb von public/,
  Auslieferung nur mit Login; Bilder, Audio und PDF inline, alles andere
  als Download (nosniff, CSP sandbox)
- Nicht gesendete Anhaenge werden nach 24 Stunden geloescht
- Benachrichtigungs-Mail nennt nur Art und Namen der Anhaenge
- Appwrite: neues Attribut portalMessages.attachments
  (scripts/setup-chat-collection.mjs, vor dem Deploy ausfuehren)
- Datenschutzerklaerung Abschnitt 6 ergaenzt (Stand 26.09.2026), PDF neu

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 14:01:17 +00:00
ClaudeandClaude Opus 5.5 48b13f4488 Abo: Uebernahmegutschrift fuer beim Altanbieter bezahlte Leistungen
- Kunde (Dashboard, nur mit laufendem Abo): Antrag mit Leistung, Anbieter,
  Domain, Rechnungsbetrag/-zeitraum, Grund, Rechnungsnachweis (PDF/JPG/PNG)
  und E-Mail fuer die Antwort; Eingangsbestaetigung per Mail, Status und
  Antwort auf Rueckfragen im Portal
- Admin-Mail mit Link admin.html?gutschrift=<id> (Login leitet zurueck)
- Admin-Tab "Gutschriften": Kunde und Vertrag, Nachweise, Verlauf,
  automatische Pruefungen (Duplikate per Datei-Hash/Domain, Abo, Zeitraum,
  DNS-Abgleich Nameserver/MX mit Anbieter), Pflicht-Checkliste, Rechner
  (tagesgenau anteilig), Genehmigen/Rueckfrage/Ablehnen mit Kundenmail
- Genehmigte Gutschrift als Stripe-Kundenguthaben (idempotent, Nachbuchen
  bei Stripe-Stoerung)
- Nachweise in upload-data/ (gitignored), Loeschung abgelehnter nach 6 Monaten
- Stundenkontingent auch fuer Monate, die ein Guthaben komplett deckt
  (invoice.total statt amount_paid)
- Datenschutzerklaerung Abschnitt 7 ergaenzt, PDF neu erzeugt
- Collection takeoverCredits in setup-abo-collections.mjs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 19:34:33 +00:00
ClaudeandClaude Opus 5.5 65429aa3ac Wartungs-Abo (50 EUR/Monat) ueber Stripe mit Stundenkonto im Portal
- Bestellung auf der Portal-Startseite: Zusammenfassung, AGB- und
  Vorab-Leistungs-Zustimmung, Button 'Zahlungspflichtig bestellen',
  danach Stripe Checkout (Abo, Kleinunternehmer-Fusszeile)
- Stripe-Webhook /api/abo/webhook spiegelt Abos nach Appwrite
  (subscriptions) und schreibt je bezahlter Rechnung 60 min gut
  (hourCredits, idempotent ueber Invoice-ID, 12 Monate gueltig)
- Stundenkonto: FIFO-Verbrauch aus Worksheets mit countsToPlan,
  15-Minuten-Takt, Mehraufwand separat ausgewiesen
- Stripe-Kundenportal fuer Zahlungsart/Rechnungen/Kuendigung
- Oeffentlicher Kuendigungsbutton (§ 312k) und Widerrufsbutton
  (§ 356a) mit Eingangsbestaetigung per Mail
- Abo-Bedingungen inkl. Leistungsbeschreibung und Widerrufsbelehrung,
  als Anhang der Vertragsbestaetigung

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 12:04:45 +00:00
knsoandClaude Fable 5 d4bd510dcd feat: Kundenportal-Ausbau - Tabs, Projekt-Einblicke, Git-Zeiterfassung, Rechnungen, Chat
Kunden-Dashboard:
- Tab-Navigation: Projekte | Was wurde gemacht | Rechnungen | Chat
- Projekt-Details pro Projekt: letzte Git-Commits (Titel+Beschreibung),
  Projektgroesse, Datei-Uebersicht (Top-Level aggregiert), Ticket-Arbeiten
- Rechnungen: gestylte Liste mit Status-Pillen, Ansehen/Zahlen-Link,
  PDF-Download ueber Server-Proxy (IDOR-geschuetzt)
- Chat mit dem Webklar-Team (Polling, Ungelesen-Badge, viewAs blockiert)

Admin-Dashboard:
- Chat-Tab: Konversationsliste + Thread + Antwortfeld, Ungelesen-Badge

Backend:
- giteaAdmin: getRepoInfo, listRepoCommits, getRepoTreeSummary
- projectInsights: 5-min-Cache, Invalidierung per Gitea-Webhook
- /api/projects/:id/git|files|work mit Ownership-Check (404)
- /api/chat/* (Kunde) + /api/portal-admin/chats/* (Admin), portalMessages-Collection
- mailer: E-Mail-Benachrichtigung an Admins bei Kundennachricht (15-min-Throttle)
- gitWorksheet: dd.mm.yyyy, voller Commit-Body, startTime leer (Zeit-Nachtrag),
  Auto-Webpage-Ticket bei Push auf Projekt ohne Ticket (ensureProjectTicket)
- customerActivity: Git-Push-Eintraege fuer Kunden sichtbar

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 18:01:24 +00:00
knsoandClaude Fable 5 177ee6a13d feat: Admin-Bereich im Kundenportal (Ticketsystem-Login, Projektsuche, Kundenverwaltung)
- Login: Appwrite-User mit Label 'admin' (Ticketsystem-Mitarbeiter) bekommen
  eine Admin-Session und landen auf /admin.html
- Admin-Dashboard: Statistik-Uebersicht, Projektsuche ueber alle Projekte
  (inkl. Preview-/Gitea-Links, Vorschau ohne Kunden-Login), Kundenliste mit
  Portal-Status, letztem Login und Projektanzahl
- Kundennummer (code) direkt im Admin-Bereich pflegbar
- 'Als Kunde ansehen': Admin sieht das Portal exakt wie der Kunde (Banner
  mit Rueckweg zur Admin-Uebersicht)
- Kunden-Dashboard: neue Bereiche 'Meine Rechnungen' (InvoiceNinja inkl.
  Link ins Rechnungsportal) und 'Was wurde gemacht' (Tickets + Worksheets
  aus dem Ticketsystem, ohne interne Akquise-Tickets); Kundennummer im Header
- Admin-API /api/portal-admin/* (Session-basiert), Kunden-API /api/invoices
  und /api/activity
- appwriteClient: uebrig gebliebene Debug-Instrumentierung entfernt

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 17:09:39 +00:00
knsoandClaude Fable 5 0320042045 fix: Gitea-Webhook akzeptiert HMAC-Signatur (X-Gitea-Signature)
Gitea sendet das Webhook-Secret als HMAC-SHA256-Signatur des Bodys, nicht als
Klartext-Header. Bisher liefen alle per Secret konfigurierten Repo-Hooks auf
401 - Push-Deploys funktionierten nur ueber ?token= in der URL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 16:49:49 +00:00
knsoandClaude Fable 5 cc57cf887a feat: HTTPS-TLS-Sync nach Deploy, Projekte ohne Subdomain, portalPassword-Feld
- previewDeploy.syncPreviewTls(): schreibt Traefik-Router (Host-Regeln) fuer alle
  Preview-Subdomains nach preview-hosts.yml, damit Let's Encrypt Zertifikate
  ausstellt. Laeuft nach jedem Deploy und beim Serverstart (ersetzt das nie
  aufgerufene bash-Script sync-preview-tls.sh).
- createProjectFromTemplate: Subdomain optional. Ohne Subdomain wird nur das
  Gitea-Repo angelegt (projectType 'repo', Status 'created'), kein Deploy.
- customerAdmin: Portal-Passwort liegt jetzt im Feld customers.portalPassword
  statt als __portalPassword__-Prefix in den Notizen; Legacy-Notizen werden
  beim naechsten Update bereinigt. CRM-Stufe (lead/customer) wird beim Setzen
  des Portal-Passworts nicht mehr auf 'active' ueberschrieben.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 16:34:23 +00:00