Files
Nexumi/docs/PHASE-TRACKING.md
TheOnlyMace 1eec10ba80 Implement ticket panel synchronization and configuration updates
- Added `panelChannelId` and `panelMessageId` fields to the `TicketConfig` model for managing ticket panel settings.
- Introduced `syncTicketPanel` function to handle posting and updating the ticket panel in Discord channels via BullMQ.
- Enhanced error handling for ticket panel synchronization, including specific error messages for missing categories and posting failures.
- Updated WebUI components to support panel channel selection and improved error messaging for synchronization issues.
- Added localization entries for new error messages related to ticket panel synchronization in both English and German.
- Refactored ticket category management to trigger panel synchronization upon category creation, update, or deletion.
2026-07-25 16:06:17 +02:00

23 KiB
Raw Blame History

Phase 6 WebUI-Fundament (Status: abgeschlossen, manuell bestätigt)

  • OAuth/Sessions, Settings-Framework, Layout, Modul-Toggles, Access-Rules
  • Login manuell bestätigt

Phase 7 WebUI Modul-Seiten + Owner-Panel (Status: abgeschlossen, manuell bestätigt)

Abgeschlossen

  • Alle Modul-Dashboard-Seiten, Commands-Seite, Overview-Aktivität
  • Owner-Panel (/owner: Übersicht, Guilds, Users, Flags, Presence, Team, Jobs, Changelog, Audit)
  • Prisma 20260722190000_phase7_owner, Shared Zod (dashboard.ts, owner.ts)
  • BullMQ WebUI↔Bot, Presence-/Wartungsmodus-Anbindung
  • Manuell bestätigt (User-Freigabe)

Phase 8 Landing, Status, Rechtsseiten (Status: abgeschlossen, manuell bestätigt)

Abgeschlossen

  • Landing /, Status /status, Rechtsseiten, Public APIs, Core-Commands, docs/verification.md
  • Manuell bestätigt (User-Freigabe)

Deploy-Branch (deploy) Traefik + Dashboard-Domain

Abgeschlossen (Code auf Branch deploy; main unverändert)

  • Traefik-Vollstack: Compose-Netz traefik-network (external) + internal
  • WebUI hinter Traefik: Host dashboard.nexumi.de, Entrypoint websecure, certresolver=letsencrypt
  • Host-Port 3000 entfernt; nur Traefik exponiert die WebUI
  • WEBUI_URL=https://dashboard.nexumi.de (OAuth-Callback: /api/auth/callback)
  • Marketing-Landing archiviert unter apps/webui/src/archived/landing-page.tsx
  • / zeigt Login; /login leitet auf / weiter (Query erhalten)
  • SPEC-Abweichung (bewusst): öffentliche Landing später extern auf nexumi.de; Dashboard unter Subdomain
  • Rechtsseiten vollständig (Impressum/Datenschutz/ToS) DE+EN; Locale per Accept-Language (Cookie hat Vorrang)
  • Plesk-Landing unter landingpage/ mit lokalen Rechtsseiten (impressum.php, datenschutz.php, nutzungsbedingungen.php)

Manuell testen (Deploy)

  • DNS dashboard.nexumi.de → Traefik-Host
  • Discord OAuth Redirect: https://dashboard.nexumi.de/api/auth/callback
  • docker compose up -d --build (Netz traefik-network muss existieren)
  • TLS-Zertifikat (Resolver-Name ggf. an Traefik anpassen)
  • Login / → Dashboard; Session-Cookie Secure

Post-Phase Premium + DSGVO (Status: implementiert, manuelle Tests offen)

Abgeschlossen (Code)

  • Premium: PremiumTierConfig, Guild-/User-Zuweisung, Owner-UI /owner/premium
  • Limits enforced (Tags/Feeds/Backups) in Bot + WebUI
  • DSGVO: /privacy, /gdpr delete confirm:true (Löschung/Anonymisierung + GdprDeletionLog)
  • Log-Retention: LoggingConfig.retentionDays + täglicher Job retention/purgeExpiredLogs
  • Snipe standardmäßig aus (GuildSettings.snipeEnabled, Toggle in Allgemeine Einstellungen)
  • Migration 20260722200000_premium_gdpr

