Files
CapaKraken/plan.md
T
Hartmut 093e13b88f feat: project cover art with AI generation, branding rename, RBAC fix, computation graph
- Add DALL-E cover art generation for projects (Azure OpenAI + standard OpenAI)
- CoverArtSection component with generate/upload/remove/focus-point controls
- Client-side image compression (10MB input → WebP/JPEG, max 1920px)
- DALL-E settings in admin panel (deployment, endpoint, API key)
- MCP assistant tools for cover art (generate_project_cover, remove_project_cover)
- Rename "Planarchy" → "plANARCHY" across all UI-facing text (13 files)
- Fix hardcoded canEdit={true} on project detail page — now checks user role
- Computation graph visualization (2D/3D) for calculation rules
- OG image and OpenGraph metadata

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-03-18 11:31:56 +01:00

18 KiB

Enterprise Notification & Task Management System

Anforderungsanalyse

Was wird gebaut?

Ein mehrstufiges Notification- und Task-Management-System, das die bestehende Notification-Infrastruktur (Prisma-Model, Bell-Icon, SSE, SMTP) zu einem vollwertigen Enterprise-System ausbaut. Vier Kernfähigkeiten:

  1. Personal Reminders — User legen eigene Erinnerungen an (Datum/Zeit, optionale Wiederholung, verknüpft mit Entity)
  2. Targeted Notifications — Admins/Manager senden Notifications an User, Rollen, Projektbeteiligte, OrgUnits
  3. Task Management — Actionable Tasks mit Status-Tracking, Dashboard-Widget, Entity-Verknüpfung
  4. AI Assistant Integration — Assistent liest offene Tasks, führt sie aus (Urlaub genehmigen, Allokation erstellen, etc.)

Bestehende Infrastruktur (wiederverwendbar)

Komponente Status Datei
Notification Prisma-Model Vorhanden (einfach) packages/db/prisma/schema.prisma:1291
Notification tRPC-Router list, unreadCount, markRead, create packages/api/src/router/notification.ts
NotificationBell + Drawer Bell-Icon mit Badge, Dropdown-Panel apps/web/src/components/notifications/NotificationBell.tsx
SSE EventBus (Redis Pub/Sub) NOTIFICATION_CREATED Event packages/api/src/sse/event-bus.ts
SMTP Email sendEmail() + SystemSettings packages/api/src/lib/email.ts
AI Assistant Tools list_notifications, mark_notification_read packages/api/src/router/assistant-tools.ts
Dashboard Widget-Registry 8 Widgets, Pattern etabliert apps/web/src/components/dashboard/widgets/

Betroffene Pakete

  • packages/db — Schema-Erweiterung (Notification -> Task-Felder, neues Broadcast-Model)
  • packages/shared — Enums, Typen, Zod-Schemas
  • packages/api — Router-Erweiterung (notification.ts, assistant-tools.ts), Targeting-Logik, Scheduler
  • apps/web — UI (Task-Widget, Reminder-UI, Notification-Center, Admin-Panel)

Datenmodell-Design

Erweiterung des bestehenden Notification-Models

Das bestehende Model wird um Task-/Reminder-/Targeting-Felder erweitert. Kein neues Model nötig — ein einheitliches System für Notifications + Tasks + Reminders.

