Files
HiveGrid-Wireframes/hivegrid-cloud/docs/INTEGRATION-CONTRACTS.md
T

11 KiB

HiveGrid Integration-Contracts

Zweck: Verbindliche Docking-Points, an denen jedes neue Modul anschließt. Wenn ein AI-Coding-Agent eine Funktion baut, ohne sie hier anzudocken, ist die Funktion nicht erreichbar und das Milestone gilt als nicht erledigt.

Diese Datei ist Quelle der Wahrheit für: Sidebar-Gruppen, Route-Patterns, Breadcrumbs, Permissions, Search-Index, Activity-Stream, Audit, i18n.

Naming-/Pfad-Realität (Stand 2026-06-04, siehe docs/ARCHITECTURE-DECISIONS.md AD-10): Das HiveGrid-UI-Paket heißt real packages/ui-app (nicht packages/ui-hivegrid). Die Sidebar-Konfiguration liegt in apps/web/app/application/sidebar/ (nicht sidebar.config.ts). Der Such-Index / indexedEntities gehört nach packages/search/ (nicht packages/db/src/search/indexed-entities.ts). Geteilte Pakete bleiben @toolctrl/*; neue HiveGrid-Querschnittsdienste (z.B. Activity/logActivity) werden als neues @hivegrid/*-Paket angelegt. Lies die ui-hivegrid/@hivegrid/*/sidebar.config.ts-Erwähnungen unten entsprechend.

1. App-Shell-Sidebar (Mandanten-App app.hivegrid.de)

Sidebar ist in 6 feste Gruppen geteilt. Jede neue Funktion gehört in genau eine Gruppe:

🏢 ARBEITEN
  ├─ Dashboard                         → M147-M150
  ├─ Globale Suche (Cmd-K)             → M058
  ├─ Lead-Inbox                        → M047-M051
  ├─ Verkaufsfälle (Sales)             → M059-M064
  ├─ Aufträge (Projekte)               → M065-M070
  ├─ Aufgaben                          → M071-M074
  ├─ Termine                           → M120
  └─ Buchungs-Seiten                   → M126-M129

📇 STAMMDATEN
  ├─ Kontakte                          → M042-M046
  ├─ Firmen                            → M042-M046
  ├─ Dateien                           → M052-M055
  ├─ Tags / Schlagwörter               → M044
  └─ Custom-Felder                     → M044

📨 KOMMUNIKATION
  ├─ Email-Inbox                       → M096-M099
  ├─ Marketing-Kampagnen               → M100-M104
  ├─ Telefonie                         → M105-M109
  ├─ Team-Chat                         → M110-M114
  └─ Notification-Center (Glocke)      → M115-M117

⚙️ AUTOMATION & KI
  ├─ Automation-Studio                 → M075-M082
  ├─ KI-Sprach-Assistent               → M086
  └─ Vorlagen / Templates              → M082

👥 PERSONAL (HR-Hub)
  ├─ Schwarzes Brett                   → M137
  ├─ Mitarbeiter-Verzeichnis           → M133
  ├─ Urlaub / Krankheit                → M135, M136
  ├─ Lohnabrechnungen                  → M134
  ├─ Anträge                           → M139
  └─ Passwort-Safe                     → M134

🛠️ EINSTELLUNGEN (Mandanten-Admin)
  ├─ Mandant (Stammdaten)              → M018
  ├─ Mitarbeiter & Rollen              → M023, M024
  ├─ Pipelines                         → M059, M065
  ├─ Forms                             → M121-M125
  ├─ Integrationen (Apps)              → M008-M010
  ├─ KWP-Verbindung                    → M089-M095
  ├─ Audit-Log                         → M151
  ├─ Subscription / Abo                → M153-M156
  ├─ Branding / Design                 → M030
  └─ DSGVO / Datenschutz               → M164-M166

Plattform-Admin-App admin.hivegrid.de hat eine separate Sidebar-Struktur (siehe M034-M041).

Customer-Portal hat eigene minimale Navigation (siehe M141-M146).

Mobile-App-Tab-Bar ist UI-Modus-abhängig — siehe M169.

2. Sidebar-Wiring-Pflicht

Jeder neue Modul-Bereich muss in packages/ui-hivegrid/src/app-shell/sidebar.config.ts registriert werden. Das ist die einzige Quelle der Wahrheit für Sidebar-Inhalte.