Manuell testen

  • Owner /owner/premium: Limits speichern, Guild PREMIUM zuweisen
  • Free-Limit: mehr Tags/Feeds/Backups als Free-Cap → Fehler
  • /privacy und /gdpr delete confirm:true
  • Logging-Retention im Dashboard setzen
  • Snipe: default aus; nach Aktivierung in Einstellungen nutzbar

Bewusst offen

  • Musik- und KI-Modul (nur auf Zuruf)
  • Premium-Zahlungsanbindung
  • Externe Marketing-Landing auf nexumi.de

Post-Phase Dashboard-UI + Command-Palette + Landing-Polish (Status: implementiert)

Abgeschlossen (Code)

  • Guild-/Owner-Shell: Branding, Sticky-Header, mobile Sidebar-Sheet, Overview-Polish
  • Globale Cmd/Ctrl+K-Suche: Seiten, Slash-Commands, Einstellungsfelder (Deep-Links)
  • Settings-Feld-Registry + Form-Anchors; Commands-Seite liest ?q=
  • Plesk-Landing: Inter, Hero-Hierarchie, dezente Motion, Designsprache an WebUI

Manuell testen

  • Dashboard: Cmd/Ctrl+K → Seite, Command und Option navigieren (Hash-Scroll)
  • Mobile: Sidebar-Sheet + Such-Trigger
  • Overview und Owner-Panel Layout
  • Landing Light/Dark (prefers-color-scheme) + CTAs

Bewusst offen

  • Musik- und KI-Modul (nur auf Zuruf)
  • Premium-Zahlungsanbindung

Post-Phase Channel-Picker überall (Status: implementiert)

Abgeschlossen (Code)

  • DiscordChannelSelect / DiscordChannelMultiSelect + useGuildChannels
  • Alle Modul-Forms: Kanal-ID-Texteingaben durch durchsuchbare Channel-Auswahl ersetzt
  • Voice-/Category-Filter für TempVoice/Stats/Tickets

Post-Phase Role-Picker überall (Status: implementiert)

Abgeschlossen (Code)

  • DiscordRoleSelect / DiscordRoleMultiSelect + useGuildRoles
  • Modul-Forms/Manager: Rollen-ID-Texteingaben durch durchsuchbare Role-Auswahl ersetzt (Welcome, Verification, Leveling, Logging, Birthdays, Giveaways, Tags, Tickets, Access Rules, Feeds, Scheduler, Commands)
  • Selfroles: Role-Builder statt Textarea (roleId | label | emoji)

Manuell testen

  • Rollen in den Modul-Settings per Dropdown setzen und speichern
  • Multi-Select (Autoroles, No-XP-Roles, Support-Roles, …) speichert string[] korrekt
  • Access-Rules: Rolle wählen und Module zuweisen

Post-Phase Command-Global-Rules + Channel-Picker (Status: implementiert)

Abgeschlossen (Code)

  • Globale Command Channel-Whitelist/-Blacklist in GuildSettings + Commands-UI
  • Searchable Multi-Select für Kanäle/Rollen (statt Raw-IDs) auf der Commands-Seite
  • APIs: /commands/globals, /channels, /roles
  • Bot erzwingt globale + per-Command Channel/Role/Cooldown-Regeln in routeCommand
  • Migration 20260722210000_command_global_channels

Manuell testen

  • Commands: globale Whitelist/Blacklist speichern, in Discord prüfen
  • Per-Command Channel/Rollen per Dropdown setzen
  • Deaktivierter Command / Cooldown antwortet ephemeral

Post-Phase Discord Embed-Builder (Status: implementiert)

Abgeschlossen (Code)

  • Wiederverwendbare DiscordEmbedBuilder-Komponente inkl. Live-Vorschau
  • Basis: Titel, Beschreibung, Farbe
  • Erweitert: Author (Name/Icon/URL), Thumbnail, großes Bild, Footer (Text/Icon), Titel-URL, Timestamp
  • Welcome/Leave, Tags (EMBED) und Scheduler nutzen denselben Builder + buildEmbedFromPayload
  • Platzhalter in Text-/URL-Feldern inkl. {user.avatar} / {server.icon} (Welcome/Tags)

Manuell testen

  • Welcome/Leave-Embed mit Author, Thumbnail, Banner und Footer speichern und in Discord prüfen
  • Tag mit Antworttyp Embed (auch nur Bild/Author ohne Titel) erstellen/bearbeiten
  • Geplante Nachricht mit erweitertem Embed anlegen
  • Einfaches Embed (nur Titel/Beschreibung/Farbe) funktioniert weiter wie zuvor

