No description
Find a file
Kundencenter 8243cdb111 feat(discord): Ticket-Befehle + saubere Rechtetrennung Kunde/Personal
Drei neue Slash-Befehle:
- /ticket (jeder verknüpfte Kunde): erstellt direkt ein neues Ticket
  samt zugehörigem privaten Thread, ganz ohne Web-Besuch.
- /zuweisen und /schliessen (nur Personal, nur innerhalb eines
  Ticket-Threads): weisen das Ticket des aktuellen Threads einer
  per Discord verknüpften Personal-Person zu bzw. schließen es.

Rechtetrennung (Kunden: nur eigenes Ticket erstellen/lesen, Personal:
mehr Rechte):
- Zuweisen/Schließen prüfen serverseitig ein verknüpftes
  Personal-Konto (kind='staff'), unabhängig von der separaten
  staffUserIds-Liste für /kc-status und /kc-kunde.
- Alle vier Personal-Befehle sind zusätzlich per
  setDefaultMemberPermissions(ManageThreads) so eingestellt, dass sie
  Kunden gar nicht erst in der Befehlsliste angezeigt werden (die
  serverseitige Prüfung bleibt trotzdem bestehen, das ist nur die
  UI-Sichtbarkeit).
- Bugfix dabei gefunden: eine Kundenantwort im Thread eines bereits
  geschlossenen Tickets hat es bisher unbemerkt wieder geöffnet (die
  Web-Oberfläche verhindert das schon lange). Jetzt wird das erkannt
  und die Antwort mit einem Hinweis abgelehnt, wie im Web.

Anleitung unter Einstellungen > Discord entsprechend ergänzt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 00:05:38 +02:00
apps feat(discord): Ticket-Befehle + saubere Rechtetrennung Kunde/Personal 2026-09-29 00:05:38 +02:00
bundles Stand vor Einführung des Nacht-Agenten 2026-09-27 00:51:32 +02:00
data Stand vor Einführung des Nacht-Agenten 2026-09-27 00:51:32 +02:00
docs Rechnungsmodul: Entwurf/Ausstellen/Bezahlt/Storno, PDF, Firmenstammdaten 2026-09-27 09:05:13 +02:00
migrations feat(mail): Begrüßungsmail mit Zugang, Produkten, Preisen und Discord 2026-09-28 23:50:53 +02:00
ops Nacht-Agent: automatische Bearbeitung von Plane-Tickets (Label agent) 2026-09-27 08:20:26 +02:00
packages feat(mail): Begrüßungsmail mit Zugang, Produkten, Preisen und Discord 2026-09-28 23:50:53 +02:00
.env.example Stand vor Einführung des Nacht-Agenten 2026-09-27 00:51:32 +02:00
.gitignore Build-Artefakt aus der Versionsverwaltung nehmen 2026-09-27 08:36:24 +02:00
package.json Stand vor Einführung des Nacht-Agenten 2026-09-27 00:51:32 +02:00
pnpm-lock.yaml feat: IMAP-Posteingang fürs Ticketsystem (Mail-Antworten -> Tickets) 2026-09-28 17:35:58 +02:00
pnpm-workspace.yaml Stand vor Einführung des Nacht-Agenten 2026-09-27 00:51:32 +02:00
README.md Rechnungsmodul: Entwurf/Ausstellen/Bezahlt/Storno, PDF, Firmenstammdaten 2026-09-27 09:05:13 +02:00
tsconfig.base.json Stand vor Einführung des Nacht-Agenten 2026-09-27 00:51:32 +02:00

Kundencenter

Modulares Kundencenter für Hosting, Server und Lizenzen (Modularer Monolith, TypeScript).

