18 KiB
Boilerplate-Abgleich: M26 — Tasks / Aufgaben
| Feld | Wert |
|---|---|
| Modul-ID | M26 |
| Name | Tasks / Aufgaben |
| Milestones | M071 (CRUD + Zuweisung), M072 (Listen pro Modul / Inline), M073 (Erinnerungen + Push + Email), M074 (Aufgaben-Sync ERP / KWP) |
| Block | Block 3 · Pflichtenheft §26 (26.1–26.10) |
| Spec | /Users/raffaelsheikh/Documents/GitHub/HiveGrid-Cloud/_bmad-output/specs/M26-tasks.md |
| Reuse-Level | low–medium (Querschnitt-Infrastruktur reif; das eigentliche Task-Domänen-Modell muss neu gebaut werden — RowTask deckt es NICHT ab) |
Boilerplate-Wurzel:
/Users/raffaelsheikh/Documents/GitHub/boilerplate(nur gelesen).
Kern-Befund (Anti-Erfindung)
In der Boilerplate existiert RowTask (prisma/schema/entityBuilder.prisma:434) — aber das ist NICHT das HiveGrid-Task-Modul. RowTask ist eine leichtgewichtige Checklisten-Sub-Entität, die fest an eine Entity-Builder-Row hängt (Mini-To-do im Row-Overview), vergleichbar mit RowComment/RowTag. Es fehlen die zentralen Eigenschaften aus der M26-Spec:
| M26-Anforderung | RowTask (Boilerplate) |
Lücke |
|---|---|---|
tenantId (direkt am Task, für Tenant-Scope-Filter + Indizes) |
fehlt (nur indirekt über row.tenantId) |
ja |
status Enum open|in_progress|done |
nur completed Boolean |
ja (kein In-Arbeit-Status) |
priority Enum low|normal|high|urgent |
fehlt | ja |
assigned_to_group_id (Gruppen-Zuweisung) |
nur assignedToUserId (Person) |
ja |
source Enum (manual|chat_message|form_submission|automation) + source_ref JSON |
fehlt | ja |
linked_entity_type / linked_entity_id (polymorphe Verknüpfung zu Contact/Company/Lead/Deal/Project) |
fehlt — Bindung ist hart an rowId einer Entity-Builder-Row |
ja (Architektur-Unterschied) |
archived_at (Auto-Archivierung) |
fehlt | ja |
deadline_at |
vorhanden (deadline DateTime?) |
nein |
completed_at / completed_by_user_id |
vorhanden (completedAt, completedByUserId) |
nein |
created_by_user_id |
vorhanden (createdByUserId) |
nein |
TaskWatcher (M:N) |
fehlt | ja |
| Reminder-Notifications / Auto-Archivierungs-Cron | fehlt | ja |
tasks.*-Permissions (read_own/read_all/write/admin) + Owner-Check + 404-statt-403 |
fehlt | ja |
Konsequenz: RowTask (Modell + UI RowTasks.tsx + Service rowTasks.db.server.ts) ist als Vorlage/Muster wertvoll (Felder, Service-Layer-Struktur, Event-DTOs, i18n-Keys, Toggle-UI), aber nicht 1:1 übernehmbar. Das HiveGrid-Task-Modell ist eine eigenständige Entität in prisma/schema/app.prisma, kein Anhängsel an Entity-Builder-Rows.
Übernehmbar aus Boilerplate
| Boilerplate-Pfad | Was | Wie nutzbar |
|---|---|---|
prisma/schema/entityBuilder.prisma:434 (model RowTask) |
Felder-Inspiration für das neue Task-Modell (title, description, completed/completedAt/completedByUserId, assignedToUserId, deadline, createdByUserId) |
als-vorlage — Feld-Set übernehmen, aber um tenantId/status/priority/group/source/linked_entity/archived erweitern |
apps/web/app/utils/db/entities/rowTasks.db.server.ts |
Service-Layer-Muster: get*/create/update*/delete*/getAll* mit include-Pattern, getAllRowTasks({ completed, assignedOrCreatedUserId, tenantId }) (Owner-/Filter-Logik) |
als-vorlage — Repository-Struktur + „assigned OR created"-Owner-Filter direkt übertragbar (entspricht Owner-Check der M26-Spec) |
apps/web/app/components/entities/rows/RowTasks.tsx |
UI-Muster: Toggle-Erledigen, Quick-Add (nur Titel), Inline-Delete mit canDelete-Permission-Gate, Empty-State, i18n-Keys (shared.addTask, shared.noTasks, models.rowTask.plural) |
als-vorlage — passt zum „Inline-Aufgaben-Bereich" (M072) + Quick-Add (Block E.1); in HiveGrid via Subframe-Adapter neu zu bauen, Logik-Muster übernehmbar |
apps/web/app/modules/events/dtos/RowTasks{Created,Updated,Deleted}Dto.ts + apps/web/app/modules/events/utils/EventUtils.ts (Cases row.tasks.created/updated/deleted) |
Event-/Activity-DTO-Muster + Klartext-Übersetzung pro Event-Typ | als-vorlage — Vorlage für M26-Activity-Typen (task_created/assigned/completed/reopened/deadline_changed/priority_changed/archived, Block G) |
prisma/schema/notifications.prisma (NotificationDelivery, UserNotificationPreference, DeviceToken) |
Vollständiges Notification-Datenmodell: In-App + Email + Push (APNs/FCM/WebPush), Per-Channel/Category-Präferenzen, @@unique([tenantId, userId, channel, sourceKey]) (Dedup) |
1:1 — direkt für M073 Reminder-Versand nutzbar (Empfänger = Assignee/Group/Watcher) |
packages/db/src/notifications.server.ts |
Notifications-Repository: createNotificationDelivery, markNotificationDeliveryStatus, upsertUserNotificationPreference, getUserNotificationPreferences, getNotificationStreamSnapshot, redactNotificationDiagnosticText; Typen NotificationPreferenceChannel/...DeliveryStatus |
1:1 — Schreib-/Lese-Fläche für Reminder-Deliveries + User-Toggle „Task-Erinnerungen" (M073, Block F.1) |
apps/web/app/modules/notifications/services/.server/NotificationService.ts |
Versand-Service (Novu-Integration, send, sendToRoles, Channel→Category-Mapping, Skipped-Delivery-Tracking, withNotificationQueue) |
anpassen — als notify()-Backend (INTEGRATION-CONTRACTS §7) für Task-Reminder; Bündelung (max 1/4h) muss ergänzt werden |
apps/worker/src/jobs/dsgvo-grace-cron.ts |
Cron-Job-Vorlage: BullMQ upsertJobScheduler (keine Doppel-Schedules bei Re-Deploy), 24h-Kadenz, host-agnostische Dependency-Injection (listOverdue… + enqueue… + logger), idempotent |
als-vorlage — Blaupause für (a) Reminder-Cron 24h-vor/bei/+24h und (b) Auto-Archivierungs-Cron done + completedAt <= now-30d (M073, Block F.2) |
apps/worker/src/jobs/email-sequence-scheduler.ts, outbox-done-retention-cron.ts, workflow-execution-stalled-reconciler-cron.ts |
Weitere reife Cron-Beispiele (Scheduler-Pattern, Retention-Sweep) | als-vorlage — Retention-Sweep = direktes Muster für Auto-Archivierung |
packages/db/src/outbox.ts (publishOutboxEvent) + prisma/schema/outbox.prisma (OutboxEvent) |
Transaktionales Outbox: Side-Effects (Reminder-Schedule, Activity, ERP-Push) atomar mit DB-Write; dispatchKey @unique (Idempotenz), scheduledAt, priority |
1:1 — Pflicht-Muster für alle Task-Side-Effects; scheduledAt deckt die 24h-Reminder-Zeitpunkte ab |
prisma/schema/permissions.prisma (Role, Permission, RolePermission, UserRole, Group, GroupUser) |
RBAC-Fundament inkl. Group/GroupUser |
1:1 — Group/GroupUser deckt assigned_to_group_id + Owner-Check „Mitglied der zugewiesenen Gruppe" (Block H) ab; tasks.*-Permissions als neue Permission-Einträge |
packages/db/src/client.server.ts, transactions.server.ts |
DB-Client (getDbClient/getReadDbClient/getExtendedDbClient), runDbTransaction |
1:1 — Fundament für alle Task-Repositories; Read-Replica für Listen-Views |
packages/db/src/dsgvo/user-fk-map.ts |
Zentrale User-FK-Karte (Test bricht CI bei fehlendem Eintrag) | anpassen (Pflicht) — neue Task-FKs (createdByUserId, assignedToUserId, completedByUserId) + TaskWatcher.userId müssen hier eingetragen werden |
prisma/schema/appsEngine.prisma (App, DataConnection, AppSyncRun, AppSyncRunLog, AppSyncItem) |
Integrations-/Sync-Engine: pro-Tenant App (@@unique([tenantId, type])), verschlüsselte DataConnection-Credentials, Sync-Run mit Status/Modus/Metriken, AppSyncItem mit sourceId/destinationId-Mapping + rolledBackData/rolledBackAt |
anpassen — Fundament für M074 KWP-Aufgaben-Sync: Source↔Destination-ID-Brücke (KWP-Email-Identifikation), Sync-Modi (manual/scheduled/webhook), Rollback. Sync-Modi A/B/C („KWP gewinnt") sind als Config-/Konfliktregel zu ergänzen |
@toolctrl/view-models (packages/view-models/src/index.ts) |
VMState<T>, ActionCallbacks, I18nLabel, assertI18nLabel, SidebarRegistryItem/RegistryGate |
1:1 — View-Model-Vertrag (INTEGRATION-CONTRACTS §11) für Task-Listen/Detail; i18n-Key-Zwang |
@toolctrl/ui-app (createSidebarRegistry, EmptyPage, generateA11yTest) |
Sidebar-Registry-Factory + a11y-Test-Template | 1:1 — Sidebar-Eintrag „Aufgaben" (Gruppe arbeiten) + a11y-Gate |
apps/web/app/components/ui/tables/* (TableSimple, TablePagination, ColumnSelector, RowsLoadMoreCard), components/ui/multi-select.tsx, calendar.tsx, command.tsx, modals/*, emptyState, loaders |
shadcn/Radix-Komponentenbibliothek: Tabelle + Cursor-Pagination („Mehr laden"), Multi-Select-Filter, Date-Picker, Modale, Empty/Loading-States | als-vorlage — deckt fast alle UI-Elemente aus Block C/D ab (Filter, Bulk-Checkboxes, Pagination, Quick-Actions); in HiveGrid via Subframe-Adapter |
apps/web/app/application/sidebar/* + apps/web/app/components/layouts/sidebars/shadcn/* |
Datengetriebene Sidebar mit Permission-/Feature-Gating, App-Shell (AppLayout/ShadcnSidebarLayout), Breadcrumb-Header |
als-vorlage — Muster für HiveGrid-sidebar.config.ts + Breadcrumb (INTEGRATION-CONTRACTS §1/§4) |
packages/i18n + apps/web/app/locale/* |
i18next + SSR (de/en), formatRelativeTime/formatDate |
1:1 — Deadline-Anzeige „relativ wenn ≤7 Tage" (Block C) + alle Klartext-Texte (Block I/F) als i18n-Keys |
prisma/schema/featureFlags.prisma + FeatureFlag-Layer |
Feature-Flags (scope tenant/user, Targeting) | 1:1 — DoD-Pflicht „Modul ohne Deploy abschaltbar"; pro-Tenant ERP-Sync-Aktivierung (M074) |
prisma/schema/core.prisma (AuditEvent, Hash-Kette) + packages/db/src/audit-hash.ts |
Tamper-evidenter Audit-Trail | 1:1 — DoD-Audit-Wiring (INTEGRATION-CONTRACTS §6); ERP-Sync-Konflikt-Markierung im Audit (M074) |
Vorhandene Daten-Modelle (konkret)
Direkt wiederverwendbar (1:1 / Querschnitt):
prisma/schema/permissions.prisma—Group,GroupUser(Gruppen-Zuweisung + Owner-Check),Permission/Role/RolePermission/UserRole(RBAC fürtasks.*).prisma/schema/notifications.prisma—NotificationDelivery,UserNotificationPreference,DeviceToken(M073 Reminder In-App/Email/Push).prisma/schema/outbox.prisma—OutboxEvent(atomare Side-Effects +scheduledAtfür Reminder-Timing).prisma/schema/core.prisma—AuditEvent(Audit-Querschnitt),FileObject(falls Attachments später).prisma/schema/accounts.prisma—User,Tenant,TenantUser(Identity/Scope-Anker).prisma/schema/featureFlags.prisma—FeatureFlag(Abschaltbarkeit + ERP-Sync-Toggle).
Vorlage / nahe verwandt, aber nicht das Task-Modell:
prisma/schema/entityBuilder.prisma:434—RowTask(Checklisten-Sub-Entität anRow; Feld-Vorlage, nicht die HiveGrid-Task).
Sync-Fundament (M074):
prisma/schema/appsEngine.prisma—App,DataConnection,AppSyncRun,AppSyncRunLog,AppSyncItem(ID-Brücke + Rollback für KWP-Aufgaben-Sync). Konkrete KWP-Sync-Foundation (M089–M095) ist Vorbedingung und liegt außerhalb dieses Moduls.
Platzhalter für Neu-Modelle:
prisma/schema/app.prisma— leerer Platzhalter (// custom database models), vorgesehener Ort fürTask+TaskWatcher(+ ggf.TaskSyncLinkfür M074).
Lücken / komplett neu zu bauen
Task-Prisma-Modell (neu, inapp.prisma): alle Felder aus Block A inkl.tenantId,status-Enum,priority-Enum,source/source_ref,linked_entity_type/linked_entity_id(polymorph),archived_at,assigned_to_group_id. Plus die 4 Indizes aus Spec Block A. Plus die Constraints (oneOf Assignee, completed-Felder nur beidone, Reset beidone→open).TaskWatcher-Modell (neu, M:N User↔Task) — existiert nirgends.tasks.*-Permissions + Bundle-Mapping (Block H):tasks.read_own/read_all/write/adminals neuePermission-Einträge + Owner-Check-Logik (Assignee OR Group-Member OR Creator OR Watcher) + 404-statt-403. Muss neu (RBAC-Fundament vorhanden, Keys nicht).- Listen-View mit Server-Side-Filter (Block C): Scope-Presets (
mine/created_by_me/all), Multi-Select-Filter (Status/Priorität/Quelle/Verknüpfungs-Typ), Date-Range mit Presets, Volltext-Suche (Titel+Beschreibung), Sortierung, Bulk-Actions, Cursor-Pagination. UI-Primitives vorhanden, die Verdrahtung + VM-Builder neu. - Detail-View mit Inline-Edit (Block D): Markdown-Editor, Assignee-Picker (Person ↔ Group umschaltbar), Entity-Picker (Auto-Complete Contact/Company/Lead/Deal/Project), Status-Wechsler, Duplizieren, Watcher-Verwaltung, Aktivitätsstrom. Neu.
- Polymorphe Entity-Verknüpfung + Embed-Anzeige (Block B/C, M072): Tasks-Tab/Section in Contact/Company/Lead/Deal/Project-Detail-Views mit Pre-Fill.
RowTask-Modell kann das architektonisch NICHT (hart an Entity-Builder-Row) — neu zu bauen. - Erstellungs-Quellen-Integration (Block E, M072): „Mark as Task" aus Team-Chat (M110–M114), Form-Action „Aufgabe erstellen" (M121–M125), Automation-Action (M075–M082). Abhängig von Modulen, die teils noch nicht existieren. Quell-DTO-Muster aus
events/dtos/RowTasks*als Vorlage. - Reminder-Logik (M073, Block F.1): Cron 24h-vor/bei/+24h, Empfänger-Auflösung (Assignee/Group-Members/Watcher), Anti-Spam-Bündelung max 1/4h pro User (Bündelung im NotificationService NICHT vorhanden — neu), Email-Eskalation bei +24h. Cron-Pattern + Notification-Layer vorhanden, Domänen-Logik neu.
- Auto-Archivierung (M073, Block F.2): täglicher Cron
status=done AND completed_at<=now-30d AND archived_at IS NULL → archived_at=now(). Cron-Vorlage vorhanden, Job neu. - Activity-Typen (Block G, M045): 7 Task-Activity-Typen mit
related_entity_refs(Task-Activity erscheint im Stream der verknüpften Entität). DTO-/Übersetzungs-Muster ausRowTasks*Dtoals Vorlage;@hivegrid/activity-logActivity-Wiring neu. - ERP-Aufgaben-Sync M074 (Pflichtenheft 26.10, [N11]): Per-Mandant/Per-Adapter aktivierbar, Sync-Modi A/B/C („KWP gewinnt"), Identifikations-Brücke (KWP-Box: Email), KWP-Badge, Sync-Status im Detail, Anti-Endlosschleife, Aushebel-Schutz.
appsEngine-Schema liefert ID-Brücke + Rollback-Run; Konflikt-Auflösung soll M093 wiederverwenden (Vorbedingung). Task-spezifische Mapping-Schicht neu. - i18n-Key-Set für alle Klartext-Texte (Block I + F + Permission-Tooltips) — neu (Pattern + Infra vorhanden).
- Sidebar-Eintrag + Route in HiveGrid-Targets (
packages/ui-hivegrid/src/app-shell/sidebar.config.ts, Gruppearbeiten) — die HiveGrid-Pakete (packages/ui-hivegrid,@hivegrid/*) existieren in der Boilerplate nicht; nur das@toolctrl/*-Äquivalent als Vorlage.
Empfohlenes Vorgehen
Phase A — Fundament (M071), zuerst aus BP übernehmen:
Task+TaskWatcherinprisma/schema/app.prismamodellieren (Felder-VorlageRowTask, erweitert um Block-A-Felder;Group/GroupUserfür Gruppen-Zuweisung wiederverwenden). Forward-Only-Migration mit Inverse-SQL.- Pflicht: neue User-FKs in
packages/db/src/dsgvo/user-fk-map.tsergänzen (sonst CI-Block). - Repository-Layer nach Muster
rowTasks.db.server.tsbauen (get*/create/update/delete/getAll+ Owner-Filter „assigned OR created OR watcher OR group-member"). DB-Client +runDbTransaction1:1 aus@toolctrl/db. tasks.*-Permissions + Bundle-Mapping (Block H) auf RBAC-Fundament; Owner-Check + 404-statt-403.- VM-Builder + Listen-/Detail-View über
@toolctrl/view-models+ shadcn-Tabellen/Modale/Picker (als-vorlage); Sidebar-Eintrag „Aufgaben" (Gruppearbeiten) via Registry-Factory; Quick-Add/Toggle-Logik ausRowTasks.tsx.
Phase B — Embed + Quellen (M072):
6. Polymorphe Verknüpfung + Tasks-Section in Entity-Detail-Views (neu); Pre-Fill bei „Aufgabe anlegen".
7. Quellen-Integration (Chat/Form/Automation) — DTO-Muster events/dtos/RowTasks* übernehmen; abhängig von M110–M114 / M121–M125 / M075–M082.
8. Activity-Typen (Block G) via logActivity + Outbox.
Phase C — Reminder & Archivierung (M073):
9. Reminder-Cron + Auto-Archivierungs-Cron als BullMQ-upsertJobScheduler-Jobs nach Vorlage dsgvo-grace-cron.ts / outbox-done-retention-cron.ts (host-agnostisch, idempotent).
10. Versand über notify()/NotificationService + notifications.server.ts (1:1); Empfänger-Auflösung + Anti-Spam-Bündelung (max 1/4h) neu ergänzen; User-Toggle über UserNotificationPreference.
Phase D — ERP-Sync (M074), zuletzt:
11. Auf appsEngine (App/DataConnection/AppSyncRun/AppSyncItem) aufsetzen; KWP-Email-Identifikations-Brücke (sourceId/destinationId), Sync-Modi A/B/C + Konflikt-Regel (M093 wiederverwenden), KWP-Badge + Sync-Status im Detail, Anti-Endlosschleife (markierte Sync-Herkunft löst keinen Rück-Push aus), Aushebel-Schutz. Vorbedingung: KWP-Sync-Foundation M089–M095.
Querschnitt durchgängig (DoD): Outbox für alle Side-Effects, Audit automatisch (M001), Feature-Flag pro Modul, i18n-Keys statt Klartext, View-Model-Trennung (keine Prisma-Imports in UI-Paket), Smoke-Test + Hot-Swap-Drill + Visual-Snapshot.
Hinweise / Vorbehalte
RowTask≠ HiveGrid-Task. WerRowTask1:1 übernimmt, baut am Datenmodell vorbei (kein tenantId/status/priority/group/source/linked_entity/archived/watcher). Nur als Feld-/Service-/UI-Vorlage verwenden.- HiveGrid-Target-Pfade existieren nicht in der BP.
packages/ui-hivegrid,@hivegrid/activity,@hivegrid/notifications,@hivegrid/audit,packages/entitlements/src/permissions.ts(HiveGrid-Variante) sind Soll-Zustand laut INTEGRATION-CONTRACTS; die BP liefert nur die@toolctrl/*-Äquivalente als Muster. - Bündelung (max 1/4h pro User) ist im vorhandenen NotificationService nicht implementiert — eigene Window-Logik nötig (M073-Erfolgskriterium).
@toolctrl/ui-subframeist leer (Stub). Der Subframe-Adapter-Layer ist nicht gebaut; HiveGrid muss diese Grenze selbst füllen (MEMORY: „Subframe mandatory for all routes").- M074 hängt an externer Foundation (M089–M095 KWP-Sync, M008–M010 Apps-Engine).
appsEngine-Schema ist das Fundament, die KWP-spezifischen Adapter/Konfliktregeln liegen außerhalb von M26.