Post-Phase Logging Multi-Event pro Kanal (Status: implementiert)

Abgeschlossen (Code)

  • Logging-UI: pro Log-Kanal mehrere Event-Typen per Multi-Select
  • Bestehende 1:1-Mappings werden beim Laden nach Kanal gruppiert; Speichern expandiert wieder auf LogChannel-Zeilen
  • Event-Typen sind exklusiv (DB @@unique([guildId, eventType])) Auswahl in einer Zeile entfernt sie aus anderen

Manuell testen

  • Mehrere Events einem Kanal zuweisen und speichern
  • Event von Kanal A nach Kanal B umhängen (verschwindet bei A)
  • Bot schreibt Logs der gewählten Events in den richtigen Kanal

Post-Phase Platzhalter-Hilfe (Status: implementiert)

Abgeschlossen (Code)

  • Aufklappbare PlaceholderHelp-Komponente mit Kopieren pro Token
  • Kontextspezifische Presets (Welcome, Tags, Birthdays, Leveling, TempVoice, Stats, Feeds, Scheduler)
  • Welcome-DM nutzt jetzt dieselben Platzhalter wie Welcome-Text (nicht nur {user})

Manuell testen

  • Welcome: Liste aufklappen, Platzhalter kopieren, in Embed/Text einfügen
  • Tags/Birthdays/Leveling/Stats/Feeds/Scheduler: nur die jeweiligen Tokens sichtbar

Post-Phase Components V2 (Status: implementiert, manuelle Tests offen)

Abgeschlossen (Code)

  • Shared Zod: MessageComponentsV2 + Actions, COMPONENTS_V2 für Welcome/Tags, Leave-Typen, custom_id cv2:{source}:{ref}:{actionId}
  • Prisma-Migration 20260722220000_components_v2: welcomeComponents/leaveType/leaveComponents, Tag.components, ScheduledMessage.components, ComponentMessageBinding
  • Bot: buildComponentsV2Payload, Anbindung Welcome/Leave/Tags/Scheduler, Interaction-Handler, Dashboard-Send-Queue messages/dashboardMessageSend
  • Slash: /embed builder + /embed components (Quick-V2)
  • WebUI: DiscordComponentsV2Builder, Mode-Switches Welcome/Tags/Scheduler, Dashboard-Seite /messages

Manuell testen

  • Welcome V2 mit Container + Thumbnail-Section + Link-Button + Toggle-Role-Button
  • Tag V2 mit String-Select → ephemeral reply
  • Scheduler V2 Ankündigung
  • Dashboard Messages: Embed + Components V2 senden
  • Slash /embed components
  • Bestehende Embeds unverändert
  • Migration anwenden (prisma migrate deploy) und Bot/WebUI neu bauen

Bewusst offen

  • Modal-only Components, File-Component, Premium-Buttons (nicht im MVP)
  • Pixelgenaue Discord-Vorschau im Dashboard

Post-Phase Harden (Sharding / Gates / Observability) (Status: implementiert)

Abgeschlossen (Code)

  • Confirmations (Moderation + Guildbackup) in Redis mit TTL statt Prozess-Map
  • Command-Registrierung einmal im Manager (Redis-Lock); Recurring Jobs einmal (Primary-Shard + Lock)
  • Modul-Toggles + FeatureFlags + User-/Guild-Blacklists im Bot erzwungen (routeCommand, Events, GuildCreate leave)
  • Moderation: Hierarchy-Checks, Duration vor Ban-Confirm, Timeout-Cap 28d, warn remove guild-scoped, atomare Case-Nummern, Temp-Ban Job-Dedup + UNBAN-Case, setDefaultMemberPermissions
  • Sentry (@sentry/node) in Bot + WebUI (instrumentation.ts); echte Prometheus-Metrics (/metrics)
  • Interaction-Registry statt if-Kette; Unit-Tests für Duration, Confirm-Store, Module-Gates, Metrics

Manuell testen

  • Ban mit Dauer: Confirm auf anderem Shard / nach Restart innerhalb TTL
  • Dashboard: Modul Moderation aus → /ban antwortet „Modul deaktiviert“
  • Owner: User-Blacklist → Interactions blockiert; Guild-Blacklist → Bot verlässt Server
  • /metrics mit Bearer-Token: Counters + Shard-Ping
  • Temp-Ban ablaufen → Unban + Case UNBAN