Prozess Pfad Port (nur 127.0.0.1) Aufgabe
kc-api apps/api 4100 Fastify-API (/v1/*), Module, Policy, Audit
kc-worker apps/worker 4102 (Health) Persistente Aufträge, Discord-Bot
kc-web apps/web 4101 Next.js-Oberfläche, Proxy /api/* → API

Stand (Grundsystem)

Login mit Passwort + TOTP, Wiederherstellungscodes, Sitzungsverwaltung, Passwort-Reset, Einladungen, Benutzerverwaltung (Mitarbeiterrollen), Kunden/Organisationen anlegen und verwalten, Rechnungsanschrift, Audit-Protokoll mit Hash-Kette, persistente Job-Queue, Discord-Bot (optional). Produkte (versioniert), Bestellungen mit Freigabe und unveränderlichem Preis-Snapshot, Verträge mit Kündigung/Verlängerung, Provisionierung über Connectoren (docs/produkte-bestellungen-vertraege.md), Connector-Framework (docs/connector-vertrag.md). Support-Tickets (je Kunde, mit internen Notizen für Personal, Dateianhänge als Bild/PDF, Discord-Benachrichtigung). Rechnungen (docs/rechnungen.md): Entwurf → Ausstellen (unveränderlich) → Bezahlt/Storno, PDF-Erzeugung, Firmenstammdaten unter Einstellungen → Firma. Noch nicht vorhanden: Zahlungsanbieter-Anbindung, automatische wiederkehrende Rechnungsstellung, E-Mail-Versand von Rechnungen, Selbstregistrierung, Plesk-Connector, Domain-Registrierung über eine Registrar-API (aktuell manuell über die Domain-Aufstellung).

Modularität

API-Module liegen in apps/api/src/modules/<name> und implementieren KcModule (core/module.ts). Sie werden in modules/index.ts eingetragen, registrieren Routen und Rechte und sprechen nur über core/* und Jobs miteinander. Neue Fähigkeiten (Connectoren, Rechnungen, Tickets) kommen als weitere Module hinzu.

Konfiguration

Geheimnisse liegen nicht im Repo, sondern in /etc/kundencenter/*.env (chmod 600): db.env, app.env, discord.env, optional SMTP in app.env. Vorlage: .env.example. Wichtig: KC_BASE_URL muss exakt der Browser-URL entsprechen (Origin-Prüfung gegen CSRF).

Betrieb

systemctl status kc-api kc-worker kc-web        # Dienste (Autostart, Restart=always)
journalctl -u kc-api -f                          # Logs
pnpm install && pnpm build                       # Update: danach chown -R kundencenter und systemctl restart kc-*
pnpm migrate                                     # Migrationen (migrations/*.sql, einmalig je Datei)
pnpm cli create-superadmin --email=… --name=… --password=…

Health: GET :4100/v1/health, GET :4100/v1/ready, GET :4102/health.

Tests

cd apps/api && pnpm test – Integrationstests gegen eine separate Datenbank kundencenter_test (wird bei jedem Lauf neu erstellt). Abgedeckt: Login, Sperre, CSRF, 2FA-Pflicht, Sitzungen, Kundenanlage, Mandantentrennung, Rechte, Audit-Kette/Maskierung.

Discord-Bot

In /etc/kundencenter/discord.env setzen: DISCORD_BOT_TOKEN, DISCORD_GUILD_ID, DISCORD_ADMIN_CHANNEL_ID, DISCORD_STAFF_USER_IDS (kommagetrennt), dann systemctl restart kc-worker. Befehle: /kc-status, /kc-kunde suche:<Text> (nur für freigegebene Discord-User, Antworten nur für sie sichtbar). In Kanäle gehen nur Ereignisse ohne personenbezogene Daten (z. B. „Neuer Kunde angelegt: K-10001“).

Backup / Restore (Datenbank)

set -a; . /etc/kundencenter/db.env; set +a
MYSQL_PWD=$DB_PASSWORD mysqldump -h127.0.0.1 -u$DB_USER --single-transaction --routines $DB_NAME | gzip > kundencenter-$(date +%F).sql.gz
gunzip -c kundencenter-DATUM.sql.gz | MYSQL_PWD=$DB_PASSWORD mysql -h127.0.0.1 -u$DB_USER $DB_NAME   # Restore in leere DB

Automatisiertes, verschlüsseltes Backup mit Restore-Test ist noch offen (siehe Plane).