// packages/ui-hivegrid/src/app-shell/sidebar.config.ts
export type SidebarEntry = {
  id: string;                        // eindeutig, kebab-case
  group: 'arbeiten' | 'stammdaten' | 'kommunikation' | 'automation-ki' | 'personal' | 'einstellungen';
  label: string;                     // i18n-Key, kein Hardcoded-String
  icon: string;                      // lucide-react Icon-Name
  route: string;                     // RR7-Route-Pattern
  permission: string | string[];     // Permission-Key aus M004; Eintrag nur sichtbar wenn berechtigt
  badge?: 'count' | 'dot' | null;    // Live-Counter (z.B. ungelesene Mails)
  order: number;                     // Sortierung innerhalb der Gruppe
  feature_flag?: string;             // optional: Sidebar-Eintrag nur sichtbar wenn Flag aktiv
};

Regel: Eine neue Funktion ohne Sidebar-Eintrag (oder ohne Inline-Verlinkung aus einem bestehenden Modul) wird nicht akzeptiert.

3. Route-Patterns

Verbindliche URL-Schemata. Abweichungen erfordern Change-Request.

Bereich Pattern Beispiel
Mandanten-App app.hivegrid.de/<modul>/... app.hivegrid.de/sales/D-2026-0042
Mandant-Settings app.hivegrid.de/settings/<modul>/... app.hivegrid.de/settings/integrationen/kwp
Plattform-Admin admin.hivegrid.de/<bereich>/... admin.hivegrid.de/mandanten/123
Customer-Portal app.hivegrid.de/portal/<tenant>/... app.hivegrid.de/portal/geerkens/projekte/42
Public-Forms app.hivegrid.de/f/<tenant>/<slug> app.hivegrid.de/f/geerkens/kontaktformular
Public-Booking app.hivegrid.de/b/<tenant>/<slug> app.hivegrid.de/b/geerkens/wartungstermin
Public-Help app.hivegrid.de/help/<lang>/<kategorie>/<slug> app.hivegrid.de/help/de/integrationen/kwp-setup
Public-API app.hivegrid.de/api/v1/<resource> app.hivegrid.de/api/v1/contacts
Connector-OAuth-Callback app.hivegrid.de/integrations/<provider>/oauth/callback app.hivegrid.de/integrations/google/oauth/callback

Die Tenant-Slug ist nicht im Pfad bei der Mandanten-App — Tenant kommt aus Subdomain oder Session.

Externe OAuth-Connectors (Google-Kalender, KWP, später AirCall/Microsoft/…): Der Redirect-/Callback-Endpoint liegt immer auf app. (nicht api.) unter /integrations/<provider>/oauth/callback — konsistent zu den Connector-Settings-Screens (/settings/integrations/<modul>, /integrations/<provider>/…). Begründung: Der OAuth-Rückweg ist browser-basiert und braucht die an app. gebundene Nutzer-Session, um den Token dem richtigen Nutzer/Tenant zuzuordnen; api.hivegrid.de (token-basiert, ohne Session) ist dafür nicht geeignet. Tenant wird im OAuth-state mitgeführt (eine feste Callback-URL je Umgebung, kein Tenant im Pfad). Pro Umgebung registriert: app.hivegrid.de, staging-app.hivegrid.de, localhost:3000. Das frühere /api/apps/<slug>/oauth/callback ist abgelöst (2026-06-21).

4. Breadcrumbs-Konvention

Jede Detail-Route hat einen Breadcrumb in packages/ui-hivegrid/src/breadcrumbs/. Format:

[Sidebar-Gruppe] > [Modul] > [Listen-Name] > [Detail-Titel]

Beispiel: Arbeiten > Verkaufsfälle > Anlagen-Verkauf > D-2026-0042 Heizung Schmidt

5. Activity-Stream-Wiring (M045)

Jede schreibende Aktion in jedem Modul muss einen Activity-Stream-Eintrag erzeugen, falls die betroffene Entität einen Stream hat (Kontakt, Firma, Lead, Verkaufsfall, Auftrag).

Pflicht-Service-Aufruf:

import { logActivity } from '@hivegrid/activity';
await logActivity({
  tenantId, actorId, actorType: 'user' | 'auto' | 'sync' | 'system',
  entityType, entityId,
  type: 'contact.created' | 'deal.stage_changed' | ...,
  payload: { ... },                    // Human-readable Klartext + ggf. Vorher/Nachher
});