Bewusst offen

  • Musik- und KI-Modul (nur auf Zuruf)
  • Premium-Zahlungsanbindung
  • P4-UX (Server-Lock, Ban deleteMessageSeconds) bewusst nachgelagert

Post-Phase Verification Captcha-Anbieter + Alt-Erkennung (Status: implementiert)

Abgeschlossen (Code)

  • Captcha-Anbieter wählbar pro Guild: MATH, RECAPTCHA_V2, RECAPTCHA_V3, HCAPTCHA, TURNSTILE
  • Google/hCaptcha/Turnstile Keys in .env (WebUI); Dashboard zeigt nur konfigurierte Anbieter
  • Captcha-Seite /verify/captcha mit Provider-Widgets; Server-side Siteverify
  • Alt-Account-Erkennung: gesalzener IP-Hash (Captcha-Flow) + Invite-Cluster; optional blockieren via failAction
  • Prisma VerificationRecord + Config-Felder; Migration 20260723120000_verification_captcha_alt
  • Slash /verify setup: captcha_provider, alt_detection

Manuell testen

  • .env: RECAPTCHA_SITE_KEY/SECRET setzen → Dashboard zeigt reCAPTCHA v2/v3
  • Guild Captcha-Modus + Anbieter wählen → Verify-Button → WebUI Captcha → Rolle
  • Alt-Erkennung an: zweiter Account gleiche IP → Kick/Ban je nach failAction
  • Migration: prisma migrate deploy + Bot/WebUI neu bauen
  • CAPTCHA_IP_HASH_SALT gesetzt (min. 16 Zeichen), sonst keine IP-Alt-Signale

Bewusst offen

  • Kein Browser-Fingerprinting (DSGVO); IP nur gehasht mit Salt
  • Keine manuelle „Alt freigeben“-UI (nur Flag in VerificationRecord)

Post-Phase Leveling Rollen-Belohnungen UI (Status: implementiert)

Abgeschlossen (Code)

  • Dashboard Leveling: Level→Rolle-Belohnungen bearbeiten (Liste, speichern ersetzt LevelReward)
  • Shared Schema rewards + hasUniqueRewardLevels; i18n DE/EN
  • Stapel-Toggle mit Hinweis neben dem Belohnungs-Editor

Manuell testen

  • Belohnung hinzufügen (z. B. Level 5 → Rolle), speichern, Mitglied levelt → Rolle vergeben
  • Stack an/aus: stapeln vs. nur aktuelle Belohnungsrolle
  • Doppeltes Level → Fehlermeldung, speichern blockiert

Post-Phase Giveaway Bugs (Timestamp + End-Status) (Status: implementiert)

Abgeschlossen (Code)

  • Embed: Endzeit als Discord-Timestamp in der Description (Footer rendert <t:…> nicht)
  • /giveaway end wirft bei fehlender/bereits beendeter ID Fehler statt Fake-Erfolg
  • Dashboard „Jetzt beenden“ prüft endedAt nach Job; Timeout/Fehler → kein Erfolgs-Toast

Manuell testen

  • Neues Giveaway: Endzeit als „in X Stunden“ sichtbar, nicht als Roh-<t:…>
  • /giveaway end mit falscher ID → Fehlermeldung; mit korrekter ID → Reroll möglich
  • Dashboard „Jetzt beenden“ → Status beendet, Discord-Nachricht aktualisiert

Post-Phase Audit Remediation (Reliability + Security) (Status: implementiert)

Abgeschlossen (Code)

  • Scheduler: Self-Remove des aktiven Jobs entfernt; safeRemove für externe Cancels
  • Channel-Picker: Fehler/leere Responses nicht cachen; Error+Reload wie Rollen
  • requirePermission: Member- vs. Bot-Permissions getrennt; Defer auf Ban/Purge/Lock/Backup/Giveaway/Media/Translate
  • Giveaway: atomares End (updateMany), Pause cancel/reschedule, Dashboard Pause/Delete via BullMQ
  • Component-/Context-Gates: Maintenance + Modul-Toggle
  • Owner-Guild-Bypass ab SUPPORT; OAuth refresh_token + Session-Refresh
  • Queue safeRemove (Temp-Ban, Reminders, Selfroles); addJobAndAwait rethrowt Enqueue-Fehler
  • DefaultMemberPermissions für Admin-Commands; Cooldown erst nach erfolgreichem Execute
  • API: BadRequest/Upstream-Errors; Discord Roles/Channels 401/403/429/502