model Notification {
  id         String    @id @default(cuid())
  userId     String

  // -- Typ & Kategorie --
  category   NotificationCategory @default(NOTIFICATION)  // NEU
  type       String               // z.B. "VACATION_REQUESTED", "TASK_ASSIGNED", "REMINDER"
  priority   NotificationPriority @default(NORMAL)         // NEU

  // -- Inhalt --
  title      String
  body       String?
  entityId   String?
  entityType String?
  link       String?              // NEU: Deep-Link zur relevanten Seite

  // -- Task-Felder (nur fuer category TASK / APPROVAL) --
  taskStatus   TaskStatus?        // NEU: OPEN / IN_PROGRESS / DONE / DISMISSED
  taskAction   String?            // NEU: maschinenlesbare Aktion z.B. "approve_vacation:clxyz123"
  assigneeId   String?            // NEU: wem der Task zugewiesen ist
  dueDate      DateTime?          // NEU: Faelligkeitsdatum
  completedAt  DateTime?          // NEU: Zeitpunkt der Erledigung
  completedBy  String?            // NEU: wer hat erledigt (User-ID, oder "ai-assistant")

  // -- Reminder-Felder --
  remindAt     DateTime?          // NEU: wann soll erinnert werden
  recurrence   String?            // NEU: "daily" | "weekly" | "monthly" | null
  nextRemindAt DateTime?          // NEU: naechster Erinnerungszeitpunkt (berechnet)

  // -- Targeting-Metadaten (fuer Bulk-Sends) --
  sourceId     String?            // NEU: Referenz auf die urspruengliche Broadcast-Nachricht
  senderId     String?            // NEU: wer hat die Notification erstellt (User-ID)
  channel      String  @default("in_app") // NEU: "in_app" | "email" | "both"

  // -- Timestamps --
  readAt     DateTime?
  createdAt  DateTime  @default(now())
  updatedAt  DateTime  @updatedAt       // NEU

  user     User  @relation(fields: [userId], references: [id], onDelete: Cascade)
  assignee User? @relation("taskAssignee", fields: [assigneeId], references: [id])
  sender   User? @relation("notificationSender", fields: [senderId], references: [id])

  @@index([userId, readAt])
  @@index([userId, category, taskStatus])           // NEU: Task-Queries
  @@index([nextRemindAt])                            // NEU: Reminder-Scheduler
  @@index([assigneeId, taskStatus])                  // NEU: Assigned-Tasks
  @@map("notifications")
}

enum NotificationCategory {
  NOTIFICATION  // System/Admin-Benachrichtigung (read-only)
  REMINDER      // Persoenliche Erinnerung (self-created)
  TASK          // Actionable Task mit Status-Tracking
  APPROVAL      // Genehmigungsworkflow (approve/reject)
}

enum NotificationPriority {
  LOW
  NORMAL
  HIGH
  URGENT
}

enum TaskStatus {
  OPEN
  IN_PROGRESS
  DONE
  DISMISSED
}

Broadcast-Model (fuer Gruppen-Notifications)

model NotificationBroadcast {
  id            String   @id @default(cuid())
  senderId      String
  title         String
  body          String?
  link          String?
  category      NotificationCategory @default(NOTIFICATION)
  priority      NotificationPriority @default(NORMAL)
  channel       String   @default("in_app")

  // -- Targeting --
  targetType    String   // "user" | "role" | "project" | "orgUnit" | "all"
  targetValue   String?  // Role-Name, Project-ID, OrgUnit-ID, oder null fuer "all"

  // -- Scheduling --
  scheduledAt   DateTime?  // null = sofort
  sentAt        DateTime?
  recipientCount Int @default(0)

  createdAt     DateTime @default(now())

  sender User @relation(fields: [senderId], references: [id])

  @@index([senderId])
  @@index([scheduledAt, sentAt])
  @@map("notification_broadcasts")
}

Task-Action Registry (Enterprise-Pattern)

Maschinenlesbare Aktionen ermoeglichen dem AI-Assistenten, Tasks direkt zu erledigen:

// packages/api/src/lib/task-actions.ts
const TASK_ACTION_REGISTRY: Record<string, TaskActionHandler> = {
  "approve_vacation":  { permission: "manageVacations",    execute: ... },
  "reject_vacation":   { permission: "manageVacations",    execute: ... },
  "fill_demand":       { permission: "manageAllocations",  execute: ... },
  "confirm_allocation":{ permission: "manageAllocations",  execute: ... },
  "review_budget":     { permission: "manageProjects",     execute: ... },
};

Format: "action_name:entity_id" — einfach parsbar, erweiterbar.


Betroffene Pakete & Dateien