Der logActivity-Aufruf ist NICHT der Audit-Eintrag — der entsteht zusätzlich automatisch via M001 Prisma-Middleware.

6. Audit-Wiring (M001)

Audit ist automatisch via Prisma-Middleware. Agent muss nichts manuell aufrufen. Wenn etwas im Audit fehlt: Bug in M001-Middleware, nicht im Modul-Code.

Ausnahme: Aktionen außerhalb von Prisma (z.B. Datei-Upload zu S3, externe Webhook-Aufrufe) müssen manuell auditiert werden:

import { auditEvent } from '@hivegrid/audit';
await auditEvent({ ... });

7. Notification-Wiring (M011)

Wenn ein Modul Mitarbeiter benachrichtigen soll: NIE direkt Email/Push senden. Immer:

import { notify } from '@hivegrid/notifications';
await notify({
  tenantId, recipientId,
  category: 'lead.received' | 'deal.won' | ...,
  template: 'lead-received',           // i18n-Key in M003
  payload: { ... },
  priority: 'normal' | 'high' | 'urgent',
});

Der Notification-Service in M011 entscheidet Kanal (In-App/Email/Push), Bündelung (M117), Stille-Stunden (M116).

8. Search-Index-Wiring (M056)

Neue Entität, die in der globalen Suche auftauchen soll, muss in packages/db/src/search/indexed-entities.ts registriert sein:

export const indexedEntities = {
  contact: { table: 'Kontakt', searchable: ['displayName', 'email', 'phone'], permission: 'crm.read' },
  deal: { table: 'Verkaufsfall', searchable: ['title', 'description'], permission: 'sales.read' },
  // ...
};

Permission-aware Search (M057) liest diese Map.

9. i18n-Wiring (M003)

Alle UI-Texte als i18n-Keys. Locale-Files unter packages/i18n/src/locales/de/<modul>.json. ESLint-Rule blockt JSX-Text-Nodes ohne t(). Build-Lint blockt Hard-Strings im Build.

Naming: <modul>.<bereich>.<key>, z.B. sales.kanban.empty_state oder auth.login.password_too_short.

10. Permission-Keys (M004)

Permission-Definition als TypeScript-Konst in packages/entitlements/src/permissions.ts:

export const Permissions = {
  CRM_READ: 'crm.read',
  CRM_READ_OWN: 'crm.read_own',
  CRM_WRITE: 'crm.write',
  SALES_READ: 'sales.read',
  SALES_VOLUME_READ: 'sales.volume.read',  // separater Key für Volumen-Sichtbarkeit (siehe 3.11.2)
  // ...
} as const;

Sidebar-Einträge, Routes, View-Models, Actions filtern alle gegen diese Keys.

11. View-Model-Pflicht (M013)

JEDE Route in app/routes/** baut im Loader ein View-Model. UI-Components in packages/ui-hivegrid/** empfangen NUR das VM und Action-Callbacks. Siehe AGENTS.md.

12. Smoke-Test pro Route (Pflicht)

Jede neue Route bekommt einen Smoke-Test in e2e/smoke/<modul>.spec.ts:

test('contact-detail loads with view-model', async ({ page }) => {
  await loginAs(page, 'geerkens-admin');
  await page.goto('/kontakte/test-kontakt-id');
  await expect(page.getByRole('heading', { name: /kontakt/i })).toBeVisible();
});

Smoke-Tests laufen im Hot-Swap-Drill (M017) gegen packages/ui-mock — wenn sie da brechen, ist die Hot-Swap-Architektur verletzt.

13. Mobile-Tab-Bar-Wiring (M169)

Neue Funktionen, die in der Mobile-App relevant sind, müssen in packages/ui-hivegrid/src/mobile/tab-bar.config.ts für mindestens einen UI-Modus (Baustelle / Büro) registriert sein.

14. Customer-Portal-Wiring (M142, M143)

Funktionen, die Endkunden sehen sollen, müssen explizit in packages/ui-hivegrid/src/customer-portal/portal-shell.config.ts registriert sein. Default-Sichtbarkeit: NICHT sichtbar. Tenant-Admin gibt explizit frei (M142.5).