Manuell testen

  • One-shot Schedule sendet einmal (kein Doppel-Post nach Worker-Retry)
  • Channel-Dropdown bei API-Fehler: Retry statt permanent „Keine Treffer“
  • Giveaway Pause im Dashboard → Button disabled; Unpause → Timer weiter; End trotz Pause
  • Modul aus → Join-Button / Ticket-Panel antwortet „Modul deaktiviert“
  • VIEWER-Owner ohne Manage Guild: kein Dashboard-Guild-Zugriff; SUPPORT+: Bypass
  • Session nach Token-Ablauf refresht ohne erzwungenen Re-Login (mit gültigem refresh_token)

Post-Phase Giveaway End Fix + Role Picker (Status: implementiert)

Abgeschlossen (Code)

  • Root cause: endGiveaway removed its own locked BullMQ job → End-Job crashte vor DB-Update (Timer/UI/Command hingen)
  • cancelGiveawayJob nur noch außerhalb des Workers (Command/Dashboard); locked remove wird ignoriert
  • Dashboard-End nutzt eindeutige Job-IDs (giveaway-end-now-…); klarere 502-Fehler statt generischem 500
  • Bot-Start: recoverOverdueGiveaways beendet überfällige aktive Giveaways
  • Role-Picker: kein Cache von leeren/fehlerhaften Responses; Redis-Cache best-effort; manuelle Filter statt cmdk-Default

Manuell testen

  • Giveaway starten (kurz), warten bis Timer abläuft → Embed „Beendet“, Button weg, Gewinner gezogen
  • Giveaway vorzeitig per Dashboard „Jetzt beenden“ → kein Internal Server Error
  • /giveaway list → ID kopieren → /giveaway end id:… → Erfolg
  • Verifizierung: Rollen-Dropdown zeigt Serverrollen (nicht nur „Keine Treffer“)
  • Nach Deploy: bereits hängende Giveaways werden beim Bot-Start recovered

Post-Phase Starboard Verbesserungen (Status: implementiert)

Abgeschlossen (Code)

  • /starboard setup funktioniert trotz enabled: false (Gate-Ausnahme)
  • Kanal-Permission-Check vor Setup; /starboard status
  • Sync: Source-Delete/Bulk-Delete, Message-Edit, RemoveAll/RemoveEmoji
  • Race-sicheres Create + Recreate wenn Starboard-Msg fehlt
  • Zod/UI: Emoji bis 80 Zeichen, Threshold 1100, Channel Pflicht bei enabled, NSFW-Hinweis
  • Unit-Tests emojiMatches / shouldIgnoreMessage

Manuell testen

  • /starboard setup auf frischem Server ohne Dashboard-Toggle
  • Stern ≥ Schwelle → Post; unter Schwelle → Post entfernt
  • Original löschen/editieren → Starboard aktualisiert/entfernt
  • Dashboard: aktivieren ohne Kanal → Fehler

Post-Phase Welcome Embed Mentions + Autorole + Preview (Status: implementiert)

Abgeschlossen (Code)

  • Embed {user} in Titel/Author/Footer als Displayname (Discord resolved Mentions dort nicht)
  • Beschreibung/Content behalten <@id>-Mentions
  • Autorole: Rollen nachladen, managed/@everyone filtern, editable-Check, Warn-Logs bei Hierarchy/Permission
  • WebUI Embed-/Components-Vorschau: echte Session-User- + Guild-Daten statt Dummy @Alex

Manuell testen

  • Welcome-Embed Titel Welcome {user} → Anzeigename, nicht <@id>
  • Beschreibung {user} → klickbare Mention
  • User-Autorollen gesetzt, Bot-Rolle über Autorolle, Manage Roles → Rolle bei Join
  • Dashboard Welcome-Embed-Vorschau zeigt eigenen Namen/Avatar und Servername/-icon

Post-Phase Owner Guild-Liste Meta + Invite (Status: implementiert)