Paket Dateien Art
packages/db prisma/schema.prisma edit — Notification erweitern, Enums, Broadcast-Model
packages/shared src/types/notification.ts create — Typen, Enums, Zod-Schemas
packages/shared src/types/enums.ts edit — re-exportieren
packages/api src/router/notification.ts edit — Task-CRUD, Reminder-CRUD, Broadcast, Targeting
packages/api src/router/index.ts edit — ggf. neuen Router registrieren
packages/api src/router/assistant-tools.ts edit — neue Tools: list_tasks, execute_task_action, etc.
packages/api src/router/assistant.ts edit — TOOL_PERMISSION_MAP + System-Prompt
packages/api src/sse/event-bus.ts edit — neue Event-Types
packages/api src/lib/email.ts edit — Notification-Email-Templates
packages/api src/lib/notification-targeting.ts create — Recipient-Aufloesung
packages/api src/lib/task-actions.ts create — Action-Registry
packages/api src/lib/reminder-scheduler.ts create — Reminder-Dispatcher
apps/web src/components/notifications/NotificationBell.tsx edit — Tabs, Task-Badge
apps/web src/components/notifications/NotificationCenter.tsx create — Full-Page
apps/web src/components/notifications/ReminderModal.tsx create
apps/web src/components/notifications/BroadcastModal.tsx create
apps/web src/components/notifications/TaskCard.tsx create
apps/web src/components/dashboard/widgets/TaskWidget.tsx create
apps/web src/app/(app)/notifications/page.tsx create
apps/web src/app/(app)/admin/notifications/page.tsx create
apps/web src/components/layout/AppShell.tsx edit — Nav-Links
apps/web src/hooks/useTimelineSSE.ts edit — Task-Events

Task-Liste (atomare Schritte)

Phase N.1 — Datenmodell & Shared Types

  • Task 1: Shared-Typen erstellen -> packages/shared/src/types/notification.ts

    • NotificationCategory, NotificationPriority, TaskStatus Enums
    • CreateReminderSchema, CreateBroadcastSchema, UpdateTaskStatusSchema (Zod)
    • TaskAction Interface
  • Task 2: Prisma-Schema erweitern -> packages/db/prisma/schema.prisma

    • Notification-Model: category, priority, taskStatus, taskAction, assigneeId, dueDate, completedAt, completedBy, remindAt, recurrence, nextRemindAt, sourceId, senderId, channel, link, updatedAt
    • Enums: NotificationCategory, NotificationPriority, TaskStatus
    • Model: NotificationBroadcast
    • User-Relations: taskAssignee, notificationSender, broadcasts
    • Indexes: [userId, category, taskStatus], [nextRemindAt], [assigneeId, taskStatus]
  • Task 3: pnpm db:push + Dev-Server neu starten

Phase N.2 — API: Router + Targeting + Scheduler

  • Task 4: SSE Event-Types erweitern -> packages/api/src/sse/event-bus.ts

    • TASK_ASSIGNED, TASK_COMPLETED, TASK_STATUS_CHANGED, REMINDER_DUE, BROADCAST_SENT
    • Emit-Helper: emitTaskAssigned(), emitTaskCompleted(), emitReminderDue()
  • Task 5: Notification-Router erweitern -> packages/api/src/router/notification.ts

    • list: Filter nach category, taskStatus, priority
    • listTasks (protectedProcedure): offene Tasks + zugewiesene Tasks
    • taskCounts (protectedProcedure): Counts nach Status
    • updateTaskStatus (protectedProcedure): OPEN->IN_PROGRESS->DONE/DISMISSED
    • createReminder (protectedProcedure): eigene Erinnerung anlegen
    • updateReminder / deleteReminder (protectedProcedure)
    • createBroadcast (managerProcedure): Targeted Notification an Gruppe
    • listBroadcasts (managerProcedure)
    • createTask (managerProcedure): Task fuer User/Gruppe
    • assignTask (managerProcedure): Task zuweisen
    • delete (protectedProcedure): eigene Notifications loeschen
  • Task 6: Broadcast-Targeting -> packages/api/src/lib/notification-targeting.ts (create)

    • resolveRecipients(targetType, targetValue, db): User-IDs aufloesen
      • "user" -> einzelner User
      • "role" -> alle User mit SystemRole
      • "project" -> Ressourcen mit aktiver Allokation -> verknuepfte User
      • "orgUnit" -> Ressourcen in OrgUnit -> verknuepfte User
      • "all" -> alle aktiven User
  • Task 7: Email-Templates -> packages/api/src/lib/email.ts (edit)

    • sendNotificationEmail(userId, notification): HTML mit Title, Body, Deep-Link
    • sendTaskEmail(userId, task): Template mit Task-Details + Action-Link
  • Task 8: Task-Action-Registry -> packages/api/src/lib/task-actions.ts (create)

    • Registry-Pattern: action_name -> { permission, execute(entityId, ctx) }
    • Initiale Actions: approve_vacation, reject_vacation, fill_demand, confirm_allocation
  • Task 9: Reminder-Scheduler -> packages/api/src/lib/reminder-scheduler.ts (create)

    • Intervall (60s): WHERE nextRemindAt <= NOW()
    • Fuer jeden faelligen Reminder: In-App Notification + optional Email
    • nextRemindAt neu berechnen oder null setzen
    • Catch-up bei Start (ueberfaellige sofort ausloesen)