Abgeschlossen (Code)

  • Owner /owner/guilds: Discord-Name, Icon, Member-Count, ID (Live-Meta via Bot-Token, Redis-Cache)
  • Suche nach Name und ID
  • Aktion „Invite erstellen“ (Systemkanal zuerst, max. 24h / 5 Uses, Clipboard + Owner-Audit)

Manuell testen

  • Serverliste zeigt Name/Logo/Mitglieder statt nur ID
  • Suche nach Servername filtert
  • Invite erstellen → Link im Toast/Clipboard; Bot braucht Create Instant Invite

Post-Phase Owner Guild-Dashboard Bypass (Status: implementiert)

Abgeschlossen (Code)

  • Owner-Team (jede Owner-Rolle) kann jedes Guild-Dashboard öffnen, in dem der Bot installiert ist — ohne Discord „Server verwalten“
  • requireGuildAccess / Layout nutzen Owner-Bypass; Guild-Meta via Bot-API wenn nicht in OAuth-Liste
  • Owner /owner/guilds: Button „Dashboard öffnen“; Hinweisbanner im Guild-Dashboard bei Bypass

Manuell testen

  • Owner-UI → Server → Dashboard öffnen (Server, auf dem man kein Member/Manager ist)
  • Welcome/Settings speichern funktioniert; Banner „Owner-Zugriff“ sichtbar
  • Nicht-Owner ohne Manage Guild → weiterhin kein Zugriff

Post-Phase Owner Presence WebUI Polish (Status: implementiert)

Abgeschlossen (Code)

  • PresenceForm: Live-Vorschau, i18n-Enums, Zeichenzähler, Switch+Confirm für Wartung, Hinweise
  • Sofort-Apply: WebUI enqueued presenceRefresh nach Save
  • Wartungsmodus: Discord DND + Wartungstext (keine Rotation)
  • VIEWER read-only auf /owner/presence (Save nur ADMIN+)

Manuell testen

  • Status/Text speichern → Discord-Präsenz innerhalb weniger Sekunden
  • Rotierende Zeilen → Vorschau erste Zeile; Job rotiert weiter
  • Wartung an → Confirm, Discord zeigt Wartungstext, kein Rotating
  • VIEWER sieht Formular, kann nicht speichern

Post-Phase Owner About /about (Status: implementiert)

Abgeschlossen (Code)

  • Core-Command /about (neben SPEC-/info); Help-Katalog + Locales DE/EN
  • Prisma BotAboutConfig Singleton + Migration 20260724120000_bot_about
  • Owner /owner/about: TEXT / Embed / Components V2 (Builder), Redis-Cache, Audit
  • Components-V2-Source a für Button-Interaktionen aus /about

Manuell testen

  • Migration deploy + Bot/WebUI neu bauen
  • Owner About Embed speichern → /about zeigt Embed
  • About deaktivieren → Deaktiviert-Hinweis
  • /info unverändert technisch

Post-Phase Automod/Moderation Dashboard Ausbau (Status: implementiert)

Abgeschlossen (Code)

  • Automod: alle 10 Filterregeln im Dashboard (Aktion, Schwellen, Link-WL/BL, Wörter/Regex, Ausnahmen)
  • Lockdown an/aus enqueued activateLockdown / deactivateLockdown an den Bot
  • Anti-Raid-Aktion VERIFY (Unverified-Rolle) zusätzlich zu LOCKDOWN
  • Moderation: Warn-Tabelle + Case edit/delete im Dashboard
  • /lock /unlock Option server für guild-weiten Lock
  • Shared: AutomodRuleDashboardSchema, CaseUpdateDashboardSchema, AntiRaidAction inkl. VERIFY

Manuell testen

  • Automod: WORD_FILTER Wörter setzen, EXTERNAL_LINK Whitelist, Regel speichern → Filter greift
  • Lockdown-Toggle aus → Kanäle wieder beschreibbar
  • Anti-Raid VERIFY: Unverified-Rolle in Verification konfiguriert, Join-Welle → Rolle
  • Cases: Grund editieren / löschen; Warnings entfernen
  • /lock server:true und /unlock server:true

Post-Phase Selfroles WebUI → Discord Sync (Status: implementiert)

Abgeschlossen (Code)

  • Root cause: Dashboard speicherte Selfrole-Panels nur in Postgres, ohne BullMQ-Job an den Bot
  • Neue Queue selfroles mit Jobs selfRolePanelCreate / Update / Delete
  • WebUI wartet (bounded) auf Bot-Bestätigung; Panel hat danach messageId
  • Update zieht fehlende Discord-Nachricht nach (auch für Alt-Panels ohne messageId)
  • Roles-JSON { entries } wird im Dashboard korrekt gelesen

Manuell testen

  • WebUI: Panel erstellen → Embed/Buttons erscheinen im gewählten Channel
  • Panel editieren (Titel/Rollen) → Discord-Nachricht aktualisiert sich
  • Channel wechseln → alte Nachricht weg, neue im Zielkanal
  • Panel löschen → Discord-Nachricht entfernt
  • Alt-Panel ohne Message speichern → Nachricht wird nachgezogen

Post-Phase Selfroles Role-Builder (Status: implementiert)

Abgeschlossen (Code)

  • Textarea roleId | label | emoji durch zeilenbasierten Builder ersetzt
  • DiscordRoleSelect + Label/Beschreibung-Felder + DiscordEmojiSelect (Server-CDN + Unicode)
  • API GET /api/guilds/[guildId]/emojis inkl. Redis-Cache; Shared DiscordEmojiOption
  • Reaktions-Modus: Emoji je Rolle vor Save Pflicht
  • Emoji-Picker Discord-ähnlich: 9er-Grid, Kategorie-Sidebar, Vollsatz via @emoji-mart/data, Hautfarben, Suche

Manuell testen

  • Panel mit Role-Picker, Label, Server-Emoji und Unicode speichern → Discord-Nachricht korrekt
  • Dropdown: optionale Beschreibung erscheint in den Select-Optionen
  • REACTIONS ohne Emoji → Toast, kein Save
  • Bestehende Panels mit Custom-Emoji-Strings laden und editieren
  • Emoji-Picker: Kategorien scrollen, Suche, Hautfarbe, Server-Grid

Nächster geplanter Schritt

  • Deploy auf Traefik-Server manuell verifizieren; danach ggf. deploymain mergen (nur auf Freigabe).

Post-Phase Verification Panel aus WebUI (Status: implementiert)

Abgeschlossen (Code)

  • Root cause: Dashboard speicherte nur VerificationConfig, ohne Panel in Discord zu posten
  • Neuer BullMQ-Job verificationPanelSync (Queue verification); WebUI wartet bounded auf Bot-Bestätigung
  • syncVerificationPanel shared für /verify panel und Dashboard (Edit bei gleichem Kanal, sonst neu posten)
  • i18n DE/EN: Hinweis in Modul-Beschreibung + Fehlertexte bei Panel-Sync-Fail

Manuell testen

  • WebUI: Verifizierung aktivieren, Kanal + Rolle setzen, Speichern → Panel erscheint im Kanal
  • Speichern mit geändertem Modus → bestehendes Panel wird aktualisiert
  • Kanal wechseln und speichern → altes Panel weg, neues im Zielkanal
  • Bot ohne Send-Permission → Fehlermeldung; Config bleibt gespeichert, erneutes Speichern nach Fix

Post-Phase Ticket Panel aus WebUI + Kategorie-Emoji-Picker (Status: implementiert)

Abgeschlossen (Code)

  • Root cause: Dashboard speicherte Ticket-Config/Kategorien ohne Panel in Discord
  • Prisma TicketConfig.panelChannelId / panelMessageId; Migration 20260725160000_ticket_panel
  • BullMQ-Job ticketPanelSync (Queue tickets); Sync auch bei Kategorie create/update/delete
  • syncTicketPanel shared für /ticket panel_create und Dashboard; Custom-Emoji-Parsing für Buttons/Select
  • WebUI: Panel-Kanal-Picker; DiscordEmojiSelect in Kategorie-Erstellung und -Bearbeitung
  • Emoji-Zod max 80 (Custom-Emoji-Format)

Manuell testen

  • WebUI: Kategorie(n) anlegen, Panel-Kanal setzen, Speichern → Panel mit Buttons im Kanal
  • Kategorie mit Emoji-Picker (Unicode + Server-Emoji) speichern → Button zeigt Emoji
  • Kategorie ändern/löschen → Panel-Buttons aktualisieren sich
  • Panel-Kanal wechseln → altes Panel weg, neues im Zielkanal