Phase N.3 — AI Assistant Integration

  • Task 10: Neue Tool-Definitionen -> packages/api/src/router/assistant-tools.ts

    • list_tasks: offene Tasks/Approvals mit Filter
    • get_task_detail: Details inkl. verknuepfter Entity
    • update_task_status: Status aendern
    • execute_task_action: maschinenlesbare Aktion ausfuehren
    • create_reminder: Erinnerung anlegen
    • create_task_for_user: Task fuer anderen User (Manager-only)
    • send_broadcast: Notification an Gruppe (Manager-only)
  • Task 11: Tool-Executors implementieren -> packages/api/src/router/assistant-tools.ts

    • execute_task_action: parst taskAction-String, dispatcht an Action-Registry
    • Permission-Check pro Action (nicht pauschal)
  • Task 12: Permission-Map + Prompt -> packages/api/src/router/assistant.ts

    • TOOL_PERMISSION_MAP erweitern
    • System-Prompt: Tasks/Reminders als Faehigkeit beschreiben

Phase N.4 — Frontend

  • Task 13: NotificationBell erweitern -> apps/web/src/components/notifications/NotificationBell.tsx

    • Zweiter Badge: Task-Count (orange) neben Notification-Count (rot)
    • Tabs: "Alle" | "Tasks" | "Erinnerungen"
    • Task-Items mit Quick-Actions (Done/Dismiss)
    • Link zu "/notifications"
  • Task 14: TaskCard-Komponente -> apps/web/src/components/notifications/TaskCard.tsx (create)

    • Titel, Body, Due-Date, Priority-Badge, Entity-Link
    • Aktionen: "Start" / "Done" / "Dismiss"
    • Approval-Variante: "Approve" / "Reject"
    • Priority-farbcodiert (URGENT=rot, HIGH=orange, NORMAL=blau, LOW=grau)
  • Task 15: ReminderModal -> apps/web/src/components/notifications/ReminderModal.tsx (create)

    • Titel, Body, Datum/Uhrzeit, Wiederholung (keine/taeglich/woechentlich/monatlich)
    • Optional: Entity-Verknuepfung (Projekt/Ressource Dropdown)
  • Task 16: BroadcastModal -> apps/web/src/components/notifications/BroadcastModal.tsx (create)

    • Manager/Admin-only
    • Targeting: Dropdown (Alle/Rolle/Projekt/OrgUnit) + Wert-Auswahl
    • Inhalt: Titel, Body, Priority, Kategorie
    • Kanal: In-App / Email / Beides
    • Scheduling: Sofort / Zeitgesteuert
    • Vorschau: "Wird an X Empfaenger gesendet"
  • Task 17: NotificationCenter -> apps/web/src/app/(app)/notifications/page.tsx (create)

    • Tabs: Alle | Notifications | Tasks | Reminders | Approvals
    • Filter: Status, Priority, Zeitraum
    • Bulk: "Alle lesen", "Alle erledigt"
    • "Neue Erinnerung" Button
  • Task 18: TaskWidget -> apps/web/src/components/dashboard/widgets/TaskWidget.tsx (create)

    • Kompakte Liste offener Tasks (max 5-7)
    • Sortiert: Priority -> Due-Date
    • Quick-Actions: Done/Dismiss
    • Footer: "X offene Tasks — Alle anzeigen"
    • In Widget-Registry eintragen
  • Task 19: Admin Broadcast-Seite -> apps/web/src/app/(app)/admin/notifications/page.tsx (create)

    • Liste gesendeter Broadcasts
    • "Neue Benachrichtigung senden" Button
    • Statistiken: gesendet/gelesen pro Broadcast
  • Task 20: AppShell Navigation -> apps/web/src/components/layout/AppShell.tsx (edit)

    • "Notifications" fuer alle Rollen
    • "Broadcast" unter Admin (ADMIN/MANAGER)
  • Task 21: SSE-Hook -> apps/web/src/hooks/useTimelineSSE.ts (edit)

    • Auf TASK_ASSIGNED, TASK_COMPLETED, REMINDER_DUE reagieren
    • React-Query invalidieren: notification.listTasks, notification.taskCounts

Phase N.5 — Auto-Tasks & Audit

  • Task 22: Automatische Task-Erzeugung bei Business-Events

    • vacation.create -> Task "Urlaubsantrag genehmigen" an Manager (APPROVAL)
    • Ueberallokation -> Task "Ueberallokation aufloesen" an Manager
    • Projekt-Deadline < 30 Tage + offene Demands -> Task "Demands besetzen"
    • demand.create -> Task "Demand besetzen" an Manager
  • Task 23: Audit-Trail -> packages/api/src/lib/audit.ts (create)

    • logTaskAction(taskId, userId, action, details)
    • completedBy: "ai-assistant" fuer AI-erledigte Tasks

Abhaengigkeiten

Task 1 (Shared Types) ---+
Task 2 (Schema) ---------+--> Task 3 (db:push)
                          |
Task 3 --> Task 4 (SSE)  |
Task 3 --> Task 5 (Router)|
Task 3 --> Task 6 (Targeting)
Task 3 --> Task 7 (Email) |
Task 3 --> Task 8 (Actions)|
                          |
Task 5 + 6 --> Task 9 (Scheduler)
Task 5 + 8 --> Task 10-12 (AI)
                          |
Task 5 --> Task 13-21 (Frontend, parallel moeglich)
Task 5 --> Task 22 (Auto-Tasks)

Parallel:

  • Task 4 + 5 + 6 + 7 + 8 (verschiedene Dateien)
  • Task 13-21 (verschiedene Dateien, 13+14 vor 17+18 empfohlen)

Sequentiell:

  • Task 1 -> 2 -> 3 (Schema)
  • Task 5 -> 10 -> 11 (Router -> Tools -> Executors)

Akzeptanzkriterien

  • pnpm db:push ohne Fehler
  • pnpm --filter @planarchy/api exec tsc --noEmit — 0 Errors
  • pnpm --filter @planarchy/web exec tsc --noEmit — 0 Errors
  • pnpm test:unit — alle Tests gruen
  • User kann eigene Erinnerung anlegen (Datum, Wiederholung, Entity)
  • Admin/Manager kann Broadcast an Rolle/Projekt/OrgUnit senden
  • Broadcast erzeugt individuelle Notifications pro Empfaenger
  • Tasks im Dashboard-Widget, sortiert nach Priority + Due-Date
  • Task-Status aenderbar ueber UI (Open -> In Progress -> Done/Dismissed)
  • AI-Assistent kann list_tasks aufrufen und offene Tasks anzeigen
  • AI-Assistent kann execute_task_action ausfuehren (z.B. Urlaub genehmigen)
  • Erledigte Tasks zeigen completedBy (User oder "AI-Assistent")
  • Email-Versand bei channel "email" oder "both"
  • SSE-Events invalidieren React-Query-Caches
  • Reminder-Scheduler erzeugt puenktlich Notifications
  • RBAC: User sehen nur eigene; Manager zugewiesene; Admin Broadcasts

Risiken & offene Fragen

Risiken

  1. Reminder-Scheduler Zuverlaessigkeit: Node.js-setInterval kann bei Restart verpassen. Mitigation: Catch-up bei Start (alle ueberfaelligen sofort ausloesen).
  2. Broadcast-Skalierung: "An alle" mit 500 Usern = 500 Rows. Mitigation: Batch-Insert (createMany).
  3. Task-Action-Sicherheit: Permissions pro Action pruefen, nicht pauschal. Mitigation: Action-Registry mit Permission pro Handler.
  4. Schema-Migration: Neue Felder nullable oder mit Default -> bestehende Notifications funktionieren weiter.

Offene Fragen

  1. Scheduler: setInterval im SSE-Handler oder separater Worker/Cron? Empfehlung: setInterval (reicht fuer <1000 User)
  2. Task-Delegation: User duerfen Tasks an andere weiterdelegieren? Empfehlung: Ja (Manager-only)
  3. Retention: Wie lange alte Notifications aufbewahren? Empfehlung: 90 Tage Auto-Cleanup
  4. Recurring Tasks: Tasks wiederkehrend wie Reminders? Empfehlung: Phase 2
  5. Approval-Chains: Mehrstufige Genehmigung? Empfehlung: Phase 2, erstmal einstufig